]> git.hungrycats.org Git - linux/commitdiff
[PATCH] cciss: PCI BAR sizing fix
authorAndrew Morton <akpm@osdl.org>
Sun, 8 Feb 2004 01:42:35 +0000 (17:42 -0800)
committerLinus Torvalds <torvalds@home.osdl.org>
Sun, 8 Feb 2004 01:42:35 +0000 (17:42 -0800)
From: <mikem@beardog.cca.cpqcorp.net>

This patch eliminates the bad assumption that all of our PCI BARs will always
be 32-bits.  Tested against the 2.6.2 kernel.

This is required to support the Pinnacles architecture.  It is already in the
2.4 tree.

(This needs to be converted to use pci_request_regions())

drivers/block/cciss.c
drivers/block/cciss.h

index 4c3ace285a5af67672f81b84f1607ad9b6b8f433..ce3ff054c89309d67134678c2a0eb917b4b5694b 100644 (file)
@@ -2078,16 +2078,51 @@ static void release_io_mem(ctlr_info_t *c)
        c->io_mem_addr = 0;
        c->io_mem_length = 0;
 }
+
+static int find_PCI_BAR_index(struct pci_dev *pdev,
+                               unsigned long pci_bar_addr)
+{
+       int i, offset, mem_type, bar_type;
+       if (pci_bar_addr == PCI_BASE_ADDRESS_0) /* looking for BAR zero? */
+               return 0;
+       offset = 0;
+       for (i=0; i<DEVICE_COUNT_RESOURCE; i++) {
+               bar_type = pci_resource_flags(pdev, i) &
+                       PCI_BASE_ADDRESS_SPACE;
+               if (bar_type == PCI_BASE_ADDRESS_SPACE_IO)
+                       offset += 4;
+               else {
+                       mem_type = pci_resource_flags(pdev, i) &
+                               PCI_BASE_ADDRESS_MEM_TYPE_MASK;
+                       switch (mem_type) {
+                               case PCI_BASE_ADDRESS_MEM_TYPE_32:
+                               case PCI_BASE_ADDRESS_MEM_TYPE_1M:
+                                       offset += 4; /* 32 bit */
+                                       break;
+                               case PCI_BASE_ADDRESS_MEM_TYPE_64:
+                                       offset += 8;
+                                       break;
+                               default: /* reserved in PCI 2.2 */
+                                       printk(KERN_WARNING "Base address is invalid\n");
+                                       return -1;
+                               break;
+                       }
+               }
+               if (offset == pci_bar_addr - PCI_BASE_ADDRESS_0)
+                       return i+1;
+       }
+       return -1;
+}
+
 static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
 {
        ushort vendor_id, device_id, command;
        unchar cache_line_size, latency_timer;
        unchar irq, revision;
-       uint addr[6];
        __u32 board_id, scratchpad = 0;
-       int cfg_offset;
-       int cfg_base_addr;
-       int cfg_base_addr_index;
+       __u64 cfg_offset;
+       __u32 cfg_base_addr;
+       __u64 cfg_base_addr_index;
        int i;
 
        if (pci_enable_device(pdev))
@@ -2105,9 +2140,6 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
        device_id = pdev->device;
        irq = pdev->irq;
 
-       for(i=0; i<6; i++)
-               addr[i] = pdev->resource[i].start;
-
        (void) pci_read_config_word(pdev, PCI_COMMAND,&command);
        (void) pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
        (void) pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE,
@@ -2125,14 +2157,13 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
        }
 
        /* search for our IO range so we can protect it */
-       for(i=0; i<6; i++)
+       for(i=0; i<DEVICE_COUNT_RESOURCE; i++)
        {
                /* is this an IO range */ 
-               if( pdev->resource[i].flags & 0x01 )
-               {
-                       c->io_mem_addr = pdev->resource[i].start;
-                       c->io_mem_length = pdev->resource[i].end -
-                               pdev->resource[i].start +1; 
+               if( pdev_resource_flags(pdev, i) & 0x01 ) {
+                       c->io_mem_addr = pdev_resource_start(pdev, i);
+                       c->io_mem_length = pdev_resource_end(pdev, i) -
+                               pdev_resource_start(pdev, i) +1;
 #ifdef CCISS_DEBUG
                        printk("IO value found base_addr[%d] %lx %lx\n", i,
                                c->io_mem_addr, c->io_mem_length);
@@ -2155,7 +2186,7 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
        printk("device_id = %x\n", device_id);
        printk("command = %x\n", command);
        for(i=0; i<6; i++)
-               printk("addr[%d] = %x\n", i, addr[i]);
+               printk("addr[%d] = %x\n", i, pci_resource_start(pdev, i);
        printk("revision = %x\n", revision);
        printk("irq = %x\n", irq);
        printk("cache_line_size = %x\n", cache_line_size);
@@ -2170,7 +2201,7 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
          *   table
         */
 
-       c->paddr = addr[0] ; /* addressing mode bits already removed */
+       c->paddr = pci_resource_start(pdev, 0); /* addressing mode bits already removed */
 #ifdef CCISS_DEBUG
        printk("address 0 = %x\n", c->paddr);
 #endif /* CCISS_DEBUG */ 
@@ -2192,22 +2223,27 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
 
        /* get the address index number */
        cfg_base_addr = readl(c->vaddr + SA5_CTCFG_OFFSET);
-       /* I am not prepared to deal with a 64 bit address value */
-       cfg_base_addr &= 0xffff;
+       cfg_base_addr &= (__u32) 0x0000ffff;
 #ifdef CCISS_DEBUG
        printk("cfg base address = %x\n", cfg_base_addr);
 #endif /* CCISS_DEBUG */
-       cfg_base_addr_index = (cfg_base_addr  - PCI_BASE_ADDRESS_0)/4;
+       cfg_base_addr_index =
+               find_PCI_BAR_index(pdev, cfg_base_addr);
 #ifdef CCISS_DEBUG
        printk("cfg base address index = %x\n", cfg_base_addr_index);
 #endif /* CCISS_DEBUG */
+       if (cfg_base_addr_index == -1) {
+               printk(KERN_WARNING "cciss: Cannot find cfg_base_addr_index\n");
+               release_io_mem(hba[i]);
+               return -1;
+       }
 
        cfg_offset = readl(c->vaddr + SA5_CTMEM_OFFSET);
 #ifdef CCISS_DEBUG
        printk("cfg offset = %x\n", cfg_offset);
 #endif /* CCISS_DEBUG */
        c->cfgtable = (CfgTable_struct *) 
-               remap_pci_mem((addr[cfg_base_addr_index] & 0xfffffff0)
+               remap_pci_mem(pci_resource_start(pdev, cfg_base_addr_index)
                                + cfg_offset, sizeof(CfgTable_struct));
        c->board_id = board_id;
 
index f1bb1e9ff5d1f492215aef6d1abf2e29ab364ea9..16bf4638ade8488d4267257f5a579db410cfbe4a 100644 (file)
@@ -42,8 +42,8 @@ struct ctlr_info
        char    firm_ver[4]; // Firmware version 
        struct pci_dev *pdev;
        __u32   board_id;
-       ulong   vaddr;
-       __u32   paddr;  
+       unsigned long vaddr;
+       unsigned long paddr;
        unsigned long io_mem_addr;
        unsigned long io_mem_length;
        CfgTable_struct *cfgtable;