Exemplo n.º 1
0
static int get_pcie_bar(struct udevice *dev, u32 *base, u32 *len)
{
	u32 pciexbar_reg;

	*base = 0;
	*len = 0;

	dm_pci_read_config32(dev, PCIEXBAR, &pciexbar_reg);

	if (!(pciexbar_reg & (1 << 0)))
		return 0;

	switch ((pciexbar_reg >> 1) & 3) {
	case 0: /* 256MB */
		*base = pciexbar_reg & ((1 << 31) | (1 << 30) | (1 << 29) |
				(1 << 28));
		*len = 256 * 1024 * 1024;
		return 1;
	case 1: /* 128M */
		*base = pciexbar_reg & ((1 << 31) | (1 << 30) | (1 << 29) |
				(1 << 28) | (1 << 27));
		*len = 128 * 1024 * 1024;
		return 1;
	case 2: /* 64M */
		*base = pciexbar_reg & ((1 << 31) | (1 << 30) | (1 << 29) |
				(1 << 28) | (1 << 27) | (1 << 26));
		*len = 64 * 1024 * 1024;
		return 1;
	}

	return 0;
}
Exemplo n.º 2
0
static int rtl8169_eth_probe(struct udevice *dev)
{
	struct pci_child_platdata *pplat = dev_get_parent_platdata(dev);
	struct rtl8169_private *priv = dev_get_priv(dev);
	struct eth_pdata *plat = dev_get_platdata(dev);
	u32 iobase;
	int region;
	int ret;

	debug("rtl8169: REALTEK RTL8169 @0x%x\n", iobase);
	switch (pplat->device) {
	case 0x8168:
		region = 2;
		break;
	default:
		region = 1;
		break;
	}
	dm_pci_read_config32(dev, PCI_BASE_ADDRESS_0 + region * 4, &iobase);
	iobase &= ~0xf;
	priv->iobase = (int)dm_pci_mem_to_phys(dev, iobase);

	ret = rtl_init(priv->iobase, dev->name, plat->enetaddr);
	if (ret < 0) {
		printf(pr_fmt("failed to initialize card: %d\n"), ret);
		return ret;
	}

	return 0;
}
Exemplo n.º 3
0
static int pch7_get_gpio_base(struct udevice *dev, u32 *gbasep)
{
	u32 base;

	/*
	 * GPIO_BASE moved to its current offset with ICH6, but prior to
	 * that it was unused (or undocumented). Check that it looks
	 * okay: not all ones or zeros.
	 *
	 * Note we don't need check bit0 here, because the Tunnel Creek
	 * GPIO base address register bit0 is reserved (read returns 0),
	 * while on the Ivybridge the bit0 is used to indicate it is an
	 * I/O space.
	 */
	dm_pci_read_config32(dev, GPIO_BASE, &base);
	if (base == 0x00000000 || base == 0xffffffff) {
		debug("%s: unexpected BASE value\n", __func__);
		return -ENODEV;
	}

	/*
	 * Okay, I guess we're looking at the right device. The actual
	 * GPIO registers are in the PCI device's I/O space, starting
	 * at the offset that we just read. Bit 0 indicates that it's
	 * an I/O address, not a memory address, so mask that off.
	 */
	*gbasep = base & 1 ? base & ~3 : base & ~15;

	return 0;
}
Exemplo n.º 4
0
Arquivo: me.c Projeto: 01hyang/u-boot
static inline void me_read_dword_ptr(struct udevice *dev, void *ptr, int offset)
{
	u32 dword;

	dm_pci_read_config32(dev, offset, &dword);
	memcpy(ptr, &dword, sizeof(dword));
}
Exemplo n.º 5
0
static int bd82x6x_northbridge_early_init(struct udevice *dev)
{
	const int chipset_type = SANDYBRIDGE_MOBILE;
	u32 capid0_a;
	u8 reg8;

	/* Device ID Override Enable should be done very early */
	dm_pci_read_config32(dev, 0xe4, &capid0_a);
	if (capid0_a & (1 << 10)) {
		dm_pci_read_config8(dev, 0xf3, &reg8);
		reg8 &= ~7; /* Clear 2:0 */

		if (chipset_type == SANDYBRIDGE_MOBILE)
			reg8 |= 1; /* Set bit 0 */

		dm_pci_write_config8(dev, 0xf3, reg8);
	}

	sandybridge_setup_northbridge_bars(dev);

	/* Device Enable */
	dm_pci_write_config32(dev, DEVEN, DEVEN_HOST | DEVEN_IGD);

	return 0;
}
Exemplo n.º 6
0
static int pch9_get_spi_base(struct udevice *dev, ulong *sbasep)
{
	uint32_t sbase_addr;

	dm_pci_read_config32(dev, SBASE_ADDR, &sbase_addr);
	*sbasep = sbase_addr & 0xfffffe00;

	return 0;
}
Exemplo n.º 7
0
static inline u32 sir_read(struct udevice *dev, int idx)
{
	u32 data;

	dm_pci_write_config32(dev, SATA_SIRI, idx);
	dm_pci_read_config32(dev, SATA_SIRD, &data);

	return data;
}
Exemplo n.º 8
0
static int pch7_get_spi_base(struct udevice *dev, ulong *sbasep)
{
	u32 rcba;

	dm_pci_read_config32(dev, PCH_RCBA, &rcba);
	/* Bits 31-14 are the base address, 13-1 are reserved, 0 is enable */
	rcba = rcba & 0xffffc000;
	*sbasep = rcba + 0x3020;

	return 0;
}
Exemplo n.º 9
0
static int pch9_get_io_base(struct udevice *dev, u32 *iobasep)
{
	u32 base;

	dm_pci_read_config32(dev, IO_BASE, &base);
	if (base == 0x00000000 || base == 0xffffffff) {
		debug("%s: unexpected BASE value\n", __func__);
		return -ENODEV;
	}

	*iobasep = base & 1 ? base & ~3 : base & ~15;

	return 0;
}
Exemplo n.º 10
0
static unsigned long get_top_of_ram(struct udevice *dev)
{
	/*
	 * Base of DPR is top of usable DRAM below 4GiB. The register has
	 * 1 MiB alignment and reports the TOP of the range, the base
	 * must be calculated from the size in MiB in bits 11:4.
	 */
	u32 dpr, tom;

	dm_pci_read_config32(dev, DPR, &dpr);
	tom = dpr & ~((1 << 20) - 1);

	debug("dpt %08x tom %08x\n", dpr, tom);
	/* Subtract DMA Protected Range size if enabled */
	if (dpr & DPR_EPM)
		tom -= (dpr & DPR_SIZE_MASK) << 16;

	return (unsigned long)tom;
}
Exemplo n.º 11
0
/**
 * sandybridge_init_iommu() - Set up IOMMU so that azalia can be used
 *
 * It is not obvious where these values come from. They may be undocumented.
 */
static void sandybridge_init_iommu(struct udevice *dev)
{
	u32 capid0_a;

	dm_pci_read_config32(dev, 0xe4, &capid0_a);
	if (capid0_a & (1 << 23)) {
		log_debug("capid0_a not needed\n");
		return;
	}

	/* setup BARs */
	writel(IOMMU_BASE1 >> 32, MCHBAR_REG(0x5404));
	writel(IOMMU_BASE1 | 1, MCHBAR_REG(0x5400));
	writel(IOMMU_BASE2 >> 32, MCHBAR_REG(0x5414));
	writel(IOMMU_BASE2 | 1, MCHBAR_REG(0x5410));

	/* lock policies */
	writel(0x80000000, IOMMU_BASE1 + 0xff0);

	/* Enable azalia sound */
	writel(0x20000000, IOMMU_BASE2 + 0xff0);
	writel(0xa0000000, IOMMU_BASE2 + 0xff0);
}
Exemplo n.º 12
0
Arquivo: me.c Projeto: 01hyang/u-boot
int intel_me_hsio_version(struct udevice *dev, uint16_t *versionp,
			  uint16_t *checksump)
{
	int count;
	u32 hsiover;
	struct me_hfs hfs;

	/* Query for HSIO version, overloads H_GS and HFS */
	dm_pci_write_config32(dev, PCI_ME_H_GS,
			      ME_HSIO_MESSAGE | ME_HSIO_CMD_GETHSIOVER);

	/* Must wait for ME acknowledgement */
	for (count = ME_RETRY; count > 0; --count) {
		me_read_dword_ptr(dev, &hfs, PCI_ME_HFS);
		if (hfs.bios_msg_ack)
			break;
		udelay(ME_DELAY);
	}
	if (!count) {
		debug("ERROR: ME failed to respond\n");
		return -ETIMEDOUT;
	}

	/* HSIO version should be in HFS_5 */
	dm_pci_read_config32(dev, PCI_ME_HFS5, &hsiover);
	*versionp = hsiover >> 16;
	*checksump = hsiover & 0xffff;

	debug("ME: HSIO Version            : %d (CRC 0x%04x)\n",
	      *versionp, *checksump);

	/* Reset registers to normal behavior */
	dm_pci_write_config32(dev, PCI_ME_H_GS,
			      ME_HSIO_MESSAGE | ME_HSIO_CMD_GETHSIOVER);

	return 0;
}
Exemplo n.º 13
0
static void xhci_pci_init(struct udevice *dev, struct xhci_hccr **ret_hccr,
			  struct xhci_hcor **ret_hcor)
{
	struct xhci_hccr *hccr;
	struct xhci_hcor *hcor;
	u32 cmd;

	hccr = (struct xhci_hccr *)dm_pci_map_bar(dev,
			PCI_BASE_ADDRESS_0, PCI_REGION_MEM);
	hcor = (struct xhci_hcor *)((uintptr_t) hccr +
			HC_LENGTH(xhci_readl(&hccr->cr_capbase)));

	debug("XHCI-PCI init hccr 0x%x and hcor 0x%x hc_length %d\n",
	      (u32)hccr, (u32)hcor,
	      (u32)HC_LENGTH(xhci_readl(&hccr->cr_capbase)));

	*ret_hccr = hccr;
	*ret_hcor = hcor;

	/* enable busmaster */
	dm_pci_read_config32(dev, PCI_COMMAND, &cmd);
	cmd |= PCI_COMMAND_MASTER;
	dm_pci_write_config32(dev, PCI_COMMAND, cmd);
}
Exemplo n.º 14
0
int pci_bar_show(struct udevice *dev)
{
	u8 header_type;
	int bar_cnt, bar_id, mem_type;
	bool is_64, is_io;
	u32 base_low, base_high;
	u32 size_low, size_high;
	u64 base, size;
	u32 reg_addr;
	int prefetchable;

	dm_pci_read_config8(dev, PCI_HEADER_TYPE, &header_type);

	if (header_type == PCI_HEADER_TYPE_CARDBUS) {
		printf("CardBus doesn't support BARs\n");
		return -ENOSYS;
	}

	bar_cnt = (header_type == PCI_HEADER_TYPE_NORMAL) ? 6 : 2;

	printf("ID   Base                Size                Width  Type\n");
	printf("----------------------------------------------------------\n");

	bar_id = 0;
	reg_addr = PCI_BASE_ADDRESS_0;
	while (bar_cnt) {
		dm_pci_read_config32(dev, reg_addr, &base_low);
		dm_pci_write_config32(dev, reg_addr, 0xffffffff);
		dm_pci_read_config32(dev, reg_addr, &size_low);
		dm_pci_write_config32(dev, reg_addr, base_low);
		reg_addr += 4;

		base = base_low & ~0xf;
		size = size_low & ~0xf;
		base_high = 0x0;
		size_high = 0xffffffff;
		is_64 = 0;
		prefetchable = base_low & PCI_BASE_ADDRESS_MEM_PREFETCH;
		is_io = base_low & PCI_BASE_ADDRESS_SPACE_IO;
		mem_type = base_low & PCI_BASE_ADDRESS_MEM_TYPE_MASK;

		if (mem_type == PCI_BASE_ADDRESS_MEM_TYPE_64) {
			dm_pci_read_config32(dev, reg_addr, &base_high);
			dm_pci_write_config32(dev, reg_addr, 0xffffffff);
			dm_pci_read_config32(dev, reg_addr, &size_high);
			dm_pci_write_config32(dev, reg_addr, base_high);
			bar_cnt--;
			reg_addr += 4;
			is_64 = 1;
		}

		base = base | ((u64)base_high << 32);
		size = size | ((u64)size_high << 32);

		if ((!is_64 && size_low) || (is_64 && size)) {
			size = ~size + 1;
			printf(" %d   %#016llx  %#016llx  %d     %s   %s\n",
			       bar_id, (unsigned long long)base,
			       (unsigned long long)size, is_64 ? 64 : 32,
			       is_io ? "I/O" : "MEM",
			       prefetchable ? "Prefetchable" : "");
		}

		bar_id++;
		bar_cnt--;
	}

	return 0;
}
Exemplo n.º 15
0
/**
 * sdram_find() - Find available memory
 *
 * This is a bit complicated since on x86 there are system memory holes all
 * over the place. We create a list of available memory blocks
 *
 * @dev:	Northbridge device
 */
static int sdram_find(struct udevice *dev)
{
	struct memory_info *info = &gd->arch.meminfo;
	uint32_t tseg_base, uma_size, tolud;
	uint64_t tom, me_base, touud;
	uint64_t uma_memory_base = 0;
	uint64_t uma_memory_size;
	unsigned long long tomk;
	uint16_t ggc;
	u32 val;

	/* Total Memory 2GB example:
	 *
	 *  00000000  0000MB-1992MB  1992MB  RAM     (writeback)
	 *  7c800000  1992MB-2000MB     8MB  TSEG    (SMRR)
	 *  7d000000  2000MB-2002MB     2MB  GFX GTT (uncached)
	 *  7d200000  2002MB-2034MB    32MB  GFX UMA (uncached)
	 *  7f200000   2034MB TOLUD
	 *  7f800000   2040MB MEBASE
	 *  7f800000  2040MB-2048MB     8MB  ME UMA  (uncached)
	 *  80000000   2048MB TOM
	 * 100000000  4096MB-4102MB     6MB  RAM     (writeback)
	 *
	 * Total Memory 4GB example:
	 *
	 *  00000000  0000MB-2768MB  2768MB  RAM     (writeback)
	 *  ad000000  2768MB-2776MB     8MB  TSEG    (SMRR)
	 *  ad800000  2776MB-2778MB     2MB  GFX GTT (uncached)
	 *  ada00000  2778MB-2810MB    32MB  GFX UMA (uncached)
	 *  afa00000   2810MB TOLUD
	 *  ff800000   4088MB MEBASE
	 *  ff800000  4088MB-4096MB     8MB  ME UMA  (uncached)
	 * 100000000   4096MB TOM
	 * 100000000  4096MB-5374MB  1278MB  RAM     (writeback)
	 * 14fe00000   5368MB TOUUD
	 */

	/* Top of Upper Usable DRAM, including remap */
	dm_pci_read_config32(dev, TOUUD + 4, &val);
	touud = (uint64_t)val << 32;
	dm_pci_read_config32(dev, TOUUD, &val);
	touud |= val;

	/* Top of Lower Usable DRAM */
	dm_pci_read_config32(dev, TOLUD, &tolud);

	/* Top of Memory - does not account for any UMA */
	dm_pci_read_config32(dev, 0xa4, &val);
	tom = (uint64_t)val << 32;
	dm_pci_read_config32(dev, 0xa0, &val);
	tom |= val;

	debug("TOUUD %llx TOLUD %08x TOM %llx\n", touud, tolud, tom);

	/* ME UMA needs excluding if total memory <4GB */
	dm_pci_read_config32(dev, 0x74, &val);
	me_base = (uint64_t)val << 32;
	dm_pci_read_config32(dev, 0x70, &val);
	me_base |= val;

	debug("MEBASE %llx\n", me_base);

	/* TODO: Get rid of all this shifting by 10 bits */
	tomk = tolud >> 10;
	if (me_base == tolud) {
		/* ME is from MEBASE-TOM */
		uma_size = (tom - me_base) >> 10;
		/* Increment TOLUD to account for ME as RAM */
		tolud += uma_size << 10;
		/* UMA starts at old TOLUD */
		uma_memory_base = tomk * 1024ULL;
		uma_memory_size = uma_size * 1024ULL;
		debug("ME UMA base %llx size %uM\n", me_base, uma_size >> 10);
	}
Exemplo n.º 16
0
void dm_pciauto_setup_device(struct udevice *dev, int bars_num,
			     struct pci_region *mem,
			     struct pci_region *prefetch, struct pci_region *io,
			     bool enum_only)
{
	u32 bar_response;
	pci_size_t bar_size;
	u16 cmdstat = 0;
	int bar, bar_nr = 0;
	u8 header_type;
	int rom_addr;
	pci_addr_t bar_value;
	struct pci_region *bar_res;
	int found_mem64 = 0;
	u16 class;

	dm_pci_read_config16(dev, PCI_COMMAND, &cmdstat);
	cmdstat = (cmdstat & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) |
			PCI_COMMAND_MASTER;

	for (bar = PCI_BASE_ADDRESS_0;
	     bar < PCI_BASE_ADDRESS_0 + (bars_num * 4); bar += 4) {
		/* Tickle the BAR and get the response */
		if (!enum_only)
			dm_pci_write_config32(dev, bar, 0xffffffff);
		dm_pci_read_config32(dev, bar, &bar_response);

		/* If BAR is not implemented go to the next BAR */
		if (!bar_response)
			continue;

		found_mem64 = 0;

		/* Check the BAR type and set our address mask */
		if (bar_response & PCI_BASE_ADDRESS_SPACE) {
			bar_size = ((~(bar_response & PCI_BASE_ADDRESS_IO_MASK))
				   & 0xffff) + 1;
			if (!enum_only)
				bar_res = io;

			debug("PCI Autoconfig: BAR %d, I/O, size=0x%llx, ",
			      bar_nr, (unsigned long long)bar_size);
		} else {
			if ((bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
			     PCI_BASE_ADDRESS_MEM_TYPE_64) {
				u32 bar_response_upper;
				u64 bar64;

				if (!enum_only) {
					dm_pci_write_config32(dev, bar + 4,
							      0xffffffff);
				}
				dm_pci_read_config32(dev, bar + 4,
						     &bar_response_upper);

				bar64 = ((u64)bar_response_upper << 32) |
						bar_response;

				bar_size = ~(bar64 & PCI_BASE_ADDRESS_MEM_MASK)
						+ 1;
				if (!enum_only)
					found_mem64 = 1;
			} else {
				bar_size = (u32)(~(bar_response &
						PCI_BASE_ADDRESS_MEM_MASK) + 1);
			}
			if (!enum_only) {
				if (prefetch && (bar_response &
					    PCI_BASE_ADDRESS_MEM_PREFETCH)) {
					bar_res = prefetch;
				} else {
					bar_res = mem;
				}
			}

			debug("PCI Autoconfig: BAR %d, %s, size=0x%llx, ",
			      bar_nr, bar_res == prefetch ? "Prf" : "Mem",
			      (unsigned long long)bar_size);
		}

		if (!enum_only && pciauto_region_allocate(bar_res, bar_size,
							  &bar_value) == 0) {
			/* Write it out and update our limit */
			dm_pci_write_config32(dev, bar, (u32)bar_value);

			if (found_mem64) {
				bar += 4;
#ifdef CONFIG_SYS_PCI_64BIT
				dm_pci_write_config32(dev, bar,
						      (u32)(bar_value >> 32));
#else
				/*
				 * If we are a 64-bit decoder then increment to
				 * the upper 32 bits of the bar and force it to
				 * locate in the lower 4GB of memory.
				 */
				dm_pci_write_config32(dev, bar, 0x00000000);
#endif
			}
		}

		cmdstat |= (bar_response & PCI_BASE_ADDRESS_SPACE) ?
			PCI_COMMAND_IO : PCI_COMMAND_MEMORY;

		debug("\n");

		bar_nr++;
	}
Exemplo n.º 17
0
static int create_pirq_routing_table(struct udevice *dev)
{
	struct irq_router *priv = dev_get_priv(dev);
	const void *blob = gd->fdt_blob;
	int node;
	int len, count;
	const u32 *cell;
	struct irq_routing_table *rt;
	struct irq_info *slot, *slot_base;
	int irq_entries = 0;
	int i;
	int ret;

	node = dev->of_offset;

	/* extract the bdf from fdt_pci_addr */
	priv->bdf = dm_pci_get_bdf(dev->parent);

	ret = fdt_stringlist_search(blob, node, "intel,pirq-config", "pci");
	if (!ret) {
		priv->config = PIRQ_VIA_PCI;
	} else {
		ret = fdt_stringlist_search(blob, node, "intel,pirq-config",
					    "ibase");
		if (!ret)
			priv->config = PIRQ_VIA_IBASE;
		else
			return -EINVAL;
	}

	ret = fdtdec_get_int(blob, node, "intel,pirq-link", -1);
	if (ret == -1)
		return ret;
	priv->link_base = ret;

	priv->irq_mask = fdtdec_get_int(blob, node,
					"intel,pirq-mask", PIRQ_BITMAP);

	if (IS_ENABLED(CONFIG_GENERATE_ACPI_TABLE)) {
		/* Reserve IRQ9 for SCI */
		priv->irq_mask &= ~(1 << 9);
	}

	if (priv->config == PIRQ_VIA_IBASE) {
		int ibase_off;

		ibase_off = fdtdec_get_int(blob, node, "intel,ibase-offset", 0);
		if (!ibase_off)
			return -EINVAL;

		/*
		 * Here we assume that the IBASE register has already been
		 * properly configured by U-Boot before.
		 *
		 * By 'valid' we mean:
		 *   1) a valid memory space carved within system memory space
		 *      assigned to IBASE register block.
		 *   2) memory range decoding is enabled.
		 * Hence we don't do any santify test here.
		 */
		dm_pci_read_config32(dev->parent, ibase_off, &priv->ibase);
		priv->ibase &= ~0xf;
	}

	priv->actl_8bit = fdtdec_get_bool(blob, node, "intel,actl-8bit");
	priv->actl_addr = fdtdec_get_int(blob, node, "intel,actl-addr", 0);

	cell = fdt_getprop(blob, node, "intel,pirq-routing", &len);
	if (!cell || len % sizeof(struct pirq_routing))
		return -EINVAL;
	count = len / sizeof(struct pirq_routing);

	rt = calloc(1, sizeof(struct irq_routing_table));
	if (!rt)
		return -ENOMEM;

	/* Populate the PIRQ table fields */
	rt->signature = PIRQ_SIGNATURE;
	rt->version = PIRQ_VERSION;
	rt->rtr_bus = PCI_BUS(priv->bdf);
	rt->rtr_devfn = (PCI_DEV(priv->bdf) << 3) | PCI_FUNC(priv->bdf);
	rt->rtr_vendor = PCI_VENDOR_ID_INTEL;
	rt->rtr_device = PCI_DEVICE_ID_INTEL_ICH7_31;

	slot_base = rt->slots;

	/* Now fill in the irq_info entries in the PIRQ table */
	for (i = 0; i < count;
	     i++, cell += sizeof(struct pirq_routing) / sizeof(u32)) {
		struct pirq_routing pr;

		pr.bdf = fdt_addr_to_cpu(cell[0]);
		pr.pin = fdt_addr_to_cpu(cell[1]);
		pr.pirq = fdt_addr_to_cpu(cell[2]);

		debug("irq_info %d: b.d.f %x.%x.%x INT%c PIRQ%c\n",
		      i, PCI_BUS(pr.bdf), PCI_DEV(pr.bdf),
		      PCI_FUNC(pr.bdf), 'A' + pr.pin - 1,
		      'A' + pr.pirq);

		slot = check_dup_entry(slot_base, irq_entries,
				       PCI_BUS(pr.bdf), PCI_DEV(pr.bdf));
		if (slot) {
			debug("found entry for bus %d device %d, ",
			      PCI_BUS(pr.bdf), PCI_DEV(pr.bdf));

			if (slot->irq[pr.pin - 1].link) {
				debug("skipping\n");

				/*
				 * Sanity test on the routed PIRQ pin
				 *
				 * If they don't match, show a warning to tell
				 * there might be something wrong with the PIRQ
				 * routing information in the device tree.
				 */
				if (slot->irq[pr.pin - 1].link !=
					LINK_N2V(pr.pirq, priv->link_base))
					debug("WARNING: Inconsistent PIRQ routing information\n");
				continue;
			}
		} else {
			slot = slot_base + irq_entries++;
		}
		debug("writing INT%c\n", 'A' + pr.pin - 1);
		fill_irq_info(priv, slot, PCI_BUS(pr.bdf), PCI_DEV(pr.bdf),
			      pr.pin, pr.pirq);
	}

	rt->size = irq_entries * sizeof(struct irq_info) + 32;

	/* Fix up the table checksum */
	rt->checksum = table_compute_checksum(rt, rt->size);

	pirq_routing_table = rt;

	return 0;
}