diff options
Diffstat (limited to 'sys')
110 files changed, 1818 insertions, 850 deletions
diff --git a/sys/amd64/vmm/intel/vmx_support.S b/sys/amd64/vmm/intel/vmx_support.S index 130130b64541..877e377f892d 100644 --- a/sys/amd64/vmm/intel/vmx_support.S +++ b/sys/amd64/vmm/intel/vmx_support.S @@ -171,13 +171,11 @@ do_launch: */ movq %rsp, %rdi /* point %rdi back to 'vmxctx' */ movl $VMX_VMLAUNCH_ERROR, %eax - jmp decode_inst_error - + /* FALLTHROUGH */ decode_inst_error: movl $VM_FAIL_VALID, %r11d - jz inst_error - movl $VM_FAIL_INVALID, %r11d -inst_error: + movl $VM_FAIL_INVALID, %esi + cmovnzl %esi, %r11d movl %r11d, VMXCTX_INST_FAIL_STATUS(%rdi) /* diff --git a/sys/arm64/arm64/trap.c b/sys/arm64/arm64/trap.c index bed58095201a..75c9b5f87892 100644 --- a/sys/arm64/arm64/trap.c +++ b/sys/arm64/arm64/trap.c @@ -246,6 +246,7 @@ external_abort(struct thread *td, struct trapframe *frame, uint64_t esr, print_registers(frame); print_gp_register("far", far); + printf(" esr: 0x%.16lx\n", esr); panic("Unhandled external data abort"); } diff --git a/sys/cam/ata/ata_all.c b/sys/cam/ata/ata_all.c index f9a2b86f0c06..7cd768a9811a 100644 --- a/sys/cam/ata/ata_all.c +++ b/sys/cam/ata/ata_all.c @@ -1151,7 +1151,7 @@ ata_zac_mgmt_out(struct ccb_ataio *ataio, uint32_t retries, /* * For SEND FPDMA QUEUED, the transfer length is * encoded in the FEATURE register, and 0 means - * that 65536 512 byte blocks are to be tranferred. + * that 65536 512 byte blocks are to be transferred. * In practice, it seems unlikely that we'll see * a transfer that large. */ @@ -1220,7 +1220,7 @@ ata_zac_mgmt_in(struct ccb_ataio *ataio, uint32_t retries, /* * For RECEIVE FPDMA QUEUED, the transfer length is * encoded in the FEATURE register, and 0 means - * that 65536 512 byte blocks are to be tranferred. + * that 65536 512 byte blocks are to be transferred. * In practice, it is unlikely we will see a transfer that * large. */ diff --git a/sys/cam/scsi/scsi_da.c b/sys/cam/scsi/scsi_da.c index d02750aaacaf..fc8c0413448d 100644 --- a/sys/cam/scsi/scsi_da.c +++ b/sys/cam/scsi/scsi_da.c @@ -6830,7 +6830,7 @@ scsi_ata_zac_mgmt_out(struct ccb_scsiio *csio, uint32_t retries, /* * For SEND FPDMA QUEUED, the transfer length is * encoded in the FEATURE register, and 0 means - * that 65536 512 byte blocks are to be tranferred. + * that 65536 512 byte blocks are to be transferred. * In practice, it seems unlikely that we'll see * a transfer that large, and it may confuse the * the SAT layer, because generally that means that @@ -6916,7 +6916,7 @@ scsi_ata_zac_mgmt_in(struct ccb_scsiio *csio, uint32_t retries, /* * For RECEIVE FPDMA QUEUED, the transfer length is * encoded in the FEATURE register, and 0 means - * that 65536 512 byte blocks are to be tranferred. + * that 65536 512 byte blocks are to be transferred. * In practice, it seems unlikely that we'll see * a transfer that large, and it may confuse the * the SAT layer, because generally that means that diff --git a/sys/compat/linuxkpi/common/include/acpi/acpi.h b/sys/compat/linuxkpi/common/include/acpi/acpi.h index 1e398d05ba20..016c7ede0f6e 100644 --- a/sys/compat/linuxkpi/common/include/acpi/acpi.h +++ b/sys/compat/linuxkpi/common/include/acpi/acpi.h @@ -37,7 +37,7 @@ /* * LINUXKPI_WANT_LINUX_ACPI is a temporary workaround to allow drm-kmod * to update all needed branches without breaking builds. - * Once that happened and checks are implemented based on __FreeBSD_verison + * Once that happened and checks are implemented based on __FreeBSD_version * we will remove these conditions again. */ diff --git a/sys/compat/linuxkpi/common/include/linux/ieee80211.h b/sys/compat/linuxkpi/common/include/linux/ieee80211.h index 5851ac08f083..b9161c586d07 100644 --- a/sys/compat/linuxkpi/common/include/linux/ieee80211.h +++ b/sys/compat/linuxkpi/common/include/linux/ieee80211.h @@ -147,9 +147,9 @@ enum ieee80211_vht_max_ampdu_len_exp { enum wlan_ht_cap_sm_ps { WLAN_HT_CAP_SM_PS_STATIC = 0, - WLAN_HT_CAP_SM_PS_DYNAMIC, - WLAN_HT_CAP_SM_PS_INVALID, - WLAN_HT_CAP_SM_PS_DISABLED, + WLAN_HT_CAP_SM_PS_DYNAMIC = 1, + WLAN_HT_CAP_SM_PS_INVALID = 2, + WLAN_HT_CAP_SM_PS_DISABLED = 3 }; #define WLAN_MAX_KEY_LEN 32 diff --git a/sys/compat/linuxkpi/common/include/linux/netdevice.h b/sys/compat/linuxkpi/common/include/linux/netdevice.h index cd7d23077a62..3b808a4a1749 100644 --- a/sys/compat/linuxkpi/common/include/linux/netdevice.h +++ b/sys/compat/linuxkpi/common/include/linux/netdevice.h @@ -4,7 +4,7 @@ * Copyright (c) 2010 Panasas, Inc. * Copyright (c) 2013-2019 Mellanox Technologies, Ltd. * All rights reserved. - * Copyright (c) 2020-2021 The FreeBSD Foundation + * Copyright (c) 2020-2025 The FreeBSD Foundation * Copyright (c) 2020-2022 Bjoern A. Zeeb * * Portions of this software were developed by Björn Zeeb @@ -302,6 +302,13 @@ netdev_rss_key_fill(uint32_t *buf, size_t len) get_random_bytes(buf, len); } +static inline void +__hw_addr_init(struct netdev_hw_addr_list *list) +{ + list->count = 0; + INIT_LIST_HEAD(&list->addr_list); +} + static inline int netdev_hw_addr_list_count(struct netdev_hw_addr_list *list) { diff --git a/sys/compat/linuxkpi/common/include/net/cfg80211.h b/sys/compat/linuxkpi/common/include/net/cfg80211.h index 044f348ef08b..239b4a5ae7b8 100644 --- a/sys/compat/linuxkpi/common/include/net/cfg80211.h +++ b/sys/compat/linuxkpi/common/include/net/cfg80211.h @@ -57,8 +57,8 @@ extern int linuxkpi_debug_80211; #endif #define TODO(fmt, ...) if (linuxkpi_debug_80211 & D80211_TODO) \ printf("%s:%d: XXX LKPI80211 TODO " fmt "\n", __func__, __LINE__, ##__VA_ARGS__) -#define IMPROVE(...) if (linuxkpi_debug_80211 & D80211_IMPROVE) \ - printf("%s:%d: XXX LKPI80211 IMPROVE\n", __func__, __LINE__) +#define IMPROVE(fmt, ...) if (linuxkpi_debug_80211 & D80211_IMPROVE) \ + printf("%s:%d: XXX LKPI80211 IMPROVE " fmt "\n", __func__, __LINE__, ##__VA_ARGS__) enum rfkill_hard_block_reasons { RFKILL_HARD_BLOCK_NOT_OWNER = BIT(0), @@ -128,19 +128,24 @@ struct ieee80211_txrx_stypes { uint16_t rx; }; -/* XXX net80211 has an ieee80211_channel as well. */ +/* + * net80211 has an ieee80211_channel as well; we use the linuxkpi_ version + * interally in LinuxKPI and re-define ieee80211_channel for the drivers + * at the end of the file. + */ struct linuxkpi_ieee80211_channel { - /* TODO FIXME */ - uint32_t hw_value; /* ic_ieee */ - uint32_t center_freq; /* ic_freq */ - enum ieee80211_channel_flags flags; /* ic_flags */ + uint32_t center_freq; + uint16_t hw_value; + enum ieee80211_channel_flags flags; enum nl80211_band band; - int8_t max_power; /* ic_maxpower */ bool beacon_found; - int max_antenna_gain, max_reg_power; - int orig_flags; - int dfs_cac_ms, dfs_state; - int orig_mpwr; + enum nl80211_dfs_state dfs_state; + unsigned int dfs_cac_ms; + int max_antenna_gain; + int max_power; + int max_reg_power; + uint32_t orig_flags; + int orig_mpwr; }; struct cfg80211_bitrate_mask { @@ -1299,10 +1304,9 @@ reg_query_regdb_wmm(uint8_t *alpha2, uint32_t center_freq, struct ieee80211_reg_rule *rule) { - /* ETSI has special rules. FreeBSD regdb needs to learn about them. */ - TODO(); + IMPROVE("regdomain.xml needs to grow wmm information for at least ETSI"); - return (-ENXIO); + return (-ENODATA); } static __inline const u8 * diff --git a/sys/compat/linuxkpi/common/include/net/mac80211.h b/sys/compat/linuxkpi/common/include/net/mac80211.h index 2ed595095f9e..0106e6648bd4 100644 --- a/sys/compat/linuxkpi/common/include/net/mac80211.h +++ b/sys/compat/linuxkpi/common/include/net/mac80211.h @@ -87,6 +87,9 @@ enum mcast_filter_flags { FIF_PSPOLL = BIT(5), FIF_CONTROL = BIT(6), FIF_MCAST_ACTION = BIT(7), + + /* Must stay last. */ + FIF_FLAGS_MASK = BIT(8)-1, }; enum ieee80211_bss_changed { @@ -1135,7 +1138,7 @@ extern const struct cfg80211_ops linuxkpi_mac80211cfgops; struct ieee80211_hw *linuxkpi_ieee80211_alloc_hw(size_t, const struct ieee80211_ops *); void linuxkpi_ieee80211_iffree(struct ieee80211_hw *); -void linuxkpi_set_ieee80211_dev(struct ieee80211_hw *, char *); +void linuxkpi_set_ieee80211_dev(struct ieee80211_hw *); int linuxkpi_ieee80211_ifattach(struct ieee80211_hw *); void linuxkpi_ieee80211_ifdetach(struct ieee80211_hw *); void linuxkpi_ieee80211_unregister_hw(struct ieee80211_hw *); @@ -1255,7 +1258,7 @@ SET_IEEE80211_DEV(struct ieee80211_hw *hw, struct device *dev) { set_wiphy_dev(hw->wiphy, dev); - linuxkpi_set_ieee80211_dev(hw, dev_name(dev)); + linuxkpi_set_ieee80211_dev(hw); IMPROVE(); } @@ -1741,12 +1744,15 @@ ieee80211_request_smps(struct ieee80211_vif *vif, u_int link_id, "SMPS_STATIC", "SMPS_DYNAMIC", "SMPS_AUTOMATIC", - "SMPS_NUM_MODES" }; - if (linuxkpi_debug_80211 & D80211_TODO) - printf("%s:%d: XXX LKPI80211 TODO smps %d %s\n", - __func__, __LINE__, smps, smps_mode_name[smps]); + if (vif->type != NL80211_IFTYPE_STATION) + return; + + if (smps >= nitems(smps_mode_name)) + panic("%s: unsupported smps value: %d\n", __func__, smps); + + IMPROVE("XXX LKPI80211 TODO smps %d %s\n", smps, smps_mode_name[smps]); } static __inline void diff --git a/sys/compat/linuxkpi/common/src/linux_80211.c b/sys/compat/linuxkpi/common/src/linux_80211.c index a7d6003843ba..e248588dd275 100644 --- a/sys/compat/linuxkpi/common/src/linux_80211.c +++ b/sys/compat/linuxkpi/common/src/linux_80211.c @@ -274,48 +274,40 @@ lkpi_nl80211_sta_info_to_str(struct sbuf *s, const char *prefix, sbuf_printf(s, "\n"); } -static int -lkpi_80211_dump_stas(SYSCTL_HANDLER_ARGS) +static void +lkpi_80211_dump_lvif_stas(struct lkpi_vif *lvif, struct sbuf *s) { struct lkpi_hw *lhw; struct ieee80211_hw *hw; struct ieee80211vap *vap; - struct lkpi_vif *lvif; struct ieee80211_vif *vif; struct lkpi_sta *lsta; struct ieee80211_sta *sta; struct station_info sinfo; - struct sbuf s; int error; - if (req->newptr) - return (EPERM); - - lvif = (struct lkpi_vif *)arg1; vif = LVIF_TO_VIF(lvif); vap = LVIF_TO_VAP(lvif); lhw = vap->iv_ic->ic_softc; hw = LHW_TO_HW(lhw); - sbuf_new_for_sysctl(&s, NULL, 1024, req); - wiphy_lock(hw->wiphy); list_for_each_entry(lsta, &lvif->lsta_list, lsta_list) { sta = LSTA_TO_STA(lsta); - sbuf_putc(&s, '\n'); - sbuf_printf(&s, "lsta %p sta %p added_to_drv %d\n", lsta, sta, lsta->added_to_drv); + sbuf_putc(s, '\n'); + sbuf_printf(s, "lsta %p sta %p added_to_drv %d\n", lsta, sta, lsta->added_to_drv); memset(&sinfo, 0, sizeof(sinfo)); error = lkpi_80211_mo_sta_statistics(hw, vif, sta, &sinfo); if (error == EEXIST) /* Not added to driver. */ continue; if (error == ENOTSUPP) { - sbuf_printf(&s, " sta_statistics not supported\n"); + sbuf_printf(s, " sta_statistics not supported\n"); continue; } if (error != 0) { - sbuf_printf(&s, " sta_statistics failed: %d\n", error); + sbuf_printf(s, " sta_statistics failed: %d\n", error); continue; } @@ -325,51 +317,76 @@ lkpi_80211_dump_stas(SYSCTL_HANDLER_ARGS) memcpy(&sinfo.rxrate, &lsta->sinfo.rxrate, sizeof(sinfo.rxrate)); sinfo.filled |= BIT_ULL(NL80211_STA_INFO_RX_BITRATE); } + /* If no CHAIN_SIGNAL is reported, try to fill it in from the lsta sinfo. */ + if ((sinfo.filled & BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL)) == 0 && + (lsta->sinfo.filled & BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL)) != 0) { + sinfo.chains = lsta->sinfo.chains; + memcpy(sinfo.chain_signal, lsta->sinfo.chain_signal, + sizeof(sinfo.chain_signal)); + sinfo.filled |= BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL); + } - lkpi_nl80211_sta_info_to_str(&s, " nl80211_sta_info (valid fields)", sinfo.filled); - sbuf_printf(&s, " connected_time %u inactive_time %u\n", + lkpi_nl80211_sta_info_to_str(s, " nl80211_sta_info (valid fields)", sinfo.filled); + sbuf_printf(s, " connected_time %u inactive_time %u\n", sinfo.connected_time, sinfo.inactive_time); - sbuf_printf(&s, " rx_bytes %ju rx_packets %u rx_dropped_misc %u\n", + sbuf_printf(s, " rx_bytes %ju rx_packets %u rx_dropped_misc %u\n", (uintmax_t)sinfo.rx_bytes, sinfo.rx_packets, sinfo.rx_dropped_misc); - sbuf_printf(&s, " rx_duration %ju rx_beacon %u rx_beacon_signal_avg %d\n", + sbuf_printf(s, " rx_duration %ju rx_beacon %u rx_beacon_signal_avg %d\n", (uintmax_t)sinfo.rx_duration, sinfo.rx_beacon, (int8_t)sinfo.rx_beacon_signal_avg); - sbuf_printf(&s, " tx_bytes %ju tx_packets %u tx_failed %u\n", + sbuf_printf(s, " tx_bytes %ju tx_packets %u tx_failed %u\n", (uintmax_t)sinfo.tx_bytes, sinfo.tx_packets, sinfo.tx_failed); - sbuf_printf(&s, " tx_duration %ju tx_retries %u\n", + sbuf_printf(s, " tx_duration %ju tx_retries %u\n", (uintmax_t)sinfo.tx_duration, sinfo.tx_retries); - sbuf_printf(&s, " signal %d signal_avg %d ack_signal %d avg_ack_signal %d\n", + sbuf_printf(s, " signal %d signal_avg %d ack_signal %d avg_ack_signal %d\n", sinfo.signal, sinfo.signal_avg, sinfo.ack_signal, sinfo.avg_ack_signal); - - sbuf_printf(&s, " generation %d assoc_req_ies_len %zu chains %d\n", + sbuf_printf(s, " generation %d assoc_req_ies_len %zu chains %#04x\n", sinfo.generation, sinfo.assoc_req_ies_len, sinfo.chains); - for (int i = 0; i < sinfo.chains && i < IEEE80211_MAX_CHAINS; i++) { - sbuf_printf(&s, " chain[%d] signal %d signal_avg %d\n", + for (int i = 0; i < nitems(sinfo.chain_signal) && i < IEEE80211_MAX_CHAINS; i++) { + if (!(sinfo.chains & BIT(i))) + continue; + sbuf_printf(s, " chain[%d] signal %d signal_avg %d\n", i, (int8_t)sinfo.chain_signal[i], (int8_t)sinfo.chain_signal_avg[i]); } /* assoc_req_ies, bss_param, sta_flags */ - sbuf_printf(&s, " rxrate: flags %b bw %u(%s) legacy %u kbit/s mcs %u nss %u\n", + sbuf_printf(s, " rxrate: flags %b bw %u(%s) legacy %u kbit/s mcs %u nss %u\n", sinfo.rxrate.flags, CFG80211_RATE_INFO_FLAGS_BITS, sinfo.rxrate.bw, lkpi_rate_info_bw_to_str(sinfo.rxrate.bw), sinfo.rxrate.legacy * 100, sinfo.rxrate.mcs, sinfo.rxrate.nss); - sbuf_printf(&s, " he_dcm %u he_gi %u he_ru_alloc %u eht_gi %u\n", + sbuf_printf(s, " he_dcm %u he_gi %u he_ru_alloc %u eht_gi %u\n", sinfo.rxrate.he_dcm, sinfo.rxrate.he_gi, sinfo.rxrate.he_ru_alloc, sinfo.rxrate.eht_gi); - sbuf_printf(&s, " txrate: flags %b bw %u(%s) legacy %u kbit/s mcs %u nss %u\n", + sbuf_printf(s, " txrate: flags %b bw %u(%s) legacy %u kbit/s mcs %u nss %u\n", sinfo.txrate.flags, CFG80211_RATE_INFO_FLAGS_BITS, sinfo.txrate.bw, lkpi_rate_info_bw_to_str(sinfo.txrate.bw), sinfo.txrate.legacy * 100, sinfo.txrate.mcs, sinfo.txrate.nss); - sbuf_printf(&s, " he_dcm %u he_gi %u he_ru_alloc %u eht_gi %u\n", + sbuf_printf(s, " he_dcm %u he_gi %u he_ru_alloc %u eht_gi %u\n", sinfo.txrate.he_dcm, sinfo.txrate.he_gi, sinfo.txrate.he_ru_alloc, sinfo.txrate.eht_gi); } wiphy_unlock(hw->wiphy); +} + +static int +lkpi_80211_dump_stas(SYSCTL_HANDLER_ARGS) +{ + struct lkpi_vif *lvif; + struct sbuf s; + + if (req->newptr) + return (EPERM); + + lvif = (struct lkpi_vif *)arg1; + + sbuf_new_for_sysctl(&s, NULL, 1024, req); + + lkpi_80211_dump_lvif_stas(lvif, &s); sbuf_finish(&s); sbuf_delete(&s); @@ -1162,7 +1179,7 @@ lkpi_find_lkpi80211_chan(struct lkpi_hw *lhw, channels = hw->wiphy->bands[band]->channels; for (i = 0; i < nchans; i++) { - if (channels[i].hw_value == c->ic_ieee) + if (channels[i].center_freq == c->ic_freq) return (&channels[i]); } @@ -1700,6 +1717,24 @@ lkpi_iv_key_update_end(struct ieee80211vap *vap) } #endif +static void +lkpi_cleanup_mcast_list_locked(struct lkpi_hw *lhw) +{ + struct list_head *le, *next; + struct netdev_hw_addr *addr; + + if (lhw->mc_list.count != 0) { + list_for_each_safe(le, next, &lhw->mc_list.addr_list) { + addr = list_entry(le, struct netdev_hw_addr, addr_list); + list_del(le); + lhw->mc_list.count--; + free(addr, M_LKPI80211); + } + } + KASSERT(lhw->mc_list.count == 0, ("%s: mc_list %p count %d != 0\n", + __func__, &lhw->mc_list, lhw->mc_list.count)); +} + static u_int lkpi_ic_update_mcast_copy(void *arg, struct sockaddr_dl *sdl, u_int cnt) { @@ -1736,16 +1771,13 @@ lkpi_ic_update_mcast_copy(void *arg, struct sockaddr_dl *sdl, u_int cnt) } static void -lkpi_update_mcast_filter(struct ieee80211com *ic, bool force) +lkpi_update_mcast_filter(struct ieee80211com *ic) { struct lkpi_hw *lhw; struct ieee80211_hw *hw; - struct netdev_hw_addr_list mc_list; - struct list_head *le, *next; - struct netdev_hw_addr *addr; - struct ieee80211vap *vap; u64 mc; - unsigned int changed_flags, total_flags; + unsigned int changed_flags, flags; + bool scanning; lhw = ic->ic_softc; @@ -1753,44 +1785,32 @@ lkpi_update_mcast_filter(struct ieee80211com *ic, bool force) lhw->ops->configure_filter == NULL) return; - if (!lhw->update_mc && !force) - return; + LKPI_80211_LHW_SCAN_LOCK(lhw); + scanning = (lhw->scan_flags & LKPI_LHW_SCAN_RUNNING) != 0; + LKPI_80211_LHW_SCAN_UNLOCK(lhw); - changed_flags = total_flags = 0; - mc_list.count = 0; - INIT_LIST_HEAD(&mc_list.addr_list); - if (ic->ic_allmulti == 0) { - TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) - if_foreach_llmaddr(vap->iv_ifp, - lkpi_ic_update_mcast_copy, &mc_list); - } else { - changed_flags |= FIF_ALLMULTI; - } + LKPI_80211_LHW_MC_LOCK(lhw); + + flags = 0; + if (scanning) + flags |= FIF_BCN_PRBRESP_PROMISC; + if (lhw->mc_all_multi) + flags |= FIF_ALLMULTI; hw = LHW_TO_HW(lhw); - mc = lkpi_80211_mo_prepare_multicast(hw, &mc_list); - /* - * XXX-BZ make sure to get this sorted what is a change, - * what gets all set; what was already set? - */ - total_flags = changed_flags; - lkpi_80211_mo_configure_filter(hw, changed_flags, &total_flags, mc); + mc = lkpi_80211_mo_prepare_multicast(hw, &lhw->mc_list); + + changed_flags = (lhw->mc_flags ^ flags) & FIF_FLAGS_MASK; + lkpi_80211_mo_configure_filter(hw, changed_flags, &flags, mc); + lhw->mc_flags = flags; #ifdef LINUXKPI_DEBUG_80211 if (linuxkpi_debug_80211 & D80211_TRACE) - printf("%s: changed_flags %#06x count %d total_flags %#010x\n", - __func__, changed_flags, mc_list.count, total_flags); + printf("%s: changed_flags %#06x count %d mc_flags %#010x\n", + __func__, changed_flags, lhw->mc_list.count, lhw->mc_flags); #endif - if (mc_list.count != 0) { - list_for_each_safe(le, next, &mc_list.addr_list) { - addr = list_entry(le, struct netdev_hw_addr, addr_list); - free(addr, M_LKPI80211); - mc_list.count--; - } - } - KASSERT(mc_list.count == 0, ("%s: mc_list %p count %d != 0\n", - __func__, &mc_list, mc_list.count)); + LKPI_80211_LHW_MC_UNLOCK(lhw); } static enum ieee80211_bss_changed @@ -1909,19 +1929,19 @@ lkpi_disassoc(struct ieee80211_sta *sta, struct ieee80211_vif *vif, struct lkpi_hw *lhw) { enum ieee80211_bss_changed changed; + struct lkpi_vif *lvif; changed = 0; sta->aid = 0; if (vif->cfg.assoc) { - lhw->update_mc = true; - lkpi_update_mcast_filter(lhw->ic, true); - vif->cfg.assoc = false; vif->cfg.aid = 0; changed |= BSS_CHANGED_ASSOC; IMPROVE(); + lkpi_update_mcast_filter(lhw->ic); + /* * Executing the bss_info_changed(BSS_CHANGED_ASSOC) with * assoc = false right away here will remove the sta from @@ -1932,6 +1952,9 @@ lkpi_disassoc(struct ieee80211_sta *sta, struct ieee80211_vif *vif, * bss_info_changed() update. * See lkpi_sta_run_to_init() for more detailed comment. */ + + lvif = VIF_TO_LVIF(vif); + lvif->beacons = 0; } return (changed); @@ -2202,6 +2225,7 @@ lkpi_sta_scan_to_auth(struct ieee80211vap *vap, enum ieee80211_state nstate, int /* vif->bss_conf.basic_rates ? Where exactly? */ + lvif->beacons = 0; /* Should almost assert it is this. */ vif->cfg.assoc = false; vif->cfg.aid = 0; @@ -2391,6 +2415,7 @@ lkpi_sta_auth_to_scan(struct ieee80211vap *vap, enum ieee80211_state nstate, int struct lkpi_sta *lsta; struct ieee80211_sta *sta; struct ieee80211_prep_tx_info prep_tx_info; + enum ieee80211_bss_changed bss_changed; int error; lhw = vap->iv_ic->ic_softc; @@ -2462,6 +2487,11 @@ lkpi_sta_auth_to_scan(struct ieee80211vap *vap, enum ieee80211_state nstate, int lsta->added_to_drv = false; /* mo manages. */ #endif + bss_changed = 0; + vif->bss_conf.dtim_period = 0; /* go back to 0. */ + bss_changed |= BSS_CHANGED_BEACON_INFO; + lkpi_80211_mo_bss_info_changed(hw, vif, &vif->bss_conf, bss_changed); + lkpi_lsta_dump(lsta, ni, __func__, __LINE__); LKPI_80211_LVIF_LOCK(lvif); @@ -2790,6 +2820,8 @@ _lkpi_sta_assoc_to_down(struct ieee80211vap *vap, enum ieee80211_state nstate, i vif->cfg.ssid_len = 0; memset(vif->cfg.ssid, '\0', sizeof(vif->cfg.ssid)); bss_changed |= BSS_CHANGED_BSSID; + vif->bss_conf.dtim_period = 0; /* go back to 0. */ + bss_changed |= BSS_CHANGED_BEACON_INFO; lkpi_80211_mo_bss_info_changed(hw, vif, &vif->bss_conf, bss_changed); LKPI_80211_LVIF_LOCK(lvif); @@ -2922,6 +2954,7 @@ lkpi_sta_assoc_to_run(struct ieee80211vap *vap, enum ieee80211_state nstate, int bss_changed |= lkpi_wme_update(lhw, vap, true); #endif if (!vif->cfg.assoc || vif->cfg.aid != IEEE80211_NODE_AID(ni)) { + lvif->beacons = 0; vif->cfg.assoc = true; vif->cfg.aid = IEEE80211_NODE_AID(ni); bss_changed |= BSS_CHANGED_ASSOC; @@ -2970,9 +3003,6 @@ lkpi_sta_assoc_to_run(struct ieee80211vap *vap, enum ieee80211_state nstate, int * - set_key (?) * - ipv6_addr_change (?) */ - /* Prepare_multicast && configure_filter. */ - lhw->update_mc = true; - lkpi_update_mcast_filter(vap->iv_ic, true); if (!ieee80211_node_is_authorized(ni)) { IMPROVE("net80211 does not consider node authorized"); @@ -3011,6 +3041,9 @@ lkpi_sta_assoc_to_run(struct ieee80211vap *vap, enum ieee80211_state nstate, int bss_changed |= lkpi_update_dtim_tsf(vif, ni, vap, __func__, __LINE__); lkpi_80211_mo_bss_info_changed(hw, vif, &vif->bss_conf, bss_changed); + /* Prepare_multicast && configure_filter. */ + lkpi_update_mcast_filter(vap->iv_ic); + out: wiphy_unlock(hw->wiphy); IEEE80211_LOCK(vap->iv_ic); @@ -3391,6 +3424,8 @@ lkpi_sta_run_to_init(struct ieee80211vap *vap, enum ieee80211_state nstate, int vif->bss_conf.use_short_preamble = false; vif->bss_conf.qos = false; /* XXX BSS_CHANGED_???? */ + vif->bss_conf.dtim_period = 0; /* go back to 0. */ + bss_changed |= BSS_CHANGED_BEACON_INFO; lkpi_80211_mo_bss_info_changed(hw, vif, &vif->bss_conf, bss_changed); LKPI_80211_LVIF_LOCK(lvif); @@ -3693,6 +3728,42 @@ lkpi_ic_wme_update(struct ieee80211com *ic) return (0); /* unused */ } +static void +lkpi_iv_sta_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, + int subtype, const struct ieee80211_rx_stats *rxs, int rssi, int nf) +{ + struct lkpi_hw *lhw; + struct ieee80211_hw *hw; + struct lkpi_vif *lvif; + struct ieee80211_vif *vif; + enum ieee80211_bss_changed bss_changed; + + lvif = VAP_TO_LVIF(ni->ni_vap); + + lvif->iv_recv_mgmt(ni, m0, subtype, rxs, rssi, nf); + + switch (subtype) { + case IEEE80211_FC0_SUBTYPE_PROBE_RESP: + break; + case IEEE80211_FC0_SUBTYPE_BEACON: + lvif->beacons++; + break; + default: + return; + } + + vif = LVIF_TO_VIF(lvif); + lhw = ni->ni_ic->ic_softc; + hw = LHW_TO_HW(lhw); + + /* + * If this direct call to mo_bss_info_changed will not work due to + * locking, see if queue_work() is fast enough. + */ + bss_changed = lkpi_update_dtim_tsf(vif, ni, ni->ni_vap, __func__, __LINE__); + lkpi_80211_mo_bss_info_changed(hw, vif, &vif->bss_conf, bss_changed); +} + /* * Change link-layer address on the vif (if the vap is not started/"UP"). * This can happen if a user changes 'ether' using ifconfig. @@ -3826,8 +3897,10 @@ lkpi_ic_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], IMPROVE(); + wiphy_lock(hw->wiphy); error = lkpi_80211_mo_start(hw); if (error != 0) { + wiphy_unlock(hw->wiphy); ic_printf(ic, "%s: failed to start hw: %d\n", __func__, error); mtx_destroy(&lvif->mtx); free(lvif, M_80211_VAP); @@ -3837,11 +3910,13 @@ lkpi_ic_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], error = lkpi_80211_mo_add_interface(hw, vif); if (error != 0) { IMPROVE(); /* XXX-BZ mo_stop()? */ + wiphy_unlock(hw->wiphy); ic_printf(ic, "%s: failed to add interface: %d\n", __func__, error); mtx_destroy(&lvif->mtx); free(lvif, M_80211_VAP); return (NULL); } + wiphy_unlock(hw->wiphy); LKPI_80211_LHW_LVIF_LOCK(lhw); TAILQ_INSERT_TAIL(&lhw->lvif_head, lvif, lvif_entry); @@ -3871,17 +3946,21 @@ lkpi_ic_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], lkpi_80211_mo_bss_info_changed(hw, vif, &vif->bss_conf, changed); /* Force MC init. */ - lkpi_update_mcast_filter(ic, true); - - IMPROVE(); + lkpi_update_mcast_filter(ic); ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid); + /* Now we have a valid vap->iv_ifp. Any checksum offloading goes below. */ + + IMPROVE(); + /* Override with LinuxKPI method so we can drive mac80211/cfg80211. */ lvif->iv_newstate = vap->iv_newstate; vap->iv_newstate = lkpi_iv_newstate; lvif->iv_update_bss = vap->iv_update_bss; vap->iv_update_bss = lkpi_iv_update_bss; + lvif->iv_recv_mgmt = vap->iv_recv_mgmt; + vap->iv_recv_mgmt = lkpi_iv_sta_recv_mgmt; #ifdef LKPI_80211_HW_CRYPTO /* Key management. */ @@ -4004,8 +4083,30 @@ lkpi_ic_vap_delete(struct ieee80211vap *vap) static void lkpi_ic_update_mcast(struct ieee80211com *ic) { + struct ieee80211vap *vap; + struct lkpi_hw *lhw; + + lhw = ic->ic_softc; + if (lhw->ops->prepare_multicast == NULL || + lhw->ops->configure_filter == NULL) + return; + + LKPI_80211_LHW_MC_LOCK(lhw); + /* Cleanup anything on the current list. */ + lkpi_cleanup_mcast_list_locked(lhw); - lkpi_update_mcast_filter(ic, false); + /* Build up the new list (or allmulti). */ + if (ic->ic_allmulti == 0) { + TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) + if_foreach_llmaddr(vap->iv_ifp, + lkpi_ic_update_mcast_copy, &lhw->mc_list); + lhw->mc_all_multi = false; + } else { + lhw->mc_all_multi = true; + } + LKPI_80211_LHW_MC_UNLOCK(lhw); + + lkpi_update_mcast_filter(ic); TRACEOK(); } @@ -4241,6 +4342,8 @@ sw_scan: if (vap->iv_state == IEEE80211_S_SCAN) lkpi_hw_conf_idle(hw, false); + lkpi_update_mcast_filter(ic); + lkpi_80211_mo_sw_scan_start(hw, vif, vif->addr); /* net80211::scan_start() handled PS for us. */ IMPROVE(); @@ -4348,7 +4451,6 @@ sw_scan: struct ieee80211_channel *c; c = ss->ss_chans[ss->ss_next + i]; - lc->hw_value = c->ic_ieee; lc->center_freq = c->ic_freq; /* XXX */ /* lc->flags */ lc->band = lkpi_net80211_chan_to_nl80211_band(c); @@ -4377,7 +4479,6 @@ sw_scan: } } #endif - hw_req->req.n_ssids = ssid_count; if (hw_req->req.n_ssids > 0) { ssids = (struct cfg80211_ssid *)lc; @@ -4424,6 +4525,8 @@ sw_scan: return; } + lkpi_update_mcast_filter(ic); + error = lkpi_80211_mo_hw_scan(hw, vif, hw_req); if (error != 0) { ieee80211_cancel_scan(vap); @@ -4449,6 +4552,7 @@ sw_scan: lhw->scan_flags &= ~LKPI_LHW_SCAN_RUNNING; } LKPI_80211_LHW_SCAN_UNLOCK(lhw); + lkpi_update_mcast_filter(ic); /* * XXX-SIGH magic number. @@ -5571,6 +5675,12 @@ lkpi_ic_ampdu_rx_start(struct ieee80211_node *ni, struct ieee80211_rx_ampdu *rap return (-ENXIO); } + if (lsta->state != IEEE80211_STA_AUTHORIZED) { + ic_printf(ic, "%s: lsta %p ni %p vap %p, sta %p state %d not AUTHORIZED\n", + __func__, lsta, ni, vap, sta, lsta->state); + return (-ENXIO); + } + params.sta = sta; params.action = IEEE80211_AMPDU_RX_START; params.buf_size = _IEEE80211_MASKSHIFT(le16toh(baparamset), IEEE80211_BAPS_BUFSIZ); @@ -5647,13 +5757,35 @@ lkpi_ic_ampdu_rx_stop(struct ieee80211_node *ni, struct ieee80211_rx_ampdu *rap) lvif = VAP_TO_LVIF(vap); vif = LVIF_TO_VIF(lvif); lsta = ni->ni_drv_data; + if (lsta == NULL) { + ic_printf(ic, "%s: lsta %p ni %p vap %p, lsta is NULL\n", + __func__, lsta, ni, vap); + goto net80211_only; + } sta = LSTA_TO_STA(lsta); + if (!lsta->added_to_drv) { + ic_printf(ic, "%s: lsta %p ni %p vap %p, sta %p not added to firmware\n", + __func__, lsta, ni, vap, sta); + goto net80211_only; + } + + if (lsta->state != IEEE80211_STA_AUTHORIZED) { + ic_printf(ic, "%s: lsta %p ni %p vap %p, sta %p state %d not AUTHORIZED\n", + __func__, lsta, ni, vap, sta, lsta->state); + goto net80211_only; + } + IMPROVE_HT("This really should be passed from ht_recv_action_ba_delba."); for (tid = 0; tid < WME_NUM_TID; tid++) { if (&ni->ni_rx_ampdu[tid] == rap) break; } + if (tid == WME_NUM_TID) { + ic_printf(ic, "%s: lsta %p ni %p vap %p, sta %p TID not found\n", + __func__, lsta, ni, vap, sta); + goto net80211_only; + } params.sta = sta; params.action = IEEE80211_AMPDU_RX_STOP; @@ -5788,8 +5920,9 @@ lkpi_ic_getradiocaps(struct ieee80211com *ic, int maxchan, cflags &= ~NET80211_CBW_FLAG_HT40; error = ieee80211_add_channel_cbw(c, maxchan, n, - channels[i].hw_value, channels[i].center_freq, - channels[i].max_power, + ieee80211_mhz2ieee(channels[i].center_freq, + lkpi_nl80211_band_to_net80211_band(channels[i].band)), + channels[i].center_freq, channels[i].max_power, nflags, bands, cflags); /* net80211::ENOBUFS: *n >= maxchans */ if (error != 0 && error != ENOBUFS) @@ -5860,8 +5993,9 @@ lkpi_ic_getradiocaps(struct ieee80211com *ic, int maxchan, cflags &= ~NET80211_CBW_FLAG_HT40; error = ieee80211_add_channel_cbw(c, maxchan, n, - channels[i].hw_value, channels[i].center_freq, - channels[i].max_power, + ieee80211_mhz2ieee(channels[i].center_freq, + lkpi_nl80211_band_to_net80211_band(channels[i].band)), + channels[i].center_freq, channels[i].max_power, nflags, bands, cflags); /* net80211::ENOBUFS: *n >= maxchans */ if (error != 0 && error != ENOBUFS) @@ -5909,7 +6043,9 @@ linuxkpi_ieee80211_alloc_hw(size_t priv_len, const struct ieee80211_ops *ops) LKPI_80211_LHW_SCAN_LOCK_INIT(lhw); LKPI_80211_LHW_TXQ_LOCK_INIT(lhw); sx_init_flags(&lhw->lvif_sx, "lhw-lvif", SX_RECURSE | SX_DUPOK); + LKPI_80211_LHW_MC_LOCK_INIT(lhw); TAILQ_INIT(&lhw->lvif_head); + __hw_addr_init(&lhw->mc_list); for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { lhw->txq_generation[ac] = 1; TAILQ_INIT(&lhw->scheduled_txqs[ac]); @@ -6006,25 +6142,43 @@ linuxkpi_ieee80211_iffree(struct ieee80211_hw *hw) } } + LKPI_80211_LHW_MC_LOCK(lhw); + lkpi_cleanup_mcast_list_locked(lhw); + LKPI_80211_LHW_MC_UNLOCK(lhw); + /* Cleanup more of lhw here or in wiphy_free()? */ LKPI_80211_LHW_TXQ_LOCK_DESTROY(lhw); LKPI_80211_LHW_SCAN_LOCK_DESTROY(lhw); sx_destroy(&lhw->lvif_sx); + LKPI_80211_LHW_MC_LOCK_DESTROY(lhw) IMPROVE(); } void -linuxkpi_set_ieee80211_dev(struct ieee80211_hw *hw, char *name) +linuxkpi_set_ieee80211_dev(struct ieee80211_hw *hw) { struct lkpi_hw *lhw; struct ieee80211com *ic; + struct device *dev; lhw = HW_TO_LHW(hw); ic = lhw->ic; - /* Now set a proper name before ieee80211_ifattach(). */ + /* Save the backpointer from net80211 to LinuxKPI. */ ic->ic_softc = lhw; - ic->ic_name = name; + + /* + * Set a proper name before ieee80211_ifattach() if dev is set. + * ath1xk also unset the dev so we need to check. + */ + dev = wiphy_dev(hw->wiphy); + if (dev != NULL) { + ic->ic_name = dev_name(dev); + } else { + TODO("adjust arguments to still have the old dev or go through " + "the hoops of getting the bsddev from hw and detach; " + "or do in XXX; check ath1kx drivers"); + } /* XXX-BZ do we also need to set wiphy name? */ } @@ -6332,8 +6486,10 @@ linuxkpi_ieee80211_ifattach(struct ieee80211_hw *hw) hw->wiphy->max_scan_ie_len -= lhw->scan_ie_len; } - if (bootverbose) + if (bootverbose) { + ic_printf(ic, "netdev_features %b\n", hw->netdev_features, NETIF_F_BITS); ieee80211_announce(ic); + } return (0); err: @@ -6832,9 +6988,17 @@ lkpi_convert_rx_status(struct ieee80211_hw *hw, struct lkpi_sta *lsta, rx_stats->c_pktflags |= IEEE80211_RX_F_FAIL_FCSCRC; #endif + /* Fill in some sinfo bits to fill gaps not reported byt the driver. */ if (lsta != NULL) { memcpy(&lsta->sinfo.rxrate, &rxrate, sizeof(rxrate)); lsta->sinfo.filled |= BIT_ULL(NL80211_STA_INFO_RX_BITRATE); + + if (rx_status->chains != 0) { + lsta->sinfo.chains = rx_status->chains; + memcpy(lsta->sinfo.chain_signal, rx_status->chain_signal, + sizeof(lsta->sinfo.chain_signal)); + lsta->sinfo.filled |= BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL); + } } } @@ -7791,8 +7955,11 @@ linuxkpi_ieee80211_connection_loss(struct ieee80211_vif *vif) nstate = IEEE80211_S_INIT; arg = 0; /* Not a valid reason. */ - ic_printf(vap->iv_ic, "%s: vif %p vap %p state %s\n", __func__, - vif, vap, ieee80211_state_name[vap->iv_state]); + ic_printf(vap->iv_ic, "%s: vif %p vap %p state %s (synched %d, assoc %d " + "beacons %d dtim_period %d)\n", __func__, vif, vap, + ieee80211_state_name[vap->iv_state], + lvif->lvif_bss_synched, vif->cfg.assoc, lvif->beacons, + vif->bss_conf.dtim_period); ieee80211_new_state(vap, nstate, arg); } @@ -7805,8 +7972,11 @@ linuxkpi_ieee80211_beacon_loss(struct ieee80211_vif *vif) lvif = VIF_TO_LVIF(vif); vap = LVIF_TO_VAP(lvif); - ic_printf(vap->iv_ic, "%s: vif %p vap %p state %s\n", __func__, - vif, vap, ieee80211_state_name[vap->iv_state]); + ic_printf(vap->iv_ic, "%s: vif %p vap %p state %s (synched %d, assoc %d " + "beacons %d dtim_period %d)\n", __func__, vif, vap, + ieee80211_state_name[vap->iv_state], + lvif->lvif_bss_synched, vif->cfg.assoc, lvif->beacons, + vif->bss_conf.dtim_period); ieee80211_beacon_miss(vap->iv_ic); } diff --git a/sys/compat/linuxkpi/common/src/linux_80211.h b/sys/compat/linuxkpi/common/src/linux_80211.h index 89afec1235bd..eaf6d804af4c 100644 --- a/sys/compat/linuxkpi/common/src/linux_80211.h +++ b/sys/compat/linuxkpi/common/src/linux_80211.h @@ -187,6 +187,11 @@ struct lkpi_vif { enum ieee80211_state, int); struct ieee80211_node * (*iv_update_bss)(struct ieee80211vap *, struct ieee80211_node *); + void (*iv_recv_mgmt)(struct ieee80211_node *, + struct mbuf *, int, + const struct ieee80211_rx_stats *, + int, int); + struct list_head lsta_list; struct lkpi_sta *lvif_bss; @@ -194,6 +199,7 @@ struct lkpi_vif { struct ieee80211_node *key_update_iv_bss; int ic_unlocked; /* Count of ic unlocks pending (*mo_set_key) */ int nt_unlocked; /* Count of nt unlocks pending (*mo_set_key) */ + int beacons; /* # of beacons since assoc */ bool lvif_bss_synched; bool added_to_drv; /* Driver knows; i.e. we called add_interface(). */ @@ -223,6 +229,9 @@ struct lkpi_hw { /* name it mac80211_sc? */ struct sx lvif_sx; struct list_head lchanctx_list; + struct netdev_hw_addr_list mc_list; + unsigned int mc_flags; + struct sx mc_sx; struct mtx txq_mtx; uint32_t txq_generation[IEEE80211_NUM_ACS]; @@ -279,7 +288,7 @@ struct lkpi_hw { /* name it mac80211_sc? */ int max_rates; /* Maximum number of bitrates supported in any channel. */ int scan_ie_len; /* Length of common per-band scan IEs. */ - bool update_mc; + bool mc_all_multi; bool update_wme; bool rxq_stopped; @@ -369,6 +378,13 @@ struct lkpi_wiphy { #define LKPI_80211_LHW_LVIF_LOCK(_lhw) sx_xlock(&(_lhw)->lvif_sx) #define LKPI_80211_LHW_LVIF_UNLOCK(_lhw) sx_xunlock(&(_lhw)->lvif_sx) +#define LKPI_80211_LHW_MC_LOCK_INIT(_lhw) \ + sx_init_flags(&lhw->mc_sx, "lhw-mc", 0); +#define LKPI_80211_LHW_MC_LOCK_DESTROY(_lhw) \ + sx_destroy(&lhw->mc_sx); +#define LKPI_80211_LHW_MC_LOCK(_lhw) sx_xlock(&(_lhw)->mc_sx) +#define LKPI_80211_LHW_MC_UNLOCK(_lhw) sx_xunlock(&(_lhw)->mc_sx) + #define LKPI_80211_LVIF_LOCK(_lvif) mtx_lock(&(_lvif)->mtx) #define LKPI_80211_LVIF_UNLOCK(_lvif) mtx_unlock(&(_lvif)->mtx) diff --git a/sys/compat/linuxkpi/common/src/linux_80211_macops.c b/sys/compat/linuxkpi/common/src/linux_80211_macops.c index 78b2120f2d8c..1046b753574f 100644 --- a/sys/compat/linuxkpi/common/src/linux_80211_macops.c +++ b/sys/compat/linuxkpi/common/src/linux_80211_macops.c @@ -53,6 +53,8 @@ lkpi_80211_mo_start(struct ieee80211_hw *hw) struct lkpi_hw *lhw; int error; + lockdep_assert_wiphy(hw->wiphy); + lhw = HW_TO_LHW(hw); if (lhw->ops->start == NULL) { error = EOPNOTSUPP; diff --git a/sys/conf/files.x86 b/sys/conf/files.x86 index 9976e9cfec5d..953da7dd1284 100644 --- a/sys/conf/files.x86 +++ b/sys/conf/files.x86 @@ -146,6 +146,7 @@ dev/hyperv/vmbus/vmbus_et.c optional hyperv dev/hyperv/vmbus/vmbus_if.m optional hyperv dev/hyperv/vmbus/vmbus_res.c optional hyperv dev/hyperv/vmbus/vmbus_xact.c optional hyperv +dev/ichwd/i6300esbwd.c optional ichwd dev/ichwd/ichwd.c optional ichwd dev/imcsmb/imcsmb.c optional imcsmb dev/imcsmb/imcsmb_pci.c optional imcsmb pci diff --git a/sys/contrib/dev/acpica/components/executer/extrace.c b/sys/contrib/dev/acpica/components/executer/extrace.c index d54d4908ca65..b48a5fcb289b 100644 --- a/sys/contrib/dev/acpica/components/executer/extrace.c +++ b/sys/contrib/dev/acpica/components/executer/extrace.c @@ -301,7 +301,7 @@ AcpiExTraceArgs(ACPI_OPERAND_OBJECT **Params, UINT32 Count) switch (obj_desc->Common.Type) { case ACPI_TYPE_INTEGER: - ACPI_DEBUG_PRINT_RAW((ACPI_DB_TRACE_POINT, "%lx", obj_desc->Integer.Value)); + ACPI_DEBUG_PRINT_RAW((ACPI_DB_TRACE_POINT, "%jx", (uintmax_t)obj_desc->Integer.Value)); break; case ACPI_TYPE_STRING: diff --git a/sys/contrib/openzfs/.github/workflows/scripts/qemu-2-start.sh b/sys/contrib/openzfs/.github/workflows/scripts/qemu-2-start.sh index 70a2364f1fc6..62e06926e268 100755 --- a/sys/contrib/openzfs/.github/workflows/scripts/qemu-2-start.sh +++ b/sys/contrib/openzfs/.github/workflows/scripts/qemu-2-start.sh @@ -25,6 +25,10 @@ UBMIRROR="https://cloud-images.ubuntu.com" # default nic model for vm's NIC="virtio" +# additional options for virt-install +OPTS[0]="" +OPTS[1]="" + case "$OS" in almalinux8) OSNAME="AlmaLinux 8" @@ -61,6 +65,14 @@ case "$OS" in OSNAME="Debian 12" URL="https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-generic-amd64.qcow2" ;; + debian13) + OSNAME="Debian 13" + # TODO: Overwrite OSv to debian13 for virt-install until it's added to osinfo + OSv="debian12" + URL="https://cloud.debian.org/images/cloud/trixie/latest/debian-13-generic-amd64.qcow2" + OPTS[0]="--boot" + OPTS[1]="uefi=on" + ;; fedora41) OSNAME="Fedora 41" OSv="fedora-unknown" @@ -242,7 +254,7 @@ sudo virt-install \ --network bridge=virbr0,model=$NIC,mac='52:54:00:83:79:00' \ --cloud-init user-data=/tmp/user-data \ --disk $DISK,bus=virtio,cache=none,format=raw,driver.discard=unmap \ - --import --noautoconsole >/dev/null + --import --noautoconsole ${OPTS[0]} ${OPTS[1]} >/dev/null # Give the VMs hostnames so we don't have to refer to them with # hardcoded IP addresses. diff --git a/sys/contrib/openzfs/.github/workflows/scripts/qemu-3-deps-vm.sh b/sys/contrib/openzfs/.github/workflows/scripts/qemu-3-deps-vm.sh index c41ecd09d52e..ee058b488088 100755 --- a/sys/contrib/openzfs/.github/workflows/scripts/qemu-3-deps-vm.sh +++ b/sys/contrib/openzfs/.github/workflows/scripts/qemu-3-deps-vm.sh @@ -41,7 +41,7 @@ function debian() { libelf-dev libffi-dev libmount-dev libpam0g-dev libselinux-dev libssl-dev \ libtool libtool-bin libudev-dev libunwind-dev linux-headers-$(uname -r) \ lsscsi nfs-kernel-server pamtester parted python3 python3-all-dev \ - python3-cffi python3-dev python3-distlib python3-packaging \ + python3-cffi python3-dev python3-distlib python3-packaging libtirpc-dev \ python3-setuptools python3-sphinx qemu-guest-agent rng-tools rpm2cpio \ rsync samba sysstat uuid-dev watchdog wget xfslibs-dev xxhash zlib1g-dev echo "##[endgroup]" diff --git a/sys/contrib/openzfs/.github/workflows/scripts/qemu-5-setup.sh b/sys/contrib/openzfs/.github/workflows/scripts/qemu-5-setup.sh index 6bf10024a1a6..0adcad2a99bc 100755 --- a/sys/contrib/openzfs/.github/workflows/scripts/qemu-5-setup.sh +++ b/sys/contrib/openzfs/.github/workflows/scripts/qemu-5-setup.sh @@ -12,16 +12,26 @@ source /var/tmp/env.txt # wait for poweroff to succeed PID=$(pidof /usr/bin/qemu-system-x86_64) tail --pid=$PID -f /dev/null -sudo virsh undefine openzfs +sudo virsh undefine --nvram openzfs # cpu pinning CPUSET=("0,1" "2,3") +# additional options for virt-install +OPTS[0]="" +OPTS[1]="" + case "$OS" in freebsd*) # FreeBSD needs only 6GiB RAM=6 ;; + debian13) + RAM=8 + # Boot Debian 13 with uefi=on and secureboot=off (ZFS Kernel Module not signed) + OPTS[0]="--boot" + OPTS[1]="firmware=efi,firmware.feature0.name=secure-boot,firmware.feature0.enabled=no" + ;; *) # Linux needs more memory, but can be optimized to share it via KSM RAM=8 @@ -79,7 +89,7 @@ EOF --network bridge=virbr0,model=$NIC,mac="52:54:00:83:79:0$i" \ --disk $DISK-system,bus=virtio,cache=none,format=$FORMAT,driver.discard=unmap \ --disk $DISK-tests,bus=virtio,cache=none,format=$FORMAT,driver.discard=unmap \ - --import --noautoconsole >/dev/null + --import --noautoconsole ${OPTS[0]} ${OPTS[1]} done # generate some memory stats diff --git a/sys/contrib/openzfs/.github/workflows/zfs-qemu.yml b/sys/contrib/openzfs/.github/workflows/zfs-qemu.yml index cda620313189..4ebb80af1f03 100644 --- a/sys/contrib/openzfs/.github/workflows/zfs-qemu.yml +++ b/sys/contrib/openzfs/.github/workflows/zfs-qemu.yml @@ -29,7 +29,7 @@ jobs: - name: Generate OS config and CI type id: os run: | - FULL_OS='["almalinux8", "almalinux9", "almalinux10", "centos-stream9", "centos-stream10", "debian11", "debian12", "fedora41", "fedora42", "freebsd13-5r", "freebsd14-3s", "freebsd15-0c", "ubuntu22", "ubuntu24"]' + FULL_OS='["almalinux8", "almalinux9", "almalinux10", "centos-stream9", "centos-stream10", "debian12", "debian13", "fedora41", "fedora42", "freebsd13-5r", "freebsd14-3s", "freebsd15-0c", "ubuntu22", "ubuntu24"]' QUICK_OS='["almalinux8", "almalinux9", "almalinux10", "debian12", "fedora42", "freebsd14-3s", "ubuntu24"]' # determine CI type when running on PR ci_type="full" @@ -63,8 +63,8 @@ jobs: strategy: fail-fast: false matrix: - # rhl: almalinux8, almalinux9, centos-stream9, fedora41 - # debian: debian11, debian12, ubuntu22, ubuntu24 + # rhl: almalinux8, almalinux9, centos-stream9, fedora4x + # debian: debian12, debian13, ubuntu22, ubuntu24 # misc: archlinux, tumbleweed # FreeBSD variants of 2025-06: # FreeBSD Release: freebsd13-5r, freebsd14-2r, freebsd14-3r diff --git a/sys/contrib/openzfs/META b/sys/contrib/openzfs/META index 1a9c671feac6..42f65290e4e3 100644 --- a/sys/contrib/openzfs/META +++ b/sys/contrib/openzfs/META @@ -1,8 +1,8 @@ Meta: 1 Name: zfs Branch: 1.0 -Version: 2.3.99 -Release: 1 +Version: 2.4.0 +Release: rc1 Release-Tags: relext License: CDDL Author: OpenZFS diff --git a/sys/contrib/openzfs/cmd/zdb/zdb.c b/sys/contrib/openzfs/cmd/zdb/zdb.c index a5f23be2aaaf..adaa5cd10961 100644 --- a/sys/contrib/openzfs/cmd/zdb/zdb.c +++ b/sys/contrib/openzfs/cmd/zdb/zdb.c @@ -1586,9 +1586,8 @@ dump_spacemap(objset_t *os, space_map_t *sm) continue; } - uint8_t words; char entry_type; - uint64_t entry_off, entry_run, entry_vdev = SM_NO_VDEVID; + uint64_t entry_off, entry_run, entry_vdev; if (sm_entry_is_single_word(word)) { entry_type = (SM_TYPE_DECODE(word) == SM_ALLOC) ? @@ -1596,35 +1595,43 @@ dump_spacemap(objset_t *os, space_map_t *sm) entry_off = (SM_OFFSET_DECODE(word) << mapshift) + sm->sm_start; entry_run = SM_RUN_DECODE(word) << mapshift; - words = 1; + + (void) printf("\t [%6llu] %c " + "range: %012llx-%012llx size: %08llx\n", + (u_longlong_t)entry_id, entry_type, + (u_longlong_t)entry_off, + (u_longlong_t)(entry_off + entry_run - 1), + (u_longlong_t)entry_run); } else { /* it is a two-word entry so we read another word */ ASSERT(sm_entry_is_double_word(word)); uint64_t extra_word; offset += sizeof (extra_word); + ASSERT3U(offset, <, space_map_length(sm)); VERIFY0(dmu_read(os, space_map_object(sm), offset, sizeof (extra_word), &extra_word, DMU_READ_PREFETCH)); - ASSERT3U(offset, <=, space_map_length(sm)); - entry_run = SM2_RUN_DECODE(word) << mapshift; entry_vdev = SM2_VDEV_DECODE(word); entry_type = (SM2_TYPE_DECODE(extra_word) == SM_ALLOC) ? 'A' : 'F'; entry_off = (SM2_OFFSET_DECODE(extra_word) << mapshift) + sm->sm_start; - words = 2; - } - (void) printf("\t [%6llu] %c range:" - " %010llx-%010llx size: %06llx vdev: %06llu words: %u\n", - (u_longlong_t)entry_id, - entry_type, (u_longlong_t)entry_off, - (u_longlong_t)(entry_off + entry_run), - (u_longlong_t)entry_run, - (u_longlong_t)entry_vdev, words); + if (zopt_metaslab_args == 0 || + zopt_metaslab[0] == entry_vdev) { + (void) printf("\t [%6llu] %c " + "range: %012llx-%012llx size: %08llx " + "vdev: %llu\n", + (u_longlong_t)entry_id, entry_type, + (u_longlong_t)entry_off, + (u_longlong_t)(entry_off + entry_run - 1), + (u_longlong_t)entry_run, + (u_longlong_t)entry_vdev); + } + } if (entry_type == 'A') alloc += entry_run; @@ -1873,7 +1880,7 @@ dump_metaslabs(spa_t *spa) (void) printf("\nMetaslabs:\n"); - if (!dump_opt['d'] && zopt_metaslab_args > 0) { + if (zopt_metaslab_args > 0) { c = zopt_metaslab[0]; if (c >= children) diff --git a/sys/contrib/openzfs/contrib/debian/rules.in b/sys/contrib/openzfs/contrib/debian/rules.in index 3226d604546c..2b0568938b25 100755 --- a/sys/contrib/openzfs/contrib/debian/rules.in +++ b/sys/contrib/openzfs/contrib/debian/rules.in @@ -93,7 +93,7 @@ override_dh_auto_install: @# Install the DKMS source. @# We only want the files needed to build the modules install -D -t '$(CURDIR)/debian/tmp/usr/src/$(NAME)-$(DEB_VERSION_UPSTREAM)/scripts' \ - '$(CURDIR)/scripts/dkms.postbuild' + '$(CURDIR)/scripts/dkms.postbuild' '$(CURDIR)/scripts/objtool-wrapper.in' $(foreach file,$(DKMSFILES),mv '$(CURDIR)/$(NAME)-$(DEB_VERSION_UPSTREAM)/$(file)' '$(CURDIR)/debian/tmp/usr/src/$(NAME)-$(DEB_VERSION_UPSTREAM)' || exit 1;) @# Only ever build Linux modules @@ -108,8 +108,8 @@ override_dh_auto_install: @# - zfs.release$ @# * Takes care of spaces and tabs @# * Remove reference to ZFS_AC_PACKAGE - awk '/^AC_CONFIG_FILES\(\[/,/^\]\)/ {\ - if ($$0 !~ /^(AC_CONFIG_FILES\(\[([ \t]+)?$$|\]\)([ \t]+)?$$|([ \t]+)?(include\/(Makefile|sys|os\/(Makefile|linux))|module\/|Makefile([ \t]+)?$$|zfs\.release([ \t]+)?$$))/) \ + awk '/^AC_CONFIG_FILES\(\[/,/\]\)/ {\ + if ($$0 !~ /^(AC_CONFIG_FILES\(\[([ \t]+)?$$|\]\)([ \t]+)?$$|([ \t]+)?(include\/(Makefile|sys|os\/(Makefile|linux))|module\/|Makefile([ \t]+)?$$|zfs\.release([ \t]+)?$$))|scripts\/objtool-wrapper.*\]\)$$/) \ {next} } {print}' \ '$(CURDIR)/$(NAME)-$(DEB_VERSION_UPSTREAM)/configure.ac' | sed '/ZFS_AC_PACKAGE/d' > '$(CURDIR)/debian/tmp/usr/src/$(NAME)-$(DEB_VERSION_UPSTREAM)/configure.ac' @# Set "SUBDIRS = module include" for CONFIG_KERNEL and remove SUBDIRS for all other configs. diff --git a/sys/contrib/openzfs/include/sys/dmu_impl.h b/sys/contrib/openzfs/include/sys/dmu_impl.h index 21a8b16a3ee6..bae872bd1907 100644 --- a/sys/contrib/openzfs/include/sys/dmu_impl.h +++ b/sys/contrib/openzfs/include/sys/dmu_impl.h @@ -168,12 +168,10 @@ extern "C" { * dn_allocated_txg * dn_free_txg * dn_assigned_txg - * dn_dirty_txg + * dn_dirtycnt * dd_assigned_tx * dn_notxholds * dn_nodnholds - * dn_dirtyctx - * dn_dirtyctx_firstset * (dn_phys copy fields?) * (dn_phys contents?) * held from: diff --git a/sys/contrib/openzfs/include/sys/dnode.h b/sys/contrib/openzfs/include/sys/dnode.h index 76218c8b09ca..8bd1db5b7165 100644 --- a/sys/contrib/openzfs/include/sys/dnode.h +++ b/sys/contrib/openzfs/include/sys/dnode.h @@ -141,12 +141,6 @@ struct dmu_buf_impl; struct objset; struct zio; -enum dnode_dirtycontext { - DN_UNDIRTIED, - DN_DIRTY_OPEN, - DN_DIRTY_SYNC -}; - /* Is dn_used in bytes? if not, it's in multiples of SPA_MINBLOCKSIZE */ #define DNODE_FLAG_USED_BYTES (1 << 0) #define DNODE_FLAG_USERUSED_ACCOUNTED (1 << 1) @@ -340,11 +334,9 @@ struct dnode { uint64_t dn_allocated_txg; uint64_t dn_free_txg; uint64_t dn_assigned_txg; - uint64_t dn_dirty_txg; /* txg dnode was last dirtied */ + uint8_t dn_dirtycnt; kcondvar_t dn_notxholds; kcondvar_t dn_nodnholds; - enum dnode_dirtycontext dn_dirtyctx; - const void *dn_dirtyctx_firstset; /* dbg: contents meaningless */ /* protected by own devices */ zfs_refcount_t dn_tx_holds; @@ -440,7 +432,6 @@ void dnode_rele_and_unlock(dnode_t *dn, const void *tag, boolean_t evicting); int dnode_try_claim(objset_t *os, uint64_t object, int slots); boolean_t dnode_is_dirty(dnode_t *dn); void dnode_setdirty(dnode_t *dn, dmu_tx_t *tx); -void dnode_set_dirtyctx(dnode_t *dn, dmu_tx_t *tx, const void *tag); void dnode_sync(dnode_t *dn, dmu_tx_t *tx); void dnode_allocate(dnode_t *dn, dmu_object_type_t ot, int blocksize, int ibs, dmu_object_type_t bonustype, int bonuslen, int dn_slots, dmu_tx_t *tx); @@ -468,9 +459,6 @@ void dnode_free_interior_slots(dnode_t *dn); void dnode_set_storage_type(dnode_t *dn, dmu_object_type_t type); -#define DNODE_IS_DIRTY(_dn) \ - ((_dn)->dn_dirty_txg >= spa_syncing_txg((_dn)->dn_objset->os_spa)) - #define DNODE_LEVEL_IS_CACHEABLE(_dn, _level) \ ((_dn)->dn_objset->os_primary_cache == ZFS_CACHE_ALL || \ (((_level) > 0 || DMU_OT_IS_METADATA((_dn)->dn_type)) && \ diff --git a/sys/contrib/openzfs/module/zfs/dbuf.c b/sys/contrib/openzfs/module/zfs/dbuf.c index 7403f10d91b7..fccc4c5b5b94 100644 --- a/sys/contrib/openzfs/module/zfs/dbuf.c +++ b/sys/contrib/openzfs/module/zfs/dbuf.c @@ -2270,14 +2270,6 @@ dbuf_dirty(dmu_buf_impl_t *db, dmu_tx_t *tx) if (dn->dn_objset->os_dsl_dataset != NULL) rrw_exit(&dn->dn_objset->os_dsl_dataset->ds_bp_rwlock, FTAG); #endif - /* - * We make this assert for private objects as well, but after we - * check if we're already dirty. They are allowed to re-dirty - * in syncing context. - */ - ASSERT(dn->dn_object == DMU_META_DNODE_OBJECT || - dn->dn_dirtyctx == DN_UNDIRTIED || dn->dn_dirtyctx == - (dmu_tx_is_syncing(tx) ? DN_DIRTY_SYNC : DN_DIRTY_OPEN)); mutex_enter(&db->db_mtx); /* @@ -2289,12 +2281,6 @@ dbuf_dirty(dmu_buf_impl_t *db, dmu_tx_t *tx) db->db_state == DB_CACHED || db->db_state == DB_FILL || db->db_state == DB_NOFILL); - mutex_enter(&dn->dn_mtx); - dnode_set_dirtyctx(dn, tx, db); - if (tx->tx_txg > dn->dn_dirty_txg) - dn->dn_dirty_txg = tx->tx_txg; - mutex_exit(&dn->dn_mtx); - if (db->db_blkid == DMU_SPILL_BLKID) dn->dn_have_spill = B_TRUE; @@ -2313,13 +2299,6 @@ dbuf_dirty(dmu_buf_impl_t *db, dmu_tx_t *tx) return (dr_next); } - /* - * Only valid if not already dirty. - */ - ASSERT(dn->dn_object == 0 || - dn->dn_dirtyctx == DN_UNDIRTIED || dn->dn_dirtyctx == - (dmu_tx_is_syncing(tx) ? DN_DIRTY_SYNC : DN_DIRTY_OPEN)); - ASSERT3U(dn->dn_nlevels, >, db->db_level); /* diff --git a/sys/contrib/openzfs/module/zfs/dmu_objset.c b/sys/contrib/openzfs/module/zfs/dmu_objset.c index a77f338bdfd3..8e6b569c2100 100644 --- a/sys/contrib/openzfs/module/zfs/dmu_objset.c +++ b/sys/contrib/openzfs/module/zfs/dmu_objset.c @@ -2037,6 +2037,8 @@ userquota_updates_task(void *arg) dn->dn_id_flags |= DN_ID_CHKED_BONUS; } dn->dn_id_flags &= ~(DN_ID_NEW_EXIST); + ASSERT3U(dn->dn_dirtycnt, >, 0); + dn->dn_dirtycnt--; mutex_exit(&dn->dn_mtx); multilist_sublist_remove(list, dn); @@ -2070,6 +2072,10 @@ dnode_rele_task(void *arg) dnode_t *dn; while ((dn = multilist_sublist_head(list)) != NULL) { + mutex_enter(&dn->dn_mtx); + ASSERT3U(dn->dn_dirtycnt, >, 0); + dn->dn_dirtycnt--; + mutex_exit(&dn->dn_mtx); multilist_sublist_remove(list, dn); dnode_rele(dn, &os->os_synced_dnodes); } diff --git a/sys/contrib/openzfs/module/zfs/dnode.c b/sys/contrib/openzfs/module/zfs/dnode.c index 963ff41232a3..6c150d31c669 100644 --- a/sys/contrib/openzfs/module/zfs/dnode.c +++ b/sys/contrib/openzfs/module/zfs/dnode.c @@ -173,9 +173,7 @@ dnode_cons(void *arg, void *unused, int kmflag) dn->dn_allocated_txg = 0; dn->dn_free_txg = 0; dn->dn_assigned_txg = 0; - dn->dn_dirty_txg = 0; - dn->dn_dirtyctx = 0; - dn->dn_dirtyctx_firstset = NULL; + dn->dn_dirtycnt = 0; dn->dn_bonus = NULL; dn->dn_have_spill = B_FALSE; dn->dn_zio = NULL; @@ -229,9 +227,7 @@ dnode_dest(void *arg, void *unused) ASSERT0(dn->dn_allocated_txg); ASSERT0(dn->dn_free_txg); ASSERT0(dn->dn_assigned_txg); - ASSERT0(dn->dn_dirty_txg); - ASSERT0(dn->dn_dirtyctx); - ASSERT0P(dn->dn_dirtyctx_firstset); + ASSERT0(dn->dn_dirtycnt); ASSERT0P(dn->dn_bonus); ASSERT(!dn->dn_have_spill); ASSERT0P(dn->dn_zio); @@ -692,10 +688,8 @@ dnode_destroy(dnode_t *dn) dn->dn_allocated_txg = 0; dn->dn_free_txg = 0; dn->dn_assigned_txg = 0; - dn->dn_dirty_txg = 0; + dn->dn_dirtycnt = 0; - dn->dn_dirtyctx = 0; - dn->dn_dirtyctx_firstset = NULL; if (dn->dn_bonus != NULL) { mutex_enter(&dn->dn_bonus->db_mtx); dbuf_destroy(dn->dn_bonus); @@ -800,11 +794,9 @@ dnode_allocate(dnode_t *dn, dmu_object_type_t ot, int blocksize, int ibs, dn->dn_bonuslen = bonuslen; dn->dn_checksum = ZIO_CHECKSUM_INHERIT; dn->dn_compress = ZIO_COMPRESS_INHERIT; - dn->dn_dirtyctx = 0; dn->dn_free_txg = 0; - dn->dn_dirtyctx_firstset = NULL; - dn->dn_dirty_txg = 0; + dn->dn_dirtycnt = 0; dn->dn_allocated_txg = tx->tx_txg; dn->dn_id_flags = 0; @@ -955,9 +947,7 @@ dnode_move_impl(dnode_t *odn, dnode_t *ndn) ndn->dn_allocated_txg = odn->dn_allocated_txg; ndn->dn_free_txg = odn->dn_free_txg; ndn->dn_assigned_txg = odn->dn_assigned_txg; - ndn->dn_dirty_txg = odn->dn_dirty_txg; - ndn->dn_dirtyctx = odn->dn_dirtyctx; - ndn->dn_dirtyctx_firstset = odn->dn_dirtyctx_firstset; + ndn->dn_dirtycnt = odn->dn_dirtycnt; ASSERT0(zfs_refcount_count(&odn->dn_tx_holds)); zfs_refcount_transfer(&ndn->dn_holds, &odn->dn_holds); ASSERT(avl_is_empty(&ndn->dn_dbufs)); @@ -1020,9 +1010,7 @@ dnode_move_impl(dnode_t *odn, dnode_t *ndn) odn->dn_allocated_txg = 0; odn->dn_free_txg = 0; odn->dn_assigned_txg = 0; - odn->dn_dirty_txg = 0; - odn->dn_dirtyctx = 0; - odn->dn_dirtyctx_firstset = NULL; + odn->dn_dirtycnt = 0; odn->dn_have_spill = B_FALSE; odn->dn_zio = NULL; odn->dn_oldused = 0; @@ -1273,8 +1261,8 @@ dnode_check_slots_free(dnode_children_t *children, int idx, int slots) } else if (DN_SLOT_IS_PTR(dn)) { mutex_enter(&dn->dn_mtx); boolean_t can_free = (dn->dn_type == DMU_OT_NONE && - zfs_refcount_is_zero(&dn->dn_holds) && - !DNODE_IS_DIRTY(dn)); + dn->dn_dirtycnt == 0 && + zfs_refcount_is_zero(&dn->dn_holds)); mutex_exit(&dn->dn_mtx); if (!can_free) @@ -1757,17 +1745,23 @@ dnode_hold(objset_t *os, uint64_t object, const void *tag, dnode_t **dnp) * reference on the dnode. Returns FALSE if unable to add a * new reference. */ +static boolean_t +dnode_add_ref_locked(dnode_t *dn, const void *tag) +{ + ASSERT(MUTEX_HELD(&dn->dn_mtx)); + if (zfs_refcount_is_zero(&dn->dn_holds)) + return (FALSE); + VERIFY(1 < zfs_refcount_add(&dn->dn_holds, tag)); + return (TRUE); +} + boolean_t dnode_add_ref(dnode_t *dn, const void *tag) { mutex_enter(&dn->dn_mtx); - if (zfs_refcount_is_zero(&dn->dn_holds)) { - mutex_exit(&dn->dn_mtx); - return (FALSE); - } - VERIFY(1 < zfs_refcount_add(&dn->dn_holds, tag)); + boolean_t r = dnode_add_ref_locked(dn, tag); mutex_exit(&dn->dn_mtx); - return (TRUE); + return (r); } void @@ -1830,31 +1824,20 @@ dnode_try_claim(objset_t *os, uint64_t object, int slots) } /* - * Checks if the dnode itself is dirty, or is carrying any uncommitted records. - * It is important to check both conditions, as some operations (eg appending - * to a file) can dirty both as a single logical unit, but they are not synced - * out atomically, so checking one and not the other can result in an object - * appearing to be clean mid-way through a commit. + * Test if the dnode is dirty, or carrying uncommitted records. * - * Do not change this lightly! If you get it wrong, dmu_offset_next() can - * detect a hole where there is really data, leading to silent corruption. + * dn_dirtycnt is the number of txgs this dnode is dirty on. It's incremented + * in dnode_setdirty() the first time the dnode is dirtied on a txg, and + * decremented in either dnode_rele_task() or userquota_updates_task() when the + * txg is synced out. */ boolean_t dnode_is_dirty(dnode_t *dn) { mutex_enter(&dn->dn_mtx); - - for (int i = 0; i < TXG_SIZE; i++) { - if (multilist_link_active(&dn->dn_dirty_link[i]) || - !list_is_empty(&dn->dn_dirty_records[i])) { - mutex_exit(&dn->dn_mtx); - return (B_TRUE); - } - } - + boolean_t dirty = (dn->dn_dirtycnt != 0); mutex_exit(&dn->dn_mtx); - - return (B_FALSE); + return (dirty); } void @@ -1916,7 +1899,11 @@ dnode_setdirty(dnode_t *dn, dmu_tx_t *tx) * dnode will hang around after we finish processing its * children. */ - VERIFY(dnode_add_ref(dn, (void *)(uintptr_t)tx->tx_txg)); + mutex_enter(&dn->dn_mtx); + VERIFY(dnode_add_ref_locked(dn, (void *)(uintptr_t)tx->tx_txg)); + dn->dn_dirtycnt++; + ASSERT3U(dn->dn_dirtycnt, <=, 3); + mutex_exit(&dn->dn_mtx); (void) dbuf_dirty(dn->dn_dbuf, tx); @@ -2221,32 +2208,6 @@ dnode_dirty_l1range(dnode_t *dn, uint64_t start_blkid, uint64_t end_blkid, mutex_exit(&dn->dn_dbufs_mtx); } -void -dnode_set_dirtyctx(dnode_t *dn, dmu_tx_t *tx, const void *tag) -{ - /* - * Don't set dirtyctx to SYNC if we're just modifying this as we - * initialize the objset. - */ - if (dn->dn_dirtyctx == DN_UNDIRTIED) { - dsl_dataset_t *ds = dn->dn_objset->os_dsl_dataset; - - if (ds != NULL) { - rrw_enter(&ds->ds_bp_rwlock, RW_READER, tag); - } - if (!BP_IS_HOLE(dn->dn_objset->os_rootbp)) { - if (dmu_tx_is_syncing(tx)) - dn->dn_dirtyctx = DN_DIRTY_SYNC; - else - dn->dn_dirtyctx = DN_DIRTY_OPEN; - dn->dn_dirtyctx_firstset = tag; - } - if (ds != NULL) { - rrw_exit(&ds->ds_bp_rwlock, tag); - } - } -} - static void dnode_partial_zero(dnode_t *dn, uint64_t off, uint64_t blkoff, uint64_t len, dmu_tx_t *tx) diff --git a/sys/contrib/vchiq/interface/vchiq_arm/vchiq_2835_arm.c b/sys/contrib/vchiq/interface/vchiq_arm/vchiq_2835_arm.c index ab8981e25cb2..0150ce72f0a4 100644 --- a/sys/contrib/vchiq/interface/vchiq_arm/vchiq_2835_arm.c +++ b/sys/contrib/vchiq/interface/vchiq_arm/vchiq_2835_arm.c @@ -464,7 +464,8 @@ create_pagelist(char __user *buf, size_t count, unsigned short type, (type == PAGELIST_READ ? VM_PROT_WRITE : 0 ) | VM_PROT_READ, pages, num_pages); if (actual_pages != num_pages) { - vm_page_unhold_pages(pages, actual_pages); + if (actual_pages > 0) + vm_page_unhold_pages(pages, actual_pages); free(pagelist, M_VCPAGELIST); return (-ENOMEM); } diff --git a/sys/dev/amdgpio/amdgpio.c b/sys/dev/amdgpio/amdgpio.c index 2bd455c612b8..20589ff71b0b 100644 --- a/sys/dev/amdgpio/amdgpio.c +++ b/sys/dev/amdgpio/amdgpio.c @@ -3,6 +3,10 @@ * * Copyright (c) 2018 Advanced Micro Devices * All rights reserved. + * Copyright (c) 2025 The FreeBSD Foundation + * + * Portions of this software were developed by Aymeric Wibo + * <obiwac@freebsd.org> under sponsorship from the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -51,11 +55,11 @@ #include <dev/acpica/acpivar.h> #include <dev/gpio/gpiobusvar.h> -#include "gpio_if.h" #include "amdgpio.h" static struct resource_spec amdgpio_spec[] = { - { SYS_RES_MEMORY, 0, RF_ACTIVE }, + { SYS_RES_MEMORY, 0, RF_ACTIVE }, + { SYS_RES_IRQ, 0, RF_ACTIVE | RF_SHAREABLE }, { -1, 0, 0 } }; @@ -196,7 +200,7 @@ static int amdgpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags) { struct amdgpio_softc *sc; - uint32_t reg, val, allowed; + uint32_t reg, val; sc = device_get_softc(dev); @@ -204,18 +208,19 @@ amdgpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags) if (!amdgpio_valid_pin(sc, pin)) return (EINVAL); - allowed = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT; + if ((flags & ~AMDGPIO_DEFAULT_CAPS) != 0) { + device_printf(dev, "disallowed flags (0x%x) trying to be set " + "(allowed is 0x%x)\n", flags, AMDGPIO_DEFAULT_CAPS); + return (EINVAL); + } - /* - * Only directtion flag allowed - */ - if (flags & ~allowed) + /* Either input or output must be selected. */ + if ((flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) == 0) return (EINVAL); - /* - * Not both directions simultaneously - */ - if ((flags & allowed) == allowed) + /* Not both directions simultaneously. */ + if ((flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) == + (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) return (EINVAL); /* Set the GPIO mode and state */ @@ -224,16 +229,21 @@ amdgpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags) reg = AMDGPIO_PIN_REGISTER(pin); val = amdgpio_read_4(sc, reg); - if (flags & GPIO_PIN_INPUT) { + if ((flags & GPIO_PIN_INPUT) != 0) val &= ~BIT(OUTPUT_ENABLE_OFF); - sc->sc_gpio_pins[pin].gp_flags = GPIO_PIN_INPUT; - } else { + else val |= BIT(OUTPUT_ENABLE_OFF); - sc->sc_gpio_pins[pin].gp_flags = GPIO_PIN_OUTPUT; - } + + val &= ~(BIT(PULL_DOWN_ENABLE_OFF) | BIT(PULL_UP_ENABLE_OFF)); + + if ((flags & GPIO_PIN_PULLDOWN) != 0) + val |= BIT(PULL_DOWN_ENABLE_OFF); + if ((flags & GPIO_PIN_PULLUP) != 0) + val |= BIT(PULL_UP_ENABLE_OFF); amdgpio_write_4(sc, reg, val); + sc->sc_gpio_pins[pin].gp_flags = flags; dprintf("pin %d flags 0x%x val 0x%x gp_flags 0x%x\n", pin, flags, val, sc->sc_gpio_pins[pin].gp_flags); @@ -359,11 +369,73 @@ amdgpio_probe(device_t dev) return (rv); } +static void +amdgpio_eoi_locked(struct amdgpio_softc *sc) +{ + uint32_t master_reg = amdgpio_read_4(sc, WAKE_INT_MASTER_REG); + + AMDGPIO_ASSERT_LOCKED(sc); + master_reg |= EOI_MASK; + amdgpio_write_4(sc, WAKE_INT_MASTER_REG, master_reg); +} + +static void +amdgpio_eoi(struct amdgpio_softc *sc) +{ + AMDGPIO_LOCK(sc); + amdgpio_eoi_locked(sc); + AMDGPIO_UNLOCK(sc); +} + +static int +amdgpio_intr_filter(void *arg) +{ + struct amdgpio_softc *sc = arg; + int off, rv = FILTER_STRAY; + uint32_t reg; + + /* We can lock in the filter routine as it is MTX_SPIN. */ + AMDGPIO_LOCK(sc); + + /* + * TODO Instead of just reading the registers of all pins, we should + * read WAKE_INT_STATUS_REG0/1. A bit set in here denotes a group of + * 4 pins where at least one has an interrupt for us. Then we can just + * iterate over those 4 pins. + * + * See GPIO_Interrupt_Status_Index_0 in BKDG. + */ + for (size_t pin = 0; pin < AMD_GPIO_PINS_EXPOSED; pin++) { + off = AMDGPIO_PIN_REGISTER(pin); + reg = amdgpio_read_4(sc, off); + if ((reg & UNSERVICED_INTERRUPT_MASK) == 0) + continue; + /* + * Must write 1's to wake/interrupt status bits to clear them. + * We can do this simply by writing back to the register. + */ + amdgpio_write_4(sc, off, reg); + } + + amdgpio_eoi_locked(sc); + AMDGPIO_UNLOCK(sc); + + rv = FILTER_HANDLED; + return (rv); +} + +static void +amdgpio_intr_handler(void *arg) +{ + /* TODO */ +} + static int amdgpio_attach(device_t dev) { struct amdgpio_softc *sc; - int i, pin, bank; + int i, pin, bank, reg; + uint32_t flags; sc = device_get_softc(dev); sc->sc_dev = dev; @@ -386,6 +458,14 @@ amdgpio_attach(device_t dev) sc->sc_bst = rman_get_bustag(sc->sc_res[0]); sc->sc_bsh = rman_get_bushandle(sc->sc_res[0]); + /* Set up interrupt handler. */ + if (bus_setup_intr(dev, sc->sc_res[1], INTR_TYPE_MISC | INTR_MPSAFE, + amdgpio_intr_filter, amdgpio_intr_handler, sc, &sc->sc_intr_handle) + != 0) { + device_printf(dev, "couldn't set up interrupt\n"); + goto err_intr; + } + /* Initialize all possible pins to be Invalid */ for (i = 0; i < AMD_GPIO_PINS_MAX ; i++) { snprintf(sc->sc_gpio_pins[i].gp_name, GPIOMAXNAME, @@ -395,7 +475,12 @@ amdgpio_attach(device_t dev) sc->sc_gpio_pins[i].gp_flags = 0; } - /* Initialize only driver exposed pins with appropriate capabilities */ + /* + * Initialize only driver exposed pins with appropriate capabilities. + * + * XXX Also mask and disable interrupts on all pins, since we don't + * support them at the moment. + */ for (i = 0; i < AMD_GPIO_PINS_EXPOSED ; i++) { pin = kernzp_pins[i].pin_num; bank = pin/AMD_GPIO_PINS_PER_BANK; @@ -406,7 +491,14 @@ amdgpio_attach(device_t dev) sc->sc_gpio_pins[pin].gp_flags = amdgpio_is_pin_output(sc, pin) ? GPIO_PIN_OUTPUT : GPIO_PIN_INPUT; + + reg = AMDGPIO_PIN_REGISTER(pin); + flags = amdgpio_read_4(sc, reg); + flags &= ~(1 << INTERRUPT_ENABLE_OFF); + flags &= ~(1 << INTERRUPT_MASK_OFF); + amdgpio_write_4(sc, reg, flags); } + amdgpio_eoi(sc); sc->sc_busdev = gpiobus_add_bus(dev); if (sc->sc_busdev == NULL) { @@ -418,8 +510,9 @@ amdgpio_attach(device_t dev) return (0); err_bus: + bus_teardown_intr(dev, sc->sc_res[1], sc->sc_intr_handle); +err_intr: bus_release_resources(dev, amdgpio_spec, sc->sc_res); - err_rsrc: AMDGPIO_LOCK_DESTROY(sc); @@ -434,7 +527,8 @@ amdgpio_detach(device_t dev) if (sc->sc_busdev) gpiobus_detach_bus(dev); - + if (sc->sc_intr_handle) + bus_teardown_intr(dev, sc->sc_res[1], sc->sc_intr_handle); bus_release_resources(dev, amdgpio_spec, sc->sc_res); AMDGPIO_LOCK_DESTROY(sc); diff --git a/sys/dev/amdgpio/amdgpio.h b/sys/dev/amdgpio/amdgpio.h index aca3039bfc98..3743eba23e17 100644 --- a/sys/dev/amdgpio/amdgpio.h +++ b/sys/dev/amdgpio/amdgpio.h @@ -50,7 +50,8 @@ AMD_GPIO_PINS_BANK1 + \ AMD_GPIO_PINS_BANK2 + \ AMD_GPIO_PINS_BANK3) -#define AMDGPIO_DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT) +#define AMDGPIO_DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | \ + GPIO_PIN_PULLDOWN | GPIO_PIN_PULLUP) /* Register related macros */ #define AMDGPIO_PIN_REGISTER(pin) (pin * 4) @@ -84,6 +85,9 @@ #define INTERRUPT_STS_OFF 28 #define WAKE_STS_OFF 29 +#define UNSERVICED_INTERRUPT_MASK \ + ((1 << INTERRUPT_STS_OFF) | (1 << WAKE_STS_OFF)) + #define DB_TMR_OUT_MASK 0xFUL #define DB_CNTRL_MASK 0x3UL #define ACTIVE_LEVEL_MASK 0x3UL @@ -316,12 +320,13 @@ struct amdgpio_softc { int sc_npins; int sc_ngroups; struct mtx sc_mtx; - struct resource *sc_res[AMD_GPIO_NUM_PIN_BANK + 1]; + struct resource *sc_res[2]; bus_space_tag_t sc_bst; bus_space_handle_t sc_bsh; struct gpio_pin sc_gpio_pins[AMD_GPIO_PINS_MAX]; const struct pin_info *sc_pin_info; const struct amd_pingroup *sc_groups; + void *sc_intr_handle; }; struct amdgpio_sysctl { diff --git a/sys/dev/bce/if_bce.c b/sys/dev/bce/if_bce.c index 16bfce5338a7..6cf39e035ea6 100644 --- a/sys/dev/bce/if_bce.c +++ b/sys/dev/bce/if_bce.c @@ -1221,7 +1221,7 @@ bce_attach(device_t dev) sc->bce_bc_ver[j++] = '.'; } - /* Check if any management firwmare is enabled. */ + /* Check if any management firmware is enabled. */ val = bce_shmem_rd(sc, BCE_PORT_FEATURE); if (val & BCE_PORT_FEATURE_ASF_ENABLED) { sc->bce_flags |= BCE_MFW_ENABLE_FLAG; diff --git a/sys/dev/gpio/gpio_if.m b/sys/dev/gpio/gpio_if.m index 5501b2b5c0e7..0b6988ceba79 100644 --- a/sys/dev/gpio/gpio_if.m +++ b/sys/dev/gpio/gpio_if.m @@ -62,6 +62,22 @@ CODE { return (0); } + + static int + gpio_default_get_pin_list(device_t dev, uint32_t *pin_list) + { + uint32_t maxpin; + int err; + + err = GPIO_PIN_MAX(dev, &maxpin); + if (err != 0) + return (ENXIO); + + for (int i = 0; i <= maxpin; i++) + pin_list[i] = i; + + return (0); + } }; HEADER { @@ -185,3 +201,13 @@ METHOD int pin_config_32 { uint32_t num_pins; uint32_t *pin_flags; } DEFAULT gpio_default_nosupport; + +# +# Get the controller's pin numbers. pin_list is expected to be an array with at +# least GPIO_PIN_MAX() elements. Populates pin_list from 0 to GPIO_PIN_MAX() by +# default. +# +METHOD int get_pin_list { + device_t dev; + uint32_t *pin_list; +} DEFAULT gpio_default_get_pin_list; diff --git a/sys/dev/gpio/gpiobus.c b/sys/dev/gpio/gpiobus.c index 5f1f6532a79b..698b5e5fdd01 100644 --- a/sys/dev/gpio/gpiobus.c +++ b/sys/dev/gpio/gpiobus.c @@ -319,10 +319,6 @@ gpiobus_add_bus(device_t dev) busdev = device_add_child(dev, "gpiobus", DEVICE_UNIT_ANY); if (busdev == NULL) return (NULL); - if (device_add_child(dev, "gpioc", DEVICE_UNIT_ANY) == NULL) { - device_delete_child(dev, busdev); - return (NULL); - } #ifdef FDT ofw_gpiobus_register_provider(dev); #endif @@ -372,6 +368,37 @@ gpiobus_init_softc(device_t dev) } int +gpiobus_add_gpioc(device_t dev) +{ + struct gpiobus_ivar *devi; + struct gpiobus_softc *sc; + device_t gpioc; + int err; + + gpioc = BUS_ADD_CHILD(dev, 0, "gpioc", DEVICE_UNIT_ANY); + if (gpioc == NULL) + return (ENXIO); + + sc = device_get_softc(dev); + devi = device_get_ivars(gpioc); + + devi->npins = sc->sc_npins; + err = gpiobus_alloc_ivars(devi); + if (err != 0) { + device_delete_child(dev, gpioc); + return (err); + } + + err = GPIO_GET_PIN_LIST(sc->sc_dev, devi->pins); + if (err != 0) { + device_delete_child(dev, gpioc); + gpiobus_free_ivars(devi); + } + + return (err); +} + +int gpiobus_alloc_ivars(struct gpiobus_ivar *devi) { @@ -562,6 +589,10 @@ gpiobus_attach(device_t dev) if (err != 0) return (err); + err = gpiobus_add_gpioc(dev); + if (err != 0) + return (err); + /* * Get parent's pins and mark them as unmapped */ @@ -961,7 +992,7 @@ gpiobus_pin_getflags(device_t dev, device_t child, uint32_t pin, if (pin >= devi->npins) return (EINVAL); - return GPIO_PIN_GETFLAGS(sc->sc_dev, devi->pins[pin], flags); + return (GPIO_PIN_GETFLAGS(sc->sc_dev, devi->pins[pin], flags)); } static int @@ -974,7 +1005,7 @@ gpiobus_pin_getcaps(device_t dev, device_t child, uint32_t pin, if (pin >= devi->npins) return (EINVAL); - return GPIO_PIN_GETCAPS(sc->sc_dev, devi->pins[pin], caps); + return (GPIO_PIN_GETCAPS(sc->sc_dev, devi->pins[pin], caps)); } static int @@ -987,7 +1018,7 @@ gpiobus_pin_set(device_t dev, device_t child, uint32_t pin, if (pin >= devi->npins) return (EINVAL); - return GPIO_PIN_SET(sc->sc_dev, devi->pins[pin], value); + return (GPIO_PIN_SET(sc->sc_dev, devi->pins[pin], value)); } static int @@ -1000,7 +1031,7 @@ gpiobus_pin_get(device_t dev, device_t child, uint32_t pin, if (pin >= devi->npins) return (EINVAL); - return GPIO_PIN_GET(sc->sc_dev, devi->pins[pin], value); + return (GPIO_PIN_GET(sc->sc_dev, devi->pins[pin], value)); } static int @@ -1012,7 +1043,57 @@ gpiobus_pin_toggle(device_t dev, device_t child, uint32_t pin) if (pin >= devi->npins) return (EINVAL); - return GPIO_PIN_TOGGLE(sc->sc_dev, devi->pins[pin]); + return (GPIO_PIN_TOGGLE(sc->sc_dev, devi->pins[pin])); +} + +/* + * Verify that a child has all the pins they are requesting + * to access in their ivars. + */ +static bool +gpiobus_pin_verify_32(struct gpiobus_ivar *devi, uint32_t first_pin, + uint32_t num_pins) +{ + if (first_pin + num_pins > devi->npins) + return (false); + + /* Make sure the pins are consecutive. */ + for (uint32_t pin = first_pin; pin < first_pin + num_pins - 1; pin++) { + if (devi->pins[pin] + 1 != devi->pins[pin + 1]) + return (false); + } + + return (true); +} + +static int +gpiobus_pin_access_32(device_t dev, device_t child, uint32_t first_pin, + uint32_t clear_pins, uint32_t change_pins, uint32_t *orig_pins) +{ + struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev); + struct gpiobus_ivar *devi = GPIOBUS_IVAR(child); + + if (!gpiobus_pin_verify_32(devi, first_pin, 32)) + return (EINVAL); + + return (GPIO_PIN_ACCESS_32(sc->sc_dev, devi->pins[first_pin], + clear_pins, change_pins, orig_pins)); +} + +static int +gpiobus_pin_config_32(device_t dev, device_t child, uint32_t first_pin, + uint32_t num_pins, uint32_t *pin_flags) +{ + struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev); + struct gpiobus_ivar *devi = GPIOBUS_IVAR(child); + + if (num_pins > 32) + return (EINVAL); + if (!gpiobus_pin_verify_32(devi, first_pin, num_pins)) + return (EINVAL); + + return (GPIO_PIN_CONFIG_32(sc->sc_dev, + devi->pins[first_pin], num_pins, pin_flags)); } static int @@ -1093,6 +1174,8 @@ static device_method_t gpiobus_methods[] = { DEVMETHOD(gpiobus_pin_get, gpiobus_pin_get), DEVMETHOD(gpiobus_pin_set, gpiobus_pin_set), DEVMETHOD(gpiobus_pin_toggle, gpiobus_pin_toggle), + DEVMETHOD(gpiobus_pin_access_32,gpiobus_pin_access_32), + DEVMETHOD(gpiobus_pin_config_32,gpiobus_pin_config_32), DEVMETHOD(gpiobus_pin_getname, gpiobus_pin_getname), DEVMETHOD(gpiobus_pin_setname, gpiobus_pin_setname), diff --git a/sys/dev/gpio/gpiobus_if.m b/sys/dev/gpio/gpiobus_if.m index 8bf29839ef4e..890738c4e809 100644 --- a/sys/dev/gpio/gpiobus_if.m +++ b/sys/dev/gpio/gpiobus_if.m @@ -107,6 +107,36 @@ METHOD int pin_setflags { }; # +# Simultaneously read and/or change up to 32 adjacent pins. +# If the device cannot change the pins simultaneously, returns EOPNOTSUPP. +# +# More details about using this interface can be found in sys/gpio.h +# +METHOD int pin_access_32 { + device_t dev; + device_t child; + uint32_t first_pin; + uint32_t clear_pins; + uint32_t change_pins; + uint32_t *orig_pins; +}; + +# +# Simultaneously configure up to 32 adjacent pins. +# This is intended to change the configuration of all the pins simultaneously, +# but unlike pin_access_32, this will not fail if the hardware can't do so. +# +# More details about using this interface can be found in sys/gpio.h +# +METHOD int pin_config_32 { + device_t dev; + device_t child; + uint32_t first_pin; + uint32_t num_pins; + uint32_t *pin_flags; +}; + +# # Get the pin name # METHOD int pin_getname { diff --git a/sys/dev/gpio/gpiobus_internal.h b/sys/dev/gpio/gpiobus_internal.h index c198e5f79989..58f862343403 100644 --- a/sys/dev/gpio/gpiobus_internal.h +++ b/sys/dev/gpio/gpiobus_internal.h @@ -44,6 +44,7 @@ int gpiobus_acquire_pin(device_t, uint32_t); void gpiobus_release_pin(device_t, uint32_t); int gpiobus_child_location(device_t, device_t, struct sbuf *); device_t gpiobus_add_child_common(device_t, u_int, const char *, int, size_t); +int gpiobus_add_gpioc(device_t); extern driver_t gpiobus_driver; #endif diff --git a/sys/dev/gpio/gpioc.c b/sys/dev/gpio/gpioc.c index 87fed38ebe3e..5a60f939dc78 100644 --- a/sys/dev/gpio/gpioc.c +++ b/sys/dev/gpio/gpioc.c @@ -45,7 +45,6 @@ #include <dev/gpio/gpiobusvar.h> -#include "gpio_if.h" #include "gpiobus_if.h" #undef GPIOC_DEBUG @@ -59,7 +58,7 @@ struct gpioc_softc { device_t sc_dev; /* gpiocX dev */ - device_t sc_pdev; /* gpioX dev */ + device_t sc_pdev; /* gpiobusX dev */ struct cdev *sc_ctl_dev; /* controller device */ int sc_unit; int sc_npins; @@ -69,6 +68,7 @@ struct gpioc_softc { struct gpioc_pin_intr { struct gpioc_softc *sc; gpio_pin_t pin; + uint32_t intr_mode; bool config_locked; int intr_rid; struct resource *intr_res; @@ -112,8 +112,10 @@ struct gpioc_pin_event { static MALLOC_DEFINE(M_GPIOC, "gpioc", "gpioc device data"); -static int gpioc_allocate_pin_intr(struct gpioc_pin_intr*, uint32_t); -static int gpioc_release_pin_intr(struct gpioc_pin_intr*); +static int gpioc_allocate_pin_intr(struct gpioc_softc*, + struct gpioc_pin_intr*, uint32_t, uint32_t); +static int gpioc_release_pin_intr(struct gpioc_softc*, + struct gpioc_pin_intr*); static int gpioc_attach_priv_pin(struct gpioc_cdevpriv*, struct gpioc_pin_intr*); static int gpioc_detach_priv_pin(struct gpioc_cdevpriv*, @@ -191,27 +193,36 @@ number_of_events(struct gpioc_cdevpriv *priv) } static int -gpioc_allocate_pin_intr(struct gpioc_pin_intr *intr_conf, uint32_t flags) +gpioc_allocate_pin_intr(struct gpioc_softc *sc, + struct gpioc_pin_intr *intr_conf, uint32_t pin, uint32_t flags) { int err; intr_conf->config_locked = true; mtx_unlock(&intr_conf->mtx); - intr_conf->intr_res = gpio_alloc_intr_resource(intr_conf->pin->dev, + MPASS(intr_conf->pin == NULL); + err = gpio_pin_get_by_bus_pinnum(sc->sc_pdev, pin, &intr_conf->pin); + if (err != 0) + goto error_exit; + + intr_conf->intr_res = gpio_alloc_intr_resource(sc->sc_dev, &intr_conf->intr_rid, RF_ACTIVE, intr_conf->pin, flags); if (intr_conf->intr_res == NULL) { err = ENXIO; - goto error_exit; + goto error_pin; } - err = bus_setup_intr(intr_conf->pin->dev, intr_conf->intr_res, + err = bus_setup_intr(sc->sc_dev, intr_conf->intr_res, INTR_TYPE_MISC | INTR_MPSAFE, NULL, gpioc_interrupt_handler, intr_conf, &intr_conf->intr_cookie); - if (err != 0) - goto error_exit; + if (err != 0) { + bus_release_resource(sc->sc_dev, intr_conf->intr_res); + intr_conf->intr_res = NULL; + goto error_pin; + } - intr_conf->pin->flags = flags; + intr_conf->intr_mode = flags; error_exit: mtx_lock(&intr_conf->mtx); @@ -219,10 +230,15 @@ error_exit: wakeup(&intr_conf->config_locked); return (err); + +error_pin: + gpio_pin_release(intr_conf->pin); + intr_conf->pin = NULL; + goto error_exit; } static int -gpioc_release_pin_intr(struct gpioc_pin_intr *intr_conf) +gpioc_release_pin_intr(struct gpioc_softc *sc, struct gpioc_pin_intr *intr_conf) { int err; @@ -230,8 +246,8 @@ gpioc_release_pin_intr(struct gpioc_pin_intr *intr_conf) mtx_unlock(&intr_conf->mtx); if (intr_conf->intr_cookie != NULL) { - err = bus_teardown_intr(intr_conf->pin->dev, - intr_conf->intr_res, intr_conf->intr_cookie); + err = bus_teardown_intr(sc->sc_dev, intr_conf->intr_res, + intr_conf->intr_cookie); if (err != 0) goto error_exit; else @@ -239,7 +255,7 @@ gpioc_release_pin_intr(struct gpioc_pin_intr *intr_conf) } if (intr_conf->intr_res != NULL) { - err = bus_release_resource(intr_conf->pin->dev, SYS_RES_IRQ, + err = bus_release_resource(sc->sc_dev, SYS_RES_IRQ, intr_conf->intr_rid, intr_conf->intr_res); if (err != 0) goto error_exit; @@ -249,7 +265,10 @@ gpioc_release_pin_intr(struct gpioc_pin_intr *intr_conf) } } - intr_conf->pin->flags = 0; + gpio_pin_release(intr_conf->pin); + intr_conf->pin = NULL; + + intr_conf->intr_mode = 0; err = 0; error_exit: @@ -386,7 +405,7 @@ gpioc_get_intr_config(struct gpioc_softc *sc, struct gpioc_cdevpriv *priv, struct gpioc_privs *priv_link; uint32_t flags; - flags = intr_conf->pin->flags; + flags = intr_conf->intr_mode; if (flags == 0) return (0); @@ -411,7 +430,7 @@ gpioc_set_intr_config(struct gpioc_softc *sc, struct gpioc_cdevpriv *priv, int res; res = 0; - if (intr_conf->pin->flags == 0 && flags == 0) { + if (intr_conf->intr_mode == 0 && flags == 0) { /* No interrupt configured and none requested: Do nothing. */ return (0); } @@ -419,17 +438,17 @@ gpioc_set_intr_config(struct gpioc_softc *sc, struct gpioc_cdevpriv *priv, while (intr_conf->config_locked == true) mtx_sleep(&intr_conf->config_locked, &intr_conf->mtx, 0, "gpicfg", 0); - if (intr_conf->pin->flags == 0 && flags != 0) { + if (intr_conf->intr_mode == 0 && flags != 0) { /* * No interrupt is configured, but one is requested: Allocate * and setup interrupt on the according pin. */ - res = gpioc_allocate_pin_intr(intr_conf, flags); + res = gpioc_allocate_pin_intr(sc, intr_conf, pin, flags); if (res == 0) res = gpioc_attach_priv_pin(priv, intr_conf); if (res == EEXIST) res = 0; - } else if (intr_conf->pin->flags == flags) { + } else if (intr_conf->intr_mode == flags) { /* * Same interrupt requested as already configured: Attach the * cdevpriv to the corresponding pin. @@ -437,14 +456,14 @@ gpioc_set_intr_config(struct gpioc_softc *sc, struct gpioc_cdevpriv *priv, res = gpioc_attach_priv_pin(priv, intr_conf); if (res == EEXIST) res = 0; - } else if (intr_conf->pin->flags != 0 && flags == 0) { + } else if (intr_conf->intr_mode != 0 && flags == 0) { /* * Interrupt configured, but none requested: Teardown and * release the pin when no other cdevpriv is attached. Otherwise * just detach pin and cdevpriv from each other. */ if (gpioc_intr_reconfig_allowed(priv, intr_conf)) { - res = gpioc_release_pin_intr(intr_conf); + res = gpioc_release_pin_intr(sc, intr_conf); } if (res == 0) res = gpioc_detach_priv_pin(priv, intr_conf); @@ -456,9 +475,10 @@ gpioc_set_intr_config(struct gpioc_softc *sc, struct gpioc_cdevpriv *priv, if (!gpioc_intr_reconfig_allowed(priv, intr_conf)) res = EBUSY; else { - res = gpioc_release_pin_intr(intr_conf); + res = gpioc_release_pin_intr(sc, intr_conf); if (res == 0) - res = gpioc_allocate_pin_intr(intr_conf, flags); + res = gpioc_allocate_pin_intr(sc, intr_conf, + pin, flags); if (res == 0) res = gpioc_attach_priv_pin(priv, intr_conf); if (res == EEXIST) @@ -475,18 +495,16 @@ gpioc_interrupt_handler(void *arg) { struct gpioc_pin_intr *intr_conf; struct gpioc_privs *privs; - struct gpioc_softc *sc; sbintime_t evtime; - uint32_t pin_state; + bool pin_state; intr_conf = arg; - sc = intr_conf->sc; /* Capture time and pin state first. */ evtime = sbinuptime(); - if (intr_conf->pin->flags & GPIO_INTR_EDGE_BOTH) - GPIO_PIN_GET(sc->sc_pdev, intr_conf->pin->pin, &pin_state); - else if (intr_conf->pin->flags & GPIO_INTR_EDGE_RISING) + if (intr_conf->intr_mode & GPIO_INTR_EDGE_BOTH) + gpio_pin_is_active(intr_conf->pin, &pin_state); + else if (intr_conf->intr_mode & GPIO_INTR_EDGE_RISING) pin_state = true; else pin_state = false; @@ -575,18 +593,11 @@ gpioc_attach(device_t dev) sc->sc_pdev = device_get_parent(dev); sc->sc_unit = device_get_unit(dev); - err = GPIO_PIN_MAX(sc->sc_pdev, &sc->sc_npins); - sc->sc_npins++; /* Number of pins is one more than max pin number. */ - if (err != 0) - return (err); + sc->sc_npins = gpiobus_get_npins(dev); sc->sc_pin_intr = malloc(sizeof(struct gpioc_pin_intr) * sc->sc_npins, M_GPIOC, M_WAITOK | M_ZERO); for (int i = 0; i < sc->sc_npins; i++) { - sc->sc_pin_intr[i].pin = malloc(sizeof(struct gpiobus_pin), - M_GPIOC, M_WAITOK | M_ZERO); sc->sc_pin_intr[i].sc = sc; - sc->sc_pin_intr[i].pin->pin = i; - sc->sc_pin_intr[i].pin->dev = sc->sc_pdev; mtx_init(&sc->sc_pin_intr[i].mtx, "gpioc pin", NULL, MTX_DEF); SLIST_INIT(&sc->sc_pin_intr[i].privs); } @@ -610,20 +621,16 @@ static int gpioc_detach(device_t dev) { struct gpioc_softc *sc = device_get_softc(dev); - int err; if (sc->sc_ctl_dev) destroy_dev(sc->sc_ctl_dev); for (int i = 0; i < sc->sc_npins; i++) { mtx_destroy(&sc->sc_pin_intr[i].mtx); - free(sc->sc_pin_intr[i].pin, M_GPIOC); + MPASS(sc->sc_pin_intr[i].pin == NULL); } free(sc->sc_pin_intr, M_GPIOC); - if ((err = bus_generic_detach(dev)) != 0) - return (err); - return (0); } @@ -655,7 +662,7 @@ gpioc_cdevpriv_dtor(void *data) KASSERT(consistency == 1, ("inconsistent links between pin config and cdevpriv")); if (gpioc_intr_reconfig_allowed(priv, pin_link->pin)) { - gpioc_release_pin_intr(pin_link->pin); + gpioc_release_pin_intr(priv->sc, pin_link->pin); } mtx_unlock(&pin_link->pin->mtx); SLIST_REMOVE(&priv->pins, pin_link, gpioc_pins, next); @@ -778,7 +785,6 @@ static int gpioc_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int fflag, struct thread *td) { - device_t bus; int max_pin, res; struct gpioc_softc *sc = cdev->si_drv1; struct gpioc_cdevpriv *priv; @@ -789,30 +795,32 @@ gpioc_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int fflag, struct gpio_event_config *evcfg; uint32_t caps, intrflags; - bus = GPIO_GET_BUS(sc->sc_pdev); - if (bus == NULL) - return (EINVAL); switch (cmd) { case GPIOMAXPIN: - max_pin = -1; - res = GPIO_PIN_MAX(sc->sc_pdev, &max_pin); + res = 0; + max_pin = sc->sc_npins - 1; bcopy(&max_pin, arg, sizeof(max_pin)); break; case GPIOGETCONFIG: bcopy(arg, &pin, sizeof(pin)); dprintf("get config pin %d\n", pin.gp_pin); - res = GPIO_PIN_GETFLAGS(sc->sc_pdev, pin.gp_pin, + res = GPIOBUS_PIN_GETFLAGS(sc->sc_pdev, sc->sc_dev, pin.gp_pin, &pin.gp_flags); /* Fail early */ - if (res) + if (res != 0) break; res = devfs_get_cdevpriv((void **)&priv); - if (res) + if (res != 0) break; pin.gp_flags |= gpioc_get_intr_config(sc, priv, pin.gp_pin); - GPIO_PIN_GETCAPS(sc->sc_pdev, pin.gp_pin, &pin.gp_caps); - GPIOBUS_PIN_GETNAME(bus, pin.gp_pin, pin.gp_name); + res = GPIOBUS_PIN_GETCAPS(sc->sc_pdev, sc->sc_dev, pin.gp_pin, + &pin.gp_caps); + if (res != 0) + break; + res = GPIOBUS_PIN_GETNAME(sc->sc_pdev, pin.gp_pin, pin.gp_name); + if (res != 0) + break; bcopy(&pin, arg, sizeof(pin)); break; case GPIOSETCONFIG: @@ -821,7 +829,8 @@ gpioc_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int fflag, res = devfs_get_cdevpriv((void **)&priv); if (res != 0) break; - res = GPIO_PIN_GETCAPS(sc->sc_pdev, pin.gp_pin, &caps); + res = GPIOBUS_PIN_GETCAPS(sc->sc_pdev, sc->sc_dev, + pin.gp_pin, &caps); if (res != 0) break; res = gpio_check_flags(caps, pin.gp_flags); @@ -847,8 +856,8 @@ gpioc_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int fflag, } if (res != 0) break; - res = GPIO_PIN_SETFLAGS(sc->sc_pdev, pin.gp_pin, - (pin.gp_flags & ~GPIO_INTR_MASK)); + res = GPIOBUS_PIN_SETFLAGS(sc->sc_pdev, sc->sc_dev, pin.gp_pin, + pin.gp_flags & ~GPIO_INTR_MASK); if (res != 0) break; res = gpioc_set_intr_config(sc, priv, pin.gp_pin, @@ -856,40 +865,43 @@ gpioc_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int fflag, break; case GPIOGET: bcopy(arg, &req, sizeof(req)); - res = GPIO_PIN_GET(sc->sc_pdev, req.gp_pin, + res = GPIOBUS_PIN_GET(sc->sc_pdev, sc->sc_dev, req.gp_pin, &req.gp_value); - dprintf("read pin %d -> %d\n", + if (res != 0) + break; + dprintf("read pin %d -> %d\n", req.gp_pin, req.gp_value); bcopy(&req, arg, sizeof(req)); break; case GPIOSET: bcopy(arg, &req, sizeof(req)); - res = GPIO_PIN_SET(sc->sc_pdev, req.gp_pin, + res = GPIOBUS_PIN_SET(sc->sc_pdev, sc->sc_dev, req.gp_pin, req.gp_value); - dprintf("write pin %d -> %d\n", + dprintf("write pin %d -> %d\n", req.gp_pin, req.gp_value); break; case GPIOTOGGLE: bcopy(arg, &req, sizeof(req)); - dprintf("toggle pin %d\n", + dprintf("toggle pin %d\n", req.gp_pin); - res = GPIO_PIN_TOGGLE(sc->sc_pdev, req.gp_pin); + res = GPIOBUS_PIN_TOGGLE(sc->sc_pdev, sc->sc_dev, req.gp_pin); break; case GPIOSETNAME: bcopy(arg, &pin, sizeof(pin)); dprintf("set name on pin %d\n", pin.gp_pin); - res = GPIOBUS_PIN_SETNAME(bus, pin.gp_pin, + res = GPIOBUS_PIN_SETNAME(sc->sc_pdev, pin.gp_pin, pin.gp_name); break; case GPIOACCESS32: a32 = (struct gpio_access_32 *)arg; - res = GPIO_PIN_ACCESS_32(sc->sc_pdev, a32->first_pin, - a32->clear_pins, a32->change_pins, &a32->orig_pins); + res = GPIOBUS_PIN_ACCESS_32(sc->sc_pdev, sc->sc_dev, + a32->first_pin, a32->clear_pins, a32->change_pins, + &a32->orig_pins); break; case GPIOCONFIG32: c32 = (struct gpio_config_32 *)arg; - res = GPIO_PIN_CONFIG_32(sc->sc_pdev, c32->first_pin, - c32->num_pins, c32->pin_flags); + res = GPIOBUS_PIN_CONFIG_32(sc->sc_pdev, sc->sc_dev, + c32->first_pin, c32->num_pins, c32->pin_flags); break; case GPIOCONFIGEVENTS: evcfg = (struct gpio_event_config *)arg; @@ -1050,9 +1062,6 @@ static device_method_t gpioc_methods[] = { DEVMETHOD(device_probe, gpioc_probe), DEVMETHOD(device_attach, gpioc_attach), DEVMETHOD(device_detach, gpioc_detach), - DEVMETHOD(device_shutdown, bus_generic_shutdown), - DEVMETHOD(device_suspend, bus_generic_suspend), - DEVMETHOD(device_resume, bus_generic_resume), DEVMETHOD_END }; @@ -1063,5 +1072,5 @@ driver_t gpioc_driver = { sizeof(struct gpioc_softc) }; -DRIVER_MODULE(gpioc, gpio, gpioc_driver, 0, 0); +DRIVER_MODULE(gpioc, gpiobus, gpioc_driver, 0, 0); MODULE_VERSION(gpioc, 1); diff --git a/sys/dev/gpio/ofw_gpiobus.c b/sys/dev/gpio/ofw_gpiobus.c index b12b78fac18c..da1bfbc268b8 100644 --- a/sys/dev/gpio/ofw_gpiobus.c +++ b/sys/dev/gpio/ofw_gpiobus.c @@ -426,6 +426,9 @@ ofw_gpiobus_attach(device_t dev) err = gpiobus_init_softc(dev); if (err != 0) return (err); + err = gpiobus_add_gpioc(dev); + if (err != 0) + return (err); bus_identify_children(dev); bus_enumerate_hinted_children(dev); /* diff --git a/sys/dev/hid/hkbd.c b/sys/dev/hid/hkbd.c index 86a2320092be..6255c42d3b62 100644 --- a/sys/dev/hid/hkbd.c +++ b/sys/dev/hid/hkbd.c @@ -1828,7 +1828,7 @@ hkbd_set_leds(struct hkbd_softc *sc, uint8_t leds) SYSCONS_UNLOCK(); error = hid_write(sc->sc_dev, buf, len); SYSCONS_LOCK(); - DPRINTF(("error %d", error)); + DPRINTF("error %d", error); return (error); } diff --git a/sys/dev/hpt27xx/hptintf.h b/sys/dev/hpt27xx/hptintf.h index 558b479ec2ee..eb8105ec5666 100644 --- a/sys/dev/hpt27xx/hptintf.h +++ b/sys/dev/hpt27xx/hptintf.h @@ -155,8 +155,8 @@ typedef HPT_U32 DEVICEID; #define ARRAY_FLAG_NEED_AUTOREBUILD 0x00000080 /* auto-rebuild should start */ #define ARRAY_FLAG_VERIFYING 0x00000100 /* is being verified */ #define ARRAY_FLAG_INITIALIZING 0x00000200 /* is being initialized */ -#define ARRAY_FLAG_TRANSFORMING 0x00000400 /* tranform in progress */ -#define ARRAY_FLAG_NEEDTRANSFORM 0x00000800 /* array need tranform */ +#define ARRAY_FLAG_TRANSFORMING 0x00000400 /* transform in progress */ +#define ARRAY_FLAG_NEEDTRANSFORM 0x00000800 /* array need transform */ #define ARRAY_FLAG_NEEDINITIALIZING 0x00001000 /* the array's initialization hasn't finished*/ #define ARRAY_FLAG_BROKEN_REDUNDANT 0x00002000 /* broken but redundant (raid6) */ #define ARRAY_FLAG_RAID15PLUS 0x80000000 /* display this RAID 1 as RAID 1.5 */ @@ -2018,7 +2018,7 @@ DEVICEID hpt_create_transform_v2(DEVICEID idArray, PCREATE_ARRAY_PARAMS_V3 destI #endif /* hpt_step_transform - * move a block in a tranform progress. + * move a block in a transform progress. * This function is called by mid-layer, not GUI (which uses set_array_state instead). * Version compatibility: v2.0.0.0 or later * Parameters: diff --git a/sys/dev/ice/ice_fw_logging.c b/sys/dev/ice/ice_fw_logging.c index 0025a65d73fc..16a9ab6823bf 100644 --- a/sys/dev/ice/ice_fw_logging.c +++ b/sys/dev/ice/ice_fw_logging.c @@ -48,7 +48,7 @@ SDT_PROVIDER_DEFINE(ice_fwlog); /* * SDT DTrace probe fired when a firmware log message is received over the - * AdminQ. It passes the buffer of the firwmare log message along with its + * AdminQ. It passes the buffer of the firmware log message along with its * length in bytes to the DTrace framework. */ SDT_PROBE_DEFINE2(ice_fwlog, , , message, "uint8_t *", "int"); diff --git a/sys/dev/ichwd/i6300esbwd.c b/sys/dev/ichwd/i6300esbwd.c new file mode 100644 index 000000000000..d95aeb53c3f5 --- /dev/null +++ b/sys/dev/ichwd/i6300esbwd.c @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2025 The FreeBSD Foundation + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +/* + * Reference: Intel 6300ESB Controller Hub Datasheet Section 16 + */ + +#include <sys/param.h> +#include <sys/eventhandler.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/sysctl.h> +#include <sys/errno.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <machine/bus.h> +#include <sys/rman.h> +#include <machine/resource.h> +#include <sys/watchdog.h> + +#include <dev/pci/pcireg.h> + +#include <dev/ichwd/ichwd.h> +#include <dev/ichwd/i6300esbwd.h> + +#include <x86/pci_cfgreg.h> +#include <dev/pci/pcivar.h> +#include <dev/pci/pci_private.h> + +struct i6300esbwd_softc { + device_t dev; + int res_id; + struct resource *res; + eventhandler_tag ev_tag; + bool locked; +}; + +static const struct i6300esbwd_pci_id { + uint16_t id; + const char *name; +} i6300esbwd_pci_devices[] = { + { DEVICEID_6300ESB_2, "6300ESB Watchdog Timer" }, +}; + +static uint16_t +i6300esbwd_cfg_read(struct i6300esbwd_softc *sc) +{ + return (pci_read_config(sc->dev, WDT_CONFIG_REG, 2)); +} + +static void +i6300esbwd_cfg_write(struct i6300esbwd_softc *sc, uint16_t val) +{ + pci_write_config(sc->dev, WDT_CONFIG_REG, val, 2); +} + +static uint8_t +i6300esbwd_lock_read(struct i6300esbwd_softc *sc) +{ + return (pci_read_config(sc->dev, WDT_LOCK_REG, 1)); +} + +static void +i6300esbwd_lock_write(struct i6300esbwd_softc *sc, uint8_t val) +{ + pci_write_config(sc->dev, WDT_LOCK_REG, val, 1); +} + +/* + * According to Intel 6300ESB I/O Controller Hub Datasheet 16.5.2, + * the resource should be unlocked before modifing any registers. + * The way to unlock is by write 0x80, 0x86 to the reload register. + */ +static void +i6300esbwd_unlock_res(struct i6300esbwd_softc *sc) +{ + bus_write_2(sc->res, WDT_RELOAD_REG, WDT_UNLOCK_SEQ_1_VAL); + bus_write_2(sc->res, WDT_RELOAD_REG, WDT_UNLOCK_SEQ_2_VAL); +} + +static int +i6300esbwd_sysctl_locked(SYSCTL_HANDLER_ARGS) +{ + struct i6300esbwd_softc *sc = (struct i6300esbwd_softc *)arg1; + int error; + int result; + + result = sc->locked; + error = sysctl_handle_int(oidp, &result, 0, req); + + if (error || !req->newptr) + return (error); + + if (result == 1 && !sc->locked) { + i6300esbwd_lock_write(sc, i6300esbwd_lock_read(sc) | WDT_LOCK); + sc->locked = true; + } + + return (0); +} + +static void +i6300esbwd_event(void *arg, unsigned int cmd, int *error) +{ + struct i6300esbwd_softc *sc = arg; + uint32_t timeout; + uint16_t regval; + + cmd &= WD_INTERVAL; + if (cmd != 0 && + (cmd < WD_TO_1MS || (cmd - WD_TO_1MS) >= WDT_PRELOAD_BIT)) { + *error = EINVAL; + return; + } + timeout = 1 << (cmd - WD_TO_1MS); + + /* reset the timer to prevent timeout a timeout is about to occur */ + i6300esbwd_unlock_res(sc); + bus_write_2(sc->res, WDT_RELOAD_REG, WDT_RELOAD); + + if (!cmd) { + /* + * when the lock is enabled, we are unable to overwrite LOCK + * register + */ + if (sc->locked) + *error = EPERM; + else + i6300esbwd_lock_write(sc, + i6300esbwd_lock_read(sc) & ~WDT_ENABLE); + return; + } + + i6300esbwd_unlock_res(sc); + bus_write_4(sc->res, WDT_PRELOAD_1_REG, timeout); + + i6300esbwd_unlock_res(sc); + bus_write_4(sc->res, WDT_PRELOAD_2_REG, timeout); + + i6300esbwd_unlock_res(sc); + bus_write_2(sc->res, WDT_RELOAD_REG, WDT_RELOAD); + + if (!sc->locked) { + i6300esbwd_lock_write(sc, WDT_ENABLE); + regval = i6300esbwd_lock_read(sc); + sc->locked = regval & WDT_LOCK; + } +} + +static int +i6300esbwd_probe(device_t dev) +{ + const struct i6300esbwd_pci_id *pci_id; + uint16_t pci_dev_id; + int err = ENXIO; + + if (pci_get_vendor(dev) != VENDORID_INTEL) + goto end; + + pci_dev_id = pci_get_device(dev); + for (pci_id = i6300esbwd_pci_devices; + pci_id < i6300esbwd_pci_devices + nitems(i6300esbwd_pci_devices); + ++pci_id) { + if (pci_id->id == pci_dev_id) { + device_set_desc(dev, pci_id->name); + err = BUS_PROBE_DEFAULT; + break; + } + } + +end: + return (err); +} + +static int +i6300esbwd_attach(device_t dev) +{ + struct i6300esbwd_softc *sc = device_get_softc(dev); + uint16_t regval; + + sc->dev = dev; + sc->res_id = PCIR_BAR(0); + sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->res_id, + RF_ACTIVE); + if (sc->res == NULL) { + device_printf(dev, "unable to map memory region\n"); + return (ENXIO); + } + + i6300esbwd_cfg_write(sc, WDT_INT_TYPE_DISABLED_VAL); + regval = i6300esbwd_lock_read(sc); + if (regval & WDT_LOCK) + sc->locked = true; + else { + sc->locked = false; + i6300esbwd_lock_write(sc, WDT_TOUT_CNF_WT_MODE); + } + + i6300esbwd_unlock_res(sc); + bus_write_2(sc->res, WDT_RELOAD_REG, WDT_RELOAD | WDT_TIMEOUT); + + sc->ev_tag = EVENTHANDLER_REGISTER(watchdog_list, i6300esbwd_event, sc, + 0); + + SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), + SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "locked", + CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, sc, 0, + i6300esbwd_sysctl_locked, "I", + "Lock the timer so that we cannot disable it"); + + return (0); +} + +static int +i6300esbwd_detach(device_t dev) +{ + struct i6300esbwd_softc *sc = device_get_softc(dev); + + if (sc->ev_tag) + EVENTHANDLER_DEREGISTER(watchdog_list, sc->ev_tag); + + if (sc->res) + bus_release_resource(dev, SYS_RES_MEMORY, sc->res_id, sc->res); + + return (0); +} + +static device_method_t i6300esbwd_methods[] = { + DEVMETHOD(device_probe, i6300esbwd_probe), + DEVMETHOD(device_attach, i6300esbwd_attach), + DEVMETHOD(device_detach, i6300esbwd_detach), + DEVMETHOD(device_shutdown, i6300esbwd_detach), + DEVMETHOD_END +}; + +static driver_t i6300esbwd_driver = { + "i6300esbwd", + i6300esbwd_methods, + sizeof(struct i6300esbwd_softc), +}; + +DRIVER_MODULE(i6300esbwd, pci, i6300esbwd_driver, NULL, NULL); diff --git a/sys/dev/ichwd/i6300esbwd.h b/sys/dev/ichwd/i6300esbwd.h new file mode 100644 index 000000000000..39ed5d5a84f6 --- /dev/null +++ b/sys/dev/ichwd/i6300esbwd.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2025 The FreeBSD Foundation + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef _I6300ESBWD_H_ +#define _I6300ESBWD_H_ + +#define WDT_CONFIG_REG 0x60 +#define WDT_LOCK_REG 0x68 + +#define WDT_PRELOAD_1_REG 0x00 +#define WDT_PRELOAD_2_REG 0x04 +#define WDT_INTR_REG 0x08 +#define WDT_RELOAD_REG 0x0C + +/* For config register */ +#define WDT_OUTPUT_EN (0x1 << 5) +#define WDT_PRE_SEL (0x1 << 2) +#define WDT_INT_TYPE_BITS (0x3) +#define WDT_INT_TYPE_IRQ_VAL (0x0) +#define WDT_INT_TYPE_RES_VAL (0x1) +#define WDT_INT_TYPE_SMI_VAL (0x2) +#define WDT_INT_TYPE_DISABLED_VAL (0x3) + +/* For lock register */ +#define WDT_TOUT_CNF_WT_MODE (0x0 << 2) +#define WDT_TOUT_CNF_FR_MODE (0x1 << 2) +#define WDT_ENABLE (0x02) +#define WDT_LOCK (0x01) + +/* For preload 1/2 registers */ +#define WDT_PRELOAD_BIT 20 +#define WDT_PRELOAD_BITS ((0x1 << WDT_PRELOAD_BIT) - 1) + +/* For interrupt register */ +#define WDT_INTR_ACT (0x01 << 0) + +/* For reload register */ +#define WDT_TIMEOUT (0x01 << 9) +#define WDT_RELOAD (0x01 << 8) +#define WDT_UNLOCK_SEQ_1_VAL 0x80 +#define WDT_UNLOCK_SEQ_2_VAL 0x86 + +#endif /* _I6300ESBWD_H_ */ diff --git a/sys/dev/ichwd/ichwd.c b/sys/dev/ichwd/ichwd.c index cade2cc4fb45..5481553cc175 100644 --- a/sys/dev/ichwd/ichwd.c +++ b/sys/dev/ichwd/ichwd.c @@ -90,7 +90,7 @@ static struct ichwd_device ichwd_devices[] = { { DEVICEID_82801E, "Intel 82801E watchdog timer", 5, 1 }, { DEVICEID_82801EB, "Intel 82801EB watchdog timer", 5, 1 }, { DEVICEID_82801EBR, "Intel 82801EB/ER watchdog timer", 5, 1 }, - { DEVICEID_6300ESB, "Intel 6300ESB watchdog timer", 5, 1 }, + { DEVICEID_6300ESB_1, "Intel 6300ESB watchdog timer", 5, 1 }, { DEVICEID_82801FBR, "Intel 82801FB/FR watchdog timer", 6, 2 }, { DEVICEID_ICH6M, "Intel ICH6M watchdog timer", 6, 2 }, { DEVICEID_ICH6W, "Intel ICH6W watchdog timer", 6, 2 }, diff --git a/sys/dev/ichwd/ichwd.h b/sys/dev/ichwd/ichwd.h index 90fda08b74c1..72d0ca1cd6aa 100644 --- a/sys/dev/ichwd/ichwd.h +++ b/sys/dev/ichwd/ichwd.h @@ -151,7 +151,8 @@ struct ichwd_softc { #define DEVICEID_82801E 0x2450 #define DEVICEID_82801EB 0x24dc #define DEVICEID_82801EBR 0x24d0 -#define DEVICEID_6300ESB 0x25a1 +#define DEVICEID_6300ESB_1 0x25a1 +#define DEVICEID_6300ESB_2 0x25ab #define DEVICEID_82801FBR 0x2640 #define DEVICEID_ICH6M 0x2641 #define DEVICEID_ICH6W 0x2642 diff --git a/sys/dev/iwx/if_iwx.c b/sys/dev/iwx/if_iwx.c index d60ef1874a6c..1fe531d69933 100644 --- a/sys/dev/iwx/if_iwx.c +++ b/sys/dev/iwx/if_iwx.c @@ -5673,6 +5673,10 @@ iwx_tx(struct iwx_softc *sc, struct mbuf *m, struct ieee80211_node *ni) if (rinfo == NULL) return EINVAL; + /* Offloaded sequence number assignment */ + /* Note: Should be done in firmware on all supported devices */ + + /* Radiotap */ if (ieee80211_radiotap_active_vap(vap)) { struct iwx_tx_radiotap_header *tap = &sc->sc_txtap; @@ -5685,6 +5689,7 @@ iwx_tx(struct iwx_softc *sc, struct mbuf *m, struct ieee80211_node *ni) ieee80211_radiotap_tx(vap, m); } + /* Encrypt - CCMP via direct HW path, TKIP/WEP indirected openbsd-style for now */ if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { k = ieee80211_crypto_get_txkey(ni, m); if (k == NULL) { @@ -10467,6 +10472,8 @@ iwx_attach(device_t dev) IEEE80211_C_BGSCAN /* capable of bg scanning */ ; ic->ic_flags_ext = IEEE80211_FEXT_SCAN_OFFLOAD; + /* Enable seqno offload */ + ic->ic_flags_ext |= IEEE80211_FEXT_SEQNO_OFFLOAD; ic->ic_txstream = 2; ic->ic_rxstream = 2; diff --git a/sys/dev/mwl/if_mwl.c b/sys/dev/mwl/if_mwl.c index 2570cbce525b..0e2eb0b2d8fe 100644 --- a/sys/dev/mwl/if_mwl.c +++ b/sys/dev/mwl/if_mwl.c @@ -1797,7 +1797,7 @@ mwl_updateslot(struct ieee80211com *ic) return; /* - * Calculate the ERP flags. The firwmare will use + * Calculate the ERP flags. The firmware will use * this to carry out the appropriate measures. */ prot = 0; diff --git a/sys/dev/nvme/nvme.c b/sys/dev/nvme/nvme.c index 84f365024f13..ead91f0d01fe 100644 --- a/sys/dev/nvme/nvme.c +++ b/sys/dev/nvme/nvme.c @@ -295,7 +295,6 @@ nvme_register_consumer(nvme_cons_ns_fn_t ns_fn, nvme_cons_ctrlr_fn_t ctrlr_fn, void nvme_unregister_consumer(struct nvme_consumer *consumer) { - consumer->id = INVALID_CONSUMER_ID; } diff --git a/sys/dev/nvme/nvme_ahci.c b/sys/dev/nvme/nvme_ahci.c index 888207a454f7..b06661226d34 100644 --- a/sys/dev/nvme/nvme_ahci.c +++ b/sys/dev/nvme/nvme_ahci.c @@ -124,6 +124,5 @@ bad: static int nvme_ahci_detach(device_t dev) { - return (nvme_detach(dev)); } diff --git a/sys/dev/nvme/nvme_ctrlr.c b/sys/dev/nvme/nvme_ctrlr.c index fd7f00ced14b..49960b0f920a 100644 --- a/sys/dev/nvme/nvme_ctrlr.c +++ b/sys/dev/nvme/nvme_ctrlr.c @@ -597,7 +597,6 @@ nvme_ctrlr_construct_namespaces(struct nvme_controller *ctrlr) static bool is_log_page_id_valid(uint8_t page_id) { - switch (page_id) { case NVME_LOG_ERROR: case NVME_LOG_HEALTH_INFORMATION: @@ -653,7 +652,6 @@ static void nvme_ctrlr_log_critical_warnings(struct nvme_controller *ctrlr, uint8_t state) { - if (state & NVME_CRIT_WARN_ST_AVAILABLE_SPARE) nvme_printf(ctrlr, "SMART WARNING: available spare space below threshold\n"); @@ -781,7 +779,6 @@ nvme_ctrlr_configure_aer(struct nvme_controller *ctrlr) static void nvme_ctrlr_configure_int_coalescing(struct nvme_controller *ctrlr) { - ctrlr->int_coal_time = 0; TUNABLE_INT_FETCH("hw.nvme.int_coal_time", &ctrlr->int_coal_time); @@ -1420,8 +1417,8 @@ nvme_ctrlr_linux_passthru_cmd(struct nvme_controller *ctrlr, req->cmd.opc = npc->opcode; req->cmd.fuse = npc->flags; - req->cmd.rsvd2 = htole16(npc->cdw2); - req->cmd.rsvd3 = htole16(npc->cdw3); + req->cmd.rsvd2 = htole32(npc->cdw2); + req->cmd.rsvd3 = htole32(npc->cdw3); req->cmd.cdw10 = htole32(npc->cdw10); req->cmd.cdw11 = htole32(npc->cdw11); req->cmd.cdw12 = htole32(npc->cdw12); @@ -1776,7 +1773,6 @@ void nvme_ctrlr_submit_admin_request(struct nvme_controller *ctrlr, struct nvme_request *req) { - nvme_qpair_submit_request(&ctrlr->adminq, req); } @@ -1793,14 +1789,12 @@ nvme_ctrlr_submit_io_request(struct nvme_controller *ctrlr, device_t nvme_ctrlr_get_device(struct nvme_controller *ctrlr) { - return (ctrlr->dev); } const struct nvme_controller_data * nvme_ctrlr_get_data(struct nvme_controller *ctrlr) { - return (&ctrlr->cdata); } @@ -1853,7 +1847,6 @@ nvme_ctrlr_suspend(struct nvme_controller *ctrlr) int nvme_ctrlr_resume(struct nvme_controller *ctrlr) { - /* * Can't touch failed controllers, so nothing to do to resume. */ diff --git a/sys/dev/nvme/nvme_ctrlr_cmd.c b/sys/dev/nvme/nvme_ctrlr_cmd.c index 993a7718356d..5a44ed425acb 100644 --- a/sys/dev/nvme/nvme_ctrlr_cmd.c +++ b/sys/dev/nvme/nvme_ctrlr_cmd.c @@ -281,7 +281,6 @@ nvme_ctrlr_cmd_get_error_page(struct nvme_controller *ctrlr, struct nvme_error_information_entry *payload, uint32_t num_entries, nvme_cb_fn_t cb_fn, void *cb_arg) { - KASSERT(num_entries > 0, ("%s called with num_entries==0\n", __func__)); /* Controller's error log page entries is 0-based. */ @@ -302,7 +301,6 @@ nvme_ctrlr_cmd_get_health_information_page(struct nvme_controller *ctrlr, uint32_t nsid, struct nvme_health_information_page *payload, nvme_cb_fn_t cb_fn, void *cb_arg) { - nvme_ctrlr_cmd_get_log_page(ctrlr, NVME_LOG_HEALTH_INFORMATION, nsid, payload, sizeof(*payload), cb_fn, cb_arg); } @@ -311,7 +309,6 @@ void nvme_ctrlr_cmd_get_firmware_page(struct nvme_controller *ctrlr, struct nvme_firmware_page *payload, nvme_cb_fn_t cb_fn, void *cb_arg) { - nvme_ctrlr_cmd_get_log_page(ctrlr, NVME_LOG_FIRMWARE_SLOT, NVME_GLOBAL_NAMESPACE_TAG, payload, sizeof(*payload), cb_fn, cb_arg); diff --git a/sys/dev/nvme/nvme_ns.c b/sys/dev/nvme/nvme_ns.c index 3f29382fe42f..e84d2066930e 100644 --- a/sys/dev/nvme/nvme_ns.c +++ b/sys/dev/nvme/nvme_ns.c @@ -129,7 +129,6 @@ static int nvme_ns_close(struct cdev *dev __unused, int flags, int fmt __unused, struct thread *td) { - return (0); } @@ -231,7 +230,6 @@ nvme_ns_get_model_number(struct nvme_namespace *ns) const struct nvme_namespace_data * nvme_ns_get_data(struct nvme_namespace *ns) { - return (&ns->data); } @@ -631,7 +629,6 @@ nvme_ns_construct(struct nvme_namespace *ns, uint32_t id, void nvme_ns_destruct(struct nvme_namespace *ns) { - if (ns->cdev != NULL) { if (ns->cdev->si_drv2 != NULL) destroy_dev(ns->cdev->si_drv2); diff --git a/sys/dev/nvme/nvme_pci.c b/sys/dev/nvme/nvme_pci.c index 29b49b7df403..c07a68d2f0dc 100644 --- a/sys/dev/nvme/nvme_pci.c +++ b/sys/dev/nvme/nvme_pci.c @@ -151,7 +151,6 @@ nvme_pci_probe (device_t device) static int nvme_ctrlr_allocate_bar(struct nvme_controller *ctrlr) { - ctrlr->resource_id = PCIR_BAR(0); ctrlr->resource = bus_alloc_resource_any(ctrlr->dev, SYS_RES_MEMORY, diff --git a/sys/dev/nvme/nvme_private.h b/sys/dev/nvme/nvme_private.h index 36f00fedc48e..52f9e12f8f9a 100644 --- a/sys/dev/nvme/nvme_private.h +++ b/sys/dev/nvme/nvme_private.h @@ -459,8 +459,7 @@ int nvme_detach(device_t dev); * vast majority of these without waiting for a tick plus scheduling delays. Since * these are on startup, this drastically reduces startup time. */ -static __inline -void +static __inline void nvme_completion_poll(struct nvme_completion_poll_status *status) { int timeout = ticks + 10 * hz; diff --git a/sys/dev/nvme/nvme_qpair.c b/sys/dev/nvme/nvme_qpair.c index bd8626e32209..4f2c44da3b4f 100644 --- a/sys/dev/nvme/nvme_qpair.c +++ b/sys/dev/nvme/nvme_qpair.c @@ -793,7 +793,6 @@ nvme_admin_qpair_destroy(struct nvme_qpair *qpair) void nvme_io_qpair_destroy(struct nvme_qpair *qpair) { - nvme_qpair_destroy(qpair); } @@ -1202,7 +1201,6 @@ _nvme_qpair_submit_request(struct nvme_qpair *qpair, struct nvme_request *req) void nvme_qpair_submit_request(struct nvme_qpair *qpair, struct nvme_request *req) { - mtx_lock(&qpair->lock); _nvme_qpair_submit_request(qpair, req); mtx_unlock(&qpair->lock); @@ -1226,7 +1224,6 @@ nvme_qpair_enable(struct nvme_qpair *qpair) void nvme_qpair_reset(struct nvme_qpair *qpair) { - qpair->sq_head = qpair->sq_tail = qpair->cq_head = 0; /* diff --git a/sys/dev/nvme/nvme_sim.c b/sys/dev/nvme/nvme_sim.c index 4974bb718222..a06774a64761 100644 --- a/sys/dev/nvme/nvme_sim.c +++ b/sys/dev/nvme/nvme_sim.c @@ -301,7 +301,6 @@ nvme_sim_action(struct cam_sim *sim, union ccb *ccb) static void nvme_sim_poll(struct cam_sim *sim) { - nvme_ctrlr_poll(sim2ctrlr(sim)); } diff --git a/sys/dev/nvme/nvme_sysctl.c b/sys/dev/nvme/nvme_sysctl.c index a5a44721f9f9..50d19e730a16 100644 --- a/sys/dev/nvme/nvme_sysctl.c +++ b/sys/dev/nvme/nvme_sysctl.c @@ -153,7 +153,6 @@ nvme_sysctl_timeout_period(SYSCTL_HANDLER_ARGS) static void nvme_qpair_reset_stats(struct nvme_qpair *qpair) { - /* * Reset the values. Due to sanity checks in * nvme_qpair_process_completions, we reset the number of interrupt diff --git a/sys/dev/nvmf/nvmf_tcp.c b/sys/dev/nvmf/nvmf_tcp.c index 6ad5229f6043..e50d7ff48d2b 100644 --- a/sys/dev/nvmf/nvmf_tcp.c +++ b/sys/dev/nvmf/nvmf_tcp.c @@ -970,7 +970,7 @@ nvmf_tcp_handle_r2t(struct nvmf_tcp_qpair *qp, struct nvmf_tcp_rxpdu *pdu) } /* - * XXX: The spec does not specify how to handle R2T tranfers + * XXX: The spec does not specify how to handle R2T transfers * out of range of the original command. */ data_len = le32toh(r2t->r2tl); diff --git a/sys/dev/puc/pucdata.c b/sys/dev/puc/pucdata.c index e911a407cca9..436af76001da 100644 --- a/sys/dev/puc/pucdata.c +++ b/sys/dev/puc/pucdata.c @@ -64,6 +64,7 @@ static puc_config_f puc_config_quatech; static puc_config_f puc_config_syba; static puc_config_f puc_config_siig; static puc_config_f puc_config_sunix; +static puc_config_f puc_config_systembase; static puc_config_f puc_config_timedia; static puc_config_f puc_config_titan; @@ -1705,6 +1706,23 @@ const struct puc_cfg puc_pci_devices[] = { PUC_PORT_4S, 0x10, 0, 8, .config_function = puc_config_icbook }, + + /* + * Systembase cards using SB16C1050 UARTs: + */ + { 0x14a1, 0x0008, 0x14a1, 0x0008, + "Systembase SB16C1058", + DEFAULT_RCLK * 8, + PUC_PORT_8S, 0x10, 0, 8, + .config_function = puc_config_systembase, + }, + { 0x14a1, 0x0004, 0x14a1, 0x0004, + "Systembase SB16C1054", + DEFAULT_RCLK * 8, + PUC_PORT_4S, 0x10, 0, 8, + .config_function = puc_config_systembase, + }, + { 0xffff, 0, 0xffff, 0, NULL, 0 } }; @@ -2294,3 +2312,28 @@ puc_config_titan(struct puc_softc *sc __unused, enum puc_cfg_cmd cmd, } return (ENXIO); } + +static int +puc_config_systembase(struct puc_softc *sc __unused, + enum puc_cfg_cmd cmd, int port, intptr_t *res) +{ + struct puc_bar *bar; + + switch (cmd) { + case PUC_CFG_SETUP: + bar = puc_get_bar(sc, 0x14); + if (bar == NULL) + return (ENXIO); + + /* + * The Systembase SB16C1058 (and probably other devices + * based on the SB16C1050 UART core) require poking a + * register in the *other* RID to turn on interrupts. + */ + bus_write_1(bar->b_res, /* OPT_IMRREG0 */ 0xc, 0xff); + return (0); + default: + break; + } + return (ENXIO); +} diff --git a/sys/dev/uart/uart_bus_pci.c b/sys/dev/uart/uart_bus_pci.c index 14ac213066b8..22af8ee8663c 100644 --- a/sys/dev/uart/uart_bus_pci.c +++ b/sys/dev/uart/uart_bus_pci.c @@ -141,6 +141,8 @@ static const struct pci_id pci_ns8250_ids[] = { 0x10, 16384000 }, { 0x1415, 0xc120, 0xffff, 0, "Oxford Semiconductor OXPCIe952 PCIe 16950 UART", 0x10 }, +{ 0x14a1, 0x0008, 0x14a1, 0x0008, "Systembase SB16C1058", + 0x10, 8 * DEFAULT_RCLK, }, { 0x14e4, 0x160a, 0xffff, 0, "Broadcom TruManage UART", 0x10, 128 * DEFAULT_RCLK, 2}, { 0x14e4, 0x4344, 0xffff, 0, "Sony Ericsson GC89 PC Card", 0x10}, diff --git a/sys/dev/usb/net/if_umb.c b/sys/dev/usb/net/if_umb.c index 5703bc03dd39..f640b4224aad 100644 --- a/sys/dev/usb/net/if_umb.c +++ b/sys/dev/usb/net/if_umb.c @@ -666,7 +666,7 @@ umb_ncm_setup(struct umb_softc *sc, struct usb_config * config) struct ncm_ntb_parameters np; usb_error_t error; - /* Query NTB tranfers sizes */ + /* Query NTB transfers sizes */ req.bmRequestType = UT_READ_CLASS_INTERFACE; req.bRequest = NCM_GET_NTB_PARAMETERS; USETW(req.wValue, 0); diff --git a/sys/dev/virtio/network/if_vtnet.c b/sys/dev/virtio/network/if_vtnet.c index ecb3dbb370e5..867da80a53a8 100644 --- a/sys/dev/virtio/network/if_vtnet.c +++ b/sys/dev/virtio/network/if_vtnet.c @@ -2551,8 +2551,10 @@ vtnet_txq_enqueue_buf(struct vtnet_txq *txq, struct mbuf **m_head, error = sglist_append_mbuf(sg, m); if (error) { m = m_defrag(m, M_NOWAIT); - if (m == NULL) + if (m == NULL) { + sc->vtnet_stats.tx_defrag_failed++; goto fail; + } *m_head = m; sc->vtnet_stats.tx_defragged++; @@ -2568,7 +2570,6 @@ vtnet_txq_enqueue_buf(struct vtnet_txq *txq, struct mbuf **m_head, return (error); fail: - sc->vtnet_stats.tx_defrag_failed++; m_freem(*m_head); *m_head = NULL; @@ -3813,9 +3814,9 @@ vtnet_rx_filter_mac(struct vtnet_softc *sc) if_printf(ifp, "error setting host MAC filter table\n"); out: - if (promisc != 0 && vtnet_set_promisc(sc, true) != 0) + if (promisc && vtnet_set_promisc(sc, true) != 0) if_printf(ifp, "cannot enable promiscuous mode\n"); - if (allmulti != 0 && vtnet_set_allmulti(sc, true) != 0) + if (allmulti && vtnet_set_allmulti(sc, true) != 0) if_printf(ifp, "cannot enable all-multicast mode\n"); } @@ -4100,21 +4101,29 @@ vtnet_setup_rxq_sysctl(struct sysctl_ctx_list *ctx, stats = &rxq->vtnrx_stats; - SYSCTL_ADD_UQUAD(ctx, list, OID_AUTO, "ipackets", CTLFLAG_RD, + SYSCTL_ADD_UQUAD(ctx, list, OID_AUTO, "ipackets", + CTLFLAG_RD | CTLFLAG_STATS, &stats->vrxs_ipackets, "Receive packets"); - SYSCTL_ADD_UQUAD(ctx, list, OID_AUTO, "ibytes", CTLFLAG_RD, + SYSCTL_ADD_UQUAD(ctx, list, OID_AUTO, "ibytes", + CTLFLAG_RD | CTLFLAG_STATS, &stats->vrxs_ibytes, "Receive bytes"); - SYSCTL_ADD_UQUAD(ctx, list, OID_AUTO, "iqdrops", CTLFLAG_RD, + SYSCTL_ADD_UQUAD(ctx, list, OID_AUTO, "iqdrops", + CTLFLAG_RD | CTLFLAG_STATS, &stats->vrxs_iqdrops, "Receive drops"); - SYSCTL_ADD_UQUAD(ctx, list, OID_AUTO, "ierrors", CTLFLAG_RD, + SYSCTL_ADD_UQUAD(ctx, list, OID_AUTO, "ierrors", + CTLFLAG_RD | CTLFLAG_STATS, &stats->vrxs_ierrors, "Receive errors"); - SYSCTL_ADD_UQUAD(ctx, list, OID_AUTO, "csum", CTLFLAG_RD, + SYSCTL_ADD_UQUAD(ctx, list, OID_AUTO, "csum", + CTLFLAG_RD | CTLFLAG_STATS, &stats->vrxs_csum, "Receive checksum offloaded"); - SYSCTL_ADD_UQUAD(ctx, list, OID_AUTO, "csum_failed", CTLFLAG_RD, + SYSCTL_ADD_UQUAD(ctx, list, OID_AUTO, "csum_failed", + CTLFLAG_RD | CTLFLAG_STATS, &stats->vrxs_csum_failed, "Receive checksum offload failed"); - SYSCTL_ADD_UQUAD(ctx, list, OID_AUTO, "host_lro", CTLFLAG_RD, + SYSCTL_ADD_UQUAD(ctx, list, OID_AUTO, "host_lro", + CTLFLAG_RD | CTLFLAG_STATS, &stats->vrxs_host_lro, "Receive host segmentation offloaded"); - SYSCTL_ADD_UQUAD(ctx, list, OID_AUTO, "rescheduled", CTLFLAG_RD, + SYSCTL_ADD_UQUAD(ctx, list, OID_AUTO, "rescheduled", + CTLFLAG_RD | CTLFLAG_STATS, &stats->vrxs_rescheduled, "Receive interrupt handler rescheduled"); } @@ -4135,17 +4144,23 @@ vtnet_setup_txq_sysctl(struct sysctl_ctx_list *ctx, stats = &txq->vtntx_stats; - SYSCTL_ADD_UQUAD(ctx, list, OID_AUTO, "opackets", CTLFLAG_RD, + SYSCTL_ADD_UQUAD(ctx, list, OID_AUTO, "opackets", + CTLFLAG_RD | CTLFLAG_STATS, &stats->vtxs_opackets, "Transmit packets"); - SYSCTL_ADD_UQUAD(ctx, list, OID_AUTO, "obytes", CTLFLAG_RD, + SYSCTL_ADD_UQUAD(ctx, list, OID_AUTO, "obytes", + CTLFLAG_RD | CTLFLAG_STATS, &stats->vtxs_obytes, "Transmit bytes"); - SYSCTL_ADD_UQUAD(ctx, list, OID_AUTO, "omcasts", CTLFLAG_RD, + SYSCTL_ADD_UQUAD(ctx, list, OID_AUTO, "omcasts", + CTLFLAG_RD | CTLFLAG_STATS, &stats->vtxs_omcasts, "Transmit multicasts"); - SYSCTL_ADD_UQUAD(ctx, list, OID_AUTO, "csum", CTLFLAG_RD, + SYSCTL_ADD_UQUAD(ctx, list, OID_AUTO, "csum", + CTLFLAG_RD | CTLFLAG_STATS, &stats->vtxs_csum, "Transmit checksum offloaded"); - SYSCTL_ADD_UQUAD(ctx, list, OID_AUTO, "tso", CTLFLAG_RD, + SYSCTL_ADD_UQUAD(ctx, list, OID_AUTO, "tso", + CTLFLAG_RD | CTLFLAG_STATS, &stats->vtxs_tso, "Transmit TCP segmentation offloaded"); - SYSCTL_ADD_UQUAD(ctx, list, OID_AUTO, "rescheduled", CTLFLAG_RD, + SYSCTL_ADD_UQUAD(ctx, list, OID_AUTO, "rescheduled", + CTLFLAG_RD | CTLFLAG_STATS, &stats->vtxs_rescheduled, "Transmit interrupt handler rescheduled"); } @@ -4170,6 +4185,102 @@ vtnet_setup_queue_sysctl(struct vtnet_softc *sc) } } +static int +vtnet_sysctl_rx_csum_failed(SYSCTL_HANDLER_ARGS) +{ + struct vtnet_softc *sc = (struct vtnet_softc *)arg1; + struct vtnet_statistics *stats = &sc->vtnet_stats; + struct vtnet_rxq_stats *rxst; + int i; + + stats->rx_csum_failed = 0; + for (i = 0; i < sc->vtnet_max_vq_pairs; i++) { + rxst = &sc->vtnet_rxqs[i].vtnrx_stats; + stats->rx_csum_failed += rxst->vrxs_csum_failed; + } + return (sysctl_handle_64(oidp, NULL, stats->rx_csum_failed, req)); +} + +static int +vtnet_sysctl_rx_csum_offloaded(SYSCTL_HANDLER_ARGS) +{ + struct vtnet_softc *sc = (struct vtnet_softc *)arg1; + struct vtnet_statistics *stats = &sc->vtnet_stats; + struct vtnet_rxq_stats *rxst; + int i; + + stats->rx_csum_offloaded = 0; + for (i = 0; i < sc->vtnet_max_vq_pairs; i++) { + rxst = &sc->vtnet_rxqs[i].vtnrx_stats; + stats->rx_csum_offloaded += rxst->vrxs_csum; + } + return (sysctl_handle_64(oidp, NULL, stats->rx_csum_offloaded, req)); +} + +static int +vtnet_sysctl_rx_task_rescheduled(SYSCTL_HANDLER_ARGS) +{ + struct vtnet_softc *sc = (struct vtnet_softc *)arg1; + struct vtnet_statistics *stats = &sc->vtnet_stats; + struct vtnet_rxq_stats *rxst; + int i; + + stats->rx_task_rescheduled = 0; + for (i = 0; i < sc->vtnet_max_vq_pairs; i++) { + rxst = &sc->vtnet_rxqs[i].vtnrx_stats; + stats->rx_task_rescheduled += rxst->vrxs_rescheduled; + } + return (sysctl_handle_64(oidp, NULL, stats->rx_task_rescheduled, req)); +} + +static int +vtnet_sysctl_tx_csum_offloaded(SYSCTL_HANDLER_ARGS) +{ + struct vtnet_softc *sc = (struct vtnet_softc *)arg1; + struct vtnet_statistics *stats = &sc->vtnet_stats; + struct vtnet_txq_stats *txst; + int i; + + stats->tx_csum_offloaded = 0; + for (i = 0; i < sc->vtnet_max_vq_pairs; i++) { + txst = &sc->vtnet_txqs[i].vtntx_stats; + stats->tx_csum_offloaded += txst->vtxs_csum; + } + return (sysctl_handle_64(oidp, NULL, stats->tx_csum_offloaded, req)); +} + +static int +vtnet_sysctl_tx_tso_offloaded(SYSCTL_HANDLER_ARGS) +{ + struct vtnet_softc *sc = (struct vtnet_softc *)arg1; + struct vtnet_statistics *stats = &sc->vtnet_stats; + struct vtnet_txq_stats *txst; + int i; + + stats->tx_tso_offloaded = 0; + for (i = 0; i < sc->vtnet_max_vq_pairs; i++) { + txst = &sc->vtnet_txqs[i].vtntx_stats; + stats->tx_tso_offloaded += txst->vtxs_tso; + } + return (sysctl_handle_64(oidp, NULL, stats->tx_tso_offloaded, req)); +} + +static int +vtnet_sysctl_tx_task_rescheduled(SYSCTL_HANDLER_ARGS) +{ + struct vtnet_softc *sc = (struct vtnet_softc *)arg1; + struct vtnet_statistics *stats = &sc->vtnet_stats; + struct vtnet_txq_stats *txst; + int i; + + stats->tx_task_rescheduled = 0; + for (i = 0; i < sc->vtnet_max_vq_pairs; i++) { + txst = &sc->vtnet_txqs[i].vtntx_stats; + stats->tx_task_rescheduled += txst->vtxs_rescheduled; + } + return (sysctl_handle_64(oidp, NULL, stats->tx_task_rescheduled, req)); +} + static void vtnet_setup_stat_sysctl(struct sysctl_ctx_list *ctx, struct sysctl_oid_list *child, struct vtnet_softc *sc) @@ -4189,69 +4300,75 @@ vtnet_setup_stat_sysctl(struct sysctl_ctx_list *ctx, stats->tx_task_rescheduled = txaccum.vtxs_rescheduled; SYSCTL_ADD_UQUAD(ctx, child, OID_AUTO, "mbuf_alloc_failed", - CTLFLAG_RD, &stats->mbuf_alloc_failed, + CTLFLAG_RD | CTLFLAG_STATS, &stats->mbuf_alloc_failed, "Mbuf cluster allocation failures"); SYSCTL_ADD_UQUAD(ctx, child, OID_AUTO, "rx_frame_too_large", - CTLFLAG_RD, &stats->rx_frame_too_large, + CTLFLAG_RD | CTLFLAG_STATS, &stats->rx_frame_too_large, "Received frame larger than the mbuf chain"); SYSCTL_ADD_UQUAD(ctx, child, OID_AUTO, "rx_enq_replacement_failed", - CTLFLAG_RD, &stats->rx_enq_replacement_failed, + CTLFLAG_RD | CTLFLAG_STATS, &stats->rx_enq_replacement_failed, "Enqueuing the replacement receive mbuf failed"); SYSCTL_ADD_UQUAD(ctx, child, OID_AUTO, "rx_mergeable_failed", - CTLFLAG_RD, &stats->rx_mergeable_failed, + CTLFLAG_RD | CTLFLAG_STATS, &stats->rx_mergeable_failed, "Mergeable buffers receive failures"); SYSCTL_ADD_UQUAD(ctx, child, OID_AUTO, "rx_csum_bad_ethtype", - CTLFLAG_RD, &stats->rx_csum_bad_ethtype, + CTLFLAG_RD | CTLFLAG_STATS, &stats->rx_csum_bad_ethtype, "Received checksum offloaded buffer with unsupported " "Ethernet type"); SYSCTL_ADD_UQUAD(ctx, child, OID_AUTO, "rx_csum_bad_ipproto", - CTLFLAG_RD, &stats->rx_csum_bad_ipproto, + CTLFLAG_RD | CTLFLAG_STATS, &stats->rx_csum_bad_ipproto, "Received checksum offloaded buffer with incorrect IP protocol"); SYSCTL_ADD_UQUAD(ctx, child, OID_AUTO, "rx_csum_bad_offset", - CTLFLAG_RD, &stats->rx_csum_bad_offset, + CTLFLAG_RD | CTLFLAG_STATS, &stats->rx_csum_bad_offset, "Received checksum offloaded buffer with incorrect offset"); SYSCTL_ADD_UQUAD(ctx, child, OID_AUTO, "rx_csum_bad_proto", - CTLFLAG_RD, &stats->rx_csum_bad_proto, + CTLFLAG_RD | CTLFLAG_STATS, &stats->rx_csum_bad_proto, "Received checksum offloaded buffer with incorrect protocol"); - SYSCTL_ADD_UQUAD(ctx, child, OID_AUTO, "rx_csum_failed", - CTLFLAG_RD, &stats->rx_csum_failed, + SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "rx_csum_failed", + CTLTYPE_U64 | CTLFLAG_RD | CTLFLAG_STATS, + sc, 0, vtnet_sysctl_rx_csum_failed, "QU", "Received buffer checksum offload failed"); - SYSCTL_ADD_UQUAD(ctx, child, OID_AUTO, "rx_csum_offloaded", - CTLFLAG_RD, &stats->rx_csum_offloaded, + SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "rx_csum_offloaded", + CTLTYPE_U64 | CTLFLAG_RD | CTLFLAG_STATS, + sc, 0, vtnet_sysctl_rx_csum_offloaded, "QU", "Received buffer checksum offload succeeded"); - SYSCTL_ADD_UQUAD(ctx, child, OID_AUTO, "rx_task_rescheduled", - CTLFLAG_RD, &stats->rx_task_rescheduled, + SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "rx_task_rescheduled", + CTLTYPE_U64 | CTLFLAG_RD | CTLFLAG_STATS, + sc, 0, vtnet_sysctl_rx_task_rescheduled, "QU", "Times the receive interrupt task rescheduled itself"); SYSCTL_ADD_UQUAD(ctx, child, OID_AUTO, "tx_csum_unknown_ethtype", - CTLFLAG_RD, &stats->tx_csum_unknown_ethtype, + CTLFLAG_RD | CTLFLAG_STATS, &stats->tx_csum_unknown_ethtype, "Aborted transmit of checksum offloaded buffer with unknown " "Ethernet type"); SYSCTL_ADD_UQUAD(ctx, child, OID_AUTO, "tx_csum_proto_mismatch", - CTLFLAG_RD, &stats->tx_csum_proto_mismatch, + CTLFLAG_RD | CTLFLAG_STATS, &stats->tx_csum_proto_mismatch, "Aborted transmit of checksum offloaded buffer because mismatched " "protocols"); SYSCTL_ADD_UQUAD(ctx, child, OID_AUTO, "tx_tso_not_tcp", - CTLFLAG_RD, &stats->tx_tso_not_tcp, + CTLFLAG_RD | CTLFLAG_STATS, &stats->tx_tso_not_tcp, "Aborted transmit of TSO buffer with non TCP protocol"); SYSCTL_ADD_UQUAD(ctx, child, OID_AUTO, "tx_tso_without_csum", - CTLFLAG_RD, &stats->tx_tso_without_csum, + CTLFLAG_RD | CTLFLAG_STATS, &stats->tx_tso_without_csum, "Aborted transmit of TSO buffer without TCP checksum offload"); SYSCTL_ADD_UQUAD(ctx, child, OID_AUTO, "tx_defragged", - CTLFLAG_RD, &stats->tx_defragged, + CTLFLAG_RD | CTLFLAG_STATS, &stats->tx_defragged, "Transmit mbufs defragged"); SYSCTL_ADD_UQUAD(ctx, child, OID_AUTO, "tx_defrag_failed", - CTLFLAG_RD, &stats->tx_defrag_failed, + CTLFLAG_RD | CTLFLAG_STATS, &stats->tx_defrag_failed, "Aborted transmit of buffer because defrag failed"); - SYSCTL_ADD_UQUAD(ctx, child, OID_AUTO, "tx_csum_offloaded", - CTLFLAG_RD, &stats->tx_csum_offloaded, + SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "tx_csum_offloaded", + CTLTYPE_U64 | CTLFLAG_RD | CTLFLAG_STATS, + sc, 0, vtnet_sysctl_tx_csum_offloaded, "QU", "Offloaded checksum of transmitted buffer"); - SYSCTL_ADD_UQUAD(ctx, child, OID_AUTO, "tx_tso_offloaded", - CTLFLAG_RD, &stats->tx_tso_offloaded, + SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "tx_tso_offloaded", + CTLTYPE_U64 | CTLFLAG_RD | CTLFLAG_STATS, + sc, 0, vtnet_sysctl_tx_tso_offloaded, "QU", "Segmentation offload of transmitted buffer"); - SYSCTL_ADD_UQUAD(ctx, child, OID_AUTO, "tx_task_rescheduled", - CTLFLAG_RD, &stats->tx_task_rescheduled, + SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "tx_task_rescheduled", + CTLTYPE_U64 | CTLFLAG_RD | CTLFLAG_STATS, + sc, 0, vtnet_sysctl_tx_task_rescheduled, "QU", "Times the transmit interrupt task rescheduled itself"); } diff --git a/sys/fs/msdosfs/bootsect.h b/sys/fs/msdosfs/bootsect.h index 170d94cb9512..94b1137a153e 100644 --- a/sys/fs/msdosfs/bootsect.h +++ b/sys/fs/msdosfs/bootsect.h @@ -20,7 +20,7 @@ /* * Format of a boot sector. This is the first sector on a DOS floppy disk - * or the fist sector of a partition on a hard disk. But, it is not the + * or the first sector of a partition on a hard disk. But, it is not the * first sector of a partitioned hard disk. */ struct bootsector33 { diff --git a/sys/fs/nfsclient/nfs_clvnops.c b/sys/fs/nfsclient/nfs_clvnops.c index a8b06fdb261b..eee571a04821 100644 --- a/sys/fs/nfsclient/nfs_clvnops.c +++ b/sys/fs/nfsclient/nfs_clvnops.c @@ -3474,7 +3474,7 @@ nfs_advlock(struct vop_advlock_args *ap) u_quad_t size; struct nfsmount *nmp; - error = NFSVOPLOCK(vp, LK_SHARED); + error = NFSVOPLOCK(vp, LK_EXCLUSIVE); if (error != 0) return (EBADF); nmp = VFSTONFS(vp->v_mount); @@ -3511,11 +3511,6 @@ nfs_advlock(struct vop_advlock_args *ap) cred = p->p_ucred; else cred = td->td_ucred; - NFSVOPLOCK(vp, LK_UPGRADE | LK_RETRY); - if (VN_IS_DOOMED(vp)) { - error = EBADF; - goto out; - } /* * If this is unlocking a write locked region, flush and diff --git a/sys/kern/vfs_init.c b/sys/kern/vfs_init.c index cd30d5cfae47..93ac001af8ad 100644 --- a/sys/kern/vfs_init.c +++ b/sys/kern/vfs_init.c @@ -103,6 +103,16 @@ struct vattr va_null; * Routines having to do with the management of the vnode table. */ +void +vfs_unref_vfsconf(struct vfsconf *vfsp) +{ + vfsconf_lock(); + KASSERT(vfsp->vfc_refcount > 0, + ("vfs %p refcount underflow %d", vfsp, vfsp->vfc_refcount)); + vfsp->vfc_refcount--; + vfsconf_unlock(); +} + static struct vfsconf * vfs_byname_locked(const char *name) { @@ -123,9 +133,11 @@ vfs_byname(const char *name) { struct vfsconf *vfsp; - vfsconf_slock(); + vfsconf_lock(); vfsp = vfs_byname_locked(name); - vfsconf_sunlock(); + if (vfsp != NULL) + vfsp->vfc_refcount++; + vfsconf_unlock(); return (vfsp); } diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c index 8e64a7fe966b..13403acacc08 100644 --- a/sys/kern/vfs_mount.c +++ b/sys/kern/vfs_mount.c @@ -683,7 +683,6 @@ vfs_mount_alloc(struct vnode *vp, struct vfsconf *vfsp, const char *fspath, MPASSERT(mp->mnt_vfs_ops == 1, mp, ("vfs_ops should be 1 but %d found", mp->mnt_vfs_ops)); (void) vfs_busy(mp, MBF_NOWAIT); - atomic_add_acq_int(&vfsp->vfc_refcount, 1); mp->mnt_op = vfsp->vfc_vfsops; mp->mnt_vfc = vfsp; mp->mnt_stat.f_type = vfsp->vfc_typenum; @@ -731,7 +730,6 @@ vfs_mount_destroy(struct mount *mp) __FILE__, __LINE__)); MPPASS(mp->mnt_writeopcount == 0, mp); MPPASS(mp->mnt_secondary_writes == 0, mp); - atomic_subtract_rel_int(&mp->mnt_vfc->vfc_refcount, 1); if (!TAILQ_EMPTY(&mp->mnt_nvnodelist)) { struct vnode *vp; @@ -769,6 +767,9 @@ vfs_mount_destroy(struct mount *mp) vfs_free_addrlist(mp->mnt_export); free(mp->mnt_export, M_MOUNT); } + vfsconf_lock(); + mp->mnt_vfc->vfc_refcount--; + vfsconf_unlock(); crfree(mp->mnt_cred); uma_zfree(mount_zone, mp); } @@ -1133,6 +1134,7 @@ vfs_domount_first( if (jailed(td->td_ucred) && (!prison_allow(td->td_ucred, vfsp->vfc_prison_flag) || vp == td->td_ucred->cr_prison->pr_root)) { vput(vp); + vfs_unref_vfsconf(vfsp); return (EPERM); } @@ -1169,6 +1171,7 @@ vfs_domount_first( } if (error != 0) { vput(vp); + vfs_unref_vfsconf(vfsp); return (error); } vn_seqc_write_begin(vp); diff --git a/sys/modules/e6000sw/Makefile b/sys/modules/e6000sw/Makefile index da08f80b0a29..73cbaea801f0 100644 --- a/sys/modules/e6000sw/Makefile +++ b/sys/modules/e6000sw/Makefile @@ -3,6 +3,6 @@ KMOD= e6000sw SRCS= e6000sw.c -SRCS+= bus_if.h etherswitch_if.h mdio_if.h miibus_if.h ofw_bus_if.h opt_platform.h +SRCS+= bus_if.h device_if.h etherswitch_if.h mdio_if.h miibus_if.h ofw_bus_if.h opt_platform.h .include <bsd.kmod.mk> diff --git a/sys/modules/etherswitch/Makefile b/sys/modules/etherswitch/Makefile index 087231545cd4..0b16a19e5117 100644 --- a/sys/modules/etherswitch/Makefile +++ b/sys/modules/etherswitch/Makefile @@ -3,7 +3,7 @@ KMOD = etherswitch SRCS= etherswitch.c -SRCS+= mdio_if.h miibus_if.h etherswitch_if.h etherswitch_if.c +SRCS+= bus_if.h device_if.h mdio_if.h miibus_if.h etherswitch_if.h etherswitch_if.c CFLAGS+= -I${SRCTOP}/sys/dev/etherswitch .include <bsd.kmod.mk> diff --git a/sys/modules/evdev/Makefile b/sys/modules/evdev/Makefile index bd66013885db..20813b73f6dd 100644 --- a/sys/modules/evdev/Makefile +++ b/sys/modules/evdev/Makefile @@ -2,7 +2,7 @@ KMOD= evdev SRCS= cdev.c evdev.c evdev_mt.c evdev_utils.c -SRCS+= opt_evdev.h bus_if.h device_if.h +SRCS+= opt_evdev.h opt_kbd.h bus_if.h device_if.h EXPORT_SYMS= YES diff --git a/sys/modules/gpio/gpioaei/Makefile b/sys/modules/gpio/gpioaei/Makefile index 8f856af48eb7..1f0f1d0e53a6 100644 --- a/sys/modules/gpio/gpioaei/Makefile +++ b/sys/modules/gpio/gpioaei/Makefile @@ -10,6 +10,8 @@ SRCS+= \ gpio_if.h \ gpiobus_if.h +SRCS+= opt_acpi.h opt_platform.h + CFLAGS+= -I. -I${SRCTOP}/sys/dev/gpio/ .include <bsd.kmod.mk> diff --git a/sys/modules/gve/Makefile b/sys/modules/gve/Makefile index 08b26a994e36..ece275485df7 100644 --- a/sys/modules/gve/Makefile +++ b/sys/modules/gve/Makefile @@ -40,5 +40,5 @@ SRCS= gve_main.c \ gve_tx_dqo.c \ gve_sysctl.c SRCS+= device_if.h bus_if.h pci_if.h - +SRCS+= opt_inet6.h .include <bsd.kmod.mk> diff --git a/sys/modules/ichwd/Makefile b/sys/modules/ichwd/Makefile index 3c3bbc37eff5..27b4c38437ff 100644 --- a/sys/modules/ichwd/Makefile +++ b/sys/modules/ichwd/Makefile @@ -1,6 +1,6 @@ .PATH: ${SRCTOP}/sys/dev/ichwd KMOD= ichwd -SRCS= ichwd.c device_if.h bus_if.h pci_if.h isa_if.h +SRCS= i6300esbwd.c ichwd.c device_if.h bus_if.h pci_if.h isa_if.h .include <bsd.kmod.mk> diff --git a/sys/modules/if_infiniband/Makefile b/sys/modules/if_infiniband/Makefile index 01e3164b1271..7ec343999da1 100644 --- a/sys/modules/if_infiniband/Makefile +++ b/sys/modules/if_infiniband/Makefile @@ -3,7 +3,8 @@ KMOD= if_infiniband SRCS= if_infiniband.c \ opt_inet.h \ - opt_inet6.h + opt_inet6.h \ + opt_kbd.h EXPORT_SYMS= YES diff --git a/sys/modules/if_vlan/Makefile b/sys/modules/if_vlan/Makefile index 3077f4289d5a..0cdab3f7653a 100644 --- a/sys/modules/if_vlan/Makefile +++ b/sys/modules/if_vlan/Makefile @@ -2,6 +2,6 @@ KMOD= if_vlan SRCS= if_vlan.c -SRCS+= opt_inet.h opt_inet6.h opt_kern_tls.h opt_vlan.h opt_ratelimit.h +SRCS+= opt_inet.h opt_inet6.h opt_ipsec.h opt_kern_tls.h opt_vlan.h opt_ratelimit.h .include <bsd.kmod.mk> diff --git a/sys/modules/irdma/Makefile b/sys/modules/irdma/Makefile index b2ffb67ca66f..a9ef6e63d3f2 100644 --- a/sys/modules/irdma/Makefile +++ b/sys/modules/irdma/Makefile @@ -1,8 +1,8 @@ .include <bsd.own.mk> -OFED_INC_DIR = ${.CURDIR}/../../ofed/include -ICE_DIR = ${.CURDIR}/../../dev/ice -.PATH: ${.CURDIR}/../../dev/irdma +OFED_INC_DIR = ${SRCTOP}/sys/ofed/include +ICE_DIR = ${SRCTOP}/sys/dev/ice +.PATH: ${SRCTOP}/sys/dev/irdma KMOD= irdma SRCS= icrdma.c diff --git a/sys/modules/linux64/Makefile b/sys/modules/linux64/Makefile index b23891a65a4f..327da11afdaf 100644 --- a/sys/modules/linux64/Makefile +++ b/sys/modules/linux64/Makefile @@ -31,6 +31,7 @@ SRCS= linux_dummy_machdep.c \ opt_ktrace.h \ opt_inet6.h \ opt_posix.h \ + opt_usb.h \ bus_if.h \ device_if.h \ vnode_if.h \ diff --git a/sys/modules/md/Makefile b/sys/modules/md/Makefile index 2b0586c44717..3f16e04860a1 100644 --- a/sys/modules/md/Makefile +++ b/sys/modules/md/Makefile @@ -1,6 +1,6 @@ .PATH: ${SRCTOP}/sys/dev/md KMOD= geom_md -SRCS= md.c opt_md.h opt_geom.h opt_rootdevname.h vnode_if.h +SRCS= bus_if.h device_if.h md.c opt_md.h opt_geom.h opt_rootdevname.h vnode_if.h .include <bsd.kmod.mk> diff --git a/sys/modules/miiproxy/Makefile b/sys/modules/miiproxy/Makefile index 5173358989da..730bef4220cd 100644 --- a/sys/modules/miiproxy/Makefile +++ b/sys/modules/miiproxy/Makefile @@ -3,7 +3,7 @@ KMOD = miiproxy SRCS= miiproxy.c -SRCS+= mdio_if.h miibus_if.h +SRCS+= bus_if.h mdio_if.h miibus_if.h opt_platform.h CFLAGS+= -I${SRCTOP}/sys/dev/etherswitch .include <bsd.kmod.mk> diff --git a/sys/modules/mlx5/Makefile b/sys/modules/mlx5/Makefile index 506c045ab0ce..65341fdfb8aa 100644 --- a/sys/modules/mlx5/Makefile +++ b/sys/modules/mlx5/Makefile @@ -46,7 +46,7 @@ mlx5_ipsec_offload.c \ mlx5_ipsec.c \ mlx5_ipsec_rxtx.c SRCS+= ${LINUXKPI_GENSRCS} -SRCS+= opt_inet.h opt_inet6.h opt_rss.h opt_ratelimit.h +SRCS+= opt_inet.h opt_inet6.h opt_ipsec.h opt_rss.h opt_ratelimit.h CFLAGS+= -I${SRCTOP}/sys/ofed/include CFLAGS+= -I${SRCTOP}/sys/ofed/include/uapi diff --git a/sys/modules/mlx5en/Makefile b/sys/modules/mlx5en/Makefile index 03bf174e33b0..3697fa65dc83 100644 --- a/sys/modules/mlx5en/Makefile +++ b/sys/modules/mlx5en/Makefile @@ -15,7 +15,7 @@ mlx5_en_rl.c \ mlx5_en_txrx.c \ mlx5_en_port_buffer.c SRCS+= ${LINUXKPI_GENSRCS} -SRCS+= opt_inet.h opt_inet6.h opt_rss.h opt_ratelimit.h opt_kern_tls.h +SRCS+= opt_inet.h opt_inet6.h opt_ipsec.h opt_rss.h opt_ratelimit.h opt_kern_tls.h .if defined(HAVE_PER_CQ_EVENT_PACKET) CFLAGS+= -DHAVE_PER_CQ_EVENT_PACKET diff --git a/sys/modules/netgraph/ksocket/Makefile b/sys/modules/netgraph/ksocket/Makefile index 395fdbd7b3e3..7099648f6219 100644 --- a/sys/modules/netgraph/ksocket/Makefile +++ b/sys/modules/netgraph/ksocket/Makefile @@ -1,4 +1,6 @@ KMOD= ng_ksocket SRCS= ng_ksocket.c +SRCS+= opt_inet6.h + .include <bsd.kmod.mk> diff --git a/sys/modules/nvmf/nvmf/Makefile b/sys/modules/nvmf/nvmf/Makefile index 7ebe614998bd..21d73d363d2f 100644 --- a/sys/modules/nvmf/nvmf/Makefile +++ b/sys/modules/nvmf/nvmf/Makefile @@ -10,4 +10,7 @@ SRCS= nvmf.c \ nvmf_qpair.c \ nvmf_sim.c +SRCS+= bus_if.h device_if.h +SRCS+= opt_cam.h + .include <bsd.kmod.mk> diff --git a/sys/modules/qlnx/qlnxev/Makefile b/sys/modules/qlnx/qlnxev/Makefile index ed62f1f1dd40..766a5a950032 100644 --- a/sys/modules/qlnx/qlnxev/Makefile +++ b/sys/modules/qlnx/qlnxev/Makefile @@ -49,6 +49,7 @@ SRCS+=ecore_vf.c SRCS+=qlnx_ioctl.c SRCS+=qlnx_os.c +SRCS+=opt_inet.h SRCS+= ${LINUXKPI_GENSRCS} diff --git a/sys/modules/uinput/Makefile b/sys/modules/uinput/Makefile index 66ade2a5bb33..a9e2ec867b91 100644 --- a/sys/modules/uinput/Makefile +++ b/sys/modules/uinput/Makefile @@ -2,6 +2,6 @@ KMOD= uinput SRCS= uinput.c -SRCS+= opt_evdev.h +SRCS+= opt_evdev.h opt_kbd.h .include <bsd.kmod.mk> diff --git a/sys/modules/usb/usie/Makefile b/sys/modules/usb/usie/Makefile index 6a5f79248ff8..9edeed082f8d 100644 --- a/sys/modules/usb/usie/Makefile +++ b/sys/modules/usb/usie/Makefile @@ -29,6 +29,6 @@ KMOD = usie SRCS = if_usie.c SRCS += opt_bus.h opt_usb.h device_if.h bus_if.h \ - usb_if.h usbdevs.h opt_inet.h + usb_if.h usbdevs.h opt_inet.h opt_inet6.h .include <bsd.kmod.mk> diff --git a/sys/modules/usb/wmt/Makefile b/sys/modules/usb/wmt/Makefile index 72cf1d814908..8cb5abd7383e 100644 --- a/sys/modules/usb/wmt/Makefile +++ b/sys/modules/usb/wmt/Makefile @@ -3,6 +3,6 @@ S= ${SRCTOP}/sys .PATH: $S/dev/usb/input KMOD= wmt -SRCS= opt_bus.h opt_usb.h device_if.h bus_if.h usb_if.h usbdevs.h wmt.c +SRCS= opt_bus.h opt_kbd.h opt_usb.h device_if.h bus_if.h usb_if.h usbdevs.h wmt.c .include <bsd.kmod.mk> diff --git a/sys/modules/zfs/zfs_config.h b/sys/modules/zfs/zfs_config.h index 12274bcceea1..72167b752e53 100644 --- a/sys/modules/zfs/zfs_config.h +++ b/sys/modules/zfs/zfs_config.h @@ -840,7 +840,7 @@ /* #undef ZFS_DEVICE_MINOR */ /* Define the project alias string. */ -#define ZFS_META_ALIAS "zfs-2.3.99-571-FreeBSD_ga9410ccbd" +#define ZFS_META_ALIAS "zfs-2.4.0-rc1-FreeBSD_g00dfa094a" /* Define the project author. */ #define ZFS_META_AUTHOR "OpenZFS" @@ -870,10 +870,10 @@ #define ZFS_META_NAME "zfs" /* Define the project release. */ -#define ZFS_META_RELEASE "571-FreeBSD_ga9410ccbd" +#define ZFS_META_RELEASE "zfs-2.4.0-rc1-FreeBSD_g00dfa094a" /* Define the project version. */ -#define ZFS_META_VERSION "2.3.99" +#define ZFS_META_VERSION "2.4.0" /* count is located in percpu_ref.data */ /* #undef ZFS_PERCPU_REF_COUNT_IN_DATA */ diff --git a/sys/modules/zfs/zfs_gitrev.h b/sys/modules/zfs/zfs_gitrev.h index 5c265cf5b08e..2b5d717da216 100644 --- a/sys/modules/zfs/zfs_gitrev.h +++ b/sys/modules/zfs/zfs_gitrev.h @@ -1 +1 @@ -#define ZFS_META_GITREV "zfs-2.3.99-571-ga9410ccbd" +#define ZFS_META_GITREV "zfs-2.4.0-rc1-0-g00dfa094a" diff --git a/sys/net/if.c b/sys/net/if.c index 79c883fd4a0a..0fc30488f1e5 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -74,7 +74,6 @@ #include <vm/uma.h> #include <net/bpf.h> -#include <net/ethernet.h> #include <net/if.h> #include <net/if_arp.h> #include <net/if_clone.h> @@ -2589,16 +2588,7 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td) * flip. They require special handling because in-kernel * consumers may indepdently toggle them. */ - if ((ifp->if_flags ^ new_flags) & IFF_PPROMISC) { - if (new_flags & IFF_PPROMISC) - ifp->if_flags |= IFF_PROMISC; - else if (ifp->if_pcount == 0) - ifp->if_flags &= ~IFF_PROMISC; - if (log_promisc_mode_change) - if_printf(ifp, "permanently promiscuous mode %s\n", - ((new_flags & IFF_PPROMISC) ? - "enabled" : "disabled")); - } + if_setppromisc(ifp, new_flags & IFF_PPROMISC); if ((ifp->if_flags ^ new_flags) & IFF_PALLMULTI) { if (new_flags & IFF_PALLMULTI) ifp->if_flags |= IFF_ALLMULTI; @@ -4456,6 +4446,32 @@ if_getmtu_family(const if_t ifp, int family) return (ifp->if_mtu); } +void +if_setppromisc(if_t ifp, bool ppromisc) +{ + int new_flags; + + if (ppromisc) + new_flags = ifp->if_flags | IFF_PPROMISC; + else + new_flags = ifp->if_flags & ~IFF_PPROMISC; + if ((ifp->if_flags ^ new_flags) & IFF_PPROMISC) { + if (new_flags & IFF_PPROMISC) + new_flags |= IFF_PROMISC; + /* + * Only unset IFF_PROMISC if there are no more consumers of + * promiscuity, i.e. the ifp->if_pcount refcount is 0. + */ + else if (ifp->if_pcount == 0) + new_flags &= ~IFF_PROMISC; + if (log_promisc_mode_change) + if_printf(ifp, "permanently promiscuous mode %s\n", + ((new_flags & IFF_PPROMISC) ? + "enabled" : "disabled")); + } + ifp->if_flags = new_flags; +} + /* * Methods for drivers to access interface unicast and multicast * link level addresses. Driver shall not know 'struct ifaddr' neither diff --git a/sys/net/if_epair.c b/sys/net/if_epair.c index a213a84e17db..581c2434b8fb 100644 --- a/sys/net/if_epair.c +++ b/sys/net/if_epair.c @@ -67,7 +67,6 @@ #include <net/if_var.h> #include <net/if_clone.h> #include <net/if_media.h> -#include <net/if_var.h> #include <net/if_private.h> #include <net/if_types.h> #include <net/netisr.h> diff --git a/sys/net/if_var.h b/sys/net/if_var.h index 08435e7bd5f6..f2df612b19c1 100644 --- a/sys/net/if_var.h +++ b/sys/net/if_var.h @@ -622,6 +622,7 @@ int if_setmtu(if_t ifp, int mtu); int if_getmtu(const if_t ifp); int if_getmtu_family(const if_t ifp, int family); void if_notifymtu(if_t ifp); +void if_setppromisc(const if_t ifp, bool ppromisc); int if_setflagbits(if_t ifp, int set, int clear); int if_setflags(if_t ifp, int flags); int if_getflags(const if_t ifp); diff --git a/sys/net80211/ieee80211_freebsd.h b/sys/net80211/ieee80211_freebsd.h index 141b13f9f740..3684fba52c5c 100644 --- a/sys/net80211/ieee80211_freebsd.h +++ b/sys/net80211/ieee80211_freebsd.h @@ -93,12 +93,22 @@ typedef struct { } while (0) #define IEEE80211_TX_LOCK_OBJ(_ic) (&(_ic)->ic_txlock.mtx) #define IEEE80211_TX_LOCK_DESTROY(_ic) mtx_destroy(IEEE80211_TX_LOCK_OBJ(_ic)) -#define IEEE80211_TX_LOCK(_ic) mtx_lock(IEEE80211_TX_LOCK_OBJ(_ic)) -#define IEEE80211_TX_UNLOCK(_ic) mtx_unlock(IEEE80211_TX_LOCK_OBJ(_ic)) -#define IEEE80211_TX_LOCK_ASSERT(_ic) \ - mtx_assert(IEEE80211_TX_LOCK_OBJ(_ic), MA_OWNED) -#define IEEE80211_TX_UNLOCK_ASSERT(_ic) \ - mtx_assert(IEEE80211_TX_LOCK_OBJ(_ic), MA_NOTOWNED) +#define IEEE80211_TX_LOCK(_ic) do { \ + if (!IEEE80211_CONF_SEQNO_OFFLOAD(_ic)) \ + mtx_lock(IEEE80211_TX_LOCK_OBJ(_ic)); \ + } while (0); +#define IEEE80211_TX_UNLOCK(_ic) do { \ + if (!IEEE80211_CONF_SEQNO_OFFLOAD(_ic)) \ + mtx_unlock(IEEE80211_TX_LOCK_OBJ(_ic)); \ + } while (0); +#define IEEE80211_TX_LOCK_ASSERT(_ic) do { \ + if (!IEEE80211_CONF_SEQNO_OFFLOAD(_ic)) \ + mtx_assert(IEEE80211_TX_LOCK_OBJ(_ic), MA_OWNED); \ + } while (0) +#define IEEE80211_TX_UNLOCK_ASSERT(_ic) { \ + if (!IEEE80211_CONF_SEQNO_OFFLOAD(_ic)) \ + mtx_assert(IEEE80211_TX_LOCK_OBJ(_ic), MA_NOTOWNED); \ + } while (0) /* * Stageq / ni_tx_superg lock diff --git a/sys/net80211/ieee80211_output.c b/sys/net80211/ieee80211_output.c index afe83ea0805c..57fe687adffe 100644 --- a/sys/net80211/ieee80211_output.c +++ b/sys/net80211/ieee80211_output.c @@ -974,7 +974,7 @@ ieee80211_send_setup( /* NB: zero out i_seq field (for s/w encryption etc) */ *(uint16_t *)&wh->i_seq[0] = 0; - } else + } else if (!IEEE80211_CONF_SEQNO_OFFLOAD(ni->ni_ic)) ieee80211_output_seqno_assign(ni, tid, m); if (IEEE80211_IS_MULTICAST(wh->i_addr1)) @@ -1810,7 +1810,8 @@ ieee80211_encap(struct ieee80211vap *vap, struct ieee80211_node *ni, * and we don't need the TX lock held. */ if ((m->m_flags & M_AMPDU_MPDU) == 0) { - ieee80211_output_seqno_assign(ni, tid, m); + if (!IEEE80211_CONF_SEQNO_OFFLOAD(ic)) + ieee80211_output_seqno_assign(ni, tid, m); } else { /* * NB: don't assign a sequence # to potential @@ -1828,7 +1829,9 @@ ieee80211_encap(struct ieee80211vap *vap, struct ieee80211_node *ni, *(uint16_t *)wh->i_seq = 0; } } else { - ieee80211_output_seqno_assign(ni, IEEE80211_NONQOS_TID, m); + if (!IEEE80211_CONF_SEQNO_OFFLOAD(ic)) + ieee80211_output_seqno_assign(ni, IEEE80211_NONQOS_TID, + m); /* * XXX TODO: we shouldn't allow EAPOL, etc that would * be forced to be non-QoS traffic to be A-MSDU encapsulated. @@ -3856,6 +3859,8 @@ ieee80211_beacon_update(struct ieee80211_node *ni, struct mbuf *m, int mcast) * If the driver identifies it does its own TX seqno management then * we can skip this (and still not do the TX seqno.) */ + + /* TODO: IEEE80211_CONF_SEQNO_OFFLOAD() */ ieee80211_output_beacon_seqno_assign(ni, m); /* XXX faster to recalculate entirely or just changes? */ diff --git a/sys/netgraph/ng_nat.c b/sys/netgraph/ng_nat.c index defbe817becd..8b82d777caeb 100644 --- a/sys/netgraph/ng_nat.c +++ b/sys/netgraph/ng_nat.c @@ -818,7 +818,8 @@ ng_nat_rcvdata(hook_p hook, item_p item ) if (ip->ip_v != IPVERSION) goto send; /* other IP version, let it pass */ - if (m->m_pkthdr.len < ipofs + ntohs(ip->ip_len)) + uint16_t ip_len = ntohs(ip->ip_len); + if (m->m_pkthdr.len < (ipofs + ip_len)) goto send; /* packet too short (i.e. fragmented or broken) */ /* @@ -852,50 +853,68 @@ ng_nat_rcvdata(hook_p hook, item_p item ) if (rval == PKT_ALIAS_RESPOND) m->m_flags |= M_SKIP_FIREWALL; - m->m_pkthdr.len = m->m_len = ntohs(ip->ip_len) + ipofs; - if ((ip->ip_off & htons(IP_OFFMASK)) == 0 && - ip->ip_p == IPPROTO_TCP) { - struct tcphdr *th = (struct tcphdr *)((caddr_t)ip + - (ip->ip_hl << 2)); + /* Re-read just in case it has been updated */ + ip_len = ntohs(ip->ip_len); + int new_m_len = ip_len + ipofs; + if (new_m_len > (m->m_len + M_TRAILINGSPACE(m))) { /* - * Here is our terrible HACK. - * - * Sometimes LibAlias edits contents of TCP packet. - * In this case it needs to recompute full TCP - * checksum. However, the problem is that LibAlias - * doesn't have any idea about checksum offloading - * in kernel. To workaround this, we do not do - * checksumming in LibAlias, but only mark the - * packets with TH_RES1 in the th_x2 field. If we - * receive a marked packet, we calculate correct - * checksum for it aware of offloading. - * - * Why do I do such a terrible hack instead of - * recalculating checksum for each packet? - * Because the previous checksum was not checked! - * Recalculating checksums for EVERY packet will - * hide ALL transmission errors. Yes, marked packets - * still suffer from this problem. But, sigh, natd(8) - * has this problem, too. + * This is just a safety railguard to make sure LibAlias has not + * screwed the IP packet up somehow, should probably be KASSERT() + * at some point. Calling in_delayed_cksum() will parse IP packet + * again and reliably panic if there is less data than the IP + * header declares, there might be some other places too. */ + log(LOG_ERR, "ng_nat_rcvdata: outgoing packet corrupted, " + "not enough data: expected %d, available (%d - %d)\n", + ip_len, m->m_len + (int)M_TRAILINGSPACE(m), ipofs); + NG_FREE_ITEM(item); + return (ENXIO); + } + + m->m_pkthdr.len = m->m_len = new_m_len; - if (tcp_get_flags(th) & TH_RES1) { - uint16_t ip_len = ntohs(ip->ip_len); + if ((ip->ip_off & htons(IP_OFFMASK)) != 0 || ip->ip_p != IPPROTO_TCP) + goto send; - tcp_set_flags(th, tcp_get_flags(th) & ~TH_RES1); - th->th_sum = in_pseudo(ip->ip_src.s_addr, - ip->ip_dst.s_addr, htons(IPPROTO_TCP + - ip_len - (ip->ip_hl << 2))); + uint16_t pl_offset = ip->ip_hl << 2; + struct tcphdr *th = (struct tcphdr *)((caddr_t)ip + pl_offset); - if ((m->m_pkthdr.csum_flags & CSUM_TCP) == 0) { - m->m_pkthdr.csum_data = offsetof(struct tcphdr, - th_sum); - in_delayed_cksum(m); - } - } - } + /* + * Here is our terrible HACK. + * + * Sometimes LibAlias edits contents of TCP packet. + * In this case it needs to recompute full TCP + * checksum. However, the problem is that LibAlias + * doesn't have any idea about checksum offloading + * in kernel. To workaround this, we do not do + * checksumming in LibAlias, but only mark the + * packets with TH_RES1 in the th_x2 field. If we + * receive a marked packet, we calculate correct + * checksum for it aware of offloading. + * + * Why do I do such a terrible hack instead of + * recalculating checksum for each packet? + * Because the previous checksum was not checked! + * Recalculating checksums for EVERY packet will + * hide ALL transmission errors. Yes, marked packets + * still suffer from this problem. But, sigh, natd(8) + * has this problem, too. + */ + + if (!(tcp_get_flags(th) & TH_RES1)) + goto send; + + tcp_set_flags(th, tcp_get_flags(th) & ~TH_RES1); + th->th_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr, + htons(IPPROTO_TCP + ip_len - pl_offset)); + + if ((m->m_pkthdr.csum_flags & CSUM_TCP) != 0) + goto send; + + m->m_pkthdr.csum_data = offsetof(struct tcphdr, th_sum); + in_delayed_cksum_o(m, ipofs); send: if (hook == priv->in) diff --git a/sys/netinet/cc/cc.c b/sys/netinet/cc/cc.c index d85ad4e9f4fd..c20a20cd983d 100644 --- a/sys/netinet/cc/cc.c +++ b/sys/netinet/cc/cc.c @@ -659,7 +659,7 @@ cc_modevent(module_t mod, int event_type, void *data) case MOD_SHUTDOWN: break; case MOD_QUIESCE: - /* Stop any new assigments */ + /* Stop any new assignments */ err = cc_stop_new_assignments(algo); break; case MOD_UNLOAD: diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index ec6ba8d92015..ef08b9cfd3d6 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -1044,14 +1044,14 @@ done: } void -in_delayed_cksum(struct mbuf *m) +in_delayed_cksum_o(struct mbuf *m, uint16_t iph_offset) { struct ip *ip; struct udphdr *uh; uint16_t cklen, csum, offset; - ip = mtod(m, struct ip *); - offset = ip->ip_hl << 2 ; + ip = (struct ip *)mtodo(m, iph_offset); + offset = iph_offset + (ip->ip_hl << 2); if (m->m_pkthdr.csum_flags & CSUM_UDP) { /* if udp header is not in the first mbuf copy udplen */ @@ -1078,6 +1078,13 @@ in_delayed_cksum(struct mbuf *m) *(u_short *)mtodo(m, offset) = csum; } +void +in_delayed_cksum(struct mbuf *m) +{ + + in_delayed_cksum_o(m, 0); +} + /* * IP socket option processing. */ diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h index f782ebc53eb0..c113484079a3 100644 --- a/sys/netinet/ip_var.h +++ b/sys/netinet/ip_var.h @@ -271,6 +271,7 @@ VNET_DECLARE(struct pfil_head *, inet_local_pfil_head); #define PFIL_INET_LOCAL_NAME "inet-local" void in_delayed_cksum(struct mbuf *m); +void in_delayed_cksum_o(struct mbuf *m, uint16_t o); /* Hooks for ipfw, dummynet, divert etc. Most are declared in raw_ip.c */ /* diff --git a/sys/netinet/tcp_hpts.c b/sys/netinet/tcp_hpts.c index b77ebc928809..63bbe4bba11b 100644 --- a/sys/netinet/tcp_hpts.c +++ b/sys/netinet/tcp_hpts.c @@ -137,8 +137,6 @@ #include <netinet/in_kdtrace.h> #include <netinet/in_pcb.h> #include <netinet/ip.h> -#include <netinet/ip_icmp.h> /* required for icmp_var.h */ -#include <netinet/icmp_var.h> /* for ICMP_BANDLIM */ #include <netinet/ip_var.h> #include <netinet/ip6.h> #include <netinet6/in6_pcb.h> diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index 6492495dc583..d5dc516c28aa 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -2562,299 +2562,270 @@ tcp_do_segment(struct tcpcb *tp, struct mbuf *m, struct tcphdr *th, hhook_run_tcp_est_in(tp, th, &to); #endif - if (SEQ_LEQ(th->th_ack, tp->snd_una)) { - maxseg = tcp_maxseg(tp); - if (no_data && - (tiwin == tp->snd_wnd || - (tp->t_flags & TF_SACK_PERMIT))) { + if (SEQ_LT(th->th_ack, tp->snd_una)) { + /* This is old ACK information, don't process it. */ + break; + } + if (th->th_ack == tp->snd_una) { + /* Check if this is a duplicate ACK. */ + if ((tp->t_flags & TF_SACK_PERMIT) && + V_tcp_do_newsack) { /* - * If this is the first time we've seen a - * FIN from the remote, this is not a - * duplicate and it needs to be processed - * normally. This happens during a - * simultaneous close. + * If SEG.ACK == SND.UNA, RFC 6675 requires a + * duplicate ACK to selectively acknowledge + * at least one byte, which was not selectively + * acknowledged before. */ - if ((thflags & TH_FIN) && - (TCPS_HAVERCVDFIN(tp->t_state) == 0)) { - tp->t_dupacks = 0; + if (sack_changed == SACK_NOCHANGE) { break; } - TCPSTAT_INC(tcps_rcvdupack); - /* - * If we have outstanding data (other than - * a window probe), this is a completely - * duplicate ack (ie, window info didn't - * change and FIN isn't set), - * the ack is the biggest we've - * seen and we've seen exactly our rexmt - * threshold of them, assume a packet - * has been dropped and retransmit it. - * Kludge snd_nxt & the congestion - * window so we send only this one - * packet. - * - * We know we're losing at the current - * window size so do congestion avoidance - * (set ssthresh to half the current window - * and pull our congestion window back to - * the new ssthresh). - * - * Dup acks mean that packets have left the - * network (they're now cached at the receiver) - * so bump cwnd by the amount in the receiver - * to keep a constant cwnd packets in the - * network. - * - * When using TCP ECN, notify the peer that - * we reduced the cwnd. - */ + } else { /* - * Following 2 kinds of acks should not affect - * dupack counting: - * 1) Old acks - * 2) Acks with SACK but without any new SACK - * information in them. These could result from - * any anomaly in the network like a switch - * duplicating packets or a possible DoS attack. + * If SEG.ACK == SND.UNA, RFC 5681 requires a + * duplicate ACK to have no data on it and to + * not be a window update. */ - if (th->th_ack != tp->snd_una || - (tcp_is_sack_recovery(tp, &to) && - (sack_changed == SACK_NOCHANGE))) { + if (!no_data || tiwin != tp->snd_wnd) { break; - } else if (!tcp_timer_active(tp, TT_REXMT)) { - tp->t_dupacks = 0; - } else if (++tp->t_dupacks > tcprexmtthresh || - IN_FASTRECOVERY(tp->t_flags)) { - cc_ack_received(tp, th, nsegs, - CC_DUPACK); - if (V_tcp_do_prr && + } + } + /* + * If this is the first time we've seen a + * FIN from the remote, this is not a + * duplicate ACK and it needs to be processed + * normally. + * This happens during a simultaneous close. + */ + if ((thflags & TH_FIN) && + (TCPS_HAVERCVDFIN(tp->t_state) == 0)) { + tp->t_dupacks = 0; + break; + } + /* Perform duplicate ACK processing. */ + TCPSTAT_INC(tcps_rcvdupack); + maxseg = tcp_maxseg(tp); + if (!tcp_timer_active(tp, TT_REXMT)) { + tp->t_dupacks = 0; + } else if (++tp->t_dupacks > tcprexmtthresh || + IN_FASTRECOVERY(tp->t_flags)) { + cc_ack_received(tp, th, nsegs, CC_DUPACK); + if (V_tcp_do_prr && + IN_FASTRECOVERY(tp->t_flags) && + (tp->t_flags & TF_SACK_PERMIT)) { + tcp_do_prr_ack(tp, th, &to, + sack_changed, &maxseg); + } else if (tcp_is_sack_recovery(tp, &to) && IN_FASTRECOVERY(tp->t_flags) && - (tp->t_flags & TF_SACK_PERMIT)) { - tcp_do_prr_ack(tp, th, &to, - sack_changed, &maxseg); - } else if (tcp_is_sack_recovery(tp, &to) && - IN_FASTRECOVERY(tp->t_flags) && - (tp->snd_nxt == tp->snd_max)) { - int awnd; + (tp->snd_nxt == tp->snd_max)) { + int awnd; - /* - * Compute the amount of data in flight first. - * We can inject new data into the pipe iff - * we have less than ssthresh - * worth of data in flight. - */ - awnd = tcp_compute_pipe(tp); - if (awnd < tp->snd_ssthresh) { - tp->snd_cwnd += imax(maxseg, - imin(2 * maxseg, - tp->sackhint.delivered_data)); - if (tp->snd_cwnd > tp->snd_ssthresh) - tp->snd_cwnd = tp->snd_ssthresh; - } - } else if (tcp_is_sack_recovery(tp, &to) && - IN_FASTRECOVERY(tp->t_flags) && - SEQ_LT(tp->snd_nxt, tp->snd_max)) { + /* + * Compute the amount of data in flight first. + * We can inject new data into the pipe iff + * we have less than ssthresh + * worth of data in flight. + */ + awnd = tcp_compute_pipe(tp); + if (awnd < tp->snd_ssthresh) { tp->snd_cwnd += imax(maxseg, imin(2 * maxseg, tp->sackhint.delivered_data)); - } else { - tp->snd_cwnd += maxseg; + if (tp->snd_cwnd > tp->snd_ssthresh) + tp->snd_cwnd = tp->snd_ssthresh; } - (void) tcp_output(tp); - goto drop; - } else if (tp->t_dupacks == tcprexmtthresh || - (tp->t_flags & TF_SACK_PERMIT && - V_tcp_do_newsack && - tp->sackhint.sacked_bytes > - (tcprexmtthresh - 1) * maxseg)) { + } else if (tcp_is_sack_recovery(tp, &to) && + IN_FASTRECOVERY(tp->t_flags) && + SEQ_LT(tp->snd_nxt, tp->snd_max)) { + tp->snd_cwnd += imax(maxseg, + imin(2 * maxseg, + tp->sackhint.delivered_data)); + } else { + tp->snd_cwnd += maxseg; + } + (void) tcp_output(tp); + goto drop; + } else if (tp->t_dupacks == tcprexmtthresh || + (tp->t_flags & TF_SACK_PERMIT && + V_tcp_do_newsack && + tp->sackhint.sacked_bytes > + (tcprexmtthresh - 1) * maxseg)) { enter_recovery: - /* - * Above is the RFC6675 trigger condition of - * more than (dupthresh-1)*maxseg sacked data. - * If the count of holes in the - * scoreboard is >= dupthresh, we could - * also enter loss recovery, but don't - * have that value readily available. - */ - tp->t_dupacks = tcprexmtthresh; - tcp_seq onxt = tp->snd_nxt; + /* + * Above is the RFC6675 trigger condition of + * more than (dupthresh-1)*maxseg sacked data. + * If the count of holes in the + * scoreboard is >= dupthresh, we could + * also enter loss recovery, but don't + * have that value readily available. + */ + tp->t_dupacks = tcprexmtthresh; + tcp_seq onxt = tp->snd_nxt; - /* - * If we're doing sack, check to - * see if we're already in sack - * recovery. If we're not doing sack, - * check to see if we're in newreno - * recovery. - */ - if (tcp_is_sack_recovery(tp, &to)) { - if (IN_FASTRECOVERY(tp->t_flags)) { - tp->t_dupacks = 0; - break; - } - } else { - if (SEQ_LEQ(th->th_ack, - tp->snd_recover)) { - tp->t_dupacks = 0; - break; - } + /* + * If we're doing sack, check to + * see if we're already in sack + * recovery. If we're not doing sack, + * check to see if we're in newreno + * recovery. + */ + if (tcp_is_sack_recovery(tp, &to)) { + if (IN_FASTRECOVERY(tp->t_flags)) { + tp->t_dupacks = 0; + break; } - /* Congestion signal before ack. */ - cc_cong_signal(tp, th, CC_NDUPACK); - cc_ack_received(tp, th, nsegs, - CC_DUPACK); - tcp_timer_activate(tp, TT_REXMT, 0); - tp->t_rtttime = 0; - if (V_tcp_do_prr) { - /* - * snd_ssthresh and snd_recover are - * already updated by cc_cong_signal. - */ - if (tcp_is_sack_recovery(tp, &to)) { - /* - * Include Limited Transmit - * segments here - */ - tp->sackhint.prr_delivered = - imin(tp->snd_max - th->th_ack, - (tp->snd_limited + 1) * maxseg); - } else { - tp->sackhint.prr_delivered = - maxseg; - } - tp->sackhint.recover_fs = max(1, - tp->snd_nxt - tp->snd_una); + } else { + if (SEQ_LEQ(th->th_ack, + tp->snd_recover)) { + tp->t_dupacks = 0; + break; } - tp->snd_limited = 0; + } + /* Congestion signal before ack. */ + cc_cong_signal(tp, th, CC_NDUPACK); + cc_ack_received(tp, th, nsegs, CC_DUPACK); + tcp_timer_activate(tp, TT_REXMT, 0); + tp->t_rtttime = 0; + if (V_tcp_do_prr) { + /* + * snd_ssthresh and snd_recover are + * already updated by cc_cong_signal. + */ if (tcp_is_sack_recovery(tp, &to)) { - TCPSTAT_INC(tcps_sack_recovery_episode); /* - * When entering LR after RTO due to - * Duplicate ACKs, retransmit existing - * holes from the scoreboard. + * Include Limited Transmit + * segments here */ - tcp_resend_sackholes(tp); - /* Avoid inflating cwnd in tcp_output */ - tp->snd_nxt = tp->snd_max; - tp->snd_cwnd = tcp_compute_pipe(tp) + + tp->sackhint.prr_delivered = + imin(tp->snd_max - th->th_ack, + (tp->snd_limited + 1) * maxseg); + } else { + tp->sackhint.prr_delivered = maxseg; - (void) tcp_output(tp); - /* Set cwnd to the expected flightsize */ - tp->snd_cwnd = tp->snd_ssthresh; - if (SEQ_GT(th->th_ack, tp->snd_una)) { - goto resume_partialack; - } - goto drop; } - tp->snd_nxt = th->th_ack; - tp->snd_cwnd = maxseg; - (void) tcp_output(tp); - KASSERT(tp->snd_limited <= 2, - ("%s: tp->snd_limited too big", - __func__)); - tp->snd_cwnd = tp->snd_ssthresh + - maxseg * - (tp->t_dupacks - tp->snd_limited); - if (SEQ_GT(onxt, tp->snd_nxt)) - tp->snd_nxt = onxt; - goto drop; - } else if (V_tcp_do_rfc3042) { - /* - * Process first and second duplicate - * ACKs. Each indicates a segment - * leaving the network, creating room - * for more. Make sure we can send a - * packet on reception of each duplicate - * ACK by increasing snd_cwnd by one - * segment. Restore the original - * snd_cwnd after packet transmission. - */ - cc_ack_received(tp, th, nsegs, CC_DUPACK); - uint32_t oldcwnd = tp->snd_cwnd; - tcp_seq oldsndmax = tp->snd_max; - u_int sent; - int avail; - - KASSERT(tp->t_dupacks == 1 || - tp->t_dupacks == 2, - ("%s: dupacks not 1 or 2", - __func__)); - if (tp->t_dupacks == 1) - tp->snd_limited = 0; - if ((tp->snd_nxt == tp->snd_max) && - (tp->t_rxtshift == 0)) - tp->snd_cwnd = - SEQ_SUB(tp->snd_nxt, - tp->snd_una) - - tcp_sack_adjust(tp); - tp->snd_cwnd += - (tp->t_dupacks - tp->snd_limited) * - maxseg - tcp_sack_adjust(tp); + tp->sackhint.recover_fs = max(1, + tp->snd_nxt - tp->snd_una); + } + tp->snd_limited = 0; + if (tcp_is_sack_recovery(tp, &to)) { + TCPSTAT_INC(tcps_sack_recovery_episode); /* - * Only call tcp_output when there - * is new data available to be sent - * or we need to send an ACK. + * When entering LR after RTO due to + * Duplicate ACKs, retransmit existing + * holes from the scoreboard. */ - SOCK_SENDBUF_LOCK(so); - avail = sbavail(&so->so_snd); - SOCK_SENDBUF_UNLOCK(so); - if (tp->t_flags & TF_ACKNOW || - (avail >= - SEQ_SUB(tp->snd_nxt, tp->snd_una))) { - (void) tcp_output(tp); - } - sent = SEQ_SUB(tp->snd_max, oldsndmax); - if (sent > maxseg) { - KASSERT((tp->t_dupacks == 2 && - tp->snd_limited == 0) || - (sent == maxseg + 1 && - tp->t_flags & TF_SENTFIN) || - (sent < 2 * maxseg && - tp->t_flags & TF_NODELAY), - ("%s: sent too much: %u>%u", - __func__, sent, maxseg)); - tp->snd_limited = 2; - } else if (sent > 0) { - ++tp->snd_limited; - } - tp->snd_cwnd = oldcwnd; + tcp_resend_sackholes(tp); + /* Avoid inflating cwnd in tcp_output */ + tp->snd_nxt = tp->snd_max; + tp->snd_cwnd = tcp_compute_pipe(tp) + + maxseg; + (void) tcp_output(tp); + /* Set cwnd to the expected flightsize */ + tp->snd_cwnd = tp->snd_ssthresh; goto drop; } - } - break; - } else { - /* - * This ack is advancing the left edge, reset the - * counter. - */ - tp->t_dupacks = 0; - /* - * If this ack also has new SACK info, increment the - * counter as per rfc6675. The variable - * sack_changed tracks all changes to the SACK - * scoreboard, including when partial ACKs without - * SACK options are received, and clear the scoreboard - * from the left side. Such partial ACKs should not be - * counted as dupacks here. - */ - if (tcp_is_sack_recovery(tp, &to) && - (((tp->t_rxtshift == 0) && (sack_changed != SACK_NOCHANGE)) || - ((tp->t_rxtshift > 0) && (sack_changed == SACK_NEWLOSS))) && - (tp->snd_nxt == tp->snd_max)) { - tp->t_dupacks++; - /* limit overhead by setting maxseg last */ - if (!IN_FASTRECOVERY(tp->t_flags) && - (tp->sackhint.sacked_bytes > - ((tcprexmtthresh - 1) * - (maxseg = tcp_maxseg(tp))))) { - goto enter_recovery; + tp->snd_nxt = th->th_ack; + tp->snd_cwnd = maxseg; + (void) tcp_output(tp); + KASSERT(tp->snd_limited <= 2, + ("%s: tp->snd_limited too big", + __func__)); + tp->snd_cwnd = tp->snd_ssthresh + + maxseg * + (tp->t_dupacks - tp->snd_limited); + if (SEQ_GT(onxt, tp->snd_nxt)) + tp->snd_nxt = onxt; + goto drop; + } else if (V_tcp_do_rfc3042) { + /* + * Process first and second duplicate + * ACKs. Each indicates a segment + * leaving the network, creating room + * for more. Make sure we can send a + * packet on reception of each duplicate + * ACK by increasing snd_cwnd by one + * segment. Restore the original + * snd_cwnd after packet transmission. + */ + cc_ack_received(tp, th, nsegs, CC_DUPACK); + uint32_t oldcwnd = tp->snd_cwnd; + tcp_seq oldsndmax = tp->snd_max; + u_int sent; + int avail; + + KASSERT(tp->t_dupacks == 1 || + tp->t_dupacks == 2, + ("%s: dupacks not 1 or 2", + __func__)); + if (tp->t_dupacks == 1) + tp->snd_limited = 0; + if ((tp->snd_nxt == tp->snd_max) && + (tp->t_rxtshift == 0)) + tp->snd_cwnd = + SEQ_SUB(tp->snd_nxt, tp->snd_una); + tp->snd_cwnd += + (tp->t_dupacks - tp->snd_limited) * maxseg; + tp->snd_cwnd -= tcp_sack_adjust(tp); + /* + * Only call tcp_output when there + * is new data available to be sent + * or we need to send an ACK. + */ + SOCK_SENDBUF_LOCK(so); + avail = sbavail(&so->so_snd); + SOCK_SENDBUF_UNLOCK(so); + if (tp->t_flags & TF_ACKNOW || + (avail >= + SEQ_SUB(tp->snd_nxt, tp->snd_una))) { + (void) tcp_output(tp); + } + sent = SEQ_SUB(tp->snd_max, oldsndmax); + if (sent > maxseg) { + KASSERT((tp->t_dupacks == 2 && + tp->snd_limited == 0) || + (sent == maxseg + 1 && + tp->t_flags & TF_SENTFIN) || + (sent < 2 * maxseg && + tp->t_flags & TF_NODELAY), + ("%s: sent too much: %u>%u", + __func__, sent, maxseg)); + tp->snd_limited = 2; + } else if (sent > 0) { + ++tp->snd_limited; } + tp->snd_cwnd = oldcwnd; + goto drop; } + break; } - -resume_partialack: KASSERT(SEQ_GT(th->th_ack, tp->snd_una), - ("%s: th_ack <= snd_una", __func__)); - + ("%s: SEQ_LEQ(th_ack, snd_una)", __func__)); + /* + * This ack is advancing the left edge, reset the + * counter. + */ + tp->t_dupacks = 0; + /* + * If this ack also has new SACK info, increment the + * t_dupacks as per RFC 6675. The variable + * sack_changed tracks all changes to the SACK + * scoreboard, including when partial ACKs without + * SACK options are received, and clear the scoreboard + * from the left side. Such partial ACKs should not be + * counted as dupacks here. + */ + if (V_tcp_do_newsack && + tcp_is_sack_recovery(tp, &to) && + (((tp->t_rxtshift == 0) && (sack_changed != SACK_NOCHANGE)) || + ((tp->t_rxtshift > 0) && (sack_changed == SACK_NEWLOSS))) && + (tp->snd_nxt == tp->snd_max)) { + tp->t_dupacks++; + /* limit overhead by setting maxseg last */ + if (!IN_FASTRECOVERY(tp->t_flags) && + (tp->sackhint.sacked_bytes > + (tcprexmtthresh - 1) * (maxseg = tcp_maxseg(tp)))) { + goto enter_recovery; + } + } /* * If the congestion window was inflated to account * for the other side's cached packets, retract it. diff --git a/sys/netinet/tcp_stacks/bbr.c b/sys/netinet/tcp_stacks/bbr.c index fed259f4d8e1..f2d7867df9b4 100644 --- a/sys/netinet/tcp_stacks/bbr.c +++ b/sys/netinet/tcp_stacks/bbr.c @@ -78,8 +78,6 @@ #include <netinet/in_kdtrace.h> #include <netinet/in_pcb.h> #include <netinet/ip.h> -#include <netinet/ip_icmp.h> /* required for icmp_var.h */ -#include <netinet/icmp_var.h> /* for ICMP_BANDLIM */ #include <netinet/ip_var.h> #include <netinet/ip6.h> #include <netinet6/in6_pcb.h> diff --git a/sys/netinet/tcp_stacks/rack.c b/sys/netinet/tcp_stacks/rack.c index 71dd4de6baf9..11ef5ba706c5 100644 --- a/sys/netinet/tcp_stacks/rack.c +++ b/sys/netinet/tcp_stacks/rack.c @@ -77,8 +77,6 @@ #include <netinet/in_kdtrace.h> #include <netinet/in_pcb.h> #include <netinet/ip.h> -#include <netinet/ip_icmp.h> /* required for icmp_var.h */ -#include <netinet/icmp_var.h> /* for ICMP_BANDLIM */ #include <netinet/ip_var.h> #include <netinet/ip6.h> #include <netinet6/in6_pcb.h> diff --git a/sys/netinet/tcp_stacks/rack_bbr_common.c b/sys/netinet/tcp_stacks/rack_bbr_common.c index fc12672a45f7..4a0a5fc118f6 100644 --- a/sys/netinet/tcp_stacks/rack_bbr_common.c +++ b/sys/netinet/tcp_stacks/rack_bbr_common.c @@ -76,8 +76,6 @@ #include <netinet/in_kdtrace.h> #include <netinet/in_pcb.h> #include <netinet/ip.h> -#include <netinet/ip_icmp.h> /* required for icmp_var.h */ -#include <netinet/icmp_var.h> /* for ICMP_BANDLIM */ #include <netinet/ip_var.h> #include <netinet/ip6.h> #include <netinet6/in6_pcb.h> diff --git a/sys/netinet/tcp_stacks/rack_pcm.c b/sys/netinet/tcp_stacks/rack_pcm.c index 759bfda98357..1a51097f627c 100644 --- a/sys/netinet/tcp_stacks/rack_pcm.c +++ b/sys/netinet/tcp_stacks/rack_pcm.c @@ -78,8 +78,6 @@ #include <netinet/in_kdtrace.h> #include <netinet/in_pcb.h> #include <netinet/ip.h> -#include <netinet/ip_icmp.h> /* required for icmp_var.h */ -#include <netinet/icmp_var.h> /* for ICMP_BANDLIM */ #include <netinet/ip_var.h> #include <netinet/ip6.h> #include <netinet6/in6_pcb.h> diff --git a/sys/netinet/tcp_stacks/tailq_hash.c b/sys/netinet/tcp_stacks/tailq_hash.c index 5ba3e7cd36c0..ff01640524b6 100644 --- a/sys/netinet/tcp_stacks/tailq_hash.c +++ b/sys/netinet/tcp_stacks/tailq_hash.c @@ -51,8 +51,6 @@ #include <netinet/in_kdtrace.h> #include <netinet/in_pcb.h> #include <netinet/ip.h> -#include <netinet/ip_icmp.h> /* required for icmp_var.h */ -#include <netinet/icmp_var.h> /* for ICMP_BANDLIM */ #include <netinet/ip_var.h> #include <netinet/ip6.h> #include <netinet6/in6_pcb.h> diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c index 80e6b53d10df..d617d0ed4aac 100644 --- a/sys/netinet/tcp_syncache.c +++ b/sys/netinet/tcp_syncache.c @@ -1294,7 +1294,6 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th, } else TCPSTAT_INC(tcps_sc_completed); -/* how do we find the inp for the new socket? */ if (sc != &scs) syncache_free(sc); return (1); diff --git a/sys/netlink/route/iface.c b/sys/netlink/route/iface.c index 8b871576d0b2..9beb80792af4 100644 --- a/sys/netlink/route/iface.c +++ b/sys/netlink/route/iface.c @@ -403,6 +403,7 @@ static const struct nlattr_parser nla_p_linfo[] = { NL_DECLARE_ATTR_PARSER(linfo_parser, nla_p_linfo); static const struct nlattr_parser nla_p_if[] = { + { .type = IFLA_ADDRESS, .off = _OUT(ifla_address), .cb = nlattr_get_nla }, { .type = IFLA_IFNAME, .off = _OUT(ifla_ifname), .cb = nlattr_get_string }, { .type = IFLA_MTU, .off = _OUT(ifla_mtu), .cb = nlattr_get_uint32 }, { .type = IFLA_LINK, .off = _OUT(ifla_link), .cb = nlattr_get_uint32 }, diff --git a/sys/netlink/route/iface_drivers.c b/sys/netlink/route/iface_drivers.c index 4bf913d9c978..4f1540740ead 100644 --- a/sys/netlink/route/iface_drivers.c +++ b/sys/netlink/route/iface_drivers.c @@ -82,26 +82,55 @@ _nl_modify_ifp_generic(struct ifnet *ifp, struct nl_parsed_link *lattrs, } } - if ((lattrs->ifi_change & IFF_UP) && (lattrs->ifi_flags & IFF_UP) == 0) { - /* Request to down the interface */ - if_down(ifp); + if ((lattrs->ifi_change & IFF_UP) != 0 || lattrs->ifi_change == 0) { + /* Request to up or down the interface */ + if (lattrs->ifi_flags & IFF_UP) + if_up(ifp); + else + if_down(ifp); } if (lattrs->ifla_mtu > 0) { if (nlp_has_priv(npt->nlp, PRIV_NET_SETIFMTU)) { struct ifreq ifr = { .ifr_mtu = lattrs->ifla_mtu }; - error = ifhwioctl(SIOCSIFMTU, ifp, (char *)&ifr, curthread); + error = ifhwioctl(SIOCSIFMTU, ifp, (char *)&ifr, + curthread); + if (error != 0) { + nlmsg_report_err_msg(npt, "Failed to set mtu"); + return (error); + } } else { nlmsg_report_err_msg(npt, "Not enough privileges to set mtu"); return (EPERM); } } - if (lattrs->ifi_change & IFF_PROMISC) { - error = ifpromisc(ifp, lattrs->ifi_flags & IFF_PROMISC); - if (error != 0) { - nlmsg_report_err_msg(npt, "unable to set promisc"); - return (error); + if ((lattrs->ifi_change & IFF_PROMISC) != 0 || + lattrs->ifi_change == 0) + /* + * When asking for IFF_PROMISC, set permanent flag instead + * (IFF_PPROMISC) as we have no way of doing promiscuity + * reference counting through ifpromisc(). Every call to this + * function either sets or unsets IFF_PROMISC, and ifi_change + * is usually set to 0xFFFFFFFF. + */ + if_setppromisc(ifp, (lattrs->ifi_flags & IFF_PROMISC) != 0); + + if (lattrs->ifla_address != NULL) { + if (nlp_has_priv(npt->nlp, PRIV_NET_SETIFMAC)) { + error = if_setlladdr(ifp, + NLA_DATA(lattrs->ifla_address), + NLA_DATA_LEN(lattrs->ifla_address)); + if (error != 0) { + nlmsg_report_err_msg(npt, + "setting IFLA_ADDRESS failed with error code: %d", + error); + return (error); + } + } else { + nlmsg_report_err_msg(npt, + "Not enough privileges to set IFLA_ADDRESS"); + return (EPERM); } } diff --git a/sys/netlink/route/route_var.h b/sys/netlink/route/route_var.h index b84b34461e35..41f110038b54 100644 --- a/sys/netlink/route/route_var.h +++ b/sys/netlink/route/route_var.h @@ -69,6 +69,7 @@ struct nl_parsed_link { char *ifla_cloner; char *ifla_ifalias; struct nlattr *ifla_idata; + struct nlattr *ifla_address; unsigned short ifi_type; int ifi_index; uint32_t ifla_link; diff --git a/sys/sys/mount.h b/sys/sys/mount.h index f6480b173a5c..18f85192f6c3 100644 --- a/sys/sys/mount.h +++ b/sys/sys/mount.h @@ -1007,6 +1007,7 @@ struct mntarg *mount_argsu(struct mntarg *ma, const char *name, const void *val, void statfs_scale_blocks(struct statfs *sf, long max_size); struct vfsconf *vfs_byname(const char *); struct vfsconf *vfs_byname_kld(const char *, struct thread *td, int *); +void vfs_unref_vfsconf(struct vfsconf *vfsp); void vfs_mount_destroy(struct mount *); void vfs_event_signal(fsid_t *, u_int32_t, intptr_t); void vfs_freeopts(struct vfsoptlist *opts); diff --git a/sys/ufs/ffs/ffs_rawread.c b/sys/ufs/ffs/ffs_rawread.c index 9db0bee0d66d..ef0b2ff4f788 100644 --- a/sys/ufs/ffs/ffs_rawread.c +++ b/sys/ufs/ffs/ffs_rawread.c @@ -281,7 +281,7 @@ ffs_rawread_main(struct vnode *vp, if (error != 0) break; - if (resid > bp->b_bufsize) { /* Setup fist readahead */ + if (resid > bp->b_bufsize) { /* Setup first readahead */ if (rawreadahead != 0) nbp = uma_zalloc(ffsraw_pbuf_zone, M_NOWAIT); diff --git a/sys/vm/vm_extern.h b/sys/vm/vm_extern.h index 93ec6014c27d..2b15a01206a2 100644 --- a/sys/vm/vm_extern.h +++ b/sys/vm/vm_extern.h @@ -91,6 +91,8 @@ void vm_fault_copy_entry(vm_map_t, vm_map_t, vm_map_entry_t, vm_map_entry_t, vm_ooffset_t *); int vm_fault_disable_pagefaults(void); void vm_fault_enable_pagefaults(int save); +int vm_fault_hold_pages_e(vm_map_t map, vm_offset_t addr, vm_size_t len, + vm_prot_t prot, vm_page_t *ma, int max_count, int *ppages_count); int vm_fault_quick_hold_pages(vm_map_t map, vm_offset_t addr, vm_size_t len, vm_prot_t prot, vm_page_t *ma, int max_count); int vm_fault_trap(vm_map_t map, vm_offset_t vaddr, vm_prot_t fault_type, diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c index 3e57e8d4f1d0..2a27f3e674a4 100644 --- a/sys/vm/vm_fault.c +++ b/sys/vm/vm_fault.c @@ -1995,32 +1995,43 @@ vm_fault_prefault(const struct faultstate *fs, vm_offset_t addra, } /* - * Hold each of the physical pages that are mapped by the specified range of - * virtual addresses, ["addr", "addr" + "len"), if those mappings are valid - * and allow the specified types of access, "prot". If all of the implied - * pages are successfully held, then the number of held pages is returned - * together with pointers to those pages in the array "ma". However, if any - * of the pages cannot be held, -1 is returned. + * Hold each of the physical pages that are mapped by the specified + * range of virtual addresses, ["addr", "addr" + "len"), if those + * mappings are valid and allow the specified types of access, "prot". + * If all of the implied pages are successfully held, then the number + * of held pages is assigned to *ppages_count, together with pointers + * to those pages in the array "ma". The returned value is zero. + * + * However, if any of the pages cannot be held, an error is returned, + * and no pages are held. + * Error values: + * ENOMEM - the range is not valid + * EINVAL - the provided vm_page array is too small to hold all pages + * EAGAIN - a page was not mapped, and the thread is in nofaulting mode + * EFAULT - a page with requested permissions cannot be mapped + * (more detailed result from vm_fault() is lost) */ int -vm_fault_quick_hold_pages(vm_map_t map, vm_offset_t addr, vm_size_t len, - vm_prot_t prot, vm_page_t *ma, int max_count) +vm_fault_hold_pages_e(vm_map_t map, vm_offset_t addr, vm_size_t len, + vm_prot_t prot, vm_page_t *ma, int max_count, int *ppages_count) { vm_offset_t end, va; vm_page_t *mp; - int count; + int count, error; boolean_t pmap_failed; - if (len == 0) + if (len == 0) { + *ppages_count = 0; return (0); + } end = round_page(addr + len); addr = trunc_page(addr); if (!vm_map_range_valid(map, addr, end)) - return (-1); + return (ENOMEM); if (atop(end - addr) > max_count) - panic("vm_fault_quick_hold_pages: count > max_count"); + return (EINVAL); count = atop(end - addr); /* @@ -2062,19 +2073,49 @@ vm_fault_quick_hold_pages(vm_map_t map, vm_offset_t addr, vm_size_t len, * the proper behaviour explicitly. */ if ((prot & VM_PROT_QUICK_NOFAULT) != 0 && - (curthread->td_pflags & TDP_NOFAULTING) != 0) - goto error; - for (mp = ma, va = addr; va < end; mp++, va += PAGE_SIZE) + (curthread->td_pflags & TDP_NOFAULTING) != 0) { + error = EAGAIN; + goto fail; + } + for (mp = ma, va = addr; va < end; mp++, va += PAGE_SIZE) { if (*mp == NULL && vm_fault(map, va, prot, - VM_FAULT_NORMAL, mp) != KERN_SUCCESS) - goto error; + VM_FAULT_NORMAL, mp) != KERN_SUCCESS) { + error = EFAULT; + goto fail; + } + } } - return (count); -error: + *ppages_count = count; + return (0); +fail: for (mp = ma; mp < ma + count; mp++) if (*mp != NULL) vm_page_unwire(*mp, PQ_INACTIVE); - return (-1); + return (error); +} + + /* + * Hold each of the physical pages that are mapped by the specified range of + * virtual addresses, ["addr", "addr" + "len"), if those mappings are valid + * and allow the specified types of access, "prot". If all of the implied + * pages are successfully held, then the number of held pages is returned + * together with pointers to those pages in the array "ma". However, if any + * of the pages cannot be held, -1 is returned. + */ +int +vm_fault_quick_hold_pages(vm_map_t map, vm_offset_t addr, vm_size_t len, + vm_prot_t prot, vm_page_t *ma, int max_count) +{ + int error, pages_count; + + error = vm_fault_hold_pages_e(map, addr, len, prot, ma, + max_count, &pages_count); + if (error != 0) { + if (error == EINVAL) + panic("vm_fault_quick_hold_pages: count > max_count"); + return (-1); + } + return (pages_count); } /* |