[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


  • To: Marek Marczykowski-Górecki <marmarek@xxxxxxxxxxxxxxxxxxxxxx>
  • From: Jan Beulich <jbeulich@xxxxxxxx>
  • Date: Thu, 4 Aug 2022 14:57:49 +0200
  • Arc-authentication-results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=suse.com; dmarc=pass action=none header.from=suse.com; dkim=pass header.d=suse.com; arc=none
  • Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=GX863cdnPMGRfoePH0UbtwPVNoWdonpfCfVzTBXZXQQ=; b=TAMtmBuGKAOAAF7rLdsjaX1KkPscbpnKupv/GUTXIYMNC8G3dCKWIupnw8IshpdUbBDMlqGJu+oagGK8JiqfImbSE17YuDJpdwurxCFl3gj6xCVoxjLEywyESI3FLRnYS9bjwRi3ZsyzyuAMr0tISWXz2bcz0MAZPPrrlx1mtiRWffLhjEnZKxHXndTVVYQBornswoLAJXsg0uAR2ksILSM1LCAQUWmCREWzrPqaFnMJx63nSiTObRFysiQ36xDJN4QUSmKKIt1Q5PDEkqViLLpkC0QuWVGgeMlM2dnCQTGDB6lFhFs9g4r4qsUWeJA35qYLPQ9IfZEQuKYVUeUqSA==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=LTsV/O230l/kAycvpcOiQLo43ItRPZbAusDPMMLdr+9XHpf745Kw/wz24i8H+6Olf6q87Uy3BZp9H13RZtITNVYk0dg0Oom6Glw9YkGTQmledEyvzxs4ucZNaO6TgN/r0ZGYc43G7VaSm5OtU6gzcHRYiUHPtn54r7lYkZArdJTcMpzpRFAS5hbCjRTKi14ZJJDH+QZkGBd3aGzIDOwwDf9KR7avwhVoFGgrsWB8DTRP3R23HCojNtz52RFYvxvBFTb1gJ+mCpDUZNQQQD/SCThj7L8/mHSO0Hgi3TnjGM2XUEEVTQ1kgqdUUyaczhpIbks5cLRTcBiYobUm7Mq8gw==
  • Authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=suse.com;
  • Cc: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>, George Dunlap <george.dunlap@xxxxxxxxxx>, Julien Grall <julien@xxxxxxx>, Stefano Stabellini <sstabellini@xxxxxxxxxx>, Wei Liu <wl@xxxxxxx>, Roger Pau Monné <roger.pau@xxxxxxxxxx>, xen-devel@xxxxxxxxxxxxxxxxxxxx
  • Delivery-date: Thu, 04 Aug 2022 12:58:02 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>

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



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.