On 03/06/2015 03:04 PM, Mason wrote: > Peter Hurley wrote: > >> Mason wrote: >> >>> Is the UART_CONFIG_TYPE flag set for an UPIO_AU iotype? >>> >>> The only place that sets UART_CONFIG_TYPE is >>> drivers/tty/serial/serial_core.c:2177 >>> >>> if (port->flags & UPF_BOOT_AUTOCONF) { >>> if (!(port->flags & UPF_FIXED_TYPE)) { >>> port->type = PORT_UNKNOWN; >>> flags |= UART_CONFIG_TYPE; >>> } >>> port->ops->config_port(port, flags); >>> } >>> >>> Don't know where to look at that point. >> >> For exactly this scenario, the 8250 core rechecks the fields >> derived from port->type (fifosize, capabilites, etc) when the port >> is first opened in serial8250_do_startup(). > > Thanks, I will take a closer look. These fields need to be defined by an entry for PORT_RT2880 in the uart_config[] table. >>> Whatever it is used for, here's the problem: >>> >>> serial_port_in(port, UART_SCR); calls au_serial_in(port, UART_SCR); >>> >>> Out-of-bound access. >> >> That's my breakage. > > Oh! I wasn't aware that the code was recent. I just grabbed the > 4.0-rc2 tarball, and started reading the code. > >>> serial_out(up, UART_SCR, canary); is even worse, as it will scribble >>> over some innocent bystander. >> >> It won't be a different device because the mmio resource request is >> for base + 8 registers. > > Do you mean that some kind of IOMMU would prevent the "misaddressed" > write? I don't think there is any protection on Tango4. I didn't realize the AU register lookup was 'sparse'. That doesn't seem like a good idea. It should at least be defined for the standard register region. >>> So an appropriate fix might be: >>> >>> --- 8250_core.c 2015-03-03 18:04:59.000000000 +0100 >>> +++ 8250_core.fix.c 2015-03-06 18:23:27.374740156 +0100 >>> @@ -378,12 +378,14 @@ >>> >>> static unsigned int au_serial_in(struct uart_port *p, int offset) >>> { >>> + if (offset > UART_MSR) return 0; >>> offset = au_io_in_map[offset] << p->regshift; >>> return __raw_readl(p->membase + offset); >>> } >>> >>> static void au_serial_out(struct uart_port *p, int offset, int value) >>> { >>> + if (offset > UART_MCR) return; >>> offset = au_io_out_map[offset] << p->regshift; >>> __raw_writel(value, p->membase + offset); >>> } >> >> If that fixes my breakage, then ok. I could also skip this UPIO_* type >> for the canary/console restore problem. >> >> Will you submit that as a patch or would you like me to? > > My patch is not even compile-tested ;-) > It was only intended to kick-start the discussion. Ok, I'll come up with something. Will you be able to test a patch? Also, looking at the RT3050 datasheet shows it has has a scratch register; I'll see if I can dig up some info on the RT2880/Au1xxx. > I was also trying to verify that serial_in/out is never called > with UART_EFR when UART_CAP_EFR is not set. Do you know? UART_EFR == 2 == UART_FCR, so yes. But not while in CONF_MODE_B, which I think is what you were asking. Regards, Peter Hurley -- To unsubscribe from this list: send the line "unsubscribe linux-serial" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html