summaryrefslogtreecommitdiffstats
path: root/freebsd/sys
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2018-08-09 13:04:41 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2018-09-21 10:29:37 +0200
commite4a8065910cd6b2e7e0448cc6431ca2906322389 (patch)
tree73492991cfa40f994c20d761d476e6bc16304536 /freebsd/sys
parentUpdate to FreeBSD head 2017-08-01 (diff)
downloadrtems-libbsd-e4a8065910cd6b2e7e0448cc6431ca2906322389.tar.bz2
Update to FreeBSD head 2017-10-01
Git mirror commit b2f0376b45428f13151d229c5ae9d4d8f74acbd1. Update #3472.
Diffstat (limited to 'freebsd/sys')
-rw-r--r--freebsd/sys/arm/ti/am335x/am335x_prcm.c4
-rw-r--r--freebsd/sys/arm/ti/ti_cpuid.h6
-rw-r--r--freebsd/sys/arm/ti/ti_scm.c5
-rw-r--r--freebsd/sys/arm/ti/ti_sdhci.c4
-rw-r--r--freebsd/sys/cam/cam_ccb.h10
-rw-r--r--freebsd/sys/cam/mmc/mmc.h1
-rw-r--r--freebsd/sys/cam/mmc/mmc_sdio.h64
-rw-r--r--freebsd/sys/cam/nvme/nvme_all.h2
-rw-r--r--freebsd/sys/cam/scsi/scsi_all.c12
-rw-r--r--freebsd/sys/dev/e1000/if_em.c84
-rw-r--r--freebsd/sys/dev/e1000/if_em.h30
-rw-r--r--freebsd/sys/dev/fdt/fdt_common.c3
-rw-r--r--freebsd/sys/dev/mmc/bridge.h12
-rw-r--r--freebsd/sys/dev/mmc/mmc.c44
-rw-r--r--freebsd/sys/dev/mmc/mmc_subr.c42
-rw-r--r--freebsd/sys/dev/mmc/mmc_subr.h12
-rw-r--r--freebsd/sys/dev/mmc/mmcreg.h46
-rw-r--r--freebsd/sys/dev/mmc/mmcsd.c248
-rw-r--r--freebsd/sys/dev/mmc/mmcvar.h4
-rw-r--r--freebsd/sys/dev/nvme/nvme.h134
-rw-r--r--freebsd/sys/dev/ofw/ofw_bus_subr.c12
-rw-r--r--freebsd/sys/dev/ofw/ofw_fdt.c17
-rw-r--r--freebsd/sys/dev/pci/pci.c10
-rw-r--r--freebsd/sys/dev/rtwn/if_rtwn_ridx.h6
-rw-r--r--freebsd/sys/dev/rtwn/if_rtwn_rx.c2
-rw-r--r--freebsd/sys/dev/rtwn/rtl8188e/r88e.h2
-rw-r--r--freebsd/sys/dev/rtwn/rtl8188e/r88e_chan.c6
-rw-r--r--freebsd/sys/dev/rtwn/rtl8192c/r92c.h4
-rw-r--r--freebsd/sys/dev/rtwn/rtl8192c/r92c_chan.c46
-rw-r--r--freebsd/sys/dev/rtwn/rtl8192c/r92c_fw.c2
-rw-r--r--freebsd/sys/dev/rtwn/rtl8192c/r92c_priv.h2
-rw-r--r--freebsd/sys/dev/rtwn/rtl8192c/r92c_rx.c6
-rw-r--r--freebsd/sys/dev/rtwn/rtl8192c/r92c_tx.c4
-rw-r--r--freebsd/sys/dev/rtwn/rtl8192c/r92c_var.h2
-rw-r--r--freebsd/sys/dev/rtwn/rtl8192e/r92e_chan.c71
-rw-r--r--freebsd/sys/dev/rtwn/rtl8812a/r12a_chan.c38
-rw-r--r--freebsd/sys/dev/rtwn/rtl8812a/r12a_rx.c6
-rw-r--r--freebsd/sys/dev/rtwn/rtl8812a/r12a_tx.c4
-rw-r--r--freebsd/sys/dev/sdhci/sdhci.c4
-rw-r--r--freebsd/sys/dev/sdhci/sdhci.h5
-rw-r--r--freebsd/sys/dev/smc/if_smc.c5
-rw-r--r--freebsd/sys/dev/usb/net/if_ure.c1
-rw-r--r--freebsd/sys/dev/usb/quirk/usb_quirk.c5
-rw-r--r--freebsd/sys/dev/usb/quirk/usb_quirk.h1
-rw-r--r--freebsd/sys/dev/usb/usb_hid.c74
-rw-r--r--freebsd/sys/dev/usb/usb_hub.c4
-rw-r--r--freebsd/sys/dev/usb/usbhid.h23
-rw-r--r--freebsd/sys/dev/usb/wlan/if_uath.c122
-rw-r--r--freebsd/sys/fs/devfs/devfs_vnops.c18
-rw-r--r--freebsd/sys/i386/include/machine/cpufunc.h12
-rw-r--r--freebsd/sys/i386/include/machine/intr_machdep.h1
-rw-r--r--freebsd/sys/i386/include/machine/md_var.h1
-rw-r--r--freebsd/sys/kern/kern_sysctl.c100
-rw-r--r--freebsd/sys/kern/subr_blist.c547
-rw-r--r--freebsd/sys/kern/subr_sbuf.c24
-rw-r--r--freebsd/sys/kern/sys_socket.c4
-rw-r--r--freebsd/sys/kern/uipc_sockbuf.c2
-rw-r--r--freebsd/sys/kern/uipc_socket.c52
-rw-r--r--freebsd/sys/kern/uipc_usrreq.c17
-rw-r--r--freebsd/sys/libkern/crc32.c5
-rw-r--r--freebsd/sys/mips/include/machine/cpufunc.h9
-rw-r--r--freebsd/sys/mips/include/machine/cpuregs.h12
-rw-r--r--freebsd/sys/net/bpf.c10
-rw-r--r--freebsd/sys/net/ieee8023ad_lacp.c6
-rw-r--r--freebsd/sys/net/if.c2
-rw-r--r--freebsd/sys/net/if_bridge.c1
-rw-r--r--freebsd/sys/net/if_enc.c49
-rw-r--r--freebsd/sys/net/if_var.h10
-rw-r--r--freebsd/sys/net/if_vlan.c526
-rw-r--r--freebsd/sys/net/iflib.h9
-rw-r--r--freebsd/sys/net/route.h12
-rw-r--r--freebsd/sys/net80211/ieee80211_ioctl.c3
-rw-r--r--freebsd/sys/net80211/ieee80211_mesh.c2
-rw-r--r--freebsd/sys/net80211/ieee80211_output.c2
-rw-r--r--freebsd/sys/netinet/if_ether.c2
-rw-r--r--freebsd/sys/netinet/in_pcb.c32
-rw-r--r--freebsd/sys/netinet/in_pcb.h1
-rw-r--r--freebsd/sys/netinet/ip_icmp.c65
-rw-r--r--freebsd/sys/netinet/sctp.h1
-rw-r--r--freebsd/sys/netinet/sctp_asconf.c33
-rw-r--r--freebsd/sys/netinet/sctp_asconf.h3
-rw-r--r--freebsd/sys/netinet/sctp_constants.h9
-rw-r--r--freebsd/sys/netinet/sctp_indata.c26
-rw-r--r--freebsd/sys/netinet/sctp_input.c43
-rw-r--r--freebsd/sys/netinet/sctp_os_bsd.h5
-rw-r--r--freebsd/sys/netinet/sctp_output.c36
-rw-r--r--freebsd/sys/netinet/sctp_output.h2
-rw-r--r--freebsd/sys/netinet/sctp_pcb.c12
-rw-r--r--freebsd/sys/netinet/sctp_pcb.h4
-rw-r--r--freebsd/sys/netinet/sctp_sysctl.c8
-rw-r--r--freebsd/sys/netinet/sctp_uio.h4
-rw-r--r--freebsd/sys/netinet/sctp_usrreq.c21
-rw-r--r--freebsd/sys/netinet/sctputil.c94
-rw-r--r--freebsd/sys/netinet/tcp_input.c38
-rw-r--r--freebsd/sys/netinet/tcp_syncache.c10
-rw-r--r--freebsd/sys/netinet/tcp_timer.c49
-rw-r--r--freebsd/sys/netinet/tcp_usrreq.c2
-rw-r--r--freebsd/sys/netinet/tcp_var.h7
-rw-r--r--freebsd/sys/netinet6/sctp6_usrreq.c2
-rw-r--r--freebsd/sys/netipsec/ipsec.c26
-rw-r--r--freebsd/sys/netipsec/ipsec.h2
-rw-r--r--freebsd/sys/netipsec/ipsec6.h2
-rw-r--r--freebsd/sys/netipsec/ipsec_output.c4
-rw-r--r--freebsd/sys/netipsec/key.c26
-rw-r--r--freebsd/sys/netipsec/udpencap.c7
-rw-r--r--freebsd/sys/netipsec/xform_ah.c4
-rw-r--r--freebsd/sys/netpfil/pf/pf_lb.c8
-rw-r--r--freebsd/sys/opencrypto/crypto.c2
-rw-r--r--freebsd/sys/opencrypto/cryptodev.c76
-rw-r--r--freebsd/sys/opencrypto/cryptodev.h10
-rw-r--r--freebsd/sys/opencrypto/xform_aes_icm.c2
-rw-r--r--freebsd/sys/opencrypto/xform_aes_xts.c2
-rw-r--r--freebsd/sys/opencrypto/xform_blf.c2
-rw-r--r--freebsd/sys/opencrypto/xform_cast5.c2
-rw-r--r--freebsd/sys/opencrypto/xform_cml.c2
-rw-r--r--freebsd/sys/opencrypto/xform_deflate.c2
-rw-r--r--freebsd/sys/opencrypto/xform_des1.c2
-rw-r--r--freebsd/sys/opencrypto/xform_des3.c2
-rw-r--r--freebsd/sys/opencrypto/xform_gmac.c2
-rw-r--r--freebsd/sys/opencrypto/xform_md5.c28
-rw-r--r--freebsd/sys/opencrypto/xform_null.c18
-rw-r--r--freebsd/sys/opencrypto/xform_rijndael.c2
-rw-r--r--freebsd/sys/opencrypto/xform_rmd160.c16
-rw-r--r--freebsd/sys/opencrypto/xform_sha1.c26
-rw-r--r--freebsd/sys/opencrypto/xform_sha2.c44
-rw-r--r--freebsd/sys/opencrypto/xform_skipjack.c2
-rw-r--r--freebsd/sys/powerpc/include/machine/spr.h9
-rw-r--r--freebsd/sys/sys/_task.h3
-rw-r--r--freebsd/sys/sys/blist.h6
-rw-r--r--freebsd/sys/sys/buf.h22
-rw-r--r--freebsd/sys/sys/conf.h11
-rw-r--r--freebsd/sys/sys/gpio.h69
-rw-r--r--freebsd/sys/sys/gtaskqueue.h18
-rw-r--r--freebsd/sys/sys/kernel.h8
-rw-r--r--freebsd/sys/sys/mbuf.h13
-rw-r--r--freebsd/sys/sys/module.h6
-rw-r--r--freebsd/sys/sys/mutex.h16
-rw-r--r--freebsd/sys/sys/sbuf.h2
-rw-r--r--freebsd/sys/sys/smp.h21
-rw-r--r--freebsd/sys/sys/systm.h7
-rw-r--r--freebsd/sys/sys/taskqueue.h4
-rw-r--r--freebsd/sys/sys/vmmeter.h15
-rw-r--r--freebsd/sys/sys/vnode.h2
-rw-r--r--freebsd/sys/vm/uma.h1
-rw-r--r--freebsd/sys/vm/uma_core.c19
-rw-r--r--freebsd/sys/vm/uma_int.h3
146 files changed, 2440 insertions, 1332 deletions
diff --git a/freebsd/sys/arm/ti/am335x/am335x_prcm.c b/freebsd/sys/arm/ti/am335x/am335x_prcm.c
index a05647d5..bc61c9f8 100644
--- a/freebsd/sys/arm/ti/am335x/am335x_prcm.c
+++ b/freebsd/sys/arm/ti/am335x/am335x_prcm.c
@@ -469,8 +469,8 @@ static driver_t am335x_prcm_driver = {
static devclass_t am335x_prcm_devclass;
-DRIVER_MODULE(am335x_prcm, simplebus, am335x_prcm_driver,
- am335x_prcm_devclass, 0, 0);
+EARLY_DRIVER_MODULE(am335x_prcm, simplebus, am335x_prcm_driver,
+ am335x_prcm_devclass, 0, 0, BUS_PASS_TIMER + BUS_PASS_ORDER_EARLY);
MODULE_VERSION(am335x_prcm, 1);
MODULE_DEPEND(am335x_prcm, ti_scm, 1, 1, 1);
diff --git a/freebsd/sys/arm/ti/ti_cpuid.h b/freebsd/sys/arm/ti/ti_cpuid.h
index 213714b3..7a3fcd5e 100644
--- a/freebsd/sys/arm/ti/ti_cpuid.h
+++ b/freebsd/sys/arm/ti/ti_cpuid.h
@@ -99,4 +99,10 @@ static __inline int ti_chip(void)
uint32_t ti_revision(void);
+static __inline bool ti_soc_is_supported(void)
+{
+
+ return (_ti_chip != -1);
+}
+
#endif /* _TI_CPUID_H_ */
diff --git a/freebsd/sys/arm/ti/ti_scm.c b/freebsd/sys/arm/ti/ti_scm.c
index 2e54262e..96b284c9 100644
--- a/freebsd/sys/arm/ti/ti_scm.c
+++ b/freebsd/sys/arm/ti/ti_scm.c
@@ -69,6 +69,7 @@ __FBSDID("$FreeBSD$");
#include <dev/fdt/fdt_pinctrl.h>
#include "ti_scm.h"
+#include "ti_cpuid.h"
static struct resource_spec ti_scm_res_spec[] = {
{ SYS_RES_MEMORY, 0, RF_ACTIVE }, /* Control memory window */
@@ -88,6 +89,10 @@ static struct ti_scm_softc *ti_scm_sc;
static int
ti_scm_probe(device_t dev)
{
+
+ if (!ti_soc_is_supported())
+ return (ENXIO);
+
if (!ofw_bus_status_okay(dev))
return (ENXIO);
diff --git a/freebsd/sys/arm/ti/ti_sdhci.c b/freebsd/sys/arm/ti/ti_sdhci.c
index 76e4b750..58d178a0 100644
--- a/freebsd/sys/arm/ti/ti_sdhci.c
+++ b/freebsd/sys/arm/ti/ti_sdhci.c
@@ -685,11 +685,7 @@ ti_sdhci_attach(device_t dev)
bus_generic_probe(dev);
bus_generic_attach(dev);
-#ifdef MMCCAM
- sdhci_cam_start_slot(&sc->slot);
-#else
sdhci_start_slot(&sc->slot);
-#endif
return (0);
fail:
diff --git a/freebsd/sys/cam/cam_ccb.h b/freebsd/sys/cam/cam_ccb.h
index 92d76d6a..97560848 100644
--- a/freebsd/sys/cam/cam_ccb.h
+++ b/freebsd/sys/cam/cam_ccb.h
@@ -379,8 +379,7 @@ struct ccb_getdev {
u_int8_t serial_num[252];
u_int8_t inq_flags;
u_int8_t serial_num_len;
- const struct nvme_controller_data *nvme_cdata;
- const struct nvme_namespace_data *nvme_data;
+ void *padding[2];
};
/* Device Statistics CCB */
@@ -644,7 +643,7 @@ struct ccb_pathinq_settings_sas {
};
struct ccb_pathinq_settings_nvme {
- uint16_t nsid; /* Namespace ID for this path */
+ uint32_t nsid; /* Namespace ID for this path */
};
#define PATHINQ_SETTINGS_SIZE 128
@@ -850,7 +849,8 @@ struct ccb_nvmeio {
struct nvme_completion cpl; /* NVME completion, per NVME standard */
uint8_t *data_ptr; /* Ptr to the data buf/SG list */
uint32_t dxfer_len; /* Data transfer length */
- uint32_t resid; /* Transfer residual length: 2's comp unused ?*/
+ uint16_t sglist_cnt; /* Number of SG list entries */
+ uint16_t unused; /* padding for removed uint32_t */
};
/*
@@ -1289,6 +1289,8 @@ struct ccb_dev_advinfo {
#define CDAI_TYPE_PHYS_PATH 3
#define CDAI_TYPE_RCAPLONG 4
#define CDAI_TYPE_EXT_INQ 5
+#define CDAI_TYPE_NVME_CNTRL 6 /* NVMe Identify Controller data */
+#define CDAI_TYPE_NVME_NS 7 /* NVMe Identify Namespace data */
off_t bufsiz; /* IN: Size of external buffer */
#define CAM_SCSI_DEVID_MAXLEN 65536 /* length in buffer is an uint16_t */
off_t provsiz; /* OUT: Size required/used */
diff --git a/freebsd/sys/cam/mmc/mmc.h b/freebsd/sys/cam/mmc/mmc.h
index 9fae837e..2e31f029 100644
--- a/freebsd/sys/cam/mmc/mmc.h
+++ b/freebsd/sys/cam/mmc/mmc.h
@@ -87,6 +87,7 @@ struct mmc_params {
#define CARD_FEATURE_SDIO 0x1 << 2
#define CARD_FEATURE_SD20 0x1 << 3
#define CARD_FEATURE_MMC 0x1 << 4
+#define CARD_FEATURE_18V 0x1 << 5
uint8_t sdio_func_count;
} __packed;
diff --git a/freebsd/sys/cam/mmc/mmc_sdio.h b/freebsd/sys/cam/mmc/mmc_sdio.h
deleted file mode 100644
index 6d22ffc0..00000000
--- a/freebsd/sys/cam/mmc/mmc_sdio.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*-
- * Copyright (c) 2014 Ilya Bakulin. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Portions of this software may have been developed with reference to
- * the SD Simplified Specification. The following disclaimer may apply:
- *
- * The following conditions apply to the release of the simplified
- * specification ("Simplified Specification") by the SD Card Association and
- * the SD Group. The Simplified Specification is a subset of the complete SD
- * Specification which is owned by the SD Card Association and the SD
- * Group. This Simplified Specification is provided on a non-confidential
- * basis subject to the disclaimers below. Any implementation of the
- * Simplified Specification may require a license from the SD Card
- * Association, SD Group, SD-3C LLC or other third parties.
- *
- * Disclaimers:
- *
- * The information contained in the Simplified Specification is presented only
- * as a standard specification for SD Cards and SD Host/Ancillary products and
- * is provided "AS-IS" without any representations or warranties of any
- * kind. No responsibility is assumed by the SD Group, SD-3C LLC or the SD
- * Card Association for any damages, any infringements of patents or other
- * right of the SD Group, SD-3C LLC, the SD Card Association or any third
- * parties, which may result from its use. No license is granted by
- * implication, estoppel or otherwise under any patent or other rights of the
- * SD Group, SD-3C LLC, the SD Card Association or any third party. Nothing
- * herein shall be construed as an obligation by the SD Group, the SD-3C LLC
- * or the SD Card Association to disclose or distribute any technical
- * information, know-how or other confidential information to any third party.
- *
- * $FreeBSD$
- */
-
-/*
- * Various SDIO-related stuff
- */
-
-#ifndef CAM_MMC_SDIO_H
-#define CAM_MMC_SDIO_H
-
-void sdio_print_stupid_message(struct cam_periph *periph);
-void sdio_fill_mmcio_rw_direct(union ccb *ccb, uint8_t f, uint8_t wr, uint32_t adr, uint8_t *data);
-uint8_t sdio_parse_mmcio_rw_direct(union ccb *ccb, uint8_t *data);
-#endif
diff --git a/freebsd/sys/cam/nvme/nvme_all.h b/freebsd/sys/cam/nvme/nvme_all.h
index 3cff74d3..b52b7a78 100644
--- a/freebsd/sys/cam/nvme/nvme_all.h
+++ b/freebsd/sys/cam/nvme/nvme_all.h
@@ -44,5 +44,7 @@ int nvme_identify_match(caddr_t identbuffer, caddr_t table_entry);
void nvme_print_ident(const struct nvme_controller_data *, const struct nvme_namespace_data *);
const char *nvme_op_string(const struct nvme_command *);
const char *nvme_cmd_string(const struct nvme_command *, char *, size_t);
+const void *nvme_get_identify_cntrl(struct cam_periph *);
+const void *nvme_get_identify_ns(struct cam_periph *);
#endif /* CAM_NVME_NVME_ALL_H */
diff --git a/freebsd/sys/cam/scsi/scsi_all.c b/freebsd/sys/cam/scsi/scsi_all.c
index 85e95cb6..c13f5516 100644
--- a/freebsd/sys/cam/scsi/scsi_all.c
+++ b/freebsd/sys/cam/scsi/scsi_all.c
@@ -471,10 +471,6 @@ static struct op_table_entry scsi_op_codes[] = {
{ 0x86, ALL & ~(L | R | F), "ACCESS CONTROL IN" },
/* 87 OO OO OOOOOOO ACCESS CONTROL OUT */
{ 0x87, ALL & ~(L | R | F), "ACCESS CONTROL OUT" },
- /*
- * XXX READ(16)/WRITE(16) were not listed for CD/DVE in op-num.txt
- * but we had it since r1.40. Do we really want them?
- */
/* 88 MM O O O READ(16) */
{ 0x88, D | T | W | O | B, "READ(16)" },
/* 89 O COMPARE AND WRITE*/
@@ -5105,8 +5101,8 @@ scsi_sense_sbuf(struct cam_device *device, struct ccb_scsiio *csio,
* errors on finicky architectures. We don't
* ensure that the sense data is pointer aligned.
*/
- bcopy(&csio->sense_data, &sense,
- sizeof(struct scsi_sense_data *));
+ bcopy((struct scsi_sense_data **)&csio->sense_data,
+ &sense, sizeof(struct scsi_sense_data *));
}
} else {
/*
@@ -5230,8 +5226,8 @@ scsi_extract_sense_ccb(union ccb *ccb,
return (0);
if (ccb->ccb_h.flags & CAM_SENSE_PTR)
- bcopy(&ccb->csio.sense_data, &sense_data,
- sizeof(struct scsi_sense_data *));
+ bcopy((struct scsi_sense_data **)&ccb->csio.sense_data,
+ &sense_data, sizeof(struct scsi_sense_data *));
else
sense_data = &ccb->csio.sense_data;
scsi_extract_sense_len(sense_data,
diff --git a/freebsd/sys/dev/e1000/if_em.c b/freebsd/sys/dev/e1000/if_em.c
index f5a0b94e..dba6ef0a 100644
--- a/freebsd/sys/dev/e1000/if_em.c
+++ b/freebsd/sys/dev/e1000/if_em.c
@@ -341,6 +341,8 @@ MODULE_DEPEND(em, pci, 1, 1, 1);
MODULE_DEPEND(em, ether, 1, 1, 1);
MODULE_DEPEND(em, iflib, 1, 1, 1);
+IFLIB_PNP_INFO(pci, em, em_vendor_info_array);
+
static driver_t igb_driver = {
"igb", igb_methods, sizeof(struct adapter),
};
@@ -352,6 +354,7 @@ MODULE_DEPEND(igb, pci, 1, 1, 1);
MODULE_DEPEND(igb, ether, 1, 1, 1);
MODULE_DEPEND(igb, iflib, 1, 1, 1);
+IFLIB_PNP_INFO(pci, igb, igb_vendor_info_array);
static device_method_t em_if_methods[] = {
DEVMETHOD(ifdi_attach_pre, em_if_attach_pre),
@@ -485,7 +488,7 @@ static struct if_shared_ctx em_sctx_init = {
.isc_vendor_info = em_vendor_info_array,
.isc_driver_version = em_driver_version,
.isc_driver = &em_if_driver,
- .isc_flags = IFLIB_NEED_SCRATCH | IFLIB_TSO_INIT_IP,
+ .isc_flags = IFLIB_NEED_SCRATCH | IFLIB_TSO_INIT_IP | IFLIB_NEED_ZERO_CSUM,
.isc_nrxd_min = {EM_MIN_RXD},
.isc_ntxd_min = {EM_MIN_TXD},
@@ -513,12 +516,12 @@ static struct if_shared_ctx igb_sctx_init = {
.isc_vendor_info = igb_vendor_info_array,
.isc_driver_version = em_driver_version,
.isc_driver = &em_if_driver,
- .isc_flags = IFLIB_NEED_SCRATCH | IFLIB_TSO_INIT_IP,
+ .isc_flags = IFLIB_NEED_SCRATCH | IFLIB_TSO_INIT_IP | IFLIB_NEED_ZERO_CSUM,
.isc_nrxd_min = {EM_MIN_RXD},
.isc_ntxd_min = {EM_MIN_TXD},
- .isc_nrxd_max = {EM_MAX_RXD},
- .isc_ntxd_max = {EM_MAX_TXD},
+ .isc_nrxd_max = {IGB_MAX_RXD},
+ .isc_ntxd_max = {IGB_MAX_TXD},
.isc_nrxd_default = {EM_DEFAULT_RXD},
.isc_ntxd_default = {EM_DEFAULT_TXD},
};
@@ -536,22 +539,26 @@ static int em_get_regs(SYSCTL_HANDLER_ARGS)
{
struct adapter *adapter = (struct adapter *)arg1;
struct e1000_hw *hw = &adapter->hw;
-
struct sbuf *sb;
- u32 *regs_buff = (u32 *)malloc(sizeof(u32) * IGB_REGS_LEN, M_DEVBUF, M_NOWAIT);
+ u32 *regs_buff;
int rc;
+ regs_buff = malloc(sizeof(u32) * IGB_REGS_LEN, M_DEVBUF, M_WAITOK);
memset(regs_buff, 0, IGB_REGS_LEN * sizeof(u32));
rc = sysctl_wire_old_buffer(req, 0);
MPASS(rc == 0);
- if (rc != 0)
+ if (rc != 0) {
+ free(regs_buff, M_DEVBUF);
return (rc);
+ }
sb = sbuf_new_for_sysctl(NULL, NULL, 32*400, req);
MPASS(sb != NULL);
- if (sb == NULL)
+ if (sb == NULL) {
+ free(regs_buff, M_DEVBUF);
return (ENOMEM);
+ }
/* General Registers */
regs_buff[0] = E1000_READ_REG(hw, E1000_CTRL);
@@ -607,6 +614,8 @@ static int em_get_regs(SYSCTL_HANDLER_ARGS)
sbuf_printf(sb, "\tTDFHS\t %08x\n", regs_buff[20]);
sbuf_printf(sb, "\tTDFPC\t %08x\n\n", regs_buff[21]);
+ free(regs_buff, M_DEVBUF);
+
#ifdef DUMP_DESCS
{
if_softc_ctx_t scctx = adapter->shared;
@@ -3641,34 +3650,13 @@ em_enable_wakeup(if_ctx_t ctx)
struct adapter *adapter = iflib_get_softc(ctx);
device_t dev = iflib_get_dev(ctx);
if_t ifp = iflib_get_ifp(ctx);
- u32 pmc, ctrl, ctrl_ext, rctl, wuc;
+ int error = 0;
+ u32 pmc, ctrl, ctrl_ext, rctl;
u16 status;
- if ((pci_find_cap(dev, PCIY_PMG, &pmc) != 0))
+ if (pci_find_cap(dev, PCIY_PMG, &pmc) != 0)
return;
- /* Advertise the wakeup capability */
- ctrl = E1000_READ_REG(&adapter->hw, E1000_CTRL);
- ctrl |= (E1000_CTRL_SWDPIN2 | E1000_CTRL_SWDPIN3);
- E1000_WRITE_REG(&adapter->hw, E1000_CTRL, ctrl);
- wuc = E1000_READ_REG(&adapter->hw, E1000_WUC);
- wuc |= (E1000_WUC_PME_EN | E1000_WUC_APME);
- E1000_WRITE_REG(&adapter->hw, E1000_WUC, wuc);
-
- if ((adapter->hw.mac.type == e1000_ich8lan) ||
- (adapter->hw.mac.type == e1000_pchlan) ||
- (adapter->hw.mac.type == e1000_ich9lan) ||
- (adapter->hw.mac.type == e1000_ich10lan))
- e1000_suspend_workarounds_ich8lan(&adapter->hw);
-
- /* Keep the laser running on Fiber adapters */
- if (adapter->hw.phy.media_type == e1000_media_type_fiber ||
- adapter->hw.phy.media_type == e1000_media_type_internal_serdes) {
- ctrl_ext = E1000_READ_REG(&adapter->hw, E1000_CTRL_EXT);
- ctrl_ext |= E1000_CTRL_EXT_SDP3_DATA;
- E1000_WRITE_REG(&adapter->hw, E1000_CTRL_EXT, ctrl_ext);
- }
-
/*
* Determine type of Wakeup: note that wol
* is set with all bits on by default.
@@ -3687,10 +3675,34 @@ em_enable_wakeup(if_ctx_t ctx)
E1000_WRITE_REG(&adapter->hw, E1000_RCTL, rctl);
}
+ if (!(adapter->wol & (E1000_WUFC_EX | E1000_WUFC_MAG | E1000_WUFC_MC)))
+ goto pme;
+
+ /* Advertise the wakeup capability */
+ ctrl = E1000_READ_REG(&adapter->hw, E1000_CTRL);
+ ctrl |= (E1000_CTRL_SWDPIN2 | E1000_CTRL_SWDPIN3);
+ E1000_WRITE_REG(&adapter->hw, E1000_CTRL, ctrl);
+
+ /* Keep the laser running on Fiber adapters */
+ if (adapter->hw.phy.media_type == e1000_media_type_fiber ||
+ adapter->hw.phy.media_type == e1000_media_type_internal_serdes) {
+ ctrl_ext = E1000_READ_REG(&adapter->hw, E1000_CTRL_EXT);
+ ctrl_ext |= E1000_CTRL_EXT_SDP3_DATA;
+ E1000_WRITE_REG(&adapter->hw, E1000_CTRL_EXT, ctrl_ext);
+ }
+
+ if ((adapter->hw.mac.type == e1000_ich8lan) ||
+ (adapter->hw.mac.type == e1000_pchlan) ||
+ (adapter->hw.mac.type == e1000_ich9lan) ||
+ (adapter->hw.mac.type == e1000_ich10lan))
+ e1000_suspend_workarounds_ich8lan(&adapter->hw);
+
if ( adapter->hw.mac.type >= e1000_pchlan) {
- if (em_enable_phy_wakeup(adapter))
- return;
+ error = em_enable_phy_wakeup(adapter);
+ if (error)
+ goto pme;
} else {
+ /* Enable wakeup by the MAC */
E1000_WRITE_REG(&adapter->hw, E1000_WUC, E1000_WUC_PME_EN);
E1000_WRITE_REG(&adapter->hw, E1000_WUFC, adapter->wol);
}
@@ -3698,10 +3710,10 @@ em_enable_wakeup(if_ctx_t ctx)
if (adapter->hw.phy.type == e1000_phy_igp_3)
e1000_igp3_phy_powerdown_workaround_ich8lan(&adapter->hw);
- /* Request PME */
+pme:
status = pci_read_config(dev, pmc + PCIR_POWER_STATUS, 2);
status &= ~(PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE);
- if (if_getcapenable(ifp) & IFCAP_WOL)
+ if (!error && (if_getcapenable(ifp) & IFCAP_WOL))
status |= PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE;
pci_write_config(dev, pmc + PCIR_POWER_STATUS, status, 2);
diff --git a/freebsd/sys/dev/e1000/if_em.h b/freebsd/sys/dev/e1000/if_em.h
index 67d97e17..b7599291 100644
--- a/freebsd/sys/dev/e1000/if_em.h
+++ b/freebsd/sys/dev/e1000/if_em.h
@@ -96,10 +96,10 @@
/* Tunables */
/*
- * EM_TXD: Maximum number of Transmit Descriptors
+ * EM_MAX_TXD: Maximum number of Transmit Descriptors
* Valid Range: 80-256 for 82542 and 82543-based adapters
* 80-4096 for others
- * Default Value: 256
+ * Default Value: 1024
* This value is the number of transmit descriptors allocated by the driver.
* Increasing this value allows the driver to queue more transmits. Each
* descriptor is 16 bytes.
@@ -111,12 +111,13 @@
#define EM_MAX_TXD 4096
#define EM_DEFAULT_TXD 1024
#define EM_DEFAULT_MULTI_TXD 4096
+#define IGB_MAX_TXD 4096
/*
- * EM_RXD - Maximum number of receive Descriptors
+ * EM_MAX_RXD - Maximum number of receive Descriptors
* Valid Range: 80-256 for 82542 and 82543-based adapters
* 80-4096 for others
- * Default Value: 256
+ * Default Value: 1024
* This value is the number of receive descriptors allocated by the driver.
* Increasing this value allows the driver to buffer more incoming packets.
* Each descriptor is 16 bytes. A receive buffer is also allocated for each
@@ -129,6 +130,7 @@
#define EM_MAX_RXD 4096
#define EM_DEFAULT_RXD 1024
#define EM_DEFAULT_MULTI_RXD 4096
+#define IGB_MAX_RXD 4096
/*
* EM_TIDV - Transmit Interrupt Delay Value
@@ -555,26 +557,6 @@ typedef struct _em_vendor_info_t {
void em_dump_rs(struct adapter *);
-#define EM_CORE_LOCK_INIT(_sc, _name) \
- mtx_init(&(_sc)->core_mtx, _name, "EM Core Lock", MTX_DEF)
-#define EM_TX_LOCK_INIT(_sc, _name) \
- mtx_init(&(_sc)->tx_mtx, _name, "EM TX Lock", MTX_DEF)
-#define EM_RX_LOCK_INIT(_sc, _name) \
- mtx_init(&(_sc)->rx_mtx, _name, "EM RX Lock", MTX_DEF)
-#define EM_CORE_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->core_mtx)
-#define EM_TX_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->tx_mtx)
-#define EM_RX_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->rx_mtx)
-#define EM_CORE_LOCK(_sc) mtx_lock(&(_sc)->core_mtx)
-#define EM_TX_LOCK(_sc) mtx_lock(&(_sc)->tx_mtx)
-#define EM_TX_TRYLOCK(_sc) mtx_trylock(&(_sc)->tx_mtx)
-#define EM_RX_LOCK(_sc) mtx_lock(&(_sc)->rx_mtx)
-#define EM_CORE_UNLOCK(_sc) mtx_unlock(&(_sc)->core_mtx)
-#define EM_TX_UNLOCK(_sc) mtx_unlock(&(_sc)->tx_mtx)
-#define EM_RX_UNLOCK(_sc) mtx_unlock(&(_sc)->rx_mtx)
-#define EM_CORE_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->core_mtx, MA_OWNED)
-#define EM_TX_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->tx_mtx, MA_OWNED)
-#define EM_RX_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->rx_mtx, MA_OWNED)
-
#define EM_RSSRK_SIZE 4
#define EM_RSSRK_VAL(key, i) (key[(i) * EM_RSSRK_SIZE] | \
key[(i) * EM_RSSRK_SIZE + 1] << 8 | \
diff --git a/freebsd/sys/dev/fdt/fdt_common.c b/freebsd/sys/dev/fdt/fdt_common.c
index b149695c..c8c777f1 100644
--- a/freebsd/sys/dev/fdt/fdt_common.c
+++ b/freebsd/sys/dev/fdt/fdt_common.c
@@ -62,6 +62,7 @@ __FBSDID("$FreeBSD$");
#define FDT_TYPE_LEN 64
#define FDT_REG_CELLS 4
+#define FDT_RANGES_SIZE 48
SYSCTL_NODE(_hw, OID_AUTO, fdt, CTLFLAG_RD, 0, "Flattened Device Tree");
@@ -151,7 +152,7 @@ fdt_get_range_by_busaddr(phandle_t node, u_long addr, u_long *base,
int
fdt_get_range(phandle_t node, int range_id, u_long *base, u_long *size)
{
- pcell_t ranges[6], *rangesptr;
+ pcell_t ranges[FDT_RANGES_SIZE], *rangesptr;
pcell_t addr_cells, size_cells, par_addr_cells;
u_long par_bus_addr, pbase, psize;
int err, len, tuple_size, tuples;
diff --git a/freebsd/sys/dev/mmc/bridge.h b/freebsd/sys/dev/mmc/bridge.h
index 53e61b48..b7d95ffc 100644
--- a/freebsd/sys/dev/mmc/bridge.h
+++ b/freebsd/sys/dev/mmc/bridge.h
@@ -65,12 +65,10 @@
* linux/mmc/host.h file.
*
* A mmc bridge is a chipset that can have one or more mmc and/or sd
- * cards attached to it. mmc cards are attached on a bus topology,
- * while sd and sdio cards are attached using a star topology (meaning
- * in practice each sd card has its own, independent slot). Each
- * mmcbr is assumed to be derived from the mmcbr. This is done to
- * allow for easier addition of bridges (as each bridge does not need
- * to be added to the mmcbus file).
+ * cards attached to it. mmc devices are attached on a bus topology,
+ * while sd and sdio cards usually are attached using a star topology
+ * (meaning in practice each sd card has its own, independent slot).
+ * Since SDHCI v3.00, buses for esd and esdio are possible, though.
*
* Attached to the mmc bridge is an mmcbus. The mmcbus is described
* in dev/mmc/mmcbus_if.m.
@@ -182,7 +180,7 @@ struct mmc_host {
extern driver_t mmc_driver;
extern devclass_t mmc_devclass;
-#define MMC_VERSION 4
+#define MMC_VERSION 5
#define MMC_DECLARE_BRIDGE(name) \
DRIVER_MODULE(mmc, name, mmc_driver, mmc_devclass, NULL, NULL); \
diff --git a/freebsd/sys/dev/mmc/mmc.c b/freebsd/sys/dev/mmc/mmc.c
index 74e26332..77934e86 100644
--- a/freebsd/sys/dev/mmc/mmc.c
+++ b/freebsd/sys/dev/mmc/mmc.c
@@ -106,12 +106,34 @@ struct mmc_ivars {
uint32_t hs_tran_speed; /* Max speed in high speed mode */
uint32_t erase_sector; /* Card native erase sector size */
uint32_t cmd6_time; /* Generic switch timeout [us] */
+ uint32_t quirks; /* Quirks as per mmc_quirk->quirks */
char card_id_string[64];/* Formatted CID info (serial, MFG, etc) */
char card_sn_string[16];/* Formatted serial # for disk->d_ident */
};
#define CMD_RETRIES 3
+static const struct mmc_quirk mmc_quirks[] = {
+ /*
+ * For some SanDisk iNAND devices, the CMD38 argument needs to be
+ * provided in EXT_CSD[113].
+ */
+ { 0x2, 0x100, "SEM02G", MMC_QUIRK_INAND_CMD38 },
+ { 0x2, 0x100, "SEM04G", MMC_QUIRK_INAND_CMD38 },
+ { 0x2, 0x100, "SEM08G", MMC_QUIRK_INAND_CMD38 },
+ { 0x2, 0x100, "SEM16G", MMC_QUIRK_INAND_CMD38 },
+ { 0x2, 0x100, "SEM32G", MMC_QUIRK_INAND_CMD38 },
+
+ /*
+ * Disable TRIM for Kingston eMMCs where a firmware bug can lead to
+ * unrecoverable data corruption.
+ */
+ { 0x70, MMC_QUIRK_OID_ANY, "V10008", MMC_QUIRK_BROKEN_TRIM },
+ { 0x70, MMC_QUIRK_OID_ANY, "V10016", MMC_QUIRK_BROKEN_TRIM },
+
+ { 0x0, 0x0, NULL, 0x0 }
+};
+
static SYSCTL_NODE(_hw, OID_AUTO, mmc, CTLFLAG_RD, NULL, "mmc driver");
static int mmc_debug;
@@ -1123,7 +1145,7 @@ mmc_format_card_id_string(struct mmc_ivars *ivar)
/*
* Format a card ID string for use by the mmcsd driver, it's what
* appears between the <> in the following:
- * mmcsd0: 968MB <SD SD01G 8.0 SN 2686905 Mfg 08/2008 by 3 TN> at mmc0
+ * mmcsd0: 968MB <SD SD01G 8.0 SN 2686905 MFG 08/2008 by 3 TN> at mmc0
* 22.5MHz/4bit/128-block
*
* Also format just the card serial number, which the mmcsd driver will
@@ -1561,6 +1583,7 @@ mmc_log_card(device_t dev, struct mmc_ivars *ivar, int newcard)
break;
}
}
+ device_printf(dev, " quirks: %b\n", ivar->quirks, MMC_QUIRKS_FMT);
device_printf(dev, " bus: %ubit, %uMHz (%s timing)\n",
(ivar->bus_width == bus_width_1 ? 1 :
(ivar->bus_width == bus_width_4 ? 4 : 8)),
@@ -1577,6 +1600,7 @@ mmc_discover_cards(struct mmc_softc *sc)
u_char switch_res[64];
uint32_t raw_cid[4];
struct mmc_ivars *ivar = NULL;
+ const struct mmc_quirk *quirk;
device_t child;
int err, host_caps, i, newcard;
uint32_t resp, sec_count, status;
@@ -1884,6 +1908,18 @@ mmc_discover_cards(struct mmc_softc *sc)
ivar->raw_ext_csd[EXT_CSD_REV] >= 5);
child_common:
+ for (quirk = &mmc_quirks[0]; quirk->mid != 0x0; quirk++) {
+ if ((quirk->mid == MMC_QUIRK_MID_ANY ||
+ quirk->mid == ivar->cid.mid) &&
+ (quirk->oid == MMC_QUIRK_OID_ANY ||
+ quirk->oid == ivar->cid.oid) &&
+ strncmp(quirk->pnm, ivar->cid.pnm,
+ sizeof(ivar->cid.pnm)) == 0) {
+ ivar->quirks = quirk->quirks;
+ break;
+ }
+ }
+
/*
* Some cards that report maximum I/O block sizes greater
* than 512 require the block length to be set to 512, even
@@ -2485,6 +2521,12 @@ mmc_read_ivar(device_t bus, device_t child, int which, uintptr_t *result)
case MMC_IVAR_MAX_DATA:
*result = mmcbr_get_max_data(bus);
break;
+ case MMC_IVAR_CMD6_TIMEOUT:
+ *result = ivar->cmd6_time;
+ break;
+ case MMC_IVAR_QUIRKS:
+ *result = ivar->quirks;
+ break;
case MMC_IVAR_CARD_ID_STRING:
*(char **)result = ivar->card_id_string;
break;
diff --git a/freebsd/sys/dev/mmc/mmc_subr.c b/freebsd/sys/dev/mmc/mmc_subr.c
index 006354ba..76a14028 100644
--- a/freebsd/sys/dev/mmc/mmc_subr.c
+++ b/freebsd/sys/dev/mmc/mmc_subr.c
@@ -74,7 +74,7 @@ __FBSDID("$FreeBSD$");
#define LOG_PPS 5 /* Log no more than 5 errors per second. */
int
-mmc_wait_for_cmd(device_t brdev, device_t reqdev, struct mmc_command *cmd,
+mmc_wait_for_cmd(device_t busdev, device_t dev, struct mmc_command *cmd,
int retries)
{
struct mmc_request mreq;
@@ -89,14 +89,14 @@ mmc_wait_for_cmd(device_t brdev, device_t reqdev, struct mmc_command *cmd,
if (cmd->data != NULL)
cmd->data->mrq = &mreq;
mreq.cmd = cmd;
- if (MMCBUS_WAIT_FOR_REQUEST(brdev, reqdev, &mreq) != 0)
+ if (MMCBUS_WAIT_FOR_REQUEST(busdev, dev, &mreq) != 0)
err = MMC_ERR_FAILED;
else
err = cmd->error;
} while (err != MMC_ERR_NONE && retries-- > 0);
- if (err != MMC_ERR_NONE && brdev == reqdev) {
- sc = device_get_softc(brdev);
+ if (err != MMC_ERR_NONE && busdev == dev) {
+ sc = device_get_softc(busdev);
if (sc->squelched == 0 && ppsratecheck(&sc->log_time,
&sc->log_count, LOG_PPS)) {
device_printf(sc->dev, "CMD%d failed, RESULT: %d\n",
@@ -108,14 +108,14 @@ mmc_wait_for_cmd(device_t brdev, device_t reqdev, struct mmc_command *cmd,
}
int
-mmc_wait_for_app_cmd(device_t brdev, device_t reqdev, uint16_t rca,
+mmc_wait_for_app_cmd(device_t busdev, device_t dev, uint16_t rca,
struct mmc_command *cmd, int retries)
{
struct mmc_command appcmd;
struct mmc_softc *sc;
int err;
- sc = device_get_softc(brdev);
+ sc = device_get_softc(busdev);
/* Squelch error reporting at lower levels, we report below. */
sc->squelched++;
@@ -124,14 +124,14 @@ mmc_wait_for_app_cmd(device_t brdev, device_t reqdev, uint16_t rca,
appcmd.opcode = MMC_APP_CMD;
appcmd.arg = (uint32_t)rca << 16;
appcmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
- if (mmc_wait_for_cmd(brdev, reqdev, &appcmd, 0) != 0)
+ if (mmc_wait_for_cmd(busdev, dev, &appcmd, 0) != 0)
err = MMC_ERR_FAILED;
else
err = appcmd.error;
if (err == MMC_ERR_NONE) {
if (!(appcmd.resp[0] & R1_APP_CMD))
err = MMC_ERR_FAILED;
- else if (mmc_wait_for_cmd(brdev, reqdev, cmd, 0) != 0)
+ else if (mmc_wait_for_cmd(busdev, dev, cmd, 0) != 0)
err = MMC_ERR_FAILED;
else
err = cmd->error;
@@ -139,7 +139,7 @@ mmc_wait_for_app_cmd(device_t brdev, device_t reqdev, uint16_t rca,
} while (err != MMC_ERR_NONE && retries-- > 0);
sc->squelched--;
- if (err != MMC_ERR_NONE && brdev == reqdev) {
+ if (err != MMC_ERR_NONE && busdev == dev) {
if (sc->squelched == 0 && ppsratecheck(&sc->log_time,
&sc->log_count, LOG_PPS)) {
device_printf(sc->dev, "ACMD%d failed, RESULT: %d\n",
@@ -151,7 +151,7 @@ mmc_wait_for_app_cmd(device_t brdev, device_t reqdev, uint16_t rca,
}
int
-mmc_switch(device_t brdev, device_t reqdev, uint16_t rca, uint8_t set,
+mmc_switch(device_t busdev, device_t dev, uint16_t rca, uint8_t set,
uint8_t index, uint8_t value, u_int timeout, bool status)
{
struct mmc_command cmd;
@@ -160,7 +160,7 @@ mmc_switch(device_t brdev, device_t reqdev, uint16_t rca, uint8_t set,
KASSERT(timeout != 0, ("%s: no timeout", __func__));
- sc = device_get_softc(brdev);
+ sc = device_get_softc(busdev);
memset(&cmd, 0, sizeof(cmd));
cmd.opcode = MMC_SWITCH_FUNC;
@@ -171,8 +171,8 @@ mmc_switch(device_t brdev, device_t reqdev, uint16_t rca, uint8_t set,
* exceeds the maximum host timeout, use a R1 instead of a R1B
* response in order to keep the hardware from timing out.
*/
- if (mmcbr_get_caps(brdev) & MMC_CAP_WAIT_WHILE_BUSY &&
- timeout > mmcbr_get_max_busy_timeout(brdev))
+ if (mmcbr_get_caps(busdev) & MMC_CAP_WAIT_WHILE_BUSY &&
+ timeout > mmcbr_get_max_busy_timeout(busdev))
cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
else
cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
@@ -182,17 +182,17 @@ mmc_switch(device_t brdev, device_t reqdev, uint16_t rca, uint8_t set,
* than to a tuning command that may have snuck in between.
*/
sc->retune_paused++;
- err = mmc_wait_for_cmd(brdev, reqdev, &cmd, CMD_RETRIES);
+ err = mmc_wait_for_cmd(busdev, dev, &cmd, CMD_RETRIES);
if (err != MMC_ERR_NONE || status == false)
goto out;
- err = mmc_switch_status(brdev, reqdev, rca, timeout);
+ err = mmc_switch_status(busdev, dev, rca, timeout);
out:
sc->retune_paused--;
return (err);
}
int
-mmc_switch_status(device_t brdev, device_t reqdev, uint16_t rca, u_int timeout)
+mmc_switch_status(device_t busdev, device_t dev, uint16_t rca, u_int timeout)
{
struct timeval cur, end;
int err;
@@ -207,7 +207,7 @@ mmc_switch_status(device_t brdev, device_t reqdev, uint16_t rca, u_int timeout)
*/
end.tv_sec = end.tv_usec = 0;
for (;;) {
- err = mmc_send_status(brdev, reqdev, rca, &status);
+ err = mmc_send_status(busdev, dev, rca, &status);
if (err != MMC_ERR_NONE)
break;
if (R1_CURRENT_STATE(status) == R1_STATE_TRAN)
@@ -228,7 +228,7 @@ mmc_switch_status(device_t brdev, device_t reqdev, uint16_t rca, u_int timeout)
}
int
-mmc_send_ext_csd(device_t brdev, device_t reqdev, uint8_t *rawextcsd)
+mmc_send_ext_csd(device_t busdev, device_t dev, uint8_t *rawextcsd)
{
struct mmc_command cmd;
struct mmc_data data;
@@ -246,12 +246,12 @@ mmc_send_ext_csd(device_t brdev, device_t reqdev, uint8_t *rawextcsd)
data.len = MMC_EXTCSD_SIZE;
data.flags = MMC_DATA_READ;
- err = mmc_wait_for_cmd(brdev, reqdev, &cmd, CMD_RETRIES);
+ err = mmc_wait_for_cmd(busdev, dev, &cmd, CMD_RETRIES);
return (err);
}
int
-mmc_send_status(device_t brdev, device_t reqdev, uint16_t rca, uint32_t *status)
+mmc_send_status(device_t busdev, device_t dev, uint16_t rca, uint32_t *status)
{
struct mmc_command cmd;
int err;
@@ -260,7 +260,7 @@ mmc_send_status(device_t brdev, device_t reqdev, uint16_t rca, uint32_t *status)
cmd.opcode = MMC_SEND_STATUS;
cmd.arg = (uint32_t)rca << 16;
cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
- err = mmc_wait_for_cmd(brdev, reqdev, &cmd, CMD_RETRIES);
+ err = mmc_wait_for_cmd(busdev, dev, &cmd, CMD_RETRIES);
*status = cmd.resp[0];
return (err);
}
diff --git a/freebsd/sys/dev/mmc/mmc_subr.h b/freebsd/sys/dev/mmc/mmc_subr.h
index 6e300d2f..33ea6760 100644
--- a/freebsd/sys/dev/mmc/mmc_subr.h
+++ b/freebsd/sys/dev/mmc/mmc_subr.h
@@ -57,16 +57,16 @@
struct mmc_command;
-int mmc_send_ext_csd(device_t brdev, device_t reqdev, uint8_t *rawextcsd);
-int mmc_send_status(device_t brdev, device_t reqdev, uint16_t rca,
+int mmc_send_ext_csd(device_t busdev, device_t dev, uint8_t *rawextcsd);
+int mmc_send_status(device_t busdev, device_t dev, uint16_t rca,
uint32_t *status);
-int mmc_switch(device_t brdev, device_t reqdev, uint16_t rca, uint8_t set,
+int mmc_switch(device_t busdev, device_t dev, uint16_t rca, uint8_t set,
uint8_t index, uint8_t value, u_int timeout, bool send_status);
-int mmc_switch_status(device_t brdev, device_t reqdev, uint16_t rca,
+int mmc_switch_status(device_t busdev, device_t dev, uint16_t rca,
u_int timeout);
-int mmc_wait_for_app_cmd(device_t brdev, device_t reqdev, uint16_t rca,
+int mmc_wait_for_app_cmd(device_t busdev, device_t dev, uint16_t rca,
struct mmc_command *cmd, int retries);
-int mmc_wait_for_cmd(device_t brdev, device_t reqdev, struct mmc_command *cmd,
+int mmc_wait_for_cmd(device_t busdev, device_t dev, struct mmc_command *cmd,
int retries);
#endif /* DEV_MMC_SUBR_H */
diff --git a/freebsd/sys/dev/mmc/mmcreg.h b/freebsd/sys/dev/mmc/mmcreg.h
index 80f433c1..8120b69f 100644
--- a/freebsd/sys/dev/mmc/mmcreg.h
+++ b/freebsd/sys/dev/mmc/mmcreg.h
@@ -276,6 +276,13 @@ struct mmc_request {
#define MMC_ERASE_GROUP_END 36
/* 37 -- reserved old command */
#define MMC_ERASE 38
+#define MMC_ERASE_ERASE 0x00000000
+#define MMC_ERASE_TRIM 0x00000001
+#define MMC_ERASE_FULE 0x00000002
+#define MMC_ERASE_DISCARD 0x00000003
+#define MMC_ERASE_SECURE_ERASE 0x80000000
+#define MMC_ERASE_SECURE_TRIM1 0x80000001
+#define MMC_ERASE_SECURE_TRIM2 0x80008000
/* Class 9: I/O mode commands */
#define MMC_FAST_IO 39
@@ -383,6 +390,7 @@ struct mmc_request {
#define EXT_CSD_ERASE_TO_MULT 223 /* RO */
#define EXT_CSD_ERASE_GRP_SIZE 224 /* RO */
#define EXT_CSD_BOOT_SIZE_MULT 226 /* RO */
+#define EXT_CSD_SEC_FEATURE_SUPPORT 231 /* RO */
#define EXT_CSD_PWR_CL_200_195 236 /* RO */
#define EXT_CSD_PWR_CL_200_360 237 /* RO */
#define EXT_CSD_PWR_CL_52_195_DDR 238 /* RO */
@@ -467,6 +475,22 @@ struct mmc_request {
#define EXT_CSD_STROBE_SUPPORT_EN 0x01
+#define EXT_CSD_SEC_FEATURE_SUPPORT_ER_EN 0x01
+#define EXT_CSD_SEC_FEATURE_SUPPORT_BD_BLK_EN 0x04
+#define EXT_CSD_SEC_FEATURE_SUPPORT_GB_CL_EN 0x10
+#define EXT_CSD_SEC_FEATURE_SUPPORT_SANITIZE 0x40
+
+/*
+ * Vendor specific EXT_CSD fields
+ */
+/* SanDisk iNAND */
+#define EXT_CSD_INAND_CMD38 113
+#define EXT_CSD_INAND_CMD38_ERASE 0x00
+#define EXT_CSD_INAND_CMD38_TRIM 0x01
+#define EXT_CSD_INAND_CMD38_SECURE_ERASE 0x80
+#define EXT_CSD_INAND_CMD38_SECURE_TRIM1 0x81
+#define EXT_CSD_INAND_CMD38_SECURE_TRIM2 0x82
+
#define MMC_TYPE_HS_26_MAX 26000000
#define MMC_TYPE_HS_52_MAX 52000000
#define MMC_TYPE_DDR52_MAX 52000000
@@ -608,8 +632,7 @@ struct mmc_cid {
uint8_t fwrev;
};
-struct mmc_csd
-{
+struct mmc_csd {
uint8_t csd_structure;
uint8_t spec_vers;
uint16_t ccc;
@@ -635,16 +658,14 @@ struct mmc_csd
wp_grp_enable:1;
};
-struct mmc_scr
-{
+struct mmc_scr {
unsigned char sda_vsn;
unsigned char bus_widths;
#define SD_SCR_BUS_WIDTH_1 (1 << 0)
#define SD_SCR_BUS_WIDTH_4 (1 << 2)
};
-struct mmc_sd_status
-{
+struct mmc_sd_status {
uint8_t bus_width;
uint8_t secured_mode;
uint16_t card_type;
@@ -657,6 +678,19 @@ struct mmc_sd_status
uint8_t erase_offset;
};
+struct mmc_quirk {
+ uint32_t mid;
+#define MMC_QUIRK_MID_ANY ((uint32_t)-1)
+ uint16_t oid;
+#define MMC_QUIRK_OID_ANY ((uint16_t)-1)
+ const char *pnm;
+ uint32_t quirks;
+#define MMC_QUIRK_INAND_CMD38 0x0001
+#define MMC_QUIRK_BROKEN_TRIM 0x0002
+};
+
+#define MMC_QUIRKS_FMT "\020" "\001INAND_CMD38" "\002BROKEN_TRIM"
+
/*
* Various MMC/SD constants
*/
diff --git a/freebsd/sys/dev/mmc/mmcsd.c b/freebsd/sys/dev/mmc/mmcsd.c
index 195feae2..45bd9c50 100644
--- a/freebsd/sys/dev/mmc/mmcsd.c
+++ b/freebsd/sys/dev/mmc/mmcsd.c
@@ -128,7 +128,7 @@ struct mmcsd_part {
struct mmcsd_softc {
device_t dev;
- device_t mmcbr;
+ device_t mmcbus;
struct mmcsd_part *part[MMC_PART_MAX];
enum mmc_card_mode mode;
u_int max_data; /* Maximum data size [blocks] */
@@ -137,6 +137,10 @@ struct mmcsd_softc {
uint8_t part_curr; /* Partition currently switched to */
uint8_t ext_csd[MMC_EXTCSD_SIZE];
uint16_t rca;
+ uint32_t flags;
+#define MMCSD_INAND_CMD38 0x0001
+#define MMCSD_USE_TRIM 0x0002
+ uint32_t cmd6_time; /* Generic switch timeout [us] */
uint32_t part_time; /* Partition switch timeout [us] */
off_t enh_base; /* Enhanced user data area slice base ... */
off_t enh_size; /* ... and size [bytes] */
@@ -147,6 +151,9 @@ struct mmcsd_softc {
#ifndef __rtems__
static const char *errmsg[] =
+#else /* __rtems__ */
+static const char * const errmsg[] =
+#endif /* __rtems__ */
{
"None",
"Timeout",
@@ -156,7 +163,6 @@ static const char *errmsg[] =
"Invalid",
"NO MEMORY"
};
-#endif /* __rtems__ */
#define LOG_PPS 5 /* Log no more than 5 errors per second. */
@@ -183,11 +189,12 @@ static int mmcsd_ioctl_rpmb(struct cdev *dev, u_long cmd, caddr_t data,
int fflag, struct thread *td);
static void mmcsd_add_part(struct mmcsd_softc *sc, u_int type,
- const char *name, u_int cnt, off_t media_size, off_t erase_size, bool ro);
+ const char *name, u_int cnt, off_t media_size, bool ro);
static int mmcsd_bus_bit_width(device_t dev);
#ifndef __rtems__
static daddr_t mmcsd_delete(struct mmcsd_part *part, struct bio *bp);
#endif /* __rtems__ */
+static const char *mmcsd_errmsg(int e);
static int mmcsd_ioctl(struct mmcsd_part *part, u_long cmd, void *data,
int fflag);
static int mmcsd_ioctl_cmd(struct mmcsd_part *part, struct mmc_ioc_cmd *mic,
@@ -440,20 +447,21 @@ error:
static int
mmcsd_attach(device_t dev)
{
- device_t mmcbr;
+ device_t mmcbus;
struct mmcsd_softc *sc;
const uint8_t *ext_csd;
off_t erase_size, sector_size, size, wp_size;
uintmax_t bytes;
int err, i;
+ uint32_t quirks;
uint8_t rev;
bool comp, ro;
char unit[2];
sc = device_get_softc(dev);
sc->dev = dev;
- sc->mmcbr = mmcbr = device_get_parent(dev);
- sc->mode = mmcbr_get_mode(mmcbr);
+ sc->mmcbus = mmcbus = device_get_parent(dev);
+ sc->mode = mmcbr_get_mode(mmcbus);
/*
* Note that in principle with an SDHCI-like re-tuning implementation,
* the maximum data size can change at runtime due to a device removal/
@@ -464,20 +472,47 @@ mmcsd_attach(device_t dev)
* place either.
*/
sc->max_data = mmc_get_max_data(dev);
- sc->erase_sector = mmc_get_erase_sector(dev);
sc->high_cap = mmc_get_high_cap(dev);
sc->rca = mmc_get_rca(dev);
+ sc->cmd6_time = mmc_get_cmd6_timeout(dev);
+ quirks = mmc_get_quirks(dev);
/* Only MMC >= 4.x devices support EXT_CSD. */
if (mmc_get_spec_vers(dev) >= 4) {
- MMCBUS_ACQUIRE_BUS(mmcbr, dev);
- err = mmc_send_ext_csd(mmcbr, dev, sc->ext_csd);
- MMCBUS_RELEASE_BUS(mmcbr, dev);
- if (err != MMC_ERR_NONE)
- bzero(sc->ext_csd, sizeof(sc->ext_csd));
+ MMCBUS_ACQUIRE_BUS(mmcbus, dev);
+ err = mmc_send_ext_csd(mmcbus, dev, sc->ext_csd);
+ MMCBUS_RELEASE_BUS(mmcbus, dev);
+ if (err != MMC_ERR_NONE) {
+ device_printf(dev, "Error reading EXT_CSD %s\n",
+ mmcsd_errmsg(err));
+ return (ENXIO);
+ }
}
ext_csd = sc->ext_csd;
+ if ((quirks & MMC_QUIRK_INAND_CMD38) != 0) {
+ if (mmc_get_spec_vers(dev) < 4) {
+ device_printf(dev,
+ "MMC_QUIRK_INAND_CMD38 set but no EXT_CSD\n");
+ return (EINVAL);
+ }
+ sc->flags |= MMCSD_INAND_CMD38;
+ }
+
+ /*
+ * EXT_CSD_SEC_FEATURE_SUPPORT_GB_CL_EN denotes support for both
+ * insecure and secure TRIM.
+ */
+ if ((ext_csd[EXT_CSD_SEC_FEATURE_SUPPORT] &
+ EXT_CSD_SEC_FEATURE_SUPPORT_GB_CL_EN) != 0 &&
+ (quirks & MMC_QUIRK_BROKEN_TRIM) == 0) {
+ if (bootverbose)
+ device_printf(dev, "taking advantage of TRIM\n");
+ sc->flags |= MMCSD_USE_TRIM;
+ sc->erase_sector = 1;
+ } else
+ sc->erase_sector = mmc_get_erase_sector(dev);
+
/*
* Enhanced user data area and general purpose partitions are only
* supported in revision 1.4 (EXT_CSD_REV == 4) and later, the RPMB
@@ -531,8 +566,7 @@ mmcsd_attach(device_t dev)
*/
ro = mmc_get_read_only(dev);
mmcsd_add_part(sc, EXT_CSD_PART_CONFIG_ACC_DEFAULT, "mmcsd",
- device_get_unit(dev), mmc_get_media_size(dev) * sector_size,
- sc->erase_sector * sector_size, ro);
+ device_get_unit(dev), mmc_get_media_size(dev) * sector_size, ro);
if (mmc_get_spec_vers(dev) < 3)
return (0);
@@ -555,13 +589,13 @@ mmcsd_attach(device_t dev)
/* Add boot partitions, which are of a fixed multiple of 128 KB. */
size = ext_csd[EXT_CSD_BOOT_SIZE_MULT] * MMC_BOOT_RPMB_BLOCK_SIZE;
- if (size > 0 && (mmcbr_get_caps(mmcbr) & MMC_CAP_BOOT_NOACC) == 0) {
+ if (size > 0 && (mmcbr_get_caps(mmcbus) & MMC_CAP_BOOT_NOACC) == 0) {
mmcsd_add_part(sc, EXT_CSD_PART_CONFIG_ACC_BOOT0,
- MMCSD_FMT_BOOT, 0, size, MMC_BOOT_RPMB_BLOCK_SIZE,
+ MMCSD_FMT_BOOT, 0, size,
ro | ((ext_csd[EXT_CSD_BOOT_WP_STATUS] &
EXT_CSD_BOOT_WP_STATUS_BOOT0_MASK) != 0));
mmcsd_add_part(sc, EXT_CSD_PART_CONFIG_ACC_BOOT1,
- MMCSD_FMT_BOOT, 1, size, MMC_BOOT_RPMB_BLOCK_SIZE,
+ MMCSD_FMT_BOOT, 1, size,
ro | ((ext_csd[EXT_CSD_BOOT_WP_STATUS] &
EXT_CSD_BOOT_WP_STATUS_BOOT1_MASK) != 0));
}
@@ -570,7 +604,7 @@ mmcsd_attach(device_t dev)
size = ext_csd[EXT_CSD_RPMB_MULT] * MMC_BOOT_RPMB_BLOCK_SIZE;
if (rev >= 5 && size > 0)
mmcsd_add_part(sc, EXT_CSD_PART_CONFIG_ACC_RPMB,
- MMCSD_FMT_RPMB, 0, size, MMC_BOOT_RPMB_BLOCK_SIZE, ro);
+ MMCSD_FMT_RPMB, 0, size, ro);
if (rev <= 3 || comp == FALSE)
return (0);
@@ -590,8 +624,7 @@ mmcsd_attach(device_t dev)
if (size == 0)
continue;
mmcsd_add_part(sc, EXT_CSD_PART_CONFIG_ACC_GP0 + i,
- MMCSD_FMT_GP, i, size * erase_size * wp_size,
- erase_size, ro);
+ MMCSD_FMT_GP, i, size * erase_size * wp_size, ro);
}
}
return (0);
@@ -644,10 +677,10 @@ static struct cdevsw mmcsd_rpmb_cdevsw = {
static void
mmcsd_add_part(struct mmcsd_softc *sc, u_int type, const char *name, u_int cnt,
- off_t media_size, off_t erase_size, bool ro)
+ off_t media_size, bool ro)
{
struct make_dev_args args;
- device_t dev, mmcbr;
+ device_t dev, mmcbus;
const char *ext;
const uint8_t *ext_csd;
struct mmcsd_part *part;
@@ -662,7 +695,7 @@ mmcsd_add_part(struct mmcsd_softc *sc, u_int type, const char *name, u_int cnt,
char unit[2];
dev = sc->dev;
- mmcbr = sc->mmcbr;
+ mmcbus = sc->mmcbus;
part = sc->part[type] = malloc(sizeof(*part), M_DEVBUF,
M_WAITOK | M_ZERO);
part->sc = sc;
@@ -710,10 +743,10 @@ mmcsd_add_part(struct mmcsd_softc *sc, u_int type, const char *name, u_int cnt,
d->d_sectorsize = mmc_get_sector_size(dev);
d->d_maxsize = sc->max_data * d->d_sectorsize;
d->d_mediasize = media_size;
- d->d_stripesize = erase_size;
+ d->d_stripesize = sc->erase_sector * d->d_sectorsize;
d->d_unit = cnt;
d->d_flags = DISKFLAG_CANDELETE;
- d->d_delmaxsize = erase_size;
+ d->d_delmaxsize = mmc_get_erase_sector(dev) * d->d_sectorsize;
strlcpy(d->d_ident, mmc_get_card_sn_string(dev),
sizeof(d->d_ident));
strlcpy(d->d_descr, mmc_get_card_id_string(dev),
@@ -735,10 +768,10 @@ mmcsd_add_part(struct mmcsd_softc *sc, u_int type, const char *name, u_int cnt,
bytes = mmcsd_pretty_size(media_size, unit);
if (type == EXT_CSD_PART_CONFIG_ACC_DEFAULT) {
- speed = mmcbr_get_clock(mmcbr);
+ speed = mmcbr_get_clock(mmcbus);
printf("%s%d: %ju%sB <%s>%s at %s %d.%01dMHz/%dbit/%d-block\n",
part->name, cnt, bytes, unit, mmc_get_card_id_string(dev),
- ro ? " (read-only)" : "", device_get_nameunit(mmcbr),
+ ro ? " (read-only)" : "", device_get_nameunit(mmcbus),
speed / 1000000, (speed / 100000) % 10,
mmcsd_bus_bit_width(dev), sc->max_data);
} else if (type == EXT_CSD_PART_CONFIG_ACC_RPMB) {
@@ -1053,7 +1086,7 @@ mmcsd_ioctl_cmd(struct mmcsd_part *part, struct mmc_ioc_cmd *mic, int fflag)
struct mmc_command cmd;
struct mmc_data data;
struct mmcsd_softc *sc;
- device_t dev, mmcbr;
+ device_t dev, mmcbus;
void *dp;
u_long len;
int err, retries;
@@ -1136,9 +1169,9 @@ mmcsd_ioctl_cmd(struct mmcsd_part *part, struct mmc_ioc_cmd *mic, int fflag)
}
}
dev = sc->dev;
- mmcbr = sc->mmcbr;
- MMCBUS_ACQUIRE_BUS(mmcbr, dev);
- err = mmcsd_switch_part(mmcbr, dev, rca, part->type);
+ mmcbus = sc->mmcbus;
+ MMCBUS_ACQUIRE_BUS(mmcbus, dev);
+ err = mmcsd_switch_part(mmcbus, dev, rca, part->type);
if (err != MMC_ERR_NONE)
goto release;
if (part->type == EXT_CSD_PART_CONFIG_ACC_RPMB) {
@@ -1148,9 +1181,9 @@ mmcsd_ioctl_cmd(struct mmcsd_part *part, struct mmc_ioc_cmd *mic, int fflag)
goto switch_back;
}
if (mic->is_acmd != 0)
- (void)mmc_wait_for_app_cmd(mmcbr, dev, rca, &cmd, 0);
+ (void)mmc_wait_for_app_cmd(mmcbus, dev, rca, &cmd, 0);
else
- (void)mmc_wait_for_cmd(mmcbr, dev, &cmd, 0);
+ (void)mmc_wait_for_cmd(mmcbus, dev, &cmd, 0);
if (part->type == EXT_CSD_PART_CONFIG_ACC_RPMB) {
/*
* If the request went to the RPMB partition, try to ensure
@@ -1158,7 +1191,7 @@ mmcsd_ioctl_cmd(struct mmcsd_part *part, struct mmc_ioc_cmd *mic, int fflag)
*/
retries = MMCSD_CMD_RETRIES;
do {
- err = mmc_send_status(mmcbr, dev, rca, &status);
+ err = mmc_send_status(mmcbus, dev, rca, &status);
if (err != MMC_ERR_NONE)
break;
if (R1_STATUS(status) == 0 &&
@@ -1169,7 +1202,7 @@ mmcsd_ioctl_cmd(struct mmcsd_part *part, struct mmc_ioc_cmd *mic, int fflag)
switch_back:
/* ... and always switch back to the default partition. */
- err = mmcsd_switch_part(mmcbr, dev, rca,
+ err = mmcsd_switch_part(mmcbus, dev, rca,
EXT_CSD_PART_CONFIG_ACC_DEFAULT);
if (err != MMC_ERR_NONE)
goto release;
@@ -1180,11 +1213,11 @@ switch_back:
* so retrieve EXT_CSD again.
*/
if (cmd.opcode == MMC_SWITCH_FUNC) {
- err = mmc_send_ext_csd(mmcbr, dev, sc->ext_csd);
+ err = mmc_send_ext_csd(mmcbus, dev, sc->ext_csd);
if (err != MMC_ERR_NONE)
goto release;
}
- MMCBUS_RELEASE_BUS(mmcbr, dev);
+ MMCBUS_RELEASE_BUS(mmcbus, dev);
if (cmd.error != MMC_ERR_NONE) {
switch (cmd.error) {
case MMC_ERR_TIMEOUT:
@@ -1214,7 +1247,7 @@ switch_back:
goto out;
release:
- MMCBUS_RELEASE_BUS(mmcbr, dev);
+ MMCBUS_RELEASE_BUS(mmcbus, dev);
err = EIO;
out:
@@ -1262,7 +1295,7 @@ mmcsd_set_blockcount(struct mmcsd_softc *sc, u_int count, bool reliable)
if (reliable)
cmd.arg |= 1 << 31;
cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
- MMCBUS_WAIT_FOR_REQUEST(sc->mmcbr, sc->dev, &req);
+ MMCBUS_WAIT_FOR_REQUEST(sc->mmcbus, sc->dev, &req);
return (cmd.error);
}
@@ -1289,7 +1322,7 @@ mmcsd_switch_part(device_t bus, device_t dev, uint16_t rca, u_int part)
* anew.
*/
if (part == EXT_CSD_PART_CONFIG_ACC_RPMB)
- MMCBUS_RETUNE_PAUSE(sc->mmcbr, sc->dev, true);
+ MMCBUS_RETUNE_PAUSE(sc->mmcbus, sc->dev, true);
if (sc->part_curr == part)
return (MMC_ERR_NONE);
@@ -1301,18 +1334,17 @@ mmcsd_switch_part(device_t bus, device_t dev, uint16_t rca, u_int part)
EXT_CSD_PART_CONFIG, value, sc->part_time, true);
if (err != MMC_ERR_NONE) {
if (part == EXT_CSD_PART_CONFIG_ACC_RPMB)
- MMCBUS_RETUNE_UNPAUSE(sc->mmcbr, sc->dev);
+ MMCBUS_RETUNE_UNPAUSE(sc->mmcbus, sc->dev);
return (err);
}
sc->ext_csd[EXT_CSD_PART_CONFIG] = value;
if (sc->part_curr == EXT_CSD_PART_CONFIG_ACC_RPMB)
- MMCBUS_RETUNE_UNPAUSE(sc->mmcbr, sc->dev);
+ MMCBUS_RETUNE_UNPAUSE(sc->mmcbus, sc->dev);
sc->part_curr = part;
return (MMC_ERR_NONE);
}
-#ifndef __rtems__
static const char *
mmcsd_errmsg(int e)
{
@@ -1322,6 +1354,7 @@ mmcsd_errmsg(int e)
return (errmsg[e]);
}
+#ifndef __rtems__
static daddr_t
mmcsd_rw(struct mmcsd_part *part, struct bio *bp)
{
@@ -1331,13 +1364,13 @@ mmcsd_rw(struct mmcsd_part *part, struct bio *bp)
struct mmc_request req;
struct mmc_data data;
struct mmcsd_softc *sc;
- device_t dev, mmcbr;
+ device_t dev, mmcbus;
u_int numblocks, sz;
char *vaddr;
sc = part->sc;
dev = sc->dev;
- mmcbr = sc->mmcbr;
+ mmcbus = sc->mmcbus;
block = bp->bio_pblkno;
sz = part->disk->d_sectorsize;
@@ -1382,7 +1415,7 @@ mmcsd_rw(struct mmcsd_part *part, struct bio *bp)
stop.mrq = &req;
req.stop = &stop;
}
- MMCBUS_WAIT_FOR_REQUEST(mmcbr, dev, &req);
+ MMCBUS_WAIT_FOR_REQUEST(mmcbus, dev, &req);
if (req.cmd->error != MMC_ERR_NONE) {
if (ppsratecheck(&sc->log_time, &sc->log_count,
LOG_PPS))
@@ -1403,32 +1436,56 @@ mmcsd_delete(struct mmcsd_part *part, struct bio *bp)
struct mmc_command cmd;
struct mmc_request req;
struct mmcsd_softc *sc;
- device_t dev, mmcbr;
+ device_t dev, mmcbus;
u_int erase_sector, sz;
+ int err;
+ bool use_trim;
sc = part->sc;
dev = sc->dev;
- mmcbr = sc->mmcbr;
+ mmcbus = sc->mmcbus;
block = bp->bio_pblkno;
sz = part->disk->d_sectorsize;
end = bp->bio_pblkno + (bp->bio_bcount / sz);
- /* Coalesce with part remaining from previous request. */
- if (block > part->eblock && block <= part->eend)
- block = part->eblock;
- if (end >= part->eblock && end < part->eend)
- end = part->eend;
- /* Safe round to the erase sector boundaries. */
- erase_sector = sc->erase_sector;
- start = block + erase_sector - 1; /* Round up. */
- start -= start % erase_sector;
- stop = end; /* Round down. */
- stop -= end % erase_sector;
- /* We can't erase an area smaller than a sector, store it for later. */
- if (start >= stop) {
- part->eblock = block;
- part->eend = end;
- return (end);
+ use_trim = sc->flags & MMCSD_USE_TRIM;
+ if (use_trim == true) {
+ start = block;
+ stop = end;
+ } else {
+ /* Coalesce with the remainder of the previous request. */
+ if (block > part->eblock && block <= part->eend)
+ block = part->eblock;
+ if (end >= part->eblock && end < part->eend)
+ end = part->eend;
+ /* Safely round to the erase sector boundaries. */
+ erase_sector = sc->erase_sector;
+ start = block + erase_sector - 1; /* Round up. */
+ start -= start % erase_sector;
+ stop = end; /* Round down. */
+ stop -= end % erase_sector;
+ /*
+ * We can't erase an area smaller than an erase sector, so
+ * store it for later.
+ */
+ if (start >= stop) {
+ part->eblock = block;
+ part->eend = end;
+ return (end);
+ }
+ }
+
+ if ((sc->flags & MMCSD_INAND_CMD38) != 0) {
+ err = mmc_switch(mmcbus, dev, sc->rca, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_INAND_CMD38, use_trim == true ?
+ EXT_CSD_INAND_CMD38_TRIM : EXT_CSD_INAND_CMD38_ERASE,
+ sc->cmd6_time, true);
+ if (err != MMC_ERR_NONE) {
+ device_printf(dev,
+ "Setting iNAND erase command failed %s\n",
+ mmcsd_errmsg(err));
+ return (block);
+ }
}
/*
@@ -1436,7 +1493,7 @@ mmcsd_delete(struct mmcsd_part *part, struct bio *bp)
* commands. Note that these latter don't use the data lines, so
* re-tuning shouldn't actually become necessary during erase.
*/
- MMCBUS_RETUNE_PAUSE(mmcbr, dev, false);
+ MMCBUS_RETUNE_PAUSE(mmcbus, dev, false);
/* Set erase start position. */
memset(&req, 0, sizeof(req));
memset(&cmd, 0, sizeof(cmd));
@@ -1450,10 +1507,10 @@ mmcsd_delete(struct mmcsd_part *part, struct bio *bp)
if (sc->high_cap == 0)
cmd.arg <<= 9;
cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
- MMCBUS_WAIT_FOR_REQUEST(mmcbr, dev, &req);
+ MMCBUS_WAIT_FOR_REQUEST(mmcbus, dev, &req);
if (req.cmd->error != MMC_ERR_NONE) {
- device_printf(dev, "Setting erase start position failed %d\n",
- req.cmd->error);
+ device_printf(dev, "Setting erase start position failed %s\n",
+ mmcsd_errmsg(req.cmd->error));
block = bp->bio_pblkno;
goto unpause;
}
@@ -1470,10 +1527,10 @@ mmcsd_delete(struct mmcsd_part *part, struct bio *bp)
cmd.arg <<= 9;
cmd.arg--;
cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
- MMCBUS_WAIT_FOR_REQUEST(mmcbr, dev, &req);
+ MMCBUS_WAIT_FOR_REQUEST(mmcbus, dev, &req);
if (req.cmd->error != MMC_ERR_NONE) {
- device_printf(dev, "Setting erase stop position failed %d\n",
- req.cmd->error);
+ device_printf(dev, "Setting erase stop position failed %s\n",
+ mmcsd_errmsg(req.cmd->error));
block = bp->bio_pblkno;
goto unpause;
}
@@ -1482,27 +1539,28 @@ mmcsd_delete(struct mmcsd_part *part, struct bio *bp)
memset(&cmd, 0, sizeof(cmd));
req.cmd = &cmd;
cmd.opcode = MMC_ERASE;
- cmd.arg = 0;
+ cmd.arg = use_trim == true ? MMC_ERASE_TRIM : MMC_ERASE_ERASE;
cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
- MMCBUS_WAIT_FOR_REQUEST(mmcbr, dev, &req);
+ MMCBUS_WAIT_FOR_REQUEST(mmcbus, dev, &req);
if (req.cmd->error != MMC_ERR_NONE) {
- device_printf(dev, "erase err3: %d\n", req.cmd->error);
- device_printf(dev, "Issuing erase command failed %d\n",
- req.cmd->error);
+ device_printf(dev, "Issuing erase command failed %s\n",
+ mmcsd_errmsg(req.cmd->error));
block = bp->bio_pblkno;
goto unpause;
}
- /* Store one of remaining parts for the next call. */
- if (bp->bio_pblkno >= part->eblock || block == start) {
- part->eblock = stop; /* Predict next forward. */
- part->eend = end;
- } else {
- part->eblock = block; /* Predict next backward. */
- part->eend = start;
+ if (use_trim == false) {
+ /* Store one of the remaining parts for the next call. */
+ if (bp->bio_pblkno >= part->eblock || block == start) {
+ part->eblock = stop; /* Predict next forward. */
+ part->eend = end;
+ } else {
+ part->eblock = block; /* Predict next backward. */
+ part->eend = start;
+ }
}
block = end;
unpause:
- MMCBUS_RETUNE_UNPAUSE(mmcbr, dev);
+ MMCBUS_RETUNE_UNPAUSE(mmcbus, dev);
return (block);
}
@@ -1515,7 +1573,7 @@ mmcsd_dump(void *arg, void *virtual, vm_offset_t physical, off_t offset,
struct disk *disk;
struct mmcsd_softc *sc;
struct mmcsd_part *part;
- device_t dev, mmcbr;
+ device_t dev, mmcbus;
int err;
/* length zero is special and really means flush buffers to media */
@@ -1526,7 +1584,7 @@ mmcsd_dump(void *arg, void *virtual, vm_offset_t physical, off_t offset,
part = disk->d_drv1;
sc = part->sc;
dev = sc->dev;
- mmcbr = sc->mmcbr;
+ mmcbus = sc->mmcbus;
g_reset_bio(&bp);
bp.bio_disk = disk;
@@ -1535,16 +1593,16 @@ mmcsd_dump(void *arg, void *virtual, vm_offset_t physical, off_t offset,
bp.bio_data = virtual;
bp.bio_cmd = BIO_WRITE;
end = bp.bio_pblkno + bp.bio_bcount / disk->d_sectorsize;
- MMCBUS_ACQUIRE_BUS(mmcbr, dev);
- err = mmcsd_switch_part(mmcbr, dev, sc->rca, part->type);
+ MMCBUS_ACQUIRE_BUS(mmcbus, dev);
+ err = mmcsd_switch_part(mmcbus, dev, sc->rca, part->type);
if (err != MMC_ERR_NONE) {
if (ppsratecheck(&sc->log_time, &sc->log_count, LOG_PPS))
device_printf(dev, "Partition switch error\n");
- MMCBUS_RELEASE_BUS(mmcbr, dev);
+ MMCBUS_RELEASE_BUS(mmcbus, dev);
return (EIO);
}
block = mmcsd_rw(part, &bp);
- MMCBUS_RELEASE_BUS(mmcbr, dev);
+ MMCBUS_RELEASE_BUS(mmcbus, dev);
return ((end < block) ? EIO : 0);
}
@@ -1555,13 +1613,13 @@ mmcsd_task(void *arg)
struct mmcsd_part *part;
struct mmcsd_softc *sc;
struct bio *bp;
- device_t dev, mmcbr;
+ device_t dev, mmcbus;
int err, sz;
part = arg;
sc = part->sc;
dev = sc->dev;
- mmcbr = sc->mmcbr;
+ mmcbus = sc->mmcbus;
while (1) {
MMCSD_DISK_LOCK(part);
@@ -1581,11 +1639,11 @@ mmcsd_task(void *arg)
biodone(bp);
continue;
}
- MMCBUS_ACQUIRE_BUS(mmcbr, dev);
+ MMCBUS_ACQUIRE_BUS(mmcbus, dev);
sz = part->disk->d_sectorsize;
block = bp->bio_pblkno;
end = bp->bio_pblkno + (bp->bio_bcount / sz);
- err = mmcsd_switch_part(mmcbr, dev, sc->rca, part->type);
+ err = mmcsd_switch_part(mmcbus, dev, sc->rca, part->type);
if (err != MMC_ERR_NONE) {
if (ppsratecheck(&sc->log_time, &sc->log_count,
LOG_PPS))
@@ -1601,7 +1659,7 @@ mmcsd_task(void *arg)
block = mmcsd_delete(part, bp);
}
release:
- MMCBUS_RELEASE_BUS(mmcbr, dev);
+ MMCBUS_RELEASE_BUS(mmcbus, dev);
if (block < end) {
bp->bio_error = EIO;
bp->bio_resid = (end - block) * sz;
diff --git a/freebsd/sys/dev/mmc/mmcvar.h b/freebsd/sys/dev/mmc/mmcvar.h
index 9f62b112..d0f4e330 100644
--- a/freebsd/sys/dev/mmc/mmcvar.h
+++ b/freebsd/sys/dev/mmc/mmcvar.h
@@ -68,6 +68,8 @@ enum mmc_device_ivars {
MMC_IVAR_BUS_WIDTH,
MMC_IVAR_ERASE_SECTOR,
MMC_IVAR_MAX_DATA,
+ MMC_IVAR_CMD6_TIMEOUT,
+ MMC_IVAR_QUIRKS,
MMC_IVAR_CARD_ID_STRING,
MMC_IVAR_CARD_SN_STRING,
};
@@ -90,6 +92,8 @@ MMC_ACCESSOR(card_type, CARD_TYPE, int)
MMC_ACCESSOR(bus_width, BUS_WIDTH, int)
MMC_ACCESSOR(erase_sector, ERASE_SECTOR, int)
MMC_ACCESSOR(max_data, MAX_DATA, int)
+MMC_ACCESSOR(cmd6_timeout, CMD6_TIMEOUT, u_int)
+MMC_ACCESSOR(quirks, QUIRKS, u_int)
MMC_ACCESSOR(card_id_string, CARD_ID_STRING, const char *)
MMC_ACCESSOR(card_sn_string, CARD_SN_STRING, const char *)
diff --git a/freebsd/sys/dev/nvme/nvme.h b/freebsd/sys/dev/nvme/nvme.h
index aa640b37..d4fc131e 100644
--- a/freebsd/sys/dev/nvme/nvme.h
+++ b/freebsd/sys/dev/nvme/nvme.h
@@ -69,6 +69,8 @@ union cap_lo_register {
} bits __packed;
} __packed;
+_Static_assert(sizeof(union cap_lo_register) == 4, "bad size for cap_lo_register");
+
union cap_hi_register {
uint32_t raw;
struct {
@@ -93,6 +95,8 @@ union cap_hi_register {
} bits __packed;
} __packed;
+_Static_assert(sizeof(union cap_hi_register) == 4, "bad size of cap_hi_register");
+
union cc_register {
uint32_t raw;
struct {
@@ -123,6 +127,8 @@ union cc_register {
} bits __packed;
} __packed;
+_Static_assert(sizeof(union cc_register) == 4, "bad size for cc_register");
+
enum shn_value {
NVME_SHN_NORMAL = 0x1,
NVME_SHN_ABRUPT = 0x2,
@@ -144,6 +150,8 @@ union csts_register {
} bits __packed;
} __packed;
+_Static_assert(sizeof(union csts_register) == 4, "bad size for csts_register");
+
enum shst_value {
NVME_SHST_NORMAL = 0x0,
NVME_SHST_OCCURRING = 0x1,
@@ -165,6 +173,8 @@ union aqa_register {
} bits __packed;
} __packed;
+_Static_assert(sizeof(union aqa_register) == 4, "bad size for aqa_resgister");
+
struct nvme_registers
{
/** controller capabilities */
@@ -198,6 +208,8 @@ struct nvme_registers
} doorbell[1] __packed;
} __packed;
+_Static_assert(sizeof(struct nvme_registers) == 0x1008, "bad size for nvme_registers");
+
struct nvme_command
{
/* dword 0 */
@@ -231,6 +243,8 @@ struct nvme_command
uint32_t cdw15; /* command-specific */
} __packed;
+_Static_assert(sizeof(struct nvme_command) == 16 * 4, "bad size for nvme_command");
+
struct nvme_status {
uint16_t p : 1; /* phase tag */
@@ -241,6 +255,8 @@ struct nvme_status {
uint16_t dnr : 1; /* do not retry */
} __packed;
+_Static_assert(sizeof(struct nvme_status) == 2, "bad size for nvme_status");
+
struct nvme_completion {
/* dword 0 */
@@ -258,6 +274,8 @@ struct nvme_completion {
struct nvme_status status;
} __packed;
+_Static_assert(sizeof(struct nvme_completion) == 4 * 4, "bad size for nvme_completion");
+
struct nvme_dsm_range {
uint32_t attributes;
@@ -265,6 +283,8 @@ struct nvme_dsm_range {
uint64_t starting_lba;
} __packed;
+_Static_assert(sizeof(struct nvme_dsm_range) == 16, "bad size for nvme_dsm_ranage");
+
/* status code types */
enum nvme_status_code_type {
NVME_SCT_GENERIC = 0x0,
@@ -377,7 +397,14 @@ enum nvme_feature {
NVME_FEAT_INTERRUPT_VECTOR_CONFIGURATION = 0x09,
NVME_FEAT_WRITE_ATOMICITY = 0x0A,
NVME_FEAT_ASYNC_EVENT_CONFIGURATION = 0x0B,
- /* 0x0C-0x7F - reserved */
+ NVME_FEAT_AUTONOMOUS_POWER_STATE_TRANSITION = 0x0C,
+ NVME_FEAT_HOST_MEMORY_BUFFER = 0x0D,
+ NVME_FEAT_TIMESTAMP = 0x0E,
+ NVME_FEAT_KEEP_ALIVE_TIMER = 0x0F,
+ NVME_FEAT_HOST_CONTROLLED_THERMAL_MGMT = 0x10,
+ NVME_FEAT_NON_OP_POWER_STATE_CONFIG = 0x11,
+ /* 0x12-0x77 - reserved */
+ /* 0x78-0x7f - NVMe Management Interface */
NVME_FEAT_SOFTWARE_PROGRESS_MARKER = 0x80,
/* 0x81-0xBF - command set specific (reserved) */
/* 0xC0-0xFF - vendor specific */
@@ -423,6 +450,8 @@ struct nvme_power_state {
uint8_t ps_rsvd10[9];
} __packed;
+_Static_assert(sizeof(struct nvme_power_state) == 32, "bad size for nvme_power_state");
+
#define NVME_SERIAL_NUMBER_LENGTH 20
#define NVME_MODEL_NUMBER_LENGTH 40
#define NVME_FIRMWARE_REVISION_LENGTH 8
@@ -461,7 +490,27 @@ struct nvme_controller_data {
/** Controller ID */
uint16_t ctrlr_id;
- uint8_t reserved1[176];
+ /** Version */
+ uint32_t ver;
+
+ /** RTD3 Resume Latency */
+ uint32_t rtd3r;
+
+ /** RTD3 Enter Latency */
+ uint32_t rtd3e;
+
+ /** Optional Asynchronous Events Supported */
+ uint32_t oaes; /* bitfield really */
+
+ /** Controller Attributes */
+ uint32_t ctratt; /* bitfield really */
+
+ uint8_t reserved1[12];
+
+ /** FRU Globally Unique Identifier */
+ uint8_t fguid[16];
+
+ uint8_t reserved2[128];
/* bytes 256-511: admin command set attributes */
@@ -521,7 +570,28 @@ struct nvme_controller_data {
uint8_t avscc_rsvd : 7;
} __packed avscc;
- uint8_t reserved2[15];
+ /** Autonomous Power State Transition Attributes */
+ struct {
+ /* Autonmous Power State Transitions supported */
+ uint8_t apst_supp : 1;
+
+ uint8_t apsta_rsvd : 7;
+ } __packed apsta;
+
+ /** Warning Composite Temperature Threshold */
+ uint16_t wctemp;
+
+ /** Critical Composite Temperature Threshold */
+ uint16_t cctemp;
+
+ /** Maximum Time for Firmware Activation */
+ uint16_t mtfa;
+
+ /** Host Memory Buffer Preferred Size */
+ uint32_t hmpre;
+
+ /** Host Memory Buffer Minimum Size */
+ uint32_t hmmin;
/** Name space capabilities */
struct {
@@ -530,7 +600,34 @@ struct nvme_controller_data {
uint8_t unvmcap[16];
} __packed untncap;
- uint8_t reserved3[200];
+ /** Replay Protected Memory Block Support */
+ uint32_t rpmbs; /* Really a bitfield */
+
+ /** Extended Device Self-test Time */
+ uint16_t edstt;
+
+ /** Device Self-test Options */
+ uint8_t dsto; /* Really a bitfield */
+
+ /** Firmware Update Granularity */
+ uint8_t fwug;
+
+ /** Keep Alive Support */
+ uint16_t kas;
+
+ /** Host Controlled Thermal Management Attributes */
+ uint16_t hctma; /* Really a bitfield */
+
+ /** Minimum Thermal Management Temperature */
+ uint16_t mntmt;
+
+ /** Maximum Thermal Management Temperature */
+ uint16_t mxtmt;
+
+ /** Sanitize Capabilities */
+ uint32_t sanicap; /* Really a bitfield */
+
+ uint8_t reserved3[180];
/* bytes 512-703: nvm command set attributes */
/** submission queue entry size */
@@ -545,7 +642,8 @@ struct nvme_controller_data {
uint8_t max : 4;
} __packed cqes;
- uint8_t reserved4[2];
+ /** Maximum Outstanding Commands */
+ uint16_t maxcmd;
/** number of namespaces */
uint32_t nn;
@@ -583,6 +681,8 @@ struct nvme_controller_data {
uint8_t vs[1024];
} __packed __aligned(4);
+_Static_assert(sizeof(struct nvme_controller_data) == 4096, "bad size for nvme_controller_data");
+
struct nvme_namespace_data {
/** namespace size */
@@ -673,6 +773,8 @@ struct nvme_namespace_data {
uint8_t vendor_specific[3712];
} __packed __aligned(4);
+_Static_assert(sizeof(struct nvme_namespace_data) == 4096, "bad size for nvme_namepsace_data");
+
enum nvme_log_page {
/* 0x00 - reserved */
@@ -715,6 +817,8 @@ struct nvme_error_information_entry {
uint8_t reserved[35];
} __packed __aligned(4);
+_Static_assert(sizeof(struct nvme_error_information_entry) == 64, "bad size for nvme_error_information_entry");
+
union nvme_critical_warning_state {
uint8_t raw;
@@ -729,6 +833,8 @@ union nvme_critical_warning_state {
} __packed bits;
} __packed;
+_Static_assert(sizeof(union nvme_critical_warning_state) == 1, "bad size for nvme_critical_warning_state");
+
struct nvme_health_information_page {
union nvme_critical_warning_state critical_warning;
@@ -765,6 +871,8 @@ struct nvme_health_information_page {
uint8_t reserved2[296];
} __packed __aligned(4);
+_Static_assert(sizeof(struct nvme_health_information_page) == 512, "bad size for nvme_health_information_page");
+
struct nvme_firmware_page {
struct {
@@ -777,6 +885,8 @@ struct nvme_firmware_page {
uint8_t reserved2[448];
} __packed __aligned(4);
+_Static_assert(sizeof(struct nvme_firmware_page) == 512, "bad size for nvme_firmware_page");
+
struct intel_log_temp_stats
{
uint64_t current;
@@ -790,6 +900,8 @@ struct intel_log_temp_stats
uint64_t est_offset;
} __packed __aligned(4);
+_Static_assert(sizeof(struct intel_log_temp_stats) == 13 * 8, "bad size for intel_log_temp_stats");
+
#define NVME_TEST_MAX_THREADS 128
struct nvme_io_test {
@@ -958,7 +1070,7 @@ int nvme_ns_bio_process(struct nvme_namespace *ns, struct bio *bp,
/* Command building helper functions -- shared with CAM */
static inline
-void nvme_ns_flush_cmd(struct nvme_command *cmd, uint16_t nsid)
+void nvme_ns_flush_cmd(struct nvme_command *cmd, uint32_t nsid)
{
cmd->opc = NVME_OPC_FLUSH;
@@ -966,7 +1078,7 @@ void nvme_ns_flush_cmd(struct nvme_command *cmd, uint16_t nsid)
}
static inline
-void nvme_ns_rw_cmd(struct nvme_command *cmd, uint32_t rwcmd, uint16_t nsid,
+void nvme_ns_rw_cmd(struct nvme_command *cmd, uint32_t rwcmd, uint32_t nsid,
uint64_t lba, uint32_t count)
{
cmd->opc = rwcmd;
@@ -980,21 +1092,21 @@ void nvme_ns_rw_cmd(struct nvme_command *cmd, uint32_t rwcmd, uint16_t nsid,
}
static inline
-void nvme_ns_write_cmd(struct nvme_command *cmd, uint16_t nsid,
+void nvme_ns_write_cmd(struct nvme_command *cmd, uint32_t nsid,
uint64_t lba, uint32_t count)
{
nvme_ns_rw_cmd(cmd, NVME_OPC_WRITE, nsid, lba, count);
}
static inline
-void nvme_ns_read_cmd(struct nvme_command *cmd, uint16_t nsid,
+void nvme_ns_read_cmd(struct nvme_command *cmd, uint32_t nsid,
uint64_t lba, uint32_t count)
{
nvme_ns_rw_cmd(cmd, NVME_OPC_READ, nsid, lba, count);
}
static inline
-void nvme_ns_trim_cmd(struct nvme_command *cmd, uint16_t nsid,
+void nvme_ns_trim_cmd(struct nvme_command *cmd, uint32_t nsid,
uint32_t num_ranges)
{
cmd->opc = NVME_OPC_DATASET_MANAGEMENT;
@@ -1003,6 +1115,8 @@ void nvme_ns_trim_cmd(struct nvme_command *cmd, uint16_t nsid,
cmd->cdw11 = NVME_DSM_ATTR_DEALLOCATE;
}
+extern int nvme_use_nvd;
+
#endif /* _KERNEL */
#endif /* __NVME_H__ */
diff --git a/freebsd/sys/dev/ofw/ofw_bus_subr.c b/freebsd/sys/dev/ofw/ofw_bus_subr.c
index cc30578d..418304a0 100644
--- a/freebsd/sys/dev/ofw/ofw_bus_subr.c
+++ b/freebsd/sys/dev/ofw/ofw_bus_subr.c
@@ -722,22 +722,14 @@ phandle_t
ofw_bus_find_compatible(phandle_t node, const char *onecompat)
{
phandle_t child, ret;
- void *compat;
- int len;
/*
* Traverse all children of 'start' node, and find first with
* matching 'compatible' property.
*/
for (child = OF_child(node); child != 0; child = OF_peer(child)) {
- len = OF_getprop_alloc(child, "compatible", 1, &compat);
- if (len >= 0) {
- ret = ofw_bus_node_is_compatible_int(compat, len,
- onecompat);
- free(compat, M_OFWPROP);
- if (ret != 0)
- return (child);
- }
+ if (ofw_bus_node_is_compatible(child, onecompat) != 0)
+ return (child);
ret = ofw_bus_find_compatible(child, onecompat);
if (ret != 0)
diff --git a/freebsd/sys/dev/ofw/ofw_fdt.c b/freebsd/sys/dev/ofw/ofw_fdt.c
index 766be90f..282c3667 100644
--- a/freebsd/sys/dev/ofw/ofw_fdt.c
+++ b/freebsd/sys/dev/ofw/ofw_fdt.c
@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofwvar.h>
#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus_subr.h>
#include <rtems/bsd/local/ofw_if.h>
@@ -388,7 +389,11 @@ ofw_fdt_setprop(ofw_t ofw, phandle_t package, const char *propname,
if (offset < 0)
return (-1);
- return (fdt_setprop_inplace(fdtp, offset, propname, buf, len));
+ if (fdt_setprop_inplace(fdtp, offset, propname, buf, len) != 0)
+ /* Try to add property, when setting value inplace failed */
+ return (fdt_setprop(fdtp, offset, propname, buf, len));
+
+ return (0);
}
/* Convert a device specifier to a fully qualified pathname. */
@@ -459,7 +464,15 @@ ofw_fdt_fixup(ofw_t ofw)
for (i = 0; fdt_fixup_table[i].model != NULL; i++) {
if (strncmp(model, fdt_fixup_table[i].model,
FDT_MODEL_LEN) != 0)
- continue;
+ /*
+ * Sometimes it's convenient to provide one
+ * fixup entry that refers to many boards.
+ * To handle this case, simply check if model
+ * is compatible parameter
+ */
+ if(!ofw_bus_node_is_compatible(root,
+ fdt_fixup_table[i].model))
+ continue;
if (fdt_fixup_table[i].handler != NULL)
(*fdt_fixup_table[i].handler)(root);
diff --git a/freebsd/sys/dev/pci/pci.c b/freebsd/sys/dev/pci/pci.c
index be4c626f..69497d2c 100644
--- a/freebsd/sys/dev/pci/pci.c
+++ b/freebsd/sys/dev/pci/pci.c
@@ -2906,13 +2906,21 @@ pci_read_bar(device_t dev, int reg, pci_addr_t *mapp, pci_addr_t *testvalp,
* Determine the BAR's length by writing all 1's. The bottom
* log_2(size) bits of the BAR will stick as 0 when we read
* the value back.
+ *
+ * NB: according to the PCI Local Bus Specification, rev. 3.0:
+ * "Software writes 0FFFFFFFFh to both registers, reads them back,
+ * and combines the result into a 64-bit value." (section 6.2.5.1)
+ *
+ * Writes to both registers must be performed before attempting to
+ * read back the size value.
*/
+ testval = 0;
pci_write_config(dev, reg, 0xffffffff, 4);
- testval = pci_read_config(dev, reg, 4);
if (ln2range == 64) {
pci_write_config(dev, reg + 4, 0xffffffff, 4);
testval |= (pci_addr_t)pci_read_config(dev, reg + 4, 4) << 32;
}
+ testval |= pci_read_config(dev, reg, 4);
/*
* Restore the original value of the BAR. We may have reprogrammed
diff --git a/freebsd/sys/dev/rtwn/if_rtwn_ridx.h b/freebsd/sys/dev/rtwn/if_rtwn_ridx.h
index eef43898..76f87aab 100644
--- a/freebsd/sys/dev/rtwn/if_rtwn_ridx.h
+++ b/freebsd/sys/dev/rtwn/if_rtwn_ridx.h
@@ -36,7 +36,7 @@
#define RTWN_RIDX_OFDM36 9
#define RTWN_RIDX_OFDM48 10
#define RTWN_RIDX_OFDM54 11
-#define RTWN_RIDX_MCS(i) (12 + (i))
+#define RTWN_RIDX_HT_MCS(i) (12 + (i))
#define RTWN_RIDX_COUNT 28
#define RTWN_RIDX_UNKNOWN (uint8_t)-1
@@ -82,10 +82,10 @@ rtwn_ctl_mcsrate(const struct ieee80211_rate_table *rt, uint8_t ridx)
uint8_t cix, rate;
/* Check if we are using MCS rate. */
- KASSERT(ridx >= RTWN_RIDX_MCS(0) && ridx != RTWN_RIDX_UNKNOWN,
+ KASSERT(ridx >= RTWN_RIDX_HT_MCS(0) && ridx != RTWN_RIDX_UNKNOWN,
("bad mcs rate index %d", ridx));
- rate = (ridx - RTWN_RIDX_MCS(0)) | IEEE80211_RATE_MCS;
+ rate = (ridx - RTWN_RIDX_HT_MCS(0)) | IEEE80211_RATE_MCS;
cix = rt->info[rt->rateCodeToIndex[rate]].ctlRateIndex;
KASSERT(cix != (uint8_t)-1, ("rate %d (%d) has no info", rate, ridx));
return rt->info[cix].dot11Rate;
diff --git a/freebsd/sys/dev/rtwn/if_rtwn_rx.c b/freebsd/sys/dev/rtwn/if_rtwn_rx.c
index 7b3f1c2e..fb260596 100644
--- a/freebsd/sys/dev/rtwn/if_rtwn_rx.c
+++ b/freebsd/sys/dev/rtwn/if_rtwn_rx.c
@@ -90,7 +90,7 @@ rtwn_get_rates(struct rtwn_softc *sc, const struct ieee80211_rateset *rs,
if ((rs_ht->rs_rates[i] & 0x7f) > 0xf)
continue;
/* 11n rates start at index 12 */
- ridx = RTWN_RIDX_MCS((rs_ht->rs_rates[i]) & 0xf);
+ ridx = RTWN_RIDX_HT_MCS((rs_ht->rs_rates[i]) & 0xf);
rates |= (1 << ridx);
/* Guard against the rate table being oddly ordered */
diff --git a/freebsd/sys/dev/rtwn/rtl8188e/r88e.h b/freebsd/sys/dev/rtwn/rtl8188e/r88e.h
index 1c03ddd3..3a3c0865 100644
--- a/freebsd/sys/dev/rtwn/rtl8188e/r88e.h
+++ b/freebsd/sys/dev/rtwn/rtl8188e/r88e.h
@@ -49,7 +49,7 @@ uint8_t r88e_temp_read(struct rtwn_softc *);
/* r88e_chan.c */
void r88e_get_txpower(struct rtwn_softc *, int,
- struct ieee80211_channel *, uint16_t[]);
+ struct ieee80211_channel *, uint8_t[]);
void r88e_set_bw20(struct rtwn_softc *, uint8_t);
void r88e_set_gain(struct rtwn_softc *, uint8_t);
diff --git a/freebsd/sys/dev/rtwn/rtl8188e/r88e_chan.c b/freebsd/sys/dev/rtwn/rtl8188e/r88e_chan.c
index 903398a4..530df320 100644
--- a/freebsd/sys/dev/rtwn/rtl8188e/r88e_chan.c
+++ b/freebsd/sys/dev/rtwn/rtl8188e/r88e_chan.c
@@ -87,7 +87,7 @@ r88e_get_power_group(struct rtwn_softc *sc, struct ieee80211_channel *c)
void
r88e_get_txpower(struct rtwn_softc *sc, int chain,
- struct ieee80211_channel *c, uint16_t power[RTWN_RIDX_COUNT])
+ struct ieee80211_channel *c, uint8_t power[RTWN_RIDX_COUNT])
{
struct r92c_softc *rs = sc->sc_priv;
const struct rtwn_r88e_txpwr *rt = rs->rs_txpwr;
@@ -103,7 +103,7 @@ r88e_get_txpower(struct rtwn_softc *sc, int chain,
/* XXX net80211 regulatory */
- max_mcs = RTWN_RIDX_MCS(sc->ntxchains * 8 - 1);
+ max_mcs = RTWN_RIDX_HT_MCS(sc->ntxchains * 8 - 1);
KASSERT(max_mcs <= RTWN_RIDX_COUNT, ("increase ridx limit\n"));
memset(power, 0, max_mcs * sizeof(power[0]));
@@ -123,7 +123,7 @@ r88e_get_txpower(struct rtwn_softc *sc, int chain,
power[ridx] = ofdmpow;
bw20pow = htpow + rt->bw20_tx_pwr_diff;
- for (ridx = RTWN_RIDX_MCS(0); ridx <= max_mcs; ridx++)
+ for (ridx = RTWN_RIDX_HT_MCS(0); ridx <= max_mcs; ridx++)
power[ridx] = bw20pow;
/* Apply max limit. */
diff --git a/freebsd/sys/dev/rtwn/rtl8192c/r92c.h b/freebsd/sys/dev/rtwn/rtl8192c/r92c.h
index 5ac666d0..d8f7afc8 100644
--- a/freebsd/sys/dev/rtwn/rtl8192c/r92c.h
+++ b/freebsd/sys/dev/rtwn/rtl8192c/r92c.h
@@ -55,7 +55,9 @@ uint8_t r92c_temp_read(struct rtwn_softc *);
/* r92c_chan.c */
void r92c_get_txpower(struct rtwn_softc *, int,
- struct ieee80211_channel *, uint16_t[]);
+ struct ieee80211_channel *, uint8_t[]);
+void r92c_write_txpower(struct rtwn_softc *, int,
+ uint8_t power[]);
void r92c_set_bw20(struct rtwn_softc *, uint8_t);
void r92c_set_chan(struct rtwn_softc *, struct ieee80211_channel *);
void r92c_set_gain(struct rtwn_softc *, uint8_t);
diff --git a/freebsd/sys/dev/rtwn/rtl8192c/r92c_chan.c b/freebsd/sys/dev/rtwn/rtl8192c/r92c_chan.c
index c5d72f87..2e50daf1 100644
--- a/freebsd/sys/dev/rtwn/rtl8192c/r92c_chan.c
+++ b/freebsd/sys/dev/rtwn/rtl8192c/r92c_chan.c
@@ -84,7 +84,7 @@ r92c_get_power_group(struct rtwn_softc *sc, struct ieee80211_channel *c)
/* XXX recheck */
void
r92c_get_txpower(struct rtwn_softc *sc, int chain,
- struct ieee80211_channel *c, uint16_t power[RTWN_RIDX_COUNT])
+ struct ieee80211_channel *c, uint8_t power[RTWN_RIDX_COUNT])
{
struct r92c_softc *rs = sc->sc_priv;
struct rtwn_r92c_txpwr *rt = rs->rs_txpwr;
@@ -101,7 +101,7 @@ r92c_get_txpower(struct rtwn_softc *sc, int chain,
/* XXX net80211 regulatory */
- max_mcs = RTWN_RIDX_MCS(sc->ntxchains * 8 - 1);
+ max_mcs = RTWN_RIDX_HT_MCS(sc->ntxchains * 8 - 1);
KASSERT(max_mcs <= RTWN_RIDX_COUNT, ("increase ridx limit\n"));
memset(power, 0, max_mcs * sizeof(power[0]));
@@ -148,7 +148,7 @@ r92c_get_txpower(struct rtwn_softc *sc, int chain,
diff = rt->ht20_tx_pwr_diff[chain][group];
htpow += diff; /* HT40->HT20 correction. */
}
- for (ridx = RTWN_RIDX_MCS(0); ridx <= max_mcs; ridx++)
+ for (ridx = RTWN_RIDX_HT_MCS(0); ridx <= max_mcs; ridx++)
power[ridx] += htpow;
/* Apply max limit. */
@@ -158,9 +158,9 @@ r92c_get_txpower(struct rtwn_softc *sc, int chain,
}
}
-static void
+void
r92c_write_txpower(struct rtwn_softc *sc, int chain,
- uint16_t power[RTWN_RIDX_COUNT])
+ uint8_t power[RTWN_RIDX_COUNT])
{
uint32_t reg;
@@ -197,33 +197,33 @@ r92c_write_txpower(struct rtwn_softc *sc, int chain,
SM(R92C_TXAGC_RATE54, power[RTWN_RIDX_OFDM54]));
/* Write per-MCS Tx power. */
rtwn_bb_write(sc, R92C_TXAGC_MCS03_MCS00(chain),
- SM(R92C_TXAGC_MCS00, power[RTWN_RIDX_MCS(0)]) |
- SM(R92C_TXAGC_MCS01, power[RTWN_RIDX_MCS(1)]) |
- SM(R92C_TXAGC_MCS02, power[RTWN_RIDX_MCS(2)]) |
- SM(R92C_TXAGC_MCS03, power[RTWN_RIDX_MCS(3)]));
+ SM(R92C_TXAGC_MCS00, power[RTWN_RIDX_HT_MCS(0)]) |
+ SM(R92C_TXAGC_MCS01, power[RTWN_RIDX_HT_MCS(1)]) |
+ SM(R92C_TXAGC_MCS02, power[RTWN_RIDX_HT_MCS(2)]) |
+ SM(R92C_TXAGC_MCS03, power[RTWN_RIDX_HT_MCS(3)]));
rtwn_bb_write(sc, R92C_TXAGC_MCS07_MCS04(chain),
- SM(R92C_TXAGC_MCS04, power[RTWN_RIDX_MCS(4)]) |
- SM(R92C_TXAGC_MCS05, power[RTWN_RIDX_MCS(5)]) |
- SM(R92C_TXAGC_MCS06, power[RTWN_RIDX_MCS(6)]) |
- SM(R92C_TXAGC_MCS07, power[RTWN_RIDX_MCS(7)]));
+ SM(R92C_TXAGC_MCS04, power[RTWN_RIDX_HT_MCS(4)]) |
+ SM(R92C_TXAGC_MCS05, power[RTWN_RIDX_HT_MCS(5)]) |
+ SM(R92C_TXAGC_MCS06, power[RTWN_RIDX_HT_MCS(6)]) |
+ SM(R92C_TXAGC_MCS07, power[RTWN_RIDX_HT_MCS(7)]));
if (sc->ntxchains >= 2) {
rtwn_bb_write(sc, R92C_TXAGC_MCS11_MCS08(chain),
- SM(R92C_TXAGC_MCS08, power[RTWN_RIDX_MCS(8)]) |
- SM(R92C_TXAGC_MCS09, power[RTWN_RIDX_MCS(9)]) |
- SM(R92C_TXAGC_MCS10, power[RTWN_RIDX_MCS(10)]) |
- SM(R92C_TXAGC_MCS11, power[RTWN_RIDX_MCS(11)]));
+ SM(R92C_TXAGC_MCS08, power[RTWN_RIDX_HT_MCS(8)]) |
+ SM(R92C_TXAGC_MCS09, power[RTWN_RIDX_HT_MCS(9)]) |
+ SM(R92C_TXAGC_MCS10, power[RTWN_RIDX_HT_MCS(10)]) |
+ SM(R92C_TXAGC_MCS11, power[RTWN_RIDX_HT_MCS(11)]));
rtwn_bb_write(sc, R92C_TXAGC_MCS15_MCS12(chain),
- SM(R92C_TXAGC_MCS12, power[RTWN_RIDX_MCS(12)]) |
- SM(R92C_TXAGC_MCS13, power[RTWN_RIDX_MCS(13)]) |
- SM(R92C_TXAGC_MCS14, power[RTWN_RIDX_MCS(14)]) |
- SM(R92C_TXAGC_MCS15, power[RTWN_RIDX_MCS(15)]));
+ SM(R92C_TXAGC_MCS12, power[RTWN_RIDX_HT_MCS(12)]) |
+ SM(R92C_TXAGC_MCS13, power[RTWN_RIDX_HT_MCS(13)]) |
+ SM(R92C_TXAGC_MCS14, power[RTWN_RIDX_HT_MCS(14)]) |
+ SM(R92C_TXAGC_MCS15, power[RTWN_RIDX_HT_MCS(15)]));
}
}
static void
r92c_set_txpower(struct rtwn_softc *sc, struct ieee80211_channel *c)
{
- uint16_t power[RTWN_RIDX_COUNT];
+ uint8_t power[RTWN_RIDX_COUNT];
int i;
for (i = 0; i < sc->ntxchains; i++) {
@@ -233,7 +233,7 @@ r92c_set_txpower(struct rtwn_softc *sc, struct ieee80211_channel *c)
if (sc->sc_debug & RTWN_DEBUG_TXPWR) {
int max_mcs, ridx;
- max_mcs = RTWN_RIDX_MCS(sc->ntxchains * 8 - 1);
+ max_mcs = RTWN_RIDX_HT_MCS(sc->ntxchains * 8 - 1);
/* Dump per-rate Tx power values. */
printf("Tx power for chain %d:\n", i);
diff --git a/freebsd/sys/dev/rtwn/rtl8192c/r92c_fw.c b/freebsd/sys/dev/rtwn/rtl8192c/r92c_fw.c
index ab8b4989..e6c09eb2 100644
--- a/freebsd/sys/dev/rtwn/rtl8192c/r92c_fw.c
+++ b/freebsd/sys/dev/rtwn/rtl8192c/r92c_fw.c
@@ -200,7 +200,7 @@ r92c_send_ra_cmd(struct rtwn_softc *sc, int macid, uint32_t rates,
#endif
/* Set rates mask for unicast frames. */
- if (maxrate >= RTWN_RIDX_MCS(0))
+ if (maxrate >= RTWN_RIDX_HT_MCS(0))
mode = R92C_RAID_11GN;
else if (maxrate >= RTWN_RIDX_OFDM6)
mode = R92C_RAID_11BG;
diff --git a/freebsd/sys/dev/rtwn/rtl8192c/r92c_priv.h b/freebsd/sys/dev/rtwn/rtl8192c/r92c_priv.h
index 13c38fb2..80f05828 100644
--- a/freebsd/sys/dev/rtwn/rtl8192c/r92c_priv.h
+++ b/freebsd/sys/dev/rtwn/rtl8192c/r92c_priv.h
@@ -333,7 +333,7 @@ static const struct rtwn_rf_prog rtl8192c_rf[] = {
struct rtwn_r92c_txagc {
- uint8_t pwr[R92C_GROUP_2G][28]; /* RTWN_RIDX_MCS(15) + 1 */
+ uint8_t pwr[R92C_GROUP_2G][28]; /* RTWN_RIDX_HT_MCS(15) + 1 */
};
/*
diff --git a/freebsd/sys/dev/rtwn/rtl8192c/r92c_rx.c b/freebsd/sys/dev/rtwn/rtl8192c/r92c_rx.c
index b877fb88..80d2859c 100644
--- a/freebsd/sys/dev/rtwn/rtl8192c/r92c_rx.c
+++ b/freebsd/sys/dev/rtwn/rtl8192c/r92c_rx.c
@@ -119,7 +119,7 @@ r92c_get_rx_stats(struct rtwn_softc *sc, struct ieee80211_rx_stats *rxs,
rxs->c_pktflags |= IEEE80211_RX_F_AMPDU;
else if (rxdw1 & R92C_RXDW1_AMPDU_MORE)
rxs->c_pktflags |= IEEE80211_RX_F_AMPDU_MORE;
- if ((rxdw3 & R92C_RXDW3_SPLCP) && rate >= RTWN_RIDX_MCS(0))
+ if ((rxdw3 & R92C_RXDW3_SPLCP) && rate >= RTWN_RIDX_HT_MCS(0))
rxs->c_pktflags |= IEEE80211_RX_F_SHORTGI;
if (rxdw3 & R92C_RXDW3_HT40)
@@ -129,13 +129,13 @@ r92c_get_rx_stats(struct rtwn_softc *sc, struct ieee80211_rx_stats *rxs,
if (RTWN_RATE_IS_CCK(rate))
rxs->c_phytype = IEEE80211_RX_FP_11B;
- else if (rate < RTWN_RIDX_MCS(0))
+ else if (rate < RTWN_RIDX_HT_MCS(0))
rxs->c_phytype = IEEE80211_RX_FP_11G;
else
rxs->c_phytype = IEEE80211_RX_FP_11NG;
/* Map HW rate index to 802.11 rate. */
- if (rate < RTWN_RIDX_MCS(0)) {
+ if (rate < RTWN_RIDX_HT_MCS(0)) {
rxs->c_rate = ridx2rate[rate];
if (RTWN_RATE_IS_CCK(rate))
rxs->c_pktflags |= IEEE80211_RX_F_CCK;
diff --git a/freebsd/sys/dev/rtwn/rtl8192c/r92c_tx.c b/freebsd/sys/dev/rtwn/rtl8192c/r92c_tx.c
index c2a6eab0..5c80af90 100644
--- a/freebsd/sys/dev/rtwn/rtl8192c/r92c_tx.c
+++ b/freebsd/sys/dev/rtwn/rtl8192c/r92c_tx.c
@@ -101,7 +101,7 @@ r92c_tx_protection(struct rtwn_softc *sc, struct r92c_tx_desc *txd,
if (mode == IEEE80211_PROT_CTSONLY ||
mode == IEEE80211_PROT_RTSCTS) {
- if (ridx >= RTWN_RIDX_MCS(0))
+ if (ridx >= RTWN_RIDX_HT_MCS(0))
rate = rtwn_ctl_mcsrate(ic->ic_rt, ridx);
else
rate = ieee80211_ctl_rate(ic->ic_rt, ridx2rate[ridx]);
@@ -287,7 +287,7 @@ r92c_fill_tx_desc(struct rtwn_softc *sc, struct ieee80211_node *ni,
txd->txdw4 |= htole32(R92C_TXDW4_DATA_SHPRE);
prot = IEEE80211_PROT_NONE;
- if (ridx >= RTWN_RIDX_MCS(0)) {
+ if (ridx >= RTWN_RIDX_HT_MCS(0)) {
r92c_tx_set_ht40(sc, txd, ni);
r92c_tx_set_sgi(sc, txd, ni);
prot = ic->ic_htprotmode;
diff --git a/freebsd/sys/dev/rtwn/rtl8192c/r92c_var.h b/freebsd/sys/dev/rtwn/rtl8192c/r92c_var.h
index c48318d9..79592449 100644
--- a/freebsd/sys/dev/rtwn/rtl8192c/r92c_var.h
+++ b/freebsd/sys/dev/rtwn/rtl8192c/r92c_var.h
@@ -53,7 +53,7 @@ struct r92c_softc {
void (*rs_set_bw20)(struct rtwn_softc *, uint8_t);
void (*rs_get_txpower)(struct rtwn_softc *, int,
- struct ieee80211_channel *, uint16_t[]);
+ struct ieee80211_channel *, uint8_t[]);
void (*rs_set_gain)(struct rtwn_softc *, uint8_t);
void (*rs_tx_enable_ampdu)(void *, int);
void (*rs_tx_setup_hwseq)(void *);
diff --git a/freebsd/sys/dev/rtwn/rtl8192e/r92e_chan.c b/freebsd/sys/dev/rtwn/rtl8192e/r92e_chan.c
index 130ac5ca..0046b9f0 100644
--- a/freebsd/sys/dev/rtwn/rtl8192e/r92e_chan.c
+++ b/freebsd/sys/dev/rtwn/rtl8192e/r92e_chan.c
@@ -59,6 +59,8 @@ __FBSDID("$FreeBSD$");
#include <dev/rtwn/if_rtwn_ridx.h>
#include <dev/rtwn/if_rtwn_rx.h>
+#include <dev/rtwn/rtl8192c/r92c.h>
+
#include <dev/rtwn/rtl8192e/r92e.h>
#include <dev/rtwn/rtl8192e/r92e_reg.h>
#include <dev/rtwn/rtl8192e/r92e_var.h>
@@ -102,7 +104,7 @@ r92e_get_txpower(struct rtwn_softc *sc, int chain, struct ieee80211_channel *c,
return;
}
- max_mcs = RTWN_RIDX_MCS(sc->ntxchains * 8 - 1);
+ max_mcs = RTWN_RIDX_HT_MCS(sc->ntxchains * 8 - 1);
/* XXX regulatory */
/* XXX net80211 regulatory */
@@ -124,7 +126,7 @@ r92e_get_txpower(struct rtwn_softc *sc, int chain, struct ieee80211_channel *c,
else
pwr_diff = rs->bw20_tx_pwr_diff_2g[chain][i];
- min_mcs = RTWN_RIDX_MCS(i * 8);
+ min_mcs = RTWN_RIDX_HT_MCS(i * 8);
for (ridx = min_mcs; ridx <= max_mcs; ridx++)
power[ridx] += pwr_diff;
@@ -146,69 +148,6 @@ r92e_get_txpower(struct rtwn_softc *sc, int chain, struct ieee80211_channel *c,
#endif
}
-
-static void
-r92e_write_txpower(struct rtwn_softc *sc, int chain,
- uint8_t power[RTWN_RIDX_COUNT])
-{
- uint32_t reg;
-
- /* Write per-CCK rate Tx power. */
- if (chain == 0) {
- reg = rtwn_bb_read(sc, R92C_TXAGC_A_CCK1_MCS32);
- reg = RW(reg, R92C_TXAGC_A_CCK1, power[RTWN_RIDX_CCK1]);
- rtwn_bb_write(sc, R92C_TXAGC_A_CCK1_MCS32, reg);
- reg = rtwn_bb_read(sc, R92C_TXAGC_B_CCK11_A_CCK2_11);
- reg = RW(reg, R92C_TXAGC_A_CCK2, power[RTWN_RIDX_CCK2]);
- reg = RW(reg, R92C_TXAGC_A_CCK55, power[RTWN_RIDX_CCK55]);
- reg = RW(reg, R92C_TXAGC_A_CCK11, power[RTWN_RIDX_CCK11]);
- rtwn_bb_write(sc, R92C_TXAGC_B_CCK11_A_CCK2_11, reg);
- } else {
- reg = rtwn_bb_read(sc, R92C_TXAGC_B_CCK1_55_MCS32);
- reg = RW(reg, R92C_TXAGC_B_CCK1, power[RTWN_RIDX_CCK1]);
- reg = RW(reg, R92C_TXAGC_B_CCK2, power[RTWN_RIDX_CCK2]);
- reg = RW(reg, R92C_TXAGC_B_CCK55, power[RTWN_RIDX_CCK55]);
- rtwn_bb_write(sc, R92C_TXAGC_B_CCK1_55_MCS32, reg);
- reg = rtwn_bb_read(sc, R92C_TXAGC_B_CCK11_A_CCK2_11);
- reg = RW(reg, R92C_TXAGC_B_CCK11, power[RTWN_RIDX_CCK11]);
- rtwn_bb_write(sc, R92C_TXAGC_B_CCK11_A_CCK2_11, reg);
- }
- /* Write per-OFDM rate Tx power. */
- rtwn_bb_write(sc, R92C_TXAGC_RATE18_06(chain),
- SM(R92C_TXAGC_RATE06, power[RTWN_RIDX_OFDM6]) |
- SM(R92C_TXAGC_RATE09, power[RTWN_RIDX_OFDM9]) |
- SM(R92C_TXAGC_RATE12, power[RTWN_RIDX_OFDM12]) |
- SM(R92C_TXAGC_RATE18, power[RTWN_RIDX_OFDM18]));
- rtwn_bb_write(sc, R92C_TXAGC_RATE54_24(chain),
- SM(R92C_TXAGC_RATE24, power[RTWN_RIDX_OFDM24]) |
- SM(R92C_TXAGC_RATE36, power[RTWN_RIDX_OFDM36]) |
- SM(R92C_TXAGC_RATE48, power[RTWN_RIDX_OFDM48]) |
- SM(R92C_TXAGC_RATE54, power[RTWN_RIDX_OFDM54]));
- /* Write per-MCS Tx power. */
- rtwn_bb_write(sc, R92C_TXAGC_MCS03_MCS00(chain),
- SM(R92C_TXAGC_MCS00, power[RTWN_RIDX_MCS(0)]) |
- SM(R92C_TXAGC_MCS01, power[RTWN_RIDX_MCS(1)]) |
- SM(R92C_TXAGC_MCS02, power[RTWN_RIDX_MCS(2)]) |
- SM(R92C_TXAGC_MCS03, power[RTWN_RIDX_MCS(3)]));
- rtwn_bb_write(sc, R92C_TXAGC_MCS07_MCS04(chain),
- SM(R92C_TXAGC_MCS04, power[RTWN_RIDX_MCS(4)]) |
- SM(R92C_TXAGC_MCS05, power[RTWN_RIDX_MCS(5)]) |
- SM(R92C_TXAGC_MCS06, power[RTWN_RIDX_MCS(6)]) |
- SM(R92C_TXAGC_MCS07, power[RTWN_RIDX_MCS(7)]));
- if (sc->ntxchains >= 2) {
- rtwn_bb_write(sc, R92C_TXAGC_MCS11_MCS08(chain),
- SM(R92C_TXAGC_MCS08, power[RTWN_RIDX_MCS(8)]) |
- SM(R92C_TXAGC_MCS09, power[RTWN_RIDX_MCS(9)]) |
- SM(R92C_TXAGC_MCS10, power[RTWN_RIDX_MCS(10)]) |
- SM(R92C_TXAGC_MCS11, power[RTWN_RIDX_MCS(11)]));
- rtwn_bb_write(sc, R92C_TXAGC_MCS15_MCS12(chain),
- SM(R92C_TXAGC_MCS12, power[RTWN_RIDX_MCS(12)]) |
- SM(R92C_TXAGC_MCS13, power[RTWN_RIDX_MCS(13)]) |
- SM(R92C_TXAGC_MCS14, power[RTWN_RIDX_MCS(14)]) |
- SM(R92C_TXAGC_MCS15, power[RTWN_RIDX_MCS(15)]));
- }
-}
-
static void
r92e_set_txpower(struct rtwn_softc *sc, struct ieee80211_channel *c)
{
@@ -220,7 +159,7 @@ r92e_set_txpower(struct rtwn_softc *sc, struct ieee80211_channel *c)
/* Compute per-rate Tx power values. */
r92e_get_txpower(sc, i, c, power);
/* Write per-rate Tx power values to hardware. */
- r92e_write_txpower(sc, i, power);
+ r92c_write_txpower(sc, i, power);
}
}
diff --git a/freebsd/sys/dev/rtwn/rtl8812a/r12a_chan.c b/freebsd/sys/dev/rtwn/rtl8812a/r12a_chan.c
index 27a71bd9..1f18bf56 100644
--- a/freebsd/sys/dev/rtwn/rtl8812a/r12a_chan.c
+++ b/freebsd/sys/dev/rtwn/rtl8812a/r12a_chan.c
@@ -91,26 +91,26 @@ r12a_write_txpower(struct rtwn_softc *sc, int chain,
SM(R12A_TXAGC_OFDM54, power[RTWN_RIDX_OFDM54]));
/* Write per-MCS Tx power. */
rtwn_bb_write(sc, R12A_TXAGC_MCS3_0(chain),
- SM(R12A_TXAGC_MCS0, power[RTWN_RIDX_MCS(0)]) |
- SM(R12A_TXAGC_MCS1, power[RTWN_RIDX_MCS(1)]) |
- SM(R12A_TXAGC_MCS2, power[RTWN_RIDX_MCS(2)]) |
- SM(R12A_TXAGC_MCS3, power[RTWN_RIDX_MCS(3)]));
+ SM(R12A_TXAGC_MCS0, power[RTWN_RIDX_HT_MCS(0)]) |
+ SM(R12A_TXAGC_MCS1, power[RTWN_RIDX_HT_MCS(1)]) |
+ SM(R12A_TXAGC_MCS2, power[RTWN_RIDX_HT_MCS(2)]) |
+ SM(R12A_TXAGC_MCS3, power[RTWN_RIDX_HT_MCS(3)]));
rtwn_bb_write(sc, R12A_TXAGC_MCS7_4(chain),
- SM(R12A_TXAGC_MCS4, power[RTWN_RIDX_MCS(4)]) |
- SM(R12A_TXAGC_MCS5, power[RTWN_RIDX_MCS(5)]) |
- SM(R12A_TXAGC_MCS6, power[RTWN_RIDX_MCS(6)]) |
- SM(R12A_TXAGC_MCS7, power[RTWN_RIDX_MCS(7)]));
+ SM(R12A_TXAGC_MCS4, power[RTWN_RIDX_HT_MCS(4)]) |
+ SM(R12A_TXAGC_MCS5, power[RTWN_RIDX_HT_MCS(5)]) |
+ SM(R12A_TXAGC_MCS6, power[RTWN_RIDX_HT_MCS(6)]) |
+ SM(R12A_TXAGC_MCS7, power[RTWN_RIDX_HT_MCS(7)]));
if (sc->ntxchains >= 2) {
rtwn_bb_write(sc, R12A_TXAGC_MCS11_8(chain),
- SM(R12A_TXAGC_MCS8, power[RTWN_RIDX_MCS(8)]) |
- SM(R12A_TXAGC_MCS9, power[RTWN_RIDX_MCS(9)]) |
- SM(R12A_TXAGC_MCS10, power[RTWN_RIDX_MCS(10)]) |
- SM(R12A_TXAGC_MCS11, power[RTWN_RIDX_MCS(11)]));
+ SM(R12A_TXAGC_MCS8, power[RTWN_RIDX_HT_MCS(8)]) |
+ SM(R12A_TXAGC_MCS9, power[RTWN_RIDX_HT_MCS(9)]) |
+ SM(R12A_TXAGC_MCS10, power[RTWN_RIDX_HT_MCS(10)]) |
+ SM(R12A_TXAGC_MCS11, power[RTWN_RIDX_HT_MCS(11)]));
rtwn_bb_write(sc, R12A_TXAGC_MCS15_12(chain),
- SM(R12A_TXAGC_MCS12, power[RTWN_RIDX_MCS(12)]) |
- SM(R12A_TXAGC_MCS13, power[RTWN_RIDX_MCS(13)]) |
- SM(R12A_TXAGC_MCS14, power[RTWN_RIDX_MCS(14)]) |
- SM(R12A_TXAGC_MCS15, power[RTWN_RIDX_MCS(15)]));
+ SM(R12A_TXAGC_MCS12, power[RTWN_RIDX_HT_MCS(12)]) |
+ SM(R12A_TXAGC_MCS13, power[RTWN_RIDX_HT_MCS(13)]) |
+ SM(R12A_TXAGC_MCS14, power[RTWN_RIDX_HT_MCS(14)]) |
+ SM(R12A_TXAGC_MCS15, power[RTWN_RIDX_HT_MCS(15)]));
}
/* TODO: VHT rates */
@@ -178,7 +178,7 @@ r12a_get_txpower(struct rtwn_softc *sc, int chain,
}
/* TODO: VHT rates. */
- max_mcs = RTWN_RIDX_MCS(sc->ntxchains * 8 - 1);
+ max_mcs = RTWN_RIDX_HT_MCS(sc->ntxchains * 8 - 1);
/* XXX regulatory */
/* XXX net80211 regulatory */
@@ -207,7 +207,7 @@ r12a_get_txpower(struct rtwn_softc *sc, int chain,
else
pwr_diff = rs->bw20_tx_pwr_diff_2g[chain][i];
- min_mcs = RTWN_RIDX_MCS(i * 8);
+ min_mcs = RTWN_RIDX_HT_MCS(i * 8);
for (ridx = min_mcs; ridx <= max_mcs; ridx++)
power[ridx] += pwr_diff;
}
@@ -233,7 +233,7 @@ r12a_get_txpower(struct rtwn_softc *sc, int chain,
else
pwr_diff = rs->bw20_tx_pwr_diff_5g[chain][i];
- min_mcs = RTWN_RIDX_MCS(i * 8);
+ min_mcs = RTWN_RIDX_HT_MCS(i * 8);
for (ridx = min_mcs; ridx <= max_mcs; ridx++)
power[ridx] += pwr_diff;
}
diff --git a/freebsd/sys/dev/rtwn/rtl8812a/r12a_rx.c b/freebsd/sys/dev/rtwn/rtl8812a/r12a_rx.c
index dd90d7e9..c2dc4c3a 100644
--- a/freebsd/sys/dev/rtwn/rtl8812a/r12a_rx.c
+++ b/freebsd/sys/dev/rtwn/rtl8812a/r12a_rx.c
@@ -264,7 +264,7 @@ r12a_get_rx_stats(struct rtwn_softc *sc, struct ieee80211_rx_stats *rxs,
rxs->c_pktflags |= IEEE80211_RX_F_AMPDU_MORE;
}
- if ((rxdw4 & R12A_RXDW4_SPLCP) && rate >= RTWN_RIDX_MCS(0))
+ if ((rxdw4 & R12A_RXDW4_SPLCP) && rate >= RTWN_RIDX_HT_MCS(0))
rxs->c_pktflags |= IEEE80211_RX_F_SHORTGI;
switch (MS(rxdw4, R12A_RXDW4_BW)) {
@@ -290,7 +290,7 @@ r12a_get_rx_stats(struct rtwn_softc *sc, struct ieee80211_rx_stats *rxs,
/* XXX check with RTL8812AU */
is5ghz = (physt->cfosho[2] != 0x01);
- if (rate < RTWN_RIDX_MCS(0)) {
+ if (rate < RTWN_RIDX_HT_MCS(0)) {
if (is5ghz)
rxs->c_phytype = IEEE80211_RX_FP_11A;
else
@@ -304,7 +304,7 @@ r12a_get_rx_stats(struct rtwn_softc *sc, struct ieee80211_rx_stats *rxs,
}
/* Map HW rate index to 802.11 rate. */
- if (rate < RTWN_RIDX_MCS(0)) {
+ if (rate < RTWN_RIDX_HT_MCS(0)) {
rxs->c_rate = ridx2rate[rate];
if (RTWN_RATE_IS_CCK(rate))
rxs->c_pktflags |= IEEE80211_RX_F_CCK;
diff --git a/freebsd/sys/dev/rtwn/rtl8812a/r12a_tx.c b/freebsd/sys/dev/rtwn/rtl8812a/r12a_tx.c
index 895f71e4..77e9e423 100644
--- a/freebsd/sys/dev/rtwn/rtl8812a/r12a_tx.c
+++ b/freebsd/sys/dev/rtwn/rtl8812a/r12a_tx.c
@@ -109,7 +109,7 @@ r12a_tx_protection(struct rtwn_softc *sc, struct r12a_tx_desc *txd,
if (mode == IEEE80211_PROT_CTSONLY ||
mode == IEEE80211_PROT_RTSCTS) {
- if (ridx >= RTWN_RIDX_MCS(0))
+ if (ridx >= RTWN_RIDX_HT_MCS(0))
rate = rtwn_ctl_mcsrate(ic->ic_rt, ridx);
else
rate = ieee80211_ctl_rate(ic->ic_rt, ridx2rate[ridx]);
@@ -294,7 +294,7 @@ r12a_fill_tx_desc(struct rtwn_softc *sc, struct ieee80211_node *ni,
txd->txdw5 |= htole32(R12A_TXDW5_DATA_SHORT);
prot = IEEE80211_PROT_NONE;
- if (ridx >= RTWN_RIDX_MCS(0)) {
+ if (ridx >= RTWN_RIDX_HT_MCS(0)) {
r12a_tx_set_ht40(sc, txd, ni);
r12a_tx_set_sgi(sc, txd, ni);
r12a_tx_set_ldpc(sc, txd, ni);
diff --git a/freebsd/sys/dev/sdhci/sdhci.c b/freebsd/sys/dev/sdhci/sdhci.c
index f1616a6e..8d1fed8f 100644
--- a/freebsd/sys/dev/sdhci/sdhci.c
+++ b/freebsd/sys/dev/sdhci/sdhci.c
@@ -1053,12 +1053,14 @@ no_tuning:
return (0);
}
+#ifndef MMCCAM
void
sdhci_start_slot(struct sdhci_slot *slot)
{
sdhci_card_task(slot, 0);
}
+#endif
int
sdhci_cleanup_slot(struct sdhci_slot *slot)
@@ -2398,7 +2400,7 @@ sdhci_generic_write_ivar(device_t bus, device_t child, int which,
#ifdef MMCCAM
void
-sdhci_cam_start_slot(struct sdhci_slot *slot)
+sdhci_start_slot(struct sdhci_slot *slot)
{
if ((slot->devq = cam_simq_alloc(1)) == NULL) {
goto fail;
diff --git a/freebsd/sys/dev/sdhci/sdhci.h b/freebsd/sys/dev/sdhci/sdhci.h
index 73aa84b6..ba66415f 100644
--- a/freebsd/sys/dev/sdhci/sdhci.h
+++ b/freebsd/sys/dev/sdhci/sdhci.h
@@ -430,9 +430,4 @@ bool sdhci_generic_get_card_present(device_t brdev, struct sdhci_slot *slot);
void sdhci_generic_set_uhs_timing(device_t brdev, struct sdhci_slot *slot);
void sdhci_handle_card_present(struct sdhci_slot *slot, bool is_present);
-#ifdef MMCCAM
-/* CAM-related */
-void sdhci_cam_start_slot(struct sdhci_slot *slot);
-#endif
-
#endif /* __SDHCI_H__ */
diff --git a/freebsd/sys/dev/smc/if_smc.c b/freebsd/sys/dev/smc/if_smc.c
index a018e09e..fd1a0960 100644
--- a/freebsd/sys/dev/smc/if_smc.c
+++ b/freebsd/sys/dev/smc/if_smc.c
@@ -784,7 +784,7 @@ smc_task_rx(void *context, int pending)
}
#ifdef DEVICE_POLLING
-static void
+static int
smc_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
{
struct smc_softc *sc;
@@ -794,12 +794,13 @@ smc_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
SMC_LOCK(sc);
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
SMC_UNLOCK(sc);
- return;
+ return (0);
}
SMC_UNLOCK(sc);
if (cmd == POLL_AND_CHECK_STATUS)
taskqueue_enqueue(sc->smc_tq, &sc->smc_intr);
+ return (0);
}
#endif
diff --git a/freebsd/sys/dev/usb/net/if_ure.c b/freebsd/sys/dev/usb/net/if_ure.c
index 27e3ecca..89ce723b 100644
--- a/freebsd/sys/dev/usb/net/if_ure.c
+++ b/freebsd/sys/dev/usb/net/if_ure.c
@@ -69,6 +69,7 @@ SYSCTL_INT(_hw_usb_ure, OID_AUTO, debug, CTLFLAG_RWTUN, &ure_debug, 0,
*/
static const STRUCT_USB_HOST_ID ure_devs[] = {
#define URE_DEV(v,p,i) { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, i) }
+ URE_DEV(LENOVO, RTL8153, 0),
URE_DEV(REALTEK, RTL8152, URE_FLAG_8152),
URE_DEV(REALTEK, RTL8153, 0),
#undef URE_DEV
diff --git a/freebsd/sys/dev/usb/quirk/usb_quirk.c b/freebsd/sys/dev/usb/quirk/usb_quirk.c
index a5fac1b3..3ea3f3c6 100644
--- a/freebsd/sys/dev/usb/quirk/usb_quirk.c
+++ b/freebsd/sys/dev/usb/quirk/usb_quirk.c
@@ -236,6 +236,7 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
UQ_MSC_FORCE_PROTO_RBC),
USB_QUIRK(INSYSTEM, STORAGE_V2, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
UQ_MSC_FORCE_PROTO_RBC),
+ USB_QUIRK(INTENSO, MEMORY_BOX, 0x0000, 0xffff, UQ_MSC_NO_INQUIRY),
USB_QUIRK(IODATA, IU_CD2, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI),
USB_QUIRK(IODATA, DVR_UEH8, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
@@ -335,7 +336,7 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_IGNORE_RESIDUE,
UQ_MSC_NO_START_STOP),
USB_QUIRK(PROLIFIC, PL2506, 0x0000, 0xffff,
- UQ_MSC_NO_SYNC_CACHE),
+ UQ_MSC_NO_SYNC_CACHE, UQ_MSC_NO_PREVENT_ALLOW),
USB_QUIRK_VP(USB_VENDOR_SAMSUNG_TECHWIN,
USB_PRODUCT_SAMSUNG_TECHWIN_DIGIMAX_410, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
@@ -509,6 +510,7 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
USB_QUIRK(ROLAND, SD20, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
USB_QUIRK(ROLAND, SD80, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
USB_QUIRK(ROLAND, UA700, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
+ USB_QUIRK(ROLAND, PCR300, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
USB_QUIRK(EGO, M4U, 0x0000, 0xffff, UQ_SINGLE_CMD_MIDI),
USB_QUIRK(LOGILINK, U2M, 0x0000, 0xffff, UQ_SINGLE_CMD_MIDI),
USB_QUIRK(MEDELI, DD305, 0x0000, 0xffff, UQ_SINGLE_CMD_MIDI, UQ_MATCH_VENDOR_ONLY),
@@ -608,6 +610,7 @@ static const char *usb_quirk_str[USB_QUIRK_MAX] = {
[UQ_SINGLE_CMD_MIDI] = "UQ_SINGLE_CMD_MIDI",
[UQ_MSC_DYMO_EJECT] = "UQ_MSC_DYMO_EJECT",
[UQ_AU_SET_SPDIF_CM6206] = "UQ_AU_SET_SPDIF_CM6206",
+ [UQ_WMT_IGNORE] = "UQ_WMT_IGNORE",
};
/*------------------------------------------------------------------------*
diff --git a/freebsd/sys/dev/usb/quirk/usb_quirk.h b/freebsd/sys/dev/usb/quirk/usb_quirk.h
index f7e490ce..bb9fe190 100644
--- a/freebsd/sys/dev/usb/quirk/usb_quirk.h
+++ b/freebsd/sys/dev/usb/quirk/usb_quirk.h
@@ -110,6 +110,7 @@ enum {
UQ_SINGLE_CMD_MIDI, /* at most one command per USB packet */
UQ_MSC_DYMO_EJECT, /* ejects Dymo MSC device */
UQ_AU_SET_SPDIF_CM6206, /* enable S/PDIF audio output */
+ UQ_WMT_IGNORE, /* device should be ignored by wmt driver */
USB_QUIRK_MAX
};
diff --git a/freebsd/sys/dev/usb/usb_hid.c b/freebsd/sys/dev/usb/usb_hid.c
index 56e31a6e..5019aa1a 100644
--- a/freebsd/sys/dev/usb/usb_hid.c
+++ b/freebsd/sys/dev/usb/usb_hid.c
@@ -851,6 +851,80 @@ usbd_req_get_hid_desc(struct usb_device *udev, struct mtx *mtx,
}
/*------------------------------------------------------------------------*
+ * calculate HID item resolution. unit/mm for distances, unit/rad for angles
+ *------------------------------------------------------------------------*/
+int32_t
+hid_item_resolution(struct hid_item *hi)
+{
+ /*
+ * hid unit scaling table according to HID Usage Table Review
+ * Request 39 Tbl 17 http://www.usb.org/developers/hidpage/HUTRR39b.pdf
+ */
+ static const int64_t scale[0x10][2] = {
+ [0x00] = { 1, 1 },
+ [0x01] = { 1, 10 },
+ [0x02] = { 1, 100 },
+ [0x03] = { 1, 1000 },
+ [0x04] = { 1, 10000 },
+ [0x05] = { 1, 100000 },
+ [0x06] = { 1, 1000000 },
+ [0x07] = { 1, 10000000 },
+ [0x08] = { 100000000, 1 },
+ [0x09] = { 10000000, 1 },
+ [0x0A] = { 1000000, 1 },
+ [0x0B] = { 100000, 1 },
+ [0x0C] = { 10000, 1 },
+ [0x0D] = { 1000, 1 },
+ [0x0E] = { 100, 1 },
+ [0x0F] = { 10, 1 },
+ };
+ int64_t logical_size;
+ int64_t physical_size;
+ int64_t multiplier;
+ int64_t divisor;
+ int64_t resolution;
+
+ switch (hi->unit) {
+ case HUM_CENTIMETER:
+ multiplier = 1;
+ divisor = 10;
+ break;
+ case HUM_INCH:
+ multiplier = 10;
+ divisor = 254;
+ break;
+ case HUM_RADIAN:
+ multiplier = 1;
+ divisor = 1;
+ break;
+ case HUM_DEGREE:
+ multiplier = 573;
+ divisor = 10;
+ break;
+ default:
+ return (0);
+ }
+
+ if ((hi->logical_maximum <= hi->logical_minimum) ||
+ (hi->physical_maximum <= hi->physical_minimum) ||
+ (hi->unit_exponent < 0) || (hi->unit_exponent >= nitems(scale)))
+ return (0);
+
+ logical_size = (int64_t)hi->logical_maximum -
+ (int64_t)hi->logical_minimum;
+ physical_size = (int64_t)hi->physical_maximum -
+ (int64_t)hi->physical_minimum;
+ /* Round to ceiling */
+ resolution = logical_size * multiplier * scale[hi->unit_exponent][0] /
+ (physical_size * divisor * scale[hi->unit_exponent][1]);
+
+ if (resolution > INT32_MAX)
+ return (0);
+
+ return (resolution);
+}
+
+/*------------------------------------------------------------------------*
* hid_is_mouse
*
* This function will decide if a USB descriptor belongs to a USB mouse.
diff --git a/freebsd/sys/dev/usb/usb_hub.c b/freebsd/sys/dev/usb/usb_hub.c
index e70be43b..0eaeeb60 100644
--- a/freebsd/sys/dev/usb/usb_hub.c
+++ b/freebsd/sys/dev/usb/usb_hub.c
@@ -102,7 +102,9 @@ SYSCTL_INT(_hw_usb, OID_AUTO, power_timeout, CTLFLAG_RWTUN,
#if USB_HAVE_DISABLE_ENUM
static int usb_disable_enumeration = 0;
SYSCTL_INT(_hw_usb, OID_AUTO, disable_enumeration, CTLFLAG_RWTUN,
- &usb_disable_enumeration, 0, "Set to disable all USB device enumeration.");
+ &usb_disable_enumeration, 0, "Set to disable all USB device enumeration. "
+ "This can secure against USB devices turning evil, "
+ "for example a USB memory stick becoming a USB keyboard.");
static int usb_disable_port_power = 0;
SYSCTL_INT(_hw_usb, OID_AUTO, disable_port_power, CTLFLAG_RWTUN,
diff --git a/freebsd/sys/dev/usb/usbhid.h b/freebsd/sys/dev/usb/usbhid.h
index 28dfede2..31aa7ea4 100644
--- a/freebsd/sys/dev/usb/usbhid.h
+++ b/freebsd/sys/dev/usb/usbhid.h
@@ -134,6 +134,12 @@ struct usb_hid_descriptor {
/* Usages Digitizers */
#define HUD_UNDEFINED 0x0000
+#define HUD_DIGITIZER 0x0001
+#define HUD_PEN 0x0002
+#define HUD_TOUCHSCREEN 0x0004
+#define HUD_TOUCHPAD 0x0005
+#define HUD_CONFIG 0x000e
+#define HUD_FINGER 0x0022
#define HUD_TIP_PRESSURE 0x0030
#define HUD_BARREL_PRESSURE 0x0031
#define HUD_IN_RANGE 0x0032
@@ -157,6 +163,16 @@ struct usb_hid_descriptor {
#define HUD_BARREL_SWITCH 0x0044
#define HUD_ERASER 0x0045
#define HUD_TABLET_PICK 0x0046
+#define HUD_CONFIDENCE 0x0047
+#define HUD_WIDTH 0x0048
+#define HUD_HEIGHT 0x0049
+#define HUD_CONTACTID 0x0051
+#define HUD_INPUT_MODE 0x0052
+#define HUD_DEVICE_INDEX 0x0053
+#define HUD_CONTACTCOUNT 0x0054
+#define HUD_CONTACT_MAX 0x0055
+#define HUD_SCAN_TIME 0x0056
+#define HUD_BUTTON_TYPE 0x0059
/* Usages, Consumer */
#define HUC_AC_PAN 0x0238
@@ -178,6 +194,12 @@ struct usb_hid_descriptor {
#define HIO_VOLATILE 0x080
#define HIO_BUFBYTES 0x100
+/* Units of Measure */
+#define HUM_CENTIMETER 0x11
+#define HUM_RADIAN 0x12
+#define HUM_INCH 0x13
+#define HUM_DEGREE 0x14
+
#ifdef _KERNEL
struct usb_config_descriptor;
@@ -244,6 +266,7 @@ struct usb_hid_descriptor *hid_get_descriptor_from_usb(
usb_error_t usbd_req_get_hid_desc(struct usb_device *udev, struct mtx *mtx,
void **descp, uint16_t *sizep, struct malloc_type *mem,
uint8_t iface_index);
+int32_t hid_item_resolution(struct hid_item *hi);
int hid_is_mouse(const void *d_ptr, uint16_t d_len);
int hid_is_keyboard(const void *d_ptr, uint16_t d_len);
#endif /* _KERNEL */
diff --git a/freebsd/sys/dev/usb/wlan/if_uath.c b/freebsd/sys/dev/usb/wlan/if_uath.c
index c3435d57..c4ebe5ed 100644
--- a/freebsd/sys/dev/usb/wlan/if_uath.c
+++ b/freebsd/sys/dev/usb/wlan/if_uath.c
@@ -2203,17 +2203,19 @@ uath_sysctl_node(struct uath_softc *sc)
#undef UATH_SYSCTL_STAT_ADD32
+CTASSERT(sizeof(u_int) >= sizeof(uint32_t));
+
static void
uath_cmdeof(struct uath_softc *sc, struct uath_cmd *cmd)
{
struct uath_cmd_hdr *hdr;
- int dlen;
+ uint32_t dlen;
hdr = (struct uath_cmd_hdr *)cmd->buf;
/* NB: msgid is passed thru w/o byte swapping */
#ifdef UATH_DEBUG
if (sc->sc_debug & UATH_DEBUG_CMDS) {
- int len = be32toh(hdr->len);
+ uint32_t len = be32toh(hdr->len);
printf("%s: %s [ix %u] len %u status %u\n",
__func__, uath_codename(be32toh(hdr->code)),
hdr->msgid, len, be32toh(hdr->magic));
@@ -2229,15 +2231,9 @@ uath_cmdeof(struct uath_softc *sc, struct uath_cmd *cmd)
switch (hdr->code & 0xff) {
/* reply to a read command */
default:
- dlen = hdr->len - sizeof(*hdr);
- if (dlen < 0) {
- device_printf(sc->sc_dev,
- "Invalid header length %d\n", dlen);
- return;
- }
DPRINTF(sc, UATH_DEBUG_RX_PROC | UATH_DEBUG_RECV_ALL,
- "%s: code %d data len %u\n",
- __func__, hdr->code & 0xff, dlen);
+ "%s: code %d hdr len %u\n",
+ __func__, hdr->code & 0xff, hdr->len);
/*
* The first response from the target after the
* HOST_AVAILABLE has an invalid msgid so we must
@@ -2247,8 +2243,8 @@ uath_cmdeof(struct uath_softc *sc, struct uath_cmd *cmd)
uint32_t *rp = (uint32_t *)(hdr+1);
u_int olen;
- if (!(sizeof(*hdr) <= hdr->len &&
- hdr->len < UATH_MAX_CMDSZ)) {
+ if (sizeof(*hdr) > hdr->len ||
+ hdr->len >= UATH_MAX_CMDSZ) {
device_printf(sc->sc_dev,
"%s: invalid WDC msg length %u; "
"msg ignored\n", __func__, hdr->len);
@@ -2260,7 +2256,8 @@ uath_cmdeof(struct uath_softc *sc, struct uath_cmd *cmd)
* number of bytes--unless it's 0 in which
* case a single 32-bit word should be present.
*/
- if (dlen >= (int)sizeof(uint32_t)) {
+ dlen = hdr->len - sizeof(*hdr);
+ if (dlen >= sizeof(uint32_t)) {
olen = be32toh(rp[0]);
dlen -= sizeof(uint32_t);
if (olen == 0) {
@@ -2280,7 +2277,7 @@ uath_cmdeof(struct uath_softc *sc, struct uath_cmd *cmd)
cmd->olen);
olen = cmd->olen;
}
- if (olen > (u_int)dlen) {
+ if (olen > dlen) {
/* XXX complain, shouldn't happen */
device_printf(sc->sc_dev,
"%s: cmd 0x%x olen %u dlen %u\n",
@@ -2302,8 +2299,10 @@ uath_cmdeof(struct uath_softc *sc, struct uath_cmd *cmd)
return;
}
dlen = hdr->len - sizeof(*hdr);
- if (dlen != (int)sizeof(uint32_t)) {
- /* XXX something wrong */
+ if (dlen != sizeof(uint32_t)) {
+ device_printf(sc->sc_dev,
+ "%s: dlen (%u) != %zu!\n",
+ __func__, dlen, sizeof(uint32_t));
return;
}
/* XXX have submitter do this */
@@ -2332,6 +2331,7 @@ uath_intr_rx_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct uath_softc *sc = usbd_xfer_softc(xfer);
struct uath_cmd *cmd;
+ struct uath_cmd_hdr *hdr;
struct usb_page_cache *pc;
int actlen;
@@ -2349,10 +2349,25 @@ uath_intr_rx_callback(struct usb_xfer *xfer, usb_error_t error)
STAILQ_INSERT_TAIL(&sc->sc_cmd_inactive, cmd, next);
UATH_STAT_INC(sc, st_cmd_inactive);
- KASSERT(actlen >= (int)sizeof(struct uath_cmd_hdr),
- ("short xfer error"));
+ if (actlen < sizeof(struct uath_cmd_hdr)) {
+ device_printf(sc->sc_dev,
+ "%s: short xfer error (actlen %d)\n",
+ __func__, actlen);
+ goto setup;
+ }
+
pc = usbd_xfer_get_frame(xfer, 0);
usbd_copy_out(pc, 0, cmd->buf, actlen);
+
+ hdr = (struct uath_cmd_hdr *)cmd->buf;
+ hdr->len = be32toh(hdr->len);
+ if (hdr->len > (uint32_t)actlen) {
+ device_printf(sc->sc_dev,
+ "%s: truncated xfer (len %u, actlen %d)\n",
+ __func__, hdr->len, actlen);
+ goto setup;
+ }
+
uath_cmdeof(sc, cmd);
case USB_ST_SETUP:
setup:
@@ -2453,6 +2468,8 @@ uath_update_rxstat(struct uath_softc *sc, uint32_t status)
}
}
+CTASSERT(UATH_MIN_RXBUFSZ >= sizeof(struct uath_chunk));
+
static struct mbuf *
uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data,
struct uath_rx_desc **pdesc)
@@ -2475,13 +2492,24 @@ uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data,
}
chunk = (struct uath_chunk *)data->buf;
- if (chunk->seqnum == 0 && chunk->flags == 0 && chunk->length == 0) {
+ chunklen = be16toh(chunk->length);
+ if (chunk->seqnum == 0 && chunk->flags == 0 && chunklen == 0) {
device_printf(sc->sc_dev, "%s: strange response\n", __func__);
counter_u64_add(ic->ic_ierrors, 1);
UATH_RESET_INTRX(sc);
return (NULL);
}
+ if (chunklen > actlen) {
+ device_printf(sc->sc_dev,
+ "%s: invalid chunk length (len %u > actlen %d)\n",
+ __func__, chunklen, actlen);
+ counter_u64_add(ic->ic_ierrors, 1);
+ /* XXX cleanup? */
+ UATH_RESET_INTRX(sc);
+ return (NULL);
+ }
+
if (chunk->seqnum != sc->sc_intrx_nextnum) {
DPRINTF(sc, UATH_DEBUG_XMIT, "invalid seqnum %d, expected %d\n",
chunk->seqnum, sc->sc_intrx_nextnum);
@@ -2498,9 +2526,19 @@ uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data,
chunk->flags & UATH_CFLAGS_RXMSG)
UATH_STAT_INC(sc, st_multichunk);
- chunklen = be16toh(chunk->length);
- if (chunk->flags & UATH_CFLAGS_FINAL)
+ if (chunk->flags & UATH_CFLAGS_FINAL) {
+ if (chunklen < sizeof(struct uath_rx_desc)) {
+ device_printf(sc->sc_dev,
+ "%s: invalid chunk length %d\n",
+ __func__, chunklen);
+ counter_u64_add(ic->ic_ierrors, 1);
+ if (sc->sc_intrx_head != NULL)
+ m_freem(sc->sc_intrx_head);
+ UATH_RESET_INTRX(sc);
+ return (NULL);
+ }
chunklen -= sizeof(struct uath_rx_desc);
+ }
if (chunklen > 0 &&
(!(chunk->flags & UATH_CFLAGS_FINAL) || !(chunk->seqnum == 0))) {
@@ -2561,6 +2599,19 @@ uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data,
(struct uath_rx_desc *)(((uint8_t *)chunk) +
sizeof(struct uath_chunk) + be16toh(chunk->length) -
sizeof(struct uath_rx_desc));
+ if ((uint8_t *)chunk + actlen - sizeof(struct uath_rx_desc) <
+ (uint8_t *)desc) {
+ device_printf(sc->sc_dev,
+ "%s: wrong Rx descriptor pointer "
+ "(desc %p chunk %p actlen %d)\n",
+ __func__, desc, chunk, actlen);
+ counter_u64_add(ic->ic_ierrors, 1);
+ if (sc->sc_intrx_head != NULL)
+ m_freem(sc->sc_intrx_head);
+ UATH_RESET_INTRX(sc);
+ return (NULL);
+ }
+
*pdesc = desc;
DPRINTF(sc, UATH_DEBUG_RECV | UATH_DEBUG_RECV_ALL,
@@ -2588,8 +2639,33 @@ uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data,
/* finalize mbuf */
if (sc->sc_intrx_head == NULL) {
- m->m_pkthdr.len = m->m_len =
- be32toh(desc->framelen) - UATH_RX_DUMMYSIZE;
+ uint32_t framelen;
+
+ if (be32toh(desc->framelen) < UATH_RX_DUMMYSIZE) {
+ device_printf(sc->sc_dev,
+ "%s: framelen too small (%u)\n",
+ __func__, be32toh(desc->framelen));
+ counter_u64_add(ic->ic_ierrors, 1);
+ if (sc->sc_intrx_head != NULL)
+ m_freem(sc->sc_intrx_head);
+ UATH_RESET_INTRX(sc);
+ return (NULL);
+ }
+
+ framelen = be32toh(desc->framelen) - UATH_RX_DUMMYSIZE;
+ if (framelen > actlen - sizeof(struct uath_chunk) ||
+ framelen < sizeof(struct ieee80211_frame_ack)) {
+ device_printf(sc->sc_dev,
+ "%s: wrong frame length (%u, actlen %d)!\n",
+ __func__, framelen, actlen);
+ counter_u64_add(ic->ic_ierrors, 1);
+ if (sc->sc_intrx_head != NULL)
+ m_freem(sc->sc_intrx_head);
+ UATH_RESET_INTRX(sc);
+ return (NULL);
+ }
+
+ m->m_pkthdr.len = m->m_len = framelen;
m->m_data += sizeof(struct uath_chunk);
} else {
mp = sc->sc_intrx_head;
diff --git a/freebsd/sys/fs/devfs/devfs_vnops.c b/freebsd/sys/fs/devfs/devfs_vnops.c
index 85c0af86..fcf69a1a 100644
--- a/freebsd/sys/fs/devfs/devfs_vnops.c
+++ b/freebsd/sys/fs/devfs/devfs_vnops.c
@@ -1193,6 +1193,24 @@ devfs_pathconf(struct vop_pathconf_args *ap)
{
switch (ap->a_name) {
+ case _PC_MAX_CANON:
+ if (ap->a_vp->v_vflag & VV_ISTTY) {
+ *ap->a_retval = MAX_CANON;
+ return (0);
+ }
+ return (EINVAL);
+ case _PC_MAX_INPUT:
+ if (ap->a_vp->v_vflag & VV_ISTTY) {
+ *ap->a_retval = MAX_INPUT;
+ return (0);
+ }
+ return (EINVAL);
+ case _PC_VDISABLE:
+ if (ap->a_vp->v_vflag & VV_ISTTY) {
+ *ap->a_retval = _POSIX_VDISABLE;
+ return (0);
+ }
+ return (EINVAL);
case _PC_MAC_PRESENT:
#ifdef MAC
/*
diff --git a/freebsd/sys/i386/include/machine/cpufunc.h b/freebsd/sys/i386/include/machine/cpufunc.h
index 923d28ea..a311cd1d 100644
--- a/freebsd/sys/i386/include/machine/cpufunc.h
+++ b/freebsd/sys/i386/include/machine/cpufunc.h
@@ -62,7 +62,7 @@ breakpoint(void)
}
#endif
-static __inline u_int
+static __inline __pure2 u_int
bsfl(u_int mask)
{
u_int result;
@@ -71,7 +71,7 @@ bsfl(u_int mask)
return (result);
}
-static __inline u_int
+static __inline __pure2 u_int
bsrl(u_int mask)
{
u_int result;
@@ -172,7 +172,7 @@ sfence(void)
#ifndef __rtems__
#define HAVE_INLINE_FFS
-static __inline int
+static __inline __pure2 int
ffs(int mask)
{
/*
@@ -186,7 +186,7 @@ ffs(int mask)
#define HAVE_INLINE_FFSL
-static __inline int
+static __inline __pure2 int
ffsl(long mask)
{
return (ffs((int)mask));
@@ -196,7 +196,7 @@ ffsl(long mask)
#endif /* __rtems__ */
#ifndef __rtems__
-static __inline int
+static __inline __pure2 int
fls(int mask)
{
return (mask == 0 ? mask : (int)bsrl((u_int)mask) + 1);
@@ -205,7 +205,7 @@ fls(int mask)
#define HAVE_INLINE_FLSL
-static __inline int
+static __inline __pure2 int
flsl(long mask)
{
return (fls((int)mask));
diff --git a/freebsd/sys/i386/include/machine/intr_machdep.h b/freebsd/sys/i386/include/machine/intr_machdep.h
index a8dd4564..5892d07c 100644
--- a/freebsd/sys/i386/include/machine/intr_machdep.h
+++ b/freebsd/sys/i386/include/machine/intr_machdep.h
@@ -130,6 +130,7 @@ struct intsrc {
u_long *is_straycount;
u_int is_index;
u_int is_handlers;
+ u_int is_cpu;
};
struct trapframe;
diff --git a/freebsd/sys/i386/include/machine/md_var.h b/freebsd/sys/i386/include/machine/md_var.h
index c93d70c8..2ca8c856 100644
--- a/freebsd/sys/i386/include/machine/md_var.h
+++ b/freebsd/sys/i386/include/machine/md_var.h
@@ -59,7 +59,6 @@ void doreti_popl_es(void) __asm(__STRING(doreti_popl_es));
void doreti_popl_es_fault(void) __asm(__STRING(doreti_popl_es_fault));
void doreti_popl_fs(void) __asm(__STRING(doreti_popl_fs));
void doreti_popl_fs_fault(void) __asm(__STRING(doreti_popl_fs_fault));
-void finishidentcpu(void);
void fill_based_sd(struct segment_descriptor *sdp, uint32_t base);
void i686_pagezero(void *addr);
void sse2_pagezero(void *addr);
diff --git a/freebsd/sys/kern/kern_sysctl.c b/freebsd/sys/kern/kern_sysctl.c
index 90b15444..e99a8bd6 100644
--- a/freebsd/sys/kern/kern_sysctl.c
+++ b/freebsd/sys/kern/kern_sysctl.c
@@ -90,7 +90,7 @@ static MALLOC_DEFINE(M_SYSCTLTMP, "sysctltmp", "sysctl temp output buffer");
* sysctl requests larger than a single page via an exclusive lock.
*/
static struct rmlock sysctllock;
-static struct sx sysctlmemlock;
+static struct sx __exclusive_cache_line sysctlmemlock;
#define SYSCTL_WLOCK() rm_wlock(&sysctllock)
#define SYSCTL_WUNLOCK() rm_wunlock(&sysctllock)
@@ -327,6 +327,91 @@ sysctl_load_tunable_by_oid_locked(struct sysctl_oid *oidp)
}
#endif /* __rtems__ */
+static int
+sbuf_printf_drain(void *arg __unused, const char *data, int len)
+{
+
+ return (printf("%.*s", len, data));
+}
+
+/*
+ * Locate the path to a given oid. Returns the length of the resulting path,
+ * or -1 if the oid was not found. nodes must have room for CTL_MAXNAME
+ * elements and be NULL initialized.
+ */
+static int
+sysctl_search_oid(struct sysctl_oid **nodes, struct sysctl_oid *needle)
+{
+ int indx;
+
+ SYSCTL_ASSERT_LOCKED();
+ indx = 0;
+ while (indx < CTL_MAXNAME && indx >= 0) {
+ if (nodes[indx] == NULL && indx == 0)
+ nodes[indx] = SLIST_FIRST(&sysctl__children);
+ else if (nodes[indx] == NULL)
+ nodes[indx] = SLIST_FIRST(&nodes[indx - 1]->oid_children);
+ else
+ nodes[indx] = SLIST_NEXT(nodes[indx], oid_link);
+
+ if (nodes[indx] == needle)
+ return (indx + 1);
+
+ if (nodes[indx] == NULL) {
+ indx--;
+ continue;
+ }
+
+ if ((nodes[indx]->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
+ indx++;
+ continue;
+ }
+ }
+ return (-1);
+}
+
+static void
+sysctl_warn_reuse(const char *func, struct sysctl_oid *leaf)
+{
+ struct sysctl_oid *nodes[CTL_MAXNAME];
+ char buf[128];
+ struct sbuf sb;
+ int rc, i;
+
+ (void)sbuf_new(&sb, buf, sizeof(buf), SBUF_FIXEDLEN | SBUF_INCLUDENUL);
+ sbuf_set_drain(&sb, sbuf_printf_drain, NULL);
+
+ sbuf_printf(&sb, "%s: can't re-use a leaf (", __func__);
+
+ memset(nodes, 0, sizeof(nodes));
+ rc = sysctl_search_oid(nodes, leaf);
+ if (rc > 0) {
+ for (i = 0; i < rc; i++)
+ sbuf_printf(&sb, "%s%.*s", nodes[i]->oid_name,
+ i != (rc - 1), ".");
+ } else {
+ sbuf_printf(&sb, "%s", leaf->oid_name);
+ }
+ sbuf_printf(&sb, ")!\n");
+
+ (void)sbuf_finish(&sb);
+}
+
+#ifdef SYSCTL_DEBUG
+static int
+sysctl_reuse_test(SYSCTL_HANDLER_ARGS)
+{
+ struct rm_priotracker tracker;
+
+ SYSCTL_RLOCK(&tracker);
+ sysctl_warn_reuse(__func__, oidp);
+ SYSCTL_RUNLOCK(&tracker);
+ return (0);
+}
+SYSCTL_PROC(_sysctl, 0, reuse_test, CTLTYPE_STRING|CTLFLAG_RD|CTLFLAG_MPSAFE,
+ 0, 0, sysctl_reuse_test, "-", "");
+#endif
+
void
sysctl_register_oid(struct sysctl_oid *oidp)
{
@@ -347,7 +432,7 @@ sysctl_register_oid(struct sysctl_oid *oidp)
p->oid_refcnt++;
return;
} else {
- printf("can't re-use a leaf (%s)!\n", p->oid_name);
+ sysctl_warn_reuse(__func__, p);
return;
}
}
@@ -721,8 +806,8 @@ sysctl_add_oid(struct sysctl_ctx_list *clist, struct sysctl_oid_list *parent,
SYSCTL_WUNLOCK();
return (oidp);
} else {
+ sysctl_warn_reuse(__func__, oidp);
SYSCTL_WUNLOCK();
- printf("can't re-use a leaf (%s)!\n", name);
return (NULL);
}
}
@@ -2005,16 +2090,9 @@ userland_sysctl(struct thread *td, int *name, u_int namelen, void *old,
}
}
req.validlen = req.oldlen;
-
- if (old) {
- if (!useracc(old, req.oldlen, VM_PROT_WRITE))
- return (EFAULT);
- req.oldptr= old;
- }
+ req.oldptr = old;
if (new != NULL) {
- if (!useracc(new, newlen, VM_PROT_READ))
- return (EFAULT);
req.newlen = newlen;
req.newptr = new;
}
diff --git a/freebsd/sys/kern/subr_blist.c b/freebsd/sys/kern/subr_blist.c
index c8e32c5b..7f232e93 100644
--- a/freebsd/sys/kern/subr_blist.c
+++ b/freebsd/sys/kern/subr_blist.c
@@ -34,14 +34,17 @@
* try to interpret the meaning of a 'block' other than to return
* SWAPBLK_NONE on an allocation failure.
*
- * A radix tree is used to maintain the bitmap. Two radix constants are
- * involved: One for the bitmaps contained in the leaf nodes (typically
- * 64), and one for the meta nodes (typically 16). Both meta and leaf
- * nodes have a hint field. This field gives us a hint as to the largest
- * free contiguous range of blocks under the node. It may contain a
- * value that is too high, but will never contain a value that is too
- * low. When the radix tree is searched, allocation failures in subtrees
- * update the hint.
+ * A radix tree controls access to pieces of the bitmap, and includes
+ * auxiliary information at each interior node about the availabilty of
+ * contiguous free blocks in the subtree rooted at that node. Two radix
+ * constants are involved: one for the size of the bitmaps contained in the
+ * leaf nodes (BLIST_BMAP_RADIX), and one for the number of descendents of
+ * each of the meta (interior) nodes (BLIST_META_RADIX). Each subtree is
+ * associated with a range of blocks. The root of any subtree stores a
+ * hint field that defines an upper bound on the size of the largest
+ * allocation that can begin in the associated block range. A hint is an
+ * upper bound on a potential allocation, but not necessarily a tight upper
+ * bound.
*
* The radix tree also implements two collapsed states for meta nodes:
* the ALL-ALLOCATED state and the ALL-FREE state. If a meta node is
@@ -92,6 +95,7 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/blist.h>
#include <sys/malloc.h>
+#include <sys/sbuf.h>
#include <sys/proc.h>
#include <sys/mutex.h>
@@ -103,6 +107,7 @@ __FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/malloc.h>
+#include <sys/sbuf.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -112,6 +117,7 @@ __FBSDID("$FreeBSD$");
#define bitcount64(x) __bitcount64((uint64_t)(x))
#define malloc(a,b,c) calloc(a, 1)
#define free(a,b) free(a)
+static __inline int imax(int a, int b) { return (a > b ? a : b); }
#include <sys/blist.h>
@@ -122,29 +128,84 @@ void panic(const char *ctl, ...);
/*
* static support functions
*/
-static daddr_t blst_leaf_alloc(blmeta_t *scan, daddr_t blk, int count,
- daddr_t cursor);
-static daddr_t blst_meta_alloc(blmeta_t *scan, daddr_t blk, daddr_t count,
- daddr_t radix, daddr_t skip, daddr_t cursor);
+static daddr_t blst_leaf_alloc(blmeta_t *scan, daddr_t blk, int count);
+static daddr_t blst_meta_alloc(blmeta_t *scan, daddr_t cursor, daddr_t count,
+ u_daddr_t radix);
static void blst_leaf_free(blmeta_t *scan, daddr_t relblk, int count);
static void blst_meta_free(blmeta_t *scan, daddr_t freeBlk, daddr_t count,
- daddr_t radix, daddr_t skip, daddr_t blk);
+ u_daddr_t radix);
static void blst_copy(blmeta_t *scan, daddr_t blk, daddr_t radix,
- daddr_t skip, blist_t dest, daddr_t count);
+ blist_t dest, daddr_t count);
static daddr_t blst_leaf_fill(blmeta_t *scan, daddr_t blk, int count);
static daddr_t blst_meta_fill(blmeta_t *scan, daddr_t allocBlk, daddr_t count,
- daddr_t radix, daddr_t skip, daddr_t blk);
-static daddr_t blst_radix_init(blmeta_t *scan, daddr_t radix, daddr_t skip,
- daddr_t count);
+ u_daddr_t radix);
+static daddr_t blst_radix_init(blmeta_t *scan, daddr_t radix, daddr_t count);
#ifndef _KERNEL
static void blst_radix_print(blmeta_t *scan, daddr_t blk, daddr_t radix,
- daddr_t skip, int tab);
+ int tab);
#endif
#ifdef _KERNEL
static MALLOC_DEFINE(M_SWAP, "SWAP", "Swap space");
#endif
+_Static_assert(BLIST_BMAP_RADIX % BLIST_META_RADIX == 0,
+ "radix divisibility error");
+#define BLIST_BMAP_MASK (BLIST_BMAP_RADIX - 1)
+#define BLIST_META_MASK (BLIST_META_RADIX - 1)
+
+/*
+ * For a subtree that can represent the state of up to 'radix' blocks, the
+ * number of leaf nodes of the subtree is L=radix/BLIST_BMAP_RADIX. If 'm'
+ * is short for BLIST_META_RADIX, then for a tree of height h with L=m**h
+ * leaf nodes, the total number of tree nodes is 1 + m + m**2 + ... + m**h,
+ * or, equivalently, (m**(h+1)-1)/(m-1). This quantity is called 'skip'
+ * in the 'meta' functions that process subtrees. Since integer division
+ * discards remainders, we can express this computation as
+ * skip = (m * m**h) / (m - 1)
+ * skip = (m * (radix / BLIST_BMAP_RADIX)) / (m - 1)
+ * and since m divides BLIST_BMAP_RADIX, we can simplify further to
+ * skip = (radix / (BLIST_BMAP_RADIX / m)) / (m - 1)
+ * skip = radix / ((BLIST_BMAP_RADIX / m) * (m - 1))
+ * so that simple integer division by a constant can safely be used for the
+ * calculation.
+ */
+static inline daddr_t
+radix_to_skip(daddr_t radix)
+{
+
+ return (radix /
+ ((BLIST_BMAP_RADIX / BLIST_META_RADIX) * BLIST_META_MASK));
+}
+
+/*
+ * Use binary search, or a faster method, to find the 1 bit in a u_daddr_t.
+ * Assumes that the argument has only one bit set.
+ */
+static inline int
+bitpos(u_daddr_t mask)
+{
+ int hi, lo, mid;
+
+ switch (sizeof(mask)) {
+#ifdef HAVE_INLINE_FFSLL
+ case sizeof(long long):
+ return (ffsll(mask) - 1);
+#endif
+ default:
+ lo = 0;
+ hi = BLIST_BMAP_RADIX;
+ while (lo + 1 < hi) {
+ mid = (lo + hi) >> 1;
+ if ((mask >> mid) != 0)
+ lo = mid;
+ else
+ hi = mid;
+ }
+ return (lo);
+ }
+}
+
/*
* blist_create() - create a blist capable of handling up to the specified
* number of blocks
@@ -159,18 +220,16 @@ blist_t
blist_create(daddr_t blocks, int flags)
{
blist_t bl;
- daddr_t nodes, radix, skip;
+ daddr_t nodes, radix;
/*
- * Calculate radix and skip field used for scanning.
+ * Calculate the radix field used for scanning.
*/
radix = BLIST_BMAP_RADIX;
- skip = 0;
while (radix < blocks) {
radix *= BLIST_META_RADIX;
- skip = (skip + 1) * BLIST_META_RADIX;
}
- nodes = 1 + blst_radix_init(NULL, radix, skip, blocks);
+ nodes = 1 + blst_radix_init(NULL, radix, blocks);
bl = malloc(sizeof(struct blist), M_SWAP, flags);
if (bl == NULL)
@@ -178,14 +237,13 @@ blist_create(daddr_t blocks, int flags)
bl->bl_blocks = blocks;
bl->bl_radix = radix;
- bl->bl_skip = skip;
bl->bl_cursor = 0;
bl->bl_root = malloc(nodes * sizeof(blmeta_t), M_SWAP, flags);
if (bl->bl_root == NULL) {
free(bl, M_SWAP);
return (NULL);
}
- blst_radix_init(bl->bl_root, radix, skip, blocks);
+ blst_radix_init(bl->bl_root, radix, blocks);
#if defined(BLIST_DEBUG)
printf(
@@ -226,10 +284,12 @@ blist_alloc(blist_t bl, daddr_t count)
* reduce the hint, stopping further iterations.
*/
while (count <= bl->bl_root->bm_bighint) {
- blk = blst_meta_alloc(bl->bl_root, 0, count, bl->bl_radix,
- bl->bl_skip, bl->bl_cursor);
+ blk = blst_meta_alloc(bl->bl_root, bl->bl_cursor, count,
+ bl->bl_radix);
if (blk != SWAPBLK_NONE) {
bl->bl_cursor = blk + count;
+ if (bl->bl_cursor == bl->bl_blocks)
+ bl->bl_cursor = 0;
return (blk);
} else if (bl->bl_cursor != 0)
bl->bl_cursor = 0;
@@ -259,7 +319,7 @@ void
blist_free(blist_t bl, daddr_t blkno, daddr_t count)
{
- blst_meta_free(bl->bl_root, blkno, count, bl->bl_radix, bl->bl_skip, 0);
+ blst_meta_free(bl->bl_root, blkno, count, bl->bl_radix);
}
/*
@@ -272,8 +332,7 @@ daddr_t
blist_fill(blist_t bl, daddr_t blkno, daddr_t count)
{
- return (blst_meta_fill(bl->bl_root, blkno, count, bl->bl_radix,
- bl->bl_skip, 0));
+ return (blst_meta_fill(bl->bl_root, blkno, count, bl->bl_radix));
}
/*
@@ -292,7 +351,7 @@ blist_resize(blist_t *pbl, daddr_t count, int freenew, int flags)
*pbl = newbl;
if (count > save->bl_blocks)
count = save->bl_blocks;
- blst_copy(save->bl_root, 0, save->bl_radix, save->bl_skip, newbl, count);
+ blst_copy(save->bl_root, 0, save->bl_radix, newbl, count);
/*
* If resizing upwards, should we free the new space or not?
@@ -311,13 +370,199 @@ blist_resize(blist_t *pbl, daddr_t count, int freenew, int flags)
void
blist_print(blist_t bl)
{
- printf("BLIST {\n");
- blst_radix_print(bl->bl_root, 0, bl->bl_radix, bl->bl_skip, 4);
+ printf("BLIST cursor = %08jx {\n", (uintmax_t)bl->bl_cursor);
+ blst_radix_print(bl->bl_root, 0, bl->bl_radix, 4);
printf("}\n");
}
#endif
+static const u_daddr_t fib[] = {
+ 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584,
+ 4181, 6765, 10946, 17711, 28657, 46368, 75025, 121393, 196418, 317811,
+ 514229, 832040, 1346269, 2178309, 3524578,
+};
+
+/*
+ * Use 'gap' to describe a maximal range of unallocated blocks/bits.
+ */
+struct gap_stats {
+ daddr_t start; /* current gap start, or SWAPBLK_NONE */
+ daddr_t num; /* number of gaps observed */
+ daddr_t max; /* largest gap size */
+ daddr_t avg; /* average gap size */
+ daddr_t err; /* sum - num * avg */
+ daddr_t histo[nitems(fib)]; /* # gaps in each size range */
+ int max_bucket; /* last histo elt with nonzero val */
+};
+
+/*
+ * gap_stats_counting() - is the state 'counting 1 bits'?
+ * or 'skipping 0 bits'?
+ */
+static inline bool
+gap_stats_counting(const struct gap_stats *stats)
+{
+
+ return (stats->start != SWAPBLK_NONE);
+}
+
+/*
+ * init_gap_stats() - initialize stats on gap sizes
+ */
+static inline void
+init_gap_stats(struct gap_stats *stats)
+{
+
+ bzero(stats, sizeof(*stats));
+ stats->start = SWAPBLK_NONE;
+}
+
+/*
+ * update_gap_stats() - update stats on gap sizes
+ */
+static void
+update_gap_stats(struct gap_stats *stats, daddr_t posn)
+{
+ daddr_t size;
+ int hi, lo, mid;
+
+ if (!gap_stats_counting(stats)) {
+ stats->start = posn;
+ return;
+ }
+ size = posn - stats->start;
+ stats->start = SWAPBLK_NONE;
+ if (size > stats->max)
+ stats->max = size;
+
+ /*
+ * Find the fibonacci range that contains size,
+ * expecting to find it in an early range.
+ */
+ lo = 0;
+ hi = 1;
+ while (hi < nitems(fib) && fib[hi] <= size) {
+ lo = hi;
+ hi *= 2;
+ }
+ if (hi >= nitems(fib))
+ hi = nitems(fib);
+ while (lo + 1 != hi) {
+ mid = (lo + hi) >> 1;
+ if (fib[mid] <= size)
+ lo = mid;
+ else
+ hi = mid;
+ }
+ stats->histo[lo]++;
+ if (lo > stats->max_bucket)
+ stats->max_bucket = lo;
+ stats->err += size - stats->avg;
+ stats->num++;
+ stats->avg += stats->err / stats->num;
+ stats->err %= stats->num;
+}
+
+/*
+ * dump_gap_stats() - print stats on gap sizes
+ */
+static inline void
+dump_gap_stats(const struct gap_stats *stats, struct sbuf *s)
+{
+ int i;
+
+ sbuf_printf(s, "number of maximal free ranges: %jd\n",
+ (intmax_t)stats->num);
+ sbuf_printf(s, "largest free range: %jd\n", (intmax_t)stats->max);
+ sbuf_printf(s, "average maximal free range size: %jd\n",
+ (intmax_t)stats->avg);
+ sbuf_printf(s, "number of maximal free ranges of different sizes:\n");
+ sbuf_printf(s, " count | size range\n");
+ sbuf_printf(s, " ----- | ----------\n");
+ for (i = 0; i < stats->max_bucket; i++) {
+ if (stats->histo[i] != 0) {
+ sbuf_printf(s, "%20jd | ",
+ (intmax_t)stats->histo[i]);
+ if (fib[i] != fib[i + 1] - 1)
+ sbuf_printf(s, "%jd to %jd\n", (intmax_t)fib[i],
+ (intmax_t)fib[i + 1] - 1);
+ else
+ sbuf_printf(s, "%jd\n", (intmax_t)fib[i]);
+ }
+ }
+ sbuf_printf(s, "%20jd | ", (intmax_t)stats->histo[i]);
+ if (stats->histo[i] > 1)
+ sbuf_printf(s, "%jd to %jd\n", (intmax_t)fib[i],
+ (intmax_t)stats->max);
+ else
+ sbuf_printf(s, "%jd\n", (intmax_t)stats->max);
+}
+
+/*
+ * blist_stats() - dump radix tree stats
+ */
+void
+blist_stats(blist_t bl, struct sbuf *s)
+{
+ struct gap_stats gstats;
+ struct gap_stats *stats = &gstats;
+ daddr_t i, nodes, radix;
+ u_daddr_t bit, diff, mask;
+
+ init_gap_stats(stats);
+ nodes = 0;
+ i = bl->bl_radix;
+ while (i < bl->bl_radix + bl->bl_blocks) {
+ /*
+ * Find max size subtree starting at i.
+ */
+ radix = BLIST_BMAP_RADIX;
+ while (((i / radix) & BLIST_META_MASK) == 0)
+ radix *= BLIST_META_RADIX;
+
+ /*
+ * Check for skippable subtrees starting at i.
+ */
+ while (radix > BLIST_BMAP_RADIX) {
+ if (bl->bl_root[nodes].u.bmu_avail == 0) {
+ if (gap_stats_counting(stats))
+ update_gap_stats(stats, i);
+ break;
+ }
+ if (bl->bl_root[nodes].u.bmu_avail == radix) {
+ if (!gap_stats_counting(stats))
+ update_gap_stats(stats, i);
+ break;
+ }
+
+ /*
+ * Skip subtree root.
+ */
+ nodes++;
+ radix /= BLIST_META_RADIX;
+ }
+ if (radix == BLIST_BMAP_RADIX) {
+ /*
+ * Scan leaf.
+ */
+ mask = bl->bl_root[nodes].u.bmu_bitmap;
+ diff = mask ^ (mask << 1);
+ if (gap_stats_counting(stats))
+ diff ^= 1;
+ while (diff != 0) {
+ bit = diff & -diff;
+ update_gap_stats(stats, i + bitpos(bit));
+ diff ^= bit;
+ }
+ }
+ nodes += radix_to_skip(radix);
+ i += radix;
+ }
+ update_gap_stats(stats, i);
+ dump_gap_stats(stats, s);
+}
+
/************************************************************************
* ALLOCATION SUPPORT FUNCTIONS *
************************************************************************
@@ -333,36 +578,19 @@ blist_print(blist_t bl)
*
* This is the core of the allocator and is optimized for the
* BLIST_BMAP_RADIX block allocation case. Otherwise, execution
- * time is proportional to log2(count) + log2(BLIST_BMAP_RADIX).
+ * time is proportional to log2(count) + bitpos time.
*/
static daddr_t
-blst_leaf_alloc(blmeta_t *scan, daddr_t blk, int count, daddr_t cursor)
+blst_leaf_alloc(blmeta_t *scan, daddr_t blk, int count)
{
u_daddr_t mask;
- int count1, hi, lo, mid, num_shifts, range1, range_ext;
+ int count1, hi, lo, num_shifts, range1, range_ext;
- if (count == BLIST_BMAP_RADIX) {
- /*
- * Optimize allocation of BLIST_BMAP_RADIX bits. If this wasn't
- * a special case, then forming the final value of 'mask' below
- * would require special handling to avoid an invalid left shift
- * when count equals the number of bits in mask.
- */
- if (~scan->u.bmu_bitmap != 0) {
- scan->bm_bighint = BLIST_BMAP_RADIX - 1;
- return (SWAPBLK_NONE);
- }
- if (cursor != blk)
- return (SWAPBLK_NONE);
- scan->u.bmu_bitmap = 0;
- scan->bm_bighint = 0;
- return (blk);
- }
range1 = 0;
count1 = count - 1;
num_shifts = fls(count1);
mask = scan->u.bmu_bitmap;
- while (mask != 0 && num_shifts > 0) {
+ while ((-mask & ~mask) != 0 && num_shifts > 0) {
/*
* If bit i is set in mask, then bits in [i, i+range1] are set
* in scan->u.bmu_bitmap. The value of range1 is equal to
@@ -370,52 +598,95 @@ blst_leaf_alloc(blmeta_t *scan, daddr_t blk, int count, daddr_t cursor)
* while preserving these invariants. The updates to mask leave
* fewer bits set, but each bit that remains set represents a
* longer string of consecutive bits set in scan->u.bmu_bitmap.
+ * If more updates to mask cannot clear more bits, because mask
+ * is partitioned with all 0 bits preceding all 1 bits, the loop
+ * terminates immediately.
*/
num_shifts--;
range_ext = range1 + ((count1 >> num_shifts) & 1);
- mask &= mask >> range_ext;
+ /*
+ * mask is a signed quantity for the shift because when it is
+ * shifted right, the sign bit should copied; when the last
+ * block of the leaf is free, pretend, for a while, that all the
+ * blocks that follow it are also free.
+ */
+ mask &= (daddr_t)mask >> range_ext;
range1 += range_ext;
}
if (mask == 0) {
/*
* Update bighint. There is no allocation bigger than range1
- * available in this leaf.
+ * starting in this leaf.
*/
scan->bm_bighint = range1;
return (SWAPBLK_NONE);
}
- /*
- * Discard any candidates that appear before the cursor.
- */
- lo = cursor - blk;
- mask &= ~(u_daddr_t)0 << lo;
-
+ /* Discard any candidates that appear before blk. */
+ mask &= (u_daddr_t)-1 << (blk & BLIST_BMAP_MASK);
if (mask == 0)
return (SWAPBLK_NONE);
/*
* The least significant set bit in mask marks the start of the first
* available range of sufficient size. Clear all the bits but that one,
- * and then perform a binary search to find its position.
+ * and then find its position.
*/
mask &= -mask;
- hi = BLIST_BMAP_RADIX - count1;
- while (lo + 1 < hi) {
- mid = (lo + hi) >> 1;
- if ((mask >> mid) != 0)
- lo = mid;
- else
- hi = mid;
+ lo = bitpos(mask);
+
+ hi = lo + count;
+ if (hi > BLIST_BMAP_RADIX) {
+ /*
+ * An allocation within this leaf is impossible, so a successful
+ * allocation depends on the next leaf providing some of the blocks.
+ */
+ if (((blk / BLIST_BMAP_RADIX + 1) & BLIST_META_MASK) == 0) {
+ /*
+ * The next leaf has a different meta-node parent, so it
+ * is not necessarily initialized. Update bighint,
+ * comparing the range found at the end of mask to the
+ * largest earlier range that could have been made to
+ * vanish in the initial processing of mask.
+ */
+ scan->bm_bighint = imax(BLIST_BMAP_RADIX - lo, range1);
+ return (SWAPBLK_NONE);
+ }
+ hi -= BLIST_BMAP_RADIX;
+ if (((scan[1].u.bmu_bitmap + 1) & ~((u_daddr_t)-1 << hi)) != 0) {
+ /*
+ * The next leaf doesn't have enough free blocks at the
+ * beginning to complete the spanning allocation. The
+ * hint cannot be updated, because the same allocation
+ * request could be satisfied later, by this leaf, if
+ * the state of the next leaf changes, and without any
+ * changes to this leaf.
+ */
+ return (SWAPBLK_NONE);
+ }
+ /* Clear the first 'hi' bits in the next leaf, allocating them. */
+ scan[1].u.bmu_bitmap &= (u_daddr_t)-1 << hi;
+ hi = BLIST_BMAP_RADIX;
}
- /*
- * Set in mask exactly the bits being allocated, and clear them from
- * the set of available bits.
- */
- mask = (mask << count) - mask;
+ /* Set the bits of mask at position 'lo' and higher. */
+ mask = -mask;
+ if (hi == BLIST_BMAP_RADIX) {
+ /*
+ * Update bighint. There is no allocation bigger than range1
+ * available in this leaf after this allocation completes.
+ */
+ scan->bm_bighint = range1;
+ } else {
+ /* Clear the bits of mask at position 'hi' and higher. */
+ mask &= (u_daddr_t)-1 >> (BLIST_BMAP_RADIX - hi);
+ /* If this allocation uses all the bits, clear the hint. */
+ if (mask == scan->u.bmu_bitmap)
+ scan->bm_bighint = 0;
+ }
+ /* Clear the allocated bits from this leaf. */
scan->u.bmu_bitmap &= ~mask;
- return (blk + lo);
+ return ((blk & ~BLIST_BMAP_MASK) + lo);
}
/*
@@ -427,15 +698,14 @@ blst_leaf_alloc(blmeta_t *scan, daddr_t blk, int count, daddr_t cursor)
* and we have a few optimizations strewn in as well.
*/
static daddr_t
-blst_meta_alloc(blmeta_t *scan, daddr_t blk, daddr_t count, daddr_t radix,
- daddr_t skip, daddr_t cursor)
+blst_meta_alloc(blmeta_t *scan, daddr_t cursor, daddr_t count, u_daddr_t radix)
{
- daddr_t i, next_skip, r;
+ daddr_t blk, i, next_skip, r, skip;
int child;
bool scan_from_start;
if (radix == BLIST_BMAP_RADIX)
- return (blst_leaf_alloc(scan, blk, count, cursor));
+ return (blst_leaf_alloc(scan, cursor, count));
if (scan->u.bmu_avail < count) {
/*
* The meta node's hint must be too large if the allocation
@@ -445,6 +715,8 @@ blst_meta_alloc(blmeta_t *scan, daddr_t blk, daddr_t count, daddr_t radix,
scan->bm_bighint = scan->u.bmu_avail;
return (SWAPBLK_NONE);
}
+ blk = cursor & -radix;
+ skip = radix_to_skip(radix);
next_skip = skip / BLIST_META_RADIX;
/*
@@ -458,7 +730,7 @@ blst_meta_alloc(blmeta_t *scan, daddr_t blk, daddr_t count, daddr_t radix,
* Reinitialize each of the meta node's children. An ALL-FREE
* meta node cannot have a terminator in any subtree.
*/
- for (i = 1; i <= skip; i += next_skip) {
+ for (i = 1; i < skip; i += next_skip) {
if (next_skip == 1)
scan[i].u.bmu_bitmap = (u_daddr_t)-1;
else
@@ -479,13 +751,13 @@ blst_meta_alloc(blmeta_t *scan, daddr_t blk, daddr_t count, daddr_t radix,
scan_from_start = cursor == blk;
child = (cursor - blk) / radix;
blk += child * radix;
- for (i = 1 + child * next_skip; i <= skip; i += next_skip) {
+ for (i = 1 + child * next_skip; i < skip; i += next_skip) {
if (count <= scan[i].bm_bighint) {
/*
- * The allocation might fit in the i'th subtree.
+ * The allocation might fit beginning in the i'th subtree.
*/
- r = blst_meta_alloc(&scan[i], blk, count, radix,
- next_skip - 1, cursor > blk ? cursor : blk);
+ r = blst_meta_alloc(&scan[i],
+ cursor > blk ? cursor : blk, count, radix);
if (r != SWAPBLK_NONE) {
scan->u.bmu_avail -= count;
return (r);
@@ -515,22 +787,20 @@ blst_meta_alloc(blmeta_t *scan, daddr_t blk, daddr_t count, daddr_t radix,
static void
blst_leaf_free(blmeta_t *scan, daddr_t blk, int count)
{
+ u_daddr_t mask;
+ int n;
+
/*
* free some data in this bitmap
- *
- * e.g.
- * 0000111111111110000
+ * mask=0000111111111110000
* \_________/\__/
- * v n
+ * count n
*/
- int n = blk & (BLIST_BMAP_RADIX - 1);
- u_daddr_t mask;
-
+ n = blk & BLIST_BMAP_MASK;
mask = ((u_daddr_t)-1 << n) &
((u_daddr_t)-1 >> (BLIST_BMAP_RADIX - count - n));
-
if (scan->u.bmu_bitmap & mask)
- panic("blst_radix_free: freeing free block");
+ panic("freeing free block");
scan->u.bmu_bitmap |= mask;
/*
@@ -553,16 +823,16 @@ blst_leaf_free(blmeta_t *scan, daddr_t blk, int count)
* range).
*/
static void
-blst_meta_free(blmeta_t *scan, daddr_t freeBlk, daddr_t count, daddr_t radix,
- daddr_t skip, daddr_t blk)
+blst_meta_free(blmeta_t *scan, daddr_t freeBlk, daddr_t count, u_daddr_t radix)
{
- daddr_t i, next_skip, v;
+ daddr_t blk, i, next_skip, skip, v;
int child;
if (scan->bm_bighint == (daddr_t)-1)
panic("freeing invalid range");
if (radix == BLIST_BMAP_RADIX)
return (blst_leaf_free(scan, freeBlk, count));
+ skip = radix_to_skip(radix);
next_skip = skip / BLIST_META_RADIX;
if (scan->u.bmu_avail == 0) {
@@ -574,7 +844,7 @@ blst_meta_free(blmeta_t *scan, daddr_t freeBlk, daddr_t count, daddr_t radix,
scan->bm_bighint = count;
if (count != radix) {
- for (i = 1; i <= skip; i += next_skip) {
+ for (i = 1; i < skip; i += next_skip) {
if (scan[i].bm_bighint == (daddr_t)-1)
break;
scan[i].bm_bighint = 0;
@@ -606,16 +876,17 @@ blst_meta_free(blmeta_t *scan, daddr_t freeBlk, daddr_t count, daddr_t radix,
* Break the free down into its components
*/
+ blk = freeBlk & -radix;
radix /= BLIST_META_RADIX;
child = (freeBlk - blk) / radix;
blk += child * radix;
i = 1 + child * next_skip;
- while (i <= skip && blk < freeBlk + count) {
+ while (i < skip && blk < freeBlk + count) {
v = blk + radix - freeBlk;
if (v > count)
v = count;
- blst_meta_free(&scan[i], freeBlk, v, radix, next_skip - 1, blk);
+ blst_meta_free(&scan[i], freeBlk, v, radix);
if (scan->bm_bighint < scan[i].bm_bighint)
scan->bm_bighint = scan[i].bm_bighint;
count -= v;
@@ -632,10 +903,10 @@ blst_meta_free(blmeta_t *scan, daddr_t freeBlk, daddr_t count, daddr_t radix,
* tree. The space may not already be free in the destination.
*/
static void
-blst_copy(blmeta_t *scan, daddr_t blk, daddr_t radix, daddr_t skip,
- blist_t dest, daddr_t count)
+blst_copy(blmeta_t *scan, daddr_t blk, daddr_t radix, blist_t dest,
+ daddr_t count)
{
- daddr_t i, next_skip;
+ daddr_t i, next_skip, skip;
/*
* Leaf node
@@ -679,21 +950,20 @@ blst_copy(blmeta_t *scan, daddr_t blk, daddr_t radix, daddr_t skip,
}
- radix /= BLIST_META_RADIX;
+ skip = radix_to_skip(radix);
next_skip = skip / BLIST_META_RADIX;
+ radix /= BLIST_META_RADIX;
- for (i = 1; count && i <= skip; i += next_skip) {
+ for (i = 1; count && i < skip; i += next_skip) {
if (scan[i].bm_bighint == (daddr_t)-1)
break;
if (count >= radix) {
- blst_copy(&scan[i], blk, radix, next_skip - 1, dest,
- radix);
+ blst_copy(&scan[i], blk, radix, dest, radix);
count -= radix;
} else {
if (count) {
- blst_copy(&scan[i], blk, radix, next_skip - 1,
- dest, count);
+ blst_copy(&scan[i], blk, radix, dest, count);
}
count = 0;
}
@@ -711,10 +981,11 @@ blst_copy(blmeta_t *scan, daddr_t blk, daddr_t radix, daddr_t skip,
static daddr_t
blst_leaf_fill(blmeta_t *scan, daddr_t blk, int count)
{
- int n = blk & (BLIST_BMAP_RADIX - 1);
daddr_t nblks;
u_daddr_t mask;
+ int n;
+ n = blk & BLIST_BMAP_MASK;
mask = ((u_daddr_t)-1 << n) &
((u_daddr_t)-1 >> (BLIST_BMAP_RADIX - count - n));
@@ -734,10 +1005,9 @@ blst_leaf_fill(blmeta_t *scan, daddr_t blk, int count)
* number of blocks allocated by the call.
*/
static daddr_t
-blst_meta_fill(blmeta_t *scan, daddr_t allocBlk, daddr_t count, daddr_t radix,
- daddr_t skip, daddr_t blk)
+blst_meta_fill(blmeta_t *scan, daddr_t allocBlk, daddr_t count, u_daddr_t radix)
{
- daddr_t i, nblks, next_skip, v;
+ daddr_t blk, i, nblks, next_skip, skip, v;
int child;
if (scan->bm_bighint == (daddr_t)-1)
@@ -760,7 +1030,9 @@ blst_meta_fill(blmeta_t *scan, daddr_t allocBlk, daddr_t count, daddr_t radix,
scan->bm_bighint = 0;
return (nblks);
}
+ skip = radix_to_skip(radix);
next_skip = skip / BLIST_META_RADIX;
+ blk = allocBlk & -radix;
/*
* An ALL-FREE meta node requires special handling before allocating
@@ -773,7 +1045,7 @@ blst_meta_fill(blmeta_t *scan, daddr_t allocBlk, daddr_t count, daddr_t radix,
* Reinitialize each of the meta node's children. An ALL-FREE
* meta node cannot have a terminator in any subtree.
*/
- for (i = 1; i <= skip; i += next_skip) {
+ for (i = 1; i < skip; i += next_skip) {
if (next_skip == 1)
scan[i].u.bmu_bitmap = (u_daddr_t)-1;
else
@@ -788,12 +1060,11 @@ blst_meta_fill(blmeta_t *scan, daddr_t allocBlk, daddr_t count, daddr_t radix,
child = (allocBlk - blk) / radix;
blk += child * radix;
i = 1 + child * next_skip;
- while (i <= skip && blk < allocBlk + count) {
+ while (i < skip && blk < allocBlk + count) {
v = blk + radix - allocBlk;
if (v > count)
v = count;
- nblks += blst_meta_fill(&scan[i], allocBlk, v, radix,
- next_skip - 1, blk);
+ nblks += blst_meta_fill(&scan[i], allocBlk, v, radix);
count -= v;
allocBlk += v;
blk += radix;
@@ -812,9 +1083,9 @@ blst_meta_fill(blmeta_t *scan, daddr_t allocBlk, daddr_t count, daddr_t radix,
* RADIX values we use.
*/
static daddr_t
-blst_radix_init(blmeta_t *scan, daddr_t radix, daddr_t skip, daddr_t count)
+blst_radix_init(blmeta_t *scan, daddr_t radix, daddr_t count)
{
- daddr_t i, memindex, next_skip;
+ daddr_t i, memindex, next_skip, skip;
memindex = 0;
@@ -841,17 +1112,18 @@ blst_radix_init(blmeta_t *scan, daddr_t radix, daddr_t skip, daddr_t count)
scan->u.bmu_avail = 0;
}
- radix /= BLIST_META_RADIX;
+ skip = radix_to_skip(radix);
next_skip = skip / BLIST_META_RADIX;
+ radix /= BLIST_META_RADIX;
- for (i = 1; i <= skip; i += next_skip) {
+ for (i = 1; i < skip; i += next_skip) {
if (count >= radix) {
/*
* Allocate the entire object
*/
memindex = i +
blst_radix_init(((scan) ? &scan[i] : NULL), radix,
- next_skip - 1, radix);
+ radix);
count -= radix;
} else if (count > 0) {
/*
@@ -859,14 +1131,18 @@ blst_radix_init(blmeta_t *scan, daddr_t radix, daddr_t skip, daddr_t count)
*/
memindex = i +
blst_radix_init(((scan) ? &scan[i] : NULL), radix,
- next_skip - 1, count);
+ count);
count = 0;
} else {
/*
- * Add terminator and break out
+ * Add terminator and break out. Make terminator bitmap
+ * zero to avoid a spanning leaf allocation that
+ * includes the terminator.
*/
- if (scan)
+ if (scan) {
scan[i].bm_bighint = (daddr_t)-1;
+ scan[i].u.bmu_bitmap = 0;
+ }
break;
}
}
@@ -878,10 +1154,9 @@ blst_radix_init(blmeta_t *scan, daddr_t radix, daddr_t skip, daddr_t count)
#ifdef BLIST_DEBUG
static void
-blst_radix_print(blmeta_t *scan, daddr_t blk, daddr_t radix, daddr_t skip,
- int tab)
+blst_radix_print(blmeta_t *scan, daddr_t blk, daddr_t radix, int tab)
{
- daddr_t i, next_skip;
+ daddr_t i, next_skip, skip;
if (radix == BLIST_BMAP_RADIX) {
printf(
@@ -922,11 +1197,12 @@ blst_radix_print(blmeta_t *scan, daddr_t blk, daddr_t radix, daddr_t skip,
(long long)scan->bm_bighint
);
- radix /= BLIST_META_RADIX;
+ skip = radix_to_skip(radix);
next_skip = skip / BLIST_META_RADIX;
+ radix /= BLIST_META_RADIX;
tab += 4;
- for (i = 1; i <= skip; i += next_skip) {
+ for (i = 1; i < skip; i += next_skip) {
if (scan[i].bm_bighint == (daddr_t)-1) {
printf(
"%*.*s(%08llx,%lld): Terminator\n",
@@ -935,7 +1211,7 @@ blst_radix_print(blmeta_t *scan, daddr_t blk, daddr_t radix, daddr_t skip,
);
break;
}
- blst_radix_print(&scan[i], blk, radix, next_skip - 1, tab);
+ blst_radix_print(&scan[i], blk, radix, tab);
blk += radix;
}
tab -= 4;
@@ -956,6 +1232,7 @@ main(int ac, char **av)
int size = 1024;
int i;
blist_t bl;
+ struct sbuf *s;
for (i = 1; i < ac; ++i) {
const char *ptr = av[i];
@@ -990,6 +1267,13 @@ main(int ac, char **av)
case 'p':
blist_print(bl);
break;
+ case 's':
+ s = sbuf_new_auto();
+ blist_stats(bl, s);
+ sbuf_finish(s);
+ printf("%s", sbuf_data(s));
+ sbuf_delete(s);
+ break;
case 'a':
if (sscanf(buf + 1, "%lld", &count) == 1) {
daddr_t blk = blist_alloc(bl, count);
@@ -1017,6 +1301,7 @@ main(int ac, char **av)
case 'h':
puts(
"p -print\n"
+ "s -stats\n"
"a %d -allocate\n"
"f %x %d -free\n"
"l %x %d -fill\n"
diff --git a/freebsd/sys/kern/subr_sbuf.c b/freebsd/sys/kern/subr_sbuf.c
index 8dd11b07..951cb50c 100644
--- a/freebsd/sys/kern/subr_sbuf.c
+++ b/freebsd/sys/kern/subr_sbuf.c
@@ -75,6 +75,8 @@ static MALLOC_DEFINE(M_SBUF, "sbuf", "string buffers");
#define SBUF_CANEXTEND(s) ((s)->s_flags & SBUF_AUTOEXTEND)
#define SBUF_ISSECTION(s) ((s)->s_flags & SBUF_INSECTION)
#define SBUF_NULINCLUDED(s) ((s)->s_flags & SBUF_INCLUDENUL)
+#define SBUF_ISDRAINTOEOR(s) ((s)->s_flags & SBUF_DRAINTOEOR)
+#define SBUF_DODRAINTOEOR(s) (SBUF_ISSECTION(s) && SBUF_ISDRAINTOEOR(s))
/*
* Set / clear flags
@@ -310,6 +312,7 @@ sbuf_clear(struct sbuf *s)
SBUF_CLEARFLAG(s, SBUF_FINISHED);
s->s_error = 0;
s->s_len = 0;
+ s->s_rec_off = 0;
s->s_sect_len = 0;
}
@@ -364,14 +367,18 @@ sbuf_drain(struct sbuf *s)
KASSERT(s->s_len > 0, ("Shouldn't drain empty sbuf %p", s));
KASSERT(s->s_error == 0, ("Called %s with error on %p", __func__, s));
- len = s->s_drain_func(s->s_drain_arg, s->s_buf, s->s_len);
- if (len < 0) {
- s->s_error = -len;
+ if (SBUF_DODRAINTOEOR(s) && s->s_rec_off == 0)
+ return (s->s_error = EDEADLK);
+ len = s->s_drain_func(s->s_drain_arg, s->s_buf,
+ SBUF_DODRAINTOEOR(s) ? s->s_rec_off : s->s_len);
+ if (len <= 0) {
+ s->s_error = len ? -len : EDEADLK;
return (s->s_error);
}
KASSERT(len > 0 && len <= s->s_len,
("Bad drain amount %d for sbuf %p", len, s));
s->s_len -= len;
+ s->s_rec_off -= len;
/*
* Fast path for the expected case where all the data was
* drained.
@@ -635,9 +642,9 @@ sbuf_vprintf(struct sbuf *s, const char *fmt, va_list ap)
break;
/* Cannot print with the current available space. */
if (s->s_drain_func != NULL && s->s_len > 0)
- error = sbuf_drain(s);
- else
- error = sbuf_extend(s, len - SBUF_FREESPACE(s));
+ error = sbuf_drain(s); /* sbuf_drain() sets s_error. */
+ else if (sbuf_extend(s, len - SBUF_FREESPACE(s)) != 0)
+ s->s_error = error = ENOMEM;
} while (error == 0);
/*
@@ -654,8 +661,6 @@ sbuf_vprintf(struct sbuf *s, const char *fmt, va_list ap)
s->s_len += len;
if (SBUF_ISSECTION(s))
s->s_sect_len += len;
- if (!SBUF_HASROOM(s) && !SBUF_CANEXTEND(s))
- s->s_error = ENOMEM;
KASSERT(s->s_len < s->s_size,
("wrote past end of sbuf (%d >= %d)", s->s_len, s->s_size));
@@ -837,6 +842,7 @@ sbuf_start_section(struct sbuf *s, ssize_t *old_lenp)
("s_sect_len != 0 when starting a section"));
if (old_lenp != NULL)
*old_lenp = -1;
+ s->s_rec_off = s->s_len;
SBUF_SETFLAG(s, SBUF_INSECTION);
} else {
KASSERT(old_lenp != NULL,
@@ -867,7 +873,7 @@ sbuf_end_section(struct sbuf *s, ssize_t old_len, size_t pad, int c)
}
len = s->s_sect_len;
if (old_len == -1) {
- s->s_sect_len = 0;
+ s->s_rec_off = s->s_sect_len = 0;
SBUF_CLEARFLAG(s, SBUF_INSECTION);
} else {
s->s_sect_len += old_len;
diff --git a/freebsd/sys/kern/sys_socket.c b/freebsd/sys/kern/sys_socket.c
index 9dd458f1..b3c9c56d 100644
--- a/freebsd/sys/kern/sys_socket.c
+++ b/freebsd/sys/kern/sys_socket.c
@@ -976,11 +976,7 @@ sowakeup_aio(struct socket *so, struct sockbuf *sb)
if (sb->sb_flags & SB_AIO_RUNNING)
return;
sb->sb_flags |= SB_AIO_RUNNING;
- if (sb == &so->so_snd)
- SOCK_LOCK(so);
soref(so);
- if (sb == &so->so_snd)
- SOCK_UNLOCK(so);
soaio_enqueue(&sb->sb_aiotask);
}
diff --git a/freebsd/sys/kern/uipc_sockbuf.c b/freebsd/sys/kern/uipc_sockbuf.c
index 4b710a2c..4ec7187c 100644
--- a/freebsd/sys/kern/uipc_sockbuf.c
+++ b/freebsd/sys/kern/uipc_sockbuf.c
@@ -336,7 +336,7 @@ sowakeup(struct socket *so, struct sockbuf *sb)
if (sb->sb_flags & SB_AIO)
sowakeup_aio(so, sb);
SOCKBUF_UNLOCK(sb);
- if (ret == SU_ISCONNECTED && !(so->so_state & SS_ISDISCONNECTED))
+ if (ret == SU_ISCONNECTED)
soisconnected(so);
if ((so->so_state & SS_ASYNC) && so->so_sigio != NULL)
pgsigio(&so->so_sigio, SIGIO, 0);
diff --git a/freebsd/sys/kern/uipc_socket.c b/freebsd/sys/kern/uipc_socket.c
index 1773606d..5e4fda56 100644
--- a/freebsd/sys/kern/uipc_socket.c
+++ b/freebsd/sys/kern/uipc_socket.c
@@ -3744,24 +3744,41 @@ soisconnecting(struct socket *so)
void
soisconnected(struct socket *so)
{
- struct socket *head;
- int ret;
- /*
- * XXXGL: this is the only place where we acquire socket locks
- * in reverse order: first child, then listening socket. To
- * avoid possible LOR, use try semantics.
- */
-restart:
SOCK_LOCK(so);
- if ((head = so->so_listen) != NULL &&
- __predict_false(SOLISTEN_TRYLOCK(head) == 0)) {
- SOCK_UNLOCK(so);
- goto restart;
- }
so->so_state &= ~(SS_ISCONNECTING|SS_ISDISCONNECTING|SS_ISCONFIRMING);
so->so_state |= SS_ISCONNECTED;
- if (head != NULL && (so->so_qstate == SQ_INCOMP)) {
+
+ if (so->so_qstate == SQ_INCOMP) {
+ struct socket *head = so->so_listen;
+ int ret;
+
+ KASSERT(head, ("%s: so %p on incomp of NULL", __func__, so));
+ /*
+ * Promoting a socket from incomplete queue to complete, we
+ * need to go through reverse order of locking. We first do
+ * trylock, and if that doesn't succeed, we go the hard way
+ * leaving a reference and rechecking consistency after proper
+ * locking.
+ */
+ if (__predict_false(SOLISTEN_TRYLOCK(head) == 0)) {
+ soref(head);
+ SOCK_UNLOCK(so);
+ SOLISTEN_LOCK(head);
+ SOCK_LOCK(so);
+ if (__predict_false(head != so->so_listen)) {
+ /*
+ * The socket went off the listen queue,
+ * should be lost race to close(2) of sol.
+ * The socket is about to soabort().
+ */
+ SOCK_UNLOCK(so);
+ sorele(head);
+ return;
+ }
+ /* Not the last one, as so holds a ref. */
+ refcount_release(&head->so_count);
+ }
again:
if ((so->so_options & SO_ACCEPTFILTER) == 0) {
TAILQ_REMOVE(&head->sol_incomp, so, so_list);
@@ -3790,8 +3807,6 @@ again:
}
return;
}
- if (head != NULL)
- SOLISTEN_UNLOCK(head);
SOCK_UNLOCK(so);
wakeup(&so->so_timeo);
sorwakeup(so);
@@ -3825,13 +3840,14 @@ soisdisconnected(struct socket *so)
so->so_state |= SS_ISDISCONNECTED;
if (!SOLISTENING(so)) {
+ SOCK_UNLOCK(so);
SOCKBUF_LOCK(&so->so_rcv);
socantrcvmore_locked(so);
SOCKBUF_LOCK(&so->so_snd);
sbdrop_locked(&so->so_snd, sbused(&so->so_snd));
socantsendmore_locked(so);
- }
- SOCK_UNLOCK(so);
+ } else
+ SOCK_UNLOCK(so);
wakeup(&so->so_timeo);
}
diff --git a/freebsd/sys/kern/uipc_usrreq.c b/freebsd/sys/kern/uipc_usrreq.c
index 7237956a..702ba1e4 100644
--- a/freebsd/sys/kern/uipc_usrreq.c
+++ b/freebsd/sys/kern/uipc_usrreq.c
@@ -698,9 +698,9 @@ uipc_close(struct socket *so)
{
struct unpcb *unp, *unp2;
#ifndef __rtems__
- struct vnode *vp;
+ struct vnode *vp = NULL;
#else /* __rtems__ */
- IMFS_generic_t *vp;
+ IMFS_generic_t *vp = NULL;
#endif /* __rtems__ */
unp = sotounpcb(so);
@@ -1181,7 +1181,11 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
release:
if (control != NULL)
m_freem(control);
- if (m != NULL)
+ /*
+ * In case of PRUS_NOTREADY, uipc_ready() is responsible
+ * for freeing memory.
+ */
+ if (m != NULL && (flags & PRUS_NOTREADY) == 0)
m_freem(m);
return (error);
}
@@ -1196,7 +1200,12 @@ uipc_ready(struct socket *so, struct mbuf *m, int count)
unp = sotounpcb(so);
UNP_LINK_RLOCK();
- unp2 = unp->unp_conn;
+ if ((unp2 = unp->unp_conn) == NULL) {
+ UNP_LINK_RUNLOCK();
+ for (int i = 0; i < count; i++)
+ m = m_free(m);
+ return (ECONNRESET);
+ }
UNP_PCB_LOCK(unp2);
so2 = unp2->unp_socket;
diff --git a/freebsd/sys/libkern/crc32.c b/freebsd/sys/libkern/crc32.c
index c987fb4d..f1f11e3b 100644
--- a/freebsd/sys/libkern/crc32.c
+++ b/freebsd/sys/libkern/crc32.c
@@ -48,6 +48,8 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
+
+#ifdef _KERNEL
#include <sys/libkern.h>
#include <sys/systm.h>
@@ -59,6 +61,7 @@ __FBSDID("$FreeBSD$");
#if defined(__aarch64__)
#include <machine/cpu.h>
#endif
+#endif /* _KERNEL */
const uint32_t crc32_tab[] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
@@ -761,6 +764,7 @@ calculate_crc32c(uint32_t crc32c,
const unsigned char *buffer,
unsigned int length)
{
+#ifdef _KERNEL
#if defined(__amd64__) || defined(__i386__)
if ((cpu_feature2 & CPUID2_SSE42) != 0) {
return (sse42_crc32c(crc32c, buffer, length));
@@ -778,6 +782,7 @@ calculate_crc32c(uint32_t crc32c,
return (armv8_crc32c(crc32c, buffer, length));
} else
#endif
+#endif /* _KERNEL */
if (length < 4) {
return (singletable_crc32c(crc32c, buffer, length));
} else {
diff --git a/freebsd/sys/mips/include/machine/cpufunc.h b/freebsd/sys/mips/include/machine/cpufunc.h
index 5ebaf4cc..d4150edd 100644
--- a/freebsd/sys/mips/include/machine/cpufunc.h
+++ b/freebsd/sys/mips/include/machine/cpufunc.h
@@ -279,6 +279,15 @@ MIPS_RW32_COP0(entrylo1, MIPS_COP_0_TLB_LO1);
MIPS_RW32_COP0(prid, MIPS_COP_0_PRID);
/* XXX 64-bit? */
MIPS_RW32_COP0_SEL(ebase, MIPS_COP_0_PRID, 1);
+
+#if defined(CPU_MIPS24K) || defined(CPU_MIPS34K) || \
+ defined(CPU_MIPS74K) || defined(CPU_MIPS1004K) || \
+ defined(CPU_MIPS1074K) || defined(CPU_INTERAPTIV) || \
+ defined(CPU_PROAPTIV)
+/* MIPS32/64 r2 intctl */
+MIPS_RW32_COP0_SEL(intctl, MIPS_COP_0_INTCTL, 1);
+#endif
+
#ifdef CPU_XBURST
MIPS_RW32_COP0_SEL(xburst_mbox0, MIPS_COP_0_XBURST_MBOX, 0);
MIPS_RW32_COP0_SEL(xburst_mbox1, MIPS_COP_0_XBURST_MBOX, 1);
diff --git a/freebsd/sys/mips/include/machine/cpuregs.h b/freebsd/sys/mips/include/machine/cpuregs.h
index b6f2433e..ca86a1c5 100644
--- a/freebsd/sys/mips/include/machine/cpuregs.h
+++ b/freebsd/sys/mips/include/machine/cpuregs.h
@@ -468,6 +468,7 @@
* 10 MIPS_COP_0_TLB_HI 3636 TLB entry high.
* 11 MIPS_COP_0_COMPARE .333 Compare (against Count).
* 12 MIPS_COP_0_STATUS 3333 Status register.
+ * 12/1 MIPS_COP_0_INTCTL ..33 Interrupt setup (MIPS32/64 r2).
* 13 MIPS_COP_0_CAUSE 3333 Exception cause register.
* 14 MIPS_COP_0_EXC_PC 3636 Exception PC.
* 15 MIPS_COP_0_PRID 3333 Processor revision identifier.
@@ -548,6 +549,7 @@
/* MIPS32/64 */
#define MIPS_COP_0_USERLOCAL _(4) /* sel 2 is userlevel register */
#define MIPS_COP_0_HWRENA _(7)
+#define MIPS_COP_0_INTCTL _(12)
#define MIPS_COP_0_DEBUG _(23)
#define MIPS_COP_0_DEPC _(24)
#define MIPS_COP_0_PERFCNT _(25)
@@ -562,6 +564,16 @@
#define MIPS_MMU_FIXED 0x03 /* Standard fixed mapping */
/*
+ * IntCtl Register Fields
+ */
+#define MIPS_INTCTL_IPTI_MASK 0xE0000000 /* bits 31..29 timer intr # */
+#define MIPS_INTCTL_IPTI_SHIFT 29
+#define MIPS_INTCTL_IPPCI_MASK 0x1C000000 /* bits 26..29 perf counter intr # */
+#define MIPS_INTCTL_IPPCI_SHIFT 26
+#define MIPS_INTCTL_VS_MASK 0x000001F0 /* bits 5..9 vector spacing */
+#define MIPS_INTCTL_VS_SHIFT 4
+
+/*
* Config Register Fields
* (See "MIPS Architecture for Programmers Volume III", MD00091, Table 9.39)
*/
diff --git a/freebsd/sys/net/bpf.c b/freebsd/sys/net/bpf.c
index b0ecb039..cd8d34d7 100644
--- a/freebsd/sys/net/bpf.c
+++ b/freebsd/sys/net/bpf.c
@@ -113,6 +113,7 @@ struct bpf_if {
struct rwlock bif_lock; /* interface lock */
LIST_HEAD(, bpf_d) bif_wlist; /* writer-only list */
int bif_flags; /* Interface flags */
+ struct bpf_if **bif_bpf; /* Pointer to pointer to us */
};
CTASSERT(offsetof(struct bpf_if, bif_ext) == 0);
@@ -2658,6 +2659,7 @@ bpfattach2(struct ifnet *ifp, u_int dlt, u_int hdrlen, struct bpf_if **driverp)
bp->bif_dlt = dlt;
rw_init(&bp->bif_lock, "bpf interface lock");
KASSERT(*driverp == NULL, ("bpfattach2: driverp already initialized"));
+ bp->bif_bpf = driverp;
*driverp = bp;
BPF_LOCK();
@@ -2728,6 +2730,7 @@ bpfdetach(struct ifnet *ifp)
*/
BPFIF_WLOCK(bp);
bp->bif_flags |= BPFIF_FLAG_DYING;
+ *bp->bif_bpf = NULL;
BPFIF_WUNLOCK(bp);
CTR4(KTR_NET, "%s: sheduling free for encap %d (%p) for if %p",
@@ -2797,13 +2800,6 @@ bpf_ifdetach(void *arg __unused, struct ifnet *ifp)
nmatched++;
}
BPF_UNLOCK();
-
- /*
- * Note that we cannot zero other pointers to
- * custom DLTs possibly used by given interface.
- */
- if (nmatched != 0)
- ifp->if_bpf = NULL;
}
/*
diff --git a/freebsd/sys/net/ieee8023ad_lacp.c b/freebsd/sys/net/ieee8023ad_lacp.c
index fefe2a1f..d3fb457e 100644
--- a/freebsd/sys/net/ieee8023ad_lacp.c
+++ b/freebsd/sys/net/ieee8023ad_lacp.c
@@ -465,7 +465,11 @@ lacp_linkstate(struct lagg_port *lgp)
uint16_t old_key;
bzero((char *)&ifmr, sizeof(ifmr));
- error = (*ifp->if_ioctl)(ifp, SIOCGIFMEDIA, (caddr_t)&ifmr);
+ error = (*ifp->if_ioctl)(ifp, SIOCGIFXMEDIA, (caddr_t)&ifmr);
+ if (error != 0) {
+ bzero((char *)&ifmr, sizeof(ifmr));
+ error = (*ifp->if_ioctl)(ifp, SIOCGIFMEDIA, (caddr_t)&ifmr);
+ }
if (error != 0)
return;
diff --git a/freebsd/sys/net/if.c b/freebsd/sys/net/if.c
index ecf9955a..00505706 100644
--- a/freebsd/sys/net/if.c
+++ b/freebsd/sys/net/if.c
@@ -2663,6 +2663,8 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td)
case SIOCGIFMEDIA:
case SIOCGIFXMEDIA:
case SIOCGIFGENERIC:
+ case SIOCGIFRSSKEY:
+ case SIOCGIFRSSHASH:
if (ifp->if_ioctl == NULL)
return (EOPNOTSUPP);
error = (*ifp->if_ioctl)(ifp, cmd, data);
diff --git a/freebsd/sys/net/if_bridge.c b/freebsd/sys/net/if_bridge.c
index 5d258493..3499f3db 100644
--- a/freebsd/sys/net/if_bridge.c
+++ b/freebsd/sys/net/if_bridge.c
@@ -586,6 +586,7 @@ static moduledata_t bridge_mod = {
};
DECLARE_MODULE(if_bridge, bridge_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
+MODULE_VERSION(if_bridge, 1);
MODULE_DEPEND(if_bridge, bridgestp, 1, 1, 1);
/*
diff --git a/freebsd/sys/net/if_enc.c b/freebsd/sys/net/if_enc.c
index 2a0b17d3..5fc53b5e 100644
--- a/freebsd/sys/net/if_enc.c
+++ b/freebsd/sys/net/if_enc.c
@@ -101,9 +101,15 @@ static void enc_remove_hhooks(struct enc_softc *);
static const char encname[] = "enc";
+#define IPSEC_ENC_AFTER_PFIL 0x04
/*
* Before and after are relative to when we are stripping the
* outer IP header.
+ *
+ * AFTER_PFIL flag used only for bpf_mask_*. It enables BPF capturing
+ * after PFIL hook execution. It might be useful when PFIL hook does
+ * some changes to the packet, e.g. address translation. If PFIL hook
+ * consumes mbuf, nothing will be captured.
*/
static VNET_DEFINE(int, filter_mask_in) = IPSEC_ENC_BEFORE;
static VNET_DEFINE(int, bpf_mask_in) = IPSEC_ENC_BEFORE;
@@ -196,6 +202,30 @@ enc_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
return (0);
}
+static void
+enc_bpftap(struct ifnet *ifp, struct mbuf *m, const struct secasvar *sav,
+ int32_t hhook_type, uint8_t enc, uint8_t af)
+{
+ struct enchdr hdr;
+
+ if (hhook_type == HHOOK_TYPE_IPSEC_IN &&
+ (enc & V_bpf_mask_in) == 0)
+ return;
+ else if (hhook_type == HHOOK_TYPE_IPSEC_OUT &&
+ (enc & V_bpf_mask_out) == 0)
+ return;
+ if (bpf_peers_present(ifp->if_bpf) == 0)
+ return;
+ hdr.af = af;
+ hdr.spi = sav->spi;
+ hdr.flags = 0;
+ if (sav->alg_enc != SADB_EALG_NONE)
+ hdr.flags |= M_CONF;
+ if (sav->alg_auth != SADB_AALG_NONE)
+ hdr.flags |= M_AUTH;
+ bpf_mtap2(ifp->if_bpf, &hdr, sizeof(hdr), m);
+}
+
/*
* One helper hook function is used by any hook points.
* + from hhook_type we can determine the packet direction:
@@ -208,7 +238,6 @@ static int
enc_hhook(int32_t hhook_type, int32_t hhook_id, void *udata, void *ctx_data,
void *hdata, struct osd *hosd)
{
- struct enchdr hdr;
struct ipsec_ctx_data *ctx;
struct enc_softc *sc;
struct ifnet *ifp, *rcvif;
@@ -225,21 +254,7 @@ enc_hhook(int32_t hhook_type, int32_t hhook_id, void *udata, void *ctx_data,
if (ctx->af != hhook_id)
return (EPFNOSUPPORT);
- if (((hhook_type == HHOOK_TYPE_IPSEC_IN &&
- (ctx->enc & V_bpf_mask_in) != 0) ||
- (hhook_type == HHOOK_TYPE_IPSEC_OUT &&
- (ctx->enc & V_bpf_mask_out) != 0)) &&
- bpf_peers_present(ifp->if_bpf) != 0) {
- hdr.af = ctx->af;
- hdr.spi = ctx->sav->spi;
- hdr.flags = 0;
- if (ctx->sav->alg_enc != SADB_EALG_NONE)
- hdr.flags |= M_CONF;
- if (ctx->sav->alg_auth != SADB_AALG_NONE)
- hdr.flags |= M_AUTH;
- bpf_mtap2(ifp->if_bpf, &hdr, sizeof(hdr), *ctx->mp);
- }
-
+ enc_bpftap(ifp, *ctx->mp, ctx->sav, hhook_type, ctx->enc, ctx->af);
switch (hhook_type) {
case HHOOK_TYPE_IPSEC_IN:
if (ctx->enc == IPSEC_ENC_BEFORE) {
@@ -292,6 +307,8 @@ enc_hhook(int32_t hhook_type, int32_t hhook_id, void *udata, void *ctx_data,
return (EACCES);
}
(*ctx->mp)->m_pkthdr.rcvif = rcvif;
+ enc_bpftap(ifp, *ctx->mp, ctx->sav, hhook_type,
+ IPSEC_ENC_AFTER_PFIL, ctx->af);
return (0);
}
diff --git a/freebsd/sys/net/if_var.h b/freebsd/sys/net/if_var.h
index b8e5e5b8..c2de24a7 100644
--- a/freebsd/sys/net/if_var.h
+++ b/freebsd/sys/net/if_var.h
@@ -183,7 +183,8 @@ struct if_encap_req {
struct m_snd_tag;
#define IF_SND_TAG_TYPE_RATE_LIMIT 0
-#define IF_SND_TAG_TYPE_MAX 1
+#define IF_SND_TAG_TYPE_UNLIMITED 1
+#define IF_SND_TAG_TYPE_MAX 2
struct if_snd_tag_alloc_header {
uint32_t type; /* send tag type, see IF_SND_TAG_XXX */
@@ -198,19 +199,26 @@ struct if_snd_tag_alloc_rate_limit {
struct if_snd_tag_rate_limit_params {
uint64_t max_rate; /* in bytes/s */
+ uint32_t queue_level; /* 0 (empty) .. 65535 (full) */
+#define IF_SND_QUEUE_LEVEL_MIN 0
+#define IF_SND_QUEUE_LEVEL_MAX 65535
+ uint32_t reserved; /* padding */
};
union if_snd_tag_alloc_params {
struct if_snd_tag_alloc_header hdr;
struct if_snd_tag_alloc_rate_limit rate_limit;
+ struct if_snd_tag_alloc_rate_limit unlimited;
};
union if_snd_tag_modify_params {
struct if_snd_tag_rate_limit_params rate_limit;
+ struct if_snd_tag_rate_limit_params unlimited;
};
union if_snd_tag_query_params {
struct if_snd_tag_rate_limit_params rate_limit;
+ struct if_snd_tag_rate_limit_params unlimited;
};
typedef int (if_snd_tag_alloc_t)(struct ifnet *, union if_snd_tag_alloc_params *,
diff --git a/freebsd/sys/net/if_vlan.c b/freebsd/sys/net/if_vlan.c
index daba2606..872b07ad 100644
--- a/freebsd/sys/net/if_vlan.c
+++ b/freebsd/sys/net/if_vlan.c
@@ -3,6 +3,7 @@
/*-
* Copyright 1998 Massachusetts Institute of Technology
* Copyright 2012 ADARA Networks, Inc.
+ * Copyright 2017 Dell EMC Isilon
*
* Portions of this software were developed by Robert N. M. Watson under
* contract to ADARA Networks, Inc.
@@ -65,6 +66,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h>
#include <sys/systm.h>
#include <sys/sx.h>
+#include <sys/taskqueue.h>
#include <net/bpf.h>
#include <net/ethernet.h>
@@ -103,6 +105,53 @@ struct ifvlantrunk {
int refcnt;
};
+/*
+ * This macro provides a facility to iterate over every vlan on a trunk with
+ * the assumption that none will be added/removed during iteration.
+ */
+#ifdef VLAN_ARRAY
+#define VLAN_FOREACH(_ifv, _trunk) \
+ size_t _i; \
+ for (_i = 0; _i < VLAN_ARRAY_SIZE; _i++) \
+ if (((_ifv) = (_trunk)->vlans[_i]) != NULL)
+#else /* VLAN_ARRAY */
+#define VLAN_FOREACH(_ifv, _trunk) \
+ struct ifvlan *_next; \
+ size_t _i; \
+ for (_i = 0; _i < (1 << (_trunk)->hwidth); _i++) \
+ LIST_FOREACH_SAFE((_ifv), &(_trunk)->hash[_i], ifv_list, _next)
+#endif /* VLAN_ARRAY */
+
+/*
+ * This macro provides a facility to iterate over every vlan on a trunk while
+ * also modifying the number of vlans on the trunk. The iteration continues
+ * until some condition is met or there are no more vlans on the trunk.
+ */
+#ifdef VLAN_ARRAY
+/* The VLAN_ARRAY case is simple -- just a for loop using the condition. */
+#define VLAN_FOREACH_UNTIL_SAFE(_ifv, _trunk, _cond) \
+ size_t _i; \
+ for (_i = 0; !(_cond) && _i < VLAN_ARRAY_SIZE; _i++) \
+ if (((_ifv) = (_trunk)->vlans[_i]))
+#else /* VLAN_ARRAY */
+/*
+ * The hash table case is more complicated. We allow for the hash table to be
+ * modified (i.e. vlans removed) while we are iterating over it. To allow for
+ * this we must restart the iteration every time we "touch" something during
+ * the iteration, since removal will resize the hash table and invalidate our
+ * current position. If acting on the touched element causes the trunk to be
+ * emptied, then iteration also stops.
+ */
+#define VLAN_FOREACH_UNTIL_SAFE(_ifv, _trunk, _cond) \
+ size_t _i; \
+ bool _touch = false; \
+ for (_i = 0; \
+ !(_cond) && _i < (1 << (_trunk)->hwidth); \
+ _i = (_touch && ((_trunk) != NULL) ? 0 : _i + 1), _touch = false) \
+ if (((_ifv) = LIST_FIRST(&(_trunk)->hash[_i])) != NULL && \
+ (_touch = true))
+#endif /* VLAN_ARRAY */
+
struct vlan_mc_entry {
struct sockaddr_dl mc_addr;
SLIST_ENTRY(vlan_mc_entry) mc_entries;
@@ -125,6 +174,7 @@ struct ifvlan {
uint16_t ifvm_vid; /* VLAN ID */
uint8_t ifvm_pcp; /* Priority Code Point (PCP). */
} ifv_mib;
+ struct task lladdr_task;
SLIST_HEAD(, vlan_mc_entry) vlan_mc_listhead;
#ifndef VLAN_ARRAY
LIST_ENTRY(ifvlan) ifv_list;
@@ -175,33 +225,92 @@ static eventhandler_tag ifdetach_tag;
static eventhandler_tag iflladdr_tag;
/*
- * We have a global mutex, that is used to serialize configuration
- * changes and isn't used in normal packet delivery.
+ * if_vlan uses two module-level locks to allow concurrent modification of vlan
+ * interfaces and (mostly) allow for vlans to be destroyed while they are being
+ * used for tx/rx. To accomplish this in a way that has acceptable performance
+ * and cooperation with other parts of the network stack there is a
+ * non-sleepable rmlock(9) and an sx(9). Both locks are exclusively acquired
+ * when destroying a vlan interface, i.e. when the if_vlantrunk field of struct
+ * ifnet is de-allocated and NULL'd. Thus a reader holding either lock has a
+ * guarantee that the struct ifvlantrunk references a valid vlan trunk.
*
- * We also have a per-trunk rmlock(9), that is locked shared on packet
- * processing and exclusive when configuration is changed.
+ * The performance-sensitive paths that warrant using the rmlock(9) are
+ * vlan_transmit and vlan_input. Both have to check for the vlan interface's
+ * existence using if_vlantrunk, and being in the network tx/rx paths the use
+ * of an rmlock(9) gives a measureable improvement in performance.
+ *
+ * The reason for having an sx(9) is mostly because there are still areas that
+ * must be sleepable and also have safe concurrent access to a vlan interface.
+ * Since the sx(9) exists, it is used by default in most paths unless sleeping
+ * is not permitted, or if it is not clear whether sleeping is permitted.
*
+ * Note that despite these protections, there is still an inherent race in the
+ * destruction of vlans since there's no guarantee that the ifnet hasn't been
+ * freed/reused when the tx/rx functions are called by the stack. This can only
+ * be fixed by addressing ifnet's lifetime issues.
+ */
+#define _VLAN_RM_ID ifv_rm_lock
+#define _VLAN_SX_ID ifv_sx
+
+static struct rmlock _VLAN_RM_ID;
+static struct sx _VLAN_SX_ID;
+
+#define VLAN_LOCKING_INIT() \
+ rm_init(&_VLAN_RM_ID, "vlan_rm"); \
+ sx_init(&_VLAN_SX_ID, "vlan_sx")
+
+#define VLAN_LOCKING_DESTROY() \
+ rm_destroy(&_VLAN_RM_ID); \
+ sx_destroy(&_VLAN_SX_ID)
+
+#define _VLAN_RM_TRACKER _vlan_rm_tracker
+#define VLAN_RLOCK() rm_rlock(&_VLAN_RM_ID, \
+ &_VLAN_RM_TRACKER)
+#define VLAN_RUNLOCK() rm_runlock(&_VLAN_RM_ID, \
+ &_VLAN_RM_TRACKER)
+#define VLAN_WLOCK() rm_wlock(&_VLAN_RM_ID)
+#define VLAN_WUNLOCK() rm_wunlock(&_VLAN_RM_ID)
+#define VLAN_RLOCK_ASSERT() rm_assert(&_VLAN_RM_ID, RA_RLOCKED)
+#define VLAN_WLOCK_ASSERT() rm_assert(&_VLAN_RM_ID, RA_WLOCKED)
+#define VLAN_RWLOCK_ASSERT() rm_assert(&_VLAN_RM_ID, RA_LOCKED)
+#define VLAN_LOCK_READER struct rm_priotracker _VLAN_RM_TRACKER
+
+#define VLAN_SLOCK() sx_slock(&_VLAN_SX_ID)
+#define VLAN_SUNLOCK() sx_sunlock(&_VLAN_SX_ID)
+#define VLAN_XLOCK() sx_xlock(&_VLAN_SX_ID)
+#define VLAN_XUNLOCK() sx_xunlock(&_VLAN_SX_ID)
+#define VLAN_SLOCK_ASSERT() sx_assert(&_VLAN_SX_ID, SA_SLOCKED)
+#define VLAN_XLOCK_ASSERT() sx_assert(&_VLAN_SX_ID, SA_XLOCKED)
+#define VLAN_SXLOCK_ASSERT() sx_assert(&_VLAN_SX_ID, SA_LOCKED)
+
+
+/*
+ * We also have a per-trunk rmlock(9), that is locked shared on packet
+ * processing and exclusive when configuration is changed. Note: This should
+ * only be acquired while there is a shared lock on either of the global locks
+ * via VLAN_SLOCK or VLAN_RLOCK. Thus, an exclusive lock on the global locks
+ * makes a call to TRUNK_RLOCK/TRUNK_WLOCK technically superfluous.
+ */
+#define _TRUNK_RM_TRACKER _trunk_rm_tracker
+#define TRUNK_LOCK_INIT(trunk) rm_init(&(trunk)->lock, vlanname)
+#define TRUNK_LOCK_DESTROY(trunk) rm_destroy(&(trunk)->lock)
+#define TRUNK_RLOCK(trunk) rm_rlock(&(trunk)->lock, \
+ &_TRUNK_RM_TRACKER)
+#define TRUNK_WLOCK(trunk) rm_wlock(&(trunk)->lock)
+#define TRUNK_RUNLOCK(trunk) rm_runlock(&(trunk)->lock, \
+ &_TRUNK_RM_TRACKER)
+#define TRUNK_WUNLOCK(trunk) rm_wunlock(&(trunk)->lock)
+#define TRUNK_RLOCK_ASSERT(trunk) rm_assert(&(trunk)->lock, RA_RLOCKED)
+#define TRUNK_LOCK_ASSERT(trunk) rm_assert(&(trunk)->lock, RA_LOCKED)
+#define TRUNK_WLOCK_ASSERT(trunk) rm_assert(&(trunk)->lock, RA_WLOCKED)
+#define TRUNK_LOCK_READER struct rm_priotracker _TRUNK_RM_TRACKER
+
+/*
* The VLAN_ARRAY substitutes the dynamic hash with a static array
* with 4096 entries. In theory this can give a boost in processing,
- * however on practice it does not. Probably this is because array
+ * however in practice it does not. Probably this is because the array
* is too big to fit into CPU cache.
*/
-static struct sx ifv_lock;
-#define VLAN_LOCK_INIT() sx_init(&ifv_lock, "vlan_global")
-#define VLAN_LOCK_DESTROY() sx_destroy(&ifv_lock)
-#define VLAN_LOCK_ASSERT() sx_assert(&ifv_lock, SA_LOCKED)
-#define VLAN_LOCK() sx_xlock(&ifv_lock)
-#define VLAN_UNLOCK() sx_xunlock(&ifv_lock)
-#define TRUNK_LOCK_INIT(trunk) rm_init(&(trunk)->lock, vlanname)
-#define TRUNK_LOCK_DESTROY(trunk) rm_destroy(&(trunk)->lock)
-#define TRUNK_LOCK(trunk) rm_wlock(&(trunk)->lock)
-#define TRUNK_UNLOCK(trunk) rm_wunlock(&(trunk)->lock)
-#define TRUNK_LOCK_ASSERT(trunk) rm_assert(&(trunk)->lock, RA_WLOCKED)
-#define TRUNK_RLOCK(trunk) rm_rlock(&(trunk)->lock, &tracker)
-#define TRUNK_RUNLOCK(trunk) rm_runlock(&(trunk)->lock, &tracker)
-#define TRUNK_LOCK_RASSERT(trunk) rm_assert(&(trunk)->lock, RA_RLOCKED)
-#define TRUNK_LOCK_READER struct rm_priotracker tracker
-
#ifndef VLAN_ARRAY
static void vlan_inithash(struct ifvlantrunk *trunk);
static void vlan_freehash(struct ifvlantrunk *trunk);
@@ -241,6 +350,8 @@ static int vlan_clone_destroy(struct if_clone *, struct ifnet *);
static void vlan_ifdetach(void *arg, struct ifnet *ifp);
static void vlan_iflladdr(void *arg, struct ifnet *ifp);
+static void vlan_lladdr_fn(void *arg, int pending);
+
static struct if_clone *vlan_cloner;
#ifdef VIMAGE
@@ -295,7 +406,7 @@ vlan_inshash(struct ifvlantrunk *trunk, struct ifvlan *ifv)
int i, b;
struct ifvlan *ifv2;
- TRUNK_LOCK_ASSERT(trunk);
+ TRUNK_WLOCK_ASSERT(trunk);
KASSERT(trunk->hwidth > 0, ("%s: hwidth not positive", __func__));
b = 1 << trunk->hwidth;
@@ -325,7 +436,7 @@ vlan_remhash(struct ifvlantrunk *trunk, struct ifvlan *ifv)
int i, b;
struct ifvlan *ifv2;
- TRUNK_LOCK_ASSERT(trunk);
+ TRUNK_WLOCK_ASSERT(trunk);
KASSERT(trunk->hwidth > 0, ("%s: hwidth not positive", __func__));
b = 1 << trunk->hwidth;
@@ -353,7 +464,7 @@ vlan_growhash(struct ifvlantrunk *trunk, int howmuch)
struct ifvlanhead *hash2;
int hwidth2, i, j, n, n2;
- TRUNK_LOCK_ASSERT(trunk);
+ TRUNK_WLOCK_ASSERT(trunk);
KASSERT(trunk->hwidth > 0, ("%s: hwidth not positive", __func__));
if (howmuch == 0) {
@@ -399,7 +510,7 @@ vlan_gethash(struct ifvlantrunk *trunk, uint16_t vid)
{
struct ifvlan *ifv;
- TRUNK_LOCK_RASSERT(trunk);
+ TRUNK_RLOCK_ASSERT(trunk);
LIST_FOREACH(ifv, &trunk->hash[HASH(vid, trunk->hmask)], ifv_list)
if (ifv->ifv_vid == vid)
@@ -469,12 +580,11 @@ vlan_inithash(struct ifvlantrunk *trunk)
static void
trunk_destroy(struct ifvlantrunk *trunk)
{
- VLAN_LOCK_ASSERT();
+ VLAN_XLOCK_ASSERT();
+ VLAN_WLOCK_ASSERT();
- TRUNK_LOCK(trunk);
vlan_freehash(trunk);
trunk->parent->if_vlantrunk = NULL;
- TRUNK_UNLOCK(trunk);
TRUNK_LOCK_DESTROY(trunk);
if_rele(trunk->parent);
free(trunk, M_VLAN);
@@ -497,9 +607,15 @@ vlan_setmulti(struct ifnet *ifp)
struct vlan_mc_entry *mc;
int error;
+ /*
+ * XXX This stupidly needs the rmlock to avoid sleeping while holding
+ * the in6_multi_mtx (see in6_mc_join_locked).
+ */
+ VLAN_RWLOCK_ASSERT();
+
/* Find the parent. */
sc = ifp->if_softc;
- TRUNK_LOCK_ASSERT(TRUNK(sc));
+ TRUNK_WLOCK_ASSERT(TRUNK(sc));
ifp_p = PARENT(sc);
CURVNET_SET_QUIET(ifp_p->if_vnet);
@@ -546,36 +662,42 @@ static void
vlan_iflladdr(void *arg __unused, struct ifnet *ifp)
{
struct ifvlan *ifv;
-#ifndef VLAN_ARRAY
- struct ifvlan *next;
-#endif
- int i;
+ struct ifnet *ifv_ifp;
+ struct ifvlantrunk *trunk;
+ struct sockaddr_dl *sdl;
+ VLAN_LOCK_READER;
- /*
- * Check if it's a trunk interface first of all
- * to avoid needless locking.
- */
- if (ifp->if_vlantrunk == NULL)
+ /* Need the rmlock since this is run on taskqueue_swi. */
+ VLAN_RLOCK();
+ trunk = ifp->if_vlantrunk;
+ if (trunk == NULL) {
+ VLAN_RUNLOCK();
return;
+ }
- VLAN_LOCK();
/*
* OK, it's a trunk. Loop over and change all vlan's lladdrs on it.
+ * We need an exclusive lock here to prevent concurrent SIOCSIFLLADDR
+ * ioctl calls on the parent garbling the lladdr of the child vlan.
*/
-#ifdef VLAN_ARRAY
- for (i = 0; i < VLAN_ARRAY_SIZE; i++)
- if ((ifv = ifp->if_vlantrunk->vlans[i])) {
-#else /* VLAN_ARRAY */
- for (i = 0; i < (1 << ifp->if_vlantrunk->hwidth); i++)
- LIST_FOREACH_SAFE(ifv, &ifp->if_vlantrunk->hash[i], ifv_list, next) {
-#endif /* VLAN_ARRAY */
- VLAN_UNLOCK();
- if_setlladdr(ifv->ifv_ifp, IF_LLADDR(ifp),
- ifp->if_addrlen);
- VLAN_LOCK();
- }
- VLAN_UNLOCK();
-
+ TRUNK_WLOCK(trunk);
+ VLAN_FOREACH(ifv, trunk) {
+ /*
+ * Copy new new lladdr into the ifv_ifp, enqueue a task
+ * to actually call if_setlladdr. if_setlladdr needs to
+ * be deferred to a taskqueue because it will call into
+ * the if_vlan ioctl path and try to acquire the global
+ * lock.
+ */
+ ifv_ifp = ifv->ifv_ifp;
+ bcopy(IF_LLADDR(ifp), IF_LLADDR(ifv_ifp),
+ ifp->if_addrlen);
+ sdl = (struct sockaddr_dl *)ifv_ifp->if_addr->ifa_addr;
+ sdl->sdl_alen = ifp->if_addrlen;
+ taskqueue_enqueue(taskqueue_thread, &ifv->lladdr_task);
+ }
+ TRUNK_WUNLOCK(trunk);
+ VLAN_RUNLOCK();
}
/*
@@ -589,46 +711,30 @@ static void
vlan_ifdetach(void *arg __unused, struct ifnet *ifp)
{
struct ifvlan *ifv;
- int i;
-
- /*
- * Check if it's a trunk interface first of all
- * to avoid needless locking.
- */
- if (ifp->if_vlantrunk == NULL)
- return;
+ struct ifvlantrunk *trunk;
/* If the ifnet is just being renamed, don't do anything. */
if (ifp->if_flags & IFF_RENAMING)
return;
+ VLAN_XLOCK();
+ trunk = ifp->if_vlantrunk;
+ if (trunk == NULL) {
+ VLAN_XUNLOCK();
+ return;
+ }
- VLAN_LOCK();
/*
* OK, it's a trunk. Loop over and detach all vlan's on it.
* Check trunk pointer after each vlan_unconfig() as it will
* free it and set to NULL after the last vlan was detached.
*/
-#ifdef VLAN_ARRAY
- for (i = 0; i < VLAN_ARRAY_SIZE; i++)
- if ((ifv = ifp->if_vlantrunk->vlans[i])) {
- vlan_unconfig_locked(ifv->ifv_ifp, 1);
- if (ifp->if_vlantrunk == NULL)
- break;
- }
-#else /* VLAN_ARRAY */
-restart:
- for (i = 0; i < (1 << ifp->if_vlantrunk->hwidth); i++)
- if ((ifv = LIST_FIRST(&ifp->if_vlantrunk->hash[i]))) {
- vlan_unconfig_locked(ifv->ifv_ifp, 1);
- if (ifp->if_vlantrunk)
- goto restart; /* trunk->hwidth can change */
- else
- break;
- }
-#endif /* VLAN_ARRAY */
+ VLAN_FOREACH_UNTIL_SAFE(ifv, ifp->if_vlantrunk,
+ ifp->if_vlantrunk == NULL)
+ vlan_unconfig_locked(ifv->ifv_ifp, 1);
+
/* Trunk should have been destroyed in vlan_unconfig(). */
KASSERT(ifp->if_vlantrunk == NULL, ("%s: purge failed", __func__));
- VLAN_UNLOCK();
+ VLAN_XUNLOCK();
}
/*
@@ -638,15 +744,18 @@ static struct ifnet *
vlan_trunkdev(struct ifnet *ifp)
{
struct ifvlan *ifv;
+ VLAN_LOCK_READER;
if (ifp->if_type != IFT_L2VLAN)
return (NULL);
+
+ /* Not clear if callers are sleepable, so acquire the rmlock. */
+ VLAN_RLOCK();
ifv = ifp->if_softc;
ifp = NULL;
- VLAN_LOCK();
if (ifv->ifv_trunk)
ifp = PARENT(ifv);
- VLAN_UNLOCK();
+ VLAN_RUNLOCK();
return (ifp);
}
@@ -708,17 +817,23 @@ vlan_devat(struct ifnet *ifp, uint16_t vid)
{
struct ifvlantrunk *trunk;
struct ifvlan *ifv;
+ VLAN_LOCK_READER;
TRUNK_LOCK_READER;
+ /* Not clear if callers are sleepable, so acquire the rmlock. */
+ VLAN_RLOCK();
trunk = ifp->if_vlantrunk;
- if (trunk == NULL)
+ if (trunk == NULL) {
+ VLAN_RUNLOCK();
return (NULL);
+ }
ifp = NULL;
TRUNK_RLOCK(trunk);
ifv = vlan_gethash(trunk, vid);
if (ifv)
ifp = ifv->ifv_ifp;
TRUNK_RUNLOCK(trunk);
+ VLAN_RUNLOCK();
return (ifp);
}
@@ -758,7 +873,7 @@ vlan_modevent(module_t mod, int type, void *data)
vlan_iflladdr, NULL, EVENTHANDLER_PRI_ANY);
if (iflladdr_tag == NULL)
return (ENOMEM);
- VLAN_LOCK_INIT();
+ VLAN_LOCKING_INIT();
vlan_input_p = vlan_input;
vlan_link_state_p = vlan_link_state;
vlan_trunk_cap_p = vlan_trunk_capabilities;
@@ -795,7 +910,7 @@ vlan_modevent(module_t mod, int type, void *data)
vlan_cookie_p = NULL;
vlan_setcookie_p = NULL;
vlan_devat_p = NULL;
- VLAN_LOCK_DESTROY();
+ VLAN_LOCKING_DESTROY();
if (bootverbose)
printf("vlan: unloaded\n");
break;
@@ -1016,9 +1131,6 @@ vlan_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params)
return (error);
}
-
- /* Update flags on the parent, if necessary. */
- vlan_setflags(ifp, 1);
}
return (0);
@@ -1032,6 +1144,12 @@ vlan_clone_destroy(struct if_clone *ifc, struct ifnet *ifp)
ether_ifdetach(ifp); /* first, remove it from system-wide lists */
vlan_unconfig(ifp); /* now it can be unconfigured and freed */
+ /*
+ * We should have the only reference to the ifv now, so we can now
+ * drain any remaining lladdr task before freeing the ifnet and the
+ * ifvlan.
+ */
+ taskqueue_drain(taskqueue_thread, &ifv->lladdr_task);
if_free(ifp);
free(ifv, M_VLAN);
ifc_free_unit(ifc, unit);
@@ -1058,8 +1176,16 @@ vlan_transmit(struct ifnet *ifp, struct mbuf *m)
struct m_tag *mtag;
uint16_t tag;
int error, len, mcast;
+ VLAN_LOCK_READER;
+ VLAN_RLOCK();
ifv = ifp->if_softc;
+ if (TRUNK(ifv) == NULL) {
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ VLAN_RUNLOCK();
+ m_freem(m);
+ return (ENETDOWN);
+ }
p = PARENT(ifv);
len = m->m_pkthdr.len;
mcast = (m->m_flags & (M_MCAST | M_BCAST)) ? 1 : 0;
@@ -1071,8 +1197,9 @@ vlan_transmit(struct ifnet *ifp, struct mbuf *m)
* or parent's driver will cause a system crash.
*/
if (!UP_AND_RUNNING(p)) {
- m_freem(m);
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ VLAN_RUNLOCK();
+ m_freem(m);
return (ENETDOWN);
}
@@ -1100,6 +1227,7 @@ vlan_transmit(struct ifnet *ifp, struct mbuf *m)
if (n > 0) {
if_printf(ifp, "cannot pad short frame\n");
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ VLAN_RUNLOCK();
m_freem(m);
return (0);
}
@@ -1125,6 +1253,7 @@ vlan_transmit(struct ifnet *ifp, struct mbuf *m)
if (m == NULL) {
if_printf(ifp, "unable to prepend VLAN header\n");
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ VLAN_RUNLOCK();
return (0);
}
}
@@ -1139,6 +1268,7 @@ vlan_transmit(struct ifnet *ifp, struct mbuf *m)
if_inc_counter(ifp, IFCOUNTER_OMCASTS, mcast);
} else
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ VLAN_RUNLOCK();
return (error);
}
@@ -1153,13 +1283,20 @@ vlan_qflush(struct ifnet *ifp __unused)
static void
vlan_input(struct ifnet *ifp, struct mbuf *m)
{
- struct ifvlantrunk *trunk = ifp->if_vlantrunk;
+ struct ifvlantrunk *trunk;
struct ifvlan *ifv;
+ VLAN_LOCK_READER;
TRUNK_LOCK_READER;
struct m_tag *mtag;
uint16_t vid, tag;
- KASSERT(trunk != NULL, ("%s: no trunk", __func__));
+ VLAN_RLOCK();
+ trunk = ifp->if_vlantrunk;
+ if (trunk == NULL) {
+ VLAN_RUNLOCK();
+ m_freem(m);
+ return;
+ }
if (m->m_flags & M_VLANTAG) {
/*
@@ -1179,6 +1316,7 @@ vlan_input(struct ifnet *ifp, struct mbuf *m)
if (m->m_len < sizeof(*evl) &&
(m = m_pullup(m, sizeof(*evl))) == NULL) {
if_printf(ifp, "cannot pullup VLAN header\n");
+ VLAN_RUNLOCK();
return;
}
evl = mtod(m, struct ether_vlan_header *);
@@ -1200,8 +1338,9 @@ vlan_input(struct ifnet *ifp, struct mbuf *m)
panic("%s: %s has unsupported if_type %u",
__func__, ifp->if_xname, ifp->if_type);
#endif
- m_freem(m);
if_inc_counter(ifp, IFCOUNTER_NOPROTO, 1);
+ VLAN_RUNLOCK();
+ m_freem(m);
return;
}
}
@@ -1212,8 +1351,9 @@ vlan_input(struct ifnet *ifp, struct mbuf *m)
ifv = vlan_gethash(trunk, vid);
if (ifv == NULL || !UP_AND_RUNNING(ifv->ifv_ifp)) {
TRUNK_RUNLOCK(trunk);
- m_freem(m);
if_inc_counter(ifp, IFCOUNTER_NOPROTO, 1);
+ VLAN_RUNLOCK();
+ m_freem(m);
return;
}
TRUNK_RUNLOCK(trunk);
@@ -1231,8 +1371,9 @@ vlan_input(struct ifnet *ifp, struct mbuf *m)
mtag = m_tag_alloc(MTAG_8021Q, MTAG_8021Q_PCP_IN,
sizeof(uint8_t), M_NOWAIT);
if (mtag == NULL) {
- m_freem(m);
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ VLAN_RUNLOCK();
+ m_freem(m);
return;
}
m_tag_prepend(m, mtag);
@@ -1242,9 +1383,22 @@ vlan_input(struct ifnet *ifp, struct mbuf *m)
m->m_pkthdr.rcvif = ifv->ifv_ifp;
if_inc_counter(ifv->ifv_ifp, IFCOUNTER_IPACKETS, 1);
+ VLAN_RUNLOCK();
/* Pass it back through the parent's input routine. */
- (*ifp->if_input)(ifv->ifv_ifp, m);
+ (*ifv->ifv_ifp->if_input)(ifv->ifv_ifp, m);
+}
+
+static void
+vlan_lladdr_fn(void *arg, int pending __unused)
+{
+ struct ifvlan *ifv;
+ struct ifnet *ifp;
+
+ ifv = (struct ifvlan *)arg;
+ ifp = ifv->ifv_ifp;
+ /* The ifv_ifp already has the lladdr copied in. */
+ if_setlladdr(ifp, IF_LLADDR(ifp), ifp->if_addrlen);
}
static int
@@ -1273,27 +1427,22 @@ vlan_config(struct ifvlan *ifv, struct ifnet *p, uint16_t vid)
if (ifv->ifv_trunk)
return (EBUSY);
+ /* Acquire rmlock after the branch so we can M_WAITOK. */
+ VLAN_XLOCK();
if (p->if_vlantrunk == NULL) {
trunk = malloc(sizeof(struct ifvlantrunk),
M_VLAN, M_WAITOK | M_ZERO);
vlan_inithash(trunk);
- VLAN_LOCK();
- if (p->if_vlantrunk != NULL) {
- /* A race that is very unlikely to be hit. */
- vlan_freehash(trunk);
- free(trunk, M_VLAN);
- goto exists;
- }
TRUNK_LOCK_INIT(trunk);
- TRUNK_LOCK(trunk);
+ VLAN_WLOCK();
+ TRUNK_WLOCK(trunk);
p->if_vlantrunk = trunk;
trunk->parent = p;
if_ref(trunk->parent);
} else {
- VLAN_LOCK();
-exists:
+ VLAN_WLOCK();
trunk = p->if_vlantrunk;
- TRUNK_LOCK(trunk);
+ TRUNK_WLOCK(trunk);
}
ifv->ifv_vid = vid; /* must set this before vlan_inshash() */
@@ -1370,15 +1519,25 @@ exists:
* Configure multicast addresses that may already be
* joined on the vlan device.
*/
- (void)vlan_setmulti(ifp); /* XXX: VLAN lock held */
+ (void)vlan_setmulti(ifp);
+
+ TASK_INIT(&ifv->lladdr_task, 0, vlan_lladdr_fn, ifv);
/* We are ready for operation now. */
ifp->if_drv_flags |= IFF_DRV_RUNNING;
+
+ /* Update flags on the parent, if necessary. */
+ vlan_setflags(ifp, 1);
done:
- TRUNK_UNLOCK(trunk);
+ /*
+ * We need to drop the non-sleepable rmlock so that the underlying
+ * devices can sleep in their vlan_config hooks.
+ */
+ TRUNK_WUNLOCK(trunk);
+ VLAN_WUNLOCK();
if (error == 0)
EVENTHANDLER_INVOKE(vlan_config, p, ifv->ifv_vid);
- VLAN_UNLOCK();
+ VLAN_XUNLOCK();
return (error);
}
@@ -1387,9 +1546,9 @@ static void
vlan_unconfig(struct ifnet *ifp)
{
- VLAN_LOCK();
+ VLAN_XLOCK();
vlan_unconfig_locked(ifp, 0);
- VLAN_UNLOCK();
+ VLAN_XUNLOCK();
}
static void
@@ -1401,15 +1560,20 @@ vlan_unconfig_locked(struct ifnet *ifp, int departing)
struct ifnet *parent;
int error;
- VLAN_LOCK_ASSERT();
+ VLAN_XLOCK_ASSERT();
ifv = ifp->if_softc;
trunk = ifv->ifv_trunk;
parent = NULL;
if (trunk != NULL) {
-
- TRUNK_LOCK(trunk);
+ /*
+ * Both vlan_transmit and vlan_input rely on the trunk fields
+ * being NULL to determine whether to bail, so we need to get
+ * an exclusive lock here to prevent them from using bad
+ * ifvlans.
+ */
+ VLAN_WLOCK();
parent = trunk->parent;
/*
@@ -1439,7 +1603,14 @@ vlan_unconfig_locked(struct ifnet *ifp, int departing)
}
vlan_setflags(ifp, 0); /* clear special flags on parent */
+
+ /*
+ * The trunk lock isn't actually required here, but
+ * vlan_remhash expects it.
+ */
+ TRUNK_WLOCK(trunk);
vlan_remhash(trunk, ifv);
+ TRUNK_WUNLOCK(trunk);
ifv->ifv_trunk = NULL;
/*
@@ -1447,17 +1618,9 @@ vlan_unconfig_locked(struct ifnet *ifp, int departing)
*/
if (trunk->refcnt == 0) {
parent->if_vlantrunk = NULL;
- /*
- * XXXGL: If some ithread has already entered
- * vlan_input() and is now blocked on the trunk
- * lock, then it should preempt us right after
- * unlock and finish its work. Then we will acquire
- * lock again in trunk_destroy().
- */
- TRUNK_UNLOCK(trunk);
trunk_destroy(trunk);
- } else
- TRUNK_UNLOCK(trunk);
+ }
+ VLAN_WUNLOCK();
}
/* Disconnect from parent. */
@@ -1484,7 +1647,7 @@ vlan_setflag(struct ifnet *ifp, int flag, int status,
struct ifvlan *ifv;
int error;
- /* XXX VLAN_LOCK_ASSERT(); */
+ VLAN_SXLOCK_ASSERT();
ifv = ifp->if_softc;
status = status ? (ifp->if_flags & flag) : 0;
@@ -1532,36 +1695,41 @@ vlan_setflags(struct ifnet *ifp, int status)
static void
vlan_link_state(struct ifnet *ifp)
{
- struct ifvlantrunk *trunk = ifp->if_vlantrunk;
+ struct ifvlantrunk *trunk;
struct ifvlan *ifv;
- int i;
+ VLAN_LOCK_READER;
- TRUNK_LOCK(trunk);
-#ifdef VLAN_ARRAY
- for (i = 0; i < VLAN_ARRAY_SIZE; i++)
- if (trunk->vlans[i] != NULL) {
- ifv = trunk->vlans[i];
-#else
- for (i = 0; i < (1 << trunk->hwidth); i++)
- LIST_FOREACH(ifv, &trunk->hash[i], ifv_list) {
-#endif
- ifv->ifv_ifp->if_baudrate = trunk->parent->if_baudrate;
- if_link_state_change(ifv->ifv_ifp,
- trunk->parent->if_link_state);
- }
- TRUNK_UNLOCK(trunk);
+ /* Called from a taskqueue_swi task, so we cannot sleep. */
+ VLAN_RLOCK();
+ trunk = ifp->if_vlantrunk;
+ if (trunk == NULL) {
+ VLAN_RUNLOCK();
+ return;
+ }
+
+ TRUNK_WLOCK(trunk);
+ VLAN_FOREACH(ifv, trunk) {
+ ifv->ifv_ifp->if_baudrate = trunk->parent->if_baudrate;
+ if_link_state_change(ifv->ifv_ifp,
+ trunk->parent->if_link_state);
+ }
+ TRUNK_WUNLOCK(trunk);
+ VLAN_RUNLOCK();
}
static void
vlan_capabilities(struct ifvlan *ifv)
{
- struct ifnet *p = PARENT(ifv);
- struct ifnet *ifp = ifv->ifv_ifp;
+ struct ifnet *p;
+ struct ifnet *ifp;
struct ifnet_hw_tsomax hw_tsomax;
int cap = 0, ena = 0, mena;
u_long hwa = 0;
- TRUNK_LOCK_ASSERT(TRUNK(ifv));
+ VLAN_SXLOCK_ASSERT();
+ TRUNK_WLOCK_ASSERT(TRUNK(ifv));
+ p = PARENT(ifv);
+ ifp = ifv->ifv_ifp;
/* Mask parent interface enabled capabilities disabled by user. */
mena = p->if_capenable & ifv->ifv_capenable;
@@ -1651,22 +1819,21 @@ vlan_capabilities(struct ifvlan *ifv)
static void
vlan_trunk_capabilities(struct ifnet *ifp)
{
- struct ifvlantrunk *trunk = ifp->if_vlantrunk;
+ struct ifvlantrunk *trunk;
struct ifvlan *ifv;
- int i;
- TRUNK_LOCK(trunk);
-#ifdef VLAN_ARRAY
- for (i = 0; i < VLAN_ARRAY_SIZE; i++)
- if (trunk->vlans[i] != NULL) {
- ifv = trunk->vlans[i];
-#else
- for (i = 0; i < (1 << trunk->hwidth); i++) {
- LIST_FOREACH(ifv, &trunk->hash[i], ifv_list)
-#endif
- vlan_capabilities(ifv);
+ VLAN_SLOCK();
+ trunk = ifp->if_vlantrunk;
+ if (trunk == NULL) {
+ VLAN_SUNLOCK();
+ return;
+ }
+ TRUNK_WLOCK(trunk);
+ VLAN_FOREACH(ifv, trunk) {
+ vlan_capabilities(ifv);
}
- TRUNK_UNLOCK(trunk);
+ TRUNK_WUNLOCK(trunk);
+ VLAN_SUNLOCK();
}
static int
@@ -1679,6 +1846,7 @@ vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
struct ifvlantrunk *trunk;
struct vlanreq vlr;
int error = 0;
+ VLAN_LOCK_READER;
ifr = (struct ifreq *)data;
ifa = (struct ifaddr *) data;
@@ -1701,11 +1869,10 @@ vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
}
break;
case SIOCGIFMEDIA:
- VLAN_LOCK();
+ VLAN_SLOCK();
if (TRUNK(ifv) != NULL) {
p = PARENT(ifv);
if_ref(p);
- VLAN_UNLOCK();
error = (*p->if_ioctl)(p, SIOCGIFMEDIA, data);
if_rele(p);
/* Limit the result to the parent's current config. */
@@ -1721,9 +1888,9 @@ vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
}
}
} else {
- VLAN_UNLOCK();
error = EINVAL;
}
+ VLAN_SUNLOCK();
break;
case SIOCSIFMEDIA:
@@ -1734,8 +1901,10 @@ vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
/*
* Set the interface MTU.
*/
- VLAN_LOCK();
- if (TRUNK(ifv) != NULL) {
+ VLAN_SLOCK();
+ trunk = TRUNK(ifv);
+ if (trunk != NULL) {
+ TRUNK_WLOCK(trunk);
if (ifr->ifr_mtu >
(PARENT(ifv)->if_mtu - ifv->ifv_mtufudge) ||
ifr->ifr_mtu <
@@ -1743,9 +1912,10 @@ vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
error = EINVAL;
else
ifp->if_mtu = ifr->ifr_mtu;
+ TRUNK_WUNLOCK(trunk);
} else
error = EINVAL;
- VLAN_UNLOCK();
+ VLAN_SUNLOCK();
break;
case SIOCSETVLAN:
@@ -1776,11 +1946,6 @@ vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
}
error = vlan_config(ifv, p, vlr.vlr_tag);
if_rele(p);
- if (error)
- break;
-
- /* Update flags on the parent, if necessary. */
- vlan_setflags(ifp, 1);
break;
case SIOCGETVLAN:
@@ -1791,13 +1956,13 @@ vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
}
#endif
bzero(&vlr, sizeof(vlr));
- VLAN_LOCK();
+ VLAN_SLOCK();
if (TRUNK(ifv) != NULL) {
strlcpy(vlr.vlr_parent, PARENT(ifv)->if_xname,
sizeof(vlr.vlr_parent));
vlr.vlr_tag = ifv->ifv_vid;
}
- VLAN_UNLOCK();
+ VLAN_SUNLOCK();
error = copyout(&vlr, ifr->ifr_data, sizeof(vlr));
break;
@@ -1806,8 +1971,10 @@ vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
* We should propagate selected flags to the parent,
* e.g., promiscuous mode.
*/
+ VLAN_XLOCK();
if (TRUNK(ifv) != NULL)
error = vlan_setflags(ifp, 1);
+ VLAN_XUNLOCK();
break;
case SIOCADDMULTI:
@@ -1815,13 +1982,18 @@ vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
/*
* If we don't have a parent, just remember the membership for
* when we do.
+ *
+ * XXX We need the rmlock here to avoid sleeping while
+ * holding in6_multi_mtx.
*/
+ VLAN_RLOCK();
trunk = TRUNK(ifv);
if (trunk != NULL) {
- TRUNK_LOCK(trunk);
+ TRUNK_WLOCK(trunk);
error = vlan_setmulti(ifp);
- TRUNK_UNLOCK(trunk);
+ TRUNK_WUNLOCK(trunk);
}
+ VLAN_RUNLOCK();
break;
case SIOCGVLANPCP:
@@ -1853,15 +2025,15 @@ vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
break;
case SIOCSIFCAP:
- VLAN_LOCK();
+ VLAN_SLOCK();
ifv->ifv_capenable = ifr->ifr_reqcap;
trunk = TRUNK(ifv);
if (trunk != NULL) {
- TRUNK_LOCK(trunk);
+ TRUNK_WLOCK(trunk);
vlan_capabilities(ifv);
- TRUNK_UNLOCK(trunk);
+ TRUNK_WUNLOCK(trunk);
}
- VLAN_UNLOCK();
+ VLAN_SUNLOCK();
break;
default:
diff --git a/freebsd/sys/net/iflib.h b/freebsd/sys/net/iflib.h
index 6ac75dbb..7249686b 100644
--- a/freebsd/sys/net/iflib.h
+++ b/freebsd/sys/net/iflib.h
@@ -173,6 +173,11 @@ typedef struct pci_vendor_info {
#define PVID_OEM(vendor, devid, svid, sdevid, revid, name) {vendor, devid, svid, sdevid, revid, 0, name}
#define PVID_END {0, 0, 0, 0, 0, 0, NULL}
+#define IFLIB_PNP_DESCR "U32:vendor;U32:device;U32:subvendor;U32:subdevice;" \
+ "U32:revision;U32:class;D:human"
+#define IFLIB_PNP_INFO(b, u, t) \
+ MODULE_PNP_INFO(IFLIB_PNP_DESCR, b, u, t, sizeof(t[0]), nitems(t))
+
typedef struct if_txrx {
int (*ift_txd_encap) (void *, if_pkt_info_t);
void (*ift_txd_flush) (void *, uint16_t, qidx_t pidx);
@@ -305,6 +310,10 @@ typedef enum {
* Interface doesn't align IP header
*/
#define IFLIB_DO_RX_FIXUP 0x40
+/*
+ * Driver needs csum zeroed for offloading
+ */
+#define IFLIB_NEED_ZERO_CSUM 0x80
diff --git a/freebsd/sys/net/route.h b/freebsd/sys/net/route.h
index 444559b5..ae052f19 100644
--- a/freebsd/sys/net/route.h
+++ b/freebsd/sys/net/route.h
@@ -67,8 +67,6 @@ struct route {
#define RT_MAY_LOOP_BIT 3 /* dst may require loop copy */
#define RT_HAS_HEADER_BIT 4 /* mbuf already have its header prepended */
-#define RT_CACHING_CONTEXT 0x1 /* XXX: not used anywhere */
-#define RT_NORTREF 0x2 /* doesn't hold reference on ro_rt */
#define RT_L2_ME (1 << RT_L2_ME_BIT) /* 0x0004 */
#define RT_MAY_LOOP (1 << RT_MAY_LOOP_BIT) /* 0x0008 */
#define RT_HAS_HEADER (1 << RT_HAS_HEADER_BIT) /* 0x0010 */
@@ -411,14 +409,8 @@ struct rt_addrinfo {
#define RO_RTFREE(_ro) do { \
if ((_ro)->ro_rt) { \
- if ((_ro)->ro_flags & RT_NORTREF) { \
- (_ro)->ro_flags &= ~RT_NORTREF; \
- (_ro)->ro_rt = NULL; \
- (_ro)->ro_lle = NULL; \
- } else { \
- RT_LOCK((_ro)->ro_rt); \
- RTFREE_LOCKED((_ro)->ro_rt); \
- } \
+ RT_LOCK((_ro)->ro_rt); \
+ RTFREE_LOCKED((_ro)->ro_rt); \
} \
} while (0)
diff --git a/freebsd/sys/net80211/ieee80211_ioctl.c b/freebsd/sys/net80211/ieee80211_ioctl.c
index 8f9e4658..68a0f9ae 100644
--- a/freebsd/sys/net80211/ieee80211_ioctl.c
+++ b/freebsd/sys/net80211/ieee80211_ioctl.c
@@ -2016,9 +2016,10 @@ setcurchan(struct ieee80211vap *vap, struct ieee80211_channel *c)
/* XXX need state machine for other vap's to follow */
ieee80211_setcurchan(ic, vap->iv_des_chan);
vap->iv_bss->ni_chan = ic->ic_curchan;
- } else
+ } else {
ic->ic_curchan = vap->iv_des_chan;
ic->ic_rt = ieee80211_get_ratetable(ic->ic_curchan);
+ }
} else {
/*
* Need to go through the state machine in case we
diff --git a/freebsd/sys/net80211/ieee80211_mesh.c b/freebsd/sys/net80211/ieee80211_mesh.c
index 3abe5a26..df2865f4 100644
--- a/freebsd/sys/net80211/ieee80211_mesh.c
+++ b/freebsd/sys/net80211/ieee80211_mesh.c
@@ -2632,7 +2632,7 @@ mesh_recv_action_meshgate(struct ieee80211_node *ni,
/* popagate only if decremented ttl >= 1 && forwarding is enabled */
if ((ie.gann_ttl - 1) < 1 && !(ms->ms_flags & IEEE80211_MESHFLAGS_FWD))
return 0;
- pgann.gann_flags = ie.gann_flags; /* Reserved */
+ pgann.gann_flags = ie.gann_flags; /* Reserved */
pgann.gann_hopcount = ie.gann_hopcount + 1;
pgann.gann_ttl = ie.gann_ttl - 1;
IEEE80211_ADDR_COPY(pgann.gann_addr, ie.gann_addr);
diff --git a/freebsd/sys/net80211/ieee80211_output.c b/freebsd/sys/net80211/ieee80211_output.c
index 85bfeb0a..93b4dc46 100644
--- a/freebsd/sys/net80211/ieee80211_output.c
+++ b/freebsd/sys/net80211/ieee80211_output.c
@@ -2502,7 +2502,7 @@ ieee80211_send_mgmt(struct ieee80211_node *ni, int type, int arg)
capinfo |= IEEE80211_CAPINFO_PRIVACY;
/*
* NB: Some 11a AP's reject the request when
- * short premable is set.
+ * short preamble is set.
*/
if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&
IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
diff --git a/freebsd/sys/netinet/if_ether.c b/freebsd/sys/netinet/if_ether.c
index 802fedbb..bdb3b054 100644
--- a/freebsd/sys/netinet/if_ether.c
+++ b/freebsd/sys/netinet/if_ether.c
@@ -1281,7 +1281,7 @@ arp_mark_lle_reachable(struct llentry *la)
}
/*
- * Add pernament link-layer record for given interface address.
+ * Add permanent link-layer record for given interface address.
*/
static __noinline void
arp_add_ifa_lle(struct ifnet *ifp, const struct sockaddr *dst)
diff --git a/freebsd/sys/netinet/in_pcb.c b/freebsd/sys/netinet/in_pcb.c
index 3d43ed92..44890e3f 100644
--- a/freebsd/sys/netinet/in_pcb.c
+++ b/freebsd/sys/netinet/in_pcb.c
@@ -2809,6 +2809,35 @@ in_pcbquery_txrtlmt(struct inpcb *inp, uint32_t *p_max_pacing_rate)
}
/*
+ * Query existing TX queue level based on the existing
+ * "inp->inp_snd_tag", if any.
+ */
+int
+in_pcbquery_txrlevel(struct inpcb *inp, uint32_t *p_txqueue_level)
+{
+ union if_snd_tag_query_params params = { };
+ struct m_snd_tag *mst;
+ struct ifnet *ifp;
+ int error;
+
+ mst = inp->inp_snd_tag;
+ if (mst == NULL)
+ return (EINVAL);
+
+ ifp = mst->ifp;
+ if (ifp == NULL)
+ return (EINVAL);
+
+ if (ifp->if_snd_tag_query == NULL)
+ return (EOPNOTSUPP);
+
+ error = ifp->if_snd_tag_query(mst, &params);
+ if (error == 0 && p_txqueue_level != NULL)
+ *p_txqueue_level = params.rate_limit.queue_level;
+ return (error);
+}
+
+/*
* Allocate a new TX rate limit send tag from the network interface
* given by the "ifp" argument and save it in "inp->inp_snd_tag":
*/
@@ -2817,7 +2846,8 @@ in_pcbattach_txrtlmt(struct inpcb *inp, struct ifnet *ifp,
uint32_t flowtype, uint32_t flowid, uint32_t max_pacing_rate)
{
union if_snd_tag_alloc_params params = {
- .rate_limit.hdr.type = IF_SND_TAG_TYPE_RATE_LIMIT,
+ .rate_limit.hdr.type = (max_pacing_rate == -1U) ?
+ IF_SND_TAG_TYPE_UNLIMITED : IF_SND_TAG_TYPE_RATE_LIMIT,
.rate_limit.hdr.flowid = flowid,
.rate_limit.hdr.flowtype = flowtype,
.rate_limit.max_rate = max_pacing_rate,
diff --git a/freebsd/sys/netinet/in_pcb.h b/freebsd/sys/netinet/in_pcb.h
index 42fd23d0..059ea90c 100644
--- a/freebsd/sys/netinet/in_pcb.h
+++ b/freebsd/sys/netinet/in_pcb.h
@@ -761,6 +761,7 @@ int in_pcbattach_txrtlmt(struct inpcb *, struct ifnet *, uint32_t, uint32_t, uin
void in_pcbdetach_txrtlmt(struct inpcb *);
int in_pcbmodify_txrtlmt(struct inpcb *, uint32_t);
int in_pcbquery_txrtlmt(struct inpcb *, uint32_t *);
+int in_pcbquery_txrlevel(struct inpcb *, uint32_t *);
void in_pcboutput_txrtlmt(struct inpcb *, struct ifnet *, struct mbuf *);
void in_pcboutput_eagain(struct inpcb *);
#endif
diff --git a/freebsd/sys/netinet/ip_icmp.c b/freebsd/sys/netinet/ip_icmp.c
index acc2e6b6..4843efcd 100644
--- a/freebsd/sys/netinet/ip_icmp.c
+++ b/freebsd/sys/netinet/ip_icmp.c
@@ -187,17 +187,14 @@ kmod_icmpstat_inc(int statnum)
void
icmp_error(struct mbuf *n, int type, int code, uint32_t dest, int mtu)
{
- struct ip *oip = mtod(n, struct ip *), *nip;
- unsigned oiphlen = oip->ip_hl << 2;
+ struct ip *oip, *nip;
struct icmp *icp;
struct mbuf *m;
- unsigned icmplen, icmpelen, nlen;
+ unsigned icmplen, icmpelen, nlen, oiphlen;
+
+ KASSERT((u_int)type <= ICMP_MAXTYPE, ("%s: illegal ICMP type",
+ __func__));
- KASSERT((u_int)type <= ICMP_MAXTYPE, ("%s: illegal ICMP type", __func__));
-#ifdef ICMPPRINTFS
- if (icmpprintfs)
- printf("icmp_error(%p, %x, %d)\n", oip, type, code);
-#endif
if (type != ICMP_REDIRECT)
ICMPSTAT_INC(icps_error);
/*
@@ -209,19 +206,28 @@ icmp_error(struct mbuf *n, int type, int code, uint32_t dest, int mtu)
*/
if (n->m_flags & M_DECRYPTED)
goto freeit;
- if (oip->ip_off & htons(~(IP_MF|IP_DF)))
- goto freeit;
if (n->m_flags & (M_BCAST|M_MCAST))
goto freeit;
+
+ /* Drop if IP header plus 8 bytes is not contiguous in first mbuf. */
+ if (n->m_len < sizeof(struct ip) + ICMP_MINLEN)
+ goto freeit;
+ oip = mtod(n, struct ip *);
+ oiphlen = oip->ip_hl << 2;
+ if (n->m_len < oiphlen + ICMP_MINLEN)
+ goto freeit;
+#ifdef ICMPPRINTFS
+ if (icmpprintfs)
+ printf("icmp_error(%p, %x, %d)\n", oip, type, code);
+#endif
+ if (oip->ip_off & htons(~(IP_MF|IP_DF)))
+ goto freeit;
if (oip->ip_p == IPPROTO_ICMP && type != ICMP_REDIRECT &&
- n->m_len >= oiphlen + ICMP_MINLEN &&
- !ICMP_INFOTYPE(((struct icmp *)((caddr_t)oip + oiphlen))->icmp_type)) {
+ !ICMP_INFOTYPE(((struct icmp *)((caddr_t)oip +
+ oiphlen))->icmp_type)) {
ICMPSTAT_INC(icps_oldicmp);
goto freeit;
}
- /* Drop if IP header plus 8 bytes is not contignous in first mbuf. */
- if (oiphlen + 8 > n->m_len)
- goto freeit;
/*
* Calculate length to quote from original packet and
* prevent the ICMP mbuf from overflowing.
@@ -237,9 +243,10 @@ icmp_error(struct mbuf *n, int type, int code, uint32_t dest, int mtu)
n->m_next == NULL)
goto stdreply;
if (n->m_len < oiphlen + sizeof(struct tcphdr) &&
- ((n = m_pullup(n, oiphlen + sizeof(struct tcphdr))) == NULL))
+ (n = m_pullup(n, oiphlen + sizeof(struct tcphdr))) == NULL)
goto freeit;
- th = (struct tcphdr *)((caddr_t)oip + oiphlen);
+ oip = mtod(n, struct ip *);
+ th = mtodo(n, oiphlen);
tcphlen = th->th_off << 2;
if (tcphlen < sizeof(struct tcphdr))
goto freeit;
@@ -247,8 +254,8 @@ icmp_error(struct mbuf *n, int type, int code, uint32_t dest, int mtu)
goto freeit;
if (oiphlen + tcphlen > n->m_len && n->m_next == NULL)
goto stdreply;
- if (n->m_len < oiphlen + tcphlen &&
- ((n = m_pullup(n, oiphlen + tcphlen)) == NULL))
+ if (n->m_len < oiphlen + tcphlen &&
+ (n = m_pullup(n, oiphlen + tcphlen)) == NULL)
goto freeit;
icmpelen = max(tcphlen, min(V_icmp_quotelen,
ntohs(oip->ip_len) - oiphlen));
@@ -264,24 +271,31 @@ icmp_error(struct mbuf *n, int type, int code, uint32_t dest, int mtu)
if (n->m_len < oiphlen + sizeof(struct sctphdr) &&
(n = m_pullup(n, oiphlen + sizeof(struct sctphdr))) == NULL)
goto freeit;
+ oip = mtod(n, struct ip *);
icmpelen = max(sizeof(struct sctphdr),
min(V_icmp_quotelen, ntohs(oip->ip_len) - oiphlen));
- sh = (struct sctphdr *)((caddr_t)oip + oiphlen);
+ sh = mtodo(n, oiphlen);
if (ntohl(sh->v_tag) == 0 &&
- ntohs(oip->ip_len) >= oiphlen + sizeof(struct sctphdr) + 8 &&
+ ntohs(oip->ip_len) >= oiphlen +
+ sizeof(struct sctphdr) + 8 &&
(n->m_len >= oiphlen + sizeof(struct sctphdr) + 8 ||
n->m_next != NULL)) {
if (n->m_len < oiphlen + sizeof(struct sctphdr) + 8 &&
- (n = m_pullup(n, oiphlen + sizeof(struct sctphdr) + 8)) == NULL)
+ (n = m_pullup(n, oiphlen +
+ sizeof(struct sctphdr) + 8)) == NULL)
goto freeit;
+ oip = mtod(n, struct ip *);
+ sh = mtodo(n, oiphlen);
ch = (struct sctp_chunkhdr *)(sh + 1);
if (ch->chunk_type == SCTP_INITIATION) {
icmpelen = max(sizeof(struct sctphdr) + 8,
- min(V_icmp_quotelen, ntohs(oip->ip_len) - oiphlen));
+ min(V_icmp_quotelen, ntohs(oip->ip_len) -
+ oiphlen));
}
}
} else
-stdreply: icmpelen = max(8, min(V_icmp_quotelen, ntohs(oip->ip_len) - oiphlen));
+stdreply: icmpelen = max(8, min(V_icmp_quotelen, ntohs(oip->ip_len) -
+ oiphlen));
icmplen = min(oiphlen + icmpelen, nlen);
if (icmplen < sizeof(struct ip))
@@ -296,7 +310,8 @@ stdreply: icmpelen = max(8, min(V_icmp_quotelen, ntohs(oip->ip_len) - oiphlen));
#ifdef MAC
mac_netinet_icmp_reply(n, m);
#endif
- icmplen = min(icmplen, M_TRAILINGSPACE(m) - sizeof(struct ip) - ICMP_MINLEN);
+ icmplen = min(icmplen, M_TRAILINGSPACE(m) -
+ sizeof(struct ip) - ICMP_MINLEN);
m_align(m, ICMP_MINLEN + icmplen);
m->m_len = ICMP_MINLEN + icmplen;
diff --git a/freebsd/sys/netinet/sctp.h b/freebsd/sys/netinet/sctp.h
index ec42cffa..578be4f6 100644
--- a/freebsd/sys/netinet/sctp.h
+++ b/freebsd/sys/netinet/sctp.h
@@ -545,7 +545,6 @@ struct sctp_error_auth_invalid_hmac {
#define SCTP_PCB_FLAGS_INTERLEAVE_STRMS 0x0000000000000010
#define SCTP_PCB_FLAGS_DO_ASCONF 0x0000000000000020
#define SCTP_PCB_FLAGS_AUTO_ASCONF 0x0000000000000040
-#define SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE 0x0000000000000080
/* socket options */
#define SCTP_PCB_FLAGS_NODELAY 0x0000000000000100
#define SCTP_PCB_FLAGS_AUTOCLOSE 0x0000000000000200
diff --git a/freebsd/sys/netinet/sctp_asconf.c b/freebsd/sys/netinet/sctp_asconf.c
index aa31e488..5f1c4e8f 100644
--- a/freebsd/sys/netinet/sctp_asconf.c
+++ b/freebsd/sys/netinet/sctp_asconf.c
@@ -2307,39 +2307,6 @@ sctp_set_primary_ip_address_sa(struct sctp_tcb *stcb, struct sockaddr *sa)
return (0);
}
-void
-sctp_set_primary_ip_address(struct sctp_ifa *ifa)
-{
- struct sctp_inpcb *inp;
-
- /* go through all our PCB's */
- LIST_FOREACH(inp, &SCTP_BASE_INFO(listhead), sctp_list) {
- struct sctp_tcb *stcb;
-
- /* process for all associations for this endpoint */
- LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
- /* queue an ASCONF:SET_PRIM_ADDR to be sent */
- if (!sctp_asconf_queue_add(stcb, ifa,
- SCTP_SET_PRIM_ADDR)) {
- /* set primary queuing succeeded */
- SCTPDBG(SCTP_DEBUG_ASCONF1, "set_primary_ip_address: queued on stcb=%p, ",
- (void *)stcb);
- SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, &ifa->address.sa);
- if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) ||
- (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
-#ifdef SCTP_TIMER_BASED_ASCONF
- sctp_timer_start(SCTP_TIMER_TYPE_ASCONF,
- stcb->sctp_ep, stcb,
- stcb->asoc.primary_destination);
-#else
- sctp_send_asconf(stcb, NULL, SCTP_ADDR_NOT_LOCKED);
-#endif
- }
- }
- } /* for each stcb */
- } /* for each inp */
-}
-
int
sctp_is_addr_pending(struct sctp_tcb *stcb, struct sctp_ifa *sctp_ifa)
{
diff --git a/freebsd/sys/netinet/sctp_asconf.h b/freebsd/sys/netinet/sctp_asconf.h
index c8d670e5..ed9160e1 100644
--- a/freebsd/sys/netinet/sctp_asconf.h
+++ b/freebsd/sys/netinet/sctp_asconf.h
@@ -73,9 +73,6 @@ sctp_set_primary_ip_address_sa(struct sctp_tcb *,
struct sockaddr *);
extern void
- sctp_set_primary_ip_address(struct sctp_ifa *ifa);
-
-extern void
sctp_check_address_list(struct sctp_tcb *, struct mbuf *, int, int,
struct sockaddr *, uint16_t, uint16_t, uint16_t, uint16_t);
diff --git a/freebsd/sys/netinet/sctp_constants.h b/freebsd/sys/netinet/sctp_constants.h
index dca34cc5..56772b34 100644
--- a/freebsd/sys/netinet/sctp_constants.h
+++ b/freebsd/sys/netinet/sctp_constants.h
@@ -555,11 +555,9 @@ __FBSDID("$FreeBSD$");
#define SCTP_TIMER_TYPE_INPKILL 15
#define SCTP_TIMER_TYPE_ASOCKILL 16
#define SCTP_TIMER_TYPE_ADDR_WQ 17
-#define SCTP_TIMER_TYPE_ZERO_COPY 18
-#define SCTP_TIMER_TYPE_ZCOPY_SENDQ 19
-#define SCTP_TIMER_TYPE_PRIM_DELETED 20
+#define SCTP_TIMER_TYPE_PRIM_DELETED 18
/* add new timers here - and increment LAST */
-#define SCTP_TIMER_TYPE_LAST 21
+#define SCTP_TIMER_TYPE_LAST 19
#define SCTP_IS_TIMER_TYPE_VALID(t) (((t) > SCTP_TIMER_TYPE_NONE) && \
((t) < SCTP_TIMER_TYPE_LAST))
@@ -971,9 +969,6 @@ __FBSDID("$FreeBSD$");
#define SCTP_SO_NOT_LOCKED 0
-#define SCTP_HOLDS_LOCK 1
-#define SCTP_NOT_LOCKED 0
-
/*-
* For address locks, do we hold the lock?
*/
diff --git a/freebsd/sys/netinet/sctp_indata.c b/freebsd/sys/netinet/sctp_indata.c
index 1924aeab..c27dd485 100644
--- a/freebsd/sys/netinet/sctp_indata.c
+++ b/freebsd/sys/netinet/sctp_indata.c
@@ -1381,10 +1381,10 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc,
}
if (sctp_place_control_in_stream(strm, asoc, control)) {
/* Duplicate SSN? */
- sctp_clean_up_control(stcb, control);
sctp_abort_in_reasm(stcb, control, chk,
abort_flag,
SCTP_FROM_SCTP_INDATA + SCTP_LOC_6);
+ sctp_clean_up_control(stcb, control);
return;
}
if ((tsn == (asoc->cumulative_tsn + 1) && (asoc->idata_supported == 0))) {
@@ -1596,9 +1596,17 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc,
next_fsn, control->fsn_included);
TAILQ_REMOVE(&control->reasm, at, sctp_next);
lenadded = sctp_add_chk_to_control(control, strm, stcb, asoc, at, SCTP_READ_LOCK_NOT_HELD);
- asoc->size_on_all_streams += lenadded;
if (control->on_read_q) {
do_wakeup = 1;
+ } else {
+ /*
+ * We only add to the
+ * size-on-all-streams if its not on
+ * the read q. The read q flag will
+ * cause a sballoc so its accounted
+ * for there.
+ */
+ asoc->size_on_all_streams += lenadded;
}
next_fsn++;
if (control->end_added && control->pdapi_started) {
@@ -1611,7 +1619,6 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc,
control,
&stcb->sctp_socket->so_rcv, control->end_added,
SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED);
- do_wakeup = 1;
}
break;
}
@@ -4207,8 +4214,6 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
again:
j = 0;
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
- int to_ticks;
-
if (win_probe_recovery && (net->window_probe)) {
win_probe_recovered = 1;
/*
@@ -4224,15 +4229,9 @@ again:
}
}
}
- if (net->RTO == 0) {
- to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
- } else {
- to_ticks = MSEC_TO_TICKS(net->RTO);
- }
if (net->flight_size) {
j++;
- (void)SCTP_OS_TIMER_START(&net->rxt_timer.timer, to_ticks,
- sctp_timeout_handler, &net->rxt_timer);
+ sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, net);
if (net->window_probe) {
net->window_probe = 0;
}
@@ -4244,8 +4243,7 @@ again:
*/
net->window_probe = 0;
if (!SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) {
- SCTP_OS_TIMER_START(&net->rxt_timer.timer, to_ticks,
- sctp_timeout_handler, &net->rxt_timer);
+ sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, net);
}
} else if (SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) {
sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
diff --git a/freebsd/sys/netinet/sctp_input.c b/freebsd/sys/netinet/sctp_input.c
index 2e844fb5..0871bdb8 100644
--- a/freebsd/sys/netinet/sctp_input.c
+++ b/freebsd/sys/netinet/sctp_input.c
@@ -199,8 +199,7 @@ sctp_handle_init(struct mbuf *m, int iphlen, int offset,
sctp_send_initiate_ack(inp, stcb, net, m, iphlen, offset,
src, dst, sh, cp,
mflowtype, mflowid,
- vrf_id, port,
- ((stcb == NULL) ? SCTP_HOLDS_LOCK : SCTP_NOT_LOCKED));
+ vrf_id, port);
}
outnow:
if (stcb == NULL) {
@@ -702,6 +701,14 @@ sctp_handle_nat_colliding_state(struct sctp_tcb *stcb)
*/
struct sctpasochead *head;
+ if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_WAIT) ||
+ (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED)) {
+ atomic_add_int(&stcb->asoc.refcnt, 1);
+ SCTP_TCB_UNLOCK(stcb);
+ SCTP_INP_INFO_WLOCK();
+ SCTP_TCB_LOCK(stcb);
+ atomic_subtract_int(&stcb->asoc.refcnt, 1);
+ }
if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_WAIT) {
/* generate a new vtag and send init */
LIST_REMOVE(stcb, sctp_asocs);
@@ -713,6 +720,7 @@ sctp_handle_nat_colliding_state(struct sctp_tcb *stcb)
*/
LIST_INSERT_HEAD(head, stcb, sctp_asocs);
sctp_send_initiate(stcb->sctp_ep, stcb, SCTP_SO_NOT_LOCKED);
+ SCTP_INP_INFO_WUNLOCK();
return (1);
}
if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED) {
@@ -734,6 +742,7 @@ sctp_handle_nat_colliding_state(struct sctp_tcb *stcb)
*/
LIST_INSERT_HEAD(head, stcb, sctp_asocs);
sctp_send_initiate(stcb->sctp_ep, stcb, SCTP_SO_NOT_LOCKED);
+ SCTP_INP_INFO_WUNLOCK();
return (1);
}
return (0);
@@ -2555,15 +2564,12 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
/* Expire time is in Ticks, so we convert to seconds */
time_expires.tv_sec = cookie->time_entered.tv_sec + TICKS_TO_SEC(cookie->cookie_life);
time_expires.tv_usec = cookie->time_entered.tv_usec;
- /*
- * TODO sctp_constants.h needs alternative time macros when _KERNEL
- * is undefined.
- */
if (timevalcmp(&now, &time_expires, >)) {
/* cookie is stale! */
struct mbuf *op_err;
struct sctp_error_stale_cookie *cause;
- uint32_t tim;
+ struct timeval diff;
+ uint32_t staleness;
op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_error_stale_cookie),
0, M_NOWAIT, 1, MT_DATA);
@@ -2577,12 +2583,19 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
cause->cause.code = htons(SCTP_CAUSE_STALE_COOKIE);
cause->cause.length = htons((sizeof(struct sctp_paramhdr) +
(sizeof(uint32_t))));
- /* seconds to usec */
- tim = (now.tv_sec - time_expires.tv_sec) * 1000000;
- /* add in usec */
- if (tim == 0)
- tim = now.tv_usec - cookie->time_entered.tv_usec;
- cause->stale_time = htonl(tim);
+ diff = now;
+ timevalsub(&diff, &time_expires);
+ if (diff.tv_sec > UINT32_MAX / 1000000) {
+ staleness = UINT32_MAX;
+ } else {
+ staleness = diff.tv_sec * 1000000;
+ }
+ if (UINT32_MAX - staleness >= (uint32_t)diff.tv_usec) {
+ staleness += diff.tv_usec;
+ } else {
+ staleness = UINT32_MAX;
+ }
+ cause->stale_time = htonl(staleness);
sctp_send_operr_to(src, dst, sh, cookie->peers_vtag, op_err,
mflowtype, mflowid, l_inp->fibnum,
vrf_id, port);
@@ -3135,14 +3148,14 @@ sctp_handle_ecn_cwr(struct sctp_cwr_chunk *cp, struct sctp_tcb *stcb, struct sct
* make sure that we have a covered ECNE in the control chunk part.
* If so remove it.
*/
- struct sctp_tmit_chunk *chk;
+ struct sctp_tmit_chunk *chk, *nchk;
struct sctp_ecne_chunk *ecne;
int override;
uint32_t cwr_tsn;
cwr_tsn = ntohl(cp->tsn);
override = cp->ch.chunk_flags & SCTP_CWR_REDUCE_OVERRIDE;
- TAILQ_FOREACH(chk, &stcb->asoc.control_send_queue, sctp_next) {
+ TAILQ_FOREACH_SAFE(chk, &stcb->asoc.control_send_queue, sctp_next, nchk) {
if (chk->rec.chunk_id.id != SCTP_ECN_ECHO) {
continue;
}
diff --git a/freebsd/sys/netinet/sctp_os_bsd.h b/freebsd/sys/netinet/sctp_os_bsd.h
index 194a03ed..045ccc38 100644
--- a/freebsd/sys/netinet/sctp_os_bsd.h
+++ b/freebsd/sys/netinet/sctp_os_bsd.h
@@ -404,11 +404,6 @@ typedef struct rtentry sctp_rtentry_t;
#define SCTP_RTALLOC(ro, vrf_id, fibnum) \
rtalloc_ign_fib((struct route *)ro, 0UL, fibnum)
-/* Future zero copy wakeup/send function */
-#define SCTP_ZERO_COPY_EVENT(inp, so)
-/* This is re-pulse ourselves for sendbuf */
-#define SCTP_ZERO_COPY_SENDQ_EVENT(inp, so)
-
/*
* SCTP protocol specific mbuf flags.
*/
diff --git a/freebsd/sys/netinet/sctp_output.c b/freebsd/sys/netinet/sctp_output.c
index 5e2fbbc2..2540b5b9 100644
--- a/freebsd/sys/netinet/sctp_output.c
+++ b/freebsd/sys/netinet/sctp_output.c
@@ -4279,11 +4279,13 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
uint32_t mtu;
mtu = SCTP_GATHER_MTU_FROM_ROUTE(net->ro._s_addr, &net->ro._l_addr.sa, ro->ro_rt);
- if (net->port) {
- mtu -= sizeof(struct udphdr);
- }
- if (mtu && (stcb->asoc.smallest_mtu > mtu)) {
- sctp_mtu_size_reset(inp, &stcb->asoc, mtu);
+ if (mtu > 0) {
+ if (net->port) {
+ mtu -= sizeof(struct udphdr);
+ }
+ if ((stcb != NULL) && (stcb->asoc.smallest_mtu > mtu)) {
+ sctp_mtu_size_reset(inp, &stcb->asoc, mtu);
+ }
net->mtu = mtu;
}
} else if (ro->ro_rt == NULL) {
@@ -4635,13 +4637,14 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
uint32_t mtu;
mtu = SCTP_GATHER_MTU_FROM_ROUTE(net->ro._s_addr, &net->ro._l_addr.sa, ro->ro_rt);
- if (mtu &&
- (stcb->asoc.smallest_mtu > mtu)) {
- sctp_mtu_size_reset(inp, &stcb->asoc, mtu);
- net->mtu = mtu;
+ if (mtu > 0) {
if (net->port) {
- net->mtu -= sizeof(struct udphdr);
+ mtu -= sizeof(struct udphdr);
+ }
+ if ((stcb != NULL) && (stcb->asoc.smallest_mtu > mtu)) {
+ sctp_mtu_size_reset(inp, &stcb->asoc, mtu);
}
+ net->mtu = mtu;
}
} else if (ifp) {
if (ND_IFINFO(ifp)->linkmtu &&
@@ -5490,7 +5493,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
struct sockaddr *src, struct sockaddr *dst,
struct sctphdr *sh, struct sctp_init_chunk *init_chk,
uint8_t mflowtype, uint32_t mflowid,
- uint32_t vrf_id, uint16_t port, int hold_inp_lock)
+ uint32_t vrf_id, uint16_t port)
{
struct sctp_association *asoc;
struct mbuf *m, *m_tmp, *m_last, *m_cookie, *op_err;
@@ -5838,10 +5841,6 @@ do_a_abort:
} else {
uint32_t vtag, itsn;
- if (hold_inp_lock) {
- SCTP_INP_INCR_REF(inp);
- SCTP_INP_RUNLOCK(inp);
- }
if (asoc) {
atomic_add_int(&asoc->refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
@@ -5861,12 +5860,12 @@ do_a_abort:
SCTP_TCB_LOCK(stcb);
atomic_add_int(&asoc->refcnt, -1);
} else {
+ SCTP_INP_INCR_REF(inp);
+ SCTP_INP_RUNLOCK(inp);
vtag = sctp_select_a_tag(inp, inp->sctp_lport, sh->src_port, 1);
initack->init.initiate_tag = htonl(vtag);
/* get a TSN to use too */
initack->init.initial_tsn = htonl(sctp_select_initial_TSN(&inp->sctp_ep));
- }
- if (hold_inp_lock) {
SCTP_INP_RLOCK(inp);
SCTP_INP_DECR_REF(inp);
}
@@ -12423,7 +12422,6 @@ sctp_copy_it_in(struct sctp_tcb *stcb,
resv_in_first = SCTP_DATA_CHUNK_OVERHEAD(stcb);
sp->data = sp->tail_mbuf = NULL;
if (sp->length == 0) {
- *error = 0;
goto skip_copy;
}
if (srcv->sinfo_keynumber_valid) {
@@ -13156,7 +13154,7 @@ skip_preblock:
if (strm->last_msg_incomplete == 0) {
do_a_copy_in:
sp = sctp_copy_it_in(stcb, asoc, srcv, uio, net, max_len, user_marks_eor, &error);
- if ((sp == NULL) || (error)) {
+ if (error) {
goto out;
}
SCTP_TCB_SEND_LOCK(stcb);
diff --git a/freebsd/sys/netinet/sctp_output.h b/freebsd/sys/netinet/sctp_output.h
index 32f968c1..0a5cf10b 100644
--- a/freebsd/sys/netinet/sctp_output.h
+++ b/freebsd/sys/netinet/sctp_output.h
@@ -86,7 +86,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *, struct sctp_tcb *,
struct sockaddr *, struct sockaddr *,
struct sctphdr *, struct sctp_init_chunk *,
uint8_t, uint32_t,
- uint32_t, uint16_t, int);
+ uint32_t, uint16_t);
struct mbuf *
sctp_arethere_unrecognized_parameters(struct mbuf *, int, int *,
diff --git a/freebsd/sys/netinet/sctp_pcb.c b/freebsd/sys/netinet/sctp_pcb.c
index 1907991e..46a91110 100644
--- a/freebsd/sys/netinet/sctp_pcb.c
+++ b/freebsd/sys/netinet/sctp_pcb.c
@@ -711,12 +711,11 @@ sctp_add_addr_to_vrf(uint32_t vrf_id, void *ifn, uint32_t ifn_index,
SCTP_WQ_ADDR_LOCK();
LIST_INSERT_HEAD(&SCTP_BASE_INFO(addr_wq), wi, sctp_nxt_addr);
- SCTP_WQ_ADDR_UNLOCK();
-
sctp_timer_start(SCTP_TIMER_TYPE_ADDR_WQ,
(struct sctp_inpcb *)NULL,
(struct sctp_tcb *)NULL,
(struct sctp_nets *)NULL);
+ SCTP_WQ_ADDR_UNLOCK();
} else {
/* it's ready for use */
sctp_ifap->localifa_flags &= ~SCTP_ADDR_DEFER_USE;
@@ -823,12 +822,11 @@ out_now:
* the newest first :-0
*/
LIST_INSERT_HEAD(&SCTP_BASE_INFO(addr_wq), wi, sctp_nxt_addr);
- SCTP_WQ_ADDR_UNLOCK();
-
sctp_timer_start(SCTP_TIMER_TYPE_ADDR_WQ,
(struct sctp_inpcb *)NULL,
(struct sctp_tcb *)NULL,
(struct sctp_nets *)NULL);
+ SCTP_WQ_ADDR_UNLOCK();
}
return;
}
@@ -2488,7 +2486,9 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
inp->sctp_flags = (SCTP_PCB_FLAGS_TCPTYPE |
SCTP_PCB_FLAGS_UNBOUND);
/* Be sure we have blocking IO by default */
+ SOCK_LOCK(so);
SCTP_CLEAR_SO_NBIO(so);
+ SOCK_UNLOCK(so);
} else {
/*
* unsupported socket type (RAW, etc)- in case we missed it
@@ -2921,9 +2921,9 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
*/
/* got to be root to get at low ports */
if (ntohs(lport) < IPPORT_RESERVED) {
- if (p && (error =
+ if ((p != NULL) && ((error =
priv_check(p, PRIV_NETINET_RESERVEDPORT)
- )) {
+ ) != 0)) {
SCTP_INP_DECR_REF(inp);
SCTP_INP_WUNLOCK(inp);
SCTP_INP_INFO_WUNLOCK();
diff --git a/freebsd/sys/netinet/sctp_pcb.h b/freebsd/sys/netinet/sctp_pcb.h
index 86fae1f4..acc68311 100644
--- a/freebsd/sys/netinet/sctp_pcb.h
+++ b/freebsd/sys/netinet/sctp_pcb.h
@@ -314,10 +314,6 @@ struct sctp_pcb {
*/
struct sctp_timer signature_change;
- /* Zero copy full buffer timer */
- struct sctp_timer zero_copy_timer;
- /* Zero copy app to transport (sendq) read repulse timer */
- struct sctp_timer zero_copy_sendq_timer;
uint32_t def_cookie_life;
/* defaults to 0 */
int auto_close_time;
diff --git a/freebsd/sys/netinet/sctp_sysctl.c b/freebsd/sys/netinet/sctp_sysctl.c
index a2364431..52361602 100644
--- a/freebsd/sys/netinet/sctp_sysctl.c
+++ b/freebsd/sys/netinet/sctp_sysctl.c
@@ -508,6 +508,14 @@ sctp_sysctl_handle_assoclist(SYSCTL_HANDLER_ARGS)
xraddr.rtt = net->rtt / 1000;
xraddr.heartbeat_interval = net->heart_beat_delay;
xraddr.ssthresh = net->ssthresh;
+ xraddr.encaps_port = net->port;
+ if (net->dest_state & SCTP_ADDR_UNCONFIRMED) {
+ xraddr.state = SCTP_UNCONFIRMED;
+ } else if (net->dest_state & SCTP_ADDR_REACHABLE) {
+ xraddr.state = SCTP_ACTIVE;
+ } else {
+ xraddr.state = SCTP_INACTIVE;
+ }
xraddr.start_time.tv_sec = (uint32_t)net->start_time.tv_sec;
xraddr.start_time.tv_usec = (uint32_t)net->start_time.tv_usec;
SCTP_INP_RUNLOCK(inp);
diff --git a/freebsd/sys/netinet/sctp_uio.h b/freebsd/sys/netinet/sctp_uio.h
index d6055163..daa6847d 100644
--- a/freebsd/sys/netinet/sctp_uio.h
+++ b/freebsd/sys/netinet/sctp_uio.h
@@ -1239,7 +1239,9 @@ struct xsctp_raddr {
uint32_t rtt;
uint32_t heartbeat_interval;
uint32_t ssthresh;
- uint32_t extra_padding[30]; /* future */
+ uint16_t encaps_port;
+ uint16_t state;
+ uint32_t extra_padding[29]; /* future */
};
#define SCTP_MAX_LOGGING_SIZE 30000
diff --git a/freebsd/sys/netinet/sctp_usrreq.c b/freebsd/sys/netinet/sctp_usrreq.c
index fa136d4e..6ab04456 100644
--- a/freebsd/sys/netinet/sctp_usrreq.c
+++ b/freebsd/sys/netinet/sctp_usrreq.c
@@ -1961,6 +1961,7 @@ flags_out:
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
} else {
id->assoc_value = stcb->asoc.vrf_id;
+ SCTP_TCB_UNLOCK(stcb);
*optsize = sizeof(struct sctp_assoc_value);
}
break;
@@ -3065,7 +3066,6 @@ flags_out:
if (event_type > 0) {
if (stcb) {
event->se_on = sctp_stcb_is_feature_on(inp, stcb, event_type);
- SCTP_TCB_UNLOCK(stcb);
} else {
if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
(inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
@@ -3079,6 +3079,9 @@ flags_out:
}
}
}
+ if (stcb != NULL) {
+ SCTP_TCB_UNLOCK(stcb);
+ }
if (error == 0) {
*optsize = sizeof(struct sctp_event);
}
@@ -3649,12 +3652,16 @@ flags_out:
sprstat->sprstat_abandoned_unsent = stcb->asoc.strmout[sid].abandoned_unsent[0];
sprstat->sprstat_abandoned_sent = stcb->asoc.strmout[sid].abandoned_sent[0];
#endif
- SCTP_TCB_UNLOCK(stcb);
- *optsize = sizeof(struct sctp_prstatus);
} else {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
}
+ if (stcb != NULL) {
+ SCTP_TCB_UNLOCK(stcb);
+ }
+ if (error == 0) {
+ *optsize = sizeof(struct sctp_prstatus);
+ }
break;
}
case SCTP_PR_ASSOC_STATUS:
@@ -3677,12 +3684,16 @@ flags_out:
sprstat->sprstat_abandoned_unsent = stcb->asoc.abandoned_unsent[policy];
sprstat->sprstat_abandoned_sent = stcb->asoc.abandoned_sent[policy];
}
- SCTP_TCB_UNLOCK(stcb);
- *optsize = sizeof(struct sctp_prstatus);
} else {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
}
+ if (stcb != NULL) {
+ SCTP_TCB_UNLOCK(stcb);
+ }
+ if (error == 0) {
+ *optsize = sizeof(struct sctp_prstatus);
+ }
break;
}
case SCTP_MAX_CWND:
diff --git a/freebsd/sys/netinet/sctputil.c b/freebsd/sys/netinet/sctputil.c
index 75c989d3..f8fd23f1 100644
--- a/freebsd/sys/netinet/sctputil.c
+++ b/freebsd/sys/netinet/sctputil.c
@@ -1464,13 +1464,11 @@ sctp_handle_addr_wq(void)
LIST_INIT(&asc->list_of_work);
asc->cnt = 0;
- SCTP_WQ_ADDR_LOCK();
LIST_FOREACH_SAFE(wi, &SCTP_BASE_INFO(addr_wq), sctp_nxt_addr, nwi) {
LIST_REMOVE(wi, sctp_nxt_addr);
LIST_INSERT_HEAD(&asc->list_of_work, wi, sctp_nxt_addr);
asc->cnt++;
}
- SCTP_WQ_ADDR_UNLOCK();
if (asc->cnt == 0) {
SCTP_FREE(asc, SCTP_M_ASC_IT);
@@ -1494,11 +1492,9 @@ sctp_handle_addr_wq(void)
if (SCTP_BASE_VAR(sctp_pcb_initialized) == 0) {
sctp_asconf_iterator_end(asc, 0);
} else {
- SCTP_WQ_ADDR_LOCK();
LIST_FOREACH(wi, &asc->list_of_work, sctp_nxt_addr) {
LIST_INSERT_HEAD(&SCTP_BASE_INFO(addr_wq), wi, sctp_nxt_addr);
}
- SCTP_WQ_ADDR_UNLOCK();
SCTP_FREE(asc, SCTP_M_ASC_IT);
}
}
@@ -1567,8 +1563,7 @@ sctp_timeout_handler(void *t)
(tmr->type != SCTP_TIMER_TYPE_SHUTDOWN) &&
(tmr->type != SCTP_TIMER_TYPE_SHUTDOWNACK) &&
(tmr->type != SCTP_TIMER_TYPE_SHUTDOWNGUARD) &&
- (tmr->type != SCTP_TIMER_TYPE_ASOCKILL))
- ) {
+ (tmr->type != SCTP_TIMER_TYPE_ASOCKILL))) {
SCTP_INP_DECR_REF(inp);
CURVNET_RESTORE();
return;
@@ -1614,6 +1609,12 @@ sctp_timeout_handler(void *t)
CURVNET_RESTORE();
return;
}
+ } else if (inp != NULL) {
+ if (type != SCTP_TIMER_TYPE_INPKILL) {
+ SCTP_INP_WLOCK(inp);
+ }
+ } else {
+ SCTP_WQ_ADDR_LOCK();
}
/* record in stopped what t-o occurred */
tmr->stopped_from = type;
@@ -1635,22 +1636,6 @@ sctp_timeout_handler(void *t)
/* call the handler for the appropriate timer type */
switch (type) {
- case SCTP_TIMER_TYPE_ZERO_COPY:
- if (inp == NULL) {
- break;
- }
- if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE)) {
- SCTP_ZERO_COPY_EVENT(inp, inp->sctp_socket);
- }
- break;
- case SCTP_TIMER_TYPE_ZCOPY_SENDQ:
- if (inp == NULL) {
- break;
- }
- if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE)) {
- SCTP_ZERO_COPY_SENDQ_EVENT(inp, inp->sctp_socket);
- }
- break;
case SCTP_TIMER_TYPE_ADDR_WQ:
sctp_handle_addr_wq();
break;
@@ -1777,7 +1762,6 @@ sctp_timeout_handler(void *t)
}
SCTP_STAT_INCR(sctps_timosecret);
(void)SCTP_GETTIME_TIMEVAL(&tv);
- SCTP_INP_WLOCK(inp);
inp->sctp_ep.time_of_secret_change = tv.tv_sec;
inp->sctp_ep.last_secret_number =
inp->sctp_ep.current_secret_number;
@@ -1791,7 +1775,6 @@ sctp_timeout_handler(void *t)
inp->sctp_ep.secret_key[secret][i] =
sctp_select_initial_TSN(&inp->sctp_ep);
}
- SCTP_INP_WUNLOCK(inp);
sctp_timer_start(SCTP_TIMER_TYPE_NEWCOOKIE, inp, stcb, net);
}
did_output = 0;
@@ -1939,7 +1922,12 @@ sctp_timeout_handler(void *t)
get_out:
if (stcb) {
SCTP_TCB_UNLOCK(stcb);
+ } else if (inp != NULL) {
+ SCTP_INP_WUNLOCK(inp);
+ } else {
+ SCTP_WQ_ADDR_UNLOCK();
}
+
out_decr:
if (inp) {
SCTP_INP_DECR_REF(inp);
@@ -1964,14 +1952,6 @@ sctp_timer_start(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
SCTP_TCB_LOCK_ASSERT(stcb);
}
switch (t_type) {
- case SCTP_TIMER_TYPE_ZERO_COPY:
- tmr = &inp->sctp_ep.zero_copy_timer;
- to_ticks = SCTP_ZERO_COPY_TICK_DELAY;
- break;
- case SCTP_TIMER_TYPE_ZCOPY_SENDQ:
- tmr = &inp->sctp_ep.zero_copy_sendq_timer;
- to_ticks = SCTP_ZERO_COPY_SENDQ_TICK_DELAY;
- break;
case SCTP_TIMER_TYPE_ADDR_WQ:
/* Only 1 tick away :-) */
tmr = &SCTP_BASE_INFO(addr_wq_timer);
@@ -2253,12 +2233,6 @@ sctp_timer_stop(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
SCTP_TCB_LOCK_ASSERT(stcb);
}
switch (t_type) {
- case SCTP_TIMER_TYPE_ZERO_COPY:
- tmr = &inp->sctp_ep.zero_copy_timer;
- break;
- case SCTP_TIMER_TYPE_ZCOPY_SENDQ:
- tmr = &inp->sctp_ep.zero_copy_sendq_timer;
- break;
case SCTP_TIMER_TYPE_ADDR_WQ:
tmr = &SCTP_BASE_INFO(addr_wq_timer);
break;
@@ -4472,36 +4446,32 @@ sctp_wakeup_the_read_socket(struct sctp_inpcb *inp,
)
{
if ((inp != NULL) && (inp->sctp_socket != NULL)) {
- if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE)) {
- SCTP_ZERO_COPY_EVENT(inp, inp->sctp_socket);
- } else {
#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
- struct socket *so;
+ struct socket *so;
- so = SCTP_INP_SO(inp);
- if (!so_locked) {
- if (stcb) {
- atomic_add_int(&stcb->asoc.refcnt, 1);
- SCTP_TCB_UNLOCK(stcb);
- }
- SCTP_SOCKET_LOCK(so, 1);
- if (stcb) {
- SCTP_TCB_LOCK(stcb);
- atomic_subtract_int(&stcb->asoc.refcnt, 1);
- }
- if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
- SCTP_SOCKET_UNLOCK(so, 1);
- return;
- }
+ so = SCTP_INP_SO(inp);
+ if (!so_locked) {
+ if (stcb) {
+ atomic_add_int(&stcb->asoc.refcnt, 1);
+ SCTP_TCB_UNLOCK(stcb);
}
-#endif
- sctp_sorwakeup(inp, inp->sctp_socket);
-#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
- if (!so_locked) {
+ SCTP_SOCKET_LOCK(so, 1);
+ if (stcb) {
+ SCTP_TCB_LOCK(stcb);
+ atomic_subtract_int(&stcb->asoc.refcnt, 1);
+ }
+ if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
SCTP_SOCKET_UNLOCK(so, 1);
+ return;
}
+ }
#endif
+ sctp_sorwakeup(inp, inp->sctp_socket);
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+ if (!so_locked) {
+ SCTP_SOCKET_UNLOCK(so, 1);
}
+#endif
}
}
@@ -6182,11 +6152,11 @@ sctp_dynamic_set_primary(struct sockaddr *sa, uint32_t vrf_id)
* newest first :-0
*/
LIST_INSERT_HEAD(&SCTP_BASE_INFO(addr_wq), wi, sctp_nxt_addr);
- SCTP_WQ_ADDR_UNLOCK();
sctp_timer_start(SCTP_TIMER_TYPE_ADDR_WQ,
(struct sctp_inpcb *)NULL,
(struct sctp_tcb *)NULL,
(struct sctp_nets *)NULL);
+ SCTP_WQ_ADDR_UNLOCK();
return (0);
}
diff --git a/freebsd/sys/netinet/tcp_input.c b/freebsd/sys/netinet/tcp_input.c
index 2195a778..663b8bc2 100644
--- a/freebsd/sys/netinet/tcp_input.c
+++ b/freebsd/sys/netinet/tcp_input.c
@@ -1696,25 +1696,6 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
to.to_tsecr = 0;
}
/*
- * If timestamps were negotiated during SYN/ACK they should
- * appear on every segment during this session and vice versa.
- */
- if ((tp->t_flags & TF_RCVD_TSTMP) && !(to.to_flags & TOF_TS)) {
- if ((s = tcp_log_addrs(inc, th, NULL, NULL))) {
- log(LOG_DEBUG, "%s; %s: Timestamp missing, "
- "no action\n", s, __func__);
- free(s, M_TCPLOG);
- }
- }
- if (!(tp->t_flags & TF_RCVD_TSTMP) && (to.to_flags & TOF_TS)) {
- if ((s = tcp_log_addrs(inc, th, NULL, NULL))) {
- log(LOG_DEBUG, "%s; %s: Timestamp not expected, "
- "no action\n", s, __func__);
- free(s, M_TCPLOG);
- }
- }
-
- /*
* Process options only when we get SYN/ACK back. The SYN case
* for incoming connections is handled in tcp_syncache.
* According to RFC1323 the window field in a SYN (i.e., a <SYN>
@@ -1745,6 +1726,25 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
}
/*
+ * If timestamps were negotiated during SYN/ACK they should
+ * appear on every segment during this session and vice versa.
+ */
+ if ((tp->t_flags & TF_RCVD_TSTMP) && !(to.to_flags & TOF_TS)) {
+ if ((s = tcp_log_addrs(inc, th, NULL, NULL))) {
+ log(LOG_DEBUG, "%s; %s: Timestamp missing, "
+ "no action\n", s, __func__);
+ free(s, M_TCPLOG);
+ }
+ }
+ if (!(tp->t_flags & TF_RCVD_TSTMP) && (to.to_flags & TOF_TS)) {
+ if ((s = tcp_log_addrs(inc, th, NULL, NULL))) {
+ log(LOG_DEBUG, "%s; %s: Timestamp not expected, "
+ "no action\n", s, __func__);
+ free(s, M_TCPLOG);
+ }
+ }
+
+ /*
* Header prediction: check for the two common cases
* of a uni-directional data xfer. If the packet has
* no control flags, is in-sequence, the window didn't
diff --git a/freebsd/sys/netinet/tcp_syncache.c b/freebsd/sys/netinet/tcp_syncache.c
index cf1f0ad1..a30def41 100644
--- a/freebsd/sys/netinet/tcp_syncache.c
+++ b/freebsd/sys/netinet/tcp_syncache.c
@@ -1644,9 +1644,7 @@ syncache_respond(struct syncache *sc, struct syncache_head *sch, int locked,
tlen = hlen + sizeof(struct tcphdr);
/* Determine MSS we advertize to other end of connection. */
- mssopt = tcp_mssopt(&sc->sc_inc);
- if (sc->sc_peer_mss)
- mssopt = max( min(sc->sc_peer_mss, mssopt), V_tcp_minmss);
+ mssopt = max(tcp_mssopt(&sc->sc_inc), V_tcp_minmss);
/* XXX: Assume that the entire packet will fit in a header mbuf. */
KASSERT(max_linkhdr + tlen + TCP_MAXOLEN <= MHLEN,
@@ -1995,7 +1993,7 @@ syncookie_mac(struct in_conninfo *inc, tcp_seq irs, uint8_t flags,
static tcp_seq
syncookie_generate(struct syncache_head *sch, struct syncache *sc)
{
- u_int i, mss, secbit, wscale;
+ u_int i, secbit, wscale;
uint32_t iss, hash;
uint8_t *secbits;
union syncookie cookie;
@@ -2005,8 +2003,8 @@ syncookie_generate(struct syncache_head *sch, struct syncache *sc)
cookie.cookie = 0;
/* Map our computed MSS into the 3-bit index. */
- mss = min(tcp_mssopt(&sc->sc_inc), max(sc->sc_peer_mss, V_tcp_minmss));
- for (i = nitems(tcp_sc_msstab) - 1; tcp_sc_msstab[i] > mss && i > 0;
+ for (i = nitems(tcp_sc_msstab) - 1;
+ tcp_sc_msstab[i] > sc->sc_peer_mss && i > 0;
i--)
;
cookie.flags.mss_idx = i;
diff --git a/freebsd/sys/netinet/tcp_timer.c b/freebsd/sys/netinet/tcp_timer.c
index ebd9e852..b4528801 100644
--- a/freebsd/sys/netinet/tcp_timer.c
+++ b/freebsd/sys/netinet/tcp_timer.c
@@ -150,29 +150,6 @@ SYSCTL_INT(_net_inet_tcp, OID_AUTO, pmtud_blackhole_detection,
&VNET_NAME(tcp_pmtud_blackhole_detect), 0,
"Path MTU Discovery Black Hole Detection Enabled");
-static VNET_DEFINE(int, tcp_pmtud_blackhole_activated);
-#define V_tcp_pmtud_blackhole_activated \
- VNET(tcp_pmtud_blackhole_activated)
-SYSCTL_INT(_net_inet_tcp, OID_AUTO, pmtud_blackhole_activated,
- CTLFLAG_RD|CTLFLAG_VNET,
- &VNET_NAME(tcp_pmtud_blackhole_activated), 0,
- "Path MTU Discovery Black Hole Detection, Activation Count");
-
-static VNET_DEFINE(int, tcp_pmtud_blackhole_activated_min_mss);
-#define V_tcp_pmtud_blackhole_activated_min_mss \
- VNET(tcp_pmtud_blackhole_activated_min_mss)
-SYSCTL_INT(_net_inet_tcp, OID_AUTO, pmtud_blackhole_activated_min_mss,
- CTLFLAG_RD|CTLFLAG_VNET,
- &VNET_NAME(tcp_pmtud_blackhole_activated_min_mss), 0,
- "Path MTU Discovery Black Hole Detection, Activation Count at min MSS");
-
-static VNET_DEFINE(int, tcp_pmtud_blackhole_failed);
-#define V_tcp_pmtud_blackhole_failed VNET(tcp_pmtud_blackhole_failed)
-SYSCTL_INT(_net_inet_tcp, OID_AUTO, pmtud_blackhole_failed,
- CTLFLAG_RD|CTLFLAG_VNET,
- &VNET_NAME(tcp_pmtud_blackhole_failed), 0,
- "Path MTU Discovery Black Hole Detection, Failure Count");
-
#ifdef INET
static VNET_DEFINE(int, tcp_pmtud_blackhole_mss) = 1200;
#define V_tcp_pmtud_blackhole_mss VNET(tcp_pmtud_blackhole_mss)
@@ -751,18 +728,20 @@ tcp_timer_rexmt(void * xtp)
*/
if (((tp->t_flags2 & (TF2_PLPMTU_PMTUD|TF2_PLPMTU_MAXSEGSNT)) ==
(TF2_PLPMTU_PMTUD|TF2_PLPMTU_MAXSEGSNT)) &&
- (tp->t_rxtshift >= 2 && tp->t_rxtshift % 2 == 0)) {
+ (tp->t_rxtshift >= 2 && tp->t_rxtshift < 6 &&
+ tp->t_rxtshift % 2 == 0)) {
/*
* Enter Path MTU Black-hole Detection mechanism:
* - Disable Path MTU Discovery (IP "DF" bit).
* - Reduce MTU to lower value than what we
* negotiated with peer.
*/
- /* Record that we may have found a black hole. */
- tp->t_flags2 |= TF2_PLPMTU_BLACKHOLE;
-
- /* Keep track of previous MSS. */
- tp->t_pmtud_saved_maxseg = tp->t_maxseg;
+ if ((tp->t_flags2 & TF2_PLPMTU_BLACKHOLE) == 0) {
+ /* Record that we may have found a black hole. */
+ tp->t_flags2 |= TF2_PLPMTU_BLACKHOLE;
+ /* Keep track of previous MSS. */
+ tp->t_pmtud_saved_maxseg = tp->t_maxseg;
+ }
/*
* Reduce the MSS to blackhole value or to the default
@@ -774,7 +753,7 @@ tcp_timer_rexmt(void * xtp)
tp->t_maxseg > V_tcp_v6pmtud_blackhole_mss) {
/* Use the sysctl tuneable blackhole MSS. */
tp->t_maxseg = V_tcp_v6pmtud_blackhole_mss;
- V_tcp_pmtud_blackhole_activated++;
+ TCPSTAT_INC(tcps_pmtud_blackhole_activated);
} else if (isipv6) {
/* Use the default MSS. */
tp->t_maxseg = V_tcp_v6mssdflt;
@@ -783,7 +762,7 @@ tcp_timer_rexmt(void * xtp)
* minmss.
*/
tp->t_flags2 &= ~TF2_PLPMTU_PMTUD;
- V_tcp_pmtud_blackhole_activated_min_mss++;
+ TCPSTAT_INC(tcps_pmtud_blackhole_activated_min_mss);
}
#endif
#if defined(INET6) && defined(INET)
@@ -793,7 +772,7 @@ tcp_timer_rexmt(void * xtp)
if (tp->t_maxseg > V_tcp_pmtud_blackhole_mss) {
/* Use the sysctl tuneable blackhole MSS. */
tp->t_maxseg = V_tcp_pmtud_blackhole_mss;
- V_tcp_pmtud_blackhole_activated++;
+ TCPSTAT_INC(tcps_pmtud_blackhole_activated);
} else {
/* Use the default MSS. */
tp->t_maxseg = V_tcp_mssdflt;
@@ -802,7 +781,7 @@ tcp_timer_rexmt(void * xtp)
* minmss.
*/
tp->t_flags2 &= ~TF2_PLPMTU_PMTUD;
- V_tcp_pmtud_blackhole_activated_min_mss++;
+ TCPSTAT_INC(tcps_pmtud_blackhole_activated_min_mss);
}
#endif
/*
@@ -821,11 +800,11 @@ tcp_timer_rexmt(void * xtp)
* stage (1448, 1188, 524) 2 chances to recover.
*/
if ((tp->t_flags2 & TF2_PLPMTU_BLACKHOLE) &&
- (tp->t_rxtshift > 6)) {
+ (tp->t_rxtshift >= 6)) {
tp->t_flags2 |= TF2_PLPMTU_PMTUD;
tp->t_flags2 &= ~TF2_PLPMTU_BLACKHOLE;
tp->t_maxseg = tp->t_pmtud_saved_maxseg;
- V_tcp_pmtud_blackhole_failed++;
+ TCPSTAT_INC(tcps_pmtud_blackhole_failed);
/*
* Reset the slow-start flight size as it
* may depend on the new MSS.
diff --git a/freebsd/sys/netinet/tcp_usrreq.c b/freebsd/sys/netinet/tcp_usrreq.c
index 198291f2..88cc3501 100644
--- a/freebsd/sys/netinet/tcp_usrreq.c
+++ b/freebsd/sys/netinet/tcp_usrreq.c
@@ -1920,6 +1920,8 @@ tcp_attach(struct socket *so)
#ifdef INET6
if (inp->inp_vflag & INP_IPV6PROTO) {
inp->inp_vflag |= INP_IPV6;
+ if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0)
+ inp->inp_vflag |= INP_IPV4;
inp->in6p_hops = -1; /* use kernel default */
}
else
diff --git a/freebsd/sys/netinet/tcp_var.h b/freebsd/sys/netinet/tcp_var.h
index 2e2f88ac..967a5139 100644
--- a/freebsd/sys/netinet/tcp_var.h
+++ b/freebsd/sys/netinet/tcp_var.h
@@ -580,6 +580,11 @@ struct tcpstat {
uint64_t tcps_sig_err_sigopt; /* No signature expected by socket */
uint64_t tcps_sig_err_nosigopt; /* No signature provided by segment */
+ /* Path MTU Discovery Black Hole Detection related stats */
+ uint64_t tcps_pmtud_blackhole_activated; /* Black Hole Count */
+ uint64_t tcps_pmtud_blackhole_activated_min_mss; /* BH at min MSS Count */
+ uint64_t tcps_pmtud_blackhole_failed; /* Black Hole Failure Count */
+
uint64_t _pad[12]; /* 6 UTO, 6 TBD */
};
@@ -650,7 +655,7 @@ struct tcp_hhook_data {
struct xtcpcb {
size_t xt_len; /* length of this structure */
struct xinpcb xt_inp;
- char xt_stack[TCP_FUNCTION_NAME_LEN_MAX]; /* (n) */
+ char xt_stack[TCP_FUNCTION_NAME_LEN_MAX]; /* (s) */
int64_t spare64[8];
int32_t t_state; /* (s,p) */
uint32_t t_flags; /* (s,p) */
diff --git a/freebsd/sys/netinet6/sctp6_usrreq.c b/freebsd/sys/netinet6/sctp6_usrreq.c
index cca2ebcf..27fcaa99 100644
--- a/freebsd/sys/netinet6/sctp6_usrreq.c
+++ b/freebsd/sys/netinet6/sctp6_usrreq.c
@@ -883,7 +883,7 @@ sctp6_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
stcb = LIST_FIRST(&inp->sctp_asoc_list);
if (stcb) {
- SCTP_TCB_UNLOCK(stcb);
+ SCTP_TCB_LOCK(stcb);
}
SCTP_INP_RUNLOCK(inp);
} else {
diff --git a/freebsd/sys/netipsec/ipsec.c b/freebsd/sys/netipsec/ipsec.c
index 4b44a8ce..79c9519c 100644
--- a/freebsd/sys/netipsec/ipsec.c
+++ b/freebsd/sys/netipsec/ipsec.c
@@ -565,7 +565,8 @@ ipsec4_setspidx_ipaddr(const struct mbuf *m, struct secpolicyindex *spidx)
}
static struct secpolicy *
-ipsec4_getpolicy(const struct mbuf *m, struct inpcb *inp, u_int dir)
+ipsec4_getpolicy(const struct mbuf *m, struct inpcb *inp, u_int dir,
+ int needport)
{
struct secpolicyindex spidx;
struct secpolicy *sp;
@@ -574,8 +575,7 @@ ipsec4_getpolicy(const struct mbuf *m, struct inpcb *inp, u_int dir)
if (sp == NULL && key_havesp(dir)) {
/* Make an index to look for a policy. */
ipsec4_setspidx_ipaddr(m, &spidx);
- /* Fill ports in spidx if we have inpcb. */
- ipsec4_get_ulp(m, &spidx, inp != NULL);
+ ipsec4_get_ulp(m, &spidx, needport);
spidx.dir = dir;
sp = key_allocsp(&spidx, dir);
}
@@ -588,12 +588,13 @@ ipsec4_getpolicy(const struct mbuf *m, struct inpcb *inp, u_int dir)
* Check security policy for *OUTBOUND* IPv4 packet.
*/
struct secpolicy *
-ipsec4_checkpolicy(const struct mbuf *m, struct inpcb *inp, int *error)
+ipsec4_checkpolicy(const struct mbuf *m, struct inpcb *inp, int *error,
+ int needport)
{
struct secpolicy *sp;
*error = 0;
- sp = ipsec4_getpolicy(m, inp, IPSEC_DIR_OUTBOUND);
+ sp = ipsec4_getpolicy(m, inp, IPSEC_DIR_OUTBOUND, needport);
if (sp != NULL)
sp = ipsec_checkpolicy(sp, inp, error);
if (sp == NULL) {
@@ -625,7 +626,7 @@ ipsec4_in_reject(const struct mbuf *m, struct inpcb *inp)
struct secpolicy *sp;
int result;
- sp = ipsec4_getpolicy(m, inp, IPSEC_DIR_INBOUND);
+ sp = ipsec4_getpolicy(m, inp, IPSEC_DIR_INBOUND, 0);
result = ipsec_in_reject(sp, inp, m);
key_freesp(&sp);
if (result != 0)
@@ -733,7 +734,8 @@ ipsec6_setspidx_ipaddr(const struct mbuf *m, struct secpolicyindex *spidx)
}
static struct secpolicy *
-ipsec6_getpolicy(const struct mbuf *m, struct inpcb *inp, u_int dir)
+ipsec6_getpolicy(const struct mbuf *m, struct inpcb *inp, u_int dir,
+ int needport)
{
struct secpolicyindex spidx;
struct secpolicy *sp;
@@ -742,8 +744,7 @@ ipsec6_getpolicy(const struct mbuf *m, struct inpcb *inp, u_int dir)
if (sp == NULL && key_havesp(dir)) {
/* Make an index to look for a policy. */
ipsec6_setspidx_ipaddr(m, &spidx);
- /* Fill ports in spidx if we have inpcb. */
- ipsec6_get_ulp(m, &spidx, inp != NULL);
+ ipsec6_get_ulp(m, &spidx, needport);
spidx.dir = dir;
sp = key_allocsp(&spidx, dir);
}
@@ -756,12 +757,13 @@ ipsec6_getpolicy(const struct mbuf *m, struct inpcb *inp, u_int dir)
* Check security policy for *OUTBOUND* IPv6 packet.
*/
struct secpolicy *
-ipsec6_checkpolicy(const struct mbuf *m, struct inpcb *inp, int *error)
+ipsec6_checkpolicy(const struct mbuf *m, struct inpcb *inp, int *error,
+ int needport)
{
struct secpolicy *sp;
*error = 0;
- sp = ipsec6_getpolicy(m, inp, IPSEC_DIR_OUTBOUND);
+ sp = ipsec6_getpolicy(m, inp, IPSEC_DIR_OUTBOUND, needport);
if (sp != NULL)
sp = ipsec_checkpolicy(sp, inp, error);
if (sp == NULL) {
@@ -793,7 +795,7 @@ ipsec6_in_reject(const struct mbuf *m, struct inpcb *inp)
struct secpolicy *sp;
int result;
- sp = ipsec6_getpolicy(m, inp, IPSEC_DIR_INBOUND);
+ sp = ipsec6_getpolicy(m, inp, IPSEC_DIR_INBOUND, 0);
result = ipsec_in_reject(sp, inp, m);
key_freesp(&sp);
if (result)
diff --git a/freebsd/sys/netipsec/ipsec.h b/freebsd/sys/netipsec/ipsec.h
index a4c3f3d2..a61730ef 100644
--- a/freebsd/sys/netipsec/ipsec.h
+++ b/freebsd/sys/netipsec/ipsec.h
@@ -320,7 +320,7 @@ int ipsec_if_input(struct mbuf *, struct secasvar *, uint32_t);
struct ipsecrequest *ipsec_newisr(void);
void ipsec_delisr(struct ipsecrequest *);
struct secpolicy *ipsec4_checkpolicy(const struct mbuf *, struct inpcb *,
- int *);
+ int *, int);
u_int ipsec_get_reqlevel(struct secpolicy *, u_int);
diff --git a/freebsd/sys/netipsec/ipsec6.h b/freebsd/sys/netipsec/ipsec6.h
index a5fae4d1..33aa30f3 100644
--- a/freebsd/sys/netipsec/ipsec6.h
+++ b/freebsd/sys/netipsec/ipsec6.h
@@ -60,7 +60,7 @@ VNET_DECLARE(int, ip6_ipsec_ecn);
struct inpcb;
struct secpolicy *ipsec6_checkpolicy(const struct mbuf *,
- struct inpcb *, int *);
+ struct inpcb *, int *, int);
void ipsec6_setsockaddrs(const struct mbuf *, union sockaddr_union *,
union sockaddr_union *);
diff --git a/freebsd/sys/netipsec/ipsec_output.c b/freebsd/sys/netipsec/ipsec_output.c
index 07e39a8a..ac9529d5 100644
--- a/freebsd/sys/netipsec/ipsec_output.c
+++ b/freebsd/sys/netipsec/ipsec_output.c
@@ -299,7 +299,7 @@ ipsec4_common_output(struct mbuf *m, struct inpcb *inp, int forwarding)
int error;
/* Lookup for the corresponding outbound security policy */
- sp = ipsec4_checkpolicy(m, inp, &error);
+ sp = ipsec4_checkpolicy(m, inp, &error, !forwarding);
if (sp == NULL) {
if (error == -EINVAL) {
/* Discarded by policy. */
@@ -601,7 +601,7 @@ ipsec6_common_output(struct mbuf *m, struct inpcb *inp, int forwarding)
int error;
/* Lookup for the corresponding outbound security policy */
- sp = ipsec6_checkpolicy(m, inp, &error);
+ sp = ipsec6_checkpolicy(m, inp, &error, !forwarding);
if (sp == NULL) {
if (error == -EINVAL) {
/* Discarded by policy. */
diff --git a/freebsd/sys/netipsec/key.c b/freebsd/sys/netipsec/key.c
index 0dfab7bd..ef5d8419 100644
--- a/freebsd/sys/netipsec/key.c
+++ b/freebsd/sys/netipsec/key.c
@@ -1405,7 +1405,8 @@ key_msg2sp(struct sadb_x_policy *xpl0, size_t len, int *error)
while (tlen > 0) {
/* length check */
- if (xisr->sadb_x_ipsecrequest_len < sizeof(*xisr)) {
+ if (xisr->sadb_x_ipsecrequest_len < sizeof(*xisr) ||
+ xisr->sadb_x_ipsecrequest_len > tlen) {
ipseclog((LOG_DEBUG, "%s: invalid ipsecrequest "
"length.\n", __func__));
key_freesp(&newsp);
@@ -1519,10 +1520,12 @@ key_msg2sp(struct sadb_x_policy *xpl0, size_t len, int *error)
if (xisr->sadb_x_ipsecrequest_len > sizeof(*xisr)) {
struct sockaddr *paddr;
+ len = tlen - sizeof(*xisr);
paddr = (struct sockaddr *)(xisr + 1);
/* validity check */
- if (paddr->sa_len
- > sizeof(isr->saidx.src)) {
+ if (len < sizeof(struct sockaddr) ||
+ len < 2 * paddr->sa_len ||
+ paddr->sa_len > sizeof(isr->saidx.src)) {
ipseclog((LOG_DEBUG, "%s: invalid "
"request address length.\n",
__func__));
@@ -1530,13 +1533,26 @@ key_msg2sp(struct sadb_x_policy *xpl0, size_t len, int *error)
*error = EINVAL;
return NULL;
}
+ /*
+ * Request length should be enough to keep
+ * source and destination addresses.
+ */
+ if (xisr->sadb_x_ipsecrequest_len <
+ sizeof(*xisr) + 2 * paddr->sa_len) {
+ ipseclog((LOG_DEBUG, "%s: invalid "
+ "ipsecrequest length.\n",
+ __func__));
+ key_freesp(&newsp);
+ *error = EINVAL;
+ return (NULL);
+ }
bcopy(paddr, &isr->saidx.src, paddr->sa_len);
paddr = (struct sockaddr *)((caddr_t)paddr +
paddr->sa_len);
/* validity check */
- if (paddr->sa_len
- > sizeof(isr->saidx.dst)) {
+ if (paddr->sa_len !=
+ isr->saidx.src.sa.sa_len) {
ipseclog((LOG_DEBUG, "%s: invalid "
"request address length.\n",
__func__));
diff --git a/freebsd/sys/netipsec/udpencap.c b/freebsd/sys/netipsec/udpencap.c
index 265461cd..3eb106b2 100644
--- a/freebsd/sys/netipsec/udpencap.c
+++ b/freebsd/sys/netipsec/udpencap.c
@@ -122,7 +122,7 @@ udp_ipsec_input(struct mbuf *m, int off, int af)
struct udphdr *udp;
struct ip *ip;
uint32_t spi;
- int error, hlen;
+ int hlen;
/*
* Just return if packet doesn't have enough data.
@@ -207,10 +207,7 @@ udp_ipsec_input(struct mbuf *m, int off, int af)
* will do this anyway, so don't touch them here.
*/
ESPSTAT_INC(esps_input);
- error = (*sav->tdb_xform->xf_input)(m, sav, hlen, off);
- if (error != 0)
- key_freesav(&sav);
-
+ (*sav->tdb_xform->xf_input)(m, sav, hlen, off);
return (EINPROGRESS); /* Consumed by IPsec. */
}
diff --git a/freebsd/sys/netipsec/xform_ah.c b/freebsd/sys/netipsec/xform_ah.c
index 9c2620f4..6e9baa1f 100644
--- a/freebsd/sys/netipsec/xform_ah.c
+++ b/freebsd/sys/netipsec/xform_ah.c
@@ -195,9 +195,9 @@ ah_init0(struct secasvar *sav, struct xformsw *xsp, struct cryptoini *cria)
return EINVAL;
}
keylen = _KEYLEN(sav->key_auth);
- if (keylen != thash->keysize && thash->keysize != 0) {
+ if (keylen > thash->keysize && thash->keysize != 0) {
DPRINTF(("%s: invalid keylength %d, algorithm %s requires "
- "keysize %d\n", __func__,
+ "keysize less than %d\n", __func__,
keylen, thash->name, thash->keysize));
return EINVAL;
}
diff --git a/freebsd/sys/netpfil/pf/pf_lb.c b/freebsd/sys/netpfil/pf/pf_lb.c
index 8d437667..abbf1c1e 100644
--- a/freebsd/sys/netpfil/pf/pf_lb.c
+++ b/freebsd/sys/netpfil/pf/pf_lb.c
@@ -261,7 +261,8 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r,
return (0);
}
} else {
- uint16_t tmp, cut;
+ uint32_t tmp;
+ uint16_t cut;
if (low > high) {
tmp = low;
@@ -271,7 +272,7 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r,
/* low < high */
cut = arc4random() % (1 + high - low) + low;
/* low <= cut <= high */
- for (tmp = cut; tmp <= high; ++(tmp)) {
+ for (tmp = cut; tmp <= high && tmp <= 0xffff; ++tmp) {
key.port[1] = htons(tmp);
if (pf_find_state_all(&key, PF_IN, NULL) ==
NULL) {
@@ -279,7 +280,8 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r,
return (0);
}
}
- for (tmp = cut - 1; tmp >= low; --(tmp)) {
+ tmp = cut;
+ for (tmp -= 1; tmp >= low && tmp <= 0xffff; --tmp) {
key.port[1] = htons(tmp);
if (pf_find_state_all(&key, PF_IN, NULL) ==
NULL) {
diff --git a/freebsd/sys/opencrypto/crypto.c b/freebsd/sys/opencrypto/crypto.c
index c1132ff3..57378e2f 100644
--- a/freebsd/sys/opencrypto/crypto.c
+++ b/freebsd/sys/opencrypto/crypto.c
@@ -467,7 +467,7 @@ crypto_newsession(u_int64_t *sid, struct cryptoini *cri, int crid)
CRYPTDEB("dev newsession failed");
} else {
CRYPTDEB("no driver");
- err = EINVAL;
+ err = EOPNOTSUPP;
}
CRYPTO_DRIVER_UNLOCK();
return err;
diff --git a/freebsd/sys/opencrypto/cryptodev.c b/freebsd/sys/opencrypto/cryptodev.c
index 20c8c89b..9d8b23dc 100644
--- a/freebsd/sys/opencrypto/cryptodev.c
+++ b/freebsd/sys/opencrypto/cryptodev.c
@@ -526,7 +526,8 @@ cryptof_ioctl(
if (thash) {
cria.cri_alg = thash->type;
cria.cri_klen = sop->mackeylen * 8;
- if (sop->mackeylen != thash->keysize) {
+ if (thash->keysize != 0 &&
+ sop->mackeylen > thash->keysize) {
CRYPTDEB("invalid mac key length");
error = EINVAL;
goto bail;
@@ -758,18 +759,22 @@ cryptodev_op(
goto bail;
}
- if (cse->thash) {
- crda = crp->crp_desc;
- if (cse->txform)
- crde = crda->crd_next;
- } else {
- if (cse->txform)
+ if (cse->thash && cse->txform) {
+ if (cop->flags & COP_F_CIPHER_FIRST) {
crde = crp->crp_desc;
- else {
- SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
- error = EINVAL;
- goto bail;
+ crda = crde->crd_next;
+ } else {
+ crda = crp->crp_desc;
+ crde = crda->crd_next;
}
+ } else if (cse->thash) {
+ crda = crp->crp_desc;
+ } else if (cse->txform) {
+ crde = crp->crp_desc;
+ } else {
+ SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
+ error = EINVAL;
+ goto bail;
}
if ((error = copyin(cop->src, cse->uio.uio_iov[0].iov_base,
@@ -925,7 +930,7 @@ cryptodev_aead(
uio->uio_iov = &cse->iovec;
uio->uio_iovcnt = 1;
uio->uio_offset = 0;
- uio->uio_resid = caead->len + caead->aadlen + cse->thash->hashsize;
+ uio->uio_resid = caead->aadlen + caead->len + cse->thash->hashsize;
uio->uio_segflg = UIO_SYSSPACE;
uio->uio_rw = UIO_WRITE;
uio->uio_td = td;
@@ -940,20 +945,33 @@ cryptodev_aead(
goto bail;
}
- crda = crp->crp_desc;
- crde = crda->crd_next;
+ if (caead->flags & COP_F_CIPHER_FIRST) {
+ crde = crp->crp_desc;
+ crda = crde->crd_next;
+ } else {
+ crda = crp->crp_desc;
+ crde = crda->crd_next;
+ }
- if ((error = copyin(caead->src, cse->uio.uio_iov[0].iov_base,
- caead->len)))
+ if ((error = copyin(caead->aad, cse->uio.uio_iov[0].iov_base,
+ caead->aadlen)))
goto bail;
- if ((error = copyin(caead->aad, (char *)cse->uio.uio_iov[0].iov_base +
- caead->len, caead->aadlen)))
+ if ((error = copyin(caead->src, (char *)cse->uio.uio_iov[0].iov_base +
+ caead->aadlen, caead->len)))
goto bail;
- crda->crd_skip = caead->len;
- crda->crd_len = caead->aadlen;
- crda->crd_inject = caead->len + caead->aadlen;
+ /*
+ * For GCM, crd_len covers only the AAD. For other ciphers
+ * chained with an HMAC, crd_len covers both the AAD and the
+ * cipher text.
+ */
+ crda->crd_skip = 0;
+ if (cse->cipher == CRYPTO_AES_NIST_GCM_16)
+ crda->crd_len = caead->aadlen;
+ else
+ crda->crd_len = caead->aadlen + caead->len;
+ crda->crd_inject = caead->aadlen + caead->len;
crda->crd_alg = cse->mac;
crda->crd_key = cse->mackey;
@@ -963,15 +981,15 @@ cryptodev_aead(
crde->crd_flags |= CRD_F_ENCRYPT;
else
crde->crd_flags &= ~CRD_F_ENCRYPT;
- /* crde->crd_skip set below */
+ crde->crd_skip = caead->aadlen;
crde->crd_len = caead->len;
- crde->crd_inject = 0;
+ crde->crd_inject = caead->aadlen;
crde->crd_alg = cse->cipher;
crde->crd_key = cse->key;
crde->crd_klen = cse->keylen * 8;
- crp->crp_ilen = caead->len + caead->aadlen;
+ crp->crp_ilen = caead->aadlen + caead->len;
crp->crp_flags = CRYPTO_F_IOV | CRYPTO_F_CBIMM
| (caead->flags & COP_F_BATCH);
crp->crp_buf = (caddr_t)&cse->uio.uio_iov;
@@ -989,10 +1007,9 @@ cryptodev_aead(
goto bail;
bcopy(cse->tmp_iv, crde->crd_iv, caead->ivlen);
crde->crd_flags |= CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT;
- crde->crd_skip = 0;
} else {
crde->crd_flags |= CRD_F_IV_PRESENT;
- crde->crd_skip = cse->txform->blocksize;
+ crde->crd_skip += cse->txform->blocksize;
crde->crd_len -= cse->txform->blocksize;
}
@@ -1032,12 +1049,13 @@ again:
goto bail;
}
- if (caead->dst && (error = copyout(cse->uio.uio_iov[0].iov_base,
- caead->dst, caead->len)))
+ if (caead->dst && (error = copyout(
+ (caddr_t)cse->uio.uio_iov[0].iov_base + caead->aadlen, caead->dst,
+ caead->len)))
goto bail;
if ((error = copyout((caddr_t)cse->uio.uio_iov[0].iov_base +
- caead->len + caead->aadlen, caead->tag, cse->thash->hashsize)))
+ caead->aadlen + caead->len, caead->tag, cse->thash->hashsize)))
goto bail;
bail:
diff --git a/freebsd/sys/opencrypto/cryptodev.h b/freebsd/sys/opencrypto/cryptodev.h
index ca584694..c42515a6 100644
--- a/freebsd/sys/opencrypto/cryptodev.h
+++ b/freebsd/sys/opencrypto/cryptodev.h
@@ -95,13 +95,6 @@
#define HMAC_IPAD_VAL 0x36
#define HMAC_OPAD_VAL 0x5C
/* HMAC Key Length */
-#define NULL_HMAC_KEY_LEN 0
-#define MD5_HMAC_KEY_LEN 16
-#define SHA1_HMAC_KEY_LEN 20
-#define RIPEMD160_HMAC_KEY_LEN 20
-#define SHA2_256_HMAC_KEY_LEN 32
-#define SHA2_384_HMAC_KEY_LEN 48
-#define SHA2_512_HMAC_KEY_LEN 64
#define AES_128_GMAC_KEY_LEN 16
#define AES_192_GMAC_KEY_LEN 24
#define AES_256_GMAC_KEY_LEN 32
@@ -238,7 +231,8 @@ struct crypt_op {
#define COP_ENCRYPT 1
#define COP_DECRYPT 2
u_int16_t flags;
-#define COP_F_BATCH 0x0008 /* Batch op if possible */
+#define COP_F_CIPHER_FIRST 0x0001 /* Cipher before MAC. */
+#define COP_F_BATCH 0x0008 /* Batch op if possible */
u_int len;
c_caddr_t src; /* become iov[] inside kernel */
caddr_t dst;
diff --git a/freebsd/sys/opencrypto/xform_aes_icm.c b/freebsd/sys/opencrypto/xform_aes_icm.c
index 94fa377a..8d3694fa 100644
--- a/freebsd/sys/opencrypto/xform_aes_icm.c
+++ b/freebsd/sys/opencrypto/xform_aes_icm.c
@@ -1,5 +1,3 @@
-#include <machine/rtems-bsd-kernel-space.h>
-
/* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */
/*-
* The authors of this code are John Ioannidis (ji@tla.org),
diff --git a/freebsd/sys/opencrypto/xform_aes_xts.c b/freebsd/sys/opencrypto/xform_aes_xts.c
index ab20368e..dedbe627 100644
--- a/freebsd/sys/opencrypto/xform_aes_xts.c
+++ b/freebsd/sys/opencrypto/xform_aes_xts.c
@@ -1,5 +1,3 @@
-#include <machine/rtems-bsd-kernel-space.h>
-
/* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */
/*-
* The authors of this code are John Ioannidis (ji@tla.org),
diff --git a/freebsd/sys/opencrypto/xform_blf.c b/freebsd/sys/opencrypto/xform_blf.c
index b88185b6..b4be5f8d 100644
--- a/freebsd/sys/opencrypto/xform_blf.c
+++ b/freebsd/sys/opencrypto/xform_blf.c
@@ -1,5 +1,3 @@
-#include <machine/rtems-bsd-kernel-space.h>
-
/* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */
/*-
* The authors of this code are John Ioannidis (ji@tla.org),
diff --git a/freebsd/sys/opencrypto/xform_cast5.c b/freebsd/sys/opencrypto/xform_cast5.c
index 6929faa3..85b346eb 100644
--- a/freebsd/sys/opencrypto/xform_cast5.c
+++ b/freebsd/sys/opencrypto/xform_cast5.c
@@ -1,5 +1,3 @@
-#include <machine/rtems-bsd-kernel-space.h>
-
/* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */
/*-
* The authors of this code are John Ioannidis (ji@tla.org),
diff --git a/freebsd/sys/opencrypto/xform_cml.c b/freebsd/sys/opencrypto/xform_cml.c
index c99b8c65..c807fa97 100644
--- a/freebsd/sys/opencrypto/xform_cml.c
+++ b/freebsd/sys/opencrypto/xform_cml.c
@@ -1,5 +1,3 @@
-#include <machine/rtems-bsd-kernel-space.h>
-
/* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */
/*-
* The authors of this code are John Ioannidis (ji@tla.org),
diff --git a/freebsd/sys/opencrypto/xform_deflate.c b/freebsd/sys/opencrypto/xform_deflate.c
index a17b87f4..c8864bf6 100644
--- a/freebsd/sys/opencrypto/xform_deflate.c
+++ b/freebsd/sys/opencrypto/xform_deflate.c
@@ -1,5 +1,3 @@
-#include <machine/rtems-bsd-kernel-space.h>
-
/* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */
/*-
* The authors of this code are John Ioannidis (ji@tla.org),
diff --git a/freebsd/sys/opencrypto/xform_des1.c b/freebsd/sys/opencrypto/xform_des1.c
index 91e52e52..cbce5e29 100644
--- a/freebsd/sys/opencrypto/xform_des1.c
+++ b/freebsd/sys/opencrypto/xform_des1.c
@@ -1,5 +1,3 @@
-#include <machine/rtems-bsd-kernel-space.h>
-
/* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */
/*-
* The authors of this code are John Ioannidis (ji@tla.org),
diff --git a/freebsd/sys/opencrypto/xform_des3.c b/freebsd/sys/opencrypto/xform_des3.c
index e47de600..1b26b622 100644
--- a/freebsd/sys/opencrypto/xform_des3.c
+++ b/freebsd/sys/opencrypto/xform_des3.c
@@ -1,5 +1,3 @@
-#include <machine/rtems-bsd-kernel-space.h>
-
/* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */
/*-
* The authors of this code are John Ioannidis (ji@tla.org),
diff --git a/freebsd/sys/opencrypto/xform_gmac.c b/freebsd/sys/opencrypto/xform_gmac.c
index be846fbf..156ed7f1 100644
--- a/freebsd/sys/opencrypto/xform_gmac.c
+++ b/freebsd/sys/opencrypto/xform_gmac.c
@@ -1,5 +1,3 @@
-#include <machine/rtems-bsd-kernel-space.h>
-
/* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */
/*-
* The authors of this code are John Ioannidis (ji@tla.org),
diff --git a/freebsd/sys/opencrypto/xform_md5.c b/freebsd/sys/opencrypto/xform_md5.c
index fd69a1c7..47dfc75c 100644
--- a/freebsd/sys/opencrypto/xform_md5.c
+++ b/freebsd/sys/opencrypto/xform_md5.c
@@ -1,5 +1,3 @@
-#include <machine/rtems-bsd-kernel-space.h>
-
/* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */
/*-
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -59,17 +57,27 @@ static int MD5Update_int(void *, const u_int8_t *, u_int16_t);
/* Authentication instances */
struct auth_hash auth_hash_hmac_md5 = {
- CRYPTO_MD5_HMAC, "HMAC-MD5",
- MD5_HMAC_KEY_LEN, MD5_HASH_LEN, sizeof(MD5_CTX), MD5_HMAC_BLOCK_LEN,
- (void (*) (void *)) MD5Init, NULL, NULL, MD5Update_int,
- (void (*) (u_int8_t *, void *)) MD5Final
+ .type = CRYPTO_MD5_HMAC,
+ .name = "HMAC-MD5",
+ .keysize = MD5_HMAC_BLOCK_LEN,
+ .hashsize = MD5_HASH_LEN,
+ .ctxsize = sizeof(MD5_CTX),
+ .blocksize = MD5_HMAC_BLOCK_LEN,
+ .Init = (void (*) (void *)) MD5Init,
+ .Update = MD5Update_int,
+ .Final = (void (*) (u_int8_t *, void *)) MD5Final,
};
struct auth_hash auth_hash_key_md5 = {
- CRYPTO_MD5_KPDK, "Keyed MD5",
- NULL_HMAC_KEY_LEN, MD5_KPDK_HASH_LEN, sizeof(MD5_CTX), 0,
- (void (*)(void *)) MD5Init, NULL, NULL, MD5Update_int,
- (void (*)(u_int8_t *, void *)) MD5Final
+ .type = CRYPTO_MD5_KPDK,
+ .name = "Keyed MD5",
+ .keysize = 0,
+ .hashsize = MD5_KPDK_HASH_LEN,
+ .ctxsize = sizeof(MD5_CTX),
+ .blocksize = 0,
+ .Init = (void (*)(void *)) MD5Init,
+ .Update = MD5Update_int,
+ .Final = (void (*)(u_int8_t *, void *)) MD5Final,
};
/*
diff --git a/freebsd/sys/opencrypto/xform_null.c b/freebsd/sys/opencrypto/xform_null.c
index 6dcf3ffd..3c499b31 100644
--- a/freebsd/sys/opencrypto/xform_null.c
+++ b/freebsd/sys/opencrypto/xform_null.c
@@ -1,5 +1,3 @@
-#include <machine/rtems-bsd-kernel-space.h>
-
/* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */
/*-
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -78,10 +76,18 @@ struct enc_xform enc_xform_null = {
};
/* Authentication instances */
-struct auth_hash auth_hash_null = { /* NB: context isn't used */
- CRYPTO_NULL_HMAC, "NULL-HMAC",
- NULL_HMAC_KEY_LEN, NULL_HASH_LEN, sizeof(int), NULL_HMAC_BLOCK_LEN,
- null_init, null_reinit, null_reinit, null_update, null_final
+struct auth_hash auth_hash_null = {
+ .type = CRYPTO_NULL_HMAC,
+ .name = "NULL-HMAC",
+ .keysize = 0,
+ .hashsize = NULL_HASH_LEN,
+ .ctxsize = sizeof(int), /* NB: context isn't used */
+ .blocksize = NULL_HMAC_BLOCK_LEN,
+ .Init = null_init,
+ .Setkey = null_reinit,
+ .Reinit = null_reinit,
+ .Update = null_update,
+ .Final = null_final,
};
/*
diff --git a/freebsd/sys/opencrypto/xform_rijndael.c b/freebsd/sys/opencrypto/xform_rijndael.c
index 9dcb4d3c..2c974f3d 100644
--- a/freebsd/sys/opencrypto/xform_rijndael.c
+++ b/freebsd/sys/opencrypto/xform_rijndael.c
@@ -1,5 +1,3 @@
-#include <machine/rtems-bsd-kernel-space.h>
-
/* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */
/*-
* The authors of this code are John Ioannidis (ji@tla.org),
diff --git a/freebsd/sys/opencrypto/xform_rmd160.c b/freebsd/sys/opencrypto/xform_rmd160.c
index 016bd627..ee344e80 100644
--- a/freebsd/sys/opencrypto/xform_rmd160.c
+++ b/freebsd/sys/opencrypto/xform_rmd160.c
@@ -1,5 +1,3 @@
-#include <machine/rtems-bsd-kernel-space.h>
-
/* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */
/*-
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -59,11 +57,15 @@ static int RMD160Update_int(void *, const u_int8_t *, u_int16_t);
/* Authentication instances */
struct auth_hash auth_hash_hmac_ripemd_160 = {
- CRYPTO_RIPEMD160_HMAC, "HMAC-RIPEMD-160",
- RIPEMD160_HMAC_KEY_LEN, RIPEMD160_HASH_LEN, sizeof(RMD160_CTX),
- RIPEMD160_HMAC_BLOCK_LEN,
- (void (*)(void *)) RMD160Init, NULL, NULL, RMD160Update_int,
- (void (*)(u_int8_t *, void *)) RMD160Final
+ .type = CRYPTO_RIPEMD160_HMAC,
+ .name = "HMAC-RIPEMD-160",
+ .keysize = RIPEMD160_HMAC_BLOCK_LEN,
+ .hashsize = RIPEMD160_HASH_LEN,
+ .ctxsize = sizeof(RMD160_CTX),
+ .blocksize = RIPEMD160_HMAC_BLOCK_LEN,
+ .Init = (void (*)(void *)) RMD160Init,
+ .Update = RMD160Update_int,
+ .Final = (void (*)(u_int8_t *, void *)) RMD160Final,
};
/*
diff --git a/freebsd/sys/opencrypto/xform_sha1.c b/freebsd/sys/opencrypto/xform_sha1.c
index 76489048..974dfb8a 100644
--- a/freebsd/sys/opencrypto/xform_sha1.c
+++ b/freebsd/sys/opencrypto/xform_sha1.c
@@ -1,5 +1,3 @@
-#include <machine/rtems-bsd-kernel-space.h>
-
/* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */
/*-
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -61,15 +59,27 @@ static void SHA1Final_int(u_int8_t *, void *);
/* Authentication instances */
struct auth_hash auth_hash_hmac_sha1 = {
- CRYPTO_SHA1_HMAC, "HMAC-SHA1",
- SHA1_HMAC_KEY_LEN, SHA1_HASH_LEN, sizeof(SHA1_CTX), SHA1_HMAC_BLOCK_LEN,
- SHA1Init_int, NULL, NULL, SHA1Update_int, SHA1Final_int
+ .type = CRYPTO_SHA1_HMAC,
+ .name = "HMAC-SHA1",
+ .keysize = SHA1_HMAC_BLOCK_LEN,
+ .hashsize = SHA1_HASH_LEN,
+ .ctxsize = sizeof(SHA1_CTX),
+ .blocksize = SHA1_HMAC_BLOCK_LEN,
+ .Init = SHA1Init_int,
+ .Update = SHA1Update_int,
+ .Final = SHA1Final_int,
};
struct auth_hash auth_hash_key_sha1 = {
- CRYPTO_SHA1_KPDK, "Keyed SHA1",
- NULL_HMAC_KEY_LEN, SHA1_KPDK_HASH_LEN, sizeof(SHA1_CTX), 0,
- SHA1Init_int, NULL, NULL, SHA1Update_int, SHA1Final_int
+ .type = CRYPTO_SHA1_KPDK,
+ .name = "Keyed SHA1",
+ .keysize = 0,
+ .hashsize = SHA1_KPDK_HASH_LEN,
+ .ctxsize = sizeof(SHA1_CTX),
+ .blocksize = 0,
+ .Init = SHA1Init_int,
+ .Update = SHA1Update_int,
+ .Final = SHA1Final_int,
};
/*
diff --git a/freebsd/sys/opencrypto/xform_sha2.c b/freebsd/sys/opencrypto/xform_sha2.c
index f3f895d0..7844b8ff 100644
--- a/freebsd/sys/opencrypto/xform_sha2.c
+++ b/freebsd/sys/opencrypto/xform_sha2.c
@@ -1,5 +1,3 @@
-#include <machine/rtems-bsd-kernel-space.h>
-
/* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */
/*-
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -63,27 +61,39 @@ static int SHA512Update_int(void *, const u_int8_t *, u_int16_t);
/* Authentication instances */
struct auth_hash auth_hash_hmac_sha2_256 = {
- CRYPTO_SHA2_256_HMAC, "HMAC-SHA2-256",
- SHA2_256_HMAC_KEY_LEN, SHA2_256_HASH_LEN, sizeof(SHA256_CTX),
- SHA2_256_HMAC_BLOCK_LEN,
- (void (*)(void *)) SHA256_Init, NULL, NULL, SHA256Update_int,
- (void (*)(u_int8_t *, void *)) SHA256_Final
+ .type = CRYPTO_SHA2_256_HMAC,
+ .name = "HMAC-SHA2-256",
+ .keysize = SHA2_256_HMAC_BLOCK_LEN,
+ .hashsize = SHA2_256_HASH_LEN,
+ .ctxsize = sizeof(SHA256_CTX),
+ .blocksize = SHA2_256_HMAC_BLOCK_LEN,
+ .Init = (void (*)(void *)) SHA256_Init,
+ .Update = SHA256Update_int,
+ .Final = (void (*)(u_int8_t *, void *)) SHA256_Final,
};
struct auth_hash auth_hash_hmac_sha2_384 = {
- CRYPTO_SHA2_384_HMAC, "HMAC-SHA2-384",
- SHA2_384_HMAC_KEY_LEN, SHA2_384_HASH_LEN, sizeof(SHA384_CTX),
- SHA2_384_HMAC_BLOCK_LEN,
- (void (*)(void *)) SHA384_Init, NULL, NULL, SHA384Update_int,
- (void (*)(u_int8_t *, void *)) SHA384_Final
+ .type = CRYPTO_SHA2_384_HMAC,
+ .name = "HMAC-SHA2-384",
+ .keysize = SHA2_384_HMAC_BLOCK_LEN,
+ .hashsize = SHA2_384_HASH_LEN,
+ .ctxsize = sizeof(SHA384_CTX),
+ .blocksize = SHA2_384_HMAC_BLOCK_LEN,
+ .Init = (void (*)(void *)) SHA384_Init,
+ .Update = SHA384Update_int,
+ .Final = (void (*)(u_int8_t *, void *)) SHA384_Final,
};
struct auth_hash auth_hash_hmac_sha2_512 = {
- CRYPTO_SHA2_512_HMAC, "HMAC-SHA2-512",
- SHA2_512_HMAC_KEY_LEN, SHA2_512_HASH_LEN, sizeof(SHA512_CTX),
- SHA2_512_HMAC_BLOCK_LEN,
- (void (*)(void *)) SHA512_Init, NULL, NULL, SHA512Update_int,
- (void (*)(u_int8_t *, void *)) SHA512_Final
+ .type = CRYPTO_SHA2_512_HMAC,
+ .name = "HMAC-SHA2-512",
+ .keysize = SHA2_512_HMAC_BLOCK_LEN,
+ .hashsize = SHA2_512_HASH_LEN,
+ .ctxsize = sizeof(SHA512_CTX),
+ .blocksize = SHA2_512_HMAC_BLOCK_LEN,
+ .Init = (void (*)(void *)) SHA512_Init,
+ .Update = SHA512Update_int,
+ .Final = (void (*)(u_int8_t *, void *)) SHA512_Final,
};
/*
diff --git a/freebsd/sys/opencrypto/xform_skipjack.c b/freebsd/sys/opencrypto/xform_skipjack.c
index 066381c9..94090d0d 100644
--- a/freebsd/sys/opencrypto/xform_skipjack.c
+++ b/freebsd/sys/opencrypto/xform_skipjack.c
@@ -1,5 +1,3 @@
-#include <machine/rtems-bsd-kernel-space.h>
-
/* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */
/*-
* The authors of this code are John Ioannidis (ji@tla.org),
diff --git a/freebsd/sys/powerpc/include/machine/spr.h b/freebsd/sys/powerpc/include/machine/spr.h
index d9501153..5efdf961 100644
--- a/freebsd/sys/powerpc/include/machine/spr.h
+++ b/freebsd/sys/powerpc/include/machine/spr.h
@@ -171,6 +171,7 @@
#define IBMPOWER7PLUS 0x004a
#define IBMPOWER8E 0x004b
#define IBMPOWER8 0x004d
+#define IBMPOWER9 0x004e
#define MPC860 0x0050
#define IBMCELLBE 0x0070
#define MPC8240 0x0081
@@ -191,6 +192,10 @@
#define FSL_E500mc 0x8023
#define FSL_E5500 0x8024
#define FSL_E6500 0x8040
+#define FSL_E300C1 0x8083
+#define FSL_E300C2 0x8084
+#define FSL_E300C3 0x8085
+#define FSL_E300C4 0x8086
#define SPR_EPCR 0x133
#define EPCR_EXTGS 0x80000000
@@ -742,6 +747,10 @@
#define SVR_P4080E 0x8209
#define SVR_P5020 0x8220
#define SVR_P5020E 0x8228
+#define SVR_P5021 0x8205
+#define SVR_P5021E 0x820d
+#define SVR_P5040 0x8204
+#define SVR_P5040E 0x820c
#define SVR_VER(svr) (((svr) >> 16) & 0xffff)
#define SPR_PID0 0x030 /* ..8 Process ID Register 0 */
diff --git a/freebsd/sys/sys/_task.h b/freebsd/sys/sys/_task.h
index d3be7198..d46659f4 100644
--- a/freebsd/sys/sys/_task.h
+++ b/freebsd/sys/sys/_task.h
@@ -65,7 +65,8 @@ struct grouptask {
void *gt_taskqueue;
LIST_ENTRY(grouptask) gt_list;
void *gt_uniq;
- char *gt_name;
+#define GROUPTASK_NAMELEN 32
+ char gt_name[GROUPTASK_NAMELEN];
int16_t gt_irq;
int16_t gt_cpu;
};
diff --git a/freebsd/sys/sys/blist.h b/freebsd/sys/sys/blist.h
index 292f9b97..486e04eb 100644
--- a/freebsd/sys/sys/blist.h
+++ b/freebsd/sys/sys/blist.h
@@ -80,8 +80,7 @@ typedef struct blmeta {
typedef struct blist {
daddr_t bl_blocks; /* area of coverage */
- daddr_t bl_radix; /* coverage radix */
- daddr_t bl_skip; /* starting skip */
+ u_daddr_t bl_radix; /* coverage radix */
daddr_t bl_cursor; /* next-fit search starts at */
blmeta_t *bl_root; /* root of radix tree */
} *blist_t;
@@ -91,6 +90,8 @@ typedef struct blist {
#define BLIST_MAX_ALLOC BLIST_BMAP_RADIX
+struct sbuf;
+
daddr_t blist_alloc(blist_t blist, daddr_t count);
daddr_t blist_avail(blist_t blist);
blist_t blist_create(daddr_t blocks, int flags);
@@ -99,6 +100,7 @@ daddr_t blist_fill(blist_t bl, daddr_t blkno, daddr_t count);
void blist_free(blist_t blist, daddr_t blkno, daddr_t count);
void blist_print(blist_t blist);
void blist_resize(blist_t *pblist, daddr_t count, int freenew, int flags);
+void blist_stats(blist_t blist, struct sbuf *s);
#endif /* _SYS_BLIST_H_ */
diff --git a/freebsd/sys/sys/buf.h b/freebsd/sys/sys/buf.h
index 58bd91e3..5d4f0dc6 100644
--- a/freebsd/sys/sys/buf.h
+++ b/freebsd/sys/sys/buf.h
@@ -70,7 +70,7 @@ extern struct bio_ops {
struct vm_object;
struct vm_page;
-typedef unsigned char b_xflags_t;
+typedef uint32_t b_xflags_t;
/*
* The buffer header describes an I/O operation in the kernel.
@@ -104,6 +104,8 @@ struct buf {
off_t b_iooffset;
long b_resid;
void (*b_iodone)(struct buf *);
+ void (*b_ckhashcalc)(struct buf *);
+ uint64_t b_ckhash; /* B_CKHASH requested check-hash */
daddr_t b_blkno; /* Underlying physical block number. */
off_t b_offset; /* Offset into file. */
TAILQ_ENTRY(buf) b_bobufs; /* (V) Buffer's associated vnode. */
@@ -209,7 +211,7 @@ struct buf {
#define B_CACHE 0x00000020 /* Bread found us in the cache. */
#define B_VALIDSUSPWRT 0x00000040 /* Valid write during suspension. */
#define B_DELWRI 0x00000080 /* Delay I/O until buffer reused. */
-#define B_00000100 0x00000100 /* Available flag. */
+#define B_CKHASH 0x00000100 /* checksum hash calculated on read */
#define B_DONE 0x00000200 /* I/O completed. */
#define B_EINTR 0x00000400 /* I/O was interrupted */
#define B_NOREUSE 0x00000800 /* Contents not reused once released. */
@@ -242,12 +244,17 @@ struct buf {
/*
* These flags are kept in b_xflags.
+ *
+ * BX_FSPRIV reserves a set of eight flags that may be used by individual
+ * filesystems for their own purpose. Their specific definitions are
+ * found in the header files for each filesystem that uses them.
*/
#define BX_VNDIRTY 0x00000001 /* On vnode dirty list */
#define BX_VNCLEAN 0x00000002 /* On vnode clean list */
#define BX_BKGRDWRITE 0x00000010 /* Do writes in background */
#define BX_BKGRDMARKER 0x00000020 /* Mark buffer for splay tree */
#define BX_ALTDATA 0x00000040 /* Holds extended data */
+#define BX_FSPRIV 0x00FF0000 /* filesystem-specific flags mask */
#define PRINT_BUF_XFLAGS "\20\7altdata\6bkgrdmarker\5bkgrdwrite\2clean\1dirty"
@@ -467,6 +474,7 @@ buf_track(struct buf *bp, const char *location)
#define GB_NOWAIT_BD 0x0004 /* Do not wait for bufdaemon. */
#define GB_UNMAPPED 0x0008 /* Do not mmap buffer pages. */
#define GB_KVAALLOC 0x0010 /* But allocate KVA. */
+#define GB_CKHASH 0x0020 /* If reading, calc checksum hash */
#ifdef _KERNEL
extern int nbuf; /* The number of buffer headers */
@@ -504,15 +512,15 @@ int buf_dirty_count_severe(void);
void bremfree(struct buf *);
void bremfreef(struct buf *); /* XXX Force bremfree, only for nfs. */
#define bread(vp, blkno, size, cred, bpp) \
- breadn_flags(vp, blkno, size, NULL, NULL, 0, cred, 0, bpp)
+ breadn_flags(vp, blkno, size, NULL, NULL, 0, cred, 0, NULL, bpp)
#define bread_gb(vp, blkno, size, cred, gbflags, bpp) \
breadn_flags(vp, blkno, size, NULL, NULL, 0, cred, \
- gbflags, bpp)
+ gbflags, NULL, bpp)
#define breadn(vp, blkno, size, rablkno, rabsize, cnt, cred, bpp) \
- breadn_flags(vp, blkno, size, rablkno, rabsize, cnt, cred, 0, bpp)
+ breadn_flags(vp, blkno, size, rablkno, rabsize, cnt, cred, \
+ 0, NULL, bpp)
int breadn_flags(struct vnode *, daddr_t, int, daddr_t *, int *, int,
- struct ucred *, int, struct buf **);
-void breada(struct vnode *, daddr_t *, int *, int, struct ucred *);
+ struct ucred *, int, void (*)(struct buf *), struct buf **);
void bdwrite(struct buf *);
void bawrite(struct buf *);
void babarrierwrite(struct buf *);
diff --git a/freebsd/sys/sys/conf.h b/freebsd/sys/sys/conf.h
index a49b6d60..8bf6a3ed 100644
--- a/freebsd/sys/sys/conf.h
+++ b/freebsd/sys/sys/conf.h
@@ -370,12 +370,13 @@ struct dumperinfo {
int set_dumper(struct dumperinfo *di, const char *devname, struct thread *td,
uint8_t encrypt, const uint8_t *key, uint32_t encryptedkeysize,
const uint8_t *encryptedkey);
+void dump_init_header(const struct dumperinfo *di, struct kerneldumpheader *kdh,
+ char *magic, uint32_t archver, uint64_t dumplen);
+int dump_start(struct dumperinfo *di, struct kerneldumpheader *kdh,
+ off_t *dumplop);
+int dump_finish(struct dumperinfo *di, struct kerneldumpheader *kdh,
+ off_t dumplo);
int dump_write(struct dumperinfo *, void *, vm_offset_t, off_t, size_t);
-int dump_write_pad(struct dumperinfo *, void *, vm_offset_t, off_t, size_t,
- size_t *);
-int dump_write_header(struct dumperinfo *di, struct kerneldumpheader *kdh,
- vm_offset_t physical, off_t offset);
-int dump_write_key(struct dumperinfo *di, vm_offset_t physical, off_t offset);
int doadump(boolean_t);
#ifndef __rtems__
extern int dumping; /* system is dumping */
diff --git a/freebsd/sys/sys/gpio.h b/freebsd/sys/sys/gpio.h
index 9b0a1b55..dbe55872 100644
--- a/freebsd/sys/sys/gpio.h
+++ b/freebsd/sys/sys/gpio.h
@@ -70,6 +70,8 @@
#define GPIO_PIN_INVIN 0x00000080 /* invert input */
#define GPIO_PIN_INVOUT 0x00000100 /* invert output */
#define GPIO_PIN_PULSATE 0x00000200 /* pulsate in hardware */
+#define GPIO_PIN_PRESET_LOW 0x00000400 /* preset pin to high or */
+#define GPIO_PIN_PRESET_HIGH 0x00000800 /* low before enabling output */
/* GPIO interrupt capabilities */
#define GPIO_INTR_NONE 0x00000000 /* no interrupt support */
#define GPIO_INTR_LEVEL_LOW 0x00010000 /* level trigger, low */
@@ -95,6 +97,71 @@ struct gpio_req {
};
/*
+ * gpio_access_32 / GPIOACCESS32
+ *
+ * Simultaneously read and/or change up to 32 adjacent pins.
+ * If the device cannot change the pins simultaneously, returns EOPNOTSUPP.
+ *
+ * This accesses an adjacent set of up to 32 pins starting at first_pin within
+ * the device's collection of pins. How the hardware pins are mapped to the 32
+ * bits in the arguments is device-specific. It is expected that lower-numbered
+ * pins in the device's number space map linearly to lower-ordered bits within
+ * the 32-bit words (i.e., bit 0 is first_pin, bit 1 is first_pin+1, etc).
+ * Other mappings are possible; know your device.
+ *
+ * Some devices may limit the value of first_pin to 0, or to multiples of 16 or
+ * 32 or some other hardware-specific number; to access pin 2 would require
+ * first_pin to be zero and then manipulate bit (1 << 2) in the 32-bit word.
+ * Invalid values in first_pin result in an EINVAL error return.
+ *
+ * The starting state of the pins is captured and stored in orig_pins, then the
+ * pins are set to ((starting_state & ~clear_pins) ^ change_pins).
+ *
+ * Clear Change Hardware pin after call
+ * 0 0 No change
+ * 0 1 Opposite of current value
+ * 1 0 Cleared
+ * 1 1 Set
+ */
+struct gpio_access_32 {
+ uint32_t first_pin; /* First pin in group of 32 adjacent */
+ uint32_t clear_pins; /* Pins are changed using: */
+ uint32_t change_pins; /* ((hwstate & ~clear_pins) ^ change_pins) */
+ uint32_t orig_pins; /* Returned hwstate of pins before change. */
+};
+
+/*
+ * gpio_config_32 / GPIOCONFIG32
+ *
+ * Simultaneously configure up to 32 adjacent pins. This is intended to change
+ * the configuration of all the pins simultaneously, such that pins configured
+ * for output all begin to drive the configured values simultaneously, but not
+ * all hardware can do that, so the driver "does the best it can" in this
+ * regard. Notably unlike pin_access_32(), this does NOT fail if the pins
+ * cannot be atomically configured; it is expected that callers understand the
+ * hardware and have decided to live with any such limitations it may have.
+ *
+ * The pin_flags argument is an array of GPIO_PIN_xxxx flags. If the array
+ * contains any GPIO_PIN_OUTPUT flags, the driver will manipulate the hardware
+ * such that all output pins become driven with the proper initial values
+ * simultaneously if it can. The elements in the array map to pins in the same
+ * way that bits are mapped by pin_acces_32(), and the same restrictions may
+ * apply. For example, to configure pins 2 and 3 it may be necessary to set
+ * first_pin to zero and only populate pin_flags[2] and pin_flags[3]. If a
+ * given array entry doesn't contain GPIO_PIN_INPUT or GPIO_PIN_OUTPUT then no
+ * configuration is done for that pin.
+ *
+ * Some devices may limit the value of first_pin to 0, or to multiples of 16 or
+ * 32 or some other hardware-specific number. Invalid values in first_pin or
+ * num_pins result in an error return with errno set to EINVAL.
+ */
+struct gpio_config_32 {
+ uint32_t first_pin;
+ uint32_t num_pins;
+ uint32_t pin_flags[32];
+};
+
+/*
* ioctls
*/
#define GPIOMAXPIN _IOR('G', 0, int)
@@ -104,5 +171,7 @@ struct gpio_req {
#define GPIOSET _IOW('G', 4, struct gpio_req)
#define GPIOTOGGLE _IOWR('G', 5, struct gpio_req)
#define GPIOSETNAME _IOW('G', 6, struct gpio_pin)
+#define GPIOACCESS32 _IOWR('G', 7, struct gpio_access_32)
+#define GPIOCONFIG32 _IOW('G', 8, struct gpio_config_32)
#endif /* __GPIO_H__ */
diff --git a/freebsd/sys/sys/gtaskqueue.h b/freebsd/sys/sys/gtaskqueue.h
index c9b34e4f..e8519637 100644
--- a/freebsd/sys/sys/gtaskqueue.h
+++ b/freebsd/sys/sys/gtaskqueue.h
@@ -80,21 +80,6 @@ int taskqgroup_adjust(struct taskqgroup *qgroup, int cnt, int stride);
#define TASKQGROUP_DECLARE(name) \
extern struct taskqgroup *qgroup_##name
-#ifdef EARLY_AP_STARTUP
-#define TASKQGROUP_DEFINE(name, cnt, stride) \
- \
-struct taskqgroup *qgroup_##name; \
- \
-static void \
-taskqgroup_define_##name(void *arg) \
-{ \
- qgroup_##name = taskqgroup_create(#name); \
- taskqgroup_adjust(qgroup_##name, (cnt), (stride)); \
-} \
- \
-SYSINIT(taskqgroup_##name, SI_SUB_INIT_IF, SI_ORDER_FIRST, \
- taskqgroup_define_##name, NULL)
-#else /* !EARLY_AP_STARTUP */
#define TASKQGROUP_DEFINE(name, cnt, stride) \
\
struct taskqgroup *qgroup_##name; \
@@ -105,7 +90,7 @@ taskqgroup_define_##name(void *arg) \
qgroup_##name = taskqgroup_create(#name); \
} \
\
-SYSINIT(taskqgroup_##name, SI_SUB_INIT_IF, SI_ORDER_FIRST, \
+SYSINIT(taskqgroup_##name, SI_SUB_TASKQ, SI_ORDER_FIRST, \
taskqgroup_define_##name, NULL); \
\
static void \
@@ -116,7 +101,6 @@ taskqgroup_adjust_##name(void *arg) \
\
SYSINIT(taskqgroup_adj_##name, SI_SUB_SMP, SI_ORDER_ANY, \
taskqgroup_adjust_##name, NULL)
-#endif /* EARLY_AP_STARTUP */
TASKQGROUP_DECLARE(net);
TASKQGROUP_DECLARE(softirq);
diff --git a/freebsd/sys/sys/kernel.h b/freebsd/sys/sys/kernel.h
index 3ca8af6e..051173f7 100644
--- a/freebsd/sys/sys/kernel.h
+++ b/freebsd/sys/sys/kernel.h
@@ -129,6 +129,7 @@ enum sysinit_sub_id {
SI_SUB_SCHED_IDLE = 0x2600000, /* required idle procs */
SI_SUB_MBUF = 0x2700000, /* mbuf subsystem */
SI_SUB_INTR = 0x2800000, /* interrupt threads */
+ SI_SUB_TASKQ = 0x2880000, /* task queues */
#ifdef EARLY_AP_STARTUP
SI_SUB_SMP = 0x2900000, /* start the APs*/
#endif
@@ -454,13 +455,16 @@ struct tunable_str {
#define TUNABLE_STR_FETCH(path, var, size)
#endif /* __rtems__ */
+typedef void (*ich_func_t)(void *_arg);
+
struct intr_config_hook {
TAILQ_ENTRY(intr_config_hook) ich_links;
- void (*ich_func)(void *arg);
- void *ich_arg;
+ ich_func_t ich_func;
+ void *ich_arg;
};
int config_intrhook_establish(struct intr_config_hook *hook);
void config_intrhook_disestablish(struct intr_config_hook *hook);
+void config_intrhook_oneshot(ich_func_t _func, void *_arg);
#endif /* !_SYS_KERNEL_H_*/
diff --git a/freebsd/sys/sys/mbuf.h b/freebsd/sys/sys/mbuf.h
index 60670697..ec98aaec 100644
--- a/freebsd/sys/sys/mbuf.h
+++ b/freebsd/sys/sys/mbuf.h
@@ -335,6 +335,16 @@ struct mbuf {
* for ordering and distribution without explicit affinity. Additionally,
* M_HASHTYPE_OPAQUE_HASH indicates that the flow identifier has hash
* properties.
+ *
+ * The meaning of the IPV6_EX suffix:
+ * "o Home address from the home address option in the IPv6 destination
+ * options header. If the extension header is not present, use the Source
+ * IPv6 Address.
+ * o IPv6 address that is contained in the Routing-Header-Type-2 from the
+ * associated extension header. If the extension header is not present,
+ * use the Destination IPv6 Address."
+ * Quoted from:
+ * https://docs.microsoft.com/en-us/windows-hardware/drivers/network/rss-hashing-types#ndishashipv6ex
*/
#define M_HASHTYPE_HASHPROP 0x80 /* has hash properties */
#define M_HASHTYPE_HASH(t) (M_HASHTYPE_HASHPROP | (t))
@@ -348,10 +358,7 @@ struct mbuf {
* ext hdrs */
#define M_HASHTYPE_RSS_TCP_IPV6_EX M_HASHTYPE_HASH(6) /* TCPv6 4-tuple +
* ext hdrs */
-/* Non-standard RSS hash types */
#define M_HASHTYPE_RSS_UDP_IPV4 M_HASHTYPE_HASH(7) /* IPv4 UDP 4-tuple*/
-#define M_HASHTYPE_RSS_UDP_IPV4_EX M_HASHTYPE_HASH(8) /* IPv4 UDP 4-tuple +
- * ext hdrs */
#define M_HASHTYPE_RSS_UDP_IPV6 M_HASHTYPE_HASH(9) /* IPv6 UDP 4-tuple*/
#define M_HASHTYPE_RSS_UDP_IPV6_EX M_HASHTYPE_HASH(10)/* IPv6 UDP 4-tuple +
* ext hdrs */
diff --git a/freebsd/sys/sys/module.h b/freebsd/sys/sys/module.h
index 5a268fc1..75471611 100644
--- a/freebsd/sys/sys/module.h
+++ b/freebsd/sys/sys/module.h
@@ -183,7 +183,7 @@ struct mod_pnp_match_info
&_module_pnp_##b##_##unique, #b);
/**
* descr is a string that describes each entry in the table. The general
- * form is (TYPE:pnp_name[/pnp_name];)*
+ * form is the grammar (TYPE:pnp_name[/pnp_name];)*
* where TYPE is one of the following:
* U8 uint8_t element
* V8 like U8 and 0xff means match any
@@ -196,12 +196,14 @@ struct mod_pnp_match_info
* V32 like U32 and 0xffffffff means match any
* W32 Two 16-bit values with first pnp_name in LSW and second in MSW.
* Z pointer to a string to match exactly
- * D like Z, but is the string passed to device_set_descr()
+ * D pointer to a string to human readable description for device
* P A pointer that should be ignored
* E EISA PNP Identifier (in binary, but bus publishes string)
* K Key for whole table. pnp_name=value. must be last, if present.
*
* The pnp_name "#" is reserved for other fields that should be ignored.
+ * Otherwise pnp_name must match the name from the parent device's pnpinfo
+ * output. The second pnp_name is used for the W32 type.
*/
extern struct sx modules_sx;
diff --git a/freebsd/sys/sys/mutex.h b/freebsd/sys/sys/mutex.h
index 5325b363..bd773b58 100644
--- a/freebsd/sys/sys/mutex.h
+++ b/freebsd/sys/sys/mutex.h
@@ -107,12 +107,12 @@ int _mtx_trylock_flags_(volatile uintptr_t *c, int opts, const char *file,
void mutex_init(void);
#ifndef __rtems__
#if LOCK_DEBUG > 0
-void __mtx_lock_sleep(volatile uintptr_t *c, uintptr_t v, uintptr_t tid,
- int opts, const char *file, int line);
+void __mtx_lock_sleep(volatile uintptr_t *c, uintptr_t v, int opts,
+ const char *file, int line);
void __mtx_unlock_sleep(volatile uintptr_t *c, int opts, const char *file,
int line);
#else
-void __mtx_lock_sleep(volatile uintptr_t *c, uintptr_t v, uintptr_t tid);
+void __mtx_lock_sleep(volatile uintptr_t *c, uintptr_t v);
void __mtx_unlock_sleep(volatile uintptr_t *c);
#endif
@@ -176,13 +176,13 @@ void thread_lock_flags_(struct thread *, int, const char *, int);
#define mtx_trylock_flags_(m, o, f, l) \
_mtx_trylock_flags_(&(m)->mtx_lock, o, f, l)
#if LOCK_DEBUG > 0
-#define _mtx_lock_sleep(m, v, t, o, f, l) \
- __mtx_lock_sleep(&(m)->mtx_lock, v, t, o, f, l)
+#define _mtx_lock_sleep(m, v, o, f, l) \
+ __mtx_lock_sleep(&(m)->mtx_lock, v, o, f, l)
#define _mtx_unlock_sleep(m, o, f, l) \
__mtx_unlock_sleep(&(m)->mtx_lock, o, f, l)
#else
-#define _mtx_lock_sleep(m, v, t, o, f, l) \
- __mtx_lock_sleep(&(m)->mtx_lock, v, t)
+#define _mtx_lock_sleep(m, v, o, f, l) \
+ __mtx_lock_sleep(&(m)->mtx_lock, v)
#define _mtx_unlock_sleep(m, o, f, l) \
__mtx_unlock_sleep(&(m)->mtx_lock)
#endif
@@ -238,7 +238,7 @@ void thread_lock_flags_(struct thread *, int, const char *, int);
\
if (__predict_false(LOCKSTAT_PROFILE_ENABLED(adaptive__acquire) ||\
!_mtx_obtain_lock_fetch((mp), &_v, _tid))) \
- _mtx_lock_sleep((mp), _v, _tid, (opts), (file), (line));\
+ _mtx_lock_sleep((mp), _v, (opts), (file), (line)); \
} while (0)
/*
diff --git a/freebsd/sys/sys/sbuf.h b/freebsd/sys/sys/sbuf.h
index c05bafd1..d0f908be 100644
--- a/freebsd/sys/sys/sbuf.h
+++ b/freebsd/sys/sys/sbuf.h
@@ -49,6 +49,7 @@ struct sbuf {
#define SBUF_FIXEDLEN 0x00000000 /* fixed length buffer (default) */
#define SBUF_AUTOEXTEND 0x00000001 /* automatically extend buffer */
#define SBUF_INCLUDENUL 0x00000002 /* nulterm byte is counted in len */
+#define SBUF_DRAINTOEOR 0x00000004 /* use section 0 as drain EOR marker */
#define SBUF_USRFLAGMSK 0x0000ffff /* mask of flags the user may specify */
#define SBUF_DYNAMIC 0x00010000 /* s_buf must be freed */
#define SBUF_FINISHED 0x00020000 /* set by sbuf_finish() */
@@ -56,6 +57,7 @@ struct sbuf {
#define SBUF_INSECTION 0x00100000 /* set by sbuf_start_section() */
int s_flags; /* flags */
ssize_t s_sect_len; /* current length of section */
+ ssize_t s_rec_off; /* current record start offset */
};
#ifndef HD_COLUMN_MASK
diff --git a/freebsd/sys/sys/smp.h b/freebsd/sys/sys/smp.h
index 9101bd76..9253304f 100644
--- a/freebsd/sys/sys/smp.h
+++ b/freebsd/sys/sys/smp.h
@@ -120,8 +120,25 @@ struct topo_node * topo_next_node(struct topo_node *top,
struct topo_node * topo_next_nonchild_node(struct topo_node *top,
struct topo_node *node);
void topo_set_pu_id(struct topo_node *node, cpuid_t id);
-int topo_analyze(struct topo_node *topo_root, int all, int *pkg_count,
- int *cores_per_pkg, int *thrs_per_core);
+
+enum topo_level {
+ TOPO_LEVEL_PKG = 0,
+ /*
+ * Some systems have useful sub-package core organizations. On these,
+ * a package has one or more subgroups. Each subgroup contains one or
+ * more cache groups (cores that share a last level cache).
+ */
+ TOPO_LEVEL_GROUP,
+ TOPO_LEVEL_CACHEGROUP,
+ TOPO_LEVEL_CORE,
+ TOPO_LEVEL_THREAD,
+ TOPO_LEVEL_COUNT /* Must be last */
+};
+struct topo_analysis {
+ int entities[TOPO_LEVEL_COUNT];
+};
+int topo_analyze(struct topo_node *topo_root, int all,
+ struct topo_analysis *results);
#define TOPO_FOREACH(i, root) \
for (i = root; i != NULL; i = topo_next_node(root, i))
diff --git a/freebsd/sys/sys/systm.h b/freebsd/sys/sys/systm.h
index 4488c7cd..92be461b 100644
--- a/freebsd/sys/sys/systm.h
+++ b/freebsd/sys/sys/systm.h
@@ -172,6 +172,7 @@ void kassert_panic(const char *fmt, ...) __printflike(1, 2);
* Align variables.
*/
#define __read_mostly __section(".data.read_mostly")
+#define __read_frequently __section(".data.read_frequently")
#define __exclusive_cache_line __aligned(CACHE_LINE_SIZE) \
__section(".data.exclusive_cache_line")
/*
@@ -329,6 +330,12 @@ void hexdump(const void *ptr, int length, const char *hdr, int flags);
#ifndef __rtems__
void bcopy(const void * _Nonnull from, void * _Nonnull to, size_t len);
void bzero(void * _Nonnull buf, size_t len);
+#define bzero(buf, len) ({ \
+ if (__builtin_constant_p(len) && (len) <= 64) \
+ __builtin_memset((buf), 0, (len)); \
+ else \
+ bzero((buf), (len)); \
+})
#else /* __rtems__ */
#define bcopy(src, dst, len) memmove((dst), (src), (len))
#define bzero(buf, size) memset((buf), 0, (size))
diff --git a/freebsd/sys/sys/taskqueue.h b/freebsd/sys/sys/taskqueue.h
index 7db75c6d..b5091d32 100644
--- a/freebsd/sys/sys/taskqueue.h
+++ b/freebsd/sys/sys/taskqueue.h
@@ -149,7 +149,7 @@ taskqueue_define_##name(void *arg) \
init; \
} \
\
-SYSINIT(taskqueue_##name, SI_SUB_INIT_IF, SI_ORDER_SECOND, \
+SYSINIT(taskqueue_##name, SI_SUB_TASKQ, SI_ORDER_SECOND, \
taskqueue_define_##name, NULL); \
\
struct __hack
@@ -174,7 +174,7 @@ taskqueue_define_##name(void *arg) \
init; \
} \
\
-SYSINIT(taskqueue_##name, SI_SUB_INIT_IF, SI_ORDER_SECOND, \
+SYSINIT(taskqueue_##name, SI_SUB_TASKQ, SI_ORDER_SECOND, \
taskqueue_define_##name, NULL); \
\
struct __hack
diff --git a/freebsd/sys/sys/vmmeter.h b/freebsd/sys/sys/vmmeter.h
index d7692583..bc536f71 100644
--- a/freebsd/sys/sys/vmmeter.h
+++ b/freebsd/sys/sys/vmmeter.h
@@ -60,6 +60,12 @@ struct vmtotal {
#if defined(_KERNEL) || defined(_WANT_VMMETER)
#include <sys/counter.h>
+#ifdef _KERNEL
+#define VMMETER_ALIGNED __aligned(CACHE_LINE_SIZE)
+#else
+#define VMMETER_ALIGNED
+#endif
+
/*
* System wide statistics counters.
* Locking:
@@ -126,14 +132,15 @@ struct vmmeter {
u_int v_free_target; /* (c) pages desired free */
u_int v_free_min; /* (c) pages desired free */
u_int v_free_count; /* (f) pages free */
- u_int v_wire_count; /* (a) pages wired down */
- u_int v_active_count; /* (q) pages active */
u_int v_inactive_target; /* (c) pages desired inactive */
- u_int v_inactive_count; /* (q) pages inactive */
- u_int v_laundry_count; /* (q) pages eligible for laundering */
u_int v_pageout_free_min; /* (c) min pages reserved for kernel */
u_int v_interrupt_free_min; /* (c) reserved pages for int code */
u_int v_free_severe; /* (c) severe page depletion point */
+ u_int v_wire_count VMMETER_ALIGNED; /* (a) pages wired down */
+ u_int v_active_count VMMETER_ALIGNED; /* (a) pages active */
+ u_int v_inactive_count VMMETER_ALIGNED; /* (a) pages inactive */
+ u_int v_laundry_count VMMETER_ALIGNED; /* (a) pages eligible for
+ laundering */
};
#endif /* _KERNEL || _WANT_VMMETER */
diff --git a/freebsd/sys/sys/vnode.h b/freebsd/sys/sys/vnode.h
index 61cbf000..0c533063 100644
--- a/freebsd/sys/sys/vnode.h
+++ b/freebsd/sys/sys/vnode.h
@@ -251,6 +251,7 @@ struct xvnode {
#define VV_DELETED 0x0400 /* should be removed */
#define VV_MD 0x0800 /* vnode backs the md device */
#define VV_FORCEINSMQ 0x1000 /* force the insmntque to succeed */
+#define VV_READLINK 0x2000 /* fdescfs linux vnode */
#define VMP_TMPMNTFREELIST 0x0001 /* Vnode is on mnt's tmp free list */
@@ -399,6 +400,7 @@ extern int vttoif_tab[];
#define V_NORMAL 0x0004 /* vinvalbuf: invalidate only regular bufs */
#define V_CLEANONLY 0x0008 /* vinvalbuf: invalidate only clean bufs */
#define V_VMIO 0x0010 /* vinvalbuf: called during pageout */
+#define V_ALLOWCLEAN 0x0020 /* vinvalbuf: allow clean buffers after flush */
#define REVOKEALL 0x0001 /* vop_revoke: revoke all aliases */
#define V_WAIT 0x0001 /* vn_start_write: sleep for suspend */
#define V_NOWAIT 0x0002 /* vn_start_write: don't sleep for suspend */
diff --git a/freebsd/sys/vm/uma.h b/freebsd/sys/vm/uma.h
index c968e67e..3781fc8a 100644
--- a/freebsd/sys/vm/uma.h
+++ b/freebsd/sys/vm/uma.h
@@ -296,6 +296,7 @@ uma_zone_t uma_zcache_create(char *name, int size, uma_ctor ctor, uma_dtor dtor,
#define UMA_ALIGN_SHORT (sizeof(short) - 1) /* "" short */
#define UMA_ALIGN_CHAR (sizeof(char) - 1) /* "" char */
#define UMA_ALIGN_CACHE (0 - 1) /* Cache line size align */
+#define UMA_ALIGNOF(type) (_Alignof(type) - 1) /* Alignment fit for 'type' */
/*
* Destroys an empty uma zone. If the zone is not empty uma complains loudly.
diff --git a/freebsd/sys/vm/uma_core.c b/freebsd/sys/vm/uma_core.c
index 011f6494..c40e682d 100644
--- a/freebsd/sys/vm/uma_core.c
+++ b/freebsd/sys/vm/uma_core.c
@@ -152,7 +152,7 @@ static LIST_HEAD(,uma_zone) uma_cachezones =
LIST_HEAD_INITIALIZER(uma_cachezones);
/* This RW lock protects the keg list */
-static struct rwlock_padalign uma_rwlock;
+static struct rwlock_padalign __exclusive_cache_line uma_rwlock;
#ifndef __rtems__
/*
@@ -1367,10 +1367,6 @@ keg_large_init(uma_keg_t keg)
keg->uk_ipers = 1;
keg->uk_rsize = keg->uk_size;
- /* We can't do OFFPAGE if we're internal, bail out here. */
- if (keg->uk_flags & UMA_ZFLAG_INTERNAL)
- return;
-
/* Check whether we have enough space to not do OFFPAGE. */
if ((keg->uk_flags & UMA_ZONE_OFFPAGE) == 0) {
shsize = sizeof(struct uma_slab);
@@ -1378,8 +1374,17 @@ keg_large_init(uma_keg_t keg)
shsize = (shsize & ~UMA_ALIGN_PTR) +
(UMA_ALIGN_PTR + 1);
- if ((PAGE_SIZE * keg->uk_ppera) - keg->uk_rsize < shsize)
- keg->uk_flags |= UMA_ZONE_OFFPAGE;
+ if (PAGE_SIZE * keg->uk_ppera - keg->uk_rsize < shsize) {
+ /*
+ * We can't do OFFPAGE if we're internal, in which case
+ * we need an extra page per allocation to contain the
+ * slab header.
+ */
+ if ((keg->uk_flags & UMA_ZFLAG_INTERNAL) == 0)
+ keg->uk_flags |= UMA_ZONE_OFFPAGE;
+ else
+ keg->uk_ppera++;
+ }
}
if ((keg->uk_flags & UMA_ZONE_OFFPAGE) &&
diff --git a/freebsd/sys/vm/uma_int.h b/freebsd/sys/vm/uma_int.h
index 35656801..df40efcd 100644
--- a/freebsd/sys/vm/uma_int.h
+++ b/freebsd/sys/vm/uma_int.h
@@ -28,6 +28,7 @@
*
*/
+#include <sys/_bitset.h>
#include <sys/_task.h>
/*
@@ -210,7 +211,7 @@ struct uma_keg {
vm_offset_t uk_kva; /* Zone base KVA */
uma_zone_t uk_slabzone; /* Slab zone backing us, if OFFPAGE */
- uint16_t uk_pgoff; /* Offset to uma_slab struct */
+ uint32_t uk_pgoff; /* Offset to uma_slab struct */
uint16_t uk_ppera; /* pages per allocation from backend */
uint16_t uk_ipers; /* Items per slab */
uint32_t uk_flags; /* Internal flags */