[Qemu-devel] [PATCH] ppc/pnv: change powernv_ prefix to pnv_ for overall naming consistency

Cédric Le Goater posted 1 patch 44 weeks ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/qemu tags/patchew/20171215061739.9494-1-clg@kaod.org
Test checkpatch passed
Test docker passed
Test ppc passed
Test s390x passed
hw/ppc/pnv.c         | 84 ++++++++++++++++++++++++++--------------------------
hw/ppc/pnv_core.c    |  8 ++---
hw/ppc/pnv_lpc.c     |  2 +-
include/hw/ppc/pnv.h |  8 ++---
4 files changed, 51 insertions(+), 51 deletions(-)

[Qemu-devel] [PATCH] ppc/pnv: change powernv_ prefix to pnv_ for overall naming consistency

Posted by Cédric Le Goater 44 weeks ago
Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 hw/ppc/pnv.c         | 84 ++++++++++++++++++++++++++--------------------------
 hw/ppc/pnv_core.c    |  8 ++---
 hw/ppc/pnv_lpc.c     |  2 +-
 include/hw/ppc/pnv.h |  8 ++---
 4 files changed, 51 insertions(+), 51 deletions(-)

diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index c35c439d816b..4bc5f61d0da7 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -77,7 +77,7 @@ static const char *pnv_chip_core_typename(const PnvChip *o)
  * that has a different "affinity". In practice, it means one range
  * per chip.
  */
-static void powernv_populate_memory_node(void *fdt, int chip_id, hwaddr start,
+static void pnv_populate_memory_node(void *fdt, int chip_id, hwaddr start,
                                          hwaddr size)
 {
     char *mem_name;
@@ -119,7 +119,7 @@ static int get_cpus_node(void *fdt)
  * device tree, used in XSCOM to address cores and in interrupt
  * servers.
  */
-static void powernv_create_core_node(PnvChip *chip, PnvCore *pc, void *fdt)
+static void pnv_create_core_node(PnvChip *chip, PnvCore *pc, void *fdt)
 {
     CPUState *cs = CPU(DEVICE(pc->threads));
     DeviceClass *dc = DEVICE_GET_CLASS(cs);
@@ -228,7 +228,7 @@ static void powernv_create_core_node(PnvChip *chip, PnvCore *pc, void *fdt)
                        servers_prop, sizeof(servers_prop))));
 }
 
-static void powernv_populate_icp(PnvChip *chip, void *fdt, uint32_t pir,
+static void pnv_populate_icp(PnvChip *chip, void *fdt, uint32_t pir,
                                  uint32_t nr_threads)
 {
     uint64_t addr = PNV_ICP_BASE(chip) | (pir << 12);
@@ -277,7 +277,7 @@ static int pnv_chip_lpc_offset(PnvChip *chip, void *fdt)
     return offset;
 }
 
-static void powernv_populate_chip(PnvChip *chip, void *fdt)
+static void pnv_populate_chip(PnvChip *chip, void *fdt)
 {
     const char *typename = pnv_chip_core_typename(chip);
     size_t typesize = object_type_get_instance_size(typename);
@@ -298,20 +298,20 @@ static void powernv_populate_chip(PnvChip *chip, void *fdt)
     for (i = 0; i < chip->nr_cores; i++) {
         PnvCore *pnv_core = PNV_CORE(chip->cores + i * typesize);
 
-        powernv_create_core_node(chip, pnv_core, fdt);
+        pnv_create_core_node(chip, pnv_core, fdt);
 
         /* Interrupt Control Presenters (ICP). One per core. */
-        powernv_populate_icp(chip, fdt, pnv_core->pir,
+        pnv_populate_icp(chip, fdt, pnv_core->pir,
                              CPU_CORE(pnv_core)->nr_threads);
     }
 
     if (chip->ram_size) {
-        powernv_populate_memory_node(fdt, chip->chip_id, chip->ram_start,
+        pnv_populate_memory_node(fdt, chip->chip_id, chip->ram_start,
                                      chip->ram_size);
     }
 }
 
-static void powernv_populate_rtc(ISADevice *d, void *fdt, int lpc_off)
+static void pnv_populate_rtc(ISADevice *d, void *fdt, int lpc_off)
 {
     uint32_t io_base = d->ioport_id;
     uint32_t io_regs[] = {
@@ -331,7 +331,7 @@ static void powernv_populate_rtc(ISADevice *d, void *fdt, int lpc_off)
     _FDT((fdt_setprop_string(fdt, node, "compatible", "pnpPNP,b00")));
 }
 
-static void powernv_populate_serial(ISADevice *d, void *fdt, int lpc_off)
+static void pnv_populate_serial(ISADevice *d, void *fdt, int lpc_off)
 {
     const char compatible[] = "ns16550\0pnpPNP,501";
     uint32_t io_base = d->ioport_id;
@@ -362,7 +362,7 @@ static void powernv_populate_serial(ISADevice *d, void *fdt, int lpc_off)
     _FDT((fdt_setprop_string(fdt, node, "device_type", "serial")));
 }
 
-static void powernv_populate_ipmi_bt(ISADevice *d, void *fdt, int lpc_off)
+static void pnv_populate_ipmi_bt(ISADevice *d, void *fdt, int lpc_off)
 {
     const char compatible[] = "bt\0ipmi-bt";
     uint32_t io_base;
@@ -401,17 +401,17 @@ typedef struct ForeachPopulateArgs {
     int offset;
 } ForeachPopulateArgs;
 
-static int powernv_populate_isa_device(DeviceState *dev, void *opaque)
+static int pnv_populate_isa_device(DeviceState *dev, void *opaque)
 {
     ForeachPopulateArgs *args = opaque;
     ISADevice *d = ISA_DEVICE(dev);
 
     if (object_dynamic_cast(OBJECT(dev), TYPE_MC146818_RTC)) {
-        powernv_populate_rtc(d, args->fdt, args->offset);
+        pnv_populate_rtc(d, args->fdt, args->offset);
     } else if (object_dynamic_cast(OBJECT(dev), TYPE_ISA_SERIAL)) {
-        powernv_populate_serial(d, args->fdt, args->offset);
+        pnv_populate_serial(d, args->fdt, args->offset);
     } else if (object_dynamic_cast(OBJECT(dev), "isa-ipmi-bt")) {
-        powernv_populate_ipmi_bt(d, args->fdt, args->offset);
+        pnv_populate_ipmi_bt(d, args->fdt, args->offset);
     } else {
         error_report("unknown isa device %s@i%x", qdev_fw_name(dev),
                      d->ioport_id);
@@ -420,7 +420,7 @@ static int powernv_populate_isa_device(DeviceState *dev, void *opaque)
     return 0;
 }
 
-static void powernv_populate_isa(ISABus *bus, void *fdt, int lpc_offset)
+static void pnv_populate_isa(ISABus *bus, void *fdt, int lpc_offset)
 {
     ForeachPopulateArgs args = {
         .fdt = fdt,
@@ -429,14 +429,14 @@ static void powernv_populate_isa(ISABus *bus, void *fdt, int lpc_offset)
 
     /* ISA devices are not necessarily parented to the ISA bus so we
      * can not use object_child_foreach() */
-    qbus_walk_children(BUS(bus), powernv_populate_isa_device,
+    qbus_walk_children(BUS(bus), pnv_populate_isa_device,
                        NULL, NULL, NULL, &args);
 }
 
-static void *powernv_create_fdt(MachineState *machine)
+static void *pnv_create_fdt(MachineState *machine)
 {
     const char plat_compat[] = "qemu,powernv\0ibm,powernv";
-    PnvMachineState *pnv = POWERNV_MACHINE(machine);
+    PnvMachineState *pnv = PNV_MACHINE(machine);
     void *fdt;
     char *buf;
     int off;
@@ -479,12 +479,12 @@ static void *powernv_create_fdt(MachineState *machine)
 
     /* Populate device tree for each chip */
     for (i = 0; i < pnv->num_chips; i++) {
-        powernv_populate_chip(pnv->chips[i], fdt);
+        pnv_populate_chip(pnv->chips[i], fdt);
     }
 
     /* Populate ISA devices on chip 0 */
     lpc_offset = pnv_chip_lpc_offset(pnv->chips[0], fdt);
-    powernv_populate_isa(pnv->isa_bus, fdt, lpc_offset);
+    pnv_populate_isa(pnv->isa_bus, fdt, lpc_offset);
 
     if (pnv->bmc) {
         pnv_bmc_populate_sensors(pnv->bmc, fdt);
@@ -495,17 +495,17 @@ static void *powernv_create_fdt(MachineState *machine)
 
 static void pnv_powerdown_notify(Notifier *n, void *opaque)
 {
-    PnvMachineState *pnv = POWERNV_MACHINE(qdev_get_machine());
+    PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
 
     if (pnv->bmc) {
         pnv_bmc_powerdown(pnv->bmc);
     }
 }
 
-static void ppc_powernv_reset(void)
+static void pnv_reset(void)
 {
     MachineState *machine = MACHINE(qdev_get_machine());
-    PnvMachineState *pnv = POWERNV_MACHINE(machine);
+    PnvMachineState *pnv = PNV_MACHINE(machine);
     void *fdt;
     Object *obj;
 
@@ -524,7 +524,7 @@ static void ppc_powernv_reset(void)
         pnv->bmc = IPMI_BMC(obj);
     }
 
-    fdt = powernv_create_fdt(machine);
+    fdt = pnv_create_fdt(machine);
 
     /* Pack resulting tree */
     _FDT((fdt_pack(fdt)));
@@ -552,9 +552,9 @@ static ISABus *pnv_isa_create(PnvChip *chip)
     return isa_bus;
 }
 
-static void ppc_powernv_init(MachineState *machine)
+static void pnv_init(MachineState *machine)
 {
-    PnvMachineState *pnv = POWERNV_MACHINE(machine);
+    PnvMachineState *pnv = PNV_MACHINE(machine);
     MemoryRegion *ram;
     char *fw_filename;
     long fw_size;
@@ -567,7 +567,7 @@ static void ppc_powernv_init(MachineState *machine)
     }
 
     ram = g_new(MemoryRegion, 1);
-    memory_region_allocate_system_memory(ram, NULL, "ppc_powernv.ram",
+    memory_region_allocate_system_memory(ram, NULL, "pnv.ram",
                                          machine->ram_size);
     memory_region_add_subregion(get_system_memory(), 0, ram);
 
@@ -974,7 +974,7 @@ static void pnv_chip_class_init(ObjectClass *klass, void *data)
 
 static ICSState *pnv_ics_get(XICSFabric *xi, int irq)
 {
-    PnvMachineState *pnv = POWERNV_MACHINE(xi);
+    PnvMachineState *pnv = PNV_MACHINE(xi);
     int i;
 
     for (i = 0; i < pnv->num_chips; i++) {
@@ -987,7 +987,7 @@ static ICSState *pnv_ics_get(XICSFabric *xi, int irq)
 
 static void pnv_ics_resend(XICSFabric *xi)
 {
-    PnvMachineState *pnv = POWERNV_MACHINE(xi);
+    PnvMachineState *pnv = PNV_MACHINE(xi);
     int i;
 
     for (i = 0; i < pnv->num_chips; i++) {
@@ -1021,7 +1021,7 @@ static ICPState *pnv_icp_get(XICSFabric *xi, int pir)
 static void pnv_pic_print_info(InterruptStatsProvider *obj,
                                Monitor *mon)
 {
-    PnvMachineState *pnv = POWERNV_MACHINE(obj);
+    PnvMachineState *pnv = PNV_MACHINE(obj);
     int i;
     CPUState *cs;
 
@@ -1039,13 +1039,13 @@ static void pnv_pic_print_info(InterruptStatsProvider *obj,
 static void pnv_get_num_chips(Object *obj, Visitor *v, const char *name,
                               void *opaque, Error **errp)
 {
-    visit_type_uint32(v, name, &POWERNV_MACHINE(obj)->num_chips, errp);
+    visit_type_uint32(v, name, &PNV_MACHINE(obj)->num_chips, errp);
 }
 
 static void pnv_set_num_chips(Object *obj, Visitor *v, const char *name,
                               void *opaque, Error **errp)
 {
-    PnvMachineState *pnv = POWERNV_MACHINE(obj);
+    PnvMachineState *pnv = PNV_MACHINE(obj);
     uint32_t num_chips;
     Error *local_err = NULL;
 
@@ -1067,13 +1067,13 @@ static void pnv_set_num_chips(Object *obj, Visitor *v, const char *name,
     pnv->num_chips = num_chips;
 }
 
-static void powernv_machine_initfn(Object *obj)
+static void pnv_machine_initfn(Object *obj)
 {
-    PnvMachineState *pnv = POWERNV_MACHINE(obj);
+    PnvMachineState *pnv = PNV_MACHINE(obj);
     pnv->num_chips = 1;
 }
 
-static void powernv_machine_class_props_init(ObjectClass *oc)
+static void pnv_machine_class_props_init(ObjectClass *oc)
 {
     object_class_property_add(oc, "num-chips", "uint32",
                               pnv_get_num_chips, pnv_set_num_chips,
@@ -1083,15 +1083,15 @@ static void powernv_machine_class_props_init(ObjectClass *oc)
                               NULL);
 }
 
-static void powernv_machine_class_init(ObjectClass *oc, void *data)
+static void pnv_machine_class_init(ObjectClass *oc, void *data)
 {
     MachineClass *mc = MACHINE_CLASS(oc);
     XICSFabricClass *xic = XICS_FABRIC_CLASS(oc);
     InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc);
 
     mc->desc = "IBM PowerNV (Non-Virtualized)";
-    mc->init = ppc_powernv_init;
-    mc->reset = ppc_powernv_reset;
+    mc->init = pnv_init;
+    mc->reset = pnv_reset;
     mc->max_cpus = MAX_CPUS;
     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0");
     mc->block_default_type = IF_IDE; /* Pnv provides a AHCI device for
@@ -1104,7 +1104,7 @@ static void powernv_machine_class_init(ObjectClass *oc, void *data)
     xic->ics_resend = pnv_ics_resend;
     ispc->print_info = pnv_pic_print_info;
 
-    powernv_machine_class_props_init(oc);
+    pnv_machine_class_props_init(oc);
 }
 
 #define DEFINE_PNV_CHIP_TYPE(type, class_initfn) \
@@ -1116,11 +1116,11 @@ static void powernv_machine_class_init(ObjectClass *oc, void *data)
 
 static const TypeInfo types[] = {
     {
-        .name          = TYPE_POWERNV_MACHINE,
+        .name          = TYPE_PNV_MACHINE,
         .parent        = TYPE_MACHINE,
         .instance_size = sizeof(PnvMachineState),
-        .instance_init = powernv_machine_initfn,
-        .class_init    = powernv_machine_class_init,
+        .instance_init = pnv_machine_initfn,
+        .class_init    = pnv_machine_class_init,
         .interfaces = (InterfaceInfo[]) {
             { TYPE_XICS_FABRIC },
             { TYPE_INTERRUPT_STATS_PROVIDER },
diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c
index 82ff440b3334..78eeadbbb6a4 100644
--- a/hw/ppc/pnv_core.c
+++ b/hw/ppc/pnv_core.c
@@ -37,7 +37,7 @@ static const char *pnv_core_cpu_typename(PnvCore *pc)
     return cpu_type;
 }
 
-static void powernv_cpu_reset(void *opaque)
+static void pnv_cpu_reset(void *opaque)
 {
     PowerPCCPU *cpu = opaque;
     CPUState *cs = CPU(cpu);
@@ -54,7 +54,7 @@ static void powernv_cpu_reset(void *opaque)
     env->msr |= MSR_HVB; /* Hypervisor mode */
 }
 
-static void powernv_cpu_init(PowerPCCPU *cpu, Error **errp)
+static void pnv_cpu_init(PowerPCCPU *cpu, Error **errp)
 {
     CPUPPCState *env = &cpu->env;
     int core_pir;
@@ -73,7 +73,7 @@ static void powernv_cpu_init(PowerPCCPU *cpu, Error **errp)
     /* Set time-base frequency to 512 MHz */
     cpu_ppc_tb_init(env, PNV_TIMEBASE_FREQ);
 
-    qemu_register_reset(powernv_cpu_reset, cpu);
+    qemu_register_reset(pnv_cpu_reset, cpu);
 }
 
 /*
@@ -146,7 +146,7 @@ static void pnv_core_realize_child(Object *child, XICSFabric *xi, Error **errp)
         return;
     }
 
-    powernv_cpu_init(cpu, &local_err);
+    pnv_cpu_init(cpu, &local_err);
     if (local_err) {
         object_unparent(obj);
         error_propagate(errp, local_err);
diff --git a/hw/ppc/pnv_lpc.c b/hw/ppc/pnv_lpc.c
index f03a80a29bf6..27f0552b1e86 100644
--- a/hw/ppc/pnv_lpc.c
+++ b/hw/ppc/pnv_lpc.c
@@ -515,7 +515,7 @@ type_init(pnv_lpc_register_types)
  */
 static void pnv_lpc_isa_irq_handler_cpld(void *opaque, int n, int level)
 {
-    PnvMachineState *pnv = POWERNV_MACHINE(qdev_get_machine());
+    PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
     uint32_t old_state = pnv->cpld_irqstate;
     PnvLpcController *lpc = PNV_LPC(opaque);
 
diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h
index 59524cd42b61..6b262202c9e6 100644
--- a/include/hw/ppc/pnv.h
+++ b/include/hw/ppc/pnv.h
@@ -26,7 +26,7 @@
 #include "hw/ppc/pnv_psi.h"
 #include "hw/ppc/pnv_occ.h"
 
-#define TYPE_PNV_CHIP "powernv-chip"
+#define TYPE_PNV_CHIP "pnv-chip"
 #define PNV_CHIP(obj) OBJECT_CHECK(PnvChip, (obj), TYPE_PNV_CHIP)
 #define PNV_CHIP_CLASS(klass) \
      OBJECT_CLASS_CHECK(PnvChipClass, (klass), TYPE_PNV_CHIP)
@@ -117,9 +117,9 @@ typedef struct PnvChipClass {
 #define PNV_CHIP_INDEX(chip)                                    \
     (((chip)->chip_id >> 2) * 2 + ((chip)->chip_id & 0x3))
 
-#define TYPE_POWERNV_MACHINE       MACHINE_TYPE_NAME("powernv")
-#define POWERNV_MACHINE(obj) \
-    OBJECT_CHECK(PnvMachineState, (obj), TYPE_POWERNV_MACHINE)
+#define TYPE_PNV_MACHINE       MACHINE_TYPE_NAME("powernv")
+#define PNV_MACHINE(obj) \
+    OBJECT_CHECK(PnvMachineState, (obj), TYPE_PNV_MACHINE)
 
 typedef struct PnvMachineState {
     /*< private >*/
-- 
2.13.6


Re: [Qemu-devel] [Qemu-ppc] [PATCH] ppc/pnv: change powernv_ prefix to pnv_ for overall naming consistency

Posted by Alexey Kardashevskiy 44 weeks ago
On 15/12/17 17:17, Cédric Le Goater wrote:
> Signed-off-by: Cédric Le Goater <clg@kaod.org>
> ---
>  hw/ppc/pnv.c         | 84 ++++++++++++++++++++++++++--------------------------
>  hw/ppc/pnv_core.c    |  8 ++---
>  hw/ppc/pnv_lpc.c     |  2 +-
>  include/hw/ppc/pnv.h |  8 ++---
>  4 files changed, 51 insertions(+), 51 deletions(-)
> 
> diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
> index c35c439d816b..4bc5f61d0da7 100644
> --- a/hw/ppc/pnv.c
> +++ b/hw/ppc/pnv.c
> @@ -77,7 +77,7 @@ static const char *pnv_chip_core_typename(const PnvChip *o)
>   * that has a different "affinity". In practice, it means one range
>   * per chip.
>   */
> -static void powernv_populate_memory_node(void *fdt, int chip_id, hwaddr start,
> +static void pnv_populate_memory_node(void *fdt, int chip_id, hwaddr start,
>                                           hwaddr size)

You may also want to fix indentations like the line above.




-- 
Alexey

Re: [Qemu-devel] [Qemu-ppc] [PATCH] ppc/pnv: change powernv_ prefix to pnv_ for overall naming consistency

Posted by Cédric Le Goater 44 weeks ago
On 12/15/2017 07:43 AM, Alexey Kardashevskiy wrote:
> On 15/12/17 17:17, Cédric Le Goater wrote:
>> Signed-off-by: Cédric Le Goater <clg@kaod.org>
>> ---
>>  hw/ppc/pnv.c         | 84 ++++++++++++++++++++++++++--------------------------
>>  hw/ppc/pnv_core.c    |  8 ++---
>>  hw/ppc/pnv_lpc.c     |  2 +-
>>  include/hw/ppc/pnv.h |  8 ++---
>>  4 files changed, 51 insertions(+), 51 deletions(-)
>>
>> diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
>> index c35c439d816b..4bc5f61d0da7 100644
>> --- a/hw/ppc/pnv.c
>> +++ b/hw/ppc/pnv.c
>> @@ -77,7 +77,7 @@ static const char *pnv_chip_core_typename(const PnvChip *o)
>>   * that has a different "affinity". In practice, it means one range
>>   * per chip.
>>   */
>> -static void powernv_populate_memory_node(void *fdt, int chip_id, hwaddr start,
>> +static void pnv_populate_memory_node(void *fdt, int chip_id, hwaddr start,
>>                                           hwaddr size)
> 
> You may also want to fix indentations like the line above.

yes. I missed that. I should run indent after using sed.

While I am at it, I can also change the name of the routines 
populating the device tree. 

David, 

are you following more or less this pattern :

	<machine>_dt_<device>

Thanks,

C.

Re: [Qemu-devel] [Qemu-ppc] [PATCH] ppc/pnv: change powernv_ prefix to pnv_ for overall naming consistency

Posted by David Gibson 44 weeks ago
On Fri, Dec 15, 2017 at 08:16:57AM +0100, C�dric Le Goater wrote:
> On 12/15/2017 07:43 AM, Alexey Kardashevskiy wrote:
> > On 15/12/17 17:17, C�dric Le Goater wrote:
> >> Signed-off-by: C�dric Le Goater <clg@kaod.org>
> >> ---
> >>  hw/ppc/pnv.c         | 84 ++++++++++++++++++++++++++--------------------------
> >>  hw/ppc/pnv_core.c    |  8 ++---
> >>  hw/ppc/pnv_lpc.c     |  2 +-
> >>  include/hw/ppc/pnv.h |  8 ++---
> >>  4 files changed, 51 insertions(+), 51 deletions(-)
> >>
> >> diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
> >> index c35c439d816b..4bc5f61d0da7 100644
> >> --- a/hw/ppc/pnv.c
> >> +++ b/hw/ppc/pnv.c
> >> @@ -77,7 +77,7 @@ static const char *pnv_chip_core_typename(const PnvChip *o)
> >>   * that has a different "affinity". In practice, it means one range
> >>   * per chip.
> >>   */
> >> -static void powernv_populate_memory_node(void *fdt, int chip_id, hwaddr start,
> >> +static void pnv_populate_memory_node(void *fdt, int chip_id, hwaddr start,
> >>                                           hwaddr size)
> > 
> > You may also want to fix indentations like the line above.
> 
> yes. I missed that. I should run indent after using sed.
> 
> While I am at it, I can also change the name of the routines 
> populating the device tree. 
> 
> David, 
> 
> are you following more or less this pattern :
> 
> 	<machine>_dt_<device>

Well, I'd only really thought about it for pseries, and I'm using
"spapr_dt_whatever()" there rather than "pseries_dt_whatever()".  Plus
that's where I'm intending to head, but I think there are still a fair
few exceptions.

"pnv_dt_whatever()" seems like a good convention for the powernv code,
though.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson