From mboxrd@z Thu Jan 1 00:00:00 1970 From: "Jan Beulich" Subject: [PATCH v2 2/4] ns16550: enable Pericom controller support Date: Tue, 22 Mar 2016 07:19:49 -0600 Message-ID: <56F1548502000078000DF2F7@prv-mh.provo.novell.com> References: <56CC4F0B02000078000D5290@prv-mh.provo.novell.com> <56CC508B02000078000D52B1@prv-mh.provo.novell.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=__PartECDB4665.1__=" Return-path: Received: from mail6.bemta3.messagelabs.com ([195.245.230.39]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1aiME3-0007JS-44 for xen-devel@lists.xenproject.org; Tue, 22 Mar 2016 13:19:59 +0000 In-Reply-To: <56CC508B02000078000D52B1@prv-mh.provo.novell.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" To: xen-devel Cc: Keir Fraser , Tim Deegan , Ian Jackson List-Id: xen-devel@lists.xenproject.org This is a MIME message. If you are reading this text, you may want to consider changing to a mail reader or gateway that understands how to properly handle MIME multipart messages. --=__PartECDB4665.1__= Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: quoted-printable Content-Disposition: inline Other than the controllers supported so far, multiple port Pericom boards map all of their ports via BAR0, which requires a number of adjustments: Instead of tracking "max_bars" we now flag whether all ports use BAR0, and whether to expect a port-I/O or MMIO resource. As a result pci_uart_config() now gets handed a port index, which it then maps into a BAR index or an offset into BAR0 depending on the bar0 flag. Signed-off-by: Jan Beulich Tested-by: Konrad Rzeszutek Wilk --- v2: Fix coding style in a piece of code being moved. Add a comment clarifying that on the 4- and 8-port variants we can't use all the ports for now. Retain previous behavior for PCI devices not explicitly listed, even if that behavior was undefined. (The rest of the series is unchanged, so I won't bother reposting the other patches.) --- a/xen/drivers/char/ns16550.c +++ b/xen/drivers/char/ns16550.c @@ -78,10 +78,20 @@ static struct ns16550 { #endif } ns16550_com[2] =3D { { 0 } }; =20 -struct ns16550_config_mmio { +#ifdef CONFIG_HAS_PCI +struct ns16550_config { u16 vendor_id; u16 dev_id; - unsigned int param; + enum { + param_default, /* Must not be referenced by any table entry. */ + param_trumanage, + param_oxford, + param_oxford_2port, + param_pericom_1port, + param_pericom_2port, + param_pericom_4port, + param_pericom_8port, + } param; }; =20 /* Defining uart config options for MMIO devices */ @@ -90,57 +100,95 @@ struct ns16550_config_param { unsigned int reg_width; unsigned int fifo_size; u8 lsr_mask; - unsigned int max_bars; + bool_t mmio; + bool_t bar0; + unsigned int max_ports; unsigned int base_baud; unsigned int uart_offset; unsigned int first_offset; }; =20 - -#ifdef CONFIG_HAS_PCI -enum { - param_default =3D 0, - param_trumanage, - param_oxford, - param_oxford_2port, -}; /* - * Create lookup tables for specific MMIO devices.. - * It is assumed that if the device found is MMIO, - * then you have indexed it here. Else, the driver - * does nothing. + * Create lookup tables for specific devices. It is assumed that if + * the device found is MMIO, then you have indexed it here. Else, the + * driver does nothing for MMIO based devices. */ static const struct ns16550_config_param __initconst uart_param[] =3D { - [param_default] =3D { }, /* Ignored. */ + [param_default] =3D { + .reg_width =3D 1, + .lsr_mask =3D UART_LSR_THRE, + .max_ports =3D 1, + }, [param_trumanage] =3D { .reg_shift =3D 2, .reg_width =3D 1, .fifo_size =3D 16, .lsr_mask =3D (UART_LSR_THRE | UART_LSR_TEMT), - .max_bars =3D 1, + .mmio =3D 1, + .max_ports =3D 1, }, [param_oxford] =3D { .base_baud =3D 4000000, .uart_offset =3D 0x200, .first_offset =3D 0x1000, .reg_width =3D 1, - .reg_shift =3D 0, .fifo_size =3D 16, .lsr_mask =3D UART_LSR_THRE, - .max_bars =3D 1, /* It can do more, but we would need more custom = code.*/ + .mmio =3D 1, + .max_ports =3D 1, /* It can do more, but we would need more = custom code.*/ }, [param_oxford_2port] =3D { .base_baud =3D 4000000, .uart_offset =3D 0x200, .first_offset =3D 0x1000, .reg_width =3D 1, - .reg_shift =3D 0, .fifo_size =3D 16, .lsr_mask =3D UART_LSR_THRE, - .max_bars =3D 2, + .mmio =3D 1, + .max_ports =3D 2, + }, + [param_pericom_1port] =3D { + .base_baud =3D 921600, + .uart_offset =3D 8, + .reg_width =3D 1, + .fifo_size =3D 16, + .lsr_mask =3D UART_LSR_THRE, + .bar0 =3D 1, + .max_ports =3D 1, + }, + [param_pericom_2port] =3D { + .base_baud =3D 921600, + .uart_offset =3D 8, + .reg_width =3D 1, + .fifo_size =3D 16, + .lsr_mask =3D UART_LSR_THRE, + .bar0 =3D 1, + .max_ports =3D 2, + }, + /* + * Of the two following ones, we can't really use all of their ports, + * unless ns16550_com[] would get grown. + */ + [param_pericom_4port] =3D { + .base_baud =3D 921600, + .uart_offset =3D 8, + .reg_width =3D 1, + .fifo_size =3D 16, + .lsr_mask =3D UART_LSR_THRE, + .bar0 =3D 1, + .max_ports =3D 4, + }, + [param_pericom_8port] =3D { + .base_baud =3D 921600, + .uart_offset =3D 8, + .reg_width =3D 1, + .fifo_size =3D 16, + .lsr_mask =3D UART_LSR_THRE, + .bar0 =3D 1, + .max_ports =3D 8, } }; -static const struct ns16550_config_mmio __initconst uart_config[] =3D +static const struct ns16550_config __initconst uart_config[] =3D { /* Broadcom TruManage device */ { @@ -339,6 +387,30 @@ static const struct ns16550_config_mmio .vendor_id =3D PCI_VENDOR_ID_OXSEMI, .dev_id =3D 0xc4cf, .param =3D param_oxford, + }, + /* Pericom PI7C9X7951 Uno UART */ + { + .vendor_id =3D PCI_VENDOR_ID_PERICOM, + .dev_id =3D 0x7951, + .param =3D param_pericom_1port + }, + /* Pericom PI7C9X7952 Duo UART */ + { + .vendor_id =3D PCI_VENDOR_ID_PERICOM, + .dev_id =3D 0x7952, + .param =3D param_pericom_2port + }, + /* Pericom PI7C9X7954 Quad UART */ + { + .vendor_id =3D PCI_VENDOR_ID_PERICOM, + .dev_id =3D 0x7954, + .param =3D param_pericom_4port + }, + /* Pericom PI7C9X7958 Octal UART */ + { + .vendor_id =3D PCI_VENDOR_ID_PERICOM, + .dev_id =3D 0x7958, + .param =3D param_pericom_8port } }; #endif @@ -629,7 +701,8 @@ static void __init ns16550_init_postirq( uart->ps_bdf[2])); else { - if ( rangeset_add_range(mmio_ro_ranges, + if ( uart->param->mmio && + rangeset_add_range(mmio_ro_ranges, uart->io_base, uart->io_base + uart->io_size - 1) ) printk(XENLOG_INFO "Error while adding MMIO range of = device to mmio_ro_ranges\n"); @@ -830,12 +903,11 @@ static int __init check_existence(struct =20 #ifdef CONFIG_HAS_PCI static int __init -pci_uart_config(struct ns16550 *uart, bool_t skip_amt, unsigned int = bar_idx) +pci_uart_config(struct ns16550 *uart, bool_t skip_amt, unsigned int idx) { u64 orig_base =3D uart->io_base; unsigned int b, d, f, nextf, i; =20 - uart->io_base =3D 0; /* NB. Start at bus 1 to avoid AMT: a plug-in card cannot be on bus = 0. */ for ( b =3D skip_amt ? 1 : 0; b < 0x100; b++ ) { @@ -843,8 +915,10 @@ pci_uart_config(struct ns16550 *uart, bo { for ( f =3D 0; f < 8; f =3D nextf ) { + unsigned int bar_idx =3D 0, port_idx =3D idx; uint32_t bar, bar_64 =3D 0, len, len_64; - u64 size; + u64 size =3D 0; + const struct ns16550_config_param *param =3D uart_param; =20 nextf =3D (f || (pci_conf_read16(0, b, d, f, PCI_HEADER_TY= PE) & 0x80)) ? f + 1 : 8; @@ -863,15 +937,39 @@ pci_uart_config(struct ns16550 *uart, bo continue; } =20 + /* Check for params in uart_config lookup table */ + for ( i =3D 0; i < ARRAY_SIZE(uart_config); i++ ) + { + u16 vendor =3D pci_conf_read16(0, b, d, f, PCI_VENDOR_= ID); + u16 device =3D pci_conf_read16(0, b, d, f, PCI_DEVICE_= ID); + + if ( uart_config[i].vendor_id =3D=3D vendor && + uart_config[i].dev_id =3D=3D device ) + { + param +=3D uart_config[i].param; + break; + } + } + + if ( !param->bar0 ) + { + bar_idx =3D idx; + port_idx =3D 0; + } + + if ( port_idx >=3D param->max_ports ) + { + idx -=3D param->max_ports; + continue; + } + + uart->io_base =3D 0; bar =3D pci_conf_read32(0, b, d, f, PCI_BASE_ADDRESS_0 + bar_idx*4); =20 /* MMIO based */ - if ( !(bar & PCI_BASE_ADDRESS_SPACE_IO) ) + if ( param->mmio && !(bar & PCI_BASE_ADDRESS_SPACE_IO) ) { - u16 vendor =3D pci_conf_read16(0, b, d, f, PCI_VENDOR_= ID); - u16 device =3D pci_conf_read16(0, b, d, f, PCI_DEVICE_= ID); - pci_conf_write32(0, b, d, f, PCI_BASE_ADDRESS_0 + bar_idx*4, = ~0u); len =3D pci_conf_read32(0, b, d, f, PCI_BASE_ADDRESS_0= + bar_idx*4); @@ -895,56 +993,11 @@ pci_uart_config(struct ns16550 *uart, bo else size =3D len & PCI_BASE_ADDRESS_MEM_MASK; =20 - size &=3D -size; - - /* Check for params in uart_config lookup table */ - for ( i =3D 0; i < ARRAY_SIZE(uart_config); i++) - { - const struct ns16550_config_param *param; - - if ( uart_config[i].vendor_id !=3D vendor ) - continue; - - if ( uart_config[i].dev_id !=3D device ) - continue; - - param =3D uart_param + uart_config[i].param; - - /* - * Force length of mmio region to be at least - * 8 bytes times (1 << reg_shift) - */ - if ( size < (0x8 * (1 << param->reg_shift)) ) - continue; - - if ( bar_idx >=3D param->max_bars ) - continue; - - uart->param =3D param; - - if ( param->fifo_size ) - uart->fifo_size =3D param->fifo_size; - - uart->reg_shift =3D param->reg_shift; - uart->reg_width =3D param->reg_width; - uart->lsr_mask =3D param->lsr_mask; - uart->io_base =3D ((u64)bar_64 << 32) | - (bar & PCI_BASE_ADDRESS_MEM_MASK);= - uart->io_base +=3D param->first_offset; - uart->io_base +=3D bar_idx * param->uart_offset; - if ( param->base_baud ) - uart->clock_hz =3D param->base_baud * 16; - size =3D max(8U << param->reg_shift, - param->uart_offset); - break; - } - - /* If we have an io_base, then we succeeded in the = lookup */ - if ( !uart->io_base ) - continue; + uart->io_base =3D ((u64)bar_64 << 32) | + (bar & PCI_BASE_ADDRESS_MEM_MASK); } /* IO based */ - else + else if ( !param->mmio && (bar & PCI_BASE_ADDRESS_SPACE_IO= ) ) { pci_conf_write32(0, b, d, f, PCI_BASE_ADDRESS_0 + bar_idx*4, = ~0u); @@ -952,22 +1005,45 @@ pci_uart_config(struct ns16550 *uart, bo pci_conf_write32(0, b, d, f, PCI_BASE_ADDRESS_0 + bar_idx*4, = bar); size =3D len & PCI_BASE_ADDRESS_IO_MASK; - size &=3D -size; - - /* Not at least 8 bytes */ - if ( size < 8 ) - continue; =20 uart->io_base =3D bar & ~PCI_BASE_ADDRESS_SPACE_IO; } =20 + /* If we have an io_base, then we succeeded in the = lookup. */ + if ( !uart->io_base ) + continue; + + size &=3D -size; + + /* + * Require length of actually used region to be at least + * 8 bytes times (1 << reg_shift). + */ + if ( size < param->first_offset + + port_idx * param->uart_offset + + (8 << param->reg_shift) ) + continue; + + uart->param =3D param; + + uart->reg_shift =3D param->reg_shift; + uart->reg_width =3D param->reg_width; + uart->lsr_mask =3D param->lsr_mask; + uart->io_base +=3D param->first_offset + + port_idx * param->uart_offset; + if ( param->base_baud ) + uart->clock_hz =3D param->base_baud * 16; + if ( param->fifo_size ) + uart->fifo_size =3D param->fifo_size; + uart->ps_bdf[0] =3D b; uart->ps_bdf[1] =3D d; uart->ps_bdf[2] =3D f; uart->bar_idx =3D bar_idx; uart->bar =3D bar; uart->bar64 =3D bar_64; - uart->io_size =3D size; + uart->io_size =3D max(8U << param->reg_shift, + param->uart_offset); uart->irq =3D pci_conf_read8(0, b, d, f, PCI_INTERRUPT_PIN= ) ? pci_conf_read8(0, b, d, f, PCI_INTERRUPT_LINE) : 0; =20 --- a/xen/include/xen/pci_ids.h +++ b/xen/include/xen/pci_ids.h @@ -2,6 +2,8 @@ =20 #define PCI_VENDOR_ID_NVIDIA 0x10de =20 +#define PCI_VENDOR_ID_PERICOM 0x12d8 + #define PCI_VENDOR_ID_OXSEMI 0x1415 =20 #define PCI_VENDOR_ID_BROADCOM 0x14e4 --=__PartECDB4665.1__= Content-Type: text/plain; name="ns16550-Pericom.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="ns16550-Pericom.patch" ns16550: enable Pericom controller support=0A=0AOther than the controllers = supported so far, multiple port Pericom=0Aboards map all of their ports = via BAR0, which requires a number of=0Aadjustments: Instead of tracking = "max_bars" we now flag whether all=0Aports use BAR0, and whether to expect = a port-I/O or MMIO resource. As=0Aa result pci_uart_config() now gets = handed a port index, which it then=0Amaps into a BAR index or an offset = into BAR0 depending on the bar0=0Aflag.=0A=0ASigned-off-by: Jan Beulich = =0ATested-by: Konrad Rzeszutek Wilk =0A---=0Av2: Fix coding style in a piece of code being moved. Add a = comment=0A clarifying that on the 4- and 8-port variants we can't use = all the=0A ports for now. Retain previous behavior for PCI devices = not=0A explicitly listed, even if that behavior was undefined. (The = rest=0A of the series is unchanged, so I won't bother reposting the = other=0A patches.)=0A=0A--- a/xen/drivers/char/ns16550.c=0A+++ = b/xen/drivers/char/ns16550.c=0A@@ -78,10 +78,20 @@ static struct ns16550 = {=0A #endif=0A } ns16550_com[2] =3D { { 0 } };=0A =0A-struct ns16550_config= _mmio {=0A+#ifdef CONFIG_HAS_PCI=0A+struct ns16550_config {=0A u16 = vendor_id;=0A u16 dev_id;=0A- unsigned int param;=0A+ enum {=0A+ = param_default, /* Must not be referenced by any table entry. */=0A+ = param_trumanage,=0A+ param_oxford,=0A+ param_oxford_2p= ort,=0A+ param_pericom_1port,=0A+ param_pericom_2port,=0A+ = param_pericom_4port,=0A+ param_pericom_8port,=0A+ } = param;=0A };=0A =0A /* Defining uart config options for MMIO devices = */=0A@@ -90,57 +100,95 @@ struct ns16550_config_param {=0A unsigned = int reg_width;=0A unsigned int fifo_size;=0A u8 lsr_mask;=0A- = unsigned int max_bars;=0A+ bool_t mmio;=0A+ bool_t bar0;=0A+ = unsigned int max_ports;=0A unsigned int base_baud;=0A unsigned int = uart_offset;=0A unsigned int first_offset;=0A };=0A =0A-=0A-#ifdef = CONFIG_HAS_PCI=0A-enum {=0A- param_default =3D 0,=0A- param_trumanage= ,=0A- param_oxford,=0A- param_oxford_2port,=0A-};=0A /*=0A- * Create = lookup tables for specific MMIO devices..=0A- * It is assumed that if the = device found is MMIO,=0A- * then you have indexed it here. Else, the = driver=0A- * does nothing.=0A+ * Create lookup tables for specific = devices. It is assumed that if=0A+ * the device found is MMIO, then you = have indexed it here. Else, the=0A+ * driver does nothing for MMIO based = devices.=0A */=0A static const struct ns16550_config_param __initconst = uart_param[] =3D {=0A- [param_default] =3D { }, /* Ignored. */=0A+ = [param_default] =3D {=0A+ .reg_width =3D 1,=0A+ .lsr_mask = =3D UART_LSR_THRE,=0A+ .max_ports =3D 1,=0A+ },=0A [param_tru= manage] =3D {=0A .reg_shift =3D 2,=0A .reg_width =3D 1,=0A = .fifo_size =3D 16,=0A .lsr_mask =3D (UART_LSR_THRE | = UART_LSR_TEMT),=0A- .max_bars =3D 1,=0A+ .mmio =3D 1,=0A+ = .max_ports =3D 1,=0A },=0A [param_oxford] =3D {=0A = .base_baud =3D 4000000,=0A .uart_offset =3D 0x200,=0A = .first_offset =3D 0x1000,=0A .reg_width =3D 1,=0A- = .reg_shift =3D 0,=0A .fifo_size =3D 16,=0A .lsr_mask =3D = UART_LSR_THRE,=0A- .max_bars =3D 1, /* It can do more, but we would = need more custom code.*/=0A+ .mmio =3D 1,=0A+ .max_ports =3D = 1, /* It can do more, but we would need more custom code.*/=0A },=0A = [param_oxford_2port] =3D {=0A .base_baud =3D 4000000,=0A = .uart_offset =3D 0x200,=0A .first_offset =3D 0x1000,=0A = .reg_width =3D 1,=0A- .reg_shift =3D 0,=0A .fifo_size =3D = 16,=0A .lsr_mask =3D UART_LSR_THRE,=0A- .max_bars =3D = 2,=0A+ .mmio =3D 1,=0A+ .max_ports =3D 2,=0A+ },=0A+ = [param_pericom_1port] =3D {=0A+ .base_baud =3D 921600,=0A+ = .uart_offset =3D 8,=0A+ .reg_width =3D 1,=0A+ .fifo_size =3D = 16,=0A+ .lsr_mask =3D UART_LSR_THRE,=0A+ .bar0 =3D 1,=0A+ = .max_ports =3D 1,=0A+ },=0A+ [param_pericom_2port] =3D {=0A+ = .base_baud =3D 921600,=0A+ .uart_offset =3D 8,=0A+ = .reg_width =3D 1,=0A+ .fifo_size =3D 16,=0A+ .lsr_mask =3D = UART_LSR_THRE,=0A+ .bar0 =3D 1,=0A+ .max_ports =3D 2,=0A+ = },=0A+ /*=0A+ * Of the two following ones, we can't really use all = of their ports,=0A+ * unless ns16550_com[] would get grown.=0A+ = */=0A+ [param_pericom_4port] =3D {=0A+ .base_baud =3D 921600,=0A+= .uart_offset =3D 8,=0A+ .reg_width =3D 1,=0A+ = .fifo_size =3D 16,=0A+ .lsr_mask =3D UART_LSR_THRE,=0A+ = .bar0 =3D 1,=0A+ .max_ports =3D 4,=0A+ },=0A+ [param_pericom_8= port] =3D {=0A+ .base_baud =3D 921600,=0A+ .uart_offset =3D = 8,=0A+ .reg_width =3D 1,=0A+ .fifo_size =3D 16,=0A+ = .lsr_mask =3D UART_LSR_THRE,=0A+ .bar0 =3D 1,=0A+ .max_ports = =3D 8,=0A }=0A };=0A-static const struct ns16550_config_mmio __initcons= t uart_config[] =3D=0A+static const struct ns16550_config __initconst = uart_config[] =3D=0A {=0A /* Broadcom TruManage device */=0A = {=0A@@ -339,6 +387,30 @@ static const struct ns16550_config_mmio=0A = .vendor_id =3D PCI_VENDOR_ID_OXSEMI,=0A .dev_id =3D 0xc4cf,=0A = .param =3D param_oxford,=0A+ },=0A+ /* Pericom PI7C9X7951 Uno = UART */=0A+ {=0A+ .vendor_id =3D PCI_VENDOR_ID_PERICOM,=0A+ = .dev_id =3D 0x7951,=0A+ .param =3D param_pericom_1port=0A+ = },=0A+ /* Pericom PI7C9X7952 Duo UART */=0A+ {=0A+ .vendor_id = =3D PCI_VENDOR_ID_PERICOM,=0A+ .dev_id =3D 0x7952,=0A+ = .param =3D param_pericom_2port=0A+ },=0A+ /* Pericom PI7C9X7954 Quad = UART */=0A+ {=0A+ .vendor_id =3D PCI_VENDOR_ID_PERICOM,=0A+ = .dev_id =3D 0x7954,=0A+ .param =3D param_pericom_4port=0A+ = },=0A+ /* Pericom PI7C9X7958 Octal UART */=0A+ {=0A+ = .vendor_id =3D PCI_VENDOR_ID_PERICOM,=0A+ .dev_id =3D 0x7958,=0A+ = .param =3D param_pericom_8port=0A }=0A };=0A #endif=0A@@ -629,7 = +701,8 @@ static void __init ns16550_init_postirq(=0A = uart->ps_bdf[2]));=0A else=0A {=0A- if ( = rangeset_add_range(mmio_ro_ranges,=0A+ if ( uart->param->mmio = &&=0A+ rangeset_add_range(mmio_ro_ranges,=0A = uart->io_base,=0A = uart->io_base + uart->io_size - 1) )=0A printk(XENLOG_INFO= "Error while adding MMIO range of device to mmio_ro_ranges\n");=0A@@ = -830,12 +903,11 @@ static int __init check_existence(struct=0A =0A #ifdef = CONFIG_HAS_PCI=0A static int __init=0A-pci_uart_config(struct ns16550 = *uart, bool_t skip_amt, unsigned int bar_idx)=0A+pci_uart_config(struct = ns16550 *uart, bool_t skip_amt, unsigned int idx)=0A {=0A u64 = orig_base =3D uart->io_base;=0A unsigned int b, d, f, nextf, i;=0A = =0A- uart->io_base =3D 0;=0A /* NB. Start at bus 1 to avoid AMT: a = plug-in card cannot be on bus 0. */=0A for ( b =3D skip_amt ? 1 : 0; b = < 0x100; b++ )=0A {=0A@@ -843,8 +915,10 @@ pci_uart_config(struct = ns16550 *uart, bo=0A {=0A for ( f =3D 0; f < 8; f =3D = nextf )=0A {=0A+ unsigned int bar_idx =3D 0, = port_idx =3D idx;=0A uint32_t bar, bar_64 =3D 0, len, = len_64;=0A- u64 size;=0A+ u64 size =3D = 0;=0A+ const struct ns16550_config_param *param =3D = uart_param;=0A =0A nextf =3D (f || (pci_conf_read16(0, b, = d, f, PCI_HEADER_TYPE) &=0A 0x80)) ? f + 1 = : 8;=0A@@ -863,15 +937,39 @@ pci_uart_config(struct ns16550 *uart, bo=0A = continue;=0A }=0A =0A+ /* = Check for params in uart_config lookup table */=0A+ for ( i = =3D 0; i < ARRAY_SIZE(uart_config); i++ )=0A+ {=0A+ = u16 vendor =3D pci_conf_read16(0, b, d, f, PCI_VENDOR_ID);=0A+ = u16 device =3D pci_conf_read16(0, b, d, f, PCI_DEVICE_ID)= ;=0A+=0A+ if ( uart_config[i].vendor_id =3D=3D vendor = &&=0A+ uart_config[i].dev_id =3D=3D device )=0A+ = {=0A+ param +=3D uart_config[i].par= am;=0A+ break;=0A+ }=0A+ = }=0A+=0A+ if ( !param->bar0 )=0A+ = {=0A+ bar_idx =3D idx;=0A+ port_idx = =3D 0;=0A+ }=0A+=0A+ if ( port_idx >=3D = param->max_ports )=0A+ {=0A+ idx -=3D = param->max_ports;=0A+ continue;=0A+ = }=0A+=0A+ uart->io_base =3D 0;=0A bar =3D = pci_conf_read32(0, b, d, f,=0A = PCI_BASE_ADDRESS_0 + bar_idx*4);=0A =0A /* MMIO based = */=0A- if ( !(bar & PCI_BASE_ADDRESS_SPACE_IO) )=0A+ = if ( param->mmio && !(bar & PCI_BASE_ADDRESS_SPACE_IO) )=0A = {=0A- u16 vendor =3D pci_conf_read16(0, b, d, = f, PCI_VENDOR_ID);=0A- u16 device =3D pci_conf_read16(0,= b, d, f, PCI_DEVICE_ID);=0A-=0A pci_conf_write32(0, = b, d, f,=0A PCI_BASE_ADDRESS_0 + = bar_idx*4, ~0u);=0A len =3D pci_conf_read32(0, b, d, = f, PCI_BASE_ADDRESS_0 + bar_idx*4);=0A@@ -895,56 +993,11 @@ pci_uart_config= (struct ns16550 *uart, bo=0A else=0A = size =3D len & PCI_BASE_ADDRESS_MEM_MASK;=0A =0A- = size &=3D -size;=0A-=0A- /* Check for params in = uart_config lookup table */=0A- for ( i =3D 0; i < = ARRAY_SIZE(uart_config); i++)=0A- {=0A- = const struct ns16550_config_param *param;=0A-=0A- = if ( uart_config[i].vendor_id !=3D vendor )=0A- = continue;=0A-=0A- if ( uart_config[i].dev_id = !=3D device )=0A- continue;=0A-=0A- = param =3D uart_param + uart_config[i].param;=0A-=0A- = /*=0A- * Force length of mmio region = to be at least=0A- * 8 bytes times (1 << reg_shift)= =0A- */=0A- if ( size < = (0x8 * (1 << param->reg_shift)) )=0A- = continue;=0A-=0A- if ( bar_idx >=3D param->max_bars = )=0A- continue;=0A-=0A- = uart->param =3D param;=0A-=0A- if ( param->fifo_size= )=0A- uart->fifo_size =3D param->fifo_size;=0A-= =0A- uart->reg_shift =3D param->reg_shift;=0A- = uart->reg_width =3D param->reg_width;=0A- = uart->lsr_mask =3D param->lsr_mask;=0A- = uart->io_base =3D ((u64)bar_64 << 32) |=0A- = (bar & PCI_BASE_ADDRESS_MEM_MASK);=0A- = uart->io_base +=3D param->first_offset;=0A- = uart->io_base +=3D bar_idx * param->uart_offset;=0A- = if ( param->base_baud )=0A- uart->clock_hz =3D = param->base_baud * 16;=0A- size =3D max(8U << = param->reg_shift,=0A- param->uart_offset)= ;=0A- break;=0A- }=0A-=0A- = /* If we have an io_base, then we succeeded in the lookup = */=0A- if ( !uart->io_base )=0A- = continue;=0A+ uart->io_base =3D ((u64)bar_64 << 32) = |=0A+ (bar & PCI_BASE_ADDRESS_MEM_MASK);= =0A }=0A /* IO based */=0A- = else=0A+ else if ( !param->mmio && (bar & PCI_BASE_ADDRESS_S= PACE_IO) )=0A {=0A pci_conf_write32(0, = b, d, f,=0A PCI_BASE_ADDRESS_0 + = bar_idx*4, ~0u);=0A@@ -952,22 +1005,45 @@ pci_uart_config(struct ns16550 = *uart, bo=0A pci_conf_write32(0, b, d, f,=0A = PCI_BASE_ADDRESS_0 + bar_idx*4, bar);=0A = size =3D len & PCI_BASE_ADDRESS_IO_MASK;=0A- = size &=3D -size;=0A-=0A- /* Not at least 8 bytes = */=0A- if ( size < 8 )=0A- = continue;=0A =0A uart->io_base =3D bar & ~PCI_BASE_ADDR= ESS_SPACE_IO;=0A }=0A =0A+ /* If we have an = io_base, then we succeeded in the lookup. */=0A+ if ( = !uart->io_base )=0A+ continue;=0A+=0A+ = size &=3D -size;=0A+=0A+ /*=0A+ * Require = length of actually used region to be at least=0A+ * 8 = bytes times (1 << reg_shift).=0A+ */=0A+ if = ( size < param->first_offset +=0A+ port_idx * = param->uart_offset +=0A+ (8 << param->reg_shift)= )=0A+ continue;=0A+=0A+ uart->param =3D = param;=0A+=0A+ uart->reg_shift =3D param->reg_shift;=0A+ = uart->reg_width =3D param->reg_width;=0A+ = uart->lsr_mask =3D param->lsr_mask;=0A+ uart->io_base +=3D = param->first_offset +=0A+ port_idx * = param->uart_offset;=0A+ if ( param->base_baud )=0A+ = uart->clock_hz =3D param->base_baud * 16;=0A+ if = ( param->fifo_size )=0A+ uart->fifo_size =3D param->fifo= _size;=0A+=0A uart->ps_bdf[0] =3D b;=0A = uart->ps_bdf[1] =3D d;=0A uart->ps_bdf[2] =3D f;=0A = uart->bar_idx =3D bar_idx;=0A uart->bar =3D = bar;=0A uart->bar64 =3D bar_64;=0A- = uart->io_size =3D size;=0A+ uart->io_size =3D max(8U << = param->reg_shift,=0A+ param->uart_offset= );=0A uart->irq =3D pci_conf_read8(0, b, d, f, PCI_INTERRUP= T_PIN) ?=0A pci_conf_read8(0, b, d, f, PCI_INTERRUPT_LI= NE) : 0;=0A =0A--- a/xen/include/xen/pci_ids.h=0A+++ b/xen/include/xen/pci_= ids.h=0A@@ -2,6 +2,8 @@=0A =0A #define PCI_VENDOR_ID_NVIDIA = 0x10de=0A =0A+#define PCI_VENDOR_ID_PERICOM 0x12d8=0A+=0A = #define PCI_VENDOR_ID_OXSEMI 0x1415=0A =0A #define PCI_VENDOR_I= D_BROADCOM 0x14e4=0A --=__PartECDB4665.1__= Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: base64 Content-Disposition: inline X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KWGVuLWRldmVs IG1haWxpbmcgbGlzdApYZW4tZGV2ZWxAbGlzdHMueGVuLm9yZwpodHRwOi8vbGlzdHMueGVuLm9y Zy94ZW4tZGV2ZWwK --=__PartECDB4665.1__=--