Re: [PATCH v6 1/4] usb: dbc: early driver for xhci debug capability

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Ingo,

On 01/22/2017 05:31 PM, Ingo Molnar wrote:
> * Lu Baolu <baolu.lu@xxxxxxxxxxxxxxx> wrote:
>
>> xHCI debug capability (DbC) is an optional but standalone
>> functionality provided by an xHCI host controller. Software
>> learns this capability by walking through the extended
>> capability list of the host. xHCI specification describes
>> DbC in section 7.6.
>>
>> This patch introduces the code to probe and initialize the
>> debug capability hardware during early boot. With hardware
>> initialized, the debug target (system on which this code is
>> running) will present a debug device through the debug port
>> (normally the first USB3 port). The debug device is fully
>> compliant with the USB framework and provides the equivalent
>> of a very high performance (USB3) full-duplex serial link
>> between the debug host and target. The DbC functionality is
>> independent of xHCI host. There isn't any precondition from
>> xHCI host side for DbC to work.
> s/xHCI host/the xHCI host
>
>> This patch also includes bulk out and bulk in interfaces.
>> These interfaces could be used to implement early printk
>> bootconsole or hook to various system debuggers.
> s/out/output
> s/in/input
>
>> +config EARLY_PRINTK_USB_XDBC
>> +	bool "Early printk via xHCI debug port"
> s/xHCI/the xHCI
>
> I remarked on this in my first review as well - mind checking the whole series for 
> uses of 'xHCI'?
>
>> +	depends on EARLY_PRINTK && PCI
>> +	select EARLY_PRINTK_USB
>> +	---help---
>> +	  Write kernel log output directly into the xHCI debug port.
>> +
>> +	  This is useful for kernel debugging when your machine crashes very
>> +	  early before the console code is initialized. For normal operation
>> +	  it is not recommended because it looks ugly and doesn't cooperate
>> +	  with klogd/syslogd or the X server. You should normally N here,
>> +	  unless you want to debug such a crash.
>> +
>>  config X86_PTDUMP_CORE
>>  	def_bool n
>>  
>> diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
>> index fbe493d..9313fff 100644
>> --- a/drivers/usb/Kconfig
>> +++ b/drivers/usb/Kconfig
>> @@ -19,6 +19,9 @@ config USB_EHCI_BIG_ENDIAN_MMIO
>>  config USB_EHCI_BIG_ENDIAN_DESC
>>  	bool
>>  
>> +config USB_EARLY_PRINTK
>> +	bool
>> +
>>  menuconfig USB_SUPPORT
>>  	bool "USB support"
>>  	depends on HAS_IOMEM
>> diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
>> index 7791af6..53d1356 100644
>> --- a/drivers/usb/Makefile
>> +++ b/drivers/usb/Makefile
>> @@ -49,7 +49,7 @@ obj-$(CONFIG_USB_MICROTEK)	+= image/
>>  obj-$(CONFIG_USB_SERIAL)	+= serial/
>>  
>>  obj-$(CONFIG_USB)		+= misc/
>> -obj-$(CONFIG_EARLY_PRINTK_DBGP)	+= early/
>> +obj-$(CONFIG_EARLY_PRINTK_USB)	+= early/
>>  
>>  obj-$(CONFIG_USB_ATM)		+= atm/
>>  obj-$(CONFIG_USB_SPEEDTOUCH)	+= atm/
>> diff --git a/drivers/usb/early/Makefile b/drivers/usb/early/Makefile
>> index 24bbe51..fcde228 100644
>> --- a/drivers/usb/early/Makefile
>> +++ b/drivers/usb/early/Makefile
>> @@ -3,3 +3,4 @@
>>  #
>>  
>>  obj-$(CONFIG_EARLY_PRINTK_DBGP) += ehci-dbgp.o
>> +obj-$(CONFIG_EARLY_PRINTK_USB_XDBC) += xhci-dbc.o
>> diff --git a/drivers/usb/early/xhci-dbc.c b/drivers/usb/early/xhci-dbc.c
>> new file mode 100644
>> index 0000000..72480c4
>> --- /dev/null
>> +++ b/drivers/usb/early/xhci-dbc.c
>> @@ -0,0 +1,1027 @@
>> +/**
>> + * xhci-dbc.c - xHCI debug capability early driver
>> + *
>> + * Copyright (C) 2016 Intel Corporation
>> + *
>> + * Author: Lu Baolu <baolu.lu@xxxxxxxxxxxxxxx>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + */
>> +
>> +#define pr_fmt(fmt)	KBUILD_MODNAME ":%s: " fmt, __func__
>> +
>> +#include <linux/console.h>
>> +#include <linux/pci_regs.h>
>> +#include <linux/pci_ids.h>
>> +#include <linux/bootmem.h>
>> +#include <linux/io.h>
>> +#include <asm/pci-direct.h>
>> +#include <asm/fixmap.h>
>> +#include <linux/bcd.h>
>> +#include <linux/export.h>
>> +#include <linux/version.h>
>> +#include <linux/module.h>
>> +#include <linux/delay.h>
>> +
>> +#include "../host/xhci.h"
>> +#include "xhci-dbc.h"
>> +
>> +static struct xdbc_state xdbc;
>> +static int early_console_keep;
>> +
>> +#ifdef XDBC_TRACE
>> +#define	xdbc_trace	trace_printk
>> +#else
>> +static inline void xdbc_trace(const char *fmt, ...) { }
>> +#endif /* XDBC_TRACE */
>> +
>> +static int xdbc_bulk_transfer(void *data, int size, bool read);
>> +
>> +static void __iomem * __init xdbc_map_pci_mmio(u32 bus, u32 dev, u32 func)
>> +{
>> +	u32 val, sz;
>> +	u64 val64, sz64, mask64;
>> +	u8 byte;
>> +	void __iomem *base;
>> +
>> +	val = read_pci_config(bus, dev, func, PCI_BASE_ADDRESS_0);
>> +	write_pci_config(bus, dev, func, PCI_BASE_ADDRESS_0, ~0);
>> +	sz = read_pci_config(bus, dev, func, PCI_BASE_ADDRESS_0);
>> +	write_pci_config(bus, dev, func, PCI_BASE_ADDRESS_0, val);
>> +	if (val == 0xffffffff || sz == 0xffffffff) {
>> +		pr_notice("invalid mmio bar\n");
>> +		return NULL;
>> +	}
>> +
>> +	val64 = val & PCI_BASE_ADDRESS_MEM_MASK;
>> +	sz64 = sz & PCI_BASE_ADDRESS_MEM_MASK;
>> +	mask64 = (u32)PCI_BASE_ADDRESS_MEM_MASK;
> Is this cast necessary?
>
>> +
>> +	if ((val & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64) {
>> +		val = read_pci_config(bus, dev, func, PCI_BASE_ADDRESS_0 + 4);
>> +		write_pci_config(bus, dev, func, PCI_BASE_ADDRESS_0 + 4, ~0);
>> +		sz = read_pci_config(bus, dev, func, PCI_BASE_ADDRESS_0 + 4);
>> +		write_pci_config(bus, dev, func, PCI_BASE_ADDRESS_0 + 4, val);
>> +
>> +		val64 |= (u64)val << 32;
>> +		sz64 |= (u64)sz << 32;
> Could these type casts be avoided by declaring 'val' and 'sz' as u64 to begin 
> with?
>
>> +		mask64 |= (u64)~0 << 32;
> Type cast could be avoided by using 0L.
>
>> +static u32 __init xdbc_find_dbgp(int xdbc_num, u32 *b, u32 *d, u32 *f)
>> +{
>> +	u32 bus, dev, func, class;
>> +
>> +	for (bus = 0; bus < XDBC_PCI_MAX_BUSES; bus++) {
>> +		for (dev = 0; dev < XDBC_PCI_MAX_DEVICES; dev++) {
>> +			for (func = 0; func < XDBC_PCI_MAX_FUNCTION; func++) {
>> +				class = read_pci_config(bus, dev, func, PCI_CLASS_REVISION);
>> +				if ((class >> 8) != PCI_CLASS_SERIAL_USB_XHCI)
>> +					continue;
>> +
>> +				if (xdbc_num-- != 0)
>> +					continue;
>> +
>> +				*b = bus;
>> +				*d = dev;
>> +				*f = func;
>> +
>> +				return 0;
>> +			}
>> +		}
>> +	}
> Nit: to me it would look more balanced visually if the body of the innermost loop 
> started with an empty newline.
>
>> +	ext_cap_offset = xhci_find_next_ext_cap(xdbc.xhci_base,
>> +						0, XHCI_EXT_CAPS_LEGACY);
> Please don't break this line. You can shorten the variable name if you want to 
> save line length.
>
>> +	/* populate the contexts */
>> +	context = (struct xdbc_context *)xdbc.dbcc_base;
>> +	context->info.string0 = cpu_to_le64(xdbc.string_dma);
>> +	context->info.manufacturer = cpu_to_le64(xdbc.string_dma + XDBC_MAX_STRING_LENGTH);
>> +	context->info.product = cpu_to_le64(xdbc.string_dma + XDBC_MAX_STRING_LENGTH * 2);
>> +	context->info.serial = cpu_to_le64(xdbc.string_dma + XDBC_MAX_STRING_LENGTH * 3);
>> +	context->info.length = cpu_to_le32(string_length);
> Wouldn't this (and some of the other initializations) look nicer this way:
>
> 	/* Populate the contexts: */
> 	context = (struct xdbc_context *)xdbc.dbcc_base;
>
> 	context->info.string0		= cpu_to_le64(xdbc.string_dma);
> 	context->info.manufacturer	= cpu_to_le64(xdbc.string_dma + XDBC_MAX_STRING_LENGTH);
> 	context->info.product		= cpu_to_le64(xdbc.string_dma + XDBC_MAX_STRING_LENGTH * 2);
> 	context->info.serial		= cpu_to_le64(xdbc.string_dma + XDBC_MAX_STRING_LENGTH * 3);
> 	context->info.length		= cpu_to_le32(string_length);
>
> ?
>
>> +	/* Check completion of the previous request. */
> Could you please standardize the capitalization and punctuation of all the 
> comments in the patches? Some are lower case, some are upper case, some have full 
> stops, some don't.
>
> One good style would be to use this form when a comment refers to what the next 
> statement does:
>
> 	/* Check completion of the previous request: */
>
>> +/**
>> + * struct xdbc_regs - xHCI Debug Capability Register interface.
>> + */
>> +struct xdbc_regs {
>> +	__le32	capability;
>> +	__le32	doorbell;
>> +	__le32	ersts;		/* Event Ring Segment Table Size*/
>> +	__le32	__reserved_0;	/* 0c~0f reserved bits */
>> +	__le64	erstba;		/* Event Ring Segment Table Base Address */
>> +	__le64	erdp;		/* Event Ring Dequeue Pointer */
>> +	__le32	control;
>> +#define DEBUG_MAX_BURST(p)	(((p) >> 16) & 0xff)
>> +#define CTRL_DCR		BIT(0)		/* DbC Run */
>> +#define CTRL_PED		BIT(1)		/* Port Enable/Disable */
>> +#define CTRL_HOT		BIT(2)		/* Halt Out TR */
>> +#define CTRL_HIT		BIT(3)		/* Halt In TR */
>> +#define CTRL_DRC		BIT(4)		/* DbC run change */
>> +#define CTRL_DCE		BIT(31)		/* DbC enable */
>> +	__le32	status;
>> +#define DCST_DPN(p)		(((p) >> 24) & 0xff)
>> +	__le32	portsc;		/* Port status and control */
>> +#define PORTSC_CCS		BIT(0)
>> +#define PORTSC_CSC		BIT(17)
>> +#define PORTSC_PRC		BIT(21)
>> +#define PORTSC_PLC		BIT(22)
>> +#define PORTSC_CEC		BIT(23)
>> +	__le32	__reserved_1;	/* 2b~28 reserved bits */
>> +	__le64	dccp;		/* Debug Capability Context Pointer */
>> +	__le32	devinfo1;	/* Device Descriptor Info Register 1 */
>> +	__le32	devinfo2;	/* Device Descriptor Info Register 2 */
>> +};
> So why are defines intermixed with the fields? If the defines relate to the field 
> then their naming sure does not express that ...
>
> I was thinking of something like:
>
> /**
>  * struct xdbc_regs - xHCI Debug Capability Register interface.
>  */
> struct xdbc_regs {
> 	__le32	capability;
> 	__le32	doorbell;
> 	__le32	ersts;		/* Event Ring Segment Table Size*/
> 	__le32	__reserved_0;	/* 0c~0f reserved bits */
> 	__le64	erstba;		/* Event Ring Segment Table Base Address */
> 	__le64	erdp;		/* Event Ring Dequeue Pointer */
> 	__le32	control;
> 	__le32	status;
> 	__le32	portsc;		/* Port status and control */
> 	__le32	__reserved_1;	/* 2b~28 reserved bits */
> 	__le64	dccp;		/* Debug Capability Context Pointer */
> 	__le32	devinfo1;	/* Device Descriptor Info Register 1 */
> 	__le32	devinfo2;	/* Device Descriptor Info Register 2 */
> };
>
> #define DEBUG_MAX_BURST(p)	(((p) >> 16) & 0xff)
>
> #define	CTRL_DCR		BIT(0)		/* DbC Run */
> #define	CTRL_PED		BIT(1)		/* Port Enable/Disable */
> #define	CTRL_HOT		BIT(2)		/* Halt Out TR */
> #define	CTRL_HIT		BIT(3)		/* Halt In TR */
> #define	CTRL_DRC		BIT(4)		/* DbC run change */
> #define CTRL_DCE		BIT(31)		/* DbC enable */
>
> #define DCST_DPN(p)		(((p) >> 24) & 0xff)
>
> #define PORTSC_CCS		BIT(0)
> #define PORTSC_CSC		BIT(17)
> #define PORTSC_PRC		BIT(21)
> #define PORTSC_PLC		BIT(22)
> #define PORTSC_CEC		BIT(23)
>
> Also, the abbreviations suck big time. What's wrong with:
>
> #define	CTRL_DBC_RUN		BIT(0)
> #define	CTRL_PORT_ENABLE	BIT(1)
> #define	CTRL_HALT_OUT_TR	BIT(2)
> #define	CTRL_HALT_IN_TR		BIT(3)
> #define	CTRL_DBC_RUN_CHANGE	BIT(4)
> #define CTRL_DBC_ENABLE		BIT(31)
>
> ?
>
> Also note how the comments became superfluous once descriptive names are chosen...
>
> Please review the rest of the defines and series for similar problems and fix 
> them, there are more of the same type.

Thank you for the comments.

I will correct all the code style issues you pointed out here. And, I will
review all patches and fix the similar code styles.

Best regards,
Lu Baolu

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux