From 07e6e93136ca61f071c819c69e1ec5bff9fda46f Mon Sep 17 00:00:00 2001 From: Sylvain Munaut Date: Sun, 16 Sep 2007 20:53:26 +1000 Subject: [POWERPC] mpc52xx: Update mpc52xx_psc structure with B revision changes On the mpc5200b the ccr register is 32 bits wide while on the mpc5200 it's only 16 bits. It's up to the driver to use the correct format depending on the chip it's running on. The 5200b also offers some more registers & status in AC97 mode. Again, if not running on a 5200b the driver should not use those. Signed-off-by: Sylvain Munaut Signed-off-by: Grant Likely --- include/asm-ppc/mpc52xx_psc.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/asm-ppc/mpc52xx_psc.h b/include/asm-ppc/mpc52xx_psc.h index 9d850b2b20b8..c82b8d49a7da 100644 --- a/include/asm-ppc/mpc52xx_psc.h +++ b/include/asm-ppc/mpc52xx_psc.h @@ -28,6 +28,10 @@ #define MPC52xx_PSC_MAXNUM 6 /* Programmable Serial Controller (PSC) status register bits */ +#define MPC52xx_PSC_SR_UNEX_RX 0x0001 +#define MPC52xx_PSC_SR_DATA_VAL 0x0002 +#define MPC52xx_PSC_SR_DATA_OVR 0x0004 +#define MPC52xx_PSC_SR_CMDSEND 0x0008 #define MPC52xx_PSC_SR_CDE 0x0080 #define MPC52xx_PSC_SR_RXRDY 0x0100 #define MPC52xx_PSC_SR_RXFULL 0x0200 @@ -132,8 +136,10 @@ struct mpc52xx_psc { u8 reserved5[3]; u8 ctlr; /* PSC + 0x1c */ u8 reserved6[3]; - u16 ccr; /* PSC + 0x20 */ - u8 reserved7[14]; + u32 ccr; /* PSC + 0x20 */ + u32 ac97_slots; /* PSC + 0x24 */ + u32 ac97_cmd; /* PSC + 0x28 */ + u32 ac97_data; /* PSC + 0x2c */ u8 ivr; /* PSC + 0x30 */ u8 reserved8[3]; u8 ip; /* PSC + 0x34 */ -- cgit v1.2.3 From fec738dd48bd33743c12cebe1bf954e487756231 Mon Sep 17 00:00:00 2001 From: Joachim Fenkes Date: Wed, 26 Sep 2007 19:44:12 +1000 Subject: [POWERPC] Move of_device allocation into of_device.[ch] Extract generic of_device allocation code from of_platform_device_create() and move it into of_device.[ch], called of_device_alloc(). Also, there's now of_device_free() which puts the device node. This way, bus drivers that build on of_platform (like ibmebus will) can build upon this code instead of reinventing the wheel. Signed-off-by: Joachim Fenkes Acked-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/of_device.c | 80 +++++++++++++++++++++++++++++++++++++++ arch/powerpc/kernel/of_platform.c | 70 +--------------------------------- include/asm-powerpc/of_device.h | 4 ++ include/linux/of_device.h | 5 +++ 4 files changed, 91 insertions(+), 68 deletions(-) (limited to 'include') diff --git a/arch/powerpc/kernel/of_device.c b/arch/powerpc/kernel/of_device.c index 8f3db32fac8b..3388ad619996 100644 --- a/arch/powerpc/kernel/of_device.c +++ b/arch/powerpc/kernel/of_device.c @@ -7,8 +7,88 @@ #include #include +#include #include +static void of_device_make_bus_id(struct of_device *dev) +{ + static atomic_t bus_no_reg_magic; + struct device_node *node = dev->node; + char *name = dev->dev.bus_id; + const u32 *reg; + u64 addr; + int magic; + + /* + * If it's a DCR based device, use 'd' for native DCRs + * and 'D' for MMIO DCRs. + */ +#ifdef CONFIG_PPC_DCR + reg = of_get_property(node, "dcr-reg", NULL); + if (reg) { +#ifdef CONFIG_PPC_DCR_NATIVE + snprintf(name, BUS_ID_SIZE, "d%x.%s", + *reg, node->name); +#else /* CONFIG_PPC_DCR_NATIVE */ + addr = of_translate_dcr_address(node, *reg, NULL); + if (addr != OF_BAD_ADDR) { + snprintf(name, BUS_ID_SIZE, + "D%llx.%s", (unsigned long long)addr, + node->name); + return; + } +#endif /* !CONFIG_PPC_DCR_NATIVE */ + } +#endif /* CONFIG_PPC_DCR */ + + /* + * For MMIO, get the physical address + */ + reg = of_get_property(node, "reg", NULL); + if (reg) { + addr = of_translate_address(node, reg); + if (addr != OF_BAD_ADDR) { + snprintf(name, BUS_ID_SIZE, + "%llx.%s", (unsigned long long)addr, + node->name); + return; + } + } + + /* + * No BusID, use the node name and add a globally incremented + * counter (and pray...) + */ + magic = atomic_add_return(1, &bus_no_reg_magic); + snprintf(name, BUS_ID_SIZE, "%s.%d", node->name, magic - 1); +} + +struct of_device *of_device_alloc(struct device_node *np, + const char *bus_id, + struct device *parent) +{ + struct of_device *dev; + + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) + return NULL; + + dev->node = of_node_get(np); + dev->dev.dma_mask = &dev->dma_mask; + dev->dev.parent = parent; + dev->dev.release = of_release_dev; + dev->dev.archdata.of_node = np; + dev->dev.archdata.numa_node = of_node_to_nid(np); + + if (bus_id) + strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE); + else + of_device_make_bus_id(dev); + + return dev; +} +EXPORT_SYMBOL(of_device_alloc); + ssize_t of_device_get_modalias(struct of_device *ofdev, char *str, ssize_t len) { diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c index eca8ccc3fa12..aeaa20268ce2 100644 --- a/arch/powerpc/kernel/of_platform.c +++ b/arch/powerpc/kernel/of_platform.c @@ -23,7 +23,6 @@ #include #include -#include #include #include #include @@ -53,8 +52,6 @@ static struct of_device_id of_default_bus_ids[] = { {}, }; -static atomic_t bus_no_reg_magic; - struct bus_type of_platform_bus_type = { .uevent = of_device_uevent, }; @@ -87,89 +84,26 @@ void of_unregister_platform_driver(struct of_platform_driver *drv) } EXPORT_SYMBOL(of_unregister_platform_driver); -static void of_platform_make_bus_id(struct of_device *dev) -{ - struct device_node *node = dev->node; - char *name = dev->dev.bus_id; - const u32 *reg; - u64 addr; - int magic; - - /* - * If it's a DCR based device, use 'd' for native DCRs - * and 'D' for MMIO DCRs. - */ -#ifdef CONFIG_PPC_DCR - reg = of_get_property(node, "dcr-reg", NULL); - if (reg) { -#ifdef CONFIG_PPC_DCR_NATIVE - snprintf(name, BUS_ID_SIZE, "d%x.%s", - *reg, node->name); -#else /* CONFIG_PPC_DCR_NATIVE */ - addr = of_translate_dcr_address(node, *reg, NULL); - if (addr != OF_BAD_ADDR) { - snprintf(name, BUS_ID_SIZE, - "D%llx.%s", (unsigned long long)addr, - node->name); - return; - } -#endif /* !CONFIG_PPC_DCR_NATIVE */ - } -#endif /* CONFIG_PPC_DCR */ - - /* - * For MMIO, get the physical address - */ - reg = of_get_property(node, "reg", NULL); - if (reg) { - addr = of_translate_address(node, reg); - if (addr != OF_BAD_ADDR) { - snprintf(name, BUS_ID_SIZE, - "%llx.%s", (unsigned long long)addr, - node->name); - return; - } - } - - /* - * No BusID, use the node name and add a globally incremented - * counter (and pray...) - */ - magic = atomic_add_return(1, &bus_no_reg_magic); - snprintf(name, BUS_ID_SIZE, "%s.%d", node->name, magic - 1); -} - struct of_device* of_platform_device_create(struct device_node *np, const char *bus_id, struct device *parent) { struct of_device *dev; - dev = kzalloc(sizeof(*dev), GFP_KERNEL); + dev = of_device_alloc(np, bus_id, parent); if (!dev) return NULL; - dev->node = of_node_get(np); dev->dma_mask = 0xffffffffUL; - dev->dev.dma_mask = &dev->dma_mask; - dev->dev.parent = parent; dev->dev.bus = &of_platform_bus_type; - dev->dev.release = of_release_dev; - dev->dev.archdata.of_node = np; - dev->dev.archdata.numa_node = of_node_to_nid(np); /* We do not fill the DMA ops for platform devices by default. * This is currently the responsibility of the platform code * to do such, possibly using a device notifier */ - if (bus_id) - strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE); - else - of_platform_make_bus_id(dev); - if (of_device_register(dev) != 0) { - kfree(dev); + of_device_free(dev); return NULL; } diff --git a/include/asm-powerpc/of_device.h b/include/asm-powerpc/of_device.h index 93262f2546ad..6526e139a463 100644 --- a/include/asm-powerpc/of_device.h +++ b/include/asm-powerpc/of_device.h @@ -17,6 +17,10 @@ struct of_device struct device dev; /* Generic device interface */ }; +extern struct of_device *of_device_alloc(struct device_node *np, + const char *bus_id, + struct device *parent); + extern ssize_t of_device_get_modalias(struct of_device *ofdev, char *str, ssize_t len); extern int of_device_uevent(struct device *dev, diff --git a/include/linux/of_device.h b/include/linux/of_device.h index 91bf84b9d144..212bffb2b174 100644 --- a/include/linux/of_device.h +++ b/include/linux/of_device.h @@ -22,5 +22,10 @@ extern int of_device_register(struct of_device *ofdev); extern void of_device_unregister(struct of_device *ofdev); extern void of_release_dev(struct device *dev); +static inline void of_device_free(struct of_device *dev) +{ + of_release_dev(&dev->dev); +} + #endif /* __KERNEL__ */ #endif /* _LINUX_OF_DEVICE_H */ -- cgit v1.2.3 From 6b08f3ae8eec27a9e557468a48540bc64fd4a524 Mon Sep 17 00:00:00 2001 From: Joachim Fenkes Date: Wed, 26 Sep 2007 19:45:51 +1000 Subject: [POWERPC] ibmebus: Move to of_device and of_platform_driver, match eHCA and eHEA drivers Replace struct ibmebus_dev and struct ibmebus_driver with struct of_device and struct of_platform_driver, respectively. Match the external ibmebus interface and drivers using it. Signed-off-by: Joachim Fenkes Acked-by: Arnd Bergmann Acked-by: Roland Dreier Acked-by: Jeff Garzik Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/ibmebus.c | 28 ++++++------ drivers/infiniband/hw/ehca/ehca_classes.h | 2 +- drivers/infiniband/hw/ehca/ehca_eq.c | 6 +-- drivers/infiniband/hw/ehca/ehca_main.c | 32 +++++++------- drivers/net/ehea/ehea.h | 2 +- drivers/net/ehea/ehea_main.c | 72 +++++++++++++++---------------- include/asm-powerpc/ibmebus.h | 38 +++------------- 7 files changed, 79 insertions(+), 101 deletions(-) (limited to 'include') diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c index d21658140b6e..289d7e935918 100644 --- a/arch/powerpc/kernel/ibmebus.c +++ b/arch/powerpc/kernel/ibmebus.c @@ -193,21 +193,26 @@ static int ibmebus_create_devices(const struct of_device_id *matches) return ret; } -int ibmebus_register_driver(struct ibmebus_driver *drv) +int ibmebus_register_driver(struct of_platform_driver *drv) { - return 0; + /* If the driver uses devices that ibmebus doesn't know, add them */ + ibmebus_create_devices(drv->match_table); + + drv->driver.name = drv->name; + drv->driver.bus = &ibmebus_bus_type; + + return driver_register(&drv->driver); } EXPORT_SYMBOL(ibmebus_register_driver); -void ibmebus_unregister_driver(struct ibmebus_driver *drv) +void ibmebus_unregister_driver(struct of_platform_driver *drv) { + driver_unregister(&drv->driver); } EXPORT_SYMBOL(ibmebus_unregister_driver); -int ibmebus_request_irq(struct ibmebus_dev *dev, - u32 ist, - irq_handler_t handler, - unsigned long irq_flags, const char * devname, +int ibmebus_request_irq(u32 ist, irq_handler_t handler, + unsigned long irq_flags, const char *devname, void *dev_id) { unsigned int irq = irq_create_mapping(NULL, ist); @@ -215,12 +220,11 @@ int ibmebus_request_irq(struct ibmebus_dev *dev, if (irq == NO_IRQ) return -EINVAL; - return request_irq(irq, handler, - irq_flags, devname, dev_id); + return request_irq(irq, handler, irq_flags, devname, dev_id); } EXPORT_SYMBOL(ibmebus_request_irq); -void ibmebus_free_irq(struct ibmebus_dev *dev, u32 ist, void *dev_id) +void ibmebus_free_irq(u32 ist, void *dev_id) { unsigned int irq = irq_find_mapping(NULL, ist); @@ -231,9 +235,7 @@ EXPORT_SYMBOL(ibmebus_free_irq); static ssize_t name_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct ibmebus_dev *ebus_dev = to_ibmebus_dev(dev); - const char *name = of_get_property(ebus_dev->ofdev.node, "name", NULL); - return sprintf(buf, "%s\n", name); + return sprintf(buf, "%s\n", to_of_device(dev)->node->name); } static struct device_attribute ibmebus_dev_attrs[] = { diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h index 0f7a55d35ea7..3f2d68cff764 100644 --- a/drivers/infiniband/hw/ehca/ehca_classes.h +++ b/drivers/infiniband/hw/ehca/ehca_classes.h @@ -107,7 +107,7 @@ struct ehca_sport { struct ehca_shca { struct ib_device ib_device; - struct ibmebus_dev *ibmebus_dev; + struct of_device *ofdev; u8 num_ports; int hw_level; struct list_head shca_list; diff --git a/drivers/infiniband/hw/ehca/ehca_eq.c b/drivers/infiniband/hw/ehca/ehca_eq.c index 1d41faa7a337..b4ac617a70e6 100644 --- a/drivers/infiniband/hw/ehca/ehca_eq.c +++ b/drivers/infiniband/hw/ehca/ehca_eq.c @@ -123,7 +123,7 @@ int ehca_create_eq(struct ehca_shca *shca, /* register interrupt handlers and initialize work queues */ if (type == EHCA_EQ) { - ret = ibmebus_request_irq(NULL, eq->ist, ehca_interrupt_eq, + ret = ibmebus_request_irq(eq->ist, ehca_interrupt_eq, IRQF_DISABLED, "ehca_eq", (void *)shca); if (ret < 0) @@ -131,7 +131,7 @@ int ehca_create_eq(struct ehca_shca *shca, tasklet_init(&eq->interrupt_task, ehca_tasklet_eq, (long)shca); } else if (type == EHCA_NEQ) { - ret = ibmebus_request_irq(NULL, eq->ist, ehca_interrupt_neq, + ret = ibmebus_request_irq(eq->ist, ehca_interrupt_neq, IRQF_DISABLED, "ehca_neq", (void *)shca); if (ret < 0) @@ -171,7 +171,7 @@ int ehca_destroy_eq(struct ehca_shca *shca, struct ehca_eq *eq) u64 h_ret; spin_lock_irqsave(&eq->spinlock, flags); - ibmebus_free_irq(NULL, eq->ist, (void *)shca); + ibmebus_free_irq(eq->ist, (void *)shca); h_ret = hipz_h_destroy_eq(shca->ipz_hca_handle, eq); diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c index 403467f66fe6..a3409fdb307c 100644 --- a/drivers/infiniband/hw/ehca/ehca_main.c +++ b/drivers/infiniband/hw/ehca/ehca_main.c @@ -404,7 +404,7 @@ int ehca_init_device(struct ehca_shca *shca) shca->ib_device.node_type = RDMA_NODE_IB_CA; shca->ib_device.phys_port_cnt = shca->num_ports; shca->ib_device.num_comp_vectors = 1; - shca->ib_device.dma_device = &shca->ibmebus_dev->ofdev.dev; + shca->ib_device.dma_device = &shca->ofdev->dev; shca->ib_device.query_device = ehca_query_device; shca->ib_device.query_port = ehca_query_port; shca->ib_device.query_gid = ehca_query_gid; @@ -658,7 +658,7 @@ static struct attribute_group ehca_dev_attr_grp = { .attrs = ehca_dev_attrs }; -static int __devinit ehca_probe(struct ibmebus_dev *dev, +static int __devinit ehca_probe(struct of_device *dev, const struct of_device_id *id) { struct ehca_shca *shca; @@ -666,16 +666,16 @@ static int __devinit ehca_probe(struct ibmebus_dev *dev, struct ib_pd *ibpd; int ret; - handle = of_get_property(dev->ofdev.node, "ibm,hca-handle", NULL); + handle = of_get_property(dev->node, "ibm,hca-handle", NULL); if (!handle) { ehca_gen_err("Cannot get eHCA handle for adapter: %s.", - dev->ofdev.node->full_name); + dev->node->full_name); return -ENODEV; } if (!(*handle)) { ehca_gen_err("Wrong eHCA handle for adapter: %s.", - dev->ofdev.node->full_name); + dev->node->full_name); return -ENODEV; } @@ -686,9 +686,9 @@ static int __devinit ehca_probe(struct ibmebus_dev *dev, } mutex_init(&shca->modify_mutex); - shca->ibmebus_dev = dev; + shca->ofdev = dev; shca->ipz_hca_handle.handle = *handle; - dev->ofdev.dev.driver_data = shca; + dev->dev.driver_data = shca; ret = ehca_sense_attributes(shca); if (ret < 0) { @@ -764,7 +764,7 @@ static int __devinit ehca_probe(struct ibmebus_dev *dev, } } - ret = sysfs_create_group(&dev->ofdev.dev.kobj, &ehca_dev_attr_grp); + ret = sysfs_create_group(&dev->dev.kobj, &ehca_dev_attr_grp); if (ret) /* only complain; we can live without attributes */ ehca_err(&shca->ib_device, "Cannot create device attributes ret=%d", ret); @@ -814,12 +814,12 @@ probe1: return -EINVAL; } -static int __devexit ehca_remove(struct ibmebus_dev *dev) +static int __devexit ehca_remove(struct of_device *dev) { - struct ehca_shca *shca = dev->ofdev.dev.driver_data; + struct ehca_shca *shca = dev->dev.driver_data; int ret; - sysfs_remove_group(&dev->ofdev.dev.kobj, &ehca_dev_attr_grp); + sysfs_remove_group(&dev->dev.kobj, &ehca_dev_attr_grp); if (ehca_open_aqp1 == 1) { int i; @@ -870,11 +870,11 @@ static struct of_device_id ehca_device_table[] = {}, }; -static struct ibmebus_driver ehca_driver = { - .name = "ehca", - .id_table = ehca_device_table, - .probe = ehca_probe, - .remove = ehca_remove, +static struct of_platform_driver ehca_driver = { + .name = "ehca", + .match_table = ehca_device_table, + .probe = ehca_probe, + .remove = ehca_remove, }; void ehca_poll_eqs(unsigned long data) diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h index ac21526b6de8..b557bb44a36f 100644 --- a/drivers/net/ehea/ehea.h +++ b/drivers/net/ehea/ehea.h @@ -388,7 +388,7 @@ struct ehea_port_res { #define EHEA_MAX_PORTS 16 struct ehea_adapter { u64 handle; - struct ibmebus_dev *ebus_dev; + struct of_device *ofdev; struct ehea_port *port[EHEA_MAX_PORTS]; struct ehea_eq *neq; /* notification event queue */ struct tasklet_struct neq_tasklet; diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index 2ba57e6ace4d..fe5ffac7ac57 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -98,10 +98,10 @@ struct work_struct ehea_rereg_mr_task; struct semaphore dlpar_mem_lock; -static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev, +static int __devinit ehea_probe_adapter(struct of_device *dev, const struct of_device_id *id); -static int __devexit ehea_remove(struct ibmebus_dev *dev); +static int __devexit ehea_remove(struct of_device *dev); static struct of_device_id ehea_device_table[] = { { @@ -111,9 +111,9 @@ static struct of_device_id ehea_device_table[] = { {}, }; -static struct ibmebus_driver ehea_driver = { +static struct of_platform_driver ehea_driver = { .name = "ehea", - .id_table = ehea_device_table, + .match_table = ehea_device_table, .probe = ehea_probe_adapter, .remove = ehea_remove, }; @@ -1044,7 +1044,7 @@ static int ehea_reg_interrupts(struct net_device *dev) snprintf(port->int_aff_name, EHEA_IRQ_NAME_SIZE - 1, "%s-aff", dev->name); - ret = ibmebus_request_irq(NULL, port->qp_eq->attr.ist1, + ret = ibmebus_request_irq(port->qp_eq->attr.ist1, ehea_qp_aff_irq_handler, IRQF_DISABLED, port->int_aff_name, port); if (ret) { @@ -1062,7 +1062,7 @@ static int ehea_reg_interrupts(struct net_device *dev) pr = &port->port_res[i]; snprintf(pr->int_send_name, EHEA_IRQ_NAME_SIZE - 1, "%s-queue%d", dev->name, i); - ret = ibmebus_request_irq(NULL, pr->eq->attr.ist1, + ret = ibmebus_request_irq(pr->eq->attr.ist1, ehea_recv_irq_handler, IRQF_DISABLED, pr->int_send_name, pr); @@ -1083,11 +1083,11 @@ out: out_free_req: while (--i >= 0) { u32 ist = port->port_res[i].eq->attr.ist1; - ibmebus_free_irq(NULL, ist, &port->port_res[i]); + ibmebus_free_irq(ist, &port->port_res[i]); } out_free_qpeq: - ibmebus_free_irq(NULL, port->qp_eq->attr.ist1, port); + ibmebus_free_irq(port->qp_eq->attr.ist1, port); i = port->num_def_qps; goto out; @@ -1104,14 +1104,14 @@ static void ehea_free_interrupts(struct net_device *dev) for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) { pr = &port->port_res[i]; - ibmebus_free_irq(NULL, pr->eq->attr.ist1, pr); + ibmebus_free_irq(pr->eq->attr.ist1, pr); if (netif_msg_intr(port)) ehea_info("free send irq for res %d with handle 0x%X", i, pr->eq->attr.ist1); } /* associated events */ - ibmebus_free_irq(NULL, port->qp_eq->attr.ist1, port); + ibmebus_free_irq(port->qp_eq->attr.ist1, port); if (netif_msg_intr(port)) ehea_info("associated event interrupt for handle 0x%X freed", port->qp_eq->attr.ist1); @@ -2832,7 +2832,7 @@ static struct device *ehea_register_port(struct ehea_port *port, int ret; port->ofdev.node = of_node_get(dn); - port->ofdev.dev.parent = &port->adapter->ebus_dev->ofdev.dev; + port->ofdev.dev.parent = &port->adapter->ofdev->dev; port->ofdev.dev.bus = &ibmebus_bus_type; sprintf(port->ofdev.dev.bus_id, "port%d", port_name_cnt++); @@ -3011,7 +3011,7 @@ static int ehea_setup_ports(struct ehea_adapter *adapter) const u32 *dn_log_port_id; int i = 0; - lhea_dn = adapter->ebus_dev->ofdev.node; + lhea_dn = adapter->ofdev->node; while ((eth_dn = of_get_next_child(lhea_dn, eth_dn))) { dn_log_port_id = of_get_property(eth_dn, "ibm,hea-port-no", @@ -3051,7 +3051,7 @@ static struct device_node *ehea_get_eth_dn(struct ehea_adapter *adapter, struct device_node *eth_dn = NULL; const u32 *dn_log_port_id; - lhea_dn = adapter->ebus_dev->ofdev.node; + lhea_dn = adapter->ofdev->node; while ((eth_dn = of_get_next_child(lhea_dn, eth_dn))) { dn_log_port_id = of_get_property(eth_dn, "ibm,hea-port-no", @@ -3157,31 +3157,31 @@ static ssize_t ehea_remove_port(struct device *dev, static DEVICE_ATTR(probe_port, S_IWUSR, NULL, ehea_probe_port); static DEVICE_ATTR(remove_port, S_IWUSR, NULL, ehea_remove_port); -int ehea_create_device_sysfs(struct ibmebus_dev *dev) +int ehea_create_device_sysfs(struct of_device *dev) { - int ret = device_create_file(&dev->ofdev.dev, &dev_attr_probe_port); + int ret = device_create_file(&dev->dev, &dev_attr_probe_port); if (ret) goto out; - ret = device_create_file(&dev->ofdev.dev, &dev_attr_remove_port); + ret = device_create_file(&dev->dev, &dev_attr_remove_port); out: return ret; } -void ehea_remove_device_sysfs(struct ibmebus_dev *dev) +void ehea_remove_device_sysfs(struct of_device *dev) { - device_remove_file(&dev->ofdev.dev, &dev_attr_probe_port); - device_remove_file(&dev->ofdev.dev, &dev_attr_remove_port); + device_remove_file(&dev->dev, &dev_attr_probe_port); + device_remove_file(&dev->dev, &dev_attr_remove_port); } -static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev, +static int __devinit ehea_probe_adapter(struct of_device *dev, const struct of_device_id *id) { struct ehea_adapter *adapter; const u64 *adapter_handle; int ret; - if (!dev || !dev->ofdev.node) { + if (!dev || !dev->node) { ehea_error("Invalid ibmebus device probed"); return -EINVAL; } @@ -3189,36 +3189,36 @@ static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev, adapter = kzalloc(sizeof(*adapter), GFP_KERNEL); if (!adapter) { ret = -ENOMEM; - dev_err(&dev->ofdev.dev, "no mem for ehea_adapter\n"); + dev_err(&dev->dev, "no mem for ehea_adapter\n"); goto out; } list_add(&adapter->list, &adapter_list); - adapter->ebus_dev = dev; + adapter->ofdev = dev; - adapter_handle = of_get_property(dev->ofdev.node, "ibm,hea-handle", + adapter_handle = of_get_property(dev->node, "ibm,hea-handle", NULL); if (adapter_handle) adapter->handle = *adapter_handle; if (!adapter->handle) { - dev_err(&dev->ofdev.dev, "failed getting handle for adapter" - " '%s'\n", dev->ofdev.node->full_name); + dev_err(&dev->dev, "failed getting handle for adapter" + " '%s'\n", dev->node->full_name); ret = -ENODEV; goto out_free_ad; } adapter->pd = EHEA_PD_ID; - dev->ofdev.dev.driver_data = adapter; + dev->dev.driver_data = adapter; /* initialize adapter and ports */ /* get adapter properties */ ret = ehea_sense_adapter_attr(adapter); if (ret) { - dev_err(&dev->ofdev.dev, "sense_adapter_attr failed: %d", ret); + dev_err(&dev->dev, "sense_adapter_attr failed: %d", ret); goto out_free_ad; } @@ -3226,18 +3226,18 @@ static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev, EHEA_NEQ, EHEA_MAX_ENTRIES_EQ, 1); if (!adapter->neq) { ret = -EIO; - dev_err(&dev->ofdev.dev, "NEQ creation failed"); + dev_err(&dev->dev, "NEQ creation failed"); goto out_free_ad; } tasklet_init(&adapter->neq_tasklet, ehea_neq_tasklet, (unsigned long)adapter); - ret = ibmebus_request_irq(NULL, adapter->neq->attr.ist1, + ret = ibmebus_request_irq(adapter->neq->attr.ist1, ehea_interrupt_neq, IRQF_DISABLED, "ehea_neq", adapter); if (ret) { - dev_err(&dev->ofdev.dev, "requesting NEQ IRQ failed"); + dev_err(&dev->dev, "requesting NEQ IRQ failed"); goto out_kill_eq; } @@ -3247,7 +3247,7 @@ static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev, ret = ehea_setup_ports(adapter); if (ret) { - dev_err(&dev->ofdev.dev, "setup_ports failed"); + dev_err(&dev->dev, "setup_ports failed"); goto out_rem_dev_sysfs; } @@ -3258,7 +3258,7 @@ out_rem_dev_sysfs: ehea_remove_device_sysfs(dev); out_free_irq: - ibmebus_free_irq(NULL, adapter->neq->attr.ist1, adapter); + ibmebus_free_irq(adapter->neq->attr.ist1, adapter); out_kill_eq: ehea_destroy_eq(adapter->neq); @@ -3269,9 +3269,9 @@ out: return ret; } -static int __devexit ehea_remove(struct ibmebus_dev *dev) +static int __devexit ehea_remove(struct of_device *dev) { - struct ehea_adapter *adapter = dev->ofdev.dev.driver_data; + struct ehea_adapter *adapter = dev->dev.driver_data; int i; for (i = 0; i < EHEA_MAX_PORTS; i++) @@ -3284,7 +3284,7 @@ static int __devexit ehea_remove(struct ibmebus_dev *dev) flush_scheduled_work(); - ibmebus_free_irq(NULL, adapter->neq->attr.ist1, adapter); + ibmebus_free_irq(adapter->neq->attr.ist1, adapter); tasklet_kill(&adapter->neq_tasklet); ehea_destroy_eq(adapter->neq); diff --git a/include/asm-powerpc/ibmebus.h b/include/asm-powerpc/ibmebus.h index 87d396e28db2..1a9d9aea21fa 100644 --- a/include/asm-powerpc/ibmebus.h +++ b/include/asm-powerpc/ibmebus.h @@ -43,42 +43,18 @@ #include #include #include -#include +#include +#include extern struct bus_type ibmebus_bus_type; -struct ibmebus_dev { - struct of_device ofdev; -}; +int ibmebus_register_driver(struct of_platform_driver *drv); +void ibmebus_unregister_driver(struct of_platform_driver *drv); -struct ibmebus_driver { - char *name; - struct of_device_id *id_table; - int (*probe) (struct ibmebus_dev *dev, const struct of_device_id *id); - int (*remove) (struct ibmebus_dev *dev); - struct device_driver driver; -}; - -int ibmebus_register_driver(struct ibmebus_driver *drv); -void ibmebus_unregister_driver(struct ibmebus_driver *drv); - -int ibmebus_request_irq(struct ibmebus_dev *dev, - u32 ist, - irq_handler_t handler, - unsigned long irq_flags, const char * devname, +int ibmebus_request_irq(u32 ist, irq_handler_t handler, + unsigned long irq_flags, const char *devname, void *dev_id); -void ibmebus_free_irq(struct ibmebus_dev *dev, u32 ist, void *dev_id); - -static inline struct ibmebus_driver *to_ibmebus_driver(struct device_driver *drv) -{ - return container_of(drv, struct ibmebus_driver, driver); -} - -static inline struct ibmebus_dev *to_ibmebus_dev(struct device *dev) -{ - return container_of(dev, struct ibmebus_dev, ofdev.dev); -} - +void ibmebus_free_irq(u32 ist, void *dev_id); #endif /* __KERNEL__ */ #endif /* _ASM_IBMEBUS_H */ -- cgit v1.2.3 From f66bce5e6aa1388289c04496c3fcae7bebf5f905 Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Tue, 16 Oct 2007 00:58:59 +1000 Subject: [POWERPC] Add 1TB workaround for PA6T PA6T has a bug where the slbie instruction does not honor the large segment bit. As a result, we have to always use slbia when switching context. We don't have to worry about changing the slbie's during fault processing, since they should never be replacing one VSID with another using the same ESID. I.e. there's no risk for inserting duplicate entries due to a failed slbie of the old entry. So as long as we clear it out on context switch we should be fine. Signed-off-by: Olof Johansson Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/entry_64.S | 6 ++++++ arch/powerpc/mm/hash_utils_64.c | 1 + arch/powerpc/mm/slb.c | 3 ++- include/asm-powerpc/cputable.h | 3 ++- 4 files changed, 11 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 0ec134034899..148a3547c9aa 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -408,6 +408,12 @@ END_FTR_SECTION_IFSET(CPU_FTR_1T_SEGMENT) std r7,SLBSHADOW_STACKVSID(r9) /* Save VSID */ std r0,SLBSHADOW_STACKESID(r9) /* Save ESID */ + /* No need to check for CPU_FTR_NO_SLBIE_B here, since when + * we have 1TB segments, the only CPUs known to have the errata + * only support less than 1TB of system memory and we'll never + * actually hit this code path. + */ + slbie r6 slbie r6 /* Workaround POWER5 < DD2.1 issue */ slbmte r7,r0 diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 09da90b53850..c78dc912411f 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c @@ -212,6 +212,7 @@ static int __init htab_dt_scan_seg_sizes(unsigned long node, return 1; } } + cur_cpu_spec->cpu_features &= ~CPU_FTR_NO_SLBIE_B; return 0; } diff --git a/arch/powerpc/mm/slb.c b/arch/powerpc/mm/slb.c index 6c164cec9d2c..bbd2c512ee05 100644 --- a/arch/powerpc/mm/slb.c +++ b/arch/powerpc/mm/slb.c @@ -157,7 +157,8 @@ void switch_slb(struct task_struct *tsk, struct mm_struct *mm) unsigned long stack = KSTK_ESP(tsk); unsigned long unmapped_base; - if (offset <= SLB_CACHE_ENTRIES) { + if (!cpu_has_feature(CPU_FTR_NO_SLBIE_B) && + offset <= SLB_CACHE_ENTRIES) { int i; asm volatile("isync" : : : "memory"); for (i = 0; i < offset; i++) { diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h index ae093ef68363..9d74338e3dec 100644 --- a/include/asm-powerpc/cputable.h +++ b/include/asm-powerpc/cputable.h @@ -165,6 +165,7 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start, #define CPU_FTR_SPURR LONG_ASM_CONST(0x0001000000000000) #define CPU_FTR_DSCR LONG_ASM_CONST(0x0002000000000000) #define CPU_FTR_1T_SEGMENT LONG_ASM_CONST(0x0004000000000000) +#define CPU_FTR_NO_SLBIE_B LONG_ASM_CONST(0x0008000000000000) #ifndef __ASSEMBLY__ @@ -367,7 +368,7 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start, #define CPU_FTRS_PA6T (CPU_FTR_USE_TB | \ CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \ CPU_FTR_ALTIVEC_COMP | CPU_FTR_CI_LARGE_PAGE | \ - CPU_FTR_PURR | CPU_FTR_REAL_LE) + CPU_FTR_PURR | CPU_FTR_REAL_LE | CPU_FTR_NO_SLBIE_B) #define CPU_FTRS_COMPATIBLE (CPU_FTR_USE_TB | \ CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2) -- cgit v1.2.3