[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v3 01/10] drivers/char: Add support for USB3 DbC debugger
On 26.07.2022 05:23, Marek Marczykowski-Górecki wrote: > +/* Defines the size in bytes of TRB rings as 2^DBC_TRB_RING_ORDER * 4096 */ > +#ifndef DBC_TRB_RING_ORDER > +#define DBC_TRB_RING_ORDER 4 > +#endif > +#define DBC_TRB_RING_CAP (DBC_TRB_PER_PAGE * (1 << DBC_TRB_RING_ORDER)) I have to admit that I'm always puzzled when seeing such - why not #define DBC_TRB_RING_CAP (DBC_TRB_PER_PAGE << DBC_TRB_RING_ORDER) ? > +struct dbc { > + struct dbc_reg __iomem *dbc_reg; > + struct xhci_dbc_ctx *dbc_ctx; > + struct xhci_erst_segment *dbc_erst; > + struct xhci_trb_ring dbc_ering; > + struct xhci_trb_ring dbc_oring; > + struct xhci_trb_ring dbc_iring; > + struct dbc_work_ring dbc_owork; > + struct xhci_string_descriptor *dbc_str; I'm afraid I still don't see why the static page this field is being initialized with is necessary. Can't you have a static variable (of some struct type) all pre-filled at build time, which you then apply virt_to_maddr() to in order to fill the respective dbc_ctx fields? That struct will be quite a bit less than a page's worth in size. If you build the file with -fshort-wchar, you may even be able to use easy to read string literals for the initializer. > +static void *dbc_sys_map_xhc(uint64_t phys, size_t size) > +{ > + size_t i; > + > + if ( size != MAX_XHCI_PAGES * DBC_PAGE_SIZE ) > + return NULL; > + > + for ( i = FIX_XHCI_END; i >= FIX_XHCI_BEGIN; i-- ) > + { > + set_fixmap_nocache(i, phys); > + phys += DBC_PAGE_SIZE; While there may be an assumption of DBC_PAGE_SIZE == PAGE_SIZE, the constant used here clearly needs to be PAGE_SIZE, as that's the unit set_fixmap_nocache() deals with. > +static bool __init dbc_init_xhc(struct dbc *dbc) > +{ > + uint32_t bar0; > + uint64_t bar1; > + uint64_t bar_size; > + uint64_t devfn; > + uint16_t cmd; > + size_t xhc_mmio_size; > + > + /* > + * Search PCI bus 0 for the xHC. All the host controllers supported so > far > + * are part of the chipset and are on bus 0. > + */ > + for ( devfn = 0; devfn < 256; devfn++ ) > + { > + pci_sbdf_t sbdf = PCI_SBDF(0, 0, devfn); > + uint8_t hdr = pci_conf_read8(sbdf, PCI_HEADER_TYPE); > + > + if ( hdr == 0 || hdr == 0x80 ) > + { > + if ( (pci_conf_read32(sbdf, PCI_CLASS_REVISION) >> 8) == > DBC_XHC_CLASSC ) > + { > + dbc->sbdf = sbdf; > + break; > + } > + } > + } > + > + if ( !dbc->sbdf.sbdf ) > + { > + dbc_error("Compatible xHC not found on bus 0\n"); > + return false; > + } > + > + /* ...we found it, so parse the BAR and map the registers */ > + bar0 = pci_conf_read32(dbc->sbdf, PCI_BASE_ADDRESS_0); > + bar1 = pci_conf_read32(dbc->sbdf, PCI_BASE_ADDRESS_1); > + > + /* IO BARs not allowed; BAR must be 64-bit */ > + if ( (bar0 & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_MEMORY || > + (bar0 & PCI_BASE_ADDRESS_MEM_TYPE_MASK) != > PCI_BASE_ADDRESS_MEM_TYPE_64 ) > + return false; > + > + cmd = pci_conf_read16(dbc->sbdf, PCI_COMMAND); > + pci_conf_write16(dbc->sbdf, PCI_COMMAND, cmd & ~PCI_COMMAND_MEMORY); > + > + pci_conf_write32(dbc->sbdf, PCI_BASE_ADDRESS_0, 0xFFFFFFFF); > + pci_conf_write32(dbc->sbdf, PCI_BASE_ADDRESS_1, 0xFFFFFFFF); > + bar_size = pci_conf_read32(dbc->sbdf, PCI_BASE_ADDRESS_0); > + bar_size |= (uint64_t)pci_conf_read32(dbc->sbdf, PCI_BASE_ADDRESS_1) << > 32; > + xhc_mmio_size = ~(bar_size & PCI_BASE_ADDRESS_MEM_MASK) + 1; > + pci_conf_write32(dbc->sbdf, PCI_BASE_ADDRESS_0, bar0); > + pci_conf_write32(dbc->sbdf, PCI_BASE_ADDRESS_1, bar1); > + > + pci_conf_write16(dbc->sbdf, PCI_COMMAND, cmd); > + > + dbc->xhc_mmio_phys = (bar0 & PCI_BASE_ADDRESS_MEM_MASK) | (bar1 << 32); > + dbc->xhc_mmio = dbc_sys_map_xhc(dbc->xhc_mmio_phys, xhc_mmio_size); Before actually using the address to map the MMIO you will want to make somewhat sure firmware did initialize it: The EHCI driver checks for all zeroes or all ones in the writable bits. > +/** > + * The first register of the debug capability is found by traversing the > + * host controller's capability list (xcap) until a capability > + * with ID = 0xA is found. The xHCI capability list begins at address > + * mmio + (HCCPARAMS1[31:16] << 2). > + */ > +static struct dbc_reg __iomem *xhci_find_dbc(struct dbc *dbc) > +{ > + uint32_t *xcap; const? > + uint32_t xcap_val; > + uint32_t next; > + uint32_t id = 0; > + uint8_t *mmio = (uint8_t *)dbc->xhc_mmio; Can't this be const void * (and probably wants to also use __iomem), avoiding the cast here, ... > + uint32_t *hccp1 = (uint32_t *)(mmio + 0x10); ... here, ... > + const uint32_t DBC_ID = 0xA; > + int ttl = 48; > + > + xcap = (uint32_t *)dbc->xhc_mmio; ... and here (if actually using the local variable you've got). > +/* > + * Note that if IN transfer support is added, then this > + * will need to be changed; it assumes an OUT transfer ring only > + */ Hmm, is this comment telling me that this driver is an output-only one? Or is it simply that input doesn't use this code path? > +static void dbc_init_string_single(struct xhci_string_descriptor *string, > + char *ascii_str, If this function has to survive, then const please here and ... > + uint64_t *str_ptr, > + uint8_t *str_size_ptr) > +{ > + size_t i, len = strlen(ascii_str); > + > + string->size = offsetof(typeof(*string), string) + len * 2; > + string->type = XHCI_DT_STRING; > + /* ASCII to UTF16 conversion */ > + for (i = 0; i < len; i++) ... this missing blanks added here. > +static struct xhci_trb evt_trb[DBC_TRB_RING_CAP]; > +static struct xhci_trb out_trb[DBC_TRB_RING_CAP]; > +static struct xhci_trb in_trb[DBC_TRB_RING_CAP]; > +static struct xhci_erst_segment erst __aligned(64); > +static struct xhci_dbc_ctx ctx __aligned(64); > +static uint8_t out_wrk_buf[DBC_WORK_RING_CAP] __aligned(DBC_PAGE_SIZE); > +static struct xhci_string_descriptor str_buf[DBC_STRINGS_COUNT]; > +static char __initdata opt_dbgp[30]; > + > +string_param("dbgp", opt_dbgp); This duplicates what ehci-dbgp.c already has. I guess we can live with it for now and de-duplicate later, but it's still a little odd. In any even please move the blank line up be a line, so that string_param() and its referenced array are kept together. > +void __init xhci_dbc_uart_init(void) > +{ > + struct dbc_uart *uart = &dbc_uart; > + struct dbc *dbc = &uart->dbc; > + > + if ( strncmp(opt_dbgp, "xhci", 4) ) > + return; > + > + memset(dbc, 0, sizeof(*dbc)); Why? dbc_uart is a static variable, and hence already zero-initialized. Jan
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |