Message ID | 20241216161042.42108-4-alejandro.lucero-palau@amd.com (mailing list archive) |
---|---|
State | Changes Requested |
Headers | show |
Series | cxl: add type2 device basic support | expand |
On Mon, 16 Dec 2024 16:10:18 +0000 <alejandro.lucero-palau@amd.com> wrote: > From: Alejandro Lucero <alucerop@amd.com> > > Type2 devices have some Type3 functionalities as optional like an mbox > or an hdm decoder, and CXL core needs a way to know what an CXL accelerator > implements. > > Add a new field to cxl_dev_state for keeping device capabilities as > discovered during initialization. Add same field to cxl_port as registers > discovery is also used during port initialization. > > Signed-off-by: Alejandro Lucero <alucerop@amd.com> > Reviewed-by: Ben Cheatham <benjamin.cheatham@amd.com> > Reviewed-by: Fan Ni <fan.ni@samsung.com> Use set_bit() not dereference and |= to set the bits in the bitmap At that point you can void need to force the length of the bitmap. Jonathan > diff --git a/drivers/cxl/core/regs.c b/drivers/cxl/core/regs.c > index 59cb35b40c7e..ac3a27c6e442 100644 > --- a/drivers/cxl/core/regs.c > +++ b/drivers/cxl/core/regs.c > @@ -113,11 +118,12 @@ EXPORT_SYMBOL_NS_GPL(cxl_probe_component_regs, "CXL"); > * @dev: Host device of the @base mapping > * @base: Mapping of CXL 2.0 8.2.8 CXL Device Register Interface > * @map: Map object describing the register block information found > + * @caps: capabilities to be set when discovered > * > * Probe for device register information and return it in map object. > */ > void cxl_probe_device_regs(struct device *dev, void __iomem *base, > - struct cxl_device_reg_map *map) > + struct cxl_device_reg_map *map, unsigned long *caps) > { > int cap, cap_count; > u64 cap_array; > @@ -146,10 +152,12 @@ void cxl_probe_device_regs(struct device *dev, void __iomem *base, > case CXLDEV_CAP_CAP_ID_DEVICE_STATUS: > dev_dbg(dev, "found Status capability (0x%x)\n", offset); > rmap = &map->status; > + *caps |= BIT(CXL_DEV_CAP_DEV_STATUS); > break; > case CXLDEV_CAP_CAP_ID_PRIMARY_MAILBOX: > dev_dbg(dev, "found Mailbox capability (0x%x)\n", offset); > rmap = &map->mbox; > + *caps |= BIT(CXL_DEV_CAP_MAILBOX_PRIMARY); > break; > case CXLDEV_CAP_CAP_ID_SECONDARY_MAILBOX: > dev_dbg(dev, "found Secondary Mailbox capability (0x%x)\n", offset); > @@ -157,6 +165,7 @@ void cxl_probe_device_regs(struct device *dev, void __iomem *base, > case CXLDEV_CAP_CAP_ID_MEMDEV: > dev_dbg(dev, "found Memory Device capability (0x%x)\n", offset); > rmap = &map->memdev; > + *caps |= BIT(CXL_DEV_CAP_MEMDEV); Ah. That would will be why the 64 below. use set_bit() for these, not a dereference. > break; > default: > if (cap_id >= 0x8000) > @@ -421,7 +430,7 @@ static void cxl_unmap_regblock(struct cxl_register_map *map) > map->base = NULL; > } > > -static int cxl_probe_regs(struct cxl_register_map *map) > +static int cxl_probe_regs(struct cxl_register_map *map, unsigned long *caps) > { > struct cxl_component_reg_map *comp_map; > struct cxl_device_reg_map *dev_map; > @@ -431,12 +440,12 @@ static int cxl_probe_regs(struct cxl_register_map *map) > switch (map->reg_type) { > case CXL_REGLOC_RBI_COMPONENT: > comp_map = &map->component_map; > - cxl_probe_component_regs(host, base, comp_map); > + cxl_probe_component_regs(host, base, comp_map, caps); > dev_dbg(host, "Set up component registers\n"); > break; > case CXL_REGLOC_RBI_MEMDEV: > dev_map = &map->device_map; > - cxl_probe_device_regs(host, base, dev_map); > + cxl_probe_device_regs(host, base, dev_map, caps); > if (!dev_map->status.valid || !dev_map->mbox.valid || > !dev_map->memdev.valid) { > dev_err(host, "registers not found: %s%s%s\n", > @@ -455,7 +464,7 @@ static int cxl_probe_regs(struct cxl_register_map *map) > return 0; > } > diff --git a/include/cxl/cxl.h b/include/cxl/cxl.h > index 19e5d883557a..f656fcd4945f 100644 > --- a/include/cxl/cxl.h > +++ b/include/cxl/cxl.h > @@ -12,6 +12,25 @@ enum cxl_resource { > CXL_RES_PMEM, > }; > > +/* Capabilities as defined for: > + * > + * Component Registers (Table 8-22 CXL 3.1 specification) > + * Device Registers (8.2.8.2.1 CXL 3.1 specification) > + * > + * and currently being used for kernel CXL support. > + */ > + > +enum cxl_dev_cap { > + /* capabilities from Component Registers */ > + CXL_DEV_CAP_RAS, > + CXL_DEV_CAP_HDM, > + /* capabilities from Device Registers */ > + CXL_DEV_CAP_DEV_STATUS, > + CXL_DEV_CAP_MAILBOX_PRIMARY, > + CXL_DEV_CAP_MEMDEV, > + CXL_MAX_CAPS = 64 Why set it to 64? All the bitmaps etc will autosize so you just need to ensure you use correct set_bit() and test_bit() that are happy dealing with bitmaps of multiple longs. > +}; > + > struct cxl_dev_state *cxl_accel_state_create(struct device *dev); > > void cxl_set_dvsec(struct cxl_dev_state *cxlds, u16 dvsec);
On 12/24/24 17:08, Jonathan Cameron wrote: > On Mon, 16 Dec 2024 16:10:18 +0000 > <alejandro.lucero-palau@amd.com> wrote: > >> From: Alejandro Lucero <alucerop@amd.com> >> >> Type2 devices have some Type3 functionalities as optional like an mbox >> or an hdm decoder, and CXL core needs a way to know what an CXL accelerator >> implements. >> >> Add a new field to cxl_dev_state for keeping device capabilities as >> discovered during initialization. Add same field to cxl_port as registers >> discovery is also used during port initialization. >> >> Signed-off-by: Alejandro Lucero <alucerop@amd.com> >> Reviewed-by: Ben Cheatham <benjamin.cheatham@amd.com> >> Reviewed-by: Fan Ni <fan.ni@samsung.com> > Use set_bit() not dereference and |= to set the bits in the bitmap > At that point you can void need to force the length of the bitmap. > > Jonathan > >> diff --git a/drivers/cxl/core/regs.c b/drivers/cxl/core/regs.c >> index 59cb35b40c7e..ac3a27c6e442 100644 >> --- a/drivers/cxl/core/regs.c >> +++ b/drivers/cxl/core/regs.c >> @@ -113,11 +118,12 @@ EXPORT_SYMBOL_NS_GPL(cxl_probe_component_regs, "CXL"); >> * @dev: Host device of the @base mapping >> * @base: Mapping of CXL 2.0 8.2.8 CXL Device Register Interface >> * @map: Map object describing the register block information found >> + * @caps: capabilities to be set when discovered >> * >> * Probe for device register information and return it in map object. >> */ >> void cxl_probe_device_regs(struct device *dev, void __iomem *base, >> - struct cxl_device_reg_map *map) >> + struct cxl_device_reg_map *map, unsigned long *caps) >> { >> int cap, cap_count; >> u64 cap_array; >> @@ -146,10 +152,12 @@ void cxl_probe_device_regs(struct device *dev, void __iomem *base, >> case CXLDEV_CAP_CAP_ID_DEVICE_STATUS: >> dev_dbg(dev, "found Status capability (0x%x)\n", offset); >> rmap = &map->status; >> + *caps |= BIT(CXL_DEV_CAP_DEV_STATUS); >> break; >> case CXLDEV_CAP_CAP_ID_PRIMARY_MAILBOX: >> dev_dbg(dev, "found Mailbox capability (0x%x)\n", offset); >> rmap = &map->mbox; >> + *caps |= BIT(CXL_DEV_CAP_MAILBOX_PRIMARY); >> break; >> case CXLDEV_CAP_CAP_ID_SECONDARY_MAILBOX: >> dev_dbg(dev, "found Secondary Mailbox capability (0x%x)\n", offset); >> @@ -157,6 +165,7 @@ void cxl_probe_device_regs(struct device *dev, void __iomem *base, >> case CXLDEV_CAP_CAP_ID_MEMDEV: >> dev_dbg(dev, "found Memory Device capability (0x%x)\n", offset); >> rmap = &map->memdev; >> + *caps |= BIT(CXL_DEV_CAP_MEMDEV); > Ah. That would will be why the 64 below. use set_bit() for these, not a dereference. > Makes sense. I'll do it. >> break; >> default: >> if (cap_id >= 0x8000) >> @@ -421,7 +430,7 @@ static void cxl_unmap_regblock(struct cxl_register_map *map) >> map->base = NULL; >> } >> >> -static int cxl_probe_regs(struct cxl_register_map *map) >> +static int cxl_probe_regs(struct cxl_register_map *map, unsigned long *caps) >> { >> struct cxl_component_reg_map *comp_map; >> struct cxl_device_reg_map *dev_map; >> @@ -431,12 +440,12 @@ static int cxl_probe_regs(struct cxl_register_map *map) >> switch (map->reg_type) { >> case CXL_REGLOC_RBI_COMPONENT: >> comp_map = &map->component_map; >> - cxl_probe_component_regs(host, base, comp_map); >> + cxl_probe_component_regs(host, base, comp_map, caps); >> dev_dbg(host, "Set up component registers\n"); >> break; >> case CXL_REGLOC_RBI_MEMDEV: >> dev_map = &map->device_map; >> - cxl_probe_device_regs(host, base, dev_map); >> + cxl_probe_device_regs(host, base, dev_map, caps); >> if (!dev_map->status.valid || !dev_map->mbox.valid || >> !dev_map->memdev.valid) { >> dev_err(host, "registers not found: %s%s%s\n", >> @@ -455,7 +464,7 @@ static int cxl_probe_regs(struct cxl_register_map *map) >> return 0; >> } >> diff --git a/include/cxl/cxl.h b/include/cxl/cxl.h >> index 19e5d883557a..f656fcd4945f 100644 >> --- a/include/cxl/cxl.h >> +++ b/include/cxl/cxl.h >> @@ -12,6 +12,25 @@ enum cxl_resource { >> CXL_RES_PMEM, >> }; >> >> +/* Capabilities as defined for: >> + * >> + * Component Registers (Table 8-22 CXL 3.1 specification) >> + * Device Registers (8.2.8.2.1 CXL 3.1 specification) >> + * >> + * and currently being used for kernel CXL support. >> + */ >> + >> +enum cxl_dev_cap { >> + /* capabilities from Component Registers */ >> + CXL_DEV_CAP_RAS, >> + CXL_DEV_CAP_HDM, >> + /* capabilities from Device Registers */ >> + CXL_DEV_CAP_DEV_STATUS, >> + CXL_DEV_CAP_MAILBOX_PRIMARY, >> + CXL_DEV_CAP_MEMDEV, >> + CXL_MAX_CAPS = 64 > Why set it to 64? All the bitmaps etc will autosize so > you just need to ensure you use correct set_bit() and test_bit() > that are happy dealing with bitmaps of multiple longs. > Initially it was set to 32, but DECLARE_BITMAP uses unsigned long, so for initializing/zeroing the locally allocated bitmap in some functions, bitmap_clear had to use sizeof for the size, and I was suggested to define CXL_MAX_CAPS to 64 and use it instead, what seems cleaner. >> +}; >> + >> struct cxl_dev_state *cxl_accel_state_create(struct device *dev); >> >> void cxl_set_dvsec(struct cxl_dev_state *cxlds, u16 dvsec);
diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c index 78a5c2c25982..831bc35c2083 100644 --- a/drivers/cxl/core/port.c +++ b/drivers/cxl/core/port.c @@ -749,7 +749,7 @@ static struct cxl_port *cxl_port_alloc(struct device *uport_dev, } static int cxl_setup_comp_regs(struct device *host, struct cxl_register_map *map, - resource_size_t component_reg_phys) + resource_size_t component_reg_phys, unsigned long *caps) { *map = (struct cxl_register_map) { .host = host, @@ -763,7 +763,7 @@ static int cxl_setup_comp_regs(struct device *host, struct cxl_register_map *map map->reg_type = CXL_REGLOC_RBI_COMPONENT; map->max_size = CXL_COMPONENT_REG_BLOCK_SIZE; - return cxl_setup_regs(map); + return cxl_setup_regs(map, caps); } static int cxl_port_setup_regs(struct cxl_port *port, @@ -772,7 +772,7 @@ static int cxl_port_setup_regs(struct cxl_port *port, if (dev_is_platform(port->uport_dev)) return 0; return cxl_setup_comp_regs(&port->dev, &port->reg_map, - component_reg_phys); + component_reg_phys, port->capabilities); } static int cxl_dport_setup_regs(struct device *host, struct cxl_dport *dport, @@ -789,7 +789,8 @@ static int cxl_dport_setup_regs(struct device *host, struct cxl_dport *dport, * NULL. */ rc = cxl_setup_comp_regs(dport->dport_dev, &dport->reg_map, - component_reg_phys); + component_reg_phys, + dport->port->capabilities); dport->reg_map.host = host; return rc; } @@ -851,6 +852,8 @@ static int cxl_port_add(struct cxl_port *port, port->reg_map = cxlds->reg_map; port->reg_map.host = &port->dev; cxlmd->endpoint = port; + bitmap_copy(port->capabilities, cxlds->capabilities, + CXL_MAX_CAPS); } else if (parent_dport) { rc = dev_set_name(dev, "port%d", port->id); if (rc) diff --git a/drivers/cxl/core/regs.c b/drivers/cxl/core/regs.c index 59cb35b40c7e..ac3a27c6e442 100644 --- a/drivers/cxl/core/regs.c +++ b/drivers/cxl/core/regs.c @@ -4,6 +4,7 @@ #include <linux/device.h> #include <linux/slab.h> #include <linux/pci.h> +#include <cxl/cxl.h> #include <cxlmem.h> #include <cxlpci.h> #include <pmu.h> @@ -29,6 +30,7 @@ * @dev: Host device of the @base mapping * @base: Mapping containing the HDM Decoder Capability Header * @map: Map object describing the register block information found + * @caps: capabilities to be set when discovered * * See CXL 2.0 8.2.4 Component Register Layout and Definition * See CXL 2.0 8.2.5.5 CXL Device Register Interface @@ -36,7 +38,8 @@ * Probe for component register information and return it in map object. */ void cxl_probe_component_regs(struct device *dev, void __iomem *base, - struct cxl_component_reg_map *map) + struct cxl_component_reg_map *map, + unsigned long *caps) { int cap, cap_count; u32 cap_array; @@ -84,6 +87,7 @@ void cxl_probe_component_regs(struct device *dev, void __iomem *base, decoder_cnt = cxl_hdm_decoder_count(hdr); length = 0x20 * decoder_cnt + 0x10; rmap = &map->hdm_decoder; + *caps |= BIT(CXL_DEV_CAP_HDM); break; } case CXL_CM_CAP_CAP_ID_RAS: @@ -91,6 +95,7 @@ void cxl_probe_component_regs(struct device *dev, void __iomem *base, offset); length = CXL_RAS_CAPABILITY_LENGTH; rmap = &map->ras; + *caps |= BIT(CXL_DEV_CAP_RAS); break; default: dev_dbg(dev, "Unknown CM cap ID: %d (0x%x)\n", cap_id, @@ -113,11 +118,12 @@ EXPORT_SYMBOL_NS_GPL(cxl_probe_component_regs, "CXL"); * @dev: Host device of the @base mapping * @base: Mapping of CXL 2.0 8.2.8 CXL Device Register Interface * @map: Map object describing the register block information found + * @caps: capabilities to be set when discovered * * Probe for device register information and return it in map object. */ void cxl_probe_device_regs(struct device *dev, void __iomem *base, - struct cxl_device_reg_map *map) + struct cxl_device_reg_map *map, unsigned long *caps) { int cap, cap_count; u64 cap_array; @@ -146,10 +152,12 @@ void cxl_probe_device_regs(struct device *dev, void __iomem *base, case CXLDEV_CAP_CAP_ID_DEVICE_STATUS: dev_dbg(dev, "found Status capability (0x%x)\n", offset); rmap = &map->status; + *caps |= BIT(CXL_DEV_CAP_DEV_STATUS); break; case CXLDEV_CAP_CAP_ID_PRIMARY_MAILBOX: dev_dbg(dev, "found Mailbox capability (0x%x)\n", offset); rmap = &map->mbox; + *caps |= BIT(CXL_DEV_CAP_MAILBOX_PRIMARY); break; case CXLDEV_CAP_CAP_ID_SECONDARY_MAILBOX: dev_dbg(dev, "found Secondary Mailbox capability (0x%x)\n", offset); @@ -157,6 +165,7 @@ void cxl_probe_device_regs(struct device *dev, void __iomem *base, case CXLDEV_CAP_CAP_ID_MEMDEV: dev_dbg(dev, "found Memory Device capability (0x%x)\n", offset); rmap = &map->memdev; + *caps |= BIT(CXL_DEV_CAP_MEMDEV); break; default: if (cap_id >= 0x8000) @@ -421,7 +430,7 @@ static void cxl_unmap_regblock(struct cxl_register_map *map) map->base = NULL; } -static int cxl_probe_regs(struct cxl_register_map *map) +static int cxl_probe_regs(struct cxl_register_map *map, unsigned long *caps) { struct cxl_component_reg_map *comp_map; struct cxl_device_reg_map *dev_map; @@ -431,12 +440,12 @@ static int cxl_probe_regs(struct cxl_register_map *map) switch (map->reg_type) { case CXL_REGLOC_RBI_COMPONENT: comp_map = &map->component_map; - cxl_probe_component_regs(host, base, comp_map); + cxl_probe_component_regs(host, base, comp_map, caps); dev_dbg(host, "Set up component registers\n"); break; case CXL_REGLOC_RBI_MEMDEV: dev_map = &map->device_map; - cxl_probe_device_regs(host, base, dev_map); + cxl_probe_device_regs(host, base, dev_map, caps); if (!dev_map->status.valid || !dev_map->mbox.valid || !dev_map->memdev.valid) { dev_err(host, "registers not found: %s%s%s\n", @@ -455,7 +464,7 @@ static int cxl_probe_regs(struct cxl_register_map *map) return 0; } -int cxl_setup_regs(struct cxl_register_map *map) +int cxl_setup_regs(struct cxl_register_map *map, unsigned long *caps) { int rc; @@ -463,7 +472,7 @@ int cxl_setup_regs(struct cxl_register_map *map) if (rc) return rc; - rc = cxl_probe_regs(map); + rc = cxl_probe_regs(map, caps); cxl_unmap_regblock(map); return rc; diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h index f6015f24ad38..22e787748d79 100644 --- a/drivers/cxl/cxl.h +++ b/drivers/cxl/cxl.h @@ -4,6 +4,7 @@ #ifndef __CXL_H__ #define __CXL_H__ +#include <cxl/cxl.h> #include <linux/libnvdimm.h> #include <linux/bitfield.h> #include <linux/notifier.h> @@ -292,9 +293,9 @@ struct cxl_register_map { }; void cxl_probe_component_regs(struct device *dev, void __iomem *base, - struct cxl_component_reg_map *map); + struct cxl_component_reg_map *map, unsigned long *caps); void cxl_probe_device_regs(struct device *dev, void __iomem *base, - struct cxl_device_reg_map *map); + struct cxl_device_reg_map *map, unsigned long *caps); int cxl_map_component_regs(const struct cxl_register_map *map, struct cxl_component_regs *regs, unsigned long map_mask); @@ -308,7 +309,7 @@ int cxl_find_regblock_instance(struct pci_dev *pdev, enum cxl_regloc_type type, struct cxl_register_map *map, int index); int cxl_find_regblock(struct pci_dev *pdev, enum cxl_regloc_type type, struct cxl_register_map *map); -int cxl_setup_regs(struct cxl_register_map *map); +int cxl_setup_regs(struct cxl_register_map *map, unsigned long *caps); struct cxl_dport; resource_size_t cxl_rcd_component_reg_phys(struct device *dev, struct cxl_dport *dport); @@ -609,6 +610,7 @@ struct cxl_dax_region { * @cdat: Cached CDAT data * @cdat_available: Should a CDAT attribute be available in sysfs * @pci_latency: Upstream latency in picoseconds + * @capabilities: those capabilities as defined in device mapped registers */ struct cxl_port { struct device dev; @@ -632,6 +634,7 @@ struct cxl_port { } cdat; bool cdat_available; long pci_latency; + DECLARE_BITMAP(capabilities, CXL_MAX_CAPS); }; /** diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h index 2a25d1957ddb..4c1c53c29544 100644 --- a/drivers/cxl/cxlmem.h +++ b/drivers/cxl/cxlmem.h @@ -428,6 +428,7 @@ struct cxl_dpa_perf { * @serial: PCIe Device Serial Number * @type: Generic Memory Class device or Vendor Specific Memory device * @cxl_mbox: CXL mailbox context + * @capabilities: those capabilities as defined in device mapped registers */ struct cxl_dev_state { struct device *dev; @@ -443,6 +444,7 @@ struct cxl_dev_state { u64 serial; enum cxl_devtype type; struct cxl_mailbox cxl_mbox; + DECLARE_BITMAP(capabilities, CXL_MAX_CAPS); }; static inline struct cxl_dev_state *mbox_to_cxlds(struct cxl_mailbox *cxl_mbox) diff --git a/drivers/cxl/pci.c b/drivers/cxl/pci.c index 36098e2b4235..dbc1cd9bec09 100644 --- a/drivers/cxl/pci.c +++ b/drivers/cxl/pci.c @@ -504,7 +504,8 @@ static int cxl_rcrb_get_comp_regs(struct pci_dev *pdev, } static int cxl_pci_setup_regs(struct pci_dev *pdev, enum cxl_regloc_type type, - struct cxl_register_map *map) + struct cxl_register_map *map, + unsigned long *caps) { int rc; @@ -534,7 +535,7 @@ static int cxl_pci_setup_regs(struct pci_dev *pdev, enum cxl_regloc_type type, return rc; } - return cxl_setup_regs(map); + return cxl_setup_regs(map, caps); } static int cxl_pci_ras_unmask(struct pci_dev *pdev) @@ -938,7 +939,8 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) cxl_set_dvsec(cxlds, dvsec); - rc = cxl_pci_setup_regs(pdev, CXL_REGLOC_RBI_MEMDEV, &map); + rc = cxl_pci_setup_regs(pdev, CXL_REGLOC_RBI_MEMDEV, &map, + cxlds->capabilities); if (rc) return rc; @@ -951,7 +953,7 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) * still be useful for management functions so don't return an error. */ rc = cxl_pci_setup_regs(pdev, CXL_REGLOC_RBI_COMPONENT, - &cxlds->reg_map); + &cxlds->reg_map, cxlds->capabilities); if (rc) dev_warn(&pdev->dev, "No component registers (%d)\n", rc); else if (!cxlds->reg_map.component_map.ras.valid) diff --git a/include/cxl/cxl.h b/include/cxl/cxl.h index 19e5d883557a..f656fcd4945f 100644 --- a/include/cxl/cxl.h +++ b/include/cxl/cxl.h @@ -12,6 +12,25 @@ enum cxl_resource { CXL_RES_PMEM, }; +/* Capabilities as defined for: + * + * Component Registers (Table 8-22 CXL 3.1 specification) + * Device Registers (8.2.8.2.1 CXL 3.1 specification) + * + * and currently being used for kernel CXL support. + */ + +enum cxl_dev_cap { + /* capabilities from Component Registers */ + CXL_DEV_CAP_RAS, + CXL_DEV_CAP_HDM, + /* capabilities from Device Registers */ + CXL_DEV_CAP_DEV_STATUS, + CXL_DEV_CAP_MAILBOX_PRIMARY, + CXL_DEV_CAP_MEMDEV, + CXL_MAX_CAPS = 64 +}; + struct cxl_dev_state *cxl_accel_state_create(struct device *dev); void cxl_set_dvsec(struct cxl_dev_state *cxlds, u16 dvsec);