• David S. Miller's avatar
    [SPARC]: Fix OF register translations under sub-PCI busses. · a83f9823
    David S. Miller authored
    There is an implicit assumption in the code that ranges will translate
    to something that can fit in 2 32-bit cells, or a 64-bit value.  For
    certain kinds of things below PCI this isn't necessarily true.
    
    Here is what the relevant OF device hierarchy looks like for one of
    the serial controllers on an Ultra5:
    
        Node 0xf005f1e0
            ranges:      00000000.00000000.00000000.000001fe.01000000.00000000.01000000
                         01000000.00000000.00000000.000001fe.02000000.00000000.01000000
                         02000000.00000000.00000000.000001ff.00000000.00000001.00000000
                         03000000.00000000.00000000.000001ff.00000000.00000001.00000000
            device_type:  'pci'
            model:  'SUNW,sabre'
    
            Node 0xf005f9d4
                device_type:  'pci'
                model:  'SUNW,simba'
    
               Node 0xf0060d24
                    ranges:  00000010.00000000 82010810.00000000.f0000000 01000000
    			 00000014.00000000 82010814.00000000.f1000000 00800000
                    name:  'ebus'
    
                    Node 0xf0062dac
                        reg:  00000014.003083f8.00000008 --> 0x1ff.f13083f8
                        device_type:  'serial'
                        name:  'su'
    
    So the correct translation here is:
    
    1) Match "su" register to second ranges entry of 'ebus', which translates
       into a PCI triplet "82010814.00000000.f1000000" of size 00800000, which
       gives us "82010814.00000000.f13083f8".
    
    2) Pass-through "SUNW,simba" since it lacks ranges property
    
    3) Match "82010814.00000000.f13083f8" to third ranges property of PCI
       controller node 'SUNW,sabre', and we arrive at the final physical
       MMIO address of "0x1fff13083f8".
    
    Due to the 2-cell assumption, we couldn't translate to a PCI 3-cell
    value, and we couldn't perform a pass-thru on it either.
    
    It was easiest to just stop splitting the ranges application operation
    between two methods, ->map and ->translate, and just let ->map do all
    the work.  That way it would work purely on 32-bit cell arrays instead
    of having to "return" some value like a u64.
    
    It's still not %100 correct because the out-of-range check is still
    done using the 64 least significant bits of the range and address.
    But it does work for all the cases I've thrown at it so far.
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    a83f9823
of_device.c 16.5 KB