Commit 9f786d03 authored by Bjorn Helgaas's avatar Bjorn Helgaas

arm/PCI: get rid of device resource fixups

Tell the PCI core about host bridge address translation so it can take
care of bus-to-resource conversion for us.

CC: Russell King <linux@arm.linux.org.uk>
Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
parent c04d9e35
...@@ -299,8 +299,8 @@ int __init it8152_pci_setup(int nr, struct pci_sys_data *sys) ...@@ -299,8 +299,8 @@ int __init it8152_pci_setup(int nr, struct pci_sys_data *sys)
goto err1; goto err1;
} }
pci_add_resource(&sys->resources, &it8152_io); pci_add_resource_offset(&sys->resources, &it8152_io, sys->io_offset);
pci_add_resource(&sys->resources, &it8152_mem); pci_add_resource_offset(&sys->resources, &it8152_mem, sys->mem_offset);
if (platform_notify || platform_notify_remove) { if (platform_notify || platform_notify_remove) {
printk(KERN_ERR "PCI: Can't use platform_notify\n"); printk(KERN_ERR "PCI: Can't use platform_notify\n");
......
...@@ -57,13 +57,7 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev, ...@@ -57,13 +57,7 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev,
extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
enum pci_mmap_state mmap_state, int write_combine); enum pci_mmap_state mmap_state, int write_combine);
extern void #define ARCH_HAS_GENERIC_PCI_OFFSETS
pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
struct resource *res);
extern void
pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
struct pci_bus_region *region);
/* /*
* Dummy implementation; always return 0. * Dummy implementation; always return 0.
......
...@@ -293,28 +293,6 @@ static inline int pdev_bad_for_parity(struct pci_dev *dev) ...@@ -293,28 +293,6 @@ static inline int pdev_bad_for_parity(struct pci_dev *dev)
} }
/*
* Adjust the device resources from bus-centric to Linux-centric.
*/
static void __devinit
pdev_fixup_device_resources(struct pci_sys_data *root, struct pci_dev *dev)
{
resource_size_t offset;
int i;
for (i = 0; i < PCI_NUM_RESOURCES; i++) {
if (dev->resource[i].start == 0)
continue;
if (dev->resource[i].flags & IORESOURCE_MEM)
offset = root->mem_offset;
else
offset = root->io_offset;
dev->resource[i].start += offset;
dev->resource[i].end += offset;
}
}
/* /*
* pcibios_fixup_bus - Called after each bus is probed, * pcibios_fixup_bus - Called after each bus is probed,
* but before its children are examined. * but before its children are examined.
...@@ -332,8 +310,6 @@ void pcibios_fixup_bus(struct pci_bus *bus) ...@@ -332,8 +310,6 @@ void pcibios_fixup_bus(struct pci_bus *bus)
list_for_each_entry(dev, &bus->devices, bus_list) { list_for_each_entry(dev, &bus->devices, bus_list) {
u16 status; u16 status;
pdev_fixup_device_resources(root, dev);
pci_read_config_word(dev, PCI_STATUS, &status); pci_read_config_word(dev, PCI_STATUS, &status);
/* /*
...@@ -398,43 +374,6 @@ void pcibios_fixup_bus(struct pci_bus *bus) ...@@ -398,43 +374,6 @@ void pcibios_fixup_bus(struct pci_bus *bus)
EXPORT_SYMBOL(pcibios_fixup_bus); EXPORT_SYMBOL(pcibios_fixup_bus);
#endif #endif
/*
* Convert from Linux-centric to bus-centric addresses for bridge devices.
*/
void
pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
struct resource *res)
{
struct pci_sys_data *root = dev->sysdata;
unsigned long offset = 0;
if (res->flags & IORESOURCE_IO)
offset = root->io_offset;
if (res->flags & IORESOURCE_MEM)
offset = root->mem_offset;
region->start = res->start - offset;
region->end = res->end - offset;
}
EXPORT_SYMBOL(pcibios_resource_to_bus);
void __devinit
pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
struct pci_bus_region *region)
{
struct pci_sys_data *root = dev->sysdata;
unsigned long offset = 0;
if (res->flags & IORESOURCE_IO)
offset = root->io_offset;
if (res->flags & IORESOURCE_MEM)
offset = root->mem_offset;
res->start = region->start + offset;
res->end = region->end + offset;
}
EXPORT_SYMBOL(pcibios_bus_to_resource);
/* /*
* Swizzle the device pin each time we cross a bridge. * Swizzle the device pin each time we cross a bridge.
* This might update pin and returns the slot number. * This might update pin and returns the slot number.
...@@ -496,10 +435,10 @@ static void __init pcibios_init_hw(struct hw_pci *hw) ...@@ -496,10 +435,10 @@ static void __init pcibios_init_hw(struct hw_pci *hw)
if (ret > 0) { if (ret > 0) {
if (list_empty(&sys->resources)) { if (list_empty(&sys->resources)) {
pci_add_resource(&sys->resources, pci_add_resource_offset(&sys->resources,
&ioport_resource); &ioport_resource, sys->io_offset);
pci_add_resource(&sys->resources, pci_add_resource_offset(&sys->resources,
&iomem_resource); &iomem_resource, sys->mem_offset);
} }
sys->bus = hw->scan(nr, sys); sys->bus = hw->scan(nr, sys);
......
...@@ -155,8 +155,8 @@ static int cns3xxx_pci_setup(int nr, struct pci_sys_data *sys) ...@@ -155,8 +155,8 @@ static int cns3xxx_pci_setup(int nr, struct pci_sys_data *sys)
BUG_ON(request_resource(&iomem_resource, res_io) || BUG_ON(request_resource(&iomem_resource, res_io) ||
request_resource(&iomem_resource, res_mem)); request_resource(&iomem_resource, res_mem));
pci_add_resource(&sys->resources, res_io); pci_add_resource_offset(&sys->resources, res_io, sys->io_offset);
pci_add_resource(&sys->resources, res_mem); pci_add_resource_offset(&sys->resources, res_mem, sys->mem_offset);
return 1; return 1;
} }
......
...@@ -69,7 +69,7 @@ static int __init dove_pcie_setup(int nr, struct pci_sys_data *sys) ...@@ -69,7 +69,7 @@ static int __init dove_pcie_setup(int nr, struct pci_sys_data *sys)
pp->res[0].flags = IORESOURCE_IO; pp->res[0].flags = IORESOURCE_IO;
if (request_resource(&ioport_resource, &pp->res[0])) if (request_resource(&ioport_resource, &pp->res[0]))
panic("Request PCIe IO resource failed\n"); panic("Request PCIe IO resource failed\n");
pci_add_resource(&sys->resources, &pp->res[0]); pci_add_resource_offset(&sys->resources, &pp->res[0], sys->io_offset);
/* /*
* IORESOURCE_MEM * IORESOURCE_MEM
...@@ -88,7 +88,7 @@ static int __init dove_pcie_setup(int nr, struct pci_sys_data *sys) ...@@ -88,7 +88,7 @@ static int __init dove_pcie_setup(int nr, struct pci_sys_data *sys)
pp->res[1].flags = IORESOURCE_MEM; pp->res[1].flags = IORESOURCE_MEM;
if (request_resource(&iomem_resource, &pp->res[1])) if (request_resource(&iomem_resource, &pp->res[1]))
panic("Request PCIe Memory resource failed\n"); panic("Request PCIe Memory resource failed\n");
pci_add_resource(&sys->resources, &pp->res[1]); pci_add_resource_offset(&sys->resources, &pp->res[1], sys->mem_offset);
return 1; return 1;
} }
......
...@@ -275,11 +275,13 @@ int __init dc21285_setup(int nr, struct pci_sys_data *sys) ...@@ -275,11 +275,13 @@ int __init dc21285_setup(int nr, struct pci_sys_data *sys)
allocate_resource(&iomem_resource, &res[0], 0x40000000, allocate_resource(&iomem_resource, &res[0], 0x40000000,
0x80000000, 0xffffffff, 0x40000000, NULL, NULL); 0x80000000, 0xffffffff, 0x40000000, NULL, NULL);
pci_add_resource(&sys->resources, &ioport_resource);
pci_add_resource(&sys->resources, &res[0]);
pci_add_resource(&sys->resources, &res[1]);
sys->mem_offset = DC21285_PCI_MEM; sys->mem_offset = DC21285_PCI_MEM;
pci_add_resource_offset(&sys->resources,
&ioport_resource, sys->io_offset);
pci_add_resource_offset(&sys->resources, &res[0], sys->mem_offset);
pci_add_resource_offset(&sys->resources, &res[1], sys->mem_offset);
return 1; return 1;
} }
......
...@@ -378,9 +378,10 @@ static int __init pci_v3_setup_resources(struct pci_sys_data *sys) ...@@ -378,9 +378,10 @@ static int __init pci_v3_setup_resources(struct pci_sys_data *sys)
* the mem resource for this bus * the mem resource for this bus
* the prefetch mem resource for this bus * the prefetch mem resource for this bus
*/ */
pci_add_resource(&sys->resources, &ioport_resource); pci_add_resource_offset(&sys->resources,
pci_add_resource(&sys->resources, &non_mem); &ioport_resource, sys->io_offset);
pci_add_resource(&sys->resources, &pre_mem); pci_add_resource_offset(&sys->resources, &non_mem, sys->mem_offset);
pci_add_resource_offset(&sys->resources, &pre_mem, sys->mem_offset);
return 1; return 1;
} }
......
...@@ -1084,8 +1084,8 @@ int iop13xx_pci_setup(int nr, struct pci_sys_data *sys) ...@@ -1084,8 +1084,8 @@ int iop13xx_pci_setup(int nr, struct pci_sys_data *sys)
request_resource(&ioport_resource, &res[0]); request_resource(&ioport_resource, &res[0]);
request_resource(&iomem_resource, &res[1]); request_resource(&iomem_resource, &res[1]);
pci_add_resource(&sys->resources, &res[0]); pci_add_resource_offset(&sys->resources, &res[0], sys->io_offset);
pci_add_resource(&sys->resources, &res[1]); pci_add_resource_offset(&sys->resources, &res[1], sys->mem_offset);
return 1; return 1;
} }
......
...@@ -243,8 +243,10 @@ int ixp2000_pci_setup(int nr, struct pci_sys_data *sys) ...@@ -243,8 +243,10 @@ int ixp2000_pci_setup(int nr, struct pci_sys_data *sys)
if (nr >= 1) if (nr >= 1)
return 0; return 0;
pci_add_resource(&sys->resources, &ixp2000_pci_io_space); pci_add_resource_offset(&sys->resources,
pci_add_resource(&sys->resources, &ixp2000_pci_mem_space); &ixp2000_pci_io_space, sys->io_offset);
pci_add_resource_offset(&sys->resources,
&ixp2000_pci_mem_space, sys->mem_offset);
return 1; return 1;
} }
......
...@@ -281,8 +281,10 @@ int ixp23xx_pci_setup(int nr, struct pci_sys_data *sys) ...@@ -281,8 +281,10 @@ int ixp23xx_pci_setup(int nr, struct pci_sys_data *sys)
if (nr >= 1) if (nr >= 1)
return 0; return 0;
pci_add_resource(&sys->resources, &ixp23xx_pci_io_space); pci_add_resource_offset(&sys->resources,
pci_add_resource(&sys->resources, &ixp23xx_pci_mem_space); &ixp23xx_pci_io_space, sys->io_offset);
pci_add_resource_offset(&sys->resources,
&ixp23xx_pci_mem_space, sys->mem_offset);
return 1; return 1;
} }
......
...@@ -472,8 +472,8 @@ int ixp4xx_setup(int nr, struct pci_sys_data *sys) ...@@ -472,8 +472,8 @@ int ixp4xx_setup(int nr, struct pci_sys_data *sys)
request_resource(&ioport_resource, &res[0]); request_resource(&ioport_resource, &res[0]);
request_resource(&iomem_resource, &res[1]); request_resource(&iomem_resource, &res[1]);
pci_add_resource(&sys->resources, &res[0]); pci_add_resource_offset(&sys->resources, &res[0], sys->io_offset);
pci_add_resource(&sys->resources, &res[1]); pci_add_resource_offset(&sys->resources, &res[1], sys->mem_offset);
platform_notify = ixp4xx_pci_platform_notify; platform_notify = ixp4xx_pci_platform_notify;
platform_notify_remove = ixp4xx_pci_platform_notify_remove; platform_notify_remove = ixp4xx_pci_platform_notify_remove;
......
...@@ -198,9 +198,9 @@ static int __init kirkwood_pcie_setup(int nr, struct pci_sys_data *sys) ...@@ -198,9 +198,9 @@ static int __init kirkwood_pcie_setup(int nr, struct pci_sys_data *sys)
if (request_resource(&iomem_resource, &pp->res[1])) if (request_resource(&iomem_resource, &pp->res[1]))
panic("Request PCIe%d Memory resource failed\n", index); panic("Request PCIe%d Memory resource failed\n", index);
pci_add_resource(&sys->resources, &pp->res[0]);
pci_add_resource(&sys->resources, &pp->res[1]);
sys->io_offset = 0; sys->io_offset = 0;
pci_add_resource_offset(&sys->resources, &pp->res[0], sys->io_offset);
pci_add_resource_offset(&sys->resources, &pp->res[1], sys->mem_offset);
/* /*
* Generic PCIe unit setup. * Generic PCIe unit setup.
......
...@@ -169,8 +169,8 @@ static int __init ks8695_pci_setup(int nr, struct pci_sys_data *sys) ...@@ -169,8 +169,8 @@ static int __init ks8695_pci_setup(int nr, struct pci_sys_data *sys)
request_resource(&iomem_resource, &pci_mem); request_resource(&iomem_resource, &pci_mem);
request_resource(&ioport_resource, &pci_io); request_resource(&ioport_resource, &pci_io);
pci_add_resource(&sys->resources, &pci_io); pci_add_resource_offset(&sys->resources, &pci_io, sys->io_offset);
pci_add_resource(&sys->resources, &pci_mem); pci_add_resource_offset(&sys->resources, &pci_mem, sys->mem_offset);
/* Assign and enable processor bridge */ /* Assign and enable processor bridge */
ks8695_local_writeconfig(PCI_BASE_ADDRESS_0, KS8695_PCIMEM_PA); ks8695_local_writeconfig(PCI_BASE_ADDRESS_0, KS8695_PCIMEM_PA);
......
...@@ -155,8 +155,8 @@ static int __init mv78xx0_pcie_setup(int nr, struct pci_sys_data *sys) ...@@ -155,8 +155,8 @@ static int __init mv78xx0_pcie_setup(int nr, struct pci_sys_data *sys)
orion_pcie_set_local_bus_nr(pp->base, sys->busnr); orion_pcie_set_local_bus_nr(pp->base, sys->busnr);
orion_pcie_setup(pp->base); orion_pcie_setup(pp->base);
pci_add_resource(&sys->resources, &pp->res[0]); pci_add_resource_offset(&sys->resources, &pp->res[0], sys->io_offset);
pci_add_resource(&sys->resources, &pp->res[1]); pci_add_resource_offset(&sys->resources, &pp->res[1], sys->mem_offset);
return 1; return 1;
} }
......
...@@ -171,13 +171,14 @@ static int __init pcie_setup(struct pci_sys_data *sys) ...@@ -171,13 +171,14 @@ static int __init pcie_setup(struct pci_sys_data *sys)
/* /*
* IORESOURCE_IO * IORESOURCE_IO
*/ */
sys->io_offset = 0;
res[0].name = "PCIe I/O Space"; res[0].name = "PCIe I/O Space";
res[0].flags = IORESOURCE_IO; res[0].flags = IORESOURCE_IO;
res[0].start = ORION5X_PCIE_IO_BUS_BASE; res[0].start = ORION5X_PCIE_IO_BUS_BASE;
res[0].end = res[0].start + ORION5X_PCIE_IO_SIZE - 1; res[0].end = res[0].start + ORION5X_PCIE_IO_SIZE - 1;
if (request_resource(&ioport_resource, &res[0])) if (request_resource(&ioport_resource, &res[0]))
panic("Request PCIe IO resource failed\n"); panic("Request PCIe IO resource failed\n");
pci_add_resource(&sys->resources, &res[0]); pci_add_resource_offset(&sys->resources, &res[0], sys->io_offset);
/* /*
* IORESOURCE_MEM * IORESOURCE_MEM
...@@ -188,9 +189,7 @@ static int __init pcie_setup(struct pci_sys_data *sys) ...@@ -188,9 +189,7 @@ static int __init pcie_setup(struct pci_sys_data *sys)
res[1].end = res[1].start + ORION5X_PCIE_MEM_SIZE - 1; res[1].end = res[1].start + ORION5X_PCIE_MEM_SIZE - 1;
if (request_resource(&iomem_resource, &res[1])) if (request_resource(&iomem_resource, &res[1]))
panic("Request PCIe Memory resource failed\n"); panic("Request PCIe Memory resource failed\n");
pci_add_resource(&sys->resources, &res[1]); pci_add_resource_offset(&sys->resources, &res[1], sys->mem_offset);
sys->io_offset = 0;
return 1; return 1;
} }
...@@ -499,13 +498,14 @@ static int __init pci_setup(struct pci_sys_data *sys) ...@@ -499,13 +498,14 @@ static int __init pci_setup(struct pci_sys_data *sys)
/* /*
* IORESOURCE_IO * IORESOURCE_IO
*/ */
sys->io_offset = 0;
res[0].name = "PCI I/O Space"; res[0].name = "PCI I/O Space";
res[0].flags = IORESOURCE_IO; res[0].flags = IORESOURCE_IO;
res[0].start = ORION5X_PCI_IO_BUS_BASE; res[0].start = ORION5X_PCI_IO_BUS_BASE;
res[0].end = res[0].start + ORION5X_PCI_IO_SIZE - 1; res[0].end = res[0].start + ORION5X_PCI_IO_SIZE - 1;
if (request_resource(&ioport_resource, &res[0])) if (request_resource(&ioport_resource, &res[0]))
panic("Request PCI IO resource failed\n"); panic("Request PCI IO resource failed\n");
pci_add_resource(&sys->resources, &res[0]); pci_add_resource_offset(&sys->resources, &res[0], sys->io_offset);
/* /*
* IORESOURCE_MEM * IORESOURCE_MEM
...@@ -516,9 +516,7 @@ static int __init pci_setup(struct pci_sys_data *sys) ...@@ -516,9 +516,7 @@ static int __init pci_setup(struct pci_sys_data *sys)
res[1].end = res[1].start + ORION5X_PCI_MEM_SIZE - 1; res[1].end = res[1].start + ORION5X_PCI_MEM_SIZE - 1;
if (request_resource(&iomem_resource, &res[1])) if (request_resource(&iomem_resource, &res[1]))
panic("Request PCI Memory resource failed\n"); panic("Request PCI Memory resource failed\n");
pci_add_resource(&sys->resources, &res[1]); pci_add_resource_offset(&sys->resources, &res[1], sys->mem_offset);
sys->io_offset = 0;
return 1; return 1;
} }
......
...@@ -244,9 +244,11 @@ static int __init pci_nanoengine_setup_resources(struct pci_sys_data *sys) ...@@ -244,9 +244,11 @@ static int __init pci_nanoengine_setup_resources(struct pci_sys_data *sys)
printk(KERN_ERR "PCI: unable to allocate prefetchable\n"); printk(KERN_ERR "PCI: unable to allocate prefetchable\n");
return -EBUSY; return -EBUSY;
} }
pci_add_resource(&sys->resources, &pci_io_ports); pci_add_resource_offset(&sys->resources, &pci_io_ports, sys->io_offset);
pci_add_resource(&sys->resources, &pci_non_prefetchable_memory); pci_add_resource_offset(&sys->resources,
pci_add_resource(&sys->resources, &pci_prefetchable_memory); &pci_non_prefetchable_memory, sys->mem_offset);
pci_add_resource_offset(&sys->resources,
&pci_prefetchable_memory, sys->mem_offset);
return 1; return 1;
} }
......
...@@ -408,7 +408,7 @@ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys) ...@@ -408,7 +408,7 @@ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys)
pp->res[0].flags = IORESOURCE_IO; pp->res[0].flags = IORESOURCE_IO;
if (request_resource(&ioport_resource, &pp->res[0])) if (request_resource(&ioport_resource, &pp->res[0]))
panic("Request PCIe IO resource failed\n"); panic("Request PCIe IO resource failed\n");
pci_add_resource(&sys->resources, &pp->res[0]); pci_add_resource_offset(&sys->resources, &pp->res[0], sys->io_offset);
/* /*
* IORESOURCE_MEM * IORESOURCE_MEM
...@@ -427,7 +427,7 @@ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys) ...@@ -427,7 +427,7 @@ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys)
pp->res[1].flags = IORESOURCE_MEM; pp->res[1].flags = IORESOURCE_MEM;
if (request_resource(&iomem_resource, &pp->res[1])) if (request_resource(&iomem_resource, &pp->res[1]))
panic("Request PCIe Memory resource failed\n"); panic("Request PCIe Memory resource failed\n");
pci_add_resource(&sys->resources, &pp->res[1]); pci_add_resource_offset(&sys->resources, &pp->res[1], sys->mem_offset);
/* /*
* IORESOURCE_MEM | IORESOURCE_PREFETCH * IORESOURCE_MEM | IORESOURCE_PREFETCH
...@@ -446,7 +446,7 @@ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys) ...@@ -446,7 +446,7 @@ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys)
pp->res[2].flags = IORESOURCE_MEM | IORESOURCE_PREFETCH; pp->res[2].flags = IORESOURCE_MEM | IORESOURCE_PREFETCH;
if (request_resource(&iomem_resource, &pp->res[2])) if (request_resource(&iomem_resource, &pp->res[2]))
panic("Request PCIe Prefetch Memory resource failed\n"); panic("Request PCIe Prefetch Memory resource failed\n");
pci_add_resource(&sys->resources, &pp->res[2]); pci_add_resource_offset(&sys->resources, &pp->res[2], sys->mem_offset);
return 1; return 1;
} }
......
...@@ -219,9 +219,9 @@ static int __init pci_versatile_setup_resources(struct list_head *resources) ...@@ -219,9 +219,9 @@ static int __init pci_versatile_setup_resources(struct list_head *resources)
* the mem resource for this bus * the mem resource for this bus
* the prefetch mem resource for this bus * the prefetch mem resource for this bus
*/ */
pci_add_resource(resources, &io_mem); pci_add_resource_offset(resources, &io_mem, sys->io_offset);
pci_add_resource(resources, &non_mem); pci_add_resource_offset(resources, &non_mem, sys->mem_offset);
pci_add_resource(resources, &pre_mem); pci_add_resource_offset(resources, &pre_mem, sys->mem_offset);
goto out; goto out;
......
...@@ -215,8 +215,8 @@ int iop3xx_pci_setup(int nr, struct pci_sys_data *sys) ...@@ -215,8 +215,8 @@ int iop3xx_pci_setup(int nr, struct pci_sys_data *sys)
sys->mem_offset = IOP3XX_PCI_LOWER_MEM_PA - *IOP3XX_OMWTVR0; sys->mem_offset = IOP3XX_PCI_LOWER_MEM_PA - *IOP3XX_OMWTVR0;
sys->io_offset = IOP3XX_PCI_LOWER_IO_PA - *IOP3XX_OIOWTVR; sys->io_offset = IOP3XX_PCI_LOWER_IO_PA - *IOP3XX_OIOWTVR;
pci_add_resource(&sys->resources, &res[0]); pci_add_resource_offset(&sys->resources, &res[0], sys->io_offset);
pci_add_resource(&sys->resources, &res[1]); pci_add_resource_offset(&sys->resources, &res[1], sys->mem_offset);
return 1; return 1;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment