]> pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge master.kernel.org:/pub/scm/linux/kernel/git/lenb/linux-2.6
authorLinus Torvalds <torvalds@g5.osdl.org>
Tue, 12 Jul 2005 23:04:50 +0000 (16:04 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Tue, 12 Jul 2005 23:04:50 +0000 (16:04 -0700)
1  2 
drivers/pcmcia/yenta_socket.c

index f9d2367b6bdf6c7200da103ad20496ac95981a68,15f716a7968aba59479812c7ef04d9d332dc8927..6837491f021c0b813aee8681cc73eb33dd0a21cd
@@@ -527,144 -527,98 +527,144 @@@ static int yenta_sock_suspend(struct pc
   * Use an adaptive allocation for the memory resource,
   * sometimes the memory behind pci bridges is limited:
   * 1/8 of the size of the io window of the parent.
 - * max 4 MB, min 16 kB.
 + * max 4 MB, min 16 kB. We try very hard to not get below
 + * the "ACC" values, though.
   */
  #define BRIDGE_MEM_MAX 4*1024*1024
 +#define BRIDGE_MEM_ACC 128*1024
  #define BRIDGE_MEM_MIN 16*1024
  
 -#define BRIDGE_IO_MAX 256
 +#define BRIDGE_IO_MAX 512
 +#define BRIDGE_IO_ACC 256
  #define BRIDGE_IO_MIN 32
  
  #ifndef PCIBIOS_MIN_CARDBUS_IO
  #define PCIBIOS_MIN_CARDBUS_IO PCIBIOS_MIN_IO
  #endif
  
 -static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned type)
 +static int yenta_search_one_res(struct resource *root, struct resource *res,
 +                              u32 min)
 +{
 +      u32 align, size, start, end;
 +
 +      if (res->flags & IORESOURCE_IO) {
 +              align = 1024;
 +              size = BRIDGE_IO_MAX;
 +              start = PCIBIOS_MIN_CARDBUS_IO;
 +              end = ~0U;
 +      } else {
 +              unsigned long avail = root->end - root->start;
 +              int i;
 +              size = BRIDGE_MEM_MAX;
 +              if (size > avail/8) {
 +                      size=(avail+1)/8;
 +                      /* round size down to next power of 2 */
 +                      i = 0;
 +                      while ((size /= 2) != 0)
 +                              i++;
 +                      size = 1 << i;
 +              }
 +              if (size < min)
 +                      size = min;
 +              align = size;
 +              start = PCIBIOS_MIN_MEM;
 +              end = ~0U;
 +      }
 +
 +      do {
 +              if (allocate_resource(root, res, size, start, end, align,
 +                                    NULL, NULL)==0) {
 +                      return 1;
 +              }
 +              size = size/2;
 +              align = size;
 +      } while (size >= min);
 +
 +      return 0;
 +}
 +
 +
 +static int yenta_search_res(struct yenta_socket *socket, struct resource *res,
 +                          u32 min)
 +{
 +      int i;
 +      for (i=0; i<PCI_BUS_NUM_RESOURCES; i++) {
 +              struct resource * root = socket->dev->bus->resource[i];
 +              if (!root)
 +                      continue;
 +
 +              if ((res->flags ^ root->flags) &
 +                  (IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_PREFETCH))
 +                      continue; /* Wrong type */
 +
 +              if (yenta_search_one_res(root, res, min))
 +                      return 1;
 +      }
 +      return 0;
 +}
 +
 +static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned type, int addr_start, int addr_end)
  {
        struct pci_bus *bus;
        struct resource *root, *res;
        u32 start, end;
 -      u32 align, size, min;
 -      unsigned offset;
        unsigned mask;
  
        res = socket->dev->resource + PCI_BRIDGE_RESOURCES + nr;
        /* Already allocated? */
        if (res->parent)
 -              return 0;
 +              return;
  
        /* The granularity of the memory limit is 4kB, on IO it's 4 bytes */
        mask = ~0xfff;
        if (type & IORESOURCE_IO)
                mask = ~3;
  
 -      offset = 0x1c + 8*nr;
        bus = socket->dev->subordinate;
        res->name = bus->name;
        res->flags = type;
 -      res->start = 0;
 -      res->end = 0;
 -      root = pci_find_parent_resource(socket->dev, res);
 -
 -      if (!root)
 -              return;
  
 -      start = config_readl(socket, offset) & mask;
 -      end = config_readl(socket, offset+4) | ~mask;
 +      start = config_readl(socket, addr_start) & mask;
 +      end = config_readl(socket, addr_end) | ~mask;
        if (start && end > start && !override_bios) {
                res->start = start;
                res->end = end;
 -              if (request_resource(root, res) == 0)
 +              root = pci_find_parent_resource(socket->dev, res);
 +              if (root && (request_resource(root, res) == 0))
                        return;
 -              printk(KERN_INFO "yenta %s: Preassigned resource %d busy, reconfiguring...\n",
 +              printk(KERN_INFO "yenta %s: Preassigned resource %d busy or not available, reconfiguring...\n",
                                pci_name(socket->dev), nr);
 -              res->start = res->end = 0;
        }
  
        if (type & IORESOURCE_IO) {
 -              align = 1024;
 -              size = BRIDGE_IO_MAX;
 -              min = BRIDGE_IO_MIN;
 -              start = PCIBIOS_MIN_CARDBUS_IO;
 -              end = ~0U;
 +              if ((yenta_search_res(socket, res, BRIDGE_IO_MAX)) ||
 +                  (yenta_search_res(socket, res, BRIDGE_IO_ACC)) ||
 +                  (yenta_search_res(socket, res, BRIDGE_IO_MIN))) {
 +                      config_writel(socket, addr_start, res->start);
 +                      config_writel(socket, addr_end, res->end);
 +              }
        } else {
 -              unsigned long avail = root->end - root->start;
 -              int i;
 -              size = BRIDGE_MEM_MAX;
 -              if (size > avail/8) {
 -                      size=(avail+1)/8;
 -                      /* round size down to next power of 2 */
 -                      i = 0;
 -                      while ((size /= 2) != 0)
 -                              i++;
 -                      size = 1 << i;
 +              if (type & IORESOURCE_PREFETCH) {
 +                      if ((yenta_search_res(socket, res, BRIDGE_MEM_MAX)) ||
 +                          (yenta_search_res(socket, res, BRIDGE_MEM_ACC)) ||
 +                          (yenta_search_res(socket, res, BRIDGE_MEM_MIN))) {
 +                              config_writel(socket, addr_start, res->start);
 +                              config_writel(socket, addr_end, res->end);
 +                      }
 +                      /* Approximating prefetchable by non-prefetchable */
 +                      res->flags = IORESOURCE_MEM;
                }
 -              if (size < BRIDGE_MEM_MIN)
 -                      size = BRIDGE_MEM_MIN;
 -              min = BRIDGE_MEM_MIN;
 -              align = size;
 -              start = PCIBIOS_MIN_MEM;
 -              end = ~0U;
 -      }
 -      
 -      do {
 -              if (allocate_resource(root, res, size, start, end, align, NULL, NULL)==0) {
 -                      config_writel(socket, offset, res->start);
 -                      config_writel(socket, offset+4, res->end);
 -                      return;
 +              if ((yenta_search_res(socket, res, BRIDGE_MEM_MAX)) ||
 +                  (yenta_search_res(socket, res, BRIDGE_MEM_ACC)) ||
 +                  (yenta_search_res(socket, res, BRIDGE_MEM_MIN))) {
 +                      config_writel(socket, addr_start, res->start);
 +                      config_writel(socket, addr_end, res->end);
                }
 -              size = size/2;
 -              align = size;
 -      } while (size >= min);
 +      }
 +
        printk(KERN_INFO "yenta %s: no resource of type %x available, trying to continue...\n",
 -                      pci_name(socket->dev), type);
 -      res->start = res->end = 0;
 +             pci_name(socket->dev), type);
 +      res->start = res->end = res->flags = 0;
  }
  
  /*
   */
  static void yenta_allocate_resources(struct yenta_socket *socket)
  {
 -      yenta_allocate_res(socket, 0, IORESOURCE_MEM|IORESOURCE_PREFETCH);
 -      yenta_allocate_res(socket, 1, IORESOURCE_MEM);
 -      yenta_allocate_res(socket, 2, IORESOURCE_IO);
 -      yenta_allocate_res(socket, 3, IORESOURCE_IO);   /* PCI isn't clever enough to use this one yet */
 +      yenta_allocate_res(socket, 0, IORESOURCE_IO,
 +                         PCI_CB_IO_BASE_0, PCI_CB_IO_LIMIT_0);
 +      yenta_allocate_res(socket, 1, IORESOURCE_IO,
 +                         PCI_CB_IO_BASE_1, PCI_CB_IO_LIMIT_1);
 +      yenta_allocate_res(socket, 2, IORESOURCE_MEM|IORESOURCE_PREFETCH,
 +                         PCI_CB_MEMORY_BASE_0, PCI_CB_MEMORY_LIMIT_0);
 +      yenta_allocate_res(socket, 3, IORESOURCE_MEM,
 +                         PCI_CB_MEMORY_BASE_1, PCI_CB_MEMORY_LIMIT_1);
  }
  
  
@@@ -1105,6 -1055,7 +1105,7 @@@ static int yenta_dev_suspend (struct pc
                pci_save_state(dev);
                pci_read_config_dword(dev, 16*4, &socket->saved_state[0]);
                pci_read_config_dword(dev, 17*4, &socket->saved_state[1]);
+               pci_disable_device(dev);
  
                /*
                 * Some laptops (IBM T22) do not like us putting the Cardbus
@@@ -1128,6 -1079,8 +1129,8 @@@ static int yenta_dev_resume (struct pci
                pci_restore_state(dev);
                pci_write_config_dword(dev, 16*4, socket->saved_state[0]);
                pci_write_config_dword(dev, 17*4, socket->saved_state[1]);
+               pci_enable_device(dev);
+               pci_set_master(dev);
  
                if (socket->type && socket->type->restore_state)
                        socket->type->restore_state(socket);