From 075b8783da0db700868c7b391636a85c06a89678 Mon Sep 17 00:00:00 2001 From: Ryan Bradetich Date: Fri, 3 Nov 2006 05:05:01 +0000 Subject: [PARISC] HPPB bus updates for E-Class systems This patch addresses the following issues: * Removes an incorrect comment. * Fixes a couple of compiler warnings. * Properly detects the HP-PB bus on E-Class systems. Signed-off-by: Ryan Bradetich Signed-off-by: Kyle McMartin --- drivers/parisc/hppb.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/parisc/hppb.c b/drivers/parisc/hppb.c index 07dc2b6d4e9..9bb4db552f3 100644 --- a/drivers/parisc/hppb.c +++ b/drivers/parisc/hppb.c @@ -10,10 +10,6 @@ ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** -** This Driver currently only supports the console (port 0) on the MUX. -** Additional work will be needed on this driver to enable the full -** functionality of the MUX. -** */ #include @@ -67,7 +63,7 @@ static int hppb_probe(struct parisc_device *dev) } card = card->next; } - printk(KERN_INFO "Found GeckoBoa at 0x%lx\n", dev->hpa.start); + printk(KERN_INFO "Found GeckoBoa at 0x%x\n", dev->hpa.start); card->hpa = dev->hpa.start; card->mmio_region.name = "HP-PB Bus"; @@ -78,16 +74,18 @@ static int hppb_probe(struct parisc_device *dev) status = ccio_request_resource(dev, &card->mmio_region); if(status < 0) { - printk(KERN_ERR "%s: failed to claim HP-PB bus space (%08lx, %08lx)\n", + printk(KERN_ERR "%s: failed to claim HP-PB bus space (%08x, %08x)\n", __FILE__, card->mmio_region.start, card->mmio_region.end); } return 0; } - static struct parisc_device_id hppb_tbl[] = { - { HPHW_BCPORT, HVERSION_REV_ANY_ID, 0x500, 0xc }, + { HPHW_BCPORT, HVERSION_REV_ANY_ID, 0x500, 0xc }, /* E25 and K */ + { HPHW_BCPORT, 0x0, 0x501, 0xc }, /* E35 */ + { HPHW_BCPORT, 0x0, 0x502, 0xc }, /* E45 */ + { HPHW_BCPORT, 0x0, 0x503, 0xc }, /* E55 */ { 0, } }; -- cgit v1.2.3-70-g09d2 From 4bd5d82779466a2969c631ce283bef926680c9f5 Mon Sep 17 00:00:00 2001 From: Ryan Bradetich Date: Fri, 3 Nov 2006 05:38:39 +0000 Subject: [PARISC] [MUX] Mux driver bug fix This patch addresses the problems identified by Russell King in the following email: http://lists.parisc-linux.org/pipermail/parisc-linux/2005-December/027912.html Signed-off-by: Ryan Bradetich Signed-off-by: Kyle McMartin --- drivers/serial/mux.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/mux.c b/drivers/serial/mux.c index 8ad1b8c5ec5..ec57a616788 100644 --- a/drivers/serial/mux.c +++ b/drivers/serial/mux.c @@ -51,7 +51,11 @@ #define MUX_NR 256 static unsigned int port_cnt __read_mostly; -static struct uart_port mux_ports[MUX_NR]; +struct mux_port { + struct uart_port port; + int enabled; +}; +static struct mux_port mux_ports[MUX_NR]; static struct uart_driver mux_driver = { .owner = THIS_MODULE, @@ -250,7 +254,7 @@ static void mux_read(struct uart_port *port) */ static int mux_startup(struct uart_port *port) { - mod_timer(&mux_timer, jiffies + MUX_POLL_DELAY); + mux_ports[port->line].enabled = 1; return 0; } @@ -262,6 +266,7 @@ static int mux_startup(struct uart_port *port) */ static void mux_shutdown(struct uart_port *port) { + mux_ports[port->line].enabled = 0; } /** @@ -319,7 +324,7 @@ static int mux_request_port(struct uart_port *port) * @port: Ptr to the uart_port. * @type: Bitmask of required configurations. * - * Perform any autoconfiguration steps for the port. This functino is + * Perform any autoconfiguration steps for the port. This function is * called if the UPF_BOOT_AUTOCONF flag is specified for the port. * [Note: This is required for now because of a bug in the Serial core. * rmk has already submitted a patch to linus, should be available for @@ -357,11 +362,11 @@ static void mux_poll(unsigned long unused) int i; for(i = 0; i < port_cnt; ++i) { - if(!mux_ports[i].info) + if(!mux_ports[i].enabled) continue; - mux_read(&mux_ports[i]); - mux_write(&mux_ports[i]); + mux_read(&mux_ports[i].port); + mux_write(&mux_ports[i].port); } mod_timer(&mux_timer, jiffies + MUX_POLL_DELAY); @@ -456,7 +461,7 @@ static int __init mux_probe(struct parisc_device *dev) } for(i = 0; i < ports; ++i, ++port_cnt) { - port = &mux_ports[port_cnt]; + port = &mux_ports[port_cnt].port; port->iobase = 0; port->mapbase = dev->hpa.start + MUX_OFFSET + (i * MUX_LINE_OFFSET); @@ -484,6 +489,8 @@ static int __init mux_probe(struct parisc_device *dev) #ifdef CONFIG_SERIAL_MUX_CONSOLE register_console(&mux_console); #endif + mod_timer(&mux_timer, jiffies + MUX_POLL_DELAY); + return 0; } @@ -520,9 +527,9 @@ static void __exit mux_exit(void) int i; for (i = 0; i < port_cnt; i++) { - uart_remove_one_port(&mux_driver, &mux_ports[i]); - if (mux_ports[i].membase) - iounmap(mux_ports[i].membase); + uart_remove_one_port(&mux_driver, &mux_ports[i].port); + if (mux_ports[i].port.membase) + iounmap(mux_ports[i].port.membase); } uart_unregister_driver(&mux_driver); -- cgit v1.2.3-70-g09d2 From 3de7b6482b4e9a34f91604ee0fb7a3ace250f3bb Mon Sep 17 00:00:00 2001 From: Ryan Bradetich Date: Fri, 3 Nov 2006 05:52:41 +0000 Subject: [PARISC] [MUX] Mux driver updates This patch changes the Mux console to use the Mux hardware instead of the PDC Software console. Signed-off-by: Ryan Bradetich Signed-off-by: Kyle McMartin --- drivers/serial/mux.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/mux.c b/drivers/serial/mux.c index ec57a616788..6408b9b1561 100644 --- a/drivers/serial/mux.c +++ b/drivers/serial/mux.c @@ -376,8 +376,17 @@ static void mux_poll(unsigned long unused) #ifdef CONFIG_SERIAL_MUX_CONSOLE static void mux_console_write(struct console *co, const char *s, unsigned count) { - while(count--) - pdc_iodc_putc(*s++); + /* Wait until the FIFO drains. */ + while(UART_GET_FIFO_CNT(&mux_ports[0].port)) + udelay(1); + + while(count--) { + if(*s == '\n') { + UART_PUT_CHAR(&mux_ports[0].port, '\r'); + } + UART_PUT_CHAR(&mux_ports[0].port, *s++); + } + } static int mux_console_setup(struct console *co, char *options) -- cgit v1.2.3-70-g09d2 From 9c6416ce6a9829ede1594403d19b22d23cf54e2e Mon Sep 17 00:00:00 2001 From: Ryan Bradetich Date: Fri, 3 Nov 2006 06:34:16 +0000 Subject: [PARISC] [MUX] Claim resources for the Mux driver This patch claims the iomem resources for the Mux driver. Signed-off-by: Ryan Bradetich Signed-off-by: Kyle McMartin --- drivers/serial/mux.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/serial/mux.c b/drivers/serial/mux.c index 6408b9b1561..f21faf16395 100644 --- a/drivers/serial/mux.c +++ b/drivers/serial/mux.c @@ -66,6 +66,13 @@ static struct uart_driver mux_driver = { .nr = MUX_NR, }; +struct mux_card { + int port_count; + struct parisc_device *dev; + struct mux_card *next; +}; + +static struct mux_card *mux_card_head; static struct timer_list mux_timer; #define UART_PUT_CHAR(p, c) __raw_writel((c), (p)->membase + IO_DATA_REG_OFFSET) @@ -433,6 +440,37 @@ static struct uart_ops mux_pops = { .verify_port = mux_verify_port, }; +/** + * get_new_mux_card - Allocate and return a new mux card. + * + * This function is used to allocate and return a new mux card. + */ +static struct mux_card * __init get_new_mux_card(void) +{ + struct mux_card *card = mux_card_head; + + if(card == NULL) { + mux_card_head = kzalloc(sizeof(struct mux_card), GFP_KERNEL); + if(!mux_card_head) { + printk(KERN_ERR "MUX: Unable to allocate memory.\n"); + return NULL; + } + return mux_card_head; + } + + while(card->next) { + card = card->next; + } + + card->next = kzalloc(sizeof(struct mux_card), GFP_KERNEL); + if(!card->next) { + printk(KERN_ERR "MUX: Unable to allocate memory.\n"); + return NULL; + } + + return card->next; +} + /** * mux_probe - Determine if the Serial Mux should claim this device. * @dev: The parisc device. @@ -446,6 +484,7 @@ static int __init mux_probe(struct parisc_device *dev) u8 iodc_data[32]; unsigned long bytecnt; struct uart_port *port; + struct mux_card *card; status = pdc_iodc_read(&bytecnt, dev->hpa.start, 0, iodc_data, 32); if(status != PDC_OK) { @@ -454,7 +493,16 @@ static int __init mux_probe(struct parisc_device *dev) } ports = GET_MUX_PORTS(iodc_data); - printk(KERN_INFO "Serial mux driver (%d ports) Revision: 0.3\n", ports); + printk(KERN_INFO "Serial mux driver (%d ports) Revision: 0.4\n", ports); + + card = get_new_mux_card(); + if(card == NULL) + return 1; + + card->dev = dev; + card->port_count = ports; + request_mem_region(card->dev->hpa.start + MUX_OFFSET, + card->port_count * MUX_LINE_OFFSET, "Mux"); if(!port_cnt) { mux_driver.cons = MUX_CONSOLE; @@ -534,6 +582,8 @@ static int __init mux_init(void) static void __exit mux_exit(void) { int i; + struct mux_card *next; + struct mux_card *card = mux_card_head; for (i = 0; i < port_cnt; i++) { uart_remove_one_port(&mux_driver, &mux_ports[i].port); @@ -541,6 +591,15 @@ static void __exit mux_exit(void) iounmap(mux_ports[i].port.membase); } + while(card != NULL) { + release_mem_region(card->dev->hpa.start + MUX_OFFSET, + card->port_count * MUX_LINE_OFFSET); + + next = card->next; + kfree(card); + card = next; + } + uart_unregister_driver(&mux_driver); } -- cgit v1.2.3-70-g09d2 From c380f057269686e17db74d360c923663889ac702 Mon Sep 17 00:00:00 2001 From: Ryan Bradetich Date: Sun, 5 Nov 2006 01:21:44 +0000 Subject: [PARISC] [MUX] Make the Serial Mux driver work as module The following updates are based off a patch from willy: * Removal of the mux_card list. * Add the mux_remove function. Other updates: * Re-organize the driver structure a bit to make the mux_init and mux_exit functions more symmetrical. * Added the del_timer. * Unregistered the console. At this point I can insmod, rmmod, and re-insmod the mux without any failures. Signed-off-by: Ryan Bradetich Signed-off-by: Kyle McMartin --- drivers/serial/mux.c | 135 ++++++++++++++++++++++----------------------------- 1 file changed, 57 insertions(+), 78 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/mux.c b/drivers/serial/mux.c index f21faf16395..5ff7e05a152 100644 --- a/drivers/serial/mux.c +++ b/drivers/serial/mux.c @@ -66,13 +66,6 @@ static struct uart_driver mux_driver = { .nr = MUX_NR, }; -struct mux_card { - int port_count; - struct parisc_device *dev; - struct mux_card *next; -}; - -static struct mux_card *mux_card_head; static struct timer_list mux_timer; #define UART_PUT_CHAR(p, c) __raw_writel((c), (p)->membase + IO_DATA_REG_OFFSET) @@ -440,37 +433,6 @@ static struct uart_ops mux_pops = { .verify_port = mux_verify_port, }; -/** - * get_new_mux_card - Allocate and return a new mux card. - * - * This function is used to allocate and return a new mux card. - */ -static struct mux_card * __init get_new_mux_card(void) -{ - struct mux_card *card = mux_card_head; - - if(card == NULL) { - mux_card_head = kzalloc(sizeof(struct mux_card), GFP_KERNEL); - if(!mux_card_head) { - printk(KERN_ERR "MUX: Unable to allocate memory.\n"); - return NULL; - } - return mux_card_head; - } - - while(card->next) { - card = card->next; - } - - card->next = kzalloc(sizeof(struct mux_card), GFP_KERNEL); - if(!card->next) { - printk(KERN_ERR "MUX: Unable to allocate memory.\n"); - return NULL; - } - - return card->next; -} - /** * mux_probe - Determine if the Serial Mux should claim this device. * @dev: The parisc device. @@ -480,11 +442,9 @@ static struct mux_card * __init get_new_mux_card(void) */ static int __init mux_probe(struct parisc_device *dev) { - int i, status, ports; + int i, status, port_count; u8 iodc_data[32]; unsigned long bytecnt; - struct uart_port *port; - struct mux_card *card; status = pdc_iodc_read(&bytecnt, dev->hpa.start, 0, iodc_data, 32); if(status != PDC_OK) { @@ -492,17 +452,12 @@ static int __init mux_probe(struct parisc_device *dev) return 1; } - ports = GET_MUX_PORTS(iodc_data); - printk(KERN_INFO "Serial mux driver (%d ports) Revision: 0.4\n", ports); + port_count = GET_MUX_PORTS(iodc_data); + printk(KERN_INFO "Serial mux driver (%d ports) Revision: 0.5\n", port_count); - card = get_new_mux_card(); - if(card == NULL) - return 1; - - card->dev = dev; - card->port_count = ports; - request_mem_region(card->dev->hpa.start + MUX_OFFSET, - card->port_count * MUX_LINE_OFFSET, "Mux"); + dev_set_drvdata(&dev->dev, (void *)(long)port_count); + request_mem_region(dev->hpa.start + MUX_OFFSET, + port_count * MUX_LINE_OFFSET, "Mux"); if(!port_cnt) { mux_driver.cons = MUX_CONSOLE; @@ -512,13 +467,10 @@ static int __init mux_probe(struct parisc_device *dev) printk(KERN_ERR "Serial mux: Unable to register driver.\n"); return 1; } - - init_timer(&mux_timer); - mux_timer.function = mux_poll; } - for(i = 0; i < ports; ++i, ++port_cnt) { - port = &mux_ports[port_cnt].port; + for(i = 0; i < port_count; ++i, ++port_cnt) { + struct uart_port *port = &mux_ports[port_cnt].port; port->iobase = 0; port->mapbase = dev->hpa.start + MUX_OFFSET + (i * MUX_LINE_OFFSET); @@ -543,11 +495,34 @@ static int __init mux_probe(struct parisc_device *dev) BUG_ON(status); } -#ifdef CONFIG_SERIAL_MUX_CONSOLE - register_console(&mux_console); -#endif - mod_timer(&mux_timer, jiffies + MUX_POLL_DELAY); + return 0; +} +static int __devexit mux_remove(struct parisc_device *dev) +{ + int i; + int port_count = (long)dev_get_drvdata(&dev->dev); + + /* Delete the Mux timer. */ + del_timer(&mux_timer); + + /* Find Port 0 for this card in the mux_ports list. */ + for(i = 0; i < port_cnt; ++i) { + if(mux_ports[i].port.mapbase == dev->hpa.start + MUX_OFFSET) + break; + } + BUG_ON(i + port_count > port_cnt); + + /* Release the resources associated with each port on the device. */ + for(; i < port_count; ++i) { + struct uart_port *port = &mux_ports[i].port; + + uart_remove_one_port(&mux_driver, port); + if(port->membase) + iounmap(port->membase); + } + + release_mem_region(dev->hpa.start + MUX_OFFSET, port_count * MUX_LINE_OFFSET); return 0; } @@ -562,6 +537,7 @@ static struct parisc_driver serial_mux_driver = { .name = "serial_mux", .id_table = mux_tbl, .probe = mux_probe, + .remove = __devexit_p(mux_remove), }; /** @@ -571,7 +547,20 @@ static struct parisc_driver serial_mux_driver = { */ static int __init mux_init(void) { - return register_parisc_driver(&serial_mux_driver); + int status = register_parisc_driver(&serial_mux_driver); + + if(port_cnt > 0) { + /* Start the Mux timer */ + init_timer(&mux_timer); + mux_timer.function = mux_poll; + mod_timer(&mux_timer, jiffies + MUX_POLL_DELAY); + +#ifdef CONFIG_SERIAL_MUX_CONSOLE + register_console(&mux_console); +#endif + } + + return status; } /** @@ -581,25 +570,15 @@ static int __init mux_init(void) */ static void __exit mux_exit(void) { - int i; - struct mux_card *next; - struct mux_card *card = mux_card_head; - - for (i = 0; i < port_cnt; i++) { - uart_remove_one_port(&mux_driver, &mux_ports[i].port); - if (mux_ports[i].port.membase) - iounmap(mux_ports[i].port.membase); - } - - while(card != NULL) { - release_mem_region(card->dev->hpa.start + MUX_OFFSET, - card->port_count * MUX_LINE_OFFSET); - - next = card->next; - kfree(card); - card = next; + /* Delete the Mux timer. */ + if(port_cnt > 0) { + del_timer(&mux_timer); +#ifdef CONFIG_SERIAL_MUX_CONSOLE + unregister_console(&mux_console); +#endif } + unregister_parisc_driver(&serial_mux_driver); uart_unregister_driver(&mux_driver); } -- cgit v1.2.3-70-g09d2 From 752b940359089ee1bcaceeb5c62d626a92586ba2 Mon Sep 17 00:00:00 2001 From: Ryan Bradetich Date: Thu, 9 Nov 2006 04:45:08 +0000 Subject: [PARISC] [MUX] Detect multiple cards in the correct order This patch follows the example of the 8250_gsc driver by probing for specific built-in Mux cards first. This allows the system to preserve the correct detection order with multiple Mux cards. Signed-off-by: Ryan Bradetich Signed-off-by: Kyle McMartin --- drivers/serial/mux.c | 38 ++++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/mux.c b/drivers/serial/mux.c index 5ff7e05a152..87269cca9c7 100644 --- a/drivers/serial/mux.c +++ b/drivers/serial/mux.c @@ -453,7 +453,7 @@ static int __init mux_probe(struct parisc_device *dev) } port_count = GET_MUX_PORTS(iodc_data); - printk(KERN_INFO "Serial mux driver (%d ports) Revision: 0.5\n", port_count); + printk(KERN_INFO "Serial mux driver (%d ports) Revision: 0.6\n", port_count); dev_set_drvdata(&dev->dev, (void *)(long)port_count); request_mem_region(dev->hpa.start + MUX_OFFSET, @@ -491,6 +491,7 @@ static int __init mux_probe(struct parisc_device *dev) */ port->timeout = HZ / 50; spin_lock_init(&port->lock); + status = uart_add_one_port(&mux_driver, port); BUG_ON(status); } @@ -500,12 +501,9 @@ static int __init mux_probe(struct parisc_device *dev) static int __devexit mux_remove(struct parisc_device *dev) { - int i; + int i, j; int port_count = (long)dev_get_drvdata(&dev->dev); - /* Delete the Mux timer. */ - del_timer(&mux_timer); - /* Find Port 0 for this card in the mux_ports list. */ for(i = 0; i < port_cnt; ++i) { if(mux_ports[i].port.mapbase == dev->hpa.start + MUX_OFFSET) @@ -514,7 +512,7 @@ static int __devexit mux_remove(struct parisc_device *dev) BUG_ON(i + port_count > port_cnt); /* Release the resources associated with each port on the device. */ - for(; i < port_count; ++i) { + for(j = 0; j < port_count; ++j, ++i) { struct uart_port *port = &mux_ports[i].port; uart_remove_one_port(&mux_driver, port); @@ -526,13 +524,35 @@ static int __devexit mux_remove(struct parisc_device *dev) return 0; } +/* Hack. This idea was taken from the 8250_gsc.c on how to properly order + * the serial port detection in the proper order. The idea is we always + * want the builtin mux to be detected before addin mux cards, so we + * specifically probe for the builtin mux cards first. + * + * This table only contains the parisc_device_id of known builtin mux + * devices. All other mux cards will be detected by the generic mux_tbl. + */ +static struct parisc_device_id builtin_mux_tbl[] = { + { HPHW_A_DIRECT, HVERSION_REV_ANY_ID, 0x15, 0x0000D }, /* All K-class */ + { HPHW_A_DIRECT, HVERSION_REV_ANY_ID, 0x44, 0x0000D }, /* E35, E45, and E55 */ + { 0, } +}; + static struct parisc_device_id mux_tbl[] = { { HPHW_A_DIRECT, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0000D }, { 0, } }; +MODULE_DEVICE_TABLE(parisc, builtin_mux_tbl); MODULE_DEVICE_TABLE(parisc, mux_tbl); +static struct parisc_driver builtin_serial_mux_driver = { + .name = "builtin_serial_mux", + .id_table = builtin_mux_tbl, + .probe = mux_probe, + .remove = __devexit_p(mux_remove), +}; + static struct parisc_driver serial_mux_driver = { .name = "serial_mux", .id_table = mux_tbl, @@ -547,7 +567,8 @@ static struct parisc_driver serial_mux_driver = { */ static int __init mux_init(void) { - int status = register_parisc_driver(&serial_mux_driver); + register_parisc_driver(&builtin_serial_mux_driver); + register_parisc_driver(&serial_mux_driver); if(port_cnt > 0) { /* Start the Mux timer */ @@ -560,7 +581,7 @@ static int __init mux_init(void) #endif } - return status; + return 0; } /** @@ -578,6 +599,7 @@ static void __exit mux_exit(void) #endif } + unregister_parisc_driver(&builtin_serial_mux_driver); unregister_parisc_driver(&serial_mux_driver); uart_unregister_driver(&mux_driver); } -- cgit v1.2.3-70-g09d2 From 614254458452d09ea0376862160662f2a6075ab9 Mon Sep 17 00:00:00 2001 From: Ryan Bradetich Date: Fri, 10 Nov 2006 03:08:45 +0000 Subject: [PARISC] [MUX] Correctly report the number of available ports This patch adds a new function to return the actual number of ports available. Some of the built-in Muxes return the number of supported ports, but not all of these port are available for use. Signed-off-by: Ryan Bradetich Signed-off-by: Kyle McMartin --- drivers/serial/mux.c | 42 +++++++++++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/mux.c b/drivers/serial/mux.c index 87269cca9c7..f5b17f5333f 100644 --- a/drivers/serial/mux.c +++ b/drivers/serial/mux.c @@ -70,7 +70,35 @@ static struct timer_list mux_timer; #define UART_PUT_CHAR(p, c) __raw_writel((c), (p)->membase + IO_DATA_REG_OFFSET) #define UART_GET_FIFO_CNT(p) __raw_readl((p)->membase + IO_DCOUNT_REG_OFFSET) -#define GET_MUX_PORTS(iodc_data) ((((iodc_data)[4] & 0xf0) >> 4) * 8) + 8 + +/** + * get_mux_port_count - Get the number of available ports on the Mux. + * @dev: The parisc device. + * + * This function is used to determine the number of ports the Mux + * supports. The IODC data reports the number of ports the Mux + * can support, but there are cases where not all the Mux ports + * are connected. This function can override the IODC and + * return the true port count. + */ +static int __init get_mux_port_count(struct parisc_device *dev) +{ + u8 iodc_data[32]; + unsigned long bytecnt; + + int status = pdc_iodc_read(&bytecnt, dev->hpa.start, 0, iodc_data, 32); + BUG_ON(status != PDC_OK); + + /* If this is the built-in Mux for the K-Class (Eole CAP/MUX), + * we only need to allocate resources for 1 port since the + * other 7 ports are not connected. + */ + if(((iodc_data[0] << 4) | ((iodc_data[1] & 0xf0) >> 4)) == 0x15) + return 1; + + /* Return the number of ports specified in the iodc data. */ + return ((((iodc_data)[4] & 0xf0) >> 4) * 8) + 8; +} /** * mux_tx_empty - Check if the transmitter fifo is empty. @@ -442,17 +470,9 @@ static struct uart_ops mux_pops = { */ static int __init mux_probe(struct parisc_device *dev) { - int i, status, port_count; - u8 iodc_data[32]; - unsigned long bytecnt; - - status = pdc_iodc_read(&bytecnt, dev->hpa.start, 0, iodc_data, 32); - if(status != PDC_OK) { - printk(KERN_ERR "Serial mux: Unable to read IODC.\n"); - return 1; - } + int i, status; - port_count = GET_MUX_PORTS(iodc_data); + int port_count = get_mux_port_count(dev); printk(KERN_INFO "Serial mux driver (%d ports) Revision: 0.6\n", port_count); dev_set_drvdata(&dev->dev, (void *)(long)port_count); -- cgit v1.2.3-70-g09d2 From 514fb84e1c5d12a0af808458bcae0c6463041f93 Mon Sep 17 00:00:00 2001 From: Ryan Bradetich Date: Fri, 10 Nov 2006 04:06:14 +0000 Subject: [PARISC] [MUX] Get the hversion directly from the parisc_device Willy pointed out the hversion is already stored in the parisc_device, so I do not need to extract this information directly from the IODC data. Also by using the information in the parisc_device I can avoid re-reading the IODC data for the Muxes with specifed port counts. Signed-off-by: Ryan Bradetich Signed-off-by: Kyle McMartin --- drivers/serial/mux.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/mux.c b/drivers/serial/mux.c index f5b17f5333f..ea9cbda7796 100644 --- a/drivers/serial/mux.c +++ b/drivers/serial/mux.c @@ -83,19 +83,20 @@ static struct timer_list mux_timer; */ static int __init get_mux_port_count(struct parisc_device *dev) { + int status; u8 iodc_data[32]; unsigned long bytecnt; - int status = pdc_iodc_read(&bytecnt, dev->hpa.start, 0, iodc_data, 32); - BUG_ON(status != PDC_OK); - /* If this is the built-in Mux for the K-Class (Eole CAP/MUX), * we only need to allocate resources for 1 port since the * other 7 ports are not connected. */ - if(((iodc_data[0] << 4) | ((iodc_data[1] & 0xf0) >> 4)) == 0x15) + if(dev->id.hversion == 0x15) return 1; + status = pdc_iodc_read(&bytecnt, dev->hpa.start, 0, iodc_data, 32); + BUG_ON(status != PDC_OK); + /* Return the number of ports specified in the iodc data. */ return ((((iodc_data)[4] & 0xf0) >> 4) * 8) + 8; } -- cgit v1.2.3-70-g09d2 From 423c8ece2941a7ee9b003564d5aab789b9b330d8 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 24 Oct 2006 13:49:54 -0600 Subject: [PARISC] parisc-agp: Fix integer/pointer warning Signed-off-by: Matthew Wilcox Signed-off-by: Kyle McMartin --- drivers/char/agp/parisc-agp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/agp/parisc-agp.c b/drivers/char/agp/parisc-agp.c index 17c50b0f83f..30cc7aeae9a 100644 --- a/drivers/char/agp/parisc-agp.c +++ b/drivers/char/agp/parisc-agp.c @@ -235,7 +235,7 @@ static int __init agp_ioc_init(void __iomem *ioc_regs) { struct _parisc_agp_info *info = &parisc_agp_info; - u64 *iova_base, *io_pdir, io_tlb_ps; + u64 iova_base, *io_pdir, io_tlb_ps; int io_tlb_shift; printk(KERN_INFO DRVPFX "IO PDIR shared with sba_iommu\n"); -- cgit v1.2.3-70-g09d2 From c2c4798e04ef836b12f5df04e7d1a1710cb39301 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 26 Oct 2006 10:06:07 -0600 Subject: [PARISC] sparse fixes 0/NULL, missing __user, missing __iomem, non-ANSI prototype. Signed-off-by: Matthew Wilcox Signed-off-by: Kyle McMartin --- arch/parisc/kernel/process.c | 4 ++-- arch/parisc/oprofile/init.c | 2 +- drivers/parisc/iosapic_private.h | 2 +- drivers/parisc/lba_pci.c | 2 +- drivers/parisc/sba_iommu.c | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c index 2f9f9dfa66f..dfca014b49b 100644 --- a/arch/parisc/kernel/process.c +++ b/arch/parisc/kernel/process.c @@ -355,8 +355,8 @@ asmlinkage int sys_execve(struct pt_regs *regs) error = PTR_ERR(filename); if (IS_ERR(filename)) goto out; - error = do_execve(filename, (char __user **) regs->gr[25], - (char __user **) regs->gr[24], regs); + error = do_execve(filename, (char __user * __user *) regs->gr[25], + (char __user * __user *) regs->gr[24], regs); if (error == 0) { task_lock(current); current->ptrace &= ~PT_DTRACE; diff --git a/arch/parisc/oprofile/init.c b/arch/parisc/oprofile/init.c index a5b898c4d0b..113f5139f55 100644 --- a/arch/parisc/oprofile/init.c +++ b/arch/parisc/oprofile/init.c @@ -18,6 +18,6 @@ int __init oprofile_arch_init(struct oprofile_operations * ops) } -void oprofile_arch_exit() +void oprofile_arch_exit(void) { } diff --git a/drivers/parisc/iosapic_private.h b/drivers/parisc/iosapic_private.h index 41e7ec2a44a..6e05e30a245 100644 --- a/drivers/parisc/iosapic_private.h +++ b/drivers/parisc/iosapic_private.h @@ -132,7 +132,7 @@ struct iosapic_irt { struct vector_info { struct iosapic_info *iosapic; /* I/O SAPIC this vector is on */ struct irt_entry *irte; /* IRT entry */ - u32 *eoi_addr; /* precalculate EOI reg address */ + u32 __iomem *eoi_addr; /* precalculate EOI reg address */ u32 eoi_data; /* IA64: ? PA: swapped txn_data */ int txn_irq; /* virtual IRQ number for processor */ ulong txn_addr; /* IA64: id_eid PA: partial HPA */ diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c index ba6769934c7..ad4a1a12a1a 100644 --- a/drivers/parisc/lba_pci.c +++ b/drivers/parisc/lba_pci.c @@ -980,7 +980,7 @@ LBA_PORT_IN(32, 0) #define LBA_PORT_OUT(size, mask) \ static void lba_pat_out##size (struct pci_hba_data *l, u16 addr, u##size val) \ { \ - void *where = (void *) PIOP_TO_GMMIO(LBA_DEV(l), addr); \ + void __iomem *where = PIOP_TO_GMMIO(LBA_DEV(l), addr); \ DBG_PORT("%s(0x%p, 0x%x, 0x%x)\n", __FUNCTION__, l, addr, val); \ WRITE_REG##size(val, where); \ /* flush the I/O down to the elroy at least */ \ diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c index f1e7ccd5475..41abbed51ea 100644 --- a/drivers/parisc/sba_iommu.c +++ b/drivers/parisc/sba_iommu.c @@ -846,7 +846,7 @@ static void *sba_alloc_consistent(struct device *hwdev, size_t size, if (!hwdev) { /* only support PCI */ *dma_handle = 0; - return 0; + return NULL; } ret = (void *) __get_free_pages(gfp, get_order(size)); -- cgit v1.2.3-70-g09d2 From 353dfe1290bdce1d40609e35ca6e42829623ff5f Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Sat, 18 Nov 2006 10:11:03 -0700 Subject: [PARISC] Fix PCI bus numbering in the presence of Cardbus bridges Firmware ignores Cardbus bridges, so when Linux assigns bus numbers, it must override firmware's notion of what the busses are numbered. This is not sufficient to support the Cardbus bridge as there is also no interrupt routing table entry for them. Signed-off-by: Matthew Wilcox Signed-off-by: Kyle McMartin --- drivers/parisc/lba_pci.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c index ad4a1a12a1a..eae0812f01a 100644 --- a/drivers/parisc/lba_pci.c +++ b/drivers/parisc/lba_pci.c @@ -1406,13 +1406,20 @@ lba_hw_init(struct lba_device *d) return 0; } - +/* + * Unfortunately, when firmware numbers busses, it doesn't take into account + * Cardbus bridges. So we have to renumber the busses to suit ourselves. + * Elroy/Mercury don't actually know what bus number they're attached to; + * we use bus 0 to indicate the directly attached bus and any other bus + * number will be taken care of by the PCI-PCI bridge. + */ +static unsigned int lba_next_bus = 0; /* -** Determine if lba should claim this chip (return 0) or not (return 1). -** If so, initialize the chip and tell other partners in crime they -** have work to do. -*/ + * Determine if lba should claim this chip (return 0) or not (return 1). + * If so, initialize the chip and tell other partners in crime they + * have work to do. + */ static int __init lba_driver_probe(struct parisc_device *dev) { @@ -1478,9 +1485,7 @@ lba_driver_probe(struct parisc_device *dev) return -ENODEV; } - /* - ** Tell I/O SAPIC driver we have a IRQ handler/region. - */ + /* Tell I/O SAPIC driver we have a IRQ handler/region. */ tmp_obj = iosapic_register(dev->hpa.start + LBA_IOSAPIC_BASE); /* NOTE: PCI devices (e.g. 103c:1005 graphics card) which don't @@ -1529,16 +1534,17 @@ lba_driver_probe(struct parisc_device *dev) lba_legacy_resources(dev, lba_dev); } - /* - ** Tell PCI support another PCI bus was found. - ** Walks PCI bus for us too. - */ + if (lba_dev->hba.bus_num.start < lba_next_bus) + lba_dev->hba.bus_num.start = lba_next_bus; + dev->dev.platform_data = lba_dev; lba_bus = lba_dev->hba.hba_bus = pci_scan_bus_parented(&dev->dev, lba_dev->hba.bus_num.start, cfg_ops, NULL); - if (lba_bus) + if (lba_bus) { + lba_next_bus = lba_bus->subordinate + 1; pci_bus_add_devices(lba_bus); + } /* This is in lieu of calling pci_assign_unassigned_resources() */ if (is_pdc_pat()) { -- cgit v1.2.3-70-g09d2 From 93ea774bf2d7f2b04ce4c57dbae08b5fa877296d Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sat, 14 Oct 2006 22:11:32 +0200 Subject: [PARISC] lasi_82596: use BUILD_BUG_ON() and constify static array Signed-off-by: Helge Deller Signed-off-by: Kyle McMartin --- drivers/net/lasi_82596.c | 34 +++++++--------------------------- 1 file changed, 7 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/net/lasi_82596.c b/drivers/net/lasi_82596.c index ea392f2a5aa..452863d5d49 100644 --- a/drivers/net/lasi_82596.c +++ b/drivers/net/lasi_82596.c @@ -384,7 +384,7 @@ struct i596_private { struct device *dev; }; -static char init_setup[] = +static const char init_setup[] = { 0x8E, /* length, prefetch on */ 0xC8, /* fifo to 8, monitor off */ @@ -683,7 +683,7 @@ static int init_i596_mem(struct net_device *dev) enable_irq(dev->irq); /* enable IRQs from LAN */ DEB(DEB_INIT, printk("%s: queuing CmdConfigure\n", dev->name)); - memcpy(lp->cf_cmd.i596_config, init_setup, 14); + memcpy(lp->cf_cmd.i596_config, init_setup, sizeof(init_setup)); lp->cf_cmd.cmd.command = CmdConfigure; CHECK_WBACK(lp, &(lp->cf_cmd), sizeof(struct cf_cmd)); i596_add_cmd(dev, &lp->cf_cmd.cmd); @@ -1156,32 +1156,12 @@ static int __devinit i82596_probe(struct net_device *dev, dma_addr_t dma_addr; /* This lot is ensure things have been cache line aligned. */ - if (sizeof(struct i596_rfd) != 32) { - printk("82596: sizeof(struct i596_rfd) = %d\n", - (int)sizeof(struct i596_rfd)); - return -ENODEV; - } - if ((sizeof(struct i596_rbd) % 32) != 0) { - printk("82596: sizeof(struct i596_rbd) = %d\n", - (int)sizeof(struct i596_rbd)); - return -ENODEV; - } - if ((sizeof(struct tx_cmd) % 32) != 0) { - printk("82596: sizeof(struct tx_cmd) = %d\n", - (int)sizeof(struct tx_cmd)); - return -ENODEV; - } - if (sizeof(struct i596_tbd) != 32) { - printk("82596: sizeof(struct i596_tbd) = %d\n", - (int)sizeof(struct i596_tbd)); - return -ENODEV; - } + BUILD_BUG_ON(sizeof(struct i596_rfd) != 32); + BUILD_BUG_ON(sizeof(struct i596_rbd) & 31); + BUILD_BUG_ON(sizeof(struct tx_cmd) & 31); + BUILD_BUG_ON(sizeof(struct i596_tbd) != 32); #ifndef __LP64__ - if (sizeof(struct i596_private) > 4096) { - printk("82596: sizeof(struct i596_private) = %d\n", - (int)sizeof(struct i596_private)); - return -ENODEV; - } + BUILD_BUG_ON(sizeof(struct i596_private) > 4096); #endif if (!dev->base_addr || !dev->irq) -- cgit v1.2.3-70-g09d2 From 6de187ee17058e7798357994696774a5c2c8a6d9 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Sat, 18 Nov 2006 10:05:16 -0700 Subject: [PARISC] Make Lasi Ethernet depend on GSC only If we separate out LASI and ASP support later, we'll need this. Plus, this makes it consistent with the ncr700 scsi driver. Signed-off-by: Matthew Wilcox Signed-off-by: Kyle McMartin --- drivers/net/Kconfig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 9de0eed6755..f59be5eeda9 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -440,10 +440,10 @@ config HPLANCE config LASI_82596 tristate "Lasi ethernet" - depends on NET_ETHERNET && PARISC && GSC_LASI + depends on NET_ETHERNET && GSC help - Say Y here to support the on-board Intel 82596 ethernet controller - built into Hewlett-Packard PA-RISC machines. + Say Y here to support the builtin Intel 82596 ethernet controller + found in Hewlett-Packard PA-RISC machines with 10Mbit ethernet. config MIPS_JAZZ_SONIC tristate "MIPS JAZZ onboard SONIC Ethernet support" -- cgit v1.2.3-70-g09d2 From 6858f3bf6e856d10a932d2d167d3f34e366042c6 Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 7 Dec 2006 15:31:38 +0000 Subject: [PATCH] WorkStruct: Fix up some PA-RISC work items Fix up some PA-RISC work items broken by the workstruct reduction. Signed-off-by: David Howells Signed-off-by: Kyle McMartin --- drivers/parisc/led.c | 12 ++++++------ drivers/parisc/power.c | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c index 8dac2ba82bb..6818c10c0c4 100644 --- a/drivers/parisc/led.c +++ b/drivers/parisc/led.c @@ -66,8 +66,8 @@ static char lcd_text_default[32] __read_mostly; static struct workqueue_struct *led_wq; -static void led_work_func(void *); -static DECLARE_WORK(led_task, led_work_func, NULL); +static void led_work_func(struct work_struct *); +static DECLARE_DELAYED_WORK(led_task, led_work_func); #if 0 #define DPRINTK(x) printk x @@ -136,7 +136,7 @@ static int start_task(void) /* Create the work queue and queue the LED task */ led_wq = create_singlethread_workqueue("led_wq"); - queue_work(led_wq, &led_task); + queue_delayed_work(led_wq, &led_task, 0); return 0; } @@ -443,7 +443,7 @@ static __inline__ int led_get_diskio_activity(void) #define LED_UPDATE_INTERVAL (1 + (HZ*19/1000)) -static void led_work_func (void *unused) +static void led_work_func (struct work_struct *unused) { static unsigned long last_jiffies; static unsigned long count_HZ; /* counter in range 0..HZ */ @@ -590,7 +590,7 @@ int __init register_led_driver(int model, unsigned long cmd_reg, unsigned long d /* Ensure the work is queued */ if (led_wq) { - queue_work(led_wq, &led_task); + queue_delayed_work(led_wq, &led_task, 0); } return 0; @@ -660,7 +660,7 @@ int lcd_print( char *str ) /* re-queue the work */ if (led_wq) { - queue_work(led_wq, &led_task); + queue_delayed_work(led_wq, &led_task, 0); } return lcd_info.lcd_width; diff --git a/drivers/parisc/power.c b/drivers/parisc/power.c index 97e9dc066f9..9228e210c3b 100644 --- a/drivers/parisc/power.c +++ b/drivers/parisc/power.c @@ -82,7 +82,7 @@ } ) -static void deferred_poweroff(void *dummy) +static void deferred_poweroff(struct work_struct *unused) { if (kill_cad_pid(SIGINT, 1)) { /* just in case killing init process failed */ @@ -96,7 +96,7 @@ static void deferred_poweroff(void *dummy) * use schedule_work(). */ -static DECLARE_WORK(poweroff_work, deferred_poweroff, NULL); +static DECLARE_WORK(poweroff_work, deferred_poweroff); static void poweroff(void) { -- cgit v1.2.3-70-g09d2 From 29a1e1d2732c7bfa94465749285aea0f2ed12213 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 5 Feb 2007 16:33:59 -0800 Subject: [PATCH] parisc: fix module_param iommu permission Fix/change module_param permissions parameter from an init value to a permission value. Signed-off-by: Randy Dunlap Cc: Kyle McMartin Cc: Matthew Wilcox Signed-off-by: Andrew Morton --- drivers/parisc/sba_iommu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c index 41abbed51ea..26fece45e73 100644 --- a/drivers/parisc/sba_iommu.c +++ b/drivers/parisc/sba_iommu.c @@ -109,7 +109,7 @@ static unsigned long piranha_bad_128k = 0; #ifdef SBA_AGP_SUPPORT static int sba_reserve_agpgart = 1; -module_param(sba_reserve_agpgart, int, 1); +module_param(sba_reserve_agpgart, int, 0444); MODULE_PARM_DESC(sba_reserve_agpgart, "Reserve half of IO pdir as AGPGART"); #endif -- cgit v1.2.3-70-g09d2 From 645d11d4baa56c6830daac46a92d63b7093cbc09 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Sun, 24 Dec 2006 19:28:42 -0700 Subject: [PARISC] lba_pci format warnings Fix resource_size_t warnings in a variety of ways Signed-off-by: Matthew Wilcox Signed-off-by: Kyle McMartin --- drivers/parisc/lba_pci.c | 56 +++++++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c index eae0812f01a..21c4c299b3d 100644 --- a/drivers/parisc/lba_pci.c +++ b/drivers/parisc/lba_pci.c @@ -168,7 +168,8 @@ lba_dump_res(struct resource *r, int d) printk(KERN_DEBUG "(%p)", r->parent); for (i = d; i ; --i) printk(" "); - printk(KERN_DEBUG "%p [%lx,%lx]/%lx\n", r, r->start, r->end, r->flags); + printk(KERN_DEBUG "%p [%lx,%lx]/%lx\n", r, + (long)r->start, (long)r->end, r->flags); lba_dump_res(r->child, d+2); lba_dump_res(r->sibling, d); } @@ -647,7 +648,7 @@ truncate_pat_collision(struct resource *root, struct resource *new) printk(KERN_WARNING "LBA: Truncating lmmio_space [%lx/%lx] " "to [%lx,%lx]\n", start, end, - new->start, new->end ); + (long)new->start, (long)new->end ); return 0; /* truncation successful */ } @@ -715,8 +716,8 @@ lba_fixup_bus(struct pci_bus *bus) printk("FAILED: lba_fixup_bus() request for " "elmmio_space [%lx/%lx]\n", - ldev->hba.elmmio_space.start, - ldev->hba.elmmio_space.end); + (long)ldev->hba.elmmio_space.start, + (long)ldev->hba.elmmio_space.end); /* lba_dump_res(&iomem_resource, 2); */ /* BUG(); */ @@ -738,15 +739,15 @@ lba_fixup_bus(struct pci_bus *bus) &(ldev->hba.lmmio_space))) { printk(KERN_WARNING "LBA: lmmio_space [%lx/%lx] duplicate!\n", - ldev->hba.lmmio_space.start, - ldev->hba.lmmio_space.end); + (long)ldev->hba.lmmio_space.start, + (long)ldev->hba.lmmio_space.end); } else { err = request_resource(&iomem_resource, &(ldev->hba.lmmio_space)); if (err < 0) { printk(KERN_ERR "FAILED: lba_fixup_bus() request for " "lmmio_space [%lx/%lx]\n", - ldev->hba.lmmio_space.start, - ldev->hba.lmmio_space.end); + (long)ldev->hba.lmmio_space.start, + (long)ldev->hba.lmmio_space.end); } else bus->resource[i++] = &(ldev->hba.lmmio_space); } @@ -758,8 +759,8 @@ lba_fixup_bus(struct pci_bus *bus) if (err < 0) { printk("FAILED: lba_fixup_bus() request for " "gmmio_space [%lx/%lx]\n", - ldev->hba.gmmio_space.start, - ldev->hba.gmmio_space.end); + (long)ldev->hba.gmmio_space.start, + (long)ldev->hba.gmmio_space.end); lba_dump_res(&iomem_resource, 2); BUG(); } @@ -1063,16 +1064,16 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) /* used to fix up pre-initialized MEM BARs */ if (!lba_dev->hba.lmmio_space.start) { sprintf(lba_dev->hba.lmmio_name, - "PCI%02lx LMMIO", - lba_dev->hba.bus_num.start); + "PCI%02x LMMIO", + (int)lba_dev->hba.bus_num.start); lba_dev->hba.lmmio_space_offset = p->start - io->start; r = &lba_dev->hba.lmmio_space; r->name = lba_dev->hba.lmmio_name; } else if (!lba_dev->hba.elmmio_space.start) { sprintf(lba_dev->hba.elmmio_name, - "PCI%02lx ELMMIO", - lba_dev->hba.bus_num.start); + "PCI%02x ELMMIO", + (int)lba_dev->hba.bus_num.start); r = &lba_dev->hba.elmmio_space; r->name = lba_dev->hba.elmmio_name; } else { @@ -1089,8 +1090,8 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) case PAT_GMMIO: /* MMIO space > 4GB phys addr; for 64-bit BAR */ - sprintf(lba_dev->hba.gmmio_name, "PCI%02lx GMMIO", - lba_dev->hba.bus_num.start); + sprintf(lba_dev->hba.gmmio_name, "PCI%02x GMMIO", + (int)lba_dev->hba.bus_num.start); r = &lba_dev->hba.gmmio_space; r->name = lba_dev->hba.gmmio_name; r->start = p->start; @@ -1112,8 +1113,8 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) */ lba_dev->iop_base = ioremap_nocache(p->start, 64 * 1024 * 1024); - sprintf(lba_dev->hba.io_name, "PCI%02lx Ports", - lba_dev->hba.bus_num.start); + sprintf(lba_dev->hba.io_name, "PCI%02x Ports", + (int)lba_dev->hba.bus_num.start); r = &lba_dev->hba.io_space; r->name = lba_dev->hba.io_name; r->start = HBA_PORT_BASE(lba_dev->hba.hba_num); @@ -1166,8 +1167,8 @@ lba_legacy_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) ** Legacy boxes but it's nice to see in /proc/iomem. */ r = &(lba_dev->hba.lmmio_space); - sprintf(lba_dev->hba.lmmio_name, "PCI%02lx LMMIO", - lba_dev->hba.bus_num.start); + sprintf(lba_dev->hba.lmmio_name, "PCI%02x LMMIO", + (int)lba_dev->hba.bus_num.start); r->name = lba_dev->hba.lmmio_name; #if 1 @@ -1275,8 +1276,8 @@ lba_legacy_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) ** an existing (but unused portion of) distributed range. */ r = &(lba_dev->hba.elmmio_space); - sprintf(lba_dev->hba.elmmio_name, "PCI%02lx ELMMIO", - lba_dev->hba.bus_num.start); + sprintf(lba_dev->hba.elmmio_name, "PCI%02x ELMMIO", + (int)lba_dev->hba.bus_num.start); r->name = lba_dev->hba.elmmio_name; #if 1 @@ -1297,8 +1298,8 @@ lba_legacy_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) #endif r = &(lba_dev->hba.io_space); - sprintf(lba_dev->hba.io_name, "PCI%02lx Ports", - lba_dev->hba.bus_num.start); + sprintf(lba_dev->hba.io_name, "PCI%02x Ports", + (int)lba_dev->hba.bus_num.start); r->name = lba_dev->hba.io_name; r->flags = IORESOURCE_IO; r->start = READ_REG32(lba_dev->hba.base_addr + LBA_IOS_BASE) & ~1L; @@ -1447,7 +1448,7 @@ lba_driver_probe(struct parisc_device *dev) } printk(KERN_INFO "Elroy version %s (0x%x) found at 0x%lx\n", - version, func_class & 0xf, dev->hpa.start); + version, func_class & 0xf, (long)dev->hpa.start); if (func_class < 2) { printk(KERN_WARNING "Can't support LBA older than " @@ -1477,11 +1478,12 @@ lba_driver_probe(struct parisc_device *dev) */ printk(KERN_INFO "%s version TR%d.%d (0x%x) found at 0x%lx\n", IS_MERCURY(dev) ? "Mercury" : "Quicksilver", major, - minor, func_class, dev->hpa.start); + minor, func_class, (long)dev->hpa.start); cfg_ops = &mercury_cfg_ops; } else { - printk(KERN_ERR "Unknown LBA found at 0x%lx\n", dev->hpa.start); + printk(KERN_ERR "Unknown LBA found at 0x%lx\n", + (long)dev->hpa.start); return -ENODEV; } -- cgit v1.2.3-70-g09d2 From 6e16d9409e1f08594587855d2a280c391ba985ff Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sun, 7 Jan 2007 16:07:48 +0100 Subject: [PARISC] Convert soft power switch driver to kthread And remove it's reference in time.c. Allow lcd_print() to take a const char *. Signed-off-by: Helge Deller Signed-off-by: Kyle McMartin --- arch/parisc/kernel/time.c | 4 - drivers/parisc/led.c | 2 +- drivers/parisc/power.c | 201 ++++++++++++++++++++-------------------------- include/asm-parisc/led.h | 2 +- 4 files changed, 91 insertions(+), 118 deletions(-) (limited to 'drivers') diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c index c33b6e0f7c4..ccdce6ef67c 100644 --- a/arch/parisc/kernel/time.c +++ b/arch/parisc/kernel/time.c @@ -148,10 +148,6 @@ irqreturn_t timer_interrupt(int irq, void *dev_id) write_sequnlock(&xtime_lock); } - /* check soft power switch status */ - if (cpu == 0 && !atomic_read(&power_tasklet.count)) - tasklet_schedule(&power_tasklet); - return IRQ_HANDLED; } diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c index 6818c10c0c4..a415d9b1c71 100644 --- a/drivers/parisc/led.c +++ b/drivers/parisc/led.c @@ -631,7 +631,7 @@ void __init register_led_regions(void) ** avoid a race condition while writing the CMD/DATA register pair. ** */ -int lcd_print( char *str ) +int lcd_print( const char *str ) { int i; diff --git a/drivers/parisc/power.c b/drivers/parisc/power.c index 9228e210c3b..6dedbdef710 100644 --- a/drivers/parisc/power.c +++ b/drivers/parisc/power.c @@ -2,7 +2,7 @@ * linux/drivers/parisc/power.c * HP PARISC soft power switch support driver * - * Copyright (c) 2001-2005 Helge Deller + * Copyright (c) 2001-2007 Helge Deller * All rights reserved. * * @@ -29,7 +29,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * * - * * HINT: * Support of the soft power switch button may be enabled or disabled at * runtime through the "/proc/sys/kernel/power" procfs entry. @@ -38,34 +37,28 @@ #include #include #include -#include #include #include #include -#include -#include +#include #include #include #include -#include +#define DRIVER_NAME "powersw" +#define KTHREAD_NAME "kpowerswd" -#ifdef DEBUG -# define DPRINTK(x...) printk(x) -#else -# define DPRINTK(x...) -#endif - - -/* filename in /proc which can be used to enable/disable the power switch */ -#define SYSCTL_FILENAME "sys/kernel/power" +/* how often should the power button be polled ? */ +#define POWERSWITCH_POLL_PER_SEC 2 +/* how long does the power button needs to be down until we react ? */ +#define POWERSWITCH_DOWN_SEC 2 +/* assembly code to access special registers */ +/* taken from PCXL ERS page 82 */ #define DIAG_CODE(code) (0x14000000 + ((code)<<5)) -/* this will go to processor.h or any other place... */ -/* taken from PCXL ERS page 82 */ #define MFCPU_X(rDiagReg, t_ch, t_th, code) \ (DIAG_CODE(code) + ((rDiagReg)<<21) + ((t_ch)<<16) + ((t_th)<<0) ) @@ -76,111 +69,95 @@ #define __getDIAG(dr) ( { \ register unsigned long __res asm("r28");\ __asm__ __volatile__ ( \ - ".word %1\n nop\n" : "=&r" (__res) : "i" (MFCPU_T(dr,28)) \ + ".word %1" : "=&r" (__res) : "i" (MFCPU_T(dr,28) ) \ ); \ __res; \ } ) - -static void deferred_poweroff(struct work_struct *unused) -{ - if (kill_cad_pid(SIGINT, 1)) { - /* just in case killing init process failed */ - machine_power_off(); - } -} - -/* - * This function gets called from interrupt context. - * As it's called within an interrupt, it wouldn't sync if we don't - * use schedule_work(). - */ - -static DECLARE_WORK(poweroff_work, deferred_poweroff); - -static void poweroff(void) -{ - static int powering_off __read_mostly; - - if (powering_off) - return; - - powering_off++; - schedule_work(&poweroff_work); -} - - -/* local time-counter for shutdown */ +/* local shutdown counter */ static int shutdown_timer __read_mostly; /* check, give feedback and start shutdown after one second */ static void process_shutdown(void) { if (shutdown_timer == 0) - DPRINTK(KERN_INFO "Shutdown requested...\n"); + printk(KERN_ALERT KTHREAD_NAME ": Shutdown requested...\n"); shutdown_timer++; /* wait until the button was pressed for 1 second */ - if (shutdown_timer == HZ) { -#if defined (DEBUG) || defined(CONFIG_CHASSIS_LCD_LED) - static char msg[] = "Shutting down..."; -#endif - DPRINTK(KERN_INFO "%s\n", msg); + if (shutdown_timer == (POWERSWITCH_DOWN_SEC*POWERSWITCH_POLL_PER_SEC)) { + static const char msg[] = "Shutting down..."; + printk(KERN_INFO KTHREAD_NAME ": %s\n", msg); lcd_print(msg); - poweroff(); + + /* send kill signal */ + if (kill_cad_pid(SIGINT, 1)) { + /* just in case killing init process failed */ + if (pm_power_off) + pm_power_off(); + } } } -/* main power switch tasklet struct (scheduled from time.c) */ -DECLARE_TASKLET_DISABLED(power_tasklet, NULL, 0); +/* main power switch task struct */ +static struct task_struct *power_task; + +/* filename in /proc which can be used to enable/disable the power switch */ +#define SYSCTL_FILENAME "sys/kernel/power" /* soft power switch enabled/disabled */ int pwrsw_enabled __read_mostly = 1; -/* - * On gecko style machines (e.g. 712/xx and 715/xx) - * the power switch status is stored in Bit 0 ("the highest bit") - * of CPU diagnose register 25. - * - */ -static void gecko_tasklet_func(unsigned long unused) +/* main kernel thread worker. It polls the button state */ +static int kpowerswd(void *param) { - if (unlikely(!pwrsw_enabled)) - return; - - if (__getDIAG(25) & 0x80000000) { - /* power switch button not pressed or released again */ - /* Warning: Some machines do never reset this DIAG flag! */ - shutdown_timer = 0; - } else { - process_shutdown(); - } -} - + __set_current_state(TASK_RUNNING); + + do { + int button_not_pressed; + unsigned long soft_power_reg = (unsigned long) param; + + schedule_timeout_interruptible(pwrsw_enabled ? HZ : HZ/POWERSWITCH_POLL_PER_SEC); + __set_current_state(TASK_RUNNING); + + if (unlikely(!pwrsw_enabled)) + continue; + + if (soft_power_reg) { + /* + * Non-Gecko-style machines: + * Check the power switch status which is read from the + * real I/O location at soft_power_reg. + * Bit 31 ("the lowest bit) is the status of the power switch. + * This bit is "1" if the button is NOT pressed. + */ + button_not_pressed = (gsc_readl(soft_power_reg) & 0x1); + } else { + /* + * On gecko style machines (e.g. 712/xx and 715/xx) + * the power switch status is stored in Bit 0 ("the highest bit") + * of CPU diagnose register 25. + * Warning: Some machines never reset the DIAG flag, even if + * the button has been released again. + */ + button_not_pressed = (__getDIAG(25) & 0x80000000); + } + + if (likely(button_not_pressed)) { + if (unlikely(shutdown_timer && /* avoid writing if not necessary */ + shutdown_timer < (POWERSWITCH_DOWN_SEC*POWERSWITCH_POLL_PER_SEC))) { + shutdown_timer = 0; + printk(KERN_INFO KTHREAD_NAME ": Shutdown request aborted.\n"); + } + } else + process_shutdown(); + + + } while (!kthread_should_stop()); - -/* - * Check the power switch status which is read from the - * real I/O location at soft_power_reg. - * Bit 31 ("the lowest bit) is the status of the power switch. - */ - -static void polling_tasklet_func(unsigned long soft_power_reg) -{ - unsigned long current_status; - - if (unlikely(!pwrsw_enabled)) - return; - - current_status = gsc_readl(soft_power_reg); - if (current_status & 0x1) { - /* power switch button not pressed */ - shutdown_timer = 0; - } else { - process_shutdown(); - } + return 0; } @@ -220,7 +197,7 @@ static struct notifier_block parisc_panic_block = { static int __init power_init(void) { unsigned long ret; - unsigned long soft_power_reg = 0; + unsigned long soft_power_reg; #if 0 request_irq( IRQ_FROM_REGION(CPU_IRQ_REGION)+2, &powerfail_interrupt, @@ -235,44 +212,44 @@ static int __init power_init(void) soft_power_reg = -1UL; switch (soft_power_reg) { - case 0: printk(KERN_INFO "Gecko-style soft power switch enabled.\n"); - power_tasklet.func = gecko_tasklet_func; + case 0: printk(KERN_INFO DRIVER_NAME ": Gecko-style soft power switch enabled.\n"); break; - case -1UL: printk(KERN_INFO "Soft power switch support not available.\n"); + case -1UL: printk(KERN_INFO DRIVER_NAME ": Soft power switch support not available.\n"); return -ENODEV; - default: printk(KERN_INFO "Soft power switch enabled, polling @ 0x%08lx.\n", + default: printk(KERN_INFO DRIVER_NAME ": Soft power switch at 0x%08lx enabled.\n", soft_power_reg); - power_tasklet.data = soft_power_reg; - power_tasklet.func = polling_tasklet_func; + } + + power_task = kthread_run(kpowerswd, (void*)soft_power_reg, KTHREAD_NAME); + if (IS_ERR(power_task)) { + printk(KERN_ERR DRIVER_NAME ": thread creation failed. Driver not loaded.\n"); + pdc_soft_power_button(0); + return -EIO; } /* Register a call for panic conditions. */ atomic_notifier_chain_register(&panic_notifier_list, &parisc_panic_block); - tasklet_enable(&power_tasklet); - return 0; } static void __exit power_exit(void) { - if (!power_tasklet.func) - return; + kthread_stop(power_task); - tasklet_disable(&power_tasklet); atomic_notifier_chain_unregister(&panic_notifier_list, &parisc_panic_block); - power_tasklet.func = NULL; + pdc_soft_power_button(0); } -module_init(power_init); +arch_initcall(power_init); module_exit(power_exit); -MODULE_AUTHOR("Helge Deller"); +MODULE_AUTHOR("Helge Deller "); MODULE_DESCRIPTION("Soft power switch driver"); MODULE_LICENSE("Dual BSD/GPL"); diff --git a/include/asm-parisc/led.h b/include/asm-parisc/led.h index efadfd543ec..c3405ab9d60 100644 --- a/include/asm-parisc/led.h +++ b/include/asm-parisc/led.h @@ -31,7 +31,7 @@ void __init register_led_regions(void); #ifdef CONFIG_CHASSIS_LCD_LED /* writes a string to the LCD display (if possible on this h/w) */ -int lcd_print(char *str); +int lcd_print(const char *str); #else #define lcd_print(str) #endif -- cgit v1.2.3-70-g09d2