Re: [BK PULL] (8/9) PCMCIA changes

From: Russell King (rmk@arm.linux.org.uk)
Date: Wed Mar 26 2003 - 14:48:27 EST


# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
# ChangeSet 1.889.359.7 -> 1.889.359.8
# drivers/pcmcia/cs_internal.h 1.8 -> 1.9
# drivers/pcmcia/cardbus.c 1.23.1.1 -> 1.23.1.2
# drivers/pcmcia/cistpl.c 1.10 -> 1.11
# drivers/pci/Makefile 1.24 -> 1.25
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 03/03/23 rmk@flint.arm.linux.org.uk 1.889.359.8
# [PCMCIA] pcmcia-10: Make cardbus use the new PCI functionality.
#
# Now that we have the critical PCI changes in place, we can convert
# cardbus to use this PCI functionality. This allows us to scan
# behind PCI to PCI bridges on cardbus cards, and setup the bus
# resources using the generic PCI support code.
#
# Note that drivers/pci/setup-bus.c needs to be built when hotplug
# (ie, cardbus) is enabled.
# --------------------------------------------
#
diff -Nru a/drivers/pci/Makefile b/drivers/pci/Makefile
--- a/drivers/pci/Makefile Wed Mar 26 19:22:24 2003
+++ b/drivers/pci/Makefile Wed Mar 26 19:22:24 2003
@@ -29,6 +29,9 @@
 obj-y += setup-bus.o
 endif
 
+# Hotplug (eg, cardbus) now requires setup-bus
+obj-$(CONFIG_HOTPLUG) += setup-bus.o
+
 ifndef CONFIG_X86
 obj-y += syscall.o
 endif
diff -Nru a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c
--- a/drivers/pcmcia/cardbus.c Wed Mar 26 19:22:24 2003
+++ b/drivers/pcmcia/cardbus.c Wed Mar 26 19:22:24 2003
@@ -89,10 +89,6 @@
 #define PCDATA_CODE_TYPE 0x0014
 #define PCDATA_INDICATOR 0x0015
 
-typedef struct cb_config_t {
- struct pci_dev *dev[8];
-} cb_config_t;
-
 /*=====================================================================
 
     Expansion ROM's have a special layout, and pointers specify an
@@ -175,11 +171,10 @@
 
         DEBUG(3, "cs: read_cb_mem(%d, %#x, %u)\n", space, addr, len);
 
- if (!s->cb_config)
+ dev = pci_find_slot(s->cap.cb_dev->subordinate->number, 0);
+ if (!dev)
                 goto fail;
 
- dev = s->cb_config->dev[0];
-
         /* Config space? */
         if (space == 0) {
                 if (addr + len > 0x100)
@@ -221,109 +216,61 @@
     
 =====================================================================*/
 
-int cb_alloc(socket_info_t * s)
+/*
+ * Since there is only one interrupt available to CardBus
+ * devices, all devices downstream of this device must
+ * be using this IRQ.
+ */
+static void cardbus_assign_irqs(struct pci_bus *bus, int irq)
 {
- struct pci_bus *bus;
- u_short vend, v, dev;
- u_char i, hdr, fn;
- cb_config_t *c;
- int irq;
-
- bus = s->cap.cb_dev->subordinate;
-
- pci_bus_read_config_word(bus, 0, PCI_VENDOR_ID, &vend);
- pci_bus_read_config_word(bus, 0, PCI_DEVICE_ID, &dev);
- printk(KERN_INFO "cs: cb_alloc(bus %d): vendor 0x%04x, "
- "device 0x%04x\n", bus->number, vend, dev);
-
- pci_bus_read_config_byte(bus, 0, PCI_HEADER_TYPE, &hdr);
- fn = 1;
- if (hdr & 0x80) {
- do {
- if (pci_bus_read_config_word(bus, fn, PCI_VENDOR_ID, &v) ||
- !v || v == 0xffff)
- break;
- fn++;
- } while (fn < 8);
- }
- s->functions = fn;
-
- c = kmalloc(sizeof(struct cb_config_t), GFP_ATOMIC);
- if (!c)
- return CS_OUT_OF_RESOURCE;
- memset(c, 0, sizeof(struct cb_config_t));
-
- for (i = 0; i < fn; i++) {
- c->dev[i] = kmalloc(sizeof(struct pci_dev), GFP_ATOMIC);
- if (!c->dev[i]) {
- for (; i--; )
- kfree(c->dev[i]);
- kfree(c);
- return CS_OUT_OF_RESOURCE;
- }
- memset(c->dev[i], 0, sizeof(struct pci_dev));
- }
+ struct pci_dev *dev;
 
- irq = s->cap.pci_irq;
- for (i = 0; i < fn; i++) {
- struct pci_dev *dev = c->dev[i];
+ list_for_each_entry(dev, &bus->devices, bus_list) {
                 u8 irq_pin;
- int r;
 
- dev->bus = bus;
- dev->sysdata = bus->sysdata;
- dev->dev.parent = bus->dev;
- dev->dev.bus = &pci_bus_type;
- dev->devfn = i;
-
- pci_read_config_word(dev, PCI_VENDOR_ID, &dev->vendor);
- pci_read_config_word(dev, PCI_DEVICE_ID, &dev->device);
- dev->hdr_type = hdr & 0x7f;
- dev->dma_mask = 0xffffffff;
- dev->dev.dma_mask = &dev->dma_mask;
-
- pci_setup_device(dev);
-
- strcpy(dev->dev.bus_id, dev->slot_name);
-
- /* We need to assign resources for expansion ROM. */
- for (r = 0; r < 7; r++) {
- struct resource *res = dev->resource + r;
- if (res->flags)
- pci_assign_resource(dev, r);
- }
-
- /* Does this function have an interrupt at all? */
                 pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &irq_pin);
- if (irq_pin)
+ if (irq_pin) {
                         dev->irq = irq;
-
- /* pci_enable_device needs to be called after pci_assign_resource */
- /* because it returns an error if (!res->start && res->end). */
- if (pci_enable_device(dev))
- continue;
-
- if (irq_pin)
- pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
-
- device_register(&dev->dev);
- pci_insert_device(dev, bus);
+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+ }
+
+ if (dev->subordinate)
+ cardbus_assign_irqs(dev->subordinate, irq);
         }
+}
+
+int cb_alloc(socket_info_t * s)
+{
+ struct pci_bus *bus = s->cap.cb_dev->subordinate;
+ struct pci_dev *dev;
+ unsigned int max, pass;
+
+ s->functions = pci_scan_slot(bus, PCI_DEVFN(0, 0));
+// pcibios_fixup_bus(bus);
+
+ max = bus->secondary;
+ for (pass = 0; pass < 2; pass++)
+ list_for_each_entry(dev, &bus->devices, bus_list)
+ if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
+ dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
+ max = pci_scan_bridge(bus, dev, max, pass);
+
+ /*
+ * Size all resources below the CardBus controller.
+ */
+ pci_bus_size_bridges(bus);
+ pci_bus_assign_resources(bus);
+ cardbus_assign_irqs(bus, s->cap.pci_irq);
+ pci_enable_bridges(bus);
+ pci_bus_add_devices(bus);
 
- s->cb_config = c;
- s->irq.AssignedIRQ = irq;
+ s->irq.AssignedIRQ = s->cap.pci_irq;
         return CS_SUCCESS;
 }
 
 void cb_free(socket_info_t * s)
 {
- cb_config_t *c = s->cb_config;
+ struct pci_dev *bridge = s->cap.cb_dev;
 
- if (c) {
- s->cb_config = NULL;
- pci_remove_behind_bridge(s->cap.cb_dev);
-
- kfree(c);
- printk(KERN_INFO "cs: cb_free(bus %d)\n", s->cap.cb_dev->subordinate->number);
- }
+ pci_remove_behind_bridge(bridge);
 }
diff -Nru a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c
--- a/drivers/pcmcia/cistpl.c Wed Mar 26 19:22:24 2003
+++ b/drivers/pcmcia/cistpl.c Wed Mar 26 19:22:24 2003
@@ -396,11 +396,9 @@
     tuple->TupleLink = tuple->Flags = 0;
 #ifdef CONFIG_CARDBUS
     if (s->state & SOCKET_CARDBUS) {
+ struct pci_dev *dev = s->cap.cb_dev;
         u_int ptr;
- struct pci_dev *dev = pci_find_slot (s->cap.cb_dev->subordinate->number, 0);
- if (!dev)
- return CS_BAD_HANDLE;
- pci_read_config_dword(dev, 0x28, &ptr);
+ pci_bus_read_config_dword(dev->subordinate, 0, PCI_CARDBUS_CIS, &ptr);
         tuple->CISOffset = ptr & ~7;
         SPACE(tuple->Flags) = (ptr & 7);
     } else
diff -Nru a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h
--- a/drivers/pcmcia/cs_internal.h Wed Mar 26 19:22:24 2003
+++ b/drivers/pcmcia/cs_internal.h Wed Mar 26 19:22:24 2003
@@ -136,7 +136,6 @@
 #ifdef CONFIG_CARDBUS
     struct resource * cb_cis_res;
     u_char *cb_cis_virt;
- struct cb_config_t *cb_config;
 #endif
     struct {
         u_int AssignedIRQ;

-- 
Russell King (rmk@arm.linux.org.uk)                The developer of ARM Linux
             http://www.arm.linux.org.uk/personal/aboutme.html

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Mon Mar 31 2003 - 22:00:25 EST