Commit c35ec6da authored by Russell King's avatar Russell King

[SERIAL] 8250: Fix resource handling.

serial8250_request_std_resource() is now responsible for claiming
the standard resources, _and_ calling ioremap if necessary.
serial8250_release_std_resource() performs the complementary function
in its entirety.
serial8250_*_rsa_resource() perform the similar operations for RSA
ports, with the exception that RSA ports can only be mapped into IO
space.
parent c1d0b9d9
...@@ -1732,147 +1732,130 @@ serial8250_pm(struct uart_port *port, unsigned int state, ...@@ -1732,147 +1732,130 @@ serial8250_pm(struct uart_port *port, unsigned int state,
} }
/* /*
* Resource handling. This is complicated by the fact that resources * Resource handling.
* depend on the port type. Maybe we should be claiming the standard
* 8250 ports, and then trying to get other resources as necessary?
*/ */
static int static int serial8250_request_std_resource(struct uart_8250_port *up)
serial8250_request_std_resource(struct uart_8250_port *up, struct resource **res)
{ {
unsigned int size = 8 << up->port.regshift; unsigned int size = 8 << up->port.regshift;
int ret = 0; int ret = 0;
switch (up->port.iotype) { switch (up->port.iotype) {
case UPIO_MEM: case UPIO_MEM:
if (up->port.mapbase) { if (!up->port.mapbase)
*res = request_mem_region(up->port.mapbase, size, "serial"); break;
if (!*res)
if (!request_mem_region(up->port.mapbase, size, "serial")) {
ret = -EBUSY; ret = -EBUSY;
break;
}
if (up->port.flags & UPF_IOREMAP) {
up->port.membase = ioremap(up->port.mapbase, size);
if (!up->port.membase) {
release_mem_region(up->port.mapbase, size);
ret = -ENOMEM;
}
} }
break; break;
case UPIO_HUB6: case UPIO_HUB6:
case UPIO_PORT: case UPIO_PORT:
*res = request_region(up->port.iobase, size, "serial"); if (!request_region(up->port.iobase, size, "serial"))
if (!*res)
ret = -EBUSY; ret = -EBUSY;
break; break;
} }
return ret; return ret;
} }
static int static void serial8250_release_std_resource(struct uart_8250_port *up)
serial8250_request_rsa_resource(struct uart_8250_port *up, struct resource **res)
{ {
unsigned int size = 8 << up->port.regshift; unsigned int size = 8 << up->port.regshift;
unsigned long start;
int ret = 0;
switch (up->port.iotype) { switch (up->port.iotype) {
case UPIO_MEM: case UPIO_MEM:
if (up->port.mapbase) { if (!up->port.mapbase)
start = up->port.mapbase; break;
start += UART_RSA_BASE << up->port.regshift;
*res = request_mem_region(start, size, "serial-rsa"); if (up->port.flags & UPF_IOREMAP) {
if (!*res) iounmap(up->port.membase);
ret = -EBUSY; up->port.membase = NULL;
} }
release_mem_region(up->port.mapbase, size);
break; break;
case UPIO_HUB6: case UPIO_HUB6:
case UPIO_PORT: case UPIO_PORT:
start = up->port.iobase; release_region(up->port.iobase, size);
start += UART_RSA_BASE << up->port.regshift;
*res = request_region(start, size, "serial-rsa");
if (!*res)
ret = -EBUSY;
break; break;
} }
return ret;
} }
static void serial8250_release_port(struct uart_port *port) static int serial8250_request_rsa_resource(struct uart_8250_port *up)
{ {
struct uart_8250_port *up = (struct uart_8250_port *)port; unsigned long start = UART_RSA_BASE << up->port.regshift;
unsigned long start, offset = 0, size = 0; unsigned int size = 8 << up->port.regshift;
int ret = 0;
if (up->port.type == PORT_RSA) {
offset = UART_RSA_BASE << up->port.regshift;
size = 8;
}
size <<= up->port.regshift;
switch (up->port.iotype) { switch (up->port.iotype) {
case UPIO_MEM: case UPIO_MEM:
if (up->port.mapbase) { ret = -EINVAL;
/*
* Unmap the area.
*/
iounmap(up->port.membase);
up->port.membase = NULL;
start = up->port.mapbase;
if (size)
release_mem_region(start + offset, size);
release_mem_region(start, 8 << up->port.regshift);
}
break; break;
case UPIO_HUB6: case UPIO_HUB6:
case UPIO_PORT: case UPIO_PORT:
start = up->port.iobase; start += up->port.iobase;
if (!request_region(start, size, "serial-rsa"))
ret = -EBUSY;
break;
}
return ret;
}
if (size) static void serial8250_release_rsa_resource(struct uart_8250_port *up)
release_region(start + offset, size); {
release_region(start + offset, 8 << up->port.regshift); unsigned long offset = UART_RSA_BASE << up->port.regshift;
unsigned int size = 8 << up->port.regshift;
switch (up->port.iotype) {
case UPIO_MEM:
break; break;
default: case UPIO_HUB6:
case UPIO_PORT:
release_region(up->port.iobase + offset, size);
break; break;
} }
} }
static void serial8250_release_port(struct uart_port *port)
{
struct uart_8250_port *up = (struct uart_8250_port *)port;
serial8250_release_std_resource(up);
if (up->port.type == PORT_RSA)
serial8250_release_rsa_resource(up);
}
static int serial8250_request_port(struct uart_port *port) static int serial8250_request_port(struct uart_port *port)
{ {
struct uart_8250_port *up = (struct uart_8250_port *)port; struct uart_8250_port *up = (struct uart_8250_port *)port;
struct resource *res = NULL, *res_rsa = NULL;
int ret = 0; int ret = 0;
if (up->port.type == PORT_RSA) { ret = serial8250_request_std_resource(up);
ret = serial8250_request_rsa_resource(up, &res_rsa); if (ret == 0 && up->port.type == PORT_RSA) {
ret = serial8250_request_rsa_resource(up);
if (ret < 0) if (ret < 0)
return ret; serial8250_release_std_resource(up);
} }
ret = serial8250_request_std_resource(up, &res);
/*
* If we have a mapbase, then request that as well.
*/
if (ret == 0 && up->port.flags & UPF_IOREMAP) {
int size = res->end - res->start + 1;
up->port.membase = ioremap(up->port.mapbase, size);
if (!up->port.membase)
ret = -ENOMEM;
}
if (ret < 0) {
if (res_rsa)
release_resource(res_rsa);
if (res)
release_resource(res);
}
return ret; return ret;
} }
static void serial8250_config_port(struct uart_port *port, int flags) static void serial8250_config_port(struct uart_port *port, int flags)
{ {
struct uart_8250_port *up = (struct uart_8250_port *)port; struct uart_8250_port *up = (struct uart_8250_port *)port;
struct resource *res_std = NULL, *res_rsa = NULL;
int probeflags = PROBE_ANY; int probeflags = PROBE_ANY;
int ret; int ret;
...@@ -1888,11 +1871,11 @@ static void serial8250_config_port(struct uart_port *port, int flags) ...@@ -1888,11 +1871,11 @@ static void serial8250_config_port(struct uart_port *port, int flags)
* Find the region that we can probe for. This in turn * Find the region that we can probe for. This in turn
* tells us whether we can probe for the type of port. * tells us whether we can probe for the type of port.
*/ */
ret = serial8250_request_std_resource(up, &res_std); ret = serial8250_request_std_resource(up);
if (ret < 0) if (ret < 0)
return; return;
ret = serial8250_request_rsa_resource(up, &res_rsa); ret = serial8250_request_rsa_resource(up);
if (ret < 0) if (ret < 0)
probeflags &= ~PROBE_RSA; probeflags &= ~PROBE_RSA;
...@@ -1901,14 +1884,10 @@ static void serial8250_config_port(struct uart_port *port, int flags) ...@@ -1901,14 +1884,10 @@ static void serial8250_config_port(struct uart_port *port, int flags)
if (up->port.type != PORT_UNKNOWN && flags & UART_CONFIG_IRQ) if (up->port.type != PORT_UNKNOWN && flags & UART_CONFIG_IRQ)
autoconfig_irq(up); autoconfig_irq(up);
/* if (up->port.type != PORT_RSA && probeflags & PROBE_RSA)
* If the port wasn't an RSA port, release the resource. serial8250_release_rsa_resource(up);
*/ if (up->port.type == PORT_UNKNOWN)
if (up->port.type != PORT_RSA && res_rsa) serial8250_release_std_resource(up);
release_resource(res_rsa);
if (up->port.type == PORT_UNKNOWN && res_std)
release_resource(res_std);
} }
static int static int
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment