diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/char/Kconfig | 2 | ||||
-rw-r--r-- | drivers/char/rtc.c | 30 | ||||
-rw-r--r-- | drivers/net/sunvnet.c | 137 | ||||
-rw-r--r-- | drivers/net/sunvnet.h | 11 | ||||
-rw-r--r-- | drivers/sbus/sbus.c | 5 | ||||
-rw-r--r-- | drivers/serial/suncore.c | 123 | ||||
-rw-r--r-- | drivers/serial/suncore.h | 2 | ||||
-rw-r--r-- | drivers/serial/sunhv.c | 13 | ||||
-rw-r--r-- | drivers/serial/sunsab.c | 22 | ||||
-rw-r--r-- | drivers/serial/sunsu.c | 23 | ||||
-rw-r--r-- | drivers/serial/sunzilog.c | 24 | ||||
-rw-r--r-- | drivers/video/aty/atyfb_base.c | 4 | ||||
-rw-r--r-- | drivers/video/igafb.c | 4 |
13 files changed, 223 insertions, 177 deletions
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 4373d7cdc5d2..c8dfd18bea44 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -726,7 +726,7 @@ config NVRAM config RTC tristate "Enhanced Real Time Clock Support" - depends on !PPC && !PARISC && !IA64 && !M68K && (!SPARC || PCI) && !FRV && !ARM && !SUPERH && !S390 + depends on !PPC && !PARISC && !IA64 && !M68K && !SPARC64 && (!SPARC32 || PCI) && !FRV && !ARM && !SUPERH && !S390 ---help--- If you say Y here and create a character special file /dev/rtc with major number 10 and minor number 135 using mknod ("man mknod"), you diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index 22cf7aa56cc4..30c3f54c7666 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c @@ -86,12 +86,9 @@ #include <asm/hpet.h> #endif -#ifdef __sparc__ +#ifdef CONFIG_SPARC32 #include <linux/pci.h> #include <asm/ebus.h> -#ifdef __sparc_v9__ -#include <asm/isa.h> -#endif static unsigned long rtc_port; static int rtc_irq = PCI_IRQ_NONE; @@ -930,13 +927,9 @@ static int __init rtc_init(void) unsigned int year, ctrl; char *guess = NULL; #endif -#ifdef __sparc__ +#ifdef CONFIG_SPARC32 struct linux_ebus *ebus; struct linux_ebus_device *edev; -#ifdef __sparc_v9__ - struct sparc_isa_bridge *isa_br; - struct sparc_isa_device *isa_dev; -#endif #else void *r; #ifdef RTC_IRQ @@ -944,7 +937,7 @@ static int __init rtc_init(void) #endif #endif -#ifdef __sparc__ +#ifdef CONFIG_SPARC32 for_each_ebus(ebus) { for_each_ebusdev(edev, ebus) { if(strcmp(edev->prom_node->name, "rtc") == 0) { @@ -954,17 +947,6 @@ static int __init rtc_init(void) } } } -#ifdef __sparc_v9__ - for_each_isa(isa_br) { - for_each_isadev(isa_dev, isa_br) { - if (strcmp(isa_dev->prom_node->name, "rtc") == 0) { - rtc_port = isa_dev->resource.start; - rtc_irq = isa_dev->irq; - goto found; - } - } - } -#endif rtc_has_irq = 0; printk(KERN_ERR "rtc_init: no PC rtc found\n"); return -EIO; @@ -1020,7 +1002,7 @@ no_irq: #endif -#endif /* __sparc__ vs. others */ +#endif /* CONFIG_SPARC32 vs. others */ if (misc_register(&rtc_dev)) { #ifdef RTC_IRQ @@ -1105,7 +1087,7 @@ static void __exit rtc_exit (void) remove_proc_entry ("driver/rtc", NULL); misc_deregister(&rtc_dev); -#ifdef __sparc__ +#ifdef CONFIG_SPARC32 if (rtc_has_irq) free_irq (rtc_irq, &rtc_port); #else @@ -1117,7 +1099,7 @@ static void __exit rtc_exit (void) if (rtc_has_irq) free_irq (RTC_IRQ, NULL); #endif -#endif /* __sparc__ */ +#endif /* CONFIG_SPARC32 */ } module_init(rtc_init); diff --git a/drivers/net/sunvnet.c b/drivers/net/sunvnet.c index ef0066bab2cf..61f98251feab 100644 --- a/drivers/net/sunvnet.c +++ b/drivers/net/sunvnet.c @@ -459,6 +459,22 @@ static int vnet_nack(struct vnet_port *port, void *msgbuf) return 0; } +static int handle_mcast(struct vnet_port *port, void *msgbuf) +{ + struct vio_net_mcast_info *pkt = msgbuf; + + if (pkt->tag.stype != VIO_SUBTYPE_ACK) + printk(KERN_ERR PFX "%s: Got unexpected MCAST reply " + "[%02x:%02x:%04x:%08x]\n", + port->vp->dev->name, + pkt->tag.type, + pkt->tag.stype, + pkt->tag.stype_env, + pkt->tag.sid); + + return 0; +} + static void maybe_tx_wakeup(struct vnet *vp) { struct net_device *dev = vp->dev; @@ -544,7 +560,10 @@ static void vnet_event(void *arg, int event) err = vnet_nack(port, &msgbuf); } } else if (msgbuf.tag.type == VIO_TYPE_CTRL) { - err = vio_control_pkt_engine(vio, &msgbuf); + if (msgbuf.tag.stype_env == VNET_MCAST_INFO) + err = handle_mcast(port, &msgbuf); + else + err = vio_control_pkt_engine(vio, &msgbuf); if (err) break; } else { @@ -731,9 +750,122 @@ static int vnet_close(struct net_device *dev) return 0; } +static struct vnet_mcast_entry *__vnet_mc_find(struct vnet *vp, u8 *addr) +{ + struct vnet_mcast_entry *m; + + for (m = vp->mcast_list; m; m = m->next) { + if (!memcmp(m->addr, addr, ETH_ALEN)) + return m; + } + return NULL; +} + +static void __update_mc_list(struct vnet *vp, struct net_device *dev) +{ + struct dev_addr_list *p; + + for (p = dev->mc_list; p; p = p->next) { + struct vnet_mcast_entry *m; + + m = __vnet_mc_find(vp, p->dmi_addr); + if (m) { + m->hit = 1; + continue; + } + + if (!m) { + m = kzalloc(sizeof(*m), GFP_ATOMIC); + if (!m) + continue; + memcpy(m->addr, p->dmi_addr, ETH_ALEN); + m->hit = 1; + + m->next = vp->mcast_list; + vp->mcast_list = m; + } + } +} + +static void __send_mc_list(struct vnet *vp, struct vnet_port *port) +{ + struct vio_net_mcast_info info; + struct vnet_mcast_entry *m, **pp; + int n_addrs; + + memset(&info, 0, sizeof(info)); + + info.tag.type = VIO_TYPE_CTRL; + info.tag.stype = VIO_SUBTYPE_INFO; + info.tag.stype_env = VNET_MCAST_INFO; + info.tag.sid = vio_send_sid(&port->vio); + info.set = 1; + + n_addrs = 0; + for (m = vp->mcast_list; m; m = m->next) { + if (m->sent) + continue; + m->sent = 1; + memcpy(&info.mcast_addr[n_addrs * ETH_ALEN], + m->addr, ETH_ALEN); + if (++n_addrs == VNET_NUM_MCAST) { + info.count = n_addrs; + + (void) vio_ldc_send(&port->vio, &info, + sizeof(info)); + n_addrs = 0; + } + } + if (n_addrs) { + info.count = n_addrs; + (void) vio_ldc_send(&port->vio, &info, sizeof(info)); + } + + info.set = 0; + + n_addrs = 0; + pp = &vp->mcast_list; + while ((m = *pp) != NULL) { + if (m->hit) { + m->hit = 0; + pp = &m->next; + continue; + } + + memcpy(&info.mcast_addr[n_addrs * ETH_ALEN], + m->addr, ETH_ALEN); + if (++n_addrs == VNET_NUM_MCAST) { + info.count = n_addrs; + (void) vio_ldc_send(&port->vio, &info, + sizeof(info)); + n_addrs = 0; + } + + *pp = m->next; + kfree(m); + } + if (n_addrs) { + info.count = n_addrs; + (void) vio_ldc_send(&port->vio, &info, sizeof(info)); + } +} + static void vnet_set_rx_mode(struct net_device *dev) { - /* XXX Implement multicast support XXX */ + struct vnet *vp = netdev_priv(dev); + struct vnet_port *port; + unsigned long flags; + + spin_lock_irqsave(&vp->lock, flags); + if (!list_empty(&vp->port_list)) { + port = list_entry(vp->port_list.next, struct vnet_port, list); + + if (port->switch_port) { + __update_mc_list(vp, dev); + __send_mc_list(vp, port); + } + } + spin_unlock_irqrestore(&vp->lock, flags); } static int vnet_change_mtu(struct net_device *dev, int new_mtu) @@ -1070,6 +1202,7 @@ static int __devinit vnet_port_probe(struct vio_dev *vdev, switch_port = 0; if (mdesc_get_property(hp, vdev->mp, "switch-port", NULL) != NULL) switch_port = 1; + port->switch_port = switch_port; spin_lock_irqsave(&vp->lock, flags); if (switch_port) diff --git a/drivers/net/sunvnet.h b/drivers/net/sunvnet.h index 7d3a0cac727b..d347a5bf24b0 100644 --- a/drivers/net/sunvnet.h +++ b/drivers/net/sunvnet.h @@ -30,6 +30,8 @@ struct vnet_port { struct hlist_node hash; u8 raddr[ETH_ALEN]; + u8 switch_port; + u8 __pad; struct vnet *vp; @@ -53,6 +55,13 @@ static inline unsigned int vnet_hashfn(u8 *mac) return val & (VNET_PORT_HASH_MASK); } +struct vnet_mcast_entry { + u8 addr[ETH_ALEN]; + u8 sent; + u8 hit; + struct vnet_mcast_entry *next; +}; + struct vnet { /* Protects port_list and port_hash. */ spinlock_t lock; @@ -65,6 +74,8 @@ struct vnet { struct hlist_head port_hash[VNET_PORT_HASH_SIZE]; + struct vnet_mcast_entry *mcast_list; + struct list_head list; u64 local_mac; }; diff --git a/drivers/sbus/sbus.c b/drivers/sbus/sbus.c index 002643392d42..2553629ec15d 100644 --- a/drivers/sbus/sbus.c +++ b/drivers/sbus/sbus.c @@ -33,6 +33,7 @@ struct sbus_bus *sbus_root; static void __init fill_sbus_device(struct device_node *dp, struct sbus_dev *sdev) { + struct dev_archdata *sd; unsigned long base; const void *pval; int len, err; @@ -67,6 +68,10 @@ static void __init fill_sbus_device(struct device_node *dp, struct sbus_dev *sde sbus_fill_device_irq(sdev); + sd = &sdev->ofdev.dev.archdata; + sd->prom_node = dp; + sd->op = &sdev->ofdev; + sdev->ofdev.node = dp; if (sdev->parent) sdev->ofdev.dev.parent = &sdev->parent->ofdev.dev; diff --git a/drivers/serial/suncore.c b/drivers/serial/suncore.c index b45ba5392dd3..70a09a3d5af0 100644 --- a/drivers/serial/suncore.c +++ b/drivers/serial/suncore.c @@ -16,9 +16,10 @@ #include <linux/tty.h> #include <linux/errno.h> #include <linux/string.h> +#include <linux/serial_core.h> #include <linux/init.h> -#include <asm/oplib.h> +#include <asm/prom.h> #include "suncore.h" @@ -26,92 +27,60 @@ int sunserial_current_minor = 64; EXPORT_SYMBOL(sunserial_current_minor); -void -sunserial_console_termios(struct console *con) +int sunserial_console_match(struct console *con, struct device_node *dp, + struct uart_driver *drv, int line) { - char mode[16], buf[16], *s; - char mode_prop[] = "ttyX-mode"; - char cd_prop[] = "ttyX-ignore-cd"; - char dtr_prop[] = "ttyX-rts-dtr-off"; - char *ssp_console_modes_prop = "ssp-console-modes"; - int baud, bits, stop, cflag; - char parity; - int carrier = 0; - int rtsdtr = 1; - int topnd, nd; - - if (!serial_console) - return; - - switch (serial_console) { - case PROMDEV_OTTYA: - mode_prop[3] = 'a'; - cd_prop[3] = 'a'; - dtr_prop[3] = 'a'; - break; - - case PROMDEV_OTTYB: - mode_prop[3] = 'b'; - cd_prop[3] = 'b'; - dtr_prop[3] = 'b'; - break; - - case PROMDEV_ORSC: - - nd = prom_pathtoinode("rsc"); - if (!nd) { - strcpy(mode, "115200,8,n,1,-"); - goto no_options; - } + int off; - if (!prom_node_has_property(nd, ssp_console_modes_prop)) { - strcpy(mode, "115200,8,n,1,-"); - goto no_options; - } + if (!con || of_console_device != dp) + return 0; - memset(mode, 0, sizeof(mode)); - prom_getstring(nd, ssp_console_modes_prop, mode, sizeof(mode)); - goto no_options; + off = 0; + if (of_console_options && + *of_console_options == 'b') + off = 1; - default: - strcpy(mode, "9600,8,n,1,-"); - goto no_options; - } + if ((line & 1) != off) + return 0; - topnd = prom_getchild(prom_root_node); - nd = prom_searchsiblings(topnd, "options"); - if (!nd) { - strcpy(mode, "9600,8,n,1,-"); - goto no_options; - } - - if (!prom_node_has_property(nd, mode_prop)) { - strcpy(mode, "9600,8,n,1,-"); - goto no_options; - } + con->index = line; + drv->cons = con; + add_preferred_console(con->name, line, NULL); - memset(mode, 0, sizeof(mode)); - prom_getstring(nd, mode_prop, mode, sizeof(mode)); - - if (prom_node_has_property(nd, cd_prop)) { - memset(buf, 0, sizeof(buf)); - prom_getstring(nd, cd_prop, buf, sizeof(buf)); - if (!strcmp(buf, "false")) - carrier = 1; - - /* XXX: this is unused below. */ - } + return 1; +} +EXPORT_SYMBOL(sunserial_console_match); - if (prom_node_has_property(nd, dtr_prop)) { - memset(buf, 0, sizeof(buf)); - prom_getstring(nd, dtr_prop, buf, sizeof(buf)); - if (!strcmp(buf, "false")) - rtsdtr = 0; +void +sunserial_console_termios(struct console *con) +{ + struct device_node *dp; + const char *od, *mode, *s; + char mode_prop[] = "ttyX-mode"; + int baud, bits, stop, cflag; + char parity; - /* XXX: this is unused below. */ + dp = of_find_node_by_path("/options"); + od = of_get_property(dp, "output-device", NULL); + if (!strcmp(od, "rsc")) { + mode = of_get_property(of_console_device, + "ssp-console-modes", NULL); + if (!mode) + mode = "115200,8,n,1,-"; + } else { + char c; + + c = 'a'; + if (of_console_options) + c = *of_console_options; + + mode_prop[3] = c; + + mode = of_get_property(dp, mode_prop, NULL); + if (!mode) + mode = "9600,8,n,1,-"; } -no_options: cflag = CREAD | HUPCL | CLOCAL; s = mode; diff --git a/drivers/serial/suncore.h b/drivers/serial/suncore.h index 513916a8ce37..829d7d65d6db 100644 --- a/drivers/serial/suncore.h +++ b/drivers/serial/suncore.h @@ -24,6 +24,8 @@ extern int suncore_mouse_baud_detection(unsigned char, int); extern int sunserial_current_minor; +extern int sunserial_console_match(struct console *, struct device_node *, + struct uart_driver *, int); extern void sunserial_console_termios(struct console *); #endif /* !(_SERIAL_SUN_H) */ diff --git a/drivers/serial/sunhv.c b/drivers/serial/sunhv.c index d82be42ff29a..8ff900b09811 100644 --- a/drivers/serial/sunhv.c +++ b/drivers/serial/sunhv.c @@ -520,16 +520,6 @@ static struct console sunhv_console = { .data = &sunhv_reg, }; -static inline struct console *SUNHV_CONSOLE(void) -{ - if (con_is_present()) - return NULL; - - sunhv_console.index = 0; - - return &sunhv_console; -} - static int __devinit hv_probe(struct of_device *op, const struct of_device_id *match) { struct uart_port *port; @@ -582,7 +572,8 @@ static int __devinit hv_probe(struct of_device *op, const struct of_device_id *m sunhv_reg.tty_driver->name_base = sunhv_reg.minor - 64; sunserial_current_minor += 1; - sunhv_reg.cons = SUNHV_CONSOLE(); + sunserial_console_match(&sunhv_console, op->node, + &sunhv_reg, port->line); err = uart_add_one_port(&sunhv_reg, port); if (err) diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c index 8a0f9e4408d4..bca57bb94939 100644 --- a/drivers/serial/sunsab.c +++ b/drivers/serial/sunsab.c @@ -968,22 +968,6 @@ static struct console sunsab_console = { static inline struct console *SUNSAB_CONSOLE(void) { - int i; - - if (con_is_present()) - return NULL; - - for (i = 0; i < num_channels; i++) { - int this_minor = sunsab_reg.minor + i; - - if ((this_minor - 64) == (serial_console - 1)) - break; - } - if (i == num_channels) - return NULL; - - sunsab_console.index = i; - return &sunsab_console; } #else @@ -1080,7 +1064,12 @@ static int __devinit sab_probe(struct of_device *op, const struct of_device_id * return err; } + sunserial_console_match(SUNSAB_CONSOLE(), op->node, + &sunsab_reg, up[0].port.line); uart_add_one_port(&sunsab_reg, &up[0].port); + + sunserial_console_match(SUNSAB_CONSOLE(), op->node, + &sunsab_reg, up[1].port.line); uart_add_one_port(&sunsab_reg, &up[1].port); dev_set_drvdata(&op->dev, &up[0]); @@ -1164,7 +1153,6 @@ static int __init sunsab_init(void) } sunsab_reg.tty_driver->name_base = sunsab_reg.minor - 64; - sunsab_reg.cons = SUNSAB_CONSOLE(); sunserial_current_minor += num_channels; } diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c index 26d720baf88c..79b13685bdfa 100644 --- a/drivers/serial/sunsu.c +++ b/drivers/serial/sunsu.c @@ -1371,28 +1371,12 @@ static struct console sunsu_console = { * Register console. */ -static inline struct console *SUNSU_CONSOLE(int num_uart) +static inline struct console *SUNSU_CONSOLE(void) { - int i; - - if (con_is_present()) - return NULL; - - for (i = 0; i < num_uart; i++) { - int this_minor = sunsu_reg.minor + i; - - if ((this_minor - 64) == (serial_console - 1)) - break; - } - if (i == num_uart) - return NULL; - - sunsu_console.index = i; - return &sunsu_console; } #else -#define SUNSU_CONSOLE(num_uart) (NULL) +#define SUNSU_CONSOLE() (NULL) #define sunsu_serial_console_init() do { } while (0) #endif @@ -1482,6 +1466,8 @@ static int __devinit su_probe(struct of_device *op, const struct of_device_id *m up->port.ops = &sunsu_pops; + sunserial_console_match(SUNSU_CONSOLE(), dp, + &sunsu_reg, up->port.line); err = uart_add_one_port(&sunsu_reg, &up->port); if (err) goto out_unmap; @@ -1572,7 +1558,6 @@ static int __init sunsu_init(void) return err; sunsu_reg.tty_driver->name_base = sunsu_reg.minor - 64; sunserial_current_minor += num_uart; - sunsu_reg.cons = SUNSU_CONSOLE(num_uart); } err = of_register_driver(&su_driver, &of_bus_type); diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c index 0a3e10a4a35d..1d262c0c613f 100644 --- a/drivers/serial/sunzilog.c +++ b/drivers/serial/sunzilog.c @@ -1226,23 +1226,6 @@ static struct console sunzilog_console_ops = { static inline struct console *SUNZILOG_CONSOLE(void) { - int i; - - if (con_is_present()) - return NULL; - - for (i = 0; i < NUM_CHANNELS; i++) { - int this_minor = sunzilog_reg.minor + i; - - if ((this_minor - 64) == (serial_console - 1)) - break; - } - if (i == NUM_CHANNELS) - return NULL; - - sunzilog_console_ops.index = i; - sunzilog_port_table[i].flags |= SUNZILOG_FLAG_IS_CONS; - return &sunzilog_console_ops; } @@ -1428,12 +1411,18 @@ static int __devinit zs_probe(struct of_device *op, const struct of_device_id *m sunzilog_init_hw(&up[1]); if (!keyboard_mouse) { + if (sunserial_console_match(SUNZILOG_CONSOLE(), op->node, + &sunzilog_reg, up[0].port.line)) + up->flags |= SUNZILOG_FLAG_IS_CONS; err = uart_add_one_port(&sunzilog_reg, &up[0].port); if (err) { of_iounmap(&op->resource[0], rp, sizeof(struct zilog_layout)); return err; } + if (sunserial_console_match(SUNZILOG_CONSOLE(), op->node, + &sunzilog_reg, up[1].port.line)) + up->flags |= SUNZILOG_FLAG_IS_CONS; err = uart_add_one_port(&sunzilog_reg, &up[1].port); if (err) { uart_remove_one_port(&sunzilog_reg, &up[0].port); @@ -1531,7 +1520,6 @@ static int __init sunzilog_init(void) goto out_free_tables; sunzilog_reg.tty_driver->name_base = sunzilog_reg.minor - 64; - sunzilog_reg.cons = SUNZILOG_CONSOLE(); sunserial_current_minor += uart_count; } diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index 0c7bf75732ea..13990697b5c1 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c @@ -2913,10 +2913,6 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev, int node, len, i, j, ret; u32 mem, chip_id; - /* Do not attach when we have a serial console. */ - if (!con_is_present()) - return -ENXIO; - /* * Map memory-mapped registers. */ diff --git a/drivers/video/igafb.c b/drivers/video/igafb.c index eb1a4812ad1d..b87ea21d3d78 100644 --- a/drivers/video/igafb.c +++ b/drivers/video/igafb.c @@ -379,10 +379,6 @@ int __init igafb_init(void) if (fb_get_options("igafb", NULL)) return -ENODEV; - /* Do not attach when we have a serial console. */ - if (!con_is_present()) - return -ENXIO; - pdev = pci_get_device(PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_1682, 0); if (pdev == NULL) { |