Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
20 years ago

kernel bug in page mapping

lwbuss had found a page mapping bug in the kernel 2.6.11 and newer. Best thanks to lwbuss.

please check if the patches work for you,

Index: include/asm-nios2nommu/io.h
===================================================================
--- include/asm-nios2nommu/io.h    (revision 9)
+++ include/asm-nios2nommu/io.h    (working copy)
@@ -225,3 +225,3 @@
 /* Pages to physical address... */
-#define page_to_phys(page)      ((page - mem_map) << PAGE_SHIFT)
-#define page_to_bus(page)       ((page - mem_map) << PAGE_SHIFT)
+#define page_to_phys(page)      __pa(page_to_virt(page))
+#define page_to_bus(page)       __pa(page_to_virt(page))

ps, use "-l" option in patch command to ignore white space, or better do it by hand.

2 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Here are the patches from lwbuss.

    I think the previous patch in post#1 is enough.

    They do the same things.

    diff -Nru orig/linux-2.6.16.2/arch/nios2nommu/drivers/pci/altpci.c current/linux-2.6.16.2/arch/nios2nommu/drivers/pci/altpci.c
    --- orig/linux-2.6.16.2/arch/nios2nommu/drivers/pci/altpci.c 2006-04-28 10:23:20.000000000 -0600
    +++ current/linux-2.6.16.2/arch/nios2nommu/drivers/pci/altpci.c 2006-04-26 14:57:43.000000000 -0600
    @@ -43,7 +43,7 @@# define ALT_PCI_IO_BASE (pciio)# define ALT_PCI_IO_SIZE 0x100000# define ALT_PCI_MEMORY_BASE (pcimm)
    -#define ALT_PCI_MEM_SIZE 0x100000
    +#define ALT_PCI_MEM_SIZE 0x200000
    /*
    * Functions for accessing PCI configuration space with type 1 accesses
    diff -Nru orig/linux-2.6.16.2/arch/nios2nommu/mm/dma-noncoherent.c current/linux-2.6.16.2/arch/nios2nommu/mm/dma-noncoherent.c
    --- orig/linux-2.6.16.2/arch/nios2nommu/mm/dma-noncoherent.c 2006-04-28 10:23:20.000000000 -0600
    +++ current/linux-2.6.16.2/arch/nios2nommu/mm/dma-noncoherent.c 2006-04-28 10:22:11.000000000 -0600
    @@ -140,7 +140,9 @@
    addr = (unsigned long) page_address(sg->page);
    if (addr) {
    __dma_sync(addr + sg->offset, sg->length, direction);
    - sg->dma_address = (dma_addr_t)page_to_phys(sg->page)
    + //sg->dma_address = (dma_addr_t)page_to_phys(sg->page)
    + // + sg->offset;
    + sg->dma_address = (dma_addr_t)page_address(sg->page)
    + sg->offset;
    }
    }
    @@ -160,7 +162,13 @@
    addr = (unsigned long) page_address(page) + offset;
    dma_cache_wback_inv(addr, size);
    - return page_to_phys(page) + offset;
    + printk("page= 0x%08x\taddr=0x%08lx\tmap_page=0x%08x\n",
    + page,
    + addr,
    + page_to_phys(page) + offset);
    +
    +// return page_to_phys(page) + offset;
    + return (dma_addr_t)addr;
    }
    EXPORT_SYMBOL(dma_map_page);
    diff -Nru orig/linux-2.6.16.2/drivers/i2c/algos/i2c-algo-oc.c current/linux-2.6.16.2/drivers/i2c/algos/i2c-algo-oc.c
    --- orig/linux-2.6.16.2/drivers/i2c/algos/i2c-algo-oc.c 2006-04-28 10:23:20.000000000 -0600
    +++ current/linux-2.6.16.2/drivers/i2c/algos/i2c-algo-oc.c 2006-04-25 14:40:14.000000000 -0600
    @@ -371,8 +371,8 @@
    /* -----exported algorithm data: ------------------------------------- */
    static struct i2c_algorithm oc_algo = {
    - .name = "Opencores algorithm",
    - .id = I2C_ALGO_OC,
    +// .name = "Opencores algorithm",
    +// .id = I2C_ALGO_OC,
    .master_xfer = oc_xfer,
    .functionality = oc_func,
    };
    @@ -382,13 +382,13 @@
    */
    int i2c_oc_add_bus(struct i2c_adapter *adap)
    {
    - struct i2c_algo_oc_data *oc_adap = adap->algo_data;
    + //struct i2c_algo_oc_data *oc_adap = adap->algo_data;
    DEB2(dev_dbg(&adap->dev, "hw routines registered.\n")wink.gif
    /* register new adapter to i2c module... */
    - adap->id |= oc_algo.id;
    + //adap->id |= oc_algo.id;
    adap->algo = &oc_algo;
    adap->timeout = 100; /* default values, should */
    diff -Nru orig/linux-2.6.16.2/drivers/i2c/busses/i2c-oc.c current/linux-2.6.16.2/drivers/i2c/busses/i2c-oc.c
    --- orig/linux-2.6.16.2/drivers/i2c/busses/i2c-oc.c 2006-04-28 10:23:20.000000000 -0600
    +++ current/linux-2.6.16.2/drivers/i2c/busses/i2c-oc.c 2006-04-25 14:44:45.000000000 -0600
    @@ -46,16 +46,20 @@
    static int base0 = 0;
    static int irq0 = 0;
    static int clock0 = 0;
    +#ifdef na_i2c_1
    static int base1 = 0;
    static int irq1 = 0;
    static int clock1 = 0;
    +#endif
    module_param(base0, int, 0);
    module_param(irq0, int, 0);
    module_param(clock0, int, 0);
    +#ifdef na_i2c_1
    module_param(base1, int, 0);
    module_param(irq1, int, 0);
    module_param(clock1, int, 0);
    +#endif
    static void oci2c_setreg (struct iic_oc_hw *hw, int regno, int val)
    {
    @@ -166,11 +170,13 @@
    .clock = nasys_clock_freq_1000,
    };
    +#ifdef na_i2c_1
    static struct iic_oc_hw oc_hw_1 = {
    .base = na_i2c_1,
    .irq = na_i2c_1_irq,
    .clock = nasys_clock_freq_1000,
    };
    +#endif
    static struct i2c_algo_oc_data oc_data_0 = {
    .hw = &oc_hw_0,
    @@ -182,6 +188,7 @@
    .timeout = 100,
    };
    +#ifdef na_i2c_1
    static struct i2c_algo_oc_data oc_data_1 = {
    .hw = &oc_hw_1,
    .setreg = oci2c_setreg,
    @@ -191,6 +198,7 @@
    .mdelay = 10,
    .timeout = 100,
    };
    +#endif
    static struct i2c_adapter oc_ops_0 = {
    .owner = THIS_MODULE,
    @@ -199,12 +207,14 @@
    .name = "Opencores i2c 0",
    };
    +#ifdef na_i2c_1
    static struct i2c_adapter oc_ops_1 = {
    .owner = THIS_MODULE,
    .id = I2C_HW_OC_UKIT,
    .algo_data = &oc_data_1,
    .name = "Opencores i2c 1",
    };
    +#endif
    static int __init i2c_oc_init(void)
    {
    @@ -218,16 +228,7 @@
    if (clock0)
    oc_hw_0.clock = clock0;
    - if (base1)
    - oc_hw_1.base = base1;
    - if (irq1)
    - oc_hw_1.irq = irq1;
    - if (clock1)
    - oc_hw_1.clock = clock1;
    -
    -
    init_waitqueue_head(&oc_hw_0.wait);
    - init_waitqueue_head(&oc_hw_1.wait);
    if (oc_hw_init(&oc_hw_0)==0) {
    if (i2c_oc_add_bus(&oc_ops_0) < 0) {
    @@ -235,11 +236,22 @@
    }
    }
    +#ifdef na_i2c_1
    + if (base1)
    + oc_hw_1.base = base1;
    + if (irq1)
    + oc_hw_1.irq = irq1;
    + if (clock1)
    + oc_hw_1.clock = clock1;
    +
    + init_waitqueue_head(&oc_hw_1.wait);
    +
    if (oc_hw_init(&oc_hw_1)==0) {
    if (i2c_oc_add_bus(&oc_ops_1) < 0) {
    oc_hw_exit(&oc_hw_1);
    }
    }
    +#endif
    return 0;
    }
    @@ -248,8 +260,10 @@
    {
    i2c_oc_del_bus(&oc_ops_0);
    oc_hw_exit(&oc_hw_0);
    +#ifdef na_i2c_1
    i2c_oc_del_bus(&oc_ops_1);
    oc_hw_exit(&oc_hw_1);
    +#endif
    }
    module_init(i2c_oc_init);
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    There are actually several changes here. The first file is just to improve the amount of memory the PCI driver can allocate to devices. Since we used 4 tables setup as

    0x0000000 Configuration

    0x0010000 I/O

    0x0020000 32-bit memory

    0x0030000 32-bit memory

    we can then use 0x200000 or 2 MB for the memory space from PCI.

    The second corrects the problem with the mapping functions that PCI eventually uses.

    The third allows the Opencores I2C function to compile and also allows for one I2C module as opposed to two.

    This set of diffs is meant for the 2.6.16.2 kernel.