aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorAlan Somers <asomers@FreeBSD.org>2019-06-27 23:50:54 +0000
committerAlan Somers <asomers@FreeBSD.org>2019-06-27 23:50:54 +0000
commit7f49ce7a0b5f0d501d233308d73ccb1bf191a68b (patch)
treee83ad4ddd396607f9b0ea1a3a8262ce92aa3fcf9 /sys
parentc1afff113ceec2c78b96b2e52379cb5a9275d5fb (diff)
parente3680954376d380b897066a542ba7cf0b7ba9124 (diff)
Notes
Diffstat (limited to 'sys')
-rw-r--r--sys/amd64/amd64/pmap.c133
-rw-r--r--sys/amd64/conf/GENERIC1
-rw-r--r--sys/amd64/conf/MINIMAL3
-rw-r--r--sys/amd64/sgx/sgx.c2
-rw-r--r--sys/amd64/vmm/vmm_instruction_emul.c95
-rw-r--r--sys/arm/allwinner/files.allwinner1
-rw-r--r--sys/arm/conf/ALPINE1
-rw-r--r--sys/arm/conf/ARMADA38X1
-rw-r--r--sys/arm/conf/ARMADAXP1
-rw-r--r--sys/arm/conf/DB-78XXX5
-rw-r--r--sys/arm/conf/DB-88F5XXX1
-rw-r--r--sys/arm/conf/DB-88F6XXX5
-rw-r--r--sys/arm/conf/DOCKSTAR1
-rw-r--r--sys/arm/conf/DREAMPLUG-10019
-rw-r--r--sys/arm/conf/EFIKA_MX1
-rw-r--r--sys/arm/conf/GENERIC4
-rw-r--r--sys/arm/conf/IMX531
-rw-r--r--sys/arm/conf/IMX61
-rw-r--r--sys/arm/conf/NOTES61
-rw-r--r--sys/arm/conf/NOTES.armv533
-rw-r--r--sys/arm/conf/NOTES.armv764
-rw-r--r--sys/arm/conf/RPI-B1
-rw-r--r--sys/arm/conf/RT13101
-rw-r--r--sys/arm/conf/SHEEVAPLUG5
-rw-r--r--sys/arm/conf/SOCFPGA1
-rw-r--r--sys/arm/conf/TEGRA1241
-rw-r--r--sys/arm/conf/TS78001
-rw-r--r--sys/arm/conf/VERSATILEPB1
-rw-r--r--sys/arm/conf/VYBRID5
-rw-r--r--sys/arm/conf/ZEDBOARD1
-rw-r--r--sys/arm/freescale/vybrid/vf_nfc.c528
-rw-r--r--sys/arm/mv/files.arm71
-rw-r--r--sys/arm/mv/files.mv1
-rw-r--r--sys/arm/ti/am335x/am335x_ehrpwm.c308
-rw-r--r--sys/arm64/acpica/acpi_iort.c34
-rw-r--r--sys/arm64/arm64/freebsd32_machdep.c10
-rw-r--r--sys/arm64/arm64/gic_v3.c4
-rw-r--r--sys/arm64/arm64/gic_v3_var.h3
-rw-r--r--sys/arm64/arm64/gicv3_its.c4
-rw-r--r--sys/arm64/arm64/machdep.c31
-rw-r--r--sys/arm64/arm64/pmap.c129
-rw-r--r--sys/arm64/conf/GENERIC1
-rw-r--r--sys/cam/ata/ata_all.c25
-rw-r--r--sys/cam/ata/ata_all.h1
-rw-r--r--sys/cam/ata/ata_xpt.c23
-rw-r--r--sys/cam/cam_xpt.c101
-rw-r--r--sys/cam/ctl/ctl_error.c6
-rw-r--r--sys/cam/scsi/scsi_all.c4
-rw-r--r--sys/cam/scsi/scsi_da.c19
-rw-r--r--sys/cam/scsi/scsi_enc.c49
-rw-r--r--sys/cam/scsi/scsi_enc.h36
-rw-r--r--sys/cam/scsi/scsi_enc_internal.h25
-rw-r--r--sys/cam/scsi/scsi_enc_safte.c27
-rw-r--r--sys/cam/scsi/scsi_enc_ses.c296
-rw-r--r--sys/cam/scsi/scsi_ses.h31
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_objset.c19
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/multilist.c22
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/multilist.h2
-rw-r--r--sys/compat/linuxkpi/common/include/asm/atomic-long.h1
-rw-r--r--sys/compat/linuxkpi/common/include/linux/rculist.h27
-rw-r--r--sys/conf/NOTES24
-rw-r--r--sys/conf/files55
-rw-r--r--sys/conf/files.amd643
-rw-r--r--sys/conf/files.arm6
-rw-r--r--sys/conf/files.arm642
-rw-r--r--sys/conf/files.powerpc4
-rw-r--r--sys/conf/kern.opts.mk1
-rw-r--r--sys/conf/makeLINT.mk5
-rw-r--r--sys/conf/options8
-rw-r--r--sys/contrib/ipfilter/netinet/fil.c42
-rw-r--r--sys/contrib/ipfilter/netinet/ip_compat.h185
-rw-r--r--sys/contrib/ipfilter/netinet/ip_fil.h1
-rw-r--r--sys/ddb/db_ps.c2
-rw-r--r--sys/dev/ahci/ahci.c48
-rw-r--r--sys/dev/ahci/ahci.h8
-rw-r--r--sys/dev/ahci/ahciem.c125
-rw-r--r--sys/dev/altera/msgdma/msgdma.c13
-rw-r--r--sys/dev/altera/msgdma/msgdma.h64
-rw-r--r--sys/dev/cxgbe/tom/t4_cpl_io.c25
-rw-r--r--sys/dev/cxgbe/tom/t4_ddp.c2
-rw-r--r--sys/dev/cxgbe/tom/t4_tom.h2
-rw-r--r--sys/dev/drm2/ttm/ttm_bo_vm.c2
-rw-r--r--sys/dev/gpio/gpiobus.c185
-rw-r--r--sys/dev/gpio/gpiobusvar.h14
-rw-r--r--sys/dev/gpio/ofw_gpiobus.c4
-rw-r--r--sys/dev/iicbus/ad7418.c9
-rw-r--r--sys/dev/nand/nand.c826
-rw-r--r--sys/dev/nand/nand.h415
-rw-r--r--sys/dev/nand/nand_bbt.c275
-rw-r--r--sys/dev/nand/nand_cdev.c454
-rw-r--r--sys/dev/nand/nand_dev.h92
-rw-r--r--sys/dev/nand/nand_ecc_pos.h58
-rw-r--r--sys/dev/nand/nand_generic.c1366
-rw-r--r--sys/dev/nand/nand_geom.c467
-rw-r--r--sys/dev/nand/nand_id.c70
-rw-r--r--sys/dev/nand/nand_if.m168
-rw-r--r--sys/dev/nand/nandbus.c542
-rw-r--r--sys/dev/nand/nandbus.h51
-rw-r--r--sys/dev/nand/nandbus_if.m100
-rw-r--r--sys/dev/nand/nandsim.c670
-rw-r--r--sys/dev/nand/nandsim.h177
-rw-r--r--sys/dev/nand/nandsim_chip.c898
-rw-r--r--sys/dev/nand/nandsim_chip.h161
-rw-r--r--sys/dev/nand/nandsim_ctrl.c398
-rw-r--r--sys/dev/nand/nandsim_log.c188
-rw-r--r--sys/dev/nand/nandsim_log.h54
-rw-r--r--sys/dev/nand/nandsim_swap.c383
-rw-r--r--sys/dev/nand/nandsim_swap.h66
-rw-r--r--sys/dev/nand/nfc_fsl.c717
-rw-r--r--sys/dev/nand/nfc_fsl.h99
-rw-r--r--sys/dev/nand/nfc_if.m165
-rw-r--r--sys/dev/nand/nfc_mv.c238
-rw-r--r--sys/dev/nand/nfc_rb.c321
-rw-r--r--sys/dev/ow/owc_gpiobus.c6
-rw-r--r--sys/dev/usb/usb_hub_acpi.c17
-rw-r--r--sys/dev/virtio/scsi/virtio_scsi.c23
-rw-r--r--sys/fs/cuse/cuse.c47
-rw-r--r--sys/fs/fifofs/fifo_vnops.c2
-rw-r--r--sys/fs/nandfs/bmap.c625
-rw-r--r--sys/fs/nandfs/bmap.h42
-rw-r--r--sys/fs/nandfs/nandfs.h312
-rw-r--r--sys/fs/nandfs/nandfs_alloc.c366
-rw-r--r--sys/fs/nandfs/nandfs_bmap.c232
-rw-r--r--sys/fs/nandfs/nandfs_buffer.c85
-rw-r--r--sys/fs/nandfs/nandfs_cleaner.c622
-rw-r--r--sys/fs/nandfs/nandfs_cpfile.c778
-rw-r--r--sys/fs/nandfs/nandfs_dat.c346
-rw-r--r--sys/fs/nandfs/nandfs_dir.c316
-rw-r--r--sys/fs/nandfs/nandfs_fs.h567
-rw-r--r--sys/fs/nandfs/nandfs_ifile.c215
-rw-r--r--sys/fs/nandfs/nandfs_mount.h52
-rw-r--r--sys/fs/nandfs/nandfs_segment.c1314
-rw-r--r--sys/fs/nandfs/nandfs_subr.c1091
-rw-r--r--sys/fs/nandfs/nandfs_subr.h240
-rw-r--r--sys/fs/nandfs/nandfs_sufile.c571
-rw-r--r--sys/fs/nandfs/nandfs_vfsops.c1601
-rw-r--r--sys/fs/nandfs/nandfs_vnops.c2454
-rw-r--r--sys/fs/smbfs/smbfs_io.c4
-rw-r--r--sys/geom/geom_flashmap.c24
-rw-r--r--sys/i386/conf/GENERIC1
-rw-r--r--sys/i386/conf/MINIMAL3
-rw-r--r--sys/kern/Make.tags.inc2
-rw-r--r--sys/kern/kern_descrip.c4
-rw-r--r--sys/kern/kern_mib.c3
-rw-r--r--sys/kern/kern_rangelock.c71
-rw-r--r--sys/kern/kern_sig.c19
-rw-r--r--sys/kern/sys_pipe.c2
-rw-r--r--sys/kern/uipc_socket.c2
-rw-r--r--sys/kern/vfs_vnops.c5
-rw-r--r--sys/mips/conf/BCM1
-rw-r--r--sys/mips/conf/BERI_DE4_BASE1
-rw-r--r--sys/mips/conf/DIR-825B11
-rw-r--r--sys/mips/conf/ERL1
-rw-r--r--sys/mips/conf/JZ47801
-rw-r--r--sys/mips/conf/OCTEON11
-rw-r--r--sys/mips/conf/PB921
-rw-r--r--sys/mips/conf/PICOSTATION_M2HP3
-rw-r--r--sys/mips/conf/WZR-300HP2
-rw-r--r--sys/mips/conf/WZR-HPAG300H2
-rw-r--r--sys/mips/conf/X10001
-rw-r--r--sys/mips/conf/std.AR53121
-rw-r--r--sys/mips/conf/std.AR53151
-rw-r--r--sys/mips/conf/std.AR_MIPS_BASE3
-rw-r--r--sys/mips/conf/std.BERI1
-rw-r--r--sys/mips/conf/std.MALTA1
-rw-r--r--sys/mips/conf/std.XLP1
-rw-r--r--sys/mips/mediatek/std.mediatek3
-rw-r--r--sys/mips/mediatek/std.rt28803
-rw-r--r--sys/modules/Makefile7
-rw-r--r--sys/modules/nand/Makefile10
-rw-r--r--sys/modules/nandfs/Makefile12
-rw-r--r--sys/modules/nandsim/Makefile9
-rw-r--r--sys/net/if_vxlan.c2
-rw-r--r--sys/net/iflib.c19
-rw-r--r--sys/net/vnet.h3
-rw-r--r--sys/netinet/in.h6
-rw-r--r--sys/netinet/in_mcast.c431
-rw-r--r--sys/netinet/in_pcb.c32
-rw-r--r--sys/netinet/in_var.h52
-rw-r--r--sys/netinet/ip_carp.c98
-rw-r--r--sys/netinet/ip_fw.h1
-rw-r--r--sys/netinet/ip_mroute.c5
-rw-r--r--sys/netinet/ip_output.c13
-rw-r--r--sys/netinet/ip_var.h10
-rw-r--r--sys/netinet/tcp_subr.c6
-rw-r--r--sys/netinet6/in6.h5
-rw-r--r--sys/netinet6/in6_ifattach.c2
-rw-r--r--sys/netinet6/in6_mcast.c435
-rw-r--r--sys/netinet6/in6_pcb.c25
-rw-r--r--sys/netinet6/in6_var.h52
-rw-r--r--sys/netinet6/ip6_var.h11
-rw-r--r--sys/netipsec/key.c2
-rw-r--r--sys/netpfil/ipfw/ip_fw2.c48
-rw-r--r--sys/netpfil/ipfw/ip_fw_sockopt.c5
-rw-r--r--sys/netpfil/pf/if_pfsync.c45
-rw-r--r--sys/powerpc/conf/GENERIC1
-rw-r--r--sys/powerpc/conf/GENERIC641
-rw-r--r--sys/powerpc/conf/MPC85XX1
-rw-r--r--sys/powerpc/conf/MPC85XXSPE1
-rw-r--r--sys/powerpc/conf/QORIQ641
-rw-r--r--sys/powerpc/conf/dpaa/DPAA1
-rw-r--r--sys/powerpc/include/trap.h2
-rw-r--r--sys/powerpc/powerpc/machdep.c13
-rw-r--r--sys/powerpc/powerpc/trap.c14
-rw-r--r--sys/riscv/conf/GENERIC1
-rw-r--r--sys/sparc64/conf/GENERIC1
-rw-r--r--sys/sys/_types.h1
-rw-r--r--sys/sys/boot.h2
-rw-r--r--sys/sys/file.h5
-rw-r--r--sys/sys/filio.h12
-rw-r--r--sys/sys/mman.h8
-rw-r--r--sys/sys/param.h2
-rw-r--r--sys/sys/pcpu.h3
-rw-r--r--sys/sys/pmckern.h2
-rw-r--r--sys/sys/random.h25
-rw-r--r--sys/sys/rangelock.h4
-rw-r--r--sys/sys/types.h2
-rw-r--r--sys/sys/vnode.h4
-rw-r--r--sys/ufs/ffs/ffs_softdep.c23
-rw-r--r--sys/vm/device_pager.c2
-rw-r--r--sys/vm/vm_fault.c2
-rw-r--r--sys/vm/vm_map.c6
-rw-r--r--sys/vm/vm_mmap.c45
-rw-r--r--sys/vm/vm_object.c8
-rw-r--r--sys/vm/vm_page.c15
-rw-r--r--sys/vm/vm_page.h2
226 files changed, 2642 insertions, 23474 deletions
diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c
index d7a35b5c9cfc0..a0a2eb0baa6bb 100644
--- a/sys/amd64/amd64/pmap.c
+++ b/sys/amd64/amd64/pmap.c
@@ -484,6 +484,9 @@ static struct pmap_invl_gen pmap_invl_gen_head = {
.next = NULL,
};
static u_long pmap_invl_gen = 1;
+static int pmap_invl_waiters;
+static struct callout pmap_invl_callout;
+static bool pmap_invl_callout_inited;
#define PMAP_ASSERT_NOT_IN_DI() \
KASSERT(pmap_not_in_di(), ("DI already started"))
@@ -538,6 +541,34 @@ pmap_thread_init_invl_gen_l(struct thread *td)
invl_gen->gen = 0;
}
+static void
+pmap_delayed_invl_wait_block(u_long *m_gen, u_long *invl_gen)
+{
+ struct turnstile *ts;
+
+ ts = turnstile_trywait(&invl_gen_ts);
+ if (*m_gen > atomic_load_long(invl_gen))
+ turnstile_wait(ts, NULL, TS_SHARED_QUEUE);
+ else
+ turnstile_cancel(ts);
+}
+
+static void
+pmap_delayed_invl_finish_unblock(u_long new_gen)
+{
+ struct turnstile *ts;
+
+ turnstile_chain_lock(&invl_gen_ts);
+ ts = turnstile_lookup(&invl_gen_ts);
+ if (new_gen != 0)
+ pmap_invl_gen = new_gen;
+ if (ts != NULL) {
+ turnstile_broadcast(ts, TS_SHARED_QUEUE);
+ turnstile_unpend(ts);
+ }
+ turnstile_chain_unlock(&invl_gen_ts);
+}
+
/*
* Start a new Delayed Invalidation (DI) block of code, executed by
* the current thread. Within a DI block, the current thread may
@@ -582,24 +613,15 @@ static void
pmap_delayed_invl_finish_l(void)
{
struct pmap_invl_gen *invl_gen, *next;
- struct turnstile *ts;
invl_gen = &curthread->td_md.md_invl_gen;
KASSERT(invl_gen->gen != 0, ("missed invl_start"));
mtx_lock(&invl_gen_mtx);
next = LIST_NEXT(invl_gen, link);
- if (next == NULL) {
- turnstile_chain_lock(&invl_gen_ts);
- ts = turnstile_lookup(&invl_gen_ts);
- pmap_invl_gen = invl_gen->gen;
- if (ts != NULL) {
- turnstile_broadcast(ts, TS_SHARED_QUEUE);
- turnstile_unpend(ts);
- }
- turnstile_chain_unlock(&invl_gen_ts);
- } else {
+ if (next == NULL)
+ pmap_delayed_invl_finish_unblock(invl_gen->gen);
+ else
next->gen = invl_gen->gen;
- }
LIST_REMOVE(invl_gen, link);
mtx_unlock(&invl_gen_mtx);
invl_gen->gen = 0;
@@ -856,6 +878,8 @@ again:
goto again;
}
critical_exit();
+ if (atomic_load_int(&pmap_invl_waiters) > 0)
+ pmap_delayed_invl_finish_unblock(0);
if (invl_gen->saved_pri != 0) {
thread_lock(td);
sched_prio(td, invl_gen->saved_pri);
@@ -888,6 +912,9 @@ DB_SHOW_COMMAND(di_queue, pmap_di_queue)
static long invl_wait;
SYSCTL_LONG(_vm_pmap, OID_AUTO, invl_wait, CTLFLAG_RD, &invl_wait, 0,
"Number of times DI invalidation blocked pmap_remove_all/write");
+static long invl_wait_slow;
+SYSCTL_LONG(_vm_pmap, OID_AUTO, invl_wait_slow, CTLFLAG_RD, &invl_wait_slow, 0,
+ "Number of slow invalidation waits for lockless DI");
#endif
static u_long *
@@ -897,6 +924,27 @@ pmap_delayed_invl_genp(vm_page_t m)
return (&pv_invl_gen[pa_index(VM_PAGE_TO_PHYS(m)) % NPV_LIST_LOCKS]);
}
+static void
+pmap_delayed_invl_callout_func(void *arg __unused)
+{
+
+ if (atomic_load_int(&pmap_invl_waiters) == 0)
+ return;
+ pmap_delayed_invl_finish_unblock(0);
+}
+
+static void
+pmap_delayed_invl_callout_init(void *arg __unused)
+{
+
+ if (pmap_di_locked())
+ return;
+ callout_init(&pmap_invl_callout, 1);
+ pmap_invl_callout_inited = true;
+}
+SYSINIT(pmap_di_callout, SI_SUB_CPU + 1, SI_ORDER_ANY,
+ pmap_delayed_invl_callout_init, NULL);
+
/*
* Ensure that all currently executing DI blocks, that need to flush
* TLB for the given page m, actually flushed the TLB at the time the
@@ -914,7 +962,6 @@ pmap_delayed_invl_genp(vm_page_t m)
static void
pmap_delayed_invl_wait_l(vm_page_t m)
{
- struct turnstile *ts;
u_long *m_gen;
#ifdef PV_STATS
bool accounted = false;
@@ -928,11 +975,7 @@ pmap_delayed_invl_wait_l(vm_page_t m)
accounted = true;
}
#endif
- ts = turnstile_trywait(&invl_gen_ts);
- if (*m_gen > pmap_invl_gen)
- turnstile_wait(ts, NULL, TS_SHARED_QUEUE);
- else
- turnstile_cancel(ts);
+ pmap_delayed_invl_wait_block(m_gen, &pmap_invl_gen);
}
}
@@ -940,19 +983,53 @@ static void
pmap_delayed_invl_wait_u(vm_page_t m)
{
u_long *m_gen;
-#ifdef PV_STATS
- bool accounted = false;
-#endif
+ struct lock_delay_arg lda;
+ bool fast;
+ fast = true;
m_gen = pmap_delayed_invl_genp(m);
+ lock_delay_arg_init(&lda, &di_delay);
while (*m_gen > atomic_load_long(&pmap_invl_gen_head.gen)) {
-#ifdef PV_STATS
- if (!accounted) {
- atomic_add_long(&invl_wait, 1);
- accounted = true;
+ if (fast || !pmap_invl_callout_inited) {
+ PV_STAT(atomic_add_long(&invl_wait, 1));
+ lock_delay(&lda);
+ fast = false;
+ } else {
+ /*
+ * The page's invalidation generation number
+ * is still below the current thread's number.
+ * Prepare to block so that we do not waste
+ * CPU cycles or worse, suffer livelock.
+ *
+ * Since it is impossible to block without
+ * racing with pmap_delayed_invl_finish_u(),
+ * prepare for the race by incrementing
+ * pmap_invl_waiters and arming a 1-tick
+ * callout which will unblock us if we lose
+ * the race.
+ */
+ atomic_add_int(&pmap_invl_waiters, 1);
+
+ /*
+ * Re-check the current thread's invalidation
+ * generation after incrementing
+ * pmap_invl_waiters, so that there is no race
+ * with pmap_delayed_invl_finish_u() setting
+ * the page generation and checking
+ * pmap_invl_waiters. The only race allowed
+ * is for a missed unblock, which is handled
+ * by the callout.
+ */
+ if (*m_gen >
+ atomic_load_long(&pmap_invl_gen_head.gen)) {
+ callout_reset(&pmap_invl_callout, 1,
+ pmap_delayed_invl_callout_func, NULL);
+ PV_STAT(atomic_add_long(&invl_wait_slow, 1));
+ pmap_delayed_invl_wait_block(m_gen,
+ &pmap_invl_gen_head.gen);
+ }
+ atomic_add_int(&pmap_invl_waiters, -1);
}
-#endif
- kern_yield(PRI_USER);
}
}
@@ -4921,6 +4998,7 @@ pmap_remove(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
pmap_delayed_invl_start();
PMAP_LOCK(pmap);
+ pmap_pkru_on_remove(pmap, sva, eva);
/*
* special handling of removing one page. a very
@@ -5014,7 +5092,6 @@ pmap_remove(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
out:
if (anyvalid)
pmap_invalidate_all(pmap);
- pmap_pkru_on_remove(pmap, sva, eva);
PMAP_UNLOCK(pmap);
pmap_delayed_invl_finish();
vm_page_free_pages_toq(&free, true);
diff --git a/sys/amd64/conf/GENERIC b/sys/amd64/conf/GENERIC
index 520f64734bb98..f04b60f3ca666 100644
--- a/sys/amd64/conf/GENERIC
+++ b/sys/amd64/conf/GENERIC
@@ -309,7 +309,6 @@ device wpi # Intel 3945ABG wireless NICs.
# Pseudo devices.
device crypto # core crypto support
device loop # Network loopback
-device random # Entropy device
device padlock_rng # VIA Padlock RNG
device rdrand_rng # Intel Bull Mountain RNG
device ether # Ethernet support
diff --git a/sys/amd64/conf/MINIMAL b/sys/amd64/conf/MINIMAL
index 481a7ce96e44a..211e00e7de46a 100644
--- a/sys/amd64/conf/MINIMAL
+++ b/sys/amd64/conf/MINIMAL
@@ -10,7 +10,7 @@
# some features (ACL, GJOURNAL) that GENERIC includes.
# o acpi as a module has been reported flakey and not well tested, so
# is included in the kernel.
-# o random is included due to uncertaty...
+# o (non-loaded) random is included due to uncertainty...
# o Many networking things are included
#
# For now, please run changes to these list past imp@freebsd.org
@@ -131,7 +131,6 @@ device agp # support several AGP chipsets
# Pseudo devices.
device loop # Network loopback
-device random # Entropy device
device padlock_rng # VIA Padlock RNG
device rdrand_rng # Intel Bull Mountain RNG
device ether # Ethernet support
diff --git a/sys/amd64/sgx/sgx.c b/sys/amd64/sgx/sgx.c
index d47d4a3596a50..3d45b60de3ef5 100644
--- a/sys/amd64/sgx/sgx.c
+++ b/sys/amd64/sgx/sgx.c
@@ -358,7 +358,7 @@ sgx_page_remove(struct sgx_softc *sc, vm_page_t p)
uint64_t offs;
vm_page_lock(p);
- vm_page_remove(p);
+ (void)vm_page_remove(p);
vm_page_unlock(p);
dprintf("%s: p->pidx %ld\n", __func__, p->pindex);
diff --git a/sys/amd64/vmm/vmm_instruction_emul.c b/sys/amd64/vmm/vmm_instruction_emul.c
index 230da1881ef0d..f3afa23d82812 100644
--- a/sys/amd64/vmm/vmm_instruction_emul.c
+++ b/sys/amd64/vmm/vmm_instruction_emul.c
@@ -78,6 +78,7 @@ enum {
VIE_OP_TYPE_BITTEST,
VIE_OP_TYPE_TWOB_GRP15,
VIE_OP_TYPE_ADD,
+ VIE_OP_TYPE_TEST,
VIE_OP_TYPE_LAST
};
@@ -221,6 +222,12 @@ static const struct vie_op one_byte_opcodes[256] = {
.op_byte = 0x8F,
.op_type = VIE_OP_TYPE_POP,
},
+ [0xF7] = {
+ /* XXX Group 3 extended opcode - not just TEST */
+ .op_byte = 0xF7,
+ .op_type = VIE_OP_TYPE_TEST,
+ .op_flags = VIE_OP_F_IMM,
+ },
[0xFF] = {
/* XXX Group 5 extended opcode - not just PUSH */
.op_byte = 0xFF,
@@ -450,6 +457,41 @@ getaddflags(int opsize, uint64_t x, uint64_t y)
return (getaddflags64(x, y));
}
+/*
+ * Return the status flags that would result from doing (x & y).
+ */
+#define GETANDFLAGS(sz) \
+static u_long \
+getandflags##sz(uint##sz##_t x, uint##sz##_t y) \
+{ \
+ u_long rflags; \
+ \
+ __asm __volatile("and %2,%1; pushfq; popq %0" : \
+ "=r" (rflags), "+r" (x) : "m" (y)); \
+ return (rflags); \
+} struct __hack
+
+GETANDFLAGS(8);
+GETANDFLAGS(16);
+GETANDFLAGS(32);
+GETANDFLAGS(64);
+
+static u_long
+getandflags(int opsize, uint64_t x, uint64_t y)
+{
+ KASSERT(opsize == 1 || opsize == 2 || opsize == 4 || opsize == 8,
+ ("getandflags: invalid operand size %d", opsize));
+
+ if (opsize == 1)
+ return (getandflags8(x, y));
+ else if (opsize == 2)
+ return (getandflags16(x, y));
+ else if (opsize == 4)
+ return (getandflags32(x, y));
+ else
+ return (getandflags64(x, y));
+}
+
static int
emulate_mov(void *vm, int vcpuid, uint64_t gpa, struct vie *vie,
mem_region_read_t memread, mem_region_write_t memwrite, void *arg)
@@ -1219,6 +1261,55 @@ emulate_cmp(void *vm, int vcpuid, uint64_t gpa, struct vie *vie,
}
static int
+emulate_test(void *vm, int vcpuid, uint64_t gpa, struct vie *vie,
+ mem_region_read_t memread, mem_region_write_t memwrite, void *arg)
+{
+ int error, size;
+ uint64_t op1, rflags, rflags2;
+
+ size = vie->opsize;
+ error = EINVAL;
+
+ switch (vie->op.op_byte) {
+ case 0xF7:
+ /*
+ * F7 /0 test r/m16, imm16
+ * F7 /0 test r/m32, imm32
+ * REX.W + F7 /0 test r/m64, imm32 sign-extended to 64
+ *
+ * Test mem (ModRM:r/m) with immediate and set status
+ * flags according to the results. The comparison is
+ * performed by anding the immediate from the first
+ * operand and then setting the status flags.
+ */
+ if ((vie->reg & 7) != 0)
+ return (EINVAL);
+
+ error = memread(vm, vcpuid, gpa, &op1, size, arg);
+ if (error)
+ return (error);
+
+ rflags2 = getandflags(size, op1, vie->immediate);
+ break;
+ default:
+ return (EINVAL);
+ }
+ error = vie_read_register(vm, vcpuid, VM_REG_GUEST_RFLAGS, &rflags);
+ if (error)
+ return (error);
+
+ /*
+ * OF and CF are cleared; the SF, ZF and PF flags are set according
+ * to the result; AF is undefined.
+ */
+ rflags &= ~RFLAGS_STATUS_BITS;
+ rflags |= rflags2 & (PSL_PF | PSL_Z | PSL_N);
+
+ error = vie_update_register(vm, vcpuid, VM_REG_GUEST_RFLAGS, rflags, 8);
+ return (error);
+}
+
+static int
emulate_add(void *vm, int vcpuid, uint64_t gpa, struct vie *vie,
mem_region_read_t memread, mem_region_write_t memwrite, void *arg)
{
@@ -1643,6 +1734,10 @@ vmm_emulate_instruction(void *vm, int vcpuid, uint64_t gpa, struct vie *vie,
error = emulate_add(vm, vcpuid, gpa, vie, memread,
memwrite, memarg);
break;
+ case VIE_OP_TYPE_TEST:
+ error = emulate_test(vm, vcpuid, gpa, vie,
+ memread, memwrite, memarg);
+ break;
default:
error = EINVAL;
break;
diff --git a/sys/arm/allwinner/files.allwinner b/sys/arm/allwinner/files.allwinner
index 73367b391c3ab..dd801c016d49a 100644
--- a/sys/arm/allwinner/files.allwinner
+++ b/sys/arm/allwinner/files.allwinner
@@ -28,7 +28,6 @@ dev/usb/controller/generic_ohci.c optional ohci
dev/usb/controller/generic_usb_if.m optional ohci
arm/allwinner/aw_sid.c optional aw_sid
arm/allwinner/aw_thermal.c optional aw_thermal
-dev/iicbus/sy8106a.c optional sy8106a
arm/allwinner/aw_cir.c optional aw_cir evdev
arm/allwinner/aw_reset.c standard
diff --git a/sys/arm/conf/ALPINE b/sys/arm/conf/ALPINE
index 6b35f120aefb7..76689b5805c9b 100644
--- a/sys/arm/conf/ALPINE
+++ b/sys/arm/conf/ALPINE
@@ -41,7 +41,6 @@ device al_udma # Universal DMA
# Pseudo devices
device loop
-device random
device pty
device md
device gpio
diff --git a/sys/arm/conf/ARMADA38X b/sys/arm/conf/ARMADA38X
index 29ea724172be5..b82c18d79c527 100644
--- a/sys/arm/conf/ARMADA38X
+++ b/sys/arm/conf/ARMADA38X
@@ -25,7 +25,6 @@ options SMP
options VM_KMEM_SIZE_MAX=0x9CCD000
# Pseudo devices
-device random
device pty
device loop
device md
diff --git a/sys/arm/conf/ARMADAXP b/sys/arm/conf/ARMADAXP
index 5e891e51fba78..7f73d69ece7a3 100644
--- a/sys/arm/conf/ARMADAXP
+++ b/sys/arm/conf/ARMADAXP
@@ -46,7 +46,6 @@ options NO_FFS_SNAPSHOT
options NO_SWAPPING
# Pseudo devices
-device random
device pty
device loop
device md
diff --git a/sys/arm/conf/DB-78XXX b/sys/arm/conf/DB-78XXX
index aa474bcc43a13..44df77cf45f1b 100644
--- a/sys/arm/conf/DB-78XXX
+++ b/sys/arm/conf/DB-78XXX
@@ -20,7 +20,6 @@ options GEOM_PART_BSD # BSD partition scheme
options GEOM_PART_MBR # MBR partition scheme
options TMPFS # Efficient memory filesystem
options FFS # Berkeley Fast Filesystem
-options NANDFS # NAND Filesystem
options NFSCL # Network Filesystem Client
options NFSLOCKD # Network Lock Manager
options NFS_ROOT # NFS usable as /, requires NFSCL
@@ -45,7 +44,6 @@ device pci
# Pseudo devices
device loop
device md
-device random
# Serial ports
device uart
@@ -75,9 +73,6 @@ device ds133x
# SATA
device mvs
-# NAND
-device nand
-
# GPIO
device gpio
diff --git a/sys/arm/conf/DB-88F5XXX b/sys/arm/conf/DB-88F5XXX
index 0199e8663336c..a13a7002332d7 100644
--- a/sys/arm/conf/DB-88F5XXX
+++ b/sys/arm/conf/DB-88F5XXX
@@ -44,7 +44,6 @@ device pci
# Pseudo devices
device md
device loop
-device random
# Serial ports
device uart
diff --git a/sys/arm/conf/DB-88F6XXX b/sys/arm/conf/DB-88F6XXX
index fa2810c971225..66a385ddbe408 100644
--- a/sys/arm/conf/DB-88F6XXX
+++ b/sys/arm/conf/DB-88F6XXX
@@ -17,7 +17,6 @@ options INET # InterNETworking
options INET6 # IPv6 communications protocols
options TCP_HHOOK # hhook(9) framework for TCP
options FFS # Berkeley Fast Filesystem
-options NANDFS # NAND Filesystem
options NFSCL # Network Filesystem Client
options NFSLOCKD # Network Lock Manager
options NFS_ROOT # NFS usable as /, requires NFSCL
@@ -46,7 +45,6 @@ device pci
# Pseudo devices
device loop
device md
-device random
# Serial ports
device uart
@@ -79,9 +77,6 @@ device twsi
# SATA
device mvs
-# NAND
-device nand
-
# GPIO
device gpio
diff --git a/sys/arm/conf/DOCKSTAR b/sys/arm/conf/DOCKSTAR
index 5684d29ef87b4..6f26d42908019 100644
--- a/sys/arm/conf/DOCKSTAR
+++ b/sys/arm/conf/DOCKSTAR
@@ -68,7 +68,6 @@ device gif # IPv6 and IPv4 tunneling
device loop # Network loopback
device md # Memory/malloc disk
device pty # BSD-style compatibility pseudo ttys
-device random # Entropy device
device tuntap # Packet tunnel.
device ether # Required for all ethernet devices
device vlan # 802.1Q VLAN support
diff --git a/sys/arm/conf/DREAMPLUG-1001 b/sys/arm/conf/DREAMPLUG-1001
index 5d6928470e5de..18b2dee86face 100644
--- a/sys/arm/conf/DREAMPLUG-1001
+++ b/sys/arm/conf/DREAMPLUG-1001
@@ -71,7 +71,6 @@ device gif # IPv6 and IPv4 tunneling
device loop # Network loopback
device md # Memory/malloc disk
device pty # BSD-style compatibility pseudo ttys
-device random # Entropy device
device tuntap # Packet tunnel.
device ether # Required for all ethernet devices
device vlan # 802.1Q VLAN support
@@ -158,14 +157,6 @@ options ALTQ_PRIQ # Priority Queueing
options ALTQ_NOPCC # Required if the TSC is unusable
#options ALTQ_DEBUG
-# To use this configuration with the (rare) model 1001N (nand flash),
-# create a kernel config file that looks like this:
-#
-# include DREAMPLUG-1001
-# nomakeoptions FDT_DTS_FILE
-# makeoptions FDT_DTS_FILE=dreamplug-1001N.dts
-# device nand
-
# Flattened Device Tree
options FDT # Configure using FDT/DTB data
options FDT_DTB_STATIC
diff --git a/sys/arm/conf/EFIKA_MX b/sys/arm/conf/EFIKA_MX
index 248060b6cf049..be5f5f35570dc 100644
--- a/sys/arm/conf/EFIKA_MX
+++ b/sys/arm/conf/EFIKA_MX
@@ -57,7 +57,6 @@ device bpf # Berkeley packet filter
# Pseudo devices.
device loop # Network loopback
-device random # Entropy device
device ether # Ethernet support
#device vlan # 802.1Q VLAN support
#device tuntap # Packet tunnel.
diff --git a/sys/arm/conf/GENERIC b/sys/arm/conf/GENERIC
index d32baa63a6673..34be5898c7eb8 100644
--- a/sys/arm/conf/GENERIC
+++ b/sys/arm/conf/GENERIC
@@ -121,7 +121,6 @@ device pl011
device pty
device snp
device md # Memory "disks"
-device random # Entropy device
device firmware # firmware assist module
device pl310 # PL310 L2 cache controller
device psci
@@ -175,6 +174,9 @@ device ti_spi
# ADC support
device ti_adc
+# PWM
+device pwm
+
# Watchdog support
# If we don't enable the watchdog driver, the BealeBone could potentially
# reboot automatically because the boot loader might have enabled the
diff --git a/sys/arm/conf/IMX53 b/sys/arm/conf/IMX53
index 7b7d67bbca9c9..be18afda6094b 100644
--- a/sys/arm/conf/IMX53
+++ b/sys/arm/conf/IMX53
@@ -44,7 +44,6 @@ device bpf # Berkeley packet filter
# Pseudo devices.
device loop # Network loopback
-device random # Entropy device
device ether # Ethernet support
#device vlan # 802.1Q VLAN support
#device tuntap # Packet tunnel.
diff --git a/sys/arm/conf/IMX6 b/sys/arm/conf/IMX6
index 3baf9f06f039f..4dbebdfccd1fa 100644
--- a/sys/arm/conf/IMX6
+++ b/sys/arm/conf/IMX6
@@ -49,7 +49,6 @@ device mpcore_timer
# Pseudo devices.
device loop # Network loopback
-device random # Entropy device
device vlan # 802.1Q VLAN support
device tuntap # Packet tunnel.
device md # Memory "disks"
diff --git a/sys/arm/conf/NOTES b/sys/arm/conf/NOTES
index 559146b580145..518cf4050ad92 100644
--- a/sys/arm/conf/NOTES
+++ b/sys/arm/conf/NOTES
@@ -1,44 +1,22 @@
# $FreeBSD$
-machine arm
-
-cpu CPU_ARM9E
-
-files "../mv/files.mv"
-files "../mv/discovery/files.db78xxx"
-files "../mv/kirkwood/files.kirkwood"
-files "../mv/orion/files.db88f5xxx"
-files "../mv/orion/files.ts7800"
-
-makeoptions CONF_CFLAGS+="-march=armv5te"
-makeoptions LDFLAGS="-zmuldefs"
-makeoptions KERNPHYSADDR=0x00000000
-
options FDT
-options SOC_MV_DISCOVERY
-options SOC_MV_KIRKWOOD
-options SOC_MV_ORION
-
-options ARM_MANY_BOARD
-device nand
-
-# IIC
-device twsi
-
-nooptions SMP
-nooptions MAXCPU
+# Undo options from sys/conf/NOTES that we do not want...
nooptions COMPAT_FREEBSD4
nooptions COMPAT_FREEBSD5
nooptions COMPAT_FREEBSD6
nooptions COMPAT_FREEBSD7
nooptions COMPAT_FREEBSD9
-nooption PPC_PROBE_CHIPSET
+nooptions PPC_PROBE_CHIPSET
+nooptions MAXCPU # value is set in machine/param.h
+
+# Devices in sys/conf/NOTES for which no such hardware exists on arm,
+# or the drivers don't compile...
nodevice fdc
nodevice sym
-nodevice ukbd
nodevice sc
nodevice blank_saver
@@ -58,28 +36,9 @@ nodevice cxgbe
nodevice cxgbev
nodevice snd_cmi
-#
-# Enable the kernel DTrace hooks which are required to load the DTrace
-# kernel modules.
-#
-options KDTRACE_HOOKS
-
-# DTrace core
-# NOTE: introduces CDDL-licensed components into the kernel
-#device dtrace
-
-# DTrace modules
-#device dtrace_profile
-#device dtrace_sdt
-#device dtrace_fbt
-#device dtrace_systrace
-#device dtrace_prototype
-#device dtnfscl
-#device dtmalloc
-
-# Alternatively include all the DTrace modules
-#device dtraceall
-
-# These aren't known to work on arm and/or don't compile
nodevice mpr
nodevice mps
+
+# Add devices which are specific to various arm platforms...
+
+device twsi # i2c controller on Marvel and Allwinner
diff --git a/sys/arm/conf/NOTES.armv5 b/sys/arm/conf/NOTES.armv5
new file mode 100644
index 0000000000000..1e8825980448d
--- /dev/null
+++ b/sys/arm/conf/NOTES.armv5
@@ -0,0 +1,33 @@
+# armv5-specific changes for doing a LINT build.
+#
+# The contents of sys/conf/NOTES, sys/arm/conf/NOTES, and this file are
+# concatenated (in that order) to create the LINT-V5 kernel config file.
+#
+# $FreeBSD$
+
+#NO_UNIVERSE
+
+machine arm arm
+cpu CPU_ARM9E
+
+files "../mv/files.mv"
+files "../mv/discovery/files.db78xxx"
+files "../mv/kirkwood/files.kirkwood"
+files "../mv/orion/files.db88f5xxx"
+files "../mv/orion/files.ts7800"
+
+makeoptions CONF_CFLAGS+="-march=armv5te"
+makeoptions LDFLAGS="-zmuldefs"
+makeoptions KERNPHYSADDR=0x00000000
+
+# Undo options from sys/conf/NOTES that we do not want...
+
+nooptions SMP # All armv5 are single-core
+
+# Add options for armv5 that are not in sys/conf/NOTES...
+
+options ARM_MANY_BOARD
+
+options SOC_MV_DISCOVERY
+options SOC_MV_KIRKWOOD
+options SOC_MV_ORION
diff --git a/sys/arm/conf/NOTES.armv7 b/sys/arm/conf/NOTES.armv7
new file mode 100644
index 0000000000000..e8a19034b001e
--- /dev/null
+++ b/sys/arm/conf/NOTES.armv7
@@ -0,0 +1,64 @@
+# armv7-specific changes for doing a LINT build.
+#
+# The contents of sys/conf/NOTES, sys/arm/conf/NOTES, and this file are
+# concatenated (in that order) to create the LINT-V7 kernel config file.
+#
+# $FreeBSD$
+
+
+#NO_UNIVERSE
+
+machine arm armv7
+cpu CPU_CORTEXA
+cpu CPU_MV_PJ4B
+makeoptions CONF_CFLAGS+="-march=armv7a"
+
+# Add options for armv7 that are not in sys/conf/NOTES...
+
+options ARM_L2_PIPT # Only L2 PIPT is supported
+options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8)
+options INTRNG # Include INTRNG framework
+options LINUX_BOOT_ABI # Process metadata passed from U-Boot
+options PLATFORM # Include platform_if support
+options SMP # Most v7 SoCs are multicore
+options VFP # Enable floating point hardware support
+
+# NOTE: dtrace introduces CDDL-licensed components into the kernel
+device dtrace # dtrace core
+device dtraceall # include all dtrace modules
+options KDTRACE_HOOKS
+
+# Add misc devices which are specific to various arm platforms...
+
+device generic_timer # ARM Generic Timer
+device gic # Interrupt controller
+device gpio # gpio interface and bus
+device mpcore_timer # ARM MPCore Timer
+device pl310 # PL310 L2 cache controller
+device pmu # PMU support (for CCNT).
+
+# Add EXT_RESOURCES pseudo devices...
+
+options EXT_RESOURCES
+device clk
+device phy
+device hwreset
+device nvmem
+device regulator
+device syscon
+
+# Build SOC-specific modules...
+
+makeoptions MODULES_EXTRA+="allwinner"
+makeoptions MODULES_EXTRA+="arm_ti"
+makeoptions MODULES_EXTRA+="imx"
+
+# Build dtb files...
+
+makeoptions MODULES_EXTRA+="dtb/allwinner"
+makeoptions MODULES_EXTRA+="dtb/am335x"
+makeoptions MODULES_EXTRA+="dtb/imx6"
+makeoptions MODULES_EXTRA+="dtb/nvidia"
+makeoptions MODULES_EXTRA+="dtb/omap4"
+makeoptions MODULES_EXTRA+="dtb/rpi"
+makeoptions MODULES_EXTRA+="dtb/zynq"
diff --git a/sys/arm/conf/RPI-B b/sys/arm/conf/RPI-B
index e1f132105c207..e456d33742b80 100644
--- a/sys/arm/conf/RPI-B
+++ b/sys/arm/conf/RPI-B
@@ -65,7 +65,6 @@ device iicbus
device bcm2835_bsc
device md
-device random # Entropy device
# USB support
device usb
diff --git a/sys/arm/conf/RT1310 b/sys/arm/conf/RT1310
index 3ade997821be8..08fde3516ac16 100644
--- a/sys/arm/conf/RT1310
+++ b/sys/arm/conf/RT1310
@@ -51,7 +51,6 @@ options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
device loop
device md
device pty
-device random
# Serial ports
device uart
diff --git a/sys/arm/conf/SHEEVAPLUG b/sys/arm/conf/SHEEVAPLUG
index ff60f82bcf60d..d7d161956ce43 100644
--- a/sys/arm/conf/SHEEVAPLUG
+++ b/sys/arm/conf/SHEEVAPLUG
@@ -19,7 +19,6 @@ options INET # InterNETworking
options INET6 # IPv6 communications protocols
options TCP_HHOOK # hhook(9) framework for TCP
options FFS # Berkeley Fast Filesystem
-options NANDFS # NAND Filesystem
options NFSCL # Network Filesystem Client
options NFSLOCKD # Network Lock Manager
options NFS_ROOT # NFS usable as /, requires NFSCL
@@ -46,7 +45,6 @@ options BOOTP_WIRED_TO=mge0
# Pseudo devices
device loop
-device random
# Serial ports
device uart
@@ -73,9 +71,6 @@ device scbus
device pass
device da
-# NAND
-device nand
-
# GPIO
device gpio
diff --git a/sys/arm/conf/SOCFPGA b/sys/arm/conf/SOCFPGA
index b740ef1b84c97..cd78e17e08a4a 100644
--- a/sys/arm/conf/SOCFPGA
+++ b/sys/arm/conf/SOCFPGA
@@ -58,7 +58,6 @@ device dwmmc
# Pseudo devices
device loop
-device random
device pty
device md
device gpio
diff --git a/sys/arm/conf/TEGRA124 b/sys/arm/conf/TEGRA124
index a830519d909e6..c44939b673015 100644
--- a/sys/arm/conf/TEGRA124
+++ b/sys/arm/conf/TEGRA124
@@ -43,7 +43,6 @@ device regulator
# Pseudo devices.
device loop # Network loopback
-device random # Entropy device
device vlan # 802.1Q VLAN support
#device tuntap # Packet tunnel.
device md # Memory "disks"
diff --git a/sys/arm/conf/TS7800 b/sys/arm/conf/TS7800
index 17b237af46ddd..15e9a77342d51 100644
--- a/sys/arm/conf/TS7800
+++ b/sys/arm/conf/TS7800
@@ -45,7 +45,6 @@ device pci
# Pseudo devices
device md
device loop
-device random
# Serial ports
device uart
diff --git a/sys/arm/conf/VERSATILEPB b/sys/arm/conf/VERSATILEPB
index 8c3e76cc2e874..3312f6d4f9e8a 100644
--- a/sys/arm/conf/VERSATILEPB
+++ b/sys/arm/conf/VERSATILEPB
@@ -66,7 +66,6 @@ options SC_DFLT_FONT # compile font in
makeoptions SC_DFLT_FONT=cp437
device md
-device random # Entropy device
options PLATFORM
diff --git a/sys/arm/conf/VYBRID b/sys/arm/conf/VYBRID
index 4ff18320df1ad..b114c6e3e9238 100644
--- a/sys/arm/conf/VYBRID
+++ b/sys/arm/conf/VYBRID
@@ -26,7 +26,6 @@ makeoptions WERROR="-Werror"
options SCHED_4BSD # 4BSD scheduler
options PLATFORM # Platform based SoC
-#options NANDFS # NAND Filesystem
#options SMP # Enable multiple cores
# NFS root from boopt/dhcp
@@ -37,7 +36,6 @@ options PLATFORM # Platform based SoC
#options BOOTP_WIRED_TO=ffec0
#options ROOTDEVNAME=\"nfs:10.5.0.1:/tftpboot/cosmic\"
-#options ROOTDEVNAME=\"nandfs:/dev/gnand0s.root\"
options ROOTDEVNAME=\"ufs:/dev/da0\"
options MUTEX_NOINLINE
@@ -59,7 +57,6 @@ device sdhci # generic sdhci
# Pseudo devices
device loop
-device random
device pty
device md
device gpio
@@ -81,8 +78,6 @@ device pass
#device atadisk
#device mvs
-device nand
-
# Serial ports
device uart
diff --git a/sys/arm/conf/ZEDBOARD b/sys/arm/conf/ZEDBOARD
index 274d96642d6b1..187d636c2e490 100644
--- a/sys/arm/conf/ZEDBOARD
+++ b/sys/arm/conf/ZEDBOARD
@@ -48,7 +48,6 @@ device pl310 # PL310 L2 cache controller
device mpcore_timer
device loop
-device random
device ether
device cgem # Zynq-7000 gig ethernet device
device mii
diff --git a/sys/arm/freescale/vybrid/vf_nfc.c b/sys/arm/freescale/vybrid/vf_nfc.c
deleted file mode 100644
index cdefa2564864f..0000000000000
--- a/sys/arm/freescale/vybrid/vf_nfc.c
+++ /dev/null
@@ -1,528 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2013 Ruslan Bukin <br@bsdpad.com>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/*
- * Vybrid Family NAND Flash Controller (NFC)
- * Chapter 31, Vybrid Reference Manual, Rev. 5, 07/2013
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/proc.h>
-#include <sys/bus.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-#include <sys/malloc.h>
-#include <sys/rman.h>
-#include <sys/lock.h>
-#include <sys/mutex.h>
-#include <sys/time.h>
-
-#include <dev/ofw/ofw_bus.h>
-#include <dev/ofw/ofw_bus_subr.h>
-#include <dev/nand/nand.h>
-#include <dev/nand/nandbus.h>
-
-#include <machine/bus.h>
-
-#include "nfc_if.h"
-
-#include <arm/freescale/vybrid/vf_common.h>
-
-enum addr_type {
- ADDR_NONE,
- ADDR_ID,
- ADDR_ROW,
- ADDR_ROWCOL
-};
-
-struct fsl_nfc_fcm {
- uint32_t addr_bits;
- enum addr_type addr_type;
- uint32_t col_addr_bits;
- uint32_t row_addr_bits;
- u_int read_ptr;
- u_int addr_ptr;
- u_int command;
- u_int code;
-};
-
-struct vf_nand_softc {
- struct nand_softc nand_dev;
- bus_space_handle_t bsh;
- bus_space_tag_t bst;
- struct resource *res[2];
- struct fsl_nfc_fcm fcm;
-};
-
-static struct resource_spec nfc_spec[] = {
- { SYS_RES_MEMORY, 0, RF_ACTIVE },
- { SYS_RES_IRQ, 0, RF_ACTIVE },
- { -1, 0 }
-};
-
-static int vf_nand_attach(device_t);
-static int vf_nand_probe(device_t);
-static int vf_nand_send_command(device_t, uint8_t);
-static int vf_nand_send_address(device_t, uint8_t);
-static int vf_nand_start_command(device_t);
-static uint8_t vf_nand_read_byte(device_t);
-static void vf_nand_read_buf(device_t, void *, uint32_t);
-static void vf_nand_write_buf(device_t, void *, uint32_t);
-static int vf_nand_select_cs(device_t, uint8_t);
-static int vf_nand_read_rnb(device_t);
-
-#define CMD_READ_PAGE 0x7EE0
-#define CMD_PROG_PAGE 0x7FC0
-#define CMD_PROG_PAGE_DMA 0xFFC8
-#define CMD_ERASE 0x4EC0
-#define CMD_READ_ID 0x4804
-#define CMD_READ_STATUS 0x4068
-#define CMD_RESET 0x4040
-#define CMD_RANDOM_IN 0x7140
-#define CMD_RANDOM_OUT 0x70E0
-
-#define CMD_BYTE2_PROG_PAGE 0x10
-#define CMD_BYTE2_PAGE_READ 0x30
-#define CMD_BYTE2_ERASE 0xD0
-
-#define NFC_CMD1 0x3F00 /* Flash command 1 */
-#define NFC_CMD2 0x3F04 /* Flash command 2 */
-#define NFC_CAR 0x3F08 /* Column address */
-#define NFC_RAR 0x3F0C /* Row address */
-#define NFC_RPT 0x3F10 /* Flash command repeat */
-#define NFC_RAI 0x3F14 /* Row address increment */
-#define NFC_SR1 0x3F18 /* Flash status 1 */
-#define NFC_SR2 0x3F1C /* Flash status 2 */
-#define NFC_DMA_CH1 0x3F20 /* DMA channel 1 address */
-#define NFC_DMACFG 0x3F24 /* DMA configuration */
-#define NFC_SWAP 0x3F28 /* Cach swap */
-#define NFC_SECSZ 0x3F2C /* Sector size */
-#define NFC_CFG 0x3F30 /* Flash configuration */
-#define NFC_DMA_CH2 0x3F34 /* DMA channel 2 address */
-#define NFC_ISR 0x3F38 /* Interrupt status */
-
-#define ECCMODE_SHIFT 17
-#define AIAD_SHIFT 5
-#define AIBN_SHIFT 4
-#define PAGECOUNT_SHIFT 0
-#define BITWIDTH_SHIFT 7
-#define BITWIDTH8 0
-#define BITWIDTH16 1
-#define PAGECOUNT_MASK 0xf
-
-#define CMD2_BYTE1_SHIFT 24
-#define CMD2_CODE_SHIFT 8
-#define CMD2_BUFNO_SHIFT 1
-#define CMD2_START_SHIFT 0
-
-static device_method_t vf_nand_methods[] = {
- DEVMETHOD(device_probe, vf_nand_probe),
- DEVMETHOD(device_attach, vf_nand_attach),
- DEVMETHOD(nfc_start_command, vf_nand_start_command),
- DEVMETHOD(nfc_send_command, vf_nand_send_command),
- DEVMETHOD(nfc_send_address, vf_nand_send_address),
- DEVMETHOD(nfc_read_byte, vf_nand_read_byte),
- DEVMETHOD(nfc_read_buf, vf_nand_read_buf),
- DEVMETHOD(nfc_write_buf, vf_nand_write_buf),
- DEVMETHOD(nfc_select_cs, vf_nand_select_cs),
- DEVMETHOD(nfc_read_rnb, vf_nand_read_rnb),
- { 0, 0 },
-};
-
-static driver_t vf_nand_driver = {
- "nand",
- vf_nand_methods,
- sizeof(struct vf_nand_softc),
-};
-
-static devclass_t vf_nand_devclass;
-DRIVER_MODULE(vf_nand, simplebus, vf_nand_driver, vf_nand_devclass, 0, 0);
-
-static int
-vf_nand_probe(device_t dev)
-{
-
- if (!ofw_bus_status_okay(dev))
- return (ENXIO);
-
- if (!ofw_bus_is_compatible(dev, "fsl,mvf600-nand"))
- return (ENXIO);
-
- device_set_desc(dev, "Vybrid Family NAND controller");
- return (BUS_PROBE_DEFAULT);
-}
-
-static int
-vf_nand_attach(device_t dev)
-{
- struct vf_nand_softc *sc;
- int err;
- int reg;
-
- sc = device_get_softc(dev);
- if (bus_alloc_resources(dev, nfc_spec, sc->res)) {
- device_printf(dev, "could not allocate resources!\n");
- return (ENXIO);
- }
-
- sc->bst = rman_get_bustag(sc->res[0]);
- sc->bsh = rman_get_bushandle(sc->res[0]);
-
- /* Size in bytes of one elementary transfer unit */
- WRITE4(sc, NFC_SECSZ, 2048);
-
- /* Flash mode width */
- reg = READ4(sc, NFC_CFG);
- reg |= (BITWIDTH16 << BITWIDTH_SHIFT);
-
- /* No correction, ECC bypass */
- reg &= ~(0x7 << ECCMODE_SHIFT);
-
- /* Disable Auto-incrementing of flash row address */
- reg &= ~(0x1 << AIAD_SHIFT);
-
- /* Disable Auto-incrementing of buffer numbers */
- reg &= ~(0x1 << AIBN_SHIFT);
-
- /*
- * Number of virtual pages (in one physical flash page)
- * to be programmed or read, etc.
- */
- reg &= ~(PAGECOUNT_MASK);
- reg |= (1 << PAGECOUNT_SHIFT);
- WRITE4(sc, NFC_CFG, reg);
-
- nand_init(&sc->nand_dev, dev, NAND_ECC_NONE, 0, 0, NULL, NULL);
- err = nandbus_create(dev);
- return (err);
-}
-
-static int
-vf_nand_start_command(device_t dev)
-{
- struct vf_nand_softc *sc;
- struct fsl_nfc_fcm *fcm;
- int reg;
-
- sc = device_get_softc(dev);
- fcm = &sc->fcm;
-
- nand_debug(NDBG_DRV,"vf_nand: start command %x", fcm->command);
-
- /* CMD2 */
- reg = READ4(sc, NFC_CMD2);
- reg &= ~(0xff << CMD2_BYTE1_SHIFT);
- reg |= (fcm->command << CMD2_BYTE1_SHIFT);
- WRITE4(sc, NFC_CMD2, reg);
-
- /* CMD1 */
- if ((fcm->command == NAND_CMD_READ) ||
- (fcm->command == NAND_CMD_PROG) ||
- (fcm->command == NAND_CMD_ERASE)) {
- reg = READ4(sc, NFC_CMD1);
- reg &= ~(0xff << 24);
-
- if (fcm->command == NAND_CMD_READ)
- reg |= (CMD_BYTE2_PAGE_READ << 24);
- else if (fcm->command == NAND_CMD_PROG)
- reg |= (CMD_BYTE2_PROG_PAGE << 24);
- else if (fcm->command == NAND_CMD_ERASE)
- reg |= (CMD_BYTE2_ERASE << 24);
-
- WRITE4(sc, NFC_CMD1, reg);
- }
-
- /* We work with 1st buffer */
- reg = READ4(sc, NFC_CMD2);
- reg &= ~(0xf << CMD2_BUFNO_SHIFT);
- reg |= (0 << CMD2_BUFNO_SHIFT);
- WRITE4(sc, NFC_CMD2, reg);
-
- /* Cmd CODE */
- reg = READ4(sc, NFC_CMD2);
- reg &= ~(0xffff << CMD2_CODE_SHIFT);
- reg |= (fcm->code << CMD2_CODE_SHIFT);
- WRITE4(sc, NFC_CMD2, reg);
-
- /* Col */
- if (fcm->addr_type == ADDR_ROWCOL) {
- reg = READ4(sc, NFC_CAR);
- reg &= ~(0xffff);
- reg |= fcm->col_addr_bits;
- nand_debug(NDBG_DRV,"setting CAR to 0x%08x\n", reg);
- WRITE4(sc, NFC_CAR, reg);
- }
-
- /* Row */
- reg = READ4(sc, NFC_RAR);
- reg &= ~(0xffffff);
- if (fcm->addr_type == ADDR_ID)
- reg |= fcm->addr_bits;
- else
- reg |= fcm->row_addr_bits;
- WRITE4(sc, NFC_RAR, reg);
-
- /* Start */
- reg = READ4(sc, NFC_CMD2);
- reg |= (1 << CMD2_START_SHIFT);
- WRITE4(sc, NFC_CMD2, reg);
-
- /* Wait command completion */
- while (READ4(sc, NFC_CMD2) & (1 << CMD2_START_SHIFT))
- ;
-
- return (0);
-}
-
-static int
-vf_nand_send_command(device_t dev, uint8_t command)
-{
- struct vf_nand_softc *sc;
- struct fsl_nfc_fcm *fcm;
-
- nand_debug(NDBG_DRV,"vf_nand: send command %x", command);
-
- sc = device_get_softc(dev);
- fcm = &sc->fcm;
-
- if ((command == NAND_CMD_READ_END) ||
- (command == NAND_CMD_PROG_END) ||
- (command == NAND_CMD_ERASE_END)) {
- return (0);
- }
-
- fcm->command = command;
-
- fcm->code = 0;
- fcm->read_ptr = 0;
- fcm->addr_type = 0;
- fcm->addr_bits = 0;
-
- fcm->addr_ptr = 0;
- fcm->col_addr_bits = 0;
- fcm->row_addr_bits = 0;
-
- switch (command) {
- case NAND_CMD_READ:
- fcm->code = CMD_READ_PAGE;
- fcm->addr_type = ADDR_ROWCOL;
- break;
- case NAND_CMD_PROG:
- fcm->code = CMD_PROG_PAGE;
- fcm->addr_type = ADDR_ROWCOL;
- break;
- case NAND_CMD_PROG_END:
- break;
- case NAND_CMD_ERASE_END:
- break;
- case NAND_CMD_RESET:
- fcm->code = CMD_RESET;
- break;
- case NAND_CMD_READ_ID:
- fcm->code = CMD_READ_ID;
- fcm->addr_type = ADDR_ID;
- break;
- case NAND_CMD_READ_PARAMETER:
- fcm->code = CMD_READ_PAGE;
- fcm->addr_type = ADDR_ID;
- break;
- case NAND_CMD_STATUS:
- fcm->code = CMD_READ_STATUS;
- break;
- case NAND_CMD_ERASE:
- fcm->code = CMD_ERASE;
- fcm->addr_type = ADDR_ROW;
- break;
- default:
- nand_debug(NDBG_DRV, "unknown command %d\n", command);
- return (1);
- }
-
- return (0);
-}
-
-static int
-vf_nand_send_address(device_t dev, uint8_t addr)
-{
- struct vf_nand_softc *sc;
- struct fsl_nfc_fcm *fcm;
-
- nand_debug(NDBG_DRV,"vf_nand: send address %x", addr);
- sc = device_get_softc(dev);
- fcm = &sc->fcm;
-
- nand_debug(NDBG_DRV, "setting addr #%d to 0x%02x\n", fcm->addr_ptr, addr);
-
- if (fcm->addr_type == ADDR_ID) {
- fcm->addr_bits = addr;
- } else if (fcm->addr_type == ADDR_ROWCOL) {
-
- if (fcm->addr_ptr < 2)
- fcm->col_addr_bits |= (addr << (fcm->addr_ptr * 8));
- else
- fcm->row_addr_bits |= (addr << ((fcm->addr_ptr - 2) * 8));
-
- } else if (fcm->addr_type == ADDR_ROW)
- fcm->row_addr_bits |= (addr << (fcm->addr_ptr * 8));
-
- fcm->addr_ptr += 1;
-
- return (0);
-}
-
-static uint8_t
-vf_nand_read_byte(device_t dev)
-{
- struct vf_nand_softc *sc;
- struct fsl_nfc_fcm *fcm;
- uint8_t data;
- int sr1, sr2;
- int b;
-
- sc = device_get_softc(dev);
- fcm = &sc->fcm;
-
- sr1 = READ4(sc, NFC_SR1);
- sr2 = READ4(sc, NFC_SR2);
-
- data = 0;
- if (fcm->addr_type == ADDR_ID) {
- b = 32 - ((fcm->read_ptr + 1) * 8);
- data = (sr1 >> b) & 0xff;
- fcm->read_ptr++;
- } else if (fcm->command == NAND_CMD_STATUS) {
- data = sr2 & 0xff;
- }
-
- nand_debug(NDBG_DRV,"vf_nand: read %x", data);
- return (data);
-}
-
-static void
-vf_nand_read_buf(device_t dev, void* buf, uint32_t len)
-{
- struct vf_nand_softc *sc;
- struct fsl_nfc_fcm *fcm;
- uint16_t *tmp;
- uint8_t *b;
- int i;
-
- b = (uint8_t*)buf;
- sc = device_get_softc(dev);
- fcm = &sc->fcm;
-
- nand_debug(NDBG_DRV, "vf_nand: read_buf len %d", len);
-
- if (fcm->command == NAND_CMD_READ_PARAMETER) {
- tmp = malloc(len, M_DEVBUF, M_NOWAIT);
- bus_read_region_2(sc->res[0], 0x0, tmp, len);
-
- for (i = 0; i < len; i += 2) {
- b[i] = tmp[i+1];
- b[i+1] = tmp[i];
- }
-
- free(tmp, M_DEVBUF);
-
-#ifdef NAND_DEBUG
- for (i = 0; i < len; i++) {
- if (!(i % 16))
- printf("%s", i == 0 ? "vf_nand:\n" : "\n");
- printf(" %x", b[i]);
- if (i == len - 1)
- printf("\n");
- }
-#endif
-
- } else {
-
- for (i = 0; i < len; i++) {
- b[i] = READ1(sc, i);
-
-#ifdef NAND_DEBUG
- if (!(i % 16))
- printf("%s", i == 0 ? "vf_nand:\n" : "\n");
- printf(" %x", b[i]);
- if (i == len - 1)
- printf("\n");
-#endif
- }
-
- }
-}
-
-static void
-vf_nand_write_buf(device_t dev, void* buf, uint32_t len)
-{
- struct vf_nand_softc *sc;
- struct fsl_nfc_fcm *fcm;
- uint8_t *b;
- int i;
-
- b = (uint8_t*)buf;
- sc = device_get_softc(dev);
- fcm = &sc->fcm;
-
- nand_debug(NDBG_DRV,"vf_nand: write_buf len %d", len);
-
- for (i = 0; i < len; i++) {
- WRITE1(sc, i, b[i]);
-
-#ifdef NAND_DEBUG
- if (!(i % 16))
- printf("%s", i == 0 ? "vf_nand:\n" : "\n");
- printf(" %x", b[i]);
- if (i == len - 1)
- printf("\n");
-#endif
-
- }
-}
-
-static int
-vf_nand_select_cs(device_t dev, uint8_t cs)
-{
-
- if (cs > 0)
- return (ENODEV);
-
- return (0);
-}
-
-static int
-vf_nand_read_rnb(device_t dev)
-{
-
- /* no-op */
- return (0); /* ready */
-}
diff --git a/sys/arm/mv/files.arm7 b/sys/arm/mv/files.arm7
index d27357480cae5..a6138042bc805 100644
--- a/sys/arm/mv/files.arm7
+++ b/sys/arm/mv/files.arm7
@@ -29,7 +29,6 @@ dev/iicbus/twsi/mv_twsi.c optional twsi
dev/mge/if_mge.c optional mge
dev/neta/if_mvneta_fdt.c optional neta fdt
dev/neta/if_mvneta.c optional neta mdio mii
-dev/nand/nfc_mv.c optional nand
dev/mvs/mvs_soc.c optional mvs
dev/uart/uart_dev_ns8250.c optional uart
dev/uart/uart_dev_snps.c optional uart
diff --git a/sys/arm/mv/files.mv b/sys/arm/mv/files.mv
index ee027f0594415..1dc45105450c8 100644
--- a/sys/arm/mv/files.mv
+++ b/sys/arm/mv/files.mv
@@ -26,7 +26,6 @@ dev/iicbus/twsi/mv_twsi.c optional twsi
dev/mge/if_mge.c optional mge
dev/neta/if_mvneta_fdt.c optional neta fdt
dev/neta/if_mvneta.c optional neta mdio mii
-dev/nand/nfc_mv.c optional nand
dev/mvs/mvs_soc.c optional mvs
dev/uart/uart_dev_ns8250.c optional uart
dev/uart/uart_dev_snps.c optional uart
diff --git a/sys/arm/ti/am335x/am335x_ehrpwm.c b/sys/arm/ti/am335x/am335x_ehrpwm.c
index 53cb3bb782493..cbb947038ba99 100644
--- a/sys/arm/ti/am335x/am335x_ehrpwm.c
+++ b/sys/arm/ti/am335x/am335x_ehrpwm.c
@@ -45,21 +45,43 @@ __FBSDID("$FreeBSD$");
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
+#include "pwmbus_if.h"
+
#include "am335x_pwm.h"
+/*******************************************************************************
+ * Enhanced resolution PWM driver. Many of the advanced featues of the hardware
+ * are not supported by this driver. What is implemented here is simple
+ * variable-duty-cycle PWM output.
+ *
+ * Note that this driver was historically configured using a set of sysctl
+ * variables/procs, and later gained support for the PWM(9) API. The sysctl
+ * code is still present to support existing apps, but that interface is
+ * considered deprecated.
+ *
+ * An important caveat is that the original sysctl interface and the new PWM API
+ * cannot both be used at once. If both interfaces are used to change
+ * configuration, it's quite likely you won't get the expected results. Also,
+ * reading the sysctl values after configuring via PWM will not return the right
+ * results.
+ ******************************************************************************/
+
/* In ticks */
#define DEFAULT_PWM_PERIOD 1000
#define PWM_CLOCK 100000000UL
+#define NS_PER_SEC 1000000000
+
#define PWM_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
#define PWM_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
+#define PWM_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->sc_mtx, MA_OWNED)
#define PWM_LOCK_INIT(_sc) mtx_init(&(_sc)->sc_mtx, \
device_get_nameunit(_sc->sc_dev), "am335x_ehrpwm softc", MTX_DEF)
#define PWM_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->sc_mtx)
-#define EPWM_READ2(_sc, reg) bus_read_2((_sc)->sc_mem_res, reg);
+#define EPWM_READ2(_sc, reg) bus_read_2((_sc)->sc_mem_res, reg)
#define EPWM_WRITE2(_sc, reg, value) \
- bus_write_2((_sc)->sc_mem_res, reg, value);
+ bus_write_2((_sc)->sc_mem_res, reg, value)
#define EPWM_TBCTL 0x00
#define TBCTL_FREERUN (2 << 14)
@@ -119,6 +141,11 @@ __FBSDID("$FreeBSD$");
#define AQCTL_ZRO_TOGGLE (3 << 0)
#define EPWM_AQSFRC 0x1a
#define EPWM_AQCSFRC 0x1c
+#define AQCSFRC_OFF 0
+#define AQCSFRC_LO 1
+#define AQCSFRC_HI 2
+#define AQCSFRC_MASK 3
+#define AQCSFRC(chan, hilo) ((hilo) << (2 * chan))
/* Trip-Zone module */
#define EPWM_TZCTL 0x28
@@ -135,12 +162,21 @@ static device_detach_t am335x_ehrpwm_detach;
static int am335x_ehrpwm_clkdiv[8] = { 1, 2, 4, 8, 16, 32, 64, 128 };
+struct ehrpwm_channel {
+ u_int duty; /* on duration, in ns */
+ bool enabled; /* channel enabled? */
+ bool inverted; /* signal inverted? */
+};
+#define NUM_CHANNELS 2
+
struct am335x_ehrpwm_softc {
device_t sc_dev;
+ device_t sc_busdev;
struct mtx sc_mtx;
struct resource *sc_mem_res;
int sc_mem_rid;
- /* sysctl for configuration */
+
+ /* Things used for configuration via sysctl [deprecated]. */
int sc_pwm_clkdiv;
int sc_pwm_freq;
struct sysctl_oid *sc_clkdiv_oid;
@@ -151,23 +187,130 @@ struct am335x_ehrpwm_softc {
uint32_t sc_pwm_period;
uint32_t sc_pwm_dutyA;
uint32_t sc_pwm_dutyB;
-};
-static device_method_t am335x_ehrpwm_methods[] = {
- DEVMETHOD(device_probe, am335x_ehrpwm_probe),
- DEVMETHOD(device_attach, am335x_ehrpwm_attach),
- DEVMETHOD(device_detach, am335x_ehrpwm_detach),
-
- DEVMETHOD_END
+ /* Things used for configuration via pwm(9) api. */
+ u_int sc_clkfreq; /* frequency in Hz */
+ u_int sc_clktick; /* duration in ns */
+ u_int sc_period; /* duration in ns */
+ struct ehrpwm_channel sc_channels[NUM_CHANNELS];
};
-static driver_t am335x_ehrpwm_driver = {
- "am335x_ehrpwm",
- am335x_ehrpwm_methods,
- sizeof(struct am335x_ehrpwm_softc),
+static struct ofw_compat_data compat_data[] = {
+ {"ti,am33xx-ehrpwm", true},
+ {NULL, false},
};
+SIMPLEBUS_PNP_INFO(compat_data);
-static devclass_t am335x_ehrpwm_devclass;
+static void
+am335x_ehrpwm_cfg_duty(struct am335x_ehrpwm_softc *sc, u_int chan, u_int duty)
+{
+ u_int tbcmp;
+
+ if (duty == 0)
+ tbcmp = 0;
+ else
+ tbcmp = max(1, duty / sc->sc_clktick);
+
+ sc->sc_channels[chan].duty = tbcmp * sc->sc_clktick;
+
+ PWM_LOCK_ASSERT(sc);
+ EPWM_WRITE2(sc, (chan == 0) ? EPWM_CMPA : EPWM_CMPB, tbcmp);
+}
+
+static void
+am335x_ehrpwm_cfg_enable(struct am335x_ehrpwm_softc *sc, u_int chan, bool enable)
+{
+ uint16_t regval;
+
+ sc->sc_channels[chan].enabled = enable;
+
+ /*
+ * Turn off any existing software-force of the channel, then force
+ * it in the right direction (high or low) if it's not being enabled.
+ */
+ PWM_LOCK_ASSERT(sc);
+ regval = EPWM_READ2(sc, EPWM_AQCSFRC);
+ regval &= ~AQCSFRC(chan, AQCSFRC_MASK);
+ if (!sc->sc_channels[chan].enabled) {
+ if (sc->sc_channels[chan].inverted)
+ regval |= AQCSFRC(chan, AQCSFRC_HI);
+ else
+ regval |= AQCSFRC(chan, AQCSFRC_LO);
+ }
+ EPWM_WRITE2(sc, EPWM_AQCSFRC, regval);
+}
+
+static bool
+am335x_ehrpwm_cfg_period(struct am335x_ehrpwm_softc *sc, u_int period)
+{
+ uint16_t regval;
+ u_int clkdiv, hspclkdiv, pwmclk, pwmtick, tbprd;
+
+ /* Can't do a period shorter than 2 clock ticks. */
+ if (period < 2 * NS_PER_SEC / PWM_CLOCK) {
+ sc->sc_clkfreq = 0;
+ sc->sc_clktick = 0;
+ sc->sc_period = 0;
+ return (false);
+ }
+
+ /*
+ * Figure out how much we have to divide down the base 100MHz clock so
+ * that we can express the requested period as a 16-bit tick count.
+ */
+ tbprd = 0;
+ for (clkdiv = 0; clkdiv < 8; ++clkdiv) {
+ const u_int cd = 1 << clkdiv;
+ for (hspclkdiv = 0; hspclkdiv < 8; ++hspclkdiv) {
+ const u_int cdhs = max(1, hspclkdiv * 2);
+ pwmclk = PWM_CLOCK / (cd * cdhs);
+ pwmtick = NS_PER_SEC / pwmclk;
+ if (period / pwmtick < 65536) {
+ tbprd = period / pwmtick;
+ break;
+ }
+ }
+ if (tbprd != 0)
+ break;
+ }
+
+ /* Handle requested period too long for available clock divisors. */
+ if (tbprd == 0)
+ return (false);
+
+ /*
+ * If anything has changed from the current settings, reprogram the
+ * clock divisors and period register.
+ */
+ if (sc->sc_clkfreq != pwmclk || sc->sc_clktick != pwmtick ||
+ sc->sc_period != tbprd * pwmtick) {
+
+ sc->sc_clkfreq = pwmclk;
+ sc->sc_clktick = pwmtick;
+ sc->sc_period = tbprd * pwmtick;
+
+ PWM_LOCK_ASSERT(sc);
+ regval = EPWM_READ2(sc, EPWM_TBCTL);
+ regval &= ~(TBCTL_CLKDIV_MASK | TBCTL_HSPCLKDIV_MASK);
+ regval |= TBCTL_CLKDIV(clkdiv) | TBCTL_HSPCLKDIV(hspclkdiv);
+ EPWM_WRITE2(sc, EPWM_TBCTL, regval);
+ EPWM_WRITE2(sc, EPWM_TBPRD, tbprd - 1);
+#if 0
+ device_printf(sc->sc_dev, "clkdiv %u hspclkdiv %u tbprd %u "
+ "clkfreq %u Hz clktick %u ns period got %u requested %u\n",
+ clkdiv, hspclkdiv, tbprd - 1,
+ sc->sc_clkfreq, sc->sc_clktick, sc->sc_period, period);
+#endif
+ /*
+ * If the period changed, that invalidates the current CMP
+ * registers (duty values), just zero them out.
+ */
+ am335x_ehrpwm_cfg_duty(sc, 0, 0);
+ am335x_ehrpwm_cfg_duty(sc, 1, 0);
+ }
+
+ return (true);
+}
static void
am335x_ehrpwm_freq(struct am335x_ehrpwm_softc *sc)
@@ -331,13 +474,89 @@ am335x_ehrpwm_sysctl_period(SYSCTL_HANDLER_ARGS)
}
static int
+am335x_ehrpwm_channel_count(device_t dev, u_int *nchannel)
+{
+
+ *nchannel = NUM_CHANNELS;
+
+ return (0);
+}
+
+static int
+am335x_ehrpwm_channel_config(device_t dev, u_int channel, u_int period, u_int duty)
+{
+ struct am335x_ehrpwm_softc *sc;
+ bool status;
+
+ if (channel >= NUM_CHANNELS)
+ return (EINVAL);
+
+ sc = device_get_softc(dev);
+
+ PWM_LOCK(sc);
+ status = am335x_ehrpwm_cfg_period(sc, period);
+ if (status)
+ am335x_ehrpwm_cfg_duty(sc, channel, duty);
+ PWM_UNLOCK(sc);
+
+ return (status ? 0 : EINVAL);
+}
+
+static int
+am335x_ehrpwm_channel_get_config(device_t dev, u_int channel,
+ u_int *period, u_int *duty)
+{
+ struct am335x_ehrpwm_softc *sc;
+
+ if (channel >= NUM_CHANNELS)
+ return (EINVAL);
+
+ sc = device_get_softc(dev);
+ *period = sc->sc_period;
+ *duty = sc->sc_channels[channel].duty;
+ return (0);
+}
+
+static int
+am335x_ehrpwm_channel_enable(device_t dev, u_int channel, bool enable)
+{
+ struct am335x_ehrpwm_softc *sc;
+
+ if (channel >= NUM_CHANNELS)
+ return (EINVAL);
+
+ sc = device_get_softc(dev);
+
+ PWM_LOCK(sc);
+ am335x_ehrpwm_cfg_enable(sc, channel, enable);
+ PWM_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+am335x_ehrpwm_channel_is_enabled(device_t dev, u_int channel, bool *enabled)
+{
+ struct am335x_ehrpwm_softc *sc;
+
+ if (channel >= NUM_CHANNELS)
+ return (EINVAL);
+
+ sc = device_get_softc(dev);
+
+ *enabled = sc->sc_channels[channel].enabled;
+
+ return (0);
+}
+
+static int
am335x_ehrpwm_probe(device_t dev)
{
if (!ofw_bus_status_okay(dev))
return (ENXIO);
- if (!ofw_bus_is_compatible(dev, "ti,am33xx-ehrpwm"))
+ if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data)
return (ENXIO);
device_set_desc(dev, "AM335x EHRPWM");
@@ -365,7 +584,7 @@ am335x_ehrpwm_attach(device_t dev)
goto fail;
}
- /* Init backlight interface */
+ /* Init sysctl interface */
ctx = device_get_sysctl_ctx(sc->sc_dev);
tree = device_get_sysctl_tree(sc->sc_dev);
@@ -414,7 +633,13 @@ am335x_ehrpwm_attach(device_t dev)
EPWM_WRITE2(sc, EPWM_TZCTL, 0xf);
reg = EPWM_READ2(sc, EPWM_TZFLG);
- return (0);
+ if ((sc->sc_busdev = device_add_child(dev, "pwmbus", -1)) == NULL) {
+ device_printf(dev, "Cannot add child pwmbus\n");
+ // This driver can still do things even without the bus child.
+ }
+
+ bus_generic_probe(dev);
+ return (bus_generic_attach(dev));
fail:
PWM_LOCK_DESTROY(sc);
if (sc->sc_mem_res)
@@ -428,13 +653,22 @@ static int
am335x_ehrpwm_detach(device_t dev)
{
struct am335x_ehrpwm_softc *sc;
+ int error;
sc = device_get_softc(dev);
+ if ((error = bus_generic_detach(sc->sc_dev)) != 0)
+ return (error);
+
PWM_LOCK(sc);
+
+ if (sc->sc_busdev != NULL)
+ device_delete_child(dev, sc->sc_busdev);
+
if (sc->sc_mem_res)
bus_release_resource(dev, SYS_RES_MEMORY,
sc->sc_mem_rid, sc->sc_mem_res);
+
PWM_UNLOCK(sc);
PWM_LOCK_DESTROY(sc);
@@ -442,6 +676,44 @@ am335x_ehrpwm_detach(device_t dev)
return (0);
}
+static phandle_t
+am335x_ehrpwm_get_node(device_t bus, device_t dev)
+{
+
+ /*
+ * Share our controller node with our pwmbus child; it instantiates
+ * devices by walking the children contained within our node.
+ */
+ return ofw_bus_get_node(bus);
+}
+
+static device_method_t am335x_ehrpwm_methods[] = {
+ DEVMETHOD(device_probe, am335x_ehrpwm_probe),
+ DEVMETHOD(device_attach, am335x_ehrpwm_attach),
+ DEVMETHOD(device_detach, am335x_ehrpwm_detach),
+
+ /* ofw_bus_if */
+ DEVMETHOD(ofw_bus_get_node, am335x_ehrpwm_get_node),
+
+ /* pwm interface */
+ DEVMETHOD(pwmbus_channel_count, am335x_ehrpwm_channel_count),
+ DEVMETHOD(pwmbus_channel_config, am335x_ehrpwm_channel_config),
+ DEVMETHOD(pwmbus_channel_get_config, am335x_ehrpwm_channel_get_config),
+ DEVMETHOD(pwmbus_channel_enable, am335x_ehrpwm_channel_enable),
+ DEVMETHOD(pwmbus_channel_is_enabled, am335x_ehrpwm_channel_is_enabled),
+
+ DEVMETHOD_END
+};
+
+static driver_t am335x_ehrpwm_driver = {
+ "pwm",
+ am335x_ehrpwm_methods,
+ sizeof(struct am335x_ehrpwm_softc),
+};
+
+static devclass_t am335x_ehrpwm_devclass;
+
DRIVER_MODULE(am335x_ehrpwm, am335x_pwmss, am335x_ehrpwm_driver, am335x_ehrpwm_devclass, 0, 0);
MODULE_VERSION(am335x_ehrpwm, 1);
MODULE_DEPEND(am335x_ehrpwm, am335x_pwmss, 1, 1, 1);
+MODULE_DEPEND(am335x_ehrpwm, pwmbus, 1, 1, 1);
diff --git a/sys/arm64/acpica/acpi_iort.c b/sys/arm64/acpica/acpi_iort.c
index edd87474c9c93..10a501254bc60 100644
--- a/sys/arm64/acpica/acpi_iort.c
+++ b/sys/arm64/acpica/acpi_iort.c
@@ -370,19 +370,44 @@ srat_resolve_its_pxm(ACPI_SUBTABLE_HEADER *entry, void *arg)
ACPI_SRAT_GIC_ITS_AFFINITY *gicits;
struct iort_node *its_node;
struct iort_its_entry *its_entry;
- int i, matches;
+ int *map_counts;
+ int i, matches, dom;
if (entry->Type != ACPI_SRAT_TYPE_GIC_ITS_AFFINITY)
return;
matches = 0;
+ map_counts = arg;
gicits = (ACPI_SRAT_GIC_ITS_AFFINITY *)entry;
+ dom = acpi_map_pxm_to_vm_domainid(gicits->ProximityDomain);
+
+ /*
+ * Catch firmware and config errors. map_counts keeps a
+ * count of ProximityDomain values mapping to a domain ID
+ */
+#if MAXMEMDOM > 1
+ if (dom == -1)
+ printf("Firmware Error: Proximity Domain %d could not be"
+ " mapped for GIC ITS ID %d!\n",
+ gicits->ProximityDomain, gicits->ItsId);
+#endif
+ /* use dom + 1 as index to handle the case where dom == -1 */
+ i = ++map_counts[dom + 1];
+ if (i > 1) {
+#ifdef NUMA
+ if (dom != -1)
+ printf("ERROR: Multiple Proximity Domains map to the"
+ " same NUMA domain %d!\n", dom);
+#else
+ printf("WARNING: multiple Proximity Domains in SRAT but NUMA"
+ " NOT enabled!\n");
+#endif
+ }
TAILQ_FOREACH(its_node, &its_groups, next) {
its_entry = its_node->entries.its;
for (i = 0; i < its_node->nentries; i++, its_entry++) {
if (its_entry->its_id == gicits->ItsId) {
- its_entry->pxm = acpi_map_pxm_to_vm_domainid(
- gicits->ProximityDomain);
+ its_entry->pxm = dom;
matches++;
}
}
@@ -401,6 +426,7 @@ iort_post_process_its(void)
ACPI_TABLE_MADT *madt;
ACPI_TABLE_SRAT *srat;
vm_paddr_t madt_pa, srat_pa;
+ int map_counts[MAXMEMDOM + 1] = { 0 };
/* Check ITS block in MADT */
madt_pa = acpi_find_table(ACPI_SIG_MADT);
@@ -417,7 +443,7 @@ iort_post_process_its(void)
srat = acpi_map_table(srat_pa, ACPI_SIG_SRAT);
KASSERT(srat != NULL, ("can't map SRAT!"));
acpi_walk_subtables(srat + 1, (char *)srat + srat->Header.Length,
- srat_resolve_its_pxm, NULL);
+ srat_resolve_its_pxm, map_counts);
acpi_unmap_table(srat);
}
return (0);
diff --git a/sys/arm64/arm64/freebsd32_machdep.c b/sys/arm64/arm64/freebsd32_machdep.c
index aeac4605f2f5c..2e25fe062b194 100644
--- a/sys/arm64/arm64/freebsd32_machdep.c
+++ b/sys/arm64/arm64/freebsd32_machdep.c
@@ -122,6 +122,7 @@ static void
get_fpcontext32(struct thread *td, mcontext32_vfp_t *mcp)
{
struct pcb *curpcb;
+ int i;
critical_enter();
curpcb = curthread->td_pcb;
@@ -137,8 +138,8 @@ get_fpcontext32(struct thread *td, mcontext32_vfp_t *mcp)
("Called get_fpcontext while the kernel is using the VFP"));
KASSERT((curpcb->pcb_fpflags & ~PCB_FP_USERMASK) == 0,
("Non-userspace FPU flags set in get_fpcontext"));
- memcpy(mcp->mcv_reg, curpcb->pcb_fpustate.vfp_regs,
- sizeof(mcp->mcv_reg));
+ for (i = 0; i < 32; i++)
+ mcp->mcv_reg[i] = (uint64_t)curpcb->pcb_fpustate.vfp_regs[i];
mcp->mcv_fpscr = VFP_FPSCR_FROM_SRCR(curpcb->pcb_fpustate.vfp_fpcr,
curpcb->pcb_fpustate.vfp_fpsr);
}
@@ -149,13 +150,14 @@ static void
set_fpcontext32(struct thread *td, mcontext32_vfp_t *mcp)
{
struct pcb *pcb;
+ int i;
critical_enter();
pcb = td->td_pcb;
if (td == curthread)
vfp_discard(td);
- memcpy(pcb->pcb_fpustate.vfp_regs, mcp->mcv_reg,
- sizeof(pcb->pcb_fpustate.vfp_regs));
+ for (i = 0; i < 32; i++)
+ pcb->pcb_fpustate.vfp_regs[i] = mcp->mcv_reg[i];
pcb->pcb_fpustate.vfp_fpsr = VFP_FPSR_FROM_FPSCR(mcp->mcv_fpscr);
pcb->pcb_fpustate.vfp_fpcr = VFP_FPSR_FROM_FPSCR(mcp->mcv_fpscr);
critical_exit();
diff --git a/sys/arm64/arm64/gic_v3.c b/sys/arm64/arm64/gic_v3.c
index af08ee992bb6a..a83ef576e30ed 100644
--- a/sys/arm64/arm64/gic_v3.c
+++ b/sys/arm64/arm64/gic_v3.c
@@ -390,10 +390,6 @@ gic_v3_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
case GICV3_IVAR_NIRQS:
*result = (NIRQ - sc->gic_nirqs) / sc->gic_nchildren;
return (0);
- case GICV3_IVAR_REDIST_VADDR:
- *result = (uintptr_t)rman_get_virtual(
- &sc->gic_redists.pcpu[PCPU_GET(cpuid)]->res);
- return (0);
case GICV3_IVAR_REDIST:
*result = (uintptr_t)sc->gic_redists.pcpu[PCPU_GET(cpuid)];
return (0);
diff --git a/sys/arm64/arm64/gic_v3_var.h b/sys/arm64/arm64/gic_v3_var.h
index 27dec4d721903..1257484a5e578 100644
--- a/sys/arm64/arm64/gic_v3_var.h
+++ b/sys/arm64/arm64/gic_v3_var.h
@@ -94,11 +94,10 @@ MALLOC_DECLARE(M_GIC_V3);
/* ivars */
#define GICV3_IVAR_NIRQS 1000
-#define GICV3_IVAR_REDIST_VADDR 1001
+/* 1001 was GICV3_IVAR_REDIST_VADDR */
#define GICV3_IVAR_REDIST 1002
__BUS_ACCESSOR(gicv3, nirqs, GICV3, NIRQS, u_int);
-__BUS_ACCESSOR(gicv3, redist_vaddr, GICV3, REDIST_VADDR, void *);
__BUS_ACCESSOR(gicv3, redist, GICV3, REDIST, void *);
/* Device methods */
diff --git a/sys/arm64/arm64/gicv3_its.c b/sys/arm64/arm64/gicv3_its.c
index f347a36c12cc9..2701a7e8df0a1 100644
--- a/sys/arm64/arm64/gicv3_its.c
+++ b/sys/arm64/arm64/gicv3_its.c
@@ -747,9 +747,7 @@ gicv3_its_attach(device_t dev)
if (domain < MAXMEMDOM)
CPU_COPY(&cpuset_domain[domain], &sc->sc_cpus);
} else {
- /* XXX : cannot handle more than one ITS per cpu */
- if (device_get_unit(dev) == 0)
- CPU_COPY(&all_cpus, &sc->sc_cpus);
+ CPU_COPY(&all_cpus, &sc->sc_cpus);
}
/* Allocate the command circular buffer */
diff --git a/sys/arm64/arm64/machdep.c b/sys/arm64/arm64/machdep.c
index b8ecfc08e676f..4356add12aa0a 100644
--- a/sys/arm64/arm64/machdep.c
+++ b/sys/arm64/arm64/machdep.c
@@ -194,6 +194,16 @@ fill_regs(struct thread *td, struct reg *regs)
memcpy(regs->x, frame->tf_x, sizeof(regs->x));
+#ifdef COMPAT_FREEBSD32
+ /*
+ * We may be called here for a 32bits process, if we're using a
+ * 64bits debugger. If so, put PC and SPSR where it expects it.
+ */
+ if (SV_PROC_FLAG(td->td_proc, SV_ILP32)) {
+ regs->x[15] = frame->tf_elr;
+ regs->x[16] = frame->tf_spsr;
+ }
+#endif
return (0);
}
@@ -211,6 +221,17 @@ set_regs(struct thread *td, struct reg *regs)
memcpy(frame->tf_x, regs->x, sizeof(frame->tf_x));
+#ifdef COMPAT_FREEBSD32
+ if (SV_PROC_FLAG(td->td_proc, SV_ILP32)) {
+ /*
+ * We may be called for a 32bits process if we're using
+ * a 64bits debugger. If so, get PC and SPSR from where
+ * it put it.
+ */
+ frame->tf_elr = regs->x[15];
+ frame->tf_spsr = regs->x[16] & PSR_FLAGS;
+ }
+#endif
return (0);
}
@@ -283,8 +304,9 @@ fill_regs32(struct thread *td, struct reg32 *regs)
tf = td->td_frame;
for (i = 0; i < 13; i++)
regs->r[i] = tf->tf_x[i];
- regs->r_sp = tf->tf_sp;
- regs->r_lr = tf->tf_lr;
+ /* For arm32, SP is r13 and LR is r14 */
+ regs->r_sp = tf->tf_x[13];
+ regs->r_lr = tf->tf_x[14];
regs->r_pc = tf->tf_elr;
regs->r_cpsr = tf->tf_spsr;
@@ -300,8 +322,9 @@ set_regs32(struct thread *td, struct reg32 *regs)
tf = td->td_frame;
for (i = 0; i < 13; i++)
tf->tf_x[i] = regs->r[i];
- tf->tf_sp = regs->r_sp;
- tf->tf_lr = regs->r_lr;
+ /* For arm 32, SP is r13 an LR is r14 */
+ tf->tf_x[13] = regs->r_sp;
+ tf->tf_x[14] = regs->r_lr;
tf->tf_elr = regs->r_pc;
tf->tf_spsr = regs->r_cpsr;
diff --git a/sys/arm64/arm64/pmap.c b/sys/arm64/arm64/pmap.c
index df34873025dd2..bf74bb55f0388 100644
--- a/sys/arm64/arm64/pmap.c
+++ b/sys/arm64/arm64/pmap.c
@@ -2510,6 +2510,82 @@ pmap_remove_l3(pmap_t pmap, pt_entry_t *l3, vm_offset_t va,
}
/*
+ * Remove the specified range of addresses from the L3 page table that is
+ * identified by the given L2 entry.
+ */
+static void
+pmap_remove_l3_range(pmap_t pmap, pd_entry_t l2e, vm_offset_t sva,
+ vm_offset_t eva, struct spglist *free, struct rwlock **lockp)
+{
+ struct md_page *pvh;
+ struct rwlock *new_lock;
+ pt_entry_t *l3, old_l3;
+ vm_offset_t va;
+ vm_page_t m;
+
+ PMAP_LOCK_ASSERT(pmap, MA_OWNED);
+ KASSERT(rounddown2(sva, L2_SIZE) + L2_SIZE == roundup2(eva, L2_SIZE),
+ ("pmap_remove_l3_range: range crosses an L3 page table boundary"));
+ va = eva;
+ for (l3 = pmap_l2_to_l3(&l2e, sva); sva != eva; l3++, sva += L3_SIZE) {
+ if (!pmap_l3_valid(pmap_load(l3))) {
+ if (va != eva) {
+ pmap_invalidate_range(pmap, va, sva);
+ va = eva;
+ }
+ continue;
+ }
+ old_l3 = pmap_load_clear(l3);
+ if ((old_l3 & ATTR_SW_WIRED) != 0)
+ pmap->pm_stats.wired_count--;
+ pmap_resident_count_dec(pmap, 1);
+ if ((old_l3 & ATTR_SW_MANAGED) != 0) {
+ m = PHYS_TO_VM_PAGE(old_l3 & ~ATTR_MASK);
+ if (pmap_page_dirty(old_l3))
+ vm_page_dirty(m);
+ if ((old_l3 & ATTR_AF) != 0)
+ vm_page_aflag_set(m, PGA_REFERENCED);
+ new_lock = PHYS_TO_PV_LIST_LOCK(VM_PAGE_TO_PHYS(m));
+ if (new_lock != *lockp) {
+ if (*lockp != NULL) {
+ /*
+ * Pending TLB invalidations must be
+ * performed before the PV list lock is
+ * released. Otherwise, a concurrent
+ * pmap_remove_all() on a physical page
+ * could return while a stale TLB entry
+ * still provides access to that page.
+ */
+ if (va != eva) {
+ pmap_invalidate_range(pmap, va,
+ sva);
+ va = eva;
+ }
+ rw_wunlock(*lockp);
+ }
+ *lockp = new_lock;
+ rw_wlock(*lockp);
+ }
+ pmap_pvh_free(&m->md, pmap, sva);
+ if (TAILQ_EMPTY(&m->md.pv_list) &&
+ (m->flags & PG_FICTITIOUS) == 0) {
+ pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m));
+ if (TAILQ_EMPTY(&pvh->pv_list))
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
+ }
+ }
+ if (va == eva)
+ va = sva;
+ if (pmap_unuse_pt(pmap, sva, l2e, free)) {
+ sva += L3_SIZE;
+ break;
+ }
+ }
+ if (va != eva)
+ pmap_invalidate_range(pmap, va, sva);
+}
+
+/*
* Remove the given range of addresses from the specified map.
*
* It is assumed that the start and end are properly
@@ -2519,9 +2595,9 @@ void
pmap_remove(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
{
struct rwlock *lock;
- vm_offset_t va, va_next;
+ vm_offset_t va_next;
pd_entry_t *l0, *l1, *l2;
- pt_entry_t l3_paddr, *l3;
+ pt_entry_t l3_paddr;
struct spglist free;
/*
@@ -2594,28 +2670,8 @@ pmap_remove(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
if (va_next > eva)
va_next = eva;
- va = va_next;
- for (l3 = pmap_l2_to_l3(l2, sva); sva != va_next; l3++,
- sva += L3_SIZE) {
- if (l3 == NULL)
- panic("l3 == NULL");
- if (pmap_load(l3) == 0) {
- if (va != va_next) {
- pmap_invalidate_range(pmap, va, sva);
- va = va_next;
- }
- continue;
- }
- if (va == va_next)
- va = sva;
- if (pmap_remove_l3(pmap, l3, sva, l3_paddr, &free,
- &lock)) {
- sva += L3_SIZE;
- break;
- }
- }
- if (va != va_next)
- pmap_invalidate_range(pmap, va, sva);
+ pmap_remove_l3_range(pmap, l3_paddr, sva, va_next, &free,
+ &lock);
}
if (lock != NULL)
rw_wunlock(lock);
@@ -3352,7 +3408,7 @@ validate:
__func__, pmap, va, new_l3);
}
} else {
- /* New mappig */
+ /* New mapping */
pmap_load_store(l3, new_l3);
dsb(ishst);
}
@@ -3419,8 +3475,7 @@ pmap_enter_l2(pmap_t pmap, vm_offset_t va, pd_entry_t new_l2, u_int flags,
vm_page_t m, struct rwlock **lockp)
{
struct spglist free;
- pd_entry_t *l2, *l3, old_l2;
- vm_offset_t sva;
+ pd_entry_t *l2, old_l2;
vm_page_t l2pg, mt;
PMAP_LOCK_ASSERT(pmap, MA_OWNED);
@@ -3449,13 +3504,8 @@ pmap_enter_l2(pmap_t pmap, vm_offset_t va, pd_entry_t new_l2, u_int flags,
(void)pmap_remove_l2(pmap, l2, va,
pmap_load(pmap_l1(pmap, va)), &free, lockp);
else
- for (sva = va; sva < va + L2_SIZE; sva += PAGE_SIZE) {
- l3 = pmap_l2_to_l3(l2, sva);
- if (pmap_l3_valid(pmap_load(l3)) &&
- pmap_remove_l3(pmap, l3, sva, old_l2, &free,
- lockp) != 0)
- break;
- }
+ pmap_remove_l3_range(pmap, old_l2, va, va + L2_SIZE,
+ &free, lockp);
vm_page_free_pages_toq(&free, true);
if (va >= VM_MAXUSER_ADDRESS) {
/*
@@ -3656,6 +3706,9 @@ pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, vm_page_t m,
l3 = pmap_l2_to_l3(pde, va);
}
+ /*
+ * Abort if a mapping already exists.
+ */
if (pmap_load(l3) != 0) {
if (mpte != NULL) {
mpte->wire_count--;
@@ -3705,7 +3758,15 @@ pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, vm_page_t m,
cpu_icache_sync_range(PHYS_TO_DMAP(pa), PAGE_SIZE);
pmap_load_store(l3, l3_val);
+
+ /*
+ * XXX In principle, because this L3 entry was invalid, we should not
+ * need to perform a TLB invalidation here. However, in practice,
+ * when simply performing a "dsb ishst" here, processes are being
+ * terminated due to bus errors and segmentation violations.
+ */
pmap_invalidate_page(pmap, va);
+
return (mpte);
}
diff --git a/sys/arm64/conf/GENERIC b/sys/arm64/conf/GENERIC
index 8e3f04fe1db1b..2adee9db99d4a 100644
--- a/sys/arm64/conf/GENERIC
+++ b/sys/arm64/conf/GENERIC
@@ -293,7 +293,6 @@ device aw_cir
# Pseudo devices.
device crypto # core crypto support
device loop # Network loopback
-device random # Entropy device
device ether # Ethernet support
device vlan # 802.1Q VLAN support
device tuntap # Packet tunnel.
diff --git a/sys/cam/ata/ata_all.c b/sys/cam/ata/ata_all.c
index 76d65ae5e4052..9a4cdbed071ba 100644
--- a/sys/cam/ata/ata_all.c
+++ b/sys/cam/ata/ata_all.c
@@ -1238,3 +1238,28 @@ ata_zac_mgmt_in(struct ccb_ataio *ataio, uint32_t retries,
ataio->aux = auxiliary;
}
}
+
+void
+ata_param_fixup(struct ata_params *ident_buf)
+{
+ int16_t *ptr;
+
+ for (ptr = (int16_t *)ident_buf;
+ ptr < (int16_t *)ident_buf + sizeof(struct ata_params)/2; ptr++) {
+ *ptr = le16toh(*ptr);
+ }
+ if (strncmp(ident_buf->model, "FX", 2) &&
+ strncmp(ident_buf->model, "NEC", 3) &&
+ strncmp(ident_buf->model, "Pioneer", 7) &&
+ strncmp(ident_buf->model, "SHARP", 5)) {
+ ata_bswap(ident_buf->model, sizeof(ident_buf->model));
+ ata_bswap(ident_buf->revision, sizeof(ident_buf->revision));
+ ata_bswap(ident_buf->serial, sizeof(ident_buf->serial));
+ }
+ ata_btrim(ident_buf->model, sizeof(ident_buf->model));
+ ata_bpack(ident_buf->model, ident_buf->model, sizeof(ident_buf->model));
+ ata_btrim(ident_buf->revision, sizeof(ident_buf->revision));
+ ata_bpack(ident_buf->revision, ident_buf->revision, sizeof(ident_buf->revision));
+ ata_btrim(ident_buf->serial, sizeof(ident_buf->serial));
+ ata_bpack(ident_buf->serial, ident_buf->serial, sizeof(ident_buf->serial));
+}
diff --git a/sys/cam/ata/ata_all.h b/sys/cam/ata/ata_all.h
index 087d6820f9808..ca635253511c4 100644
--- a/sys/cam/ata/ata_all.h
+++ b/sys/cam/ata/ata_all.h
@@ -135,6 +135,7 @@ void ata_read_log(struct ccb_ataio *ataio, uint32_t retries,
uint16_t block_count, uint32_t protocol,
uint8_t *data_ptr, uint32_t dxfer_len, uint32_t timeout);
+void ata_param_fixup(struct ata_params *ident_buf);
void ata_bswap(int8_t *buf, int len);
void ata_btrim(int8_t *buf, int len);
void ata_bpack(int8_t *src, int8_t *dst, int len);
diff --git a/sys/cam/ata/ata_xpt.c b/sys/cam/ata/ata_xpt.c
index 94dc435b099b7..017db8854b088 100644
--- a/sys/cam/ata/ata_xpt.c
+++ b/sys/cam/ata/ata_xpt.c
@@ -893,14 +893,13 @@ noerror:
case PROBE_IDENTIFY:
{
struct ccb_pathinq cpi;
- int16_t *ptr;
int veto = 0;
+ /*
+ * Convert to host byte order, and fix the strings.
+ */
ident_buf = &softc->ident_data;
- for (ptr = (int16_t *)ident_buf;
- ptr < (int16_t *)ident_buf + sizeof(struct ata_params)/2; ptr++) {
- *ptr = le16toh(*ptr);
- }
+ ata_param_fixup(ident_buf);
/*
* Allow others to veto this ATA disk attachment. This
@@ -912,20 +911,6 @@ noerror:
goto device_fail;
}
- if (strncmp(ident_buf->model, "FX", 2) &&
- strncmp(ident_buf->model, "NEC", 3) &&
- strncmp(ident_buf->model, "Pioneer", 7) &&
- strncmp(ident_buf->model, "SHARP", 5)) {
- ata_bswap(ident_buf->model, sizeof(ident_buf->model));
- ata_bswap(ident_buf->revision, sizeof(ident_buf->revision));
- ata_bswap(ident_buf->serial, sizeof(ident_buf->serial));
- }
- ata_btrim(ident_buf->model, sizeof(ident_buf->model));
- ata_bpack(ident_buf->model, ident_buf->model, sizeof(ident_buf->model));
- ata_btrim(ident_buf->revision, sizeof(ident_buf->revision));
- ata_bpack(ident_buf->revision, ident_buf->revision, sizeof(ident_buf->revision));
- ata_btrim(ident_buf->serial, sizeof(ident_buf->serial));
- ata_bpack(ident_buf->serial, ident_buf->serial, sizeof(ident_buf->serial));
/* Device may need spin-up before IDENTIFY become valid. */
if ((ident_buf->specconf == 0x37c8 ||
ident_buf->specconf == 0x738c) &&
diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c
index 2217ecc6d2ff2..4736c7212a2c8 100644
--- a/sys/cam/cam_xpt.c
+++ b/sys/cam/cam_xpt.c
@@ -1244,6 +1244,7 @@ xpt_getattr(char *buf, size_t len, const char *attr, struct cam_path *path)
{
int ret = -1, l, o;
struct ccb_dev_advinfo cdai;
+ struct scsi_vpd_device_id *did;
struct scsi_vpd_id_descriptor *idd;
xpt_path_assert(path, MA_OWNED);
@@ -1253,6 +1254,7 @@ xpt_getattr(char *buf, size_t len, const char *attr, struct cam_path *path)
cdai.ccb_h.func_code = XPT_DEV_ADVINFO;
cdai.flags = CDAI_FLAG_NONE;
cdai.bufsiz = len;
+ cdai.buf = buf;
if (!strcmp(attr, "GEOM::ident"))
cdai.buftype = CDAI_TYPE_SERIAL_NUM;
@@ -1262,44 +1264,49 @@ xpt_getattr(char *buf, size_t len, const char *attr, struct cam_path *path)
strcmp(attr, "GEOM::lunname") == 0) {
cdai.buftype = CDAI_TYPE_SCSI_DEVID;
cdai.bufsiz = CAM_SCSI_DEVID_MAXLEN;
+ cdai.buf = malloc(cdai.bufsiz, M_CAMXPT, M_NOWAIT);
+ if (cdai.buf == NULL) {
+ ret = ENOMEM;
+ goto out;
+ }
} else
goto out;
- cdai.buf = malloc(cdai.bufsiz, M_CAMXPT, M_NOWAIT|M_ZERO);
- if (cdai.buf == NULL) {
- ret = ENOMEM;
- goto out;
- }
xpt_action((union ccb *)&cdai); /* can only be synchronous */
if ((cdai.ccb_h.status & CAM_DEV_QFRZN) != 0)
cam_release_devq(cdai.ccb_h.path, 0, 0, 0, FALSE);
if (cdai.provsiz == 0)
goto out;
- if (cdai.buftype == CDAI_TYPE_SCSI_DEVID) {
+ switch(cdai.buftype) {
+ case CDAI_TYPE_SCSI_DEVID:
+ did = (struct scsi_vpd_device_id *)cdai.buf;
if (strcmp(attr, "GEOM::lunid") == 0) {
- idd = scsi_get_devid((struct scsi_vpd_device_id *)cdai.buf,
- cdai.provsiz, scsi_devid_is_lun_naa);
+ idd = scsi_get_devid(did, cdai.provsiz,
+ scsi_devid_is_lun_naa);
if (idd == NULL)
- idd = scsi_get_devid((struct scsi_vpd_device_id *)cdai.buf,
- cdai.provsiz, scsi_devid_is_lun_eui64);
+ idd = scsi_get_devid(did, cdai.provsiz,
+ scsi_devid_is_lun_eui64);
if (idd == NULL)
- idd = scsi_get_devid((struct scsi_vpd_device_id *)cdai.buf,
- cdai.provsiz, scsi_devid_is_lun_uuid);
+ idd = scsi_get_devid(did, cdai.provsiz,
+ scsi_devid_is_lun_uuid);
if (idd == NULL)
- idd = scsi_get_devid((struct scsi_vpd_device_id *)cdai.buf,
- cdai.provsiz, scsi_devid_is_lun_md5);
+ idd = scsi_get_devid(did, cdai.provsiz,
+ scsi_devid_is_lun_md5);
} else
idd = NULL;
+
if (idd == NULL)
- idd = scsi_get_devid((struct scsi_vpd_device_id *)cdai.buf,
- cdai.provsiz, scsi_devid_is_lun_t10);
+ idd = scsi_get_devid(did, cdai.provsiz,
+ scsi_devid_is_lun_t10);
if (idd == NULL)
- idd = scsi_get_devid((struct scsi_vpd_device_id *)cdai.buf,
- cdai.provsiz, scsi_devid_is_lun_name);
+ idd = scsi_get_devid(did, cdai.provsiz,
+ scsi_devid_is_lun_name);
if (idd == NULL)
- goto out;
+ break;
+
ret = 0;
- if ((idd->proto_codeset & SVPD_ID_CODESET_MASK) == SVPD_ID_CODESET_ASCII) {
+ if ((idd->proto_codeset & SVPD_ID_CODESET_MASK) ==
+ SVPD_ID_CODESET_ASCII) {
if (idd->length < len) {
for (l = 0; l < idd->length; l++)
buf[l] = idd->identifier[l] ?
@@ -1307,40 +1314,50 @@ xpt_getattr(char *buf, size_t len, const char *attr, struct cam_path *path)
buf[l] = 0;
} else
ret = EFAULT;
- } else if ((idd->proto_codeset & SVPD_ID_CODESET_MASK) == SVPD_ID_CODESET_UTF8) {
+ break;
+ }
+ if ((idd->proto_codeset & SVPD_ID_CODESET_MASK) ==
+ SVPD_ID_CODESET_UTF8) {
l = strnlen(idd->identifier, idd->length);
if (l < len) {
bcopy(idd->identifier, buf, l);
buf[l] = 0;
} else
ret = EFAULT;
- } else if ((idd->id_type & SVPD_ID_TYPE_MASK) == SVPD_ID_TYPE_UUID
- && idd->identifier[0] == 0x10) {
- if ((idd->length - 2) * 2 + 4 < len) {
- for (l = 2, o = 0; l < idd->length; l++) {
- if (l == 6 || l == 8 || l == 10 || l == 12)
- o += sprintf(buf + o, "-");
- o += sprintf(buf + o, "%02x",
- idd->identifier[l]);
- }
- } else
- ret = EFAULT;
- } else {
- if (idd->length * 2 < len) {
- for (l = 0; l < idd->length; l++)
- sprintf(buf + l * 2, "%02x",
- idd->identifier[l]);
- } else
+ break;
+ }
+ if ((idd->id_type & SVPD_ID_TYPE_MASK) ==
+ SVPD_ID_TYPE_UUID && idd->identifier[0] == 0x10) {
+ if ((idd->length - 2) * 2 + 4 >= len) {
ret = EFAULT;
+ break;
+ }
+ for (l = 2, o = 0; l < idd->length; l++) {
+ if (l == 6 || l == 8 || l == 10 || l == 12)
+ o += sprintf(buf + o, "-");
+ o += sprintf(buf + o, "%02x",
+ idd->identifier[l]);
+ }
+ break;
}
- } else {
- ret = 0;
- if (strlcpy(buf, cdai.buf, len) >= len)
+ if (idd->length * 2 < len) {
+ for (l = 0; l < idd->length; l++)
+ sprintf(buf + l * 2, "%02x",
+ idd->identifier[l]);
+ } else
+ ret = EFAULT;
+ break;
+ default:
+ if (cdai.provsiz < len) {
+ cdai.buf[cdai.provsiz] = 0;
+ ret = 0;
+ } else
ret = EFAULT;
+ break;
}
out:
- if (cdai.buf != NULL)
+ if ((char *)cdai.buf != buf)
free(cdai.buf, M_CAMXPT);
return ret;
}
diff --git a/sys/cam/ctl/ctl_error.c b/sys/cam/ctl/ctl_error.c
index 17e9e3a51d800..dae4deb9e5e7b 100644
--- a/sys/cam/ctl/ctl_error.c
+++ b/sys/cam/ctl/ctl_error.c
@@ -81,6 +81,12 @@ ctl_set_sense_data_va(struct scsi_sense_data *sense_data, u_int *sense_len,
*/
if (sense_format == SSD_TYPE_NONE) {
/*
+ * SPC-3 and up require some UAs to be returned as fixed.
+ */
+ if (asc == 0x29 || (asc == 0x2A && ascq == 0x01))
+ sense_format = SSD_TYPE_FIXED;
+ else
+ /*
* If the format isn't specified, we only return descriptor
* sense if the LUN exists and descriptor sense is turned
* on for that LUN.
diff --git a/sys/cam/scsi/scsi_all.c b/sys/cam/scsi/scsi_all.c
index 1d92c4d8e915f..5ab37e3f64164 100644
--- a/sys/cam/scsi/scsi_all.c
+++ b/sys/cam/scsi/scsi_all.c
@@ -5574,6 +5574,7 @@ scsi_devid_is_naa_ieee_reg(uint8_t *bufp)
{
struct scsi_vpd_id_descriptor *descr;
struct scsi_vpd_id_naa_basic *naa;
+ int n;
descr = (struct scsi_vpd_id_descriptor *)bufp;
naa = (struct scsi_vpd_id_naa_basic *)descr->identifier;
@@ -5581,7 +5582,8 @@ scsi_devid_is_naa_ieee_reg(uint8_t *bufp)
return 0;
if (descr->length < sizeof(struct scsi_vpd_id_naa_ieee_reg))
return 0;
- if ((naa->naa >> SVPD_ID_NAA_NAA_SHIFT) != SVPD_ID_NAA_IEEE_REG)
+ n = naa->naa >> SVPD_ID_NAA_NAA_SHIFT;
+ if (n != SVPD_ID_NAA_LOCAL_REG && n != SVPD_ID_NAA_IEEE_REG)
return 0;
return 1;
}
diff --git a/sys/cam/scsi/scsi_da.c b/sys/cam/scsi/scsi_da.c
index a89c40e19a7b6..f2f60d35b2e28 100644
--- a/sys/cam/scsi/scsi_da.c
+++ b/sys/cam/scsi/scsi_da.c
@@ -64,6 +64,9 @@ __FBSDID("$FreeBSD$");
#include <cam/cam_ccb.h>
#include <cam/cam_periph.h>
#include <cam/cam_xpt_periph.h>
+#ifdef _KERNEL
+#include <cam/cam_xpt_internal.h>
+#endif /* _KERNEL */
#include <cam/cam_sim.h>
#include <cam/cam_iosched.h>
@@ -3613,15 +3616,7 @@ out:
break;
}
- ata_params = (struct ata_params*)
- malloc(sizeof(*ata_params), M_SCSIDA,M_NOWAIT|M_ZERO);
-
- if (ata_params == NULL) {
- xpt_print(periph->path, "Couldn't malloc ata_params "
- "data\n");
- /* da_free_periph??? */
- break;
- }
+ ata_params = &periph->path->device->ident_data;
scsi_ata_identify(&start_ccb->csio,
/*retries*/da_retry_count,
@@ -5192,7 +5187,7 @@ dadone_probeata(struct cam_periph *periph, union ccb *done_ccb)
struct da_softc *softc;
u_int32_t priority;
int continue_probe;
- int error, i;
+ int error;
int16_t *ptr;
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("dadone_probeata\n"));
@@ -5210,8 +5205,7 @@ dadone_probeata(struct cam_periph *periph, union ccb *done_ccb)
if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
uint16_t old_rate;
- for (i = 0; i < sizeof(*ata_params) / 2; i++)
- ptr[i] = le16toh(ptr[i]);
+ ata_param_fixup(ata_params);
if (ata_params->support_dsm & ATA_SUPPORT_DSM_TRIM &&
(softc->quirks & DA_Q_NO_UNMAP) == 0) {
dadeleteflag(softc, DA_DELETE_ATA_TRIM, 1);
@@ -5295,7 +5289,6 @@ dadone_probeata(struct cam_periph *periph, union ccb *done_ccb)
}
}
- free(ata_params, M_SCSIDA);
if ((softc->zone_mode == DA_ZONE_HOST_AWARE)
|| (softc->zone_mode == DA_ZONE_HOST_MANAGED)) {
/*
diff --git a/sys/cam/scsi/scsi_enc.c b/sys/cam/scsi/scsi_enc.c
index 363f27db5f784..ec190232fff97 100644
--- a/sys/cam/scsi/scsi_enc.c
+++ b/sys/cam/scsi/scsi_enc.c
@@ -81,6 +81,17 @@ static enctyp enc_type(struct ccb_getdev *);
SYSCTL_NODE(_kern_cam, OID_AUTO, enc, CTLFLAG_RD, 0,
"CAM Enclosure Services driver");
+#if defined(DEBUG) || defined(ENC_DEBUG)
+int enc_verbose = 1;
+#else
+int enc_verbose = 0;
+#endif
+SYSCTL_INT(_kern_cam_enc, OID_AUTO, verbose, CTLFLAG_RWTUN,
+ &enc_verbose, 0, "Enable verbose logging");
+
+const char *elm_type_names[] = ELM_TYPE_NAMES;
+CTASSERT(nitems(elm_type_names) - 1 == ELMTYP_LAST);
+
static struct periph_driver encdriver = {
enc_init, "ses",
TAILQ_HEAD_INITIALIZER(encdriver.units), /* generation */ 0
@@ -232,11 +243,17 @@ enc_async(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
struct enc_softc *softc;
softc = (struct enc_softc *)periph->softc;
- if (xpt_path_path_id(periph->path) != path_id
- || softc == NULL
- || (softc->enc_flags & ENC_FLAG_INITIALIZED)
- == 0
- || softc->enc_vec.device_found == NULL)
+
+ /* Check this SEP is ready. */
+ if (softc == NULL || (softc->enc_flags &
+ ENC_FLAG_INITIALIZED) == 0 ||
+ softc->enc_vec.device_found == NULL)
+ continue;
+
+ /* Check this SEP may manage this device. */
+ if (xpt_path_path_id(periph->path) != path_id &&
+ (softc->enc_type != ENC_SEMB_SES ||
+ cgd->protocol != PROTO_ATA))
continue;
softc->enc_vec.device_found(softc);
@@ -432,7 +449,7 @@ enc_ioctl(struct cdev *dev, u_long cmd, caddr_t arg_addr, int flag,
encioc_element_t kelm;
kelm.elm_idx = i;
kelm.elm_subenc_id = cache->elm_map[i].subenclosure;
- kelm.elm_type = cache->elm_map[i].enctype;
+ kelm.elm_type = cache->elm_map[i].elm_type;
error = copyout(&kelm, &uelm[i], sizeof(kelm));
if (error)
break;
@@ -684,14 +701,8 @@ enc_type(struct ccb_getdev *cgd)
buflen = min(sizeof(cgd->inq_data),
SID_ADDITIONAL_LENGTH(&cgd->inq_data));
- if ((iqd[0] & 0x1f) == T_ENCLOSURE) {
- if ((iqd[2] & 0x7) > 2) {
- return (ENC_SES);
- } else {
- return (ENC_SES_SCSI2);
- }
- return (ENC_NONE);
- }
+ if ((iqd[0] & 0x1f) == T_ENCLOSURE)
+ return (ENC_SES);
#ifdef SES_ENABLE_PASSTHROUGH
if ((iqd[6] & 0x40) && (iqd[2] & 0x7) >= 2) {
@@ -928,7 +939,6 @@ enc_ctor(struct cam_periph *periph, void *arg)
switch (enc->enc_type) {
case ENC_SES:
- case ENC_SES_SCSI2:
case ENC_SES_PASSTHROUGH:
case ENC_SEMB_SES:
err = ses_softc_init(enc);
@@ -1017,17 +1027,14 @@ enc_ctor(struct cam_periph *periph, void *arg)
case ENC_NONE:
tname = "No ENC device";
break;
- case ENC_SES_SCSI2:
- tname = "SCSI-2 ENC Device";
- break;
case ENC_SES:
- tname = "SCSI-3 ENC Device";
+ tname = "SES Device";
break;
case ENC_SES_PASSTHROUGH:
- tname = "ENC Passthrough Device";
+ tname = "SES Passthrough Device";
break;
case ENC_SAFT:
- tname = "SAF-TE Compliant Device";
+ tname = "SAF-TE Device";
break;
case ENC_SEMB_SES:
tname = "SEMB SES Device";
diff --git a/sys/cam/scsi/scsi_enc.h b/sys/cam/scsi/scsi_enc.h
index fc7e3bd3f1c6b..f9abe099e337c 100644
--- a/sys/cam/scsi/scsi_enc.h
+++ b/sys/cam/scsi/scsi_enc.h
@@ -120,10 +120,42 @@ typedef enum {
ELMTYP_SCSI_INI = 0x15,
ELMTYP_SUBENC = 0x16,
ELMTYP_ARRAY_DEV = 0x17,
- ELMTYP_SAS_EXP = 0x18, /* SAS expander */
- ELMTYP_SAS_CONN = 0x19 /* SAS connector */
+ ELMTYP_SAS_EXP = 0x18, /* SAS Expander */
+ ELMTYP_SAS_CONN = 0x19, /* SAS Connector */
+ ELMTYP_LAST = ELMTYP_SAS_CONN
} elm_type_t;
+#define ELM_TYPE_NAMES { \
+ "Unspecified", \
+ "Device Slot", \
+ "Power Supply", \
+ "Cooling", \
+ "Temperature Sensors", \
+ "Door", \
+ "Audible alarm", \
+ "Enclosure Services Controller Electronics", \
+ "SCC Controller Electronics", \
+ "Nonvolatile Cache", \
+ "Invalid Operation Reason", \
+ "Uninterruptible Power Supply", \
+ "Display", \
+ "Key Pad Entry", \
+ "Enclosure", \
+ "SCSI Port/Transceiver", \
+ "Language", \
+ "Communication Port", \
+ "Voltage Sensor", \
+ "Current Sensor", \
+ "SCSI Target Port", \
+ "SCSI Initiator Port", \
+ "Simple Subenclosure", \
+ "Array Device Slot", \
+ "SAS Expander", \
+ "SAS Connector" \
+}
+
+extern const char *elm_type_names[];
+
typedef struct encioc_element {
/* Element Index */
unsigned int elm_idx;
diff --git a/sys/cam/scsi/scsi_enc_internal.h b/sys/cam/scsi/scsi_enc_internal.h
index 0d4bdffda4f9a..293da3ee7386b 100644
--- a/sys/cam/scsi/scsi_enc_internal.h
+++ b/sys/cam/scsi/scsi_enc_internal.h
@@ -36,17 +36,15 @@
#ifndef __SCSI_ENC_INTERNAL_H__
#define __SCSI_ENC_INTERNAL_H__
+#include <sys/sysctl.h>
+
typedef struct enc_element {
- uint32_t
- enctype : 8, /* enclosure type */
- subenclosure : 8, /* subenclosure id */
- svalid : 1, /* enclosure information valid */
- overall_status_elem: 1,/*
- * This object represents generic
- * status about all objects of this
- * type.
- */
- priv : 14; /* private data, per object */
+ uint8_t elm_idx; /* index of element */
+ uint8_t elm_type; /* element type */
+ uint8_t subenclosure; /* subenclosure id */
+ uint8_t type_elm_idx; /* index of element within type */
+ uint8_t svalid; /* enclosure information valid */
+ uint16_t priv; /* private data, per object */
uint8_t encstat[4]; /* state && stats */
uint8_t *physical_path; /* Device physical path data. */
u_int physical_path_len; /* Length of device path data. */
@@ -55,10 +53,8 @@ typedef struct enc_element {
typedef enum {
ENC_NONE,
- ENC_SES_SCSI2,
ENC_SES,
ENC_SES_PASSTHROUGH,
- ENC_SEN,
ENC_SAFT,
ENC_SEMB_SES,
ENC_SEMB_SAFT
@@ -206,6 +202,9 @@ enc_softc_init_t ses_softc_init;
/* SAF-TE interface */
enc_softc_init_t safte_softc_init;
+SYSCTL_DECL(_kern_cam_enc);
+extern int enc_verbose;
+
/* Helper macros */
MALLOC_DECLARE(M_SCSIENC);
#define ENC_CFLAGS CAM_RETRY_SELTO
@@ -218,7 +217,7 @@ MALLOC_DECLARE(M_SCSIENC);
#else
#define ENC_DLOG if (0) enc_log
#endif
-#define ENC_VLOG if (bootverbose) enc_log
+#define ENC_VLOG if (enc_verbose) enc_log
#define ENC_MALLOC(amt) malloc(amt, M_SCSIENC, M_NOWAIT)
#define ENC_MALLOCZ(amt) malloc(amt, M_SCSIENC, M_ZERO|M_NOWAIT)
/* Cast away const avoiding GCC warnings. */
diff --git a/sys/cam/scsi/scsi_enc_safte.c b/sys/cam/scsi/scsi_enc_safte.c
index 8afcc323991a6..94219cde7a89b 100644
--- a/sys/cam/scsi/scsi_enc_safte.c
+++ b/sys/cam/scsi/scsi_enc_safte.c
@@ -227,7 +227,6 @@ static char *safte_2little = "Too Little Data Returned (%d) at line %d\n";
}
int emulate_array_devices = 1;
-SYSCTL_DECL(_kern_cam_enc);
SYSCTL_INT(_kern_cam_enc, OID_AUTO, emulate_array_devices, CTLFLAG_RWTUN,
&emulate_array_devices, 0, "Emulate Array Devices for SAF-TE");
@@ -302,21 +301,21 @@ safte_process_config(enc_softc_t *enc, struct enc_fsm_state *state,
* in later fetches of status.
*/
for (i = 0; i < cfg->Nfans; i++)
- enc->enc_cache.elm_map[r++].enctype = ELMTYP_FAN;
+ enc->enc_cache.elm_map[r++].elm_type = ELMTYP_FAN;
cfg->pwroff = (uint8_t) r;
for (i = 0; i < cfg->Npwr; i++)
- enc->enc_cache.elm_map[r++].enctype = ELMTYP_POWER;
+ enc->enc_cache.elm_map[r++].elm_type = ELMTYP_POWER;
for (i = 0; i < cfg->DoorLock; i++)
- enc->enc_cache.elm_map[r++].enctype = ELMTYP_DOORLOCK;
+ enc->enc_cache.elm_map[r++].elm_type = ELMTYP_DOORLOCK;
if (cfg->Nspkrs > 0)
- enc->enc_cache.elm_map[r++].enctype = ELMTYP_ALARM;
+ enc->enc_cache.elm_map[r++].elm_type = ELMTYP_ALARM;
for (i = 0; i < cfg->Ntherm; i++)
- enc->enc_cache.elm_map[r++].enctype = ELMTYP_THERM;
+ enc->enc_cache.elm_map[r++].elm_type = ELMTYP_THERM;
for (i = 0; i <= cfg->Ntstats; i++)
- enc->enc_cache.elm_map[r++].enctype = ELMTYP_THERM;
+ enc->enc_cache.elm_map[r++].elm_type = ELMTYP_THERM;
cfg->slotoff = (uint8_t) r;
for (i = 0; i < cfg->Nslots; i++)
- enc->enc_cache.elm_map[r++].enctype =
+ enc->enc_cache.elm_map[r++].elm_type =
emulate_array_devices ? ELMTYP_ARRAY_DEV :
ELMTYP_DEVICE;
@@ -506,7 +505,7 @@ safte_process_status(enc_softc_t *enc, struct enc_fsm_state *state,
*/
for (i = 0; i < cfg->Nslots; i++) {
SAFT_BAIL(r, xfer_len);
- if (cache->elm_map[cfg->slotoff + i].enctype == ELMTYP_DEVICE)
+ if (cache->elm_map[cfg->slotoff + i].elm_type == ELMTYP_DEVICE)
cache->elm_map[cfg->slotoff + i].encstat[1] = buf[r];
r++;
}
@@ -679,7 +678,7 @@ safte_process_slotstatus(enc_softc_t *enc, struct enc_fsm_state *state,
oid = cfg->slotoff;
for (r = i = 0; i < cfg->Nslots; i++, r += 4) {
SAFT_BAIL(r+3, xfer_len);
- if (cache->elm_map[oid].enctype == ELMTYP_ARRAY_DEV)
+ if (cache->elm_map[oid].elm_type == ELMTYP_ARRAY_DEV)
cache->elm_map[oid].encstat[1] = 0;
cache->elm_map[oid].encstat[2] &= SESCTL_RQSID;
cache->elm_map[oid].encstat[3] = 0;
@@ -706,7 +705,7 @@ safte_process_slotstatus(enc_softc_t *enc, struct enc_fsm_state *state,
cache->elm_map[oid].encstat[3] |= SESCTL_RQSFLT;
if (buf[r+0] & 0x40)
cache->elm_map[oid].encstat[0] |= SESCTL_PRDFAIL;
- if (cache->elm_map[oid].enctype == ELMTYP_ARRAY_DEV) {
+ if (cache->elm_map[oid].elm_type == ELMTYP_ARRAY_DEV) {
if (buf[r+0] & 0x01)
cache->elm_map[oid].encstat[1] |= 0x80;
if (buf[r+0] & 0x04)
@@ -772,7 +771,7 @@ safte_fill_control_request(enc_softc_t *enc, struct enc_fsm_state *state,
} else {
ep = &enc->enc_cache.elm_map[idx];
- switch (ep->enctype) {
+ switch (ep->elm_type) {
case ELMTYP_DEVICE:
case ELMTYP_ARRAY_DEV:
switch (cfg->current_request_stage) {
@@ -782,7 +781,7 @@ safte_fill_control_request(enc_softc_t *enc, struct enc_fsm_state *state,
ep->priv |= 0x40;
if (req->elm_stat[3] & SESCTL_RQSFLT)
ep->priv |= 0x02;
- if (ep->enctype == ELMTYP_ARRAY_DEV) {
+ if (ep->elm_type == ELMTYP_ARRAY_DEV) {
if (req->elm_stat[1] & 0x01)
ep->priv |= 0x200;
if (req->elm_stat[1] & 0x02)
@@ -971,7 +970,7 @@ safte_process_control_request(enc_softc_t *enc, struct enc_fsm_state *state,
if (idx == SES_SETSTATUS_ENC_IDX)
type = -1;
else
- type = enc->enc_cache.elm_map[idx].enctype;
+ type = enc->enc_cache.elm_map[idx].elm_type;
if (type == ELMTYP_DEVICE || type == ELMTYP_ARRAY_DEV)
enc_update_request(enc, SAFTE_UPDATE_READSLOTSTATUS);
else
diff --git a/sys/cam/scsi/scsi_enc_ses.c b/sys/cam/scsi/scsi_enc_ses.c
index 5e9d2dc94d2d2..e5a18d5d9a45f 100644
--- a/sys/cam/scsi/scsi_enc_ses.c
+++ b/sys/cam/scsi/scsi_enc_ses.c
@@ -102,6 +102,7 @@ typedef struct ses_addl_status {
union {
union ses_fcobj_hdr *fc;
union ses_elm_sas_hdr *sas;
+ struct ses_elm_ata_hdr *ata;
} proto_hdr;
union ses_addl_data proto_data; /* array sizes stored in header */
} ses_add_status_t;
@@ -444,6 +445,7 @@ ses_iter_next(struct ses_iterator *iter)
iter->type_element_index = ITERATOR_INDEX_END;
iter->global_element_index = ITERATOR_INDEX_END;
iter->individual_element_index = ITERATOR_INDEX_END;
+ iter->saved_individual_element_index = ITERATOR_INDEX_END;
return (NULL);
}
@@ -468,17 +470,12 @@ ses_iter_next(struct ses_iterator *iter)
*/
iter->type_index++;
iter->type_element_index = 0;
- iter->saved_individual_element_index
- = iter->individual_element_index;
iter->individual_element_index = ITERATOR_INDEX_INVALID;
}
if (iter->type_element_index > 0) {
- if (iter->type_element_index == 1) {
- iter->individual_element_index
- = iter->saved_individual_element_index;
- }
- iter->individual_element_index++;
+ iter->individual_element_index =
+ ++iter->saved_individual_element_index;
}
return (&iter->cache->elm_map[iter->global_element_index]);
@@ -829,14 +826,6 @@ ses_devids_iter(enc_softc_t *enc, enc_element_t *elm,
elmpriv = elm->elm_private;
addl = &(elmpriv->addl);
- /*
- * Don't assume this object has additional status information, or
- * that it is a SAS device, or that it is a device slot device.
- */
- if (addl->hdr == NULL || addl->proto_hdr.sas == NULL
- || addl->proto_data.sasdev_phys == NULL)
- return;
-
devid_record_size = SVPD_DEVICE_ID_DESC_HDR_LEN
+ sizeof(struct scsi_vpd_id_naa_ieee_reg);
for (i = 0; i < addl->proto_hdr.sas->base_hdr.num_phys; i++) {
@@ -954,11 +943,40 @@ static void
ses_paths_iter(enc_softc_t *enc, enc_element_t *elm,
ses_path_callback_t *callback, void *callback_arg)
{
- ses_path_iter_args_t args;
+ ses_element_t *elmpriv;
+ struct ses_addl_status *addl;
+
+ elmpriv = elm->elm_private;
+ addl = &(elmpriv->addl);
+
+ if (addl->hdr == NULL)
+ return;
- args.callback = callback;
- args.callback_arg = callback_arg;
- ses_devids_iter(enc, elm, ses_path_iter_devid_callback, &args);
+ if (addl->proto_hdr.sas != NULL &&
+ addl->proto_data.sasdev_phys != NULL) {
+ ses_path_iter_args_t args;
+
+ args.callback = callback;
+ args.callback_arg = callback_arg;
+ ses_devids_iter(enc, elm, ses_path_iter_devid_callback, &args);
+ } else if (addl->proto_hdr.ata != NULL) {
+ struct cam_path *path;
+ struct ccb_getdev cgd;
+
+ if (xpt_create_path(&path, /*periph*/NULL,
+ scsi_4btoul(addl->proto_hdr.ata->bus),
+ scsi_4btoul(addl->proto_hdr.ata->target), 0)
+ != CAM_REQ_CMP)
+ return;
+
+ xpt_setup_ccb(&cgd.ccb_h, path, CAM_PRIORITY_NORMAL);
+ cgd.ccb_h.func_code = XPT_GDEV_TYPE;
+ xpt_action((union ccb *)&cgd);
+ if (cgd.ccb_h.status == CAM_REQ_CMP)
+ callback(enc, elm, path, callback_arg);
+
+ xpt_free_path(path);
+ }
}
/**
@@ -1063,6 +1081,10 @@ ses_set_physpath(enc_softc_t *enc, enc_element_t *elm,
ret = EIO;
devid = NULL;
+ elmpriv = elm->elm_private;
+ if (elmpriv->addl.hdr == NULL)
+ goto out;
+
/*
* Assemble the components of the physical path starting with
* the device ID of the enclosure itself.
@@ -1095,7 +1117,6 @@ ses_set_physpath(enc_softc_t *enc, enc_element_t *elm,
scsi_8btou64(idd->identifier), iter->type_index,
iter->type_element_index);
/* Append the element descriptor if one exists */
- elmpriv = elm->elm_private;
if (elmpriv->descr != NULL && elmpriv->descr_len > 0) {
sbuf_cat(&sb, "/elmdesc@");
for (i = 0, c = elmpriv->descr; i < elmpriv->descr_len;
@@ -1461,9 +1482,10 @@ ses_process_config(enc_softc_t *enc, struct enc_fsm_state *state,
iter.global_element_index, iter.type_index, nelm,
iter.type_element_index);
thdr = ses_cache->ses_types[iter.type_index].hdr;
+ element->elm_idx = iter.global_element_index;
+ element->elm_type = thdr->etype_elm_type;
element->subenclosure = thdr->etype_subenc;
- element->enctype = thdr->etype_elm_type;
- element->overall_status_elem = iter.type_element_index == 0;
+ element->type_elm_idx = iter.type_element_index;
element->elm_private = malloc(sizeof(ses_element_t),
M_SCSIENC, M_WAITOK|M_ZERO);
ENC_DLOG(enc, "%s: creating elmpriv %d(%d,%d) subenc %d "
@@ -1667,6 +1689,8 @@ static int ses_get_elm_addlstatus_fc(enc_softc_t *, enc_cache_t *,
uint8_t *, int);
static int ses_get_elm_addlstatus_sas(enc_softc_t *, enc_cache_t *, uint8_t *,
int, int, int, int);
+static int ses_get_elm_addlstatus_ata(enc_softc_t *, enc_cache_t *, uint8_t *,
+ int, int, int, int);
/**
* \brief Parse the additional status element data for each object.
@@ -1685,7 +1709,6 @@ ses_process_elm_addlstatus(enc_softc_t *enc, struct enc_fsm_state *state,
struct ses_iterator iter, titer;
int eip;
int err;
- int ignore_index = 0;
int length;
int offset;
enc_cache_t *enc_cache;
@@ -1756,7 +1779,7 @@ ses_process_elm_addlstatus(enc_softc_t *enc, struct enc_fsm_state *state,
elm_hdr = (struct ses_elm_addlstatus_base_hdr *)&buf[offset];
eip = ses_elm_addlstatus_eip(elm_hdr);
- if (eip && !ignore_index) {
+ if (eip) {
struct ses_elm_addlstatus_eip_hdr *eip_hdr;
int expected_index, index;
ses_elem_index_type_t index_type;
@@ -1769,17 +1792,44 @@ ses_process_elm_addlstatus(enc_softc_t *enc, struct enc_fsm_state *state,
index_type = SES_ELEM_INDEX_INDIVIDUAL;
expected_index = iter.individual_element_index;
}
+ if (eip_hdr->element_index < expected_index) {
+ ENC_VLOG(enc, "%s: provided %selement index "
+ "%d is lower then expected %d\n",
+ __func__, (eip_hdr->byte2 &
+ SES_ADDL_EIP_EIIOE) ? "global " : "",
+ eip_hdr->element_index, expected_index);
+ goto badindex;
+ }
titer = iter;
telement = ses_iter_seek_to(&titer,
eip_hdr->element_index, index_type);
- if (telement != NULL &&
- (ses_typehasaddlstatus(enc, titer.type_index) !=
- TYPE_ADDLSTATUS_NONE ||
- titer.type_index > ELMTYP_SAS_CONN)) {
+ if (telement == NULL) {
+ ENC_VLOG(enc, "%s: provided %selement index "
+ "%d does not exist\n", __func__,
+ (eip_hdr->byte2 & SES_ADDL_EIP_EIIOE) ?
+ "global " : "", eip_hdr->element_index);
+ goto badindex;
+ }
+ if (ses_typehasaddlstatus(enc, titer.type_index) ==
+ TYPE_ADDLSTATUS_NONE) {
+ ENC_VLOG(enc, "%s: provided %selement index "
+ "%d can't have additional status\n",
+ __func__,
+ (eip_hdr->byte2 & SES_ADDL_EIP_EIIOE) ?
+ "global " : "", eip_hdr->element_index);
+badindex:
+ /*
+ * If we expected mandatory element, we may
+ * guess it was just a wrong index and we may
+ * use the status. If element was optional,
+ * then we have no idea where status belongs.
+ */
+ if (status_type == TYPE_ADDLSTATUS_OPTIONAL)
+ break;
+ } else {
iter = titer;
element = telement;
- } else
- ignore_index = 1;
+ }
if (eip_hdr->byte2 & SES_ADDL_EIP_EIIOE)
index = iter.global_element_index;
@@ -1796,40 +1846,46 @@ ses_process_elm_addlstatus(enc_softc_t *enc, struct enc_fsm_state *state,
}
}
elmpriv = element->elm_private;
- elmpriv->addl.hdr = elm_hdr;
ENC_DLOG(enc, "%s: global element index=%d, type index=%d "
"type element index=%d, offset=0x%x, "
"byte0=0x%x, length=0x%x\n", __func__,
iter.global_element_index, iter.type_index,
- iter.type_element_index, offset, elmpriv->addl.hdr->byte0,
- elmpriv->addl.hdr->length);
+ iter.type_element_index, offset, elm_hdr->byte0,
+ elm_hdr->length);
/* Skip to after the length field */
offset += sizeof(struct ses_elm_addlstatus_base_hdr);
/* Make sure the descriptor is within bounds */
- if ((offset + elmpriv->addl.hdr->length) > length) {
+ if ((offset + elm_hdr->length) > length) {
ENC_VLOG(enc, "Element %d Beyond End "
"of Additional Element Status Descriptors\n",
iter.global_element_index);
break;
}
+ /* Skip elements marked as invalid. */
+ if (ses_elm_addlstatus_invalid(elm_hdr)) {
+ offset += elm_hdr->length;
+ continue;
+ }
+ elmpriv->addl.hdr = elm_hdr;
+
/* Advance to the protocol data, skipping eip bytes if needed */
offset += (eip * SES_EIP_HDR_EXTRA_LEN);
- proto_info_len = elmpriv->addl.hdr->length
+ proto_info_len = elm_hdr->length
- (eip * SES_EIP_HDR_EXTRA_LEN);
/* Errors in this block are ignored as they are non-fatal */
- switch(ses_elm_addlstatus_proto(elmpriv->addl.hdr)) {
+ switch(ses_elm_addlstatus_proto(elm_hdr)) {
case SPSP_PROTO_FC:
- if (elmpriv->addl.hdr->length == 0)
+ if (elm_hdr->length == 0)
break;
ses_get_elm_addlstatus_fc(enc, enc_cache,
&buf[offset], proto_info_len);
break;
case SPSP_PROTO_SAS:
- if (elmpriv->addl.hdr->length <= 2)
+ if (elm_hdr->length <= 2)
break;
ses_get_elm_addlstatus_sas(enc, enc_cache,
&buf[offset],
@@ -1837,10 +1893,17 @@ ses_process_elm_addlstatus(enc_softc_t *enc, struct enc_fsm_state *state,
eip, iter.type_index,
iter.global_element_index);
break;
+ case SPSP_PROTO_ATA:
+ ses_get_elm_addlstatus_ata(enc, enc_cache,
+ &buf[offset],
+ proto_info_len,
+ eip, iter.type_index,
+ iter.global_element_index);
+ break;
default:
ENC_VLOG(enc, "Element %d: Unknown Additional Element "
"Protocol 0x%x\n", iter.global_element_index,
- ses_elm_addlstatus_proto(elmpriv->addl.hdr));
+ ses_elm_addlstatus_proto(elm_hdr));
break;
}
@@ -2165,18 +2228,16 @@ ses_get_elm_addlstatus_fc(enc_softc_t *enc, enc_cache_t *enc_cache,
}
#define SES_PRINT_PORTS(p, type) do { \
- sbuf_printf(sbp, " %s(", type); \
- if (((p) & SES_SASOBJ_DEV_PHY_PROTOMASK) == 0) \
- sbuf_printf(sbp, " None"); \
- else { \
+ if (((p) & SES_SASOBJ_DEV_PHY_PROTOMASK) != 0) { \
+ sbuf_printf(sbp, " %s (", type); \
if ((p) & SES_SASOBJ_DEV_PHY_SMP) \
sbuf_printf(sbp, " SMP"); \
if ((p) & SES_SASOBJ_DEV_PHY_STP) \
sbuf_printf(sbp, " STP"); \
if ((p) & SES_SASOBJ_DEV_PHY_SSP) \
sbuf_printf(sbp, " SSP"); \
+ sbuf_printf(sbp, " )"); \
} \
- sbuf_printf(sbp, " )"); \
} while(0)
/**
@@ -2186,11 +2247,10 @@ ses_get_elm_addlstatus_fc(enc_softc_t *enc, enc_cache_t *enc_cache,
* \param sesname SES device name associated with the object.
* \param sbp Sbuf to print to.
* \param obj The object to print the data for.
- * \param periph_name Peripheral string associated with the object.
*/
static void
ses_print_addl_data_sas_type0(char *sesname, struct sbuf *sbp,
- enc_element_t *obj, char *periph_name)
+ enc_element_t *obj)
{
int i;
ses_element_t *elmpriv;
@@ -2199,16 +2259,12 @@ ses_print_addl_data_sas_type0(char *sesname, struct sbuf *sbp,
elmpriv = obj->elm_private;
addl = &(elmpriv->addl);
- if (addl->proto_hdr.sas == NULL)
- return;
- sbuf_printf(sbp, "%s: %s: SAS Device Slot Element:",
- sesname, periph_name);
- sbuf_printf(sbp, " %d Phys", addl->proto_hdr.sas->base_hdr.num_phys);
+ sbuf_printf(sbp, ", SAS Slot: %d%s phys",
+ addl->proto_hdr.sas->base_hdr.num_phys,
+ ses_elm_sas_type0_not_all_phys(addl->proto_hdr.sas) ? "+" : "");
if (ses_elm_addlstatus_eip(addl->hdr))
- sbuf_printf(sbp, " at Slot %d",
+ sbuf_printf(sbp, " at slot %d",
addl->proto_hdr.sas->type0_eip.dev_slot_num);
- if (ses_elm_sas_type0_not_all_phys(addl->proto_hdr.sas))
- sbuf_printf(sbp, ", Not All Phys");
sbuf_printf(sbp, "\n");
if (addl->proto_data.sasdev_phys == NULL)
return;
@@ -2219,9 +2275,8 @@ ses_print_addl_data_sas_type0(char *sesname, struct sbuf *sbp,
/* Spec says all other fields are specific values */
sbuf_printf(sbp, " SATA device\n");
else {
- sbuf_printf(sbp, " SAS device type %d id %d\n",
+ sbuf_printf(sbp, " SAS device type %d phy %d",
ses_elm_sas_dev_phy_dev_type(phy), phy->phy_id);
- sbuf_printf(sbp, "%s: phy %d: protocols:", sesname, i);
SES_PRINT_PORTS(phy->initiator_ports, "Initiator");
SES_PRINT_PORTS(phy->target_ports, "Target");
sbuf_printf(sbp, "\n");
@@ -2235,32 +2290,16 @@ ses_print_addl_data_sas_type0(char *sesname, struct sbuf *sbp,
#undef SES_PRINT_PORTS
/**
- * \brief Report whether a given enclosure object is an expander.
- *
- * \param enc SES softc associated with object.
- * \param obj Enclosure object to report for.
- *
- * \return 1 if true, 0 otherwise.
- */
-static int
-ses_obj_is_expander(enc_softc_t *enc, enc_element_t *obj)
-{
- return (obj->enctype == ELMTYP_SAS_EXP);
-}
-
-/**
* \brief Print the additional element status data for this object, for SAS
* type 1 objects. See SES2 r20 Sections 6.1.13.3.3 and 6.1.13.3.4.
*
- * \param enc SES enclosure, needed for type identification.
* \param sesname SES device name associated with the object.
* \param sbp Sbuf to print to.
* \param obj The object to print the data for.
- * \param periph_name Peripheral string associated with the object.
*/
static void
-ses_print_addl_data_sas_type1(enc_softc_t *enc, char *sesname,
- struct sbuf *sbp, enc_element_t *obj, char *periph_name)
+ses_print_addl_data_sas_type1(char *sesname, struct sbuf *sbp,
+ enc_element_t *obj)
{
int i, num_phys;
ses_element_t *elmpriv;
@@ -2270,12 +2309,10 @@ ses_print_addl_data_sas_type1(enc_softc_t *enc, char *sesname,
elmpriv = obj->elm_private;
addl = &(elmpriv->addl);
- if (addl->proto_hdr.sas == NULL)
- return;
- sbuf_printf(sbp, "%s: %s: SAS ", sesname, periph_name);
- if (ses_obj_is_expander(enc, obj)) {
+ sbuf_printf(sbp, ", SAS ");
+ if (obj->elm_type == ELMTYP_SAS_EXP) {
num_phys = addl->proto_hdr.sas->base_hdr.num_phys;
- sbuf_printf(sbp, "Expander: %d Phys", num_phys);
+ sbuf_printf(sbp, "Expander: %d phys", num_phys);
if (addl->proto_data.sasexp_phys == NULL)
return;
for (i = 0;i < num_phys;i++) {
@@ -2286,7 +2323,7 @@ ses_print_addl_data_sas_type1(enc_softc_t *enc, char *sesname,
}
} else {
num_phys = addl->proto_hdr.sas->base_hdr.num_phys;
- sbuf_printf(sbp, "Port: %d Phys", num_phys);
+ sbuf_printf(sbp, "Port: %d phys", num_phys);
if (addl->proto_data.sasport_phys == NULL)
return;
for (i = 0;i < num_phys;i++) {
@@ -2302,6 +2339,24 @@ ses_print_addl_data_sas_type1(enc_softc_t *enc, char *sesname,
}
/**
+ * \brief Print the additional element status data for this object, for
+ * ATA objects.
+ *
+ * \param sbp Sbuf to print to.
+ * \param obj The object to print the data for.
+ */
+static void
+ses_print_addl_data_ata(struct sbuf *sbp, enc_element_t *obj)
+{
+ ses_element_t *elmpriv = obj->elm_private;
+ struct ses_addl_status *addl = &elmpriv->addl;
+ struct ses_elm_ata_hdr *ata = addl->proto_hdr.ata;
+
+ sbuf_printf(sbp, ", SATA Slot: scbus%d target %d\n",
+ scsi_4btoul(ata->bus), scsi_4btoul(ata->target));
+}
+
+/**
* \brief Print the additional element status data for this object.
*
* \param enc SES softc associated with the object.
@@ -2332,27 +2387,45 @@ ses_print_addl_data(enc_softc_t *enc, enc_element_t *obj)
sbuf_printf(&sesname, "%s%d", enc->periph->periph_name,
enc->periph->unit_number);
sbuf_finish(&sesname);
+ sbuf_printf(&out, "%s: %s in ", sbuf_data(&sesname), sbuf_data(&name));
if (elmpriv->descr != NULL)
- sbuf_printf(&out, "%s: %s: Element descriptor: '%s'\n",
- sbuf_data(&sesname), sbuf_data(&name), elmpriv->descr);
+ sbuf_printf(&out, "'%s'", elmpriv->descr);
+ else {
+ if (obj->elm_type <= ELMTYP_LAST)
+ sbuf_cat(&out, elm_type_names[obj->elm_type]);
+ else
+ sbuf_printf(&out, "<Type 0x%02x>", obj->elm_type);
+ sbuf_printf(&out, " %d", obj->type_elm_idx);
+ if (obj->subenclosure != 0)
+ sbuf_printf(&out, " of subenc %d", obj->subenclosure);
+ }
switch(ses_elm_addlstatus_proto(addl->hdr)) {
+ case SPSP_PROTO_FC:
+ goto noaddl; /* stubbed for now */
case SPSP_PROTO_SAS:
+ if (addl->proto_hdr.sas == NULL)
+ goto noaddl;
switch(ses_elm_sas_descr_type(addl->proto_hdr.sas)) {
case SES_SASOBJ_TYPE_SLOT:
ses_print_addl_data_sas_type0(sbuf_data(&sesname),
- &out, obj, sbuf_data(&name));
+ &out, obj);
break;
case SES_SASOBJ_TYPE_OTHER:
- ses_print_addl_data_sas_type1(enc, sbuf_data(&sesname),
- &out, obj, sbuf_data(&name));
+ ses_print_addl_data_sas_type1(sbuf_data(&sesname),
+ &out, obj);
break;
default:
- break;
+ goto noaddl;
}
break;
- case SPSP_PROTO_FC: /* stubbed for now */
+ case SPSP_PROTO_ATA:
+ if (addl->proto_hdr.ata == NULL)
+ goto noaddl;
+ ses_print_addl_data_ata(&out, obj);
break;
default:
+noaddl:
+ sbuf_cat(&out, "\n");
break;
}
sbuf_finish(&out);
@@ -2457,7 +2530,7 @@ ses_get_elm_addlstatus_sas_type1(enc_softc_t *enc, enc_cache_t *enc_cache,
goto out;
/* Process expanders differently from other type1 cases */
- if (ses_obj_is_expander(enc, obj)) {
+ if (obj->elm_type == ELMTYP_SAS_EXP) {
offset += sizeof(struct ses_elm_sas_type1_expander_hdr);
physz = addl->proto_hdr.sas->base_hdr.num_phys *
sizeof(struct ses_elm_sas_expander_phy);
@@ -2565,6 +2638,53 @@ out:
return (err);
}
+/**
+ * \brief Update the softc with the additional element status data for this
+ * object, for ATA objects.
+ *
+ * \param enc SES softc to be updated.
+ * \param buf The additional element status response buffer.
+ * \param bufsiz Size of the response buffer.
+ * \param eip The EIP bit value.
+ * \param tidx Type index for this object.
+ * \param nobj Number of objects attached to the SES softc.
+ *
+ * \return 0 on success, errno otherwise.
+ */
+static int
+ses_get_elm_addlstatus_ata(enc_softc_t *enc, enc_cache_t *enc_cache,
+ uint8_t *buf, int bufsiz, int eip, int tidx,
+ int nobj)
+{
+ int err;
+ ses_cache_t *ses_cache;
+
+ if (bufsiz < sizeof(struct ses_elm_ata_hdr)) {
+ err = EIO;
+ goto out;
+ }
+
+ ses_cache = enc_cache->private;
+ switch(ses_cache->ses_types[tidx].hdr->etype_elm_type) {
+ case ELMTYP_DEVICE:
+ case ELMTYP_ARRAY_DEV:
+ break;
+ default:
+ ENC_VLOG(enc, "Element %d has Additional Status, "
+ "invalid for SES element type 0x%x\n", nobj,
+ ses_cache->ses_types[tidx].hdr->etype_elm_type);
+ err = ENODEV;
+ goto out;
+ }
+
+ ((ses_element_t *)enc_cache->elm_map[nobj].elm_private)
+ ->addl.proto_hdr.ata = (struct ses_elm_ata_hdr *)buf;
+ err = 0;
+
+out:
+ return (err);
+}
+
static void
ses_softc_invalidate(enc_softc_t *enc)
{
diff --git a/sys/cam/scsi/scsi_ses.h b/sys/cam/scsi/scsi_ses.h
index 779b3a97a00d2..b9c69cbcfe308 100644
--- a/sys/cam/scsi/scsi_ses.h
+++ b/sys/cam/scsi/scsi_ses.h
@@ -2181,15 +2181,27 @@ struct ses_status_page_hdr {
#define SESCTL_DISABLE 0x20
#define SESCTL_RSTSWAP 0x10
-
-/* Control bits, Device Elements, byte 2 */
-#define SESCTL_DRVLCK 0x40 /* "DO NOT REMOVE" */
+/* Control bits, Array Device Slot Elements, byte 1 */
+#define SESCTL_RQSOK 0x80 /* RQST OK */
+#define SESCTL_RQSRSV 0x40 /* RQST RSVD DEVICE */
+#define SESCTL_RQSSPR 0x20 /* RQST HOT SPARE */
+#define SESCTL_RQSCCH 0x10 /* RQST CONS CHECK */
+#define SESCTL_RQSCRA 0x08 /* RQST IN CRIT ARRAY */
+#define SESCTL_RQSFAA 0x04 /* RQST IN FAILED ARRAY */
+#define SESCTL_RQSRR 0x02 /* RQST REBUI/REMAP */
+#define SESCTL_RQSRRA 0x01 /* RQST R/R ABORT */
+/* Control bits, [Array] Device Slot Elements, byte 2 */
+#define SESCTL_RQSACT 0x80 /* RQST ACTIVE */
+#define SESCTL_DRVLCK 0x40 /* DO NOT REMOVE */
+#define SESCTL_RQSMSN 0x10 /* RQST MISSING */
#define SESCTL_RQSINS 0x08 /* RQST INSERT */
#define SESCTL_RQSRMV 0x04 /* RQST REMOVE */
#define SESCTL_RQSID 0x02 /* RQST IDENT */
-/* Control bits, Device Elements, byte 3 */
+/* Control bits, [Array] Device Slot Elements, byte 3 */
#define SESCTL_RQSFLT 0x20 /* RQST FAULT */
#define SESCTL_DEVOFF 0x10 /* DEVICE OFF */
+#define SESCTL_ENBYPA 0x08 /* ENABLE BYP A */
+#define SESCTL_ENBYPB 0x04 /* ENABLE BYP B */
/* Control bits, Generic, byte 3 */
#define SESCTL_RQSTFAIL 0x40
@@ -2399,6 +2411,17 @@ union ses_elm_sas_hdr {
int ses_elm_sas_type0_not_all_phys(union ses_elm_sas_hdr *);
int ses_elm_sas_descr_type(union ses_elm_sas_hdr *);
+/*
+ * This structure for SPSP_PROTO_ATA is not defined by SES specs,
+ * but purely my own design to make AHCI EM interoperate with SES.
+ * Since no other software I know can talk to SEMB, and we do not
+ * expose this this outside, it should be safe to do what we want.
+ */
+struct ses_elm_ata_hdr {
+ uint8_t bus[4];
+ uint8_t target[4];
+};
+
struct ses_elm_addlstatus_base_hdr {
uint8_t byte0;
/*
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_objset.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_objset.c
index 2e36e0e5eec1a..71d9cd7b6f172 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_objset.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_objset.c
@@ -1334,6 +1334,8 @@ dmu_objset_sync(objset_t *os, zio_t *pio, dmu_tx_t *tx)
zio_t *zio;
list_t *list;
dbuf_dirty_record_t *dr;
+ int num_sublists;
+ multilist_t *ml;
blkptr_t *blkptr_copy = kmem_alloc(sizeof (*os->os_rootbp), KM_SLEEP);
*blkptr_copy = *os->os_rootbp;
@@ -1402,10 +1404,13 @@ dmu_objset_sync(objset_t *os, zio_t *pio, dmu_tx_t *tx)
}
}
- for (int i = 0;
- i < multilist_get_num_sublists(os->os_dirty_dnodes[txgoff]); i++) {
+ ml = os->os_dirty_dnodes[txgoff];
+ num_sublists = multilist_get_num_sublists(ml);
+ for (int i = 0; i < num_sublists; i++) {
+ if (multilist_sublist_is_empty_idx(ml, i))
+ continue;
sync_dnodes_arg_t *sda = kmem_alloc(sizeof (*sda), KM_SLEEP);
- sda->sda_list = os->os_dirty_dnodes[txgoff];
+ sda->sda_list = ml;
sda->sda_sublist_idx = i;
sda->sda_tx = tx;
(void) taskq_dispatch(dmu_objset_pool(os)->dp_sync_taskq,
@@ -1619,6 +1624,8 @@ userquota_updates_task(void *arg)
void
dmu_objset_do_userquota_updates(objset_t *os, dmu_tx_t *tx)
{
+ int num_sublists;
+
if (!dmu_objset_userused_enabled(os))
return;
@@ -1632,8 +1639,10 @@ dmu_objset_do_userquota_updates(objset_t *os, dmu_tx_t *tx)
DMU_OT_USERGROUP_USED, DMU_OT_NONE, 0, tx));
}
- for (int i = 0;
- i < multilist_get_num_sublists(os->os_synced_dnodes); i++) {
+ num_sublists = multilist_get_num_sublists(os->os_synced_dnodes);
+ for (int i = 0; i < num_sublists; i++) {
+ if (multilist_sublist_is_empty_idx(os->os_synced_dnodes, i))
+ continue;
userquota_updates_arg_t *uua =
kmem_alloc(sizeof (*uua), KM_SLEEP);
uua->uua_os = os;
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/multilist.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/multilist.c
index b61d1358c8a83..f517454d3d6da 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/multilist.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/multilist.c
@@ -360,6 +360,28 @@ multilist_sublist_remove(multilist_sublist_t *mls, void *obj)
list_remove(&mls->mls_list, obj);
}
+int
+multilist_sublist_is_empty(multilist_sublist_t *mls)
+{
+ ASSERT(MUTEX_HELD(&mls->mls_lock));
+ return (list_is_empty(&mls->mls_list));
+}
+
+int
+multilist_sublist_is_empty_idx(multilist_t *ml, unsigned int sublist_idx)
+{
+ multilist_sublist_t *mls;
+ int empty;
+
+ ASSERT3U(sublist_idx, <, ml->ml_num_sublists);
+ mls = &ml->ml_sublists[sublist_idx];
+ ASSERT(!MUTEX_HELD(&mls->mls_lock));
+ mutex_enter(&mls->mls_lock);
+ empty = list_is_empty(&mls->mls_list);
+ mutex_exit(&mls->mls_lock);
+ return (empty);
+}
+
void *
multilist_sublist_head(multilist_sublist_t *mls)
{
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/multilist.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/multilist.h
index 7f386fb7c3bec..a3b44e60eb97b 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/multilist.h
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/multilist.h
@@ -89,6 +89,8 @@ void multilist_sublist_insert_head(multilist_sublist_t *, void *);
void multilist_sublist_insert_tail(multilist_sublist_t *, void *);
void multilist_sublist_move_forward(multilist_sublist_t *mls, void *obj);
void multilist_sublist_remove(multilist_sublist_t *, void *);
+int multilist_sublist_is_empty(multilist_sublist_t *);
+int multilist_sublist_is_empty_idx(multilist_t *, unsigned int);
void *multilist_sublist_head(multilist_sublist_t *);
void *multilist_sublist_tail(multilist_sublist_t *);
diff --git a/sys/compat/linuxkpi/common/include/asm/atomic-long.h b/sys/compat/linuxkpi/common/include/asm/atomic-long.h
index d7f839f2541f5..108d7f4f7b3a3 100644
--- a/sys/compat/linuxkpi/common/include/asm/atomic-long.h
+++ b/sys/compat/linuxkpi/common/include/asm/atomic-long.h
@@ -42,6 +42,7 @@ typedef struct {
} atomic_long_t;
#define atomic_long_add(i, v) atomic_long_add_return((i), (v))
+#define atomic_long_sub(i, v) atomic_long_add_return(-(i), (v))
#define atomic_long_inc_return(v) atomic_long_add_return(1, (v))
#define atomic_long_inc_not_zero(v) atomic_long_add_unless((v), 1, 0)
diff --git a/sys/compat/linuxkpi/common/include/linux/rculist.h b/sys/compat/linuxkpi/common/include/linux/rculist.h
index e4823de7a3bf7..0a4ad499c3807 100644
--- a/sys/compat/linuxkpi/common/include/linux/rculist.h
+++ b/sys/compat/linuxkpi/common/include/linux/rculist.h
@@ -33,6 +33,25 @@
#include <linux/list.h>
#include <linux/rcupdate.h>
+#define list_entry_rcu(ptr, type, member) \
+ container_of(READ_ONCE(ptr), type, member)
+
+#define list_next_rcu(head) (*((struct list_head **)(&(head)->next)))
+
+#define list_for_each_entry_rcu(pos, head, member) \
+ for (pos = list_entry_rcu((head)->next, typeof(*(pos)), member); \
+ &(pos)->member != (head); \
+ pos = list_entry_rcu((pos)->member.next, typeof(*(pos)), member))
+
+static inline void
+list_add_rcu(struct list_head *new, struct list_head *prev)
+{
+ new->next = prev->next;
+ new->prev = prev;
+ rcu_assign_pointer(list_next_rcu(prev), new);
+ prev->prev = new;
+}
+
#define hlist_first_rcu(head) (*((struct hlist_node **)(&(head)->first)))
#define hlist_next_rcu(node) (*((struct hlist_node **)(&(node)->next)))
#define hlist_pprev_rcu(node) (*((struct hlist_node **)((node)->pprev)))
@@ -47,8 +66,12 @@ hlist_add_behind_rcu(struct hlist_node *n, struct hlist_node *prev)
n->next->pprev = &n->next;
}
-#define hlist_for_each_entry_rcu(pos, head, member) \
- hlist_for_each_entry(pos, head, member)
+#define hlist_for_each_entry_rcu(pos, head, member) \
+ for (pos = hlist_entry_safe (rcu_dereference_raw(hlist_first_rcu(head)),\
+ typeof(*(pos)), member); \
+ (pos); \
+ pos = hlist_entry_safe(rcu_dereference_raw(hlist_next_rcu( \
+ &(pos)->member)), typeof(*(pos)), member))
static inline void
hlist_del_rcu(struct hlist_node *n)
diff --git a/sys/conf/NOTES b/sys/conf/NOTES
index 30ae142ba29b3..dfa5ff68d802d 100644
--- a/sys/conf/NOTES
+++ b/sys/conf/NOTES
@@ -1170,9 +1170,6 @@ options NFS_DEBUG # Enable NFS Debugging
#
options EXT2FS
-# Cryptographically secure random number generator; /dev/random
-device random
-
# The system memory devices; /dev/mem, /dev/kmem
device mem
@@ -2424,14 +2421,19 @@ device iicoc # OpenCores I2C controller support
# I2C peripheral devices
#
+device ad7418 # Analog Devices temp and voltage sensor
device ds1307 # Dallas DS1307 RTC and compatible
device ds13rtc # All Dallas/Maxim ds13xx chips
device ds1672 # Dallas DS1672 RTC
device ds3231 # Dallas DS3231 RTC + temperature
device icee # AT24Cxxx and compatible EEPROMs
+device isl12xx # Intersil ISL12xx RTC
device lm75 # LM75 compatible temperature sensor
device nxprtc # NXP RTCs: PCA/PFC212x PCA/PCF85xx
+device rtc8583 # Epson RTC-8583
device s35390a # Seiko Instruments S-35390A RTC
+device sy8106a # Silergy Corp. SY8106A buck regulator
+device syr827 # Silergy Corp. DC/DC regulator
# Parallel-Port Bus
#
@@ -2479,6 +2481,22 @@ device pps
device lpbb
device pcfclock
+# General Purpose I/O pins
+device gpio # gpio interfaces and bus support
+device gpiobacklight # sysctl control of gpio-based backlight
+device gpioiic # i2c via gpio bitbang
+device gpiokeys # kbd(4) glue for gpio-based key input
+device gpioled # led(4) gpio glue
+device gpiopower # event handler for gpio-based powerdown
+device gpiopps # Pulse per second input from gpio pin
+device gpioregulator # extres/regulator glue for gpio pin
+device gpiospi # SPI via gpio bitbang
+device gpioths # 1-wire temp/humidity sensor on gpio pin
+
+# Pulse width modulation
+device pwmbus # pwm interface and bus support
+device pwmc # userland control access to pwm outputs
+
#
# Etherswitch framework and drivers
#
diff --git a/sys/conf/files b/sys/conf/files
index dd67e0ec7a684..c62a9e285e47e 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -686,14 +686,14 @@ crypto/des/des_ecb.c optional crypto | ipsec | ipsec_support | netsmb
crypto/des/des_setkey.c optional crypto | ipsec | ipsec_support | netsmb
crypto/rc4/rc4.c optional netgraph_mppc_encryption | kgssapi
crypto/rijndael/rijndael-alg-fst.c optional crypto | ekcd | geom_bde | \
- ipsec | ipsec_support | random !random_loadable | wlan_ccmp
-crypto/rijndael/rijndael-api-fst.c optional ekcd | geom_bde | random !random_loadable
+ ipsec | ipsec_support | !random_loadable | wlan_ccmp
+crypto/rijndael/rijndael-api-fst.c optional ekcd | geom_bde | !random_loadable
crypto/rijndael/rijndael-api.c optional crypto | ipsec | ipsec_support | \
wlan_ccmp
crypto/sha1.c optional carp | crypto | ether | ipsec | \
ipsec_support | netgraph_mppc_encryption | sctp
crypto/sha2/sha256c.c optional crypto | ekcd | geom_bde | ipsec | \
- ipsec_support | random !random_loadable | sctp | zfs
+ ipsec_support | !random_loadable | sctp | zfs
crypto/sha2/sha512c.c optional crypto | geom_bde | ipsec | \
ipsec_support | zfs
crypto/skein/skein.c optional crypto | zfs
@@ -1708,7 +1708,7 @@ dev/fdt/fdt_clock_if.m optional fdt fdt_clock
dev/fdt/fdt_common.c optional fdt
dev/fdt/fdt_pinctrl.c optional fdt fdt_pinctrl
dev/fdt/fdt_pinctrl_if.m optional fdt fdt_pinctrl
-dev/fdt/fdt_slicer.c optional fdt cfi | fdt nand | fdt mx25l | fdt n25q | fdt at45d
+dev/fdt/fdt_slicer.c optional fdt cfi | fdt mx25l | fdt n25q | fdt at45d
dev/fdt/fdt_static_dtb.S optional fdt fdt_dtb_static \
dependency "${FDT_DTS_FILE:T:R}.dtb"
dev/fdt/simplebus.c optional fdt
@@ -1751,7 +1751,7 @@ dev/gpio/gpiospi.c optional gpiospi
dev/gpio/gpioths.c optional gpioths
dev/gpio/gpio_if.m optional gpio
dev/gpio/gpiobus_if.m optional gpio
-dev/gpio/gpiopps.c optional gpiopps
+dev/gpio/gpiopps.c optional gpiopps fdt
dev/gpio/ofw_gpiobus.c optional fdt gpio
dev/hifn/hifn7751.c optional hifn
dev/hme/if_hme.c optional hme
@@ -1775,7 +1775,7 @@ dev/iicbus/ds13rtc.c optional ds13rtc | ds133x | ds1374
dev/iicbus/ds1672.c optional ds1672
dev/iicbus/ds3231.c optional ds3231
dev/iicbus/rtc8583.c optional rtc8583
-dev/iicbus/syr827.c optional ext_resources syr827
+dev/iicbus/syr827.c optional syr827 ext_resources fdt
dev/iicbus/icee.c optional icee
dev/iicbus/if_ic.c optional ic
dev/iicbus/iic.c optional iic
@@ -1792,7 +1792,9 @@ dev/iicbus/isl12xx.c optional isl12xx
dev/iicbus/lm75.c optional lm75
dev/iicbus/nxprtc.c optional nxprtc | pcf8563
dev/iicbus/ofw_iicbus.c optional fdt iicbus
+dev/iicbus/rtc8583.c optional rtc8583
dev/iicbus/s35390a.c optional s35390a
+dev/iicbus/sy8106a.c optional sy8106a ext_resources fdt
dev/iir/iir.c optional iir
dev/iir/iir_ctrl.c optional iir
dev/iir/iir_pci.c optional iir pci
@@ -2455,21 +2457,6 @@ dev/mxge/mxge_ethp_z8e.c optional mxge pci
dev/mxge/mxge_rss_eth_z8e.c optional mxge pci
dev/mxge/mxge_rss_ethp_z8e.c optional mxge pci
dev/my/if_my.c optional my
-dev/nand/nand.c optional nand
-dev/nand/nand_bbt.c optional nand
-dev/nand/nand_cdev.c optional nand
-dev/nand/nand_generic.c optional nand
-dev/nand/nand_geom.c optional nand
-dev/nand/nand_id.c optional nand
-dev/nand/nandbus.c optional nand
-dev/nand/nandbus_if.m optional nand
-dev/nand/nand_if.m optional nand
-dev/nand/nandsim.c optional nandsim nand
-dev/nand/nandsim_chip.c optional nandsim nand
-dev/nand/nandsim_ctrl.c optional nandsim nand
-dev/nand/nandsim_log.c optional nandsim nand
-dev/nand/nandsim_swap.c optional nandsim nand
-dev/nand/nfc_if.m optional nand
dev/netmap/if_ptnet.c optional netmap inet
dev/netmap/netmap.c optional netmap
dev/netmap/netmap_bdg.c optional netmap
@@ -2766,11 +2753,11 @@ rt2860.fw optional rt2860fw | ralfw \
compile-with "${NORMAL_FW}" \
no-obj no-implicit-rule \
clean "rt2860.fw"
-dev/random/random_infra.c optional random
-dev/random/random_harvestq.c optional random
-dev/random/randomdev.c optional random !random_loadable
-dev/random/fortuna.c optional random !random_loadable
-dev/random/hash.c optional random !random_loadable
+dev/random/random_infra.c standard
+dev/random/random_harvestq.c standard
+dev/random/randomdev.c optional !random_loadable
+dev/random/fortuna.c optional !random_loadable
+dev/random/hash.c optional !random_loadable
dev/rc/rc.c optional rc
dev/rccgpio/rccgpio.c optional rccgpio gpio
dev/re/if_re.c optional re
@@ -3497,20 +3484,6 @@ fs/msdosfs/msdosfs_iconv.c optional msdosfs_iconv
fs/msdosfs/msdosfs_lookup.c optional msdosfs
fs/msdosfs/msdosfs_vfsops.c optional msdosfs
fs/msdosfs/msdosfs_vnops.c optional msdosfs
-fs/nandfs/bmap.c optional nandfs
-fs/nandfs/nandfs_alloc.c optional nandfs
-fs/nandfs/nandfs_bmap.c optional nandfs
-fs/nandfs/nandfs_buffer.c optional nandfs
-fs/nandfs/nandfs_cleaner.c optional nandfs
-fs/nandfs/nandfs_cpfile.c optional nandfs
-fs/nandfs/nandfs_dat.c optional nandfs
-fs/nandfs/nandfs_dir.c optional nandfs
-fs/nandfs/nandfs_ifile.c optional nandfs
-fs/nandfs/nandfs_segment.c optional nandfs
-fs/nandfs/nandfs_subr.c optional nandfs
-fs/nandfs/nandfs_sufile.c optional nandfs
-fs/nandfs/nandfs_vfsops.c optional nandfs
-fs/nandfs/nandfs_vnops.c optional nandfs
fs/nfs/nfs_commonkrpc.c optional nfscl | nfsd
fs/nfs/nfs_commonsubs.c optional nfscl | nfsd
fs/nfs/nfs_commonport.c optional nfscl | nfsd
@@ -3598,7 +3571,7 @@ geom/geom_disk.c standard
geom/geom_dump.c standard
geom/geom_event.c standard
geom/geom_fox.c optional geom_fox
-geom/geom_flashmap.c optional fdt cfi | fdt nand | fdt mx25l | mmcsd | fdt n25q | fdt at45d
+geom/geom_flashmap.c optional fdt cfi | fdt mx25l | mmcsd | fdt n25q | fdt at45d
geom/geom_io.c standard
geom/geom_kern.c standard
geom/geom_map.c optional geom_map
diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64
index 1d399122c50c2..81cd730a5c343 100644
--- a/sys/conf/files.amd64
+++ b/sys/conf/files.amd64
@@ -389,6 +389,9 @@ dev/qlxgbe/ql_isr.c optional qlxgbe pci
dev/qlxgbe/ql_misc.c optional qlxgbe pci
dev/qlxgbe/ql_os.c optional qlxgbe pci
dev/qlxgbe/ql_reset.c optional qlxgbe pci
+dev/qlxgbe/ql_fw.c optional qlxgbe pci
+dev/qlxgbe/ql_boot.c optional qlxgbe pci
+dev/qlxgbe/ql_minidump.c optional qlxgbe pci
dev/qlnx/qlnxe/ecore_cxt.c optional qlnxe pci \
compile-with "${LINUXKPI_C}"
dev/qlnx/qlnxe/ecore_dbg_fw_funcs.c optional qlnxe pci \
diff --git a/sys/conf/files.arm b/sys/conf/files.arm
index 6134b20e11772..8d890144b277b 100644
--- a/sys/conf/files.arm
+++ b/sys/conf/files.arm
@@ -166,6 +166,12 @@ cloudabi32_vdso_blob.o optional compat_cloudabi32 \
clean "cloudabi32_vdso_blob.o"
#
+#
+ukbdmap.h optional ukbd_dflt_keymap \
+ compile-with "kbdcontrol -P ${S:S/sys$/share/}/vt/keymaps -P ${S:S/sys$/share/}/syscons/keymaps -L ${UKBD_DFLT_KEYMAP} | sed -e 's/^static keymap_t.* = /static keymap_t key_map = /' -e 's/^static accentmap_t.* = /static accentmap_t accent_map = /' > ukbdmap.h" \
+ no-obj no-implicit-rule before-depend \
+ clean "ukbdmap.h"
+
# Annapurna support
arm/annapurna/alpine/alpine_ccu.c optional al_ccu fdt
arm/annapurna/alpine/alpine_nb_service.c optional al_nb_service fdt
diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64
index f8d9beba599da..b8c0234252935 100644
--- a/sys/conf/files.arm64
+++ b/sys/conf/files.arm64
@@ -87,7 +87,7 @@ arm/broadcom/bcm2835/bcm2835_ft5406.c optional evdev bcm2835_ft5406 soc_brcm_bc
arm/broadcom/bcm2835/bcm2835_gpio.c optional gpio soc_brcm_bcm2837 fdt
arm/broadcom/bcm2835/bcm2835_intr.c optional soc_brcm_bcm2837 fdt
arm/broadcom/bcm2835/bcm2835_mbox.c optional soc_brcm_bcm2837 fdt
-arm/broadcom/bcm2835/bcm2835_rng.c optional random !random_loadable soc_brcm_bcm2837 fdt
+arm/broadcom/bcm2835/bcm2835_rng.c optional !random_loadable soc_brcm_bcm2837 fdt
arm/broadcom/bcm2835/bcm2835_sdhci.c optional sdhci soc_brcm_bcm2837 fdt
arm/broadcom/bcm2835/bcm2835_sdhost.c optional sdhci soc_brcm_bcm2837 fdt
arm/broadcom/bcm2835/bcm2835_spi.c optional bcm2835_spi soc_brcm_bcm2837 fdt
diff --git a/sys/conf/files.powerpc b/sys/conf/files.powerpc
index cbda69a0d7cf0..5383595b1411c 100644
--- a/sys/conf/files.powerpc
+++ b/sys/conf/files.powerpc
@@ -43,8 +43,6 @@ dev/iicbus/max6690.c optional max6690 powermac
dev/iicbus/ofw_iicbus.c optional iicbus aim
dev/ipmi/ipmi.c optional ipmi
dev/ipmi/ipmi_opal.c optional powernv ipmi
-dev/nand/nfc_fsl.c optional nand mpc85xx
-dev/nand/nfc_rb.c optional nand mpc85xx
# Most ofw stuff below is brought in by conf/files for options FDT, but
# we always want it, even on non-FDT platforms.
dev/fdt/simplebus.c standard
@@ -62,7 +60,7 @@ dev/ofw/ofw_standard.c optional aim powerpc
dev/ofw/ofw_subr.c standard
dev/powermac_nvram/powermac_nvram.c optional powermac_nvram powermac
dev/quicc/quicc_bfe_fdt.c optional quicc mpc85xx
-dev/random/darn.c optional powerpc64 random !random_loadable
+dev/random/darn.c optional powerpc64 !random_loadable
dev/scc/scc_bfe_macio.c optional scc powermac
dev/sdhci/fsl_sdhci.c optional mpc85xx sdhci
dev/sec/sec.c optional sec mpc85xx
diff --git a/sys/conf/kern.opts.mk b/sys/conf/kern.opts.mk
index 33aa0bcba9892..58f125efbd061 100644
--- a/sys/conf/kern.opts.mk
+++ b/sys/conf/kern.opts.mk
@@ -52,7 +52,6 @@ __DEFAULT_YES_OPTIONS = \
__DEFAULT_NO_OPTIONS = \
EXTRA_TCP_STACKS \
KERNEL_RETPOLINE \
- NAND \
OFED \
RATELIMIT
diff --git a/sys/conf/makeLINT.mk b/sys/conf/makeLINT.mk
index 52dddf5a97d74..d3a414c14ff6f 100644
--- a/sys/conf/makeLINT.mk
+++ b/sys/conf/makeLINT.mk
@@ -47,6 +47,11 @@ LINT: ${NOTES} ${MAKELINT_SED}
echo "nodevice txp" >> ${.TARGET}-NOIP
echo "nodevice netmap" >> ${.TARGET}-NOIP
.endif
+.if ${TARGET} == "arm"
+ cat ${.TARGET} ${.CURDIR}/NOTES.armv5 > ${.TARGET}-V5
+ cat ${.TARGET} ${.CURDIR}/NOTES.armv7 > ${.TARGET}-V7
+ rm ${.TARGET}
+.endif
.if ${TARGET} == "mips"
echo "machine ${TARGET} ${TARGET_ARCH}" >> ${.TARGET}
.endif
diff --git a/sys/conf/options b/sys/conf/options
index df394936b9d41..c4c3bb7eed67d 100644
--- a/sys/conf/options
+++ b/sys/conf/options
@@ -256,7 +256,6 @@ FDESCFS opt_dontuse.h
FFS opt_dontuse.h
FUSEFS opt_dontuse.h
MSDOSFS opt_dontuse.h
-NANDFS opt_dontuse.h
NULLFS opt_dontuse.h
PROCFS opt_dontuse.h
PSEUDOFS opt_dontuse.h
@@ -734,7 +733,6 @@ DEV_PCI opt_pci.h
DEV_PF opt_pf.h
DEV_PFLOG opt_pf.h
DEV_PFSYNC opt_pf.h
-DEV_RANDOM opt_global.h
DEV_SPLASH opt_splash.h
DEV_VLAN opt_vlan.h
@@ -863,6 +861,12 @@ AH_INTERRUPT_DEBUGGING opt_ah.h
# XXX do not use this for AR9130
AH_AR5416_INTERRUPT_MITIGATION opt_ah.h
+# options for the Altera mSGDMA driver (altera_msgdma)
+ALTERA_MSGDMA_DESC_STD opt_altera_msgdma.h
+ALTERA_MSGDMA_DESC_EXT opt_altera_msgdma.h
+ALTERA_MSGDMA_DESC_PF_STD opt_altera_msgdma.h
+ALTERA_MSGDMA_DESC_PF_EXT opt_altera_msgdma.h
+
# options for the Broadcom BCM43xx driver (bwi)
BWI_DEBUG opt_bwi.h
BWI_DEBUG_VERBOSE opt_bwi.h
diff --git a/sys/contrib/ipfilter/netinet/fil.c b/sys/contrib/ipfilter/netinet/fil.c
index a0d008dbd2d72..1d142165c3411 100644
--- a/sys/contrib/ipfilter/netinet/fil.c
+++ b/sys/contrib/ipfilter/netinet/fil.c
@@ -1723,29 +1723,31 @@ ipf_pr_ipv4hdr(fin)
* calculate the byte offset that it represents.
*/
off &= IP_MF|IP_OFFMASK;
+ if (off == 1 && p == IPPROTO_TCP) {
+ fin->fin_flx |= FI_SHORT; /* RFC 3128 */
+ DT1(ipf_fi_tcp_frag_off_1, fr_info_t *, fin);
+ }
if (off != 0) {
int morefrag = off & IP_MF;
fi->fi_flx |= FI_FRAG;
off &= IP_OFFMASK;
- if (off != 0) {
- fin->fin_flx |= FI_FRAGBODY;
- off <<= 3;
- if ((off + fin->fin_dlen > 65535) ||
- (fin->fin_dlen == 0) ||
- ((morefrag != 0) && ((fin->fin_dlen & 7) != 0))) {
- /*
- * The length of the packet, starting at its
- * offset cannot exceed 65535 (0xffff) as the
- * length of an IP packet is only 16 bits.
- *
- * Any fragment that isn't the last fragment
- * must have a length greater than 0 and it
- * must be an even multiple of 8.
- */
- fi->fi_flx |= FI_BAD;
- DT1(ipf_fi_bad_fragbody_gt_65535, fr_info_t *, fin);
- }
+ fin->fin_flx |= FI_FRAGBODY;
+ off <<= 3;
+ if ((off + fin->fin_dlen > 65535) ||
+ (fin->fin_dlen == 0) ||
+ ((morefrag != 0) && ((fin->fin_dlen & 7) != 0))) {
+ /*
+ * The length of the packet, starting at its
+ * offset cannot exceed 65535 (0xffff) as the
+ * length of an IP packet is only 16 bits.
+ *
+ * Any fragment that isn't the last fragment
+ * must have a length greater than 0 and it
+ * must be an even multiple of 8.
+ */
+ fi->fi_flx |= FI_BAD;
+ DT1(ipf_fi_bad_fragbody_gt_65535, fr_info_t *, fin);
}
}
fin->fin_off = off;
@@ -7472,10 +7474,6 @@ ipf_resolvedest(softc, base, fdp, v)
}
fdp->fd_ptr = ifp;
- if ((ifp != NULL) && (ifp != (void *)-1)) {
- fdp->fd_local = ipf_deliverlocal(softc, v, ifp, &fdp->fd_ip6);
- }
-
return errval;
}
diff --git a/sys/contrib/ipfilter/netinet/ip_compat.h b/sys/contrib/ipfilter/netinet/ip_compat.h
index 777495b39aed4..75f4d7c116ce4 100644
--- a/sys/contrib/ipfilter/netinet/ip_compat.h
+++ b/sys/contrib/ipfilter/netinet/ip_compat.h
@@ -829,190 +829,9 @@ typedef struct tcpiphdr tcpiphdr_t;
#undef IPOPT_AH
#define IPOPT_AH 256+IPPROTO_AH
-#ifndef TCPOPT_EOL
-# define TCPOPT_EOL 0
-#endif
-#ifndef TCPOPT_NOP
-# define TCPOPT_NOP 1
-#endif
-#ifndef TCPOPT_MAXSEG
-# define TCPOPT_MAXSEG 2
-#endif
-#ifndef TCPOLEN_MAXSEG
-# define TCPOLEN_MAXSEG 4
-#endif
-#ifndef TCPOPT_WINDOW
-# define TCPOPT_WINDOW 3
-#endif
-#ifndef TCPOLEN_WINDOW
-# define TCPOLEN_WINDOW 3
-#endif
-#ifndef TCPOPT_SACK_PERMITTED
-# define TCPOPT_SACK_PERMITTED 4
-#endif
-#ifndef TCPOLEN_SACK_PERMITTED
-# define TCPOLEN_SACK_PERMITTED 2
-#endif
-#ifndef TCPOPT_SACK
-# define TCPOPT_SACK 5
-#endif
-#ifndef TCPOPT_TIMESTAMP
-# define TCPOPT_TIMESTAMP 8
-#endif
+# define ICMP_UNREACH_ADMIN_PROHIBIT ICMP_UNREACH_FILTER_PROHIB
+# define ICMP_UNREACH_FILTER ICMP_UNREACH_FILTER_PROHIB
-#ifndef ICMP_MINLEN
-# define ICMP_MINLEN 8
-#endif
-#ifndef ICMP_ECHOREPLY
-# define ICMP_ECHOREPLY 0
-#endif
-#ifndef ICMP_UNREACH
-# define ICMP_UNREACH 3
-#endif
-#ifndef ICMP_UNREACH_NET
-# define ICMP_UNREACH_NET 0
-#endif
-#ifndef ICMP_UNREACH_HOST
-# define ICMP_UNREACH_HOST 1
-#endif
-#ifndef ICMP_UNREACH_PROTOCOL
-# define ICMP_UNREACH_PROTOCOL 2
-#endif
-#ifndef ICMP_UNREACH_PORT
-# define ICMP_UNREACH_PORT 3
-#endif
-#ifndef ICMP_UNREACH_NEEDFRAG
-# define ICMP_UNREACH_NEEDFRAG 4
-#endif
-#ifndef ICMP_UNREACH_SRCFAIL
-# define ICMP_UNREACH_SRCFAIL 5
-#endif
-#ifndef ICMP_UNREACH_NET_UNKNOWN
-# define ICMP_UNREACH_NET_UNKNOWN 6
-#endif
-#ifndef ICMP_UNREACH_HOST_UNKNOWN
-# define ICMP_UNREACH_HOST_UNKNOWN 7
-#endif
-#ifndef ICMP_UNREACH_ISOLATED
-# define ICMP_UNREACH_ISOLATED 8
-#endif
-#ifndef ICMP_UNREACH_NET_PROHIB
-# define ICMP_UNREACH_NET_PROHIB 9
-#endif
-#ifndef ICMP_UNREACH_HOST_PROHIB
-# define ICMP_UNREACH_HOST_PROHIB 10
-#endif
-#ifndef ICMP_UNREACH_TOSNET
-# define ICMP_UNREACH_TOSNET 11
-#endif
-#ifndef ICMP_UNREACH_TOSHOST
-# define ICMP_UNREACH_TOSHOST 12
-#endif
-#ifndef ICMP_UNREACH_ADMIN_PROHIBIT
-# define ICMP_UNREACH_ADMIN_PROHIBIT 13
-#endif
-#ifndef ICMP_UNREACH_FILTER
-# define ICMP_UNREACH_FILTER 13
-#endif
-#ifndef ICMP_UNREACH_HOST_PRECEDENCE
-# define ICMP_UNREACH_HOST_PRECEDENCE 14
-#endif
-#ifndef ICMP_UNREACH_PRECEDENCE_CUTOFF
-# define ICMP_UNREACH_PRECEDENCE_CUTOFF 15
-#endif
-#ifndef ICMP_SOURCEQUENCH
-# define ICMP_SOURCEQUENCH 4
-#endif
-#ifndef ICMP_REDIRECT_NET
-# define ICMP_REDIRECT_NET 0
-#endif
-#ifndef ICMP_REDIRECT_HOST
-# define ICMP_REDIRECT_HOST 1
-#endif
-#ifndef ICMP_REDIRECT_TOSNET
-# define ICMP_REDIRECT_TOSNET 2
-#endif
-#ifndef ICMP_REDIRECT_TOSHOST
-# define ICMP_REDIRECT_TOSHOST 3
-#endif
-#ifndef ICMP_ALTHOSTADDR
-# define ICMP_ALTHOSTADDR 6
-#endif
-#ifndef ICMP_TIMXCEED
-# define ICMP_TIMXCEED 11
-#endif
-#ifndef ICMP_TIMXCEED_INTRANS
-# define ICMP_TIMXCEED_INTRANS 0
-#endif
-#ifndef ICMP_TIMXCEED_REASS
-# define ICMP_TIMXCEED_REASS 1
-#endif
-#ifndef ICMP_PARAMPROB
-# define ICMP_PARAMPROB 12
-#endif
-#ifndef ICMP_PARAMPROB_ERRATPTR
-# define ICMP_PARAMPROB_ERRATPTR 0
-#endif
-#ifndef ICMP_PARAMPROB_OPTABSENT
-# define ICMP_PARAMPROB_OPTABSENT 1
-#endif
-#ifndef ICMP_PARAMPROB_LENGTH
-# define ICMP_PARAMPROB_LENGTH 2
-#endif
-#ifndef ICMP_TSTAMP
-# define ICMP_TSTAMP 13
-#endif
-#ifndef ICMP_TSTAMPREPLY
-# define ICMP_TSTAMPREPLY 14
-#endif
-#ifndef ICMP_IREQ
-# define ICMP_IREQ 15
-#endif
-#ifndef ICMP_IREQREPLY
-# define ICMP_IREQREPLY 16
-#endif
-#ifndef ICMP_MASKREQ
-# define ICMP_MASKREQ 17
-#endif
-#ifndef ICMP_MASKREPLY
-# define ICMP_MASKREPLY 18
-#endif
-#ifndef ICMP_TRACEROUTE
-# define ICMP_TRACEROUTE 30
-#endif
-#ifndef ICMP_DATACONVERR
-# define ICMP_DATACONVERR 31
-#endif
-#ifndef ICMP_MOBILE_REDIRECT
-# define ICMP_MOBILE_REDIRECT 32
-#endif
-#ifndef ICMP_IPV6_WHEREAREYOU
-# define ICMP_IPV6_WHEREAREYOU 33
-#endif
-#ifndef ICMP_IPV6_IAMHERE
-# define ICMP_IPV6_IAMHERE 34
-#endif
-#ifndef ICMP_MOBILE_REGREQUEST
-# define ICMP_MOBILE_REGREQUEST 35
-#endif
-#ifndef ICMP_MOBILE_REGREPLY
-# define ICMP_MOBILE_REGREPLY 36
-#endif
-#ifndef ICMP_SKIP
-# define ICMP_SKIP 39
-#endif
-#ifndef ICMP_PHOTURIS
-# define ICMP_PHOTURIS 40
-#endif
-#ifndef ICMP_PHOTURIS_UNKNOWN_INDEX
-# define ICMP_PHOTURIS_UNKNOWN_INDEX 1
-#endif
-#ifndef ICMP_PHOTURIS_AUTH_FAILED
-# define ICMP_PHOTURIS_AUTH_FAILED 2
-#endif
-#ifndef ICMP_PHOTURIS_DECRYPT_FAILED
-# define ICMP_PHOTURIS_DECRYPT_FAILED 3
-#endif
#ifndef IPVERSION
# define IPVERSION 4
#endif
diff --git a/sys/contrib/ipfilter/netinet/ip_fil.h b/sys/contrib/ipfilter/netinet/ip_fil.h
index f3185c6458d7f..032cf0dea853f 100644
--- a/sys/contrib/ipfilter/netinet/ip_fil.h
+++ b/sys/contrib/ipfilter/netinet/ip_fil.h
@@ -560,7 +560,6 @@ typedef struct frdest {
addrfamily_t fd_addr;
fr_dtypes_t fd_type;
int fd_name;
- int fd_local;
} frdest_t;
#define fd_ip6 fd_addr.adf_addr
diff --git a/sys/ddb/db_ps.c b/sys/ddb/db_ps.c
index 72bf0edd91618..82e50e0ca85d2 100644
--- a/sys/ddb/db_ps.c
+++ b/sys/ddb/db_ps.c
@@ -481,7 +481,7 @@ DB_SHOW_COMMAND(proc, db_show_proc)
dump_args(p);
db_printf("\n");
}
- db_printf(" repear: %p reapsubtree: %d\n",
+ db_printf(" reaper: %p reapsubtree: %d\n",
p->p_reaper, p->p_reapsubtree);
db_printf(" sigparent: %d\n", p->p_sigparent);
db_printf(" vmspace: %p\n", p->p_vmspace);
diff --git a/sys/dev/ahci/ahci.c b/sys/dev/ahci/ahci.c
index 4a17fb535498f..435661107e955 100644
--- a/sys/dev/ahci/ahci.c
+++ b/sys/dev/ahci/ahci.c
@@ -186,6 +186,7 @@ ahci_attach(device_t dev)
ctlr->ccc = 0;
resource_int_value(device_get_name(dev),
device_get_unit(dev), "ccc", &ctlr->ccc);
+ mtx_init(&ctlr->ch_mtx, "AHCI channels lock", NULL, MTX_DEF);
/* Setup our own memory management for channels. */
ctlr->sc_iomem.rm_start = rman_get_start(ctlr->r_mem);
@@ -379,6 +380,7 @@ ahci_detach(device_t dev)
/* Free memory. */
rman_fini(&ctlr->sc_iomem);
ahci_free_mem(dev);
+ mtx_destroy(&ctlr->ch_mtx);
return (0);
}
@@ -666,6 +668,50 @@ ahci_get_dma_tag(device_t dev, device_t child)
return (ctlr->dma_tag);
}
+void
+ahci_attached(device_t dev, struct ahci_channel *ch)
+{
+ struct ahci_controller *ctlr = device_get_softc(dev);
+
+ mtx_lock(&ctlr->ch_mtx);
+ ctlr->ch[ch->unit] = ch;
+ mtx_unlock(&ctlr->ch_mtx);
+}
+
+void
+ahci_detached(device_t dev, struct ahci_channel *ch)
+{
+ struct ahci_controller *ctlr = device_get_softc(dev);
+
+ mtx_lock(&ctlr->ch_mtx);
+ mtx_lock(&ch->mtx);
+ ctlr->ch[ch->unit] = NULL;
+ mtx_unlock(&ch->mtx);
+ mtx_unlock(&ctlr->ch_mtx);
+}
+
+struct ahci_channel *
+ahci_getch(device_t dev, int n)
+{
+ struct ahci_controller *ctlr = device_get_softc(dev);
+ struct ahci_channel *ch;
+
+ KASSERT(n >= 0 && n < AHCI_MAX_PORTS, ("Bad channel number %d", n));
+ mtx_lock(&ctlr->ch_mtx);
+ ch = ctlr->ch[n];
+ if (ch != NULL)
+ mtx_lock(&ch->mtx);
+ mtx_unlock(&ctlr->ch_mtx);
+ return (ch);
+}
+
+void
+ahci_putch(struct ahci_channel *ch)
+{
+
+ mtx_unlock(&ch->mtx);
+}
+
static int
ahci_ch_probe(device_t dev)
{
@@ -824,6 +870,7 @@ ahci_ch_attach(device_t dev)
ahci_ch_pm, ch);
}
mtx_unlock(&ch->mtx);
+ ahci_attached(device_get_parent(dev), ch);
ctx = device_get_sysctl_ctx(dev);
tree = device_get_sysctl_tree(dev);
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "disable_phy",
@@ -849,6 +896,7 @@ ahci_ch_detach(device_t dev)
{
struct ahci_channel *ch = device_get_softc(dev);
+ ahci_detached(device_get_parent(dev), ch);
mtx_lock(&ch->mtx);
xpt_async(AC_LOST_DEVICE, ch->path, NULL);
/* Forget about reset. */
diff --git a/sys/dev/ahci/ahci.h b/sys/dev/ahci/ahci.h
index fc53d346f17fc..27b3970dadfc1 100644
--- a/sys/dev/ahci/ahci.h
+++ b/sys/dev/ahci/ahci.h
@@ -524,6 +524,8 @@ struct ahci_controller {
} interrupt[AHCI_MAX_PORTS];
void (*ch_start)(struct ahci_channel *);
int dma_coherent; /* DMA is cache-coherent */
+ struct mtx ch_mtx; /* Lock for attached channels */
+ struct ahci_channel *ch[AHCI_MAX_PORTS]; /* Attached channels */
};
enum ahci_err_type {
@@ -654,5 +656,11 @@ int ahci_ctlr_reset(device_t dev);
int ahci_ctlr_setup(device_t dev);
void ahci_free_mem(device_t dev);
+/* Functions to allow AHCI EM to access other channels. */
+void ahci_attached(device_t dev, struct ahci_channel *ch);
+void ahci_detached(device_t dev, struct ahci_channel *ch);
+struct ahci_channel * ahci_getch(device_t dev, int n);
+void ahci_putch(struct ahci_channel *ch);
+
extern devclass_t ahci_devclass;
diff --git a/sys/dev/ahci/ahciem.c b/sys/dev/ahci/ahciem.c
index 9bb4d97177630..a6f22fac56393 100644
--- a/sys/dev/ahci/ahciem.c
+++ b/sys/dev/ahci/ahciem.c
@@ -294,14 +294,14 @@ ahci_em_setleds(device_t dev, int c)
enc = device_get_softc(dev);
val = 0;
- if (enc->status[c][2] & 0x80) /* Activity */
+ if (enc->status[c][2] & SESCTL_RQSACT) /* Activity */
val |= (1 << 0);
- if (enc->status[c][2] & SESCTL_RQSID) /* Identification */
+ if (enc->status[c][1] & SESCTL_RQSRR) /* Rebuild */
+ val |= (1 << 6) | (1 << 3);
+ else if (enc->status[c][2] & SESCTL_RQSID) /* Identification */
val |= (1 << 3);
else if (enc->status[c][3] & SESCTL_RQSFLT) /* Fault */
val |= (1 << 6);
- else if (enc->status[c][1] & 0x02) /* Rebuild */
- val |= (1 << 6) | (1 << 3);
timeout = 10000;
while (ATA_INL(enc->r_memc, 0) & (AHCI_EM_TM | AHCI_EM_RST) &&
@@ -366,9 +366,12 @@ static void
ahci_em_emulate_ses_on_led(device_t dev, union ccb *ccb)
{
struct ahci_enclosure *enc;
+ struct ahci_channel *ch;
struct ses_status_page *page;
struct ses_status_array_dev_slot *ads, *ads0;
struct ses_elm_desc_hdr *elmd;
+ struct ses_elm_addlstatus_eip_hdr *elma;
+ struct ses_elm_ata_hdr *elmb;
uint8_t *buf;
int i;
@@ -391,7 +394,7 @@ ahci_em_emulate_ses_on_led(device_t dev, union ccb *ccb)
strncpy(&buf[3], device_get_nameunit(dev), 7);
strncpy(&buf[10], "AHCI ", SID_VENDOR_SIZE);
strncpy(&buf[18], "SGPIO Enclosure ", SID_PRODUCT_SIZE);
- strncpy(&buf[34], "1.00", SID_REVISION_SIZE);
+ strncpy(&buf[34], "2.00", SID_REVISION_SIZE);
strncpy(&buf[39], "0001", 4);
strncpy(&buf[43], "S-E-S ", 6);
strncpy(&buf[49], "2.00", 4);
@@ -403,14 +406,15 @@ ahci_em_emulate_ses_on_led(device_t dev, union ccb *ccb)
page = (struct ses_status_page *)buf;
if (ccb->ataio.cmd.lba_low == 0x02 &&
ccb->ataio.cmd.features == 0x00 &&
- ccb->ataio.cmd.sector_count >= 2) {
+ ccb->ataio.cmd.sector_count >= 3) {
bzero(buf, ccb->ataio.dxfer_len);
page->hdr.page_code = 0;
- scsi_ulto2b(4, page->hdr.length);
- buf[4] = 0;
- buf[5] = 1;
- buf[6] = 2;
- buf[7] = 7;
+ scsi_ulto2b(5, page->hdr.length);
+ buf[4] = 0x00;
+ buf[5] = 0x01;
+ buf[6] = 0x02;
+ buf[7] = 0x07;
+ buf[8] = 0x0a;
ccb->ccb_h.status = CAM_REQ_CMP;
goto out;
}
@@ -418,26 +422,30 @@ ahci_em_emulate_ses_on_led(device_t dev, union ccb *ccb)
/* SEMB RECEIVE DIAGNOSTIC RESULT (1) */
if (ccb->ataio.cmd.lba_low == 0x02 &&
ccb->ataio.cmd.features == 0x01 &&
- ccb->ataio.cmd.sector_count >= 13) {
+ ccb->ataio.cmd.sector_count >= 16) {
struct ses_enc_desc *ed;
struct ses_elm_type_desc *td;
bzero(buf, ccb->ataio.dxfer_len);
page->hdr.page_code = 0x01;
- scsi_ulto2b(4 + 4 + 36 + 4, page->hdr.length);
+ scsi_ulto2b(4 + sizeof(*ed) + sizeof(*td) + 11,
+ page->hdr.length);
ed = (struct ses_enc_desc *)&buf[8];
ed->byte0 = 0x11;
ed->subenc_id = 0;
ed->num_types = 1;
ed->length = 36;
+ ed->logical_id[0] = 0x30; /* NAA Locally Assigned. */
+ strncpy(&ed->logical_id[1], device_get_nameunit(dev), 7);
strncpy(ed->vendor_id, "AHCI ", SID_VENDOR_SIZE);
strncpy(ed->product_id, "SGPIO Enclosure ", SID_PRODUCT_SIZE);
- strncpy(ed->product_rev, " ", SID_REVISION_SIZE);
+ strncpy(ed->product_rev, "2.00", SID_REVISION_SIZE);
td = (struct ses_elm_type_desc *)ses_enc_desc_next(ed);
td->etype_elm_type = 0x17;
td->etype_maxelt = enc->channels;
td->etype_subenc = 0;
- td->etype_txt_len = 0;
+ td->etype_txt_len = 11;
+ snprintf((char *)(td + 1), 12, "Drive Slots");
ccb->ccb_h.status = CAM_REQ_CMP;
goto out;
}
@@ -453,10 +461,22 @@ ahci_em_emulate_ses_on_led(device_t dev, union ccb *ccb)
for (i = 0; i < enc->channels; i++) {
ads = &page->elements[i + 1].array_dev_slot;
memcpy(ads, enc->status[i], 4);
- ads->common.bytes[0] |=
- (enc->ichannels & (1 << i)) ?
- SES_OBJSTAT_UNKNOWN :
- SES_OBJSTAT_NOTINSTALLED;
+ ch = ahci_getch(device_get_parent(dev), i);
+ if (ch == NULL) {
+ ads->common.bytes[0] |= SES_OBJSTAT_UNKNOWN;
+ continue;
+ }
+ if (ch->pm_present)
+ ads->common.bytes[0] |= SES_OBJSTAT_UNKNOWN;
+ else if (ch->devices)
+ ads->common.bytes[0] |= SES_OBJSTAT_OK;
+ else if (ch->disablephy)
+ ads->common.bytes[0] |= SES_OBJSTAT_NOTAVAIL;
+ else
+ ads->common.bytes[0] |= SES_OBJSTAT_NOTINSTALLED;
+ if (ch->disablephy)
+ ads->common.bytes[3] |= SESCTL_DEVOFF;
+ ahci_putch(ch);
}
ccb->ccb_h.status = CAM_REQ_CMP;
goto out;
@@ -471,21 +491,21 @@ ahci_em_emulate_ses_on_led(device_t dev, union ccb *ccb)
ads = &page->elements[i + 1].array_dev_slot;
if (ads->common.bytes[0] & SESCTL_CSEL) {
enc->status[i][0] = 0;
- enc->status[i][1] =
- ads->bytes[0] & 0x02;
- enc->status[i][2] =
- ads->bytes[1] & (0x80 | SESCTL_RQSID);
- enc->status[i][3] =
- ads->bytes[2] & SESCTL_RQSFLT;
+ enc->status[i][1] = ads->bytes[0] &
+ SESCTL_RQSRR;
+ enc->status[i][2] = ads->bytes[1] &
+ (SESCTL_RQSACT | SESCTL_RQSID);
+ enc->status[i][3] = ads->bytes[2] &
+ SESCTL_RQSFLT;
ahci_em_setleds(dev, i);
} else if (ads0->common.bytes[0] & SESCTL_CSEL) {
enc->status[i][0] = 0;
- enc->status[i][1] =
- ads0->bytes[0] & 0x02;
- enc->status[i][2] =
- ads0->bytes[1] & (0x80 | SESCTL_RQSID);
- enc->status[i][3] =
- ads0->bytes[2] & SESCTL_RQSFLT;
+ enc->status[i][1] = ads0->bytes[0] &
+ SESCTL_RQSRR;
+ enc->status[i][2] = ads0->bytes[1] &
+ (SESCTL_RQSACT | SESCTL_RQSID);
+ enc->status[i][3] = ads0->bytes[2] &
+ SESCTL_RQSFLT;
ahci_em_setleds(dev, i);
}
}
@@ -496,15 +516,48 @@ ahci_em_emulate_ses_on_led(device_t dev, union ccb *ccb)
/* SEMB RECEIVE DIAGNOSTIC RESULT (7) */
if (ccb->ataio.cmd.lba_low == 0x02 &&
ccb->ataio.cmd.features == 0x07 &&
- ccb->ataio.cmd.sector_count >= (3 + 3 * enc->channels)) {
+ ccb->ataio.cmd.sector_count >= (6 + 3 * enc->channels)) {
bzero(buf, ccb->ataio.dxfer_len);
page->hdr.page_code = 0x07;
- scsi_ulto2b(4 + 4 + 12 * enc->channels,
+ scsi_ulto2b(4 + 15 + 11 * enc->channels, page->hdr.length);
+ elmd = (struct ses_elm_desc_hdr *)&buf[8];
+ scsi_ulto2b(11, elmd->length);
+ snprintf((char *)(elmd + 1), 12, "Drive Slots");
+ for (i = 0; i < enc->channels; i++) {
+ elmd = (struct ses_elm_desc_hdr *)&buf[8 + 15 + 11 * i];
+ scsi_ulto2b(7, elmd->length);
+ snprintf((char *)(elmd + 1), 8, "Slot %02d", i);
+ }
+ ccb->ccb_h.status = CAM_REQ_CMP;
+ goto out;
+ }
+
+ /* SEMB RECEIVE DIAGNOSTIC RESULT (a) */
+ if (ccb->ataio.cmd.lba_low == 0x02 &&
+ ccb->ataio.cmd.features == 0x0a &&
+ ccb->ataio.cmd.sector_count >= (2 + 3 * enc->channels)) {
+ bzero(buf, ccb->ataio.dxfer_len);
+ page->hdr.page_code = 0x0a;
+ scsi_ulto2b(4 + (sizeof(*elma) + sizeof(*elmb)) * enc->channels,
page->hdr.length);
for (i = 0; i < enc->channels; i++) {
- elmd = (struct ses_elm_desc_hdr *)&buf[8 + 4 + 12 * i];
- scsi_ulto2b(8, elmd->length);
- snprintf((char *)(elmd + 1), 9, "SLOT %03d", i);
+ elma = (struct ses_elm_addlstatus_eip_hdr *)&buf[
+ 8 + (sizeof(*elma) + sizeof(*elmb)) * i];
+ elma->base.byte0 = 0x10 | SPSP_PROTO_ATA;
+ elma->base.length = 2 + sizeof(*elmb);
+ elma->byte2 = 0x01;
+ elma->element_index = 1 + i;
+ ch = ahci_getch(device_get_parent(dev), i);
+ if (ch == NULL) {
+ elma->base.byte0 |= 0x80;
+ continue;
+ }
+ if (ch->devices == 0 || ch->pm_present)
+ elma->base.byte0 |= 0x80;
+ elmb = (struct ses_elm_ata_hdr *)(elma + 1);
+ scsi_ulto4b(cam_sim_path(ch->sim), elmb->bus);
+ scsi_ulto4b(0, elmb->target);
+ ahci_putch(ch);
}
ccb->ccb_h.status = CAM_REQ_CMP;
goto out;
diff --git a/sys/dev/altera/msgdma/msgdma.c b/sys/dev/altera/msgdma/msgdma.c
index c60c7ccfe3521..9acb313f91f59 100644
--- a/sys/dev/altera/msgdma/msgdma.c
+++ b/sys/dev/altera/msgdma/msgdma.c
@@ -60,6 +60,7 @@ __FBSDID("$FreeBSD$");
#include <dev/xdma/xdma.h>
#include "xdma_if.h"
+#include "opt_altera_msgdma.h"
#include <dev/altera/msgdma/msgdma.h>
@@ -470,8 +471,8 @@ msgdma_channel_submit_sg(device_t dev, struct xdma_channel *xchan,
struct msgdma_channel *chan;
struct msgdma_desc *desc;
struct msgdma_softc *sc;
- uint32_t src_addr_lo;
- uint32_t dst_addr_lo;
+ bus_addr_t src_addr_lo;
+ bus_addr_t dst_addr_lo;
uint32_t len;
uint32_t tmp;
int i;
@@ -481,14 +482,18 @@ msgdma_channel_submit_sg(device_t dev, struct xdma_channel *xchan,
chan = (struct msgdma_channel *)xchan->chan;
for (i = 0; i < sg_n; i++) {
- src_addr_lo = (uint32_t)sg[i].src_addr;
- dst_addr_lo = (uint32_t)sg[i].dst_addr;
+ src_addr_lo = sg[i].src_addr;
+ dst_addr_lo = sg[i].dst_addr;
len = (uint32_t)sg[i].len;
dprintf("%s: src %x dst %x len %d\n", __func__,
src_addr_lo, dst_addr_lo, len);
desc = chan->descs[chan->idx_head];
+#if defined(ALTERA_MSGDMA_DESC_EXT) || defined(ALTERA_MSGDMA_DESC_PF_EXT)
+ desc->read_hi = htole32(src_addr_lo >> 32);
+ desc->write_hi = htole32(dst_addr_lo >> 32);
+#endif
desc->read_lo = htole32(src_addr_lo);
desc->write_lo = htole32(dst_addr_lo);
desc->length = htole32(len);
diff --git a/sys/dev/altera/msgdma/msgdma.h b/sys/dev/altera/msgdma/msgdma.h
index e10a233902a2d..498fb93d86bf5 100644
--- a/sys/dev/altera/msgdma/msgdma.h
+++ b/sys/dev/altera/msgdma/msgdma.h
@@ -30,6 +30,8 @@
* $FreeBSD$
*/
+#include "opt_altera_msgdma.h"
+
/* Altera mSGDMA registers. */
#define DMA_STATUS 0x00
#define STATUS_RESETTING (1 << 6)
@@ -75,15 +77,36 @@
#define WRITE4_DESC(_sc, _reg, _val) \
bus_space_write_4(_sc->bst_d, _sc->bsh_d, _reg, htole32(_val))
-/* Prefetcher-disabled descriptor format. */
-struct msgdma_desc_nonpf {
- uint32_t src_addr;
- uint32_t dst_addr;
+#if defined(ALTERA_MSGDMA_DESC_STD)
+
+/* Standard descriptor format with prefetcher disabled. */
+struct msgdma_desc {
+ uint32_t read_lo;
+ uint32_t write_lo;
uint32_t length;
uint32_t control;
};
-/* Prefetcher-enabled descriptor format. */
+#elif defined(ALTERA_MSGDMA_DESC_EXT)
+
+/* Extended descriptor format with prefetcher disabled. */
+struct msgdma_desc {
+ uint32_t read_lo;
+ uint32_t write_lo;
+ uint32_t length;
+ uint8_t write_burst;
+ uint8_t read_burst;
+ uint16_t seq_num;
+ uint16_t write_stride;
+ uint16_t read_stride;
+ uint32_t read_hi;
+ uint32_t write_hi;
+ uint32_t control;
+};
+
+#elif defined(ALTERA_MSGDMA_DESC_PF_STD)
+
+/* Standard descriptor format with prefetcher enabled. */
struct msgdma_desc {
uint32_t read_lo;
uint32_t write_lo;
@@ -94,3 +117,34 @@ struct msgdma_desc {
uint32_t reserved;
uint32_t control;
};
+
+#elif defined(ALTERA_MSGDMA_DESC_PF_EXT)
+
+/* Extended descriptor format with prefetcher enabled. */
+struct msgdma_desc {
+ uint32_t read_lo;
+ uint32_t write_lo;
+ uint32_t length;
+ uint32_t next;
+ uint32_t transferred;
+ uint32_t status;
+ uint32_t reserved;
+ uint8_t write_burst;
+ uint8_t read_burst;
+ uint16_t seq_num;
+ uint16_t write_stride;
+ uint16_t read_stride;
+ uint32_t read_hi;
+ uint32_t write_hi;
+ uint32_t next_hi;
+ uint32_t reserved1;
+ uint32_t reserved2;
+ uint32_t reserved3;
+ uint32_t control;
+};
+
+#else
+
+#error "mSGDMA descriptor format (kernel option) is not set."
+
+#endif
diff --git a/sys/dev/cxgbe/tom/t4_cpl_io.c b/sys/dev/cxgbe/tom/t4_cpl_io.c
index 27ef745c764c0..fd4f376d86762 100644
--- a/sys/dev/cxgbe/tom/t4_cpl_io.c
+++ b/sys/dev/cxgbe/tom/t4_cpl_io.c
@@ -74,7 +74,7 @@ __FBSDID("$FreeBSD$");
#include "tom/t4_tom.h"
static void t4_aiotx_cancel(struct kaiocb *job);
-static void t4_aiotx_queue_toep(struct toepcb *toep);
+static void t4_aiotx_queue_toep(struct socket *so, struct toepcb *toep);
static size_t
aiotx_mbuf_pgoff(struct mbuf *m)
@@ -785,7 +785,7 @@ t4_push_frames(struct adapter *sc, struct toepcb *toep, int drop)
if (sowwakeup) {
if (!TAILQ_EMPTY(
&toep->aiotx_jobq))
- t4_aiotx_queue_toep(
+ t4_aiotx_queue_toep(so,
toep);
sowwakeup_locked(so);
} else
@@ -829,7 +829,7 @@ t4_push_frames(struct adapter *sc, struct toepcb *toep, int drop)
}
if (sowwakeup) {
if (!TAILQ_EMPTY(&toep->aiotx_jobq))
- t4_aiotx_queue_toep(toep);
+ t4_aiotx_queue_toep(so, toep);
sowwakeup_locked(so);
} else
SOCKBUF_UNLOCK(sb);
@@ -1821,7 +1821,7 @@ do_fw4_ack(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
tls_ofld->sb_off -= plen;
}
if (!TAILQ_EMPTY(&toep->aiotx_jobq))
- t4_aiotx_queue_toep(toep);
+ t4_aiotx_queue_toep(so, toep);
sowwakeup_locked(so); /* unlocks so_snd */
}
SOCKBUF_UNLOCK_ASSERT(sb);
@@ -2195,10 +2195,10 @@ static void
t4_aiotx_task(void *context, int pending)
{
struct toepcb *toep = context;
- struct inpcb *inp = toep->inp;
- struct socket *so = inp->inp_socket;
+ struct socket *so;
struct kaiocb *job;
+ so = toep->aiotx_so;
CURVNET_SET(toep->vnet);
SOCKBUF_LOCK(&so->so_snd);
while (!TAILQ_EMPTY(&toep->aiotx_jobq) && sowriteable(so)) {
@@ -2209,15 +2209,17 @@ t4_aiotx_task(void *context, int pending)
t4_aiotx_process_job(toep, so, job);
}
- toep->aiotx_task_active = false;
+ toep->aiotx_so = NULL;
SOCKBUF_UNLOCK(&so->so_snd);
CURVNET_RESTORE();
free_toepcb(toep);
+ SOCK_LOCK(so);
+ sorele(so);
}
static void
-t4_aiotx_queue_toep(struct toepcb *toep)
+t4_aiotx_queue_toep(struct socket *so, struct toepcb *toep)
{
SOCKBUF_LOCK_ASSERT(&toep->inp->inp_socket->so_snd);
@@ -2225,9 +2227,10 @@ t4_aiotx_queue_toep(struct toepcb *toep)
CTR3(KTR_CXGBE, "%s: queueing aiotx task for tid %d, active = %s",
__func__, toep->tid, toep->aiotx_task_active ? "true" : "false");
#endif
- if (toep->aiotx_task_active)
+ if (toep->aiotx_so != NULL)
return;
- toep->aiotx_task_active = true;
+ soref(so);
+ toep->aiotx_so = so;
hold_toepcb(toep);
soaio_enqueue(&toep->aiotx_task);
}
@@ -2284,7 +2287,7 @@ t4_aio_queue_aiotx(struct socket *so, struct kaiocb *job)
panic("new job was cancelled");
TAILQ_INSERT_TAIL(&toep->aiotx_jobq, job, list);
if (sowriteable(so))
- t4_aiotx_queue_toep(toep);
+ t4_aiotx_queue_toep(so, toep);
SOCKBUF_UNLOCK(&so->so_snd);
return (0);
}
diff --git a/sys/dev/cxgbe/tom/t4_ddp.c b/sys/dev/cxgbe/tom/t4_ddp.c
index 47062e634bbf0..f3f03e0faa2c4 100644
--- a/sys/dev/cxgbe/tom/t4_ddp.c
+++ b/sys/dev/cxgbe/tom/t4_ddp.c
@@ -220,7 +220,7 @@ release_ddp_resources(struct toepcb *toep)
int i;
DDP_LOCK(toep);
- toep->flags |= DDP_DEAD;
+ toep->ddp.flags |= DDP_DEAD;
for (i = 0; i < nitems(toep->ddp.db); i++) {
free_ddp_buffer(toep->td, &toep->ddp.db[i]);
}
diff --git a/sys/dev/cxgbe/tom/t4_tom.h b/sys/dev/cxgbe/tom/t4_tom.h
index db9e50cd39e16..d4ff4490abad8 100644
--- a/sys/dev/cxgbe/tom/t4_tom.h
+++ b/sys/dev/cxgbe/tom/t4_tom.h
@@ -194,7 +194,7 @@ struct toepcb {
TAILQ_HEAD(, kaiocb) aiotx_jobq;
struct task aiotx_task;
- bool aiotx_task_active;
+ struct socket *aiotx_so;
/* Tx software descriptor */
uint8_t txsd_total;
diff --git a/sys/dev/drm2/ttm/ttm_bo_vm.c b/sys/dev/drm2/ttm/ttm_bo_vm.c
index 6f7184857ce6f..43d027fc5cd91 100644
--- a/sys/dev/drm2/ttm/ttm_bo_vm.c
+++ b/sys/dev/drm2/ttm/ttm_bo_vm.c
@@ -115,7 +115,7 @@ ttm_bo_vm_fault(vm_object_t vm_obj, vm_ooffset_t offset,
vm_object_pip_add(vm_obj, 1);
if (*mres != NULL) {
vm_page_lock(*mres);
- vm_page_remove(*mres);
+ (void)vm_page_remove(*mres);
vm_page_unlock(*mres);
}
retry:
diff --git a/sys/dev/gpio/gpiobus.c b/sys/dev/gpio/gpiobus.c
index 133b72185d7f4..64fadb382a02f 100644
--- a/sys/dev/gpio/gpiobus.c
+++ b/sys/dev/gpio/gpiobus.c
@@ -255,13 +255,6 @@ gpiobus_alloc_ivars(struct gpiobus_ivar *devi)
M_NOWAIT | M_ZERO);
if (devi->pins == NULL)
return (ENOMEM);
- devi->flags = malloc(sizeof(uint32_t) * devi->npins, M_DEVBUF,
- M_NOWAIT | M_ZERO);
- if (devi->flags == NULL) {
- free(devi->pins, M_DEVBUF);
- return (ENOMEM);
- }
-
return (0);
}
@@ -269,14 +262,11 @@ void
gpiobus_free_ivars(struct gpiobus_ivar *devi)
{
- if (devi->flags) {
- free(devi->flags, M_DEVBUF);
- devi->flags = NULL;
- }
if (devi->pins) {
free(devi->pins, M_DEVBUF);
devi->pins = NULL;
}
+ devi->npins = 0;
}
int
@@ -326,6 +316,34 @@ gpiobus_release_pin(device_t bus, uint32_t pin)
}
static int
+gpiobus_acquire_child_pins(device_t dev, device_t child)
+{
+ struct gpiobus_ivar *devi = GPIOBUS_IVAR(child);
+ int i;
+
+ for (i = 0; i < devi->npins; i++) {
+ /* Reserve the GPIO pin. */
+ if (gpiobus_acquire_pin(dev, devi->pins[i]) != 0) {
+ device_printf(child, "cannot acquire pin %d\n",
+ devi->pins[i]);
+ while (--i >= 0) {
+ (void)gpiobus_release_pin(dev,
+ devi->pins[i]);
+ }
+ gpiobus_free_ivars(devi);
+ return (EBUSY);
+ }
+ }
+ for (i = 0; i < devi->npins; i++) {
+ /* Use the child name as pin name. */
+ GPIOBUS_PIN_SETNAME(dev, devi->pins[i],
+ device_get_nameunit(child));
+
+ }
+ return (0);
+}
+
+static int
gpiobus_parse_pins(struct gpiobus_softc *sc, device_t child, int mask)
{
struct gpiobus_ivar *devi = GPIOBUS_IVAR(child);
@@ -349,17 +367,66 @@ gpiobus_parse_pins(struct gpiobus_softc *sc, device_t child, int mask)
for (i = 0; i < 32; i++) {
if ((mask & (1 << i)) == 0)
continue;
- /* Reserve the GPIO pin. */
- if (gpiobus_acquire_pin(sc->sc_busdev, i) != 0) {
- gpiobus_free_ivars(devi);
- return (EINVAL);
- }
devi->pins[npins++] = i;
- /* Use the child name as pin name. */
- GPIOBUS_PIN_SETNAME(sc->sc_busdev, i,
- device_get_nameunit(child));
}
+ if (gpiobus_acquire_child_pins(sc->sc_busdev, child) != 0)
+ return (EINVAL);
+ return (0);
+}
+
+static int
+gpiobus_parse_pin_list(struct gpiobus_softc *sc, device_t child,
+ const char *pins)
+{
+ struct gpiobus_ivar *devi = GPIOBUS_IVAR(child);
+ const char *p;
+ char *endp;
+ unsigned long pin;
+ int i, npins;
+
+ npins = 0;
+ p = pins;
+ for (;;) {
+ pin = strtoul(p, &endp, 0);
+ if (endp == p)
+ break;
+ npins++;
+ if (*endp == '\0')
+ break;
+ p = endp + 1;
+ }
+
+ if (*endp != '\0') {
+ device_printf(child, "garbage in the pin list: %s\n", endp);
+ return (EINVAL);
+ }
+ if (npins == 0) {
+ device_printf(child, "empty pin list\n");
+ return (EINVAL);
+ }
+
+ devi->npins = npins;
+ if (gpiobus_alloc_ivars(devi) != 0) {
+ device_printf(child, "cannot allocate device ivars\n");
+ return (EINVAL);
+ }
+
+ i = 0;
+ p = pins;
+ for (;;) {
+ pin = strtoul(p, &endp, 0);
+
+ devi->pins[i] = pin;
+
+ if (*endp == '\0')
+ break;
+ i++;
+ p = endp + 1;
+ }
+
+ if (gpiobus_acquire_child_pins(sc->sc_busdev, child) != 0)
+ return (EINVAL);
return (0);
}
@@ -539,15 +606,26 @@ gpiobus_hinted_child(device_t bus, const char *dname, int dunit)
struct gpiobus_softc *sc = GPIOBUS_SOFTC(bus);
struct gpiobus_ivar *devi;
device_t child;
- int irq, pins;
+ const char *pins;
+ int irq, pinmask;
child = BUS_ADD_CHILD(bus, 0, dname, dunit);
devi = GPIOBUS_IVAR(child);
- resource_int_value(dname, dunit, "pins", &pins);
- if (gpiobus_parse_pins(sc, child, pins)) {
- resource_list_free(&devi->rl);
- free(devi, M_DEVBUF);
- device_delete_child(bus, child);
+ if (resource_int_value(dname, dunit, "pins", &pinmask) == 0) {
+ if (gpiobus_parse_pins(sc, child, pinmask)) {
+ resource_list_free(&devi->rl);
+ free(devi, M_DEVBUF);
+ device_delete_child(bus, child);
+ return;
+ }
+ }
+ else if (resource_string_value(dname, dunit, "pin_list", &pins) == 0) {
+ if (gpiobus_parse_pin_list(sc, child, pins)) {
+ resource_list_free(&devi->rl);
+ free(devi, M_DEVBUF);
+ device_delete_child(bus, child);
+ return;
+ }
}
if (resource_int_value(dname, dunit, "irq", &irq) == 0) {
if (bus_set_resource(child, SYS_RES_IRQ, 0, irq, 1) != 0)
@@ -574,6 +652,61 @@ gpiobus_set_resource(device_t dev, device_t child, int type, int rid,
return (0);
}
+static int
+gpiobus_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
+{
+ struct gpiobus_ivar *devi;
+
+ devi = GPIOBUS_IVAR(child);
+ switch (which) {
+ case GPIOBUS_IVAR_NPINS:
+ *result = devi->npins;
+ break;
+ case GPIOBUS_IVAR_PINS:
+ /* Children do not ever need to directly examine this. */
+ return (ENOTSUP);
+ default:
+ return (ENOENT);
+ }
+
+ return (0);
+}
+
+static int
+gpiobus_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
+{
+ struct gpiobus_ivar *devi;
+ const uint32_t *ptr;
+ int i;
+
+ devi = GPIOBUS_IVAR(child);
+ switch (which) {
+ case GPIOBUS_IVAR_NPINS:
+ /* GPIO ivars are set once. */
+ if (devi->npins != 0) {
+ return (EBUSY);
+ }
+ devi->npins = value;
+ if (gpiobus_alloc_ivars(devi) != 0) {
+ device_printf(child, "cannot allocate device ivars\n");
+ devi->npins = 0;
+ return (ENOMEM);
+ }
+ break;
+ case GPIOBUS_IVAR_PINS:
+ ptr = (const uint32_t *)value;
+ for (i = 0; i < devi->npins; i++)
+ devi->pins[i] = ptr[i];
+ if (gpiobus_acquire_child_pins(dev, child) != 0)
+ return (EBUSY);
+ break;
+ default:
+ return (ENOENT);
+ }
+
+ return (0);
+}
+
static struct resource *
gpiobus_alloc_resource(device_t bus, device_t child, int type, int *rid,
rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
@@ -833,6 +966,8 @@ static device_method_t gpiobus_methods[] = {
DEVMETHOD(bus_child_pnpinfo_str, gpiobus_child_pnpinfo_str),
DEVMETHOD(bus_child_location_str, gpiobus_child_location_str),
DEVMETHOD(bus_hinted_child, gpiobus_hinted_child),
+ DEVMETHOD(bus_read_ivar, gpiobus_read_ivar),
+ DEVMETHOD(bus_write_ivar, gpiobus_write_ivar),
/* GPIO protocol */
DEVMETHOD(gpiobus_acquire_bus, gpiobus_acquire_bus),
diff --git a/sys/dev/gpio/gpiobusvar.h b/sys/dev/gpio/gpiobusvar.h
index 5aa363a23daf8..08f0ccf904d02 100644
--- a/sys/dev/gpio/gpiobusvar.h
+++ b/sys/dev/gpio/gpiobusvar.h
@@ -107,10 +107,22 @@ struct gpiobus_ivar
{
struct resource_list rl; /* isr resource list */
uint32_t npins; /* pins total */
- uint32_t *flags; /* pins flags */
uint32_t *pins; /* pins map */
};
+enum gpiobus_ivars {
+ GPIOBUS_IVAR_NPINS = 10500,
+ GPIOBUS_IVAR_PINS,
+};
+
+#define GPIOBUS_ACCESSOR(var, ivar, type) \
+ __BUS_ACCESSOR(gpiobus, var, GPIOBUS, ivar, type)
+
+GPIOBUS_ACCESSOR(npins, NPINS, uint32_t)
+GPIOBUS_ACCESSOR(pins, PINS, const uint32_t *)
+
+#undef GPIOBUS_ACCESSOR
+
#ifdef FDT
struct ofw_gpiobus_devinfo {
struct gpiobus_ivar opd_dinfo;
diff --git a/sys/dev/gpio/ofw_gpiobus.c b/sys/dev/gpio/ofw_gpiobus.c
index 698701c8769d0..3c48c62feed3a 100644
--- a/sys/dev/gpio/ofw_gpiobus.c
+++ b/sys/dev/gpio/ofw_gpiobus.c
@@ -321,10 +321,8 @@ ofw_gpiobus_setup_devinfo(device_t bus, device_t child, phandle_t node)
ofw_gpiobus_destroy_devinfo(bus, dinfo);
return (NULL);
}
- for (i = 0; i < devi->npins; i++) {
- devi->flags[i] = pins[i].flags;
+ for (i = 0; i < devi->npins; i++)
devi->pins[i] = pins[i].pin;
- }
free(pins, M_DEVBUF);
/* Parse the interrupt resources. */
if (ofw_bus_intr_to_rl(bus, node, &dinfo->opd_dinfo.rl, NULL) != 0) {
diff --git a/sys/dev/iicbus/ad7418.c b/sys/dev/iicbus/ad7418.c
index 457b3626c8efa..0345977687909 100644
--- a/sys/dev/iicbus/ad7418.c
+++ b/sys/dev/iicbus/ad7418.c
@@ -35,18 +35,9 @@ __FBSDID("$FreeBSD$");
#include <sys/lock.h>
#include <sys/module.h>
#include <sys/bus.h>
-#include <sys/resource.h>
-#include <sys/rman.h>
#include <sys/sysctl.h>
#include <sys/sx.h>
-#include <machine/bus.h>
-#include <machine/cpu.h>
-#include <machine/cpufunc.h>
-#include <machine/frame.h>
-#include <machine/resource.h>
-#include <machine/intr.h>
-
#include <dev/iicbus/iiconf.h>
#include "iicbus_if.h"
diff --git a/sys/dev/nand/nand.c b/sys/dev/nand/nand.c
deleted file mode 100644
index 6997ef7f8a0d6..0000000000000
--- a/sys/dev/nand/nand.c
+++ /dev/null
@@ -1,826 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (C) 2009-2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/socket.h>
-#include <sys/malloc.h>
-#include <sys/module.h>
-#include <sys/bus.h>
-#include <sys/lock.h>
-#include <sys/mutex.h>
-#include <sys/callout.h>
-#include <sys/sysctl.h>
-
-#include <dev/nand/nand.h>
-#include <dev/nand/nandbus.h>
-#include <dev/nand/nand_ecc_pos.h>
-#include "nfc_if.h"
-#include "nand_if.h"
-#include "nandbus_if.h"
-#include <machine/stdarg.h>
-
-#define NAND_RESET_DELAY 1000 /* tRST */
-#define NAND_ERASE_DELAY 3000 /* tBERS */
-#define NAND_PROG_DELAY 700 /* tPROG */
-#define NAND_READ_DELAY 50 /* tR */
-
-#define BIT0(x) ((x) & 0x1)
-#define BIT1(x) (BIT0(x >> 1))
-#define BIT2(x) (BIT0(x >> 2))
-#define BIT3(x) (BIT0(x >> 3))
-#define BIT4(x) (BIT0(x >> 4))
-#define BIT5(x) (BIT0(x >> 5))
-#define BIT6(x) (BIT0(x >> 6))
-#define BIT7(x) (BIT0(x >> 7))
-
-#define SOFTECC_SIZE 256
-#define SOFTECC_BYTES 3
-
-int nand_debug_flag = 0;
-SYSCTL_INT(_debug, OID_AUTO, nand_debug, CTLFLAG_RWTUN, &nand_debug_flag, 0,
- "NAND subsystem debug flag");
-
-MALLOC_DEFINE(M_NAND, "NAND", "NAND dynamic data");
-
-static void calculate_ecc(const uint8_t *, uint8_t *);
-static int correct_ecc(uint8_t *, uint8_t *, uint8_t *);
-
-void
-nand_debug(int level, const char *fmt, ...)
-{
- va_list ap;
-
- if (!(nand_debug_flag & level))
- return;
- va_start(ap, fmt);
- vprintf(fmt, ap);
- va_end(ap);
- printf("\n");
-}
-
-void
-nand_init(struct nand_softc *nand, device_t dev, int ecc_mode,
- int ecc_bytes, int ecc_size, uint16_t *eccposition, char *cdev_name)
-{
-
- nand->ecc.eccmode = ecc_mode;
- nand->chip_cdev_name = cdev_name;
-
- if (ecc_mode == NAND_ECC_SOFT) {
- nand->ecc.eccbytes = SOFTECC_BYTES;
- nand->ecc.eccsize = SOFTECC_SIZE;
- } else if (ecc_mode != NAND_ECC_NONE) {
- nand->ecc.eccbytes = ecc_bytes;
- nand->ecc.eccsize = ecc_size;
- if (eccposition)
- nand->ecc.eccpositions = eccposition;
- }
-}
-
-void
-nand_onfi_set_params(struct nand_chip *chip, struct onfi_chip_params *params)
-{
- struct chip_geom *cg;
-
- cg = &chip->chip_geom;
-
- init_chip_geom(cg, params->luns, params->blocks_per_lun,
- params->pages_per_block, params->bytes_per_page,
- params->spare_bytes_per_page);
- chip->t_bers = params->t_bers;
- chip->t_prog = params->t_prog;
- chip->t_r = params->t_r;
- chip->t_ccs = params->t_ccs;
-
- if (params->features & ONFI_FEAT_16BIT)
- chip->flags |= NAND_16_BIT;
-}
-
-void
-nand_set_params(struct nand_chip *chip, struct nand_params *params)
-{
- struct chip_geom *cg;
- uint32_t blocks_per_chip;
-
- cg = &chip->chip_geom;
- blocks_per_chip = (params->chip_size << 20) /
- (params->page_size * params->pages_per_block);
-
- init_chip_geom(cg, 1, blocks_per_chip,
- params->pages_per_block, params->page_size,
- params->oob_size);
-
- chip->t_bers = NAND_ERASE_DELAY;
- chip->t_prog = NAND_PROG_DELAY;
- chip->t_r = NAND_READ_DELAY;
- chip->t_ccs = 0;
-
- if (params->flags & NAND_16_BIT)
- chip->flags |= NAND_16_BIT;
-}
-
-int
-nand_init_stat(struct nand_chip *chip)
-{
- struct block_stat *blk_stat;
- struct page_stat *pg_stat;
- struct chip_geom *cg;
- uint32_t blks, pgs;
-
- cg = &chip->chip_geom;
- blks = cg->blks_per_lun * cg->luns;
- blk_stat = malloc(sizeof(struct block_stat) * blks, M_NAND,
- M_WAITOK | M_ZERO);
- if (!blk_stat)
- return (ENOMEM);
-
- pgs = blks * cg->pgs_per_blk;
- pg_stat = malloc(sizeof(struct page_stat) * pgs, M_NAND,
- M_WAITOK | M_ZERO);
- if (!pg_stat) {
- free(blk_stat, M_NAND);
- return (ENOMEM);
- }
-
- chip->blk_stat = blk_stat;
- chip->pg_stat = pg_stat;
-
- return (0);
-}
-
-void
-nand_destroy_stat(struct nand_chip *chip)
-{
-
- free(chip->pg_stat, M_NAND);
- free(chip->blk_stat, M_NAND);
-}
-
-int
-init_chip_geom(struct chip_geom *cg, uint32_t luns, uint32_t blks_per_lun,
- uint32_t pgs_per_blk, uint32_t pg_size, uint32_t oob_size)
-{
- int shift;
-
- if (!cg)
- return (-1);
-
- cg->luns = luns;
- cg->blks_per_lun = blks_per_lun;
- cg->blks_per_chip = blks_per_lun * luns;
- cg->pgs_per_blk = pgs_per_blk;
-
- cg->page_size = pg_size;
- cg->oob_size = oob_size;
- cg->block_size = cg->page_size * cg->pgs_per_blk;
- cg->chip_size = cg->block_size * cg->blks_per_chip;
-
- shift = fls(cg->pgs_per_blk - 1);
- cg->pg_mask = (1 << shift) - 1;
- cg->blk_shift = shift;
-
- if (cg->blks_per_lun > 0) {
- shift = fls(cg->blks_per_lun - 1);
- cg->blk_mask = ((1 << shift) - 1) << cg->blk_shift;
- } else {
- shift = 0;
- cg->blk_mask = 0;
- }
-
- cg->lun_shift = shift + cg->blk_shift;
- shift = fls(cg->luns - 1);
- cg->lun_mask = ((1 << shift) - 1) << cg->lun_shift;
-
- nand_debug(NDBG_NAND, "Masks: lun 0x%x blk 0x%x page 0x%x\n"
- "Shifts: lun %d blk %d",
- cg->lun_mask, cg->blk_mask, cg->pg_mask,
- cg->lun_shift, cg->blk_shift);
-
- return (0);
-}
-
-int
-nand_row_to_blkpg(struct chip_geom *cg, uint32_t row, uint32_t *lun,
- uint32_t *blk, uint32_t *pg)
-{
-
- if (!cg || !lun || !blk || !pg)
- return (-1);
-
- if (row & ~(cg->lun_mask | cg->blk_mask | cg->pg_mask)) {
- nand_debug(NDBG_NAND,"Address out of bounds\n");
- return (-1);
- }
-
- *lun = (row & cg->lun_mask) >> cg->lun_shift;
- *blk = (row & cg->blk_mask) >> cg->blk_shift;
- *pg = (row & cg->pg_mask);
-
- nand_debug(NDBG_NAND,"address %x-%x-%x\n", *lun, *blk, *pg);
-
- return (0);
-}
-
-int page_to_row(struct chip_geom *cg, uint32_t page, uint32_t *row)
-{
- uint32_t lun, block, pg_in_blk;
-
- if (!cg || !row)
- return (-1);
-
- block = page / cg->pgs_per_blk;
- pg_in_blk = page % cg->pgs_per_blk;
-
- lun = block / cg->blks_per_lun;
- block = block % cg->blks_per_lun;
-
- *row = (lun << cg->lun_shift) & cg->lun_mask;
- *row |= ((block << cg->blk_shift) & cg->blk_mask);
- *row |= (pg_in_blk & cg->pg_mask);
-
- return (0);
-}
-
-int
-nand_check_page_boundary(struct nand_chip *chip, uint32_t page)
-{
- struct chip_geom* cg;
-
- cg = &chip->chip_geom;
- if (page >= (cg->pgs_per_blk * cg->blks_per_lun * cg->luns)) {
- nand_debug(NDBG_GEN,"%s: page number too big %#x\n",
- __func__, page);
- return (1);
- }
-
- return (0);
-}
-
-void
-nand_get_chip_param(struct nand_chip *chip, struct chip_param_io *param)
-{
- struct chip_geom *cg;
-
- cg = &chip->chip_geom;
- param->page_size = cg->page_size;
- param->oob_size = cg->oob_size;
-
- param->blocks = cg->blks_per_lun * cg->luns;
- param->pages_per_block = cg->pgs_per_blk;
-}
-
-static uint16_t *
-default_software_ecc_positions(struct nand_chip *chip)
-{
- /* If positions have been set already, use them. */
- if (chip->nand->ecc.eccpositions)
- return (chip->nand->ecc.eccpositions);
-
- /*
- * XXX Note that the following logic isn't really sufficient, especially
- * in the ONFI case where the number of ECC bytes can be dictated by
- * values in the parameters page, and that could lead to needing more
- * byte positions than exist within the tables of software-ecc defaults.
- */
- if (chip->chip_geom.oob_size >= 128)
- return (default_software_ecc_positions_128);
- if (chip->chip_geom.oob_size >= 64)
- return (default_software_ecc_positions_64);
- else if (chip->chip_geom.oob_size >= 16)
- return (default_software_ecc_positions_16);
-
- return (NULL);
-}
-
-static void
-calculate_ecc(const uint8_t *buf, uint8_t *ecc)
-{
- uint8_t p8, byte;
- int i;
-
- memset(ecc, 0, 3);
-
- for (i = 0; i < 256; i++) {
- byte = buf[i];
- ecc[0] ^= (BIT0(byte) ^ BIT2(byte) ^ BIT4(byte) ^
- BIT6(byte)) << 2;
- ecc[0] ^= (BIT1(byte) ^ BIT3(byte) ^ BIT5(byte) ^
- BIT7(byte)) << 3;
- ecc[0] ^= (BIT0(byte) ^ BIT1(byte) ^ BIT4(byte) ^
- BIT5(byte)) << 4;
- ecc[0] ^= (BIT2(byte) ^ BIT3(byte) ^ BIT6(byte) ^
- BIT7(byte)) << 5;
- ecc[0] ^= (BIT0(byte) ^ BIT1(byte) ^ BIT2(byte) ^
- BIT3(byte)) << 6;
- ecc[0] ^= (BIT4(byte) ^ BIT5(byte) ^ BIT6(byte) ^
- BIT7(byte)) << 7;
-
- p8 = BIT0(byte) ^ BIT1(byte) ^ BIT2(byte) ^
- BIT3(byte) ^ BIT4(byte) ^ BIT5(byte) ^ BIT6(byte) ^
- BIT7(byte);
-
- if (p8) {
- ecc[2] ^= (0x1 << BIT0(i));
- ecc[2] ^= (0x4 << BIT1(i));
- ecc[2] ^= (0x10 << BIT2(i));
- ecc[2] ^= (0x40 << BIT3(i));
-
- ecc[1] ^= (0x1 << BIT4(i));
- ecc[1] ^= (0x4 << BIT5(i));
- ecc[1] ^= (0x10 << BIT6(i));
- ecc[1] ^= (0x40 << BIT7(i));
- }
- }
- ecc[0] = ~ecc[0];
- ecc[1] = ~ecc[1];
- ecc[2] = ~ecc[2];
- ecc[0] |= 3;
-}
-
-static int
-correct_ecc(uint8_t *buf, uint8_t *calc_ecc, uint8_t *read_ecc)
-{
- uint8_t ecc0, ecc1, ecc2, onesnum, bit, byte;
- uint16_t addr = 0;
-
- ecc0 = calc_ecc[0] ^ read_ecc[0];
- ecc1 = calc_ecc[1] ^ read_ecc[1];
- ecc2 = calc_ecc[2] ^ read_ecc[2];
-
- if (!ecc0 && !ecc1 && !ecc2)
- return (ECC_OK);
-
- addr = BIT3(ecc0) | (BIT5(ecc0) << 1) | (BIT7(ecc0) << 2);
- addr |= (BIT1(ecc2) << 3) | (BIT3(ecc2) << 4) |
- (BIT5(ecc2) << 5) | (BIT7(ecc2) << 6);
- addr |= (BIT1(ecc1) << 7) | (BIT3(ecc1) << 8) |
- (BIT5(ecc1) << 9) | (BIT7(ecc1) << 10);
-
- onesnum = 0;
- while (ecc0 || ecc1 || ecc2) {
- if (ecc0 & 1)
- onesnum++;
- if (ecc1 & 1)
- onesnum++;
- if (ecc2 & 1)
- onesnum++;
-
- ecc0 >>= 1;
- ecc1 >>= 1;
- ecc2 >>= 1;
- }
-
- if (onesnum == 11) {
- /* Correctable error */
- bit = addr & 7;
- byte = addr >> 3;
- buf[byte] ^= (1 << bit);
- return (ECC_CORRECTABLE);
- } else if (onesnum == 1) {
- /* ECC error */
- return (ECC_ERROR_ECC);
- } else {
- /* Uncorrectable error */
- return (ECC_UNCORRECTABLE);
- }
-
- return (0);
-}
-
-int
-nand_softecc_get(device_t dev, uint8_t *buf, int pagesize, uint8_t *ecc)
-{
- int steps = pagesize / SOFTECC_SIZE;
- int i = 0, j = 0;
-
- for (; i < (steps * SOFTECC_BYTES);
- i += SOFTECC_BYTES, j += SOFTECC_SIZE) {
- calculate_ecc(&buf[j], &ecc[i]);
- }
-
- return (0);
-}
-
-int
-nand_softecc_correct(device_t dev, uint8_t *buf, int pagesize,
- uint8_t *readecc, uint8_t *calcecc)
-{
- int steps = pagesize / SOFTECC_SIZE;
- int i = 0, j = 0, ret = 0;
-
- for (i = 0; i < (steps * SOFTECC_BYTES);
- i += SOFTECC_BYTES, j += SOFTECC_SIZE) {
- ret += correct_ecc(&buf[j], &calcecc[i], &readecc[i]);
- if (ret < 0)
- return (ret);
- }
-
- return (ret);
-}
-
-static int
-offset_to_page(struct chip_geom *cg, uint32_t offset)
-{
-
- return (offset / cg->page_size);
-}
-
-int
-nand_read_pages(struct nand_chip *chip, uint32_t offset, void *buf,
- uint32_t len)
-{
- struct chip_geom *cg;
- struct nand_ecc_data *eccd;
- struct page_stat *pg_stat;
- device_t nandbus;
- void *oob = NULL;
- uint8_t *ptr;
- uint16_t *eccpos = NULL;
- uint32_t page, num, steps = 0;
- int i, retval = 0, needwrite;
-
- nand_debug(NDBG_NAND,"%p read page %x[%x]", chip, offset, len);
- cg = &chip->chip_geom;
- eccd = &chip->nand->ecc;
- page = offset_to_page(cg, offset);
- num = len / cg->page_size;
-
- if (eccd->eccmode != NAND_ECC_NONE) {
- steps = cg->page_size / eccd->eccsize;
- eccpos = default_software_ecc_positions(chip);
- oob = malloc(cg->oob_size, M_NAND, M_WAITOK);
- }
-
- nandbus = device_get_parent(chip->dev);
- NANDBUS_LOCK(nandbus);
- NANDBUS_SELECT_CS(device_get_parent(chip->dev), chip->num);
-
- ptr = (uint8_t *)buf;
- while (num--) {
- pg_stat = &(chip->pg_stat[page]);
-
- if (NAND_READ_PAGE(chip->dev, page, ptr, cg->page_size, 0)) {
- retval = ENXIO;
- break;
- }
-
- if (eccd->eccmode != NAND_ECC_NONE) {
- if (NAND_GET_ECC(chip->dev, ptr, eccd->ecccalculated,
- &needwrite)) {
- retval = ENXIO;
- break;
- }
- nand_debug(NDBG_ECC,"%s: ECC calculated:",
- __func__);
- if (nand_debug_flag & NDBG_ECC)
- for (i = 0; i < (eccd->eccbytes * steps); i++)
- printf("%x ", eccd->ecccalculated[i]);
-
- nand_debug(NDBG_ECC,"\n");
-
- if (NAND_READ_OOB(chip->dev, page, oob, cg->oob_size,
- 0)) {
- retval = ENXIO;
- break;
- }
- for (i = 0; i < (eccd->eccbytes * steps); i++)
- eccd->eccread[i] = ((uint8_t *)oob)[eccpos[i]];
-
- nand_debug(NDBG_ECC,"%s: ECC read:", __func__);
- if (nand_debug_flag & NDBG_ECC)
- for (i = 0; i < (eccd->eccbytes * steps); i++)
- printf("%x ", eccd->eccread[i]);
- nand_debug(NDBG_ECC,"\n");
-
- retval = NAND_CORRECT_ECC(chip->dev, ptr, eccd->eccread,
- eccd->ecccalculated);
-
- nand_debug(NDBG_ECC, "NAND_CORRECT_ECC() returned %d",
- retval);
-
- if (retval == 0)
- pg_stat->ecc_stat.ecc_succeded++;
- else if (retval > 0) {
- pg_stat->ecc_stat.ecc_corrected += retval;
- retval = ECC_CORRECTABLE;
- } else {
- pg_stat->ecc_stat.ecc_failed++;
- break;
- }
- }
-
- pg_stat->page_read++;
- page++;
- ptr += cg->page_size;
- }
-
- NANDBUS_UNLOCK(nandbus);
-
- if (oob)
- free(oob, M_NAND);
-
- return (retval);
-}
-
-int
-nand_read_pages_raw(struct nand_chip *chip, uint32_t offset, void *buf,
- uint32_t len)
-{
- struct chip_geom *cg;
- device_t nandbus;
- uint8_t *ptr;
- uint32_t page, num, end, begin = 0, begin_off;
- int retval = 0;
-
- cg = &chip->chip_geom;
- page = offset_to_page(cg, offset);
- begin_off = offset - page * cg->page_size;
- if (begin_off) {
- begin = cg->page_size - begin_off;
- len -= begin;
- }
- num = len / cg->page_size;
- end = len % cg->page_size;
-
- nandbus = device_get_parent(chip->dev);
- NANDBUS_LOCK(nandbus);
- NANDBUS_SELECT_CS(device_get_parent(chip->dev), chip->num);
-
- ptr = (uint8_t *)buf;
- if (begin_off) {
- if (NAND_READ_PAGE(chip->dev, page, ptr, begin, begin_off)) {
- NANDBUS_UNLOCK(nandbus);
- return (ENXIO);
- }
-
- page++;
- ptr += begin;
- }
-
- while (num--) {
- if (NAND_READ_PAGE(chip->dev, page, ptr, cg->page_size, 0)) {
- NANDBUS_UNLOCK(nandbus);
- return (ENXIO);
- }
-
- page++;
- ptr += cg->page_size;
- }
-
- if (end)
- if (NAND_READ_PAGE(chip->dev, page, ptr, end, 0)) {
- NANDBUS_UNLOCK(nandbus);
- return (ENXIO);
- }
-
- NANDBUS_UNLOCK(nandbus);
-
- return (retval);
-}
-
-
-int
-nand_prog_pages(struct nand_chip *chip, uint32_t offset, uint8_t *buf,
- uint32_t len)
-{
- struct chip_geom *cg;
- struct page_stat *pg_stat;
- struct nand_ecc_data *eccd;
- device_t nandbus;
- uint32_t page, num;
- uint8_t *oob = NULL;
- uint16_t *eccpos = NULL;
- int steps = 0, i, needwrite, err = 0;
-
- nand_debug(NDBG_NAND,"%p prog page %x[%x]", chip, offset, len);
-
- eccd = &chip->nand->ecc;
- cg = &chip->chip_geom;
- page = offset_to_page(cg, offset);
- num = len / cg->page_size;
-
- if (eccd->eccmode != NAND_ECC_NONE) {
- steps = cg->page_size / eccd->eccsize;
- oob = malloc(cg->oob_size, M_NAND, M_WAITOK);
- eccpos = default_software_ecc_positions(chip);
- }
-
- nandbus = device_get_parent(chip->dev);
- NANDBUS_LOCK(nandbus);
- NANDBUS_SELECT_CS(device_get_parent(chip->dev), chip->num);
-
- while (num--) {
- if (NAND_PROGRAM_PAGE(chip->dev, page, buf, cg->page_size, 0)) {
- err = ENXIO;
- break;
- }
-
- if (eccd->eccmode != NAND_ECC_NONE) {
- if (NAND_GET_ECC(chip->dev, buf, &eccd->ecccalculated,
- &needwrite)) {
- err = ENXIO;
- break;
- }
- nand_debug(NDBG_ECC,"ECC calculated:");
- if (nand_debug_flag & NDBG_ECC)
- for (i = 0; i < (eccd->eccbytes * steps); i++)
- printf("%x ", eccd->ecccalculated[i]);
-
- nand_debug(NDBG_ECC,"\n");
-
- if (needwrite) {
- if (NAND_READ_OOB(chip->dev, page, oob, cg->oob_size,
- 0)) {
- err = ENXIO;
- break;
- }
-
- for (i = 0; i < (eccd->eccbytes * steps); i++)
- oob[eccpos[i]] = eccd->ecccalculated[i];
-
- if (NAND_PROGRAM_OOB(chip->dev, page, oob,
- cg->oob_size, 0)) {
- err = ENXIO;
- break;
- }
- }
- }
-
- pg_stat = &(chip->pg_stat[page]);
- pg_stat->page_written++;
-
- page++;
- buf += cg->page_size;
- }
-
- NANDBUS_UNLOCK(nandbus);
-
- if (oob)
- free(oob, M_NAND);
-
- return (err);
-}
-
-int
-nand_prog_pages_raw(struct nand_chip *chip, uint32_t offset, void *buf,
- uint32_t len)
-{
- struct chip_geom *cg;
- device_t nandbus;
- uint8_t *ptr;
- uint32_t page, num, end, begin = 0, begin_off;
- int retval = 0;
-
- cg = &chip->chip_geom;
- page = offset_to_page(cg, offset);
- begin_off = offset - page * cg->page_size;
- if (begin_off) {
- begin = cg->page_size - begin_off;
- len -= begin;
- }
- num = len / cg->page_size;
- end = len % cg->page_size;
-
- nandbus = device_get_parent(chip->dev);
- NANDBUS_LOCK(nandbus);
- NANDBUS_SELECT_CS(device_get_parent(chip->dev), chip->num);
-
- ptr = (uint8_t *)buf;
- if (begin_off) {
- if (NAND_PROGRAM_PAGE(chip->dev, page, ptr, begin, begin_off)) {
- NANDBUS_UNLOCK(nandbus);
- return (ENXIO);
- }
-
- page++;
- ptr += begin;
- }
-
- while (num--) {
- if (NAND_PROGRAM_PAGE(chip->dev, page, ptr, cg->page_size, 0)) {
- NANDBUS_UNLOCK(nandbus);
- return (ENXIO);
- }
-
- page++;
- ptr += cg->page_size;
- }
-
- if (end)
- retval = NAND_PROGRAM_PAGE(chip->dev, page, ptr, end, 0);
-
- NANDBUS_UNLOCK(nandbus);
-
- return (retval);
-}
-
-int
-nand_read_oob(struct nand_chip *chip, uint32_t page, void *buf,
- uint32_t len)
-{
- device_t nandbus;
- int retval = 0;
-
- nandbus = device_get_parent(chip->dev);
- NANDBUS_LOCK(nandbus);
- NANDBUS_SELECT_CS(device_get_parent(chip->dev), chip->num);
-
- retval = NAND_READ_OOB(chip->dev, page, buf, len, 0);
-
- NANDBUS_UNLOCK(nandbus);
-
- return (retval);
-}
-
-
-int
-nand_prog_oob(struct nand_chip *chip, uint32_t page, void *buf,
- uint32_t len)
-{
- device_t nandbus;
- int retval = 0;
-
- nandbus = device_get_parent(chip->dev);
- NANDBUS_LOCK(nandbus);
- NANDBUS_SELECT_CS(device_get_parent(chip->dev), chip->num);
-
- retval = NAND_PROGRAM_OOB(chip->dev, page, buf, len, 0);
-
- NANDBUS_UNLOCK(nandbus);
-
- return (retval);
-}
-
-int
-nand_erase_blocks(struct nand_chip *chip, off_t offset, size_t len)
-{
- device_t nandbus;
- struct chip_geom *cg;
- uint32_t block, num_blocks;
- int err = 0;
-
- cg = &chip->chip_geom;
- if ((offset % cg->block_size) || (len % cg->block_size))
- return (EINVAL);
-
- block = offset / cg->block_size;
- num_blocks = len / cg->block_size;
- nand_debug(NDBG_NAND,"%p erase blocks %d[%d]", chip, block, num_blocks);
-
- nandbus = device_get_parent(chip->dev);
- NANDBUS_LOCK(nandbus);
- NANDBUS_SELECT_CS(device_get_parent(chip->dev), chip->num);
-
- while (num_blocks--) {
- if (!nand_check_bad_block(chip, block)) {
- if (NAND_ERASE_BLOCK(chip->dev, block)) {
- nand_debug(NDBG_NAND,"%p erase blocks %d error",
- chip, block);
- nand_mark_bad_block(chip, block);
- err = ENXIO;
- }
- } else
- err = ENXIO;
-
- block++;
- }
-
- NANDBUS_UNLOCK(nandbus);
-
- if (err)
- nand_update_bbt(chip);
-
- return (err);
-}
-
-MODULE_VERSION(nand, 1);
diff --git a/sys/dev/nand/nand.h b/sys/dev/nand/nand.h
deleted file mode 100644
index 06902601b8d0e..0000000000000
--- a/sys/dev/nand/nand.h
+++ /dev/null
@@ -1,415 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (C) 2009-2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef _DEV_NAND_H_
-#define _DEV_NAND_H_
-
-#include <sys/bus.h>
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/lock.h>
-#include <sys/sx.h>
-#include <sys/taskqueue.h>
-#include <sys/queue.h>
-#include <sys/bio.h>
-#include <sys/lock.h>
-#include <sys/mutex.h>
-#include <sys/malloc.h>
-
-#include <dev/nand/nand_dev.h>
-
-MALLOC_DECLARE(M_NAND);
-
-/* Read commands */
-#define NAND_CMD_READ 0x00
-#define NAND_CMD_CHNG_READ_COL 0x05
-#define NAND_CMD_READ_END 0x30
-#define NAND_CMD_READ_CACHE 0x31
-#define NAND_CMD_READ_CPBK 0x35
-#define NAND_CMD_READ_CACHE_END 0x3F
-#define NAND_CMD_CHNG_READ_COL_END 0xE0
-
-/* Erase commands */
-#define NAND_CMD_ERASE 0x60
-#define NAND_CMD_ERASE_END 0xD0
-#define NAND_CMD_ERASE_INTLV 0xD1
-
-/* Program commands */
-#define NAND_CMD_PROG 0x80
-#define NAND_CMD_CHNG_WRITE_COL 0x85
-#define NAND_CMD_PROG_END 0x10
-#define NAND_CMD_PROG_INTLV 0x11
-#define NAND_CMD_PROG_CACHE 0x15
-
-/* Misc commands */
-#define NAND_CMD_STATUS 0x70
-#define NAND_CMD_STATUS_ENH 0x78
-#define NAND_CMD_READ_ID 0x90
-#define NAND_CMD_READ_PARAMETER 0xec
-#define NAND_CMD_READ_UNIQUE_ID 0xed
-#define NAND_CMD_GET_FEATURE 0xee
-#define NAND_CMD_SET_FEATURE 0xef
-
-/* Reset commands */
-#define NAND_CMD_SYNCH_RESET 0xfc
-#define NAND_CMD_RESET 0xff
-
-/* Small page flash commands */
-#define NAND_CMD_SMALLA 0x00
-#define NAND_CMD_SMALLB 0x01
-#define NAND_CMD_SMALLOOB 0x50
-
-#define NAND_STATUS_FAIL 0x1
-#define NAND_STATUS_FAILC 0x2
-#define NAND_STATUS_ARDY 0x20
-#define NAND_STATUS_RDY 0x40
-#define NAND_STATUS_WP 0x80
-
-#define NAND_LP_OOB_COLUMN_START 0x800
-#define NAND_LP_OOBSZ 0x40
-#define NAND_SP_OOB_COLUMN_START 0x200
-#define NAND_SP_OOBSZ 0x10
-
-#define PAGE_PARAM_LENGTH 0x100
-#define PAGE_PARAMETER_DEF 0x0
-#define PAGE_PARAMETER_RED_1 0x100
-#define PAGE_PARAMETER_RED_2 0x200
-
-#define ONFI_SIG_ADDR 0x20
-
-#define NAND_MAX_CHIPS 0x4
-#define NAND_MAX_OOBSZ 512
-#define NAND_MAX_PAGESZ 16384
-
-#define NAND_SMALL_PAGE_SIZE 0x200
-
-#define NAND_16_BIT 0x00000001
-
-#define NAND_ECC_NONE 0x0
-#define NAND_ECC_SOFT 0x1
-#define NAND_ECC_FULLHW 0x2
-#define NAND_ECC_PARTHW 0x4
-#define NAND_ECC_MODE_MASK 0x7
-
-#define ECC_OK 0
-#define ECC_CORRECTABLE 1
-#define ECC_ERROR_ECC (-1)
-#define ECC_UNCORRECTABLE (-2)
-
-#define NAND_MAN_SAMSUNG 0xec
-#define NAND_MAN_HYNIX 0xad
-#define NAND_MAN_STMICRO 0x20
-#define NAND_MAN_MICRON 0x2c
-
-struct nand_id {
- uint8_t man_id;
- uint8_t dev_id;
-};
-
-struct nand_params {
- struct nand_id id;
- char *name;
- uint32_t chip_size;
- uint32_t page_size;
- uint32_t oob_size;
- uint32_t pages_per_block;
- uint32_t flags;
-};
-
-/* nand debug levels */
-#define NDBG_NAND 0x01
-#define NDBG_CDEV 0x02
-#define NDBG_GEN 0x04
-#define NDBG_GEOM 0x08
-#define NDBG_BUS 0x10
-#define NDBG_SIM 0x20
-#define NDBG_CTRL 0x40
-#define NDBG_DRV 0x80
-#define NDBG_ECC 0x100
-
-/* nand_debug_function */
-void nand_debug(int level, const char *fmt, ...);
-extern int nand_debug_flag;
-
-/* ONFI features bit*/
-#define ONFI_FEAT_16BIT 0x01
-#define ONFI_FEAT_MULT_LUN 0x02
-#define ONFI_FEAT_INTLV_OPS 0x04
-#define ONFI_FEAT_CPBK_RESTRICT 0x08
-#define ONFI_FEAT_SRC_SYNCH 0x10
-
-/* ONFI optional commands bits */
-#define ONFI_OPTCOM_PROG_CACHE 0x01
-#define ONFI_OPTCOM_READ_CACHE 0x02
-#define ONFI_OPTCOM_GETSET_FEAT 0x04
-#define ONFI_OPTCOM_STATUS_ENH 0x08
-#define ONFI_OPTCOM_COPYBACK 0x10
-#define ONFI_OPTCOM_UNIQUE_ID 0x20
-
-
-/* Layout of parameter page is defined in ONFI */
-struct onfi_params {
- char signature[4];
- uint16_t rev;
- uint16_t features;
- uint16_t optional_commands;
- uint8_t primary_advanced_command;
- uint8_t res1;
- uint16_t extended_parameter_page_length;
- uint8_t parameter_page_count;
- uint8_t res2[17];
- char manufacturer_name[12];
- char device_model[20];
- uint8_t manufacturer_id;
- uint8_t manufacture_date_yy;
- uint8_t manufacture_date_ww;
- uint8_t res3[13];
- uint32_t bytes_per_page;
- uint16_t spare_bytes_per_page;
- uint32_t bytes_per_partial_page;
- uint16_t spare_bytes_per_partial_page;
- uint32_t pages_per_block;
- uint32_t blocks_per_lun;
- uint8_t luns;
- uint8_t address_cycles;
- uint8_t bits_per_cell;
- uint16_t max_bad_block_per_lun;
- uint16_t block_endurance;
- uint8_t guaranteed_valid_blocks;
- uint16_t valid_block_endurance;
- uint8_t programs_per_page;
- uint8_t partial_prog_attr;
- uint8_t bits_of_ecc;
- uint8_t interleaved_addr_bits;
- uint8_t interleaved_oper_attr;
- uint8_t eznand_support;
- uint8_t res4[12];
- uint8_t pin_capacitance;
- uint16_t asynch_timing_mode_support;
- uint16_t asynch_prog_cache_timing_mode_support;
- uint16_t t_prog; /* us, max page program time */
- uint16_t t_bers; /* us, max block erase time */
- uint16_t t_r; /* us, max page read time */
- uint16_t t_ccs; /* ns, min change column setup time */
- uint16_t source_synch_timing_mode_support;
- uint8_t source_synch_feat;
- uint16_t clk_input_capacitance;
- uint16_t io_capacitance;
- uint16_t input_capacitance;
- uint8_t input_capacitance_max;
- uint8_t driver_strength_support;
- uint16_t t_r_interleaved;
- uint16_t t_adl;
- uint16_t t_r_eznand;
- uint8_t nv_ddr2_features;
- uint8_t nv_ddr2_warmup_cycles;
- uint8_t res5[4];
- uint16_t vendor_rev;
- uint8_t vendor_spec[88];
- uint16_t crc;
-}__attribute__((packed));
-CTASSERT(sizeof(struct onfi_params) == 256);
-
-struct onfi_chip_params {
- uint32_t blocks_per_lun;
- uint32_t pages_per_block;
- uint32_t bytes_per_page;
- uint32_t spare_bytes_per_page;
- uint16_t t_bers;
- uint16_t t_prog;
- uint16_t t_r;
- uint16_t t_ccs;
- uint16_t features;
- uint8_t address_cycles;
- uint8_t luns;
-};
-
-struct nand_ecc_data {
- int eccsize; /* Number of data bytes per ECC step */
- int eccmode;
- int eccbytes; /* Number of ECC bytes per step */
-
- uint16_t *eccpositions; /* Positions of ecc bytes */
- uint8_t ecccalculated[NAND_MAX_OOBSZ];
- uint8_t eccread[NAND_MAX_OOBSZ];
-};
-
-struct ecc_stat {
- uint32_t ecc_succeded;
- uint32_t ecc_corrected;
- uint32_t ecc_failed;
-};
-
-struct page_stat {
- struct ecc_stat ecc_stat;
- uint32_t page_read;
- uint32_t page_raw_read;
- uint32_t page_written;
- uint32_t page_raw_written;
-};
-
-struct block_stat {
- uint32_t block_erased;
-};
-
-struct chip_geom {
- uint32_t chip_size;
- uint32_t block_size;
- uint32_t page_size;
- uint32_t oob_size;
-
- uint32_t luns;
- uint32_t blks_per_lun;
- uint32_t blks_per_chip;
- uint32_t pgs_per_blk;
-
- uint32_t pg_mask;
- uint32_t blk_mask;
- uint32_t lun_mask;
- uint8_t blk_shift;
- uint8_t lun_shift;
-};
-
-struct nand_chip {
- device_t dev;
- struct nand_id id;
- struct chip_geom chip_geom;
-
- uint16_t t_prog; /* us, max page program time */
- uint16_t t_bers; /* us, max block erase time */
- uint16_t t_r; /* us, max page read time */
- uint16_t t_ccs; /* ns, min change column setup time */
- uint8_t num;
- uint8_t flags;
-
- struct page_stat *pg_stat;
- struct block_stat *blk_stat;
- struct nand_softc *nand;
- struct nand_bbt *bbt;
- struct nand_ops *ops;
- struct cdev *cdev;
-
- struct disk *ndisk;
- struct disk *rdisk;
- struct bio_queue_head bioq; /* bio queue */
- struct mtx qlock; /* bioq lock */
- struct taskqueue *tq; /* private task queue for i/o request */
- struct task iotask; /* i/o processing */
-
-};
-
-struct nand_softc {
- uint8_t flags;
-
- char *chip_cdev_name;
- struct nand_ecc_data ecc;
-};
-
-/* NAND ops */
-int nand_erase_blocks(struct nand_chip *chip, off_t offset, size_t len);
-int nand_prog_pages(struct nand_chip *chip, uint32_t offset, uint8_t *buf,
- uint32_t len);
-int nand_read_pages(struct nand_chip *chip, uint32_t offset, void *buf,
- uint32_t len);
-int nand_read_pages_raw(struct nand_chip *chip, uint32_t offset, void *buf,
- uint32_t len);
-int nand_prog_pages_raw(struct nand_chip *chip, uint32_t offset, void *buf,
- uint32_t len);
-int nand_read_oob(struct nand_chip *chip, uint32_t page, void *buf,
- uint32_t len);
-int nand_prog_oob(struct nand_chip *chip, uint32_t page, void *buf,
- uint32_t len);
-
-int nand_select_cs(device_t dev, uint8_t cs);
-
-int nand_read_parameter(struct nand_softc *nand, struct onfi_params *param);
-int nand_synch_reset(struct nand_softc *nand);
-int nand_chng_read_col(device_t dev, uint32_t col, void *buf, size_t len);
-int nand_chng_write_col(device_t dev, uint32_t col, void *buf, size_t len);
-int nand_get_feature(device_t dev, uint8_t feat, void* buf);
-int nand_set_feature(device_t dev, uint8_t feat, void* buf);
-
-
-int nand_erase_block_intlv(device_t dev, uint32_t block);
-int nand_copyback_read(device_t dev, uint32_t page, uint32_t col,
- void *buf, size_t len);
-int nand_copyback_prog(device_t dev, uint32_t page, uint32_t col,
- void *buf, size_t len);
-int nand_copyback_prog_intlv(device_t dev, uint32_t page);
-int nand_prog_cache(device_t dev, uint32_t page, uint32_t col,
- void *buf, size_t len, uint8_t end);
-int nand_prog_intlv(device_t dev, uint32_t page, uint32_t col,
- void *buf, size_t len);
-int nand_read_cache(device_t dev, uint32_t page, uint32_t col,
- void *buf, size_t len, uint8_t end);
-
-int nand_write_ecc(struct nand_softc *nand, uint32_t page, uint8_t *data);
-int nand_read_ecc(struct nand_softc *nand, uint32_t page, uint8_t *data);
-
-int nand_softecc_get(device_t dev, uint8_t *buf, int pagesize, uint8_t *ecc);
-int nand_softecc_correct(device_t dev, uint8_t *buf, int pagesize,
- uint8_t *readecc, uint8_t *calcecc);
-
-/* Chip initialization */
-void nand_init(struct nand_softc *nand, device_t dev, int ecc_mode,
- int ecc_bytes, int ecc_size, uint16_t* eccposition, char* cdev_name);
-void nand_detach(struct nand_softc *nand);
-struct nand_params *nand_get_params(struct nand_id *id);
-
-void nand_onfi_set_params(struct nand_chip *chip, struct onfi_chip_params *params);
-void nand_set_params(struct nand_chip *chip, struct nand_params *params);
-int nand_init_stat(struct nand_chip *chip);
-void nand_destroy_stat(struct nand_chip *chip);
-
-/* BBT */
-int nand_init_bbt(struct nand_chip *chip);
-void nand_destroy_bbt(struct nand_chip *chip);
-int nand_update_bbt(struct nand_chip *chip);
-int nand_mark_bad_block(struct nand_chip* chip, uint32_t block_num);
-int nand_check_bad_block(struct nand_chip* chip, uint32_t block_num);
-
-/* cdev creation/removal */
-int nand_make_dev(struct nand_chip* chip);
-void nand_destroy_dev(struct nand_chip *chip);
-
-int create_geom_disk(struct nand_chip* chip);
-int create_geom_raw_disk(struct nand_chip *chip);
-void destroy_geom_disk(struct nand_chip *chip);
-void destroy_geom_raw_disk(struct nand_chip *chip);
-
-int init_chip_geom(struct chip_geom* cg, uint32_t luns, uint32_t blks_per_lun,
- uint32_t pgs_per_blk, uint32_t pg_size, uint32_t oob_size);
-int nand_row_to_blkpg(struct chip_geom *cg, uint32_t row, uint32_t *lun,
- uint32_t *blk, uint32_t *pg);
-int page_to_row(struct chip_geom *cg, uint32_t page, uint32_t *row);
-int nand_check_page_boundary(struct nand_chip *chip, uint32_t page);
-void nand_get_chip_param(struct nand_chip *chip, struct chip_param_io *param);
-
-#endif /* _DEV_NAND_H_ */
diff --git a/sys/dev/nand/nand_bbt.c b/sys/dev/nand/nand_bbt.c
deleted file mode 100644
index d99ed67523a20..0000000000000
--- a/sys/dev/nand/nand_bbt.c
+++ /dev/null
@@ -1,275 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2009-2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#include <sys/cdefs.h>
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/socket.h>
-#include <sys/malloc.h>
-#include <sys/bus.h>
-
-#include <dev/nand/nand.h>
-
-#include "nand_if.h"
-
-#define BBT_PRIMARY_PATTERN 0x01020304
-#define BBT_SECONDARY_PATTERN 0x05060708
-
-enum bbt_place {
- BBT_NONE,
- BBT_PRIMARY,
- BBT_SECONDARY
-};
-
-struct nand_bbt {
- struct nand_chip *chip;
- uint32_t primary_map;
- uint32_t secondary_map;
- enum bbt_place active;
- struct bbt_header *hdr;
- uint32_t tab_len;
- uint32_t *table;
-};
-
-struct bbt_header {
- uint32_t pattern;
- int32_t seq_nr;
-};
-
-static int nand_bbt_save(struct nand_bbt *);
-static int nand_bbt_load_hdr(struct nand_bbt *, struct bbt_header *, int8_t);
-static int nand_bbt_load_table(struct nand_bbt *);
-static int nand_bbt_prescan(struct nand_bbt *);
-
-int
-nand_init_bbt(struct nand_chip *chip)
-{
- struct chip_geom *cg;
- struct nand_bbt *bbt;
- int err;
-
- cg = &chip->chip_geom;
-
- bbt = malloc(sizeof(struct nand_bbt), M_NAND, M_ZERO | M_WAITOK);
- if (!bbt) {
- device_printf(chip->dev,
- "Cannot allocate memory for bad block struct");
- return (ENOMEM);
- }
-
- bbt->chip = chip;
- bbt->active = BBT_NONE;
- bbt->primary_map = cg->chip_size - cg->block_size;
- bbt->secondary_map = cg->chip_size - 2 * cg->block_size;
- bbt->tab_len = cg->blks_per_chip * sizeof(uint32_t);
- bbt->hdr = malloc(sizeof(struct bbt_header) + bbt->tab_len, M_NAND,
- M_WAITOK);
- if (!bbt->hdr) {
- device_printf(chip->dev, "Cannot allocate %d bytes for BB "
- "Table", bbt->tab_len);
- free(bbt, M_NAND);
- return (ENOMEM);
- }
- bbt->hdr->seq_nr = 0;
- bbt->table = (uint32_t *)((uint8_t *)bbt->hdr +
- sizeof(struct bbt_header));
-
- err = nand_bbt_load_table(bbt);
- if (err) {
- free(bbt->table, M_NAND);
- free(bbt, M_NAND);
- return (err);
- }
-
- chip->bbt = bbt;
- if (bbt->active == BBT_NONE) {
- bbt->active = BBT_PRIMARY;
- memset(bbt->table, 0xff, bbt->tab_len);
- nand_bbt_prescan(bbt);
- nand_bbt_save(bbt);
- } else
- device_printf(chip->dev, "Found BBT table for chip\n");
-
- return (0);
-}
-
-void
-nand_destroy_bbt(struct nand_chip *chip)
-{
-
- if (chip->bbt) {
- nand_bbt_save(chip->bbt);
-
- free(chip->bbt->hdr, M_NAND);
- free(chip->bbt, M_NAND);
- chip->bbt = NULL;
- }
-}
-
-int
-nand_update_bbt(struct nand_chip *chip)
-{
-
- nand_bbt_save(chip->bbt);
-
- return (0);
-}
-
-static int
-nand_bbt_save(struct nand_bbt *bbt)
-{
- enum bbt_place next;
- uint32_t addr;
- int32_t err;
-
- if (bbt->active == BBT_PRIMARY) {
- addr = bbt->secondary_map;
- bbt->hdr->pattern = BBT_SECONDARY_PATTERN;
- next = BBT_SECONDARY;
- } else {
- addr = bbt->primary_map;
- bbt->hdr->pattern = BBT_PRIMARY_PATTERN;
- next = BBT_PRIMARY;
- }
-
- err = nand_erase_blocks(bbt->chip, addr,
- bbt->chip->chip_geom.block_size);
- if (err)
- return (err);
-
- bbt->hdr->seq_nr++;
-
- err = nand_prog_pages_raw(bbt->chip, addr, bbt->hdr,
- bbt->tab_len + sizeof(struct bbt_header));
- if (err)
- return (err);
-
- bbt->active = next;
- return (0);
-}
-
-static int
-nand_bbt_load_hdr(struct nand_bbt *bbt, struct bbt_header *hdr, int8_t primary)
-{
- uint32_t addr;
-
- if (primary)
- addr = bbt->primary_map;
- else
- addr = bbt->secondary_map;
-
- return (nand_read_pages_raw(bbt->chip, addr, hdr,
- sizeof(struct bbt_header)));
-}
-
-static int
-nand_bbt_load_table(struct nand_bbt *bbt)
-{
- struct bbt_header hdr1, hdr2;
- uint32_t address = 0;
- int err = 0;
-
- bzero(&hdr1, sizeof(hdr1));
- bzero(&hdr2, sizeof(hdr2));
-
- nand_bbt_load_hdr(bbt, &hdr1, 1);
- if (hdr1.pattern == BBT_PRIMARY_PATTERN) {
- bbt->active = BBT_PRIMARY;
- address = bbt->primary_map;
- } else
- bzero(&hdr1, sizeof(hdr1));
-
-
- nand_bbt_load_hdr(bbt, &hdr2, 0);
- if ((hdr2.pattern == BBT_SECONDARY_PATTERN) &&
- (hdr2.seq_nr > hdr1.seq_nr)) {
- bbt->active = BBT_SECONDARY;
- address = bbt->secondary_map;
- } else
- bzero(&hdr2, sizeof(hdr2));
-
- if (bbt->active != BBT_NONE)
- err = nand_read_pages_raw(bbt->chip, address, bbt->hdr,
- bbt->tab_len + sizeof(struct bbt_header));
-
- return (err);
-}
-
-static int
-nand_bbt_prescan(struct nand_bbt *bbt)
-{
- int32_t i;
- uint8_t bad;
- bool printed_hash = 0;
-
- device_printf(bbt->chip->dev, "No BBT found. Prescan chip...\n");
- for (i = 0; i < bbt->chip->chip_geom.blks_per_chip; i++) {
- if (NAND_IS_BLK_BAD(bbt->chip->dev, i, &bad))
- return (ENXIO);
-
- if (bad) {
- device_printf(bbt->chip->dev, "Bad block(%d)\n", i);
- bbt->table[i] = 0x0FFFFFFF;
- }
- if (!(i % 100)) {
- printf("#");
- printed_hash = 1;
- }
- }
-
- if (printed_hash)
- printf("\n");
-
- return (0);
-}
-
-int
-nand_check_bad_block(struct nand_chip *chip, uint32_t block_number)
-{
-
- if (!chip || !chip->bbt)
- return (0);
-
- if ((chip->bbt->table[block_number] & 0xF0000000) == 0)
- return (1);
-
- return (0);
-}
-
-int
-nand_mark_bad_block(struct nand_chip *chip, uint32_t block_number)
-{
-
- chip->bbt->table[block_number] = 0x0FFFFFFF;
-
- return (0);
-}
diff --git a/sys/dev/nand/nand_cdev.c b/sys/dev/nand/nand_cdev.c
deleted file mode 100644
index 53c62dbc29135..0000000000000
--- a/sys/dev/nand/nand_cdev.c
+++ /dev/null
@@ -1,454 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (C) 2009-2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/conf.h>
-#include <sys/bus.h>
-#include <sys/malloc.h>
-#include <sys/uio.h>
-#include <sys/bio.h>
-
-#include <dev/nand/nand.h>
-#include <dev/nand/nandbus.h>
-#include <dev/nand/nand_dev.h>
-#include "nand_if.h"
-#include "nandbus_if.h"
-
-static int nand_page_stat(struct nand_chip *, struct page_stat_io *);
-static int nand_block_stat(struct nand_chip *, struct block_stat_io *);
-
-static d_ioctl_t nand_ioctl;
-static d_open_t nand_open;
-static d_strategy_t nand_strategy;
-
-static struct cdevsw nand_cdevsw = {
- .d_version = D_VERSION,
- .d_name = "nand",
- .d_open = nand_open,
- .d_read = physread,
- .d_write = physwrite,
- .d_ioctl = nand_ioctl,
- .d_strategy = nand_strategy,
-};
-
-static int
-offset_to_page(struct chip_geom *cg, uint32_t offset)
-{
-
- return (offset / cg->page_size);
-}
-
-static int
-offset_to_page_off(struct chip_geom *cg, uint32_t offset)
-{
-
- return (offset % cg->page_size);
-}
-
-int
-nand_make_dev(struct nand_chip *chip)
-{
- struct nandbus_ivar *ivar;
- device_t parent, nandbus;
- int parent_unit, unit;
- char *name;
-
- ivar = device_get_ivars(chip->dev);
- nandbus = device_get_parent(chip->dev);
-
- if (ivar->chip_cdev_name) {
- name = ivar->chip_cdev_name;
-
- /*
- * If we got distinct name for chip device we can enumarete it
- * based on contoller number.
- */
- parent = device_get_parent(nandbus);
- } else {
- name = "nand";
- parent = nandbus;
- }
-
- parent_unit = device_get_unit(parent);
- unit = parent_unit * 4 + chip->num;
- chip->cdev = make_dev(&nand_cdevsw, unit, UID_ROOT, GID_WHEEL,
- 0666, "%s%d.%d", name, parent_unit, chip->num);
-
- if (chip->cdev == NULL)
- return (ENXIO);
-
- if (bootverbose)
- device_printf(chip->dev, "Created cdev %s%d.%d for chip "
- "[0x%0x, 0x%0x]\n", name, parent_unit, chip->num,
- ivar->man_id, ivar->dev_id);
-
- chip->cdev->si_drv1 = chip;
-
- return (0);
-}
-
-void
-nand_destroy_dev(struct nand_chip *chip)
-{
-
- if (chip->cdev)
- destroy_dev(chip->cdev);
-}
-
-static int
-nand_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
-{
-
- return (0);
-}
-
-static int
-nand_read(struct nand_chip *chip, uint32_t offset, void *buf, uint32_t len)
-{
- struct chip_geom *cg;
- device_t nandbus;
- int start_page, count, off, err = 0;
- uint8_t *ptr, *tmp;
-
- nand_debug(NDBG_CDEV, "Read from chip%d [%p] at %d\n", chip->num,
- chip, offset);
-
- nandbus = device_get_parent(chip->dev);
- NANDBUS_LOCK(nandbus);
- NANDBUS_SELECT_CS(device_get_parent(chip->dev), chip->num);
-
- cg = &chip->chip_geom;
- start_page = offset_to_page(cg, offset);
- off = offset_to_page_off(cg, offset);
- count = (len > cg->page_size - off) ? cg->page_size - off : len;
-
- ptr = (uint8_t *)buf;
- while (len > 0) {
- if (len < cg->page_size) {
- tmp = malloc(cg->page_size, M_NAND, M_WAITOK);
- if (!tmp) {
- err = ENOMEM;
- break;
- }
- err = NAND_READ_PAGE(chip->dev, start_page,
- tmp, cg->page_size, 0);
- if (err) {
- free(tmp, M_NAND);
- break;
- }
- bcopy(tmp + off, ptr, count);
- free(tmp, M_NAND);
- } else {
- err = NAND_READ_PAGE(chip->dev, start_page,
- ptr, cg->page_size, 0);
- if (err)
- break;
- }
-
- len -= count;
- start_page++;
- ptr += count;
- count = (len > cg->page_size) ? cg->page_size : len;
- off = 0;
- }
-
- NANDBUS_UNLOCK(nandbus);
- return (err);
-}
-
-static int
-nand_write(struct nand_chip *chip, uint32_t offset, void* buf, uint32_t len)
-{
- struct chip_geom *cg;
- device_t nandbus;
- int off, start_page, err = 0;
- uint8_t *ptr;
-
- nand_debug(NDBG_CDEV, "Write to chip %d [%p] at %d\n", chip->num,
- chip, offset);
-
- nandbus = device_get_parent(chip->dev);
- NANDBUS_LOCK(nandbus);
- NANDBUS_SELECT_CS(device_get_parent(chip->dev), chip->num);
-
- cg = &chip->chip_geom;
- start_page = offset_to_page(cg, offset);
- off = offset_to_page_off(cg, offset);
-
- if (off != 0 || (len % cg->page_size) != 0) {
- printf("Not aligned write start [0x%08x] size [0x%08x]\n",
- off, len);
- NANDBUS_UNLOCK(nandbus);
- return (EINVAL);
- }
-
- ptr = (uint8_t *)buf;
- while (len > 0) {
- err = NAND_PROGRAM_PAGE(chip->dev, start_page, ptr,
- cg->page_size, 0);
- if (err)
- break;
-
- len -= cg->page_size;
- start_page++;
- ptr += cg->page_size;
- }
-
- NANDBUS_UNLOCK(nandbus);
- return (err);
-}
-
-static void
-nand_strategy(struct bio *bp)
-{
- struct nand_chip *chip;
- struct cdev *dev;
- int err = 0;
-
- dev = bp->bio_dev;
- chip = dev->si_drv1;
-
- nand_debug(NDBG_CDEV, "Strategy %s on chip %d [%p]\n",
- bp->bio_cmd == BIO_READ ? "READ" : "WRITE",
- chip->num, chip);
-
- if (bp->bio_cmd == BIO_READ) {
- err = nand_read(chip,
- bp->bio_offset & 0xffffffff,
- bp->bio_data, bp->bio_bcount);
- } else {
- err = nand_write(chip,
- bp->bio_offset & 0xffffffff,
- bp->bio_data, bp->bio_bcount);
- }
-
- if (err == 0)
- bp->bio_resid = 0;
- else {
- bp->bio_error = EIO;
- bp->bio_flags |= BIO_ERROR;
- bp->bio_resid = bp->bio_bcount;
- }
-
- biodone(bp);
-}
-
-static int
-nand_oob_access(struct nand_chip *chip, uint32_t page, uint32_t offset,
- uint32_t len, uint8_t *data, uint8_t write)
-{
- struct chip_geom *cg;
- uint8_t *buf = NULL;
- int ret = 0;
-
- cg = &chip->chip_geom;
-
- buf = malloc(cg->oob_size, M_NAND, M_WAITOK);
- if (!buf)
- return (ENOMEM);
-
- memset(buf, 0xff, cg->oob_size);
-
- if (!write) {
- ret = nand_read_oob(chip, page, buf, cg->oob_size);
- copyout(buf, data, len);
- } else {
- copyin(data, buf, len);
- ret = nand_prog_oob(chip, page, buf, cg->oob_size);
- }
-
- free(buf, M_NAND);
-
- return (ret);
-}
-
-static int
-nand_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
- struct thread *td)
-{
- struct nand_chip *chip;
- struct chip_geom *cg;
- struct nand_oob_rw *oob_rw = NULL;
- struct nand_raw_rw *raw_rw = NULL;
- device_t nandbus;
- size_t bufsize = 0, len = 0;
- size_t raw_size;
- off_t off;
- uint8_t *buf = NULL;
- int ret = 0;
- uint8_t status;
-
- chip = (struct nand_chip *)dev->si_drv1;
- cg = &chip->chip_geom;
- nandbus = device_get_parent(chip->dev);
-
- if ((cmd == NAND_IO_RAW_READ) || (cmd == NAND_IO_RAW_PROG)) {
- raw_rw = (struct nand_raw_rw *)data;
- raw_size = cg->pgs_per_blk * (cg->page_size + cg->oob_size);
-
- /* Check if len is not bigger than chip size */
- if (raw_rw->len > raw_size)
- return (EFBIG);
-
- /*
- * Do not ask for too much memory, in case of large transfers
- * read/write in 16-pages chunks
- */
- bufsize = 16 * (cg->page_size + cg->oob_size);
- if (raw_rw->len < bufsize)
- bufsize = raw_rw->len;
-
- buf = malloc(bufsize, M_NAND, M_WAITOK);
- len = raw_rw->len;
- off = 0;
- }
- switch(cmd) {
- case NAND_IO_ERASE:
- ret = nand_erase_blocks(chip, ((off_t *)data)[0],
- ((off_t *)data)[1]);
- break;
-
- case NAND_IO_OOB_READ:
- oob_rw = (struct nand_oob_rw *)data;
- ret = nand_oob_access(chip, oob_rw->page, 0,
- oob_rw->len, oob_rw->data, 0);
- break;
-
- case NAND_IO_OOB_PROG:
- oob_rw = (struct nand_oob_rw *)data;
- ret = nand_oob_access(chip, oob_rw->page, 0,
- oob_rw->len, oob_rw->data, 1);
- break;
-
- case NAND_IO_GET_STATUS:
- NANDBUS_LOCK(nandbus);
- ret = NANDBUS_GET_STATUS(nandbus, &status);
- if (ret == 0)
- *(uint8_t *)data = status;
- NANDBUS_UNLOCK(nandbus);
- break;
-
- case NAND_IO_RAW_PROG:
- while (len > 0) {
- if (len < bufsize)
- bufsize = len;
- ret = copyin(raw_rw->data + off, buf, bufsize);
- if (ret)
- break;
- ret = nand_prog_pages_raw(chip, raw_rw->off + off, buf,
- bufsize);
- if (ret)
- break;
- len -= bufsize;
- off += bufsize;
- }
- break;
-
- case NAND_IO_RAW_READ:
- while (len > 0) {
- if (len < bufsize)
- bufsize = len;
-
- ret = nand_read_pages_raw(chip, raw_rw->off + off, buf,
- bufsize);
- if (ret)
- break;
-
- ret = copyout(buf, raw_rw->data + off, bufsize);
- if (ret)
- break;
- len -= bufsize;
- off += bufsize;
- }
- break;
-
- case NAND_IO_PAGE_STAT:
- ret = nand_page_stat(chip, (struct page_stat_io *)data);
- break;
-
- case NAND_IO_BLOCK_STAT:
- ret = nand_block_stat(chip, (struct block_stat_io *)data);
- break;
-
- case NAND_IO_GET_CHIP_PARAM:
- nand_get_chip_param(chip, (struct chip_param_io *)data);
- break;
-
- default:
- printf("Unknown nand_ioctl request \n");
- ret = EIO;
- }
-
- if (buf)
- free(buf, M_NAND);
-
- return (ret);
-}
-
-static int
-nand_page_stat(struct nand_chip *chip, struct page_stat_io *page_stat)
-{
- struct chip_geom *cg;
- struct page_stat *stat;
- int num_pages;
-
- cg = &chip->chip_geom;
- num_pages = cg->pgs_per_blk * cg->blks_per_lun * cg->luns;
- if (page_stat->page_num >= num_pages)
- return (EINVAL);
-
- stat = &chip->pg_stat[page_stat->page_num];
- page_stat->page_read = stat->page_read;
- page_stat->page_written = stat->page_written;
- page_stat->page_raw_read = stat->page_raw_read;
- page_stat->page_raw_written = stat->page_raw_written;
- page_stat->ecc_succeded = stat->ecc_stat.ecc_succeded;
- page_stat->ecc_corrected = stat->ecc_stat.ecc_corrected;
- page_stat->ecc_failed = stat->ecc_stat.ecc_failed;
-
- return (0);
-}
-
-static int
-nand_block_stat(struct nand_chip *chip, struct block_stat_io *block_stat)
-{
- struct chip_geom *cg;
- uint32_t block_num = block_stat->block_num;
-
- cg = &chip->chip_geom;
- if (block_num >= cg->blks_per_lun * cg->luns)
- return (EINVAL);
-
- block_stat->block_erased = chip->blk_stat[block_num].block_erased;
-
- return (0);
-}
diff --git a/sys/dev/nand/nand_dev.h b/sys/dev/nand/nand_dev.h
deleted file mode 100644
index bd00c4d4b3b4d..0000000000000
--- a/sys/dev/nand/nand_dev.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (C) 2009-2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef _DEV_NAND_CDEV_H_
-#define _DEV_NAND_CDEV_H_
-
-#include <sys/ioccom.h>
-#include <sys/param.h>
-
-struct nand_raw_rw {
- off_t off;
- off_t len;
- uint8_t *data;
-};
-
-struct nand_oob_rw {
- uint32_t page;
- off_t len;
- uint8_t *data;
-};
-
-#define NAND_IOCTL_GROUP 'N'
-#define NAND_IO_ERASE _IOWR(NAND_IOCTL_GROUP, 0x0, off_t[2])
-
-#define NAND_IO_OOB_READ _IOWR(NAND_IOCTL_GROUP, 0x1, struct nand_oob_rw)
-
-#define NAND_IO_OOB_PROG _IOWR(NAND_IOCTL_GROUP, 0x2, struct nand_oob_rw)
-
-#define NAND_IO_RAW_READ _IOWR(NAND_IOCTL_GROUP, 0x3, struct nand_raw_rw)
-
-#define NAND_IO_RAW_PROG _IOWR(NAND_IOCTL_GROUP, 0x4, struct nand_raw_rw)
-
-#define NAND_IO_GET_STATUS _IOWR(NAND_IOCTL_GROUP, 0x5, uint8_t)
-
-struct page_stat_io {
- uint32_t page_num;
- uint32_t page_read;
- uint32_t page_written;
- uint32_t page_raw_read;
- uint32_t page_raw_written;
- uint32_t ecc_succeded;
- uint32_t ecc_corrected;
- uint32_t ecc_failed;
-};
-#define NAND_IO_PAGE_STAT _IOWR(NAND_IOCTL_GROUP, 0x6, \
- struct page_stat_io)
-
-struct block_stat_io {
- uint32_t block_num;
- uint32_t block_erased;
-};
-#define NAND_IO_BLOCK_STAT _IOWR(NAND_IOCTL_GROUP, 0x7, \
- struct block_stat_io)
-
-struct chip_param_io {
- uint32_t page_size;
- uint32_t oob_size;
-
- uint32_t blocks;
- uint32_t pages_per_block;
-};
-#define NAND_IO_GET_CHIP_PARAM _IOWR(NAND_IOCTL_GROUP, 0x8, \
- struct chip_param_io)
-
-#endif /* _DEV_NAND_CDEV_H_ */
diff --git a/sys/dev/nand/nand_ecc_pos.h b/sys/dev/nand/nand_ecc_pos.h
deleted file mode 100644
index 835f45e6c0836..0000000000000
--- a/sys/dev/nand/nand_ecc_pos.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (C) 2009-2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef _DEV_NAND_ECC_POS_H_
-#define _DEV_NAND_ECC_POS_H_
-
-static uint16_t default_software_ecc_positions_16[] = {2, 0, 1, 7, 4, 6};
-
-static uint16_t default_software_ecc_positions_64[] = {
-
- 42, 40, 41, 45, 43, 44, 48, 46,
- 47, 51, 49, 50, 54, 52, 53, 57,
- 55, 56, 60, 58, 59, 63, 61, 62
-};
-
-static uint16_t default_software_ecc_positions_128[] = {
- 8, 9, 10, 11, 12, 13,
- 18, 19, 20, 21, 22, 23,
- 28, 29, 30, 31, 32, 33,
- 38, 39, 40, 41, 42, 43,
- 48, 49, 50, 51, 52, 53,
- 58, 59, 60, 61, 62, 63,
- 68, 69, 70, 71, 72, 73,
- 78, 79, 80, 81, 82, 83,
- 88, 89, 90, 91, 92, 93,
- 98, 99, 100, 101, 102, 103,
- 108, 109, 110, 111, 112, 113,
- 118, 119, 120, 121, 122, 123,
-};
-#endif /* _DEV_NAND_ECC_POS_H_ */
-
diff --git a/sys/dev/nand/nand_generic.c b/sys/dev/nand/nand_generic.c
deleted file mode 100644
index cc6ef9bd57b07..0000000000000
--- a/sys/dev/nand/nand_generic.c
+++ /dev/null
@@ -1,1366 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (C) 2009-2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/* Generic NAND driver */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/proc.h>
-#include <sys/bus.h>
-#include <sys/conf.h>
-#include <sys/endian.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-#include <sys/rman.h>
-#include <sys/lock.h>
-#include <sys/mutex.h>
-#include <sys/time.h>
-#include <sys/malloc.h>
-
-#include <dev/nand/nand.h>
-#include <dev/nand/nandbus.h>
-#include "nfc_if.h"
-#include "nand_if.h"
-#include "nandbus_if.h"
-
-
-static int onfi_nand_probe(device_t dev);
-static int large_nand_probe(device_t dev);
-static int small_nand_probe(device_t dev);
-static int generic_nand_attach(device_t dev);
-static int generic_nand_detach(device_t dev);
-
-static int generic_erase_block(device_t, uint32_t);
-static int generic_erase_block_intlv(device_t, uint32_t);
-static int generic_read_page (device_t, uint32_t, void *, uint32_t, uint32_t);
-static int generic_read_oob(device_t, uint32_t, void *, uint32_t, uint32_t);
-static int generic_program_page(device_t, uint32_t, void *, uint32_t, uint32_t);
-static int generic_program_page_intlv(device_t, uint32_t, void *, uint32_t,
- uint32_t);
-static int generic_program_oob(device_t, uint32_t, void *, uint32_t, uint32_t);
-static int generic_is_blk_bad(device_t, uint32_t, uint8_t *);
-static int generic_get_ecc(device_t, void *, void *, int *);
-static int generic_correct_ecc(device_t, void *, void *, void *);
-
-static int small_read_page(device_t, uint32_t, void *, uint32_t, uint32_t);
-static int small_read_oob(device_t, uint32_t, void *, uint32_t, uint32_t);
-static int small_program_page(device_t, uint32_t, void *, uint32_t, uint32_t);
-static int small_program_oob(device_t, uint32_t, void *, uint32_t, uint32_t);
-
-static int onfi_is_blk_bad(device_t, uint32_t, uint8_t *);
-static int onfi_read_parameter(struct nand_chip *, struct onfi_chip_params *);
-
-static int nand_send_address(device_t, int32_t, int32_t, int8_t);
-
-static device_method_t onand_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe, onfi_nand_probe),
- DEVMETHOD(device_attach, generic_nand_attach),
- DEVMETHOD(device_detach, generic_nand_detach),
-
- DEVMETHOD(nand_read_page, generic_read_page),
- DEVMETHOD(nand_program_page, generic_program_page),
- DEVMETHOD(nand_program_page_intlv, generic_program_page_intlv),
- DEVMETHOD(nand_read_oob, generic_read_oob),
- DEVMETHOD(nand_program_oob, generic_program_oob),
- DEVMETHOD(nand_erase_block, generic_erase_block),
- DEVMETHOD(nand_erase_block_intlv, generic_erase_block_intlv),
-
- DEVMETHOD(nand_is_blk_bad, onfi_is_blk_bad),
- DEVMETHOD(nand_get_ecc, generic_get_ecc),
- DEVMETHOD(nand_correct_ecc, generic_correct_ecc),
- { 0, 0 }
-};
-
-static device_method_t lnand_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe, large_nand_probe),
- DEVMETHOD(device_attach, generic_nand_attach),
- DEVMETHOD(device_detach, generic_nand_detach),
-
- DEVMETHOD(nand_read_page, generic_read_page),
- DEVMETHOD(nand_program_page, generic_program_page),
- DEVMETHOD(nand_read_oob, generic_read_oob),
- DEVMETHOD(nand_program_oob, generic_program_oob),
- DEVMETHOD(nand_erase_block, generic_erase_block),
-
- DEVMETHOD(nand_is_blk_bad, generic_is_blk_bad),
- DEVMETHOD(nand_get_ecc, generic_get_ecc),
- DEVMETHOD(nand_correct_ecc, generic_correct_ecc),
- { 0, 0 }
-};
-
-static device_method_t snand_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe, small_nand_probe),
- DEVMETHOD(device_attach, generic_nand_attach),
- DEVMETHOD(device_detach, generic_nand_detach),
-
- DEVMETHOD(nand_read_page, small_read_page),
- DEVMETHOD(nand_program_page, small_program_page),
- DEVMETHOD(nand_read_oob, small_read_oob),
- DEVMETHOD(nand_program_oob, small_program_oob),
- DEVMETHOD(nand_erase_block, generic_erase_block),
-
- DEVMETHOD(nand_is_blk_bad, generic_is_blk_bad),
- DEVMETHOD(nand_get_ecc, generic_get_ecc),
- DEVMETHOD(nand_correct_ecc, generic_correct_ecc),
- { 0, 0 }
-};
-
-devclass_t onand_devclass;
-devclass_t lnand_devclass;
-devclass_t snand_devclass;
-
-driver_t onand_driver = {
- "onand",
- onand_methods,
- sizeof(struct nand_chip)
-};
-
-driver_t lnand_driver = {
- "lnand",
- lnand_methods,
- sizeof(struct nand_chip)
-};
-
-driver_t snand_driver = {
- "snand",
- snand_methods,
- sizeof(struct nand_chip)
-};
-
-DRIVER_MODULE(onand, nandbus, onand_driver, onand_devclass, 0, 0);
-DRIVER_MODULE(lnand, nandbus, lnand_driver, lnand_devclass, 0, 0);
-DRIVER_MODULE(snand, nandbus, snand_driver, snand_devclass, 0, 0);
-
-static int
-onfi_nand_probe(device_t dev)
-{
- struct nandbus_ivar *ivar;
-
- ivar = device_get_ivars(dev);
- if (ivar && ivar->is_onfi) {
- device_set_desc(dev, "ONFI compliant NAND");
- return (BUS_PROBE_DEFAULT);
- }
-
- return (ENODEV);
-}
-
-static int
-large_nand_probe(device_t dev)
-{
- struct nandbus_ivar *ivar;
-
- ivar = device_get_ivars(dev);
- if (ivar && !ivar->is_onfi && ivar->params->page_size >= 512) {
- device_set_desc(dev, ivar->params->name);
- return (BUS_PROBE_DEFAULT);
- }
-
- return (ENODEV);
-}
-
-static int
-small_nand_probe(device_t dev)
-{
- struct nandbus_ivar *ivar;
-
- ivar = device_get_ivars(dev);
- if (ivar && !ivar->is_onfi && ivar->params->page_size == 512) {
- device_set_desc(dev, ivar->params->name);
- return (BUS_PROBE_DEFAULT);
- }
-
- return (ENODEV);
-}
-
-static int
-generic_nand_attach(device_t dev)
-{
- struct nand_chip *chip;
- struct nandbus_ivar *ivar;
- struct onfi_chip_params *onfi_chip_params;
- device_t nandbus, nfc;
- int err;
-
- chip = device_get_softc(dev);
- chip->dev = dev;
-
- ivar = device_get_ivars(dev);
- chip->id.man_id = ivar->man_id;
- chip->id.dev_id = ivar->dev_id;
- chip->num = ivar->cs;
-
- /* TODO remove when HW ECC supported */
- nandbus = device_get_parent(dev);
- nfc = device_get_parent(nandbus);
-
- chip->nand = device_get_softc(nfc);
-
- if (ivar->is_onfi) {
- onfi_chip_params = malloc(sizeof(struct onfi_chip_params),
- M_NAND, M_WAITOK | M_ZERO);
-
- if (onfi_read_parameter(chip, onfi_chip_params)) {
- nand_debug(NDBG_GEN,"Could not read parameter page!\n");
- free(onfi_chip_params, M_NAND);
- return (ENXIO);
- }
-
- nand_onfi_set_params(chip, onfi_chip_params);
- /* Set proper column and row cycles */
- ivar->cols = (onfi_chip_params->address_cycles >> 4) & 0xf;
- ivar->rows = onfi_chip_params->address_cycles & 0xf;
- free(onfi_chip_params, M_NAND);
-
- } else {
- nand_set_params(chip, ivar->params);
- }
-
- err = nand_init_stat(chip);
- if (err) {
- generic_nand_detach(dev);
- return (err);
- }
-
- err = nand_init_bbt(chip);
- if (err) {
- generic_nand_detach(dev);
- return (err);
- }
-
- err = nand_make_dev(chip);
- if (err) {
- generic_nand_detach(dev);
- return (err);
- }
-
- err = create_geom_disk(chip);
- if (err) {
- generic_nand_detach(dev);
- return (err);
- }
-
- return (0);
-}
-
-static int
-generic_nand_detach(device_t dev)
-{
- struct nand_chip *chip;
-
- chip = device_get_softc(dev);
-
- nand_destroy_bbt(chip);
- destroy_geom_disk(chip);
- nand_destroy_dev(chip);
- nand_destroy_stat(chip);
-
- return (0);
-}
-
-static int
-can_write(device_t nandbus)
-{
- uint8_t status;
-
- if (NANDBUS_WAIT_READY(nandbus, &status))
- return (0);
-
- if (!(status & NAND_STATUS_WP)) {
- nand_debug(NDBG_GEN,"Chip is write-protected");
- return (0);
- }
-
- return (1);
-}
-
-static int
-check_fail(device_t nandbus)
-{
- uint8_t status;
-
- NANDBUS_WAIT_READY(nandbus, &status);
- if (status & NAND_STATUS_FAIL) {
- nand_debug(NDBG_GEN,"Status failed %x", status);
- return (ENXIO);
- }
-
- return (0);
-}
-
-static uint16_t
-onfi_crc(const void *buf, size_t buflen)
-{
- int i, j;
- uint16_t crc;
- const uint8_t *bufptr;
-
- bufptr = buf;
- crc = 0x4f4e;
- for (j = 0; j < buflen; j++) {
- crc ^= *bufptr++ << 8;
- for (i = 0; i < 8; i++)
- if (crc & 0x8000)
- crc = (crc << 1) ^ 0x8005;
- else
- crc <<= 1;
- }
- return crc;
-}
-
-static int
-onfi_read_parameter(struct nand_chip *chip, struct onfi_chip_params *chip_params)
-{
- device_t nandbus;
- struct onfi_params params;
- int found, sigcount, trycopy;
-
- nand_debug(NDBG_GEN,"read parameter");
-
- nandbus = device_get_parent(chip->dev);
-
- NANDBUS_SELECT_CS(nandbus, chip->num);
-
- if (NANDBUS_SEND_COMMAND(nandbus, NAND_CMD_READ_PARAMETER))
- return (ENXIO);
-
- if (nand_send_address(chip->dev, -1, -1, PAGE_PARAMETER_DEF))
- return (ENXIO);
-
- if (NANDBUS_START_COMMAND(nandbus))
- return (ENXIO);
-
- /*
- * XXX Bogus DELAY, we really need a nandbus_wait_ready() here, but it's
- * not accessible from here (static to nandbus).
- */
- DELAY(1000);
-
- /*
- * The ONFI spec mandates a minimum of three copies of the parameter
- * data, so loop up to 3 times trying to find good data. Each copy is
- * validated by a signature of "ONFI" and a crc. There is a very strange
- * rule that the signature is valid if any 2 of the 4 bytes are correct.
- */
- for (found= 0, trycopy = 0; !found && trycopy < 3; trycopy++) {
- NANDBUS_READ_BUFFER(nandbus, &params, sizeof(struct onfi_params));
- sigcount = params.signature[0] == 'O';
- sigcount += params.signature[1] == 'N';
- sigcount += params.signature[2] == 'F';
- sigcount += params.signature[3] == 'I';
- if (sigcount < 2)
- continue;
- if (onfi_crc(&params, 254) != params.crc)
- continue;
- found = 1;
- }
- if (!found)
- return (ENXIO);
-
- chip_params->luns = params.luns;
- chip_params->blocks_per_lun = le32dec(&params.blocks_per_lun);
- chip_params->pages_per_block = le32dec(&params.pages_per_block);
- chip_params->bytes_per_page = le32dec(&params.bytes_per_page);
- chip_params->spare_bytes_per_page = le16dec(&params.spare_bytes_per_page);
- chip_params->t_bers = le16dec(&params.t_bers);
- chip_params->t_prog = le16dec(&params.t_prog);
- chip_params->t_r = le16dec(&params.t_r);
- chip_params->t_ccs = le16dec(&params.t_ccs);
- chip_params->features = le16dec(&params.features);
- chip_params->address_cycles = params.address_cycles;
-
- return (0);
-}
-
-static int
-send_read_page(device_t nand, uint8_t start_command, uint8_t end_command,
- uint32_t row, uint32_t column)
-{
- device_t nandbus = device_get_parent(nand);
-
- if (NANDBUS_SEND_COMMAND(nandbus, start_command))
- return (ENXIO);
-
- if (nand_send_address(nand, row, column, -1))
- return (ENXIO);
-
- if (NANDBUS_SEND_COMMAND(nandbus, end_command))
- return (ENXIO);
-
- if (NANDBUS_START_COMMAND(nandbus))
- return (ENXIO);
-
- return (0);
-}
-
-static int
-generic_read_page(device_t nand, uint32_t page, void *buf, uint32_t len,
- uint32_t offset)
-{
- struct nand_chip *chip;
- struct page_stat *pg_stat;
- device_t nandbus;
- uint32_t row;
-
- nand_debug(NDBG_GEN,"%p raw read page %x[%x] at %x", nand, page, len, offset);
- chip = device_get_softc(nand);
- nandbus = device_get_parent(nand);
-
- if (nand_check_page_boundary(chip, page))
- return (ENXIO);
-
- page_to_row(&chip->chip_geom, page, &row);
-
- if (send_read_page(nand, NAND_CMD_READ, NAND_CMD_READ_END, row,
- offset))
- return (ENXIO);
-
- DELAY(chip->t_r);
-
- NANDBUS_READ_BUFFER(nandbus, buf, len);
-
- if (check_fail(nandbus))
- return (ENXIO);
-
- pg_stat = &(chip->pg_stat[page]);
- pg_stat->page_raw_read++;
-
- return (0);
-}
-
-static int
-generic_read_oob(device_t nand, uint32_t page, void* buf, uint32_t len,
- uint32_t offset)
-{
- struct nand_chip *chip;
- device_t nandbus;
- uint32_t row;
-
- nand_debug(NDBG_GEN,"%p raw read oob %x[%x] at %x", nand, page, len, offset);
- chip = device_get_softc(nand);
- nandbus = device_get_parent(nand);
-
- if (nand_check_page_boundary(chip, page)) {
- nand_debug(NDBG_GEN,"page boundary check failed: %08x\n", page);
- return (ENXIO);
- }
-
- page_to_row(&chip->chip_geom, page, &row);
-
- offset += chip->chip_geom.page_size;
-
- if (send_read_page(nand, NAND_CMD_READ, NAND_CMD_READ_END, row,
- offset))
- return (ENXIO);
-
- DELAY(chip->t_r);
-
- NANDBUS_READ_BUFFER(nandbus, buf, len);
-
- if (check_fail(nandbus))
- return (ENXIO);
-
- return (0);
-}
-
-static int
-send_start_program_page(device_t nand, uint32_t row, uint32_t column)
-{
- device_t nandbus = device_get_parent(nand);
-
- if (NANDBUS_SEND_COMMAND(nandbus, NAND_CMD_PROG))
- return (ENXIO);
-
- if (nand_send_address(nand, row, column, -1))
- return (ENXIO);
-
- return (0);
-}
-
-static int
-send_end_program_page(device_t nandbus, uint8_t end_command)
-{
-
- if (NANDBUS_SEND_COMMAND(nandbus, end_command))
- return (ENXIO);
-
- if (NANDBUS_START_COMMAND(nandbus))
- return (ENXIO);
-
- return (0);
-}
-
-static int
-generic_program_page(device_t nand, uint32_t page, void *buf, uint32_t len,
- uint32_t offset)
-{
- struct nand_chip *chip;
- struct page_stat *pg_stat;
- device_t nandbus;
- uint32_t row;
-
- nand_debug(NDBG_GEN,"%p raw prog page %x[%x] at %x", nand, page, len,
- offset);
- chip = device_get_softc(nand);
- nandbus = device_get_parent(nand);
-
- if (nand_check_page_boundary(chip, page))
- return (ENXIO);
-
- page_to_row(&chip->chip_geom, page, &row);
-
- if (!can_write(nandbus))
- return (ENXIO);
-
- if (send_start_program_page(nand, row, offset))
- return (ENXIO);
-
- NANDBUS_WRITE_BUFFER(nandbus, buf, len);
-
- if (send_end_program_page(nandbus, NAND_CMD_PROG_END))
- return (ENXIO);
-
- DELAY(chip->t_prog);
-
- if (check_fail(nandbus))
- return (ENXIO);
-
- pg_stat = &(chip->pg_stat[page]);
- pg_stat->page_raw_written++;
-
- return (0);
-}
-
-static int
-generic_program_page_intlv(device_t nand, uint32_t page, void *buf,
- uint32_t len, uint32_t offset)
-{
- struct nand_chip *chip;
- struct page_stat *pg_stat;
- device_t nandbus;
- uint32_t row;
-
- nand_debug(NDBG_GEN,"%p raw prog page %x[%x] at %x", nand, page, len, offset);
- chip = device_get_softc(nand);
- nandbus = device_get_parent(nand);
-
- if (nand_check_page_boundary(chip, page))
- return (ENXIO);
-
- page_to_row(&chip->chip_geom, page, &row);
-
- if (!can_write(nandbus))
- return (ENXIO);
-
- if (send_start_program_page(nand, row, offset))
- return (ENXIO);
-
- NANDBUS_WRITE_BUFFER(nandbus, buf, len);
-
- if (send_end_program_page(nandbus, NAND_CMD_PROG_INTLV))
- return (ENXIO);
-
- DELAY(chip->t_prog);
-
- if (check_fail(nandbus))
- return (ENXIO);
-
- pg_stat = &(chip->pg_stat[page]);
- pg_stat->page_raw_written++;
-
- return (0);
-}
-
-static int
-generic_program_oob(device_t nand, uint32_t page, void* buf, uint32_t len,
- uint32_t offset)
-{
- struct nand_chip *chip;
- device_t nandbus;
- uint32_t row;
-
- nand_debug(NDBG_GEN,"%p raw prog oob %x[%x] at %x", nand, page, len,
- offset);
- chip = device_get_softc(nand);
- nandbus = device_get_parent(nand);
-
- if (nand_check_page_boundary(chip, page))
- return (ENXIO);
-
- page_to_row(&chip->chip_geom, page, &row);
- offset += chip->chip_geom.page_size;
-
- if (!can_write(nandbus))
- return (ENXIO);
-
- if (send_start_program_page(nand, row, offset))
- return (ENXIO);
-
- NANDBUS_WRITE_BUFFER(nandbus, buf, len);
-
- if (send_end_program_page(nandbus, NAND_CMD_PROG_END))
- return (ENXIO);
-
- DELAY(chip->t_prog);
-
- if (check_fail(nandbus))
- return (ENXIO);
-
- return (0);
-}
-
-static int
-send_erase_block(device_t nand, uint32_t row, uint8_t second_command)
-{
- device_t nandbus = device_get_parent(nand);
-
- if (NANDBUS_SEND_COMMAND(nandbus, NAND_CMD_ERASE))
- return (ENXIO);
-
- if (nand_send_address(nand, row, -1, -1))
- return (ENXIO);
-
- if (NANDBUS_SEND_COMMAND(nandbus, second_command))
- return (ENXIO);
-
- if (NANDBUS_START_COMMAND(nandbus))
- return (ENXIO);
-
- return (0);
-}
-
-static int
-generic_erase_block(device_t nand, uint32_t block)
-{
- struct block_stat *blk_stat;
- struct nand_chip *chip;
- device_t nandbus;
- int row;
-
- nand_debug(NDBG_GEN,"%p erase block %x", nand, block);
- nandbus = device_get_parent(nand);
- chip = device_get_softc(nand);
-
- if (block >= (chip->chip_geom.blks_per_lun * chip->chip_geom.luns))
- return (ENXIO);
-
- row = (block << chip->chip_geom.blk_shift) &
- chip->chip_geom.blk_mask;
-
- nand_debug(NDBG_GEN,"%p erase block row %x", nand, row);
-
- if (!can_write(nandbus))
- return (ENXIO);
-
- send_erase_block(nand, row, NAND_CMD_ERASE_END);
-
- DELAY(chip->t_bers);
-
- if (check_fail(nandbus))
- return (ENXIO);
-
- blk_stat = &(chip->blk_stat[block]);
- blk_stat->block_erased++;
-
- return (0);
-}
-
-static int
-generic_erase_block_intlv(device_t nand, uint32_t block)
-{
- struct block_stat *blk_stat;
- struct nand_chip *chip;
- device_t nandbus;
- int row;
-
- nand_debug(NDBG_GEN,"%p erase block %x", nand, block);
- nandbus = device_get_parent(nand);
- chip = device_get_softc(nand);
-
- if (block >= (chip->chip_geom.blks_per_lun * chip->chip_geom.luns))
- return (ENXIO);
-
- row = (block << chip->chip_geom.blk_shift) &
- chip->chip_geom.blk_mask;
-
- if (!can_write(nandbus))
- return (ENXIO);
-
- send_erase_block(nand, row, NAND_CMD_ERASE_INTLV);
-
- DELAY(chip->t_bers);
-
- if (check_fail(nandbus))
- return (ENXIO);
-
- blk_stat = &(chip->blk_stat[block]);
- blk_stat->block_erased++;
-
- return (0);
-
-}
-
-static int
-onfi_is_blk_bad(device_t device, uint32_t block_number, uint8_t *bad)
-{
- struct nand_chip *chip;
- int page_number, i, j, err;
- uint8_t *oob;
-
- chip = device_get_softc(device);
-
- oob = malloc(chip->chip_geom.oob_size, M_NAND, M_WAITOK);
-
- page_number = block_number * chip->chip_geom.pgs_per_blk;
- *bad = 0;
- /* Check OOB of first and last page */
- for (i = 0; i < 2; i++, page_number+= chip->chip_geom.pgs_per_blk - 1) {
- err = generic_read_oob(device, page_number, oob,
- chip->chip_geom.oob_size, 0);
- if (err) {
- device_printf(device, "%s: cannot allocate oob\n",
- __func__);
- free(oob, M_NAND);
- return (ENOMEM);
- }
-
- for (j = 0; j < chip->chip_geom.oob_size; j++) {
- if (!oob[j]) {
- *bad = 1;
- free(oob, M_NAND);
- return (0);
- }
- }
- }
-
- free(oob, M_NAND);
-
- return (0);
-}
-
-static int
-send_small_read_page(device_t nand, uint8_t start_command,
- uint32_t row, uint32_t column)
-{
- device_t nandbus = device_get_parent(nand);
-
- if (NANDBUS_SEND_COMMAND(nandbus, start_command))
- return (ENXIO);
-
- if (nand_send_address(nand, row, column, -1))
- return (ENXIO);
-
- if (NANDBUS_START_COMMAND(nandbus))
- return (ENXIO);
-
- return (0);
-}
-
-
-static int
-small_read_page(device_t nand, uint32_t page, void *buf, uint32_t len,
- uint32_t offset)
-{
- struct nand_chip *chip;
- struct page_stat *pg_stat;
- device_t nandbus;
- uint32_t row;
-
- nand_debug(NDBG_GEN,"%p small read page %x[%x] at %x", nand, page, len, offset);
- chip = device_get_softc(nand);
- nandbus = device_get_parent(nand);
-
- if (nand_check_page_boundary(chip, page))
- return (ENXIO);
-
- page_to_row(&chip->chip_geom, page, &row);
-
- if (offset < 256) {
- if (send_small_read_page(nand, NAND_CMD_SMALLA, row, offset))
- return (ENXIO);
- } else {
- offset -= 256;
- if (send_small_read_page(nandbus, NAND_CMD_SMALLB, row, offset))
- return (ENXIO);
- }
-
- DELAY(chip->t_r);
-
- NANDBUS_READ_BUFFER(nandbus, buf, len);
-
- if (check_fail(nandbus))
- return (ENXIO);
-
- pg_stat = &(chip->pg_stat[page]);
- pg_stat->page_raw_read++;
-
- return (0);
-}
-
-static int
-small_read_oob(device_t nand, uint32_t page, void *buf, uint32_t len,
- uint32_t offset)
-{
- struct nand_chip *chip;
- struct page_stat *pg_stat;
- device_t nandbus;
- uint32_t row;
-
- nand_debug(NDBG_GEN,"%p small read oob %x[%x] at %x", nand, page, len, offset);
- chip = device_get_softc(nand);
- nandbus = device_get_parent(nand);
-
- if (nand_check_page_boundary(chip, page))
- return (ENXIO);
-
- page_to_row(&chip->chip_geom, page, &row);
-
- if (send_small_read_page(nand, NAND_CMD_SMALLOOB, row, 0))
- return (ENXIO);
-
- DELAY(chip->t_r);
-
- NANDBUS_READ_BUFFER(nandbus, buf, len);
-
- if (check_fail(nandbus))
- return (ENXIO);
-
- pg_stat = &(chip->pg_stat[page]);
- pg_stat->page_raw_read++;
-
- return (0);
-}
-
-static int
-small_program_page(device_t nand, uint32_t page, void* buf, uint32_t len,
- uint32_t offset)
-{
- struct nand_chip *chip;
- device_t nandbus;
- uint32_t row;
-
- nand_debug(NDBG_GEN,"%p small prog page %x[%x] at %x", nand, page, len, offset);
- chip = device_get_softc(nand);
- nandbus = device_get_parent(nand);
-
- if (nand_check_page_boundary(chip, page))
- return (ENXIO);
-
- page_to_row(&chip->chip_geom, page, &row);
-
- if (!can_write(nandbus))
- return (ENXIO);
-
- if (offset < 256) {
- if (NANDBUS_SEND_COMMAND(nandbus, NAND_CMD_SMALLA))
- return (ENXIO);
- } else {
- if (NANDBUS_SEND_COMMAND(nandbus, NAND_CMD_SMALLB))
- return (ENXIO);
- }
-
- if (send_start_program_page(nand, row, offset))
- return (ENXIO);
-
- NANDBUS_WRITE_BUFFER(nandbus, buf, len);
-
- if (send_end_program_page(nandbus, NAND_CMD_PROG_END))
- return (ENXIO);
-
- DELAY(chip->t_prog);
-
- if (check_fail(nandbus))
- return (ENXIO);
-
- return (0);
-}
-
-static int
-small_program_oob(device_t nand, uint32_t page, void* buf, uint32_t len,
- uint32_t offset)
-{
- struct nand_chip *chip;
- device_t nandbus;
- uint32_t row;
-
- nand_debug(NDBG_GEN,"%p small prog oob %x[%x] at %x", nand, page, len, offset);
- chip = device_get_softc(nand);
- nandbus = device_get_parent(nand);
-
- if (nand_check_page_boundary(chip, page))
- return (ENXIO);
-
- page_to_row(&chip->chip_geom, page, &row);
-
- if (!can_write(nandbus))
- return (ENXIO);
-
- if (NANDBUS_SEND_COMMAND(nandbus, NAND_CMD_SMALLOOB))
- return (ENXIO);
-
- if (send_start_program_page(nand, row, offset))
- return (ENXIO);
-
- NANDBUS_WRITE_BUFFER(nandbus, buf, len);
-
- if (send_end_program_page(nandbus, NAND_CMD_PROG_END))
- return (ENXIO);
-
- DELAY(chip->t_prog);
-
- if (check_fail(nandbus))
- return (ENXIO);
-
- return (0);
-}
-
-int
-nand_send_address(device_t nand, int32_t row, int32_t col, int8_t id)
-{
- struct nandbus_ivar *ivar;
- device_t nandbus;
- uint8_t addr;
- int err = 0;
- int i;
-
- nandbus = device_get_parent(nand);
- ivar = device_get_ivars(nand);
-
- if (id != -1) {
- nand_debug(NDBG_GEN,"send_address: send id %02x", id);
- err = NANDBUS_SEND_ADDRESS(nandbus, id);
- }
-
- if (!err && col != -1) {
- for (i = 0; i < ivar->cols; i++, col >>= 8) {
- addr = (uint8_t)(col & 0xff);
- nand_debug(NDBG_GEN,"send_address: send address column "
- "%02x", addr);
- err = NANDBUS_SEND_ADDRESS(nandbus, addr);
- if (err)
- break;
- }
- }
-
- if (!err && row != -1) {
- for (i = 0; i < ivar->rows; i++, row >>= 8) {
- addr = (uint8_t)(row & 0xff);
- nand_debug(NDBG_GEN,"send_address: send address row "
- "%02x", addr);
- err = NANDBUS_SEND_ADDRESS(nandbus, addr);
- if (err)
- break;
- }
- }
-
- return (err);
-}
-
-static int
-generic_is_blk_bad(device_t dev, uint32_t block, uint8_t *bad)
-{
- struct nand_chip *chip;
- int page_number, err, i;
- uint8_t *oob;
-
- chip = device_get_softc(dev);
-
- oob = malloc(chip->chip_geom.oob_size, M_NAND, M_WAITOK);
-
- page_number = block * chip->chip_geom.pgs_per_blk;
- *bad = 0;
-
- /* Check OOB of first and second page */
- for (i = 0; i < 2; i++) {
- err = NAND_READ_OOB(dev, page_number + i, oob,
- chip->chip_geom.oob_size, 0);
- if (err) {
- device_printf(dev, "%s: cannot allocate OOB\n",
- __func__);
- free(oob, M_NAND);
- return (ENOMEM);
- }
-
- if (!oob[0]) {
- *bad = 1;
- free(oob, M_NAND);
- return (0);
- }
- }
-
- free(oob, M_NAND);
-
- return (0);
-}
-
-static int
-generic_get_ecc(device_t dev, void *buf, void *ecc, int *needwrite)
-{
- struct nand_chip *chip = device_get_softc(dev);
- struct chip_geom *cg = &chip->chip_geom;
-
- return (NANDBUS_GET_ECC(device_get_parent(dev), buf, cg->page_size,
- ecc, needwrite));
-}
-
-static int
-generic_correct_ecc(device_t dev, void *buf, void *readecc, void *calcecc)
-{
- struct nand_chip *chip = device_get_softc(dev);
- struct chip_geom *cg = &chip->chip_geom;
-
- return (NANDBUS_CORRECT_ECC(device_get_parent(dev), buf,
- cg->page_size, readecc, calcecc));
-}
-
-
-#if 0
-int
-nand_chng_read_col(device_t nand, uint32_t col, void *buf, size_t len)
-{
- struct nand_chip *chip;
- device_t nandbus;
-
- chip = device_get_softc(nand);
- nandbus = device_get_parent(nand);
-
- if (NANDBUS_SEND_COMMAND(nandbus, NAND_CMD_CHNG_READ_COL))
- return (ENXIO);
-
- if (NANDBUS_SEND_ADDRESS(nandbus, -1, col, -1))
- return (ENXIO);
-
- if (NANDBUS_SEND_COMMAND(nandbus, NAND_CMD_CHNG_READ_COL_END))
- return (ENXIO);
-
- if (NANDBUS_START_COMMAND(nandbus))
- return (ENXIO);
-
- if (buf != NULL && len > 0)
- NANDBUS_READ_BUFFER(nandbus, buf, len);
-
- return (0);
-}
-
-int
-nand_chng_write_col(device_t dev, uint32_t col, void *buf,
- size_t len)
-{
- struct nand_chip *chip;
- device_t nandbus;
-
- chip = device_get_softc(dev);
- nandbus = device_get_parent(dev);
-
- if (NANDBUS_SEND_COMMAND(nandbus, NAND_CMD_CHNG_WRITE_COL))
- return (ENXIO);
-
- if (NANDBUS_SEND_ADDRESS(nandbus, -1, col, -1))
- return (ENXIO);
-
- if (buf != NULL && len > 0)
- NANDBUS_WRITE_BUFFER(nandbus, buf, len);
-
- if (NANDBUS_SEND_COMMAND(nandbus, NAND_CMD_CHNG_READ_COL_END))
- return (ENXIO);
-
- if (NANDBUS_START_COMMAND(nandbus))
- return (ENXIO);
-
- return (0);
-}
-
-int
-nand_copyback_read(device_t dev, uint32_t page, uint32_t col,
- void *buf, size_t len)
-{
- struct nand_chip *chip;
- struct page_stat *pg_stat;
- device_t nandbus;
- uint32_t row;
-
- nand_debug(NDBG_GEN," raw read page %x[%x] at %x", page, col, len);
- chip = device_get_softc(dev);
- nandbus = device_get_parent(dev);
-
- if (nand_check_page_boundary(chip, page))
- return (ENXIO);
-
- page_to_row(&chip->chip_geom, page, &row);
-
- if (send_read_page(nand, NAND_CMD_READ, NAND_CMD_READ_CPBK, row, 0))
- return (ENXIO);
-
- DELAY(chip->t_r);
- if (check_fail(nandbus))
- return (ENXIO);
-
- if (buf != NULL && len > 0)
- NANDBUS_READ_BUFFER(nandbus, buf, len);
-
- pg_stat = &(chip->pg_stat[page]);
- pg_stat->page_raw_read++;
-
- return (0);
-}
-
-int
-nand_copyback_prog(device_t dev, uint32_t page, uint32_t col,
- void *buf, size_t len)
-{
- struct nand_chip *chip;
- struct page_stat *pg_stat;
- device_t nandbus;
- uint32_t row;
-
- nand_debug(NDBG_GEN,"copyback prog page %x[%x]", page, len);
- chip = device_get_softc(dev);
- nandbus = device_get_parent(dev);
-
- if (nand_check_page_boundary(chip, page))
- return (ENXIO);
-
- page_to_row(&chip->chip_geom, page, &row);
-
- if (!can_write(nandbus))
- return (ENXIO);
-
- if (NANDBUS_SEND_COMMAND(nandbus, NAND_CMD_CHNG_WRITE_COL))
- return (ENXIO);
-
- if (NANDBUS_SEND_ADDRESS(nandbus, row, col, -1))
- return (ENXIO);
-
- if (buf != NULL && len > 0)
- NANDBUS_WRITE_BUFFER(nandbus, buf, len);
-
- if (send_end_program_page(nandbus, NAND_CMD_PROG_END))
- return (ENXIO);
-
- DELAY(chip->t_prog);
-
- if (check_fail(nandbus))
- return (ENXIO);
-
- pg_stat = &(chip->pg_stat[page]);
- pg_stat->page_raw_written++;
-
- return (0);
-}
-
-int
-nand_copyback_prog_intlv(device_t dev, uint32_t page)
-{
- struct nand_chip *chip;
- struct page_stat *pg_stat;
- device_t nandbus;
- uint32_t row;
-
- nand_debug(NDBG_GEN,"cache prog page %x", page);
- chip = device_get_softc(dev);
- nandbus = device_get_parent(dev);
-
- if (nand_check_page_boundary(chip, page))
- return (ENXIO);
-
- page_to_row(&chip->chip_geom, page, &row);
-
- if (!can_write(nandbus))
- return (ENXIO);
-
- if (send_start_program_page(nand, row, 0))
- return (ENXIO);
-
- if (send_end_program_page(nandbus, NAND_CMD_PROG_INTLV))
- return (ENXIO);
-
- DELAY(chip->t_prog);
-
- if (check_fail(nandbus))
- return (ENXIO);
-
- pg_stat = &(chip->pg_stat[page]);
- pg_stat->page_raw_written++;
-
- return (0);
-}
-
-int
-nand_prog_cache(device_t dev, uint32_t page, uint32_t col,
- void *buf, size_t len, uint8_t end)
-{
- struct nand_chip *chip;
- struct page_stat *pg_stat;
- device_t nandbus;
- uint32_t row;
- uint8_t command;
-
- nand_debug(NDBG_GEN,"cache prog page %x[%x]", page, len);
- chip = device_get_softc(dev);
- nandbus = device_get_parent(dev);
-
- if (nand_check_page_boundary(chip, page))
- return (ENXIO);
-
- page_to_row(&chip->chip_geom, page, &row);
-
- if (!can_write(nandbus))
- return (ENXIO);
-
- if (send_start_program_page(dev, row, 0))
- return (ENXIO);
-
- NANDBUS_WRITE_BUFFER(nandbus, buf, len);
-
- if (end)
- command = NAND_CMD_PROG_END;
- else
- command = NAND_CMD_PROG_CACHE;
-
- if (send_end_program_page(nandbus, command))
- return (ENXIO);
-
- DELAY(chip->t_prog);
-
- if (check_fail(nandbus))
- return (ENXIO);
-
- pg_stat = &(chip->pg_stat[page]);
- pg_stat->page_raw_written++;
-
- return (0);
-}
-
-int
-nand_read_cache(device_t dev, uint32_t page, uint32_t col,
- void *buf, size_t len, uint8_t end)
-{
- struct nand_chip *chip;
- struct page_stat *pg_stat;
- device_t nandbus;
- uint32_t row;
- uint8_t command;
-
- nand_debug(NDBG_GEN,"cache read page %x[%x] ", page, len);
- chip = device_get_softc(dev);
- nandbus = device_get_parent(dev);
-
- if (nand_check_page_boundary(chip, page))
- return (ENXIO);
-
- page_to_row(&chip->chip_geom, page, &row);
-
- if (page != -1) {
- if (NANDBUS_SEND_COMMAND(nandbus, NAND_CMD_READ))
- return (ENXIO);
-
- if (NANDBUS_SEND_ADDRESS(nandbus, row, col, -1))
- return (ENXIO);
- }
-
- if (end)
- command = NAND_CMD_READ_CACHE_END;
- else
- command = NAND_CMD_READ_CACHE;
-
- if (NANDBUS_SEND_COMMAND(nandbus, command))
- return (ENXIO);
-
- if (NANDBUS_START_COMMAND(nandbus))
- return (ENXIO);
-
- DELAY(chip->t_r);
- if (check_fail(nandbus))
- return (ENXIO);
-
- if (buf != NULL && len > 0)
- NANDBUS_READ_BUFFER(nandbus, buf, len);
-
- pg_stat = &(chip->pg_stat[page]);
- pg_stat->page_raw_read++;
-
- return (0);
-}
-
-int
-nand_get_feature(device_t dev, uint8_t feat, void *buf)
-{
- struct nand_chip *chip;
- device_t nandbus;
-
- nand_debug(NDBG_GEN,"nand get feature");
-
- chip = device_get_softc(dev);
- nandbus = device_get_parent(dev);
-
- if (NANDBUS_SEND_COMMAND(nandbus, NAND_CMD_GET_FEATURE))
- return (ENXIO);
-
- if (NANDBUS_SEND_ADDRESS(nandbus, -1, -1, feat))
- return (ENXIO);
-
- if (NANDBUS_START_COMMAND(nandbus))
- return (ENXIO);
-
- DELAY(chip->t_r);
- NANDBUS_READ_BUFFER(nandbus, buf, 4);
-
- return (0);
-}
-
-int
-nand_set_feature(device_t dev, uint8_t feat, void *buf)
-{
- struct nand_chip *chip;
- device_t nandbus;
-
- nand_debug(NDBG_GEN,"nand set feature");
-
- chip = device_get_softc(dev);
- nandbus = device_get_parent(dev);
-
- if (NANDBUS_SEND_COMMAND(nandbus, NAND_CMD_SET_FEATURE))
- return (ENXIO);
-
- if (NANDBUS_SEND_ADDRESS(nandbus, -1, -1, feat))
- return (ENXIO);
-
- NANDBUS_WRITE_BUFFER(nandbus, buf, 4);
-
- if (NANDBUS_START_COMMAND(nandbus))
- return (ENXIO);
-
- return (0);
-}
-#endif
diff --git a/sys/dev/nand/nand_geom.c b/sys/dev/nand/nand_geom.c
deleted file mode 100644
index b814ffc4e0a9a..0000000000000
--- a/sys/dev/nand/nand_geom.c
+++ /dev/null
@@ -1,467 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (C) 2009-2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/conf.h>
-#include <sys/bus.h>
-#include <sys/malloc.h>
-#include <sys/uio.h>
-#include <sys/bio.h>
-#include <geom/geom.h>
-#include <geom/geom_disk.h>
-
-#include <dev/nand/nand.h>
-#include <dev/nand/nandbus.h>
-#include <dev/nand/nand_dev.h>
-#include "nand_if.h"
-#include "nandbus_if.h"
-
-#define BIO_NAND_STD ((void *)1)
-#define BIO_NAND_RAW ((void *)2)
-
-static disk_ioctl_t nand_ioctl;
-static disk_getattr_t nand_getattr;
-static disk_strategy_t nand_strategy;
-static disk_strategy_t nand_strategy_raw;
-
-static int
-nand_read(struct nand_chip *chip, uint32_t offset, void *buf, uint32_t len)
-{
-
- nand_debug(NDBG_GEOM, "Read from chip %d [%p] at %d", chip->num, chip,
- offset);
-
- return (nand_read_pages(chip, offset, buf, len));
-}
-
-static int
-nand_write(struct nand_chip *chip, uint32_t offset, void* buf, uint32_t len)
-{
-
- nand_debug(NDBG_GEOM, "Write to chip %d [%p] at %d", chip->num, chip,
- offset);
-
- return (nand_prog_pages(chip, offset, buf, len));
-}
-
-static int
-nand_read_raw(struct nand_chip *chip, uint32_t offset, void *buf, uint32_t len)
-{
- nand_debug(NDBG_GEOM, "Raw read from chip %d [%p] at %d", chip->num,
- chip, offset);
-
- return (nand_read_pages_raw(chip, offset, buf, len));
-}
-
-static int
-nand_write_raw(struct nand_chip *chip, uint32_t offset, void *buf, uint32_t len)
-{
-
- nand_debug(NDBG_GEOM, "Raw write to chip %d [%p] at %d", chip->num,
- chip, offset);
-
- return (nand_prog_pages_raw(chip, offset, buf, len));
-}
-
-static void
-nand_strategy(struct bio *bp)
-{
- struct nand_chip *chip;
-
- chip = (struct nand_chip *)bp->bio_disk->d_drv1;
-
- bp->bio_driver1 = BIO_NAND_STD;
-
- nand_debug(NDBG_GEOM, "Strategy %s on chip %d [%p]",
- bp->bio_cmd == BIO_READ ? "READ" :
- (bp->bio_cmd == BIO_WRITE ? "WRITE" :
- (bp->bio_cmd == BIO_DELETE ? "DELETE" : "UNKNOWN")),
- chip->num, chip);
-
- mtx_lock(&chip->qlock);
- bioq_insert_tail(&chip->bioq, bp);
- mtx_unlock(&chip->qlock);
- taskqueue_enqueue(chip->tq, &chip->iotask);
-}
-
-static void
-nand_strategy_raw(struct bio *bp)
-{
- struct nand_chip *chip;
-
- chip = (struct nand_chip *)bp->bio_disk->d_drv1;
-
- /* Inform taskqueue that it's a raw access */
- bp->bio_driver1 = BIO_NAND_RAW;
-
- nand_debug(NDBG_GEOM, "Strategy %s on chip %d [%p]",
- bp->bio_cmd == BIO_READ ? "READ" :
- (bp->bio_cmd == BIO_WRITE ? "WRITE" :
- (bp->bio_cmd == BIO_DELETE ? "DELETE" : "UNKNOWN")),
- chip->num, chip);
-
- mtx_lock(&chip->qlock);
- bioq_insert_tail(&chip->bioq, bp);
- mtx_unlock(&chip->qlock);
- taskqueue_enqueue(chip->tq, &chip->iotask);
-}
-
-static int
-nand_oob_access(struct nand_chip *chip, uint32_t page, uint32_t offset,
- uint32_t len, uint8_t *data, uint8_t write)
-{
- struct chip_geom *cg;
- int ret = 0;
-
- cg = &chip->chip_geom;
-
- if (!write)
- ret = nand_read_oob(chip, page, data, cg->oob_size);
- else
- ret = nand_prog_oob(chip, page, data, cg->oob_size);
-
- return (ret);
-}
-
-static int
-nand_getattr(struct bio *bp)
-{
- struct nand_chip *chip;
- struct chip_geom *cg;
- device_t dev;
- int val;
-
- if (bp->bio_disk == NULL || bp->bio_disk->d_drv1 == NULL)
- return (ENXIO);
-
- chip = (struct nand_chip *)bp->bio_disk->d_drv1;
- cg = &(chip->chip_geom);
-
- dev = device_get_parent(chip->dev);
- dev = device_get_parent(dev);
-
- if (strcmp(bp->bio_attribute, "NAND::device") == 0) {
- if (bp->bio_length != sizeof(dev))
- return (EFAULT);
- bcopy(&dev, bp->bio_data, sizeof(dev));
- } else {
- if (strcmp(bp->bio_attribute, "NAND::oobsize") == 0)
- val = cg->oob_size;
- else if (strcmp(bp->bio_attribute, "NAND::pagesize") == 0)
- val = cg->page_size;
- else if (strcmp(bp->bio_attribute, "NAND::blocksize") == 0)
- val = cg->block_size;
- else
- return (-1);
- if (bp->bio_length != sizeof(val))
- return (EFAULT);
- bcopy(&val, bp->bio_data, sizeof(val));
- }
- bp->bio_completed = bp->bio_length;
- return (0);
-}
-
-static int
-nand_ioctl(struct disk *ndisk, u_long cmd, void *data, int fflag,
- struct thread *td)
-{
- struct nand_chip *chip;
- struct chip_geom *cg;
- struct nand_oob_rw *oob_rw = NULL;
- struct nand_raw_rw *raw_rw = NULL;
- device_t nandbus;
- size_t bufsize = 0, len = 0;
- size_t raw_size;
- off_t off;
- uint8_t *buf = NULL;
- int ret = 0;
- uint8_t status;
-
- chip = (struct nand_chip *)ndisk->d_drv1;
- cg = &chip->chip_geom;
- nandbus = device_get_parent(chip->dev);
-
- if ((cmd == NAND_IO_RAW_READ) || (cmd == NAND_IO_RAW_PROG)) {
- raw_rw = (struct nand_raw_rw *)data;
- raw_size = cg->pgs_per_blk * (cg->page_size + cg->oob_size);
-
- /* Check if len is not bigger than chip size */
- if (raw_rw->len > raw_size)
- return (EFBIG);
-
- /*
- * Do not ask for too much memory, in case of large transfers
- * read/write in 16-pages chunks
- */
- bufsize = 16 * (cg->page_size + cg->oob_size);
- if (raw_rw->len < bufsize)
- bufsize = raw_rw->len;
-
- buf = malloc(bufsize, M_NAND, M_WAITOK);
- len = raw_rw->len;
- off = 0;
- }
-
- switch (cmd) {
- case NAND_IO_ERASE:
- ret = nand_erase_blocks(chip, ((off_t *)data)[0],
- ((off_t *)data)[1]);
- break;
-
- case NAND_IO_OOB_READ:
- oob_rw = (struct nand_oob_rw *)data;
- ret = nand_oob_access(chip, oob_rw->page, 0,
- oob_rw->len, oob_rw->data, 0);
- break;
-
- case NAND_IO_OOB_PROG:
- oob_rw = (struct nand_oob_rw *)data;
- ret = nand_oob_access(chip, oob_rw->page, 0,
- oob_rw->len, oob_rw->data, 1);
- break;
-
- case NAND_IO_GET_STATUS:
- NANDBUS_LOCK(nandbus);
- ret = NANDBUS_GET_STATUS(nandbus, &status);
- if (ret == 0)
- *(uint8_t *)data = status;
- NANDBUS_UNLOCK(nandbus);
- break;
-
- case NAND_IO_RAW_PROG:
- while (len > 0) {
- if (len < bufsize)
- bufsize = len;
-
- ret = copyin(raw_rw->data + off, buf, bufsize);
- if (ret)
- break;
- ret = nand_prog_pages_raw(chip, raw_rw->off + off, buf,
- bufsize);
- if (ret)
- break;
- len -= bufsize;
- off += bufsize;
- }
- break;
-
- case NAND_IO_RAW_READ:
- while (len > 0) {
- if (len < bufsize)
- bufsize = len;
-
- ret = nand_read_pages_raw(chip, raw_rw->off + off, buf,
- bufsize);
- if (ret)
- break;
-
- ret = copyout(buf, raw_rw->data + off, bufsize);
- if (ret)
- break;
- len -= bufsize;
- off += bufsize;
- }
- break;
-
- case NAND_IO_GET_CHIP_PARAM:
- nand_get_chip_param(chip, (struct chip_param_io *)data);
- break;
-
- default:
- printf("Unknown nand_ioctl request \n");
- ret = EIO;
- }
-
- if (buf)
- free(buf, M_NAND);
-
- return (ret);
-}
-
-static void
-nand_io_proc(void *arg, int pending)
-{
- struct nand_chip *chip = arg;
- struct bio *bp;
- int err = 0;
-
- for (;;) {
- mtx_lock(&chip->qlock);
- bp = bioq_takefirst(&chip->bioq);
- mtx_unlock(&chip->qlock);
- if (bp == NULL)
- break;
-
- if (bp->bio_driver1 == BIO_NAND_STD) {
- if (bp->bio_cmd == BIO_READ) {
- err = nand_read(chip,
- bp->bio_offset & 0xffffffff,
- bp->bio_data, bp->bio_bcount);
- } else if (bp->bio_cmd == BIO_WRITE) {
- err = nand_write(chip,
- bp->bio_offset & 0xffffffff,
- bp->bio_data, bp->bio_bcount);
- }
- } else if (bp->bio_driver1 == BIO_NAND_RAW) {
- if (bp->bio_cmd == BIO_READ) {
- err = nand_read_raw(chip,
- bp->bio_offset & 0xffffffff,
- bp->bio_data, bp->bio_bcount);
- } else if (bp->bio_cmd == BIO_WRITE) {
- err = nand_write_raw(chip,
- bp->bio_offset & 0xffffffff,
- bp->bio_data, bp->bio_bcount);
- }
- } else
- panic("Unknown access type in bio->bio_driver1\n");
-
- if (bp->bio_cmd == BIO_DELETE) {
- nand_debug(NDBG_GEOM, "Delete on chip%d offset %lld "
- "length %ld\n", chip->num, bp->bio_offset,
- bp->bio_bcount);
- err = nand_erase_blocks(chip,
- bp->bio_offset & 0xffffffff,
- bp->bio_bcount);
- }
-
- if (err == 0 || err == ECC_CORRECTABLE)
- bp->bio_resid = 0;
- else {
- nand_debug(NDBG_GEOM,"nand_[read|write|erase_blocks] "
- "error: %d\n", err);
-
- bp->bio_error = EIO;
- bp->bio_flags |= BIO_ERROR;
- bp->bio_resid = bp->bio_bcount;
- }
- biodone(bp);
- }
-}
-
-int
-create_geom_disk(struct nand_chip *chip)
-{
- struct disk *ndisk, *rdisk;
-
- /* Create the disk device */
- ndisk = disk_alloc();
- ndisk->d_strategy = nand_strategy;
- ndisk->d_ioctl = nand_ioctl;
- ndisk->d_getattr = nand_getattr;
- ndisk->d_name = "gnand";
- ndisk->d_drv1 = chip;
- ndisk->d_maxsize = chip->chip_geom.block_size;
- ndisk->d_sectorsize = chip->chip_geom.page_size;
- ndisk->d_mediasize = chip->chip_geom.chip_size;
- ndisk->d_unit = chip->num +
- 10 * device_get_unit(device_get_parent(chip->dev));
-
- /*
- * When using BBT, make two last blocks of device unavailable
- * to user (because those are used to store BBT table).
- */
- if (chip->bbt != NULL)
- ndisk->d_mediasize -= (2 * chip->chip_geom.block_size);
-
- ndisk->d_flags = DISKFLAG_CANDELETE;
-
- snprintf(ndisk->d_ident, sizeof(ndisk->d_ident),
- "nand: Man:0x%02x Dev:0x%02x", chip->id.man_id, chip->id.dev_id);
- ndisk->d_rotation_rate = DISK_RR_NON_ROTATING;
-
- disk_create(ndisk, DISK_VERSION);
-
- /* Create the RAW disk device */
- rdisk = disk_alloc();
- rdisk->d_strategy = nand_strategy_raw;
- rdisk->d_ioctl = nand_ioctl;
- rdisk->d_getattr = nand_getattr;
- rdisk->d_name = "gnand.raw";
- rdisk->d_drv1 = chip;
- rdisk->d_maxsize = chip->chip_geom.block_size;
- rdisk->d_sectorsize = chip->chip_geom.page_size;
- rdisk->d_mediasize = chip->chip_geom.chip_size;
- rdisk->d_unit = chip->num +
- 10 * device_get_unit(device_get_parent(chip->dev));
-
- rdisk->d_flags = DISKFLAG_CANDELETE;
-
- snprintf(rdisk->d_ident, sizeof(rdisk->d_ident),
- "nand_raw: Man:0x%02x Dev:0x%02x", chip->id.man_id,
- chip->id.dev_id);
- rdisk->d_rotation_rate = DISK_RR_NON_ROTATING;
-
- disk_create(rdisk, DISK_VERSION);
-
- chip->ndisk = ndisk;
- chip->rdisk = rdisk;
-
- mtx_init(&chip->qlock, "NAND I/O lock", NULL, MTX_DEF);
- bioq_init(&chip->bioq);
-
- TASK_INIT(&chip->iotask, 0, nand_io_proc, chip);
- chip->tq = taskqueue_create("nand_taskq", M_WAITOK,
- taskqueue_thread_enqueue, &chip->tq);
- taskqueue_start_threads(&chip->tq, 1, PI_DISK, "nand taskq");
-
- if (bootverbose)
- device_printf(chip->dev, "Created gnand%d for chip [0x%0x, "
- "0x%0x]\n", ndisk->d_unit, chip->id.man_id,
- chip->id.dev_id);
-
- return (0);
-}
-
-void
-destroy_geom_disk(struct nand_chip *chip)
-{
- struct bio *bp;
-
- taskqueue_free(chip->tq);
- disk_destroy(chip->ndisk);
- disk_destroy(chip->rdisk);
-
- mtx_lock(&chip->qlock);
- for (;;) {
- bp = bioq_takefirst(&chip->bioq);
- if (bp == NULL)
- break;
- bp->bio_error = EIO;
- bp->bio_flags |= BIO_ERROR;
- bp->bio_resid = bp->bio_bcount;
-
- biodone(bp);
- }
- mtx_unlock(&chip->qlock);
-
- mtx_destroy(&chip->qlock);
-}
diff --git a/sys/dev/nand/nand_id.c b/sys/dev/nand/nand_id.c
deleted file mode 100644
index 7259c951bfc93..0000000000000
--- a/sys/dev/nand/nand_id.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (C) 2009-2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-
-#include <dev/nand/nand.h>
-
-struct nand_params nand_ids[] = {
- { { NAND_MAN_SAMSUNG, 0x75 }, "Samsung K9F5608U0B NAND 32MiB 8-bit",
- 0x20, 0x200, 0x10, 0x20, 0 },
- { { NAND_MAN_SAMSUNG, 0xf1 }, "Samsung K9F1G08U0A NAND 128MiB 3,3V 8-bit",
- 0x80, 0x800, 0x40, 0x40, 0 },
- { { NAND_MAN_SAMSUNG, 0xda }, "Samsung K9F2G08U0A NAND 256MiB 3,3V 8-bit",
- 0x100, 0x800, 0x40, 0x40, 0 },
- { { NAND_MAN_SAMSUNG, 0xdc }, "Samsung NAND 512MiB 3,3V 8-bit",
- 0x200, 0x800, 0x40, 0x40, 0 },
- { { NAND_MAN_SAMSUNG, 0xd3 }, "Samsung NAND 1GiB 3,3V 8-bit",
- 0x400, 0x800, 0x40, 0x40, 0 },
- { { NAND_MAN_HYNIX, 0x76 }, "Hynix NAND 64MiB 3,3V 8-bit",
- 0x40, 0x200, 0x10, 0x20, 0 },
- { { NAND_MAN_HYNIX, 0xdc }, "Hynix NAND 512MiB 3,3V 8-bit",
- 0x200, 0x800, 0x40, 0x40, 0 },
- { { NAND_MAN_HYNIX, 0x79 }, "Hynix NAND 128MB 3,3V 8-bit",
- 0x80, 0x200, 0x10, 0x20, 0 },
- { { NAND_MAN_STMICRO, 0xf1 }, "STMicro 128MB 3,3V 8-bit",
- 0x80, 2048, 64, 0x40, 0 },
- { { NAND_MAN_MICRON, 0xcc }, "Micron NAND 512MiB 3,3V 16-bit",
- 0x200, 2048, 64, 0x40, 0 },
-};
-
-struct nand_params *nand_get_params(struct nand_id *id)
-{
- int i;
-
- for (i = 0; i < nitems(nand_ids); i++)
- if (nand_ids[i].id.man_id == id->man_id &&
- nand_ids[i].id.dev_id == id->dev_id)
- return (&nand_ids[i]);
-
- return (NULL);
-}
diff --git a/sys/dev/nand/nand_if.m b/sys/dev/nand/nand_if.m
deleted file mode 100644
index 49c8879b68902..0000000000000
--- a/sys/dev/nand/nand_if.m
+++ /dev/null
@@ -1,168 +0,0 @@
-#-
-# Copyright (C) 2009-2012 Semihalf
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-# SUCH DAMAGE.
-#
-# $FreeBSD$
-
-# NAND chip interface description
-#
-
-#include <sys/bus.h>
-#include <dev/nand/nand.h>
-
-INTERFACE nand;
-
-CODE {
- static int nand_method_not_supported(device_t dev)
- {
- return (ENOENT);
- }
-};
-
-# Read NAND page
-#
-# Return values:
-# 0: Success
-#
-METHOD int read_page {
- device_t dev;
- uint32_t page;
- void* buf;
- uint32_t len;
- uint32_t offset;
-};
-
-# Program NAND page
-#
-# Return values:
-# 0: Success
-#
-METHOD int program_page {
- device_t dev;
- uint32_t page;
- void* buf;
- uint32_t len;
- uint32_t offset;
-};
-
-# Program NAND page interleaved
-#
-# Return values:
-# 0: Success
-#
-METHOD int program_page_intlv {
- device_t dev;
- uint32_t page;
- void* buf;
- uint32_t len;
- uint32_t offset;
-} DEFAULT nand_method_not_supported;
-
-# Read NAND oob
-#
-# Return values:
-# 0: Success
-#
-METHOD int read_oob {
- device_t dev;
- uint32_t page;
- void* buf;
- uint32_t len;
- uint32_t offset;
-};
-
-# Program NAND oob
-#
-# Return values:
-# 0: Success
-#
-METHOD int program_oob {
- device_t dev;
- uint32_t page;
- void* buf;
- uint32_t len;
- uint32_t offset;
-};
-
-# Erase NAND block
-#
-# Return values:
-# 0: Success
-#
-METHOD int erase_block {
- device_t dev;
- uint32_t block;
-};
-
-# Erase NAND block interleaved
-#
-# Return values:
-# 0: Success
-#
-METHOD int erase_block_intlv {
- device_t dev;
- uint32_t block;
-} DEFAULT nand_method_not_supported;
-
-# NAND get status
-#
-# Return values:
-# 0: Success
-#
-METHOD int get_status {
- device_t dev;
- uint8_t *status;
-};
-
-# NAND check if block is bad
-#
-# Return values:
-# 0: Success
-#
-METHOD int is_blk_bad {
- device_t dev;
- uint32_t block_number;
- uint8_t *bad;
-};
-
-# NAND get ECC
-#
-#
-METHOD int get_ecc {
- device_t dev;
- void *buf;
- void *ecc;
- int *needwrite;
-};
-
-# NAND correct ECC
-#
-#
-METHOD int correct_ecc {
- device_t dev;
- void *buf;
- void *readecc;
- void *calcecc;
-};
-
diff --git a/sys/dev/nand/nandbus.c b/sys/dev/nand/nandbus.c
deleted file mode 100644
index 003c1797af644..0000000000000
--- a/sys/dev/nand/nandbus.c
+++ /dev/null
@@ -1,542 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (C) 2009-2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/socket.h>
-#include <sys/malloc.h>
-#include <sys/module.h>
-#include <sys/bus.h>
-#include <sys/proc.h>
-#include <sys/lock.h>
-#include <sys/mutex.h>
-#include <sys/condvar.h>
-
-#include <dev/nand/nand.h>
-#include <dev/nand/nandbus.h>
-#include "nand_if.h"
-#include "nandbus_if.h"
-#include "nfc_if.h"
-
-#define NAND_NCS 4
-
-static int nandbus_probe(device_t dev);
-static int nandbus_attach(device_t dev);
-static int nandbus_detach(device_t dev);
-
-static int nandbus_child_location_str(device_t, device_t, char *, size_t);
-static int nandbus_child_pnpinfo_str(device_t, device_t, char *, size_t);
-
-static int nandbus_get_status(device_t, uint8_t *);
-static void nandbus_read_buffer(device_t, void *, uint32_t);
-static int nandbus_select_cs(device_t, uint8_t);
-static int nandbus_send_command(device_t, uint8_t);
-static int nandbus_send_address(device_t, uint8_t);
-static int nandbus_start_command(device_t);
-static int nandbus_wait_ready(device_t, uint8_t *);
-static void nandbus_write_buffer(device_t, void *, uint32_t);
-static int nandbus_get_ecc(device_t, void *, uint32_t, void *, int *);
-static int nandbus_correct_ecc(device_t, void *, int, void *, void *);
-static void nandbus_lock(device_t);
-static void nandbus_unlock(device_t);
-
-static int nand_readid(device_t, uint8_t *, uint8_t *);
-static int nand_probe_onfi(device_t, uint8_t *);
-static int nand_reset(device_t);
-
-struct nandbus_softc {
- device_t dev;
- struct cv nandbus_cv;
- struct mtx nandbus_mtx;
- uint8_t busy;
-};
-
-static device_method_t nandbus_methods[] = {
- /* device interface */
- DEVMETHOD(device_probe, nandbus_probe),
- DEVMETHOD(device_attach, nandbus_attach),
- DEVMETHOD(device_detach, nandbus_detach),
- DEVMETHOD(device_shutdown, bus_generic_shutdown),
-
- /* bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
- DEVMETHOD(bus_driver_added, bus_generic_driver_added),
- DEVMETHOD(bus_child_pnpinfo_str, nandbus_child_pnpinfo_str),
- DEVMETHOD(bus_child_location_str, nandbus_child_location_str),
-
- /* nandbus interface */
- DEVMETHOD(nandbus_get_status, nandbus_get_status),
- DEVMETHOD(nandbus_read_buffer, nandbus_read_buffer),
- DEVMETHOD(nandbus_select_cs, nandbus_select_cs),
- DEVMETHOD(nandbus_send_command, nandbus_send_command),
- DEVMETHOD(nandbus_send_address, nandbus_send_address),
- DEVMETHOD(nandbus_start_command,nandbus_start_command),
- DEVMETHOD(nandbus_wait_ready, nandbus_wait_ready),
- DEVMETHOD(nandbus_write_buffer, nandbus_write_buffer),
- DEVMETHOD(nandbus_get_ecc, nandbus_get_ecc),
- DEVMETHOD(nandbus_correct_ecc, nandbus_correct_ecc),
- DEVMETHOD(nandbus_lock, nandbus_lock),
- DEVMETHOD(nandbus_unlock, nandbus_unlock),
- { 0, 0 }
-};
-
-devclass_t nandbus_devclass;
-
-driver_t nandbus_driver = {
- "nandbus",
- nandbus_methods,
- sizeof(struct nandbus_softc)
-};
-
-DRIVER_MODULE(nandbus, nand, nandbus_driver, nandbus_devclass, 0, 0);
-
-int
-nandbus_create(device_t nfc)
-{
- device_t child;
-
- child = device_add_child(nfc, "nandbus", -1);
- if (!child)
- return (ENODEV);
-
- bus_generic_attach(nfc);
-
- return(0);
-}
-
-void
-nandbus_destroy(device_t nfc)
-{
- device_t *children;
- int nchildren, i;
-
- mtx_lock(&Giant);
- /* Detach & delete all children */
- if (!device_get_children(nfc, &children, &nchildren)) {
- for (i = 0; i < nchildren; i++)
- device_delete_child(nfc, children[i]);
-
- free(children, M_TEMP);
- }
- mtx_unlock(&Giant);
-}
-
-static int
-nandbus_probe(device_t dev)
-{
-
- device_set_desc(dev, "NAND bus");
-
- return (0);
-}
-
-static int
-nandbus_attach(device_t dev)
-{
- device_t child, nfc;
- struct nand_id chip_id;
- struct nandbus_softc *sc;
- struct nandbus_ivar *ivar;
- struct nand_softc *nfc_sc;
- struct nand_params *chip_params;
- uint8_t cs, onfi;
-
- sc = device_get_softc(dev);
- sc->dev = dev;
-
- nfc = device_get_parent(dev);
- nfc_sc = device_get_softc(nfc);
-
- mtx_init(&sc->nandbus_mtx, "nandbus lock", NULL, MTX_DEF);
- cv_init(&sc->nandbus_cv, "nandbus cv");
-
- /* Check each possible CS for existing nand devices */
- for (cs = 0; cs < NAND_NCS; cs++) {
- nand_debug(NDBG_BUS,"probe chip select %x", cs);
-
- /* Select & reset chip */
- if (nandbus_select_cs(dev, cs))
- break;
-
- if (nand_reset(dev))
- continue;
-
- /* Read manufacturer and device id */
- if (nand_readid(dev, &chip_id.man_id, &chip_id.dev_id))
- continue;
-
- if (chip_id.man_id == 0xff)
- continue;
-
- /*
- * First try to get info from the table. If that fails, see if
- * the chip can provide ONFI info. We check the table first to
- * allow table entries to override info from chips that are
- * known to provide bad ONFI data.
- */
- onfi = 0;
- chip_params = nand_get_params(&chip_id);
- if (chip_params == NULL) {
- nand_probe_onfi(dev, &onfi);
- }
-
- /*
- * At this point it appears there is a chip at this chipselect,
- * so if we can't work with it, whine about it.
- */
- if (chip_params == NULL && onfi == 0) {
- if (bootverbose || (nand_debug_flag & NDBG_BUS))
- printf("Chip params not found, chipsel: %d "
- "(manuf: 0x%0x, chipid: 0x%0x, onfi: %d)\n",
- cs, chip_id.man_id, chip_id.dev_id, onfi);
- continue;
- }
-
- ivar = malloc(sizeof(struct nandbus_ivar),
- M_NAND, M_WAITOK);
-
- if (onfi == 1) {
- ivar->cs = cs;
- ivar->cols = 0;
- ivar->rows = 0;
- ivar->params = NULL;
- ivar->man_id = chip_id.man_id;
- ivar->dev_id = chip_id.dev_id;
- ivar->is_onfi = onfi;
- ivar->chip_cdev_name = nfc_sc->chip_cdev_name;
-
- child = device_add_child(dev, NULL, -1);
- device_set_ivars(child, ivar);
- continue;
- }
-
- ivar->cs = cs;
- ivar->cols = 1;
- ivar->rows = 2;
- ivar->params = chip_params;
- ivar->man_id = chip_id.man_id;
- ivar->dev_id = chip_id.dev_id;
- ivar->is_onfi = onfi;
- ivar->chip_cdev_name = nfc_sc->chip_cdev_name;
-
- /*
- * Check what type of device we have.
- * devices bigger than 32MiB have on more row (3)
- */
- if (chip_params->chip_size > 32)
- ivar->rows++;
- /* Large page devices have one more col (2) */
- if (chip_params->chip_size >= 128 &&
- chip_params->page_size > 512)
- ivar->cols++;
-
- child = device_add_child(dev, NULL, -1);
- device_set_ivars(child, ivar);
- }
-
- bus_generic_attach(dev);
- return (0);
-}
-
-static int
-nandbus_detach(device_t dev)
-{
- struct nandbus_softc *sc;
-
- sc = device_get_softc(dev);
-
- bus_generic_detach(dev);
-
- mtx_destroy(&sc->nandbus_mtx);
- cv_destroy(&sc->nandbus_cv);
-
- return (0);
-}
-
-static int
-nandbus_child_location_str(device_t bus, device_t child, char *buf,
- size_t buflen)
-{
- struct nandbus_ivar *ivar = device_get_ivars(child);
-
- snprintf(buf, buflen, "at cs#%d", ivar->cs);
- return (0);
-}
-
-static int
-nandbus_child_pnpinfo_str(device_t bus, device_t child, char *buf,
- size_t buflen)
-{
- // XXX man id, model id ????
- *buf = '\0';
- return (0);
-}
-
-static int
-nand_readid(device_t bus, uint8_t *man_id, uint8_t *dev_id)
-{
- device_t nfc;
-
- if (!bus || !man_id || !dev_id)
- return (EINVAL);
-
- nand_debug(NDBG_BUS,"read id");
-
- nfc = device_get_parent(bus);
-
- if (NFC_SEND_COMMAND(nfc, NAND_CMD_READ_ID)) {
- nand_debug(NDBG_BUS,"Error : could not send READ ID command");
- return (ENXIO);
- }
-
- if (NFC_SEND_ADDRESS(nfc, 0)) {
- nand_debug(NDBG_BUS,"Error : could not sent address to chip");
- return (ENXIO);
- }
-
- if (NFC_START_COMMAND(nfc) != 0) {
- nand_debug(NDBG_BUS,"Error : could not start command");
- return (ENXIO);
- }
-
- DELAY(25);
-
- *man_id = NFC_READ_BYTE(nfc);
- *dev_id = NFC_READ_BYTE(nfc);
-
- nand_debug(NDBG_BUS,"manufacturer id: %x chip id: %x", *man_id,
- *dev_id);
-
- return (0);
-}
-
-static int
-nand_probe_onfi(device_t bus, uint8_t *onfi_compliant)
-{
- device_t nfc;
- char onfi_id[] = {'O', 'N', 'F', 'I', '\0'};
- int i;
-
- nand_debug(NDBG_BUS,"probing ONFI");
-
- nfc = device_get_parent(bus);
-
- if (NFC_SEND_COMMAND(nfc, NAND_CMD_READ_ID)) {
- nand_debug(NDBG_BUS,"Error : could not sent READ ID command");
- return (ENXIO);
- }
-
- if (NFC_SEND_ADDRESS(nfc, ONFI_SIG_ADDR)) {
- nand_debug(NDBG_BUS,"Error : could not sent address to chip");
- return (ENXIO);
- }
-
- if (NFC_START_COMMAND(nfc) != 0) {
- nand_debug(NDBG_BUS,"Error : could not start command");
- return (ENXIO);
- }
- for (i = 0; onfi_id[i] != '\0'; i++)
- if (NFC_READ_BYTE(nfc) != onfi_id[i]) {
- nand_debug(NDBG_BUS,"ONFI non-compliant");
- *onfi_compliant = 0;
- return (0);
- }
-
- nand_debug(NDBG_BUS,"ONFI compliant");
- *onfi_compliant = 1;
-
- return (0);
-}
-
-static int
-nand_reset(device_t bus)
-{
- device_t nfc;
- nand_debug(NDBG_BUS,"resetting...");
-
- nfc = device_get_parent(bus);
-
- if (NFC_SEND_COMMAND(nfc, NAND_CMD_RESET) != 0) {
- nand_debug(NDBG_BUS,"Error : could not sent RESET command");
- return (ENXIO);
- }
-
- if (NFC_START_COMMAND(nfc) != 0) {
- nand_debug(NDBG_BUS,"Error : could not start RESET command");
- return (ENXIO);
- }
-
- DELAY(1000);
-
- return (0);
-}
-
-void
-nandbus_lock(device_t dev)
-{
- struct nandbus_softc *sc;
-
- sc = device_get_softc(dev);
-
- mtx_lock(&sc->nandbus_mtx);
- if (sc->busy)
- cv_wait(&sc->nandbus_cv, &sc->nandbus_mtx);
- sc->busy = 1;
- mtx_unlock(&sc->nandbus_mtx);
-}
-
-void
-nandbus_unlock(device_t dev)
-{
- struct nandbus_softc *sc;
-
- sc = device_get_softc(dev);
-
- mtx_lock(&sc->nandbus_mtx);
- sc->busy = 0;
- cv_signal(&sc->nandbus_cv);
- mtx_unlock(&sc->nandbus_mtx);
-}
-
-int
-nandbus_select_cs(device_t dev, uint8_t cs)
-{
-
- return (NFC_SELECT_CS(device_get_parent(dev), cs));
-}
-
-int
-nandbus_send_command(device_t dev, uint8_t command)
-{
- int err;
-
- if ((err = NFC_SEND_COMMAND(device_get_parent(dev), command)))
- nand_debug(NDBG_BUS,"Err: Could not send command %x, err %x",
- command, err);
-
- return (err);
-}
-
-int
-nandbus_send_address(device_t dev, uint8_t address)
-{
- int err;
-
- if ((err = NFC_SEND_ADDRESS(device_get_parent(dev), address)))
- nand_debug(NDBG_BUS,"Err: Could not send address %x, err %x",
- address, err);
-
- return (err);
-}
-
-int
-nandbus_start_command(device_t dev)
-{
- int err;
-
- if ((err = NFC_START_COMMAND(device_get_parent(dev))))
- nand_debug(NDBG_BUS,"Err: Could not start command, err %x",
- err);
-
- return (err);
-}
-
-void
-nandbus_read_buffer(device_t dev, void *buf, uint32_t len)
-{
-
- NFC_READ_BUF(device_get_parent(dev), buf, len);
-}
-
-void
-nandbus_write_buffer(device_t dev, void *buf, uint32_t len)
-{
-
- NFC_WRITE_BUF(device_get_parent(dev), buf, len);
-}
-
-int
-nandbus_get_status(device_t dev, uint8_t *status)
-{
- int err;
-
- if ((err = NANDBUS_SEND_COMMAND(dev, NAND_CMD_STATUS)))
- return (err);
- if ((err = NANDBUS_START_COMMAND(dev)))
- return (err);
-
- *status = NFC_READ_BYTE(device_get_parent(dev));
-
- return (0);
-}
-
-int
-nandbus_wait_ready(device_t dev, uint8_t *status)
-{
- struct timeval tv, tv2;
-
- tv2.tv_sec = 0;
- tv2.tv_usec = 50 * 5000; /* 250ms */
-
- getmicrotime(&tv);
- timevaladd(&tv, &tv2);
-
- do {
- if (NANDBUS_GET_STATUS(dev, status))
- return (ENXIO);
-
- if (*status & NAND_STATUS_RDY)
- return (0);
-
- getmicrotime(&tv2);
- } while (timevalcmp(&tv2, &tv, <=));
-
- return (EBUSY);
-}
-
-int
-nandbus_get_ecc(device_t dev, void *buf, uint32_t pagesize, void *ecc,
- int *needwrite)
-{
-
- return (NFC_GET_ECC(device_get_parent(dev), buf, pagesize, ecc, needwrite));
-}
-
-int
-nandbus_correct_ecc(device_t dev, void *buf, int pagesize, void *readecc,
- void *calcecc)
-{
-
- return (NFC_CORRECT_ECC(device_get_parent(dev), buf, pagesize,
- readecc, calcecc));
-}
-
diff --git a/sys/dev/nand/nandbus.h b/sys/dev/nand/nandbus.h
deleted file mode 100644
index 6dd4cbf26daa8..0000000000000
--- a/sys/dev/nand/nandbus.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (C) 2009-2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef _NANDBUS_H_
-#define _NANDBUS_H_
-
-struct nandbus_ivar {
- uint8_t cs;
- uint8_t cols;
- uint8_t rows;
- uint8_t man_id;
- uint8_t dev_id;
- uint8_t is_onfi;
- char *chip_cdev_name;
- struct nand_params *params;
-};
-
-extern devclass_t nandbus_devclass;
-extern driver_t nandbus_driver;
-
-int nandbus_create(device_t nfc);
-void nandbus_destroy(device_t nfc);
-
-#endif /* _NANDBUS_H_ */
diff --git a/sys/dev/nand/nandbus_if.m b/sys/dev/nand/nandbus_if.m
deleted file mode 100644
index e914e18de6616..0000000000000
--- a/sys/dev/nand/nandbus_if.m
+++ /dev/null
@@ -1,100 +0,0 @@
-#-
-# Copyright (C) 2009-2012 Semihalf
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-# SUCH DAMAGE.
-#
-# $FreeBSD$
-
-# NAND bus interface description
-#
-
-#include <sys/bus.h>
-#include <dev/nand/nand.h>
-
-INTERFACE nandbus;
-
-METHOD int get_status {
- device_t dev;
- uint8_t * status;
-};
-
-METHOD void read_buffer {
- device_t dev;
- void * buf;
- uint32_t len;
-};
-
-METHOD int select_cs {
- device_t dev;
- uint8_t cs;
-};
-
-METHOD int send_command {
- device_t dev;
- uint8_t command;
-};
-
-METHOD int send_address {
- device_t dev;
- uint8_t address;
-};
-
-METHOD int start_command {
- device_t dev;
-};
-
-METHOD int wait_ready {
- device_t dev;
- uint8_t * status;
-}
-
-METHOD void write_buffer {
- device_t dev;
- void * buf;
- uint32_t len;
-};
-
-METHOD int get_ecc {
- device_t dev;
- void * buf;
- uint32_t pagesize;
- void * ecc;
- int * needwrite;
-};
-
-METHOD int correct_ecc {
- device_t dev;
- void * buf;
- int pagesize;
- void * readecc;
- void * calcecc;
-};
-
-METHOD void lock {
- device_t dev;
-};
-
-METHOD void unlock {
- device_t dev;
-};
-
diff --git a/sys/dev/nand/nandsim.c b/sys/dev/nand/nandsim.c
deleted file mode 100644
index 4639a15700a20..0000000000000
--- a/sys/dev/nand/nandsim.c
+++ /dev/null
@@ -1,670 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (C) 2009-2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/* Simulated NAND controller driver */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/proc.h>
-#include <sys/bus.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-#include <sys/malloc.h>
-
-#include <dev/nand/nand.h>
-#include <dev/nand/nandsim.h>
-#include <dev/nand/nandsim_chip.h>
-#include <dev/nand/nandsim_log.h>
-#include <dev/nand/nandsim_swap.h>
-
-struct sim_param sim;
-struct sim_ctrl_conf ctrls[MAX_SIM_DEV];
-
-static struct cdev *nandsim_dev;
-static d_ioctl_t nandsim_ioctl;
-
-static void nandsim_init_sim_param(struct sim_param *);
-static int nandsim_create_ctrl(struct sim_ctrl *);
-static int nandsim_destroy_ctrl(int);
-static int nandsim_ctrl_status(struct sim_ctrl *);
-static int nandsim_create_chip(struct sim_chip *);
-static int nandsim_destroy_chip(struct sim_ctrl_chip *);
-static int nandsim_chip_status(struct sim_chip *);
-static int nandsim_start_ctrl(int);
-static int nandsim_stop_ctrl(int);
-static int nandsim_inject_error(struct sim_error *);
-static int nandsim_get_block_state(struct sim_block_state *);
-static int nandsim_set_block_state(struct sim_block_state *);
-static int nandsim_modify(struct sim_mod *);
-static int nandsim_dump(struct sim_dump *);
-static int nandsim_restore(struct sim_dump *);
-static int nandsim_freeze(struct sim_ctrl_chip *);
-static void nandsim_print_log(struct sim_log *);
-static struct nandsim_chip *get_nandsim_chip(uint8_t, uint8_t);
-
-static struct cdevsw nandsim_cdevsw = {
- .d_version = D_VERSION,
- .d_flags = D_NEEDGIANT,
- .d_ioctl = nandsim_ioctl,
- .d_name = "nandsim",
-};
-
-int
-nandsim_ioctl(struct cdev *dev, u_long cmd, caddr_t data,
- int flags, struct thread *td)
-{
- int ret = 0;
-
- switch (cmd) {
- case NANDSIM_SIM_PARAM:
- nandsim_init_sim_param((struct sim_param *)data);
- break;
- case NANDSIM_CREATE_CTRL:
- ret = nandsim_create_ctrl((struct sim_ctrl *)data);
- break;
- case NANDSIM_DESTROY_CTRL:
- ret = nandsim_destroy_ctrl(*(int *)data);
- break;
- case NANDSIM_STATUS_CTRL:
- ret = nandsim_ctrl_status((struct sim_ctrl *)data);
- break;
- case NANDSIM_CREATE_CHIP:
- ret = nandsim_create_chip((struct sim_chip *)data);
- break;
- case NANDSIM_DESTROY_CHIP:
- ret = nandsim_destroy_chip((struct sim_ctrl_chip *)data);
- break;
- case NANDSIM_STATUS_CHIP:
- ret = nandsim_chip_status((struct sim_chip *)data);
- break;
- case NANDSIM_MODIFY:
- ret = nandsim_modify((struct sim_mod *)data);
- break;
- case NANDSIM_START_CTRL:
- ret = nandsim_start_ctrl(*(int *)data);
- break;
- case NANDSIM_STOP_CTRL:
- ret = nandsim_stop_ctrl(*(int *)data);
- break;
- case NANDSIM_INJECT_ERROR:
- ret = nandsim_inject_error((struct sim_error *)data);
- break;
- case NANDSIM_SET_BLOCK_STATE:
- ret = nandsim_set_block_state((struct sim_block_state *)data);
- break;
- case NANDSIM_GET_BLOCK_STATE:
- ret = nandsim_get_block_state((struct sim_block_state *)data);
- break;
- case NANDSIM_PRINT_LOG:
- nandsim_print_log((struct sim_log *)data);
- break;
- case NANDSIM_DUMP:
- ret = nandsim_dump((struct sim_dump *)data);
- break;
- case NANDSIM_RESTORE:
- ret = nandsim_restore((struct sim_dump *)data);
- break;
- case NANDSIM_FREEZE:
- ret = nandsim_freeze((struct sim_ctrl_chip *)data);
- break;
- default:
- ret = EINVAL;
- break;
- }
-
- return (ret);
-}
-
-static void
-nandsim_init_sim_param(struct sim_param *param)
-{
-
- if (!param)
- return;
-
- nand_debug(NDBG_SIM,"log level:%d output %d", param->log_level,
- param->log_output);
- nandsim_log_level = param->log_level;
- nandsim_log_output = param->log_output;
-}
-
-static int
-nandsim_create_ctrl(struct sim_ctrl *ctrl)
-{
- struct sim_ctrl_conf *sim_ctrl;
-
- nand_debug(NDBG_SIM,"create controller num:%d cs:%d",ctrl->num,
- ctrl->num_cs);
-
- if (ctrl->num >= MAX_SIM_DEV) {
- return (EINVAL);
- }
-
- sim_ctrl = &ctrls[ctrl->num];
- if(sim_ctrl->created)
- return (EEXIST);
-
- sim_ctrl->num = ctrl->num;
- sim_ctrl->num_cs = ctrl->num_cs;
- sim_ctrl->ecc = ctrl->ecc;
- memcpy(sim_ctrl->ecc_layout, ctrl->ecc_layout,
- MAX_ECC_BYTES * sizeof(ctrl->ecc_layout[0]));
- strlcpy(sim_ctrl->filename, ctrl->filename,
- FILENAME_SIZE);
- sim_ctrl->created = 1;
-
- return (0);
-}
-
-static int
-nandsim_destroy_ctrl(int ctrl_num)
-{
-
- nand_debug(NDBG_SIM,"destroy controller num:%d", ctrl_num);
-
- if (ctrl_num >= MAX_SIM_DEV) {
- return (EINVAL);
- }
-
- if (!ctrls[ctrl_num].created) {
- return (ENODEV);
- }
-
- if (ctrls[ctrl_num].running) {
- return (EBUSY);
- }
-
- memset(&ctrls[ctrl_num], 0, sizeof(ctrls[ctrl_num]));
-
- return (0);
-}
-
-static int
-nandsim_ctrl_status(struct sim_ctrl *ctrl)
-{
-
- nand_debug(NDBG_SIM,"status controller num:%d cs:%d",ctrl->num,
- ctrl->num_cs);
-
- if (ctrl->num >= MAX_SIM_DEV) {
- return (EINVAL);
- }
-
- ctrl->num_cs = ctrls[ctrl->num].num_cs;
- ctrl->ecc = ctrls[ctrl->num].ecc;
- memcpy(ctrl->ecc_layout, ctrls[ctrl->num].ecc_layout,
- MAX_ECC_BYTES * sizeof(ctrl->ecc_layout[0]));
- strlcpy(ctrl->filename, ctrls[ctrl->num].filename,
- FILENAME_SIZE);
- ctrl->running = ctrls[ctrl->num].running;
- ctrl->created = ctrls[ctrl->num].created;
-
- return (0);
-}
-
-static int
-nandsim_create_chip(struct sim_chip *chip)
-{
- struct sim_chip *sim_chip;
-
- nand_debug(NDBG_SIM,"create chip num:%d at ctrl:%d", chip->num,
- chip->ctrl_num);
-
- if (chip->ctrl_num >= MAX_SIM_DEV ||
- chip->num >= MAX_CTRL_CS) {
- return (EINVAL);
- }
-
- if (ctrls[chip->ctrl_num].chips[chip->num]) {
- return (EEXIST);
- }
-
- sim_chip = malloc(sizeof(*sim_chip), M_NANDSIM,
- M_WAITOK);
- if (sim_chip == NULL) {
- return (ENOMEM);
- }
-
- memcpy(sim_chip, chip, sizeof(*sim_chip));
- ctrls[chip->ctrl_num].chips[chip->num] = sim_chip;
- sim_chip->created = 1;
-
- return (0);
-}
-
-static int
-nandsim_destroy_chip(struct sim_ctrl_chip *chip)
-{
- struct sim_ctrl_conf *ctrl_conf;
-
- nand_debug(NDBG_SIM,"destroy chip num:%d at ctrl:%d", chip->chip_num,
- chip->ctrl_num);
-
- if (chip->ctrl_num >= MAX_SIM_DEV ||
- chip->chip_num >= MAX_CTRL_CS)
- return (EINVAL);
-
- ctrl_conf = &ctrls[chip->ctrl_num];
-
- if (!ctrl_conf->created || !ctrl_conf->chips[chip->chip_num])
- return (ENODEV);
-
- if (ctrl_conf->running)
- return (EBUSY);
-
- free(ctrl_conf->chips[chip->chip_num], M_NANDSIM);
- ctrl_conf->chips[chip->chip_num] = NULL;
-
- return (0);
-}
-
-static int
-nandsim_chip_status(struct sim_chip *chip)
-{
- struct sim_ctrl_conf *ctrl_conf;
-
- nand_debug(NDBG_SIM,"status for chip num:%d at ctrl:%d", chip->num,
- chip->ctrl_num);
-
- if (chip->ctrl_num >= MAX_SIM_DEV &&
- chip->num >= MAX_CTRL_CS)
- return (EINVAL);
-
- ctrl_conf = &ctrls[chip->ctrl_num];
- if (!ctrl_conf->chips[chip->num])
- chip->created = 0;
- else
- memcpy(chip, ctrl_conf->chips[chip->num], sizeof(*chip));
-
- return (0);
-}
-
-static int
-nandsim_start_ctrl(int num)
-{
- device_t nexus, ndev;
- devclass_t nexus_devclass;
- int ret = 0;
-
- nand_debug(NDBG_SIM,"start ctlr num:%d", num);
-
- if (num >= MAX_SIM_DEV)
- return (EINVAL);
-
- if (!ctrls[num].created)
- return (ENODEV);
-
- if (ctrls[num].running)
- return (EBUSY);
-
- /* We will add our device as a child of the nexus0 device */
- if (!(nexus_devclass = devclass_find("nexus")) ||
- !(nexus = devclass_get_device(nexus_devclass, 0)))
- return (EFAULT);
-
- /*
- * Create a newbus device representing this frontend instance
- *
- * XXX powerpc nexus doesn't implement bus_add_child, so child
- * must be added by device_add_child().
- */
-#if defined(__powerpc__)
- ndev = device_add_child(nexus, "nandsim", num);
-#else
- ndev = BUS_ADD_CHILD(nexus, 0, "nandsim", num);
-#endif
- if (!ndev)
- return (EFAULT);
-
- mtx_lock(&Giant);
- ret = device_probe_and_attach(ndev);
- mtx_unlock(&Giant);
-
- if (ret == 0) {
- ctrls[num].sim_ctrl_dev = ndev;
- ctrls[num].running = 1;
- }
-
- return (ret);
-}
-
-static int
-nandsim_stop_ctrl(int num)
-{
- device_t nexus;
- devclass_t nexus_devclass;
- int ret = 0;
-
- nand_debug(NDBG_SIM,"stop controller num:%d", num);
-
- if (num >= MAX_SIM_DEV) {
- return (EINVAL);
- }
-
- if (!ctrls[num].created || !ctrls[num].running) {
- return (ENODEV);
- }
-
- /* We will add our device as a child of the nexus0 device */
- if (!(nexus_devclass = devclass_find("nexus")) ||
- !(nexus = devclass_get_device(nexus_devclass, 0))) {
- return (ENODEV);
- }
-
- mtx_lock(&Giant);
- if (ctrls[num].sim_ctrl_dev) {
- ret = device_delete_child(nexus, ctrls[num].sim_ctrl_dev);
- ctrls[num].sim_ctrl_dev = NULL;
- }
- mtx_unlock(&Giant);
-
- ctrls[num].running = 0;
-
- return (ret);
-}
-
-static struct nandsim_chip *
-get_nandsim_chip(uint8_t ctrl_num, uint8_t chip_num)
-{
- struct nandsim_softc *sc;
-
- if (!ctrls[ctrl_num].sim_ctrl_dev)
- return (NULL);
-
- sc = device_get_softc(ctrls[ctrl_num].sim_ctrl_dev);
- return (sc->chips[chip_num]);
-}
-
-static void
-nandsim_print_log(struct sim_log *sim_log)
-{
- struct nandsim_softc *sc;
- int len1, len2;
-
- if (!ctrls[sim_log->ctrl_num].sim_ctrl_dev)
- return;
-
- sc = device_get_softc(ctrls[sim_log->ctrl_num].sim_ctrl_dev);
- if (sc->log_buff) {
- len1 = strlen(&sc->log_buff[sc->log_idx + 1]);
- if (len1 >= sim_log->len)
- len1 = sim_log->len;
- copyout(&sc->log_buff[sc->log_idx + 1], sim_log->log, len1);
- len2 = strlen(sc->log_buff);
- if (len2 >= (sim_log->len - len1))
- len2 = (sim_log->len - len1);
- copyout(sc->log_buff, &sim_log->log[len1], len2);
- sim_log->len = len1 + len2;
- }
-}
-
-static int
-nandsim_inject_error(struct sim_error *error)
-{
- struct nandsim_chip *chip;
- struct block_space *bs;
- struct onfi_params *param;
- int page, page_size, block, offset;
-
- nand_debug(NDBG_SIM,"inject error for chip %d at ctrl %d\n",
- error->chip_num, error->ctrl_num);
-
- if (error->ctrl_num >= MAX_SIM_DEV ||
- error->chip_num >= MAX_CTRL_CS)
- return (EINVAL);
-
- if (!ctrls[error->ctrl_num].created || !ctrls[error->ctrl_num].running)
- return (ENODEV);
-
- chip = get_nandsim_chip(error->ctrl_num, error->chip_num);
- param = &chip->params;
- page_size = param->bytes_per_page + param->spare_bytes_per_page;
- block = error->page_num / param->pages_per_block;
- page = error->page_num % param->pages_per_block;
-
- bs = get_bs(chip->swap, block, 1);
- if (!bs)
- return (EINVAL);
-
- offset = (page * page_size) + error->column;
- memset(&bs->blk_ptr[offset], error->pattern, error->len);
-
- return (0);
-}
-
-static int
-nandsim_set_block_state(struct sim_block_state *bs)
-{
- struct onfi_params *params;
- struct nandsim_chip *chip;
- int blocks;
-
- nand_debug(NDBG_SIM,"set block state for %d:%d block %d\n",
- bs->chip_num, bs->ctrl_num, bs->block_num);
-
- if (bs->ctrl_num >= MAX_SIM_DEV ||
- bs->chip_num >= MAX_CTRL_CS)
- return (EINVAL);
-
- chip = get_nandsim_chip(bs->ctrl_num, bs->chip_num);
- params = &chip->params;
- blocks = params->luns * params->blocks_per_lun;
-
- if (bs->block_num > blocks)
- return (EINVAL);
-
- chip->blk_state[bs->block_num].is_bad = bs->state;
-
- if (bs->wearout >= 0)
- chip->blk_state[bs->block_num].wear_lev = bs->wearout;
-
- return (0);
-}
-
-static int
-nandsim_get_block_state(struct sim_block_state *bs)
-{
- struct onfi_params *params;
- struct nandsim_chip *chip;
- int blocks;
-
- if (bs->ctrl_num >= MAX_SIM_DEV ||
- bs->chip_num >= MAX_CTRL_CS)
- return (EINVAL);
-
- nand_debug(NDBG_SIM,"get block state for %d:%d block %d\n",
- bs->chip_num, bs->ctrl_num, bs->block_num);
-
- chip = get_nandsim_chip(bs->ctrl_num, bs->chip_num);
- params = &chip->params;
- blocks = params->luns * params->blocks_per_lun;
-
- if (bs->block_num > blocks)
- return (EINVAL);
-
- bs->state = chip->blk_state[bs->block_num].is_bad;
- bs->wearout = chip->blk_state[bs->block_num].wear_lev;
-
- return (0);
-}
-
-static int
-nandsim_dump(struct sim_dump *dump)
-{
- struct nandsim_chip *chip;
- struct block_space *bs;
- int blk_size;
-
- nand_debug(NDBG_SIM,"dump chip %d %d\n", dump->ctrl_num, dump->chip_num);
-
- if (dump->ctrl_num >= MAX_SIM_DEV ||
- dump->chip_num >= MAX_CTRL_CS)
- return (EINVAL);
-
- chip = get_nandsim_chip(dump->ctrl_num, dump->chip_num);
- blk_size = chip->cg.block_size +
- (chip->cg.oob_size * chip->cg.pgs_per_blk);
-
- bs = get_bs(chip->swap, dump->block_num, 0);
- if (!bs)
- return (EINVAL);
-
- if (dump->len > blk_size)
- dump->len = blk_size;
-
- copyout(bs->blk_ptr, dump->data, dump->len);
-
- return (0);
-}
-
-static int
-nandsim_restore(struct sim_dump *dump)
-{
- struct nandsim_chip *chip;
- struct block_space *bs;
- int blk_size;
-
- nand_debug(NDBG_SIM,"restore chip %d %d\n", dump->ctrl_num,
- dump->chip_num);
-
- if (dump->ctrl_num >= MAX_SIM_DEV ||
- dump->chip_num >= MAX_CTRL_CS)
- return (EINVAL);
-
- chip = get_nandsim_chip(dump->ctrl_num, dump->chip_num);
- blk_size = chip->cg.block_size +
- (chip->cg.oob_size * chip->cg.pgs_per_blk);
-
- bs = get_bs(chip->swap, dump->block_num, 1);
- if (!bs)
- return (EINVAL);
-
- if (dump->len > blk_size)
- dump->len = blk_size;
-
-
- copyin(dump->data, bs->blk_ptr, dump->len);
-
- return (0);
-}
-
-static int
-nandsim_freeze(struct sim_ctrl_chip *ctrl_chip)
-{
- struct nandsim_chip *chip;
-
- if (ctrl_chip->ctrl_num >= MAX_SIM_DEV ||
- ctrl_chip->chip_num >= MAX_CTRL_CS)
- return (EINVAL);
-
- chip = get_nandsim_chip(ctrl_chip->ctrl_num, ctrl_chip->chip_num);
- nandsim_chip_freeze(chip);
-
- return (0);
-}
-
-static int
-nandsim_modify(struct sim_mod *mod)
-{
- struct sim_chip *sim_conf = NULL;
- struct nandsim_chip *sim_chip = NULL;
-
- nand_debug(NDBG_SIM,"modify ctlr %d chip %d", mod->ctrl_num,
- mod->chip_num);
-
- if (mod->field != SIM_MOD_LOG_LEVEL) {
- if (mod->ctrl_num >= MAX_SIM_DEV ||
- mod->chip_num >= MAX_CTRL_CS)
- return (EINVAL);
-
- sim_conf = ctrls[mod->ctrl_num].chips[mod->chip_num];
- sim_chip = get_nandsim_chip(mod->ctrl_num, mod->chip_num);
- }
-
- switch (mod->field) {
- case SIM_MOD_LOG_LEVEL:
- nandsim_log_level = mod->new_value;
- break;
- case SIM_MOD_ERASE_TIME:
- sim_conf->erase_time = sim_chip->erase_delay = mod->new_value;
- break;
- case SIM_MOD_PROG_TIME:
- sim_conf->prog_time = sim_chip->prog_delay = mod->new_value;
- break;
- case SIM_MOD_READ_TIME:
- sim_conf->read_time = sim_chip->read_delay = mod->new_value;
- break;
- case SIM_MOD_ERROR_RATIO:
- sim_conf->error_ratio = mod->new_value;
- sim_chip->error_ratio = mod->new_value;
- break;
- default:
- break;
- }
-
- return (0);
-}
-static int
-nandsim_modevent(module_t mod __unused, int type, void *data __unused)
-{
- struct sim_ctrl_chip chip_ctrl;
- int i, j;
-
- switch (type) {
- case MOD_LOAD:
- nandsim_dev = make_dev(&nandsim_cdevsw, 0,
- UID_ROOT, GID_WHEEL, 0600, "nandsim.ioctl");
- break;
- case MOD_UNLOAD:
- for (i = 0; i < MAX_SIM_DEV; i++) {
- nandsim_stop_ctrl(i);
- chip_ctrl.ctrl_num = i;
- for (j = 0; j < MAX_CTRL_CS; j++) {
- chip_ctrl.chip_num = j;
- nandsim_destroy_chip(&chip_ctrl);
- }
- nandsim_destroy_ctrl(i);
- }
- destroy_dev(nandsim_dev);
- break;
- case MOD_SHUTDOWN:
- break;
- default:
- return (EOPNOTSUPP);
- }
- return (0);
-}
-
-DEV_MODULE(nandsim, nandsim_modevent, NULL);
-MODULE_VERSION(nandsim, 1);
-MODULE_DEPEND(nandsim, nand, 1, 1, 1);
-MODULE_DEPEND(nandsim, alq, 1, 1, 1);
diff --git a/sys/dev/nand/nandsim.h b/sys/dev/nand/nandsim.h
deleted file mode 100644
index d4b225113bfd6..0000000000000
--- a/sys/dev/nand/nandsim.h
+++ /dev/null
@@ -1,177 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (C) 2009-2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef _NANDSIM_H_
-#define _NANDSIM_H_
-
-#include <sys/ioccom.h>
-#include <sys/types.h>
-
-#define MAX_SIM_DEV 4
-#define MAX_CTRL_CS 4
-#define MAX_ECC_BYTES 512
-#define MAX_BAD_BLOCKS 512
-#define DEV_MODEL_STR_SIZE 21
-#define MAN_STR_SIZE 13
-#define FILENAME_SIZE 20
-
-#define MAX_CHIPS (MAX_SIM_DEV*MAX_CTRL_CS)
-
-#define NANDSIM_OUTPUT_NONE 0x0
-#define NANDSIM_OUTPUT_CONSOLE 0x1
-#define NANDSIM_OUTPUT_RAM 0x2
-#define NANDSIM_OUTPUT_FILE 0x3
-
-struct sim_ctrl_chip {
- uint8_t ctrl_num;
- uint8_t chip_num;
-};
-
-#define NANDSIM_BASE 'A'
-
-struct sim_param {
- uint8_t log_level;
- uint8_t log_output;
-};
-
-#define NANDSIM_SIM_PARAM _IOW(NANDSIM_BASE, 1, struct sim_param)
-
-struct sim_ctrl {
- uint8_t running;
- uint8_t created;
- uint8_t num;
- uint8_t num_cs;
- uint8_t ecc;
- char filename[FILENAME_SIZE];
- uint16_t ecc_layout[MAX_ECC_BYTES];
-};
-#define NANDSIM_CREATE_CTRL _IOW(NANDSIM_BASE, 2, struct sim_ctrl)
-#define NANDSIM_DESTROY_CTRL _IOW(NANDSIM_BASE, 3, int)
-
-struct sim_chip {
- uint8_t num;
- uint8_t ctrl_num;
- uint8_t created;
- uint8_t device_id;
- uint8_t manufact_id;
- char device_model[DEV_MODEL_STR_SIZE];
- char manufacturer[MAN_STR_SIZE];
- uint8_t col_addr_cycles;
- uint8_t row_addr_cycles;
- uint8_t features;
- uint8_t width;
- uint32_t page_size;
- uint32_t oob_size;
- uint32_t pgs_per_blk;
- uint32_t blks_per_lun;
- uint32_t luns;
-
- uint32_t prog_time;
- uint32_t erase_time;
- uint32_t read_time;
- uint32_t ccs_time;
-
- uint32_t error_ratio;
- uint32_t wear_level;
- uint32_t bad_block_map[MAX_BAD_BLOCKS];
- uint8_t is_wp;
-};
-
-#define NANDSIM_CREATE_CHIP _IOW(NANDSIM_BASE, 3, struct sim_chip)
-
-struct sim_chip_destroy {
- uint8_t ctrl_num;
- uint8_t chip_num;
-};
-#define NANDSIM_DESTROY_CHIP _IOW(NANDSIM_BASE, 4, struct sim_chip_destroy)
-
-#define NANDSIM_START_CTRL _IOW(NANDSIM_BASE, 5, int)
-#define NANDSIM_STOP_CTRL _IOW(NANDSIM_BASE, 6, int)
-#define NANDSIM_RESTART_CTRL _IOW(NANDSIM_BASE, 7, int)
-
-#define NANDSIM_STATUS_CTRL _IOWR(NANDSIM_BASE, 8, struct sim_ctrl)
-#define NANDSIM_STATUS_CHIP _IOWR(NANDSIM_BASE, 9, struct sim_chip)
-
-struct sim_mod {
- uint8_t chip_num;
- uint8_t ctrl_num;
- uint32_t field;
- uint32_t new_value;
-};
-#define SIM_MOD_LOG_LEVEL 0
-#define SIM_MOD_ERASE_TIME 1
-#define SIM_MOD_PROG_TIME 2
-#define SIM_MOD_READ_TIME 3
-#define SIM_MOD_CCS_TIME 4
-#define SIM_MOD_ERROR_RATIO 5
-
-#define NANDSIM_MODIFY _IOW(NANDSIM_BASE, 10, struct sim_mod)
-#define NANDSIM_FREEZE _IOW(NANDSIM_BASE, 11, struct sim_ctrl_chip)
-
-struct sim_error {
- uint8_t ctrl_num;
- uint8_t chip_num;
- uint32_t page_num;
- uint32_t column;
- uint32_t len;
- uint32_t pattern;
-};
-#define NANDSIM_INJECT_ERROR _IOW(NANDSIM_BASE, 20, struct sim_error)
-
-#define NANDSIM_GOOD_BLOCK 0
-#define NANDSIM_BAD_BLOCK 1
-struct sim_block_state {
- uint8_t ctrl_num;
- uint8_t chip_num;
- uint32_t block_num;
- int wearout;
- uint8_t state;
-};
-#define NANDSIM_SET_BLOCK_STATE _IOW(NANDSIM_BASE, 21, struct sim_block_state)
-#define NANDSIM_GET_BLOCK_STATE _IOWR(NANDSIM_BASE, 22, struct sim_block_state)
-
-struct sim_log {
- uint8_t ctrl_num;
- char* log;
- size_t len;
-};
-#define NANDSIM_PRINT_LOG _IOWR(NANDSIM_BASE, 23, struct sim_log)
-
-struct sim_dump {
- uint8_t ctrl_num;
- uint8_t chip_num;
- uint32_t block_num;
- uint32_t len;
- void* data;
-};
-#define NANDSIM_DUMP _IOWR(NANDSIM_BASE, 24, struct sim_dump)
-#define NANDSIM_RESTORE _IOWR(NANDSIM_BASE, 25, struct sim_dump)
-
-#endif /* _NANDSIM_H_ */
diff --git a/sys/dev/nand/nandsim_chip.c b/sys/dev/nand/nandsim_chip.c
deleted file mode 100644
index b7ab83b9d2083..0000000000000
--- a/sys/dev/nand/nandsim_chip.c
+++ /dev/null
@@ -1,898 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (C) 2009-2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/module.h>
-#include <sys/mutex.h>
-#include <sys/proc.h>
-#include <sys/sched.h>
-#include <sys/kthread.h>
-#include <sys/unistd.h>
-
-#include <dev/nand/nand.h>
-#include <dev/nand/nandsim_chip.h>
-#include <dev/nand/nandsim_log.h>
-#include <dev/nand/nandsim_swap.h>
-
-MALLOC_DEFINE(M_NANDSIM, "NANDsim", "NANDsim dynamic data");
-
-#define NANDSIM_CHIP_LOCK(chip) mtx_lock(&(chip)->ns_lock)
-#define NANDSIM_CHIP_UNLOCK(chip) mtx_unlock(&(chip)->ns_lock)
-
-static nandsim_evh_t erase_evh;
-static nandsim_evh_t idle_evh;
-static nandsim_evh_t poweron_evh;
-static nandsim_evh_t reset_evh;
-static nandsim_evh_t read_evh;
-static nandsim_evh_t readid_evh;
-static nandsim_evh_t readparam_evh;
-static nandsim_evh_t write_evh;
-
-static void nandsim_loop(void *);
-static void nandsim_undefined(struct nandsim_chip *, uint8_t);
-static void nandsim_bad_address(struct nandsim_chip *, uint8_t *);
-static void nandsim_ignore_address(struct nandsim_chip *, uint8_t);
-static void nandsim_sm_error(struct nandsim_chip *);
-static void nandsim_start_handler(struct nandsim_chip *, nandsim_evh_t);
-
-static void nandsim_callout_eh(void *);
-static int nandsim_delay(struct nandsim_chip *, int);
-
-static int nandsim_bbm_init(struct nandsim_chip *, uint32_t, uint32_t *);
-static int nandsim_blk_state_init(struct nandsim_chip *, uint32_t, uint32_t);
-static void nandsim_blk_state_destroy(struct nandsim_chip *);
-static int nandchip_is_block_valid(struct nandsim_chip *, int);
-
-static void nandchip_set_status(struct nandsim_chip *, uint8_t);
-static void nandchip_clear_status(struct nandsim_chip *, uint8_t);
-
-struct proc *nandsim_proc;
-
-struct nandsim_chip *
-nandsim_chip_init(struct nandsim_softc* sc, uint8_t chip_num,
- struct sim_chip *sim_chip)
-{
- struct nandsim_chip *chip;
- struct onfi_params *chip_param;
- char swapfile[20];
- uint32_t size;
- int error;
-
- chip = malloc(sizeof(*chip), M_NANDSIM, M_WAITOK | M_ZERO);
-
- mtx_init(&chip->ns_lock, "nandsim lock", NULL, MTX_DEF);
- callout_init(&chip->ns_callout, 1);
- STAILQ_INIT(&chip->nandsim_events);
-
- chip->chip_num = chip_num;
- chip->ctrl_num = sim_chip->ctrl_num;
- chip->sc = sc;
-
- if (!sim_chip->is_wp)
- nandchip_set_status(chip, NAND_STATUS_WP);
-
- chip_param = &chip->params;
-
- chip->id.dev_id = sim_chip->device_id;
- chip->id.man_id = sim_chip->manufact_id;
-
- chip->error_ratio = sim_chip->error_ratio;
- chip->wear_level = sim_chip->wear_level;
- chip->prog_delay = sim_chip->prog_time;
- chip->erase_delay = sim_chip->erase_time;
- chip->read_delay = sim_chip->read_time;
-
- chip_param->t_prog = sim_chip->prog_time;
- chip_param->t_bers = sim_chip->erase_time;
- chip_param->t_r = sim_chip->read_time;
- bcopy("onfi", &chip_param->signature, 4);
-
- chip_param->manufacturer_id = sim_chip->manufact_id;
- strncpy(chip_param->manufacturer_name, sim_chip->manufacturer, 12);
- chip_param->manufacturer_name[11] = 0;
- strncpy(chip_param->device_model, sim_chip->device_model, 20);
- chip_param->device_model[19] = 0;
-
- chip_param->bytes_per_page = sim_chip->page_size;
- chip_param->spare_bytes_per_page = sim_chip->oob_size;
- chip_param->pages_per_block = sim_chip->pgs_per_blk;
- chip_param->blocks_per_lun = sim_chip->blks_per_lun;
- chip_param->luns = sim_chip->luns;
-
- init_chip_geom(&chip->cg, chip_param->luns, chip_param->blocks_per_lun,
- chip_param->pages_per_block, chip_param->bytes_per_page,
- chip_param->spare_bytes_per_page);
-
- chip_param->address_cycles = sim_chip->row_addr_cycles |
- (sim_chip->col_addr_cycles << 4);
- chip_param->features = sim_chip->features;
- if (sim_chip->width == 16)
- chip_param->features |= ONFI_FEAT_16BIT;
-
- size = chip_param->blocks_per_lun * chip_param->luns;
-
- error = nandsim_blk_state_init(chip, size, sim_chip->wear_level);
- if (error) {
- mtx_destroy(&chip->ns_lock);
- free(chip, M_NANDSIM);
- return (NULL);
- }
-
- error = nandsim_bbm_init(chip, size, sim_chip->bad_block_map);
- if (error) {
- mtx_destroy(&chip->ns_lock);
- nandsim_blk_state_destroy(chip);
- free(chip, M_NANDSIM);
- return (NULL);
- }
-
- nandsim_start_handler(chip, poweron_evh);
-
- nand_debug(NDBG_SIM,"Create thread for chip%d [%8p]", chip->chip_num,
- chip);
- /* Create chip thread */
- error = kproc_kthread_add(nandsim_loop, chip, &nandsim_proc,
- &chip->nandsim_td, RFSTOPPED | RFHIGHPID,
- 0, "nandsim", "chip");
- if (error) {
- mtx_destroy(&chip->ns_lock);
- nandsim_blk_state_destroy(chip);
- free(chip, M_NANDSIM);
- return (NULL);
- }
-
- thread_lock(chip->nandsim_td);
- sched_class(chip->nandsim_td, PRI_REALTIME);
- sched_add(chip->nandsim_td, SRQ_BORING);
- thread_unlock(chip->nandsim_td);
-
- size = (chip_param->bytes_per_page +
- chip_param->spare_bytes_per_page) *
- chip_param->pages_per_block;
-
- sprintf(swapfile, "chip%d%d.swp", chip->ctrl_num, chip->chip_num);
- chip->swap = nandsim_swap_init(swapfile, chip_param->blocks_per_lun *
- chip_param->luns, size);
- if (!chip->swap)
- nandsim_chip_destroy(chip);
-
- /* Wait for new thread to enter main loop */
- tsleep(chip->nandsim_td, PWAIT, "ns_chip", 1 * hz);
-
- return (chip);
-}
-
-static int
-nandsim_blk_state_init(struct nandsim_chip *chip, uint32_t size,
- uint32_t wear_lev)
-{
- int i;
-
- if (!chip || size == 0)
- return (-1);
-
- chip->blk_state = malloc(size * sizeof(struct nandsim_block_state),
- M_NANDSIM, M_WAITOK | M_ZERO);
-
- for (i = 0; i < size; i++) {
- if (wear_lev)
- chip->blk_state[i].wear_lev = wear_lev;
- else
- chip->blk_state[i].wear_lev = -1;
- }
-
- return (0);
-}
-
-static void
-nandsim_blk_state_destroy(struct nandsim_chip *chip)
-{
-
- if (chip && chip->blk_state)
- free(chip->blk_state, M_NANDSIM);
-}
-
-static int
-nandsim_bbm_init(struct nandsim_chip *chip, uint32_t size,
- uint32_t *sim_bbm)
-{
- uint32_t index;
- int i;
-
- if ((chip == NULL) || (size == 0))
- return (-1);
-
- if (chip->blk_state == NULL)
- return (-1);
-
- if (sim_bbm == NULL)
- return (0);
-
- for (i = 0; i < MAX_BAD_BLOCKS; i++) {
- index = sim_bbm[i];
-
- if (index == 0xffffffff)
- break;
- else if (index > size)
- return (-1);
- else
- chip->blk_state[index].is_bad = 1;
- }
-
- return (0);
-}
-
-void
-nandsim_chip_destroy(struct nandsim_chip *chip)
-{
- struct nandsim_ev *ev;
-
- ev = create_event(chip, NANDSIM_EV_EXIT, 0);
- if (ev)
- send_event(ev);
-}
-
-void
-nandsim_chip_freeze(struct nandsim_chip *chip)
-{
-
- chip->flags |= NANDSIM_CHIP_FROZEN;
-}
-
-static void
-nandsim_loop(void *arg)
-{
- struct nandsim_chip *chip = (struct nandsim_chip *)arg;
- struct nandsim_ev *ev;
-
- nand_debug(NDBG_SIM,"Start main loop for chip%d [%8p]", chip->chip_num,
- chip);
- for(;;) {
- NANDSIM_CHIP_LOCK(chip);
- if (!(chip->flags & NANDSIM_CHIP_ACTIVE)) {
- chip->flags |= NANDSIM_CHIP_ACTIVE;
- wakeup(chip->nandsim_td);
- }
-
- if (STAILQ_EMPTY(&chip->nandsim_events)) {
- nand_debug(NDBG_SIM,"Chip%d [%8p] going sleep",
- chip->chip_num, chip);
- msleep(chip, &chip->ns_lock, PRIBIO, "nandev", 0);
- }
-
- ev = STAILQ_FIRST(&chip->nandsim_events);
- STAILQ_REMOVE_HEAD(&chip->nandsim_events, links);
- NANDSIM_CHIP_UNLOCK(chip);
- if (ev->type == NANDSIM_EV_EXIT) {
- NANDSIM_CHIP_LOCK(chip);
- destroy_event(ev);
- wakeup(ev);
- while (!STAILQ_EMPTY(&chip->nandsim_events)) {
- ev = STAILQ_FIRST(&chip->nandsim_events);
- STAILQ_REMOVE_HEAD(&chip->nandsim_events,
- links);
- destroy_event(ev);
- wakeup(ev);
- }
- NANDSIM_CHIP_UNLOCK(chip);
- nandsim_log(chip, NANDSIM_LOG_SM, "destroyed\n");
- mtx_destroy(&chip->ns_lock);
- nandsim_blk_state_destroy(chip);
- nandsim_swap_destroy(chip->swap);
- free(chip, M_NANDSIM);
- nandsim_proc = NULL;
-
- kthread_exit();
- }
-
- if (!(chip->flags & NANDSIM_CHIP_FROZEN)) {
- nand_debug(NDBG_SIM,"Chip [%x] get event [%x]",
- chip->chip_num, ev->type);
- chip->ev_handler(chip, ev->type, ev->data);
- }
-
- wakeup(ev);
- destroy_event(ev);
- }
-
-}
-
-struct nandsim_ev *
-create_event(struct nandsim_chip *chip, uint8_t type, uint8_t data_size)
-{
- struct nandsim_ev *ev;
-
- ev = malloc(sizeof(*ev), M_NANDSIM, M_NOWAIT | M_ZERO);
- if (!ev) {
- nand_debug(NDBG_SIM,"Cannot create event");
- return (NULL);
- }
-
- if (data_size > 0)
- ev->data = malloc(sizeof(*ev), M_NANDSIM, M_NOWAIT | M_ZERO);
- ev->type = type;
- ev->chip = chip;
-
- return (ev);
-}
-
-void
-destroy_event(struct nandsim_ev *ev)
-{
-
- if (ev->data)
- free(ev->data, M_NANDSIM);
- free(ev, M_NANDSIM);
-}
-
-int
-send_event(struct nandsim_ev *ev)
-{
- struct nandsim_chip *chip = ev->chip;
-
- if (!(chip->flags & NANDSIM_CHIP_FROZEN)) {
- nand_debug(NDBG_SIM,"Chip%d [%p] send event %x",
- chip->chip_num, chip, ev->type);
-
- NANDSIM_CHIP_LOCK(chip);
- STAILQ_INSERT_TAIL(&chip->nandsim_events, ev, links);
- NANDSIM_CHIP_UNLOCK(chip);
-
- wakeup(chip);
- if ((ev->type != NANDSIM_EV_TIMEOUT) && chip->nandsim_td &&
- (curthread != chip->nandsim_td))
- tsleep(ev, PWAIT, "ns_ev", 5 * hz);
- }
-
- return (0);
-}
-
-static void
-nandsim_callout_eh(void *arg)
-{
- struct nandsim_ev *ev = (struct nandsim_ev *)arg;
-
- send_event(ev);
-}
-
-static int
-nandsim_delay(struct nandsim_chip *chip, int timeout)
-{
- struct nandsim_ev *ev;
- struct timeval delay;
- int tm;
-
- nand_debug(NDBG_SIM,"Chip[%d] Set delay: %d", chip->chip_num, timeout);
-
- ev = create_event(chip, NANDSIM_EV_TIMEOUT, 0);
- if (!ev)
- return (-1);
-
- chip->sm_state = NANDSIM_STATE_TIMEOUT;
- tm = (timeout/10000) * (hz / 100);
- if (callout_reset(&chip->ns_callout, tm, nandsim_callout_eh, ev))
- return (-1);
-
- delay.tv_sec = chip->read_delay / 1000000;
- delay.tv_usec = chip->read_delay % 1000000;
- timevaladd(&chip->delay_tv, &delay);
-
- return (0);
-}
-
-static void
-nandsim_start_handler(struct nandsim_chip *chip, nandsim_evh_t evh)
-{
- struct nandsim_ev *ev;
-
- chip->ev_handler = evh;
-
- nand_debug(NDBG_SIM,"Start handler %p for chip%d [%p]", evh,
- chip->chip_num, chip);
- ev = create_event(chip, NANDSIM_EV_START, 0);
- if (!ev)
- nandsim_sm_error(chip);
-
- send_event(ev);
-}
-
-static void
-nandchip_set_data(struct nandsim_chip *chip, uint8_t *data, uint32_t len,
- uint32_t idx)
-{
-
- nand_debug(NDBG_SIM,"Chip [%x] data %p [%x] at %x", chip->chip_num,
- data, len, idx);
- chip->data.data_ptr = data;
- chip->data.size = len;
- chip->data.index = idx;
-}
-
-static int
-nandchip_chip_space(struct nandsim_chip *chip, int32_t row, int32_t column,
- size_t size, uint8_t writing)
-{
- struct block_space *blk_space;
- uint32_t lun, block, page, offset, block_size;
- int err;
-
- block_size = chip->cg.block_size +
- (chip->cg.oob_size * chip->cg.pgs_per_blk);
-
- err = nand_row_to_blkpg(&chip->cg, row, &lun, &block, &page);
- if (err) {
- nand_debug(NDBG_SIM,"cannot get address\n");
- return (-1);
- }
-
- if (!nandchip_is_block_valid(chip, block)) {
- nandchip_set_data(chip, NULL, 0, 0);
- return (-1);
- }
-
- blk_space = get_bs(chip->swap, block, writing);
- if (!blk_space) {
- nandchip_set_data(chip, NULL, 0, 0);
- return (-1);
- }
-
- if (size > block_size)
- size = block_size;
-
- if (size == block_size) {
- offset = 0;
- column = 0;
- } else
- offset = page * (chip->cg.page_size + chip->cg.oob_size);
-
- nandchip_set_data(chip, &blk_space->blk_ptr[offset], size, column);
-
- return (0);
-}
-
-static int
-nandchip_get_addr_byte(struct nandsim_chip *chip, void *data, uint32_t *value)
-{
- int ncycles = 0;
- uint8_t byte;
- uint8_t *buffer;
-
- buffer = (uint8_t *)value;
- byte = *((uint8_t *)data);
-
- KASSERT((chip->sm_state == NANDSIM_STATE_WAIT_ADDR_ROW ||
- chip->sm_state == NANDSIM_STATE_WAIT_ADDR_COL),
- ("unexpected state"));
-
- if (chip->sm_state == NANDSIM_STATE_WAIT_ADDR_ROW) {
- ncycles = chip->params.address_cycles & 0xf;
- buffer[chip->sm_addr_cycle++] = byte;
- } else if (chip->sm_state == NANDSIM_STATE_WAIT_ADDR_COL) {
- ncycles = (chip->params.address_cycles >> 4) & 0xf;
- buffer[chip->sm_addr_cycle++] = byte;
- }
-
- nand_debug(NDBG_SIM, "Chip [%x] read addr byte: %02x (%d of %d)\n",
- chip->chip_num, byte, chip->sm_addr_cycle, ncycles);
-
- if (chip->sm_addr_cycle == ncycles) {
- chip->sm_addr_cycle = 0;
- return (0);
- }
-
- return (1);
-}
-
-static int
-nandchip_is_block_valid(struct nandsim_chip *chip, int block_num)
-{
-
- if (!chip || !chip->blk_state)
- return (0);
-
- if (chip->blk_state[block_num].wear_lev == 0 ||
- chip->blk_state[block_num].is_bad)
- return (0);
-
- return (1);
-}
-
-static void
-nandchip_set_status(struct nandsim_chip *chip, uint8_t flags)
-{
-
- chip->chip_status |= flags;
-}
-
-static void
-nandchip_clear_status(struct nandsim_chip *chip, uint8_t flags)
-{
-
- chip->chip_status &= ~flags;
-}
-
-uint8_t
-nandchip_get_status(struct nandsim_chip *chip)
-{
- return (chip->chip_status);
-}
-
-void
-nandsim_chip_timeout(struct nandsim_chip *chip)
-{
- struct timeval tv;
-
- getmicrotime(&tv);
-
- if (chip->sm_state == NANDSIM_STATE_TIMEOUT &&
- timevalcmp(&tv, &chip->delay_tv, >=)) {
- nandchip_set_status(chip, NAND_STATUS_RDY);
- }
-}
-void
-poweron_evh(struct nandsim_chip *chip, uint32_t type, void *data)
-{
- uint8_t cmd;
-
- if (type == NANDSIM_EV_START)
- chip->sm_state = NANDSIM_STATE_IDLE;
- else if (type == NANDSIM_EV_CMD) {
- cmd = *(uint8_t *)data;
- switch(cmd) {
- case NAND_CMD_RESET:
- nandsim_log(chip, NANDSIM_LOG_SM, "in RESET state\n");
- nandsim_start_handler(chip, reset_evh);
- break;
- default:
- nandsim_undefined(chip, type);
- break;
- }
- } else
- nandsim_undefined(chip, type);
-}
-
-void
-idle_evh(struct nandsim_chip *chip, uint32_t type, void *data)
-{
- uint8_t cmd;
-
- if (type == NANDSIM_EV_START) {
- nandsim_log(chip, NANDSIM_LOG_SM, "in IDLE state\n");
- chip->sm_state = NANDSIM_STATE_WAIT_CMD;
- } else if (type == NANDSIM_EV_CMD) {
- nandchip_clear_status(chip, NAND_STATUS_FAIL);
- getmicrotime(&chip->delay_tv);
- cmd = *(uint8_t *)data;
- switch(cmd) {
- case NAND_CMD_READ_ID:
- nandsim_start_handler(chip, readid_evh);
- break;
- case NAND_CMD_READ_PARAMETER:
- nandsim_start_handler(chip, readparam_evh);
- break;
- case NAND_CMD_READ:
- nandsim_start_handler(chip, read_evh);
- break;
- case NAND_CMD_PROG:
- nandsim_start_handler(chip, write_evh);
- break;
- case NAND_CMD_ERASE:
- nandsim_start_handler(chip, erase_evh);
- break;
- default:
- nandsim_undefined(chip, type);
- break;
- }
- } else
- nandsim_undefined(chip, type);
-}
-
-void
-readid_evh(struct nandsim_chip *chip, uint32_t type, void *data)
-{
- struct onfi_params *params;
- uint8_t addr;
-
- params = &chip->params;
-
- if (type == NANDSIM_EV_START) {
- nandsim_log(chip, NANDSIM_LOG_SM, "in READID state\n");
- chip->sm_state = NANDSIM_STATE_WAIT_ADDR_BYTE;
- } else if (type == NANDSIM_EV_ADDR) {
-
- addr = *((uint8_t *)data);
-
- if (addr == 0x0)
- nandchip_set_data(chip, (uint8_t *)&chip->id, 2, 0);
- else if (addr == ONFI_SIG_ADDR)
- nandchip_set_data(chip, (uint8_t *)&params->signature,
- 4, 0);
- else
- nandsim_bad_address(chip, &addr);
-
- nandsim_start_handler(chip, idle_evh);
- } else
- nandsim_undefined(chip, type);
-}
-
-void
-readparam_evh(struct nandsim_chip *chip, uint32_t type, void *data)
-{
- struct onfi_params *params;
- uint8_t addr;
-
- params = &chip->params;
-
- if (type == NANDSIM_EV_START) {
- nandsim_log(chip, NANDSIM_LOG_SM, "in READPARAM state\n");
- chip->sm_state = NANDSIM_STATE_WAIT_ADDR_BYTE;
- } else if (type == NANDSIM_EV_ADDR) {
- addr = *((uint8_t *)data);
-
- if (addr == 0) {
- nandchip_set_data(chip, (uint8_t *)params,
- sizeof(*params), 0);
- } else
- nandsim_bad_address(chip, &addr);
-
- nandsim_start_handler(chip, idle_evh);
- } else
- nandsim_undefined(chip, type);
-}
-
-void
-read_evh(struct nandsim_chip *chip, uint32_t type, void *data)
-{
- static uint32_t column = 0, row = 0;
- uint32_t size;
- uint8_t cmd;
-
- size = chip->cg.page_size + chip->cg.oob_size;
-
- switch (type) {
- case NANDSIM_EV_START:
- nandsim_log(chip, NANDSIM_LOG_SM, "in READ state\n");
- chip->sm_state = NANDSIM_STATE_WAIT_ADDR_COL;
- break;
- case NANDSIM_EV_ADDR:
- if (chip->sm_state == NANDSIM_STATE_WAIT_ADDR_COL) {
- if (nandchip_get_addr_byte(chip, data, &column))
- break;
-
- chip->sm_state = NANDSIM_STATE_WAIT_ADDR_ROW;
- } else if (chip->sm_state == NANDSIM_STATE_WAIT_ADDR_ROW) {
- if (nandchip_get_addr_byte(chip, data, &row))
- break;
-
- chip->sm_state = NANDSIM_STATE_WAIT_CMD;
- } else
- nandsim_ignore_address(chip, *((uint8_t *)data));
- break;
- case NANDSIM_EV_CMD:
- cmd = *(uint8_t *)data;
- if (chip->sm_state == NANDSIM_STATE_WAIT_CMD &&
- cmd == NAND_CMD_READ_END) {
- if (chip->read_delay != 0 &&
- nandsim_delay(chip, chip->read_delay) == 0)
- nandchip_clear_status(chip, NAND_STATUS_RDY);
- else {
- nandchip_chip_space(chip, row, column, size, 0);
- nandchip_set_status(chip, NAND_STATUS_RDY);
- nandsim_start_handler(chip, idle_evh);
- }
- } else
- nandsim_undefined(chip, type);
- break;
- case NANDSIM_EV_TIMEOUT:
- if (chip->sm_state == NANDSIM_STATE_TIMEOUT) {
- nandchip_chip_space(chip, row, column, size, 0);
- nandchip_set_status(chip, NAND_STATUS_RDY);
- nandsim_start_handler(chip, idle_evh);
- } else
- nandsim_undefined(chip, type);
- break;
- }
-}
-void
-write_evh(struct nandsim_chip *chip, uint32_t type, void *data)
-{
- static uint32_t column, row;
- uint32_t size;
- uint8_t cmd;
- int err;
-
- size = chip->cg.page_size + chip->cg.oob_size;
-
- switch(type) {
- case NANDSIM_EV_START:
- nandsim_log(chip, NANDSIM_LOG_SM, "in WRITE state\n");
- chip->sm_state = NANDSIM_STATE_WAIT_ADDR_COL;
- break;
- case NANDSIM_EV_ADDR:
- if (chip->sm_state == NANDSIM_STATE_WAIT_ADDR_COL) {
- if (nandchip_get_addr_byte(chip, data, &column))
- break;
-
- chip->sm_state = NANDSIM_STATE_WAIT_ADDR_ROW;
- } else if (chip->sm_state == NANDSIM_STATE_WAIT_ADDR_ROW) {
- if (nandchip_get_addr_byte(chip, data, &row))
- break;
-
- err = nandchip_chip_space(chip, row, column, size, 1);
- if (err == -1)
- nandchip_set_status(chip, NAND_STATUS_FAIL);
-
- chip->sm_state = NANDSIM_STATE_WAIT_CMD;
- } else
- nandsim_ignore_address(chip, *((uint8_t *)data));
- break;
- case NANDSIM_EV_CMD:
- cmd = *(uint8_t *)data;
- if (chip->sm_state == NANDSIM_STATE_WAIT_CMD &&
- cmd == NAND_CMD_PROG_END) {
- if (chip->prog_delay != 0 &&
- nandsim_delay(chip, chip->prog_delay) == 0)
- nandchip_clear_status(chip, NAND_STATUS_RDY);
- else {
- nandchip_set_status(chip, NAND_STATUS_RDY);
- nandsim_start_handler(chip, idle_evh);
- }
- } else
- nandsim_undefined(chip, type);
- break;
- case NANDSIM_EV_TIMEOUT:
- if (chip->sm_state == NANDSIM_STATE_TIMEOUT) {
- nandsim_start_handler(chip, idle_evh);
- nandchip_set_status(chip, NAND_STATUS_RDY);
- } else
- nandsim_undefined(chip, type);
- break;
- }
-}
-
-void
-erase_evh(struct nandsim_chip *chip, uint32_t type, void *data)
-{
- static uint32_t row, block_size;
- uint32_t lun, block, page;
- int err;
- uint8_t cmd;
-
- block_size = chip->cg.block_size +
- (chip->cg.oob_size * chip->cg.pgs_per_blk);
-
- switch (type) {
- case NANDSIM_EV_START:
- nandsim_log(chip, NANDSIM_LOG_SM, "in ERASE state\n");
- chip->sm_state = NANDSIM_STATE_WAIT_ADDR_ROW;
- break;
- case NANDSIM_EV_CMD:
- cmd = *(uint8_t *)data;
- if (chip->sm_state == NANDSIM_STATE_WAIT_CMD &&
- cmd == NAND_CMD_ERASE_END) {
- if (chip->data.data_ptr != NULL &&
- chip->data.size == block_size)
- memset(chip->data.data_ptr, 0xff, block_size);
- else
- nand_debug(NDBG_SIM,"Bad block erase data\n");
-
- err = nand_row_to_blkpg(&chip->cg, row, &lun,
- &block, &page);
- if (!err) {
- if (chip->blk_state[block].wear_lev > 0)
- chip->blk_state[block].wear_lev--;
- }
-
- if (chip->erase_delay != 0 &&
- nandsim_delay(chip, chip->erase_delay) == 0)
- nandchip_clear_status(chip, NAND_STATUS_RDY);
- else {
- nandchip_set_status(chip, NAND_STATUS_RDY);
- nandsim_start_handler(chip, idle_evh);
- }
- } else
- nandsim_undefined(chip, type);
- break;
- case NANDSIM_EV_ADDR:
- if (chip->sm_state == NANDSIM_STATE_WAIT_ADDR_ROW) {
- if (nandchip_get_addr_byte(chip, data, &row))
- break;
-
- err = nandchip_chip_space(chip, row, 0, block_size, 1);
- if (err == -1) {
- nandchip_set_status(chip, NAND_STATUS_FAIL);
- }
- chip->sm_state = NANDSIM_STATE_WAIT_CMD;
- } else
- nandsim_ignore_address(chip, *((uint8_t *)data));
- break;
- case NANDSIM_EV_TIMEOUT:
- if (chip->sm_state == NANDSIM_STATE_TIMEOUT) {
- nandchip_set_status(chip, NAND_STATUS_RDY);
- nandsim_start_handler(chip, idle_evh);
- } else
- nandsim_undefined(chip, type);
- break;
- }
-}
-
-void
-reset_evh(struct nandsim_chip *chip, uint32_t type, void *data)
-{
-
- if (type == NANDSIM_EV_START) {
- nandsim_log(chip, NANDSIM_LOG_SM, "in RESET state\n");
- chip->sm_state = NANDSIM_STATE_TIMEOUT;
- nandchip_set_data(chip, NULL, 0, 0);
- DELAY(500);
- nandsim_start_handler(chip, idle_evh);
- } else
- nandsim_undefined(chip, type);
-}
-
-static void
-nandsim_undefined(struct nandsim_chip *chip, uint8_t type)
-{
-
- nandsim_log(chip, NANDSIM_LOG_ERR,
- "ERR: Chip received ev %x in state %x\n",
- type, chip->sm_state);
- nandsim_start_handler(chip, idle_evh);
-}
-
-static void
-nandsim_bad_address(struct nandsim_chip *chip, uint8_t *addr)
-{
-
- nandsim_log(chip, NANDSIM_LOG_ERR,
- "ERR: Chip received out of range address"
- "%02x%02x - %02x%02x%02x\n", addr[0], addr[1], addr[2],
- addr[3], addr[4]);
-}
-
-static void
-nandsim_ignore_address(struct nandsim_chip *chip, uint8_t byte)
-{
- nandsim_log(chip, NANDSIM_LOG_SM, "ignored address byte: %d\n", byte);
-}
-
-static void
-nandsim_sm_error(struct nandsim_chip *chip)
-{
-
- nandsim_log(chip, NANDSIM_LOG_ERR, "ERR: State machine error."
- "Restart required.\n");
-}
diff --git a/sys/dev/nand/nandsim_chip.h b/sys/dev/nand/nandsim_chip.h
deleted file mode 100644
index 86ced5ea2bf27..0000000000000
--- a/sys/dev/nand/nandsim_chip.h
+++ /dev/null
@@ -1,161 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (C) 2009-2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef _NANDSIM_CHIP_H
-#define _NANDSIM_CHIP_H
-
-#include <sys/malloc.h>
-#include <sys/callout.h>
-#include <dev/nand/nand.h>
-#include <dev/nand/nandsim.h>
-#include <dev/nand/nandsim_swap.h>
-
-MALLOC_DECLARE(M_NANDSIM);
-
-#define MAX_CS_NUM 4
-struct nandsim_chip;
-
-typedef void nandsim_evh_t(struct nandsim_chip *chip, uint32_t ev, void *data);
-
-enum addr_type {
- ADDR_NONE,
- ADDR_ID,
- ADDR_ROW,
- ADDR_ROWCOL
-};
-
-struct nandsim_softc {
- struct nand_softc nand_dev;
- device_t dev;
-
- struct nandsim_chip *chips[MAX_CS_NUM];
- struct nandsim_chip *active_chip;
-
- uint8_t address_cycle;
- enum addr_type address_type;
- int log_idx;
- char *log_buff;
- struct alq *alq;
-};
-
-struct nandsim_ev {
- STAILQ_ENTRY(nandsim_ev) links;
- struct nandsim_chip *chip;
- uint8_t type;
- void *data;
-};
-
-struct nandsim_data {
- uint8_t *data_ptr;
- uint32_t index;
- uint32_t size;
-};
-
-struct nandsim_block_state {
- int32_t wear_lev;
- uint8_t is_bad;
-};
-
-#define NANDSIM_CHIP_ACTIVE 0x1
-#define NANDSIM_CHIP_FROZEN 0x2
-#define NANDSIM_CHIP_GET_STATUS 0x4
-
-struct nandsim_chip {
- struct nandsim_softc *sc;
- struct thread *nandsim_td;
-
- STAILQ_HEAD(, nandsim_ev) nandsim_events;
- nandsim_evh_t *ev_handler;
- struct mtx ns_lock;
- struct callout ns_callout;
-
- struct chip_geom cg;
- struct nand_id id;
- struct onfi_params params;
- struct nandsim_data data;
- struct nandsim_block_state *blk_state;
-
- struct chip_swap *swap;
-
- uint32_t error_ratio;
- uint32_t wear_level;
- uint32_t sm_state;
- uint32_t sm_addr_cycle;
-
- uint32_t erase_delay;
- uint32_t prog_delay;
- uint32_t read_delay;
- struct timeval delay_tv;
-
- uint8_t flags;
- uint8_t chip_status;
- uint8_t ctrl_num;
- uint8_t chip_num;
-};
-
-struct sim_ctrl_conf {
- uint8_t num;
- uint8_t num_cs;
- uint8_t ecc;
- uint8_t running;
- uint8_t created;
- device_t sim_ctrl_dev;
- struct sim_chip *chips[MAX_CTRL_CS];
- uint16_t ecc_layout[MAX_ECC_BYTES];
- char filename[FILENAME_SIZE];
-};
-
-#define NANDSIM_STATE_IDLE 0x0
-#define NANDSIM_STATE_WAIT_ADDR_BYTE 0x1
-#define NANDSIM_STATE_WAIT_CMD 0x2
-#define NANDSIM_STATE_TIMEOUT 0x3
-#define NANDSIM_STATE_WAIT_ADDR_ROW 0x4
-#define NANDSIM_STATE_WAIT_ADDR_COL 0x5
-
-#define NANDSIM_EV_START 0x1
-#define NANDSIM_EV_CMD 0x2
-#define NANDSIM_EV_ADDR 0x3
-#define NANDSIM_EV_TIMEOUT 0x4
-#define NANDSIM_EV_EXIT 0xff
-
-struct nandsim_chip *nandsim_chip_init(struct nandsim_softc *,
- uint8_t, struct sim_chip *);
-void nandsim_chip_destroy(struct nandsim_chip *);
-void nandsim_chip_freeze(struct nandsim_chip *);
-void nandsim_chip_timeout(struct nandsim_chip *);
-int nandsim_chip_check_bad_block(struct nandsim_chip *, int);
-
-uint8_t nandchip_get_status(struct nandsim_chip *);
-
-void destroy_event(struct nandsim_ev *);
-int send_event(struct nandsim_ev *);
-struct nandsim_ev *create_event(struct nandsim_chip *, uint8_t, uint8_t);
-
-#endif /* _NANDSIM_CHIP_H */
diff --git a/sys/dev/nand/nandsim_ctrl.c b/sys/dev/nand/nandsim_ctrl.c
deleted file mode 100644
index bc203902fe7e8..0000000000000
--- a/sys/dev/nand/nandsim_ctrl.c
+++ /dev/null
@@ -1,398 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (C) 2009-2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/* Simulated NAND controller driver */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/proc.h>
-#include <sys/bus.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-#include <sys/rman.h>
-#include <sys/lock.h>
-#include <sys/mutex.h>
-#include <sys/time.h>
-
-#include <dev/nand/nand.h>
-#include <dev/nand/nandbus.h>
-#include <dev/nand/nandsim.h>
-#include <dev/nand/nandsim_log.h>
-#include <dev/nand/nandsim_chip.h>
-#include "nfc_if.h"
-
-#define ADDRESS_SIZE 5
-
-extern struct sim_ctrl_conf ctrls[MAX_SIM_DEV];
-
-static void byte_corrupt(struct nandsim_chip *, uint8_t *);
-
-static int nandsim_attach(device_t);
-static int nandsim_detach(device_t);
-static int nandsim_probe(device_t);
-
-static uint8_t nandsim_read_byte(device_t);
-static uint16_t nandsim_read_word(device_t);
-static int nandsim_select_cs(device_t, uint8_t);
-static void nandsim_write_byte(device_t, uint8_t);
-static void nandsim_write_word(device_t, uint16_t);
-static void nandsim_read_buf(device_t, void *, uint32_t);
-static void nandsim_write_buf(device_t, void *, uint32_t);
-static int nandsim_send_command(device_t, uint8_t);
-static int nandsim_send_address(device_t, uint8_t);
-
-static device_method_t nandsim_methods[] = {
- DEVMETHOD(device_probe, nandsim_probe),
- DEVMETHOD(device_attach, nandsim_attach),
- DEVMETHOD(device_detach, nandsim_detach),
-
- DEVMETHOD(nfc_select_cs, nandsim_select_cs),
- DEVMETHOD(nfc_send_command, nandsim_send_command),
- DEVMETHOD(nfc_send_address, nandsim_send_address),
- DEVMETHOD(nfc_read_byte, nandsim_read_byte),
- DEVMETHOD(nfc_read_word, nandsim_read_word),
- DEVMETHOD(nfc_write_byte, nandsim_write_byte),
- DEVMETHOD(nfc_read_buf, nandsim_read_buf),
- DEVMETHOD(nfc_write_buf, nandsim_write_buf),
-
- { 0, 0 },
-};
-
-static driver_t nandsim_driver = {
- "nandsim",
- nandsim_methods,
- sizeof(struct nandsim_softc),
-};
-
-static devclass_t nandsim_devclass;
-DRIVER_MODULE(nandsim, nexus, nandsim_driver, nandsim_devclass, 0, 0);
-DRIVER_MODULE(nandbus, nandsim, nandbus_driver, nandbus_devclass, 0, 0);
-
-static int
-nandsim_probe(device_t dev)
-{
-
- device_set_desc(dev, "NAND controller simulator");
- return (BUS_PROBE_DEFAULT);
-}
-
-static int
-nandsim_attach(device_t dev)
-{
- struct nandsim_softc *sc;
- struct sim_ctrl_conf *params;
- struct sim_chip *chip;
- uint16_t *eccpos;
- int i, err;
-
- sc = device_get_softc(dev);
- params = &ctrls[device_get_unit(dev)];
-
- if (strlen(params->filename) == 0)
- snprintf(params->filename, FILENAME_SIZE, "ctrl%d.log",
- params->num);
-
- nandsim_log_init(sc, params->filename);
- for (i = 0; i < params->num_cs; i++) {
- chip = params->chips[i];
- if (chip && chip->device_id != 0) {
- sc->chips[i] = nandsim_chip_init(sc, i, chip);
- if (chip->features & ONFI_FEAT_16BIT)
- sc->nand_dev.flags |= NAND_16_BIT;
- }
- }
-
- if (params->ecc_layout[0] != 0xffff)
- eccpos = params->ecc_layout;
- else
- eccpos = NULL;
-
- nand_init(&sc->nand_dev, dev, params->ecc, 0, 0, eccpos, "nandsim");
-
- err = nandbus_create(dev);
-
- return (err);
-}
-
-static int
-nandsim_detach(device_t dev)
-{
- struct nandsim_softc *sc;
- struct sim_ctrl_conf *params;
- int i;
-
- sc = device_get_softc(dev);
- params = &ctrls[device_get_unit(dev)];
-
- for (i = 0; i < params->num_cs; i++)
- if (sc->chips[i] != NULL)
- nandsim_chip_destroy(sc->chips[i]);
-
- nandsim_log_close(sc);
-
- return (0);
-}
-
-static int
-nandsim_select_cs(device_t dev, uint8_t cs)
-{
- struct nandsim_softc *sc;
-
- sc = device_get_softc(dev);
-
- if (cs >= MAX_CS_NUM)
- return (EINVAL);
-
- sc->active_chip = sc->chips[cs];
-
- if (sc->active_chip)
- nandsim_log(sc->active_chip, NANDSIM_LOG_EV,
- "Select cs %d\n", cs);
-
- return (0);
-}
-
-static int
-nandsim_send_command(device_t dev, uint8_t command)
-{
- struct nandsim_softc *sc;
- struct nandsim_chip *chip;
- struct nandsim_ev *ev;
-
- sc = device_get_softc(dev);
- chip = sc->active_chip;
-
- if (chip == NULL)
- return (0);
-
- nandsim_log(chip, NANDSIM_LOG_EV, "Send command %x\n", command);
-
- switch (command) {
- case NAND_CMD_READ_ID:
- case NAND_CMD_READ_PARAMETER:
- sc->address_type = ADDR_ID;
- break;
- case NAND_CMD_ERASE:
- sc->address_type = ADDR_ROW;
- break;
- case NAND_CMD_READ:
- case NAND_CMD_PROG:
- sc->address_type = ADDR_ROWCOL;
- break;
- default:
- sc->address_type = ADDR_NONE;
- break;
- }
-
- if (command == NAND_CMD_STATUS)
- chip->flags |= NANDSIM_CHIP_GET_STATUS;
- else {
- ev = create_event(chip, NANDSIM_EV_CMD, 1);
- *(uint8_t *)ev->data = command;
- send_event(ev);
- }
-
- return (0);
-}
-
-static int
-nandsim_send_address(device_t dev, uint8_t addr)
-{
- struct nandsim_ev *ev;
- struct nandsim_softc *sc;
- struct nandsim_chip *chip;
-
- sc = device_get_softc(dev);
- chip = sc->active_chip;
-
- if (chip == NULL)
- return (0);
-
- KASSERT((sc->address_type != ADDR_NONE), ("unexpected address"));
- nandsim_log(chip, NANDSIM_LOG_EV, "Send addr %x\n", addr);
-
- ev = create_event(chip, NANDSIM_EV_ADDR, 1);
-
- *((uint8_t *)(ev->data)) = addr;
-
- send_event(ev);
- return (0);
-}
-
-static uint8_t
-nandsim_read_byte(device_t dev)
-{
- struct nandsim_softc *sc;
- struct nandsim_chip *chip;
- uint8_t ret = 0xff;
-
- sc = device_get_softc(dev);
- chip = sc->active_chip;
-
- if (chip && !(chip->flags & NANDSIM_CHIP_FROZEN)) {
- if (chip->flags & NANDSIM_CHIP_GET_STATUS) {
- nandsim_chip_timeout(chip);
- ret = nandchip_get_status(chip);
- chip->flags &= ~NANDSIM_CHIP_GET_STATUS;
- } else if (chip->data.index < chip->data.size) {
- ret = chip->data.data_ptr[chip->data.index++];
- byte_corrupt(chip, &ret);
- }
- nandsim_log(chip, NANDSIM_LOG_DATA, "read %02x\n", ret);
- }
-
- return (ret);
-}
-
-static uint16_t
-nandsim_read_word(device_t dev)
-{
- struct nandsim_softc *sc;
- struct nandsim_chip *chip;
- uint16_t *data_ptr;
- uint16_t ret = 0xffff;
- uint8_t *byte_ret = (uint8_t *)&ret;
-
- sc = device_get_softc(dev);
- chip = sc->active_chip;
-
- if (chip && !(chip->flags & NANDSIM_CHIP_FROZEN)) {
- if (chip->data.index < chip->data.size - 1) {
- data_ptr =
- (uint16_t *)&(chip->data.data_ptr[chip->data.index]);
- ret = *data_ptr;
- chip->data.index += 2;
- byte_corrupt(chip, byte_ret);
- byte_corrupt(chip, byte_ret + 1);
- }
- nandsim_log(chip, NANDSIM_LOG_DATA, "read %04x\n", ret);
- }
-
- return (ret);
-}
-
-static void
-nandsim_write_byte(device_t dev, uint8_t byte)
-{
- struct nandsim_softc *sc;
- struct nandsim_chip *chip;
-
- sc = device_get_softc(dev);
- chip = sc->active_chip;
-
- if (chip && !(chip->flags & NANDSIM_CHIP_FROZEN) &&
- (chip->data.index < chip->data.size)) {
- byte_corrupt(chip, &byte);
- chip->data.data_ptr[chip->data.index] &= byte;
- chip->data.index++;
- nandsim_log(chip, NANDSIM_LOG_DATA, "write %02x\n", byte);
- }
-}
-
-static void
-nandsim_write_word(device_t dev, uint16_t word)
-{
- struct nandsim_softc *sc;
- struct nandsim_chip *chip;
- uint16_t *data_ptr;
- uint8_t *byte_ptr = (uint8_t *)&word;
-
- sc = device_get_softc(dev);
- chip = sc->active_chip;
-
- if (chip && !(chip->flags & NANDSIM_CHIP_FROZEN)) {
- if ((chip->data.index + 1) < chip->data.size) {
- byte_corrupt(chip, byte_ptr);
- byte_corrupt(chip, byte_ptr + 1);
- data_ptr =
- (uint16_t *)&(chip->data.data_ptr[chip->data.index]);
- *data_ptr &= word;
- chip->data.index += 2;
- }
-
- nandsim_log(chip, NANDSIM_LOG_DATA, "write %04x\n", word);
- }
-}
-
-static void
-nandsim_read_buf(device_t dev, void *buf, uint32_t len)
-{
- struct nandsim_softc *sc;
- uint16_t *buf16 = (uint16_t *)buf;
- uint8_t *buf8 = (uint8_t *)buf;
- int i;
-
- sc = device_get_softc(dev);
-
- if (sc->nand_dev.flags & NAND_16_BIT) {
- for (i = 0; i < len / 2; i++)
- buf16[i] = nandsim_read_word(dev);
- } else {
- for (i = 0; i < len; i++)
- buf8[i] = nandsim_read_byte(dev);
- }
-}
-
-static void
-nandsim_write_buf(device_t dev, void *buf, uint32_t len)
-{
- struct nandsim_softc *sc;
- uint16_t *buf16 = (uint16_t *)buf;
- uint8_t *buf8 = (uint8_t *)buf;
- int i;
-
- sc = device_get_softc(dev);
-
- if (sc->nand_dev.flags & NAND_16_BIT) {
- for (i = 0; i < len / 2; i++)
- nandsim_write_word(dev, buf16[i]);
- } else {
- for (i = 0; i < len; i++)
- nandsim_write_byte(dev, buf8[i]);
- }
-}
-
-static void
-byte_corrupt(struct nandsim_chip *chip, uint8_t *byte)
-{
- uint32_t rand;
- uint8_t bit;
-
- rand = random();
- if ((rand % 1000000) < chip->error_ratio) {
- bit = rand % 8;
- if (*byte & (1 << bit))
- *byte &= ~(1 << bit);
- else
- *byte |= (1 << bit);
- }
-}
diff --git a/sys/dev/nand/nandsim_log.c b/sys/dev/nand/nandsim_log.c
deleted file mode 100644
index 0bd316ace4e2d..0000000000000
--- a/sys/dev/nand/nandsim_log.c
+++ /dev/null
@@ -1,188 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (C) 2009-2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-#include <sys/malloc.h>
-#include <sys/proc.h>
-#include <sys/alq.h>
-#include <sys/time.h>
-
-#include <machine/stdarg.h>
-
-#include <dev/nand/nandsim_log.h>
-
-int nandsim_log_level;
-int nandsim_log_output;
-int log_size = NANDSIM_RAM_LOG_SIZE;
-
-static int nandsim_entry_size = NANDSIM_ENTRY_SIZE;
-static int nandsim_entry_count = NANDSIM_ENTRY_COUNT;
-static int str_index = 0;
-static char string[NANDSIM_ENTRY_SIZE + 1] = {0};
-
-int
-nandsim_log_init(struct nandsim_softc *sc, char *filename)
-{
- int error = 0;
-
- if (nandsim_log_output == NANDSIM_OUTPUT_FILE) {
- error = alq_open(&sc->alq, filename,
- curthread->td_ucred, 0644,
- nandsim_entry_size, nandsim_entry_count);
- } else if (nandsim_log_output == NANDSIM_OUTPUT_RAM) {
- sc->log_buff = malloc(log_size, M_NANDSIM, M_WAITOK | M_ZERO);
- if (!sc->log_buff)
- error = ENOMEM;
- }
-
- return (error);
-}
-
-void
-nandsim_log_close(struct nandsim_softc *sc)
-{
-
- if (nandsim_log_output == NANDSIM_OUTPUT_FILE) {
- memset(&string[str_index], 0, NANDSIM_ENTRY_SIZE - str_index);
- alq_write(sc->alq, (void *) string, ALQ_NOWAIT);
- str_index = 0;
- string[0] = '\0';
- alq_close(sc->alq);
- } else if (nandsim_log_output == NANDSIM_OUTPUT_RAM) {
- free(sc->log_buff, M_NANDSIM);
- sc->log_buff = NULL;
- }
-}
-
-void
-nandsim_log(struct nandsim_chip *chip, int level, const char *fmt, ...)
-{
- char hdr[TIME_STR_SIZE];
- char tmp[NANDSIM_ENTRY_SIZE];
- struct nandsim_softc *sc;
- struct timeval currtime;
- va_list ap;
- int hdr_len, len, rest;
-
- if (nandsim_log_output == NANDSIM_OUTPUT_NONE)
- return;
-
- if (chip == NULL)
- return;
-
- sc = chip->sc;
- if (!sc->alq && nandsim_log_output == NANDSIM_OUTPUT_FILE)
- return;
-
- if (level <= nandsim_log_level) {
- microtime(&currtime);
- hdr_len = sprintf(hdr, "%08jd.%08li [chip:%d, ctrl:%d]: ",
- (intmax_t)currtime.tv_sec, currtime.tv_usec,
- chip->chip_num, chip->ctrl_num);
-
- switch(nandsim_log_output) {
- case NANDSIM_OUTPUT_CONSOLE:
- printf("%s", hdr);
- va_start(ap, fmt);
- vprintf(fmt, ap);
- va_end(ap);
- break;
- case NANDSIM_OUTPUT_RAM:
- va_start(ap, fmt);
- len = vsnprintf(tmp, NANDSIM_ENTRY_SIZE - 1, fmt, ap);
- tmp[NANDSIM_ENTRY_SIZE - 1] = 0;
- va_end(ap);
-
- rest = log_size - sc->log_idx - 1;
- if (rest >= hdr_len) {
- bcopy(hdr, &sc->log_buff[sc->log_idx],
- hdr_len);
- sc->log_idx += hdr_len;
- sc->log_buff[sc->log_idx] = 0;
- } else {
- bcopy(hdr, &sc->log_buff[sc->log_idx], rest);
- bcopy(&hdr[rest], sc->log_buff,
- hdr_len - rest);
- sc->log_idx = hdr_len - rest;
- sc->log_buff[sc->log_idx] = 0;
- }
-
- rest = log_size - sc->log_idx - 1;
- if (rest >= len) {
- bcopy(tmp, &sc->log_buff[sc->log_idx], len);
- sc->log_idx += len;
- sc->log_buff[sc->log_idx] = 0;
- } else {
- bcopy(tmp, &sc->log_buff[sc->log_idx], rest);
- bcopy(&tmp[rest], sc->log_buff, len - rest);
- sc->log_idx = len - rest;
- sc->log_buff[sc->log_idx] = 0;
- }
-
- break;
-
- case NANDSIM_OUTPUT_FILE:
- va_start(ap, fmt);
- len = vsnprintf(tmp, NANDSIM_ENTRY_SIZE - 1, fmt, ap);
- tmp[NANDSIM_ENTRY_SIZE - 1] = 0;
- va_end(ap);
-
- rest = NANDSIM_ENTRY_SIZE - str_index;
- if (rest >= hdr_len) {
- strcat(string, hdr);
- str_index += hdr_len;
- } else {
- strlcat(string, hdr, NANDSIM_ENTRY_SIZE + 1);
- alq_write(sc->alq, (void *) string,
- ALQ_NOWAIT);
- strcpy(string, &hdr[rest]);
- str_index = hdr_len - rest;
- }
- rest = NANDSIM_ENTRY_SIZE - str_index;
- if (rest >= len) {
- strcat(string, tmp);
- str_index += len;
- } else {
- strlcat(string, tmp, NANDSIM_ENTRY_SIZE + 1);
- alq_write(sc->alq, (void *) string,
- ALQ_NOWAIT);
- strcpy(string, &tmp[rest]);
- str_index = len - rest;
- }
- break;
- default:
- break;
- }
- }
-}
diff --git a/sys/dev/nand/nandsim_log.h b/sys/dev/nand/nandsim_log.h
deleted file mode 100644
index 5e5a055a40533..0000000000000
--- a/sys/dev/nand/nandsim_log.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (C) 2009-2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef _NANDSIM_LOG_H
-#define _NANDSIM_LOG_H
-
-#include <dev/nand/nandsim_chip.h>
-
-#define NANDSIM_ENTRY_SIZE 128
-#define NANDSIM_ENTRY_COUNT 1024
-#define NANDSIM_RAM_LOG_SIZE 16384
-#define TIME_STR_SIZE 40
-
-#define NANDSIM_LOG_ERR 1
-#define NANDSIM_LOG_SM 5
-#define NANDSIM_LOG_EV 10
-#define NANDSIM_LOG_DATA 15
-
-extern int nandsim_log_level;
-extern int nandsim_log_output;
-
-int nandsim_log_init(struct nandsim_softc *, char *);
-void nandsim_log_close(struct nandsim_softc *);
-void nandsim_log(struct nandsim_chip *, int, const char *, ...);
-
-#endif /* _NANDSIM_LOG_H */
-
diff --git a/sys/dev/nand/nandsim_swap.c b/sys/dev/nand/nandsim_swap.c
deleted file mode 100644
index 78e14e9557bd5..0000000000000
--- a/sys/dev/nand/nandsim_swap.c
+++ /dev/null
@@ -1,383 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (C) 2009-2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/systm.h>
-#include <sys/malloc.h>
-#include <sys/queue.h>
-#include <sys/fcntl.h>
-#include <sys/proc.h>
-#include <sys/namei.h>
-#include <sys/lock.h>
-#include <sys/vnode.h>
-#include <sys/mount.h>
-
-#include <dev/nand/nandsim_chip.h>
-#include <dev/nand/nandsim_swap.h>
-
-static int init_block_state(struct chip_swap *);
-static void destroy_block_state(struct chip_swap *);
-
-static int create_buffers(struct chip_swap *);
-static void destroy_buffers(struct chip_swap *);
-
-static int swap_file_open(struct chip_swap *, const char *);
-static void swap_file_close(struct chip_swap *);
-static int swap_file_write(struct chip_swap *, struct block_state *);
-static int swap_file_read(struct chip_swap *, struct block_state *);
-
-#define CHIP_SWAP_CMODE 0600
-#define CHIP_SWAP_BLOCKSPACES 2
-
-static int
-init_block_state(struct chip_swap *swap)
-{
- struct block_state *blk_state;
- int i;
-
- if (swap == NULL)
- return (-1);
-
- blk_state = malloc(swap->nof_blks * sizeof(struct block_state),
- M_NANDSIM, M_WAITOK | M_ZERO);
-
- for (i = 0; i < swap->nof_blks; i++)
- blk_state[i].offset = 0xffffffff;
-
- swap->blk_state = blk_state;
-
- return (0);
-}
-
-static void
-destroy_block_state(struct chip_swap *swap)
-{
-
- if (swap == NULL)
- return;
-
- if (swap->blk_state != NULL)
- free(swap->blk_state, M_NANDSIM);
-}
-
-static int
-create_buffers(struct chip_swap *swap)
-{
- struct block_space *block_space;
- void *block;
- int i;
-
- for (i = 0; i < CHIP_SWAP_BLOCKSPACES; i++) {
- block_space = malloc(sizeof(*block_space), M_NANDSIM, M_WAITOK);
- block = malloc(swap->blk_size, M_NANDSIM, M_WAITOK);
- block_space->blk_ptr = block;
- SLIST_INSERT_HEAD(&swap->free_bs, block_space, free_link);
- nand_debug(NDBG_SIM,"created blk_space %p[%p]\n", block_space,
- block);
- }
-
- if (i == 0)
- return (-1);
-
- return (0);
-}
-
-static void
-destroy_buffers(struct chip_swap *swap)
-{
- struct block_space *blk_space;
-
- if (swap == NULL)
- return;
-
- blk_space = SLIST_FIRST(&swap->free_bs);
- while (blk_space) {
- SLIST_REMOVE_HEAD(&swap->free_bs, free_link);
- nand_debug(NDBG_SIM,"destroyed blk_space %p[%p]\n",
- blk_space, blk_space->blk_ptr);
- free(blk_space->blk_ptr, M_NANDSIM);
- free(blk_space, M_NANDSIM);
- blk_space = SLIST_FIRST(&swap->free_bs);
- }
-
- blk_space = STAILQ_FIRST(&swap->used_bs);
- while (blk_space) {
- STAILQ_REMOVE_HEAD(&swap->used_bs, used_link);
- nand_debug(NDBG_SIM,"destroyed blk_space %p[%p]\n",
- blk_space, blk_space->blk_ptr);
- free(blk_space->blk_ptr, M_NANDSIM);
- free(blk_space, M_NANDSIM);
- blk_space = STAILQ_FIRST(&swap->used_bs);
- }
-}
-
-static int
-swap_file_open(struct chip_swap *swap, const char *swap_file)
-{
- struct nameidata nd;
- int flags, error;
-
- NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, swap_file,
- curthread);
-
- flags = FWRITE | FREAD | O_NOFOLLOW | O_CREAT | O_TRUNC;
-
- error = vn_open(&nd, &flags, CHIP_SWAP_CMODE, NULL);
- if (error) {
- nand_debug(NDBG_SIM,"Cannot create swap file %s", swap_file);
- NDFREE(&nd, NDF_ONLY_PNBUF);
- return (error);
- }
-
- swap->swap_cred = crhold(curthread->td_ucred);
- NDFREE(&nd, NDF_ONLY_PNBUF);
-
- /* We just unlock so we hold a reference */
- VOP_UNLOCK(nd.ni_vp, 0);
-
- swap->swap_vp = nd.ni_vp;
-
- return (0);
-}
-
-static void
-swap_file_close(struct chip_swap *swap)
-{
-
- if (swap == NULL)
- return;
-
- if (swap->swap_vp == NULL)
- return;
-
- vn_close(swap->swap_vp, FWRITE, swap->swap_cred, curthread);
- crfree(swap->swap_cred);
-}
-
-static int
-swap_file_write(struct chip_swap *swap, struct block_state *blk_state)
-{
- struct block_space *blk_space;
- struct thread *td;
- struct mount *mp;
- struct vnode *vp;
- struct uio auio;
- struct iovec aiov;
-
- if (swap == NULL || blk_state == NULL)
- return (-1);
-
- blk_space = blk_state->blk_sp;
- if (blk_state->offset == -1) {
- blk_state->offset = swap->swap_offset;
- swap->swap_offset += swap->blk_size;
- }
-
- nand_debug(NDBG_SIM,"saving %p[%p] at %x\n",
- blk_space, blk_space->blk_ptr, blk_state->offset);
-
- bzero(&aiov, sizeof(aiov));
- bzero(&auio, sizeof(auio));
-
- aiov.iov_base = blk_space->blk_ptr;
- aiov.iov_len = swap->blk_size;
- td = curthread;
- vp = swap->swap_vp;
-
- auio.uio_iov = &aiov;
- auio.uio_offset = blk_state->offset;
- auio.uio_segflg = UIO_SYSSPACE;
- auio.uio_rw = UIO_WRITE;
- auio.uio_iovcnt = 1;
- auio.uio_resid = swap->blk_size;
- auio.uio_td = td;
-
- vn_start_write(vp, &mp, V_WAIT);
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
- VOP_WRITE(vp, &auio, IO_UNIT, swap->swap_cred);
- VOP_UNLOCK(vp, 0);
- vn_finished_write(mp);
-
- return (0);
-}
-
-static int
-swap_file_read(struct chip_swap *swap, struct block_state *blk_state)
-{
- struct block_space *blk_space;
- struct thread *td;
- struct vnode *vp;
- struct uio auio;
- struct iovec aiov;
-
- if (swap == NULL || blk_state == NULL)
- return (-1);
-
- blk_space = blk_state->blk_sp;
-
- nand_debug(NDBG_SIM,"restore %p[%p] at %x\n",
- blk_space, blk_space->blk_ptr, blk_state->offset);
-
- bzero(&aiov, sizeof(aiov));
- bzero(&auio, sizeof(auio));
-
- aiov.iov_base = blk_space->blk_ptr;
- aiov.iov_len = swap->blk_size;
- td = curthread;
- vp = swap->swap_vp;
-
- auio.uio_iov = &aiov;
- auio.uio_offset = blk_state->offset;
- auio.uio_segflg = UIO_SYSSPACE;
- auio.uio_rw = UIO_READ;
- auio.uio_iovcnt = 1;
- auio.uio_resid = swap->blk_size;
- auio.uio_td = td;
-
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
- VOP_READ(vp, &auio, 0, swap->swap_cred);
- VOP_UNLOCK(vp, 0);
-
- return (0);
-}
-
-struct chip_swap *
-nandsim_swap_init(const char *swap_file, uint32_t nof_blks, uint32_t blk_size)
-{
- struct chip_swap *swap;
- int err = 0;
-
- if ((swap_file == NULL) || (nof_blks == 0) || (blk_size == 0))
- return (NULL);
-
- swap = malloc(sizeof(*swap), M_NANDSIM, M_WAITOK | M_ZERO);
-
- SLIST_INIT(&swap->free_bs);
- STAILQ_INIT(&swap->used_bs);
- swap->blk_size = blk_size;
- swap->nof_blks = nof_blks;
-
- err = init_block_state(swap);
- if (err) {
- nandsim_swap_destroy(swap);
- return (NULL);
- }
-
- err = create_buffers(swap);
- if (err) {
- nandsim_swap_destroy(swap);
- return (NULL);
- }
-
- err = swap_file_open(swap, swap_file);
- if (err) {
- nandsim_swap_destroy(swap);
- return (NULL);
- }
-
- return (swap);
-}
-
-void
-nandsim_swap_destroy(struct chip_swap *swap)
-{
-
- if (swap == NULL)
- return;
-
- destroy_block_state(swap);
- destroy_buffers(swap);
- swap_file_close(swap);
- free(swap, M_NANDSIM);
-}
-
-struct block_space *
-get_bs(struct chip_swap *swap, uint32_t block, uint8_t writing)
-{
- struct block_state *blk_state, *old_blk_state = NULL;
- struct block_space *blk_space;
-
- if (swap == NULL || (block >= swap->nof_blks))
- return (NULL);
-
- blk_state = &swap->blk_state[block];
- nand_debug(NDBG_SIM,"blk_state %x\n", blk_state->status);
-
- if (blk_state->status & BLOCK_ALLOCATED) {
- blk_space = blk_state->blk_sp;
- } else {
- blk_space = SLIST_FIRST(&swap->free_bs);
- if (blk_space) {
- SLIST_REMOVE_HEAD(&swap->free_bs, free_link);
- STAILQ_INSERT_TAIL(&swap->used_bs, blk_space,
- used_link);
- } else {
- blk_space = STAILQ_FIRST(&swap->used_bs);
- old_blk_state = blk_space->blk_state;
- STAILQ_REMOVE_HEAD(&swap->used_bs, used_link);
- STAILQ_INSERT_TAIL(&swap->used_bs, blk_space,
- used_link);
- if (old_blk_state->status & BLOCK_DIRTY) {
- swap_file_write(swap, old_blk_state);
- old_blk_state->status &= ~BLOCK_DIRTY;
- old_blk_state->status |= BLOCK_SWAPPED;
- }
- }
- }
-
- if (blk_space == NULL)
- return (NULL);
-
- if (old_blk_state != NULL) {
- old_blk_state->status &= ~BLOCK_ALLOCATED;
- old_blk_state->blk_sp = NULL;
- }
-
- blk_state->blk_sp = blk_space;
- blk_space->blk_state = blk_state;
-
- if (!(blk_state->status & BLOCK_ALLOCATED)) {
- if (blk_state->status & BLOCK_SWAPPED)
- swap_file_read(swap, blk_state);
- else
- memset(blk_space->blk_ptr, 0xff, swap->blk_size);
- blk_state->status |= BLOCK_ALLOCATED;
- }
-
- if (writing)
- blk_state->status |= BLOCK_DIRTY;
-
- nand_debug(NDBG_SIM,"get_bs returned %p[%p] state %x\n", blk_space,
- blk_space->blk_ptr, blk_state->status);
-
- return (blk_space);
-}
diff --git a/sys/dev/nand/nandsim_swap.h b/sys/dev/nand/nandsim_swap.h
deleted file mode 100644
index c9eb0be63a9cd..0000000000000
--- a/sys/dev/nand/nandsim_swap.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (C) 2009-2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef _NANDSIM_SWAP_CHIP_H_
-#define _NANDSIM_SWAP_CHIP_H_
-
-struct block_space {
- SLIST_ENTRY(block_space) free_link;
- STAILQ_ENTRY(block_space) used_link;
- struct block_state *blk_state;
- uint8_t *blk_ptr;
-};
-
-#define BLOCK_ALLOCATED 0x1
-#define BLOCK_SWAPPED 0x2
-#define BLOCK_DIRTY 0x4
-
-struct block_state {
- struct block_space *blk_sp;
- uint32_t offset;
- uint8_t status;
-};
-
-struct chip_swap {
- struct block_state *blk_state;
- SLIST_HEAD(,block_space) free_bs;
- STAILQ_HEAD(,block_space) used_bs;
- struct ucred *swap_cred;
- struct vnode *swap_vp;
- uint32_t swap_offset;
- uint32_t blk_size;
- uint32_t nof_blks;
-};
-
-struct chip_swap *nandsim_swap_init(const char *, uint32_t, uint32_t);
-void nandsim_swap_destroy(struct chip_swap *);
-struct block_space *get_bs(struct chip_swap *, uint32_t, uint8_t);
-
-#endif /* _NANDSIM_SWAP_CHIP_H_ */
diff --git a/sys/dev/nand/nfc_fsl.c b/sys/dev/nand/nfc_fsl.c
deleted file mode 100644
index 992cfeb784fe5..0000000000000
--- a/sys/dev/nand/nfc_fsl.c
+++ /dev/null
@@ -1,717 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (C) 2012 Juniper Networks, Inc.
- * Copyright (C) 2009-2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-/*
- * TODO :
- *
- * -- test support for small pages
- * -- support for reading ONFI parameters
- * -- support for cached and interleaving commands
- * -- proper setting of AL bits in FMR
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/proc.h>
-#include <sys/bus.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-#include <sys/malloc.h>
-#include <sys/rman.h>
-#include <sys/sysctl.h>
-#include <sys/time.h>
-#include <sys/kdb.h>
-
-#include <machine/bus.h>
-
-#include <dev/ofw/ofw_bus.h>
-#include <dev/ofw/ofw_bus_subr.h>
-
-#include <powerpc/mpc85xx/lbc.h>
-
-#include <dev/nand/nand.h>
-#include <dev/nand/nandbus.h>
-
-#include "nfc_fsl.h"
-
-#include "nfc_if.h"
-
-#define LBC_READ(regname) lbc_read_reg(dev, (LBC85XX_ ## regname))
-#define LBC_WRITE(regname, val) lbc_write_reg(dev, (LBC85XX_ ## regname), val)
-
-enum addr_type {
- ADDR_NONE,
- ADDR_ID,
- ADDR_ROW,
- ADDR_ROWCOL
-};
-
-struct fsl_nfc_fcm {
- /* Read-only after initialization */
- uint32_t reg_fmr;
-
- /* To be preserved across "start_command" */
- u_int buf_ofs;
- u_int read_ptr;
- u_int status:1;
-
- /* Command state -- cleared by "start_command" */
- uint32_t fcm_startzero;
- uint32_t reg_fcr;
- uint32_t reg_fir;
- uint32_t reg_mdr;
- uint32_t reg_fbcr;
- uint32_t reg_fbar;
- uint32_t reg_fpar;
- u_int cmdnr;
- u_int opnr;
- u_int pg_ofs;
- enum addr_type addr_type;
- u_int addr_bytes;
- u_int row_addr;
- u_int column_addr;
- u_int data_fir:8;
- uint32_t fcm_endzero;
-};
-
-struct fsl_nand_softc {
- struct nand_softc nand_dev;
- device_t dev;
- struct resource *res;
- int rid; /* Resourceid */
- struct lbc_devinfo *dinfo;
- struct fsl_nfc_fcm fcm;
- uint8_t col_cycles;
- uint8_t row_cycles;
- uint16_t pgsz; /* Page size */
-};
-
-static int fsl_nand_attach(device_t dev);
-static int fsl_nand_probe(device_t dev);
-static int fsl_nand_detach(device_t dev);
-
-static int fsl_nfc_select_cs(device_t dev, uint8_t cs);
-static int fsl_nfc_read_rnb(device_t dev);
-static int fsl_nfc_send_command(device_t dev, uint8_t command);
-static int fsl_nfc_send_address(device_t dev, uint8_t address);
-static uint8_t fsl_nfc_read_byte(device_t dev);
-static int fsl_nfc_start_command(device_t dev);
-static void fsl_nfc_read_buf(device_t dev, void *buf, uint32_t len);
-static void fsl_nfc_write_buf(device_t dev, void *buf, uint32_t len);
-
-static device_method_t fsl_nand_methods[] = {
- DEVMETHOD(device_probe, fsl_nand_probe),
- DEVMETHOD(device_attach, fsl_nand_attach),
- DEVMETHOD(device_detach, fsl_nand_detach),
-
- DEVMETHOD(nfc_select_cs, fsl_nfc_select_cs),
- DEVMETHOD(nfc_read_rnb, fsl_nfc_read_rnb),
- DEVMETHOD(nfc_start_command, fsl_nfc_start_command),
- DEVMETHOD(nfc_send_command, fsl_nfc_send_command),
- DEVMETHOD(nfc_send_address, fsl_nfc_send_address),
- DEVMETHOD(nfc_read_byte, fsl_nfc_read_byte),
- DEVMETHOD(nfc_read_buf, fsl_nfc_read_buf),
- DEVMETHOD(nfc_write_buf, fsl_nfc_write_buf),
- { 0, 0 },
-};
-
-static driver_t fsl_nand_driver = {
- "nand",
- fsl_nand_methods,
- sizeof(struct fsl_nand_softc),
-};
-
-static devclass_t fsl_nand_devclass;
-
-DRIVER_MODULE(fsl_nand, lbc, fsl_nand_driver, fsl_nand_devclass,
- 0, 0);
-
-static int fsl_nand_build_address(device_t dev, uint32_t page, uint32_t column);
-static int fsl_nand_chip_preprobe(device_t dev, struct nand_id *id);
-
-#ifdef NAND_DEBUG_TIMING
-static device_t fcm_devs[8];
-#endif
-
-#define CMD_SHIFT(cmd_num) (24 - ((cmd_num) * 8))
-#define OP_SHIFT(op_num) (28 - ((op_num) * 4))
-
-#define FSL_LARGE_PAGE_SIZE (2112)
-#define FSL_SMALL_PAGE_SIZE (528)
-
-static void
-fsl_nand_init_regs(struct fsl_nand_softc *sc)
-{
- uint32_t or_v, br_v;
- device_t dev;
-
- dev = sc->dev;
-
- sc->fcm.reg_fmr = (15 << FMR_CWTO_SHIFT);
-
- /*
- * Setup 4 row cycles and hope that chip ignores superfluous address
- * bytes.
- */
- sc->fcm.reg_fmr |= (2 << FMR_AL_SHIFT);
-
- /* Reprogram BR(x) */
- br_v = lbc_read_reg(dev, LBC85XX_BR(sc->dinfo->di_bank));
- br_v &= 0xffff8000;
- br_v |= 1 << 11; /* 8-bit port size */
- br_v |= 0 << 9; /* No ECC checking and generation */
- br_v |= 1 << 5; /* FCM machine */
- br_v |= 1; /* Valid */
- lbc_write_reg(dev, LBC85XX_BR(sc->dinfo->di_bank), br_v);
-
- /* Reprogram OR(x) */
- or_v = lbc_read_reg(dev, LBC85XX_OR(sc->dinfo->di_bank));
- or_v &= 0xfffffc00;
- or_v |= 0x03AE; /* Default POR timing */
- lbc_write_reg(dev, LBC85XX_OR(sc->dinfo->di_bank), or_v);
-
- if (or_v & OR_FCM_PAGESIZE) {
- sc->pgsz = FSL_LARGE_PAGE_SIZE;
- sc->col_cycles = 2;
- nand_debug(NDBG_DRV, "%s: large page NAND device at #%d",
- device_get_nameunit(dev), sc->dinfo->di_bank);
- } else {
- sc->pgsz = FSL_SMALL_PAGE_SIZE;
- sc->col_cycles = 1;
- nand_debug(NDBG_DRV, "%s: small page NAND device at #%d",
- device_get_nameunit(dev), sc->dinfo->di_bank);
- }
-}
-
-static int
-fsl_nand_probe(device_t dev)
-{
-
- if (!ofw_bus_is_compatible(dev, "fsl,elbc-fcm-nand"))
- return (ENXIO);
-
- device_set_desc(dev, "Freescale localbus FCM Controller");
- return (BUS_PROBE_DEFAULT);
-}
-
-static int
-fsl_nand_attach(device_t dev)
-{
- struct fsl_nand_softc *sc;
- struct nand_id id;
- struct nand_params *param;
- uint32_t num_pages;
-
- sc = device_get_softc(dev);
- sc->dev = dev;
- sc->dinfo = device_get_ivars(dev);
-
- sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->rid,
- RF_ACTIVE);
- if (sc->res == NULL) {
- device_printf(dev, "could not allocate resources!\n");
- return (ENXIO);
- }
-
- bzero(&sc->fcm, sizeof(sc->fcm));
-
- /* Init register and check if HW ECC turned on */
- fsl_nand_init_regs(sc);
-
- /* Chip is probed, so determine number of row address cycles */
- fsl_nand_chip_preprobe(dev, &id);
- param = nand_get_params(&id);
- if (param != NULL) {
- num_pages = (param->chip_size << 20) / param->page_size;
- while(num_pages) {
- sc->row_cycles++;
- num_pages >>= 8;
- }
-
- sc->fcm.reg_fmr &= ~(FMR_AL);
- sc->fcm.reg_fmr |= (sc->row_cycles - 2) << FMR_AL_SHIFT;
- }
-
- nand_init(&sc->nand_dev, dev, NAND_ECC_SOFT, 0, 0, NULL, NULL);
-
-#ifdef NAND_DEBUG_TIMING
- fcm_devs[sc->dinfo->di_bank] = dev;
-#endif
-
- return (nandbus_create(dev));
-}
-
-static int
-fsl_nand_detach(device_t dev)
-{
- struct fsl_nand_softc *sc;
-
- sc = device_get_softc(dev);
-
- if (sc->res != NULL)
- bus_release_resource(dev, SYS_RES_MEMORY, sc->rid, sc->res);
-
- return (0);
-}
-
-static int
-fsl_nfc_select_cs(device_t dev, uint8_t cs)
-{
-
- // device_printf(dev, "%s(cs=%u)\n", __func__, cs);
- return ((cs > 0) ? EINVAL : 0);
-}
-
-static int
-fsl_nfc_read_rnb(device_t dev)
-{
-
- // device_printf(dev, "%s()\n", __func__);
- return (0);
-}
-
-static int
-fsl_nfc_send_command(device_t dev, uint8_t command)
-{
- struct fsl_nand_softc *sc;
- struct fsl_nfc_fcm *fcm;
- uint8_t fir_op;
-
- // device_printf(dev, "%s(command=%u)\n", __func__, command);
-
- sc = device_get_softc(dev);
- fcm = &sc->fcm;
-
- if (command == NAND_CMD_PROG_END) {
- fcm->reg_fir |= (FIR_OP_WB << OP_SHIFT(fcm->opnr));
- fcm->opnr++;
- }
- fcm->reg_fcr |= command << CMD_SHIFT(fcm->cmdnr);
- fir_op = (fcm->cmdnr == 0) ? FIR_OP_CW0 : FIR_OP_CM(fcm->cmdnr);
- fcm->cmdnr++;
-
- fcm->reg_fir |= (fir_op << OP_SHIFT(fcm->opnr));
- fcm->opnr++;
-
- switch (command) {
- case NAND_CMD_READ_ID:
- fcm->data_fir = FIR_OP_RBW;
- fcm->addr_type = ADDR_ID;
- break;
- case NAND_CMD_SMALLOOB:
- fcm->pg_ofs += 256;
- /*FALLTHROUGH*/
- case NAND_CMD_SMALLB:
- fcm->pg_ofs += 256;
- /*FALLTHROUGH*/
- case NAND_CMD_READ: /* NAND_CMD_SMALLA */
- fcm->data_fir = FIR_OP_RBW;
- fcm->addr_type = ADDR_ROWCOL;
- break;
- case NAND_CMD_STATUS:
- fcm->data_fir = FIR_OP_RS;
- fcm->status = 1;
- break;
- case NAND_CMD_ERASE:
- fcm->addr_type = ADDR_ROW;
- break;
- case NAND_CMD_PROG:
- fcm->addr_type = ADDR_ROWCOL;
- break;
- }
- return (0);
-}
-
-static int
-fsl_nfc_send_address(device_t dev, uint8_t addr)
-{
- struct fsl_nand_softc *sc;
- struct fsl_nfc_fcm *fcm;
- uint32_t addr_bits;
-
- // device_printf(dev, "%s(address=%u)\n", __func__, addr);
-
- sc = device_get_softc(dev);
- fcm = &sc->fcm;
-
- KASSERT(fcm->addr_type != ADDR_NONE,
- ("controller doesn't expect address cycle"));
-
- addr_bits = addr;
-
- if (fcm->addr_type == ADDR_ID) {
- fcm->reg_fir |= (FIR_OP_UA << OP_SHIFT(fcm->opnr));
- fcm->opnr++;
-
- fcm->reg_fbcr = 5;
- fcm->reg_fbar = 0;
- fcm->reg_fpar = 0;
- fcm->reg_mdr = addr_bits;
- fcm->buf_ofs = 0;
- fcm->read_ptr = 0;
- return (0);
- }
-
- if (fcm->addr_type == ADDR_ROW) {
- addr_bits <<= fcm->addr_bytes * 8;
- fcm->row_addr |= addr_bits;
- fcm->addr_bytes++;
- if (fcm->addr_bytes < sc->row_cycles)
- return (0);
- } else {
- if (fcm->addr_bytes < sc->col_cycles) {
- addr_bits <<= fcm->addr_bytes * 8;
- fcm->column_addr |= addr_bits;
- } else {
- addr_bits <<= (fcm->addr_bytes - sc->col_cycles) * 8;
- fcm->row_addr |= addr_bits;
- }
- fcm->addr_bytes++;
- if (fcm->addr_bytes < (sc->row_cycles + sc->col_cycles))
- return (0);
- }
-
- return (fsl_nand_build_address(dev, fcm->row_addr, fcm->column_addr));
-}
-
-static int
-fsl_nand_build_address(device_t dev, uint32_t row, uint32_t column)
-{
- struct fsl_nand_softc *sc;
- struct fsl_nfc_fcm *fcm;
- uint32_t byte_count = 0;
- uint32_t block_address = 0;
- uint32_t page_address = 0;
-
- sc = device_get_softc(dev);
- fcm = &sc->fcm;
-
- fcm->read_ptr = 0;
- fcm->buf_ofs = 0;
-
- if (fcm->addr_type == ADDR_ROWCOL) {
- fcm->reg_fir |= (FIR_OP_CA << OP_SHIFT(fcm->opnr));
- fcm->opnr++;
-
- column += fcm->pg_ofs;
- fcm->pg_ofs = 0;
-
- page_address |= column;
-
- if (column != 0) {
- byte_count = sc->pgsz - column;
- fcm->read_ptr = column;
- }
- }
-
- fcm->reg_fir |= (FIR_OP_PA << OP_SHIFT(fcm->opnr));
- fcm->opnr++;
-
- if (sc->pgsz == FSL_LARGE_PAGE_SIZE) {
- block_address = row >> 6;
- page_address |= ((row << FPAR_LP_PI_SHIFT) & FPAR_LP_PI);
- fcm->buf_ofs = (row & 1) * 4096;
- } else {
- block_address = row >> 5;
- page_address |= ((row << FPAR_SP_PI_SHIFT) & FPAR_SP_PI);
- fcm->buf_ofs = (row & 7) * 1024;
- }
-
- fcm->reg_fbcr = byte_count;
- fcm->reg_fbar = block_address;
- fcm->reg_fpar = page_address;
- return (0);
-}
-
-static int
-fsl_nfc_start_command(device_t dev)
-{
- struct fsl_nand_softc *sc;
- struct fsl_nfc_fcm *fcm;
- uint32_t fmr, ltesr_v;
- int error, timeout;
-
- // device_printf(dev, "%s()\n", __func__);
-
- sc = device_get_softc(dev);
- fcm = &sc->fcm;
-
- fmr = fcm->reg_fmr | FMR_OP;
-
- if (fcm->data_fir)
- fcm->reg_fir |= (fcm->data_fir << OP_SHIFT(fcm->opnr));
-
- LBC_WRITE(FIR, fcm->reg_fir);
- LBC_WRITE(FCR, fcm->reg_fcr);
-
- LBC_WRITE(FMR, fmr);
-
- LBC_WRITE(FBCR, fcm->reg_fbcr);
- LBC_WRITE(FBAR, fcm->reg_fbar);
- LBC_WRITE(FPAR, fcm->reg_fpar);
-
- if (fcm->addr_type == ADDR_ID)
- LBC_WRITE(MDR, fcm->reg_mdr);
-
- nand_debug(NDBG_DRV, "BEFORE:\nFMR=%#x, FIR=%#x, FCR=%#x", fmr,
- fcm->reg_fir, fcm->reg_fcr);
- nand_debug(NDBG_DRV, "MDR=%#x, FBAR=%#x, FPAR=%#x, FBCR=%#x",
- LBC_READ(MDR), fcm->reg_fbar, fcm->reg_fpar, fcm->reg_fbcr);
-
- LBC_WRITE(LSOR, sc->dinfo->di_bank);
-
- timeout = (cold) ? FSL_FCM_WAIT_TIMEOUT : ~0;
- error = 0;
- ltesr_v = LBC_READ(LTESR);
- while (!error && (ltesr_v & LTESR_CC) == 0) {
- if (cold) {
- DELAY(1000);
- timeout--;
- if (timeout < 0)
- error = EWOULDBLOCK;
- } else
- error = tsleep(device_get_parent(sc->dev), PRIBIO,
- "nfcfsl", hz);
- ltesr_v = LBC_READ(LTESR);
- }
- if (error)
- nand_debug(NDBG_DRV, "Command complete wait timeout\n");
-
- nand_debug(NDBG_DRV, "AFTER:\nLTESR=%#x, LTEDR=%#x, LTEIR=%#x,"
- " LTEATR=%#x, LTEAR=%#x, LTECCR=%#x", ltesr_v,
- LBC_READ(LTEDR), LBC_READ(LTEIR), LBC_READ(LTEATR),
- LBC_READ(LTEAR), LBC_READ(LTECCR));
-
- bzero(&fcm->fcm_startzero,
- __rangeof(struct fsl_nfc_fcm, fcm_startzero, fcm_endzero));
-
- if (fcm->status)
- sc->fcm.reg_mdr = LBC_READ(MDR);
-
- /* Even if timeout occurred, we should perform steps below */
- LBC_WRITE(LTESR, ltesr_v);
- LBC_WRITE(LTEATR, 0);
-
- return (error);
-}
-
-static uint8_t
-fsl_nfc_read_byte(device_t dev)
-{
- struct fsl_nand_softc *sc = device_get_softc(dev);
- uint32_t offset;
-
- // device_printf(dev, "%s()\n", __func__);
-
- /*
- * LBC controller allows us to read status into a MDR instead of FCM
- * buffer. If last operation requested before read_byte() was STATUS,
- * then return MDR instead of reading a single byte from a buffer.
- */
- if (sc->fcm.status) {
- sc->fcm.status = 0;
- return (sc->fcm.reg_mdr);
- }
-
- KASSERT(sc->fcm.read_ptr < sc->pgsz,
- ("Attempt to read beyond buffer %x %x", sc->fcm.read_ptr,
- sc->pgsz));
-
- offset = sc->fcm.buf_ofs + sc->fcm.read_ptr;
- sc->fcm.read_ptr++;
- return (bus_read_1(sc->res, offset));
-}
-
-static void
-fsl_nfc_read_buf(device_t dev, void *buf, uint32_t len)
-{
- struct fsl_nand_softc *sc = device_get_softc(dev);
- uint32_t offset;
- int bytesleft = 0;
-
- // device_printf(dev, "%s(buf=%p, len=%u)\n", __func__, buf, len);
-
- nand_debug(NDBG_DRV, "REQUEST OF 0x%0x B (BIB=0x%0x, NTR=0x%0x)",
- len, sc->pgsz, sc->fcm.read_ptr);
-
- bytesleft = MIN((unsigned int)len, sc->pgsz - sc->fcm.read_ptr);
-
- offset = sc->fcm.buf_ofs + sc->fcm.read_ptr;
- bus_read_region_1(sc->res, offset, buf, bytesleft);
- sc->fcm.read_ptr += bytesleft;
-}
-
-static void
-fsl_nfc_write_buf(device_t dev, void *buf, uint32_t len)
-{
- struct fsl_nand_softc *sc = device_get_softc(dev);
- uint32_t offset;
- int bytesleft = 0;
-
- // device_printf(dev, "%s(buf=%p, len=%u)\n", __func__, buf, len);
-
- KASSERT(len <= sc->pgsz - sc->fcm.read_ptr,
- ("Attempt to write beyond buffer"));
-
- bytesleft = MIN((unsigned int)len, sc->pgsz - sc->fcm.read_ptr);
-
- nand_debug(NDBG_DRV, "REQUEST TO WRITE 0x%0x (BIB=0x%0x, NTR=0x%0x)",
- bytesleft, sc->pgsz, sc->fcm.read_ptr);
-
- offset = sc->fcm.buf_ofs + sc->fcm.read_ptr;
- bus_write_region_1(sc->res, offset, buf, bytesleft);
- sc->fcm.read_ptr += bytesleft;
-}
-
-static int
-fsl_nand_chip_preprobe(device_t dev, struct nand_id *id)
-{
-
- if (fsl_nfc_send_command(dev, NAND_CMD_RESET) != 0)
- return (ENXIO);
-
- if (fsl_nfc_start_command(dev) != 0)
- return (ENXIO);
-
- DELAY(1000);
-
- if (fsl_nfc_send_command(dev, NAND_CMD_READ_ID))
- return (ENXIO);
-
- if (fsl_nfc_send_address(dev, 0))
- return (ENXIO);
-
- if (fsl_nfc_start_command(dev) != 0)
- return (ENXIO);
-
- DELAY(25);
-
- id->man_id = fsl_nfc_read_byte(dev);
- id->dev_id = fsl_nfc_read_byte(dev);
-
- nand_debug(NDBG_DRV, "manufacturer id: %x chip id: %x",
- id->man_id, id->dev_id);
-
- return (0);
-}
-
-#ifdef NAND_DEBUG_TIMING
-
-static SYSCTL_NODE(_debug, OID_AUTO, fcm, CTLFLAG_RD, 0, "FCM timing");
-
-static u_int csct = 1; /* 22: Chip select to command time (trlx). */
-SYSCTL_UINT(_debug_fcm, OID_AUTO, csct, CTLFLAG_RW, &csct, 1,
- "Chip select to command time: determines how far in advance -LCSn is "
- "asserted prior to any bus activity during a NAND Flash access handled "
- "by the FCM. This helps meet chip-select setup times for slow memories.");
-
-static u_int cst = 1; /* 23: Command setup time (trlx). */
-SYSCTL_UINT(_debug_fcm, OID_AUTO, cst, CTLFLAG_RW, &cst, 1,
- "Command setup time: determines the delay of -LFWE assertion relative to "
- "the command, address, or data change when the external memory access "
- "is handled by the FCM.");
-
-static u_int cht = 1; /* 24: Command hold time (trlx). */
-SYSCTL_UINT(_debug_fcm, OID_AUTO, cht, CTLFLAG_RW, &cht, 1,
- "Command hold time: determines the -LFWE negation prior to the command, "
- "address, or data change when the external memory access is handled by "
- "the FCM.");
-
-static u_int scy = 2; /* 25-27: Cycle length in bus clocks */
-SYSCTL_UINT(_debug_fcm, OID_AUTO, scy, CTLFLAG_RW, &scy, 2,
- "Cycle length in bus clocks: see RM");
-
-static u_int rst = 1; /* 28: Read setup time (trlx). */
-SYSCTL_UINT(_debug_fcm, OID_AUTO, rst, CTLFLAG_RW, &rst, 1,
- "Read setup time: determines the delay of -LFRE assertion relative to "
- "sampling of read data when the external memory access is handled by "
- "the FCM.");
-
-static u_int trlx = 1; /* 29: Timing relaxed. */
-SYSCTL_UINT(_debug_fcm, OID_AUTO, trlx, CTLFLAG_RW, &trlx, 1,
- "Timing relaxed: modifies the settings of timing parameters for slow "
- "memories. See RM");
-
-static u_int ehtr = 1; /* 30: Extended hold time on read accesses. */
-SYSCTL_UINT(_debug_fcm, OID_AUTO, ehtr, CTLFLAG_RW, &ehtr, 1,
- "Extended hold time on read accesses: indicates with TRLX how many "
- "cycles are inserted between a read access from the current bank and "
- "the next access.");
-
-static u_int
-fsl_nand_get_timing(void)
-{
- u_int timing;
-
- timing = ((csct & 1) << 9) | ((cst & 1) << 8) | ((cht & 1) << 7) |
- ((scy & 7) << 4) | ((rst & 1) << 3) | ((trlx & 1) << 2) |
- ((ehtr & 1) << 1);
-
- printf("nfc_fsl: timing = %u\n", timing);
- return (timing);
-}
-
-static int
-fsl_sysctl_program(SYSCTL_HANDLER_ARGS)
-{
- struct fsl_nand_softc *sc;
- int error, i;
- device_t dev;
- uint32_t or_v;
-
- error = sysctl_wire_old_buffer(req, sizeof(int));
- if (error == 0) {
- i = 0;
- error = sysctl_handle_int(oidp, &i, 0, req);
- }
- if (error != 0 || req->newptr == NULL)
- return (error);
-
- for (i = 0; i < 8; i++) {
- dev = fcm_devs[i];
- if (dev == NULL)
- continue;
- sc = device_get_softc(dev);
-
- /* Reprogram OR(x) */
- or_v = lbc_read_reg(dev, LBC85XX_OR(sc->dinfo->di_bank));
- or_v &= 0xfffffc00;
- or_v |= fsl_nand_get_timing();
- lbc_write_reg(dev, LBC85XX_OR(sc->dinfo->di_bank), or_v);
- }
- return (0);
-}
-
-SYSCTL_PROC(_debug_fcm, OID_AUTO, program, CTLTYPE_INT | CTLFLAG_RW, NULL, 0,
- fsl_sysctl_program, "I", "write to program FCM with current values");
-
-#endif /* NAND_DEBUG_TIMING */
diff --git a/sys/dev/nand/nfc_fsl.h b/sys/dev/nand/nfc_fsl.h
deleted file mode 100644
index 5410da5581712..0000000000000
--- a/sys/dev/nand/nfc_fsl.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (C) 2012 Juniper Networks, Inc.
- * Copyright (C) 2009-2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef _NAND_NFC_FSL_H_
-#define _NAND_NFC_FSL_H_
-
-/* LBC BR/OR Registers layout definitions */
-#define BR_V 0x00000001
-#define BR_V_SHIFT 0
-#define BR_MSEL 0x000000E0
-#define BR_MSEL_SHIFT 5
-#define BR_DECC_CHECK_MODE 0x00000600
-#define BR_DECC_CHECK_GEN 0x00000400
-
-#define OR_FCM_PAGESIZE 0x00000400
-
-/* Options definitions */
-#define NAND_OPT_ECC_MODE_HW 1
-#define NAND_OPT_ECC_MODE_SOFT (1 << 1)
-
-/* FMR - Flash Mode Register */
-#define FMR_CWTO 0xF000
-#define FMR_CWTO_SHIFT 12
-#define FMR_BOOT 0x0800
-#define FMR_ECCM 0x0100
-#define FMR_AL 0x0030
-#define FMR_AL_SHIFT 4
-#define FMR_OP 0x0003
-#define FMR_OP_SHIFT 0
-
-#define FIR_OP_NOP 0x0 /* No operation and end of sequence */
-#define FIR_OP_CA 0x1 /* Issue current column address */
-#define FIR_OP_PA 0x2 /* Issue current block+page address */
-#define FIR_OP_UA 0x3 /* Issue user defined address */
-#define FIR_OP_CM(x) (4 + (x)) /* Issue command from FCR[CMD(x)] */
-#define FIR_OP_WB 0x8 /* Write FBCR bytes from FCM buffer */
-#define FIR_OP_WS 0x9 /* Write 1 or 2 bytes from MDR[AS] */
-#define FIR_OP_RB 0xA /* Read FBCR bytes to FCM buffer */
-#define FIR_OP_RS 0xB /* Read 1 or 2 bytes to MDR[AS] */
-#define FIR_OP_CW0 0xC /* Wait then issue FCR[CMD0] */
-#define FIR_OP_CW1 0xD /* Wait then issue FCR[CMD1] */
-#define FIR_OP_RBW 0xE /* Wait then read FBCR bytes */
-#define FIR_OP_RSW 0xF /* Wait then read 1 or 2 bytes */
-
-/* LTESR - Transfer Error Status Register */
-#define LTESR_BM 0x80000000
-#define LTESR_FCT 0x40000000
-#define LTESR_PAR 0x20000000
-#define LTESR_WP 0x04000000
-#define LTESR_ATMW 0x00800000
-#define LTESR_ATMR 0x00400000
-#define LTESR_CS 0x00080000
-#define LTESR_CC 0x00000001
-
-#define LTESR_NAND_MASK (LTESR_FCT | LTESR_CC | LTESR_CS)
-
-/* FPAR - Flash Page Address Register */
-#define FPAR_SP_PI 0x00007C00
-#define FPAR_SP_PI_SHIFT 10
-#define FPAR_SP_MS 0x00000200
-#define FPAR_SP_CI 0x000001FF
-#define FPAR_SP_CI_SHIFT 0
-#define FPAR_LP_PI 0x0003F000
-#define FPAR_LP_PI_SHIFT 12
-#define FPAR_LP_MS 0x00000800
-#define FPAR_LP_CI 0x000007FF
-#define FPAR_LP_CI_SHIFT 0
-
-#define FSL_FCM_WAIT_TIMEOUT 10
-
-#endif /* _NAND_NFC_FSL_H_ */
diff --git a/sys/dev/nand/nfc_if.m b/sys/dev/nand/nfc_if.m
deleted file mode 100644
index a4e1099220acc..0000000000000
--- a/sys/dev/nand/nfc_if.m
+++ /dev/null
@@ -1,165 +0,0 @@
-#-
-# Copyright (C) 2009-2012 Semihalf
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-# SUCH DAMAGE.
-#
-# $FreeBSD$
-
-# NAND controller interface description
-#
-
-#include <sys/bus.h>
-#include <dev/nand/nand.h>
-
-INTERFACE nfc;
-
-CODE {
- static int nfc_default_method(device_t dev)
- {
- return (0);
- }
-
- static int nfc_softecc_get(device_t dev, void *buf, int pagesize,
- void *ecc, int *needwrite)
- {
- *needwrite = 1;
- return (nand_softecc_get(dev, buf, pagesize, ecc));
- }
-
- static int nfc_softecc_correct(device_t dev, void *buf, int pagesize,
- void *readecc, void *calcecc)
- {
- return (nand_softecc_correct(dev, buf, pagesize, readecc,
- calcecc));
- }
-};
-
-# Send command to a NAND chip
-#
-# Return values:
-# 0: Success
-#
-METHOD int send_command {
- device_t dev;
- uint8_t command;
-};
-
-# Send address to a NAND chip
-#
-# Return values:
-# 0: Success
-#
-METHOD int send_address {
- device_t dev;
- uint8_t address;
-};
-
-# Read byte
-#
-# Return values:
-# byte read
-#
-METHOD uint8_t read_byte {
- device_t dev;
-};
-
-# Write byte
-#
-METHOD void write_byte {
- device_t dev;
- uint8_t byte;
-};
-
-# Read word
-#
-# Return values:
-# word read
-#
-METHOD uint16_t read_word {
- device_t dev;
-};
-
-# Write word
-#
-METHOD void write_word {
- device_t dev;
- uint16_t word;
-};
-
-# Read buf
-#
-METHOD void read_buf {
- device_t dev;
- void *buf;
- uint32_t len;
-};
-
-# Write buf
-#
-METHOD void write_buf {
- device_t dev;
- void *buf;
- uint32_t len;
-};
-
-# Select CS
-#
-METHOD int select_cs {
- device_t dev;
- uint8_t cs;
-};
-
-# Read ready/busy signal
-#
-METHOD int read_rnb {
- device_t dev;
-};
-
-# Start command
-#
-# Return values:
-# 0: Success
-#
-METHOD int start_command {
- device_t dev;
-} DEFAULT nfc_default_method;
-
-# Generate ECC or get it from H/W
-#
-METHOD int get_ecc {
- device_t dev;
- void *buf;
- int pagesize;
- void *ecc;
- int *needwrite;
-} DEFAULT nfc_softecc_get;
-
-# Correct ECC
-#
-METHOD int correct_ecc {
- device_t dev;
- void *buf;
- int pagesize;
- void *readecc;
- void *calcecc;
-} DEFAULT nfc_softecc_correct;
diff --git a/sys/dev/nand/nfc_mv.c b/sys/dev/nand/nfc_mv.c
deleted file mode 100644
index 0d78d34d9912c..0000000000000
--- a/sys/dev/nand/nfc_mv.c
+++ /dev/null
@@ -1,238 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (C) 2009-2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/* Integrated NAND controller driver */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/proc.h>
-#include <sys/bus.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-#include <sys/malloc.h>
-#include <sys/rman.h>
-#include <sys/lock.h>
-#include <sys/mutex.h>
-#include <sys/time.h>
-
-#include <machine/bus.h>
-#include <machine/fdt.h>
-#include <arm/mv/mvvar.h>
-#include <arm/mv/mvwin.h>
-
-#include <dev/ofw/ofw_bus.h>
-#include <dev/ofw/ofw_bus_subr.h>
-
-#include <dev/nand/nand.h>
-#include <dev/nand/nandbus.h>
-#include "nfc_if.h"
-
-#define MV_NAND_DATA (0x00)
-#define MV_NAND_COMMAND (0x01)
-#define MV_NAND_ADDRESS (0x02)
-
-struct mv_nand_softc {
- struct nand_softc nand_dev;
- bus_space_handle_t sc_handle;
- bus_space_tag_t sc_tag;
- struct resource *res;
- int rid;
-};
-
-static int mv_nand_attach(device_t);
-static int mv_nand_probe(device_t);
-static int mv_nand_send_command(device_t, uint8_t);
-static int mv_nand_send_address(device_t, uint8_t);
-static uint8_t mv_nand_read_byte(device_t);
-static void mv_nand_read_buf(device_t, void *, uint32_t);
-static void mv_nand_write_buf(device_t, void *, uint32_t);
-static int mv_nand_select_cs(device_t, uint8_t);
-static int mv_nand_read_rnb(device_t);
-
-static device_method_t mv_nand_methods[] = {
- DEVMETHOD(device_probe, mv_nand_probe),
- DEVMETHOD(device_attach, mv_nand_attach),
-
- DEVMETHOD(nfc_send_command, mv_nand_send_command),
- DEVMETHOD(nfc_send_address, mv_nand_send_address),
- DEVMETHOD(nfc_read_byte, mv_nand_read_byte),
- DEVMETHOD(nfc_read_buf, mv_nand_read_buf),
- DEVMETHOD(nfc_write_buf, mv_nand_write_buf),
- DEVMETHOD(nfc_select_cs, mv_nand_select_cs),
- DEVMETHOD(nfc_read_rnb, mv_nand_read_rnb),
-
- { 0, 0 },
-};
-
-static driver_t mv_nand_driver = {
- "nand",
- mv_nand_methods,
- sizeof(struct mv_nand_softc),
-};
-
-static devclass_t mv_nand_devclass;
-DRIVER_MODULE(mv_nand, localbus, mv_nand_driver, mv_nand_devclass, 0, 0);
-
-static int
-mv_nand_probe(device_t dev)
-{
-
- if (!ofw_bus_is_compatible(dev, "mrvl,nfc"))
- return (ENXIO);
-
- device_set_desc(dev, "Marvell NAND controller");
- return (BUS_PROBE_DEFAULT);
-}
-
-static int
-mv_nand_attach(device_t dev)
-{
- struct mv_nand_softc *sc;
- int err;
-
- sc = device_get_softc(dev);
- sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->rid,
- RF_ACTIVE);
- if (sc->res == NULL) {
- device_printf(dev, "could not allocate resources!\n");
- return (ENXIO);
- }
-
- sc->sc_tag = rman_get_bustag(sc->res);
- sc->sc_handle = rman_get_bushandle(sc->res);
-
- nand_init(&sc->nand_dev, dev, NAND_ECC_SOFT, 0, 0, NULL, NULL);
-
- err = nandbus_create(dev);
-
- return (err);
-}
-
-static int
-mv_nand_send_command(device_t dev, uint8_t command)
-{
- struct mv_nand_softc *sc;
-
- nand_debug(NDBG_DRV,"mv_nand: send command %x", command);
-
- sc = device_get_softc(dev);
- bus_space_write_1(sc->sc_tag, sc->sc_handle, MV_NAND_COMMAND, command);
- return (0);
-}
-
-static int
-mv_nand_send_address(device_t dev, uint8_t addr)
-{
- struct mv_nand_softc *sc;
-
- nand_debug(NDBG_DRV,"mv_nand: send address %x", addr);
-
- sc = device_get_softc(dev);
- bus_space_write_1(sc->sc_tag, sc->sc_handle, MV_NAND_ADDRESS, addr);
- return (0);
-}
-
-static uint8_t
-mv_nand_read_byte(device_t dev)
-{
- struct mv_nand_softc *sc;
- uint8_t data;
-
- sc = device_get_softc(dev);
- data = bus_space_read_1(sc->sc_tag, sc->sc_handle, MV_NAND_DATA);
-
- nand_debug(NDBG_DRV,"mv_nand: read %x", data);
-
- return (data);
-}
-
-static void
-mv_nand_read_buf(device_t dev, void* buf, uint32_t len)
-{
- struct mv_nand_softc *sc;
- int i;
- uint8_t *b = (uint8_t*)buf;
-
- sc = device_get_softc(dev);
-
- for (i = 0; i < len; i++) {
- b[i] = bus_space_read_1(sc->sc_tag, sc->sc_handle,
- MV_NAND_DATA);
-#ifdef NAND_DEBUG
- if (!(i % 16))
- printf("%s", i == 0 ? "mv_nand:\n" : "\n");
- printf(" %x", b[i]);
- if (i == len - 1)
- printf("\n");
-#endif
- }
-}
-
-static void
-mv_nand_write_buf(device_t dev, void* buf, uint32_t len)
-{
- struct mv_nand_softc *sc;
- int i;
- uint8_t *b = (uint8_t*)buf;
-
- sc = device_get_softc(dev);
-
- for (i = 0; i < len; i++) {
-#ifdef NAND_DEBUG
- if (!(i % 16))
- printf("%s", i == 0 ? "mv_nand:\n" : "\n");
- printf(" %x", b[i]);
- if (i == len - 1)
- printf("\n");
-#endif
- bus_space_write_1(sc->sc_tag, sc->sc_handle, MV_NAND_DATA,
- b[i]);
- }
-}
-
-static int
-mv_nand_select_cs(device_t dev, uint8_t cs)
-{
-
- if (cs > 0)
- return (ENODEV);
-
- return (0);
-}
-
-static int
-mv_nand_read_rnb(device_t dev)
-{
-
- /* no-op */
- return (0); /* ready */
-}
diff --git a/sys/dev/nand/nfc_rb.c b/sys/dev/nand/nfc_rb.c
deleted file mode 100644
index 1102b3abb9c41..0000000000000
--- a/sys/dev/nand/nfc_rb.c
+++ /dev/null
@@ -1,321 +0,0 @@
-/*-
- * Copyright (C) 2015 Justin Hibbits
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/* RouterBoard 600/800 NAND controller driver. */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/bus.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-#include <sys/malloc.h>
-#include <sys/rman.h>
-#include <sys/slicer.h>
-
-#include <geom/geom_disk.h>
-
-#include <machine/bus.h>
-
-#include <dev/ofw/ofw_bus.h>
-#include <dev/ofw/ofw_bus_subr.h>
-
-#include <dev/nand/nand.h>
-#include <dev/nand/nandbus.h>
-
-#include <powerpc/mpc85xx/mpc85xx.h>
-
-#include "nfc_if.h"
-#include "gpio_if.h"
-
-#define RB_NAND_DATA (0x00)
-
-struct rb_nand_softc {
- struct nand_softc nand_dev;
- struct resource *sc_mem;
- int rid;
- device_t sc_gpio;
- uint32_t sc_rdy_pin;
- uint32_t sc_nce_pin;
- uint32_t sc_cle_pin;
- uint32_t sc_ale_pin;
-};
-
-static int rb_nand_attach(device_t);
-static int rb_nand_probe(device_t);
-static int rb_nand_send_command(device_t, uint8_t);
-static int rb_nand_send_address(device_t, uint8_t);
-static uint8_t rb_nand_read_byte(device_t);
-static void rb_nand_read_buf(device_t, void *, uint32_t);
-static void rb_nand_write_buf(device_t, void *, uint32_t);
-static int rb_nand_select_cs(device_t, uint8_t);
-static int rb_nand_read_rnb(device_t);
-
-static device_method_t rb_nand_methods[] = {
- DEVMETHOD(device_probe, rb_nand_probe),
- DEVMETHOD(device_attach, rb_nand_attach),
-
- DEVMETHOD(nfc_send_command, rb_nand_send_command),
- DEVMETHOD(nfc_send_address, rb_nand_send_address),
- DEVMETHOD(nfc_read_byte, rb_nand_read_byte),
- DEVMETHOD(nfc_read_buf, rb_nand_read_buf),
- DEVMETHOD(nfc_write_buf, rb_nand_write_buf),
- DEVMETHOD(nfc_select_cs, rb_nand_select_cs),
- DEVMETHOD(nfc_read_rnb, rb_nand_read_rnb),
-
- { 0, 0 },
-};
-
-static driver_t rb_nand_driver = {
- "nand",
- rb_nand_methods,
- sizeof(struct rb_nand_softc),
-};
-
-static devclass_t rb_nand_devclass;
-DRIVER_MODULE(rb_nand, ofwbus, rb_nand_driver, rb_nand_devclass, 0, 0);
-
-#if 0
-static const struct nand_ecc_data rb_ecc = {
- .eccsize = 6,
- .eccmode = NAND_ECC_SOFT,
- .eccbytes = 6,
- .eccpositions = { 8, 9, 10, 13, 14, 15 },
-};
-#endif
-
-/* Slicer operates on the NAND controller, so we have to find the chip. */
-static int
-rb_nand_slicer(device_t dev, const char *provider __unused,
- struct flash_slice *slices, int *nslices)
-{
- struct nand_chip *chip;
- device_t *children;
- int n;
-
- if (device_get_children(dev, &children, &n) != 0) {
- panic("Slicer called on controller with no child!");
- }
- dev = children[0];
- free(children, M_TEMP);
-
- if (device_get_children(dev, &children, &n) != 0) {
- panic("Slicer called on controller with nandbus but no child!");
- }
- dev = children[0];
- free(children, M_TEMP);
-
- chip = device_get_softc(dev);
- *nslices = 2;
- slices[0].base = 0;
- slices[0].size = 4 * 1024 * 1024;
- slices[0].label = "boot";
-
- slices[1].base = 4 * 1024 * 1024;
- slices[1].size = chip->ndisk->d_mediasize - slices[0].size;
- slices[1].label = "rootfs";
-
- return (0);
-}
-
-static int
-rb_nand_probe(device_t dev)
-{
- const char *device_type;
-
- device_type = ofw_bus_get_type(dev);
-
- if (!device_type || strcmp(device_type, "rb,nand"))
- return (ENXIO);
-
- device_set_desc(dev, "RouterBoard 333/600/800 NAND controller");
- return (BUS_PROBE_DEFAULT);
-}
-
-static int
-rb_nand_attach(device_t dev)
-{
- struct rb_nand_softc *sc;
- phandle_t node;
- uint32_t ale[2],cle[2],nce[2],rdy[2];
- u_long size,start;
- int err;
-
- sc = device_get_softc(dev);
- node = ofw_bus_get_node(dev);
-
- if (OF_getprop(node, "ale", ale, sizeof(ale)) <= 0) {
- return (ENXIO);
- }
- if (OF_getprop(node, "cle", cle, sizeof(cle)) <= 0) {
- return (ENXIO);
- }
- if (OF_getprop(node, "nce", nce, sizeof(nce)) <= 0) {
- return (ENXIO);
- }
- if (OF_getprop(node, "rdy", rdy, sizeof(rdy)) <= 0) {
- return (ENXIO);
- }
-
- if (ale[0] != cle[0] || ale[0] != nce[0] || ale[0] != rdy[0]) {
- device_printf(dev, "GPIO handles for signals must match.\n");
- return (ENXIO);
- }
- sc->sc_ale_pin = ale[1];
- sc->sc_cle_pin = cle[1];
- sc->sc_nce_pin = nce[1];
- sc->sc_rdy_pin = rdy[1];
-
- sc->sc_gpio = OF_device_from_xref(ale[0]);
- if (sc->sc_gpio == NULL) {
- device_printf(dev, "No GPIO resource found!\n");
- return (ENXIO);
- }
-
- sc->sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->rid,
- RF_ACTIVE);
- if (sc->sc_mem == NULL) {
- device_printf(dev, "could not allocate resources!\n");
- return (ENXIO);
- }
-
- start = rman_get_start(sc->sc_mem);
- size = rman_get_size(sc->sc_mem);
- if (law_enable(OCP85XX_TGTIF_LBC, start, size) != 0) {
- bus_release_resource(dev, SYS_RES_MEMORY, sc->rid, sc->sc_mem);
- device_printf(dev, "could not allocate local address window.\n");
- return (ENXIO);
- }
-
- flash_register_slicer(rb_nand_slicer, FLASH_SLICES_TYPE_NAND, TRUE);
-
- nand_init(&sc->nand_dev, dev, NAND_ECC_SOFT, 0, 0, NULL, NULL);
-
- err = nandbus_create(dev);
-
- return (err);
-}
-
-static int
-rb_nand_send_command(device_t dev, uint8_t command)
-{
- struct rb_nand_softc *sc;
-
- nand_debug(NDBG_DRV,"rb_nand: send command %x", command);
-
- sc = device_get_softc(dev);
- GPIO_PIN_SET(sc->sc_gpio, sc->sc_cle_pin, 1);
- GPIO_PIN_SET(sc->sc_gpio, sc->sc_ale_pin, 0);
- GPIO_PIN_SET(sc->sc_gpio, sc->sc_nce_pin, 0);
- bus_write_1(sc->sc_mem, RB_NAND_DATA, command);
- GPIO_PIN_SET(sc->sc_gpio, sc->sc_cle_pin, 0);
- return (0);
-}
-
-static int
-rb_nand_send_address(device_t dev, uint8_t addr)
-{
- struct rb_nand_softc *sc;
-
- nand_debug(NDBG_DRV,"rb_nand: send address %x", addr);
-
- sc = device_get_softc(dev);
- GPIO_PIN_SET(sc->sc_gpio, sc->sc_cle_pin, 0);
- GPIO_PIN_SET(sc->sc_gpio, sc->sc_ale_pin, 1);
- GPIO_PIN_SET(sc->sc_gpio, sc->sc_nce_pin, 0);
- bus_write_1(sc->sc_mem, RB_NAND_DATA, addr);
- GPIO_PIN_SET(sc->sc_gpio, sc->sc_ale_pin, 0);
- return (0);
-}
-
-static uint8_t
-rb_nand_read_byte(device_t dev)
-{
- struct rb_nand_softc *sc;
- uint8_t data;
-
- sc = device_get_softc(dev);
- data = bus_read_1(sc->sc_mem, RB_NAND_DATA);
-
- nand_debug(NDBG_DRV,"rb_nand: read %x", data);
-
- return (data);
-}
-
-static void
-rb_nand_read_buf(device_t dev, void* buf, uint32_t len)
-{
- struct rb_nand_softc *sc;
-
- sc = device_get_softc(dev);
-
- bus_read_region_1(sc->sc_mem, RB_NAND_DATA, buf, len);
-}
-
-static void
-rb_nand_write_buf(device_t dev, void* buf, uint32_t len)
-{
- struct rb_nand_softc *sc;
- int i;
- uint8_t *b = (uint8_t*)buf;
-
- sc = device_get_softc(dev);
-
- for (i = 0; i < len; i++) {
-#ifdef NAND_DEBUG
- if (!(i % 16))
- printf("%s", i == 0 ? "rb_nand:\n" : "\n");
- printf(" %x", b[i]);
- if (i == len - 1)
- printf("\n");
-#endif
- bus_write_1(sc->sc_mem, RB_NAND_DATA, b[i]);
- }
-}
-
-static int
-rb_nand_select_cs(device_t dev, uint8_t cs)
-{
-
- if (cs > 0)
- return (ENODEV);
-
- return (0);
-}
-
-static int
-rb_nand_read_rnb(device_t dev)
-{
- struct rb_nand_softc *sc;
- uint32_t rdy_bit;
-
- sc = device_get_softc(dev);
- GPIO_PIN_GET(sc->sc_gpio, sc->sc_rdy_pin, &rdy_bit);
-
- return (rdy_bit); /* ready */
-}
diff --git a/sys/dev/ow/owc_gpiobus.c b/sys/dev/ow/owc_gpiobus.c
index f03d01432b03f..24a18789bea88 100644
--- a/sys/dev/ow/owc_gpiobus.c
+++ b/sys/dev/ow/owc_gpiobus.c
@@ -416,5 +416,7 @@ static driver_t owc_gpiobus_driver = {
sizeof(struct owc_gpiobus_softc),
};
-DRIVER_MODULE(owc_gpiobus_fdt, gpiobus, owc_gpiobus_driver, owc_gpiobus_devclass, 0, 0);
-MODULE_DEPEND(owc_gpiobus_fdt, ow, 1, 1, 1);
+DRIVER_MODULE(owc_gpiobus, gpiobus, owc_gpiobus_driver, owc_gpiobus_devclass, 0, 0);
+MODULE_DEPEND(owc_gpiobus, ow, 1, 1, 1);
+MODULE_DEPEND(owc_gpiobus, gpiobus, 1, 1, 1);
+MODULE_VERSION(owc_gpiobus, 1);
diff --git a/sys/dev/usb/usb_hub_acpi.c b/sys/dev/usb/usb_hub_acpi.c
index 5dd9f06ebaa45..b536a3d282e9e 100644
--- a/sys/dev/usb/usb_hub_acpi.c
+++ b/sys/dev/usb/usb_hub_acpi.c
@@ -243,13 +243,14 @@ acpi_uhub_parse_pld(device_t dev, unsigned int port, ACPI_HANDLE ah)
}
ACPI_STATUS
-acpi_uhub_find_rh(device_t dev, ACPI_HANDLE * ah){
+acpi_uhub_find_rh(device_t dev, ACPI_HANDLE * ah)
+{
device_t grand;
ACPI_HANDLE gah;
+ *ah = NULL;
grand = device_get_parent(device_get_parent(dev));
if ((gah = acpi_get_handle(grand)) == NULL) {
- *ah = NULL;
return AE_ERROR;
}
return AcpiWalkNamespace(ACPI_TYPE_DEVICE, gah, 1,
@@ -257,7 +258,8 @@ acpi_uhub_find_rh(device_t dev, ACPI_HANDLE * ah){
}
ACPI_STATUS
-acpi_usb_hub_port_probe_cb(ACPI_HANDLE ah, UINT32 lv, void *ctx, void **rv){
+acpi_usb_hub_port_probe_cb(ACPI_HANDLE ah, UINT32 lv, void *ctx, void **rv)
+{
ACPI_DEVICE_INFO *devinfo;
device_t dev = ctx;
struct acpi_uhub_softc *sc = device_get_softc(dev);
@@ -281,7 +283,8 @@ acpi_usb_hub_port_probe_cb(ACPI_HANDLE ah, UINT32 lv, void *ctx, void **rv){
}
ACPI_STATUS
-acpi_usb_hub_port_probe(device_t dev, ACPI_HANDLE ah){
+acpi_usb_hub_port_probe(device_t dev, ACPI_HANDLE ah)
+{
return AcpiWalkNamespace(ACPI_TYPE_DEVICE,
ah, 1,
acpi_usb_hub_port_probe_cb,
@@ -293,6 +296,9 @@ acpi_uhub_root_probe(device_t dev)
ACPI_HANDLE ah;
ACPI_STATUS status;
+ if(acpi_disabled("usb")) {
+ return ENXIO;
+ }
status = acpi_uhub_find_rh(dev, &ah);
if (ACPI_SUCCESS(status)
&& ah != NULL
@@ -308,7 +314,7 @@ acpi_uhub_probe(device_t dev)
{
ACPI_HANDLE ah = acpi_get_handle(dev);
- if (ah && (uhub_probe(dev) <= 0)) {
+ if (!acpi_disabled("usb") && ah && (uhub_probe(dev) <= 0)) {
/*success prior than non - acpi hub*/
return (BUS_PROBE_DEFAULT + 1);
}
@@ -335,7 +341,6 @@ acpi_uhub_root_attach(device_t dev)
sc->nports = uh->nports;
sc->porthandle = malloc(sizeof(ACPI_HANDLE) * uh->nports,
M_USBDEV, M_WAITOK | M_ZERO);
- acpi_uhub_find_rh(dev, &devhandle);
acpi_usb_hub_port_probe(dev, devhandle);
return 0;
diff --git a/sys/dev/virtio/scsi/virtio_scsi.c b/sys/dev/virtio/scsi/virtio_scsi.c
index ec98178d5697d..6f2dfbcac5a46 100644
--- a/sys/dev/virtio/scsi/virtio_scsi.c
+++ b/sys/dev/virtio/scsi/virtio_scsi.c
@@ -81,6 +81,7 @@ static void vtscsi_read_config(struct vtscsi_softc *,
struct virtio_scsi_config *);
static int vtscsi_maximum_segments(struct vtscsi_softc *, int);
static int vtscsi_alloc_virtqueues(struct vtscsi_softc *);
+static void vtscsi_check_sizes(struct vtscsi_softc *);
static void vtscsi_write_device_config(struct vtscsi_softc *);
static int vtscsi_reinit(struct vtscsi_softc *);
@@ -311,6 +312,8 @@ vtscsi_attach(device_t dev)
goto fail;
}
+ vtscsi_check_sizes(sc);
+
error = vtscsi_init_event_vq(sc);
if (error) {
device_printf(dev, "cannot populate the eventvq\n");
@@ -478,6 +481,26 @@ vtscsi_alloc_virtqueues(struct vtscsi_softc *sc)
}
static void
+vtscsi_check_sizes(struct vtscsi_softc *sc)
+{
+ int rqsize;
+
+ if ((sc->vtscsi_flags & VTSCSI_FLAG_INDIRECT) == 0) {
+ /*
+ * Ensure the assertions in virtqueue_enqueue(),
+ * even if the hypervisor reports a bad seg_max.
+ */
+ rqsize = virtqueue_size(sc->vtscsi_request_vq);
+ if (sc->vtscsi_max_nsegs > rqsize) {
+ device_printf(sc->vtscsi_dev,
+ "clamping seg_max (%d %d)\n", sc->vtscsi_max_nsegs,
+ rqsize);
+ sc->vtscsi_max_nsegs = rqsize;
+ }
+ }
+}
+
+static void
vtscsi_write_device_config(struct vtscsi_softc *sc)
{
diff --git a/sys/fs/cuse/cuse.c b/sys/fs/cuse/cuse.c
index 578bf3eda74f7..765fe308af7bb 100644
--- a/sys/fs/cuse/cuse.c
+++ b/sys/fs/cuse/cuse.c
@@ -671,8 +671,6 @@ cuse_server_unref(struct cuse_server *pcs)
TAILQ_REMOVE(&cuse_server_head, pcs, entry);
- cuse_free_unit_by_id_locked(pcs, -1);
-
while ((pcsd = TAILQ_FIRST(&pcs->hdev)) != NULL) {
TAILQ_REMOVE(&pcs->hdev, pcsd, entry);
cuse_unlock();
@@ -680,6 +678,8 @@ cuse_server_unref(struct cuse_server *pcs)
cuse_lock();
}
+ cuse_free_unit_by_id_locked(pcs, -1);
+
while ((mem = TAILQ_FIRST(&pcs->hmem)) != NULL) {
TAILQ_REMOVE(&pcs->hmem, mem, entry);
cuse_unlock();
@@ -699,12 +699,38 @@ cuse_server_unref(struct cuse_server *pcs)
free(pcs, M_CUSE);
}
+static int
+cuse_server_do_close(struct cuse_server *pcs)
+{
+ int retval;
+
+ cuse_lock();
+ cuse_server_is_closing(pcs);
+ /* final client wakeup, if any */
+ cuse_server_wakeup_all_client_locked(pcs);
+
+ knlist_clear(&pcs->selinfo.si_note, 1);
+
+ retval = pcs->refs;
+ cuse_unlock();
+
+ return (retval);
+}
+
static void
cuse_server_free(void *arg)
{
struct cuse_server *pcs = arg;
- /* drop refcount */
+ /*
+ * The final server unref should be done by the server thread
+ * to prevent deadlock in the client cdevpriv destructor,
+ * which cannot destroy itself.
+ */
+ while (cuse_server_do_close(pcs) != 1)
+ pause("W", hz);
+
+ /* drop final refcount */
cuse_server_unref(pcs);
}
@@ -746,21 +772,10 @@ static int
cuse_server_close(struct cdev *dev, int fflag, int devtype, struct thread *td)
{
struct cuse_server *pcs;
- int error;
- error = cuse_server_get(&pcs);
- if (error != 0)
- goto done;
+ if (cuse_server_get(&pcs) == 0)
+ cuse_server_do_close(pcs);
- cuse_lock();
- cuse_server_is_closing(pcs);
- /* final client wakeup, if any */
- cuse_server_wakeup_all_client_locked(pcs);
-
- knlist_clear(&pcs->selinfo.si_note, 1);
- cuse_unlock();
-
-done:
return (0);
}
diff --git a/sys/fs/fifofs/fifo_vnops.c b/sys/fs/fifofs/fifo_vnops.c
index 96dd05a183236..b4fefbde79a67 100644
--- a/sys/fs/fifofs/fifo_vnops.c
+++ b/sys/fs/fifofs/fifo_vnops.c
@@ -174,7 +174,7 @@ fifo_open(ap)
if (fip->fi_writers > 0)
wakeup(&fip->fi_writers);
}
- fp->f_seqcount = fpipe->pipe_wgen - fip->fi_writers;
+ fp->f_pipegen = fpipe->pipe_wgen - fip->fi_writers;
}
if (ap->a_mode & FWRITE) {
if ((ap->a_mode & O_NONBLOCK) && fip->fi_readers == 0) {
diff --git a/sys/fs/nandfs/bmap.c b/sys/fs/nandfs/bmap.c
deleted file mode 100644
index 5721cf0157bc7..0000000000000
--- a/sys/fs/nandfs/bmap.c
+++ /dev/null
@@ -1,625 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/namei.h>
-#include <sys/kernel.h>
-#include <sys/stat.h>
-#include <sys/buf.h>
-#include <sys/bio.h>
-#include <sys/proc.h>
-#include <sys/mount.h>
-#include <sys/vnode.h>
-#include <sys/signalvar.h>
-#include <sys/malloc.h>
-#include <sys/dirent.h>
-#include <sys/lockf.h>
-#include <sys/ktr.h>
-#include <sys/kdb.h>
-
-#include <vm/vm.h>
-#include <vm/vm_extern.h>
-#include <vm/vm_object.h>
-#include <vm/vnode_pager.h>
-
-#include <machine/_inttypes.h>
-
-#include <vm/vm.h>
-#include <vm/vm_extern.h>
-#include <vm/vm_object.h>
-#include <vm/vnode_pager.h>
-
-#include "nandfs_mount.h"
-#include "nandfs.h"
-#include "nandfs_subr.h"
-#include "bmap.h"
-
-static int bmap_getlbns(struct nandfs_node *, nandfs_lbn_t,
- struct nandfs_indir *, int *);
-
-int
-bmap_lookup(struct nandfs_node *node, nandfs_lbn_t lblk, nandfs_daddr_t *vblk)
-{
- struct nandfs_inode *ip;
- struct nandfs_indir a[NANDFS_NIADDR + 1], *ap;
- nandfs_daddr_t daddr;
- struct buf *bp;
- int error;
- int num, *nump;
-
- DPRINTF(BMAP, ("%s: node %p lblk %jx enter\n", __func__, node, lblk));
- ip = &node->nn_inode;
-
- ap = a;
- nump = &num;
-
- error = bmap_getlbns(node, lblk, ap, nump);
- if (error)
- return (error);
-
- if (num == 0) {
- *vblk = ip->i_db[lblk];
- return (0);
- }
-
- DPRINTF(BMAP, ("%s: node %p lblk=%jx trying ip->i_ib[%x]\n", __func__,
- node, lblk, ap->in_off));
- daddr = ip->i_ib[ap->in_off];
- for (bp = NULL, ++ap; --num; ap++) {
- if (daddr == 0) {
- DPRINTF(BMAP, ("%s: node %p lblk=%jx returning with "
- "vblk 0\n", __func__, node, lblk));
- *vblk = 0;
- return (0);
- }
- if (ap->in_lbn == lblk) {
- DPRINTF(BMAP, ("%s: node %p lblk=%jx ap->in_lbn=%jx "
- "returning address of indirect block (%jx)\n",
- __func__, node, lblk, ap->in_lbn, daddr));
- *vblk = daddr;
- return (0);
- }
-
- DPRINTF(BMAP, ("%s: node %p lblk=%jx reading block "
- "ap->in_lbn=%jx\n", __func__, node, lblk, ap->in_lbn));
-
- error = nandfs_bread_meta(node, ap->in_lbn, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
-
- daddr = ((nandfs_daddr_t *)bp->b_data)[ap->in_off];
- brelse(bp);
- }
-
- DPRINTF(BMAP, ("%s: node %p lblk=%jx returning with %jx\n", __func__,
- node, lblk, daddr));
- *vblk = daddr;
-
- return (0);
-}
-
-int
-bmap_dirty_meta(struct nandfs_node *node, nandfs_lbn_t lblk, int force)
-{
- struct nandfs_indir a[NANDFS_NIADDR+1], *ap;
-#ifdef DEBUG
- nandfs_daddr_t daddr;
-#endif
- struct buf *bp;
- int error;
- int num, *nump;
-
- DPRINTF(BMAP, ("%s: node %p lblk=%jx\n", __func__, node, lblk));
-
- ap = a;
- nump = &num;
-
- error = bmap_getlbns(node, lblk, ap, nump);
- if (error)
- return (error);
-
- /*
- * Direct block, nothing to do
- */
- if (num == 0)
- return (0);
-
- DPRINTF(BMAP, ("%s: node %p reading blocks\n", __func__, node));
-
- for (bp = NULL, ++ap; --num; ap++) {
- error = nandfs_bread_meta(node, ap->in_lbn, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
-
-#ifdef DEBUG
- daddr = ((nandfs_daddr_t *)bp->b_data)[ap->in_off];
- MPASS(daddr != 0 || node->nn_ino == 3);
-#endif
-
- error = nandfs_dirty_buf_meta(bp, force);
- if (error)
- return (error);
- }
-
- return (0);
-}
-
-int
-bmap_insert_block(struct nandfs_node *node, nandfs_lbn_t lblk,
- nandfs_daddr_t vblk)
-{
- struct nandfs_inode *ip;
- struct nandfs_indir a[NANDFS_NIADDR+1], *ap;
- struct buf *bp;
- nandfs_daddr_t daddr;
- int error;
- int num, *nump, i;
-
- DPRINTF(BMAP, ("%s: node %p lblk=%jx vblk=%jx\n", __func__, node, lblk,
- vblk));
-
- ip = &node->nn_inode;
-
- ap = a;
- nump = &num;
-
- error = bmap_getlbns(node, lblk, ap, nump);
- if (error)
- return (error);
-
- DPRINTF(BMAP, ("%s: node %p lblk=%jx vblk=%jx got num=%d\n", __func__,
- node, lblk, vblk, num));
-
- if (num == 0) {
- DPRINTF(BMAP, ("%s: node %p lblk=%jx direct block\n", __func__,
- node, lblk));
- ip->i_db[lblk] = vblk;
- return (0);
- }
-
- DPRINTF(BMAP, ("%s: node %p lblk=%jx indirect block level %d\n",
- __func__, node, lblk, ap->in_off));
-
- if (num == 1) {
- DPRINTF(BMAP, ("%s: node %p lblk=%jx indirect block: inserting "
- "%jx as vblk for indirect block %d\n", __func__, node,
- lblk, vblk, ap->in_off));
- ip->i_ib[ap->in_off] = vblk;
- return (0);
- }
-
- bp = NULL;
- daddr = ip->i_ib[a[0].in_off];
- for (i = 1; i < num; i++) {
- if (bp)
- brelse(bp);
- if (daddr == 0) {
- DPRINTF(BMAP, ("%s: node %p lblk=%jx vblk=%jx create "
- "block %jx %d\n", __func__, node, lblk, vblk,
- a[i].in_lbn, a[i].in_off));
- error = nandfs_bcreate_meta(node, a[i].in_lbn, NOCRED,
- 0, &bp);
- if (error)
- return (error);
- } else {
- DPRINTF(BMAP, ("%s: node %p lblk=%jx vblk=%jx read "
- "block %jx %d\n", __func__, node, daddr, vblk,
- a[i].in_lbn, a[i].in_off));
- error = nandfs_bread_meta(node, a[i].in_lbn, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
- }
- daddr = ((nandfs_daddr_t *)bp->b_data)[a[i].in_off];
- }
- i--;
-
- DPRINTF(BMAP,
- ("%s: bmap node %p lblk=%jx vblk=%jx inserting vblk level %d at "
- "offset %d at %jx\n", __func__, node, lblk, vblk, i, a[i].in_off,
- daddr));
-
- if (!bp) {
- nandfs_error("%s: cannot find indirect block\n", __func__);
- return (-1);
- }
- ((nandfs_daddr_t *)bp->b_data)[a[i].in_off] = vblk;
-
- error = nandfs_dirty_buf_meta(bp, 0);
- if (error) {
- nandfs_warning("%s: dirty failed buf: %p\n", __func__, bp);
- return (error);
- }
- DPRINTF(BMAP, ("%s: exiting node %p lblk=%jx vblk=%jx\n", __func__,
- node, lblk, vblk));
-
- return (error);
-}
-
-CTASSERT(NANDFS_NIADDR <= 3);
-#define SINGLE 0 /* index of single indirect block */
-#define DOUBLE 1 /* index of double indirect block */
-#define TRIPLE 2 /* index of triple indirect block */
-
-static __inline nandfs_lbn_t
-lbn_offset(struct nandfs_device *fsdev, int level)
-{
- nandfs_lbn_t res;
-
- for (res = 1; level > 0; level--)
- res *= MNINDIR(fsdev);
- return (res);
-}
-
-static nandfs_lbn_t
-blocks_inside(struct nandfs_device *fsdev, int level, struct nandfs_indir *nip)
-{
- nandfs_lbn_t blocks;
-
- for (blocks = 1; level >= SINGLE; level--, nip++) {
- MPASS(nip->in_off >= 0 && nip->in_off < MNINDIR(fsdev));
- blocks += nip->in_off * lbn_offset(fsdev, level);
- }
-
- return (blocks);
-}
-
-static int
-bmap_truncate_indirect(struct nandfs_node *node, int level, nandfs_lbn_t *left,
- int *cleaned, struct nandfs_indir *ap, struct nandfs_indir *fp,
- nandfs_daddr_t *copy)
-{
- struct buf *bp;
- nandfs_lbn_t i, lbn, nlbn, factor, tosub;
- struct nandfs_device *fsdev;
- int error, lcleaned, modified;
-
- DPRINTF(BMAP, ("%s: node %p level %d left %jx\n", __func__,
- node, level, *left));
-
- fsdev = node->nn_nandfsdev;
-
- MPASS(ap->in_off >= 0 && ap->in_off < MNINDIR(fsdev));
-
- factor = lbn_offset(fsdev, level);
- lbn = ap->in_lbn;
-
- error = nandfs_bread_meta(node, lbn, NOCRED, 0, &bp);
- if (error) {
- if (bp != NULL)
- brelse(bp);
- return (error);
- }
-
- bcopy(bp->b_data, copy, fsdev->nd_blocksize);
- bqrelse(bp);
-
- modified = 0;
-
- i = ap->in_off;
-
- if (ap != fp)
- ap++;
- for (nlbn = lbn + 1 - i * factor; i >= 0 && *left > 0; i--,
- nlbn += factor) {
- lcleaned = 0;
-
- DPRINTF(BMAP,
- ("%s: node %p i=%jx nlbn=%jx left=%jx ap=%p vblk %jx\n",
- __func__, node, i, nlbn, *left, ap, copy[i]));
-
- if (copy[i] == 0) {
- tosub = blocks_inside(fsdev, level - 1, ap);
- if (tosub > *left)
- tosub = 0;
-
- *left -= tosub;
- } else {
- if (level > SINGLE) {
- if (ap == fp)
- ap->in_lbn = nlbn;
-
- error = bmap_truncate_indirect(node, level - 1,
- left, &lcleaned, ap, fp,
- copy + MNINDIR(fsdev));
- if (error)
- return (error);
- } else {
- error = nandfs_bdestroy(node, copy[i]);
- if (error)
- return (error);
- lcleaned = 1;
- *left -= 1;
- }
- }
-
- if (lcleaned) {
- if (level > SINGLE) {
- error = nandfs_vblock_end(fsdev, copy[i]);
- if (error)
- return (error);
- }
- copy[i] = 0;
- modified++;
- }
-
- ap = fp;
- }
-
- if (i == -1)
- *cleaned = 1;
-
- error = nandfs_bread_meta(node, lbn, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
- if (modified)
- bcopy(copy, bp->b_data, fsdev->nd_blocksize);
-
- /* Force success even if we can't dirty the buffer metadata when freeing space */
- nandfs_dirty_buf_meta(bp, 1);
-
- return (0);
-}
-
-int
-bmap_truncate_mapping(struct nandfs_node *node, nandfs_lbn_t lastblk,
- nandfs_lbn_t todo)
-{
- struct nandfs_inode *ip;
- struct nandfs_indir a[NANDFS_NIADDR + 1], f[NANDFS_NIADDR], *ap;
- nandfs_daddr_t indir_lbn[NANDFS_NIADDR];
- nandfs_daddr_t *copy;
- int error, level;
- nandfs_lbn_t left, tosub;
- struct nandfs_device *fsdev;
- int cleaned, i;
- int num, *nump;
-
- DPRINTF(BMAP, ("%s: node %p lastblk %jx truncating by %jx\n", __func__,
- node, lastblk, todo));
-
- ip = &node->nn_inode;
- fsdev = node->nn_nandfsdev;
-
- ap = a;
- nump = &num;
-
- error = bmap_getlbns(node, lastblk, ap, nump);
- if (error)
- return (error);
-
- indir_lbn[SINGLE] = -NANDFS_NDADDR;
- indir_lbn[DOUBLE] = indir_lbn[SINGLE] - MNINDIR(fsdev) - 1;
- indir_lbn[TRIPLE] = indir_lbn[DOUBLE] - MNINDIR(fsdev)
- * MNINDIR(fsdev) - 1;
-
- for (i = 0; i < NANDFS_NIADDR; i++) {
- f[i].in_off = MNINDIR(fsdev) - 1;
- f[i].in_lbn = 0xdeadbeef;
- }
-
- left = todo;
-
-#ifdef DEBUG
- a[num].in_off = -1;
-#endif
-
- ap++;
- num -= 2;
-
- if (num < 0)
- goto direct;
-
- copy = malloc(MNINDIR(fsdev) * sizeof(nandfs_daddr_t) * (num + 1),
- M_NANDFSTEMP, M_WAITOK);
-
- for (level = num; level >= SINGLE && left > 0; level--) {
- cleaned = 0;
-
- if (ip->i_ib[level] == 0) {
- tosub = blocks_inside(fsdev, level, ap);
- if (tosub > left)
- left = 0;
- else
- left -= tosub;
- } else {
- if (ap == f)
- ap->in_lbn = indir_lbn[level];
- error = bmap_truncate_indirect(node, level, &left,
- &cleaned, ap, f, copy);
- if (error) {
- free(copy, M_NANDFSTEMP);
- nandfs_error("%s: error %d when truncate "
- "at level %d\n", __func__, error, level);
- return (error);
- }
- }
-
- if (cleaned) {
- nandfs_vblock_end(fsdev, ip->i_ib[level]);
- ip->i_ib[level] = 0;
- }
-
- ap = f;
- }
-
- free(copy, M_NANDFSTEMP);
-
-direct:
- if (num < 0)
- i = lastblk;
- else
- i = NANDFS_NDADDR - 1;
-
- for (; i >= 0 && left > 0; i--) {
- if (ip->i_db[i] != 0) {
- error = nandfs_bdestroy(node, ip->i_db[i]);
- if (error) {
- nandfs_error("%s: cannot destroy "
- "block %jx, error %d\n", __func__,
- (uintmax_t)ip->i_db[i], error);
- return (error);
- }
- ip->i_db[i] = 0;
- }
-
- left--;
- }
-
- KASSERT(left == 0,
- ("truncated wrong number of blocks (%jd should be 0)", left));
-
- return (error);
-}
-
-nandfs_lbn_t
-get_maxfilesize(struct nandfs_device *fsdev)
-{
- struct nandfs_indir f[NANDFS_NIADDR];
- nandfs_lbn_t max;
- int i;
-
- max = NANDFS_NDADDR;
-
- for (i = 0; i < NANDFS_NIADDR; i++) {
- f[i].in_off = MNINDIR(fsdev) - 1;
- max += blocks_inside(fsdev, i, f);
- }
-
- max *= fsdev->nd_blocksize;
-
- return (max);
-}
-
-/*
- * This is ufs_getlbns with minor modifications.
- */
-/*
- * Create an array of logical block number/offset pairs which represent the
- * path of indirect blocks required to access a data block. The first "pair"
- * contains the logical block number of the appropriate single, double or
- * triple indirect block and the offset into the inode indirect block array.
- * Note, the logical block number of the inode single/double/triple indirect
- * block appears twice in the array, once with the offset into the i_ib and
- * once with the offset into the page itself.
- */
-static int
-bmap_getlbns(struct nandfs_node *node, nandfs_lbn_t bn, struct nandfs_indir *ap, int *nump)
-{
- nandfs_daddr_t blockcnt;
- nandfs_lbn_t metalbn, realbn;
- struct nandfs_device *fsdev;
- int i, numlevels, off;
-
- fsdev = node->nn_nandfsdev;
-
- DPRINTF(BMAP, ("%s: node %p bn=%jx mnindir=%zd enter\n", __func__,
- node, bn, MNINDIR(fsdev)));
-
- if (nump)
- *nump = 0;
- numlevels = 0;
- realbn = bn;
-
- if (bn < 0)
- bn = -bn;
-
- /* The first NANDFS_NDADDR blocks are direct blocks. */
- if (bn < NANDFS_NDADDR)
- return (0);
-
- /*
- * Determine the number of levels of indirection. After this loop
- * is done, blockcnt indicates the number of data blocks possible
- * at the previous level of indirection, and NANDFS_NIADDR - i is the
- * number of levels of indirection needed to locate the requested block.
- */
- for (blockcnt = 1, i = NANDFS_NIADDR, bn -= NANDFS_NDADDR;; i--, bn -= blockcnt) {
- DPRINTF(BMAP, ("%s: blockcnt=%jd i=%d bn=%jd\n", __func__,
- blockcnt, i, bn));
- if (i == 0)
- return (EFBIG);
- blockcnt *= MNINDIR(fsdev);
- if (bn < blockcnt)
- break;
- }
-
- /* Calculate the address of the first meta-block. */
- if (realbn >= 0)
- metalbn = -(realbn - bn + NANDFS_NIADDR - i);
- else
- metalbn = -(-realbn - bn + NANDFS_NIADDR - i);
-
- /*
- * At each iteration, off is the offset into the bap array which is
- * an array of disk addresses at the current level of indirection.
- * The logical block number and the offset in that block are stored
- * into the argument array.
- */
- ap->in_lbn = metalbn;
- ap->in_off = off = NANDFS_NIADDR - i;
-
- DPRINTF(BMAP, ("%s: initial: ap->in_lbn=%jx ap->in_off=%d\n", __func__,
- metalbn, off));
-
- ap++;
- for (++numlevels; i <= NANDFS_NIADDR; i++) {
- /* If searching for a meta-data block, quit when found. */
- if (metalbn == realbn)
- break;
-
- blockcnt /= MNINDIR(fsdev);
- off = (bn / blockcnt) % MNINDIR(fsdev);
-
- ++numlevels;
- ap->in_lbn = metalbn;
- ap->in_off = off;
-
- DPRINTF(BMAP, ("%s: in_lbn=%jx in_off=%d\n", __func__,
- ap->in_lbn, ap->in_off));
- ++ap;
-
- metalbn -= -1 + off * blockcnt;
- }
- if (nump)
- *nump = numlevels;
-
- DPRINTF(BMAP, ("%s: numlevels=%d\n", __func__, numlevels));
-
- return (0);
-}
diff --git a/sys/fs/nandfs/bmap.h b/sys/fs/nandfs/bmap.h
deleted file mode 100644
index a4784f7a88f98..0000000000000
--- a/sys/fs/nandfs/bmap.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef _BMAP_H
-#define _BMAP_H
-
-#include "nandfs_fs.h"
-
-int bmap_lookup(struct nandfs_node *, nandfs_lbn_t, nandfs_daddr_t *);
-int bmap_insert_block(struct nandfs_node *, nandfs_lbn_t, nandfs_daddr_t);
-int bmap_truncate_mapping(struct nandfs_node *, nandfs_lbn_t, nandfs_lbn_t);
-int bmap_dirty_meta(struct nandfs_node *, nandfs_lbn_t, int);
-
-nandfs_lbn_t get_maxfilesize(struct nandfs_device *);
-
-#endif /* _BMAP_H */
diff --git a/sys/fs/nandfs/nandfs.h b/sys/fs/nandfs/nandfs.h
deleted file mode 100644
index 9a9b28a1bc0ba..0000000000000
--- a/sys/fs/nandfs/nandfs.h
+++ /dev/null
@@ -1,312 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2010-2012 Semihalf
- * Copyright (c) 2008, 2009 Reinoud Zandijk
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * From: NetBSD: nilfs.h,v 1.1 2009/07/18 16:31:42 reinoud
- *
- * $FreeBSD$
- */
-
-#ifndef _FS_NANDFS_NANDFS_H_
-#define _FS_NANDFS_NANDFS_H_
-
-#include <sys/param.h>
-#include <sys/proc.h>
-#include <sys/condvar.h>
-#include <sys/lock.h>
-#include <sys/mutex.h>
-
-#include <sys/queue.h>
-#include <sys/uio.h>
-#include <sys/mutex.h>
-
-#include <sys/disk.h>
-#include <sys/kthread.h>
-#include "nandfs_fs.h"
-
-MALLOC_DECLARE(M_NANDFSTEMP);
-
-/* Debug categories */
-#define NANDFS_DEBUG_VOLUMES 0x000001
-#define NANDFS_DEBUG_BLOCK 0x000004
-#define NANDFS_DEBUG_LOCKING 0x000008
-#define NANDFS_DEBUG_NODE 0x000010
-#define NANDFS_DEBUG_LOOKUP 0x000020
-#define NANDFS_DEBUG_READDIR 0x000040
-#define NANDFS_DEBUG_TRANSLATE 0x000080
-#define NANDFS_DEBUG_STRATEGY 0x000100
-#define NANDFS_DEBUG_READ 0x000200
-#define NANDFS_DEBUG_WRITE 0x000400
-#define NANDFS_DEBUG_IFILE 0x000800
-#define NANDFS_DEBUG_ATTR 0x001000
-#define NANDFS_DEBUG_EXTATTR 0x002000
-#define NANDFS_DEBUG_ALLOC 0x004000
-#define NANDFS_DEBUG_CPFILE 0x008000
-#define NANDFS_DEBUG_DIRHASH 0x010000
-#define NANDFS_DEBUG_NOTIMPL 0x020000
-#define NANDFS_DEBUG_SHEDULE 0x040000
-#define NANDFS_DEBUG_SEG 0x080000
-#define NANDFS_DEBUG_SYNC 0x100000
-#define NANDFS_DEBUG_PARANOIA 0x200000
-#define NANDFS_DEBUG_VNCALL 0x400000
-#define NANDFS_DEBUG_BUF 0x1000000
-#define NANDFS_DEBUG_BMAP 0x2000000
-#define NANDFS_DEBUG_DAT 0x4000000
-#define NANDFS_DEBUG_GENERIC 0x8000000
-#define NANDFS_DEBUG_CLEAN 0x10000000
-
-extern int nandfs_verbose;
-
-#define DPRINTF(name, arg) { \
- if (nandfs_verbose & NANDFS_DEBUG_##name) {\
- printf arg;\
- };\
- }
-#define DPRINTFIF(name, cond, arg) { \
- if (nandfs_verbose & NANDFS_DEBUG_##name) { \
- if (cond) printf arg;\
- };\
- }
-
-#define VFSTONANDFS(mp) ((struct nandfsmount *)((mp)->mnt_data))
-#define VTON(vp) ((struct nandfs_node *)(vp)->v_data)
-#define NTOV(xp) ((xp)->nn_vnode)
-
-int nandfs_init(struct vfsconf *);
-int nandfs_uninit(struct vfsconf *);
-
-extern struct vop_vector nandfs_vnodeops;
-extern struct vop_vector nandfs_system_vnodeops;
-
-struct nandfs_node;
-
-/* Structure and derivatives */
-struct nandfs_mdt {
- uint32_t entries_per_block;
- uint32_t entries_per_group;
- uint32_t blocks_per_group;
- uint32_t groups_per_desc_block; /* desc is super group */
- uint32_t blocks_per_desc_block; /* desc is super group */
-};
-
-struct nandfs_segment {
- LIST_ENTRY(nandfs_segment) seg_link;
-
- struct nandfs_device *fsdev;
-
- TAILQ_HEAD(, buf) segsum;
- TAILQ_HEAD(, buf) data;
-
- uint64_t seg_num;
- uint64_t seg_next;
- uint64_t start_block;
- uint32_t num_blocks;
-
- uint32_t nblocks;
- uint32_t nbinfos;
- uint32_t segsum_blocks;
- uint32_t segsum_bytes;
- uint32_t bytes_left;
- char *current_off;
-};
-
-struct nandfs_seginfo {
- LIST_HEAD( ,nandfs_segment) seg_list;
- struct nandfs_segment *curseg;
- struct nandfs_device *fsdev;
- uint32_t blocks;
- uint8_t reiterate;
-};
-
-#define NANDFS_FSSTOR_FAILED 1
-struct nandfs_fsarea {
- int offset;
- int flags;
- int last_used;
-};
-
-extern int nandfs_cleaner_enable;
-extern int nandfs_cleaner_interval;
-extern int nandfs_cleaner_segments;
-
-struct nandfs_device {
- struct vnode *nd_devvp;
- struct g_consumer *nd_gconsumer;
-
- struct thread *nd_syncer;
- struct thread *nd_cleaner;
- int nd_syncer_exit;
- int nd_cleaner_exit;
-
- struct nandfs_fsarea nd_fsarea[NANDFS_NFSAREAS];
- int nd_last_fsarea;
-
- STAILQ_HEAD(nandfs_mnts, nandfsmount) nd_mounts;
- SLIST_ENTRY(nandfs_device) nd_next_device;
-
- /* FS structures */
- struct nandfs_fsdata nd_fsdata;
- struct nandfs_super_block nd_super;
- struct nandfs_segment_summary nd_last_segsum;
- struct nandfs_super_root nd_super_root;
- struct nandfs_node *nd_dat_node;
- struct nandfs_node *nd_cp_node;
- struct nandfs_node *nd_su_node;
- struct nandfs_node *nd_gc_node;
-
- struct nandfs_mdt nd_dat_mdt;
- struct nandfs_mdt nd_ifile_mdt;
-
- struct timespec nd_ts;
-
- /* Synchronization */
- struct mtx nd_mutex;
- struct mtx nd_sync_mtx;
- struct cv nd_sync_cv;
- struct mtx nd_clean_mtx;
- struct cv nd_clean_cv;
- struct lock nd_seg_const;
-
- struct nandfs_seginfo *nd_seginfo;
-
- /* FS geometry */
- uint64_t nd_devsize;
- uint64_t nd_maxfilesize;
- uint32_t nd_blocksize;
- uint32_t nd_erasesize;
-
- uint32_t nd_devblocksize;
-
- uint32_t nd_segs_reserved;
-
- /* Segment usage */
- uint64_t nd_clean_segs;
- uint64_t *nd_free_base;
- uint64_t nd_free_count;
- uint64_t nd_dirty_bufs;
-
- /* Running values */
- uint64_t nd_seg_sequence;
- uint64_t nd_seg_num;
- uint64_t nd_next_seg_num;
- uint64_t nd_last_pseg;
- uint64_t nd_last_cno;
- uint64_t nd_last_ino;
- uint64_t nd_fakevblk;
-
- int nd_mount_state;
- int nd_refcnt;
- int nd_syncing;
- int nd_cleaning;
-};
-
-extern SLIST_HEAD(_nandfs_devices, nandfs_device) nandfs_devices;
-
-#define NANDFS_FORCE_SYNCER 0x1
-#define NANDFS_UMOUNT 0x2
-
-#define SYNCER_UMOUNT 0x0
-#define SYNCER_VFS_SYNC 0x1
-#define SYNCER_BDFLUSH 0x2
-#define SYNCER_FFORCE 0x3
-#define SYNCER_FSYNC 0x4
-#define SYNCER_ROUPD 0x5
-
-static __inline int
-nandfs_writelockflags(struct nandfs_device *fsdev, int flags)
-{
- int error = 0;
-
- if (lockstatus(&fsdev->nd_seg_const) != LK_EXCLUSIVE)
- error = lockmgr(&fsdev->nd_seg_const, flags | LK_SHARED, NULL);
-
- return (error);
-}
-
-static __inline void
-nandfs_writeunlock(struct nandfs_device *fsdev)
-{
-
- if (lockstatus(&fsdev->nd_seg_const) != LK_EXCLUSIVE)
- lockmgr(&(fsdev)->nd_seg_const, LK_RELEASE, NULL);
-}
-
-#define NANDFS_WRITELOCKFLAGS(fsdev, flags) nandfs_writelockflags(fsdev, flags)
-
-#define NANDFS_WRITELOCK(fsdev) NANDFS_WRITELOCKFLAGS(fsdev, 0)
-
-#define NANDFS_WRITEUNLOCK(fsdev) nandfs_writeunlock(fsdev)
-
-#define NANDFS_WRITEASSERT(fsdev) lockmgr_assert(&(fsdev)->nd_seg_const, KA_LOCKED)
-
-/* Specific mountpoint; head or a checkpoint/snapshot */
-struct nandfsmount {
- STAILQ_ENTRY(nandfsmount) nm_next_mount;
-
- struct mount *nm_vfs_mountp;
- struct nandfs_device *nm_nandfsdev;
- struct nandfs_args nm_mount_args;
- struct nandfs_node *nm_ifile_node;
-
- uint8_t nm_flags;
- int8_t nm_ronly;
-};
-
-struct nandfs_node {
- struct vnode *nn_vnode;
- struct nandfsmount *nn_nmp;
- struct nandfs_device *nn_nandfsdev;
- struct lockf *nn_lockf;
-
- uint64_t nn_ino;
- struct nandfs_inode nn_inode;
-
- uint64_t nn_diroff;
- uint32_t nn_flags;
-};
-
-#define IN_ACCESS 0x0001 /* Inode access time update request */
-#define IN_CHANGE 0x0002 /* Inode change time update request */
-#define IN_UPDATE 0x0004 /* Inode was written to; update mtime*/
-#define IN_MODIFIED 0x0008 /* node has been modified */
-#define IN_RENAME 0x0010 /* node is being renamed. */
-
-/* File permissions. */
-#define IEXEC 0000100 /* Executable. */
-#define IWRITE 0000200 /* Writeable. */
-#define IREAD 0000400 /* Readable. */
-#define ISVTX 0001000 /* Sticky bit. */
-#define ISGID 0002000 /* Set-gid. */
-#define ISUID 0004000 /* Set-uid. */
-
-#define PRINT_NODE_FLAGS \
- "\10\1IN_ACCESS\2IN_CHANGE\3IN_UPDATE\4IN_MODIFIED\5IN_RENAME"
-
-#define NANDFS_GATHER(x) ((x)->b_flags |= B_FS_FLAG1)
-#define NANDFS_UNGATHER(x) ((x)->b_flags &= ~B_FS_FLAG1)
-#define NANDFS_ISGATHERED(x) ((x)->b_flags & B_FS_FLAG1)
-
-#endif /* !_FS_NANDFS_NANDFS_H_ */
diff --git a/sys/fs/nandfs/nandfs_alloc.c b/sys/fs/nandfs/nandfs_alloc.c
deleted file mode 100644
index afff174d130d5..0000000000000
--- a/sys/fs/nandfs/nandfs_alloc.c
+++ /dev/null
@@ -1,366 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2010-2012 Semihalf.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/mount.h>
-#include <sys/mutex.h>
-#include <sys/namei.h>
-#include <sys/sysctl.h>
-#include <sys/vnode.h>
-#include <sys/buf.h>
-#include <sys/bio.h>
-
-#include <vm/vm.h>
-#include <vm/vm_param.h>
-#include <vm/vm_kern.h>
-#include <vm/vm_page.h>
-
-#include <fs/nandfs/nandfs_mount.h>
-#include <fs/nandfs/nandfs.h>
-#include <fs/nandfs/nandfs_subr.h>
-
-static void
-nandfs_get_desc_block_nr(struct nandfs_mdt *mdt, uint64_t desc,
- uint64_t *desc_block)
-{
-
- *desc_block = desc * mdt->blocks_per_desc_block;
-}
-
-static void
-nandfs_get_group_block_nr(struct nandfs_mdt *mdt, uint64_t group,
- uint64_t *group_block)
-{
- uint64_t desc, group_off;
-
- desc = group / mdt->groups_per_desc_block;
- group_off = group % mdt->groups_per_desc_block;
- *group_block = desc * mdt->blocks_per_desc_block +
- 1 + group_off * mdt->blocks_per_group;
-}
-
-static void
-init_desc_block(struct nandfs_mdt *mdt, uint8_t *block_data)
-{
- struct nandfs_block_group_desc *desc;
- uint32_t i;
-
- desc = (struct nandfs_block_group_desc *) block_data;
- for (i = 0; i < mdt->groups_per_desc_block; i++)
- desc[i].bg_nfrees = mdt->entries_per_group;
-}
-
-int
-nandfs_find_free_entry(struct nandfs_mdt *mdt, struct nandfs_node *node,
- struct nandfs_alloc_request *req)
-{
- nandfs_daddr_t desc, group, maxgroup, maxdesc, pos = 0;
- nandfs_daddr_t start_group, start_desc;
- nandfs_daddr_t desc_block, group_block;
- nandfs_daddr_t file_blocks;
- struct nandfs_block_group_desc *descriptors;
- struct buf *bp, *bp2;
- uint32_t *mask, i, mcount, msize;
- int error;
-
- file_blocks = node->nn_inode.i_blocks;
- maxgroup = 0x100000000ull / mdt->entries_per_group;
- maxdesc = maxgroup / mdt->groups_per_desc_block;
- start_group = req->entrynum / mdt->entries_per_group;
- start_desc = start_group / mdt->groups_per_desc_block;
-
- bp = bp2 = NULL;
-restart:
- for (desc = start_desc; desc < maxdesc; desc++) {
- nandfs_get_desc_block_nr(mdt, desc, &desc_block);
-
- if (bp)
- brelse(bp);
- if (desc_block < file_blocks) {
- error = nandfs_bread(node, desc_block, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
- } else {
- error = nandfs_bcreate(node, desc_block, NOCRED, 0,
- &bp);
- if (error)
- return (error);
- file_blocks++;
- init_desc_block(mdt, bp->b_data);
- }
-
- descriptors = (struct nandfs_block_group_desc *) bp->b_data;
- for (group = start_group; group < mdt->groups_per_desc_block;
- group++) {
- if (descriptors[group].bg_nfrees > 0) {
- nandfs_get_group_block_nr(mdt, group,
- &group_block);
-
- if (bp2)
- brelse(bp2);
- if (group_block < file_blocks) {
- error = nandfs_bread(node, group_block,
- NOCRED, 0, &bp2);
- if (error) {
- brelse(bp);
- return (error);
- }
- } else {
- error = nandfs_bcreate(node,
- group_block, NOCRED, 0, &bp2);
- if (error)
- return (error);
- file_blocks++;
- }
- mask = (uint32_t *)bp2->b_data;
- msize = (sizeof(uint32_t) * __CHAR_BIT);
- mcount = mdt->entries_per_group / msize;
- for (i = 0; i < mcount; i++) {
- if (mask[i] == UINT32_MAX)
- continue;
-
- pos = ffs(~mask[i]) - 1;
- pos += (msize * i);
- pos += (group * mdt->entries_per_group);
- pos += desc * group *
- mdt->groups_per_desc_block *
- mdt->entries_per_group;
- goto found;
- }
- }
- }
- start_group = 0;
- }
-
- if (start_desc != 0) {
- maxdesc = start_desc;
- start_desc = 0;
- req->entrynum = 0;
- goto restart;
- }
-
- return (ENOENT);
-
-found:
- req->entrynum = pos;
- req->bp_desc = bp;
- req->bp_bitmap = bp2;
- DPRINTF(ALLOC, ("%s: desc: %p bitmap: %p entry: %#jx\n",
- __func__, req->bp_desc, req->bp_bitmap, (uintmax_t)pos));
-
- return (0);
-}
-
-int
-nandfs_find_entry(struct nandfs_mdt* mdt, struct nandfs_node *nnode,
- struct nandfs_alloc_request *req)
-{
- uint64_t dblock, bblock, eblock;
- uint32_t offset;
- int error;
-
- nandfs_mdt_trans_blk(mdt, req->entrynum, &dblock, &bblock, &eblock,
- &offset);
-
- error = nandfs_bread(nnode, dblock, NOCRED, 0, &req->bp_desc);
- if (error) {
- brelse(req->bp_desc);
- return (error);
- }
-
- error = nandfs_bread(nnode, bblock, NOCRED, 0, &req->bp_bitmap);
- if (error) {
- brelse(req->bp_desc);
- brelse(req->bp_bitmap);
- return (error);
- }
-
- error = nandfs_bread(nnode, eblock, NOCRED, 0, &req->bp_entry);
- if (error) {
- brelse(req->bp_desc);
- brelse(req->bp_bitmap);
- brelse(req->bp_entry);
- return (error);
- }
-
- DPRINTF(ALLOC,
- ("%s: desc_buf: %p bitmap_buf %p entry_buf %p offset %x\n",
- __func__, req->bp_desc, req->bp_bitmap, req->bp_entry, offset));
-
- return (0);
-}
-
-static __inline void
-nandfs_calc_idx_entry(struct nandfs_mdt* mdt, uint32_t entrynum,
- uint64_t *group, uint64_t *bitmap_idx, uint64_t *bitmap_off)
-{
-
- /* Find group_desc index */
- entrynum = entrynum %
- (mdt->entries_per_group * mdt->groups_per_desc_block);
- *group = entrynum / mdt->entries_per_group;
- /* Find bitmap index and bit offset */
- entrynum = entrynum % mdt->entries_per_group;
- *bitmap_idx = entrynum / (sizeof(uint32_t) * __CHAR_BIT);
- *bitmap_off = entrynum % (sizeof(uint32_t) * __CHAR_BIT);
-}
-
-int
-nandfs_free_entry(struct nandfs_mdt* mdt, struct nandfs_alloc_request *req)
-{
- struct nandfs_block_group_desc *descriptors;
- uint64_t bitmap_idx, bitmap_off;
- uint64_t group;
- uint32_t *mask, maskrw;
-
- nandfs_calc_idx_entry(mdt, req->entrynum, &group, &bitmap_idx,
- &bitmap_off);
-
- DPRINTF(ALLOC, ("nandfs_free_entry: req->entrynum=%jx bitmap_idx=%jx"
- " bitmap_off=%jx group=%jx\n", (uintmax_t)req->entrynum,
- (uintmax_t)bitmap_idx, (uintmax_t)bitmap_off, (uintmax_t)group));
-
- /* Update counter of free entries for group */
- descriptors = (struct nandfs_block_group_desc *) req->bp_desc->b_data;
- descriptors[group].bg_nfrees++;
-
- /* Set bit to indicate that entry is taken */
- mask = (uint32_t *)req->bp_bitmap->b_data;
- maskrw = mask[bitmap_idx];
- KASSERT(maskrw & (1 << bitmap_off), ("freeing unallocated vblock"));
- maskrw &= ~(1 << bitmap_off);
- mask[bitmap_idx] = maskrw;
-
- /* Make descriptor, bitmap and entry buffer dirty */
- if (nandfs_dirty_buf(req->bp_desc, 0) == 0) {
- nandfs_dirty_buf(req->bp_bitmap, 1);
- nandfs_dirty_buf(req->bp_entry, 1);
- } else {
- brelse(req->bp_bitmap);
- brelse(req->bp_entry);
- return (-1);
- }
-
- return (0);
-}
-
-int
-nandfs_alloc_entry(struct nandfs_mdt* mdt, struct nandfs_alloc_request *req)
-{
- struct nandfs_block_group_desc *descriptors;
- uint64_t bitmap_idx, bitmap_off;
- uint64_t group;
- uint32_t *mask, maskrw;
-
- nandfs_calc_idx_entry(mdt, req->entrynum, &group, &bitmap_idx,
- &bitmap_off);
-
- DPRINTF(ALLOC, ("nandfs_alloc_entry: req->entrynum=%jx bitmap_idx=%jx"
- " bitmap_off=%jx group=%jx\n", (uintmax_t)req->entrynum,
- (uintmax_t)bitmap_idx, (uintmax_t)bitmap_off, (uintmax_t)group));
-
- /* Update counter of free entries for group */
- descriptors = (struct nandfs_block_group_desc *) req->bp_desc->b_data;
- descriptors[group].bg_nfrees--;
-
- /* Clear bit to indicate that entry is free */
- mask = (uint32_t *)req->bp_bitmap->b_data;
- maskrw = mask[bitmap_idx];
- maskrw |= 1 << bitmap_off;
- mask[bitmap_idx] = maskrw;
-
- /* Make descriptor, bitmap and entry buffer dirty */
- if (nandfs_dirty_buf(req->bp_desc, 0) == 0) {
- nandfs_dirty_buf(req->bp_bitmap, 1);
- nandfs_dirty_buf(req->bp_entry, 1);
- } else {
- brelse(req->bp_bitmap);
- brelse(req->bp_entry);
- return (-1);
- }
-
- return (0);
-}
-
-void
-nandfs_abort_entry(struct nandfs_alloc_request *req)
-{
-
- brelse(req->bp_desc);
- brelse(req->bp_bitmap);
- brelse(req->bp_entry);
-}
-
-int
-nandfs_get_entry_block(struct nandfs_mdt *mdt, struct nandfs_node *node,
- struct nandfs_alloc_request *req, uint32_t *entry, int create)
-{
- struct buf *bp;
- nandfs_lbn_t blocknr;
- int error;
-
- /* Find buffer number for given entry */
- nandfs_mdt_trans(mdt, req->entrynum, &blocknr, entry);
- DPRINTF(ALLOC, ("%s: ino %#jx entrynum:%#jx block:%#jx entry:%x\n",
- __func__, (uintmax_t)node->nn_ino, (uintmax_t)req->entrynum,
- (uintmax_t)blocknr, *entry));
-
- /* Read entry block or create if 'create' parameter is not zero */
- bp = NULL;
-
- if (blocknr < node->nn_inode.i_blocks)
- error = nandfs_bread(node, blocknr, NOCRED, 0, &bp);
- else if (create)
- error = nandfs_bcreate(node, blocknr, NOCRED, 0, &bp);
- else
- error = E2BIG;
-
- if (error) {
- DPRINTF(ALLOC, ("%s: ino %#jx block %#jx entry %x error %d\n",
- __func__, (uintmax_t)node->nn_ino, (uintmax_t)blocknr,
- *entry, error));
- if (bp)
- brelse(bp);
- return (error);
- }
-
- MPASS(nandfs_vblk_get(bp) != 0 || node->nn_ino == NANDFS_DAT_INO);
-
- req->bp_entry = bp;
- return (0);
-}
diff --git a/sys/fs/nandfs/nandfs_bmap.c b/sys/fs/nandfs/nandfs_bmap.c
deleted file mode 100644
index 6a1c2b0775d59..0000000000000
--- a/sys/fs/nandfs/nandfs_bmap.c
+++ /dev/null
@@ -1,232 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2010-2012 Semihalf
- * Copyright (c) 2008, 2009 Reinoud Zandijk
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * From: NetBSD: nilfs_subr.c,v 1.4 2009/07/29 17:06:57 reinoud
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/namei.h>
-#include <sys/kernel.h>
-#include <sys/stat.h>
-#include <sys/buf.h>
-#include <sys/bio.h>
-#include <sys/proc.h>
-#include <sys/mount.h>
-#include <sys/vnode.h>
-#include <sys/signalvar.h>
-#include <sys/malloc.h>
-#include <sys/dirent.h>
-#include <sys/lockf.h>
-#include <sys/ktr.h>
-
-#include <vm/vm.h>
-#include <vm/vm_extern.h>
-#include <vm/vm_object.h>
-#include <vm/vnode_pager.h>
-
-#include <machine/_inttypes.h>
-
-#include <vm/vm.h>
-#include <vm/vm_extern.h>
-#include <vm/vm_object.h>
-#include <vm/vnode_pager.h>
-
-#include "nandfs_mount.h"
-#include "nandfs.h"
-#include "nandfs_subr.h"
-#include "bmap.h"
-
-nandfs_lbn_t
-nandfs_get_maxfilesize(struct nandfs_device *fsdev)
-{
-
- return (get_maxfilesize(fsdev));
-}
-
-int
-nandfs_bmap_lookup(struct nandfs_node *node, nandfs_lbn_t lblk,
- nandfs_daddr_t *vblk)
-{
- int error = 0;
-
- if (node->nn_ino == NANDFS_GC_INO && lblk >= 0)
- *vblk = lblk;
- else
- error = bmap_lookup(node, lblk, vblk);
-
- DPRINTF(TRANSLATE, ("%s: error %d ino %#jx lblocknr %#jx -> %#jx\n",
- __func__, error, (uintmax_t)node->nn_ino, (uintmax_t)lblk,
- (uintmax_t)*vblk));
-
- if (error)
- nandfs_error("%s: returned %d", __func__, error);
-
- return (error);
-}
-
-int
-nandfs_bmap_insert_block(struct nandfs_node *node, nandfs_lbn_t lblk,
- struct buf *bp)
-{
- struct nandfs_device *fsdev;
- nandfs_daddr_t vblk;
- int error;
-
- fsdev = node->nn_nandfsdev;
-
- vblk = 0;
- if (node->nn_ino != NANDFS_DAT_INO) {
- error = nandfs_vblock_alloc(fsdev, &vblk);
- if (error)
- return (error);
- }
-
- nandfs_buf_set(bp, NANDFS_VBLK_ASSIGNED);
- nandfs_vblk_set(bp, vblk);
-
- error = bmap_insert_block(node, lblk, vblk);
- if (error) {
- nandfs_vblock_free(fsdev, vblk);
- return (error);
- }
-
- return (0);
-}
-
-int
-nandfs_bmap_dirty_blocks(struct nandfs_node *node, struct buf *bp, int force)
-{
- int error;
-
- error = bmap_dirty_meta(node, bp->b_lblkno, force);
- if (error)
- nandfs_error("%s: cannot dirty buffer %p\n",
- __func__, bp);
-
- return (error);
-}
-
-static int
-nandfs_bmap_update_mapping(struct nandfs_node *node, nandfs_lbn_t lblk,
- nandfs_daddr_t blknr)
-{
- int error;
-
- DPRINTF(BMAP,
- ("%s: node: %p ino: %#jx lblk: %#jx vblk: %#jx\n",
- __func__, node, (uintmax_t)node->nn_ino, (uintmax_t)lblk,
- (uintmax_t)blknr));
-
- error = bmap_insert_block(node, lblk, blknr);
-
- return (error);
-}
-
-int
-nandfs_bmap_update_block(struct nandfs_node *node, struct buf *bp,
- nandfs_lbn_t blknr)
-{
- nandfs_lbn_t lblk;
- int error;
-
- lblk = bp->b_lblkno;
- nandfs_vblk_set(bp, blknr);
-
- DPRINTF(BMAP, ("%s: node: %p ino: %#jx bp: %p lblk: %#jx blk: %#jx\n",
- __func__, node, (uintmax_t)node->nn_ino, bp,
- (uintmax_t)lblk, (uintmax_t)blknr));
-
- error = nandfs_bmap_update_mapping(node, lblk, blknr);
- if (error) {
- nandfs_error("%s: cannot update lblk:%jx to blk:%jx for "
- "node:%p, error:%d\n", __func__, (uintmax_t)lblk,
- (uintmax_t)blknr, node, error);
- return (error);
- }
-
- return (error);
-}
-
-int
-nandfs_bmap_update_dat(struct nandfs_node *node, nandfs_daddr_t oldblk,
- struct buf *bp)
-{
- struct nandfs_device *fsdev;
- nandfs_daddr_t vblk = 0;
- int error;
-
- if (node->nn_ino == NANDFS_DAT_INO)
- return (0);
-
- if (nandfs_buf_check(bp, NANDFS_VBLK_ASSIGNED)) {
- nandfs_buf_clear(bp, NANDFS_VBLK_ASSIGNED);
- return (0);
- }
-
- fsdev = node->nn_nandfsdev;
-
- /* First alloc new virtual block.... */
- error = nandfs_vblock_alloc(fsdev, &vblk);
- if (error)
- return (error);
-
- error = nandfs_bmap_update_block(node, bp, vblk);
- if (error)
- return (error);
-
- /* Then we can end up with old one */
- nandfs_vblock_end(fsdev, oldblk);
-
- DPRINTF(BMAP,
- ("%s: ino %#jx block %#jx: update vblk %#jx to %#jx\n",
- __func__, (uintmax_t)node->nn_ino, (uintmax_t)bp->b_lblkno,
- (uintmax_t)oldblk, (uintmax_t)vblk));
- return (error);
-}
-
-int
-nandfs_bmap_truncate_mapping(struct nandfs_node *node, nandfs_lbn_t oblk,
- nandfs_lbn_t nblk)
-{
- nandfs_lbn_t todo;
- int error;
-
- todo = oblk - nblk;
-
- DPRINTF(BMAP, ("%s: node %p oblk %jx nblk %jx truncate by %jx\n",
- __func__, node, oblk, nblk, todo));
-
- error = bmap_truncate_mapping(node, oblk, todo);
- if (error)
- return (error);
-
- return (error);
-}
diff --git a/sys/fs/nandfs/nandfs_buffer.c b/sys/fs/nandfs/nandfs_buffer.c
deleted file mode 100644
index 57089718554fd..0000000000000
--- a/sys/fs/nandfs/nandfs_buffer.c
+++ /dev/null
@@ -1,85 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2010-2012 Semihalf.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/mount.h>
-#include <sys/mutex.h>
-#include <sys/buf.h>
-#include <sys/namei.h>
-#include <sys/vnode.h>
-#include <sys/bio.h>
-
-#include <fs/nandfs/nandfs_mount.h>
-#include <fs/nandfs/nandfs.h>
-#include <fs/nandfs/nandfs_subr.h>
-
-struct buf *
-nandfs_geteblk(int size, int flags)
-{
- struct buf *bp;
-
- /*
- * XXX
- * Right now we can call geteblk with GB_NOWAIT_BD flag, which means
- * it can return NULL. But we cannot afford to get NULL, hence this panic.
- */
- bp = geteblk(size, flags);
- if (bp == NULL)
- panic("geteblk returned NULL");
-
- return (bp);
-}
-
-void
-nandfs_dirty_bufs_increment(struct nandfs_device *fsdev)
-{
-
- mtx_lock(&fsdev->nd_mutex);
- KASSERT(fsdev->nd_dirty_bufs >= 0, ("negative nd_dirty_bufs"));
- fsdev->nd_dirty_bufs++;
- mtx_unlock(&fsdev->nd_mutex);
-}
-
-void
-nandfs_dirty_bufs_decrement(struct nandfs_device *fsdev)
-{
-
- mtx_lock(&fsdev->nd_mutex);
- KASSERT(fsdev->nd_dirty_bufs > 0,
- ("decrementing not-positive nd_dirty_bufs"));
- fsdev->nd_dirty_bufs--;
- mtx_unlock(&fsdev->nd_mutex);
-}
diff --git a/sys/fs/nandfs/nandfs_cleaner.c b/sys/fs/nandfs/nandfs_cleaner.c
deleted file mode 100644
index 3241c8701bfca..0000000000000
--- a/sys/fs/nandfs/nandfs_cleaner.c
+++ /dev/null
@@ -1,622 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2010-2012 Semihalf.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/mount.h>
-#include <sys/mutex.h>
-#include <sys/buf.h>
-#include <sys/namei.h>
-#include <sys/vnode.h>
-#include <sys/bio.h>
-
-#include <fs/nandfs/nandfs_mount.h>
-#include <fs/nandfs/nandfs.h>
-#include <fs/nandfs/nandfs_subr.h>
-
-#define NANDFS_CLEANER_KILL 1
-
-static void nandfs_cleaner(struct nandfs_device *);
-static int nandfs_cleaner_clean_segments(struct nandfs_device *,
- struct nandfs_vinfo *, uint32_t, struct nandfs_period *, uint32_t,
- struct nandfs_bdesc *, uint32_t, uint64_t *, uint32_t);
-
-static int
-nandfs_process_bdesc(struct nandfs_device *nffsdev, struct nandfs_bdesc *bd,
- uint64_t nmembs);
-
-static void
-nandfs_wakeup_wait_cleaner(struct nandfs_device *fsdev, int reason)
-{
-
- mtx_lock(&fsdev->nd_clean_mtx);
- if (reason == NANDFS_CLEANER_KILL)
- fsdev->nd_cleaner_exit = 1;
- if (fsdev->nd_cleaning == 0) {
- fsdev->nd_cleaning = 1;
- wakeup(&fsdev->nd_cleaning);
- }
- cv_wait(&fsdev->nd_clean_cv, &fsdev->nd_clean_mtx);
- mtx_unlock(&fsdev->nd_clean_mtx);
-}
-
-int
-nandfs_start_cleaner(struct nandfs_device *fsdev)
-{
- int error;
-
- MPASS(fsdev->nd_cleaner == NULL);
-
- fsdev->nd_cleaner_exit = 0;
-
- error = kthread_add((void(*)(void *))nandfs_cleaner, fsdev, NULL,
- &fsdev->nd_cleaner, 0, 0, "nandfs_cleaner");
- if (error)
- printf("nandfs: could not start cleaner: %d\n", error);
-
- return (error);
-}
-
-int
-nandfs_stop_cleaner(struct nandfs_device *fsdev)
-{
-
- MPASS(fsdev->nd_cleaner != NULL);
- nandfs_wakeup_wait_cleaner(fsdev, NANDFS_CLEANER_KILL);
- fsdev->nd_cleaner = NULL;
-
- DPRINTF(CLEAN, ("cleaner stopped\n"));
- return (0);
-}
-
-static int
-nandfs_cleaner_finished(struct nandfs_device *fsdev)
-{
- int exit;
-
- mtx_lock(&fsdev->nd_clean_mtx);
- fsdev->nd_cleaning = 0;
- if (!fsdev->nd_cleaner_exit) {
- DPRINTF(CLEAN, ("%s: sleep\n", __func__));
- msleep(&fsdev->nd_cleaning, &fsdev->nd_clean_mtx, PRIBIO, "-",
- hz * nandfs_cleaner_interval);
- }
- exit = fsdev->nd_cleaner_exit;
- cv_broadcast(&fsdev->nd_clean_cv);
- mtx_unlock(&fsdev->nd_clean_mtx);
- if (exit) {
- DPRINTF(CLEAN, ("%s: no longer active\n", __func__));
- return (1);
- }
-
- return (0);
-}
-
-static void
-print_suinfo(struct nandfs_suinfo *suinfo, int nsegs)
-{
- int i;
-
- for (i = 0; i < nsegs; i++) {
- DPRINTF(CLEAN, ("%jx %jd %c%c%c %10u\n",
- suinfo[i].nsi_num, suinfo[i].nsi_lastmod,
- (suinfo[i].nsi_flags &
- (NANDFS_SEGMENT_USAGE_ACTIVE) ? 'a' : '-'),
- (suinfo[i].nsi_flags &
- (NANDFS_SEGMENT_USAGE_DIRTY) ? 'd' : '-'),
- (suinfo[i].nsi_flags &
- (NANDFS_SEGMENT_USAGE_ERROR) ? 'e' : '-'),
- suinfo[i].nsi_blocks));
- }
-}
-
-static int
-nandfs_cleaner_vblock_is_alive(struct nandfs_device *fsdev,
- struct nandfs_vinfo *vinfo, struct nandfs_cpinfo *cp, uint32_t ncps)
-{
- int64_t idx, min, max;
-
- if (vinfo->nvi_end >= fsdev->nd_last_cno)
- return (1);
-
- if (ncps == 0)
- return (0);
-
- if (vinfo->nvi_end < cp[0].nci_cno ||
- vinfo->nvi_start > cp[ncps - 1].nci_cno)
- return (0);
-
- idx = min = 0;
- max = ncps - 1;
- while (min <= max) {
- idx = (min + max) / 2;
- if (vinfo->nvi_start == cp[idx].nci_cno)
- return (1);
- if (vinfo->nvi_start < cp[idx].nci_cno)
- max = idx - 1;
- else
- min = idx + 1;
- }
-
- return (vinfo->nvi_end >= cp[idx].nci_cno);
-}
-
-static void
-nandfs_cleaner_vinfo_mark_alive(struct nandfs_device *fsdev,
- struct nandfs_vinfo *vinfo, uint32_t nmembs, struct nandfs_cpinfo *cp,
- uint32_t ncps)
-{
- uint32_t i;
-
- for (i = 0; i < nmembs; i++)
- vinfo[i].nvi_alive =
- nandfs_cleaner_vblock_is_alive(fsdev, &vinfo[i], cp, ncps);
-}
-
-static int
-nandfs_cleaner_bdesc_is_alive(struct nandfs_device *fsdev,
- struct nandfs_bdesc *bdesc)
-{
- int alive;
-
- alive = bdesc->bd_oblocknr == bdesc->bd_blocknr;
- if (!alive)
- MPASS(abs(bdesc->bd_oblocknr - bdesc->bd_blocknr) > 2);
-
- return (alive);
-}
-
-static void
-nandfs_cleaner_bdesc_mark_alive(struct nandfs_device *fsdev,
- struct nandfs_bdesc *bdesc, uint32_t nmembs)
-{
- uint32_t i;
-
- for (i = 0; i < nmembs; i++)
- bdesc[i].bd_alive = nandfs_cleaner_bdesc_is_alive(fsdev,
- &bdesc[i]);
-}
-
-static void
-nandfs_cleaner_iterate_psegment(struct nandfs_device *fsdev,
- struct nandfs_segment_summary *segsum, union nandfs_binfo *binfo,
- nandfs_daddr_t blk, struct nandfs_vinfo **vipp, struct nandfs_bdesc **bdpp)
-{
- int i;
-
- DPRINTF(CLEAN, ("%s nbinfos %x\n", __func__, segsum->ss_nbinfos));
- for (i = 0; i < segsum->ss_nbinfos; i++) {
- if (binfo[i].bi_v.bi_ino == NANDFS_DAT_INO) {
- (*bdpp)->bd_oblocknr = blk + segsum->ss_nblocks -
- segsum->ss_nbinfos + i;
- /*
- * XXX Hack
- */
- if (segsum->ss_flags & NANDFS_SS_SR)
- (*bdpp)->bd_oblocknr--;
- (*bdpp)->bd_level = binfo[i].bi_dat.bi_level;
- (*bdpp)->bd_offset = binfo[i].bi_dat.bi_blkoff;
- (*bdpp)++;
- } else {
- (*vipp)->nvi_ino = binfo[i].bi_v.bi_ino;
- (*vipp)->nvi_vblocknr = binfo[i].bi_v.bi_vblocknr;
- (*vipp)++;
- }
- }
-}
-
-static int
-nandfs_cleaner_iterate_segment(struct nandfs_device *fsdev, uint64_t segno,
- struct nandfs_vinfo **vipp, struct nandfs_bdesc **bdpp, int *select)
-{
- struct nandfs_segment_summary *segsum;
- union nandfs_binfo *binfo;
- struct buf *bp;
- uint32_t nblocks;
- nandfs_daddr_t curr, start, end;
- int error = 0;
-
- nandfs_get_segment_range(fsdev, segno, &start, &end);
-
- DPRINTF(CLEAN, ("%s: segno %jx start %jx end %jx\n", __func__, segno,
- start, end));
-
- *select = 0;
-
- for (curr = start; curr < end; curr += nblocks) {
- error = nandfs_dev_bread(fsdev, curr, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- nandfs_error("%s: couldn't load segment summary of %jx: %d\n",
- __func__, segno, error);
- return (error);
- }
-
- segsum = (struct nandfs_segment_summary *)bp->b_data;
- binfo = (union nandfs_binfo *)(bp->b_data + segsum->ss_bytes);
-
- if (!nandfs_segsum_valid(segsum)) {
- brelse(bp);
- nandfs_error("nandfs: invalid summary of segment %jx\n", segno);
- return (error);
- }
-
- DPRINTF(CLEAN, ("%s: %jx magic %x bytes %x nblocks %x nbinfos "
- "%x\n", __func__, segno, segsum->ss_magic, segsum->ss_bytes,
- segsum->ss_nblocks, segsum->ss_nbinfos));
-
- nandfs_cleaner_iterate_psegment(fsdev, segsum, binfo, curr,
- vipp, bdpp);
- nblocks = segsum->ss_nblocks;
- brelse(bp);
- }
-
- if (error == 0)
- *select = 1;
-
- return (error);
-}
-
-static int
-nandfs_cleaner_choose_segment(struct nandfs_device *fsdev, uint64_t **segpp,
- uint64_t nsegs, uint64_t *rseg)
-{
- struct nandfs_suinfo *suinfo;
- uint64_t i, ssegs;
- int error;
-
- suinfo = malloc(sizeof(*suinfo) * nsegs, M_NANDFSTEMP,
- M_ZERO | M_WAITOK);
-
- if (*rseg >= fsdev->nd_fsdata.f_nsegments)
- *rseg = 0;
-
-retry:
- error = nandfs_get_segment_info_filter(fsdev, suinfo, nsegs, *rseg,
- &ssegs, NANDFS_SEGMENT_USAGE_DIRTY,
- NANDFS_SEGMENT_USAGE_ACTIVE | NANDFS_SEGMENT_USAGE_ERROR |
- NANDFS_SEGMENT_USAGE_GC);
- if (error) {
- nandfs_error("%s:%d", __FILE__, __LINE__);
- goto out;
- }
- if (ssegs == 0 && *rseg != 0) {
- *rseg = 0;
- goto retry;
- }
- if (ssegs > 0) {
- print_suinfo(suinfo, ssegs);
-
- for (i = 0; i < ssegs; i++) {
- (**segpp) = suinfo[i].nsi_num;
- (*segpp)++;
- }
- *rseg = suinfo[i - 1].nsi_num + 1;
- }
-
-out:
- free(suinfo, M_NANDFSTEMP);
- return (error);
-}
-
-static int
-nandfs_cleaner_body(struct nandfs_device *fsdev, uint64_t *rseg)
-{
- struct nandfs_vinfo *vinfo, *vip, *vipi;
- struct nandfs_bdesc *bdesc, *bdp, *bdpi;
- struct nandfs_cpstat cpstat;
- struct nandfs_cpinfo *cpinfo = NULL;
- uint64_t *segnums, *segp;
- int select, selected;
- int error = 0;
- int nsegs;
- int i;
-
- nsegs = nandfs_cleaner_segments;
-
- vip = vinfo = malloc(sizeof(*vinfo) *
- fsdev->nd_fsdata.f_blocks_per_segment * nsegs, M_NANDFSTEMP,
- M_ZERO | M_WAITOK);
- bdp = bdesc = malloc(sizeof(*bdesc) *
- fsdev->nd_fsdata.f_blocks_per_segment * nsegs, M_NANDFSTEMP,
- M_ZERO | M_WAITOK);
- segp = segnums = malloc(sizeof(*segnums) * nsegs, M_NANDFSTEMP,
- M_WAITOK);
-
- error = nandfs_cleaner_choose_segment(fsdev, &segp, nsegs, rseg);
- if (error) {
- nandfs_error("%s:%d", __FILE__, __LINE__);
- goto out;
- }
-
- if (segnums == segp)
- goto out;
-
- selected = 0;
- for (i = 0; i < segp - segnums; i++) {
- error = nandfs_cleaner_iterate_segment(fsdev, segnums[i], &vip,
- &bdp, &select);
- if (error) {
- /*
- * XXX deselect (see below)?
- */
- goto out;
- }
- if (!select)
- segnums[i] = NANDFS_NOSEGMENT;
- else {
- error = nandfs_markgc_segment(fsdev, segnums[i]);
- if (error) {
- nandfs_error("%s:%d\n", __FILE__, __LINE__);
- goto out;
- }
- selected++;
- }
- }
-
- if (selected == 0) {
- MPASS(vinfo == vip);
- MPASS(bdesc == bdp);
- goto out;
- }
-
- error = nandfs_get_cpstat(fsdev->nd_cp_node, &cpstat);
- if (error) {
- nandfs_error("%s:%d\n", __FILE__, __LINE__);
- goto out;
- }
-
- if (cpstat.ncp_nss != 0) {
- cpinfo = malloc(sizeof(struct nandfs_cpinfo) * cpstat.ncp_nss,
- M_NANDFSTEMP, M_WAITOK);
- error = nandfs_get_cpinfo(fsdev->nd_cp_node, 1, NANDFS_SNAPSHOT,
- cpinfo, cpstat.ncp_nss, NULL);
- if (error) {
- nandfs_error("%s:%d\n", __FILE__, __LINE__);
- goto out_locked;
- }
- }
-
- NANDFS_WRITELOCK(fsdev);
- DPRINTF(CLEAN, ("%s: got lock\n", __func__));
-
- error = nandfs_get_dat_vinfo(fsdev, vinfo, vip - vinfo);
- if (error) {
- nandfs_error("%s:%d\n", __FILE__, __LINE__);
- goto out_locked;
- }
-
- nandfs_cleaner_vinfo_mark_alive(fsdev, vinfo, vip - vinfo, cpinfo,
- cpstat.ncp_nss);
-
- error = nandfs_get_dat_bdescs(fsdev, bdesc, bdp - bdesc);
- if (error) {
- nandfs_error("%s:%d\n", __FILE__, __LINE__);
- goto out_locked;
- }
-
- nandfs_cleaner_bdesc_mark_alive(fsdev, bdesc, bdp - bdesc);
-
- DPRINTF(CLEAN, ("got:\n"));
- for (vipi = vinfo; vipi < vip; vipi++) {
- DPRINTF(CLEAN, ("v ino %jx vblocknr %jx start %jx end %jx "
- "alive %d\n", vipi->nvi_ino, vipi->nvi_vblocknr,
- vipi->nvi_start, vipi->nvi_end, vipi->nvi_alive));
- }
- for (bdpi = bdesc; bdpi < bdp; bdpi++) {
- DPRINTF(CLEAN, ("b oblocknr %jx blocknr %jx offset %jx "
- "alive %d\n", bdpi->bd_oblocknr, bdpi->bd_blocknr,
- bdpi->bd_offset, bdpi->bd_alive));
- }
- DPRINTF(CLEAN, ("end list\n"));
-
- error = nandfs_cleaner_clean_segments(fsdev, vinfo, vip - vinfo, NULL,
- 0, bdesc, bdp - bdesc, segnums, segp - segnums);
- if (error)
- nandfs_error("%s:%d\n", __FILE__, __LINE__);
-
-out_locked:
- NANDFS_WRITEUNLOCK(fsdev);
-out:
- free(cpinfo, M_NANDFSTEMP);
- free(segnums, M_NANDFSTEMP);
- free(bdesc, M_NANDFSTEMP);
- free(vinfo, M_NANDFSTEMP);
-
- return (error);
-}
-
-static void
-nandfs_cleaner(struct nandfs_device *fsdev)
-{
- uint64_t checked_seg = 0;
- int error;
-
- while (!nandfs_cleaner_finished(fsdev)) {
- if (!nandfs_cleaner_enable || rebooting)
- continue;
-
- DPRINTF(CLEAN, ("%s: run started\n", __func__));
-
- fsdev->nd_cleaning = 1;
-
- error = nandfs_cleaner_body(fsdev, &checked_seg);
-
- DPRINTF(CLEAN, ("%s: run finished error %d\n", __func__,
- error));
- }
-
- DPRINTF(CLEAN, ("%s: exiting\n", __func__));
- kthread_exit();
-}
-
-static int
-nandfs_cleaner_clean_segments(struct nandfs_device *nffsdev,
- struct nandfs_vinfo *vinfo, uint32_t nvinfo,
- struct nandfs_period *pd, uint32_t npd,
- struct nandfs_bdesc *bdesc, uint32_t nbdesc,
- uint64_t *segments, uint32_t nsegs)
-{
- struct nandfs_node *gc;
- struct buf *bp;
- uint32_t i;
- int error = 0;
-
- gc = nffsdev->nd_gc_node;
-
- DPRINTF(CLEAN, ("%s: enter\n", __func__));
-
- VOP_LOCK(NTOV(gc), LK_EXCLUSIVE);
- for (i = 0; i < nvinfo; i++) {
- if (!vinfo[i].nvi_alive)
- continue;
- DPRINTF(CLEAN, ("%s: read vblknr:%#jx blk:%#jx\n",
- __func__, (uintmax_t)vinfo[i].nvi_vblocknr,
- (uintmax_t)vinfo[i].nvi_blocknr));
- error = nandfs_bread(nffsdev->nd_gc_node, vinfo[i].nvi_blocknr,
- NULL, 0, &bp);
- if (error) {
- nandfs_error("%s:%d", __FILE__, __LINE__);
- VOP_UNLOCK(NTOV(gc), 0);
- goto out;
- }
- nandfs_vblk_set(bp, vinfo[i].nvi_vblocknr);
- nandfs_buf_set(bp, NANDFS_VBLK_ASSIGNED);
- nandfs_dirty_buf(bp, 1);
- }
- VOP_UNLOCK(NTOV(gc), 0);
-
- /* Delete checkpoints */
- for (i = 0; i < npd; i++) {
- DPRINTF(CLEAN, ("delete checkpoint: %jx\n",
- (uintmax_t)pd[i].p_start));
- error = nandfs_delete_cp(nffsdev->nd_cp_node, pd[i].p_start,
- pd[i].p_end);
- if (error) {
- nandfs_error("%s:%d", __FILE__, __LINE__);
- goto out;
- }
- }
-
- /* Update vblocks */
- for (i = 0; i < nvinfo; i++) {
- if (vinfo[i].nvi_alive)
- continue;
- DPRINTF(CLEAN, ("freeing vblknr: %jx\n", vinfo[i].nvi_vblocknr));
- error = nandfs_vblock_free(nffsdev, vinfo[i].nvi_vblocknr);
- if (error) {
- nandfs_error("%s:%d", __FILE__, __LINE__);
- goto out;
- }
- }
-
- error = nandfs_process_bdesc(nffsdev, bdesc, nbdesc);
- if (error) {
- nandfs_error("%s:%d", __FILE__, __LINE__);
- goto out;
- }
-
- /* Add segments to clean */
- if (nffsdev->nd_free_count) {
- nffsdev->nd_free_base = realloc(nffsdev->nd_free_base,
- (nffsdev->nd_free_count + nsegs) * sizeof(uint64_t),
- M_NANDFSTEMP, M_WAITOK | M_ZERO);
- memcpy(&nffsdev->nd_free_base[nffsdev->nd_free_count], segments,
- nsegs * sizeof(uint64_t));
- nffsdev->nd_free_count += nsegs;
- } else {
- nffsdev->nd_free_base = malloc(nsegs * sizeof(uint64_t),
- M_NANDFSTEMP, M_WAITOK|M_ZERO);
- memcpy(nffsdev->nd_free_base, segments,
- nsegs * sizeof(uint64_t));
- nffsdev->nd_free_count = nsegs;
- }
-
-out:
-
- DPRINTF(CLEAN, ("%s: exit error %d\n", __func__, error));
-
- return (error);
-}
-
-static int
-nandfs_process_bdesc(struct nandfs_device *nffsdev, struct nandfs_bdesc *bd,
- uint64_t nmembs)
-{
- struct nandfs_node *dat_node;
- struct buf *bp;
- uint64_t i;
- int error;
-
- dat_node = nffsdev->nd_dat_node;
-
- VOP_LOCK(NTOV(dat_node), LK_EXCLUSIVE);
-
- for (i = 0; i < nmembs; i++) {
- if (!bd[i].bd_alive)
- continue;
- DPRINTF(CLEAN, ("%s: idx %jx offset %jx\n",
- __func__, i, bd[i].bd_offset));
- if (bd[i].bd_level) {
- error = nandfs_bread_meta(dat_node, bd[i].bd_offset,
- NULL, 0, &bp);
- if (error) {
- nandfs_error("%s: cannot read dat node "
- "level:%d\n", __func__, bd[i].bd_level);
- brelse(bp);
- VOP_UNLOCK(NTOV(dat_node), 0);
- return (error);
- }
- nandfs_dirty_buf_meta(bp, 1);
- nandfs_bmap_dirty_blocks(VTON(bp->b_vp), bp, 1);
- } else {
- error = nandfs_bread(dat_node, bd[i].bd_offset, NULL,
- 0, &bp);
- if (error) {
- nandfs_error("%s: cannot read dat node\n",
- __func__);
- brelse(bp);
- VOP_UNLOCK(NTOV(dat_node), 0);
- return (error);
- }
- nandfs_dirty_buf(bp, 1);
- }
- DPRINTF(CLEAN, ("%s: bp: %p\n", __func__, bp));
- }
-
- VOP_UNLOCK(NTOV(dat_node), 0);
-
- return (0);
-}
diff --git a/sys/fs/nandfs/nandfs_cpfile.c b/sys/fs/nandfs/nandfs_cpfile.c
deleted file mode 100644
index 8c9a695879e42..0000000000000
--- a/sys/fs/nandfs/nandfs_cpfile.c
+++ /dev/null
@@ -1,778 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2010-2012 Semihalf.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/mount.h>
-#include <sys/mutex.h>
-#include <sys/namei.h>
-#include <sys/sysctl.h>
-#include <sys/vnode.h>
-#include <sys/buf.h>
-#include <sys/bio.h>
-
-#include <vm/vm.h>
-#include <vm/vm_param.h>
-#include <vm/vm_kern.h>
-#include <vm/vm_page.h>
-
-#include "nandfs_mount.h"
-#include "nandfs.h"
-#include "nandfs_subr.h"
-
-
-static int
-nandfs_checkpoint_size(struct nandfs_device *fsdev)
-{
-
- return (fsdev->nd_fsdata.f_checkpoint_size);
-}
-
-static int
-nandfs_checkpoint_blk_offset(struct nandfs_device *fsdev, uint64_t cn,
- uint64_t *blk, uint64_t *offset)
-{
- uint64_t off;
- uint16_t cp_size, cp_per_blk;
-
- KASSERT((cn), ("checkpoing cannot be zero"));
-
- cp_size = fsdev->nd_fsdata.f_checkpoint_size;
- cp_per_blk = fsdev->nd_blocksize / cp_size;
- off = roundup(sizeof(struct nandfs_cpfile_header), cp_size) / cp_size;
- off += (cn - 1);
-
- *blk = off / cp_per_blk;
- *offset = (off % cp_per_blk) * cp_size;
-
- return (0);
-}
-
-static int
-nandfs_checkpoint_blk_remaining(struct nandfs_device *fsdev, uint64_t cn,
- uint64_t blk, uint64_t offset)
-{
- uint16_t cp_size, cp_remaining;
-
- cp_size = fsdev->nd_fsdata.f_checkpoint_size;
- cp_remaining = (fsdev->nd_blocksize - offset) / cp_size;
-
- return (cp_remaining);
-}
-
-int
-nandfs_get_checkpoint(struct nandfs_device *fsdev, struct nandfs_node *cp_node,
- uint64_t cn)
-{
- struct buf *bp;
- uint64_t blk, offset;
- int error;
-
- if (cn != fsdev->nd_last_cno && cn != (fsdev->nd_last_cno + 1)) {
- return (-1);
- }
-
- error = nandfs_bread(cp_node, 0, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (-1);
- }
-
- error = nandfs_dirty_buf(bp, 0);
- if (error)
- return (-1);
-
-
- nandfs_checkpoint_blk_offset(fsdev, cn, &blk, &offset);
-
- if (blk != 0) {
- if (blk < cp_node->nn_inode.i_blocks)
- error = nandfs_bread(cp_node, blk, NOCRED, 0, &bp);
- else
- error = nandfs_bcreate(cp_node, blk, NOCRED, 0, &bp);
- if (error) {
- if (bp)
- brelse(bp);
- return (-1);
- }
-
- nandfs_dirty_buf(bp, 1);
- }
-
- DPRINTF(CPFILE, ("%s: cn:%#jx entry block:%#jx offset:%#jx\n",
- __func__, (uintmax_t)cn, (uintmax_t)blk, (uintmax_t)offset));
-
- return (0);
-}
-
-int
-nandfs_set_checkpoint(struct nandfs_device *fsdev, struct nandfs_node *cp_node,
- uint64_t cn, struct nandfs_inode *ifile_inode, uint64_t nblocks)
-{
- struct nandfs_cpfile_header *cnh;
- struct nandfs_checkpoint *cnp;
- struct buf *bp;
- uint64_t blk, offset;
- int error;
-
- if (cn != fsdev->nd_last_cno && cn != (fsdev->nd_last_cno + 1)) {
- nandfs_error("%s: trying to set invalid chekpoint %jx - %jx\n",
- __func__, cn, fsdev->nd_last_cno);
- return (-1);
- }
-
- error = nandfs_bread(cp_node, 0, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return error;
- }
-
- cnh = (struct nandfs_cpfile_header *) bp->b_data;
- cnh->ch_ncheckpoints++;
-
- nandfs_checkpoint_blk_offset(fsdev, cn, &blk, &offset);
-
- if(blk != 0) {
- brelse(bp);
- error = nandfs_bread(cp_node, blk, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return error;
- }
- }
-
- cnp = (struct nandfs_checkpoint *)((uint8_t *)bp->b_data + offset);
- cnp->cp_flags = 0;
- cnp->cp_checkpoints_count = 1;
- memset(&cnp->cp_snapshot_list, 0, sizeof(struct nandfs_snapshot_list));
- cnp->cp_cno = cn;
- cnp->cp_create = fsdev->nd_ts.tv_sec;
- cnp->cp_nblk_inc = nblocks;
- cnp->cp_blocks_count = 0;
- memcpy (&cnp->cp_ifile_inode, ifile_inode, sizeof(cnp->cp_ifile_inode));
-
- DPRINTF(CPFILE, ("%s: cn:%#jx ctime:%#jx nblk:%#jx\n",
- __func__, (uintmax_t)cn, (uintmax_t)cnp->cp_create,
- (uintmax_t)nblocks));
-
- brelse(bp);
- return (0);
-}
-
-static int
-nandfs_cp_mounted(struct nandfs_device *nandfsdev, uint64_t cno)
-{
- struct nandfsmount *nmp;
- int mounted = 0;
-
- mtx_lock(&nandfsdev->nd_mutex);
- /* No double-mounting of the same checkpoint */
- STAILQ_FOREACH(nmp, &nandfsdev->nd_mounts, nm_next_mount) {
- if (nmp->nm_mount_args.cpno == cno) {
- mounted = 1;
- break;
- }
- }
- mtx_unlock(&nandfsdev->nd_mutex);
-
- return (mounted);
-}
-
-static int
-nandfs_cp_set_snapshot(struct nandfs_node *cp_node, uint64_t cno)
-{
- struct nandfs_device *fsdev;
- struct nandfs_cpfile_header *cnh;
- struct nandfs_checkpoint *cnp;
- struct nandfs_snapshot_list *list;
- struct buf *bp;
- uint64_t blk, prev_blk, offset;
- uint64_t curr, prev;
- int error;
-
- fsdev = cp_node->nn_nandfsdev;
-
- /* Get snapshot data */
- nandfs_checkpoint_blk_offset(fsdev, cno, &blk, &offset);
- error = nandfs_bread(cp_node, blk, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
- cnp = (struct nandfs_checkpoint *)(bp->b_data + offset);
- if (cnp->cp_flags & NANDFS_CHECKPOINT_INVALID) {
- brelse(bp);
- return (ENOENT);
- }
- if ((cnp->cp_flags & NANDFS_CHECKPOINT_SNAPSHOT)) {
- brelse(bp);
- return (EINVAL);
- }
-
- brelse(bp);
- /* Get list from header */
- error = nandfs_bread(cp_node, 0, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
-
- cnh = (struct nandfs_cpfile_header *) bp->b_data;
- list = &cnh->ch_snapshot_list;
- prev = list->ssl_prev;
- brelse(bp);
- prev_blk = ~(0);
- curr = 0;
- while (prev > cno) {
- curr = prev;
- nandfs_checkpoint_blk_offset(fsdev, prev, &prev_blk, &offset);
- error = nandfs_bread(cp_node, prev_blk, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
- cnp = (struct nandfs_checkpoint *)(bp->b_data + offset);
- list = &cnp->cp_snapshot_list;
- prev = list->ssl_prev;
- brelse(bp);
- }
-
- if (curr == 0) {
- nandfs_bread(cp_node, 0, NOCRED, 0, &bp);
- cnh = (struct nandfs_cpfile_header *) bp->b_data;
- list = &cnh->ch_snapshot_list;
- } else {
- nandfs_checkpoint_blk_offset(fsdev, curr, &blk, &offset);
- error = nandfs_bread(cp_node, blk, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
- cnp = (struct nandfs_checkpoint *)(bp->b_data + offset);
- list = &cnp->cp_snapshot_list;
- }
-
- list->ssl_prev = cno;
- error = nandfs_dirty_buf(bp, 0);
- if (error)
- return (error);
-
-
- /* Update snapshot for cno */
- nandfs_checkpoint_blk_offset(fsdev, cno, &blk, &offset);
- error = nandfs_bread(cp_node, blk, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
- cnp = (struct nandfs_checkpoint *)(bp->b_data + offset);
- list = &cnp->cp_snapshot_list;
- list->ssl_prev = prev;
- list->ssl_next = curr;
- cnp->cp_flags |= NANDFS_CHECKPOINT_SNAPSHOT;
- nandfs_dirty_buf(bp, 1);
-
- if (prev == 0) {
- nandfs_bread(cp_node, 0, NOCRED, 0, &bp);
- cnh = (struct nandfs_cpfile_header *) bp->b_data;
- list = &cnh->ch_snapshot_list;
- } else {
- /* Update snapshot list for prev */
- nandfs_checkpoint_blk_offset(fsdev, prev, &blk, &offset);
- error = nandfs_bread(cp_node, blk, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
- cnp = (struct nandfs_checkpoint *)(bp->b_data + offset);
- list = &cnp->cp_snapshot_list;
- }
- list->ssl_next = cno;
- nandfs_dirty_buf(bp, 1);
-
- /* Update header */
- error = nandfs_bread(cp_node, 0, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
- cnh = (struct nandfs_cpfile_header *) bp->b_data;
- cnh->ch_nsnapshots++;
- nandfs_dirty_buf(bp, 1);
-
- return (0);
-}
-
-static int
-nandfs_cp_clr_snapshot(struct nandfs_node *cp_node, uint64_t cno)
-{
- struct nandfs_device *fsdev;
- struct nandfs_cpfile_header *cnh;
- struct nandfs_checkpoint *cnp;
- struct nandfs_snapshot_list *list;
- struct buf *bp;
- uint64_t blk, offset, snapshot_cnt;
- uint64_t next, prev;
- int error;
-
- fsdev = cp_node->nn_nandfsdev;
-
- /* Get snapshot data */
- nandfs_checkpoint_blk_offset(fsdev, cno, &blk, &offset);
- error = nandfs_bread(cp_node, blk, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
- cnp = (struct nandfs_checkpoint *)(bp->b_data + offset);
- if (cnp->cp_flags & NANDFS_CHECKPOINT_INVALID) {
- brelse(bp);
- return (ENOENT);
- }
- if (!(cnp->cp_flags & NANDFS_CHECKPOINT_SNAPSHOT)) {
- brelse(bp);
- return (EINVAL);
- }
-
- list = &cnp->cp_snapshot_list;
- next = list->ssl_next;
- prev = list->ssl_prev;
- brelse(bp);
-
- /* Get previous snapshot */
- if (prev != 0) {
- nandfs_checkpoint_blk_offset(fsdev, prev, &blk, &offset);
- error = nandfs_bread(cp_node, blk, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
- cnp = (struct nandfs_checkpoint *)(bp->b_data + offset);
- list = &cnp->cp_snapshot_list;
- } else {
- nandfs_bread(cp_node, 0, NOCRED, 0, &bp);
- cnh = (struct nandfs_cpfile_header *) bp->b_data;
- list = &cnh->ch_snapshot_list;
- }
-
- list->ssl_next = next;
- error = nandfs_dirty_buf(bp, 0);
- if (error)
- return (error);
-
- /* Get next snapshot */
- if (next != 0) {
- nandfs_checkpoint_blk_offset(fsdev, next, &blk, &offset);
- error = nandfs_bread(cp_node, blk, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
- cnp = (struct nandfs_checkpoint *)(bp->b_data + offset);
- list = &cnp->cp_snapshot_list;
- } else {
- nandfs_bread(cp_node, 0, NOCRED, 0, &bp);
- cnh = (struct nandfs_cpfile_header *) bp->b_data;
- list = &cnh->ch_snapshot_list;
- }
- list->ssl_prev = prev;
- nandfs_dirty_buf(bp, 1);
-
- /* Update snapshot list for cno */
- nandfs_checkpoint_blk_offset(fsdev, cno, &blk, &offset);
- error = nandfs_bread(cp_node, blk, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
- cnp = (struct nandfs_checkpoint *)(bp->b_data + offset);
- list = &cnp->cp_snapshot_list;
- list->ssl_prev = 0;
- list->ssl_next = 0;
- cnp->cp_flags &= !NANDFS_CHECKPOINT_SNAPSHOT;
- nandfs_dirty_buf(bp, 1);
-
- /* Update header */
- error = nandfs_bread(cp_node, 0, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
- cnh = (struct nandfs_cpfile_header *) bp->b_data;
- snapshot_cnt = cnh->ch_nsnapshots;
- snapshot_cnt--;
- cnh->ch_nsnapshots = snapshot_cnt;
- nandfs_dirty_buf(bp, 1);
-
- return (0);
-}
-
-int
-nandfs_chng_cpmode(struct nandfs_node *node, struct nandfs_cpmode *ncpm)
-{
- struct nandfs_device *fsdev;
- uint64_t cno = ncpm->ncpm_cno;
- int mode = ncpm->ncpm_mode;
- int ret;
-
- fsdev = node->nn_nandfsdev;
- VOP_LOCK(NTOV(node), LK_EXCLUSIVE);
- switch (mode) {
- case NANDFS_CHECKPOINT:
- if (nandfs_cp_mounted(fsdev, cno)) {
- ret = EBUSY;
- } else
- ret = nandfs_cp_clr_snapshot(node, cno);
- break;
- case NANDFS_SNAPSHOT:
- ret = nandfs_cp_set_snapshot(node, cno);
- break;
- default:
- ret = EINVAL;
- break;
- }
- VOP_UNLOCK(NTOV(node), 0);
-
- return (ret);
-}
-
-static void
-nandfs_cpinfo_fill(struct nandfs_checkpoint *cnp, struct nandfs_cpinfo *nci)
-{
-
- nci->nci_flags = cnp->cp_flags;
- nci->nci_pad = 0;
- nci->nci_cno = cnp->cp_cno;
- nci->nci_create = cnp->cp_create;
- nci->nci_nblk_inc = cnp->cp_nblk_inc;
- nci->nci_blocks_count = cnp->cp_blocks_count;
- nci->nci_next = cnp->cp_snapshot_list.ssl_next;
- DPRINTF(CPFILE, ("%s: cn:%#jx ctime:%#jx\n",
- __func__, (uintmax_t)cnp->cp_cno,
- (uintmax_t)cnp->cp_create));
-}
-
-static int
-nandfs_get_cpinfo_cp(struct nandfs_node *node, uint64_t cno,
- struct nandfs_cpinfo *nci, uint32_t mnmembs, uint32_t *nmembs)
-{
- struct nandfs_device *fsdev;
- struct buf *bp;
- uint64_t blk, offset, last_cno, i;
- uint16_t remaining;
- int error;
-#ifdef INVARIANTS
- uint64_t testblk, testoffset;
-#endif
-
- if (cno == 0) {
- return (ENOENT);
- }
-
- if (mnmembs < 1) {
- return (EINVAL);
- }
-
- fsdev = node->nn_nandfsdev;
- last_cno = fsdev->nd_last_cno;
- DPRINTF(CPFILE, ("%s: cno:%#jx mnmembs: %#jx last:%#jx\n", __func__,
- (uintmax_t)cno, (uintmax_t)mnmembs,
- (uintmax_t)fsdev->nd_last_cno));
-
- /*
- * do {
- * get block
- * read checkpoints until we hit last checkpoint, end of block or
- * requested number
- * } while (last read checkpoint <= last checkpoint on fs &&
- * read checkpoints < request number);
- */
- *nmembs = i = 0;
- do {
- nandfs_checkpoint_blk_offset(fsdev, cno, &blk, &offset);
- remaining = nandfs_checkpoint_blk_remaining(fsdev, cno,
- blk, offset);
- error = nandfs_bread(node, blk, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
-
- while (cno <= last_cno && i < mnmembs && remaining) {
-#ifdef INVARIANTS
- nandfs_checkpoint_blk_offset(fsdev, cno, &testblk,
- &testoffset);
- KASSERT(testblk == blk, ("testblk != blk"));
- KASSERT(testoffset == offset, ("testoffset != offset"));
-#endif
- DPRINTF(CPFILE, ("%s: cno %#jx\n", __func__,
- (uintmax_t)cno));
-
- nandfs_cpinfo_fill((struct nandfs_checkpoint *)
- (bp->b_data + offset), nci);
- offset += nandfs_checkpoint_size(fsdev);
- i++;
- nci++;
- cno++;
- (*nmembs)++;
- remaining--;
- }
- brelse(bp);
- } while (cno <= last_cno && i < mnmembs);
-
- return (0);
-}
-
-static int
-nandfs_get_cpinfo_sp(struct nandfs_node *node, uint64_t cno,
- struct nandfs_cpinfo *nci, uint32_t mnmembs, uint32_t *nmembs)
-{
- struct nandfs_checkpoint *cnp;
- struct nandfs_cpfile_header *cnh;
- struct nandfs_device *fsdev;
- struct buf *bp = NULL;
- uint64_t curr = 0;
- uint64_t blk, offset, curr_cno;
- uint32_t flag;
- int i, error;
-
- if (cno == 0 || cno == ~(0))
- return (ENOENT);
-
- fsdev = node->nn_nandfsdev;
- curr_cno = cno;
-
- if (nmembs)
- *nmembs = 0;
- if (curr_cno == 1) {
- /* Get list from header */
- error = nandfs_bread(node, 0, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
- cnh = (struct nandfs_cpfile_header *) bp->b_data;
- curr_cno = cnh->ch_snapshot_list.ssl_next;
- brelse(bp);
- bp = NULL;
-
- /* No snapshots */
- if (curr_cno == 0)
- return (0);
- }
-
- for (i = 0; i < mnmembs; i++, nci++) {
- nandfs_checkpoint_blk_offset(fsdev, curr_cno, &blk, &offset);
- if (i == 0 || curr != blk) {
- if (bp)
- brelse(bp);
- error = nandfs_bread(node, blk, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (ENOENT);
- }
- curr = blk;
- }
- cnp = (struct nandfs_checkpoint *)(bp->b_data + offset);
- flag = cnp->cp_flags;
- if (!(flag & NANDFS_CHECKPOINT_SNAPSHOT) ||
- (flag & NANDFS_CHECKPOINT_INVALID))
- break;
-
- nci->nci_flags = flag;
- nci->nci_pad = 0;
- nci->nci_cno = cnp->cp_cno;
- nci->nci_create = cnp->cp_create;
- nci->nci_nblk_inc = cnp->cp_nblk_inc;
- nci->nci_blocks_count = cnp->cp_blocks_count;
- nci->nci_next = cnp->cp_snapshot_list.ssl_next;
- if (nmembs)
- (*nmembs)++;
-
- curr_cno = nci->nci_next;
- if (!curr_cno)
- break;
- }
-
- brelse(bp);
-
- return (0);
-}
-
-int
-nandfs_get_cpinfo(struct nandfs_node *node, uint64_t cno, uint16_t flags,
- struct nandfs_cpinfo *nci, uint32_t nmembs, uint32_t *nnmembs)
-{
- int error;
-
- VOP_LOCK(NTOV(node), LK_EXCLUSIVE);
- switch (flags) {
- case NANDFS_CHECKPOINT:
- error = nandfs_get_cpinfo_cp(node, cno, nci, nmembs, nnmembs);
- break;
- case NANDFS_SNAPSHOT:
- error = nandfs_get_cpinfo_sp(node, cno, nci, nmembs, nnmembs);
- break;
- default:
- error = EINVAL;
- break;
- }
- VOP_UNLOCK(NTOV(node), 0);
-
- return (error);
-}
-
-int
-nandfs_get_cpinfo_ioctl(struct nandfs_node *node, struct nandfs_argv *nargv)
-{
- struct nandfs_cpinfo *nci;
- uint64_t cno = nargv->nv_index;
- void *buf = (void *)((uintptr_t)nargv->nv_base);
- uint16_t flags = nargv->nv_flags;
- uint32_t nmembs = 0;
- int error;
-
- if (nargv->nv_nmembs > NANDFS_CPINFO_MAX)
- return (EINVAL);
-
- nci = malloc(sizeof(struct nandfs_cpinfo) * nargv->nv_nmembs,
- M_NANDFSTEMP, M_WAITOK | M_ZERO);
-
- error = nandfs_get_cpinfo(node, cno, flags, nci, nargv->nv_nmembs, &nmembs);
-
- if (error == 0) {
- nargv->nv_nmembs = nmembs;
- error = copyout(nci, buf,
- sizeof(struct nandfs_cpinfo) * nmembs);
- }
-
- free(nci, M_NANDFSTEMP);
- return (error);
-}
-
-int
-nandfs_delete_cp(struct nandfs_node *node, uint64_t start, uint64_t end)
-{
- struct nandfs_checkpoint *cnp;
- struct nandfs_device *fsdev;
- struct buf *bp;
- uint64_t cno = start, blk, offset;
- int error;
-
- DPRINTF(CPFILE, ("%s: delete cno %jx-%jx\n", __func__, start, end));
- VOP_LOCK(NTOV(node), LK_EXCLUSIVE);
- fsdev = node->nn_nandfsdev;
- for (cno = start; cno <= end; cno++) {
- if (!cno)
- continue;
-
- nandfs_checkpoint_blk_offset(fsdev, cno, &blk, &offset);
- error = nandfs_bread(node, blk, NOCRED, 0, &bp);
- if (error) {
- VOP_UNLOCK(NTOV(node), 0);
- brelse(bp);
- return (error);
- }
-
- cnp = (struct nandfs_checkpoint *)(bp->b_data + offset);
- if (cnp->cp_flags & NANDFS_CHECKPOINT_SNAPSHOT) {
- brelse(bp);
- VOP_UNLOCK(NTOV(node), 0);
- return (0);
- }
-
- cnp->cp_flags |= NANDFS_CHECKPOINT_INVALID;
-
- error = nandfs_dirty_buf(bp, 0);
- if (error)
- return (error);
- }
- VOP_UNLOCK(NTOV(node), 0);
-
- return (0);
-}
-
-int
-nandfs_make_snap(struct nandfs_device *fsdev, uint64_t *cno)
-{
- struct nandfs_cpmode cpm;
- int error;
-
- *cno = cpm.ncpm_cno = fsdev->nd_last_cno;
- cpm.ncpm_mode = NANDFS_SNAPSHOT;
- error = nandfs_chng_cpmode(fsdev->nd_cp_node, &cpm);
- return (error);
-}
-
-int
-nandfs_delete_snap(struct nandfs_device *fsdev, uint64_t cno)
-{
- struct nandfs_cpmode cpm;
- int error;
-
- cpm.ncpm_cno = cno;
- cpm.ncpm_mode = NANDFS_CHECKPOINT;
- error = nandfs_chng_cpmode(fsdev->nd_cp_node, &cpm);
- return (error);
-}
-
-int nandfs_get_cpstat(struct nandfs_node *cp_node, struct nandfs_cpstat *ncp)
-{
- struct nandfs_device *fsdev;
- struct nandfs_cpfile_header *cnh;
- struct buf *bp;
- int error;
-
- VOP_LOCK(NTOV(cp_node), LK_EXCLUSIVE);
- fsdev = cp_node->nn_nandfsdev;
-
- /* Get header */
- error = nandfs_bread(cp_node, 0, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- VOP_UNLOCK(NTOV(cp_node), 0);
- return (error);
- }
- cnh = (struct nandfs_cpfile_header *) bp->b_data;
- ncp->ncp_cno = fsdev->nd_last_cno;
- ncp->ncp_ncps = cnh->ch_ncheckpoints;
- ncp->ncp_nss = cnh->ch_nsnapshots;
- DPRINTF(CPFILE, ("%s: cno:%#jx ncps:%#jx nss:%#jx\n",
- __func__, ncp->ncp_cno, ncp->ncp_ncps, ncp->ncp_nss));
- brelse(bp);
- VOP_UNLOCK(NTOV(cp_node), 0);
-
- return (0);
-}
diff --git a/sys/fs/nandfs/nandfs_dat.c b/sys/fs/nandfs/nandfs_dat.c
deleted file mode 100644
index e81a117589f82..0000000000000
--- a/sys/fs/nandfs/nandfs_dat.c
+++ /dev/null
@@ -1,346 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2010-2012 Semihalf.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/mount.h>
-#include <sys/mutex.h>
-#include <sys/namei.h>
-#include <sys/sysctl.h>
-#include <sys/vnode.h>
-#include <sys/buf.h>
-#include <sys/bio.h>
-
-#include <vm/vm.h>
-#include <vm/vm_param.h>
-#include <vm/vm_kern.h>
-#include <vm/vm_page.h>
-
-#include <fs/nandfs/nandfs_mount.h>
-#include <fs/nandfs/nandfs.h>
-#include <fs/nandfs/nandfs_subr.h>
-
-int
-nandfs_vblock_alloc(struct nandfs_device *nandfsdev, nandfs_daddr_t *vblock)
-{
- struct nandfs_node *dat;
- struct nandfs_mdt *mdt;
- struct nandfs_alloc_request req;
- struct nandfs_dat_entry *dat_entry;
- uint64_t start;
- uint32_t entry;
- int locked, error;
-
- dat = nandfsdev->nd_dat_node;
- mdt = &nandfsdev->nd_dat_mdt;
- start = nandfsdev->nd_last_cno + 1;
-
- locked = NANDFS_VOP_ISLOCKED(NTOV(dat));
- if (!locked)
- VOP_LOCK(NTOV(dat), LK_EXCLUSIVE);
- req.entrynum = 0;
-
- /* Alloc vblock number */
- error = nandfs_find_free_entry(mdt, dat, &req);
- if (error) {
- nandfs_error("%s: cannot find free vblk entry\n",
- __func__);
- if (!locked)
- VOP_UNLOCK(NTOV(dat), 0);
- return (error);
- }
-
- /* Read/create buffer */
- error = nandfs_get_entry_block(mdt, dat, &req, &entry, 1);
- if (error) {
- nandfs_error("%s: cannot get free vblk entry\n",
- __func__);
- nandfs_abort_entry(&req);
- if (!locked)
- VOP_UNLOCK(NTOV(dat), 0);
- return (error);
- }
-
- /* Fill out vblock data */
- dat_entry = (struct nandfs_dat_entry *) req.bp_entry->b_data;
- dat_entry[entry].de_start = start;
- dat_entry[entry].de_end = UINTMAX_MAX;
- dat_entry[entry].de_blocknr = 0;
-
- /* Commit allocation */
- error = nandfs_alloc_entry(mdt, &req);
- if (error) {
- nandfs_error("%s: cannot get free vblk entry\n",
- __func__);
- if (!locked)
- VOP_UNLOCK(NTOV(dat), 0);
- return (error);
- }
-
- /* Return allocated vblock */
- *vblock = req.entrynum;
- DPRINTF(DAT, ("%s: allocated vblock %#jx\n",
- __func__, (uintmax_t)*vblock));
-
- if (!locked)
- VOP_UNLOCK(NTOV(dat), 0);
- return (error);
-}
-
-int
-nandfs_vblock_assign(struct nandfs_device *nandfsdev, nandfs_daddr_t vblock,
- nandfs_lbn_t block)
-{
- struct nandfs_node *dat;
- struct nandfs_mdt *mdt;
- struct nandfs_alloc_request req;
- struct nandfs_dat_entry *dat_entry;
- uint32_t entry;
- int locked, error;
-
- dat = nandfsdev->nd_dat_node;
- mdt = &nandfsdev->nd_dat_mdt;
-
- locked = NANDFS_VOP_ISLOCKED(NTOV(dat));
- if (!locked)
- VOP_LOCK(NTOV(dat), LK_EXCLUSIVE);
- req.entrynum = vblock;
-
- error = nandfs_get_entry_block(mdt, dat, &req, &entry, 0);
- if (!error) {
- dat_entry = (struct nandfs_dat_entry *) req.bp_entry->b_data;
- dat_entry[entry].de_blocknr = block;
-
- DPRINTF(DAT, ("%s: assing vblock %jx->%jx\n",
- __func__, (uintmax_t)vblock, (uintmax_t)block));
-
- /*
- * It is mostly called from syncer() so
- * we want to force making buf dirty
- */
- error = nandfs_dirty_buf(req.bp_entry, 1);
- }
-
- if (!locked)
- VOP_UNLOCK(NTOV(dat), 0);
-
- return (error);
-}
-
-int
-nandfs_vblock_end(struct nandfs_device *nandfsdev, nandfs_daddr_t vblock)
-{
- struct nandfs_node *dat;
- struct nandfs_mdt *mdt;
- struct nandfs_alloc_request req;
- struct nandfs_dat_entry *dat_entry;
- uint64_t end;
- uint32_t entry;
- int locked, error;
-
- dat = nandfsdev->nd_dat_node;
- mdt = &nandfsdev->nd_dat_mdt;
- end = nandfsdev->nd_last_cno;
-
- locked = NANDFS_VOP_ISLOCKED(NTOV(dat));
- if (!locked)
- VOP_LOCK(NTOV(dat), LK_EXCLUSIVE);
- req.entrynum = vblock;
-
- error = nandfs_get_entry_block(mdt, dat, &req, &entry, 0);
- if (!error) {
- dat_entry = (struct nandfs_dat_entry *) req.bp_entry->b_data;
- dat_entry[entry].de_end = end;
- DPRINTF(DAT, ("%s: end vblock %#jx at checkpoint %#jx\n",
- __func__, (uintmax_t)vblock, (uintmax_t)end));
-
- /*
- * It is mostly called from syncer() so
- * we want to force making buf dirty
- */
- error = nandfs_dirty_buf(req.bp_entry, 1);
- }
-
- if (!locked)
- VOP_UNLOCK(NTOV(dat), 0);
-
- return (error);
-}
-
-int
-nandfs_vblock_free(struct nandfs_device *nandfsdev, nandfs_daddr_t vblock)
-{
- struct nandfs_node *dat;
- struct nandfs_mdt *mdt;
- struct nandfs_alloc_request req;
- int error;
-
- dat = nandfsdev->nd_dat_node;
- mdt = &nandfsdev->nd_dat_mdt;
-
- VOP_LOCK(NTOV(dat), LK_EXCLUSIVE);
- req.entrynum = vblock;
-
- error = nandfs_find_entry(mdt, dat, &req);
- if (!error) {
- DPRINTF(DAT, ("%s: vblk %#jx\n", __func__, (uintmax_t)vblock));
- nandfs_free_entry(mdt, &req);
- }
-
- VOP_UNLOCK(NTOV(dat), 0);
- return (error);
-}
-
-int
-nandfs_get_dat_vinfo_ioctl(struct nandfs_device *nandfsdev, struct nandfs_argv *nargv)
-{
- struct nandfs_vinfo *vinfo;
- size_t size;
- int error;
-
- if (nargv->nv_nmembs > NANDFS_VINFO_MAX)
- return (EINVAL);
-
- size = sizeof(struct nandfs_vinfo) * nargv->nv_nmembs;
- vinfo = malloc(size, M_NANDFSTEMP, M_WAITOK|M_ZERO);
-
- error = copyin((void *)(uintptr_t)nargv->nv_base, vinfo, size);
- if (error) {
- free(vinfo, M_NANDFSTEMP);
- return (error);
- }
-
- error = nandfs_get_dat_vinfo(nandfsdev, vinfo, nargv->nv_nmembs);
- if (error == 0)
- error = copyout(vinfo, (void *)(uintptr_t)nargv->nv_base, size);
- free(vinfo, M_NANDFSTEMP);
- return (error);
-}
-
-int
-nandfs_get_dat_vinfo(struct nandfs_device *nandfsdev, struct nandfs_vinfo *vinfo,
- uint32_t nmembs)
-{
- struct nandfs_node *dat;
- struct nandfs_mdt *mdt;
- struct nandfs_alloc_request req;
- struct nandfs_dat_entry *dat_entry;
- uint32_t i, idx;
- int error = 0;
-
- dat = nandfsdev->nd_dat_node;
- mdt = &nandfsdev->nd_dat_mdt;
-
- DPRINTF(DAT, ("%s: nmembs %#x\n", __func__, nmembs));
-
- VOP_LOCK(NTOV(dat), LK_EXCLUSIVE);
-
- for (i = 0; i < nmembs; i++) {
- req.entrynum = vinfo[i].nvi_vblocknr;
-
- error = nandfs_get_entry_block(mdt, dat,&req, &idx, 0);
- if (error)
- break;
-
- dat_entry = ((struct nandfs_dat_entry *) req.bp_entry->b_data);
- vinfo[i].nvi_start = dat_entry[idx].de_start;
- vinfo[i].nvi_end = dat_entry[idx].de_end;
- vinfo[i].nvi_blocknr = dat_entry[idx].de_blocknr;
-
- DPRINTF(DAT, ("%s: vinfo: %jx[%jx-%jx]->%jx\n",
- __func__, vinfo[i].nvi_vblocknr, vinfo[i].nvi_start,
- vinfo[i].nvi_end, vinfo[i].nvi_blocknr));
-
- brelse(req.bp_entry);
- }
-
- VOP_UNLOCK(NTOV(dat), 0);
- return (error);
-}
-
-int
-nandfs_get_dat_bdescs_ioctl(struct nandfs_device *nffsdev,
- struct nandfs_argv *nargv)
-{
- struct nandfs_bdesc *bd;
- size_t size;
- int error;
-
- size = nargv->nv_nmembs * sizeof(struct nandfs_bdesc);
- bd = malloc(size, M_NANDFSTEMP, M_WAITOK);
- error = copyin((void *)(uintptr_t)nargv->nv_base, bd, size);
- if (error) {
- free(bd, M_NANDFSTEMP);
- return (error);
- }
-
- error = nandfs_get_dat_bdescs(nffsdev, bd, nargv->nv_nmembs);
-
- if (error == 0)
- error = copyout(bd, (void *)(uintptr_t)nargv->nv_base, size);
-
- free(bd, M_NANDFSTEMP);
- return (error);
-}
-
-int
-nandfs_get_dat_bdescs(struct nandfs_device *nffsdev, struct nandfs_bdesc *bd,
- uint32_t nmembs)
-{
- struct nandfs_node *dat_node;
- uint64_t map;
- uint32_t i;
- int error = 0;
-
- dat_node = nffsdev->nd_dat_node;
-
- VOP_LOCK(NTOV(dat_node), LK_EXCLUSIVE);
-
- for (i = 0; i < nmembs; i++) {
- DPRINTF(CLEAN,
- ("%s: bd ino:%#jx oblk:%#jx blocknr:%#jx off:%#jx\n",
- __func__, (uintmax_t)bd[i].bd_ino,
- (uintmax_t)bd[i].bd_oblocknr, (uintmax_t)bd[i].bd_blocknr,
- (uintmax_t)bd[i].bd_offset));
-
- error = nandfs_bmap_lookup(dat_node, bd[i].bd_offset, &map);
- if (error)
- break;
- bd[i].bd_blocknr = map;
- }
-
- VOP_UNLOCK(NTOV(dat_node), 0);
- return (error);
-}
diff --git a/sys/fs/nandfs/nandfs_dir.c b/sys/fs/nandfs/nandfs_dir.c
deleted file mode 100644
index 404edecfaa08f..0000000000000
--- a/sys/fs/nandfs/nandfs_dir.c
+++ /dev/null
@@ -1,316 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2010-2012 Semihalf
- * Copyright (c) 2008, 2009 Reinoud Zandijk
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * From: NetBSD: nilfs_subr.c,v 1.4 2009/07/29 17:06:57 reinoud
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/namei.h>
-#include <sys/kernel.h>
-#include <sys/stat.h>
-#include <sys/buf.h>
-#include <sys/bio.h>
-#include <sys/proc.h>
-#include <sys/mount.h>
-#include <sys/vnode.h>
-#include <sys/signalvar.h>
-#include <sys/malloc.h>
-#include <sys/dirent.h>
-#include <sys/lockf.h>
-
-#include <vm/vm.h>
-#include <vm/vm_extern.h>
-
-#include "nandfs_mount.h"
-#include "nandfs.h"
-#include "nandfs_subr.h"
-
-int
-nandfs_add_dirent(struct vnode *dvp, uint64_t ino, char *nameptr, long namelen,
- uint8_t type)
-{
- struct nandfs_node *dir_node = VTON(dvp);
- struct nandfs_dir_entry *dirent, *pdirent;
- uint32_t blocksize = dir_node->nn_nandfsdev->nd_blocksize;
- uint64_t filesize = dir_node->nn_inode.i_size;
- uint64_t inode_blks = dir_node->nn_inode.i_blocks;
- uint32_t off, rest;
- uint8_t *pos;
- struct buf *bp;
- int error;
-
- pdirent = NULL;
- bp = NULL;
- if (inode_blks) {
- error = nandfs_bread(dir_node, inode_blks - 1, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
-
- pos = bp->b_data;
- off = 0;
- while (off < blocksize) {
- pdirent = (struct nandfs_dir_entry *) (pos + off);
- if (!pdirent->rec_len) {
- pdirent = NULL;
- break;
- }
- off += pdirent->rec_len;
- }
-
- if (pdirent)
- rest = pdirent->rec_len -
- NANDFS_DIR_REC_LEN(pdirent->name_len);
- else
- rest = blocksize;
-
- if (rest < NANDFS_DIR_REC_LEN(namelen)) {
- /* Do not update pdirent as new block is created */
- pdirent = NULL;
- brelse(bp);
- /* Set to NULL to create new */
- bp = NULL;
- filesize += rest;
- }
- }
-
- /* If no bp found create new */
- if (!bp) {
- error = nandfs_bcreate(dir_node, inode_blks, NOCRED, 0, &bp);
- if (error)
- return (error);
- off = 0;
- pos = bp->b_data;
- }
-
- /* Modify pdirent if exists */
- if (pdirent) {
- DPRINTF(LOOKUP, ("modify pdirent %p\n", pdirent));
- /* modify last de */
- off -= pdirent->rec_len;
- pdirent->rec_len =
- NANDFS_DIR_REC_LEN(pdirent->name_len);
- off += pdirent->rec_len;
- }
-
- /* Create new dirent */
- dirent = (struct nandfs_dir_entry *) (pos + off);
- dirent->rec_len = blocksize - off;
- dirent->inode = ino;
- dirent->name_len = namelen;
- memset(dirent->name, 0, NANDFS_DIR_NAME_LEN(namelen));
- memcpy(dirent->name, nameptr, namelen);
- dirent->file_type = type;
-
- filesize += NANDFS_DIR_REC_LEN(dirent->name_len);
-
- DPRINTF(LOOKUP, ("create dir_entry '%.*s' at %p with size %x "
- "new filesize: %jx\n",
- (int)namelen, dirent->name, dirent, dirent->rec_len,
- (uintmax_t)filesize));
-
- error = nandfs_dirty_buf(bp, 0);
- if (error)
- return (error);
-
- dir_node->nn_inode.i_size = filesize;
- dir_node->nn_flags |= IN_CHANGE | IN_UPDATE;
- vnode_pager_setsize(dvp, filesize);
-
- return (0);
-}
-
-int
-nandfs_remove_dirent(struct vnode *dvp, struct nandfs_node *node,
- struct componentname *cnp)
-{
- struct nandfs_node *dir_node;
- struct nandfs_dir_entry *dirent, *pdirent;
- struct buf *bp;
- uint64_t filesize, blocknr, ino, offset;
- uint32_t blocksize, limit, off;
- uint16_t newsize;
- uint8_t *pos;
- int error, found;
-
- dir_node = VTON(dvp);
- filesize = dir_node->nn_inode.i_size;
- if (!filesize)
- return (0);
-
- if (node) {
- offset = node->nn_diroff;
- ino = node->nn_ino;
- } else {
- offset = dir_node->nn_diroff;
- ino = NANDFS_WHT_INO;
- }
-
- dirent = pdirent = NULL;
- blocksize = dir_node->nn_nandfsdev->nd_blocksize;
- blocknr = offset / blocksize;
-
- DPRINTF(LOOKUP, ("rm direntry dvp %p node %p ino %#jx at off %#jx\n",
- dvp, node, (uintmax_t)ino, (uintmax_t)offset));
-
- error = nandfs_bread(dir_node, blocknr, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
-
- pos = bp->b_data;
- off = 0;
- found = 0;
- limit = offset % blocksize;
- pdirent = (struct nandfs_dir_entry *) bp->b_data;
- while (off <= limit) {
- dirent = (struct nandfs_dir_entry *) (pos + off);
-
- if ((off == limit) &&
- (dirent->inode == ino)) {
- found = 1;
- break;
- }
- if (dirent->inode != 0)
- pdirent = dirent;
- off += dirent->rec_len;
- }
-
- if (!found) {
- nandfs_error("cannot find entry to remove");
- brelse(bp);
- return (error);
- }
- DPRINTF(LOOKUP,
- ("rm dirent ino %#jx at %#x with size %#x\n",
- (uintmax_t)dirent->inode, off, dirent->rec_len));
-
- newsize = (uintptr_t)dirent - (uintptr_t)pdirent;
- newsize += dirent->rec_len;
- pdirent->rec_len = newsize;
- dirent->inode = 0;
- error = nandfs_dirty_buf(bp, 0);
- if (error)
- return (error);
-
- dir_node->nn_flags |= IN_CHANGE | IN_UPDATE;
- /* If last one modify filesize */
- if ((offset + NANDFS_DIR_REC_LEN(dirent->name_len)) == filesize) {
- filesize = blocknr * blocksize +
- ((uintptr_t)pdirent - (uintptr_t)pos) +
- NANDFS_DIR_REC_LEN(pdirent->name_len);
- dir_node->nn_inode.i_size = filesize;
- }
-
- return (0);
-}
-
-int
-nandfs_update_parent_dir(struct vnode *dvp, uint64_t newparent)
-{
- struct nandfs_dir_entry *dirent;
- struct nandfs_node *dir_node;
- struct buf *bp;
- int error;
-
- dir_node = VTON(dvp);
- error = nandfs_bread(dir_node, 0, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
- dirent = (struct nandfs_dir_entry *)bp->b_data;
- dirent->inode = newparent;
- error = nandfs_dirty_buf(bp, 0);
- if (error)
- return (error);
-
- return (0);
-}
-
-int
-nandfs_update_dirent(struct vnode *dvp, struct nandfs_node *fnode,
- struct nandfs_node *tnode)
-{
- struct nandfs_node *dir_node;
- struct nandfs_dir_entry *dirent;
- struct buf *bp;
- uint64_t file_size, blocknr;
- uint32_t blocksize, off;
- uint8_t *pos;
- int error;
-
- dir_node = VTON(dvp);
- file_size = dir_node->nn_inode.i_size;
- if (!file_size)
- return (0);
-
- DPRINTF(LOOKUP,
- ("chg direntry dvp %p ino %#jx to in %#jx at off %#jx\n",
- dvp, (uintmax_t)tnode->nn_ino, (uintmax_t)fnode->nn_ino,
- (uintmax_t)tnode->nn_diroff));
-
- blocksize = dir_node->nn_nandfsdev->nd_blocksize;
- blocknr = tnode->nn_diroff / blocksize;
- off = tnode->nn_diroff % blocksize;
- error = nandfs_bread(dir_node, blocknr, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
-
- pos = bp->b_data;
- dirent = (struct nandfs_dir_entry *) (pos + off);
- KASSERT((dirent->inode == tnode->nn_ino),
- ("direntry mismatch"));
-
- dirent->inode = fnode->nn_ino;
- error = nandfs_dirty_buf(bp, 0);
- if (error)
- return (error);
-
- return (0);
-}
-
-int
-nandfs_init_dir(struct vnode *dvp, uint64_t ino, uint64_t parent_ino)
-{
-
- if (nandfs_add_dirent(dvp, parent_ino, "..", 2, DT_DIR) ||
- nandfs_add_dirent(dvp, ino, ".", 1, DT_DIR)) {
- nandfs_error("%s: cannot initialize dir ino:%jd(pino:%jd)\n",
- __func__, ino, parent_ino);
- return (-1);
- }
- return (0);
-}
diff --git a/sys/fs/nandfs/nandfs_fs.h b/sys/fs/nandfs/nandfs_fs.h
deleted file mode 100644
index 9cb440ebcb906..0000000000000
--- a/sys/fs/nandfs/nandfs_fs.h
+++ /dev/null
@@ -1,567 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2010-2012 Semihalf
- * Copyright (c) 2008, 2009 Reinoud Zandijk
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Original definitions written by Koji Sato <koji@osrg.net>
- * and Ryusuke Konishi <ryusuke@osrg.net>
- * From: NetBSD: nandfs_fs.h,v 1.1 2009/07/18 16:31:42 reinoud
- *
- * $FreeBSD$
- */
-
-#ifndef _NANDFS_FS_H
-#define _NANDFS_FS_H
-
-#include <sys/uuid.h>
-
-#define MNINDIR(fsdev) ((fsdev)->nd_blocksize / sizeof(nandfs_daddr_t))
-
-/*
- * Inode structure. There are a few dedicated inode numbers that are
- * defined here first.
- */
-#define NANDFS_WHT_INO 1 /* Whiteout ino */
-#define NANDFS_ROOT_INO 2 /* Root file inode */
-#define NANDFS_DAT_INO 3 /* DAT file */
-#define NANDFS_CPFILE_INO 4 /* checkpoint file */
-#define NANDFS_SUFILE_INO 5 /* segment usage file */
-#define NANDFS_IFILE_INO 6 /* ifile */
-#define NANDFS_GC_INO 7 /* Cleanerd node */
-#define NANDFS_ATIME_INO 8 /* Atime file (reserved) */
-#define NANDFS_XATTR_INO 9 /* Xattribute file (reserved) */
-#define NANDFS_SKETCH_INO 10 /* Sketch file (obsolete) */
-#define NANDFS_USER_INO 11 /* First user's file inode number */
-
-#define NANDFS_SYS_NODE(ino) \
- (((ino) >= NANDFS_DAT_INO) && ((ino) <= NANDFS_GC_INO))
-
-#define NANDFS_NDADDR 12 /* Direct addresses in inode. */
-#define NANDFS_NIADDR 3 /* Indirect addresses in inode. */
-
-typedef int64_t nandfs_daddr_t;
-typedef int64_t nandfs_lbn_t;
-
-struct nandfs_inode {
- uint64_t i_blocks; /* 0: size in device blocks */
- uint64_t i_size; /* 8: size in bytes */
- uint64_t i_ctime; /* 16: creation time in seconds */
- uint64_t i_mtime; /* 24: modification time in seconds part*/
- uint32_t i_ctime_nsec; /* 32: creation time nanoseconds part */
- uint32_t i_mtime_nsec; /* 36: modification time in nanoseconds */
- uint32_t i_uid; /* 40: user id */
- uint32_t i_gid; /* 44: group id */
- uint16_t i_mode; /* 48: file mode */
- uint16_t i_links_count; /* 50: number of references to the inode*/
- uint32_t i_flags; /* 52: NANDFS_*_FL flags */
- nandfs_daddr_t i_special; /* 56: special */
- nandfs_daddr_t i_db[NANDFS_NDADDR]; /* 64: Direct disk blocks. */
- nandfs_daddr_t i_ib[NANDFS_NIADDR]; /* 160: Indirect disk blocks. */
- uint64_t i_xattr; /* 184: reserved for extended attributes*/
- uint32_t i_generation; /* 192: file generation for NFS */
- uint32_t i_pad[15]; /* 196: make it 64 bits aligned */
-};
-
-#ifdef _KERNEL
-CTASSERT(sizeof(struct nandfs_inode) == 256);
-#endif
-
-/*
- * Each checkpoint/snapshot has a super root.
- *
- * The super root holds the inodes of the three system files: `dat', `cp' and
- * 'su' files. All other FS state is defined by those.
- *
- * It is CRC checksum'ed and time stamped.
- */
-
-struct nandfs_super_root {
- uint32_t sr_sum; /* check-sum */
- uint16_t sr_bytes; /* byte count of this structure */
- uint16_t sr_flags; /* reserved for flags */
- uint64_t sr_nongc_ctime; /* timestamp, not for cleaner(?) */
- struct nandfs_inode sr_dat; /* DAT, virt->phys translation inode */
- struct nandfs_inode sr_cpfile; /* CP, checkpoints inode */
- struct nandfs_inode sr_sufile; /* SU, segment usage inode */
-};
-
-#define NANDFS_SR_MDT_OFFSET(inode_size, i) \
- ((uint32_t)&((struct nandfs_super_root *)0)->sr_dat + \
- (inode_size) * (i))
-
-#define NANDFS_SR_DAT_OFFSET(inode_size) NANDFS_SR_MDT_OFFSET(inode_size, 0)
-#define NANDFS_SR_CPFILE_OFFSET(inode_size) NANDFS_SR_MDT_OFFSET(inode_size, 1)
-#define NANDFS_SR_SUFILE_OFFSET(inode_size) NANDFS_SR_MDT_OFFSET(inode_size, 2)
-#define NANDFS_SR_BYTES (sizeof(struct nandfs_super_root))
-
-/*
- * The superblock describes the basic structure and mount history. It also
- * records some sizes of structures found on the disc for sanity checks.
- *
- * The superblock is stored at two places: NANDFS_SB_OFFSET_BYTES and
- * NANDFS_SB2_OFFSET_BYTES.
- */
-
-/* File system states stored on media in superblock's sbp->s_state */
-#define NANDFS_VALID_FS 0x0001 /* cleanly unmounted and all is ok */
-#define NANDFS_ERROR_FS 0x0002 /* there were errors detected, fsck */
-#define NANDFS_RESIZE_FS 0x0004 /* resize required, XXX unknown flag*/
-#define NANDFS_MOUNT_STATE_BITS "\20\1VALID_FS\2ERROR_FS\3RESIZE_FS"
-
-/*
- * Brief description of control structures:
- *
- * NANDFS_NFSAREAS first blocks contain fsdata and some amount of super blocks.
- * Simple round-robin policy is used in order to choose which block will
- * contain new super block.
- *
- * Simple case with 2 blocks:
- * 1: fsdata sblock1 [sblock3 [sblock5 ..]]
- * 2: fsdata sblock2 [sblock4 [sblock6 ..]]
- */
-struct nandfs_fsdata {
- uint16_t f_magic;
- uint16_t f_bytes;
-
- uint32_t f_sum; /* checksum of fsdata */
- uint32_t f_rev_level; /* major disk format revision */
-
- uint64_t f_ctime; /* creation time (execution time
- of newfs) */
- /* Block size represented as: blocksize = 1 << (f_log_block_size + 10) */
- uint32_t f_log_block_size;
-
- uint16_t f_inode_size; /* size of an inode */
- uint16_t f_dat_entry_size; /* size of a dat entry */
- uint16_t f_checkpoint_size; /* size of a checkpoint */
- uint16_t f_segment_usage_size; /* size of a segment usage */
-
- uint16_t f_sbbytes; /* byte count of CRC calculation
- for super blocks. s_reserved
- is excluded! */
-
- uint16_t f_errors; /* behaviour on detecting errors */
-
- uint32_t f_erasesize;
- uint64_t f_nsegments; /* number of segm. in filesystem */
- nandfs_daddr_t f_first_data_block; /* 1st seg disk block number */
- uint32_t f_blocks_per_segment; /* number of blocks per segment */
- uint32_t f_r_segments_percentage; /* reserved segments percentage */
-
- struct uuid f_uuid; /* 128-bit uuid for volume */
- char f_volume_name[16]; /* volume name */
- uint32_t f_pad[104];
-} __packed;
-
-#ifdef _KERNEL
-CTASSERT(sizeof(struct nandfs_fsdata) == 512);
-#endif
-
-struct nandfs_super_block {
- uint16_t s_magic; /* magic value for identification */
-
- uint32_t s_sum; /* check sum of super block */
-
- uint64_t s_last_cno; /* last checkpoint number */
- uint64_t s_last_pseg; /* addr part. segm. written last */
- uint64_t s_last_seq; /* seq.number of seg written last */
- uint64_t s_free_blocks_count; /* free blocks count */
-
- uint64_t s_mtime; /* mount time */
- uint64_t s_wtime; /* write time */
- uint16_t s_state; /* file system state */
-
- char s_last_mounted[64]; /* directory where last mounted */
-
- uint32_t s_c_interval; /* commit interval of segment */
- uint32_t s_c_block_max; /* threshold of data amount for
- the segment construction */
- uint32_t s_reserved[32]; /* padding to end of the block */
-} __packed;
-
-#ifdef _KERNEL
-CTASSERT(sizeof(struct nandfs_super_block) == 256);
-#endif
-
-#define NANDFS_FSDATA_MAGIC 0xf8da
-#define NANDFS_SUPER_MAGIC 0x8008
-
-#define NANDFS_NFSAREAS 4
-#define NANDFS_DATA_OFFSET_BYTES(esize) (NANDFS_NFSAREAS * (esize))
-
-#define NANDFS_SBLOCK_OFFSET_BYTES (sizeof(struct nandfs_fsdata))
-
-#define NANDFS_DEF_BLOCKSIZE 4096
-#define NANDFS_MIN_BLOCKSIZE 512
-
-#define NANDFS_DEF_ERASESIZE (2 << 16)
-
-#define NANDFS_MIN_SEGSIZE NANDFS_DEF_ERASESIZE
-
-#define NANDFS_CURRENT_REV 9 /* current major revision */
-
-#define NANDFS_FSDATA_CRC_BYTES offsetof(struct nandfs_fsdata, f_pad)
-/* Bytes count of super_block for CRC-calculation */
-#define NANDFS_SB_BYTES offsetof(struct nandfs_super_block, s_reserved)
-
-/* Maximal count of links to a file */
-#define NANDFS_LINK_MAX 32000
-
-/*
- * Structure of a directory entry.
- *
- * Note that they can't span blocks; the rec_len fills out.
- */
-
-#define NANDFS_NAME_LEN 255
-struct nandfs_dir_entry {
- uint64_t inode; /* inode number */
- uint16_t rec_len; /* directory entry length */
- uint8_t name_len; /* name length */
- uint8_t file_type;
- char name[NANDFS_NAME_LEN]; /* file name */
- char pad;
-};
-
-/*
- * NANDFS_DIR_PAD defines the directory entries boundaries
- *
- * NOTE: It must be a multiple of 8
- */
-#define NANDFS_DIR_PAD 8
-#define NANDFS_DIR_ROUND (NANDFS_DIR_PAD - 1)
-#define NANDFS_DIR_NAME_OFFSET (offsetof(struct nandfs_dir_entry, name))
-#define NANDFS_DIR_REC_LEN(name_len) \
- (((name_len) + NANDFS_DIR_NAME_OFFSET + NANDFS_DIR_ROUND) \
- & ~NANDFS_DIR_ROUND)
-#define NANDFS_DIR_NAME_LEN(name_len) \
- (NANDFS_DIR_REC_LEN(name_len) - NANDFS_DIR_NAME_OFFSET)
-
-/*
- * NiLFS/NANDFS devides the disc into fixed length segments. Each segment is
- * filled with one or more partial segments of variable lengths.
- *
- * Each partial segment has a segment summary header followed by updates of
- * files and optionally a super root.
- */
-
-/*
- * Virtual to physical block translation information. For data blocks it maps
- * logical block number bi_blkoff to virtual block nr bi_vblocknr. For non
- * datablocks it is the virtual block number assigned to an indirect block
- * and has no bi_blkoff. The physical block number is the next
- * available data block in the partial segment after all the binfo's.
- */
-struct nandfs_binfo_v {
- uint64_t bi_ino; /* file's inode */
- uint64_t bi_vblocknr; /* assigned virtual block number */
- uint64_t bi_blkoff; /* for file's logical block number */
-};
-
-/*
- * DAT allocation. For data blocks just the logical block number that maps on
- * the next available data block in the partial segment after the binfo's.
- */
-struct nandfs_binfo_dat {
- uint64_t bi_ino;
- uint64_t bi_blkoff; /* DAT file's logical block number */
- uint8_t bi_level; /* whether this is meta block */
- uint8_t bi_pad[7];
-};
-
-#ifdef _KERNEL
-CTASSERT(sizeof(struct nandfs_binfo_v) == sizeof(struct nandfs_binfo_dat));
-#endif
-
-/* Convenience union for both types of binfo's */
-union nandfs_binfo {
- struct nandfs_binfo_v bi_v;
- struct nandfs_binfo_dat bi_dat;
-};
-
-/* Indirect buffers path */
-struct nandfs_indir {
- nandfs_daddr_t in_lbn;
- int in_off;
-};
-
-/* The (partial) segment summary */
-struct nandfs_segment_summary {
- uint32_t ss_datasum; /* CRC of complete data block */
- uint32_t ss_sumsum; /* CRC of segment summary only */
- uint32_t ss_magic; /* magic to identify segment summary */
- uint16_t ss_bytes; /* size of segment summary structure */
- uint16_t ss_flags; /* NANDFS_SS_* flags */
- uint64_t ss_seq; /* sequence number of this segm. sum */
- uint64_t ss_create; /* creation timestamp in seconds */
- uint64_t ss_next; /* blocknumber of next segment */
- uint32_t ss_nblocks; /* number of blocks used by summary */
- uint32_t ss_nbinfos; /* number of binfo structures */
- uint32_t ss_sumbytes; /* total size of segment summary */
- uint32_t ss_pad;
- /* stream of binfo structures */
-};
-
-#define NANDFS_SEGSUM_MAGIC 0x8e680011 /* segment summary magic number */
-
-/* Segment summary flags */
-#define NANDFS_SS_LOGBGN 0x0001 /* begins a logical segment */
-#define NANDFS_SS_LOGEND 0x0002 /* ends a logical segment */
-#define NANDFS_SS_SR 0x0004 /* has super root */
-#define NANDFS_SS_SYNDT 0x0008 /* includes data only updates */
-#define NANDFS_SS_GC 0x0010 /* segment written for cleaner operation */
-#define NANDFS_SS_FLAG_BITS "\20\1LOGBGN\2LOGEND\3SR\4SYNDT\5GC"
-
-/* Segment summary constrains */
-#define NANDFS_SEG_MIN_BLOCKS 16 /* minimum number of blocks in a
- full segment */
-#define NANDFS_PSEG_MIN_BLOCKS 2 /* minimum number of blocks in a
- partial segment */
-#define NANDFS_MIN_NRSVSEGS 8 /* minimum number of reserved
- segments */
-
-/*
- * Structure of DAT/inode file.
- *
- * A DAT file is divided into groups. The maximum number of groups is the
- * number of block group descriptors that fit into one block; this descriptor
- * only gives the number of free entries in the associated group.
- *
- * Each group has a block sized bitmap indicating if an entry is taken or
- * empty. Each bit stands for a DAT entry.
- *
- * The inode file has exactly the same format only the entries are inode
- * entries.
- */
-
-struct nandfs_block_group_desc {
- uint32_t bg_nfrees; /* num. free entries in block group */
-};
-
-/* DAT entry in a super root's DAT file */
-struct nandfs_dat_entry {
- uint64_t de_blocknr; /* block number */
- uint64_t de_start; /* valid from checkpoint */
- uint64_t de_end; /* valid till checkpoint */
- uint64_t de_rsv; /* reserved for future use */
-};
-
-/*
- * Structure of CP file.
- *
- * A snapshot is just a checkpoint only it's protected against removal by the
- * cleaner. The snapshots are kept on a double linked list of checkpoints.
- */
-struct nandfs_snapshot_list {
- uint64_t ssl_next; /* checkpoint nr. forward */
- uint64_t ssl_prev; /* checkpoint nr. back */
-};
-
-/* Checkpoint entry structure */
-struct nandfs_checkpoint {
- uint32_t cp_flags; /* NANDFS_CHECKPOINT_* flags */
- uint32_t cp_checkpoints_count; /* ZERO, not used anymore? */
- struct nandfs_snapshot_list cp_snapshot_list; /* list of snapshots */
- uint64_t cp_cno; /* checkpoint number */
- uint64_t cp_create; /* creation timestamp */
- uint64_t cp_nblk_inc; /* number of blocks incremented */
- uint64_t cp_blocks_count; /* reserved (might be deleted) */
- struct nandfs_inode cp_ifile_inode; /* inode file inode */
-};
-
-/* Checkpoint flags */
-#define NANDFS_CHECKPOINT_SNAPSHOT 1
-#define NANDFS_CHECKPOINT_INVALID 2
-#define NANDFS_CHECKPOINT_SKETCH 4
-#define NANDFS_CHECKPOINT_MINOR 8
-#define NANDFS_CHECKPOINT_BITS "\20\1SNAPSHOT\2INVALID\3SKETCH\4MINOR"
-
-/* Header of the checkpoint file */
-struct nandfs_cpfile_header {
- uint64_t ch_ncheckpoints; /* number of checkpoints */
- uint64_t ch_nsnapshots; /* number of snapshots */
- struct nandfs_snapshot_list ch_snapshot_list; /* snapshot list */
-};
-
-#define NANDFS_CPFILE_FIRST_CHECKPOINT_OFFSET \
- ((sizeof(struct nandfs_cpfile_header) + \
- sizeof(struct nandfs_checkpoint) - 1) / \
- sizeof(struct nandfs_checkpoint))
-
-
-#define NANDFS_NOSEGMENT 0xffffffff
-
-/*
- * Structure of SU file.
- *
- * The segment usage file sums up how each of the segments are used. They are
- * indexed by their segment number.
- */
-
-/* Segment usage entry */
-struct nandfs_segment_usage {
- uint64_t su_lastmod; /* last modified timestamp */
- uint32_t su_nblocks; /* number of blocks in segment */
- uint32_t su_flags; /* NANDFS_SEGMENT_USAGE_* flags */
-};
-
-/* Segment usage flag */
-#define NANDFS_SEGMENT_USAGE_ACTIVE 1
-#define NANDFS_SEGMENT_USAGE_DIRTY 2
-#define NANDFS_SEGMENT_USAGE_ERROR 4
-#define NANDFS_SEGMENT_USAGE_GC 8
-#define NANDFS_SEGMENT_USAGE_BITS "\20\1ACTIVE\2DIRTY\3ERROR"
-
-/* Header of the segment usage file */
-struct nandfs_sufile_header {
- uint64_t sh_ncleansegs; /* number of segments marked clean */
- uint64_t sh_ndirtysegs; /* number of segments marked dirty */
- uint64_t sh_last_alloc; /* last allocated segment number */
-};
-
-#define NANDFS_SUFILE_FIRST_SEGMENT_USAGE_OFFSET \
- ((sizeof(struct nandfs_sufile_header) + \
- sizeof(struct nandfs_segment_usage) - 1) / \
- sizeof(struct nandfs_segment_usage))
-
-struct nandfs_seg_stat {
- uint64_t nss_nsegs;
- uint64_t nss_ncleansegs;
- uint64_t nss_ndirtysegs;
- uint64_t nss_ctime;
- uint64_t nss_nongc_ctime;
- uint64_t nss_prot_seq;
-};
-
-enum {
- NANDFS_CHECKPOINT,
- NANDFS_SNAPSHOT
-};
-
-#define NANDFS_CPINFO_MAX 512
-
-struct nandfs_cpinfo {
- uint32_t nci_flags;
- uint32_t nci_pad;
- uint64_t nci_cno;
- uint64_t nci_create;
- uint64_t nci_nblk_inc;
- uint64_t nci_blocks_count;
- uint64_t nci_next;
-};
-
-#define NANDFS_SEGMENTS_MAX 512
-
-struct nandfs_suinfo {
- uint64_t nsi_num;
- uint64_t nsi_lastmod;
- uint32_t nsi_blocks;
- uint32_t nsi_flags;
-};
-
-#define NANDFS_VINFO_MAX 512
-
-struct nandfs_vinfo {
- uint64_t nvi_ino;
- uint64_t nvi_vblocknr;
- uint64_t nvi_start;
- uint64_t nvi_end;
- uint64_t nvi_blocknr;
- int nvi_alive;
-};
-
-struct nandfs_cpmode {
- uint64_t ncpm_cno;
- uint32_t ncpm_mode;
- uint32_t ncpm_pad;
-};
-
-struct nandfs_argv {
- uint64_t nv_base;
- uint32_t nv_nmembs;
- uint16_t nv_size;
- uint16_t nv_flags;
- uint64_t nv_index;
-};
-
-struct nandfs_cpstat {
- uint64_t ncp_cno;
- uint64_t ncp_ncps;
- uint64_t ncp_nss;
-};
-
-struct nandfs_period {
- uint64_t p_start;
- uint64_t p_end;
-};
-
-struct nandfs_vdesc {
- uint64_t vd_ino;
- uint64_t vd_cno;
- uint64_t vd_vblocknr;
- struct nandfs_period vd_period;
- uint64_t vd_blocknr;
- uint64_t vd_offset;
- uint32_t vd_flags;
- uint32_t vd_pad;
-};
-
-struct nandfs_bdesc {
- uint64_t bd_ino;
- uint64_t bd_oblocknr;
- uint64_t bd_blocknr;
- uint64_t bd_offset;
- uint32_t bd_level;
- uint32_t bd_alive;
-};
-
-#ifndef _KERNEL
-#ifndef MNAMELEN
-#define MNAMELEN 1024
-#endif
-#endif
-
-struct nandfs_fsinfo {
- struct nandfs_fsdata fs_fsdata;
- struct nandfs_super_block fs_super;
- char fs_dev[MNAMELEN];
-};
-
-#define NANDFS_MAX_MOUNTS 65535
-
-#define NANDFS_IOCTL_GET_SUSTAT _IOR('N', 100, struct nandfs_seg_stat)
-#define NANDFS_IOCTL_CHANGE_CPMODE _IOWR('N', 101, struct nandfs_cpmode)
-#define NANDFS_IOCTL_GET_CPINFO _IOWR('N', 102, struct nandfs_argv)
-#define NANDFS_IOCTL_DELETE_CP _IOWR('N', 103, uint64_t[2])
-#define NANDFS_IOCTL_GET_CPSTAT _IOR('N', 104, struct nandfs_cpstat)
-#define NANDFS_IOCTL_GET_SUINFO _IOWR('N', 105, struct nandfs_argv)
-#define NANDFS_IOCTL_GET_VINFO _IOWR('N', 106, struct nandfs_argv)
-#define NANDFS_IOCTL_GET_BDESCS _IOWR('N', 107, struct nandfs_argv)
-#define NANDFS_IOCTL_GET_FSINFO _IOR('N', 108, struct nandfs_fsinfo)
-#define NANDFS_IOCTL_MAKE_SNAP _IOWR('N', 109, uint64_t)
-#define NANDFS_IOCTL_DELETE_SNAP _IOWR('N', 110, uint64_t)
-#define NANDFS_IOCTL_SYNC _IOWR('N', 111, uint64_t)
-
-#endif /* _NANDFS_FS_H */
diff --git a/sys/fs/nandfs/nandfs_ifile.c b/sys/fs/nandfs/nandfs_ifile.c
deleted file mode 100644
index 2c10bbac1ffea..0000000000000
--- a/sys/fs/nandfs/nandfs_ifile.c
+++ /dev/null
@@ -1,215 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2010-2012 Semihalf.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/mount.h>
-#include <sys/mutex.h>
-#include <sys/namei.h>
-#include <sys/sysctl.h>
-#include <sys/vnode.h>
-#include <sys/buf.h>
-#include <sys/bio.h>
-
-#include <vm/vm.h>
-#include <vm/vm_param.h>
-#include <vm/vm_kern.h>
-#include <vm/vm_page.h>
-
-#include <fs/nandfs/nandfs_mount.h>
-#include <fs/nandfs/nandfs.h>
-#include <fs/nandfs/nandfs_subr.h>
-
-int
-nandfs_node_create(struct nandfsmount *nmp, struct nandfs_node **node,
- uint16_t mode)
-{
- struct nandfs_alloc_request req;
- struct nandfs_device *nandfsdev;
- struct nandfs_mdt *mdt;
- struct nandfs_node *ifile;
- struct nandfs_inode *inode;
- struct vnode *vp;
- uint32_t entry;
- int error = 0;
-
- nandfsdev = nmp->nm_nandfsdev;
- mdt = &nandfsdev->nd_ifile_mdt;
- ifile = nmp->nm_ifile_node;
- vp = NTOV(ifile);
-
- VOP_LOCK(vp, LK_EXCLUSIVE);
- /* Allocate new inode in ifile */
- req.entrynum = nandfsdev->nd_last_ino + 1;
- error = nandfs_find_free_entry(mdt, ifile, &req);
- if (error) {
- VOP_UNLOCK(vp, 0);
- return (error);
- }
-
- error = nandfs_get_entry_block(mdt, ifile, &req, &entry, 1);
- if (error) {
- VOP_UNLOCK(vp, 0);
- return (error);
- }
-
- /* Inode initialization */
- inode = ((struct nandfs_inode *) req.bp_entry->b_data) + entry;
- nandfs_inode_init(inode, mode);
-
- error = nandfs_alloc_entry(mdt, &req);
- if (error) {
- VOP_UNLOCK(vp, 0);
- return (error);
- }
-
- VOP_UNLOCK(vp, 0);
-
- nandfsdev->nd_last_ino = req.entrynum;
- error = nandfs_get_node(nmp, req.entrynum, node);
- DPRINTF(IFILE, ("%s: node: %p ino: %#jx\n",
- __func__, node, (uintmax_t)((*node)->nn_ino)));
-
- return (error);
-}
-
-int
-nandfs_node_destroy(struct nandfs_node *node)
-{
- struct nandfs_alloc_request req;
- struct nandfsmount *nmp;
- struct nandfs_mdt *mdt;
- struct nandfs_node *ifile;
- struct vnode *vp;
- int error = 0;
-
- nmp = node->nn_nmp;
- req.entrynum = node->nn_ino;
- mdt = &nmp->nm_nandfsdev->nd_ifile_mdt;
- ifile = nmp->nm_ifile_node;
- vp = NTOV(ifile);
-
- DPRINTF(IFILE, ("%s: destroy node: %p ino: %#jx\n",
- __func__, node, (uintmax_t)node->nn_ino));
- VOP_LOCK(vp, LK_EXCLUSIVE);
-
- error = nandfs_find_entry(mdt, ifile, &req);
- if (error) {
- nandfs_error("%s: finding entry error:%d node %p(%jx)",
- __func__, error, node, node->nn_ino);
- VOP_UNLOCK(vp, 0);
- return (error);
- }
-
- nandfs_inode_destroy(&node->nn_inode);
-
- error = nandfs_free_entry(mdt, &req);
- if (error) {
- nandfs_error("%s: freing entry error:%d node %p(%jx)",
- __func__, error, node, node->nn_ino);
- VOP_UNLOCK(vp, 0);
- return (error);
- }
-
- VOP_UNLOCK(vp, 0);
- DPRINTF(IFILE, ("%s: freed node %p ino %#jx\n",
- __func__, node, (uintmax_t)node->nn_ino));
- return (error);
-}
-
-int
-nandfs_node_update(struct nandfs_node *node)
-{
- struct nandfs_alloc_request req;
- struct nandfsmount *nmp;
- struct nandfs_mdt *mdt;
- struct nandfs_node *ifile;
- struct nandfs_inode *inode;
- uint32_t index;
- int error = 0;
-
- nmp = node->nn_nmp;
- ifile = nmp->nm_ifile_node;
- ASSERT_VOP_LOCKED(NTOV(ifile), __func__);
-
- req.entrynum = node->nn_ino;
- mdt = &nmp->nm_nandfsdev->nd_ifile_mdt;
-
- DPRINTF(IFILE, ("%s: node:%p ino:%#jx\n",
- __func__, &node->nn_inode, (uintmax_t)node->nn_ino));
-
- error = nandfs_get_entry_block(mdt, ifile, &req, &index, 0);
- if (error) {
- printf("nandfs_get_entry_block returned with ERROR=%d\n",
- error);
- return (error);
- }
-
- inode = ((struct nandfs_inode *) req.bp_entry->b_data) + index;
- memcpy(inode, &node->nn_inode, sizeof(*inode));
- error = nandfs_dirty_buf(req.bp_entry, 0);
-
- return (error);
-}
-
-int
-nandfs_get_node_entry(struct nandfsmount *nmp, struct nandfs_inode **inode,
- uint64_t ino, struct buf **bp)
-{
- struct nandfs_alloc_request req;
- struct nandfs_mdt *mdt;
- struct nandfs_node *ifile;
- struct vnode *vp;
- uint32_t index;
- int error = 0;
-
- req.entrynum = ino;
- mdt = &nmp->nm_nandfsdev->nd_ifile_mdt;
- ifile = nmp->nm_ifile_node;
- vp = NTOV(ifile);
-
- VOP_LOCK(vp, LK_EXCLUSIVE);
- error = nandfs_get_entry_block(mdt, ifile, &req, &index, 0);
- if (error) {
- VOP_UNLOCK(vp, 0);
- return (error);
- }
-
- *inode = ((struct nandfs_inode *) req.bp_entry->b_data) + index;
- *bp = req.bp_entry;
- VOP_UNLOCK(vp, 0);
- return (0);
-}
-
diff --git a/sys/fs/nandfs/nandfs_mount.h b/sys/fs/nandfs/nandfs_mount.h
deleted file mode 100644
index cc6e30eb0bbd7..0000000000000
--- a/sys/fs/nandfs/nandfs_mount.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-4-Clause
- *
- * Copyright (c) 2008, 2009 Reinoud Zandijk
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed for the
- * NetBSD Project. See http://www.NetBSD.org/ for
- * information about NetBSD.
- * 4. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * From: NetBSD: nilfs_mount.h,v 1.1 2009/07/18 16:31:42 reinoud
- *
- * $FreeBSD$
- */
-
-#ifndef _FS_NANDFS_NANDFS_MOUNT_H_
-#define _FS_NANDFS_NANDFS_MOUNT_H_
-
-/*
- * Arguments to mount NANDFS filingsystem.
- */
-
-struct nandfs_args {
- char *fspec; /* mount specifier */
- int64_t cpno; /* checkpoint number */
-};
-
-#endif /* !_FS_NANDFS_NANDFS_MOUNT_H_ */
-
diff --git a/sys/fs/nandfs/nandfs_segment.c b/sys/fs/nandfs/nandfs_segment.c
deleted file mode 100644
index 36efc89af4099..0000000000000
--- a/sys/fs/nandfs/nandfs_segment.c
+++ /dev/null
@@ -1,1314 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2010-2012 Semihalf.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include "opt_ddb.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/conf.h>
-#include <sys/gsb_crc32.h>
-#include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/mount.h>
-#include <sys/mutex.h>
-#include <sys/namei.h>
-#include <sys/rwlock.h>
-#include <sys/sysctl.h>
-#include <sys/vnode.h>
-#include <sys/buf.h>
-#include <sys/bio.h>
-#include <sys/libkern.h>
-
-#include <ddb/ddb.h>
-
-#include <vm/vm.h>
-#include <vm/vm_param.h>
-#include <vm/vm_kern.h>
-#include <vm/vm_page.h>
-
-#include <geom/geom.h>
-#include <geom/geom_vfs.h>
-
-#include <fs/nandfs/nandfs_mount.h>
-#include <fs/nandfs/nandfs.h>
-#include <fs/nandfs/nandfs_subr.h>
-
-static int
-nandfs_new_segment(struct nandfs_device *fsdev)
-{
- int error = 0;
- uint64_t new;
-
- error = nandfs_alloc_segment(fsdev, &new);
- if (!error) {
- fsdev->nd_seg_num = fsdev->nd_next_seg_num;
- fsdev->nd_next_seg_num = new;
- }
- DPRINTF(SYNC, ("%s: new segment %jx next %jx error %d\n",
- __func__, (uintmax_t)fsdev->nd_seg_num, (uintmax_t)new, error));
- if (error)
- nandfs_error("%s: cannot create segment error %d\n",
- __func__, error);
-
- return (error);
-}
-
-static int
-create_segment(struct nandfs_seginfo *seginfo)
-{
- struct nandfs_segment *seg;
- struct nandfs_device *fsdev;
- struct nandfs_segment *prev;
- struct buf *bp;
- uint64_t start_block, curr;
- uint32_t blks_per_seg, nblocks;
- int error;
-
- fsdev = seginfo->fsdev;
- prev = seginfo->curseg;
- blks_per_seg = fsdev->nd_fsdata.f_blocks_per_segment;
- nblocks = fsdev->nd_last_segsum.ss_nblocks;
-
- if (!prev) {
- vfs_timestamp(&fsdev->nd_ts);
- /* Touch current segment */
- error = nandfs_touch_segment(fsdev, fsdev->nd_seg_num);
- if (error) {
- nandfs_error("%s: cannot preallocate segment %jx\n",
- __func__, fsdev->nd_seg_num);
- return (error);
- }
- error = nandfs_touch_segment(fsdev, 0);
- if (error) {
- nandfs_error("%s: cannot dirty block with segment 0\n",
- __func__);
- return (error);
- }
- start_block = fsdev->nd_last_pseg + (uint64_t)nblocks;
- /*
- * XXX Hack
- */
- if (blks_per_seg - (start_block % blks_per_seg) - 1 == 0)
- start_block++;
- curr = nandfs_get_segnum_of_block(fsdev, start_block);
- /* Allocate new segment if last one is full */
- if (fsdev->nd_seg_num != curr) {
- error = nandfs_new_segment(fsdev);
- if (error) {
- nandfs_error("%s: cannot create new segment\n",
- __func__);
- return (error);
- }
- /*
- * XXX Hack
- */
- nandfs_get_segment_range(fsdev, fsdev->nd_seg_num, &start_block, NULL);
- }
- } else {
- nandfs_get_segment_range(fsdev, fsdev->nd_next_seg_num,
- &start_block, NULL);
-
- /* Touch current segment and allocate and touch new one */
- error = nandfs_new_segment(fsdev);
- if (error) {
- nandfs_error("%s: cannot create next segment\n",
- __func__);
- return (error);
- }
-
- /* Reiterate in case new buf is dirty */
- seginfo->reiterate = 1;
- }
-
- /* Allocate and initialize nandfs_segment structure */
- seg = malloc(sizeof(*seg), M_DEVBUF, M_WAITOK|M_ZERO);
- TAILQ_INIT(&seg->segsum);
- TAILQ_INIT(&seg->data);
- seg->fsdev = fsdev;
- seg->start_block = start_block;
- seg->num_blocks = blks_per_seg - (start_block % blks_per_seg) - 1;
- seg->seg_num = fsdev->nd_seg_num;
- seg->seg_next = fsdev->nd_next_seg_num;
- seg->segsum_blocks = 1;
- seg->bytes_left = fsdev->nd_blocksize -
- sizeof(struct nandfs_segment_summary);
- seg->segsum_bytes = sizeof(struct nandfs_segment_summary);
-
- /* Allocate buffer for segment summary */
- bp = getblk(fsdev->nd_devvp, nandfs_block_to_dblock(fsdev,
- seg->start_block), fsdev->nd_blocksize, 0, 0, 0);
- bzero(bp->b_data, seginfo->fsdev->nd_blocksize);
- bp->b_bufobj = &seginfo->fsdev->nd_devvp->v_bufobj;
- bp->b_flags |= B_MANAGED;
-
- /* Add buffer to segment */
- TAILQ_INSERT_TAIL(&seg->segsum, bp, b_cluster.cluster_entry);
- seg->current_off = bp->b_data + sizeof(struct nandfs_segment_summary);
-
- DPRINTF(SYNC, ("%s: seg %p : initial settings: start %#jx size :%#x\n",
- __func__, seg, (uintmax_t)seg->start_block, seg->num_blocks));
- DPRINTF(SYNC, ("%s: seg->seg_num %#jx cno %#jx next %#jx\n", __func__,
- (uintmax_t)seg->seg_num, (uintmax_t)(fsdev->nd_last_cno + 1),
- (uintmax_t)seg->seg_next));
-
- if (!prev)
- LIST_INSERT_HEAD(&seginfo->seg_list, seg, seg_link);
- else
- LIST_INSERT_AFTER(prev, seg, seg_link);
-
- seginfo->curseg = seg;
-
- return (0);
-}
-
-static int
-delete_segment(struct nandfs_seginfo *seginfo)
-{
- struct nandfs_segment *seg, *tseg;
- struct buf *bp, *tbp;
-
- LIST_FOREACH_SAFE(seg, &seginfo->seg_list, seg_link, tseg) {
- TAILQ_FOREACH_SAFE(bp, &seg->segsum, b_cluster.cluster_entry,
- tbp) {
- TAILQ_REMOVE(&seg->segsum, bp, b_cluster.cluster_entry);
- bp->b_flags &= ~B_MANAGED;
- brelse(bp);
- }
-
- LIST_REMOVE(seg, seg_link);
- free(seg, M_DEVBUF);
- }
-
- return (0);
-}
-
-static int
-create_seginfo(struct nandfs_device *fsdev, struct nandfs_seginfo **seginfo)
-{
- struct nandfs_seginfo *info;
-
- info = malloc(sizeof(*info), M_DEVBUF, M_WAITOK);
-
- LIST_INIT(&info->seg_list);
- info->fsdev = fsdev;
- info->curseg = NULL;
- info->blocks = 0;
- *seginfo = info;
- fsdev->nd_seginfo = info;
- return (0);
-}
-
-static int
-delete_seginfo(struct nandfs_seginfo *seginfo)
-{
- struct nandfs_device *nffsdev;
-
- nffsdev = seginfo->fsdev;
- delete_segment(seginfo);
- nffsdev->nd_seginfo = NULL;
- free(seginfo, M_DEVBUF);
-
- return (0);
-}
-
-static int
-nandfs_create_superroot_block(struct nandfs_seginfo *seginfo,
- struct buf **newbp)
-{
- struct buf *bp;
- int error;
-
- bp = nandfs_geteblk(seginfo->fsdev->nd_blocksize, GB_NOWAIT_BD);
-
- bzero(bp->b_data, seginfo->fsdev->nd_blocksize);
- bp->b_bufobj = &seginfo->fsdev->nd_devvp->v_bufobj;
- bp->b_flags |= B_MANAGED;
-
- if (!(seginfo->curseg) || !seginfo->curseg->num_blocks) {
- error = create_segment(seginfo);
- if (error) {
- brelse(bp);
- nandfs_error("%s: no segment for superroot\n",
- __func__);
- return (error);
- }
- }
-
- TAILQ_INSERT_TAIL(&seginfo->curseg->data, bp, b_cluster.cluster_entry);
-
- seginfo->curseg->nblocks++;
- seginfo->curseg->num_blocks--;
- seginfo->blocks++;
-
- *newbp = bp;
- return (0);
-}
-
-static int
-nandfs_add_superroot(struct nandfs_seginfo *seginfo)
-{
- struct nandfs_device *fsdev;
- struct nandfs_super_root *sr;
- struct buf *bp = NULL;
- uint64_t crc_skip;
- uint32_t crc_calc;
- int error;
-
- fsdev = seginfo->fsdev;
-
- error = nandfs_create_superroot_block(seginfo, &bp);
- if (error) {
- nandfs_error("%s: cannot add superroot\n", __func__);
- return (error);
- }
-
- sr = (struct nandfs_super_root *)bp->b_data;
- /* Save superroot CRC */
- sr->sr_bytes = NANDFS_SR_BYTES;
- sr->sr_flags = 0;
- sr->sr_nongc_ctime = 0;
-
- memcpy(&sr->sr_dat, &fsdev->nd_dat_node->nn_inode,
- sizeof(struct nandfs_inode));
- memcpy(&sr->sr_cpfile, &fsdev->nd_cp_node->nn_inode,
- sizeof(struct nandfs_inode));
- memcpy(&sr->sr_sufile, &fsdev->nd_su_node->nn_inode,
- sizeof(struct nandfs_inode));
-
- crc_skip = sizeof(sr->sr_sum);
- crc_calc = crc32((uint8_t *)sr + crc_skip, NANDFS_SR_BYTES - crc_skip);
-
- sr->sr_sum = crc_calc;
-
- bp->b_flags |= B_MANAGED;
- bp->b_bufobj = &seginfo->fsdev->nd_devvp->v_bufobj;
-
- bp->b_flags &= ~B_INVAL;
- nandfs_dirty_bufs_increment(fsdev);
- DPRINTF(SYNC, ("%s: bp:%p\n", __func__, bp));
-
- return (0);
-}
-
-static int
-nandfs_add_segsum_block(struct nandfs_seginfo *seginfo, struct buf **newbp)
-{
- struct nandfs_device *fsdev;
- nandfs_daddr_t blk;
- struct buf *bp;
- int error;
-
- if (!(seginfo->curseg) || seginfo->curseg->num_blocks <= 1) {
- error = create_segment(seginfo);
- if (error) {
- nandfs_error("%s: error:%d when creating segment\n",
- __func__, error);
- return (error);
- }
- *newbp = TAILQ_FIRST(&seginfo->curseg->segsum);
- return (0);
- }
-
- fsdev = seginfo->fsdev;
- blk = nandfs_block_to_dblock(fsdev, seginfo->curseg->start_block +
- seginfo->curseg->segsum_blocks);
-
- bp = getblk(fsdev->nd_devvp, blk, fsdev->nd_blocksize, 0, 0, 0);
-
- bzero(bp->b_data, seginfo->fsdev->nd_blocksize);
- bp->b_bufobj = &seginfo->fsdev->nd_devvp->v_bufobj;
- bp->b_flags |= B_MANAGED;
-
- TAILQ_INSERT_TAIL(&seginfo->curseg->segsum, bp,
- b_cluster.cluster_entry);
- seginfo->curseg->num_blocks--;
-
- seginfo->curseg->segsum_blocks++;
- seginfo->curseg->bytes_left = seginfo->fsdev->nd_blocksize;
- seginfo->curseg->current_off = bp->b_data;
- seginfo->blocks++;
-
- *newbp = bp;
-
- DPRINTF(SYNC, ("%s: bp %p\n", __func__, bp));
-
- return (0);
-}
-
-static int
-nandfs_add_blocks(struct nandfs_seginfo *seginfo, struct nandfs_node *node,
- struct buf *bp)
-{
- union nandfs_binfo *binfo;
- struct buf *seg_bp;
- int error;
-
- if (!(seginfo->curseg) || !seginfo->curseg->num_blocks) {
- error = create_segment(seginfo);
- if (error) {
- nandfs_error("%s: error:%d when creating segment\n",
- __func__, error);
- return (error);
- }
- }
-
- if (seginfo->curseg->bytes_left < sizeof(union nandfs_binfo)) {
- error = nandfs_add_segsum_block(seginfo, &seg_bp);
- if (error) {
- nandfs_error("%s: error:%d when adding segsum\n",
- __func__, error);
- return (error);
- }
- }
- binfo = (union nandfs_binfo *)seginfo->curseg->current_off;
-
- if (node->nn_ino != NANDFS_DAT_INO) {
- binfo->bi_v.bi_blkoff = bp->b_lblkno;
- binfo->bi_v.bi_ino = node->nn_ino;
- } else {
- binfo->bi_dat.bi_blkoff = bp->b_lblkno;
- binfo->bi_dat.bi_ino = node->nn_ino;
- if (NANDFS_IS_INDIRECT(bp))
- binfo->bi_dat.bi_level = 1;
- else
- binfo->bi_dat.bi_level = 0;
- }
- binfo++;
-
- seginfo->curseg->bytes_left -= sizeof(union nandfs_binfo);
- seginfo->curseg->segsum_bytes += sizeof(union nandfs_binfo);
- seginfo->curseg->current_off = (char *)binfo;
-
- TAILQ_INSERT_TAIL(&seginfo->curseg->data, bp, b_cluster.cluster_entry);
-
- seginfo->curseg->nbinfos++;
- seginfo->curseg->nblocks++;
- seginfo->curseg->num_blocks--;
- seginfo->blocks++;
-
- DPRINTF(SYNC, ("%s: bp (%p) number %x (left %x)\n",
- __func__, bp, seginfo->curseg->nblocks,
- seginfo->curseg->num_blocks));
- return (0);
-}
-
-static int
-nandfs_iterate_dirty_buf(struct vnode *vp, struct nandfs_seginfo *seginfo,
- uint8_t hold)
-{
- struct buf *bp, *tbd;
- struct bufobj *bo;
- struct nandfs_node *node;
- int error;
-
- node = VTON(vp);
- bo = &vp->v_bufobj;
-
- ASSERT_VOP_ELOCKED(vp, __func__);
-
- /* Iterate dirty data bufs */
- TAILQ_FOREACH_SAFE(bp, &bo->bo_dirty.bv_hd, b_bobufs, tbd) {
- DPRINTF(SYNC, ("%s: vp (%p): bp (%p) with lblkno %jx ino %jx "
- "add buf\n", __func__, vp, bp, bp->b_lblkno, node->nn_ino));
-
- if (!(NANDFS_ISGATHERED(bp))) {
- error = nandfs_bmap_update_dat(node,
- nandfs_vblk_get(bp), bp);
- if (error)
- return (error);
- NANDFS_GATHER(bp);
- nandfs_add_blocks(seginfo, node, bp);
- }
- }
-
- return (0);
-}
-
-static int
-nandfs_iterate_system_vnode(struct nandfs_node *node,
- struct nandfs_seginfo *seginfo)
-{
- struct vnode *vp;
- int nblocks;
- uint8_t hold = 0;
-
- if (node->nn_ino != NANDFS_IFILE_INO)
- hold = 1;
-
- vp = NTOV(node);
-
- nblocks = vp->v_bufobj.bo_dirty.bv_cnt;
- DPRINTF(SYNC, ("%s: vp (%p): nblocks %x ino %jx\n",
- __func__, vp, nblocks, node->nn_ino));
-
- if (nblocks)
- nandfs_iterate_dirty_buf(vp, seginfo, hold);
-
- return (0);
-}
-
-static int
-nandfs_iterate_dirty_vnodes(struct mount *mp, struct nandfs_seginfo *seginfo)
-{
- struct nandfs_node *nandfs_node;
- struct vnode *vp, *mvp;
- struct thread *td;
- struct bufobj *bo;
- int error, update;
-
- td = curthread;
-
- MNT_VNODE_FOREACH_ACTIVE(vp, mp, mvp) {
- update = 0;
-
- if (mp->mnt_syncer == vp || VOP_ISLOCKED(vp)) {
- VI_UNLOCK(vp);
- continue;
- }
- if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK | LK_NOWAIT, td) != 0)
- continue;
-
- nandfs_node = VTON(vp);
- if (nandfs_node->nn_flags & IN_MODIFIED) {
- nandfs_node->nn_flags &= ~(IN_MODIFIED);
- update = 1;
- }
-
- bo = &vp->v_bufobj;
- BO_LOCK(bo);
- if (vp->v_bufobj.bo_dirty.bv_cnt) {
- error = nandfs_iterate_dirty_buf(vp, seginfo, 0);
- if (error) {
- nandfs_error("%s: cannot iterate vnode:%p "
- "err:%d\n", __func__, vp, error);
- vput(vp);
- BO_UNLOCK(bo);
- return (error);
- }
- update = 1;
- } else
- vput(vp);
- BO_UNLOCK(bo);
-
- if (update)
- nandfs_node_update(nandfs_node);
- }
-
- return (0);
-}
-
-static int
-nandfs_update_phys_block(struct nandfs_device *fsdev, struct buf *bp,
- uint64_t phys_blknr, union nandfs_binfo *binfo)
-{
- struct nandfs_node *node, *dat;
- struct vnode *vp;
- uint64_t new_blknr;
- int error;
-
- vp = bp->b_vp;
- node = VTON(vp);
- new_blknr = nandfs_vblk_get(bp);
- dat = fsdev->nd_dat_node;
-
- DPRINTF(BMAP, ("%s: ino %#jx lblk %#jx: vblk %#jx -> %#jx\n",
- __func__, (uintmax_t)node->nn_ino, (uintmax_t)bp->b_lblkno,
- (uintmax_t)new_blknr, (uintmax_t)phys_blknr));
-
- if (node->nn_ino != NANDFS_DAT_INO) {
- KASSERT((new_blknr != 0), ("vblk for bp %p is 0", bp));
-
- nandfs_vblock_assign(fsdev, new_blknr, phys_blknr);
- binfo->bi_v.bi_vblocknr = new_blknr;
- binfo->bi_v.bi_blkoff = bp->b_lblkno;
- binfo->bi_v.bi_ino = node->nn_ino;
- } else {
- VOP_LOCK(NTOV(dat), LK_EXCLUSIVE);
- error = nandfs_bmap_update_block(node, bp, phys_blknr);
- if (error) {
- nandfs_error("%s: error updating block:%jx for bp:%p\n",
- __func__, (uintmax_t)phys_blknr, bp);
- VOP_UNLOCK(NTOV(dat), 0);
- return (error);
- }
- VOP_UNLOCK(NTOV(dat), 0);
- binfo->bi_dat.bi_blkoff = bp->b_lblkno;
- binfo->bi_dat.bi_ino = node->nn_ino;
- if (NANDFS_IS_INDIRECT(bp))
- binfo->bi_dat.bi_level = 1;
- else
- binfo->bi_dat.bi_level = 0;
- }
-
- return (0);
-}
-
-#define NBINFO(off) ((off) + sizeof(union nandfs_binfo))
-static int
-nandfs_segment_assign_pblk(struct nandfs_segment *nfsseg)
-{
- struct nandfs_device *fsdev;
- union nandfs_binfo *binfo;
- struct buf *bp, *seg_bp;
- uint64_t blocknr;
- uint32_t curr_off, blocksize;
- int error;
-
- fsdev = nfsseg->fsdev;
- blocksize = fsdev->nd_blocksize;
-
- blocknr = nfsseg->start_block + nfsseg->segsum_blocks;
- seg_bp = TAILQ_FIRST(&nfsseg->segsum);
- DPRINTF(SYNC, ("%s: seg:%p segsum bp:%p data:%p\n",
- __func__, nfsseg, seg_bp, seg_bp->b_data));
-
- binfo = (union nandfs_binfo *)(seg_bp->b_data +
- sizeof(struct nandfs_segment_summary));
- curr_off = sizeof(struct nandfs_segment_summary);
-
- TAILQ_FOREACH(bp, &nfsseg->data, b_cluster.cluster_entry) {
- KASSERT((bp->b_vp), ("bp %p has not vp", bp));
-
- DPRINTF(BMAP, ("\n\n%s: assign buf %p for ino %#jx next %p\n",
- __func__, bp, (uintmax_t)VTON(bp->b_vp)->nn_ino,
- TAILQ_NEXT(bp, b_cluster.cluster_entry)));
-
- if (NBINFO(curr_off) > blocksize) {
- seg_bp = TAILQ_NEXT(seg_bp, b_cluster.cluster_entry);
- binfo = (union nandfs_binfo *)seg_bp->b_data;
- curr_off = 0;
- DPRINTF(SYNC, ("%s: next segsum %p data %p\n",
- __func__, seg_bp, seg_bp->b_data));
- }
-
- error = nandfs_update_phys_block(fsdev, bp, blocknr, binfo);
- if (error) {
- nandfs_error("%s: err:%d when updatinng phys block:%jx"
- " for bp:%p and binfo:%p\n", __func__, error,
- (uintmax_t)blocknr, bp, binfo);
- return (error);
- }
- binfo++;
- curr_off = NBINFO(curr_off);
-
- blocknr++;
- }
-
- return (0);
-}
-
-static int
-nandfs_seginfo_assign_pblk(struct nandfs_seginfo *seginfo)
-{
- struct nandfs_segment *nfsseg;
- int error = 0;
-
- LIST_FOREACH(nfsseg, &seginfo->seg_list, seg_link) {
- error = nandfs_segment_assign_pblk(nfsseg);
- if (error)
- break;
- }
-
- return (error);
-}
-
-static struct nandfs_segment_summary *
-nandfs_fill_segsum(struct nandfs_segment *seg, int has_sr)
-{
- struct nandfs_segment_summary *ss;
- struct nandfs_device *fsdev;
- struct buf *bp;
- uint32_t rest, segsum_size, blocksize, crc_calc;
- uint16_t flags;
- uint8_t *crc_area, crc_skip;
-
- DPRINTF(SYNC, ("%s: seg %#jx nblocks %#x sumbytes %#x\n",
- __func__, (uintmax_t) seg->seg_num,
- seg->nblocks + seg->segsum_blocks,
- seg->segsum_bytes));
-
- fsdev = seg->fsdev;
-
- flags = NANDFS_SS_LOGBGN | NANDFS_SS_LOGEND;
- if (has_sr)
- flags |= NANDFS_SS_SR;
-
- bp = TAILQ_FIRST(&seg->segsum);
- ss = (struct nandfs_segment_summary *) bp->b_data;
- ss->ss_magic = NANDFS_SEGSUM_MAGIC;
- ss->ss_bytes = sizeof(struct nandfs_segment_summary);
- ss->ss_flags = flags;
- ss->ss_seq = ++(fsdev->nd_seg_sequence);
- ss->ss_create = fsdev->nd_ts.tv_sec;
- nandfs_get_segment_range(fsdev, seg->seg_next, &ss->ss_next, NULL);
- ss->ss_nblocks = seg->nblocks + seg->segsum_blocks;
- ss->ss_nbinfos = seg->nbinfos;
- ss->ss_sumbytes = seg->segsum_bytes;
-
- crc_skip = sizeof(ss->ss_datasum) + sizeof(ss->ss_sumsum);
- blocksize = seg->fsdev->nd_blocksize;
-
- segsum_size = seg->segsum_bytes - crc_skip;
- rest = min(seg->segsum_bytes, blocksize) - crc_skip;
- crc_area = (uint8_t *)ss + crc_skip;
- crc_calc = ~0U;
- while (segsum_size > 0) {
- crc_calc = crc32_raw(crc_area, rest, crc_calc);
- segsum_size -= rest;
- if (!segsum_size)
- break;
- bp = TAILQ_NEXT(bp, b_cluster.cluster_entry);
- crc_area = (uint8_t *)bp->b_data;
- rest = segsum_size <= blocksize ? segsum_size : blocksize;
- }
- ss->ss_sumsum = crc_calc ^ ~0U;
-
- return (ss);
-
-}
-
-static int
-nandfs_save_buf(struct buf *bp, uint64_t blocknr, struct nandfs_device *fsdev)
-{
- struct bufobj *bo;
- int error;
-
- bo = &fsdev->nd_devvp->v_bufobj;
-
- bp->b_blkno = nandfs_block_to_dblock(fsdev, blocknr);
- bp->b_iooffset = dbtob(bp->b_blkno);
-
- KASSERT(bp->b_bufobj != NULL, ("no bufobj for %p", bp));
- if (bp->b_bufobj != bo) {
- BO_LOCK(bp->b_bufobj);
- BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK,
- BO_LOCKPTR(bp->b_bufobj));
- KASSERT(BUF_ISLOCKED(bp), ("Problem with locking buffer"));
- }
-
- DPRINTF(SYNC, ("%s: buf: %p offset %#jx blk %#jx size %#x\n",
- __func__, bp, (uintmax_t)bp->b_offset, (uintmax_t)blocknr,
- fsdev->nd_blocksize));
-
- NANDFS_UNGATHER(bp);
- nandfs_buf_clear(bp, 0xffffffff);
- bp->b_flags &= ~(B_ASYNC|B_INVAL|B_MANAGED);
- error = bwrite(bp);
- if (error) {
- nandfs_error("%s: error:%d when writing buffer:%p\n",
- __func__, error, bp);
- return (error);
- }
- return (error);
-}
-
-static void
-nandfs_clean_buf(struct nandfs_device *fsdev, struct buf *bp)
-{
-
- DPRINTF(SYNC, ("%s: buf: %p\n", __func__, bp));
-
- NANDFS_UNGATHER(bp);
- nandfs_buf_clear(bp, 0xffffffff);
- bp->b_flags &= ~(B_ASYNC|B_INVAL|B_MANAGED);
- nandfs_undirty_buf_fsdev(fsdev, bp);
-}
-
-static void
-nandfs_clean_segblocks(struct nandfs_segment *seg, uint8_t unlock)
-{
- struct nandfs_device *fsdev = seg->fsdev;
- struct nandfs_segment *next_seg;
- struct buf *bp, *tbp, *next_bp;
- struct vnode *vp, *next_vp;
-
- VOP_LOCK(fsdev->nd_devvp, LK_EXCLUSIVE);
- TAILQ_FOREACH_SAFE(bp, &seg->segsum, b_cluster.cluster_entry, tbp) {
- TAILQ_REMOVE(&seg->segsum, bp, b_cluster.cluster_entry);
- nandfs_clean_buf(fsdev, bp);
- }
-
- TAILQ_FOREACH_SAFE(bp, &seg->data, b_cluster.cluster_entry, tbp) {
- TAILQ_REMOVE(&seg->data, bp, b_cluster.cluster_entry);
-
- /*
- * If bp is not super-root and vnode is not currently
- * locked lock it.
- */
- vp = bp->b_vp;
- next_vp = NULL;
- next_bp = TAILQ_NEXT(bp, b_cluster.cluster_entry);
- if (!next_bp) {
- next_seg = LIST_NEXT(seg, seg_link);
- if (next_seg)
- next_bp = TAILQ_FIRST(&next_seg->data);
- }
-
- if (next_bp)
- next_vp = next_bp->b_vp;
-
- nandfs_clean_buf(fsdev, bp);
-
- if (unlock && vp != NULL && next_vp != vp &&
- !NANDFS_SYS_NODE(VTON(vp)->nn_ino))
- vput(vp);
-
- nandfs_dirty_bufs_decrement(fsdev);
- }
-
- VOP_UNLOCK(fsdev->nd_devvp, 0);
-}
-
-static int
-nandfs_save_segblocks(struct nandfs_segment *seg, uint8_t unlock)
-{
- struct nandfs_device *fsdev = seg->fsdev;
- struct nandfs_segment *next_seg;
- struct buf *bp, *tbp, *next_bp;
- struct vnode *vp, *next_vp;
- uint64_t blocknr;
- uint32_t i = 0;
- int error = 0;
-
- VOP_LOCK(fsdev->nd_devvp, LK_EXCLUSIVE);
- TAILQ_FOREACH_SAFE(bp, &seg->segsum, b_cluster.cluster_entry, tbp) {
- TAILQ_REMOVE(&seg->segsum, bp, b_cluster.cluster_entry);
- blocknr = seg->start_block + i;
- error = nandfs_save_buf(bp, blocknr, fsdev);
- if (error) {
- nandfs_error("%s: error saving buf: %p blocknr:%jx\n",
- __func__, bp, (uintmax_t)blocknr);
- goto out;
- }
- i++;
- }
-
- i = 0;
- TAILQ_FOREACH_SAFE(bp, &seg->data, b_cluster.cluster_entry, tbp) {
- TAILQ_REMOVE(&seg->data, bp, b_cluster.cluster_entry);
-
- blocknr = seg->start_block + seg->segsum_blocks + i;
- /*
- * If bp is not super-root and vnode is not currently
- * locked lock it.
- */
- vp = bp->b_vp;
- next_vp = NULL;
- next_bp = TAILQ_NEXT(bp, b_cluster.cluster_entry);
- if (!next_bp) {
- next_seg = LIST_NEXT(seg, seg_link);
- if (next_seg)
- next_bp = TAILQ_FIRST(&next_seg->data);
- }
-
- if (next_bp)
- next_vp = next_bp->b_vp;
-
- error = nandfs_save_buf(bp, blocknr, fsdev);
- if (error) {
- nandfs_error("%s: error saving buf: %p blknr: %jx\n",
- __func__, bp, (uintmax_t)blocknr);
- if (unlock && vp != NULL && next_vp != vp &&
- !NANDFS_SYS_NODE(VTON(vp)->nn_ino))
- vput(vp);
- goto out;
- }
-
- if (unlock && vp != NULL && next_vp != vp &&
- !NANDFS_SYS_NODE(VTON(vp)->nn_ino))
- vput(vp);
-
- i++;
- nandfs_dirty_bufs_decrement(fsdev);
- }
-out:
- if (error) {
- nandfs_clean_segblocks(seg, unlock);
- VOP_UNLOCK(fsdev->nd_devvp, 0);
- return (error);
- }
-
- VOP_UNLOCK(fsdev->nd_devvp, 0);
- return (error);
-}
-
-
-static void
-clean_seginfo(struct nandfs_seginfo *seginfo, uint8_t unlock)
-{
- struct nandfs_segment *seg;
-
- DPRINTF(SYNC, ("%s: seginfo %p\n", __func__, seginfo));
-
- LIST_FOREACH(seg, &seginfo->seg_list, seg_link) {
- nandfs_clean_segblocks(seg, unlock);
- }
-}
-
-static int
-save_seginfo(struct nandfs_seginfo *seginfo, uint8_t unlock)
-{
- struct nandfs_segment *seg;
- struct nandfs_device *fsdev;
- struct nandfs_segment_summary *ss;
- int error = 0;
-
- fsdev = seginfo->fsdev;
-
- DPRINTF(SYNC, ("%s: seginfo %p\n", __func__, seginfo));
-
- LIST_FOREACH(seg, &seginfo->seg_list, seg_link) {
- if (LIST_NEXT(seg, seg_link)) {
- nandfs_fill_segsum(seg, 0);
- error = nandfs_save_segblocks(seg, unlock);
- if (error) {
- nandfs_error("%s: error:%d saving seg:%p\n",
- __func__, error, seg);
- goto out;
- }
- } else {
- ss = nandfs_fill_segsum(seg, 1);
- fsdev->nd_last_segsum = *ss;
- error = nandfs_save_segblocks(seg, unlock);
- if (error) {
- nandfs_error("%s: error:%d saving seg:%p\n",
- __func__, error, seg);
- goto out;
- }
- fsdev->nd_last_cno++;
- fsdev->nd_last_pseg = seg->start_block;
- }
- }
-out:
- if (error)
- clean_seginfo(seginfo, unlock);
- return (error);
-}
-
-static void
-nandfs_invalidate_bufs(struct nandfs_device *fsdev, uint64_t segno)
-{
- uint64_t start, end;
- struct buf *bp, *tbd;
- struct bufobj *bo;
-
- nandfs_get_segment_range(fsdev, segno, &start, &end);
-
- bo = &NTOV(fsdev->nd_gc_node)->v_bufobj;
-
- BO_LOCK(bo);
-restart_locked_gc:
- TAILQ_FOREACH_SAFE(bp, &bo->bo_clean.bv_hd, b_bobufs, tbd) {
- if (!(bp->b_lblkno >= start && bp->b_lblkno <= end))
- continue;
-
- if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT, NULL))
- goto restart_locked_gc;
-
- bremfree(bp);
- bp->b_flags |= (B_INVAL | B_RELBUF);
- bp->b_flags &= ~(B_ASYNC | B_MANAGED);
- BO_UNLOCK(bo);
- brelse(bp);
- BO_LOCK(bo);
- }
- BO_UNLOCK(bo);
-}
-
-/* Process segments marks to free by cleaner */
-static void
-nandfs_process_segments(struct nandfs_device *fsdev)
-{
- uint64_t saved_segment;
- int i;
-
- if (fsdev->nd_free_base) {
- saved_segment = nandfs_get_segnum_of_block(fsdev,
- fsdev->nd_super.s_last_pseg);
- for (i = 0; i < fsdev->nd_free_count; i++) {
- if (fsdev->nd_free_base[i] == NANDFS_NOSEGMENT)
- continue;
- /* Update superblock if clearing segment point by it */
- if (fsdev->nd_free_base[i] == saved_segment) {
- nandfs_write_superblock(fsdev);
- saved_segment = nandfs_get_segnum_of_block(
- fsdev, fsdev->nd_super.s_last_pseg);
- }
- nandfs_invalidate_bufs(fsdev, fsdev->nd_free_base[i]);
- nandfs_clear_segment(fsdev, fsdev->nd_free_base[i]);
- }
-
- free(fsdev->nd_free_base, M_NANDFSTEMP);
- fsdev->nd_free_base = NULL;
- fsdev->nd_free_count = 0;
- }
-}
-
-/* Collect and write dirty buffers */
-int
-nandfs_sync_file(struct vnode *vp)
-{
- struct nandfs_device *fsdev;
- struct nandfs_node *nandfs_node;
- struct nandfsmount *nmp;
- struct nandfs_node *dat, *su, *ifile, *cp;
- struct nandfs_seginfo *seginfo = NULL;
- struct nandfs_segment *seg;
- int update, error;
- int cno_changed;
-
- ASSERT_VOP_LOCKED(vp, __func__);
- DPRINTF(SYNC, ("%s: START\n", __func__));
-
- error = 0;
- nmp = VFSTONANDFS(vp->v_mount);
- fsdev = nmp->nm_nandfsdev;
-
- dat = fsdev->nd_dat_node;
- su = fsdev->nd_su_node;
- cp = fsdev->nd_cp_node;
- ifile = nmp->nm_ifile_node;
-
- NANDFS_WRITEASSERT(fsdev);
- if (lockmgr(&fsdev->nd_seg_const, LK_UPGRADE, NULL) != 0) {
- DPRINTF(SYNC, ("%s: lost shared lock\n", __func__));
- if (lockmgr(&fsdev->nd_seg_const, LK_EXCLUSIVE, NULL) != 0)
- panic("couldn't lock exclusive");
- }
- DPRINTF(SYNC, ("%s: got lock\n", __func__));
-
- VOP_LOCK(NTOV(su), LK_EXCLUSIVE);
- create_seginfo(fsdev, &seginfo);
-
- update = 0;
-
- nandfs_node = VTON(vp);
- if (nandfs_node->nn_flags & IN_MODIFIED) {
- nandfs_node->nn_flags &= ~(IN_MODIFIED);
- update = 1;
- }
-
- if (vp->v_bufobj.bo_dirty.bv_cnt) {
- error = nandfs_iterate_dirty_buf(vp, seginfo, 0);
- if (error) {
- clean_seginfo(seginfo, 0);
- delete_seginfo(seginfo);
- VOP_UNLOCK(NTOV(su), 0);
- lockmgr(&fsdev->nd_seg_const, LK_DOWNGRADE, NULL);
- nandfs_error("%s: err:%d iterating dirty bufs vp:%p",
- __func__, error, vp);
- return (error);
- }
- update = 1;
- }
-
- if (update) {
- VOP_LOCK(NTOV(ifile), LK_EXCLUSIVE);
- error = nandfs_node_update(nandfs_node);
- if (error) {
- clean_seginfo(seginfo, 0);
- delete_seginfo(seginfo);
- VOP_UNLOCK(NTOV(ifile), 0);
- VOP_UNLOCK(NTOV(su), 0);
- lockmgr(&fsdev->nd_seg_const, LK_DOWNGRADE, NULL);
- nandfs_error("%s: err:%d updating vp:%p",
- __func__, error, vp);
- return (error);
- }
- VOP_UNLOCK(NTOV(ifile), 0);
- }
-
- cno_changed = 0;
- if (seginfo->blocks) {
- VOP_LOCK(NTOV(cp), LK_EXCLUSIVE);
- cno_changed = 1;
- /* Create new checkpoint */
- error = nandfs_get_checkpoint(fsdev, cp, fsdev->nd_last_cno + 1);
- if (error) {
- clean_seginfo(seginfo, 0);
- delete_seginfo(seginfo);
- VOP_UNLOCK(NTOV(cp), 0);
- VOP_UNLOCK(NTOV(su), 0);
- lockmgr(&fsdev->nd_seg_const, LK_DOWNGRADE, NULL);
- nandfs_error("%s: err:%d getting cp:%jx",
- __func__, error, fsdev->nd_last_cno + 1);
- return (error);
- }
-
- /* Reiterate all blocks and assign physical block number */
- nandfs_seginfo_assign_pblk(seginfo);
-
- /* Fill checkpoint data */
- error = nandfs_set_checkpoint(fsdev, cp, fsdev->nd_last_cno + 1,
- &ifile->nn_inode, seginfo->blocks);
- if (error) {
- clean_seginfo(seginfo, 0);
- delete_seginfo(seginfo);
- VOP_UNLOCK(NTOV(cp), 0);
- VOP_UNLOCK(NTOV(su), 0);
- lockmgr(&fsdev->nd_seg_const, LK_DOWNGRADE, NULL);
- nandfs_error("%s: err:%d setting cp:%jx",
- __func__, error, fsdev->nd_last_cno + 1);
- return (error);
- }
-
- VOP_UNLOCK(NTOV(cp), 0);
- LIST_FOREACH(seg, &seginfo->seg_list, seg_link)
- nandfs_update_segment(fsdev, seg->seg_num,
- seg->nblocks + seg->segsum_blocks);
-
- VOP_LOCK(NTOV(dat), LK_EXCLUSIVE);
- error = save_seginfo(seginfo, 0);
- if (error) {
- clean_seginfo(seginfo, 0);
- delete_seginfo(seginfo);
- VOP_UNLOCK(NTOV(dat), 0);
- VOP_UNLOCK(NTOV(su), 0);
- lockmgr(&fsdev->nd_seg_const, LK_DOWNGRADE, NULL);
- nandfs_error("%s: err:%d updating seg",
- __func__, error);
- return (error);
- }
- VOP_UNLOCK(NTOV(dat), 0);
- }
-
- VOP_UNLOCK(NTOV(su), 0);
-
- delete_seginfo(seginfo);
- lockmgr(&fsdev->nd_seg_const, LK_DOWNGRADE, NULL);
-
- if (cno_changed && !error) {
- if (nandfs_cps_between_sblocks != 0 &&
- fsdev->nd_last_cno % nandfs_cps_between_sblocks == 0)
- nandfs_write_superblock(fsdev);
- }
-
- ASSERT_VOP_LOCKED(vp, __func__);
- DPRINTF(SYNC, ("%s: END error %d\n", __func__, error));
- return (error);
-}
-
-int
-nandfs_segment_constructor(struct nandfsmount *nmp, int flags)
-{
- struct nandfs_device *fsdev;
- struct nandfs_seginfo *seginfo = NULL;
- struct nandfs_segment *seg;
- struct nandfs_node *dat, *su, *ifile, *cp, *gc;
- int cno_changed, error;
-
- DPRINTF(SYNC, ("%s: START\n", __func__));
- fsdev = nmp->nm_nandfsdev;
-
- lockmgr(&fsdev->nd_seg_const, LK_EXCLUSIVE, NULL);
- DPRINTF(SYNC, ("%s: git lock\n", __func__));
-again:
- create_seginfo(fsdev, &seginfo);
-
- dat = fsdev->nd_dat_node;
- su = fsdev->nd_su_node;
- cp = fsdev->nd_cp_node;
- gc = fsdev->nd_gc_node;
- ifile = nmp->nm_ifile_node;
-
- VOP_LOCK(NTOV(su), LK_EXCLUSIVE);
- VOP_LOCK(NTOV(ifile), LK_EXCLUSIVE);
- VOP_LOCK(NTOV(gc), LK_EXCLUSIVE);
- VOP_LOCK(NTOV(cp), LK_EXCLUSIVE);
-
- nandfs_iterate_system_vnode(gc, seginfo);
- nandfs_iterate_dirty_vnodes(nmp->nm_vfs_mountp, seginfo);
- nandfs_iterate_system_vnode(ifile, seginfo);
- nandfs_iterate_system_vnode(su, seginfo);
-
- cno_changed = 0;
- if (seginfo->blocks || flags) {
- cno_changed = 1;
- /* Create new checkpoint */
- error = nandfs_get_checkpoint(fsdev, cp, fsdev->nd_last_cno + 1);
- if (error) {
- clean_seginfo(seginfo, 0);
- delete_seginfo(seginfo);
- goto error_locks;
- }
-
- /* Collect blocks from system files */
- nandfs_iterate_system_vnode(cp, seginfo);
- nandfs_iterate_system_vnode(su, seginfo);
- VOP_LOCK(NTOV(dat), LK_EXCLUSIVE);
- nandfs_iterate_system_vnode(dat, seginfo);
- VOP_UNLOCK(NTOV(dat), 0);
-reiterate:
- seginfo->reiterate = 0;
- nandfs_iterate_system_vnode(su, seginfo);
- VOP_LOCK(NTOV(dat), LK_EXCLUSIVE);
- nandfs_iterate_system_vnode(dat, seginfo);
- VOP_UNLOCK(NTOV(dat), 0);
- if (seginfo->reiterate)
- goto reiterate;
- if (!(seginfo->curseg) || !seginfo->curseg->num_blocks) {
- error = create_segment(seginfo);
- if (error) {
- clean_seginfo(seginfo, 0);
- delete_seginfo(seginfo);
- goto error_locks;
- }
- goto reiterate;
- }
-
- /* Reiterate all blocks and assign physical block number */
- nandfs_seginfo_assign_pblk(seginfo);
-
- /* Fill superroot */
- error = nandfs_add_superroot(seginfo);
- if (error) {
- clean_seginfo(seginfo, 0);
- delete_seginfo(seginfo);
- goto error_locks;
- }
- KASSERT(!(seginfo->reiterate), ("reiteration after superroot"));
-
- /* Fill checkpoint data */
- nandfs_set_checkpoint(fsdev, cp, fsdev->nd_last_cno + 1,
- &ifile->nn_inode, seginfo->blocks);
-
- LIST_FOREACH(seg, &seginfo->seg_list, seg_link)
- nandfs_update_segment(fsdev, seg->seg_num,
- seg->nblocks + seg->segsum_blocks);
-
- VOP_LOCK(NTOV(dat), LK_EXCLUSIVE);
- error = save_seginfo(seginfo, 1);
- if (error) {
- clean_seginfo(seginfo, 1);
- delete_seginfo(seginfo);
- goto error_dat;
- }
- VOP_UNLOCK(NTOV(dat), 0);
- }
-
- VOP_UNLOCK(NTOV(cp), 0);
- VOP_UNLOCK(NTOV(gc), 0);
- VOP_UNLOCK(NTOV(ifile), 0);
-
- nandfs_process_segments(fsdev);
-
- VOP_UNLOCK(NTOV(su), 0);
-
- delete_seginfo(seginfo);
-
- /*
- * XXX: a hack, will go away soon
- */
- if ((NTOV(dat)->v_bufobj.bo_dirty.bv_cnt != 0 ||
- NTOV(cp)->v_bufobj.bo_dirty.bv_cnt != 0 ||
- NTOV(gc)->v_bufobj.bo_dirty.bv_cnt != 0 ||
- NTOV(ifile)->v_bufobj.bo_dirty.bv_cnt != 0 ||
- NTOV(su)->v_bufobj.bo_dirty.bv_cnt != 0) &&
- (flags & NANDFS_UMOUNT)) {
- DPRINTF(SYNC, ("%s: RERUN\n", __func__));
- goto again;
- }
-
- MPASS(fsdev->nd_free_base == NULL);
-
- lockmgr(&fsdev->nd_seg_const, LK_RELEASE, NULL);
-
- if (cno_changed) {
- if ((nandfs_cps_between_sblocks != 0 &&
- fsdev->nd_last_cno % nandfs_cps_between_sblocks == 0) ||
- flags & NANDFS_UMOUNT)
- nandfs_write_superblock(fsdev);
- }
-
- DPRINTF(SYNC, ("%s: END\n", __func__));
- return (0);
-error_dat:
- VOP_UNLOCK(NTOV(dat), 0);
-error_locks:
- VOP_UNLOCK(NTOV(cp), 0);
- VOP_UNLOCK(NTOV(gc), 0);
- VOP_UNLOCK(NTOV(ifile), 0);
- VOP_UNLOCK(NTOV(su), 0);
- lockmgr(&fsdev->nd_seg_const, LK_RELEASE, NULL);
-
- return (error);
-}
-
-#ifdef DDB
-/*
- * Show details about the given NANDFS mount point.
- */
-DB_SHOW_COMMAND(nandfs, db_show_nandfs)
-{
- struct mount *mp;
- struct nandfs_device *nffsdev;
- struct nandfs_segment *seg;
- struct nandfsmount *nmp;
- struct buf *bp;
- struct vnode *vp;
-
- if (!have_addr) {
- db_printf("\nUsage: show nandfs <mount_addr>\n");
- return;
- }
-
- mp = (struct mount *)addr;
- db_printf("%p %s on %s (%s)\n", mp, mp->mnt_stat.f_mntfromname,
- mp->mnt_stat.f_mntonname, mp->mnt_stat.f_fstypename);
-
-
- nmp = (struct nandfsmount *)(mp->mnt_data);
- nffsdev = nmp->nm_nandfsdev;
- db_printf("dev vnode:%p\n", nffsdev->nd_devvp);
- db_printf("blocksize:%jx last cno:%jx last pseg:%jx seg num:%jx\n",
- (uintmax_t)nffsdev->nd_blocksize, (uintmax_t)nffsdev->nd_last_cno,
- (uintmax_t)nffsdev->nd_last_pseg, (uintmax_t)nffsdev->nd_seg_num);
- db_printf("system nodes: dat:%p cp:%p su:%p ifile:%p gc:%p\n",
- nffsdev->nd_dat_node, nffsdev->nd_cp_node, nffsdev->nd_su_node,
- nmp->nm_ifile_node, nffsdev->nd_gc_node);
-
- if (nffsdev->nd_seginfo != NULL) {
- LIST_FOREACH(seg, &nffsdev->nd_seginfo->seg_list, seg_link) {
- db_printf("seg: %p\n", seg);
- TAILQ_FOREACH(bp, &seg->segsum,
- b_cluster.cluster_entry)
- db_printf("segbp %p\n", bp);
- TAILQ_FOREACH(bp, &seg->data,
- b_cluster.cluster_entry) {
- vp = bp->b_vp;
- db_printf("bp:%p bp->b_vp:%p ino:%jx\n", bp, vp,
- (uintmax_t)(vp ? VTON(vp)->nn_ino : 0));
- }
- }
- }
-}
-#endif
diff --git a/sys/fs/nandfs/nandfs_subr.c b/sys/fs/nandfs/nandfs_subr.c
deleted file mode 100644
index 0a3f65a505438..0000000000000
--- a/sys/fs/nandfs/nandfs_subr.c
+++ /dev/null
@@ -1,1091 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2010-2012 Semihalf
- * Copyright (c) 2008, 2009 Reinoud Zandijk
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * From: NetBSD: nilfs_subr.c,v 1.4 2009/07/29 17:06:57 reinoud
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/gsb_crc32.h>
-#include <sys/namei.h>
-#include <sys/resourcevar.h>
-#include <sys/kernel.h>
-#include <sys/file.h>
-#include <sys/stat.h>
-#include <sys/buf.h>
-#include <sys/bio.h>
-#include <sys/proc.h>
-#include <sys/mount.h>
-#include <sys/vnode.h>
-#include <sys/signalvar.h>
-#include <sys/malloc.h>
-#include <sys/dirent.h>
-#include <sys/lockf.h>
-#include <sys/libkern.h>
-
-#include <geom/geom.h>
-#include <geom/geom_vfs.h>
-
-#include <vm/vm.h>
-#include <vm/vm_extern.h>
-
-#include <machine/_inttypes.h>
-#include "nandfs_mount.h"
-#include "nandfs.h"
-#include "nandfs_subr.h"
-
-MALLOC_DEFINE(M_NANDFSMNT, "nandfs_mount", "NANDFS mount");
-MALLOC_DEFINE(M_NANDFSTEMP, "nandfs_tmt", "NANDFS tmp");
-
-uma_zone_t nandfs_node_zone;
-
-void nandfs_bdflush(struct bufobj *bo, struct buf *bp);
-int nandfs_bufsync(struct bufobj *bo, int waitfor);
-
-struct buf_ops buf_ops_nandfs = {
- .bop_name = "buf_ops_nandfs",
- .bop_write = bufwrite,
- .bop_strategy = bufstrategy,
- .bop_sync = nandfs_bufsync,
- .bop_bdflush = nandfs_bdflush,
-};
-
-int
-nandfs_bufsync(struct bufobj *bo, int waitfor)
-{
- struct vnode *vp;
- int error = 0;
-
- vp = bo2vnode(bo);
-
- ASSERT_VOP_LOCKED(vp, __func__);
- error = nandfs_sync_file(vp);
- if (error)
- nandfs_warning("%s: cannot flush buffers err:%d\n",
- __func__, error);
-
- return (error);
-}
-
-void
-nandfs_bdflush(bo, bp)
- struct bufobj *bo;
- struct buf *bp;
-{
- struct vnode *vp;
- int error;
-
- if (bo->bo_dirty.bv_cnt <= ((dirtybufthresh * 8) / 10))
- return;
-
- vp = bp->b_vp;
- if (NANDFS_SYS_NODE(VTON(vp)->nn_ino))
- return;
-
- if (NANDFS_IS_INDIRECT(bp))
- return;
-
- error = nandfs_sync_file(vp);
- if (error)
- nandfs_warning("%s: cannot flush buffers err:%d\n",
- __func__, error);
-}
-
-int
-nandfs_init(struct vfsconf *vfsp)
-{
-
- nandfs_node_zone = uma_zcreate("nandfs node zone",
- sizeof(struct nandfs_node), NULL, NULL, NULL, NULL, 0, 0);
-
- return (0);
-}
-
-int
-nandfs_uninit(struct vfsconf *vfsp)
-{
-
- uma_zdestroy(nandfs_node_zone);
- return (0);
-}
-
-/* Basic calculators */
-uint64_t
-nandfs_get_segnum_of_block(struct nandfs_device *nandfsdev,
- nandfs_daddr_t blocknr)
-{
- uint64_t segnum, blks_per_seg;
-
- MPASS(blocknr >= nandfsdev->nd_fsdata.f_first_data_block);
-
- blks_per_seg = nandfsdev->nd_fsdata.f_blocks_per_segment;
-
- segnum = blocknr / blks_per_seg;
- segnum -= nandfsdev->nd_fsdata.f_first_data_block / blks_per_seg;
-
- DPRINTF(SYNC, ("%s: returning blocknr %jx -> segnum %jx\n", __func__,
- blocknr, segnum));
-
- return (segnum);
-}
-
-void
-nandfs_get_segment_range(struct nandfs_device *nandfsdev, uint64_t segnum,
- uint64_t *seg_start, uint64_t *seg_end)
-{
- uint64_t blks_per_seg;
-
- blks_per_seg = nandfsdev->nd_fsdata.f_blocks_per_segment;
- *seg_start = nandfsdev->nd_fsdata.f_first_data_block +
- blks_per_seg * segnum;
- if (seg_end != NULL)
- *seg_end = *seg_start + blks_per_seg -1;
-}
-
-void nandfs_calc_mdt_consts(struct nandfs_device *nandfsdev,
- struct nandfs_mdt *mdt, int entry_size)
-{
- uint32_t blocksize = nandfsdev->nd_blocksize;
-
- mdt->entries_per_group = blocksize * 8;
- mdt->entries_per_block = blocksize / entry_size;
-
- mdt->blocks_per_group =
- (mdt->entries_per_group -1) / mdt->entries_per_block + 1 + 1;
- mdt->groups_per_desc_block =
- blocksize / sizeof(struct nandfs_block_group_desc);
- mdt->blocks_per_desc_block =
- mdt->groups_per_desc_block * mdt->blocks_per_group + 1;
-}
-
-int
-nandfs_dev_bread(struct nandfs_device *nandfsdev, nandfs_lbn_t blocknr,
- struct ucred *cred, int flags, struct buf **bpp)
-{
- int blk2dev = nandfsdev->nd_blocksize / DEV_BSIZE;
- int error;
-
- DPRINTF(BLOCK, ("%s: read from block %jx vp %p\n", __func__,
- blocknr * blk2dev, nandfsdev->nd_devvp));
- error = bread(nandfsdev->nd_devvp, blocknr * blk2dev,
- nandfsdev->nd_blocksize, NOCRED, bpp);
- if (error)
- nandfs_error("%s: cannot read from device - blk:%jx\n",
- __func__, blocknr);
- return (error);
-}
-
-/* Read on a node */
-int
-nandfs_bread(struct nandfs_node *node, nandfs_lbn_t blocknr,
- struct ucred *cred, int flags, struct buf **bpp)
-{
- nandfs_daddr_t vblk;
- int error;
-
- DPRINTF(BLOCK, ("%s: vp:%p lbn:%#jx\n", __func__, NTOV(node),
- blocknr));
-
- error = bread(NTOV(node), blocknr, node->nn_nandfsdev->nd_blocksize,
- cred, bpp);
-
- KASSERT(error == 0, ("%s: vp:%p lbn:%#jx err:%d\n", __func__,
- NTOV(node), blocknr, error));
-
- if (!nandfs_vblk_get(*bpp) &&
- ((*bpp)->b_flags & B_CACHE) && node->nn_ino != NANDFS_DAT_INO) {
- nandfs_bmap_lookup(node, blocknr, &vblk);
- nandfs_vblk_set(*bpp, vblk);
- }
- return (error);
-}
-
-int
-nandfs_bread_meta(struct nandfs_node *node, nandfs_lbn_t blocknr,
- struct ucred *cred, int flags, struct buf **bpp)
-{
- nandfs_daddr_t vblk;
- int error;
-
- DPRINTF(BLOCK, ("%s: vp:%p lbn:%#jx\n", __func__, NTOV(node),
- blocknr));
-
- error = bread(NTOV(node), blocknr, node->nn_nandfsdev->nd_blocksize,
- cred, bpp);
-
- KASSERT(error == 0, ("%s: vp:%p lbn:%#jx err:%d\n", __func__,
- NTOV(node), blocknr, error));
-
- if (!nandfs_vblk_get(*bpp) &&
- ((*bpp)->b_flags & B_CACHE) && node->nn_ino != NANDFS_DAT_INO) {
- nandfs_bmap_lookup(node, blocknr, &vblk);
- nandfs_vblk_set(*bpp, vblk);
- }
-
- return (error);
-}
-
-int
-nandfs_bdestroy(struct nandfs_node *node, nandfs_daddr_t vblk)
-{
- int error;
-
- if (!NANDFS_SYS_NODE(node->nn_ino))
- NANDFS_WRITEASSERT(node->nn_nandfsdev);
-
- error = nandfs_vblock_end(node->nn_nandfsdev, vblk);
- if (error) {
- nandfs_error("%s: ending vblk: %jx failed\n",
- __func__, (uintmax_t)vblk);
- return (error);
- }
- node->nn_inode.i_blocks--;
-
- return (0);
-}
-
-int
-nandfs_bcreate(struct nandfs_node *node, nandfs_lbn_t blocknr,
- struct ucred *cred, int flags, struct buf **bpp)
-{
- int error;
-
- ASSERT_VOP_LOCKED(NTOV(node), __func__);
- if (!NANDFS_SYS_NODE(node->nn_ino))
- NANDFS_WRITEASSERT(node->nn_nandfsdev);
-
- DPRINTF(BLOCK, ("%s: vp:%p lbn:%#jx\n", __func__, NTOV(node),
- blocknr));
-
- *bpp = getblk(NTOV(node), blocknr, node->nn_nandfsdev->nd_blocksize,
- 0, 0, 0);
-
- KASSERT((*bpp), ("%s: vp:%p lbn:%#jx\n", __func__,
- NTOV(node), blocknr));
-
- if (*bpp) {
- vfs_bio_clrbuf(*bpp);
- (*bpp)->b_blkno = ~(0); /* To avoid VOP_BMAP in bdwrite */
- error = nandfs_bmap_insert_block(node, blocknr, *bpp);
- if (error) {
- nandfs_warning("%s: failed bmap insert node:%p"
- " blk:%jx\n", __func__, node, blocknr);
- brelse(*bpp);
- return (error);
- }
- node->nn_inode.i_blocks++;
-
- return (0);
- }
-
- return (-1);
-}
-
-int
-nandfs_bcreate_meta(struct nandfs_node *node, nandfs_lbn_t blocknr,
- struct ucred *cred, int flags, struct buf **bpp)
-{
- struct nandfs_device *fsdev;
- nandfs_daddr_t vblk;
- int error;
-
- ASSERT_VOP_LOCKED(NTOV(node), __func__);
- NANDFS_WRITEASSERT(node->nn_nandfsdev);
-
- DPRINTF(BLOCK, ("%s: vp:%p lbn:%#jx\n", __func__, NTOV(node),
- blocknr));
-
- fsdev = node->nn_nandfsdev;
-
- *bpp = getblk(NTOV(node), blocknr, node->nn_nandfsdev->nd_blocksize,
- 0, 0, 0);
-
- KASSERT((*bpp), ("%s: vp:%p lbn:%#jx\n", __func__,
- NTOV(node), blocknr));
-
- memset((*bpp)->b_data, 0, fsdev->nd_blocksize);
-
- vfs_bio_clrbuf(*bpp);
- (*bpp)->b_blkno = ~(0); /* To avoid VOP_BMAP in bdwrite */
-
- nandfs_buf_set(*bpp, NANDFS_VBLK_ASSIGNED);
-
- if (node->nn_ino != NANDFS_DAT_INO) {
- error = nandfs_vblock_alloc(fsdev, &vblk);
- if (error) {
- nandfs_buf_clear(*bpp, NANDFS_VBLK_ASSIGNED);
- brelse(*bpp);
- return (error);
- }
- } else
- vblk = fsdev->nd_fakevblk++;
-
- nandfs_vblk_set(*bpp, vblk);
-
- nandfs_bmap_insert_block(node, blocknr, *bpp);
- return (0);
-}
-
-/* Translate index to a file block number and an entry */
-void
-nandfs_mdt_trans(struct nandfs_mdt *mdt, uint64_t index,
- nandfs_lbn_t *blocknr, uint32_t *entry_in_block)
-{
- uint64_t blknr;
- uint64_t group, group_offset, blocknr_in_group;
- uint64_t desc_block, desc_offset;
-
- /* Calculate our offset in the file */
- group = index / mdt->entries_per_group;
- group_offset = index % mdt->entries_per_group;
- desc_block = group / mdt->groups_per_desc_block;
- desc_offset = group % mdt->groups_per_desc_block;
- blocknr_in_group = group_offset / mdt->entries_per_block;
-
- /* To descgroup offset */
- blknr = 1 + desc_block * mdt->blocks_per_desc_block;
-
- /* To group offset */
- blknr += desc_offset * mdt->blocks_per_group;
-
- /* To actual file block */
- blknr += 1 + blocknr_in_group;
-
- *blocknr = blknr;
- *entry_in_block = group_offset % mdt->entries_per_block;
-}
-
-void
-nandfs_mdt_trans_blk(struct nandfs_mdt *mdt, uint64_t index,
- uint64_t *desc, uint64_t *bitmap, nandfs_lbn_t *blocknr,
- uint32_t *entry_in_block)
-{
- uint64_t blknr;
- uint64_t group, group_offset, blocknr_in_group;
- uint64_t desc_block, desc_offset;
-
- /* Calculate our offset in the file */
- group = index / mdt->entries_per_group;
- group_offset = index % mdt->entries_per_group;
- desc_block = group / mdt->groups_per_desc_block;
- desc_offset = group % mdt->groups_per_desc_block;
- blocknr_in_group = group_offset / mdt->entries_per_block;
-
- /* To descgroup offset */
- *desc = desc_block * mdt->blocks_per_desc_block;
- blknr = 1 + desc_block * mdt->blocks_per_desc_block;
-
- /* To group offset */
- blknr += desc_offset * mdt->blocks_per_group;
- *bitmap = blknr;
-
- /* To actual file block */
- blknr += 1 + blocknr_in_group;
-
- *blocknr = blknr;
- *entry_in_block = group_offset % mdt->entries_per_block;
-
- DPRINTF(ALLOC,
- ("%s: desc_buf: %jx bitmap_buf: %jx entry_buf: %jx entry: %x\n",
- __func__, (uintmax_t)*desc, (uintmax_t)*bitmap,
- (uintmax_t)*blocknr, *entry_in_block));
-}
-
-int
-nandfs_vtop(struct nandfs_node *node, nandfs_daddr_t vblocknr,
- nandfs_daddr_t *pblocknr)
-{
- struct nandfs_node *dat_node;
- struct nandfs_dat_entry *entry;
- struct buf *bp;
- nandfs_lbn_t ldatblknr;
- uint32_t entry_in_block;
- int locked, error;
-
- if (node->nn_ino == NANDFS_DAT_INO || node->nn_ino == NANDFS_GC_INO) {
- *pblocknr = vblocknr;
- return (0);
- }
-
- /* only translate valid vblocknrs */
- if (vblocknr == 0)
- return (0);
-
- dat_node = node->nn_nandfsdev->nd_dat_node;
- nandfs_mdt_trans(&node->nn_nandfsdev->nd_dat_mdt, vblocknr, &ldatblknr,
- &entry_in_block);
-
- locked = NANDFS_VOP_ISLOCKED(NTOV(dat_node));
- if (!locked)
- VOP_LOCK(NTOV(dat_node), LK_SHARED);
- error = nandfs_bread(dat_node, ldatblknr, NOCRED, 0, &bp);
- if (error) {
- DPRINTF(TRANSLATE, ("vtop: can't read in DAT block %#jx!\n",
- (uintmax_t)ldatblknr));
- brelse(bp);
- VOP_UNLOCK(NTOV(dat_node), 0);
- return (error);
- }
-
- /* Get our translation */
- entry = ((struct nandfs_dat_entry *) bp->b_data) + entry_in_block;
- DPRINTF(TRANSLATE, ("\tentry %p data %p entry_in_block %x\n",
- entry, bp->b_data, entry_in_block))
- DPRINTF(TRANSLATE, ("\tvblk %#jx -> %#jx for cp [%#jx-%#jx]\n",
- (uintmax_t)vblocknr, (uintmax_t)entry->de_blocknr,
- (uintmax_t)entry->de_start, (uintmax_t)entry->de_end));
-
- *pblocknr = entry->de_blocknr;
- brelse(bp);
- if (!locked)
- VOP_UNLOCK(NTOV(dat_node), 0);
-
- MPASS(*pblocknr >= node->nn_nandfsdev->nd_fsdata.f_first_data_block ||
- *pblocknr == 0);
-
- return (0);
-}
-
-int
-nandfs_segsum_valid(struct nandfs_segment_summary *segsum)
-{
-
- return (segsum->ss_magic == NANDFS_SEGSUM_MAGIC);
-}
-
-int
-nandfs_load_segsum(struct nandfs_device *fsdev, nandfs_daddr_t blocknr,
- struct nandfs_segment_summary *segsum)
-{
- struct buf *bp;
- int error;
-
- DPRINTF(VOLUMES, ("nandfs: try segsum at block %jx\n",
- (uintmax_t)blocknr));
-
- error = nandfs_dev_bread(fsdev, blocknr, NOCRED, 0, &bp);
- if (error)
- return (error);
-
- memcpy(segsum, bp->b_data, sizeof(struct nandfs_segment_summary));
- brelse(bp);
-
- if (!nandfs_segsum_valid(segsum)) {
- DPRINTF(VOLUMES, ("%s: bad magic pseg:%jx\n", __func__,
- blocknr));
- return (EINVAL);
- }
-
- return (error);
-}
-
-static int
-nandfs_load_super_root(struct nandfs_device *nandfsdev,
- struct nandfs_segment_summary *segsum, uint64_t pseg)
-{
- struct nandfs_super_root super_root;
- struct buf *bp;
- uint64_t blocknr;
- uint32_t super_root_crc, comp_crc;
- int off, error;
-
- /* Check if there is a superroot */
- if ((segsum->ss_flags & NANDFS_SS_SR) == 0) {
- DPRINTF(VOLUMES, ("%s: no super root in pseg:%jx\n", __func__,
- pseg));
- return (ENOENT);
- }
-
- /* Get our super root, located at the end of the pseg */
- blocknr = pseg + segsum->ss_nblocks - 1;
- DPRINTF(VOLUMES, ("%s: try at %#jx\n", __func__, (uintmax_t)blocknr));
-
- error = nandfs_dev_bread(nandfsdev, blocknr, NOCRED, 0, &bp);
- if (error)
- return (error);
-
- memcpy(&super_root, bp->b_data, sizeof(struct nandfs_super_root));
- brelse(bp);
-
- /* Check super root CRC */
- super_root_crc = super_root.sr_sum;
- off = sizeof(super_root.sr_sum);
- comp_crc = crc32((uint8_t *)&super_root + off,
- NANDFS_SR_BYTES - off);
-
- if (super_root_crc != comp_crc) {
- DPRINTF(VOLUMES, ("%s: invalid crc:%#x [expect:%#x]\n",
- __func__, super_root_crc, comp_crc));
- return (EINVAL);
- }
-
- nandfsdev->nd_super_root = super_root;
- DPRINTF(VOLUMES, ("%s: got valid superroot\n", __func__));
-
- return (0);
-}
-
-/*
- * Search for the last super root recorded.
- */
-int
-nandfs_search_super_root(struct nandfs_device *nandfsdev)
-{
- struct nandfs_super_block *super;
- struct nandfs_segment_summary segsum;
- uint64_t seg_start, seg_end, cno, seq, create, pseg;
- uint64_t segnum;
- int error, found;
-
- error = found = 0;
-
- /* Search for last super root */
- pseg = nandfsdev->nd_super.s_last_pseg;
- segnum = nandfs_get_segnum_of_block(nandfsdev, pseg);
-
- cno = nandfsdev->nd_super.s_last_cno;
- create = seq = 0;
- DPRINTF(VOLUMES, ("%s: start in pseg %#jx\n", __func__,
- (uintmax_t)pseg));
-
- for (;;) {
- error = nandfs_load_segsum(nandfsdev, pseg, &segsum);
- if (error)
- break;
-
- if (segsum.ss_seq < seq || segsum.ss_create < create)
- break;
-
- /* Try to load super root */
- if (segsum.ss_flags & NANDFS_SS_SR) {
- error = nandfs_load_super_root(nandfsdev, &segsum, pseg);
- if (error)
- break; /* confused */
- found = 1;
-
- super = &nandfsdev->nd_super;
- nandfsdev->nd_last_segsum = segsum;
- super->s_last_pseg = pseg;
- super->s_last_cno = cno++;
- super->s_last_seq = segsum.ss_seq;
- super->s_state = NANDFS_VALID_FS;
- seq = segsum.ss_seq;
- create = segsum.ss_create;
- } else {
- seq = segsum.ss_seq;
- create = segsum.ss_create;
- }
-
- /* Calculate next partial segment location */
- pseg += segsum.ss_nblocks;
- DPRINTF(VOLUMES, ("%s: next partial seg is %jx\n", __func__,
- (uintmax_t)pseg));
-
- /* Did we reach the end of the segment? if so, go to the next */
- nandfs_get_segment_range(nandfsdev, segnum, &seg_start,
- &seg_end);
- if (pseg >= seg_end) {
- pseg = segsum.ss_next;
- DPRINTF(VOLUMES,
- (" partial seg oor next is %jx[%jx - %jx]\n",
- (uintmax_t)pseg, (uintmax_t)seg_start,
- (uintmax_t)seg_end));
- }
- segnum = nandfs_get_segnum_of_block(nandfsdev, pseg);
- }
-
- if (error && !found)
- return (error);
-
- return (0);
-}
-
-int
-nandfs_get_node_raw(struct nandfs_device *nandfsdev, struct nandfsmount *nmp,
- uint64_t ino, struct nandfs_inode *inode, struct nandfs_node **nodep)
-{
- struct nandfs_node *node;
- struct vnode *nvp;
- struct mount *mp;
- int error;
-
- *nodep = NULL;
-
- /* Associate with mountpoint if present */
- if (nmp) {
- mp = nmp->nm_vfs_mountp;
- error = getnewvnode("nandfs", mp, &nandfs_vnodeops, &nvp);
- if (error)
- return (error);
- } else {
- mp = NULL;
- error = getnewvnode("snandfs", mp, &nandfs_system_vnodeops,
- &nvp);
- if (error)
- return (error);
- }
-
- if (mp)
- NANDFS_WRITELOCK(nandfsdev);
-
- DPRINTF(IFILE, ("%s: ino: %#jx -> vp: %p\n",
- __func__, (uintmax_t)ino, nvp));
- /* Lock node */
- lockmgr(nvp->v_vnlock, LK_EXCLUSIVE, NULL);
-
- if (mp) {
- error = insmntque(nvp, mp);
- if (error != 0) {
- *nodep = NULL;
- return (error);
- }
- }
-
- node = uma_zalloc(nandfs_node_zone, M_WAITOK | M_ZERO);
-
- /* Crosslink */
- node->nn_vnode = nvp;
- nvp->v_bufobj.bo_ops = &buf_ops_nandfs;
- node->nn_nmp = nmp;
- node->nn_nandfsdev = nandfsdev;
- nvp->v_data = node;
-
- /* Initiase NANDFS node */
- node->nn_ino = ino;
- if (inode != NULL)
- node->nn_inode = *inode;
-
- nandfs_vinit(nvp, ino);
-
- /* Return node */
- *nodep = node;
- DPRINTF(IFILE, ("%s: ino:%#jx vp:%p node:%p\n",
- __func__, (uintmax_t)ino, nvp, *nodep));
-
- return (0);
-}
-
-int
-nandfs_get_node(struct nandfsmount *nmp, uint64_t ino,
- struct nandfs_node **nodep)
-{
- struct nandfs_device *nandfsdev;
- struct nandfs_inode inode, *entry;
- struct vnode *nvp, *vpp;
- struct thread *td;
- struct buf *bp;
- uint64_t ivblocknr;
- uint32_t entry_in_block;
- int error;
-
- /* Look up node in hash table */
- td = curthread;
- *nodep = NULL;
-
- if ((ino < NANDFS_ATIME_INO) && (ino != NANDFS_ROOT_INO)) {
- printf("nandfs_get_node: system ino %"PRIu64" not in mount "
- "point!\n", ino);
- return (ENOENT);
- }
-
- error = vfs_hash_get(nmp->nm_vfs_mountp, ino, LK_EXCLUSIVE, td, &nvp,
- NULL, NULL);
- if (error)
- return (error);
-
- if (nvp != NULL) {
- *nodep = (struct nandfs_node *)nvp->v_data;
- return (0);
- }
-
- /* Look up inode structure in mountpoints ifile */
- nandfsdev = nmp->nm_nandfsdev;
- nandfs_mdt_trans(&nandfsdev->nd_ifile_mdt, ino, &ivblocknr,
- &entry_in_block);
-
- VOP_LOCK(NTOV(nmp->nm_ifile_node), LK_SHARED);
- error = nandfs_bread(nmp->nm_ifile_node, ivblocknr, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- VOP_UNLOCK(NTOV(nmp->nm_ifile_node), 0);
- return (ENOENT);
- }
-
- /* Get inode entry */
- entry = (struct nandfs_inode *) bp->b_data + entry_in_block;
- memcpy(&inode, entry, sizeof(struct nandfs_inode));
- brelse(bp);
- VOP_UNLOCK(NTOV(nmp->nm_ifile_node), 0);
-
- /* Get node */
- error = nandfs_get_node_raw(nmp->nm_nandfsdev, nmp, ino, &inode, nodep);
- if (error) {
- *nodep = NULL;
- return (error);
- }
-
- nvp = (*nodep)->nn_vnode;
- error = vfs_hash_insert(nvp, ino, 0, td, &vpp, NULL, NULL);
- if (error) {
- *nodep = NULL;
- return (error);
- }
-
- return (error);
-}
-
-void
-nandfs_dispose_node(struct nandfs_node **nodep)
-{
- struct nandfs_node *node;
- struct vnode *vp;
-
- /* Protect against rogue values */
- node = *nodep;
- if (!node) {
- return;
- }
- DPRINTF(NODE, ("nandfs_dispose_node: %p\n", *nodep));
-
- vp = NTOV(node);
- vp->v_data = NULL;
-
- /* Free our associated memory */
- uma_zfree(nandfs_node_zone, node);
-
- *nodep = NULL;
-}
-
-int
-nandfs_lookup_name_in_dir(struct vnode *dvp, const char *name, int namelen,
- uint64_t *ino, int *found, uint64_t *off)
-{
- struct nandfs_node *dir_node = VTON(dvp);
- struct nandfs_dir_entry *ndirent;
- struct buf *bp;
- uint64_t file_size, diroffset, blkoff;
- uint64_t blocknr;
- uint32_t blocksize = dir_node->nn_nandfsdev->nd_blocksize;
- uint8_t *pos, name_len;
- int error;
-
- *found = 0;
-
- DPRINTF(VNCALL, ("%s: %s file\n", __func__, name));
- if (dvp->v_type != VDIR) {
- return (ENOTDIR);
- }
-
- /* Get directory filesize */
- file_size = dir_node->nn_inode.i_size;
-
- /* Walk the directory */
- diroffset = 0;
- blocknr = 0;
- blkoff = 0;
- error = nandfs_bread(dir_node, blocknr, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (EIO);
- }
-
- while (diroffset < file_size) {
- if (blkoff >= blocksize) {
- blkoff = 0; blocknr++;
- brelse(bp);
- error = nandfs_bread(dir_node, blocknr, NOCRED, 0,
- &bp);
- if (error) {
- brelse(bp);
- return (EIO);
- }
- }
-
- /* Read in one dirent */
- pos = (uint8_t *) bp->b_data + blkoff;
- ndirent = (struct nandfs_dir_entry *) pos;
- name_len = ndirent->name_len;
-
- if ((name_len == namelen) &&
- (strncmp(name, ndirent->name, name_len) == 0) &&
- (ndirent->inode != 0)) {
- *ino = ndirent->inode;
- *off = diroffset;
- DPRINTF(LOOKUP, ("found `%.*s` with ino %"PRIx64"\n",
- name_len, ndirent->name, *ino));
- *found = 1;
- break;
- }
-
- /* Advance */
- diroffset += ndirent->rec_len;
- blkoff += ndirent->rec_len;
- }
- brelse(bp);
-
- return (error);
-}
-
-int
-nandfs_get_fsinfo(struct nandfsmount *nmp, struct nandfs_fsinfo *fsinfo)
-{
- struct nandfs_device *fsdev;
-
- fsdev = nmp->nm_nandfsdev;
-
- memcpy(&fsinfo->fs_fsdata, &fsdev->nd_fsdata, sizeof(fsdev->nd_fsdata));
- memcpy(&fsinfo->fs_super, &fsdev->nd_super, sizeof(fsdev->nd_super));
- snprintf(fsinfo->fs_dev, sizeof(fsinfo->fs_dev),
- "%s", nmp->nm_vfs_mountp->mnt_stat.f_mntfromname);
-
- return (0);
-}
-
-void
-nandfs_inode_init(struct nandfs_inode *inode, uint16_t mode)
-{
- struct timespec ts;
-
- vfs_timestamp(&ts);
-
- inode->i_blocks = 0;
- inode->i_size = 0;
- inode->i_ctime = ts.tv_sec;
- inode->i_ctime_nsec = ts.tv_nsec;
- inode->i_mtime = ts.tv_sec;
- inode->i_mtime_nsec = ts.tv_nsec;
- inode->i_mode = mode;
- inode->i_links_count = 1;
- if (S_ISDIR(mode))
- inode->i_links_count = 2;
- inode->i_flags = 0;
-
- inode->i_special = 0;
- memset(inode->i_db, 0, sizeof(inode->i_db));
- memset(inode->i_ib, 0, sizeof(inode->i_ib));
-}
-
-void
-nandfs_inode_destroy(struct nandfs_inode *inode)
-{
-
- MPASS(inode->i_blocks == 0);
- bzero(inode, sizeof(*inode));
-}
-
-int
-nandfs_fs_full(struct nandfs_device *nffsdev)
-{
- uint64_t space, bps;
-
- bps = nffsdev->nd_fsdata.f_blocks_per_segment;
- space = (nffsdev->nd_clean_segs - 1) * bps;
-
- DPRINTF(BUF, ("%s: bufs:%jx space:%jx\n", __func__,
- (uintmax_t)nffsdev->nd_dirty_bufs, (uintmax_t)space));
-
- if (nffsdev->nd_dirty_bufs + (nffsdev->nd_segs_reserved * bps) >= space)
- return (1);
-
- return (0);
-}
-
-static int
-_nandfs_dirty_buf(struct buf *bp, int dirty_meta, int force)
-{
- struct nandfs_device *nffsdev;
- struct nandfs_node *node;
- uint64_t ino, bps;
-
- if (NANDFS_ISGATHERED(bp)) {
- bqrelse(bp);
- return (0);
- }
- if ((bp->b_flags & (B_MANAGED | B_DELWRI)) == (B_MANAGED | B_DELWRI)) {
- bqrelse(bp);
- return (0);
- }
-
- node = VTON(bp->b_vp);
- nffsdev = node->nn_nandfsdev;
- DPRINTF(BUF, ("%s: buf:%p\n", __func__, bp));
- ino = node->nn_ino;
-
- if (nandfs_fs_full(nffsdev) && !NANDFS_SYS_NODE(ino) && !force) {
- brelse(bp);
- return (ENOSPC);
- }
-
- bp->b_flags |= B_MANAGED;
- bdwrite(bp);
-
- nandfs_dirty_bufs_increment(nffsdev);
-
- KASSERT((bp->b_vp), ("vp missing for bp"));
- KASSERT((nandfs_vblk_get(bp) || ino == NANDFS_DAT_INO),
- ("bp vblk is 0"));
-
- /*
- * To maintain consistency of FS we need to force making
- * meta buffers dirty, even if free space is low.
- */
- if (dirty_meta && ino != NANDFS_GC_INO)
- nandfs_bmap_dirty_blocks(VTON(bp->b_vp), bp, 1);
-
- bps = nffsdev->nd_fsdata.f_blocks_per_segment;
-
- if (nffsdev->nd_dirty_bufs >= (bps * nandfs_max_dirty_segs)) {
- mtx_lock(&nffsdev->nd_sync_mtx);
- if (nffsdev->nd_syncing == 0) {
- DPRINTF(SYNC, ("%s: wakeup gc\n", __func__));
- nffsdev->nd_syncing = 1;
- wakeup(&nffsdev->nd_syncing);
- }
- mtx_unlock(&nffsdev->nd_sync_mtx);
- }
-
- return (0);
-}
-
-int
-nandfs_dirty_buf(struct buf *bp, int force)
-{
-
- return (_nandfs_dirty_buf(bp, 1, force));
-}
-
-int
-nandfs_dirty_buf_meta(struct buf *bp, int force)
-{
-
- return (_nandfs_dirty_buf(bp, 0, force));
-}
-
-void
-nandfs_undirty_buf_fsdev(struct nandfs_device *nffsdev, struct buf *bp)
-{
-
- BUF_ASSERT_HELD(bp);
-
- if (bp->b_flags & B_DELWRI) {
- bp->b_flags &= ~(B_DELWRI|B_MANAGED);
- nandfs_dirty_bufs_decrement(nffsdev);
- }
- /*
- * Since it is now being written, we can clear its deferred write flag.
- */
- bp->b_flags &= ~B_DEFERRED;
-
- brelse(bp);
-}
-
-void
-nandfs_undirty_buf(struct buf *bp)
-{
- struct nandfs_node *node;
-
- node = VTON(bp->b_vp);
-
- nandfs_undirty_buf_fsdev(node->nn_nandfsdev, bp);
-}
-
-void
-nandfs_vblk_set(struct buf *bp, nandfs_daddr_t blocknr)
-{
-
- nandfs_daddr_t *vblk = (nandfs_daddr_t *)(&bp->b_fsprivate1);
- *vblk = blocknr;
-}
-
-nandfs_daddr_t
-nandfs_vblk_get(struct buf *bp)
-{
-
- nandfs_daddr_t *vblk = (nandfs_daddr_t *)(&bp->b_fsprivate1);
- return (*vblk);
-}
-
-void
-nandfs_buf_set(struct buf *bp, uint32_t bits)
-{
- uintptr_t flags;
-
- flags = (uintptr_t)bp->b_fsprivate3;
- flags |= (uintptr_t)bits;
- bp->b_fsprivate3 = (void *)flags;
-}
-
-void
-nandfs_buf_clear(struct buf *bp, uint32_t bits)
-{
- uintptr_t flags;
-
- flags = (uintptr_t)bp->b_fsprivate3;
- flags &= ~(uintptr_t)bits;
- bp->b_fsprivate3 = (void *)flags;
-}
-
-int
-nandfs_buf_check(struct buf *bp, uint32_t bits)
-{
- uintptr_t flags;
-
- flags = (uintptr_t)bp->b_fsprivate3;
- if (flags & bits)
- return (1);
- return (0);
-}
-
-int
-nandfs_erase(struct nandfs_device *fsdev, off_t offset, size_t size)
-{
- DPRINTF(BLOCK, ("%s: performing erase at offset %jx size %zx\n",
- __func__, offset, size));
-
- MPASS(size % fsdev->nd_erasesize == 0);
-
- return (g_delete_data(fsdev->nd_gconsumer, offset, size));
-}
-
-int
-nandfs_vop_islocked(struct vnode *vp)
-{
- int islocked;
-
- islocked = VOP_ISLOCKED(vp);
- return (islocked == LK_EXCLUSIVE || islocked == LK_SHARED);
-}
-
-nandfs_daddr_t
-nandfs_block_to_dblock(struct nandfs_device *fsdev, nandfs_lbn_t block)
-{
-
- return (btodb(block * fsdev->nd_blocksize));
-}
diff --git a/sys/fs/nandfs/nandfs_subr.h b/sys/fs/nandfs/nandfs_subr.h
deleted file mode 100644
index 36c2c9dc2ff2d..0000000000000
--- a/sys/fs/nandfs/nandfs_subr.h
+++ /dev/null
@@ -1,240 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2010-2012 Semihalf
- * Copyright (c) 2008, 2009 Reinoud Zandijk
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * From: NetBSD: nilfs_subr.h,v 1.1 2009/07/18 16:31:42 reinoud
- *
- * $FreeBSD$
- */
-
-#ifndef _FS_NANDFS_NANDFS_SUBR_H_
-#define _FS_NANDFS_NANDFS_SUBR_H_
-
-struct nandfs_mdt;
-
-struct nandfs_alloc_request
-{
- uint64_t entrynum;
- struct buf *bp_desc;
- struct buf *bp_bitmap;
- struct buf *bp_entry;
-};
-
-/* Segment creation */
-void nandfs_wakeup_wait_sync(struct nandfs_device *, int);
-int nandfs_segment_constructor(struct nandfsmount *, int);
-int nandfs_sync_file(struct vnode *);
-
-/* Basic calculators */
-uint64_t nandfs_get_segnum_of_block(struct nandfs_device *, nandfs_daddr_t);
-void nandfs_get_segment_range(struct nandfs_device *, uint64_t, uint64_t *,
- uint64_t *);
-void nandfs_calc_mdt_consts(struct nandfs_device *, struct nandfs_mdt *, int);
-
-/* Log reading / volume helpers */
-int nandfs_search_super_root(struct nandfs_device *);
-
-/* Reading */
-int nandfs_dev_bread(struct nandfs_device *, nandfs_daddr_t, struct ucred *,
- int, struct buf **);
-int nandfs_bread(struct nandfs_node *, nandfs_lbn_t, struct ucred *, int,
- struct buf **);
-int nandfs_bread_meta(struct nandfs_node *, nandfs_lbn_t, struct ucred *, int,
- struct buf **);
-int nandfs_bdestroy(struct nandfs_node *, nandfs_daddr_t);
-int nandfs_bcreate(struct nandfs_node *, nandfs_lbn_t, struct ucred *, int,
- struct buf **);
-int nandfs_bcreate_meta(struct nandfs_node *, nandfs_lbn_t, struct ucred *,
- int, struct buf **);
-int nandfs_bread_create(struct nandfs_node *, nandfs_lbn_t, struct ucred *,
- int, struct buf **);
-
-/* vtop operations */
-int nandfs_vtop(struct nandfs_node *, nandfs_daddr_t, nandfs_daddr_t *);
-
-/* Node action implementators */
-int nandfs_vinit(struct vnode *, uint64_t);
-int nandfs_get_node(struct nandfsmount *, uint64_t, struct nandfs_node **);
-int nandfs_get_node_raw(struct nandfs_device *, struct nandfsmount *, uint64_t,
- struct nandfs_inode *, struct nandfs_node **);
-void nandfs_dispose_node(struct nandfs_node **);
-
-void nandfs_itimes(struct vnode *);
-int nandfs_lookup_name_in_dir(struct vnode *, const char *, int, uint64_t *,
- int *, uint64_t *);
-int nandfs_create_node(struct vnode *, struct vnode **, struct vattr *,
- struct componentname *);
-void nandfs_delete_node(struct nandfs_node *);
-
-int nandfs_chsize(struct vnode *, u_quad_t, struct ucred *);
-int nandfs_dir_detach(struct nandfsmount *, struct nandfs_node *,
- struct nandfs_node *, struct componentname *);
-int nandfs_dir_attach(struct nandfsmount *, struct nandfs_node *,
- struct nandfs_node *, struct vattr *, struct componentname *);
-
-int nandfs_dirty_buf(struct buf *, int);
-int nandfs_dirty_buf_meta(struct buf *, int);
-int nandfs_fs_full(struct nandfs_device *);
-void nandfs_undirty_buf_fsdev(struct nandfs_device *, struct buf *);
-void nandfs_undirty_buf(struct buf *);
-
-void nandfs_clear_buf(struct buf *);
-void nandfs_buf_set(struct buf *, uint32_t);
-void nandfs_buf_clear(struct buf *, uint32_t);
-int nandfs_buf_check(struct buf *, uint32_t);
-
-int nandfs_find_free_entry(struct nandfs_mdt *, struct nandfs_node *,
- struct nandfs_alloc_request *);
-int nandfs_find_entry(struct nandfs_mdt *, struct nandfs_node *,
- struct nandfs_alloc_request *);
-int nandfs_alloc_entry(struct nandfs_mdt *, struct nandfs_alloc_request *);
-void nandfs_abort_entry(struct nandfs_alloc_request *);
-int nandfs_free_entry(struct nandfs_mdt *, struct nandfs_alloc_request *);
-int nandfs_get_entry_block(struct nandfs_mdt *, struct nandfs_node *,
- struct nandfs_alloc_request *, uint32_t *, int);
-
-/* Inode management. */
-int nandfs_node_create(struct nandfsmount *, struct nandfs_node **, uint16_t);
-int nandfs_node_destroy(struct nandfs_node *);
-int nandfs_node_update(struct nandfs_node *);
-int nandfs_get_node_entry(struct nandfsmount *, struct nandfs_inode **,
- uint64_t, struct buf **);
-void nandfs_mdt_trans_blk(struct nandfs_mdt *, uint64_t, uint64_t *,
- uint64_t *, nandfs_lbn_t *, uint32_t *);
-
-/* vblock management */
-void nandfs_mdt_trans(struct nandfs_mdt *, uint64_t, nandfs_lbn_t *, uint32_t *);
-int nandfs_vblock_alloc(struct nandfs_device *, nandfs_daddr_t *);
-int nandfs_vblock_end(struct nandfs_device *, nandfs_daddr_t);
-int nandfs_vblock_assign(struct nandfs_device *, nandfs_daddr_t,
- nandfs_lbn_t);
-int nandfs_vblock_free(struct nandfs_device *, nandfs_daddr_t);
-
-/* Checkpoint management */
-int nandfs_get_checkpoint(struct nandfs_device *, struct nandfs_node *,
- uint64_t);
-int nandfs_set_checkpoint(struct nandfs_device *, struct nandfs_node *,
- uint64_t, struct nandfs_inode *, uint64_t);
-
-/* Segment management */
-int nandfs_alloc_segment(struct nandfs_device *, uint64_t *);
-int nandfs_update_segment(struct nandfs_device *, uint64_t, uint32_t);
-int nandfs_free_segment(struct nandfs_device *, uint64_t);
-int nandfs_clear_segment(struct nandfs_device *, uint64_t);
-int nandfs_touch_segment(struct nandfs_device *, uint64_t);
-int nandfs_markgc_segment(struct nandfs_device *, uint64_t);
-
-int nandfs_bmap_insert_block(struct nandfs_node *, nandfs_lbn_t, struct buf *);
-int nandfs_bmap_update_block(struct nandfs_node *, struct buf *, nandfs_lbn_t);
-int nandfs_bmap_update_dat(struct nandfs_node *, nandfs_daddr_t, struct buf *);
-int nandfs_bmap_dirty_blocks(struct nandfs_node *, struct buf *, int);
-int nandfs_bmap_truncate_mapping(struct nandfs_node *, nandfs_lbn_t,
- nandfs_lbn_t);
-int nandfs_bmap_lookup(struct nandfs_node *, nandfs_lbn_t, nandfs_daddr_t *);
-
-/* dirent */
-int nandfs_add_dirent(struct vnode *, uint64_t, char *, long, uint8_t);
-int nandfs_remove_dirent(struct vnode *, struct nandfs_node *,
- struct componentname *);
-int nandfs_update_dirent(struct vnode *, struct nandfs_node *,
- struct nandfs_node *);
-int nandfs_init_dir(struct vnode *, uint64_t, uint64_t);
-int nandfs_update_parent_dir(struct vnode *, uint64_t);
-
-void nandfs_vblk_set(struct buf *, nandfs_daddr_t);
-nandfs_daddr_t nandfs_vblk_get(struct buf *);
-
-void nandfs_inode_init(struct nandfs_inode *, uint16_t);
-void nandfs_inode_destroy(struct nandfs_inode *);
-
-/* ioctl */
-int nandfs_get_seg_stat(struct nandfs_device *, struct nandfs_seg_stat *);
-int nandfs_chng_cpmode(struct nandfs_node *, struct nandfs_cpmode *);
-int nandfs_get_cpinfo_ioctl(struct nandfs_node *, struct nandfs_argv *);
-int nandfs_delete_cp(struct nandfs_node *, uint64_t start, uint64_t);
-int nandfs_make_snap(struct nandfs_device *, uint64_t *);
-int nandfs_delete_snap(struct nandfs_device *, uint64_t);
-int nandfs_get_cpstat(struct nandfs_node *, struct nandfs_cpstat *);
-int nandfs_get_segment_info_ioctl(struct nandfs_device *, struct nandfs_argv *);
-int nandfs_get_dat_vinfo_ioctl(struct nandfs_device *, struct nandfs_argv *);
-int nandfs_get_dat_bdescs_ioctl(struct nandfs_device *, struct nandfs_argv *);
-int nandfs_get_fsinfo(struct nandfsmount *, struct nandfs_fsinfo *);
-
-int nandfs_get_cpinfo(struct nandfs_node *, uint64_t, uint16_t,
- struct nandfs_cpinfo *, uint32_t, uint32_t *);
-
-nandfs_lbn_t nandfs_get_maxfilesize(struct nandfs_device *);
-
-int nandfs_write_superblock(struct nandfs_device *);
-
-extern int nandfs_sync_interval;
-extern int nandfs_max_dirty_segs;
-extern int nandfs_cps_between_sblocks;
-
-struct buf *nandfs_geteblk(int, int);
-
-void nandfs_dirty_bufs_increment(struct nandfs_device *);
-void nandfs_dirty_bufs_decrement(struct nandfs_device *);
-
-int nandfs_start_cleaner(struct nandfs_device *);
-int nandfs_stop_cleaner(struct nandfs_device *);
-
-int nandfs_segsum_valid(struct nandfs_segment_summary *);
-int nandfs_load_segsum(struct nandfs_device *, nandfs_daddr_t,
- struct nandfs_segment_summary *);
-int nandfs_get_segment_info(struct nandfs_device *, struct nandfs_suinfo *,
- uint32_t, uint64_t);
-int nandfs_get_segment_info_filter(struct nandfs_device *,
- struct nandfs_suinfo *, uint32_t, uint64_t, uint64_t *, uint32_t, uint32_t);
-int nandfs_get_dat_vinfo(struct nandfs_device *, struct nandfs_vinfo *,
- uint32_t);
-int nandfs_get_dat_bdescs(struct nandfs_device *, struct nandfs_bdesc *,
- uint32_t);
-
-#define NANDFS_VBLK_ASSIGNED 1
-
-#define NANDFS_IS_INDIRECT(bp) ((bp)->b_lblkno < 0)
-
-int nandfs_erase(struct nandfs_device *, off_t, size_t);
-
-#define NANDFS_VOP_ISLOCKED(vp) nandfs_vop_islocked((vp))
-int nandfs_vop_islocked(struct vnode *vp);
-
-nandfs_daddr_t nandfs_block_to_dblock(struct nandfs_device *, nandfs_lbn_t);
-
-#define DEBUG_MODE
-#if defined(DEBUG_MODE)
-#define nandfs_error panic
-#define nandfs_warning printf
-#elif defined(TEST_MODE)
-#define nandfs_error printf
-#define nandfs_warning printf
-#else
-#define nandfs_error(...)
-#define nandfs_warning(...)
-#endif
-
-#endif /* !_FS_NANDFS_NANDFS_SUBR_H_ */
diff --git a/sys/fs/nandfs/nandfs_sufile.c b/sys/fs/nandfs/nandfs_sufile.c
deleted file mode 100644
index 5276008de096c..0000000000000
--- a/sys/fs/nandfs/nandfs_sufile.c
+++ /dev/null
@@ -1,571 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2010-2012 Semihalf.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/mount.h>
-#include <sys/mutex.h>
-#include <sys/namei.h>
-#include <sys/sysctl.h>
-#include <sys/vnode.h>
-#include <sys/buf.h>
-#include <sys/bio.h>
-
-#include <vm/vm.h>
-#include <vm/vm_param.h>
-#include <vm/vm_kern.h>
-#include <vm/vm_page.h>
-
-#include <geom/geom.h>
-#include <geom/geom_vfs.h>
-
-#include <fs/nandfs/nandfs_mount.h>
-#include <fs/nandfs/nandfs.h>
-#include <fs/nandfs/nandfs_subr.h>
-
-#define SU_USAGE_OFF(bp, offset) \
- ((struct nandfs_segment_usage *)((bp)->b_data + offset))
-
-static int
-nandfs_seg_usage_blk_offset(struct nandfs_device *fsdev, uint64_t seg,
- uint64_t *blk, uint64_t *offset)
-{
- uint64_t off;
- uint16_t seg_size;
-
- seg_size = fsdev->nd_fsdata.f_segment_usage_size;
-
- off = roundup(sizeof(struct nandfs_sufile_header), seg_size);
- off += (seg * seg_size);
-
- *blk = off / fsdev->nd_blocksize;
- *offset = off % fsdev->nd_blocksize;
- return (0);
-}
-
-/* Alloc new segment */
-int
-nandfs_alloc_segment(struct nandfs_device *fsdev, uint64_t *seg)
-{
- struct nandfs_node *su_node;
- struct nandfs_sufile_header *su_header;
- struct nandfs_segment_usage *su_usage;
- struct buf *bp_header, *bp;
- uint64_t blk, vblk, offset, i, rest, nsegments;
- uint16_t seg_size;
- int error, found;
-
- seg_size = fsdev->nd_fsdata.f_segment_usage_size;
- nsegments = fsdev->nd_fsdata.f_nsegments;
-
- su_node = fsdev->nd_su_node;
- ASSERT_VOP_LOCKED(NTOV(su_node), __func__);
-
- /* Read header buffer */
- error = nandfs_bread(su_node, 0, NOCRED, 0, &bp_header);
- if (error) {
- brelse(bp_header);
- return (error);
- }
-
- su_header = (struct nandfs_sufile_header *)bp_header->b_data;
-
- /* Get last allocated segment */
- i = su_header->sh_last_alloc + 1;
-
- found = 0;
- bp = NULL;
- while (!found) {
- nandfs_seg_usage_blk_offset(fsdev, i, &blk, &offset);
- if(blk != 0) {
- error = nandfs_bmap_lookup(su_node, blk, &vblk);
- if (error) {
- nandfs_error("%s: cannot find vblk for blk "
- "blk:%jx\n", __func__, blk);
- return (error);
- }
- if (vblk)
- error = nandfs_bread(su_node, blk, NOCRED, 0,
- &bp);
- else
- error = nandfs_bcreate(su_node, blk, NOCRED, 0,
- &bp);
- if (error) {
- nandfs_error("%s: cannot create/read "
- "vblk:%jx\n", __func__, vblk);
- if (bp)
- brelse(bp);
- return (error);
- }
-
- su_usage = SU_USAGE_OFF(bp, offset);
- } else {
- su_usage = SU_USAGE_OFF(bp_header, offset);
- bp = bp_header;
- }
-
- rest = (fsdev->nd_blocksize - offset) / seg_size;
- /* Go through all su usage in block */
- while (rest) {
- /* When last check start from beginning */
- if (i == nsegments)
- break;
-
- if (!su_usage->su_flags) {
- su_usage->su_flags = 1;
- found = 1;
- break;
- }
- su_usage++;
- i++;
-
- /* If all checked return error */
- if (i == su_header->sh_last_alloc) {
- DPRINTF(SEG, ("%s: cannot allocate segment \n",
- __func__));
- brelse(bp_header);
- if (blk != 0)
- brelse(bp);
- return (1);
- }
- rest--;
- }
- if (!found) {
- /* Otherwise read another block */
- if (blk != 0)
- brelse(bp);
- if (i == nsegments) {
- blk = 0;
- i = 0;
- } else
- blk++;
- offset = 0;
- }
- }
-
- if (found) {
- *seg = i;
- su_header->sh_last_alloc = i;
- su_header->sh_ncleansegs--;
- su_header->sh_ndirtysegs++;
-
- fsdev->nd_super.s_free_blocks_count = su_header->sh_ncleansegs *
- fsdev->nd_fsdata.f_blocks_per_segment;
- fsdev->nd_clean_segs--;
-
- /*
- * It is mostly called from syncer() so we want to force
- * making buf dirty.
- */
- error = nandfs_dirty_buf(bp_header, 1);
- if (error) {
- if (bp && bp != bp_header)
- brelse(bp);
- return (error);
- }
- if (bp && bp != bp_header)
- nandfs_dirty_buf(bp, 1);
-
- DPRINTF(SEG, ("%s: seg:%#jx\n", __func__, (uintmax_t)i));
-
- return (0);
- }
-
- DPRINTF(SEG, ("%s: failed\n", __func__));
-
- return (1);
-}
-
-/*
- * Make buffer dirty, it will be updated soon but first it need to be
- * gathered by syncer.
- */
-int
-nandfs_touch_segment(struct nandfs_device *fsdev, uint64_t seg)
-{
- struct nandfs_node *su_node;
- struct buf *bp;
- uint64_t blk, offset;
- int error;
-
- su_node = fsdev->nd_su_node;
- ASSERT_VOP_LOCKED(NTOV(su_node), __func__);
-
- nandfs_seg_usage_blk_offset(fsdev, seg, &blk, &offset);
-
- error = nandfs_bread(su_node, blk, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- nandfs_error("%s: cannot preallocate new segment\n", __func__);
- return (error);
- } else
- nandfs_dirty_buf(bp, 1);
-
- DPRINTF(SEG, ("%s: seg:%#jx\n", __func__, (uintmax_t)seg));
- return (error);
-}
-
-/* Update block count of segment */
-int
-nandfs_update_segment(struct nandfs_device *fsdev, uint64_t seg, uint32_t nblks)
-{
- struct nandfs_node *su_node;
- struct nandfs_segment_usage *su_usage;
- struct buf *bp;
- uint64_t blk, offset;
- int error;
-
- su_node = fsdev->nd_su_node;
- ASSERT_VOP_LOCKED(NTOV(su_node), __func__);
-
- nandfs_seg_usage_blk_offset(fsdev, seg, &blk, &offset);
-
- error = nandfs_bread(su_node, blk, NOCRED, 0, &bp);
- if (error) {
- nandfs_error("%s: read block:%jx to update\n",
- __func__, blk);
- brelse(bp);
- return (error);
- }
-
- su_usage = SU_USAGE_OFF(bp, offset);
- su_usage->su_lastmod = fsdev->nd_ts.tv_sec;
- su_usage->su_flags = NANDFS_SEGMENT_USAGE_DIRTY;
- su_usage->su_nblocks += nblks;
-
- DPRINTF(SEG, ("%s: seg:%#jx inc:%#x cur:%#x\n", __func__,
- (uintmax_t)seg, nblks, su_usage->su_nblocks));
-
- nandfs_dirty_buf(bp, 1);
-
- return (0);
-}
-
-/* Make segment free */
-int
-nandfs_free_segment(struct nandfs_device *fsdev, uint64_t seg)
-{
- struct nandfs_node *su_node;
- struct nandfs_sufile_header *su_header;
- struct nandfs_segment_usage *su_usage;
- struct buf *bp_header, *bp;
- uint64_t blk, offset;
- int error;
-
- su_node = fsdev->nd_su_node;
- ASSERT_VOP_LOCKED(NTOV(su_node), __func__);
-
- /* Read su header */
- error = nandfs_bread(su_node, 0, NOCRED, 0, &bp_header);
- if (error) {
- brelse(bp_header);
- return (error);
- }
-
- su_header = (struct nandfs_sufile_header *)bp_header->b_data;
- nandfs_seg_usage_blk_offset(fsdev, seg, &blk, &offset);
-
- /* Read su usage block if other than su header block */
- if (blk != 0) {
- error = nandfs_bread(su_node, blk, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- brelse(bp_header);
- return (error);
- }
- } else
- bp = bp_header;
-
- /* Reset su usage data */
- su_usage = SU_USAGE_OFF(bp, offset);
- su_usage->su_lastmod = fsdev->nd_ts.tv_sec;
- su_usage->su_nblocks = 0;
- su_usage->su_flags = 0;
-
- /* Update clean/dirty counter in header */
- su_header->sh_ncleansegs++;
- su_header->sh_ndirtysegs--;
-
- /*
- * Make buffers dirty, called by cleaner
- * so force dirty even if no much space left
- * on device
- */
- nandfs_dirty_buf(bp_header, 1);
- if (bp != bp_header)
- nandfs_dirty_buf(bp, 1);
-
- /* Update free block count */
- fsdev->nd_super.s_free_blocks_count = su_header->sh_ncleansegs *
- fsdev->nd_fsdata.f_blocks_per_segment;
- fsdev->nd_clean_segs++;
-
- DPRINTF(SEG, ("%s: seg:%#jx\n", __func__, (uintmax_t)seg));
-
- return (0);
-}
-
-static int
-nandfs_bad_segment(struct nandfs_device *fsdev, uint64_t seg)
-{
- struct nandfs_node *su_node;
- struct nandfs_segment_usage *su_usage;
- struct buf *bp;
- uint64_t blk, offset;
- int error;
-
- su_node = fsdev->nd_su_node;
- ASSERT_VOP_LOCKED(NTOV(su_node), __func__);
-
- nandfs_seg_usage_blk_offset(fsdev, seg, &blk, &offset);
-
- error = nandfs_bread(su_node, blk, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
-
- su_usage = SU_USAGE_OFF(bp, offset);
- su_usage->su_lastmod = fsdev->nd_ts.tv_sec;
- su_usage->su_flags = NANDFS_SEGMENT_USAGE_ERROR;
-
- DPRINTF(SEG, ("%s: seg:%#jx\n", __func__, (uintmax_t)seg));
-
- nandfs_dirty_buf(bp, 1);
-
- return (0);
-}
-
-int
-nandfs_markgc_segment(struct nandfs_device *fsdev, uint64_t seg)
-{
- struct nandfs_node *su_node;
- struct nandfs_segment_usage *su_usage;
- struct buf *bp;
- uint64_t blk, offset;
- int error;
-
- su_node = fsdev->nd_su_node;
-
- VOP_LOCK(NTOV(su_node), LK_EXCLUSIVE);
-
- nandfs_seg_usage_blk_offset(fsdev, seg, &blk, &offset);
-
- error = nandfs_bread(su_node, blk, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- VOP_UNLOCK(NTOV(su_node), 0);
- return (error);
- }
-
- su_usage = SU_USAGE_OFF(bp, offset);
- MPASS((su_usage->su_flags & NANDFS_SEGMENT_USAGE_GC) == 0);
- su_usage->su_flags |= NANDFS_SEGMENT_USAGE_GC;
-
- brelse(bp);
- VOP_UNLOCK(NTOV(su_node), 0);
-
- DPRINTF(SEG, ("%s: seg:%#jx\n", __func__, (uintmax_t)seg));
-
- return (0);
-}
-
-int
-nandfs_clear_segment(struct nandfs_device *fsdev, uint64_t seg)
-{
- uint64_t offset, segsize;
- uint32_t bps, bsize;
- int error = 0;
-
- bps = fsdev->nd_fsdata.f_blocks_per_segment;
- bsize = fsdev->nd_blocksize;
- segsize = bsize * bps;
- nandfs_get_segment_range(fsdev, seg, &offset, NULL);
- offset *= bsize;
-
- DPRINTF(SEG, ("%s: seg:%#jx\n", __func__, (uintmax_t)seg));
-
- /* Erase it and mark it bad when fail */
- if (nandfs_erase(fsdev, offset, segsize))
- error = nandfs_bad_segment(fsdev, seg);
-
- if (error)
- return (error);
-
- /* Mark it free */
- error = nandfs_free_segment(fsdev, seg);
-
- return (error);
-}
-
-int
-nandfs_get_seg_stat(struct nandfs_device *nandfsdev,
- struct nandfs_seg_stat *nss)
-{
- struct nandfs_sufile_header *suhdr;
- struct nandfs_node *su_node;
- struct buf *bp;
- int err;
-
- su_node = nandfsdev->nd_su_node;
-
- NANDFS_WRITELOCK(nandfsdev);
- VOP_LOCK(NTOV(su_node), LK_SHARED);
- err = nandfs_bread(nandfsdev->nd_su_node, 0, NOCRED, 0, &bp);
- if (err) {
- brelse(bp);
- VOP_UNLOCK(NTOV(su_node), 0);
- NANDFS_WRITEUNLOCK(nandfsdev);
- return (-1);
- }
-
- suhdr = (struct nandfs_sufile_header *)bp->b_data;
- nss->nss_nsegs = nandfsdev->nd_fsdata.f_nsegments;
- nss->nss_ncleansegs = suhdr->sh_ncleansegs;
- nss->nss_ndirtysegs = suhdr->sh_ndirtysegs;
- nss->nss_ctime = 0;
- nss->nss_nongc_ctime = nandfsdev->nd_ts.tv_sec;
- nss->nss_prot_seq = nandfsdev->nd_seg_sequence;
-
- brelse(bp);
- VOP_UNLOCK(NTOV(su_node), 0);
-
- NANDFS_WRITEUNLOCK(nandfsdev);
-
- return (0);
-}
-
-int
-nandfs_get_segment_info_ioctl(struct nandfs_device *fsdev,
- struct nandfs_argv *nargv)
-{
- struct nandfs_suinfo *nsi;
- int error;
-
- if (nargv->nv_nmembs > NANDFS_SEGMENTS_MAX)
- return (EINVAL);
-
- nsi = malloc(sizeof(struct nandfs_suinfo) * nargv->nv_nmembs,
- M_NANDFSTEMP, M_WAITOK | M_ZERO);
-
- error = nandfs_get_segment_info(fsdev, nsi, nargv->nv_nmembs,
- nargv->nv_index);
-
- if (error == 0)
- error = copyout(nsi, (void *)(uintptr_t)nargv->nv_base,
- sizeof(struct nandfs_suinfo) * nargv->nv_nmembs);
-
- free(nsi, M_NANDFSTEMP);
- return (error);
-}
-
-int
-nandfs_get_segment_info(struct nandfs_device *fsdev, struct nandfs_suinfo *nsi,
- uint32_t nmembs, uint64_t segment)
-{
-
- return (nandfs_get_segment_info_filter(fsdev, nsi, nmembs, segment,
- NULL, 0, 0));
-}
-
-int
-nandfs_get_segment_info_filter(struct nandfs_device *fsdev,
- struct nandfs_suinfo *nsi, uint32_t nmembs, uint64_t segment,
- uint64_t *nsegs, uint32_t filter, uint32_t nfilter)
-{
- struct nandfs_segment_usage *su;
- struct nandfs_node *su_node;
- struct buf *bp;
- uint64_t curr, blocknr, blockoff, i;
- uint32_t flags;
- int err = 0;
-
- curr = ~(0);
-
- lockmgr(&fsdev->nd_seg_const, LK_EXCLUSIVE, NULL);
- su_node = fsdev->nd_su_node;
-
- VOP_LOCK(NTOV(su_node), LK_SHARED);
-
- bp = NULL;
- if (nsegs != NULL)
- *nsegs = 0;
- for (i = 0; i < nmembs; segment++) {
- if (segment == fsdev->nd_fsdata.f_nsegments)
- break;
-
- nandfs_seg_usage_blk_offset(fsdev, segment, &blocknr,
- &blockoff);
-
- if (i == 0 || curr != blocknr) {
- if (bp != NULL)
- brelse(bp);
- err = nandfs_bread(su_node, blocknr, NOCRED,
- 0, &bp);
- if (err) {
- goto out;
- }
- curr = blocknr;
- }
-
- su = SU_USAGE_OFF(bp, blockoff);
- flags = su->su_flags;
- if (segment == fsdev->nd_seg_num ||
- segment == fsdev->nd_next_seg_num)
- flags |= NANDFS_SEGMENT_USAGE_ACTIVE;
-
- if (nfilter != 0 && (flags & nfilter) != 0)
- continue;
- if (filter != 0 && (flags & filter) == 0)
- continue;
-
- nsi->nsi_num = segment;
- nsi->nsi_lastmod = su->su_lastmod;
- nsi->nsi_blocks = su->su_nblocks;
- nsi->nsi_flags = flags;
- nsi++;
- i++;
- if (nsegs != NULL)
- (*nsegs)++;
- }
-
-out:
- if (bp != NULL)
- brelse(bp);
- VOP_UNLOCK(NTOV(su_node), 0);
- lockmgr(&fsdev->nd_seg_const, LK_RELEASE, NULL);
-
- return (err);
-}
diff --git a/sys/fs/nandfs/nandfs_vfsops.c b/sys/fs/nandfs/nandfs_vfsops.c
deleted file mode 100644
index f703044728ef8..0000000000000
--- a/sys/fs/nandfs/nandfs_vfsops.c
+++ /dev/null
@@ -1,1601 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2010-2012 Semihalf
- * Copyright (c) 2008, 2009 Reinoud Zandijk
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * From: NetBSD: nilfs_vfsops.c,v 1.1 2009/07/18 16:31:42 reinoud Exp
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/fcntl.h>
-#include <sys/gsb_crc32.h>
-#include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/mount.h>
-#include <sys/namei.h>
-#include <sys/proc.h>
-#include <sys/priv.h>
-#include <sys/vnode.h>
-#include <sys/buf.h>
-#include <sys/sysctl.h>
-#include <sys/libkern.h>
-
-#include <geom/geom.h>
-#include <geom/geom_vfs.h>
-
-#include <machine/_inttypes.h>
-
-#include <fs/nandfs/nandfs_mount.h>
-#include <fs/nandfs/nandfs.h>
-#include <fs/nandfs/nandfs_subr.h>
-
-static MALLOC_DEFINE(M_NANDFSMNT, "nandfs_mount", "NANDFS mount structure");
-
-#define NANDFS_SET_SYSTEMFILE(vp) { \
- (vp)->v_vflag |= VV_SYSTEM; \
- vref(vp); \
- vput(vp); }
-
-#define NANDFS_UNSET_SYSTEMFILE(vp) { \
- VOP_LOCK(vp, LK_EXCLUSIVE); \
- MPASS(vp->v_bufobj.bo_dirty.bv_cnt == 0); \
- (vp)->v_vflag &= ~VV_SYSTEM; \
- vgone(vp); \
- vput(vp); }
-
-/* Globals */
-struct _nandfs_devices nandfs_devices;
-
-/* Parameters */
-int nandfs_verbose = 0;
-
-static void
-nandfs_tunable_init(void *arg)
-{
-
- TUNABLE_INT_FETCH("vfs.nandfs.verbose", &nandfs_verbose);
-}
-SYSINIT(nandfs_tunables, SI_SUB_VFS, SI_ORDER_ANY, nandfs_tunable_init, NULL);
-
-static SYSCTL_NODE(_vfs, OID_AUTO, nandfs, CTLFLAG_RD, 0, "NAND filesystem");
-static SYSCTL_NODE(_vfs_nandfs, OID_AUTO, mount, CTLFLAG_RD, 0,
- "NANDFS mountpoints");
-SYSCTL_INT(_vfs_nandfs, OID_AUTO, verbose, CTLFLAG_RW, &nandfs_verbose, 0, "");
-
-#define NANDFS_CONSTR_INTERVAL 5
-int nandfs_sync_interval = NANDFS_CONSTR_INTERVAL; /* sync every 5 seconds */
-SYSCTL_UINT(_vfs_nandfs, OID_AUTO, sync_interval, CTLFLAG_RW,
- &nandfs_sync_interval, 0, "");
-
-#define NANDFS_MAX_DIRTY_SEGS 5
-int nandfs_max_dirty_segs = NANDFS_MAX_DIRTY_SEGS; /* sync when 5 dirty seg */
-SYSCTL_UINT(_vfs_nandfs, OID_AUTO, max_dirty_segs, CTLFLAG_RW,
- &nandfs_max_dirty_segs, 0, "");
-
-#define NANDFS_CPS_BETWEEN_SBLOCKS 5
-int nandfs_cps_between_sblocks = NANDFS_CPS_BETWEEN_SBLOCKS; /* write superblock every 5 checkpoints */
-SYSCTL_UINT(_vfs_nandfs, OID_AUTO, cps_between_sblocks, CTLFLAG_RW,
- &nandfs_cps_between_sblocks, 0, "");
-
-#define NANDFS_CLEANER_ENABLE 1
-int nandfs_cleaner_enable = NANDFS_CLEANER_ENABLE;
-SYSCTL_UINT(_vfs_nandfs, OID_AUTO, cleaner_enable, CTLFLAG_RW,
- &nandfs_cleaner_enable, 0, "");
-
-#define NANDFS_CLEANER_INTERVAL 5
-int nandfs_cleaner_interval = NANDFS_CLEANER_INTERVAL;
-SYSCTL_UINT(_vfs_nandfs, OID_AUTO, cleaner_interval, CTLFLAG_RW,
- &nandfs_cleaner_interval, 0, "");
-
-#define NANDFS_CLEANER_SEGMENTS 5
-int nandfs_cleaner_segments = NANDFS_CLEANER_SEGMENTS;
-SYSCTL_UINT(_vfs_nandfs, OID_AUTO, cleaner_segments, CTLFLAG_RW,
- &nandfs_cleaner_segments, 0, "");
-
-static int nandfs_mountfs(struct vnode *devvp, struct mount *mp);
-static vfs_mount_t nandfs_mount;
-static vfs_root_t nandfs_root;
-static vfs_statfs_t nandfs_statfs;
-static vfs_unmount_t nandfs_unmount;
-static vfs_vget_t nandfs_vget;
-static vfs_sync_t nandfs_sync;
-static const char *nandfs_opts[] = {
- "snap", "from", "noatime", NULL
-};
-
-/* System nodes */
-static int
-nandfs_create_system_nodes(struct nandfs_device *nandfsdev)
-{
- int error;
-
- error = nandfs_get_node_raw(nandfsdev, NULL, NANDFS_DAT_INO,
- &nandfsdev->nd_super_root.sr_dat, &nandfsdev->nd_dat_node);
- if (error)
- goto errorout;
-
- error = nandfs_get_node_raw(nandfsdev, NULL, NANDFS_CPFILE_INO,
- &nandfsdev->nd_super_root.sr_cpfile, &nandfsdev->nd_cp_node);
- if (error)
- goto errorout;
-
- error = nandfs_get_node_raw(nandfsdev, NULL, NANDFS_SUFILE_INO,
- &nandfsdev->nd_super_root.sr_sufile, &nandfsdev->nd_su_node);
- if (error)
- goto errorout;
-
- error = nandfs_get_node_raw(nandfsdev, NULL, NANDFS_GC_INO,
- NULL, &nandfsdev->nd_gc_node);
- if (error)
- goto errorout;
-
- NANDFS_SET_SYSTEMFILE(NTOV(nandfsdev->nd_dat_node));
- NANDFS_SET_SYSTEMFILE(NTOV(nandfsdev->nd_cp_node));
- NANDFS_SET_SYSTEMFILE(NTOV(nandfsdev->nd_su_node));
- NANDFS_SET_SYSTEMFILE(NTOV(nandfsdev->nd_gc_node));
-
- DPRINTF(VOLUMES, ("System vnodes: dat: %p cp: %p su: %p\n",
- NTOV(nandfsdev->nd_dat_node), NTOV(nandfsdev->nd_cp_node),
- NTOV(nandfsdev->nd_su_node)));
- return (0);
-
-errorout:
- nandfs_dispose_node(&nandfsdev->nd_gc_node);
- nandfs_dispose_node(&nandfsdev->nd_dat_node);
- nandfs_dispose_node(&nandfsdev->nd_cp_node);
- nandfs_dispose_node(&nandfsdev->nd_su_node);
-
- return (error);
-}
-
-static void
-nandfs_release_system_nodes(struct nandfs_device *nandfsdev)
-{
-
- if (!nandfsdev)
- return;
- if (nandfsdev->nd_refcnt > 0)
- return;
-
- if (nandfsdev->nd_gc_node)
- NANDFS_UNSET_SYSTEMFILE(NTOV(nandfsdev->nd_gc_node));
- if (nandfsdev->nd_dat_node)
- NANDFS_UNSET_SYSTEMFILE(NTOV(nandfsdev->nd_dat_node));
- if (nandfsdev->nd_cp_node)
- NANDFS_UNSET_SYSTEMFILE(NTOV(nandfsdev->nd_cp_node));
- if (nandfsdev->nd_su_node)
- NANDFS_UNSET_SYSTEMFILE(NTOV(nandfsdev->nd_su_node));
-}
-
-static int
-nandfs_check_fsdata_crc(struct nandfs_fsdata *fsdata)
-{
- uint32_t fsdata_crc, comp_crc;
-
- if (fsdata->f_magic != NANDFS_FSDATA_MAGIC)
- return (0);
-
- /* Preserve CRC */
- fsdata_crc = fsdata->f_sum;
-
- /* Calculate */
- fsdata->f_sum = (0);
- comp_crc = crc32((uint8_t *)fsdata, fsdata->f_bytes);
-
- /* Restore */
- fsdata->f_sum = fsdata_crc;
-
- /* Check CRC */
- return (fsdata_crc == comp_crc);
-}
-
-static int
-nandfs_check_superblock_crc(struct nandfs_fsdata *fsdata,
- struct nandfs_super_block *super)
-{
- uint32_t super_crc, comp_crc;
-
- /* Check super block magic */
- if (super->s_magic != NANDFS_SUPER_MAGIC)
- return (0);
-
- /* Preserve CRC */
- super_crc = super->s_sum;
-
- /* Calculate */
- super->s_sum = (0);
- comp_crc = crc32((uint8_t *)super, fsdata->f_sbbytes);
-
- /* Restore */
- super->s_sum = super_crc;
-
- /* Check CRC */
- return (super_crc == comp_crc);
-}
-
-static void
-nandfs_calc_superblock_crc(struct nandfs_fsdata *fsdata,
- struct nandfs_super_block *super)
-{
- uint32_t comp_crc;
-
- /* Calculate */
- super->s_sum = 0;
- comp_crc = crc32((uint8_t *)super, fsdata->f_sbbytes);
-
- /* Restore */
- super->s_sum = comp_crc;
-}
-
-static int
-nandfs_is_empty(u_char *area, int size)
-{
- int i;
-
- for (i = 0; i < size; i++)
- if (area[i] != 0xff)
- return (0);
-
- return (1);
-}
-
-static __inline int
-nandfs_sblocks_in_esize(struct nandfs_device *fsdev)
-{
-
- return ((fsdev->nd_erasesize - NANDFS_SBLOCK_OFFSET_BYTES) /
- sizeof(struct nandfs_super_block));
-}
-
-static __inline int
-nandfs_max_sblocks(struct nandfs_device *fsdev)
-{
-
- return (NANDFS_NFSAREAS * nandfs_sblocks_in_esize(fsdev));
-}
-
-static __inline int
-nandfs_sblocks_in_block(struct nandfs_device *fsdev)
-{
-
- return (fsdev->nd_devblocksize / sizeof(struct nandfs_super_block));
-}
-
-#if 0
-static __inline int
-nandfs_sblocks_in_first_block(struct nandfs_device *fsdev)
-{
- int n;
-
- n = nandfs_sblocks_in_block(fsdev) -
- NANDFS_SBLOCK_OFFSET_BYTES / sizeof(struct nandfs_super_block);
- if (n < 0)
- n = 0;
-
- return (n);
-}
-#endif
-
-static int
-nandfs_write_superblock_at(struct nandfs_device *fsdev,
- struct nandfs_fsarea *fstp)
-{
- struct nandfs_super_block *super, *supert;
- struct buf *bp;
- int sb_per_sector, sbs_in_fsd, read_block;
- int index, pos, error;
- off_t offset;
-
- DPRINTF(SYNC, ("%s: last_used %d nandfs_sblocks_in_esize %d\n",
- __func__, fstp->last_used, nandfs_sblocks_in_esize(fsdev)));
- if (fstp->last_used == nandfs_sblocks_in_esize(fsdev) - 1)
- index = 0;
- else
- index = fstp->last_used + 1;
-
- super = &fsdev->nd_super;
- supert = NULL;
-
- sb_per_sector = nandfs_sblocks_in_block(fsdev);
- sbs_in_fsd = sizeof(struct nandfs_fsdata) /
- sizeof(struct nandfs_super_block);
- index += sbs_in_fsd;
- offset = fstp->offset;
-
- DPRINTF(SYNC, ("%s: offset %#jx s_last_pseg %#jx s_last_cno %#jx "
- "s_last_seq %#jx wtime %jd index %d\n", __func__, offset,
- super->s_last_pseg, super->s_last_cno, super->s_last_seq,
- super->s_wtime, index));
-
- read_block = btodb(offset + rounddown(index, sb_per_sector) *
- sizeof(struct nandfs_super_block));
-
- DPRINTF(SYNC, ("%s: read_block %#x\n", __func__, read_block));
-
- if (index == sbs_in_fsd) {
- error = nandfs_erase(fsdev, offset, fsdev->nd_erasesize);
- if (error)
- return (error);
-
- error = bread(fsdev->nd_devvp, btodb(offset),
- fsdev->nd_devblocksize, NOCRED, &bp);
- if (error) {
- printf("NANDFS: couldn't read initial data: %d\n",
- error);
- brelse(bp);
- return (error);
- }
- memcpy(bp->b_data, &fsdev->nd_fsdata, sizeof(fsdev->nd_fsdata));
- /*
- * 0xff-out the rest. This bp could be cached, so potentially
- * b_data contains stale super blocks.
- *
- * We don't mind cached bp since most of the time we just add
- * super blocks to already 0xff-out b_data and don't need to
- * perform actual read.
- */
- if (fsdev->nd_devblocksize > sizeof(fsdev->nd_fsdata))
- memset(bp->b_data + sizeof(fsdev->nd_fsdata), 0xff,
- fsdev->nd_devblocksize - sizeof(fsdev->nd_fsdata));
- error = bwrite(bp);
- if (error) {
- printf("NANDFS: cannot rewrite initial data at %jx\n",
- offset);
- return (error);
- }
- }
-
- error = bread(fsdev->nd_devvp, read_block, fsdev->nd_devblocksize,
- NOCRED, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
-
- supert = (struct nandfs_super_block *)(bp->b_data);
- pos = index % sb_per_sector;
-
- DPRINTF(SYNC, ("%s: storing at %d\n", __func__, pos));
- memcpy(&supert[pos], super, sizeof(struct nandfs_super_block));
-
- /*
- * See comment above in code that performs erase.
- */
- if (pos == 0)
- memset(&supert[1], 0xff,
- (sb_per_sector - 1) * sizeof(struct nandfs_super_block));
-
- error = bwrite(bp);
- if (error) {
- printf("NANDFS: cannot update superblock at %jx\n", offset);
- return (error);
- }
-
- DPRINTF(SYNC, ("%s: fstp->last_used %d -> %d\n", __func__,
- fstp->last_used, index - sbs_in_fsd));
- fstp->last_used = index - sbs_in_fsd;
-
- return (0);
-}
-
-int
-nandfs_write_superblock(struct nandfs_device *fsdev)
-{
- struct nandfs_super_block *super;
- struct timespec ts;
- int error;
- int i, j;
-
- vfs_timestamp(&ts);
-
- super = &fsdev->nd_super;
-
- super->s_last_pseg = fsdev->nd_last_pseg;
- super->s_last_cno = fsdev->nd_last_cno;
- super->s_last_seq = fsdev->nd_seg_sequence;
- super->s_wtime = ts.tv_sec;
-
- nandfs_calc_superblock_crc(&fsdev->nd_fsdata, super);
-
- error = 0;
- for (i = 0, j = fsdev->nd_last_fsarea; i < NANDFS_NFSAREAS;
- i++, j = (j + 1 % NANDFS_NFSAREAS)) {
- if (fsdev->nd_fsarea[j].flags & NANDFS_FSSTOR_FAILED) {
- DPRINTF(SYNC, ("%s: skipping %d\n", __func__, j));
- continue;
- }
- error = nandfs_write_superblock_at(fsdev, &fsdev->nd_fsarea[j]);
- if (error) {
- printf("NANDFS: writing superblock at offset %d failed:"
- "%d\n", j * fsdev->nd_erasesize, error);
- fsdev->nd_fsarea[j].flags |= NANDFS_FSSTOR_FAILED;
- } else
- break;
- }
-
- if (i == NANDFS_NFSAREAS) {
- printf("NANDFS: superblock was not written\n");
- /*
- * TODO: switch to read-only?
- */
- return (error);
- } else
- fsdev->nd_last_fsarea = (j + 1) % NANDFS_NFSAREAS;
-
- return (0);
-}
-
-static int
-nandfs_select_fsdata(struct nandfs_device *fsdev,
- struct nandfs_fsdata *fsdatat, struct nandfs_fsdata **fsdata, int nfsds)
-{
- int i;
-
- *fsdata = NULL;
- for (i = 0; i < nfsds; i++) {
- DPRINTF(VOLUMES, ("%s: i %d f_magic %x f_crc %x\n", __func__,
- i, fsdatat[i].f_magic, fsdatat[i].f_sum));
- if (!nandfs_check_fsdata_crc(&fsdatat[i]))
- continue;
- *fsdata = &fsdatat[i];
- break;
- }
-
- return (*fsdata != NULL ? 0 : EINVAL);
-}
-
-static int
-nandfs_select_sb(struct nandfs_device *fsdev,
- struct nandfs_super_block *supert, struct nandfs_super_block **super,
- int nsbs)
-{
- int i;
-
- *super = NULL;
- for (i = 0; i < nsbs; i++) {
- if (!nandfs_check_superblock_crc(&fsdev->nd_fsdata, &supert[i]))
- continue;
- DPRINTF(SYNC, ("%s: i %d s_last_cno %jx s_magic %x "
- "s_wtime %jd\n", __func__, i, supert[i].s_last_cno,
- supert[i].s_magic, supert[i].s_wtime));
- if (*super == NULL || supert[i].s_last_cno >
- (*super)->s_last_cno)
- *super = &supert[i];
- }
-
- return (*super != NULL ? 0 : EINVAL);
-}
-
-static int
-nandfs_read_structures_at(struct nandfs_device *fsdev,
- struct nandfs_fsarea *fstp, struct nandfs_fsdata *fsdata,
- struct nandfs_super_block *super)
-{
- struct nandfs_super_block *tsuper, *tsuperd;
- struct buf *bp;
- int error, read_size;
- int i;
- int offset;
-
- offset = fstp->offset;
-
- if (fsdev->nd_erasesize > MAXBSIZE)
- read_size = MAXBSIZE;
- else
- read_size = fsdev->nd_erasesize;
-
- error = bread(fsdev->nd_devvp, btodb(offset), read_size, NOCRED, &bp);
- if (error) {
- printf("couldn't read: %d\n", error);
- brelse(bp);
- fstp->flags |= NANDFS_FSSTOR_FAILED;
- return (error);
- }
-
- tsuper = super;
-
- memcpy(fsdata, bp->b_data, sizeof(struct nandfs_fsdata));
- memcpy(tsuper, (bp->b_data + sizeof(struct nandfs_fsdata)),
- read_size - sizeof(struct nandfs_fsdata));
- brelse(bp);
-
- tsuper += (read_size - sizeof(struct nandfs_fsdata)) /
- sizeof(struct nandfs_super_block);
-
- for (i = 1; i < fsdev->nd_erasesize / read_size; i++) {
- error = bread(fsdev->nd_devvp, btodb(offset + i * read_size),
- read_size, NOCRED, &bp);
- if (error) {
- printf("couldn't read: %d\n", error);
- brelse(bp);
- fstp->flags |= NANDFS_FSSTOR_FAILED;
- return (error);
- }
- memcpy(tsuper, bp->b_data, read_size);
- tsuper += read_size / sizeof(struct nandfs_super_block);
- brelse(bp);
- }
-
- tsuper -= 1;
- fstp->last_used = nandfs_sblocks_in_esize(fsdev) - 1;
- for (tsuperd = super - 1; (tsuper != tsuperd); tsuper -= 1) {
- if (nandfs_is_empty((u_char *)tsuper, sizeof(*tsuper)))
- fstp->last_used--;
- else
- break;
- }
-
- DPRINTF(VOLUMES, ("%s: last_used %d\n", __func__, fstp->last_used));
-
- return (0);
-}
-
-static int
-nandfs_read_structures(struct nandfs_device *fsdev)
-{
- struct nandfs_fsdata *fsdata, *fsdatat;
- struct nandfs_super_block *sblocks, *ssblock;
- u_int nsbs, nfsds, i;
- int error = 0;
- int nrsbs;
-
- nfsds = NANDFS_NFSAREAS;
- nsbs = nandfs_max_sblocks(fsdev);
-
- fsdatat = malloc(sizeof(struct nandfs_fsdata) * nfsds, M_NANDFSTEMP,
- M_WAITOK | M_ZERO);
- sblocks = malloc(sizeof(struct nandfs_super_block) * nsbs, M_NANDFSTEMP,
- M_WAITOK | M_ZERO);
-
- nrsbs = 0;
- for (i = 0; i < NANDFS_NFSAREAS; i++) {
- fsdev->nd_fsarea[i].offset = i * fsdev->nd_erasesize;
- error = nandfs_read_structures_at(fsdev, &fsdev->nd_fsarea[i],
- &fsdatat[i], sblocks + nrsbs);
- if (error)
- continue;
- nrsbs += (fsdev->nd_fsarea[i].last_used + 1);
- if (fsdev->nd_fsarea[fsdev->nd_last_fsarea].last_used >
- fsdev->nd_fsarea[i].last_used)
- fsdev->nd_last_fsarea = i;
- }
-
- if (nrsbs == 0) {
- printf("nandfs: no valid superblocks found\n");
- error = EINVAL;
- goto out;
- }
-
- error = nandfs_select_fsdata(fsdev, fsdatat, &fsdata, nfsds);
- if (error)
- goto out;
- memcpy(&fsdev->nd_fsdata, fsdata, sizeof(struct nandfs_fsdata));
-
- error = nandfs_select_sb(fsdev, sblocks, &ssblock, nsbs);
- if (error)
- goto out;
-
- memcpy(&fsdev->nd_super, ssblock, sizeof(struct nandfs_super_block));
-out:
- free(fsdatat, M_NANDFSTEMP);
- free(sblocks, M_NANDFSTEMP);
-
- if (error == 0)
- DPRINTF(VOLUMES, ("%s: selected sb with w_time %jd "
- "last_pseg %#jx\n", __func__, fsdev->nd_super.s_wtime,
- fsdev->nd_super.s_last_pseg));
-
- return (error);
-}
-
-static void
-nandfs_unmount_base(struct nandfs_device *nandfsdev)
-{
- int error;
-
- if (!nandfsdev)
- return;
-
- /* Remove all our information */
- error = vinvalbuf(nandfsdev->nd_devvp, V_SAVE, 0, 0);
- if (error) {
- /*
- * Flushing buffers failed when fs was umounting, can't do
- * much now, just printf error and continue with umount.
- */
- nandfs_error("%s(): error:%d when umounting FS\n",
- __func__, error);
- }
-
- /* Release the device's system nodes */
- nandfs_release_system_nodes(nandfsdev);
-}
-
-static void
-nandfs_get_ncleanseg(struct nandfs_device *nandfsdev)
-{
- struct nandfs_seg_stat nss;
-
- nandfs_get_seg_stat(nandfsdev, &nss);
- nandfsdev->nd_clean_segs = nss.nss_ncleansegs;
- DPRINTF(VOLUMES, ("nandfs_mount: clean segs: %jx\n",
- (uintmax_t)nandfsdev->nd_clean_segs));
-}
-
-
-static int
-nandfs_mount_base(struct nandfs_device *nandfsdev, struct mount *mp,
- struct nandfs_args *args)
-{
- uint32_t log_blocksize;
- int error;
-
- /* Flush out any old buffers remaining from a previous use. */
- if ((error = vinvalbuf(nandfsdev->nd_devvp, V_SAVE, 0, 0)))
- return (error);
-
- error = nandfs_read_structures(nandfsdev);
- if (error) {
- printf("nandfs: could not get valid filesystem structures\n");
- return (error);
- }
-
- if (nandfsdev->nd_fsdata.f_rev_level != NANDFS_CURRENT_REV) {
- printf("nandfs: unsupported file system revision: %d "
- "(supported is %d).\n", nandfsdev->nd_fsdata.f_rev_level,
- NANDFS_CURRENT_REV);
- return (EINVAL);
- }
-
- if (nandfsdev->nd_fsdata.f_erasesize != nandfsdev->nd_erasesize) {
- printf("nandfs: erasesize mismatch (device %#x, fs %#x)\n",
- nandfsdev->nd_erasesize, nandfsdev->nd_fsdata.f_erasesize);
- return (EINVAL);
- }
-
- /* Get our blocksize */
- log_blocksize = nandfsdev->nd_fsdata.f_log_block_size;
- nandfsdev->nd_blocksize = (uint64_t) 1 << (log_blocksize + 10);
- DPRINTF(VOLUMES, ("%s: blocksize:%x\n", __func__,
- nandfsdev->nd_blocksize));
-
- DPRINTF(VOLUMES, ("%s: accepted super block with cp %#jx\n", __func__,
- (uintmax_t)nandfsdev->nd_super.s_last_cno));
-
- /* Calculate dat structure parameters */
- nandfs_calc_mdt_consts(nandfsdev, &nandfsdev->nd_dat_mdt,
- nandfsdev->nd_fsdata.f_dat_entry_size);
- nandfs_calc_mdt_consts(nandfsdev, &nandfsdev->nd_ifile_mdt,
- nandfsdev->nd_fsdata.f_inode_size);
-
- /* Search for the super root and roll forward when needed */
- if (nandfs_search_super_root(nandfsdev)) {
- printf("Cannot find valid SuperRoot\n");
- return (EINVAL);
- }
-
- nandfsdev->nd_mount_state = nandfsdev->nd_super.s_state;
- if (nandfsdev->nd_mount_state != NANDFS_VALID_FS) {
- printf("FS is seriously damaged, needs repairing\n");
- printf("aborting mount\n");
- return (EINVAL);
- }
-
- /*
- * FS should be ok now. The superblock and the last segsum could be
- * updated from the repair so extract running values again.
- */
- nandfsdev->nd_last_pseg = nandfsdev->nd_super.s_last_pseg;
- nandfsdev->nd_seg_sequence = nandfsdev->nd_super.s_last_seq;
- nandfsdev->nd_seg_num = nandfs_get_segnum_of_block(nandfsdev,
- nandfsdev->nd_last_pseg);
- nandfsdev->nd_next_seg_num = nandfs_get_segnum_of_block(nandfsdev,
- nandfsdev->nd_last_segsum.ss_next);
- nandfsdev->nd_ts.tv_sec = nandfsdev->nd_last_segsum.ss_create;
- nandfsdev->nd_last_cno = nandfsdev->nd_super.s_last_cno;
- nandfsdev->nd_fakevblk = 1;
- /*
- * FIXME: bogus calculation. Should use actual number of usable segments
- * instead of total amount.
- */
- nandfsdev->nd_segs_reserved =
- nandfsdev->nd_fsdata.f_nsegments *
- nandfsdev->nd_fsdata.f_r_segments_percentage / 100;
- nandfsdev->nd_last_ino = NANDFS_USER_INO;
- DPRINTF(VOLUMES, ("%s: last_pseg %#jx last_cno %#jx last_seq %#jx\n"
- "fsdev: last_seg: seq %#jx num %#jx, next_seg_num %#jx "
- "segs_reserved %#jx\n",
- __func__, (uintmax_t)nandfsdev->nd_last_pseg,
- (uintmax_t)nandfsdev->nd_last_cno,
- (uintmax_t)nandfsdev->nd_seg_sequence,
- (uintmax_t)nandfsdev->nd_seg_sequence,
- (uintmax_t)nandfsdev->nd_seg_num,
- (uintmax_t)nandfsdev->nd_next_seg_num,
- (uintmax_t)nandfsdev->nd_segs_reserved));
-
- DPRINTF(VOLUMES, ("nandfs_mount: accepted super root\n"));
-
- /* Create system vnodes for DAT, CP and SEGSUM */
- error = nandfs_create_system_nodes(nandfsdev);
- if (error)
- nandfs_unmount_base(nandfsdev);
-
- nandfs_get_ncleanseg(nandfsdev);
-
- return (error);
-}
-
-static void
-nandfs_unmount_device(struct nandfs_device *nandfsdev)
-{
-
- /* Is there anything? */
- if (nandfsdev == NULL)
- return;
-
- /* Remove the device only if we're the last reference */
- nandfsdev->nd_refcnt--;
- if (nandfsdev->nd_refcnt >= 1)
- return;
-
- MPASS(nandfsdev->nd_syncer == NULL);
- MPASS(nandfsdev->nd_cleaner == NULL);
- MPASS(nandfsdev->nd_free_base == NULL);
-
- /* Unmount our base */
- nandfs_unmount_base(nandfsdev);
-
- /* Remove from our device list */
- SLIST_REMOVE(&nandfs_devices, nandfsdev, nandfs_device, nd_next_device);
-
- DROP_GIANT();
- g_topology_lock();
- g_vfs_close(nandfsdev->nd_gconsumer);
- g_topology_unlock();
- PICKUP_GIANT();
-
- DPRINTF(VOLUMES, ("closing device\n"));
-
- /* Clear our mount reference and release device node */
- vrele(nandfsdev->nd_devvp);
-
- dev_rel(nandfsdev->nd_devvp->v_rdev);
-
- /* Free our device info */
- cv_destroy(&nandfsdev->nd_sync_cv);
- mtx_destroy(&nandfsdev->nd_sync_mtx);
- cv_destroy(&nandfsdev->nd_clean_cv);
- mtx_destroy(&nandfsdev->nd_clean_mtx);
- mtx_destroy(&nandfsdev->nd_mutex);
- lockdestroy(&nandfsdev->nd_seg_const);
- free(nandfsdev, M_NANDFSMNT);
-}
-
-static int
-nandfs_check_mounts(struct nandfs_device *nandfsdev, struct mount *mp,
- struct nandfs_args *args)
-{
- struct nandfsmount *nmp;
- uint64_t last_cno;
-
- /* no double-mounting of the same checkpoint */
- STAILQ_FOREACH(nmp, &nandfsdev->nd_mounts, nm_next_mount) {
- if (nmp->nm_mount_args.cpno == args->cpno)
- return (EBUSY);
- }
-
- /* Allow readonly mounts without questioning here */
- if (mp->mnt_flag & MNT_RDONLY)
- return (0);
-
- /* Read/write mount */
- STAILQ_FOREACH(nmp, &nandfsdev->nd_mounts, nm_next_mount) {
- /* Only one RW mount on this device! */
- if ((nmp->nm_vfs_mountp->mnt_flag & MNT_RDONLY)==0)
- return (EROFS);
- /* RDONLY on last mountpoint is device busy */
- last_cno = nmp->nm_nandfsdev->nd_super.s_last_cno;
- if (nmp->nm_mount_args.cpno == last_cno)
- return (EBUSY);
- }
-
- /* OK for now */
- return (0);
-}
-
-static int
-nandfs_mount_device(struct vnode *devvp, struct mount *mp,
- struct nandfs_args *args, struct nandfs_device **nandfsdev_p)
-{
- struct nandfs_device *nandfsdev;
- struct g_provider *pp;
- struct g_consumer *cp;
- struct cdev *dev;
- uint32_t erasesize;
- int error, size;
- int ronly;
-
- DPRINTF(VOLUMES, ("Mounting NANDFS device\n"));
-
- ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
-
- /* Look up device in our nandfs_mountpoints */
- *nandfsdev_p = NULL;
- SLIST_FOREACH(nandfsdev, &nandfs_devices, nd_next_device)
- if (nandfsdev->nd_devvp == devvp)
- break;
-
- if (nandfsdev) {
- DPRINTF(VOLUMES, ("device already mounted\n"));
- error = nandfs_check_mounts(nandfsdev, mp, args);
- if (error)
- return error;
- nandfsdev->nd_refcnt++;
- *nandfsdev_p = nandfsdev;
-
- if (!ronly) {
- DROP_GIANT();
- g_topology_lock();
- error = g_access(nandfsdev->nd_gconsumer, 0, 1, 0);
- g_topology_unlock();
- PICKUP_GIANT();
- }
- return (error);
- }
-
- vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
- dev = devvp->v_rdev;
- dev_ref(dev);
- DROP_GIANT();
- g_topology_lock();
- error = g_vfs_open(devvp, &cp, "nandfs", ronly ? 0 : 1);
- pp = g_dev_getprovider(dev);
- g_topology_unlock();
- PICKUP_GIANT();
- VOP_UNLOCK(devvp, 0);
- if (error) {
- dev_rel(dev);
- return (error);
- }
-
- nandfsdev = malloc(sizeof(struct nandfs_device), M_NANDFSMNT, M_WAITOK | M_ZERO);
-
- /* Initialise */
- nandfsdev->nd_refcnt = 1;
- nandfsdev->nd_devvp = devvp;
- nandfsdev->nd_syncing = 0;
- nandfsdev->nd_cleaning = 0;
- nandfsdev->nd_gconsumer = cp;
- cv_init(&nandfsdev->nd_sync_cv, "nandfssync");
- mtx_init(&nandfsdev->nd_sync_mtx, "nffssyncmtx", NULL, MTX_DEF);
- cv_init(&nandfsdev->nd_clean_cv, "nandfsclean");
- mtx_init(&nandfsdev->nd_clean_mtx, "nffscleanmtx", NULL, MTX_DEF);
- mtx_init(&nandfsdev->nd_mutex, "nandfsdev lock", NULL, MTX_DEF);
- lockinit(&nandfsdev->nd_seg_const, PVFS, "nffssegcon", VLKTIMEOUT,
- LK_CANRECURSE);
- STAILQ_INIT(&nandfsdev->nd_mounts);
-
- nandfsdev->nd_devsize = pp->mediasize;
- nandfsdev->nd_devblocksize = pp->sectorsize;
-
- size = sizeof(erasesize);
- error = g_io_getattr("NAND::blocksize", nandfsdev->nd_gconsumer, &size,
- &erasesize);
- if (error) {
- DPRINTF(VOLUMES, ("couldn't get erasesize: %d\n", error));
-
- if (error == ENOIOCTL || error == EOPNOTSUPP) {
- /*
- * We conclude that this is not NAND storage
- */
- erasesize = NANDFS_DEF_ERASESIZE;
- } else {
- DROP_GIANT();
- g_topology_lock();
- g_vfs_close(nandfsdev->nd_gconsumer);
- g_topology_unlock();
- PICKUP_GIANT();
- dev_rel(dev);
- free(nandfsdev, M_NANDFSMNT);
- return (error);
- }
- }
- nandfsdev->nd_erasesize = erasesize;
-
- DPRINTF(VOLUMES, ("%s: erasesize %x\n", __func__,
- nandfsdev->nd_erasesize));
-
- /* Register nandfs_device in list */
- SLIST_INSERT_HEAD(&nandfs_devices, nandfsdev, nd_next_device);
-
- error = nandfs_mount_base(nandfsdev, mp, args);
- if (error) {
- /* Remove all our information */
- nandfs_unmount_device(nandfsdev);
- return (EINVAL);
- }
-
- nandfsdev->nd_maxfilesize = nandfs_get_maxfilesize(nandfsdev);
-
- *nandfsdev_p = nandfsdev;
- DPRINTF(VOLUMES, ("NANDFS device mounted ok\n"));
-
- return (0);
-}
-
-static int
-nandfs_mount_checkpoint(struct nandfsmount *nmp)
-{
- struct nandfs_cpfile_header *cphdr;
- struct nandfs_checkpoint *cp;
- struct nandfs_inode ifile_inode;
- struct nandfs_node *cp_node;
- struct buf *bp;
- uint64_t ncp, nsn, cpno, fcpno, blocknr, last_cno;
- uint32_t off, dlen;
- int cp_per_block, error;
-
- cpno = nmp->nm_mount_args.cpno;
- if (cpno == 0)
- cpno = nmp->nm_nandfsdev->nd_super.s_last_cno;
-
- DPRINTF(VOLUMES, ("%s: trying to mount checkpoint number %"PRIu64"\n",
- __func__, cpno));
-
- cp_node = nmp->nm_nandfsdev->nd_cp_node;
-
- VOP_LOCK(NTOV(cp_node), LK_SHARED);
- /* Get cpfile header from 1st block of cp file */
- error = nandfs_bread(cp_node, 0, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- VOP_UNLOCK(NTOV(cp_node), 0);
- return (error);
- }
-
- cphdr = (struct nandfs_cpfile_header *) bp->b_data;
- ncp = cphdr->ch_ncheckpoints;
- nsn = cphdr->ch_nsnapshots;
-
- brelse(bp);
-
- DPRINTF(VOLUMES, ("mount_nandfs: checkpoint header read in\n"));
- DPRINTF(VOLUMES, ("\tNumber of checkpoints %"PRIu64"\n", ncp));
- DPRINTF(VOLUMES, ("\tNumber of snapshots %"PRIu64"\n", nsn));
-
- /* Read in our specified checkpoint */
- dlen = nmp->nm_nandfsdev->nd_fsdata.f_checkpoint_size;
- cp_per_block = nmp->nm_nandfsdev->nd_blocksize / dlen;
-
- fcpno = cpno + NANDFS_CPFILE_FIRST_CHECKPOINT_OFFSET - 1;
- blocknr = fcpno / cp_per_block;
- off = (fcpno % cp_per_block) * dlen;
- error = nandfs_bread(cp_node, blocknr, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- VOP_UNLOCK(NTOV(cp_node), 0);
- printf("mount_nandfs: couldn't read cp block %"PRIu64"\n",
- fcpno);
- return (EINVAL);
- }
-
- /* Needs to be a valid checkpoint */
- cp = (struct nandfs_checkpoint *) ((uint8_t *) bp->b_data + off);
- if (cp->cp_flags & NANDFS_CHECKPOINT_INVALID) {
- printf("mount_nandfs: checkpoint marked invalid\n");
- brelse(bp);
- VOP_UNLOCK(NTOV(cp_node), 0);
- return (EINVAL);
- }
-
- /* Is this really the checkpoint we want? */
- if (cp->cp_cno != cpno) {
- printf("mount_nandfs: checkpoint file corrupt? "
- "expected cpno %"PRIu64", found cpno %"PRIu64"\n",
- cpno, cp->cp_cno);
- brelse(bp);
- VOP_UNLOCK(NTOV(cp_node), 0);
- return (EINVAL);
- }
-
- /* Check if it's a snapshot ! */
- last_cno = nmp->nm_nandfsdev->nd_super.s_last_cno;
- if (cpno != last_cno) {
- /* Only allow snapshots if not mounting on the last cp */
- if ((cp->cp_flags & NANDFS_CHECKPOINT_SNAPSHOT) == 0) {
- printf( "mount_nandfs: checkpoint %"PRIu64" is not a "
- "snapshot\n", cpno);
- brelse(bp);
- VOP_UNLOCK(NTOV(cp_node), 0);
- return (EINVAL);
- }
- }
-
- ifile_inode = cp->cp_ifile_inode;
- brelse(bp);
-
- /* Get ifile inode */
- error = nandfs_get_node_raw(nmp->nm_nandfsdev, NULL, NANDFS_IFILE_INO,
- &ifile_inode, &nmp->nm_ifile_node);
- if (error) {
- printf("mount_nandfs: can't read ifile node\n");
- VOP_UNLOCK(NTOV(cp_node), 0);
- return (EINVAL);
- }
-
- NANDFS_SET_SYSTEMFILE(NTOV(nmp->nm_ifile_node));
- VOP_UNLOCK(NTOV(cp_node), 0);
- /* Get root node? */
-
- return (0);
-}
-
-static void
-free_nandfs_mountinfo(struct mount *mp)
-{
- struct nandfsmount *nmp = VFSTONANDFS(mp);
-
- if (nmp == NULL)
- return;
-
- free(nmp, M_NANDFSMNT);
-}
-
-void
-nandfs_wakeup_wait_sync(struct nandfs_device *nffsdev, int reason)
-{
- char *reasons[] = {
- "umount",
- "vfssync",
- "bdflush",
- "fforce",
- "fsync",
- "ro_upd"
- };
-
- DPRINTF(SYNC, ("%s: %s\n", __func__, reasons[reason]));
- mtx_lock(&nffsdev->nd_sync_mtx);
- if (nffsdev->nd_syncing)
- cv_wait(&nffsdev->nd_sync_cv, &nffsdev->nd_sync_mtx);
- if (reason == SYNCER_UMOUNT)
- nffsdev->nd_syncer_exit = 1;
- nffsdev->nd_syncing = 1;
- wakeup(&nffsdev->nd_syncing);
- cv_wait(&nffsdev->nd_sync_cv, &nffsdev->nd_sync_mtx);
-
- mtx_unlock(&nffsdev->nd_sync_mtx);
-}
-
-static void
-nandfs_gc_finished(struct nandfs_device *nffsdev, int exit)
-{
- int error;
-
- mtx_lock(&nffsdev->nd_sync_mtx);
- nffsdev->nd_syncing = 0;
- DPRINTF(SYNC, ("%s: cleaner finish\n", __func__));
- cv_broadcast(&nffsdev->nd_sync_cv);
- mtx_unlock(&nffsdev->nd_sync_mtx);
- if (!exit) {
- error = tsleep(&nffsdev->nd_syncing, PRIBIO, "-",
- hz * nandfs_sync_interval);
- DPRINTF(SYNC, ("%s: cleaner waked up: %d\n",
- __func__, error));
- }
-}
-
-static void
-nandfs_syncer(struct nandfsmount *nmp)
-{
- struct nandfs_device *nffsdev;
- struct mount *mp;
- int flags, error;
-
- mp = nmp->nm_vfs_mountp;
- nffsdev = nmp->nm_nandfsdev;
- tsleep(&nffsdev->nd_syncing, PRIBIO, "-", hz * nandfs_sync_interval);
-
- while (!nffsdev->nd_syncer_exit) {
- DPRINTF(SYNC, ("%s: syncer run\n", __func__));
- nffsdev->nd_syncing = 1;
-
- flags = (nmp->nm_flags & (NANDFS_FORCE_SYNCER | NANDFS_UMOUNT));
-
- error = nandfs_segment_constructor(nmp, flags);
- if (error)
- nandfs_error("%s: error:%d when creating segments\n",
- __func__, error);
-
- nmp->nm_flags &= ~flags;
-
- nandfs_gc_finished(nffsdev, 0);
- }
-
- MPASS(nffsdev->nd_cleaner == NULL);
- error = nandfs_segment_constructor(nmp,
- NANDFS_FORCE_SYNCER | NANDFS_UMOUNT);
- if (error)
- nandfs_error("%s: error:%d when creating segments\n",
- __func__, error);
- nandfs_gc_finished(nffsdev, 1);
- nffsdev->nd_syncer = NULL;
- MPASS(nffsdev->nd_free_base == NULL);
-
- DPRINTF(SYNC, ("%s: exiting\n", __func__));
- kthread_exit();
-}
-
-static int
-start_syncer(struct nandfsmount *nmp)
-{
- int error;
-
- MPASS(nmp->nm_nandfsdev->nd_syncer == NULL);
-
- DPRINTF(SYNC, ("%s: start syncer\n", __func__));
-
- nmp->nm_nandfsdev->nd_syncer_exit = 0;
-
- error = kthread_add((void(*)(void *))nandfs_syncer, nmp, NULL,
- &nmp->nm_nandfsdev->nd_syncer, 0, 0, "nandfs_syncer");
-
- if (error)
- printf("nandfs: could not start syncer: %d\n", error);
-
- return (error);
-}
-
-static int
-stop_syncer(struct nandfsmount *nmp)
-{
-
- MPASS(nmp->nm_nandfsdev->nd_syncer != NULL);
-
- nandfs_wakeup_wait_sync(nmp->nm_nandfsdev, SYNCER_UMOUNT);
-
- DPRINTF(SYNC, ("%s: stop syncer\n", __func__));
- return (0);
-}
-
-/*
- * Mount null layer
- */
-static int
-nandfs_mount(struct mount *mp)
-{
- struct nandfsmount *nmp;
- struct vnode *devvp;
- struct nameidata nd;
- struct vfsoptlist *opts;
- struct thread *td;
- char *from;
- int error = 0, flags;
-
- DPRINTF(VOLUMES, ("%s: mp = %p\n", __func__, (void *)mp));
-
- td = curthread;
- opts = mp->mnt_optnew;
-
- if (vfs_filteropt(opts, nandfs_opts))
- return (EINVAL);
-
- /*
- * Update is a no-op
- */
- if (mp->mnt_flag & MNT_UPDATE) {
- nmp = VFSTONANDFS(mp);
- if (vfs_flagopt(mp->mnt_optnew, "export", NULL, 0)) {
- return (error);
- }
- if (!(nmp->nm_ronly) && vfs_flagopt(opts, "ro", NULL, 0)) {
- vn_start_write(NULL, &mp, V_WAIT);
- error = VFS_SYNC(mp, MNT_WAIT);
- if (error)
- return (error);
- vn_finished_write(mp);
-
- flags = WRITECLOSE;
- if (mp->mnt_flag & MNT_FORCE)
- flags |= FORCECLOSE;
-
- nandfs_wakeup_wait_sync(nmp->nm_nandfsdev,
- SYNCER_ROUPD);
- error = vflush(mp, 0, flags, td);
- if (error)
- return (error);
-
- nandfs_stop_cleaner(nmp->nm_nandfsdev);
- stop_syncer(nmp);
- DROP_GIANT();
- g_topology_lock();
- g_access(nmp->nm_nandfsdev->nd_gconsumer, 0, -1, 0);
- g_topology_unlock();
- PICKUP_GIANT();
- MNT_ILOCK(mp);
- mp->mnt_flag |= MNT_RDONLY;
- MNT_IUNLOCK(mp);
- nmp->nm_ronly = 1;
-
- } else if ((nmp->nm_ronly) &&
- !vfs_flagopt(opts, "ro", NULL, 0)) {
- /*
- * Don't allow read-write snapshots.
- */
- if (nmp->nm_mount_args.cpno != 0)
- return (EROFS);
- /*
- * If upgrade to read-write by non-root, then verify
- * that user has necessary permissions on the device.
- */
- devvp = nmp->nm_nandfsdev->nd_devvp;
- vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
- error = VOP_ACCESS(devvp, VREAD | VWRITE,
- td->td_ucred, td);
- if (error) {
- error = priv_check(td, PRIV_VFS_MOUNT_PERM);
- if (error) {
- VOP_UNLOCK(devvp, 0);
- return (error);
- }
- }
-
- VOP_UNLOCK(devvp, 0);
- DROP_GIANT();
- g_topology_lock();
- error = g_access(nmp->nm_nandfsdev->nd_gconsumer, 0, 1,
- 0);
- g_topology_unlock();
- PICKUP_GIANT();
- if (error)
- return (error);
-
- MNT_ILOCK(mp);
- mp->mnt_flag &= ~MNT_RDONLY;
- MNT_IUNLOCK(mp);
- error = start_syncer(nmp);
- if (error == 0)
- error = nandfs_start_cleaner(nmp->nm_nandfsdev);
- if (error) {
- DROP_GIANT();
- g_topology_lock();
- g_access(nmp->nm_nandfsdev->nd_gconsumer, 0, -1,
- 0);
- g_topology_unlock();
- PICKUP_GIANT();
- return (error);
- }
-
- nmp->nm_ronly = 0;
- }
- return (0);
- }
-
- from = vfs_getopts(opts, "from", &error);
- if (error)
- return (error);
-
- /*
- * Find device node
- */
- NDINIT(&nd, LOOKUP, FOLLOW|LOCKLEAF, UIO_SYSSPACE, from, curthread);
- error = namei(&nd);
- if (error)
- return (error);
- NDFREE(&nd, NDF_ONLY_PNBUF);
-
- devvp = nd.ni_vp;
-
- if (!vn_isdisk(devvp, &error)) {
- vput(devvp);
- return (error);
- }
-
- /* Check the access rights on the mount device */
- error = VOP_ACCESS(devvp, VREAD, curthread->td_ucred, curthread);
- if (error)
- error = priv_check(curthread, PRIV_VFS_MOUNT_PERM);
- if (error) {
- vput(devvp);
- return (error);
- }
-
- vfs_getnewfsid(mp);
-
- error = nandfs_mountfs(devvp, mp);
- if (error)
- return (error);
- vfs_mountedfrom(mp, from);
-
- return (0);
-}
-
-static int
-nandfs_mountfs(struct vnode *devvp, struct mount *mp)
-{
- struct nandfsmount *nmp = NULL;
- struct nandfs_args *args = NULL;
- struct nandfs_device *nandfsdev;
- char *from;
- int error, ronly;
- char *cpno;
-
- ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
-
- if (devvp->v_rdev->si_iosize_max != 0)
- mp->mnt_iosize_max = devvp->v_rdev->si_iosize_max;
- VOP_UNLOCK(devvp, 0);
-
- if (mp->mnt_iosize_max > MAXPHYS)
- mp->mnt_iosize_max = MAXPHYS;
-
- from = vfs_getopts(mp->mnt_optnew, "from", &error);
- if (error)
- goto error;
-
- error = vfs_getopt(mp->mnt_optnew, "snap", (void **)&cpno, NULL);
- if (error == ENOENT)
- cpno = NULL;
- else if (error)
- goto error;
-
- args = (struct nandfs_args *)malloc(sizeof(struct nandfs_args),
- M_NANDFSMNT, M_WAITOK | M_ZERO);
-
- if (cpno != NULL)
- args->cpno = strtoul(cpno, (char **)NULL, 10);
- else
- args->cpno = 0;
- args->fspec = from;
-
- if (args->cpno != 0 && !ronly) {
- error = EROFS;
- goto error;
- }
-
- printf("WARNING: NANDFS is considered to be a highly experimental "
- "feature in FreeBSD.\n");
-
- error = nandfs_mount_device(devvp, mp, args, &nandfsdev);
- if (error)
- goto error;
-
- nmp = (struct nandfsmount *) malloc(sizeof(struct nandfsmount),
- M_NANDFSMNT, M_WAITOK | M_ZERO);
-
- mp->mnt_data = nmp;
- nmp->nm_vfs_mountp = mp;
- nmp->nm_ronly = ronly;
- MNT_ILOCK(mp);
- mp->mnt_flag |= MNT_LOCAL;
- mp->mnt_kern_flag |= MNTK_USES_BCACHE;
- MNT_IUNLOCK(mp);
- nmp->nm_nandfsdev = nandfsdev;
- /* Add our mountpoint */
- STAILQ_INSERT_TAIL(&nandfsdev->nd_mounts, nmp, nm_next_mount);
-
- if (args->cpno > nandfsdev->nd_last_cno) {
- printf("WARNING: supplied checkpoint number (%jd) is greater "
- "than last known checkpoint on filesystem (%jd). Mounting"
- " checkpoint %jd\n", (uintmax_t)args->cpno,
- (uintmax_t)nandfsdev->nd_last_cno,
- (uintmax_t)nandfsdev->nd_last_cno);
- args->cpno = nandfsdev->nd_last_cno;
- }
-
- /* Setting up other parameters */
- nmp->nm_mount_args = *args;
- free(args, M_NANDFSMNT);
- error = nandfs_mount_checkpoint(nmp);
- if (error) {
- nandfs_unmount(mp, MNT_FORCE);
- goto unmounted;
- }
-
- if (!ronly) {
- error = start_syncer(nmp);
- if (error == 0)
- error = nandfs_start_cleaner(nmp->nm_nandfsdev);
- if (error)
- nandfs_unmount(mp, MNT_FORCE);
- }
-
- return (0);
-
-error:
- if (args != NULL)
- free(args, M_NANDFSMNT);
-
- if (nmp != NULL) {
- free(nmp, M_NANDFSMNT);
- mp->mnt_data = NULL;
- }
-unmounted:
- return (error);
-}
-
-static int
-nandfs_unmount(struct mount *mp, int mntflags)
-{
- struct nandfs_device *nandfsdev;
- struct nandfsmount *nmp;
- int error;
- int flags = 0;
-
- DPRINTF(VOLUMES, ("%s: mp = %p\n", __func__, (void *)mp));
-
- if (mntflags & MNT_FORCE)
- flags |= FORCECLOSE;
-
- nmp = mp->mnt_data;
- nandfsdev = nmp->nm_nandfsdev;
-
- error = vflush(mp, 0, flags | SKIPSYSTEM, curthread);
- if (error)
- return (error);
-
- if (!(nmp->nm_ronly)) {
- nandfs_stop_cleaner(nandfsdev);
- stop_syncer(nmp);
- }
-
- if (nmp->nm_ifile_node)
- NANDFS_UNSET_SYSTEMFILE(NTOV(nmp->nm_ifile_node));
-
- /* Remove our mount point */
- STAILQ_REMOVE(&nandfsdev->nd_mounts, nmp, nandfsmount, nm_next_mount);
-
- /* Unmount the device itself when we're the last one */
- nandfs_unmount_device(nandfsdev);
-
- free_nandfs_mountinfo(mp);
-
- /*
- * Finally, throw away the null_mount structure
- */
- mp->mnt_data = 0;
- MNT_ILOCK(mp);
- mp->mnt_flag &= ~MNT_LOCAL;
- MNT_IUNLOCK(mp);
-
- return (0);
-}
-
-static int
-nandfs_statfs(struct mount *mp, struct statfs *sbp)
-{
- struct nandfsmount *nmp;
- struct nandfs_device *nandfsdev;
- struct nandfs_fsdata *fsdata;
- struct nandfs_super_block *sb;
- struct nandfs_block_group_desc *groups;
- struct nandfs_node *ifile;
- struct nandfs_mdt *mdt;
- struct buf *bp;
- int i, error;
- uint32_t entries_per_group;
- uint64_t files = 0;
-
- nmp = mp->mnt_data;
- nandfsdev = nmp->nm_nandfsdev;
- fsdata = &nandfsdev->nd_fsdata;
- sb = &nandfsdev->nd_super;
- ifile = nmp->nm_ifile_node;
- mdt = &nandfsdev->nd_ifile_mdt;
- entries_per_group = mdt->entries_per_group;
-
- VOP_LOCK(NTOV(ifile), LK_SHARED);
- error = nandfs_bread(ifile, 0, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- VOP_UNLOCK(NTOV(ifile), 0);
- return (error);
- }
-
- groups = (struct nandfs_block_group_desc *)bp->b_data;
-
- for (i = 0; i < mdt->groups_per_desc_block; i++)
- files += (entries_per_group - groups[i].bg_nfrees);
-
- brelse(bp);
- VOP_UNLOCK(NTOV(ifile), 0);
-
- sbp->f_bsize = nandfsdev->nd_blocksize;
- sbp->f_iosize = sbp->f_bsize;
- sbp->f_blocks = fsdata->f_blocks_per_segment * fsdata->f_nsegments;
- sbp->f_bfree = sb->s_free_blocks_count;
- sbp->f_bavail = sbp->f_bfree;
- sbp->f_files = files;
- sbp->f_ffree = 0;
- return (0);
-}
-
-static int
-nandfs_root(struct mount *mp, int flags, struct vnode **vpp)
-{
- struct nandfsmount *nmp = VFSTONANDFS(mp);
- struct nandfs_node *node;
- int error;
-
- error = nandfs_get_node(nmp, NANDFS_ROOT_INO, &node);
- if (error)
- return (error);
-
- KASSERT(NTOV(node)->v_vflag & VV_ROOT,
- ("root_vp->v_vflag & VV_ROOT"));
-
- *vpp = NTOV(node);
-
- return (error);
-}
-
-static int
-nandfs_vget(struct mount *mp, ino_t ino, int flags, struct vnode **vpp)
-{
- struct nandfsmount *nmp = VFSTONANDFS(mp);
- struct nandfs_node *node;
- int error;
-
- error = nandfs_get_node(nmp, ino, &node);
- if (node)
- *vpp = NTOV(node);
-
- return (error);
-}
-
-static int
-nandfs_sync(struct mount *mp, int waitfor)
-{
- struct nandfsmount *nmp = VFSTONANDFS(mp);
-
- DPRINTF(SYNC, ("%s: mp %p waitfor %d\n", __func__, mp, waitfor));
-
- /*
- * XXX: A hack to be removed soon
- */
- if (waitfor == MNT_LAZY)
- return (0);
- if (waitfor == MNT_SUSPEND)
- return (0);
- nandfs_wakeup_wait_sync(nmp->nm_nandfsdev, SYNCER_VFS_SYNC);
- return (0);
-}
-
-static struct vfsops nandfs_vfsops = {
- .vfs_init = nandfs_init,
- .vfs_mount = nandfs_mount,
- .vfs_root = nandfs_root,
- .vfs_statfs = nandfs_statfs,
- .vfs_uninit = nandfs_uninit,
- .vfs_unmount = nandfs_unmount,
- .vfs_vget = nandfs_vget,
- .vfs_sync = nandfs_sync,
-};
-
-VFS_SET(nandfs_vfsops, nandfs, VFCF_LOOPBACK);
diff --git a/sys/fs/nandfs/nandfs_vnops.c b/sys/fs/nandfs/nandfs_vnops.c
deleted file mode 100644
index 5027d6adbbc1a..0000000000000
--- a/sys/fs/nandfs/nandfs_vnops.c
+++ /dev/null
@@ -1,2454 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2010-2012 Semihalf
- * Copyright (c) 2008, 2009 Reinoud Zandijk
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * From: NetBSD: nilfs_vnops.c,v 1.2 2009/08/26 03:40:48 elad
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/lockf.h>
-#include <sys/malloc.h>
-#include <sys/mount.h>
-#include <sys/mutex.h>
-#include <sys/namei.h>
-#include <sys/sysctl.h>
-#include <sys/unistd.h>
-#include <sys/vnode.h>
-#include <sys/buf.h>
-#include <sys/bio.h>
-#include <sys/fcntl.h>
-#include <sys/dirent.h>
-#include <sys/rwlock.h>
-#include <sys/stat.h>
-#include <sys/priv.h>
-
-#include <vm/vm.h>
-#include <vm/vm_extern.h>
-#include <vm/vm_object.h>
-#include <vm/vnode_pager.h>
-
-#include <machine/_inttypes.h>
-
-#include <fs/nandfs/nandfs_mount.h>
-#include <fs/nandfs/nandfs.h>
-#include <fs/nandfs/nandfs_subr.h>
-
-extern uma_zone_t nandfs_node_zone;
-static void nandfs_read_filebuf(struct nandfs_node *, struct buf *);
-static void nandfs_itimes_locked(struct vnode *);
-static int nandfs_truncate(struct vnode *, uint64_t);
-
-static vop_pathconf_t nandfs_pathconf;
-
-#define UPDATE_CLOSE 0
-#define UPDATE_WAIT 0
-
-static int
-nandfs_inactive(struct vop_inactive_args *ap)
-{
- struct vnode *vp = ap->a_vp;
- struct nandfs_node *node = VTON(vp);
- int error = 0;
-
- DPRINTF(VNCALL, ("%s: vp:%p node:%p\n", __func__, vp, node));
-
- if (node == NULL) {
- DPRINTF(NODE, ("%s: inactive NULL node\n", __func__));
- return (0);
- }
-
- if (node->nn_inode.i_mode != 0 && !(node->nn_inode.i_links_count)) {
- nandfs_truncate(vp, 0);
- error = nandfs_node_destroy(node);
- if (error)
- nandfs_error("%s: destroy node: %p\n", __func__, node);
- node->nn_flags = 0;
- vrecycle(vp);
- }
-
- return (error);
-}
-
-static int
-nandfs_reclaim(struct vop_reclaim_args *ap)
-{
- struct vnode *vp = ap->a_vp;
- struct nandfs_node *nandfs_node = VTON(vp);
- struct nandfs_device *fsdev = nandfs_node->nn_nandfsdev;
- uint64_t ino = nandfs_node->nn_ino;
-
- DPRINTF(VNCALL, ("%s: vp:%p node:%p\n", __func__, vp, nandfs_node));
-
- /* Invalidate all entries to a particular vnode. */
- cache_purge(vp);
-
- /* Destroy the vm object and flush associated pages. */
- vnode_destroy_vobject(vp);
-
- /* Remove from vfs hash if not system vnode */
- if (!NANDFS_SYS_NODE(nandfs_node->nn_ino))
- vfs_hash_remove(vp);
-
- /* Dispose all node knowledge */
- nandfs_dispose_node(&nandfs_node);
-
- if (!NANDFS_SYS_NODE(ino))
- NANDFS_WRITEUNLOCK(fsdev);
-
- return (0);
-}
-
-static int
-nandfs_read(struct vop_read_args *ap)
-{
- struct vnode *vp = ap->a_vp;
- struct nandfs_node *node = VTON(vp);
- struct nandfs_device *nandfsdev = node->nn_nandfsdev;
- struct uio *uio = ap->a_uio;
- struct buf *bp;
- uint64_t size;
- uint32_t blocksize;
- off_t bytesinfile;
- ssize_t toread, off;
- daddr_t lbn;
- ssize_t resid;
- int error = 0;
-
- if (uio->uio_resid == 0)
- return (0);
-
- size = node->nn_inode.i_size;
- if (uio->uio_offset >= size)
- return (0);
-
- blocksize = nandfsdev->nd_blocksize;
- bytesinfile = size - uio->uio_offset;
-
- resid = omin(uio->uio_resid, bytesinfile);
-
- while (resid) {
- lbn = uio->uio_offset / blocksize;
- off = uio->uio_offset & (blocksize - 1);
-
- toread = omin(resid, blocksize - off);
-
- DPRINTF(READ, ("nandfs_read bn: 0x%jx toread: 0x%zx (0x%x)\n",
- (uintmax_t)lbn, toread, blocksize));
-
- error = nandfs_bread(node, lbn, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- break;
- }
-
- error = uiomove(bp->b_data + off, toread, uio);
- if (error) {
- brelse(bp);
- break;
- }
-
- brelse(bp);
- resid -= toread;
- }
-
- return (error);
-}
-
-static int
-nandfs_write(struct vop_write_args *ap)
-{
- struct nandfs_device *fsdev;
- struct nandfs_node *node;
- struct vnode *vp;
- struct uio *uio;
- struct buf *bp;
- uint64_t file_size, vblk;
- uint32_t blocksize;
- ssize_t towrite, off;
- daddr_t lbn;
- ssize_t resid;
- int error, ioflag, modified;
-
- vp = ap->a_vp;
- uio = ap->a_uio;
- ioflag = ap->a_ioflag;
- node = VTON(vp);
- fsdev = node->nn_nandfsdev;
-
- if (nandfs_fs_full(fsdev))
- return (ENOSPC);
-
- DPRINTF(WRITE, ("nandfs_write called %#zx at %#jx\n",
- uio->uio_resid, (uintmax_t)uio->uio_offset));
-
- if (uio->uio_offset < 0)
- return (EINVAL);
- if (uio->uio_resid == 0)
- return (0);
-
- blocksize = fsdev->nd_blocksize;
- file_size = node->nn_inode.i_size;
-
- switch (vp->v_type) {
- case VREG:
- if (ioflag & IO_APPEND)
- uio->uio_offset = file_size;
- break;
- case VDIR:
- return (EISDIR);
- case VLNK:
- break;
- default:
- panic("%s: bad file type vp: %p", __func__, vp);
- }
-
- /* If explicitly asked to append, uio_offset can be wrong? */
- if (ioflag & IO_APPEND)
- uio->uio_offset = file_size;
-
- resid = uio->uio_resid;
- modified = error = 0;
-
- while (uio->uio_resid) {
- lbn = uio->uio_offset / blocksize;
- off = uio->uio_offset & (blocksize - 1);
-
- towrite = omin(uio->uio_resid, blocksize - off);
-
- DPRINTF(WRITE, ("%s: lbn: 0x%jd toread: 0x%zx (0x%x)\n",
- __func__, (uintmax_t)lbn, towrite, blocksize));
-
- error = nandfs_bmap_lookup(node, lbn, &vblk);
- if (error)
- break;
-
- DPRINTF(WRITE, ("%s: lbn: 0x%jd toread: 0x%zx (0x%x) "
- "vblk=%jx\n", __func__, (uintmax_t)lbn, towrite, blocksize,
- vblk));
-
- if (vblk != 0)
- error = nandfs_bread(node, lbn, NOCRED, 0, &bp);
- else
- error = nandfs_bcreate(node, lbn, NOCRED, 0, &bp);
-
- DPRINTF(WRITE, ("%s: vp %p bread bp %p lbn %#jx\n", __func__,
- vp, bp, (uintmax_t)lbn));
- if (error) {
- if (bp)
- brelse(bp);
- break;
- }
-
- error = uiomove((char *)bp->b_data + off, (int)towrite, uio);
- if (error)
- break;
-
- error = nandfs_dirty_buf(bp, 0);
- if (error)
- break;
-
- modified++;
- }
-
- /* XXX proper handling when only part of file was properly written */
- if (modified) {
- if (resid > uio->uio_resid && ap->a_cred &&
- ap->a_cred->cr_uid != 0)
- node->nn_inode.i_mode &= ~(ISUID | ISGID);
-
- if (file_size < uio->uio_offset + uio->uio_resid) {
- node->nn_inode.i_size = uio->uio_offset +
- uio->uio_resid;
- node->nn_flags |= IN_CHANGE | IN_UPDATE;
- vnode_pager_setsize(vp, uio->uio_offset +
- uio->uio_resid);
- nandfs_itimes(vp);
- }
- }
-
- DPRINTF(WRITE, ("%s: return:%d\n", __func__, error));
-
- return (error);
-}
-
-static int
-nandfs_lookup(struct vop_cachedlookup_args *ap)
-{
- struct vnode *dvp, **vpp;
- struct componentname *cnp;
- struct ucred *cred;
- struct thread *td;
- struct nandfs_node *dir_node, *node;
- struct nandfsmount *nmp;
- uint64_t ino, off;
- const char *name;
- int namelen, nameiop, islastcn, mounted_ro;
- int error, found;
-
- DPRINTF(VNCALL, ("%s\n", __func__));
-
- dvp = ap->a_dvp;
- vpp = ap->a_vpp;
- *vpp = NULL;
-
- cnp = ap->a_cnp;
- cred = cnp->cn_cred;
- td = cnp->cn_thread;
-
- dir_node = VTON(dvp);
- nmp = dir_node->nn_nmp;
-
- /* Simplify/clarification flags */
- nameiop = cnp->cn_nameiop;
- islastcn = cnp->cn_flags & ISLASTCN;
- mounted_ro = dvp->v_mount->mnt_flag & MNT_RDONLY;
-
- /*
- * If requesting a modify on the last path element on a read-only
- * filingsystem, reject lookup;
- */
- if (islastcn && mounted_ro && (nameiop == DELETE || nameiop == RENAME))
- return (EROFS);
-
- if (dir_node->nn_inode.i_links_count == 0)
- return (ENOENT);
-
- /*
- * Obviously, the file is not (anymore) in the namecache, we have to
- * search for it. There are three basic cases: '.', '..' and others.
- *
- * Following the guidelines of VOP_LOOKUP manpage and tmpfs.
- */
- error = 0;
- if ((cnp->cn_namelen == 1) && (cnp->cn_nameptr[0] == '.')) {
- DPRINTF(LOOKUP, ("\tlookup '.'\n"));
- /* Special case 1 '.' */
- VREF(dvp);
- *vpp = dvp;
- /* Done */
- } else if (cnp->cn_flags & ISDOTDOT) {
- /* Special case 2 '..' */
- DPRINTF(LOOKUP, ("\tlookup '..'\n"));
-
- /* Get our node */
- name = "..";
- namelen = 2;
- error = nandfs_lookup_name_in_dir(dvp, name, namelen, &ino,
- &found, &off);
- if (error)
- goto out;
- if (!found)
- error = ENOENT;
-
- /* First unlock parent */
- VOP_UNLOCK(dvp, 0);
-
- if (error == 0) {
- DPRINTF(LOOKUP, ("\tfound '..'\n"));
- /* Try to create/reuse the node */
- error = nandfs_get_node(nmp, ino, &node);
-
- if (!error) {
- DPRINTF(LOOKUP,
- ("\tnode retrieved/created OK\n"));
- *vpp = NTOV(node);
- }
- }
-
- /* Try to relock parent */
- vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
- } else {
- DPRINTF(LOOKUP, ("\tlookup file\n"));
- /* All other files */
- /* Look up filename in the directory returning its inode */
- name = cnp->cn_nameptr;
- namelen = cnp->cn_namelen;
- error = nandfs_lookup_name_in_dir(dvp, name, namelen,
- &ino, &found, &off);
- if (error)
- goto out;
- if (!found) {
- DPRINTF(LOOKUP, ("\tNOT found\n"));
- /*
- * UGH, didn't find name. If we're creating or
- * renaming on the last name this is OK and we ought
- * to return EJUSTRETURN if its allowed to be created.
- */
- error = ENOENT;
- if ((nameiop == CREATE || nameiop == RENAME) &&
- islastcn) {
- error = VOP_ACCESS(dvp, VWRITE, cred, td);
- if (!error) {
- /* keep the component name */
- cnp->cn_flags |= SAVENAME;
- error = EJUSTRETURN;
- }
- }
- /* Done */
- } else {
- if (ino == NANDFS_WHT_INO)
- cnp->cn_flags |= ISWHITEOUT;
-
- if ((cnp->cn_flags & ISWHITEOUT) &&
- (nameiop == LOOKUP))
- return (ENOENT);
-
- if ((nameiop == DELETE) && islastcn) {
- if ((cnp->cn_flags & ISWHITEOUT) &&
- (cnp->cn_flags & DOWHITEOUT)) {
- cnp->cn_flags |= SAVENAME;
- dir_node->nn_diroff = off;
- return (EJUSTRETURN);
- }
-
- error = VOP_ACCESS(dvp, VWRITE, cred,
- cnp->cn_thread);
- if (error)
- return (error);
-
- /* Try to create/reuse the node */
- error = nandfs_get_node(nmp, ino, &node);
- if (!error) {
- *vpp = NTOV(node);
- node->nn_diroff = off;
- }
-
- if ((dir_node->nn_inode.i_mode & ISVTX) &&
- cred->cr_uid != 0 &&
- cred->cr_uid != dir_node->nn_inode.i_uid &&
- node->nn_inode.i_uid != cred->cr_uid) {
- vput(*vpp);
- *vpp = NULL;
- return (EPERM);
- }
- } else if ((nameiop == RENAME) && islastcn) {
- error = VOP_ACCESS(dvp, VWRITE, cred,
- cnp->cn_thread);
- if (error)
- return (error);
-
- /* Try to create/reuse the node */
- error = nandfs_get_node(nmp, ino, &node);
- if (!error) {
- *vpp = NTOV(node);
- node->nn_diroff = off;
- }
- } else {
- /* Try to create/reuse the node */
- error = nandfs_get_node(nmp, ino, &node);
- if (!error) {
- *vpp = NTOV(node);
- node->nn_diroff = off;
- }
- }
- }
- }
-
-out:
- /*
- * Store result in the cache if requested. If we are creating a file,
- * the file might not be found and thus putting it into the namecache
- * might be seen as negative caching.
- */
- if ((cnp->cn_flags & MAKEENTRY) != 0)
- cache_enter(dvp, *vpp, cnp);
-
- return (error);
-
-}
-
-static int
-nandfs_getattr(struct vop_getattr_args *ap)
-{
- struct vnode *vp = ap->a_vp;
- struct vattr *vap = ap->a_vap;
- struct nandfs_node *node = VTON(vp);
- struct nandfs_inode *inode = &node->nn_inode;
-
- DPRINTF(VNCALL, ("%s: vp: %p\n", __func__, vp));
- nandfs_itimes(vp);
-
- /* Basic info */
- VATTR_NULL(vap);
- vap->va_atime.tv_sec = inode->i_mtime;
- vap->va_atime.tv_nsec = inode->i_mtime_nsec;
- vap->va_mtime.tv_sec = inode->i_mtime;
- vap->va_mtime.tv_nsec = inode->i_mtime_nsec;
- vap->va_ctime.tv_sec = inode->i_ctime;
- vap->va_ctime.tv_nsec = inode->i_ctime_nsec;
- vap->va_type = IFTOVT(inode->i_mode);
- vap->va_mode = inode->i_mode & ~S_IFMT;
- vap->va_nlink = inode->i_links_count;
- vap->va_uid = inode->i_uid;
- vap->va_gid = inode->i_gid;
- vap->va_rdev = inode->i_special;
- vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
- vap->va_fileid = node->nn_ino;
- vap->va_size = inode->i_size;
- vap->va_blocksize = node->nn_nandfsdev->nd_blocksize;
- vap->va_gen = 0;
- vap->va_flags = inode->i_flags;
- vap->va_bytes = inode->i_blocks * vap->va_blocksize;
- vap->va_filerev = 0;
- vap->va_vaflags = 0;
-
- return (0);
-}
-
-static int
-nandfs_vtruncbuf(struct vnode *vp, uint64_t nblks)
-{
- struct nandfs_device *nffsdev;
- struct bufobj *bo;
- struct buf *bp, *nbp;
-
- bo = &vp->v_bufobj;
- nffsdev = VTON(vp)->nn_nandfsdev;
-
- ASSERT_VOP_LOCKED(vp, "nandfs_truncate");
-restart:
- BO_LOCK(bo);
-restart_locked:
- TAILQ_FOREACH_SAFE(bp, &bo->bo_clean.bv_hd, b_bobufs, nbp) {
- if (bp->b_lblkno < nblks)
- continue;
- if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT, NULL))
- goto restart_locked;
-
- bremfree(bp);
- bp->b_flags |= (B_INVAL | B_RELBUF);
- bp->b_flags &= ~(B_ASYNC | B_MANAGED);
- BO_UNLOCK(bo);
- brelse(bp);
- BO_LOCK(bo);
- }
-
- TAILQ_FOREACH_SAFE(bp, &bo->bo_dirty.bv_hd, b_bobufs, nbp) {
- if (bp->b_lblkno < nblks)
- continue;
- if (BUF_LOCK(bp,
- LK_EXCLUSIVE | LK_SLEEPFAIL | LK_INTERLOCK,
- BO_LOCKPTR(bo)) == ENOLCK)
- goto restart;
- bp->b_flags |= (B_INVAL | B_RELBUF);
- bp->b_flags &= ~(B_ASYNC | B_MANAGED);
- brelse(bp);
- nandfs_dirty_bufs_decrement(nffsdev);
- BO_LOCK(bo);
- }
-
- BO_UNLOCK(bo);
-
- return (0);
-}
-
-static int
-nandfs_truncate(struct vnode *vp, uint64_t newsize)
-{
- struct nandfs_device *nffsdev;
- struct nandfs_node *node;
- struct nandfs_inode *inode;
- struct buf *bp = NULL;
- uint64_t oblks, nblks, vblk, size, rest;
- int error;
-
- node = VTON(vp);
- nffsdev = node->nn_nandfsdev;
- inode = &node->nn_inode;
-
- /* Calculate end of file */
- size = inode->i_size;
-
- if (newsize == size) {
- node->nn_flags |= IN_CHANGE | IN_UPDATE;
- nandfs_itimes(vp);
- return (0);
- }
-
- if (newsize > size) {
- inode->i_size = newsize;
- vnode_pager_setsize(vp, newsize);
- node->nn_flags |= IN_CHANGE | IN_UPDATE;
- nandfs_itimes(vp);
- return (0);
- }
-
- nblks = howmany(newsize, nffsdev->nd_blocksize);
- oblks = howmany(size, nffsdev->nd_blocksize);
- rest = newsize % nffsdev->nd_blocksize;
-
- if (rest) {
- error = nandfs_bmap_lookup(node, nblks - 1, &vblk);
- if (error)
- return (error);
-
- if (vblk != 0)
- error = nandfs_bread(node, nblks - 1, NOCRED, 0, &bp);
- else
- error = nandfs_bcreate(node, nblks - 1, NOCRED, 0, &bp);
-
- if (error) {
- if (bp)
- brelse(bp);
- return (error);
- }
-
- bzero((char *)bp->b_data + rest,
- (u_int)(nffsdev->nd_blocksize - rest));
- error = nandfs_dirty_buf(bp, 0);
- if (error)
- return (error);
- }
-
- DPRINTF(VNCALL, ("%s: vp %p oblks %jx nblks %jx\n", __func__, vp, oblks,
- nblks));
-
- error = nandfs_bmap_truncate_mapping(node, oblks - 1, nblks - 1);
- if (error) {
- if (bp)
- nandfs_undirty_buf(bp);
- return (error);
- }
-
- error = nandfs_vtruncbuf(vp, nblks);
- if (error) {
- if (bp)
- nandfs_undirty_buf(bp);
- return (error);
- }
-
- inode->i_size = newsize;
- vnode_pager_setsize(vp, newsize);
- node->nn_flags |= IN_CHANGE | IN_UPDATE;
- nandfs_itimes(vp);
-
- return (error);
-}
-
-static void
-nandfs_itimes_locked(struct vnode *vp)
-{
- struct nandfs_node *node;
- struct nandfs_inode *inode;
- struct timespec ts;
-
- ASSERT_VI_LOCKED(vp, __func__);
-
- node = VTON(vp);
- inode = &node->nn_inode;
-
- if ((node->nn_flags & (IN_ACCESS | IN_CHANGE | IN_UPDATE)) == 0)
- return;
-
- if (((vp->v_mount->mnt_kern_flag &
- (MNTK_SUSPENDED | MNTK_SUSPEND)) == 0) ||
- (node->nn_flags & (IN_CHANGE | IN_UPDATE)))
- node->nn_flags |= IN_MODIFIED;
-
- vfs_timestamp(&ts);
- if (node->nn_flags & IN_UPDATE) {
- inode->i_mtime = ts.tv_sec;
- inode->i_mtime_nsec = ts.tv_nsec;
- }
- if (node->nn_flags & IN_CHANGE) {
- inode->i_ctime = ts.tv_sec;
- inode->i_ctime_nsec = ts.tv_nsec;
- }
-
- node->nn_flags &= ~(IN_ACCESS | IN_CHANGE | IN_UPDATE);
-}
-
-void
-nandfs_itimes(struct vnode *vp)
-{
-
- VI_LOCK(vp);
- nandfs_itimes_locked(vp);
- VI_UNLOCK(vp);
-}
-
-static int
-nandfs_chmod(struct vnode *vp, int mode, struct ucred *cred, struct thread *td)
-{
- struct nandfs_node *node = VTON(vp);
- struct nandfs_inode *inode = &node->nn_inode;
- uint16_t nmode;
- int error = 0;
-
- DPRINTF(VNCALL, ("%s: vp %p, mode %x, cred %p, td %p\n", __func__, vp,
- mode, cred, td));
- /*
- * To modify the permissions on a file, must possess VADMIN
- * for that file.
- */
- if ((error = VOP_ACCESS(vp, VADMIN, cred, td)))
- return (error);
-
- /*
- * Privileged processes may set the sticky bit on non-directories,
- * as well as set the setgid bit on a file with a group that the
- * process is not a member of. Both of these are allowed in
- * jail(8).
- */
- if (vp->v_type != VDIR && (mode & S_ISTXT)) {
- if (priv_check_cred(cred, PRIV_VFS_STICKYFILE))
- return (EFTYPE);
- }
- if (!groupmember(inode->i_gid, cred) && (mode & ISGID)) {
- error = priv_check_cred(cred, PRIV_VFS_SETGID);
- if (error)
- return (error);
- }
-
- /*
- * Deny setting setuid if we are not the file owner.
- */
- if ((mode & ISUID) && inode->i_uid != cred->cr_uid) {
- error = priv_check_cred(cred, PRIV_VFS_ADMIN);
- if (error)
- return (error);
- }
-
- nmode = inode->i_mode;
- nmode &= ~ALLPERMS;
- nmode |= (mode & ALLPERMS);
- inode->i_mode = nmode;
- node->nn_flags |= IN_CHANGE;
-
- DPRINTF(VNCALL, ("%s: to mode %x\n", __func__, nmode));
-
- return (error);
-}
-
-static int
-nandfs_chown(struct vnode *vp, uid_t uid, gid_t gid, struct ucred *cred,
- struct thread *td)
-{
- struct nandfs_node *node = VTON(vp);
- struct nandfs_inode *inode = &node->nn_inode;
- uid_t ouid;
- gid_t ogid;
- int error = 0;
-
- if (uid == (uid_t)VNOVAL)
- uid = inode->i_uid;
- if (gid == (gid_t)VNOVAL)
- gid = inode->i_gid;
- /*
- * To modify the ownership of a file, must possess VADMIN for that
- * file.
- */
- if ((error = VOP_ACCESSX(vp, VWRITE_OWNER, cred, td)))
- return (error);
- /*
- * To change the owner of a file, or change the group of a file to a
- * group of which we are not a member, the caller must have
- * privilege.
- */
- if (((uid != inode->i_uid && uid != cred->cr_uid) ||
- (gid != inode->i_gid && !groupmember(gid, cred))) &&
- (error = priv_check_cred(cred, PRIV_VFS_CHOWN)))
- return (error);
- ogid = inode->i_gid;
- ouid = inode->i_uid;
-
- inode->i_gid = gid;
- inode->i_uid = uid;
-
- node->nn_flags |= IN_CHANGE;
- if ((inode->i_mode & (ISUID | ISGID)) &&
- (ouid != uid || ogid != gid)) {
- if (priv_check_cred(cred, PRIV_VFS_RETAINSUGID))
- inode->i_mode &= ~(ISUID | ISGID);
- }
- DPRINTF(VNCALL, ("%s: vp %p, cred %p, td %p - ret OK\n", __func__, vp,
- cred, td));
- return (0);
-}
-
-static int
-nandfs_setattr(struct vop_setattr_args *ap)
-{
- struct vnode *vp = ap->a_vp;
- struct nandfs_node *node = VTON(vp);
- struct nandfs_inode *inode = &node->nn_inode;
- struct vattr *vap = ap->a_vap;
- struct ucred *cred = ap->a_cred;
- struct thread *td = curthread;
- uint32_t flags;
- int error = 0;
-
- if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) ||
- (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) ||
- (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) ||
- (vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) {
- DPRINTF(VNCALL, ("%s: unsettable attribute\n", __func__));
- return (EINVAL);
- }
-
- if (vap->va_flags != VNOVAL) {
- DPRINTF(VNCALL, ("%s: vp:%p td:%p flags:%lx\n", __func__, vp,
- td, vap->va_flags));
-
- if (vp->v_mount->mnt_flag & MNT_RDONLY)
- return (EROFS);
- /*
- * Callers may only modify the file flags on objects they
- * have VADMIN rights for.
- */
- if ((error = VOP_ACCESS(vp, VADMIN, cred, td)))
- return (error);
- /*
- * Unprivileged processes are not permitted to unset system
- * flags, or modify flags if any system flags are set.
- * Privileged non-jail processes may not modify system flags
- * if securelevel > 0 and any existing system flags are set.
- * Privileged jail processes behave like privileged non-jail
- * processes if the PR_ALLOW_CHFLAGS permission bit is set;
- * otherwise, they behave like unprivileged processes.
- */
-
- flags = inode->i_flags;
- if (!priv_check_cred(cred, PRIV_VFS_SYSFLAGS)) {
- if (flags & (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND)) {
- error = securelevel_gt(cred, 0);
- if (error)
- return (error);
- }
- /* Snapshot flag cannot be set or cleared */
- if (((vap->va_flags & SF_SNAPSHOT) != 0 &&
- (flags & SF_SNAPSHOT) == 0) ||
- ((vap->va_flags & SF_SNAPSHOT) == 0 &&
- (flags & SF_SNAPSHOT) != 0))
- return (EPERM);
-
- inode->i_flags = vap->va_flags;
- } else {
- if (flags & (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND) ||
- (vap->va_flags & UF_SETTABLE) != vap->va_flags)
- return (EPERM);
-
- flags &= SF_SETTABLE;
- flags |= (vap->va_flags & UF_SETTABLE);
- inode->i_flags = flags;
- }
- node->nn_flags |= IN_CHANGE;
- if (vap->va_flags & (IMMUTABLE | APPEND))
- return (0);
- }
- if (inode->i_flags & (IMMUTABLE | APPEND))
- return (EPERM);
-
- if (vap->va_size != (u_quad_t)VNOVAL) {
- DPRINTF(VNCALL, ("%s: vp:%p td:%p size:%jx\n", __func__, vp, td,
- (uintmax_t)vap->va_size));
-
- switch (vp->v_type) {
- case VDIR:
- return (EISDIR);
- case VLNK:
- case VREG:
- if (vp->v_mount->mnt_flag & MNT_RDONLY)
- return (EROFS);
- if ((inode->i_flags & SF_SNAPSHOT) != 0)
- return (EPERM);
- break;
- default:
- return (0);
- }
-
- if (vap->va_size > node->nn_nandfsdev->nd_maxfilesize)
- return (EFBIG);
-
- KASSERT((vp->v_type == VREG), ("Set size %d", vp->v_type));
- nandfs_truncate(vp, vap->va_size);
- node->nn_flags |= IN_CHANGE;
-
- return (0);
- }
-
- if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL) {
- if (vp->v_mount->mnt_flag & MNT_RDONLY)
- return (EROFS);
- DPRINTF(VNCALL, ("%s: vp:%p td:%p uid/gid %x/%x\n", __func__,
- vp, td, vap->va_uid, vap->va_gid));
- error = nandfs_chown(vp, vap->va_uid, vap->va_gid, cred, td);
- if (error)
- return (error);
- }
-
- if (vap->va_mode != (mode_t)VNOVAL) {
- if (vp->v_mount->mnt_flag & MNT_RDONLY)
- return (EROFS);
- DPRINTF(VNCALL, ("%s: vp:%p td:%p mode %x\n", __func__, vp, td,
- vap->va_mode));
-
- error = nandfs_chmod(vp, (int)vap->va_mode, cred, td);
- if (error)
- return (error);
- }
- if (vap->va_atime.tv_sec != VNOVAL ||
- vap->va_mtime.tv_sec != VNOVAL ||
- vap->va_birthtime.tv_sec != VNOVAL) {
- DPRINTF(VNCALL, ("%s: vp:%p td:%p time a/m/b %jx/%jx/%jx\n",
- __func__, vp, td, (uintmax_t)vap->va_atime.tv_sec,
- (uintmax_t)vap->va_mtime.tv_sec,
- (uintmax_t)vap->va_birthtime.tv_sec));
-
- if (vap->va_atime.tv_sec != VNOVAL)
- node->nn_flags |= IN_ACCESS;
- if (vap->va_mtime.tv_sec != VNOVAL)
- node->nn_flags |= IN_CHANGE | IN_UPDATE;
- if (vap->va_birthtime.tv_sec != VNOVAL)
- node->nn_flags |= IN_MODIFIED;
- nandfs_itimes(vp);
- return (0);
- }
-
- return (0);
-}
-
-static int
-nandfs_open(struct vop_open_args *ap)
-{
- struct nandfs_node *node = VTON(ap->a_vp);
- uint64_t filesize;
-
- DPRINTF(VNCALL, ("nandfs_open called ap->a_mode %x\n", ap->a_mode));
-
- if (ap->a_vp->v_type == VCHR || ap->a_vp->v_type == VBLK)
- return (EOPNOTSUPP);
-
- if ((node->nn_inode.i_flags & APPEND) &&
- (ap->a_mode & (FWRITE | O_APPEND)) == FWRITE)
- return (EPERM);
-
- filesize = node->nn_inode.i_size;
- vnode_create_vobject(ap->a_vp, filesize, ap->a_td);
-
- return (0);
-}
-
-static int
-nandfs_close(struct vop_close_args *ap)
-{
- struct vnode *vp = ap->a_vp;
- struct nandfs_node *node = VTON(vp);
-
- DPRINTF(VNCALL, ("%s: vp %p node %p\n", __func__, vp, node));
-
- mtx_lock(&vp->v_interlock);
- if (vp->v_usecount > 1)
- nandfs_itimes_locked(vp);
- mtx_unlock(&vp->v_interlock);
-
- return (0);
-}
-
-static int
-nandfs_check_possible(struct vnode *vp, struct vattr *vap, mode_t mode)
-{
-
- /* Check if we are allowed to write */
- switch (vap->va_type) {
- case VDIR:
- case VLNK:
- case VREG:
- /*
- * Normal nodes: check if we're on a read-only mounted
- * filingsystem and bomb out if we're trying to write.
- */
- if ((mode & VMODIFY_PERMS) && (vp->v_mount->mnt_flag & MNT_RDONLY))
- return (EROFS);
- break;
- case VBLK:
- case VCHR:
- case VSOCK:
- case VFIFO:
- /*
- * Special nodes: even on read-only mounted filingsystems
- * these are allowed to be written to if permissions allow.
- */
- break;
- default:
- /* No idea what this is */
- return (EINVAL);
- }
-
- /* No one may write immutable files */
- if ((mode & VWRITE) && (VTON(vp)->nn_inode.i_flags & IMMUTABLE))
- return (EPERM);
-
- return (0);
-}
-
-static int
-nandfs_check_permitted(struct vnode *vp, struct vattr *vap, mode_t mode,
- struct ucred *cred)
-{
-
- return (vaccess(vp->v_type, vap->va_mode, vap->va_uid, vap->va_gid, mode,
- cred, NULL));
-}
-
-static int
-nandfs_advlock(struct vop_advlock_args *ap)
-{
- struct nandfs_node *nvp;
- quad_t size;
-
- nvp = VTON(ap->a_vp);
- size = nvp->nn_inode.i_size;
- return (lf_advlock(ap, &(nvp->nn_lockf), size));
-}
-
-static int
-nandfs_access(struct vop_access_args *ap)
-{
- struct vnode *vp = ap->a_vp;
- accmode_t accmode = ap->a_accmode;
- struct ucred *cred = ap->a_cred;
- struct vattr vap;
- int error;
-
- DPRINTF(VNCALL, ("%s: vp:%p mode: %x\n", __func__, vp, accmode));
-
- error = VOP_GETATTR(vp, &vap, NULL);
- if (error)
- return (error);
-
- error = nandfs_check_possible(vp, &vap, accmode);
- if (error)
- return (error);
-
- error = nandfs_check_permitted(vp, &vap, accmode, cred);
-
- return (error);
-}
-
-static int
-nandfs_print(struct vop_print_args *ap)
-{
- struct vnode *vp = ap->a_vp;
- struct nandfs_node *nvp = VTON(vp);
-
- printf("\tvp=%p, nandfs_node=%p\n", vp, nvp);
- printf("nandfs inode %#jx\n", (uintmax_t)nvp->nn_ino);
- printf("flags = 0x%b\n", (u_int)nvp->nn_flags, PRINT_NODE_FLAGS);
-
- return (0);
-}
-
-static void
-nandfs_read_filebuf(struct nandfs_node *node, struct buf *bp)
-{
- struct nandfs_device *nandfsdev = node->nn_nandfsdev;
- struct buf *nbp;
- nandfs_daddr_t vblk, pblk;
- nandfs_lbn_t from;
- uint32_t blocksize;
- int error = 0;
- int blk2dev = nandfsdev->nd_blocksize / DEV_BSIZE;
-
- /*
- * Translate all the block sectors into a series of buffers to read
- * asynchronously from the nandfs device. Note that this lookup may
- * induce readin's too.
- */
-
- blocksize = nandfsdev->nd_blocksize;
- if (bp->b_bcount / blocksize != 1)
- panic("invalid b_count in bp %p\n", bp);
-
- from = bp->b_blkno;
-
- DPRINTF(READ, ("\tread in from inode %#jx blkno %#jx"
- " count %#lx\n", (uintmax_t)node->nn_ino, from,
- bp->b_bcount));
-
- /* Get virtual block numbers for the vnode's buffer span */
- error = nandfs_bmap_lookup(node, from, &vblk);
- if (error) {
- bp->b_error = EINVAL;
- bp->b_ioflags |= BIO_ERROR;
- bufdone(bp);
- return;
- }
-
- /* Translate virtual block numbers to physical block numbers */
- error = nandfs_vtop(node, vblk, &pblk);
- if (error) {
- bp->b_error = EINVAL;
- bp->b_ioflags |= BIO_ERROR;
- bufdone(bp);
- return;
- }
-
- /* Issue translated blocks */
- bp->b_resid = bp->b_bcount;
-
- /* Note virtual block 0 marks not mapped */
- if (vblk == 0) {
- vfs_bio_clrbuf(bp);
- bufdone(bp);
- return;
- }
-
- nbp = bp;
- nbp->b_blkno = pblk * blk2dev;
- bp->b_iooffset = dbtob(nbp->b_blkno);
- MPASS(bp->b_iooffset >= 0);
- BO_STRATEGY(&nandfsdev->nd_devvp->v_bufobj, nbp);
- nandfs_vblk_set(bp, vblk);
- DPRINTF(READ, ("read_filebuf : ino %#jx blk %#jx -> "
- "%#jx -> %#jx [bp %p]\n", (uintmax_t)node->nn_ino,
- (uintmax_t)(from), (uintmax_t)vblk,
- (uintmax_t)pblk, nbp));
-}
-
-static void
-nandfs_write_filebuf(struct nandfs_node *node, struct buf *bp)
-{
- struct nandfs_device *nandfsdev = node->nn_nandfsdev;
-
- bp->b_iooffset = dbtob(bp->b_blkno);
- MPASS(bp->b_iooffset >= 0);
- BO_STRATEGY(&nandfsdev->nd_devvp->v_bufobj, bp);
-}
-
-static int
-nandfs_strategy(struct vop_strategy_args *ap)
-{
- struct vnode *vp = ap->a_vp;
- struct buf *bp = ap->a_bp;
- struct nandfs_node *node = VTON(vp);
-
-
- /* check if we ought to be here */
- KASSERT((vp->v_type != VBLK && vp->v_type != VCHR),
- ("nandfs_strategy on type %d", vp->v_type));
-
- /* Translate if needed and pass on */
- if (bp->b_iocmd == BIO_READ) {
- nandfs_read_filebuf(node, bp);
- return (0);
- }
-
- /* Send to segment collector */
- nandfs_write_filebuf(node, bp);
- return (0);
-}
-
-static int
-nandfs_readdir(struct vop_readdir_args *ap)
-{
- struct uio *uio = ap->a_uio;
- struct vnode *vp = ap->a_vp;
- struct nandfs_node *node = VTON(vp);
- struct nandfs_dir_entry *ndirent;
- struct dirent dirent;
- struct buf *bp;
- uint64_t file_size, diroffset, transoffset, blkoff;
- uint64_t blocknr;
- uint32_t blocksize = node->nn_nandfsdev->nd_blocksize;
- uint8_t *pos, name_len;
- int error;
-
- DPRINTF(READDIR, ("nandfs_readdir called\n"));
-
- if (vp->v_type != VDIR)
- return (ENOTDIR);
-
- file_size = node->nn_inode.i_size;
- DPRINTF(READDIR, ("nandfs_readdir filesize %jd resid %zd\n",
- (uintmax_t)file_size, uio->uio_resid ));
-
- /* We are called just as long as we keep on pushing data in */
- error = 0;
- if ((uio->uio_offset < file_size) &&
- (uio->uio_resid >= sizeof(struct dirent))) {
- diroffset = uio->uio_offset;
- transoffset = diroffset;
-
- blocknr = diroffset / blocksize;
- blkoff = diroffset % blocksize;
- error = nandfs_bread(node, blocknr, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (EIO);
- }
- while (diroffset < file_size) {
- DPRINTF(READDIR, ("readdir : offset = %"PRIu64"\n",
- diroffset));
- if (blkoff >= blocksize) {
- blkoff = 0; blocknr++;
- brelse(bp);
- error = nandfs_bread(node, blocknr, NOCRED, 0,
- &bp);
- if (error) {
- brelse(bp);
- return (EIO);
- }
- }
-
- /* Read in one dirent */
- pos = (uint8_t *)bp->b_data + blkoff;
- ndirent = (struct nandfs_dir_entry *)pos;
-
- name_len = ndirent->name_len;
- memset(&dirent, 0, sizeof(dirent));
- dirent.d_fileno = ndirent->inode;
- if (dirent.d_fileno) {
- dirent.d_type = ndirent->file_type;
- dirent.d_namlen = name_len;
- strncpy(dirent.d_name, ndirent->name, name_len);
- dirent.d_reclen = GENERIC_DIRSIZ(&dirent);
- /* NOTE: d_off is the offset of the *next* entry. */
- dirent.d_off = diroffset + ndirent->rec_len;
- dirent_terminate(&dirent);
- DPRINTF(READDIR, ("copying `%*.*s`\n", name_len,
- name_len, dirent.d_name));
- }
-
- /*
- * If there isn't enough space in the uio to return a
- * whole dirent, break off read
- */
- if (uio->uio_resid < GENERIC_DIRSIZ(&dirent))
- break;
-
- /* Transfer */
- if (dirent.d_fileno)
- uiomove(&dirent, dirent.d_reclen, uio);
-
- /* Advance */
- diroffset += ndirent->rec_len;
- blkoff += ndirent->rec_len;
-
- /* Remember the last entry we transferred */
- transoffset = diroffset;
- }
- brelse(bp);
-
- /* Pass on last transferred offset */
- uio->uio_offset = transoffset;
- }
-
- if (ap->a_eofflag)
- *ap->a_eofflag = (uio->uio_offset >= file_size);
-
- return (error);
-}
-
-static int
-nandfs_dirempty(struct vnode *dvp, uint64_t parentino, struct ucred *cred)
-{
- struct nandfs_node *dnode = VTON(dvp);
- struct nandfs_dir_entry *dirent;
- uint64_t file_size = dnode->nn_inode.i_size;
- uint64_t blockcount = dnode->nn_inode.i_blocks;
- uint64_t blocknr;
- uint32_t blocksize = dnode->nn_nandfsdev->nd_blocksize;
- uint32_t limit;
- uint32_t off;
- uint8_t *pos;
- struct buf *bp;
- int error;
-
- DPRINTF(LOOKUP, ("%s: dvp %p parentino %#jx cred %p\n", __func__, dvp,
- (uintmax_t)parentino, cred));
-
- KASSERT((file_size != 0), ("nandfs_dirempty for NULL dir %p", dvp));
-
- blocknr = 0;
- while (blocknr < blockcount) {
- error = nandfs_bread(dnode, blocknr, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (0);
- }
-
- pos = (uint8_t *)bp->b_data;
- off = 0;
-
- if (blocknr == (blockcount - 1))
- limit = file_size % blocksize;
- else
- limit = blocksize;
-
- while (off < limit) {
- dirent = (struct nandfs_dir_entry *)(pos + off);
- off += dirent->rec_len;
-
- if (dirent->inode == 0)
- continue;
-
- switch (dirent->name_len) {
- case 0:
- break;
- case 1:
- if (dirent->name[0] != '.')
- goto notempty;
-
- KASSERT(dirent->inode == dnode->nn_ino,
- (".'s inode does not match dir"));
- break;
- case 2:
- if (dirent->name[0] != '.' &&
- dirent->name[1] != '.')
- goto notempty;
-
- KASSERT(dirent->inode == parentino,
- ("..'s inode does not match parent"));
- break;
- default:
- goto notempty;
- }
- }
-
- brelse(bp);
- blocknr++;
- }
-
- return (1);
-notempty:
- brelse(bp);
- return (0);
-}
-
-static int
-nandfs_link(struct vop_link_args *ap)
-{
- struct vnode *tdvp = ap->a_tdvp;
- struct vnode *vp = ap->a_vp;
- struct componentname *cnp = ap->a_cnp;
- struct nandfs_node *node = VTON(vp);
- struct nandfs_inode *inode = &node->nn_inode;
- int error;
-
- if (inode->i_links_count >= NANDFS_LINK_MAX)
- return (EMLINK);
-
- if (inode->i_flags & (IMMUTABLE | APPEND))
- return (EPERM);
-
- /* Update link count */
- inode->i_links_count++;
-
- /* Add dir entry */
- error = nandfs_add_dirent(tdvp, node->nn_ino, cnp->cn_nameptr,
- cnp->cn_namelen, IFTODT(inode->i_mode));
- if (error) {
- inode->i_links_count--;
- }
-
- node->nn_flags |= IN_CHANGE;
- nandfs_itimes(vp);
- DPRINTF(VNCALL, ("%s: tdvp %p vp %p cnp %p\n",
- __func__, tdvp, vp, cnp));
-
- return (0);
-}
-
-static int
-nandfs_create(struct vop_create_args *ap)
-{
- struct vnode *dvp = ap->a_dvp;
- struct vnode **vpp = ap->a_vpp;
- struct componentname *cnp = ap->a_cnp;
- uint16_t mode = MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode);
- struct nandfs_node *dir_node = VTON(dvp);
- struct nandfsmount *nmp = dir_node->nn_nmp;
- struct nandfs_node *node;
- int error;
-
- DPRINTF(VNCALL, ("%s: dvp %p\n", __func__, dvp));
-
- if (nandfs_fs_full(dir_node->nn_nandfsdev))
- return (ENOSPC);
-
- /* Create new vnode/inode */
- error = nandfs_node_create(nmp, &node, mode);
- if (error)
- return (error);
- node->nn_inode.i_gid = dir_node->nn_inode.i_gid;
- node->nn_inode.i_uid = cnp->cn_cred->cr_uid;
-
- /* Add new dir entry */
- error = nandfs_add_dirent(dvp, node->nn_ino, cnp->cn_nameptr,
- cnp->cn_namelen, IFTODT(mode));
- if (error) {
- if (nandfs_node_destroy(node)) {
- nandfs_error("%s: error destroying node %p\n",
- __func__, node);
- }
- return (error);
- }
- *vpp = NTOV(node);
- if ((cnp->cn_flags & MAKEENTRY) != 0)
- cache_enter(dvp, *vpp, cnp);
-
- DPRINTF(VNCALL, ("created file vp %p nandnode %p ino %jx\n", *vpp, node,
- (uintmax_t)node->nn_ino));
- return (0);
-}
-
-static int
-nandfs_remove(struct vop_remove_args *ap)
-{
- struct vnode *vp = ap->a_vp;
- struct vnode *dvp = ap->a_dvp;
- struct nandfs_node *node = VTON(vp);
- struct nandfs_node *dnode = VTON(dvp);
- struct componentname *cnp = ap->a_cnp;
-
- DPRINTF(VNCALL, ("%s: dvp %p vp %p nandnode %p ino %#jx link %d\n",
- __func__, dvp, vp, node, (uintmax_t)node->nn_ino,
- node->nn_inode.i_links_count));
-
- if (vp->v_type == VDIR)
- return (EISDIR);
-
- /* Files marked as immutable or append-only cannot be deleted. */
- if ((node->nn_inode.i_flags & (IMMUTABLE | APPEND | NOUNLINK)) ||
- (dnode->nn_inode.i_flags & APPEND))
- return (EPERM);
-
- nandfs_remove_dirent(dvp, node, cnp);
- node->nn_inode.i_links_count--;
- node->nn_flags |= IN_CHANGE;
-
- return (0);
-}
-
-/*
- * Check if source directory is in the path of the target directory.
- * Target is supplied locked, source is unlocked.
- * The target is always vput before returning.
- */
-static int
-nandfs_checkpath(struct nandfs_node *src, struct nandfs_node *dest,
- struct ucred *cred)
-{
- struct vnode *vp;
- int error, rootino;
- struct nandfs_dir_entry dirent;
-
- vp = NTOV(dest);
- if (src->nn_ino == dest->nn_ino) {
- error = EEXIST;
- goto out;
- }
- rootino = NANDFS_ROOT_INO;
- error = 0;
- if (dest->nn_ino == rootino)
- goto out;
-
- for (;;) {
- if (vp->v_type != VDIR) {
- error = ENOTDIR;
- break;
- }
-
- error = vn_rdwr(UIO_READ, vp, (caddr_t)&dirent,
- NANDFS_DIR_REC_LEN(2), (off_t)0, UIO_SYSSPACE,
- IO_NODELOCKED | IO_NOMACCHECK, cred, NOCRED,
- NULL, NULL);
- if (error != 0)
- break;
- if (dirent.name_len != 2 ||
- dirent.name[0] != '.' ||
- dirent.name[1] != '.') {
- error = ENOTDIR;
- break;
- }
- if (dirent.inode == src->nn_ino) {
- error = EINVAL;
- break;
- }
- if (dirent.inode == rootino)
- break;
- vput(vp);
- if ((error = VFS_VGET(vp->v_mount, dirent.inode,
- LK_EXCLUSIVE, &vp)) != 0) {
- vp = NULL;
- break;
- }
- }
-
-out:
- if (error == ENOTDIR)
- printf("checkpath: .. not a directory\n");
- if (vp != NULL)
- vput(vp);
- return (error);
-}
-
-static int
-nandfs_rename(struct vop_rename_args *ap)
-{
- struct vnode *tvp = ap->a_tvp;
- struct vnode *tdvp = ap->a_tdvp;
- struct vnode *fvp = ap->a_fvp;
- struct vnode *fdvp = ap->a_fdvp;
- struct componentname *tcnp = ap->a_tcnp;
- struct componentname *fcnp = ap->a_fcnp;
- int doingdirectory = 0, oldparent = 0, newparent = 0;
- int error = 0;
-
- struct nandfs_node *fdnode, *fnode, *fnode1;
- struct nandfs_node *tdnode = VTON(tdvp);
- struct nandfs_node *tnode;
-
- uint32_t tdflags, fflags, fdflags;
- uint16_t mode;
-
- DPRINTF(VNCALL, ("%s: fdvp:%p fvp:%p tdvp:%p tdp:%p\n", __func__, fdvp,
- fvp, tdvp, tvp));
-
- /*
- * Check for cross-device rename.
- */
- if ((fvp->v_mount != tdvp->v_mount) ||
- (tvp && (fvp->v_mount != tvp->v_mount))) {
- error = EXDEV;
-abortit:
- if (tdvp == tvp)
- vrele(tdvp);
- else
- vput(tdvp);
- if (tvp)
- vput(tvp);
- vrele(fdvp);
- vrele(fvp);
- return (error);
- }
-
- tdflags = tdnode->nn_inode.i_flags;
- if (tvp &&
- ((VTON(tvp)->nn_inode.i_flags & (NOUNLINK | IMMUTABLE | APPEND)) ||
- (tdflags & APPEND))) {
- error = EPERM;
- goto abortit;
- }
-
- /*
- * Renaming a file to itself has no effect. The upper layers should
- * not call us in that case. Temporarily just warn if they do.
- */
- if (fvp == tvp) {
- printf("nandfs_rename: fvp == tvp (can't happen)\n");
- error = 0;
- goto abortit;
- }
-
- if ((error = vn_lock(fvp, LK_EXCLUSIVE)) != 0)
- goto abortit;
-
- fdnode = VTON(fdvp);
- fnode = VTON(fvp);
-
- if (fnode->nn_inode.i_links_count >= NANDFS_LINK_MAX) {
- VOP_UNLOCK(fvp, 0);
- error = EMLINK;
- goto abortit;
- }
-
- fflags = fnode->nn_inode.i_flags;
- fdflags = fdnode->nn_inode.i_flags;
-
- if ((fflags & (NOUNLINK | IMMUTABLE | APPEND)) ||
- (fdflags & APPEND)) {
- VOP_UNLOCK(fvp, 0);
- error = EPERM;
- goto abortit;
- }
-
- mode = fnode->nn_inode.i_mode;
- if ((mode & S_IFMT) == S_IFDIR) {
- /*
- * Avoid ".", "..", and aliases of "." for obvious reasons.
- */
-
- if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') ||
- (fdvp == fvp) ||
- ((fcnp->cn_flags | tcnp->cn_flags) & ISDOTDOT) ||
- (fnode->nn_flags & IN_RENAME)) {
- VOP_UNLOCK(fvp, 0);
- error = EINVAL;
- goto abortit;
- }
- fnode->nn_flags |= IN_RENAME;
- doingdirectory = 1;
- DPRINTF(VNCALL, ("%s: doingdirectory dvp %p\n", __func__,
- tdvp));
- oldparent = fdnode->nn_ino;
- }
-
- vrele(fdvp);
-
- tnode = NULL;
- if (tvp)
- tnode = VTON(tvp);
-
- /*
- * Bump link count on fvp while we are moving stuff around. If we
- * crash before completing the work, the link count may be wrong
- * but correctable.
- */
- fnode->nn_inode.i_links_count++;
-
- /* Check for in path moving XXX */
- error = VOP_ACCESS(fvp, VWRITE, tcnp->cn_cred, tcnp->cn_thread);
- VOP_UNLOCK(fvp, 0);
- if (oldparent != tdnode->nn_ino)
- newparent = tdnode->nn_ino;
- if (doingdirectory && newparent) {
- if (error) /* write access check above */
- goto bad;
- if (tnode != NULL)
- vput(tvp);
-
- error = nandfs_checkpath(fnode, tdnode, tcnp->cn_cred);
- if (error)
- goto out;
-
- VREF(tdvp);
- error = relookup(tdvp, &tvp, tcnp);
- if (error)
- goto out;
- vrele(tdvp);
- tdnode = VTON(tdvp);
- tnode = NULL;
- if (tvp)
- tnode = VTON(tvp);
- }
-
- /*
- * If the target doesn't exist, link the target to the source and
- * unlink the source. Otherwise, rewrite the target directory to
- * reference the source and remove the original entry.
- */
-
- if (tvp == NULL) {
- /*
- * Account for ".." in new directory.
- */
- if (doingdirectory && fdvp != tdvp)
- tdnode->nn_inode.i_links_count++;
-
- DPRINTF(VNCALL, ("%s: new entry in dvp:%p\n", __func__, tdvp));
- /*
- * Add name in new directory.
- */
- error = nandfs_add_dirent(tdvp, fnode->nn_ino, tcnp->cn_nameptr,
- tcnp->cn_namelen, IFTODT(fnode->nn_inode.i_mode));
- if (error) {
- if (doingdirectory && fdvp != tdvp)
- tdnode->nn_inode.i_links_count--;
- goto bad;
- }
-
- vput(tdvp);
- } else {
- /*
- * If the parent directory is "sticky", then the user must
- * own the parent directory, or the destination of the rename,
- * otherwise the destination may not be changed (except by
- * root). This implements append-only directories.
- */
- if ((tdnode->nn_inode.i_mode & S_ISTXT) &&
- tcnp->cn_cred->cr_uid != 0 &&
- tcnp->cn_cred->cr_uid != tdnode->nn_inode.i_uid &&
- tnode->nn_inode.i_uid != tcnp->cn_cred->cr_uid) {
- error = EPERM;
- goto bad;
- }
- /*
- * Target must be empty if a directory and have no links
- * to it. Also, ensure source and target are compatible
- * (both directories, or both not directories).
- */
- mode = tnode->nn_inode.i_mode;
- if ((mode & S_IFMT) == S_IFDIR) {
- if (!nandfs_dirempty(tvp, tdnode->nn_ino,
- tcnp->cn_cred)) {
- error = ENOTEMPTY;
- goto bad;
- }
- if (!doingdirectory) {
- error = ENOTDIR;
- goto bad;
- }
- /*
- * Update name cache since directory is going away.
- */
- cache_purge(tdvp);
- } else if (doingdirectory) {
- error = EISDIR;
- goto bad;
- }
-
- DPRINTF(VNCALL, ("%s: update entry dvp:%p\n", __func__, tdvp));
- /*
- * Change name tcnp in tdvp to point at fvp.
- */
- error = nandfs_update_dirent(tdvp, fnode, tnode);
- if (error)
- goto bad;
-
- if (doingdirectory && !newparent)
- tdnode->nn_inode.i_links_count--;
-
- vput(tdvp);
-
- tnode->nn_inode.i_links_count--;
- vput(tvp);
- tnode = NULL;
- }
-
- /*
- * Unlink the source.
- */
- fcnp->cn_flags &= ~MODMASK;
- fcnp->cn_flags |= LOCKPARENT | LOCKLEAF;
- VREF(fdvp);
- error = relookup(fdvp, &fvp, fcnp);
- if (error == 0)
- vrele(fdvp);
- if (fvp != NULL) {
- fnode1 = VTON(fvp);
- fdnode = VTON(fdvp);
- } else {
- /*
- * From name has disappeared.
- */
- if (doingdirectory)
- panic("nandfs_rename: lost dir entry");
- vrele(ap->a_fvp);
- return (0);
- }
-
- DPRINTF(VNCALL, ("%s: unlink source fnode:%p\n", __func__, fnode));
-
- /*
- * Ensure that the directory entry still exists and has not
- * changed while the new name has been entered. If the source is
- * a file then the entry may have been unlinked or renamed. In
- * either case there is no further work to be done. If the source
- * is a directory then it cannot have been rmdir'ed; its link
- * count of three would cause a rmdir to fail with ENOTEMPTY.
- * The IN_RENAME flag ensures that it cannot be moved by another
- * rename.
- */
- if (fnode != fnode1) {
- if (doingdirectory)
- panic("nandfs: lost dir entry");
- } else {
- /*
- * If the source is a directory with a
- * new parent, the link count of the old
- * parent directory must be decremented
- * and ".." set to point to the new parent.
- */
- if (doingdirectory && newparent) {
- DPRINTF(VNCALL, ("%s: new parent %#jx -> %#jx\n",
- __func__, (uintmax_t) oldparent,
- (uintmax_t) newparent));
- error = nandfs_update_parent_dir(fvp, newparent);
- if (!error) {
- fdnode->nn_inode.i_links_count--;
- fdnode->nn_flags |= IN_CHANGE;
- }
- }
- error = nandfs_remove_dirent(fdvp, fnode, fcnp);
- if (!error) {
- fnode->nn_inode.i_links_count--;
- fnode->nn_flags |= IN_CHANGE;
- }
- fnode->nn_flags &= ~IN_RENAME;
- }
- if (fdnode)
- vput(fdvp);
- if (fnode)
- vput(fvp);
- vrele(ap->a_fvp);
- return (error);
-
-bad:
- DPRINTF(VNCALL, ("%s: error:%d\n", __func__, error));
- if (tnode)
- vput(NTOV(tnode));
- vput(NTOV(tdnode));
-out:
- if (doingdirectory)
- fnode->nn_flags &= ~IN_RENAME;
- if (vn_lock(fvp, LK_EXCLUSIVE) == 0) {
- fnode->nn_inode.i_links_count--;
- fnode->nn_flags |= IN_CHANGE;
- fnode->nn_flags &= ~IN_RENAME;
- vput(fvp);
- } else
- vrele(fvp);
- return (error);
-}
-
-static int
-nandfs_mkdir(struct vop_mkdir_args *ap)
-{
- struct vnode *dvp = ap->a_dvp;
- struct vnode **vpp = ap->a_vpp;
- struct componentname *cnp = ap->a_cnp;
- struct nandfs_node *dir_node = VTON(dvp);
- struct nandfs_inode *dir_inode = &dir_node->nn_inode;
- struct nandfs_node *node;
- struct nandfsmount *nmp = dir_node->nn_nmp;
- uint16_t mode = MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode);
- int error;
-
- DPRINTF(VNCALL, ("%s: dvp %p\n", __func__, dvp));
-
- if (nandfs_fs_full(dir_node->nn_nandfsdev))
- return (ENOSPC);
-
- if (dir_inode->i_links_count >= NANDFS_LINK_MAX)
- return (EMLINK);
-
- error = nandfs_node_create(nmp, &node, mode);
- if (error)
- return (error);
-
- node->nn_inode.i_gid = dir_node->nn_inode.i_gid;
- node->nn_inode.i_uid = cnp->cn_cred->cr_uid;
-
- *vpp = NTOV(node);
-
- error = nandfs_add_dirent(dvp, node->nn_ino, cnp->cn_nameptr,
- cnp->cn_namelen, IFTODT(mode));
- if (error) {
- vput(*vpp);
- return (error);
- }
-
- dir_node->nn_inode.i_links_count++;
- dir_node->nn_flags |= IN_CHANGE;
-
- error = nandfs_init_dir(NTOV(node), node->nn_ino, dir_node->nn_ino);
- if (error) {
- vput(NTOV(node));
- return (error);
- }
-
- DPRINTF(VNCALL, ("created dir vp %p nandnode %p ino %jx\n", *vpp, node,
- (uintmax_t)node->nn_ino));
- return (0);
-}
-
-static int
-nandfs_mknod(struct vop_mknod_args *ap)
-{
- struct vnode *dvp = ap->a_dvp;
- struct vnode **vpp = ap->a_vpp;
- struct vattr *vap = ap->a_vap;
- uint16_t mode = MAKEIMODE(vap->va_type, vap->va_mode);
- struct componentname *cnp = ap->a_cnp;
- struct nandfs_node *dir_node = VTON(dvp);
- struct nandfsmount *nmp = dir_node->nn_nmp;
- struct nandfs_node *node;
- int error;
-
- if (nandfs_fs_full(dir_node->nn_nandfsdev))
- return (ENOSPC);
-
- error = nandfs_node_create(nmp, &node, mode);
- if (error)
- return (error);
- node->nn_inode.i_gid = dir_node->nn_inode.i_gid;
- node->nn_inode.i_uid = cnp->cn_cred->cr_uid;
- if (vap->va_rdev != VNOVAL)
- node->nn_inode.i_special = vap->va_rdev;
-
- *vpp = NTOV(node);
-
- if (nandfs_add_dirent(dvp, node->nn_ino, cnp->cn_nameptr,
- cnp->cn_namelen, IFTODT(mode))) {
- vput(*vpp);
- return (ENOTDIR);
- }
-
- node->nn_flags |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
-
- return (0);
-}
-
-static int
-nandfs_symlink(struct vop_symlink_args *ap)
-{
- struct vnode **vpp = ap->a_vpp;
- struct vnode *dvp = ap->a_dvp;
- uint16_t mode = MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode);
- struct componentname *cnp = ap->a_cnp;
- struct nandfs_node *dir_node = VTON(dvp);
- struct nandfsmount *nmp = dir_node->nn_nmp;
- struct nandfs_node *node;
- int len, error;
-
- if (nandfs_fs_full(dir_node->nn_nandfsdev))
- return (ENOSPC);
-
- error = nandfs_node_create(nmp, &node, S_IFLNK | mode);
- if (error)
- return (error);
- node->nn_inode.i_gid = dir_node->nn_inode.i_gid;
- node->nn_inode.i_uid = cnp->cn_cred->cr_uid;
-
- *vpp = NTOV(node);
-
- if (nandfs_add_dirent(dvp, node->nn_ino, cnp->cn_nameptr,
- cnp->cn_namelen, IFTODT(mode))) {
- vput(*vpp);
- return (ENOTDIR);
- }
-
-
- len = strlen(ap->a_target);
- error = vn_rdwr(UIO_WRITE, *vpp, __DECONST(void *, ap->a_target),
- len, (off_t)0, UIO_SYSSPACE, IO_NODELOCKED | IO_NOMACCHECK,
- cnp->cn_cred, NOCRED, NULL, NULL);
- if (error)
- vput(*vpp);
-
- return (error);
-}
-
-static int
-nandfs_readlink(struct vop_readlink_args *ap)
-{
- struct vnode *vp = ap->a_vp;
-
- return (VOP_READ(vp, ap->a_uio, 0, ap->a_cred));
-}
-
-static int
-nandfs_rmdir(struct vop_rmdir_args *ap)
-{
- struct vnode *vp = ap->a_vp;
- struct vnode *dvp = ap->a_dvp;
- struct componentname *cnp = ap->a_cnp;
- struct nandfs_node *node, *dnode;
- uint32_t dflag, flag;
- int error = 0;
-
- node = VTON(vp);
- dnode = VTON(dvp);
-
- /* Files marked as immutable or append-only cannot be deleted. */
- if ((node->nn_inode.i_flags & (IMMUTABLE | APPEND | NOUNLINK)) ||
- (dnode->nn_inode.i_flags & APPEND))
- return (EPERM);
-
- DPRINTF(VNCALL, ("%s: dvp %p vp %p nandnode %p ino %#jx\n", __func__,
- dvp, vp, node, (uintmax_t)node->nn_ino));
-
- if (node->nn_inode.i_links_count < 2)
- return (EINVAL);
-
- if (!nandfs_dirempty(vp, dnode->nn_ino, cnp->cn_cred))
- return (ENOTEMPTY);
-
- /* Files marked as immutable or append-only cannot be deleted. */
- dflag = dnode->nn_inode.i_flags;
- flag = node->nn_inode.i_flags;
- if ((dflag & APPEND) ||
- (flag & (NOUNLINK | IMMUTABLE | APPEND))) {
- return (EPERM);
- }
-
- if (vp->v_mountedhere != 0)
- return (EINVAL);
-
- nandfs_remove_dirent(dvp, node, cnp);
- dnode->nn_inode.i_links_count -= 1;
- dnode->nn_flags |= IN_CHANGE;
-
- cache_purge(dvp);
-
- error = nandfs_truncate(vp, (uint64_t)0);
- if (error)
- return (error);
-
- node->nn_inode.i_links_count -= 2;
- node->nn_flags |= IN_CHANGE;
-
- cache_purge(vp);
-
- return (error);
-}
-
-static int
-nandfs_fsync(struct vop_fsync_args *ap)
-{
- struct vnode *vp = ap->a_vp;
- struct nandfs_node *node = VTON(vp);
- int locked;
-
- DPRINTF(VNCALL, ("%s: vp %p nandnode %p ino %#jx\n", __func__, vp,
- node, (uintmax_t)node->nn_ino));
-
- /*
- * Start syncing vnode only if inode was modified or
- * there are some dirty buffers
- */
- if (VTON(vp)->nn_flags & IN_MODIFIED ||
- vp->v_bufobj.bo_dirty.bv_cnt) {
- locked = VOP_ISLOCKED(vp);
- VOP_UNLOCK(vp, 0);
- nandfs_wakeup_wait_sync(node->nn_nandfsdev, SYNCER_FSYNC);
- VOP_LOCK(vp, locked | LK_RETRY);
- }
-
- return (0);
-}
-
-static int
-nandfs_bmap(struct vop_bmap_args *ap)
-{
- struct vnode *vp = ap->a_vp;
- struct nandfs_node *nnode = VTON(vp);
- struct nandfs_device *nandfsdev = nnode->nn_nandfsdev;
- nandfs_daddr_t l2vmap, v2pmap;
- int error;
- int blk2dev = nandfsdev->nd_blocksize / DEV_BSIZE;
-
- DPRINTF(VNCALL, ("%s: vp %p nandnode %p ino %#jx\n", __func__, vp,
- nnode, (uintmax_t)nnode->nn_ino));
-
- if (ap->a_bop != NULL)
- *ap->a_bop = &nandfsdev->nd_devvp->v_bufobj;
- if (ap->a_bnp == NULL)
- return (0);
- if (ap->a_runp != NULL)
- *ap->a_runp = 0;
- if (ap->a_runb != NULL)
- *ap->a_runb = 0;
-
- /*
- * Translate all the block sectors into a series of buffers to read
- * asynchronously from the nandfs device. Note that this lookup may
- * induce readin's too.
- */
-
- /* Get virtual block numbers for the vnode's buffer span */
- error = nandfs_bmap_lookup(nnode, ap->a_bn, &l2vmap);
- if (error)
- return (-1);
-
- /* Translate virtual block numbers to physical block numbers */
- error = nandfs_vtop(nnode, l2vmap, &v2pmap);
- if (error)
- return (-1);
-
- /* Note virtual block 0 marks not mapped */
- if (l2vmap == 0)
- *ap->a_bnp = -1;
- else
- *ap->a_bnp = v2pmap * blk2dev; /* in DEV_BSIZE */
-
- DPRINTF(VNCALL, ("%s: vp %p nandnode %p ino %#jx lblk %jx -> blk %jx\n",
- __func__, vp, nnode, (uintmax_t)nnode->nn_ino, (uintmax_t)ap->a_bn,
- (uintmax_t)*ap->a_bnp ));
-
- return (0);
-}
-
-static void
-nandfs_force_syncer(struct nandfsmount *nmp)
-{
-
- nmp->nm_flags |= NANDFS_FORCE_SYNCER;
- nandfs_wakeup_wait_sync(nmp->nm_nandfsdev, SYNCER_FFORCE);
-}
-
-static int
-nandfs_ioctl(struct vop_ioctl_args *ap)
-{
- struct vnode *vp = ap->a_vp;
- u_long command = ap->a_command;
- caddr_t data = ap->a_data;
- struct nandfs_node *node = VTON(vp);
- struct nandfs_device *nandfsdev = node->nn_nandfsdev;
- struct nandfsmount *nmp = node->nn_nmp;
- uint64_t *tab, *cno;
- struct nandfs_seg_stat *nss;
- struct nandfs_cpmode *ncpm;
- struct nandfs_argv *nargv;
- struct nandfs_cpstat *ncp;
- int error;
-
- DPRINTF(VNCALL, ("%s: %x\n", __func__, (uint32_t)command));
-
- error = priv_check(ap->a_td, PRIV_VFS_MOUNT);
- if (error)
- return (error);
-
- if (nmp->nm_ronly) {
- switch (command) {
- case NANDFS_IOCTL_GET_FSINFO:
- case NANDFS_IOCTL_GET_SUSTAT:
- case NANDFS_IOCTL_GET_CPINFO:
- case NANDFS_IOCTL_GET_CPSTAT:
- case NANDFS_IOCTL_GET_SUINFO:
- case NANDFS_IOCTL_GET_VINFO:
- case NANDFS_IOCTL_GET_BDESCS:
- break;
- default:
- return (EROFS);
- }
- }
-
- switch (command) {
- case NANDFS_IOCTL_GET_FSINFO:
- error = nandfs_get_fsinfo(nmp, (struct nandfs_fsinfo *)data);
- break;
- case NANDFS_IOCTL_GET_SUSTAT:
- nss = (struct nandfs_seg_stat *)data;
- error = nandfs_get_seg_stat(nandfsdev, nss);
- break;
- case NANDFS_IOCTL_CHANGE_CPMODE:
- ncpm = (struct nandfs_cpmode *)data;
- error = nandfs_chng_cpmode(nandfsdev->nd_cp_node, ncpm);
- nandfs_force_syncer(nmp);
- break;
- case NANDFS_IOCTL_GET_CPINFO:
- nargv = (struct nandfs_argv *)data;
- error = nandfs_get_cpinfo_ioctl(nandfsdev->nd_cp_node, nargv);
- break;
- case NANDFS_IOCTL_DELETE_CP:
- tab = (uint64_t *)data;
- error = nandfs_delete_cp(nandfsdev->nd_cp_node, tab[0], tab[1]);
- nandfs_force_syncer(nmp);
- break;
- case NANDFS_IOCTL_GET_CPSTAT:
- ncp = (struct nandfs_cpstat *)data;
- error = nandfs_get_cpstat(nandfsdev->nd_cp_node, ncp);
- break;
- case NANDFS_IOCTL_GET_SUINFO:
- nargv = (struct nandfs_argv *)data;
- error = nandfs_get_segment_info_ioctl(nandfsdev, nargv);
- break;
- case NANDFS_IOCTL_GET_VINFO:
- nargv = (struct nandfs_argv *)data;
- error = nandfs_get_dat_vinfo_ioctl(nandfsdev, nargv);
- break;
- case NANDFS_IOCTL_GET_BDESCS:
- nargv = (struct nandfs_argv *)data;
- error = nandfs_get_dat_bdescs_ioctl(nandfsdev, nargv);
- break;
- case NANDFS_IOCTL_SYNC:
- cno = (uint64_t *)data;
- nandfs_force_syncer(nmp);
- *cno = nandfsdev->nd_last_cno;
- error = 0;
- break;
- case NANDFS_IOCTL_MAKE_SNAP:
- cno = (uint64_t *)data;
- error = nandfs_make_snap(nandfsdev, cno);
- nandfs_force_syncer(nmp);
- break;
- case NANDFS_IOCTL_DELETE_SNAP:
- cno = (uint64_t *)data;
- error = nandfs_delete_snap(nandfsdev, *cno);
- nandfs_force_syncer(nmp);
- break;
- default:
- error = ENOTTY;
- break;
- }
-
- return (error);
-}
-
-/*
- * Whiteout vnode call
- */
-static int
-nandfs_whiteout(struct vop_whiteout_args *ap)
-{
- struct vnode *dvp = ap->a_dvp;
- struct componentname *cnp = ap->a_cnp;
- int error = 0;
-
- switch (ap->a_flags) {
- case LOOKUP:
- return (0);
- case CREATE:
- /* Create a new directory whiteout */
-#ifdef INVARIANTS
- if ((cnp->cn_flags & SAVENAME) == 0)
- panic("nandfs_whiteout: missing name");
-#endif
- error = nandfs_add_dirent(dvp, NANDFS_WHT_INO, cnp->cn_nameptr,
- cnp->cn_namelen, DT_WHT);
- break;
-
- case DELETE:
- /* Remove an existing directory whiteout */
- cnp->cn_flags &= ~DOWHITEOUT;
- error = nandfs_remove_dirent(dvp, NULL, cnp);
- break;
- default:
- panic("nandf_whiteout: unknown op: %d", ap->a_flags);
- }
-
- return (error);
-}
-
-static int
-nandfs_pathconf(struct vop_pathconf_args *ap)
-{
- int error;
-
- error = 0;
- switch (ap->a_name) {
- case _PC_LINK_MAX:
- *ap->a_retval = NANDFS_LINK_MAX;
- break;
- case _PC_NAME_MAX:
- *ap->a_retval = NANDFS_NAME_LEN;
- break;
- case _PC_PIPE_BUF:
- if (ap->a_vp->v_type == VDIR || ap->a_vp->v_type == VFIFO)
- *ap->a_retval = PIPE_BUF;
- else
- error = EINVAL;
- break;
- case _PC_CHOWN_RESTRICTED:
- *ap->a_retval = 1;
- break;
- case _PC_NO_TRUNC:
- *ap->a_retval = 1;
- break;
- case _PC_ALLOC_SIZE_MIN:
- *ap->a_retval = ap->a_vp->v_mount->mnt_stat.f_bsize;
- break;
- case _PC_FILESIZEBITS:
- *ap->a_retval = 64;
- break;
- case _PC_REC_INCR_XFER_SIZE:
- *ap->a_retval = ap->a_vp->v_mount->mnt_stat.f_iosize;
- break;
- case _PC_REC_MAX_XFER_SIZE:
- *ap->a_retval = -1; /* means ``unlimited'' */
- break;
- case _PC_REC_MIN_XFER_SIZE:
- *ap->a_retval = ap->a_vp->v_mount->mnt_stat.f_iosize;
- break;
- default:
- error = vop_stdpathconf(ap);
- break;
- }
- return (error);
-}
-
-static int
-nandfs_vnlock1(struct vop_lock1_args *ap)
-{
- struct vnode *vp = ap->a_vp;
- struct nandfs_node *node = VTON(vp);
- int error, vi_locked;
-
- /*
- * XXX can vnode go away while we are sleeping?
- */
- vi_locked = mtx_owned(&vp->v_interlock);
- if (vi_locked)
- VI_UNLOCK(vp);
- error = NANDFS_WRITELOCKFLAGS(node->nn_nandfsdev,
- ap->a_flags & LK_NOWAIT);
- if (vi_locked && !error)
- VI_LOCK(vp);
- if (error)
- return (error);
-
- error = vop_stdlock(ap);
- if (error) {
- NANDFS_WRITEUNLOCK(node->nn_nandfsdev);
- return (error);
- }
-
- return (0);
-}
-
-static int
-nandfs_vnunlock(struct vop_unlock_args *ap)
-{
- struct vnode *vp = ap->a_vp;
- struct nandfs_node *node = VTON(vp);
- int error;
-
- error = vop_stdunlock(ap);
- if (error)
- return (error);
-
- NANDFS_WRITEUNLOCK(node->nn_nandfsdev);
-
- return (0);
-}
-
-/*
- * Global vfs data structures
- */
-struct vop_vector nandfs_vnodeops = {
- .vop_default = &default_vnodeops,
- .vop_access = nandfs_access,
- .vop_advlock = nandfs_advlock,
- .vop_bmap = nandfs_bmap,
- .vop_close = nandfs_close,
- .vop_create = nandfs_create,
- .vop_fsync = nandfs_fsync,
- .vop_getattr = nandfs_getattr,
- .vop_inactive = nandfs_inactive,
- .vop_cachedlookup = nandfs_lookup,
- .vop_ioctl = nandfs_ioctl,
- .vop_link = nandfs_link,
- .vop_lookup = vfs_cache_lookup,
- .vop_mkdir = nandfs_mkdir,
- .vop_mknod = nandfs_mknod,
- .vop_open = nandfs_open,
- .vop_pathconf = nandfs_pathconf,
- .vop_print = nandfs_print,
- .vop_read = nandfs_read,
- .vop_readdir = nandfs_readdir,
- .vop_readlink = nandfs_readlink,
- .vop_reclaim = nandfs_reclaim,
- .vop_remove = nandfs_remove,
- .vop_rename = nandfs_rename,
- .vop_rmdir = nandfs_rmdir,
- .vop_whiteout = nandfs_whiteout,
- .vop_write = nandfs_write,
- .vop_setattr = nandfs_setattr,
- .vop_strategy = nandfs_strategy,
- .vop_symlink = nandfs_symlink,
- .vop_lock1 = nandfs_vnlock1,
- .vop_unlock = nandfs_vnunlock,
-};
-
-struct vop_vector nandfs_system_vnodeops = {
- .vop_default = &default_vnodeops,
- .vop_close = nandfs_close,
- .vop_inactive = nandfs_inactive,
- .vop_reclaim = nandfs_reclaim,
- .vop_strategy = nandfs_strategy,
- .vop_fsync = nandfs_fsync,
- .vop_bmap = nandfs_bmap,
- .vop_access = VOP_PANIC,
- .vop_advlock = VOP_PANIC,
- .vop_create = VOP_PANIC,
- .vop_getattr = VOP_PANIC,
- .vop_cachedlookup = VOP_PANIC,
- .vop_ioctl = VOP_PANIC,
- .vop_link = VOP_PANIC,
- .vop_lookup = VOP_PANIC,
- .vop_mkdir = VOP_PANIC,
- .vop_mknod = VOP_PANIC,
- .vop_open = VOP_PANIC,
- .vop_pathconf = VOP_PANIC,
- .vop_print = VOP_PANIC,
- .vop_read = VOP_PANIC,
- .vop_readdir = VOP_PANIC,
- .vop_readlink = VOP_PANIC,
- .vop_remove = VOP_PANIC,
- .vop_rename = VOP_PANIC,
- .vop_rmdir = VOP_PANIC,
- .vop_whiteout = VOP_PANIC,
- .vop_write = VOP_PANIC,
- .vop_setattr = VOP_PANIC,
- .vop_symlink = VOP_PANIC,
-};
-
-static int
-nandfsfifo_close(struct vop_close_args *ap)
-{
- struct vnode *vp = ap->a_vp;
- struct nandfs_node *node = VTON(vp);
-
- DPRINTF(VNCALL, ("%s: vp %p node %p\n", __func__, vp, node));
-
- mtx_lock(&vp->v_interlock);
- if (vp->v_usecount > 1)
- nandfs_itimes_locked(vp);
- mtx_unlock(&vp->v_interlock);
-
- return (fifo_specops.vop_close(ap));
-}
-
-struct vop_vector nandfs_fifoops = {
- .vop_default = &fifo_specops,
- .vop_fsync = VOP_PANIC,
- .vop_access = nandfs_access,
- .vop_close = nandfsfifo_close,
- .vop_getattr = nandfs_getattr,
- .vop_inactive = nandfs_inactive,
- .vop_pathconf = nandfs_pathconf,
- .vop_print = nandfs_print,
- .vop_read = VOP_PANIC,
- .vop_reclaim = nandfs_reclaim,
- .vop_setattr = nandfs_setattr,
- .vop_write = VOP_PANIC,
- .vop_lock1 = nandfs_vnlock1,
- .vop_unlock = nandfs_vnunlock,
-};
-
-int
-nandfs_vinit(struct vnode *vp, uint64_t ino)
-{
- struct nandfs_node *node;
-
- ASSERT_VOP_LOCKED(vp, __func__);
-
- node = VTON(vp);
-
- /* Check if we're fetching the root */
- if (ino == NANDFS_ROOT_INO)
- vp->v_vflag |= VV_ROOT;
-
- if (ino != NANDFS_GC_INO)
- vp->v_type = IFTOVT(node->nn_inode.i_mode);
- else
- vp->v_type = VREG;
-
- if (vp->v_type == VFIFO)
- vp->v_op = &nandfs_fifoops;
-
- return (0);
-}
diff --git a/sys/fs/smbfs/smbfs_io.c b/sys/fs/smbfs/smbfs_io.c
index 4edba5c761e7f..fa6a140242137 100644
--- a/sys/fs/smbfs/smbfs_io.c
+++ b/sys/fs/smbfs/smbfs_io.c
@@ -375,9 +375,6 @@ smbfs_doio(struct vnode *vp, struct buf *bp, struct ucred *cr, struct thread *td
*/
if (error == EINTR
|| (!error && (bp->b_flags & B_NEEDCOMMIT))) {
- int s;
-
- s = splbio();
bp->b_flags &= ~(B_INVAL|B_NOCACHE);
if ((bp->b_flags & B_ASYNC) == 0)
bp->b_flags |= B_EINTR;
@@ -387,7 +384,6 @@ smbfs_doio(struct vnode *vp, struct buf *bp, struct ucred *cr, struct thread *td
}
if ((bp->b_flags & B_ASYNC) == 0)
bp->b_flags |= B_EINTR;
- splx(s);
} else {
if (error) {
bp->b_ioflags |= BIO_ERROR;
diff --git a/sys/geom/geom_flashmap.c b/sys/geom/geom_flashmap.c
index ac7344a34bb61..71007a4f7936d 100644
--- a/sys/geom/geom_flashmap.c
+++ b/sys/geom/geom_flashmap.c
@@ -43,8 +43,6 @@ __FBSDID("$FreeBSD$");
#include <geom/geom_flashmap.h>
#include <geom/geom_slice.h>
-#include <dev/nand/nand_dev.h>
-
struct g_flashmap_slice {
off_t sl_start;
off_t sl_end;
@@ -65,7 +63,6 @@ static struct {
{ "MMC::device", NULL }
};
-static g_ioctl_t g_flashmap_ioctl;
static g_taste_t g_flashmap_taste;
static int g_flashmap_load(device_t dev, struct g_provider *pp,
@@ -127,26 +124,6 @@ g_flashmap_modify(struct g_flashmap *gfp, struct g_geom *gp,
return (0);
}
-static int
-g_flashmap_ioctl(struct g_provider *pp, u_long cmd, void *data, int fflag,
- struct thread *td)
-{
- struct g_consumer *cp;
- struct g_geom *gp;
-
- if (cmd != NAND_IO_GET_CHIP_PARAM)
- return (ENOIOCTL);
-
- cp = LIST_FIRST(&pp->geom->consumer);
- if (cp == NULL)
- return (ENOIOCTL);
- gp = cp->provider->geom;
- if (gp->ioctl == NULL)
- return (ENOIOCTL);
-
- return (gp->ioctl(cp->provider, cmd, data, fflag, td));
-}
-
static struct g_geom *
g_flashmap_taste(struct g_class *mp, struct g_provider *pp, int flags)
{
@@ -245,7 +222,6 @@ static struct g_class g_flashmap_class = {
.name = FLASHMAP_CLASS_NAME,
.version = G_VERSION,
.taste = g_flashmap_taste,
- .ioctl = g_flashmap_ioctl,
};
DECLARE_GEOM_CLASS(g_flashmap_class, g_flashmap);
diff --git a/sys/i386/conf/GENERIC b/sys/i386/conf/GENERIC
index dab73ee51da6e..ddeabf5952c8b 100644
--- a/sys/i386/conf/GENERIC
+++ b/sys/i386/conf/GENERIC
@@ -292,7 +292,6 @@ device wpi # Intel 3945ABG wireless NICs.
# Pseudo devices.
device crypto # core crypto support
device loop # Network loopback
-device random # Entropy device
device padlock_rng # VIA Padlock RNG
device rdrand_rng # Intel Bull Mountain RNG
device ether # Ethernet support
diff --git a/sys/i386/conf/MINIMAL b/sys/i386/conf/MINIMAL
index 0b0bd23f40b40..0f1d268d013ee 100644
--- a/sys/i386/conf/MINIMAL
+++ b/sys/i386/conf/MINIMAL
@@ -10,7 +10,7 @@
# some features (ACL, GJOURNAL) that GENERIC includes.
# o acpi as a module has been reported flakey and not well tested, so
# is included in the kernel.
-# o random is included due to uncertaty...
+# o (non-loaded) random is included due to uncertainty...
# o Many networking things are included
#
# For now, please run changes to these list past imp@freebsd.org
@@ -132,7 +132,6 @@ device agp # support several AGP chipsets
# Pseudo devices.
device loop # Network loopback
-device random # Entropy device
device padlock_rng # VIA Padlock RNG
device rdrand_rng # Intel Bull Mountain RNG
device ether # Ethernet support
diff --git a/sys/kern/Make.tags.inc b/sys/kern/Make.tags.inc
index 50aed68dbf40d..cdefa98a32f65 100644
--- a/sys/kern/Make.tags.inc
+++ b/sys/kern/Make.tags.inc
@@ -28,7 +28,6 @@ COMM= ${SYS}/sys/vnode.h \
${SYS}/fs/fifofs/*.[ch] \
${SYS}/fs/fuse/*.[ch] \
${SYS}/fs/msdosfs/*.[ch] \
- ${SYS}/fs/nandfs/*.[ch] \
${SYS}/fs/nfs/*.[ch] \
${SYS}/fs/nfsclient/*.[ch] \
${SYS}/fs/nfsserver/*.[ch] \
@@ -82,7 +81,6 @@ COMMDIR2= ${SYS}/dev/alc \
${SYS}/fs/fifofs \
${SYS}/fs/fuse \
${SYS}/fs/msdosfs \
- ${SYS}/fs/nandfs \
${SYS}/fs/nfs \
${SYS}/fs/nfsclient \
${SYS}/fs/nfsserver \
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index 4d09eea37d562..4bc1a1546820b 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -780,7 +780,9 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg)
}
if (arg >= 0) {
bsize = fp->f_vnode->v_mount->mnt_stat.f_iosize;
- fp->f_seqcount = (arg + bsize - 1) / bsize;
+ arg = MIN(arg, INT_MAX - bsize + 1);
+ fp->f_seqcount = MIN(IO_SEQMAX,
+ (arg + bsize - 1) / bsize);
atomic_set_int(&fp->f_flag, FRDAHEAD);
} else {
atomic_clear_int(&fp->f_flag, FRDAHEAD);
diff --git a/sys/kern/kern_mib.c b/sys/kern/kern_mib.c
index a92f6488c39f3..54cdff1482472 100644
--- a/sys/kern/kern_mib.c
+++ b/sys/kern/kern_mib.c
@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
#include "opt_config.h"
#include <sys/param.h>
+#include <sys/boot.h>
#include <sys/jail.h>
#include <sys/kernel.h>
#include <sys/limits.h>
@@ -136,7 +137,7 @@ SYSCTL_INT(_kern, KERN_SAVED_IDS, saved_ids, CTLFLAG_RD|CTLFLAG_CAPRD,
SYSCTL_NULL_INT_PTR, 0, "Whether saved set-group/user ID is available");
#endif
-char kernelname[MAXPATHLEN] = "/boot/kernel/kernel"; /* XXX bloat */
+char kernelname[MAXPATHLEN] = PATH_KERNEL; /* XXX bloat */
SYSCTL_STRING(_kern, KERN_BOOTFILE, bootfile, CTLFLAG_RW | CTLFLAG_MPSAFE,
kernelname, sizeof kernelname, "Name of kernel file booted");
diff --git a/sys/kern/kern_rangelock.c b/sys/kern/kern_rangelock.c
index 35bd6e864d374..b434ac4b4c1c7 100644
--- a/sys/kern/kern_rangelock.c
+++ b/sys/kern/kern_rangelock.c
@@ -141,15 +141,33 @@ out:
static void
rangelock_unlock_locked(struct rangelock *lock, struct rl_q_entry *entry,
- struct mtx *ilk)
+ struct mtx *ilk, bool do_calc_block)
{
MPASS(lock != NULL && entry != NULL && ilk != NULL);
mtx_assert(ilk, MA_OWNED);
- KASSERT(entry != lock->rl_currdep, ("stuck currdep"));
+
+ if (!do_calc_block) {
+ /*
+ * This is the case where rangelock_enqueue() has been called
+ * with trylock == true and just inserted this entry in the
+ * queue.
+ * If rl_currdep is this entry, rl_currdep needs to
+ * be set to the next entry in the rl_waiters list.
+ * However, since this entry is the last entry in the
+ * list, the next entry is NULL.
+ */
+ if (lock->rl_currdep == entry) {
+ KASSERT(TAILQ_NEXT(lock->rl_currdep, rl_q_link) == NULL,
+ ("rangelock_enqueue: next entry not NULL"));
+ lock->rl_currdep = NULL;
+ }
+ } else
+ KASSERT(entry != lock->rl_currdep, ("stuck currdep"));
TAILQ_REMOVE(&lock->rl_waiters, entry, rl_q_link);
- rangelock_calc_block(lock);
+ if (do_calc_block)
+ rangelock_calc_block(lock);
mtx_unlock(ilk);
if (curthread->td_rlqe == NULL)
curthread->td_rlqe = entry;
@@ -164,7 +182,7 @@ rangelock_unlock(struct rangelock *lock, void *cookie, struct mtx *ilk)
MPASS(lock != NULL && cookie != NULL && ilk != NULL);
mtx_lock(ilk);
- rangelock_unlock_locked(lock, cookie, ilk);
+ rangelock_unlock_locked(lock, cookie, ilk, true);
}
/*
@@ -185,7 +203,7 @@ rangelock_unlock_range(struct rangelock *lock, void *cookie, off_t start,
mtx_lock(ilk);
if (entry->rl_q_end == end) {
- rangelock_unlock_locked(lock, cookie, ilk);
+ rangelock_unlock_locked(lock, cookie, ilk, true);
return (NULL);
}
entry->rl_q_end = end;
@@ -196,11 +214,11 @@ rangelock_unlock_range(struct rangelock *lock, void *cookie, off_t start,
/*
* Add the lock request to the queue of the pending requests for
- * rangelock. Sleep until the request can be granted.
+ * rangelock. Sleep until the request can be granted unless trylock == true.
*/
static void *
rangelock_enqueue(struct rangelock *lock, off_t start, off_t end, int mode,
- struct mtx *ilk)
+ struct mtx *ilk, bool trylock)
{
struct rl_q_entry *entry;
struct thread *td;
@@ -226,11 +244,28 @@ rangelock_enqueue(struct rangelock *lock, off_t start, off_t end, int mode,
*/
TAILQ_INSERT_TAIL(&lock->rl_waiters, entry, rl_q_link);
+ /*
+ * If rl_currdep == NULL, there is no entry waiting for a conflicting
+ * range to be resolved, so set rl_currdep to this entry. If there is
+ * no conflicting entry for this entry, rl_currdep will be set back to
+ * NULL by rangelock_calc_block().
+ */
if (lock->rl_currdep == NULL)
lock->rl_currdep = entry;
rangelock_calc_block(lock);
- while (!(entry->rl_q_flags & RL_LOCK_GRANTED))
+ while (!(entry->rl_q_flags & RL_LOCK_GRANTED)) {
+ if (trylock) {
+ /*
+ * For this case, the range is not actually locked
+ * yet, but removal from the list requires the same
+ * steps, except for not doing a rangelock_calc_block()
+ * call, since rangelock_calc_block() was called above.
+ */
+ rangelock_unlock_locked(lock, entry, ilk, false);
+ return (NULL);
+ }
msleep(entry, ilk, 0, "range", 0);
+ }
mtx_unlock(ilk);
return (entry);
}
@@ -239,12 +274,28 @@ void *
rangelock_rlock(struct rangelock *lock, off_t start, off_t end, struct mtx *ilk)
{
- return (rangelock_enqueue(lock, start, end, RL_LOCK_READ, ilk));
+ return (rangelock_enqueue(lock, start, end, RL_LOCK_READ, ilk, false));
+}
+
+void *
+rangelock_tryrlock(struct rangelock *lock, off_t start, off_t end,
+ struct mtx *ilk)
+{
+
+ return (rangelock_enqueue(lock, start, end, RL_LOCK_READ, ilk, true));
}
void *
rangelock_wlock(struct rangelock *lock, off_t start, off_t end, struct mtx *ilk)
{
- return (rangelock_enqueue(lock, start, end, RL_LOCK_WRITE, ilk));
+ return (rangelock_enqueue(lock, start, end, RL_LOCK_WRITE, ilk, false));
+}
+
+void *
+rangelock_trywlock(struct rangelock *lock, off_t start, off_t end,
+ struct mtx *ilk)
+{
+
+ return (rangelock_enqueue(lock, start, end, RL_LOCK_WRITE, ilk, true));
}
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index 044865a489a69..8a1ee1e53cbe1 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -3415,10 +3415,16 @@ corefile_open_last(struct thread *td, char *name, int indexpos,
}
if (oldvp != NULL) {
- if (nextvp == NULL)
- nextvp = oldvp;
- else
+ if (nextvp == NULL) {
+ if ((td->td_proc->p_flag & P_SUGID) != 0) {
+ error = EFAULT;
+ vnode_close_locked(td, oldvp);
+ } else {
+ nextvp = oldvp;
+ }
+ } else {
vnode_close_locked(td, oldvp);
+ }
}
if (error != 0) {
if (nextvp != NULL)
@@ -3538,6 +3544,8 @@ corefile_open(const char *comm, uid_t uid, pid_t pid, struct thread *td,
oflags = VN_OPEN_NOAUDIT | VN_OPEN_NAMECACHE |
(capmode_coredump ? VN_OPEN_NOCAPCHECK : 0);
flags = O_CREAT | FWRITE | O_NOFOLLOW;
+ if ((td->td_proc->p_flag & P_SUGID) != 0)
+ flags |= O_EXCL;
NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, name, td);
error = vn_open_cred(&nd, &flags, cmode, oflags, td->td_ucred,
@@ -3614,10 +3622,11 @@ coredump(struct thread *td)
/*
* Don't dump to non-regular files or files with links.
- * Do not dump into system files.
+ * Do not dump into system files. Effective user must own the corefile.
*/
if (vp->v_type != VREG || VOP_GETATTR(vp, &vattr, cred) != 0 ||
- vattr.va_nlink != 1 || (vp->v_vflag & VV_SYSTEM) != 0) {
+ vattr.va_nlink != 1 || (vp->v_vflag & VV_SYSTEM) != 0 ||
+ vattr.va_uid != cred->cr_uid) {
VOP_UNLOCK(vp, 0);
error = EFAULT;
goto out;
diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c
index eafb902601d7f..3c04e8607a718 100644
--- a/sys/kern/sys_pipe.c
+++ b/sys/kern/sys_pipe.c
@@ -1414,7 +1414,7 @@ pipe_poll(struct file *fp, int events, struct ucred *active_cred,
levents = events &
(POLLIN | POLLINIGNEOF | POLLPRI | POLLRDNORM | POLLRDBAND);
if (rpipe->pipe_state & PIPE_NAMED && fp->f_flag & FREAD && levents &&
- fp->f_seqcount == rpipe->pipe_wgen)
+ fp->f_pipegen == rpipe->pipe_wgen)
events |= POLLINIGNEOF;
if ((events & POLLINIGNEOF) == 0) {
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
index e38f8c06bbb36..05be168e8a841 100644
--- a/sys/kern/uipc_socket.c
+++ b/sys/kern/uipc_socket.c
@@ -1044,7 +1044,7 @@ sofree(struct socket *so)
*
* We used to do a lot of socket buffer and socket locking here, as
* well as invoke sorflush() and perform wakeups. The direct call to
- * dom_dispose() and sbrelease_internal() are an inlining of what was
+ * dom_dispose() and sbdestroy() are an inlining of what was
* necessary from sorflush().
*
* Notice that the socket buffer and kqueue state are torn down
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index 7871e536b56e5..aba141c262494 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -499,9 +499,8 @@ sequential_heuristic(struct uio *uio, struct file *fp)
* closely related to the best I/O size for real disks than
* to any block size used by software.
*/
- fp->f_seqcount += howmany(uio->uio_resid, 16384);
- if (fp->f_seqcount > IO_SEQMAX)
- fp->f_seqcount = IO_SEQMAX;
+ fp->f_seqcount += lmin(IO_SEQMAX,
+ howmany(uio->uio_resid, 16384));
return (fp->f_seqcount << IO_SEQSHIFT);
}
diff --git a/sys/mips/conf/BCM b/sys/mips/conf/BCM
index 5c2753279a234..27d93766c3549 100644
--- a/sys/mips/conf/BCM
+++ b/sys/mips/conf/BCM
@@ -82,7 +82,6 @@ device uart
#Base
device loop
device ether
-device random
device md
#Performance
diff --git a/sys/mips/conf/BERI_DE4_BASE b/sys/mips/conf/BERI_DE4_BASE
index 0985d60e60d1a..7719009ccf5ae 100644
--- a/sys/mips/conf/BERI_DE4_BASE
+++ b/sys/mips/conf/BERI_DE4_BASE
@@ -44,6 +44,7 @@ options DEVICE_POLLING
#
# DMA support
#
+options ALTERA_MSGDMA_DESC_PF_STD
device xdma
device altera_softdma
device altera_msgdma
diff --git a/sys/mips/conf/DIR-825B1 b/sys/mips/conf/DIR-825B1
index 80a1d17c0ac08..8b43cf1b22ca9 100644
--- a/sys/mips/conf/DIR-825B1
+++ b/sys/mips/conf/DIR-825B1
@@ -21,7 +21,6 @@ hints "DIR-825B1.hints"
# Since the kernel image must fit inside 1024KiB, we have to build almost
# everything as modules.
-# nodevice random
nodevice gpio
nodevice gpioled
nodevice gif
diff --git a/sys/mips/conf/ERL b/sys/mips/conf/ERL
index f12f6228bd95d..a0e79450c871d 100644
--- a/sys/mips/conf/ERL
+++ b/sys/mips/conf/ERL
@@ -149,7 +149,6 @@ device wlan_amrr # AMRR transmit rate control algorithm
# Pseudo devices.
device loop # Network loopback
-device random # Entropy device
device ether # Ethernet support
device vlan # 802.1Q VLAN support
device tuntap # Packet tunnel.
diff --git a/sys/mips/conf/JZ4780 b/sys/mips/conf/JZ4780
index a3716cbe48733..459f908857a64 100644
--- a/sys/mips/conf/JZ4780
+++ b/sys/mips/conf/JZ4780
@@ -68,7 +68,6 @@ device miibus
device bpf
device md
device uart
-device random
device fdt_pinctrl
diff --git a/sys/mips/conf/OCTEON1 b/sys/mips/conf/OCTEON1
index 6c536f0d6ed46..256b66eff71fd 100644
--- a/sys/mips/conf/OCTEON1
+++ b/sys/mips/conf/OCTEON1
@@ -184,7 +184,6 @@ device ral # Ralink Technology RT2500 wireless NICs.
# Pseudo devices.
device loop # Network loopback
-device random # Entropy device
device ether # Ethernet support
device vlan # 802.1Q VLAN support
device tuntap # Packet tunnel.
diff --git a/sys/mips/conf/PB92 b/sys/mips/conf/PB92
index 4d3e890d0f968..64a0e6db120b8 100644
--- a/sys/mips/conf/PB92
+++ b/sys/mips/conf/PB92
@@ -133,5 +133,4 @@ device loop
device ether
#device md
#device bpf
-device random
#device if_bridge
diff --git a/sys/mips/conf/PICOSTATION_M2HP b/sys/mips/conf/PICOSTATION_M2HP
index e331f7764d2db..38e3d69c05091 100644
--- a/sys/mips/conf/PICOSTATION_M2HP
+++ b/sys/mips/conf/PICOSTATION_M2HP
@@ -68,6 +68,3 @@ device arswitch
# Enable GPIO
device gpio
device gpioled
-
-# RNG
-device random
diff --git a/sys/mips/conf/WZR-300HP b/sys/mips/conf/WZR-300HP
index 217e444f1b896..dd767888a1e98 100644
--- a/sys/mips/conf/WZR-300HP
+++ b/sys/mips/conf/WZR-300HP
@@ -49,4 +49,4 @@ device hwpmc
# load these via modules, shrink kernel
nodevice if_bridge
nodevice bridgestp
-nodevice random
+options RANDOM_LOADABLE
diff --git a/sys/mips/conf/WZR-HPAG300H b/sys/mips/conf/WZR-HPAG300H
index b46f9de3eb8d6..3337af682f2c4 100644
--- a/sys/mips/conf/WZR-HPAG300H
+++ b/sys/mips/conf/WZR-HPAG300H
@@ -49,4 +49,4 @@ device hwpmc
# load these via modules, shrink kernel
nodevice if_bridge
nodevice bridgestp
-nodevice random
+options RANDOM_LOADABLE
diff --git a/sys/mips/conf/X1000 b/sys/mips/conf/X1000
index 907ea814de8f5..8f10337218a5c 100644
--- a/sys/mips/conf/X1000
+++ b/sys/mips/conf/X1000
@@ -63,7 +63,6 @@ device miibus
device bpf
device md
device uart
-device random
device fdt_pinctrl
diff --git a/sys/mips/conf/std.AR5312 b/sys/mips/conf/std.AR5312
index a3b055bfb743e..56a45cb4c869e 100644
--- a/sys/mips/conf/std.AR5312
+++ b/sys/mips/conf/std.AR5312
@@ -72,7 +72,6 @@ device loop
device ether
device md
device bpf
-device random
options ARGE_DEBUG # Enable if_arge debugging for now
diff --git a/sys/mips/conf/std.AR5315 b/sys/mips/conf/std.AR5315
index c9f85f6c08135..74a888c32f85c 100644
--- a/sys/mips/conf/std.AR5315
+++ b/sys/mips/conf/std.AR5315
@@ -72,7 +72,6 @@ device loop
device ether
device md
device bpf
-device random
options ARGE_DEBUG # Enable if_arge debugging for now
diff --git a/sys/mips/conf/std.AR_MIPS_BASE b/sys/mips/conf/std.AR_MIPS_BASE
index 37544a9b66603..ab0947a391ea9 100644
--- a/sys/mips/conf/std.AR_MIPS_BASE
+++ b/sys/mips/conf/std.AR_MIPS_BASE
@@ -25,9 +25,6 @@ makeoptions MODULES_OVERRIDE+="gpio ar71xx if_gif if_vlan if_gre if_tuntap"
makeoptions MODULES_OVERRIDE+="if_bridge bridgestp usb"
makeoptions MODULES_OVERRIDE+="alq"
-# Random - required during early boot!
-device random
-
# net80211
options IEEE80211_DEBUG
options IEEE80211_SUPPORT_MESH
diff --git a/sys/mips/conf/std.BERI b/sys/mips/conf/std.BERI
index 903af51875afc..07f907b760df6 100644
--- a/sys/mips/conf/std.BERI
+++ b/sys/mips/conf/std.BERI
@@ -61,5 +61,4 @@ device ether
device geom_map
device loop
device md
-device random
device snp
diff --git a/sys/mips/conf/std.MALTA b/sys/mips/conf/std.MALTA
index 4c1965650fba5..26940db1b92f4 100644
--- a/sys/mips/conf/std.MALTA
+++ b/sys/mips/conf/std.MALTA
@@ -55,4 +55,3 @@ device miibus
device bpf
device md
device uart
-device random
diff --git a/sys/mips/conf/std.XLP b/sys/mips/conf/std.XLP
index 5330c19b36577..cbc13746fd063 100644
--- a/sys/mips/conf/std.XLP
+++ b/sys/mips/conf/std.XLP
@@ -66,7 +66,6 @@ makeoptions FDT_DTS_FILE=xlp-basic.dts
# Pseudo
device loop
-device random
device md
device bpf
diff --git a/sys/mips/mediatek/std.mediatek b/sys/mips/mediatek/std.mediatek
index 7806da8f099a2..d8c351aab36ff 100644
--- a/sys/mips/mediatek/std.mediatek
+++ b/sys/mips/mediatek/std.mediatek
@@ -74,9 +74,6 @@ device fdt_pinctrl
# UART support
device uart
-# random support
-device random
-
# loop device support
device loop
diff --git a/sys/mips/mediatek/std.rt2880 b/sys/mips/mediatek/std.rt2880
index 8040585e9cb94..397a0bc322daf 100644
--- a/sys/mips/mediatek/std.rt2880
+++ b/sys/mips/mediatek/std.rt2880
@@ -73,9 +73,6 @@ device fdt_pinctrl
# UART support
device uart
-# random support
-device random
-
# loop device support
device loop
diff --git a/sys/modules/Makefile b/sys/modules/Makefile
index a9a5c5ed98efd..876a13f19ea92 100644
--- a/sys/modules/Makefile
+++ b/sys/modules/Makefile
@@ -255,8 +255,6 @@ SUBDIR= \
${_mwlfw} \
mxge \
my \
- ${_nandfs} \
- ${_nandsim} \
${_nctgpio} \
${_ndis} \
${_netgraph} \
@@ -489,11 +487,6 @@ _mlx5ib= mlx5ib
.endif
.endif
-.if ${MK_NAND} != "no" || defined(ALL_MODULES)
-_nandfs= nandfs
-_nandsim= nandsim
-.endif
-
.if ${MK_NETGRAPH} != "no" || defined(ALL_MODULES)
_netgraph= netgraph
.endif
diff --git a/sys/modules/nand/Makefile b/sys/modules/nand/Makefile
deleted file mode 100644
index c9d9962e897f4..0000000000000
--- a/sys/modules/nand/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-# $FreeBSD$
-
-.PATH: ${SRCTOP}/sys/dev/nand
-
-KMOD = nand
-SRCS= nand.c nand_bbt.c nand_cdev.c nand_generic.c nand_geom.c \
- nand_id.c nandbus.c nandbus_if.c nand_if.c nfc_if.c \
- nand_if.h device_if.h bus_if.h nfc_if.h nandbus_if.h
-
-.include <bsd.kmod.mk>
diff --git a/sys/modules/nandfs/Makefile b/sys/modules/nandfs/Makefile
deleted file mode 100644
index f13858c57c7b2..0000000000000
--- a/sys/modules/nandfs/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-# $FreeBSD$
-
-.PATH: ${SRCTOP}/sys/fs/nandfs
-
-KMOD= nandfs
-SRCS= vnode_if.h opt_ddb.h \
- bmap.c nandfs_bmap.c nandfs_dir.c nandfs_subr.c nandfs_vfsops.c \
- nandfs_vnops.c nandfs_alloc.c nandfs_cpfile.c nandfs_dat.c \
- nandfs_ifile.c nandfs_segment.c nandfs_sufile.c nandfs_buffer.c \
- nandfs_cleaner.c
-
-.include <bsd.kmod.mk>
diff --git a/sys/modules/nandsim/Makefile b/sys/modules/nandsim/Makefile
deleted file mode 100644
index 4f0aeca9eb4b7..0000000000000
--- a/sys/modules/nandsim/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-# $FreeBSD$
-
-.PATH: ${SRCTOP}/sys/dev/nand
-
-KMOD= nandsim
-SRCS= nandsim.c nandsim_chip.c nandsim_swap.c nandsim_ctrl.c nandsim_log.c\
- bus_if.h device_if.h vnode_if.h nfc_if.h nand_if.h
-
-.include <bsd.kmod.mk>
diff --git a/sys/net/if_vxlan.c b/sys/net/if_vxlan.c
index 81065bcec4319..5e35baae2dbc0 100644
--- a/sys/net/if_vxlan.c
+++ b/sys/net/if_vxlan.c
@@ -1134,7 +1134,7 @@ vxlan_socket_mc_join_group(struct vxlan_socket *vso,
* If we really need to, we can of course look in the INP's
* membership list:
* sotoinpcb(vso->vxlso_sock)->inp_moptions->
- * imo_membership[]->inm_ifp
+ * imo_head[]->imf_inm->inm_ifp
* similarly to imo_match_group().
*/
source->in4.sin_addr = local->in4.sin_addr;
diff --git a/sys/net/iflib.c b/sys/net/iflib.c
index d932e9373be0a..e33c2bec61e26 100644
--- a/sys/net/iflib.c
+++ b/sys/net/iflib.c
@@ -3580,10 +3580,10 @@ iflib_txq_drain(struct ifmp_ring *r, uint32_t cidx, uint32_t pidx)
iflib_txq_t txq = r->cookie;
if_ctx_t ctx = txq->ift_ctx;
if_t ifp = ctx->ifc_ifp;
- struct mbuf **mp, *m;
- int i, count, consumed, pkt_sent, bytes_sent, mcast_sent, avail;
- int reclaimed, err, in_use_prev, desc_used;
- bool do_prefetch, ring, rang;
+ struct mbuf *m, **mp;
+ int avail, bytes_sent, consumed, count, err, i, in_use_prev;
+ int mcast_sent, pkt_sent, reclaimed, txq_avail;
+ bool do_prefetch, rang, ring;
if (__predict_false(!(if_getdrvflags(ifp) & IFF_DRV_RUNNING) ||
!LINK_ACTIVE(ctx))) {
@@ -3621,16 +3621,15 @@ iflib_txq_drain(struct ifmp_ring *r, uint32_t cidx, uint32_t pidx)
avail, ctx->ifc_flags, TXQ_AVAIL(txq));
#endif
do_prefetch = (ctx->ifc_flags & IFC_PREFETCH);
- avail = TXQ_AVAIL(txq);
+ txq_avail = TXQ_AVAIL(txq);
err = 0;
- for (desc_used = i = 0; i < count && avail > MAX_TX_DESC(ctx) + 2; i++) {
+ for (i = 0; i < count && txq_avail > MAX_TX_DESC(ctx) + 2; i++) {
int rem = do_prefetch ? count - i : 0;
mp = _ring_peek_one(r, cidx, i, rem);
MPASS(mp != NULL && *mp != NULL);
if (__predict_false(*mp == (struct mbuf *)txq)) {
consumed++;
- reclaimed++;
continue;
}
in_use_prev = txq->ift_in_use;
@@ -3649,10 +3648,9 @@ iflib_txq_drain(struct ifmp_ring *r, uint32_t cidx, uint32_t pidx)
DBG_COUNTER_INC(tx_sent);
bytes_sent += m->m_pkthdr.len;
mcast_sent += !!(m->m_flags & M_MCAST);
- avail = TXQ_AVAIL(txq);
+ txq_avail = TXQ_AVAIL(txq);
txq->ift_db_pending += (txq->ift_in_use - in_use_prev);
- desc_used += (txq->ift_in_use - in_use_prev);
ETHER_BPF_MTAP(ifp, m);
if (__predict_false(!(ifp->if_drv_flags & IFF_DRV_RUNNING)))
break;
@@ -6155,9 +6153,6 @@ iflib_tx_credits_update(if_ctx_t ctx, iflib_txq_t txq)
int credits_pre = txq->ift_cidx_processed;
#endif
- if (ctx->isc_txd_credits_update == NULL)
- return (0);
-
bus_dmamap_sync(txq->ift_ifdi->idi_tag, txq->ift_ifdi->idi_map,
BUS_DMASYNC_POSTREAD);
if ((credits = ctx->isc_txd_credits_update(ctx->ifc_softc, txq->ift_id, true)) == 0)
diff --git a/sys/net/vnet.h b/sys/net/vnet.h
index b4168750e0263..a8c9887ed506b 100644
--- a/sys/net/vnet.h
+++ b/sys/net/vnet.h
@@ -273,7 +273,8 @@ extern struct sx vnet_sxlock;
/* struct _hack is to stop this from being used with static data */
#define VNET_DEFINE(t, n) \
struct _hack; t VNET_NAME(n) __section(VNET_SETNAME) __used
-#if defined(KLD_MODULE) && (defined(__aarch64__) || defined(__riscv))
+#if defined(KLD_MODULE) && (defined(__aarch64__) || defined(__riscv) \
+ || defined(__powerpc64__))
/*
* As with DPCPU_DEFINE_STATIC we are unable to mark this data as static
* in modules on some architectures.
diff --git a/sys/netinet/in.h b/sys/netinet/in.h
index 148d51eff36ae..cfa168f99be68 100644
--- a/sys/netinet/in.h
+++ b/sys/netinet/in.h
@@ -505,13 +505,9 @@ __END_DECLS
#define IP_DEFAULT_MULTICAST_LOOP 1 /* normally hear sends if a member */
/*
- * The imo_membership vector for each socket is now dynamically allocated at
- * run-time, bounded by USHRT_MAX, and is reallocated when needed, sized
- * according to a power-of-two increment.
+ * Limit for IPv4 multicast memberships
*/
-#define IP_MIN_MEMBERSHIPS 31
#define IP_MAX_MEMBERSHIPS 4095
-#define IP_MAX_SOURCE_FILTER 1024 /* XXX to be unused */
/*
* Default resource limits for IPv4 multicast source filtering.
diff --git a/sys/netinet/in_mcast.c b/sys/netinet/in_mcast.c
index 2980c1a463caa..ac5c6a03ab549 100644
--- a/sys/netinet/in_mcast.c
+++ b/sys/netinet/in_mcast.c
@@ -94,7 +94,9 @@ static MALLOC_DEFINE(M_IPMSOURCE, "ip_msource",
/*
* Locking:
- * - Lock order is: Giant, INP_WLOCK, IN_MULTI_LIST_LOCK, IGMP_LOCK, IF_ADDR_LOCK.
+ *
+ * - Lock order is: Giant, IN_MULTI_LOCK, INP_WLOCK,
+ * IN_MULTI_LIST_LOCK, IGMP_LOCK, IF_ADDR_LOCK.
* - The IF_ADDR_LOCK is implicitly taken by inm_lookup() earlier, however
* it can be taken by code in net/if.c also.
* - ip_moptions and in_mfilter are covered by the INP_WLOCK.
@@ -144,12 +146,11 @@ static int imf_prune(struct in_mfilter *, const struct sockaddr_in *);
static void imf_purge(struct in_mfilter *);
static void imf_rollback(struct in_mfilter *);
static void imf_reap(struct in_mfilter *);
-static int imo_grow(struct ip_moptions *);
-static size_t imo_match_group(const struct ip_moptions *,
+static struct in_mfilter *
+ imo_match_group(const struct ip_moptions *,
const struct ifnet *, const struct sockaddr *);
static struct in_msource *
- imo_match_source(const struct ip_moptions *, const size_t,
- const struct sockaddr *);
+ imo_match_source(struct in_mfilter *, const struct sockaddr *);
static void ims_merge(struct ip_msource *ims,
const struct in_msource *lims, const int rollback);
static int in_getmulti(struct ifnet *, const struct in_addr *,
@@ -333,6 +334,26 @@ imf_init(struct in_mfilter *imf, const int st0, const int st1)
imf->imf_st[1] = st1;
}
+struct in_mfilter *
+ip_mfilter_alloc(const int mflags, const int st0, const int st1)
+{
+ struct in_mfilter *imf;
+
+ imf = malloc(sizeof(*imf), M_INMFILTER, mflags);
+ if (imf != NULL)
+ imf_init(imf, st0, st1);
+
+ return (imf);
+}
+
+void
+ip_mfilter_free(struct in_mfilter *imf)
+{
+
+ imf_purge(imf);
+ free(imf, M_INMFILTER);
+}
+
/*
* Function for looking up an in_multi record for an IPv4 multicast address
* on a given interface. ifp must be valid. If no record found, return NULL.
@@ -379,89 +400,30 @@ inm_lookup(struct ifnet *ifp, const struct in_addr ina)
}
/*
- * Resize the ip_moptions vector to the next power-of-two minus 1.
- * May be called with locks held; do not sleep.
- */
-static int
-imo_grow(struct ip_moptions *imo)
-{
- struct in_multi **nmships;
- struct in_multi **omships;
- struct in_mfilter *nmfilters;
- struct in_mfilter *omfilters;
- size_t idx;
- size_t newmax;
- size_t oldmax;
-
- nmships = NULL;
- nmfilters = NULL;
- omships = imo->imo_membership;
- omfilters = imo->imo_mfilters;
- oldmax = imo->imo_max_memberships;
- newmax = ((oldmax + 1) * 2) - 1;
-
- if (newmax <= IP_MAX_MEMBERSHIPS) {
- nmships = (struct in_multi **)realloc(omships,
- sizeof(struct in_multi *) * newmax, M_IPMOPTS, M_NOWAIT);
- nmfilters = (struct in_mfilter *)realloc(omfilters,
- sizeof(struct in_mfilter) * newmax, M_INMFILTER, M_NOWAIT);
- if (nmships != NULL && nmfilters != NULL) {
- /* Initialize newly allocated source filter heads. */
- for (idx = oldmax; idx < newmax; idx++) {
- imf_init(&nmfilters[idx], MCAST_UNDEFINED,
- MCAST_EXCLUDE);
- }
- imo->imo_max_memberships = newmax;
- imo->imo_membership = nmships;
- imo->imo_mfilters = nmfilters;
- }
- }
-
- if (nmships == NULL || nmfilters == NULL) {
- if (nmships != NULL)
- free(nmships, M_IPMOPTS);
- if (nmfilters != NULL)
- free(nmfilters, M_INMFILTER);
- return (ETOOMANYREFS);
- }
-
- return (0);
-}
-
-/*
* Find an IPv4 multicast group entry for this ip_moptions instance
* which matches the specified group, and optionally an interface.
* Return its index into the array, or -1 if not found.
*/
-static size_t
+static struct in_mfilter *
imo_match_group(const struct ip_moptions *imo, const struct ifnet *ifp,
const struct sockaddr *group)
{
const struct sockaddr_in *gsin;
- struct in_multi **pinm;
- int idx;
- int nmships;
+ struct in_mfilter *imf;
+ struct in_multi *inm;
gsin = (const struct sockaddr_in *)group;
- /* The imo_membership array may be lazy allocated. */
- if (imo->imo_membership == NULL || imo->imo_num_memberships == 0)
- return (-1);
-
- nmships = imo->imo_num_memberships;
- pinm = &imo->imo_membership[0];
- for (idx = 0; idx < nmships; idx++, pinm++) {
- if (*pinm == NULL)
+ IP_MFILTER_FOREACH(imf, &imo->imo_head) {
+ inm = imf->imf_inm;
+ if (inm == NULL)
continue;
- if ((ifp == NULL || ((*pinm)->inm_ifp == ifp)) &&
- in_hosteq((*pinm)->inm_addr, gsin->sin_addr)) {
+ if ((ifp == NULL || (inm->inm_ifp == ifp)) &&
+ in_hosteq(inm->inm_addr, gsin->sin_addr)) {
break;
}
}
- if (idx >= nmships)
- idx = -1;
-
- return (idx);
+ return (imf);
}
/*
@@ -472,22 +434,13 @@ imo_match_group(const struct ip_moptions *imo, const struct ifnet *ifp,
* it exists, which may not be the desired behaviour.
*/
static struct in_msource *
-imo_match_source(const struct ip_moptions *imo, const size_t gidx,
- const struct sockaddr *src)
+imo_match_source(struct in_mfilter *imf, const struct sockaddr *src)
{
struct ip_msource find;
- struct in_mfilter *imf;
struct ip_msource *ims;
const sockunion_t *psa;
KASSERT(src->sa_family == AF_INET, ("%s: !AF_INET", __func__));
- KASSERT(gidx != -1 && gidx < imo->imo_num_memberships,
- ("%s: invalid index %d\n", __func__, (int)gidx));
-
- /* The imo_mfilters array may be lazy allocated. */
- if (imo->imo_mfilters == NULL)
- return (NULL);
- imf = &imo->imo_mfilters[gidx];
/* Source trees are keyed in host byte order. */
psa = (const sockunion_t *)src;
@@ -507,14 +460,14 @@ int
imo_multi_filter(const struct ip_moptions *imo, const struct ifnet *ifp,
const struct sockaddr *group, const struct sockaddr *src)
{
- size_t gidx;
+ struct in_mfilter *imf;
struct in_msource *ims;
int mode;
KASSERT(ifp != NULL, ("%s: null ifp", __func__));
- gidx = imo_match_group(imo, ifp, group);
- if (gidx == -1)
+ imf = imo_match_group(imo, ifp, group);
+ if (imf == NULL)
return (MCAST_NOTGMEMBER);
/*
@@ -526,8 +479,8 @@ imo_multi_filter(const struct ip_moptions *imo, const struct ifnet *ifp,
* NOTE: We are comparing group state here at IGMP t1 (now)
* with socket-layer t0 (since last downcall).
*/
- mode = imo->imo_mfilters[gidx].imf_st[1];
- ims = imo_match_source(imo, gidx, src);
+ mode = imf->imf_st[1];
+ ims = imo_match_source(imf, src);
if ((ims == NULL && mode == MCAST_INCLUDE) ||
(ims != NULL && ims->imsl_st[0] != mode))
@@ -1452,7 +1405,6 @@ inp_block_unblock_source(struct inpcb *inp, struct sockopt *sopt)
struct ip_moptions *imo;
struct in_msource *ims;
struct in_multi *inm;
- size_t idx;
uint16_t fmode;
int error, doblock;
@@ -1531,20 +1483,18 @@ inp_block_unblock_source(struct inpcb *inp, struct sockopt *sopt)
if (!IN_MULTICAST(ntohl(gsa->sin.sin_addr.s_addr)))
return (EINVAL);
+ IN_MULTI_LOCK();
+
/*
* Check if we are actually a member of this group.
*/
imo = inp_findmoptions(inp);
- idx = imo_match_group(imo, ifp, &gsa->sa);
- if (idx == -1 || imo->imo_mfilters == NULL) {
+ imf = imo_match_group(imo, ifp, &gsa->sa);
+ if (imf == NULL) {
error = EADDRNOTAVAIL;
goto out_inp_locked;
}
-
- KASSERT(imo->imo_mfilters != NULL,
- ("%s: imo_mfilters not allocated", __func__));
- imf = &imo->imo_mfilters[idx];
- inm = imo->imo_membership[idx];
+ inm = imf->imf_inm;
/*
* Attempting to use the delta-based API on an
@@ -1562,7 +1512,7 @@ inp_block_unblock_source(struct inpcb *inp, struct sockopt *sopt)
* Asked to unblock, but nothing to unblock.
* If adding a new block entry, allocate it.
*/
- ims = imo_match_source(imo, idx, &ssa->sa);
+ ims = imo_match_source(imf, &ssa->sa);
if ((ims != NULL && doblock) || (ims == NULL && !doblock)) {
CTR3(KTR_IGMPV3, "%s: source 0x%08x %spresent", __func__,
ntohl(ssa->sin.sin_addr.s_addr), doblock ? "" : "not ");
@@ -1593,14 +1543,13 @@ inp_block_unblock_source(struct inpcb *inp, struct sockopt *sopt)
/*
* Begin state merge transaction at IGMP layer.
*/
- IN_MULTI_LOCK();
CTR1(KTR_IGMPV3, "%s: merge inm state", __func__);
IN_MULTI_LIST_LOCK();
error = inm_merge(inm, imf);
if (error) {
CTR1(KTR_IGMPV3, "%s: failed to merge inm state", __func__);
IN_MULTI_LIST_UNLOCK();
- goto out_in_multi_locked;
+ goto out_imf_rollback;
}
CTR1(KTR_IGMPV3, "%s: doing igmp downcall", __func__);
@@ -1609,9 +1558,6 @@ inp_block_unblock_source(struct inpcb *inp, struct sockopt *sopt)
if (error)
CTR1(KTR_IGMPV3, "%s: failed igmp downcall", __func__);
-out_in_multi_locked:
-
- IN_MULTI_UNLOCK();
out_imf_rollback:
if (error)
imf_rollback(imf);
@@ -1622,6 +1568,7 @@ out_imf_rollback:
out_inp_locked:
INP_WUNLOCK(inp);
+ IN_MULTI_UNLOCK();
return (error);
}
@@ -1636,9 +1583,6 @@ static struct ip_moptions *
inp_findmoptions(struct inpcb *inp)
{
struct ip_moptions *imo;
- struct in_multi **immp;
- struct in_mfilter *imfp;
- size_t idx;
INP_WLOCK(inp);
if (inp->inp_moptions != NULL)
@@ -1647,29 +1591,16 @@ inp_findmoptions(struct inpcb *inp)
INP_WUNLOCK(inp);
imo = malloc(sizeof(*imo), M_IPMOPTS, M_WAITOK);
- immp = malloc(sizeof(*immp) * IP_MIN_MEMBERSHIPS, M_IPMOPTS,
- M_WAITOK | M_ZERO);
- imfp = malloc(sizeof(struct in_mfilter) * IP_MIN_MEMBERSHIPS,
- M_INMFILTER, M_WAITOK);
imo->imo_multicast_ifp = NULL;
imo->imo_multicast_addr.s_addr = INADDR_ANY;
imo->imo_multicast_vif = -1;
imo->imo_multicast_ttl = IP_DEFAULT_MULTICAST_TTL;
imo->imo_multicast_loop = in_mcast_loop;
- imo->imo_num_memberships = 0;
- imo->imo_max_memberships = IP_MIN_MEMBERSHIPS;
- imo->imo_membership = immp;
-
- /* Initialize per-group source filters. */
- for (idx = 0; idx < IP_MIN_MEMBERSHIPS; idx++)
- imf_init(&imfp[idx], MCAST_UNDEFINED, MCAST_EXCLUDE);
- imo->imo_mfilters = imfp;
+ STAILQ_INIT(&imo->imo_head);
INP_WLOCK(inp);
if (inp->inp_moptions != NULL) {
- free(imfp, M_INMFILTER);
- free(immp, M_IPMOPTS);
free(imo, M_IPMOPTS);
return (inp->inp_moptions);
}
@@ -1680,32 +1611,25 @@ inp_findmoptions(struct inpcb *inp)
static void
inp_gcmoptions(struct ip_moptions *imo)
{
- struct in_mfilter *imf;
+ struct in_mfilter *imf;
struct in_multi *inm;
struct ifnet *ifp;
- size_t idx, nmships;
- nmships = imo->imo_num_memberships;
- for (idx = 0; idx < nmships; ++idx) {
- imf = imo->imo_mfilters ? &imo->imo_mfilters[idx] : NULL;
- if (imf)
- imf_leave(imf);
- inm = imo->imo_membership[idx];
- ifp = inm->inm_ifp;
- if (ifp != NULL) {
- CURVNET_SET(ifp->if_vnet);
- (void)in_leavegroup(inm, imf);
- CURVNET_RESTORE();
- } else {
- (void)in_leavegroup(inm, imf);
+ while ((imf = ip_mfilter_first(&imo->imo_head)) != NULL) {
+ ip_mfilter_remove(&imo->imo_head, imf);
+
+ imf_leave(imf);
+ if ((inm = imf->imf_inm) != NULL) {
+ if ((ifp = inm->inm_ifp) != NULL) {
+ CURVNET_SET(ifp->if_vnet);
+ (void)in_leavegroup(inm, imf);
+ CURVNET_RESTORE();
+ } else {
+ (void)in_leavegroup(inm, imf);
+ }
}
- if (imf)
- imf_purge(imf);
+ ip_mfilter_free(imf);
}
-
- if (imo->imo_mfilters)
- free(imo->imo_mfilters, M_INMFILTER);
- free(imo->imo_membership, M_IPMOPTS);
free(imo, M_IPMOPTS);
}
@@ -1741,7 +1665,7 @@ inp_get_source_filters(struct inpcb *inp, struct sockopt *sopt)
struct sockaddr_storage *ptss;
struct sockaddr_storage *tss;
int error;
- size_t idx, nsrcs, ncsrcs;
+ size_t nsrcs, ncsrcs;
INP_WLOCK_ASSERT(inp);
@@ -1768,12 +1692,11 @@ inp_get_source_filters(struct inpcb *inp, struct sockopt *sopt)
* Lookup group on the socket.
*/
gsa = (sockunion_t *)&msfr.msfr_group;
- idx = imo_match_group(imo, ifp, &gsa->sa);
- if (idx == -1 || imo->imo_mfilters == NULL) {
+ imf = imo_match_group(imo, ifp, &gsa->sa);
+ if (imf == NULL) {
INP_WUNLOCK(inp);
return (EADDRNOTAVAIL);
}
- imf = &imo->imo_mfilters[idx];
/*
* Ignore memberships which are in limbo.
@@ -2033,14 +1956,11 @@ inp_join_group(struct inpcb *inp, struct sockopt *sopt)
struct ip_moptions *imo;
struct in_multi *inm;
struct in_msource *lims;
- size_t idx;
int error, is_new;
ifp = NULL;
- imf = NULL;
lims = NULL;
error = 0;
- is_new = 0;
memset(&gsr, 0, sizeof(struct group_source_req));
gsa = (sockunion_t *)&gsr.gsr_group;
@@ -2148,13 +2068,25 @@ inp_join_group(struct inpcb *inp, struct sockopt *sopt)
if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0)
return (EADDRNOTAVAIL);
+ IN_MULTI_LOCK();
+
+ /*
+ * Find the membership in the membership list.
+ */
imo = inp_findmoptions(inp);
- idx = imo_match_group(imo, ifp, &gsa->sa);
- if (idx == -1) {
+ imf = imo_match_group(imo, ifp, &gsa->sa);
+ if (imf == NULL) {
is_new = 1;
+ inm = NULL;
+
+ if (ip_mfilter_count(&imo->imo_head) >= IP_MAX_MEMBERSHIPS) {
+ error = ENOMEM;
+ goto out_inp_locked;
+ }
} else {
- inm = imo->imo_membership[idx];
- imf = &imo->imo_mfilters[idx];
+ is_new = 0;
+ inm = imf->imf_inm;
+
if (ssa->ss.ss_family != AF_UNSPEC) {
/*
* MCAST_JOIN_SOURCE_GROUP on an exclusive membership
@@ -2181,7 +2113,7 @@ inp_join_group(struct inpcb *inp, struct sockopt *sopt)
* full-state SSM API with the delta-based API,
* which is discouraged in the relevant RFCs.
*/
- lims = imo_match_source(imo, idx, &ssa->sa);
+ lims = imo_match_source(imf, &ssa->sa);
if (lims != NULL /*&&
lims->imsl_st[1] == MCAST_INCLUDE*/) {
error = EADDRNOTAVAIL;
@@ -2214,27 +2146,6 @@ inp_join_group(struct inpcb *inp, struct sockopt *sopt)
*/
INP_WLOCK_ASSERT(inp);
- if (is_new) {
- if (imo->imo_num_memberships == imo->imo_max_memberships) {
- error = imo_grow(imo);
- if (error)
- goto out_inp_locked;
- }
- /*
- * Allocate the new slot upfront so we can deal with
- * grafting the new source filter in same code path
- * as for join-source on existing membership.
- */
- idx = imo->imo_num_memberships;
- imo->imo_membership[idx] = NULL;
- imo->imo_num_memberships++;
- KASSERT(imo->imo_mfilters != NULL,
- ("%s: imf_mfilters vector was not allocated", __func__));
- imf = &imo->imo_mfilters[idx];
- KASSERT(RB_EMPTY(&imf->imf_sources),
- ("%s: imf_sources not empty", __func__));
- }
-
/*
* Graft new source into filter list for this inpcb's
* membership of the group. The in_multi may not have
@@ -2250,7 +2161,11 @@ inp_join_group(struct inpcb *inp, struct sockopt *sopt)
/* Membership starts in IN mode */
if (is_new) {
CTR1(KTR_IGMPV3, "%s: new join w/source", __func__);
- imf_init(imf, MCAST_UNDEFINED, MCAST_INCLUDE);
+ imf = ip_mfilter_alloc(M_NOWAIT, MCAST_UNDEFINED, MCAST_INCLUDE);
+ if (imf == NULL) {
+ error = ENOMEM;
+ goto out_inp_locked;
+ }
} else {
CTR2(KTR_IGMPV3, "%s: %s source", __func__, "allow");
}
@@ -2259,34 +2174,41 @@ inp_join_group(struct inpcb *inp, struct sockopt *sopt)
CTR1(KTR_IGMPV3, "%s: merge imf state failed",
__func__);
error = ENOMEM;
- goto out_imo_free;
+ goto out_inp_locked;
}
} else {
/* No address specified; Membership starts in EX mode */
if (is_new) {
CTR1(KTR_IGMPV3, "%s: new join w/o source", __func__);
- imf_init(imf, MCAST_UNDEFINED, MCAST_EXCLUDE);
+ imf = ip_mfilter_alloc(M_NOWAIT, MCAST_UNDEFINED, MCAST_EXCLUDE);
+ if (imf == NULL) {
+ error = ENOMEM;
+ goto out_inp_locked;
+ }
}
}
/*
* Begin state merge transaction at IGMP layer.
*/
- in_pcbref(inp);
- INP_WUNLOCK(inp);
- IN_MULTI_LOCK();
-
if (is_new) {
+ in_pcbref(inp);
+ INP_WUNLOCK(inp);
+
error = in_joingroup_locked(ifp, &gsa->sin.sin_addr, imf,
- &inm);
+ &imf->imf_inm);
+
+ INP_WLOCK(inp);
+ if (in_pcbrele_wlocked(inp)) {
+ error = ENXIO;
+ goto out_inp_unlocked;
+ }
if (error) {
CTR1(KTR_IGMPV3, "%s: in_joingroup_locked failed",
__func__);
- IN_MULTI_LIST_UNLOCK();
- goto out_imo_free;
+ goto out_inp_locked;
}
- inm_acquire(inm);
- imo->imo_membership[idx] = inm;
+ inm_acquire(imf->imf_inm);
} else {
CTR1(KTR_IGMPV3, "%s: merge inm state", __func__);
IN_MULTI_LIST_LOCK();
@@ -2295,7 +2217,9 @@ inp_join_group(struct inpcb *inp, struct sockopt *sopt)
CTR1(KTR_IGMPV3, "%s: failed to merge inm state",
__func__);
IN_MULTI_LIST_UNLOCK();
- goto out_in_multi_locked;
+ imf_rollback(imf);
+ imf_reap(imf);
+ goto out_inp_locked;
}
CTR1(KTR_IGMPV3, "%s: doing igmp downcall", __func__);
error = igmp_change_state(inm);
@@ -2303,40 +2227,30 @@ inp_join_group(struct inpcb *inp, struct sockopt *sopt)
if (error) {
CTR1(KTR_IGMPV3, "%s: failed igmp downcall",
__func__);
- goto out_in_multi_locked;
+ imf_rollback(imf);
+ imf_reap(imf);
+ goto out_inp_locked;
}
}
+ if (is_new)
+ ip_mfilter_insert(&imo->imo_head, imf);
-out_in_multi_locked:
+ imf_commit(imf);
+ imf = NULL;
+out_inp_locked:
+ INP_WUNLOCK(inp);
+out_inp_unlocked:
IN_MULTI_UNLOCK();
- INP_WLOCK(inp);
- if (in_pcbrele_wlocked(inp))
- return (ENXIO);
- if (error) {
- imf_rollback(imf);
- if (is_new)
- imf_purge(imf);
- else
- imf_reap(imf);
- } else {
- imf_commit(imf);
- }
-out_imo_free:
- if (error && is_new) {
- inm = imo->imo_membership[idx];
- if (inm != NULL) {
+ if (is_new && imf) {
+ if (imf->imf_inm != NULL) {
IN_MULTI_LIST_LOCK();
- inm_release_deferred(inm);
+ inm_release_deferred(imf->imf_inm);
IN_MULTI_LIST_UNLOCK();
}
- imo->imo_membership[idx] = NULL;
- --imo->imo_num_memberships;
+ ip_mfilter_free(imf);
}
-
-out_inp_locked:
- INP_WUNLOCK(inp);
return (error);
}
@@ -2355,12 +2269,12 @@ inp_leave_group(struct inpcb *inp, struct sockopt *sopt)
struct ip_moptions *imo;
struct in_msource *ims;
struct in_multi *inm;
- size_t idx;
- int error, is_final;
+ int error;
+ bool is_final;
ifp = NULL;
error = 0;
- is_final = 1;
+ is_final = true;
memset(&gsr, 0, sizeof(struct group_source_req));
gsa = (sockunion_t *)&gsr.gsr_group;
@@ -2460,20 +2374,21 @@ inp_leave_group(struct inpcb *inp, struct sockopt *sopt)
if (!IN_MULTICAST(ntohl(gsa->sin.sin_addr.s_addr)))
return (EINVAL);
+ IN_MULTI_LOCK();
+
/*
- * Find the membership in the membership array.
+ * Find the membership in the membership list.
*/
imo = inp_findmoptions(inp);
- idx = imo_match_group(imo, ifp, &gsa->sa);
- if (idx == -1) {
+ imf = imo_match_group(imo, ifp, &gsa->sa);
+ if (imf == NULL) {
error = EADDRNOTAVAIL;
goto out_inp_locked;
}
- inm = imo->imo_membership[idx];
- imf = &imo->imo_mfilters[idx];
+ inm = imf->imf_inm;
if (ssa->ss.ss_family != AF_UNSPEC)
- is_final = 0;
+ is_final = false;
/*
* Begin state merge transaction at socket layer.
@@ -2485,13 +2400,14 @@ inp_leave_group(struct inpcb *inp, struct sockopt *sopt)
* MCAST_LEAVE_SOURCE_GROUP is only valid for inclusive memberships.
*/
if (is_final) {
+ ip_mfilter_remove(&imo->imo_head, imf);
imf_leave(imf);
} else {
if (imf->imf_st[0] == MCAST_EXCLUDE) {
error = EADDRNOTAVAIL;
goto out_inp_locked;
}
- ims = imo_match_source(imo, idx, &ssa->sa);
+ ims = imo_match_source(imf, &ssa->sa);
if (ims == NULL) {
CTR3(KTR_IGMPV3, "%s: source 0x%08x %spresent",
__func__, ntohl(ssa->sin.sin_addr.s_addr), "not ");
@@ -2510,17 +2426,7 @@ inp_leave_group(struct inpcb *inp, struct sockopt *sopt)
/*
* Begin state merge transaction at IGMP layer.
*/
- in_pcbref(inp);
- INP_WUNLOCK(inp);
- IN_MULTI_LOCK();
-
- if (is_final) {
- /*
- * Give up the multicast address record to which
- * the membership points.
- */
- (void)in_leavegroup_locked(inm, imf);
- } else {
+ if (!is_final) {
CTR1(KTR_IGMPV3, "%s: merge inm state", __func__);
IN_MULTI_LIST_LOCK();
error = inm_merge(inm, imf);
@@ -2528,7 +2434,9 @@ inp_leave_group(struct inpcb *inp, struct sockopt *sopt)
CTR1(KTR_IGMPV3, "%s: failed to merge inm state",
__func__);
IN_MULTI_LIST_UNLOCK();
- goto out_in_multi_locked;
+ imf_rollback(imf);
+ imf_reap(imf);
+ goto out_inp_locked;
}
CTR1(KTR_IGMPV3, "%s: doing igmp downcall", __func__);
@@ -2537,38 +2445,27 @@ inp_leave_group(struct inpcb *inp, struct sockopt *sopt)
if (error) {
CTR1(KTR_IGMPV3, "%s: failed igmp downcall",
__func__);
+ imf_rollback(imf);
+ imf_reap(imf);
+ goto out_inp_locked;
}
}
-
-out_in_multi_locked:
-
- IN_MULTI_UNLOCK();
- INP_WLOCK(inp);
- if (in_pcbrele_wlocked(inp))
- return (ENXIO);
-
- if (error)
- imf_rollback(imf);
- else
- imf_commit(imf);
-
+ imf_commit(imf);
imf_reap(imf);
- if (is_final) {
- /* Remove the gap in the membership and filter array. */
- KASSERT(RB_EMPTY(&imf->imf_sources),
- ("%s: imf_sources not empty", __func__));
- for (++idx; idx < imo->imo_num_memberships; ++idx) {
- imo->imo_membership[idx - 1] = imo->imo_membership[idx];
- imo->imo_mfilters[idx - 1] = imo->imo_mfilters[idx];
- }
- imf_init(&imo->imo_mfilters[idx - 1], MCAST_UNDEFINED,
- MCAST_EXCLUDE);
- imo->imo_num_memberships--;
- }
-
out_inp_locked:
INP_WUNLOCK(inp);
+
+ if (is_final && imf) {
+ /*
+ * Give up the multicast address record to which
+ * the membership points.
+ */
+ (void) in_leavegroup_locked(imf->imf_inm, imf);
+ ip_mfilter_free(imf);
+ }
+
+ IN_MULTI_UNLOCK();
return (error);
}
@@ -2658,7 +2555,6 @@ inp_set_source_filters(struct inpcb *inp, struct sockopt *sopt)
struct in_mfilter *imf;
struct ip_moptions *imo;
struct in_multi *inm;
- size_t idx;
int error;
error = sooptcopyin(sopt, &msfr, sizeof(struct __msfilterreq),
@@ -2690,18 +2586,19 @@ inp_set_source_filters(struct inpcb *inp, struct sockopt *sopt)
if (ifp == NULL)
return (EADDRNOTAVAIL);
+ IN_MULTI_LOCK();
+
/*
* Take the INP write lock.
* Check if this socket is a member of this group.
*/
imo = inp_findmoptions(inp);
- idx = imo_match_group(imo, ifp, &gsa->sa);
- if (idx == -1 || imo->imo_mfilters == NULL) {
+ imf = imo_match_group(imo, ifp, &gsa->sa);
+ if (imf == NULL) {
error = EADDRNOTAVAIL;
goto out_inp_locked;
}
- inm = imo->imo_membership[idx];
- imf = &imo->imo_mfilters[idx];
+ inm = imf->imf_inm;
/*
* Begin state merge transaction at socket layer.
@@ -2778,7 +2675,6 @@ inp_set_source_filters(struct inpcb *inp, struct sockopt *sopt)
goto out_imf_rollback;
INP_WLOCK_ASSERT(inp);
- IN_MULTI_LOCK();
/*
* Begin state merge transaction at IGMP layer.
@@ -2789,7 +2685,7 @@ inp_set_source_filters(struct inpcb *inp, struct sockopt *sopt)
if (error) {
CTR1(KTR_IGMPV3, "%s: failed to merge inm state", __func__);
IN_MULTI_LIST_UNLOCK();
- goto out_in_multi_locked;
+ goto out_imf_rollback;
}
CTR1(KTR_IGMPV3, "%s: doing igmp downcall", __func__);
@@ -2798,10 +2694,6 @@ inp_set_source_filters(struct inpcb *inp, struct sockopt *sopt)
if (error)
CTR1(KTR_IGMPV3, "%s: failed igmp downcall", __func__);
-out_in_multi_locked:
-
- IN_MULTI_UNLOCK();
-
out_imf_rollback:
if (error)
imf_rollback(imf);
@@ -2812,6 +2704,7 @@ out_imf_rollback:
out_inp_locked:
INP_WUNLOCK(inp);
+ IN_MULTI_UNLOCK();
return (error);
}
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
index 17fa348955958..b68475afa6557 100644
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -86,6 +86,9 @@ __FBSDID("$FreeBSD$");
#if defined(INET) || defined(INET6)
#include <netinet/in.h>
#include <netinet/in_pcb.h>
+#ifdef INET
+#include <netinet/in_var.h>
+#endif
#include <netinet/ip_var.h>
#include <netinet/tcp_var.h>
#ifdef TCPHPTS
@@ -93,16 +96,13 @@ __FBSDID("$FreeBSD$");
#endif
#include <netinet/udp.h>
#include <netinet/udp_var.h>
-#endif
-#ifdef INET
-#include <netinet/in_var.h>
-#endif
#ifdef INET6
#include <netinet/ip6.h>
#include <netinet6/in6_pcb.h>
#include <netinet6/in6_var.h>
#include <netinet6/ip6_var.h>
#endif /* INET6 */
+#endif
#include <netipsec/ipsec_support.h>
@@ -1779,8 +1779,9 @@ void
in_pcbpurgeif0(struct inpcbinfo *pcbinfo, struct ifnet *ifp)
{
struct inpcb *inp;
+ struct in_multi *inm;
+ struct in_mfilter *imf;
struct ip_moptions *imo;
- int i, gap;
INP_INFO_WLOCK(pcbinfo);
CK_LIST_FOREACH(inp, pcbinfo->ipi_listhead, inp_list) {
@@ -1801,17 +1802,18 @@ in_pcbpurgeif0(struct inpcbinfo *pcbinfo, struct ifnet *ifp)
*
* XXX This can all be deferred to an epoch_call
*/
- for (i = 0, gap = 0; i < imo->imo_num_memberships;
- i++) {
- if (imo->imo_membership[i]->inm_ifp == ifp) {
- IN_MULTI_LOCK_ASSERT();
- in_leavegroup_locked(imo->imo_membership[i], NULL);
- gap++;
- } else if (gap != 0)
- imo->imo_membership[i - gap] =
- imo->imo_membership[i];
+restart:
+ IP_MFILTER_FOREACH(imf, &imo->imo_head) {
+ if ((inm = imf->imf_inm) == NULL)
+ continue;
+ if (inm->inm_ifp != ifp)
+ continue;
+ ip_mfilter_remove(&imo->imo_head, imf);
+ IN_MULTI_LOCK_ASSERT();
+ in_leavegroup_locked(inm, NULL);
+ ip_mfilter_free(imf);
+ goto restart;
}
- imo->imo_num_memberships -= gap;
}
INP_WUNLOCK(inp);
}
diff --git a/sys/netinet/in_var.h b/sys/netinet/in_var.h
index 5b7a464bd3e82..50112481f2364 100644
--- a/sys/netinet/in_var.h
+++ b/sys/netinet/in_var.h
@@ -232,9 +232,61 @@ struct in_mfilter {
struct ip_msource_tree imf_sources; /* source list for (S,G) */
u_long imf_nsrc; /* # of source entries */
uint8_t imf_st[2]; /* state before/at commit */
+ struct in_multi *imf_inm; /* associated multicast address */
+ STAILQ_ENTRY(in_mfilter) imf_entry; /* list entry */
};
/*
+ * Helper types and functions for IPv4 multicast filters.
+ */
+STAILQ_HEAD(ip_mfilter_head, in_mfilter);
+
+struct in_mfilter *ip_mfilter_alloc(int mflags, int st0, int st1);
+void ip_mfilter_free(struct in_mfilter *);
+
+static inline void
+ip_mfilter_init(struct ip_mfilter_head *head)
+{
+
+ STAILQ_INIT(head);
+}
+
+static inline struct in_mfilter *
+ip_mfilter_first(const struct ip_mfilter_head *head)
+{
+
+ return (STAILQ_FIRST(head));
+}
+
+static inline void
+ip_mfilter_insert(struct ip_mfilter_head *head, struct in_mfilter *imf)
+{
+
+ STAILQ_INSERT_TAIL(head, imf, imf_entry);
+}
+
+static inline void
+ip_mfilter_remove(struct ip_mfilter_head *head, struct in_mfilter *imf)
+{
+
+ STAILQ_REMOVE(head, imf, in_mfilter, imf_entry);
+}
+
+#define IP_MFILTER_FOREACH(imf, head) \
+ STAILQ_FOREACH(imf, head, imf_entry)
+
+static inline size_t
+ip_mfilter_count(struct ip_mfilter_head *head)
+{
+ struct in_mfilter *imf;
+ size_t num = 0;
+
+ STAILQ_FOREACH(imf, head, imf_entry)
+ num++;
+ return (num);
+}
+
+/*
* IPv4 group descriptor.
*
* For every entry on an ifnet's if_multiaddrs list which represents
diff --git a/sys/netinet/ip_carp.c b/sys/netinet/ip_carp.c
index 9c24fb9fdd67b..819a0f9c75e6b 100644
--- a/sys/netinet/ip_carp.c
+++ b/sys/netinet/ip_carp.c
@@ -1371,25 +1371,24 @@ carp_multicast_setup(struct carp_if *cif, sa_family_t sa)
case AF_INET:
{
struct ip_moptions *imo = &cif->cif_imo;
+ struct in_mfilter *imf;
struct in_addr addr;
- if (imo->imo_membership)
+ if (ip_mfilter_first(&imo->imo_head) != NULL)
return (0);
- imo->imo_membership = (struct in_multi **)malloc(
- (sizeof(struct in_multi *) * IP_MIN_MEMBERSHIPS), M_CARP,
- M_WAITOK);
- imo->imo_mfilters = NULL;
- imo->imo_max_memberships = IP_MIN_MEMBERSHIPS;
+ imf = ip_mfilter_alloc(M_WAITOK, 0, 0);
+ ip_mfilter_init(&imo->imo_head);
imo->imo_multicast_vif = -1;
addr.s_addr = htonl(INADDR_CARP_GROUP);
if ((error = in_joingroup(ifp, &addr, NULL,
- &imo->imo_membership[0])) != 0) {
- free(imo->imo_membership, M_CARP);
+ &imf->imf_inm)) != 0) {
+ ip_mfilter_free(imf);
break;
}
- imo->imo_num_memberships++;
+
+ ip_mfilter_insert(&imo->imo_head, imf);
imo->imo_multicast_ifp = ifp;
imo->imo_multicast_ttl = CARP_DFLTTL;
imo->imo_multicast_loop = 0;
@@ -1400,17 +1399,16 @@ carp_multicast_setup(struct carp_if *cif, sa_family_t sa)
case AF_INET6:
{
struct ip6_moptions *im6o = &cif->cif_im6o;
+ struct in6_mfilter *im6f[2];
struct in6_addr in6;
- struct in6_multi *in6m;
- if (im6o->im6o_membership)
+ if (ip6_mfilter_first(&im6o->im6o_head))
return (0);
- im6o->im6o_membership = (struct in6_multi **)malloc(
- (sizeof(struct in6_multi *) * IPV6_MIN_MEMBERSHIPS), M_CARP,
- M_ZERO | M_WAITOK);
- im6o->im6o_mfilters = NULL;
- im6o->im6o_max_memberships = IPV6_MIN_MEMBERSHIPS;
+ im6f[0] = ip6_mfilter_alloc(M_WAITOK, 0, 0);
+ im6f[1] = ip6_mfilter_alloc(M_WAITOK, 0, 0);
+
+ ip6_mfilter_init(&im6o->im6o_head);
im6o->im6o_multicast_hlim = CARP_DFLTTL;
im6o->im6o_multicast_ifp = ifp;
@@ -1419,17 +1417,15 @@ carp_multicast_setup(struct carp_if *cif, sa_family_t sa)
in6.s6_addr16[0] = htons(0xff02);
in6.s6_addr8[15] = 0x12;
if ((error = in6_setscope(&in6, ifp, NULL)) != 0) {
- free(im6o->im6o_membership, M_CARP);
+ ip6_mfilter_free(im6f[0]);
+ ip6_mfilter_free(im6f[1]);
break;
}
- in6m = NULL;
- if ((error = in6_joingroup(ifp, &in6, NULL, &in6m, 0)) != 0) {
- free(im6o->im6o_membership, M_CARP);
+ if ((error = in6_joingroup(ifp, &in6, NULL, &im6f[0]->im6f_in6m, 0)) != 0) {
+ ip6_mfilter_free(im6f[0]);
+ ip6_mfilter_free(im6f[1]);
break;
}
- in6m_acquire(in6m);
- im6o->im6o_membership[0] = in6m;
- im6o->im6o_num_memberships++;
/* Join solicited multicast address. */
bzero(&in6, sizeof(in6));
@@ -1438,20 +1434,21 @@ carp_multicast_setup(struct carp_if *cif, sa_family_t sa)
in6.s6_addr32[2] = htonl(1);
in6.s6_addr32[3] = 0;
in6.s6_addr8[12] = 0xff;
+
if ((error = in6_setscope(&in6, ifp, NULL)) != 0) {
- in6_leavegroup(im6o->im6o_membership[0], NULL);
- free(im6o->im6o_membership, M_CARP);
+ ip6_mfilter_free(im6f[0]);
+ ip6_mfilter_free(im6f[1]);
break;
}
- in6m = NULL;
- if ((error = in6_joingroup(ifp, &in6, NULL, &in6m, 0)) != 0) {
- in6_leavegroup(im6o->im6o_membership[0], NULL);
- free(im6o->im6o_membership, M_CARP);
+
+ if ((error = in6_joingroup(ifp, &in6, NULL, &im6f[1]->im6f_in6m, 0)) != 0) {
+ in6_leavegroup(im6f[0]->im6f_in6m, NULL);
+ ip6_mfilter_free(im6f[0]);
+ ip6_mfilter_free(im6f[1]);
break;
}
- in6m_acquire(in6m);
- im6o->im6o_membership[1] = in6m;
- im6o->im6o_num_memberships++;
+ ip6_mfilter_insert(&im6o->im6o_head, im6f[0]);
+ ip6_mfilter_insert(&im6o->im6o_head, im6f[1]);
break;
}
#endif
@@ -1466,35 +1463,38 @@ carp_multicast_setup(struct carp_if *cif, sa_family_t sa)
static void
carp_multicast_cleanup(struct carp_if *cif, sa_family_t sa)
{
-
+#ifdef INET
+ struct ip_moptions *imo = &cif->cif_imo;
+ struct in_mfilter *imf;
+#endif
+#ifdef INET6
+ struct ip6_moptions *im6o = &cif->cif_im6o;
+ struct in6_mfilter *im6f;
+#endif
sx_assert(&carp_sx, SA_XLOCKED);
switch (sa) {
#ifdef INET
case AF_INET:
- if (cif->cif_naddrs == 0) {
- struct ip_moptions *imo = &cif->cif_imo;
-
- in_leavegroup(imo->imo_membership[0], NULL);
- KASSERT(imo->imo_mfilters == NULL,
- ("%s: imo_mfilters != NULL", __func__));
- free(imo->imo_membership, M_CARP);
- imo->imo_membership = NULL;
+ if (cif->cif_naddrs != 0)
+ break;
+ while ((imf = ip_mfilter_first(&imo->imo_head)) != NULL) {
+ ip_mfilter_remove(&imo->imo_head, imf);
+ in_leavegroup(imf->imf_inm, NULL);
+ ip_mfilter_free(imf);
}
break;
#endif
#ifdef INET6
case AF_INET6:
- if (cif->cif_naddrs6 == 0) {
- struct ip6_moptions *im6o = &cif->cif_im6o;
+ if (cif->cif_naddrs6 != 0)
+ break;
- in6_leavegroup(im6o->im6o_membership[0], NULL);
- in6_leavegroup(im6o->im6o_membership[1], NULL);
- KASSERT(im6o->im6o_mfilters == NULL,
- ("%s: im6o_mfilters != NULL", __func__));
- free(im6o->im6o_membership, M_CARP);
- im6o->im6o_membership = NULL;
+ while ((im6f = ip6_mfilter_first(&im6o->im6o_head)) != NULL) {
+ ip6_mfilter_remove(&im6o->im6o_head, im6f);
+ in6_leavegroup(im6f->im6f_in6m, NULL);
+ ip6_mfilter_free(im6f);
}
break;
#endif
diff --git a/sys/netinet/ip_fw.h b/sys/netinet/ip_fw.h
index de0cc29db1d21..7a01c82ba58b6 100644
--- a/sys/netinet/ip_fw.h
+++ b/sys/netinet/ip_fw.h
@@ -293,6 +293,7 @@ enum ipfw_opcodes { /* arguments (4 byte each) */
O_EXTERNAL_DATA, /* variable length data */
O_SKIP_ACTION, /* none */
+ O_TCPMSS, /* arg1=MSS value */
O_LAST_OPCODE /* not an opcode! */
};
diff --git a/sys/netinet/ip_mroute.c b/sys/netinet/ip_mroute.c
index 0439d353575dc..14ebb6ef10079 100644
--- a/sys/netinet/ip_mroute.c
+++ b/sys/netinet/ip_mroute.c
@@ -1680,7 +1680,6 @@ static void
send_packet(struct vif *vifp, struct mbuf *m)
{
struct ip_moptions imo;
- struct in_multi *imm[2];
int error __unused;
VIF_LOCK_ASSERT();
@@ -1689,9 +1688,7 @@ send_packet(struct vif *vifp, struct mbuf *m)
imo.imo_multicast_ttl = mtod(m, struct ip *)->ip_ttl - 1;
imo.imo_multicast_loop = 1;
imo.imo_multicast_vif = -1;
- imo.imo_num_memberships = 0;
- imo.imo_max_memberships = 2;
- imo.imo_membership = &imm[0];
+ STAILQ_INIT(&imo.imo_head);
/*
* Re-entrancy should not be a problem here, because
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
index 99b8c3662be50..2a7eb7f562862 100644
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -109,20 +109,24 @@ extern int in_mcast_loop;
extern struct protosw inetsw[];
static inline int
-ip_output_pfil(struct mbuf **mp, struct ifnet *ifp, struct inpcb *inp,
- struct sockaddr_in *dst, int *fibnum, int *error)
+ip_output_pfil(struct mbuf **mp, struct ifnet *ifp, int flags,
+ struct inpcb *inp, struct sockaddr_in *dst, int *fibnum, int *error)
{
struct m_tag *fwd_tag = NULL;
struct mbuf *m;
struct in_addr odst;
struct ip *ip;
+ int pflags = PFIL_OUT;
+
+ if (flags & IP_FORWARDING)
+ pflags |= PFIL_FWD;
m = *mp;
ip = mtod(m, struct ip *);
/* Run through list of hooks for output packets. */
odst.s_addr = ip->ip_dst.s_addr;
- switch (pfil_run_hooks(V_inet_pfil_head, mp, ifp, PFIL_OUT, inp)) {
+ switch (pfil_run_hooks(V_inet_pfil_head, mp, ifp, pflags, inp)) {
case PFIL_DROPPED:
*error = EPERM;
/* FALLTHROUGH */
@@ -653,7 +657,8 @@ sendit:
/* Jump over all PFIL processing if hooks are not active. */
if (PFIL_HOOKED_OUT(V_inet_pfil_head)) {
- switch (ip_output_pfil(&m, ifp, inp, dst, &fibnum, &error)) {
+ switch (ip_output_pfil(&m, ifp, flags, inp, dst, &fibnum,
+ &error)) {
case 1: /* Finished */
goto done;
diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h
index 38602efb3f4e4..7580a7b452129 100644
--- a/sys/netinet/ip_var.h
+++ b/sys/netinet/ip_var.h
@@ -82,6 +82,7 @@ struct ipoption {
char ipopt_list[MAX_IPOPTLEN]; /* options proper */
};
+#if defined(_NETINET_IN_VAR_H_) && defined(_KERNEL)
/*
* Structure attached to inpcb.ip_moptions and
* passed to ip_output when IP multicast options are in use.
@@ -93,12 +94,11 @@ struct ip_moptions {
u_long imo_multicast_vif; /* vif num outgoing multicasts */
u_char imo_multicast_ttl; /* TTL for outgoing multicasts */
u_char imo_multicast_loop; /* 1 => hear sends if a member */
- u_short imo_num_memberships; /* no. memberships this socket */
- u_short imo_max_memberships; /* max memberships this socket */
- struct in_multi **imo_membership; /* group memberships */
- struct in_mfilter *imo_mfilters; /* source filters */
- struct epoch_context imo_epoch_ctx;
+ struct ip_mfilter_head imo_head; /* group membership list */
};
+#else
+struct ip_moptions;
+#endif
struct ipstat {
uint64_t ips_total; /* total packets received */
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index 4ac87cb0d4706..8f767305f97d8 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -798,8 +798,12 @@ register_tcp_functions_as_names(struct tcp_function_block *blk, int wait,
}
}
+ if (blk->tfb_flags & TCP_FUNC_BEING_REMOVED) {
+ *num_names = 0;
+ return (EINVAL);
+ }
+
refcount_init(&blk->tfb_refcnt, 0);
- blk->tfb_flags = 0;
blk->tfb_id = atomic_fetchadd_int(&next_tcp_stack_id, 1);
for (i = 0; i < *num_names; i++) {
n = malloc(sizeof(struct tcp_function), M_TCPFUNCTIONS, wait);
diff --git a/sys/netinet6/in6.h b/sys/netinet6/in6.h
index 37d6ad40289e5..56ab11460af2b 100644
--- a/sys/netinet6/in6.h
+++ b/sys/netinet6/in6.h
@@ -523,11 +523,8 @@ struct route_in6 {
#define IPV6_DEFAULT_MULTICAST_LOOP 1 /* normally hear sends if a member */
/*
- * The im6o_membership vector for each socket is now dynamically allocated at
- * run-time, bounded by USHRT_MAX, and is reallocated when needed, sized
- * according to a power-of-two increment.
+ * Limit for IPv6 multicast memberships
*/
-#define IPV6_MIN_MEMBERSHIPS 31
#define IPV6_MAX_MEMBERSHIPS 4095
/*
diff --git a/sys/netinet6/in6_ifattach.c b/sys/netinet6/in6_ifattach.c
index a1a707449bf21..7ce680f2f91ad 100644
--- a/sys/netinet6/in6_ifattach.c
+++ b/sys/netinet6/in6_ifattach.c
@@ -774,9 +774,11 @@ _in6_ifdetach(struct ifnet *ifp, int purgeulp)
in6_purgeaddr(ifa);
}
if (purgeulp) {
+ IN6_MULTI_LOCK();
in6_pcbpurgeif0(&V_udbinfo, ifp);
in6_pcbpurgeif0(&V_ulitecbinfo, ifp);
in6_pcbpurgeif0(&V_ripcbinfo, ifp);
+ IN6_MULTI_UNLOCK();
}
/* leave from all multicast groups joined */
in6_purgemaddrs(ifp);
diff --git a/sys/netinet6/in6_mcast.c b/sys/netinet6/in6_mcast.c
index 5557a7c765640..f68b0a84d17db 100644
--- a/sys/netinet6/in6_mcast.c
+++ b/sys/netinet6/in6_mcast.c
@@ -102,7 +102,8 @@ RB_GENERATE(ip6_msource_tree, ip6_msource, im6s_link, ip6_msource_cmp);
/*
* Locking:
- * - Lock order is: Giant, INP_WLOCK, IN6_MULTI_LOCK, MLD_LOCK, IF_ADDR_LOCK.
+ * - Lock order is: Giant, IN6_MULTI_LOCK, INP_WLOCK,
+ * IN6_MULTI_LIST_LOCK, MLD_LOCK, IF_ADDR_LOCK.
* - The IF_ADDR_LOCK is implicitly taken by in6m_lookup() earlier, however
* it can be taken by code in net/if.c also.
* - ip6_moptions and in6_mfilter are covered by the INP_WLOCK.
@@ -134,12 +135,11 @@ static int im6f_prune(struct in6_mfilter *, const struct sockaddr_in6 *);
static void im6f_purge(struct in6_mfilter *);
static void im6f_rollback(struct in6_mfilter *);
static void im6f_reap(struct in6_mfilter *);
-static int im6o_grow(struct ip6_moptions *);
-static size_t im6o_match_group(const struct ip6_moptions *,
+static struct in6_mfilter *
+ im6o_match_group(const struct ip6_moptions *,
const struct ifnet *, const struct sockaddr *);
static struct in6_msource *
- im6o_match_source(const struct ip6_moptions *, const size_t,
- const struct sockaddr *);
+ im6o_match_source(struct in6_mfilter *, const struct sockaddr *);
static void im6s_merge(struct ip6_msource *ims,
const struct in6_msource *lims, const int rollback);
static int in6_getmulti(struct ifnet *, const struct in6_addr *,
@@ -228,55 +228,25 @@ im6f_init(struct in6_mfilter *imf, const int st0, const int st1)
imf->im6f_st[1] = st1;
}
-/*
- * Resize the ip6_moptions vector to the next power-of-two minus 1.
- * May be called with locks held; do not sleep.
- */
-static int
-im6o_grow(struct ip6_moptions *imo)
+struct in6_mfilter *
+ip6_mfilter_alloc(const int mflags, const int st0, const int st1)
{
- struct in6_multi **nmships;
- struct in6_multi **omships;
- struct in6_mfilter *nmfilters;
- struct in6_mfilter *omfilters;
- size_t idx;
- size_t newmax;
- size_t oldmax;
+ struct in6_mfilter *imf;
- nmships = NULL;
- nmfilters = NULL;
- omships = imo->im6o_membership;
- omfilters = imo->im6o_mfilters;
- oldmax = imo->im6o_max_memberships;
- newmax = ((oldmax + 1) * 2) - 1;
+ imf = malloc(sizeof(*imf), M_IN6MFILTER, mflags);
- if (newmax <= IPV6_MAX_MEMBERSHIPS) {
- nmships = (struct in6_multi **)realloc(omships,
- sizeof(struct in6_multi *) * newmax, M_IP6MOPTS, M_NOWAIT);
- nmfilters = (struct in6_mfilter *)realloc(omfilters,
- sizeof(struct in6_mfilter) * newmax, M_IN6MFILTER,
- M_NOWAIT);
- if (nmships != NULL && nmfilters != NULL) {
- /* Initialize newly allocated source filter heads. */
- for (idx = oldmax; idx < newmax; idx++) {
- im6f_init(&nmfilters[idx], MCAST_UNDEFINED,
- MCAST_EXCLUDE);
- }
- imo->im6o_max_memberships = newmax;
- imo->im6o_membership = nmships;
- imo->im6o_mfilters = nmfilters;
- }
- }
+ if (imf != NULL)
+ im6f_init(imf, st0, st1);
- if (nmships == NULL || nmfilters == NULL) {
- if (nmships != NULL)
- free(nmships, M_IP6MOPTS);
- if (nmfilters != NULL)
- free(nmfilters, M_IN6MFILTER);
- return (ETOOMANYREFS);
- }
+ return (imf);
+}
- return (0);
+void
+ip6_mfilter_free(struct in6_mfilter *imf)
+{
+
+ im6f_purge(imf);
+ free(imf, M_IN6MFILTER);
}
/*
@@ -284,36 +254,27 @@ im6o_grow(struct ip6_moptions *imo)
* which matches the specified group, and optionally an interface.
* Return its index into the array, or -1 if not found.
*/
-static size_t
+static struct in6_mfilter *
im6o_match_group(const struct ip6_moptions *imo, const struct ifnet *ifp,
const struct sockaddr *group)
{
const struct sockaddr_in6 *gsin6;
- struct in6_multi **pinm;
- int idx;
- int nmships;
+ struct in6_mfilter *imf;
+ struct in6_multi *inm;
- gsin6 = (const struct sockaddr_in6 *)group;
+ gsin6 = (const struct sockaddr_in6 *)group;
- /* The im6o_membership array may be lazy allocated. */
- if (imo->im6o_membership == NULL || imo->im6o_num_memberships == 0)
- return (-1);
-
- nmships = imo->im6o_num_memberships;
- pinm = &imo->im6o_membership[0];
- for (idx = 0; idx < nmships; idx++, pinm++) {
- if (*pinm == NULL)
+ IP6_MFILTER_FOREACH(imf, &imo->im6o_head) {
+ inm = imf->im6f_in6m;
+ if (inm == NULL)
continue;
- if ((ifp == NULL || ((*pinm)->in6m_ifp == ifp)) &&
- IN6_ARE_ADDR_EQUAL(&(*pinm)->in6m_addr,
+ if ((ifp == NULL || (inm->in6m_ifp == ifp)) &&
+ IN6_ARE_ADDR_EQUAL(&inm->in6m_addr,
&gsin6->sin6_addr)) {
break;
}
}
- if (idx >= nmships)
- idx = -1;
-
- return (idx);
+ return (imf);
}
/*
@@ -328,22 +289,13 @@ im6o_match_group(const struct ip6_moptions *imo, const struct ifnet *ifp,
* it exists, which may not be the desired behaviour.
*/
static struct in6_msource *
-im6o_match_source(const struct ip6_moptions *imo, const size_t gidx,
- const struct sockaddr *src)
+im6o_match_source(struct in6_mfilter *imf, const struct sockaddr *src)
{
struct ip6_msource find;
- struct in6_mfilter *imf;
struct ip6_msource *ims;
const sockunion_t *psa;
KASSERT(src->sa_family == AF_INET6, ("%s: !AF_INET6", __func__));
- KASSERT(gidx != -1 && gidx < imo->im6o_num_memberships,
- ("%s: invalid index %d\n", __func__, (int)gidx));
-
- /* The im6o_mfilters array may be lazy allocated. */
- if (imo->im6o_mfilters == NULL)
- return (NULL);
- imf = &imo->im6o_mfilters[gidx];
psa = (const sockunion_t *)src;
find.im6s_addr = psa->sin6.sin6_addr;
@@ -363,14 +315,14 @@ int
im6o_mc_filter(const struct ip6_moptions *imo, const struct ifnet *ifp,
const struct sockaddr *group, const struct sockaddr *src)
{
- size_t gidx;
+ struct in6_mfilter *imf;
struct in6_msource *ims;
int mode;
KASSERT(ifp != NULL, ("%s: null ifp", __func__));
- gidx = im6o_match_group(imo, ifp, group);
- if (gidx == -1)
+ imf = im6o_match_group(imo, ifp, group);
+ if (imf == NULL)
return (MCAST_NOTGMEMBER);
/*
@@ -382,8 +334,8 @@ im6o_mc_filter(const struct ip6_moptions *imo, const struct ifnet *ifp,
* NOTE: We are comparing group state here at MLD t1 (now)
* with socket-layer t0 (since last downcall).
*/
- mode = imo->im6o_mfilters[gidx].im6f_st[1];
- ims = im6o_match_source(imo, gidx, src);
+ mode = imf->im6f_st[1];
+ ims = im6o_match_source(imf, src);
if ((ims == NULL && mode == MCAST_INCLUDE) ||
(ims != NULL && ims->im6sl_st[0] != mode))
@@ -1447,7 +1399,6 @@ in6p_block_unblock_source(struct inpcb *inp, struct sockopt *sopt)
struct ip6_moptions *imo;
struct in6_msource *ims;
struct in6_multi *inm;
- size_t idx;
uint16_t fmode;
int error, doblock;
#ifdef KTR
@@ -1504,16 +1455,12 @@ in6p_block_unblock_source(struct inpcb *inp, struct sockopt *sopt)
* Check if we are actually a member of this group.
*/
imo = in6p_findmoptions(inp);
- idx = im6o_match_group(imo, ifp, &gsa->sa);
- if (idx == -1 || imo->im6o_mfilters == NULL) {
+ imf = im6o_match_group(imo, ifp, &gsa->sa);
+ if (imf == NULL) {
error = EADDRNOTAVAIL;
goto out_in6p_locked;
}
-
- KASSERT(imo->im6o_mfilters != NULL,
- ("%s: im6o_mfilters not allocated", __func__));
- imf = &imo->im6o_mfilters[idx];
- inm = imo->im6o_membership[idx];
+ inm = imf->im6f_in6m;
/*
* Attempting to use the delta-based API on an
@@ -1531,7 +1478,7 @@ in6p_block_unblock_source(struct inpcb *inp, struct sockopt *sopt)
* Asked to unblock, but nothing to unblock.
* If adding a new block entry, allocate it.
*/
- ims = im6o_match_source(imo, idx, &ssa->sa);
+ ims = im6o_match_source(imf, &ssa->sa);
if ((ims != NULL && doblock) || (ims == NULL && !doblock)) {
CTR3(KTR_MLD, "%s: source %s %spresent", __func__,
ip6_sprintf(ip6tbuf, &ssa->sin6.sin6_addr),
@@ -1601,9 +1548,6 @@ static struct ip6_moptions *
in6p_findmoptions(struct inpcb *inp)
{
struct ip6_moptions *imo;
- struct in6_multi **immp;
- struct in6_mfilter *imfp;
- size_t idx;
INP_WLOCK(inp);
if (inp->in6p_moptions != NULL)
@@ -1612,27 +1556,14 @@ in6p_findmoptions(struct inpcb *inp)
INP_WUNLOCK(inp);
imo = malloc(sizeof(*imo), M_IP6MOPTS, M_WAITOK);
- immp = malloc(sizeof(*immp) * IPV6_MIN_MEMBERSHIPS, M_IP6MOPTS,
- M_WAITOK | M_ZERO);
- imfp = malloc(sizeof(struct in6_mfilter) * IPV6_MIN_MEMBERSHIPS,
- M_IN6MFILTER, M_WAITOK);
imo->im6o_multicast_ifp = NULL;
imo->im6o_multicast_hlim = V_ip6_defmcasthlim;
imo->im6o_multicast_loop = in6_mcast_loop;
- imo->im6o_num_memberships = 0;
- imo->im6o_max_memberships = IPV6_MIN_MEMBERSHIPS;
- imo->im6o_membership = immp;
-
- /* Initialize per-group source filters. */
- for (idx = 0; idx < IPV6_MIN_MEMBERSHIPS; idx++)
- im6f_init(&imfp[idx], MCAST_UNDEFINED, MCAST_EXCLUDE);
- imo->im6o_mfilters = imfp;
+ STAILQ_INIT(&imo->im6o_head);
INP_WLOCK(inp);
if (inp->in6p_moptions != NULL) {
- free(imfp, M_IN6MFILTER);
- free(immp, M_IP6MOPTS);
free(imo, M_IP6MOPTS);
return (inp->in6p_moptions);
}
@@ -1652,33 +1583,26 @@ in6p_findmoptions(struct inpcb *inp)
static void
inp_gcmoptions(struct ip6_moptions *imo)
{
- struct in6_mfilter *imf;
+ struct in6_mfilter *imf;
struct in6_multi *inm;
struct ifnet *ifp;
- size_t idx, nmships;
- nmships = imo->im6o_num_memberships;
- for (idx = 0; idx < nmships; ++idx) {
- imf = imo->im6o_mfilters ? &imo->im6o_mfilters[idx] : NULL;
- if (imf)
- im6f_leave(imf);
- inm = imo->im6o_membership[idx];
- ifp = inm->in6m_ifp;
- if (ifp != NULL) {
- CURVNET_SET(ifp->if_vnet);
- (void)in6_leavegroup(inm, imf);
- CURVNET_RESTORE();
- } else {
- (void)in6_leavegroup(inm, imf);
- }
- if (imf)
- im6f_purge(imf);
- }
+ while ((imf = ip6_mfilter_first(&imo->im6o_head)) != NULL) {
+ ip6_mfilter_remove(&imo->im6o_head, imf);
- if (imo->im6o_mfilters)
- free(imo->im6o_mfilters, M_IN6MFILTER);
- free(imo->im6o_membership, M_IP6MOPTS);
- free(imo, M_IP6MOPTS);
+ im6f_leave(imf);
+ if ((inm = imf->im6f_in6m) != NULL) {
+ if ((ifp = inm->in6m_ifp) != NULL) {
+ CURVNET_SET(ifp->if_vnet);
+ (void)in6_leavegroup(inm, imf);
+ CURVNET_RESTORE();
+ } else {
+ (void)in6_leavegroup(inm, imf);
+ }
+ }
+ ip6_mfilter_free(imf);
+ }
+ free(imo, M_IP6MOPTS);
}
void
@@ -1707,7 +1631,7 @@ in6p_get_source_filters(struct inpcb *inp, struct sockopt *sopt)
struct sockaddr_storage *ptss;
struct sockaddr_storage *tss;
int error;
- size_t idx, nsrcs, ncsrcs;
+ size_t nsrcs, ncsrcs;
INP_WLOCK_ASSERT(inp);
@@ -1741,12 +1665,11 @@ in6p_get_source_filters(struct inpcb *inp, struct sockopt *sopt)
/*
* Lookup group on the socket.
*/
- idx = im6o_match_group(imo, ifp, &gsa->sa);
- if (idx == -1 || imo->im6o_mfilters == NULL) {
+ imf = im6o_match_group(imo, ifp, &gsa->sa);
+ if (imf == NULL) {
INP_WUNLOCK(inp);
return (EADDRNOTAVAIL);
}
- imf = &imo->im6o_mfilters[idx];
/*
* Ignore memberships which are in limbo.
@@ -1943,15 +1866,12 @@ in6p_join_group(struct inpcb *inp, struct sockopt *sopt)
struct ip6_moptions *imo;
struct in6_multi *inm;
struct in6_msource *lims;
- size_t idx;
int error, is_new;
SLIST_INIT(&inmh);
ifp = NULL;
- imf = NULL;
lims = NULL;
error = 0;
- is_new = 0;
memset(&gsr, 0, sizeof(struct group_source_req));
gsa = (sockunion_t *)&gsr.gsr_group;
@@ -2052,13 +1972,25 @@ in6p_join_group(struct inpcb *inp, struct sockopt *sopt)
*/
(void)in6_setscope(&gsa->sin6.sin6_addr, ifp, NULL);
+ IN6_MULTI_LOCK();
+
+ /*
+ * Find the membership in the membership list.
+ */
imo = in6p_findmoptions(inp);
- idx = im6o_match_group(imo, ifp, &gsa->sa);
- if (idx == -1) {
+ imf = im6o_match_group(imo, ifp, &gsa->sa);
+ if (imf == NULL) {
is_new = 1;
+ inm = NULL;
+
+ if (ip6_mfilter_count(&imo->im6o_head) >= IPV6_MAX_MEMBERSHIPS) {
+ error = ENOMEM;
+ goto out_in6p_locked;
+ }
} else {
- inm = imo->im6o_membership[idx];
- imf = &imo->im6o_mfilters[idx];
+ is_new = 0;
+ inm = imf->im6f_in6m;
+
if (ssa->ss.ss_family != AF_UNSPEC) {
/*
* MCAST_JOIN_SOURCE_GROUP on an exclusive membership
@@ -2085,7 +2017,7 @@ in6p_join_group(struct inpcb *inp, struct sockopt *sopt)
* full-state SSM API with the delta-based API,
* which is discouraged in the relevant RFCs.
*/
- lims = im6o_match_source(imo, idx, &ssa->sa);
+ lims = im6o_match_source(imf, &ssa->sa);
if (lims != NULL /*&&
lims->im6sl_st[1] == MCAST_INCLUDE*/) {
error = EADDRNOTAVAIL;
@@ -2113,27 +2045,6 @@ in6p_join_group(struct inpcb *inp, struct sockopt *sopt)
*/
INP_WLOCK_ASSERT(inp);
- if (is_new) {
- if (imo->im6o_num_memberships == imo->im6o_max_memberships) {
- error = im6o_grow(imo);
- if (error)
- goto out_in6p_locked;
- }
- /*
- * Allocate the new slot upfront so we can deal with
- * grafting the new source filter in same code path
- * as for join-source on existing membership.
- */
- idx = imo->im6o_num_memberships;
- imo->im6o_membership[idx] = NULL;
- imo->im6o_num_memberships++;
- KASSERT(imo->im6o_mfilters != NULL,
- ("%s: im6f_mfilters vector was not allocated", __func__));
- imf = &imo->im6o_mfilters[idx];
- KASSERT(RB_EMPTY(&imf->im6f_sources),
- ("%s: im6f_sources not empty", __func__));
- }
-
/*
* Graft new source into filter list for this inpcb's
* membership of the group. The in6_multi may not have
@@ -2149,7 +2060,11 @@ in6p_join_group(struct inpcb *inp, struct sockopt *sopt)
/* Membership starts in IN mode */
if (is_new) {
CTR1(KTR_MLD, "%s: new join w/source", __func__);
- im6f_init(imf, MCAST_UNDEFINED, MCAST_INCLUDE);
+ imf = ip6_mfilter_alloc(M_NOWAIT, MCAST_UNDEFINED, MCAST_INCLUDE);
+ if (imf == NULL) {
+ error = ENOMEM;
+ goto out_in6p_locked;
+ }
} else {
CTR2(KTR_MLD, "%s: %s source", __func__, "allow");
}
@@ -2158,81 +2073,88 @@ in6p_join_group(struct inpcb *inp, struct sockopt *sopt)
CTR1(KTR_MLD, "%s: merge imf state failed",
__func__);
error = ENOMEM;
- goto out_im6o_free;
+ goto out_in6p_locked;
}
} else {
/* No address specified; Membership starts in EX mode */
if (is_new) {
CTR1(KTR_MLD, "%s: new join w/o source", __func__);
- im6f_init(imf, MCAST_UNDEFINED, MCAST_EXCLUDE);
+ imf = ip6_mfilter_alloc(M_NOWAIT, MCAST_UNDEFINED, MCAST_EXCLUDE);
+ if (imf == NULL) {
+ error = ENOMEM;
+ goto out_in6p_locked;
+ }
}
}
/*
* Begin state merge transaction at MLD layer.
*/
- in_pcbref(inp);
- INP_WUNLOCK(inp);
- IN6_MULTI_LOCK();
-
if (is_new) {
+ in_pcbref(inp);
+ INP_WUNLOCK(inp);
+
error = in6_joingroup_locked(ifp, &gsa->sin6.sin6_addr, imf,
- &inm, 0);
+ &imf->im6f_in6m, 0);
+
+ INP_WLOCK(inp);
+ if (in_pcbrele_wlocked(inp)) {
+ error = ENXIO;
+ goto out_in6p_unlocked;
+ }
if (error) {
- IN6_MULTI_UNLOCK();
- goto out_im6o_free;
+ goto out_in6p_locked;
}
/*
* NOTE: Refcount from in6_joingroup_locked()
* is protecting membership.
*/
- imo->im6o_membership[idx] = inm;
} else {
CTR1(KTR_MLD, "%s: merge inm state", __func__);
IN6_MULTI_LIST_LOCK();
error = in6m_merge(inm, imf);
- if (error)
+ if (error) {
CTR1(KTR_MLD, "%s: failed to merge inm state",
__func__);
- else {
- CTR1(KTR_MLD, "%s: doing mld downcall", __func__);
- error = mld_change_state(inm, 0);
- if (error)
- CTR1(KTR_MLD, "%s: failed mld downcall",
- __func__);
+ IN6_MULTI_LIST_UNLOCK();
+ im6f_rollback(imf);
+ im6f_reap(imf);
+ goto out_in6p_locked;
}
+ CTR1(KTR_MLD, "%s: doing mld downcall", __func__);
+ error = mld_change_state(inm, 0);
IN6_MULTI_LIST_UNLOCK();
- }
- IN6_MULTI_UNLOCK();
- INP_WLOCK(inp);
- if (in_pcbrele_wlocked(inp))
- return (ENXIO);
- if (error) {
- im6f_rollback(imf);
- if (is_new)
- im6f_purge(imf);
- else
+ if (error) {
+ CTR1(KTR_MLD, "%s: failed mld downcall",
+ __func__);
+ im6f_rollback(imf);
im6f_reap(imf);
- } else {
- im6f_commit(imf);
- }
-
-out_im6o_free:
- if (error && is_new) {
- inm = imo->im6o_membership[idx];
- if (inm != NULL) {
- IN6_MULTI_LIST_LOCK();
- in6m_rele_locked(&inmh, inm);
- IN6_MULTI_LIST_UNLOCK();
+ goto out_in6p_locked;
}
- imo->im6o_membership[idx] = NULL;
- --imo->im6o_num_memberships;
}
+ if (is_new)
+ ip6_mfilter_insert(&imo->im6o_head, imf);
+
+ im6f_commit(imf);
+ imf = NULL;
+
out_in6p_locked:
INP_WUNLOCK(inp);
- in6m_release_list_deferred(&inmh);
+out_in6p_unlocked:
+ IN6_MULTI_UNLOCK();
+
+ if (is_new && imf) {
+ if (imf->im6f_in6m != NULL) {
+ struct in6_multi_head inmh;
+
+ SLIST_INIT(&inmh);
+ SLIST_INSERT_HEAD(&inmh, imf->im6f_in6m, in6m_defer);
+ in6m_release_list_deferred(&inmh);
+ }
+ ip6_mfilter_free(imf);
+ }
return (error);
}
@@ -2251,8 +2173,8 @@ in6p_leave_group(struct inpcb *inp, struct sockopt *sopt)
struct in6_msource *ims;
struct in6_multi *inm;
uint32_t ifindex;
- size_t idx;
- int error, is_final;
+ int error;
+ bool is_final;
#ifdef KTR
char ip6tbuf[INET6_ADDRSTRLEN];
#endif
@@ -2260,7 +2182,7 @@ in6p_leave_group(struct inpcb *inp, struct sockopt *sopt)
ifp = NULL;
ifindex = 0;
error = 0;
- is_final = 1;
+ is_final = true;
memset(&gsr, 0, sizeof(struct group_source_req));
gsa = (sockunion_t *)&gsr.gsr_group;
@@ -2378,20 +2300,21 @@ in6p_leave_group(struct inpcb *inp, struct sockopt *sopt)
CTR2(KTR_MLD, "%s: ifp = %p", __func__, ifp);
KASSERT(ifp != NULL, ("%s: ifp did not resolve", __func__));
+ IN6_MULTI_LOCK();
+
/*
- * Find the membership in the membership array.
+ * Find the membership in the membership list.
*/
imo = in6p_findmoptions(inp);
- idx = im6o_match_group(imo, ifp, &gsa->sa);
- if (idx == -1) {
+ imf = im6o_match_group(imo, ifp, &gsa->sa);
+ if (imf == NULL) {
error = EADDRNOTAVAIL;
goto out_in6p_locked;
}
- inm = imo->im6o_membership[idx];
- imf = &imo->im6o_mfilters[idx];
+ inm = imf->im6f_in6m;
if (ssa->ss.ss_family != AF_UNSPEC)
- is_final = 0;
+ is_final = false;
/*
* Begin state merge transaction at socket layer.
@@ -2403,13 +2326,14 @@ in6p_leave_group(struct inpcb *inp, struct sockopt *sopt)
* MCAST_LEAVE_SOURCE_GROUP is only valid for inclusive memberships.
*/
if (is_final) {
+ ip6_mfilter_remove(&imo->im6o_head, imf);
im6f_leave(imf);
} else {
if (imf->im6f_st[0] == MCAST_EXCLUDE) {
error = EADDRNOTAVAIL;
goto out_in6p_locked;
}
- ims = im6o_match_source(imo, idx, &ssa->sa);
+ ims = im6o_match_source(imf, &ssa->sa);
if (ims == NULL) {
CTR3(KTR_MLD, "%s: source %p %spresent", __func__,
ip6_sprintf(ip6tbuf, &ssa->sin6.sin6_addr),
@@ -2429,60 +2353,47 @@ in6p_leave_group(struct inpcb *inp, struct sockopt *sopt)
/*
* Begin state merge transaction at MLD layer.
*/
- in_pcbref(inp);
- INP_WUNLOCK(inp);
- IN6_MULTI_LOCK();
-
- if (is_final) {
- /*
- * Give up the multicast address record to which
- * the membership points.
- */
- (void)in6_leavegroup_locked(inm, imf);
- } else {
+ if (!is_final) {
CTR1(KTR_MLD, "%s: merge inm state", __func__);
IN6_MULTI_LIST_LOCK();
error = in6m_merge(inm, imf);
- if (error)
+ if (error) {
CTR1(KTR_MLD, "%s: failed to merge inm state",
__func__);
- else {
- CTR1(KTR_MLD, "%s: doing mld downcall", __func__);
- error = mld_change_state(inm, 0);
- if (error)
- CTR1(KTR_MLD, "%s: failed mld downcall",
- __func__);
+ IN6_MULTI_LIST_UNLOCK();
+ im6f_rollback(imf);
+ im6f_reap(imf);
+ goto out_in6p_locked;
}
+
+ CTR1(KTR_MLD, "%s: doing mld downcall", __func__);
+ error = mld_change_state(inm, 0);
IN6_MULTI_LIST_UNLOCK();
+ if (error) {
+ CTR1(KTR_MLD, "%s: failed mld downcall",
+ __func__);
+ im6f_rollback(imf);
+ im6f_reap(imf);
+ goto out_in6p_locked;
+ }
}
- IN6_MULTI_UNLOCK();
- INP_WLOCK(inp);
- if (in_pcbrele_wlocked(inp))
- return (ENXIO);
-
- if (error)
- im6f_rollback(imf);
- else
- im6f_commit(imf);
-
+ im6f_commit(imf);
im6f_reap(imf);
- if (is_final) {
- /* Remove the gap in the membership array. */
- KASSERT(RB_EMPTY(&imf->im6f_sources),
- ("%s: im6f_sources not empty", __func__));
- for (++idx; idx < imo->im6o_num_memberships; ++idx) {
- imo->im6o_membership[idx - 1] = imo->im6o_membership[idx];
- imo->im6o_mfilters[idx - 1] = imo->im6o_mfilters[idx];
- }
- im6f_init(&imo->im6o_mfilters[idx - 1], MCAST_UNDEFINED,
- MCAST_EXCLUDE);
- imo->im6o_num_memberships--;
- }
-
out_in6p_locked:
INP_WUNLOCK(inp);
+
+ if (is_final && imf) {
+ /*
+ * Give up the multicast address record to which
+ * the membership points.
+ */
+ (void)in6_leavegroup_locked(inm, imf);
+ ip6_mfilter_free(imf);
+ }
+
+ IN6_MULTI_UNLOCK();
return (error);
}
@@ -2540,7 +2451,6 @@ in6p_set_source_filters(struct inpcb *inp, struct sockopt *sopt)
struct in6_mfilter *imf;
struct ip6_moptions *imo;
struct in6_multi *inm;
- size_t idx;
int error;
error = sooptcopyin(sopt, &msfr, sizeof(struct __msfilterreq),
@@ -2577,13 +2487,12 @@ in6p_set_source_filters(struct inpcb *inp, struct sockopt *sopt)
* Check if this socket is a member of this group.
*/
imo = in6p_findmoptions(inp);
- idx = im6o_match_group(imo, ifp, &gsa->sa);
- if (idx == -1 || imo->im6o_mfilters == NULL) {
+ imf = im6o_match_group(imo, ifp, &gsa->sa);
+ if (imf == NULL) {
error = EADDRNOTAVAIL;
goto out_in6p_locked;
}
- inm = imo->im6o_membership[idx];
- imf = &imo->im6o_mfilters[idx];
+ inm = imf->im6f_in6m;
/*
* Begin state merge transaction at socket layer.
diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c
index c27464b1e3e75..abad883dc623e 100644
--- a/sys/netinet6/in6_pcb.c
+++ b/sys/netinet6/in6_pcb.c
@@ -802,8 +802,9 @@ void
in6_pcbpurgeif0(struct inpcbinfo *pcbinfo, struct ifnet *ifp)
{
struct inpcb *in6p;
+ struct in6_multi *inm;
+ struct in6_mfilter *imf;
struct ip6_moptions *im6o;
- int i, gap;
INP_INFO_WLOCK(pcbinfo);
CK_LIST_FOREACH(in6p, pcbinfo->ipi_listhead, inp_list) {
@@ -824,18 +825,18 @@ in6_pcbpurgeif0(struct inpcbinfo *pcbinfo, struct ifnet *ifp)
* Drop multicast group membership if we joined
* through the interface being detached.
*/
- gap = 0;
- for (i = 0; i < im6o->im6o_num_memberships; i++) {
- if (im6o->im6o_membership[i]->in6m_ifp ==
- ifp) {
- in6_leavegroup(im6o->im6o_membership[i], NULL);
- gap++;
- } else if (gap != 0) {
- im6o->im6o_membership[i - gap] =
- im6o->im6o_membership[i];
- }
+restart:
+ IP6_MFILTER_FOREACH(imf, &im6o->im6o_head) {
+ if ((inm = imf->im6f_in6m) == NULL)
+ continue;
+ if (inm->in6m_ifp != ifp)
+ continue;
+ ip6_mfilter_remove(&im6o->im6o_head, imf);
+ IN6_MULTI_LOCK_ASSERT();
+ in6_leavegroup_locked(inm, NULL);
+ ip6_mfilter_free(imf);
+ goto restart;
}
- im6o->im6o_num_memberships -= gap;
}
INP_WUNLOCK(in6p);
}
diff --git a/sys/netinet6/in6_var.h b/sys/netinet6/in6_var.h
index 3e965c2d4b320..3e535310b29e1 100644
--- a/sys/netinet6/in6_var.h
+++ b/sys/netinet6/in6_var.h
@@ -602,9 +602,61 @@ struct in6_mfilter {
struct ip6_msource_tree im6f_sources; /* source list for (S,G) */
u_long im6f_nsrc; /* # of source entries */
uint8_t im6f_st[2]; /* state before/at commit */
+ struct in6_multi *im6f_in6m; /* associated multicast address */
+ STAILQ_ENTRY(in6_mfilter) im6f_entry; /* list entry */
};
/*
+ * Helper types and functions for IPv4 multicast filters.
+ */
+STAILQ_HEAD(ip6_mfilter_head, in6_mfilter);
+
+struct in6_mfilter *ip6_mfilter_alloc(int mflags, int st0, int st1);
+void ip6_mfilter_free(struct in6_mfilter *);
+
+static inline void
+ip6_mfilter_init(struct ip6_mfilter_head *head)
+{
+
+ STAILQ_INIT(head);
+}
+
+static inline struct in6_mfilter *
+ip6_mfilter_first(const struct ip6_mfilter_head *head)
+{
+
+ return (STAILQ_FIRST(head));
+}
+
+static inline void
+ip6_mfilter_insert(struct ip6_mfilter_head *head, struct in6_mfilter *imf)
+{
+
+ STAILQ_INSERT_TAIL(head, imf, im6f_entry);
+}
+
+static inline void
+ip6_mfilter_remove(struct ip6_mfilter_head *head, struct in6_mfilter *imf)
+{
+
+ STAILQ_REMOVE(head, imf, in6_mfilter, im6f_entry);
+}
+
+#define IP6_MFILTER_FOREACH(imf, head) \
+ STAILQ_FOREACH(imf, head, im6f_entry)
+
+static inline size_t
+ip6_mfilter_count(struct ip6_mfilter_head *head)
+{
+ struct in6_mfilter *imf;
+ size_t num = 0;
+
+ STAILQ_FOREACH(imf, head, im6f_entry)
+ num++;
+ return (num);
+}
+
+/*
* Legacy KAME IPv6 multicast membership descriptor.
*/
struct in6_multi_mship {
diff --git a/sys/netinet6/ip6_var.h b/sys/netinet6/ip6_var.h
index 40f502abcd087..45ee4425fb745 100644
--- a/sys/netinet6/ip6_var.h
+++ b/sys/netinet6/ip6_var.h
@@ -110,6 +110,7 @@ struct ip6_direct_ctx {
uint32_t ip6dc_off; /* offset to next header */
};
+#if defined(_NETINET6_IN6_VAR_H_) && defined(_KERNEL)
/*
* Structure attached to inpcb.in6p_moptions and
* passed to ip6_output when IPv6 multicast options are in use.
@@ -119,13 +120,11 @@ struct ip6_moptions {
struct ifnet *im6o_multicast_ifp; /* ifp for outgoing multicasts */
u_char im6o_multicast_hlim; /* hoplimit for outgoing multicasts */
u_char im6o_multicast_loop; /* 1 >= hear sends if a member */
- u_short im6o_num_memberships; /* no. memberships this socket */
- u_short im6o_max_memberships; /* max memberships this socket */
- struct in6_multi **im6o_membership; /* group memberships */
- struct in6_mfilter *im6o_mfilters; /* source filters */
- struct epoch_context imo6_epoch_ctx;
+ struct ip6_mfilter_head im6o_head; /* group membership list */
};
-
+#else
+struct ip6_moptions;
+#endif
/*
* Control options for outgoing packets
*/
diff --git a/sys/netipsec/key.c b/sys/netipsec/key.c
index d54427410b925..82a84a4125385 100644
--- a/sys/netipsec/key.c
+++ b/sys/netipsec/key.c
@@ -7164,7 +7164,7 @@ key_register(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp)
return key_senderror(so, m, ENOBUFS);
MGETHDR(n, M_NOWAIT, MT_DATA);
- if (len > MHLEN) {
+ if (n != NULL && len > MHLEN) {
if (!(MCLGET(n, M_NOWAIT))) {
m_freem(n);
n = NULL;
diff --git a/sys/netpfil/ipfw/ip_fw2.c b/sys/netpfil/ipfw/ip_fw2.c
index a4a3830132eb5..535be037b6cca 100644
--- a/sys/netpfil/ipfw/ip_fw2.c
+++ b/sys/netpfil/ipfw/ip_fw2.c
@@ -331,10 +331,10 @@ ipopts_match(struct ip *ip, ipfw_insn *cmd)
}
static int
-tcpopts_match(struct tcphdr *tcp, ipfw_insn *cmd)
+tcpopts_parse(struct tcphdr *tcp, uint16_t *mss)
{
- int optlen, bits = 0;
u_char *cp = (u_char *)(tcp + 1);
+ int optlen, bits = 0;
int x = (tcp->th_off << 2) - sizeof(struct tcphdr);
for (; x > 0; x -= optlen, cp += optlen) {
@@ -350,12 +350,13 @@ tcpopts_match(struct tcphdr *tcp, ipfw_insn *cmd)
}
switch (opt) {
-
default:
break;
case TCPOPT_MAXSEG:
bits |= IP_FW_TCPOPT_MSS;
+ if (mss != NULL)
+ *mss = be16dec(cp + 2);
break;
case TCPOPT_WINDOW:
@@ -370,10 +371,16 @@ tcpopts_match(struct tcphdr *tcp, ipfw_insn *cmd)
case TCPOPT_TIMESTAMP:
bits |= IP_FW_TCPOPT_TS;
break;
-
}
}
- return (flags_match(cmd, bits));
+ return (bits);
+}
+
+static int
+tcpopts_match(struct tcphdr *tcp, ipfw_insn *cmd)
+{
+
+ return (flags_match(cmd, tcpopts_parse(tcp, NULL)));
}
static int
@@ -1712,6 +1719,11 @@ do { \
default:
break;
}
+ } else {
+ if (offset == 1 && proto == IPPROTO_TCP) {
+ /* RFC 3128 */
+ goto pullup_failed;
+ }
}
UPDATE_POINTERS();
@@ -2316,6 +2328,31 @@ do { \
TCP(ulp)->th_ack);
break;
+ case O_TCPMSS:
+ if (proto == IPPROTO_TCP &&
+ (args->f_id._flags & TH_SYN) != 0 &&
+ ulp != NULL) {
+ uint16_t mss, *p;
+ int i;
+
+ PULLUP_LEN(hlen, ulp,
+ (TCP(ulp)->th_off << 2));
+ if ((tcpopts_parse(TCP(ulp), &mss) &
+ IP_FW_TCPOPT_MSS) == 0)
+ break;
+ if (cmdlen == 1) {
+ match = (cmd->arg1 == mss);
+ break;
+ }
+ /* Otherwise we have ranges. */
+ p = ((ipfw_insn_u16 *)cmd)->ports;
+ i = cmdlen - 1;
+ for (; !match && i > 0; i--, p += 2)
+ match = (mss >= p[0] &&
+ mss <= p[1]);
+ }
+ break;
+
case O_TCPWIN:
if (proto == IPPROTO_TCP && offset == 0) {
uint16_t x;
@@ -3332,6 +3369,7 @@ vnet_ipfw_init(const void *unused)
/* fill and insert the default rule */
rule = ipfw_alloc_rule(chain, sizeof(struct ip_fw));
+ rule->flags |= IPFW_RULE_NOOPT;
rule->cmd_len = 1;
rule->cmd[0].len = 1;
rule->cmd[0].opcode = default_to_accept ? O_ACCEPT : O_DENY;
diff --git a/sys/netpfil/ipfw/ip_fw_sockopt.c b/sys/netpfil/ipfw/ip_fw_sockopt.c
index a83e754476335..297b01ca7d3da 100644
--- a/sys/netpfil/ipfw/ip_fw_sockopt.c
+++ b/sys/netpfil/ipfw/ip_fw_sockopt.c
@@ -1176,7 +1176,9 @@ move_objects(struct ip_fw_chain *ch, ipfw_range_tlv *rt)
}
}
return (c);
-}/*
+}
+
+/*
* Changes set of given rule rannge @rt
* with each other.
*
@@ -1907,6 +1909,7 @@ check_ipfw_rule_body(ipfw_insn *cmd, int cmd_len, struct rule_check_info *ci)
case O_IPTTL:
case O_IPLEN:
case O_TCPDATALEN:
+ case O_TCPMSS:
case O_TCPWIN:
case O_TAGGED:
if (cmdlen < 1 || cmdlen > 31)
diff --git a/sys/netpfil/pf/if_pfsync.c b/sys/netpfil/pf/if_pfsync.c
index 45b1e090f95c9..0566593b76169 100644
--- a/sys/netpfil/pf/if_pfsync.c
+++ b/sys/netpfil/pf/if_pfsync.c
@@ -264,7 +264,7 @@ static void pfsync_push(struct pfsync_bucket *);
static void pfsync_push_all(struct pfsync_softc *);
static void pfsyncintr(void *);
static int pfsync_multicast_setup(struct pfsync_softc *, struct ifnet *,
- void *);
+ struct in_mfilter *imf);
static void pfsync_multicast_cleanup(struct pfsync_softc *);
static void pfsync_pointers_init(void);
static void pfsync_pointers_uninit(void);
@@ -430,8 +430,7 @@ pfsync_clone_destroy(struct ifnet *ifp)
pfsync_drop(sc);
if_free(ifp);
- if (sc->sc_imo.imo_membership)
- pfsync_multicast_cleanup(sc);
+ pfsync_multicast_cleanup(sc);
mtx_destroy(&sc->sc_mtx);
mtx_destroy(&sc->sc_bulk_mtx);
@@ -1373,10 +1372,9 @@ pfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
case SIOCSETPFSYNC:
{
- struct ip_moptions *imo = &sc->sc_imo;
+ struct in_mfilter *imf = NULL;
struct ifnet *sifp;
struct ip *ip;
- void *mship = NULL;
if ((error = priv_check(curthread, PRIV_NETINET_PF)) != 0)
return (error);
@@ -1396,8 +1394,7 @@ pfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
pfsyncr.pfsyncr_syncpeer.s_addr == 0 ||
pfsyncr.pfsyncr_syncpeer.s_addr ==
htonl(INADDR_PFSYNC_GROUP)))
- mship = malloc((sizeof(struct in_multi *) *
- IP_MIN_MEMBERSHIPS), M_PFSYNC, M_WAITOK | M_ZERO);
+ imf = ip_mfilter_alloc(M_WAITOK, 0, 0);
PFSYNC_LOCK(sc);
if (pfsyncr.pfsyncr_syncpeer.s_addr == 0)
@@ -1419,8 +1416,7 @@ pfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
if (sc->sc_sync_if)
if_rele(sc->sc_sync_if);
sc->sc_sync_if = NULL;
- if (imo->imo_membership)
- pfsync_multicast_cleanup(sc);
+ pfsync_multicast_cleanup(sc);
PFSYNC_UNLOCK(sc);
break;
}
@@ -1436,14 +1432,13 @@ pfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
PFSYNC_BUCKET_UNLOCK(&sc->sc_buckets[c]);
}
- if (imo->imo_membership)
- pfsync_multicast_cleanup(sc);
+ pfsync_multicast_cleanup(sc);
if (sc->sc_sync_peer.s_addr == htonl(INADDR_PFSYNC_GROUP)) {
- error = pfsync_multicast_setup(sc, sifp, mship);
+ error = pfsync_multicast_setup(sc, sifp, imf);
if (error) {
if_rele(sifp);
- free(mship, M_PFSYNC);
+ ip_mfilter_free(imf);
PFSYNC_UNLOCK(sc);
return (error);
}
@@ -2353,7 +2348,8 @@ pfsyncintr(void *arg)
}
static int
-pfsync_multicast_setup(struct pfsync_softc *sc, struct ifnet *ifp, void *mship)
+pfsync_multicast_setup(struct pfsync_softc *sc, struct ifnet *ifp,
+ struct in_mfilter *imf)
{
struct ip_moptions *imo = &sc->sc_imo;
int error;
@@ -2361,16 +2357,14 @@ pfsync_multicast_setup(struct pfsync_softc *sc, struct ifnet *ifp, void *mship)
if (!(ifp->if_flags & IFF_MULTICAST))
return (EADDRNOTAVAIL);
- imo->imo_membership = (struct in_multi **)mship;
- imo->imo_max_memberships = IP_MIN_MEMBERSHIPS;
imo->imo_multicast_vif = -1;
if ((error = in_joingroup(ifp, &sc->sc_sync_peer, NULL,
- &imo->imo_membership[0])) != 0) {
- imo->imo_membership = NULL;
+ &imf->imf_inm)) != 0)
return (error);
- }
- imo->imo_num_memberships++;
+
+ ip_mfilter_init(&imo->imo_head);
+ ip_mfilter_insert(&imo->imo_head, imf);
imo->imo_multicast_ifp = ifp;
imo->imo_multicast_ttl = PFSYNC_DFLTTL;
imo->imo_multicast_loop = 0;
@@ -2382,10 +2376,13 @@ static void
pfsync_multicast_cleanup(struct pfsync_softc *sc)
{
struct ip_moptions *imo = &sc->sc_imo;
+ struct in_mfilter *imf;
- in_leavegroup(imo->imo_membership[0], NULL);
- free(imo->imo_membership, M_PFSYNC);
- imo->imo_membership = NULL;
+ while ((imf = ip_mfilter_first(&imo->imo_head)) != NULL) {
+ ip_mfilter_remove(&imo->imo_head, imf);
+ in_leavegroup(imf->imf_inm, NULL);
+ ip_mfilter_free(imf);
+ }
imo->imo_multicast_ifp = NULL;
}
@@ -2404,7 +2401,7 @@ pfsync_detach_ifnet(struct ifnet *ifp)
* is going away. We do need to ensure we don't try to do
* cleanup later.
*/
- sc->sc_imo.imo_membership = NULL;
+ ip_mfilter_init(&sc->sc_imo.imo_head);
sc->sc_imo.imo_multicast_ifp = NULL;
sc->sc_sync_if = NULL;
}
diff --git a/sys/powerpc/conf/GENERIC b/sys/powerpc/conf/GENERIC
index dc19d7a85598c..78d83c9ba12de 100644
--- a/sys/powerpc/conf/GENERIC
+++ b/sys/powerpc/conf/GENERIC
@@ -162,7 +162,6 @@ device fxp # Intel EtherExpress PRO/100B (82557, 82558)
# Pseudo devices.
device crypto # core crypto support
device loop # Network loopback
-device random # Entropy device
device ether # Ethernet support
device vlan # 802.1Q VLAN support
device tuntap # Packet tunnel.
diff --git a/sys/powerpc/conf/GENERIC64 b/sys/powerpc/conf/GENERIC64
index dc3d54e371c9a..409062047b244 100644
--- a/sys/powerpc/conf/GENERIC64
+++ b/sys/powerpc/conf/GENERIC64
@@ -183,7 +183,6 @@ device rl # RealTek 8129/8139
# Pseudo devices.
device crypto # core crypto support
device loop # Network loopback
-device random # Entropy device
device ether # Ethernet support
device vlan # 802.1Q VLAN support
device tuntap # Packet tunnel.
diff --git a/sys/powerpc/conf/MPC85XX b/sys/powerpc/conf/MPC85XX
index 3eeba5f54ec47..7962bdc22db07 100644
--- a/sys/powerpc/conf/MPC85XX
+++ b/sys/powerpc/conf/MPC85XX
@@ -93,7 +93,6 @@ device mmcsd
device pass
device pci
device quicc
-device random
#device rl
device scbus
device scc
diff --git a/sys/powerpc/conf/MPC85XXSPE b/sys/powerpc/conf/MPC85XXSPE
index 1d649c1b36b9b..2cea302361a37 100644
--- a/sys/powerpc/conf/MPC85XXSPE
+++ b/sys/powerpc/conf/MPC85XXSPE
@@ -94,7 +94,6 @@ device mmcsd
device pass
device pci
device quicc
-device random
#device rl
device scbus
device scc
diff --git a/sys/powerpc/conf/QORIQ64 b/sys/powerpc/conf/QORIQ64
index eecc0eb8e06b2..1661829a6d25e 100644
--- a/sys/powerpc/conf/QORIQ64
+++ b/sys/powerpc/conf/QORIQ64
@@ -99,7 +99,6 @@ device mmc
device mmcsd
device pass
device pci
-device random
#device rl
device scbus
device scc
diff --git a/sys/powerpc/conf/dpaa/DPAA b/sys/powerpc/conf/dpaa/DPAA
index 2cbc908ec1206..4aa24c188accf 100644
--- a/sys/powerpc/conf/dpaa/DPAA
+++ b/sys/powerpc/conf/dpaa/DPAA
@@ -96,7 +96,6 @@ device pci
# Pseudo devices
device ether # Ethernet support
device loop # Network loopback
-device random # Entropy device
device bpf # Berkeley packet filter
device md # Memory "disks"
diff --git a/sys/powerpc/include/trap.h b/sys/powerpc/include/trap.h
index 5017a7535d292..56b789c248ef9 100644
--- a/sys/powerpc/include/trap.h
+++ b/sys/powerpc/include/trap.h
@@ -130,7 +130,7 @@
/* Macros to extract register information */
#define EXC_ALI_RST(dsisr) ((dsisr >> 5) & 0x1f) /* source or target */
#define EXC_ALI_RA(dsisr) (dsisr & 0x1f)
-#define EXC_ALI_SPE_REG(instr) ((instr >> 21) & 0x1f)
+#define EXC_ALI_INST_RST(instr) ((instr >> 21) & 0x1f)
/*
* SRR1 bits for program exception traps. These identify what caused
diff --git a/sys/powerpc/powerpc/machdep.c b/sys/powerpc/powerpc/machdep.c
index 6fb874e31d9cb..0bd6a11197abd 100644
--- a/sys/powerpc/powerpc/machdep.c
+++ b/sys/powerpc/powerpc/machdep.c
@@ -595,3 +595,16 @@ bzero(void *buf, size_t len)
len--;
}
}
+
+/* __stack_chk_fail_local() is called in secure-plt (32-bit). */
+#if !defined(__powerpc64__)
+extern void __stack_chk_fail(void);
+void __stack_chk_fail_local(void);
+
+void
+__stack_chk_fail_local(void)
+{
+
+ __stack_chk_fail();
+}
+#endif
diff --git a/sys/powerpc/powerpc/trap.c b/sys/powerpc/powerpc/trap.c
index 0200c7bbd1428..3cc04fbc75ad8 100644
--- a/sys/powerpc/powerpc/trap.c
+++ b/sys/powerpc/powerpc/trap.c
@@ -788,7 +788,7 @@ static int
fix_unaligned(struct thread *td, struct trapframe *frame)
{
struct thread *fputhread;
-#ifdef __SPE__
+#ifdef BOOKE
uint32_t inst;
#endif
int indicator, reg;
@@ -799,7 +799,7 @@ fix_unaligned(struct thread *td, struct trapframe *frame)
if (indicator & ESR_SPE) {
if (copyin((void *)frame->srr0, &inst, sizeof(inst)) != 0)
return (-1);
- reg = EXC_ALI_SPE_REG(inst);
+ reg = EXC_ALI_INST_RST(inst);
fpr = (double *)td->td_pcb->pcb_vec.vr[reg];
fputhread = PCPU_GET(vecthread);
@@ -829,12 +829,22 @@ fix_unaligned(struct thread *td, struct trapframe *frame)
return (0);
}
#else
+#ifdef BOOKE
+ indicator = (frame->cpu.booke.esr & ESR_ST) ? EXC_ALI_STFD : EXC_ALI_LFD;
+#else
indicator = EXC_ALI_OPCODE_INDICATOR(frame->cpu.aim.dsisr);
+#endif
switch (indicator) {
case EXC_ALI_LFD:
case EXC_ALI_STFD:
+#ifdef BOOKE
+ if (copyin((void *)frame->srr0, &inst, sizeof(inst)) != 0)
+ return (-1);
+ reg = EXC_ALI_INST_RST(inst);
+#else
reg = EXC_ALI_RST(frame->cpu.aim.dsisr);
+#endif
fpr = &td->td_pcb->pcb_fpu.fpr[reg].fpr;
fputhread = PCPU_GET(fputhread);
diff --git a/sys/riscv/conf/GENERIC b/sys/riscv/conf/GENERIC
index 559e9166daa95..5b647977879fd 100644
--- a/sys/riscv/conf/GENERIC
+++ b/sys/riscv/conf/GENERIC
@@ -137,7 +137,6 @@ options ZSTDIO # zstd-compressed kernel and user dumps
# Pseudo devices.
device crypto # core crypto support
device loop # Network loopback
-device random # Entropy device
device ether # Ethernet support
device vlan # 802.1Q VLAN support
device tuntap # Packet tunnel.
diff --git a/sys/sparc64/conf/GENERIC b/sys/sparc64/conf/GENERIC
index 285adadf332c0..75fe3f8425775 100644
--- a/sys/sparc64/conf/GENERIC
+++ b/sys/sparc64/conf/GENERIC
@@ -224,7 +224,6 @@ device ath_rate_sample # SampleRate tx rate control for ath
# Pseudo devices.
device crypto # core crypto support
device loop # Network loopback
-device random # Entropy device
device ether # Ethernet support
device vlan # 802.1Q VLAN support
device tuntap # Packet tunnel.
diff --git a/sys/sys/_types.h b/sys/sys/_types.h
index 22a37c53389ae..020ba025ea98c 100644
--- a/sys/sys/_types.h
+++ b/sys/sys/_types.h
@@ -68,6 +68,7 @@ typedef unsigned int __useconds_t; /* microseconds (unsigned) */
typedef int __cpuwhich_t; /* which parameter for cpuset. */
typedef int __cpulevel_t; /* level parameter for cpuset. */
typedef int __cpusetid_t; /* cpuset identifier. */
+typedef __int64_t __daddr_t; /* bwrite(3), FIOBMAP2, etc */
/*
* Unusual type definitions.
diff --git a/sys/sys/boot.h b/sys/sys/boot.h
index 68b9e1e0daf3e..7874d96637364 100644
--- a/sys/sys/boot.h
+++ b/sys/sys/boot.h
@@ -32,6 +32,8 @@
#ifndef _SYS_BOOT_H_
#define _SYS_BOOT_H_
+#define PATH_KERNEL "/boot/kernel/kernel"
+
int boot_env_to_howto(void);
void boot_howto_to_env(int howto);
int boot_parse_arg(char *v);
diff --git a/sys/sys/file.h b/sys/sys/file.h
index 82af5e6b1bbe4..942380c1647f1 100644
--- a/sys/sys/file.h
+++ b/sys/sys/file.h
@@ -179,7 +179,10 @@ struct file {
/*
* DTYPE_VNODE specific fields.
*/
- int f_seqcount; /* (a) Count of sequential accesses. */
+ union {
+ int16_t f_seqcount; /* (a) Count of sequential accesses. */
+ int f_pipegen;
+ };
off_t f_nextoff; /* next expected read/write offset. */
union {
struct cdev_privdata *fvn_cdevpriv;
diff --git a/sys/sys/filio.h b/sys/sys/filio.h
index e85db9cff4d1e..c5cf3d4432e97 100644
--- a/sys/sys/filio.h
+++ b/sys/sys/filio.h
@@ -40,7 +40,7 @@
#ifndef _SYS_FILIO_H_
#define _SYS_FILIO_H_
-#include <sys/types.h>
+#include <sys/_types.h>
#include <sys/ioccom.h>
/* Generic file-descriptor ioctl's. */
@@ -64,12 +64,12 @@ struct fiodgname_arg {
#define FIOSEEKDATA _IOWR('f', 97, off_t) /* SEEK_DATA */
#define FIOSEEKHOLE _IOWR('f', 98, off_t) /* SEEK_HOLE */
struct fiobmap2_arg {
- int64_t bn;
- int runp;
- int runb;
+ __daddr_t bn;
+ int runp;
+ int runb;
};
-/* Get the file's bmap info for the logical block bn */
-#define FIOBMAP2 _IOWR('f', 99, struct fiobmap2_arg)
+/* Get the file's bmap info for the logical block bn. */
+#define FIOBMAP2 _IOWR('f', 99, struct fiobmap2_arg)
#ifdef _KERNEL
#ifdef COMPAT_FREEBSD32
diff --git a/sys/sys/mman.h b/sys/sys/mman.h
index b2fad0e475799..1b1b4bcc2cb92 100644
--- a/sys/sys/mman.h
+++ b/sys/sys/mman.h
@@ -55,6 +55,14 @@
#define PROT_READ 0x01 /* pages can be read */
#define PROT_WRITE 0x02 /* pages can be written */
#define PROT_EXEC 0x04 /* pages can be executed */
+#if __BSD_VISIBLE
+#define _PROT_ALL (PROT_READ | PROT_WRITE | PROT_EXEC)
+#define PROT_EXTRACT(prot) ((prot) & _PROT_ALL)
+
+#define _PROT_MAX_SHIFT 16
+#define PROT_MAX(prot) ((prot) << _PROT_MAX_SHIFT)
+#define PROT_MAX_EXTRACT(prot) (((prot) >> _PROT_MAX_SHIFT) & _PROT_ALL)
+#endif
/*
* Flags contain sharing type and options.
diff --git a/sys/sys/param.h b/sys/sys/param.h
index 2534537558c53..9a68762388f2d 100644
--- a/sys/sys/param.h
+++ b/sys/sys/param.h
@@ -60,7 +60,7 @@
* in the range 5 to 9.
*/
#undef __FreeBSD_version
-#define __FreeBSD_version 1300032 /* Master, propagated to newvers */
+#define __FreeBSD_version 1300034 /* Master, propagated to newvers */
/*
* __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,
diff --git a/sys/sys/pcpu.h b/sys/sys/pcpu.h
index 38785cd26c94c..3672d6070deb7 100644
--- a/sys/sys/pcpu.h
+++ b/sys/sys/pcpu.h
@@ -85,7 +85,8 @@ extern uintptr_t dpcpu_off[];
/* struct _hack is to stop this from being used with the static keyword. */
#define DPCPU_DEFINE(t, n) \
struct _hack; t DPCPU_NAME(n) __section(DPCPU_SETNAME) __used
-#if defined(KLD_MODULE) && (defined(__aarch64__) || defined(__riscv))
+#if defined(KLD_MODULE) && (defined(__aarch64__) || defined(__riscv) \
+ || defined(__powerpc64__))
/*
* On some architectures the compiler will use PC-relative load to
* find the address of DPCPU data with the static keyword. We then
diff --git a/sys/sys/pmckern.h b/sys/sys/pmckern.h
index e892d658a1ca2..5b337f8d76df0 100644
--- a/sys/sys/pmckern.h
+++ b/sys/sys/pmckern.h
@@ -226,7 +226,7 @@ do { \
*/
#define PMC_CALL_HOOK_UNLOCKED(t, cmd, arg) \
do { \
- if (pmc_hook != NULL) \
+ if (pmc_hook != NULL) \
(pmc_hook)((t), (cmd), (arg)); \
} while (0)
diff --git a/sys/sys/random.h b/sys/sys/random.h
index aa8c5f02c32e1..8bcbe470cfc11 100644
--- a/sys/sys/random.h
+++ b/sys/sys/random.h
@@ -37,26 +37,9 @@
struct uio;
-#if defined(DEV_RANDOM)
void read_random(void *, u_int);
int read_random_uio(struct uio *, bool);
bool is_random_seeded(void);
-#else
-static __inline int
-read_random_uio(void *a __unused, u_int b __unused)
-{
- return (0);
-}
-static __inline void
-read_random(void *a __unused, u_int b __unused)
-{
-}
-static __inline bool
-is_random_seeded(void)
-{
- return (false);
-}
-#endif
/*
* Note: if you add or remove members of random_entropy_source, remember to
@@ -101,7 +84,6 @@ _Static_assert(ENTROPYSOURCE <= 32,
#define RANDOM_LEGACY_BOOT_ENTROPY_MODULE "/boot/entropy"
#define RANDOM_CACHED_BOOT_ENTROPY_MODULE "boot_entropy_cache"
-#if defined(DEV_RANDOM)
extern u_int hc_source_mask;
void random_harvest_queue_(const void *, u_int, enum random_entropy_source);
void random_harvest_fast_(const void *, u_int);
@@ -133,13 +115,6 @@ random_harvest_direct(const void *entropy, u_int size, enum random_entropy_sourc
void random_harvest_register_source(enum random_entropy_source);
void random_harvest_deregister_source(enum random_entropy_source);
-#else
-#define random_harvest_queue(a, b, c) do {} while (0)
-#define random_harvest_fast(a, b, c) do {} while (0)
-#define random_harvest_direct(a, b, c) do {} while (0)
-#define random_harvest_register_source(a) do {} while (0)
-#define random_harvest_deregister_source(a) do {} while (0)
-#endif
#if defined(RANDOM_ENABLE_UMA)
#define random_harvest_fast_uma(a, b, c) random_harvest_fast(a, b, c)
diff --git a/sys/sys/rangelock.h b/sys/sys/rangelock.h
index 732bd9406d481..9a8a107aed8f4 100644
--- a/sys/sys/rangelock.h
+++ b/sys/sys/rangelock.h
@@ -75,8 +75,12 @@ void *rangelock_unlock_range(struct rangelock *lock, void *cookie,
off_t start, off_t end, struct mtx *ilk);
void *rangelock_rlock(struct rangelock *lock, off_t start, off_t end,
struct mtx *ilk);
+void *rangelock_tryrlock(struct rangelock *lock, off_t start, off_t end,
+ struct mtx *ilk);
void *rangelock_wlock(struct rangelock *lock, off_t start, off_t end,
struct mtx *ilk);
+void *rangelock_trywlock(struct rangelock *lock, off_t start, off_t end,
+ struct mtx *ilk);
void rlqentry_free(struct rl_q_entry *rlqe);
#endif /* _KERNEL */
diff --git a/sys/sys/types.h b/sys/sys/types.h
index 39d8d63262e8b..c3ece22e58b83 100644
--- a/sys/sys/types.h
+++ b/sys/sys/types.h
@@ -101,7 +101,7 @@ typedef __clockid_t clockid_t;
#endif
typedef __critical_t critical_t; /* Critical section value */
-typedef __int64_t daddr_t; /* disk address */
+typedef __daddr_t daddr_t; /* disk address */
#ifndef _DEV_T_DECLARED
typedef __dev_t dev_t; /* device number or struct cdev */
diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h
index 50eae14026afd..9c0dc25f3f83b 100644
--- a/sys/sys/vnode.h
+++ b/sys/sys/vnode.h
@@ -722,8 +722,12 @@ int vn_io_fault_pgmove(vm_page_t ma[], vm_offset_t offset, int xfersize,
VI_MTX(vp))
#define vn_rangelock_rlock(vp, start, end) \
rangelock_rlock(&(vp)->v_rl, (start), (end), VI_MTX(vp))
+#define vn_rangelock_tryrlock(vp, start, end) \
+ rangelock_tryrlock(&(vp)->v_rl, (start), (end), VI_MTX(vp))
#define vn_rangelock_wlock(vp, start, end) \
rangelock_wlock(&(vp)->v_rl, (start), (end), VI_MTX(vp))
+#define vn_rangelock_trywlock(vp, start, end) \
+ rangelock_trywlock(&(vp)->v_rl, (start), (end), VI_MTX(vp))
int vfs_cache_lookup(struct vop_lookup_args *ap);
void vfs_timestamp(struct timespec *);
diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c
index 3a4a20b8565c0..8d43e5528e185 100644
--- a/sys/ufs/ffs/ffs_softdep.c
+++ b/sys/ufs/ffs/ffs_softdep.c
@@ -2110,7 +2110,6 @@ pagedep_find(pagedephd, ino, lbn, pagedeppp)
* Look up a pagedep. Return 1 if found, 0 otherwise.
* If not found, allocate if DEPALLOC flag is passed.
* Found or allocated entry is returned in pagedeppp.
- * This routine must be called with splbio interrupts blocked.
*/
static int
pagedep_lookup(mp, bp, ino, lbn, flags, pagedeppp)
@@ -2202,7 +2201,6 @@ inodedep_find(inodedephd, inum, inodedeppp)
* Look up an inodedep. Return 1 if found, 0 if not found.
* If not found, allocate if DEPALLOC flag is passed.
* Found or allocated entry is returned in inodedeppp.
- * This routine must be called with splbio interrupts blocked.
*/
static int
inodedep_lookup(mp, inum, flags, inodedeppp)
@@ -5478,7 +5476,6 @@ jnewblk_merge(new, old, wkhd)
/*
* Replace an old allocdirect dependency with a newer one.
- * This routine must be called with splbio interrupts blocked.
*/
static void
allocdirect_merge(adphead, newadp, oldadp)
@@ -7534,7 +7531,6 @@ free_newblk(newblk)
/*
* Free a newdirblk. Clear the NEWBLOCK flag on its associated pagedep.
- * This routine must be called with splbio interrupts blocked.
*/
static void
free_newdirblk(newdirblk)
@@ -7665,7 +7661,6 @@ softdep_freefile(pvp, ino, mode)
/*
* Check to see if an inode has never been written to disk. If
* so free the inodedep and return success, otherwise return failure.
- * This routine must be called with splbio interrupts blocked.
*
* If we still have a bitmap dependency, then the inode has never
* been written to disk. Drop the dependency as it is no longer
@@ -8897,8 +8892,7 @@ cancel_diradd(dap, dirrem, jremref, dotremref, dotdotremref)
}
/*
- * Free a diradd dependency structure. This routine must be called
- * with splbio interrupts blocked.
+ * Free a diradd dependency structure.
*/
static void
free_diradd(dap, wkhd)
@@ -11195,9 +11189,7 @@ softdep_disk_write_complete(bp)
}
/*
- * Called from within softdep_disk_write_complete above. Note that
- * this routine is always called from interrupt level with further
- * splbio interrupts blocked.
+ * Called from within softdep_disk_write_complete above.
*/
static void
handle_allocdirect_partdone(adp, wkhd)
@@ -11209,6 +11201,7 @@ handle_allocdirect_partdone(adp, wkhd)
struct inodedep *inodedep;
long bsize;
+ LOCK_OWNED(VFSTOUFS(adp->ad_block.nb_list.wk_mp));
if ((adp->ad_state & ALLCOMPLETE) != ALLCOMPLETE)
return;
/*
@@ -11818,7 +11811,6 @@ handle_written_indirdep(indirdep, bp, bpp, flags)
/*
* Process a diradd entry after its dependent inode has been written.
- * This routine must be called with splbio interrupts blocked.
*/
static void
diradd_inode_written(dap, inodedep)
@@ -11826,6 +11818,7 @@ diradd_inode_written(dap, inodedep)
struct inodedep *inodedep;
{
+ LOCK_OWNED(VFSTOUFS(dap->da_list.wk_mp));
dap->da_state |= COMPLETE;
complete_diradd(dap);
WORKLIST_INSERT(&inodedep->id_pendinghd, &dap->da_list);
@@ -12386,8 +12379,7 @@ retry:
/*
* Merge the a new inode dependency list (such as id_newinoupdt) into an
- * old inode dependency list (such as id_inoupdt). This routine must be
- * called with splbio interrupts blocked.
+ * old inode dependency list (such as id_inoupdt).
*/
static void
merge_inode_lists(newlisthead, oldlisthead)
@@ -12397,6 +12389,8 @@ merge_inode_lists(newlisthead, oldlisthead)
struct allocdirect *listadp, *newadp;
newadp = TAILQ_FIRST(newlisthead);
+ if (newadp != NULL)
+ LOCK_OWNED(VFSTOUFS(newadp->ad_block.nb_list.wk_mp));
for (listadp = TAILQ_FIRST(oldlisthead); listadp && newadp;) {
if (listadp->ad_offset < newadp->ad_offset) {
listadp = TAILQ_NEXT(listadp, ad_next);
@@ -12891,7 +12885,6 @@ out:
/*
* Flush the dependencies associated with an inodedep.
- * Called with splbio blocked.
*/
static int
flush_inodedep_deps(vp, mp, ino)
@@ -12956,7 +12949,6 @@ restart:
/*
* Flush an inode dependency list.
- * Called with splbio blocked.
*/
static int
flush_deplist(listhead, waitfor, errorp)
@@ -13098,7 +13090,6 @@ flush_newblk_dep(vp, mp, lbn)
/*
* Eliminate a pagedep dependency by flushing out all its diradd dependencies.
- * Called with splbio blocked.
*/
static int
flush_pagedep_deps(pvp, mp, diraddhdp)
diff --git a/sys/vm/device_pager.c b/sys/vm/device_pager.c
index c27d60869deff..7dce4778f9513 100644
--- a/sys/vm/device_pager.c
+++ b/sys/vm/device_pager.c
@@ -236,7 +236,7 @@ cdev_pager_free_page(vm_object_t object, vm_page_t m)
KASSERT((m->oflags & VPO_UNMANAGED) == 0, ("unmanaged %p", m));
pmap_remove_all(m);
vm_page_lock(m);
- vm_page_remove(m);
+ (void)vm_page_remove(m);
vm_page_unlock(m);
} else if (object->type == OBJT_DEVICE)
dev_pager_free_page(object, m);
diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c
index 4268db264d52b..ae0103595ae7d 100644
--- a/sys/vm/vm_fault.c
+++ b/sys/vm/vm_fault.c
@@ -1144,7 +1144,7 @@ readrest:
fs.object == fs.first_object->backing_object) {
vm_page_lock(fs.m);
vm_page_dequeue(fs.m);
- vm_page_remove(fs.m);
+ (void)vm_page_remove(fs.m);
vm_page_unlock(fs.m);
vm_page_lock(fs.first_m);
vm_page_replace_checked(fs.m, fs.first_object,
diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c
index 9120317020700..38afe6308cc83 100644
--- a/sys/vm/vm_map.c
+++ b/sys/vm/vm_map.c
@@ -2472,11 +2472,8 @@ again:
VM_MAP_RANGE_CHECK(map, start, end);
- if (vm_map_lookup_entry(map, start, &entry)) {
- vm_map_clip_start(map, entry, start);
- } else {
+ if (!vm_map_lookup_entry(map, start, &entry))
entry = entry->next;
- }
/*
* Make a first pass to check for protection violations.
@@ -2515,6 +2512,7 @@ again:
* now will do cow due to allowed write (e.g. debugger sets
* breakpoint on text segment)
*/
+ vm_map_clip_start(map, entry, start);
for (current = entry; current->start < end; current = current->next) {
vm_map_clip_end(map, current, end);
diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c
index cd483527af712..24864889060ca 100644
--- a/sys/vm/vm_mmap.c
+++ b/sys/vm/vm_mmap.c
@@ -103,6 +103,9 @@ SYSCTL_INT(_vm, OID_AUTO, old_mlock, CTLFLAG_RWTUN, &old_mlock, 0,
static int mincore_mapped = 1;
SYSCTL_INT(_vm, OID_AUTO, mincore_mapped, CTLFLAG_RWTUN, &mincore_mapped, 0,
"mincore reports mappings, not residency");
+static int imply_prot_max = 0;
+SYSCTL_INT(_vm, OID_AUTO, imply_prot_max, CTLFLAG_RWTUN, &imply_prot_max, 0,
+ "Imply maximum page permissions in mmap() when none are specified");
#ifdef MAP_32BIT
#define MAP_32BIT_MAX_ADDR ((vm_offset_t)1 << 31)
@@ -187,9 +190,25 @@ kern_mmap(struct thread *td, uintptr_t addr0, size_t len, int prot, int flags,
vm_offset_t addr;
vm_size_t pageoff, size;
vm_prot_t cap_maxprot;
- int align, error;
+ int align, error, max_prot;
cap_rights_t rights;
+ if ((prot & ~(_PROT_ALL | PROT_MAX(_PROT_ALL))) != 0)
+ return (EINVAL);
+ max_prot = PROT_MAX_EXTRACT(prot);
+ prot = PROT_EXTRACT(prot);
+ if (max_prot != 0 && (max_prot & prot) != prot)
+ return (EINVAL);
+ /*
+ * Always honor PROT_MAX if set. If not, default to all
+ * permissions unless we're implying maximum permissions.
+ *
+ * XXX: should be tunable per process and ABI.
+ */
+ if (max_prot == 0)
+ max_prot = (imply_prot_max && prot != PROT_NONE) ?
+ prot : _PROT_ALL;
+
vms = td->td_proc->p_vmspace;
fp = NULL;
AUDIT_ARG_FD(fd);
@@ -335,7 +354,7 @@ kern_mmap(struct thread *td, uintptr_t addr0, size_t len, int prot, int flags,
* This relies on VM_PROT_* matching PROT_*.
*/
error = vm_mmap_object(&vms->vm_map, &addr, size, prot,
- VM_PROT_ALL, flags, NULL, pos, FALSE, td);
+ max_prot, flags, NULL, pos, FALSE, td);
} else {
/*
* Mapping file, get fp for validation and don't let the
@@ -363,7 +382,7 @@ kern_mmap(struct thread *td, uintptr_t addr0, size_t len, int prot, int flags,
/* This relies on VM_PROT_* matching PROT_*. */
error = fo_mmap(fp, &vms->vm_map, &addr, size, prot,
- cap_maxprot, flags, pos, td);
+ max_prot & cap_maxprot, flags, pos, td);
}
if (error == 0)
@@ -594,9 +613,13 @@ kern_mprotect(struct thread *td, uintptr_t addr0, size_t size, int prot)
{
vm_offset_t addr;
vm_size_t pageoff;
+ int vm_error, max_prot;
addr = addr0;
- prot = (prot & VM_PROT_ALL);
+ if ((prot & ~(_PROT_ALL | PROT_MAX(_PROT_ALL))) != 0)
+ return (EINVAL);
+ max_prot = PROT_MAX_EXTRACT(prot);
+ prot = PROT_EXTRACT(prot);
pageoff = (addr & PAGE_MASK);
addr -= pageoff;
size += pageoff;
@@ -610,8 +633,18 @@ kern_mprotect(struct thread *td, uintptr_t addr0, size_t size, int prot)
if (addr + size < addr)
return (EINVAL);
- switch (vm_map_protect(&td->td_proc->p_vmspace->vm_map, addr,
- addr + size, prot, FALSE)) {
+ vm_error = KERN_SUCCESS;
+ if (max_prot != 0) {
+ if ((max_prot & prot) != prot)
+ return (EINVAL);
+ vm_error = vm_map_protect(&td->td_proc->p_vmspace->vm_map,
+ addr, addr + size, max_prot, TRUE);
+ }
+ if (vm_error == KERN_SUCCESS)
+ vm_error = vm_map_protect(&td->td_proc->p_vmspace->vm_map,
+ addr, addr + size, prot, FALSE);
+
+ switch (vm_error) {
case KERN_SUCCESS:
return (0);
case KERN_PROTECTION_FAILURE:
diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c
index 9fd90f04b6d97..7c3575e646cf8 100644
--- a/sys/vm/vm_object.c
+++ b/sys/vm/vm_object.c
@@ -1595,10 +1595,8 @@ vm_object_collapse_scan(vm_object_t object, int op)
vm_page_lock(p);
KASSERT(!pmap_page_is_mapped(p),
("freeing mapped page %p", p));
- if (!vm_page_wired(p))
+ if (vm_page_remove(p))
vm_page_free(p);
- else
- vm_page_remove(p);
vm_page_unlock(p);
continue;
}
@@ -1639,10 +1637,8 @@ vm_object_collapse_scan(vm_object_t object, int op)
vm_page_lock(p);
KASSERT(!pmap_page_is_mapped(p),
("freeing mapped page %p", p));
- if (!vm_page_wired(p))
+ if (vm_page_remove(p))
vm_page_free(p);
- else
- vm_page_remove(p);
vm_page_unlock(p);
continue;
}
diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c
index a90961ce57b55..e43817b812a0e 100644
--- a/sys/vm/vm_page.c
+++ b/sys/vm/vm_page.c
@@ -1458,20 +1458,21 @@ vm_page_insert_radixdone(vm_page_t m, vm_object_t object, vm_page_t mpred)
* vm_page_remove:
*
* Removes the specified page from its containing object, but does not
- * invalidate any backing storage.
+ * invalidate any backing storage. Return true if the page may be safely
+ * freed and false otherwise.
*
* The object must be locked. The page must be locked if it is managed.
*/
-void
+bool
vm_page_remove(vm_page_t m)
{
vm_object_t object;
vm_page_t mrem;
+ object = m->object;
+
if ((m->oflags & VPO_UNMANAGED) == 0)
vm_page_assert_locked(m);
- if ((object = m->object) == NULL)
- return;
VM_OBJECT_ASSERT_WLOCKED(object);
if (vm_page_xbusied(m))
vm_page_xunbusy_maybelocked(m);
@@ -1495,6 +1496,7 @@ vm_page_remove(vm_page_t m)
vdrop(object->handle);
m->object = NULL;
+ return (!vm_page_wired(m));
}
/*
@@ -1665,7 +1667,7 @@ vm_page_rename(vm_page_t m, vm_object_t new_object, vm_pindex_t new_pindex)
*/
m->pindex = opidx;
vm_page_lock(m);
- vm_page_remove(m);
+ (void)vm_page_remove(m);
/* Return back to the new pindex to complete vm_page_insert(). */
m->pindex = new_pindex;
@@ -3436,7 +3438,8 @@ vm_page_free_prep(vm_page_t m)
if (vm_page_sbusied(m))
panic("vm_page_free_prep: freeing busy page %p", m);
- vm_page_remove(m);
+ if (m->object != NULL)
+ (void)vm_page_remove(m);
/*
* If fictitious remove object association and
diff --git a/sys/vm/vm_page.h b/sys/vm/vm_page.h
index d1938d2a1bd88..57f9f6e9081ce 100644
--- a/sys/vm/vm_page.h
+++ b/sys/vm/vm_page.h
@@ -561,7 +561,7 @@ bool vm_page_reclaim_contig(int req, u_long npages, vm_paddr_t low,
bool vm_page_reclaim_contig_domain(int domain, int req, u_long npages,
vm_paddr_t low, vm_paddr_t high, u_long alignment, vm_paddr_t boundary);
void vm_page_reference(vm_page_t m);
-void vm_page_remove (vm_page_t);
+bool vm_page_remove(vm_page_t);
int vm_page_rename (vm_page_t, vm_object_t, vm_pindex_t);
vm_page_t vm_page_replace(vm_page_t mnew, vm_object_t object,
vm_pindex_t pindex);