linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / drivers / sn / ioc4.c
index 8562821..771e868 100644 (file)
@@ -31,7 +31,7 @@
 #include <linux/ioc4.h>
 #include <linux/mmtimer.h>
 #include <linux/rtc.h>
-#include <linux/mutex.h>
+#include <linux/rwsem.h>
 #include <asm/sn/addrs.h>
 #include <asm/sn/clksupport.h>
 #include <asm/sn/shub_mmr.h>
  * Submodule management *
  ************************/
 
-static DEFINE_MUTEX(ioc4_mutex);
-
 static LIST_HEAD(ioc4_devices);
+static DECLARE_RWSEM(ioc4_devices_rwsem);
+
 static LIST_HEAD(ioc4_submodules);
+static DECLARE_RWSEM(ioc4_submodules_rwsem);
 
 /* Register an IOC4 submodule */
 int
@@ -65,13 +66,15 @@ ioc4_register_submodule(struct ioc4_submodule *is)
 {
        struct ioc4_driver_data *idd;
 
-       mutex_lock(&ioc4_mutex);
+       down_write(&ioc4_submodules_rwsem);
        list_add(&is->is_list, &ioc4_submodules);
+       up_write(&ioc4_submodules_rwsem);
 
        /* Initialize submodule for each IOC4 */
        if (!is->is_probe)
-               goto out;
+               return 0;
 
+       down_read(&ioc4_devices_rwsem);
        list_for_each_entry(idd, &ioc4_devices, idd_list) {
                if (is->is_probe(idd)) {
                        printk(KERN_WARNING
@@ -81,8 +84,8 @@ ioc4_register_submodule(struct ioc4_submodule *is)
                               pci_name(idd->idd_pdev));
                }
        }
- out:
-       mutex_unlock(&ioc4_mutex);
+       up_read(&ioc4_devices_rwsem);
+
        return 0;
 }
 
@@ -92,13 +95,15 @@ ioc4_unregister_submodule(struct ioc4_submodule *is)
 {
        struct ioc4_driver_data *idd;
 
-       mutex_lock(&ioc4_mutex);
+       down_write(&ioc4_submodules_rwsem);
        list_del(&is->is_list);
+       up_write(&ioc4_submodules_rwsem);
 
        /* Remove submodule for each IOC4 */
        if (!is->is_remove)
-               goto out;
+               return;
 
+       down_read(&ioc4_devices_rwsem);
        list_for_each_entry(idd, &ioc4_devices, idd_list) {
                if (is->is_remove(idd)) {
                        printk(KERN_WARNING
@@ -108,8 +113,7 @@ ioc4_unregister_submodule(struct ioc4_submodule *is)
                               pci_name(idd->idd_pdev));
                }
        }
- out:
-       mutex_unlock(&ioc4_mutex);
+       up_read(&ioc4_devices_rwsem);
 }
 
 /*********************
@@ -160,6 +164,9 @@ ioc4_clock_calibrate(struct ioc4_driver_data *idd)
        writel(0, &idd->idd_misc_regs->int_out.raw);
        mmiowb();
 
+       printk(KERN_INFO
+              "%s: Calibrating PCI bus speed "
+              "for pci_dev %s ... ", __FUNCTION__, pci_name(idd->idd_pdev));
        /* Set up square wave */
        int_out.raw = 0;
        int_out.fields.count = IOC4_CALIBRATE_COUNT;
@@ -203,16 +210,11 @@ ioc4_clock_calibrate(struct ioc4_driver_data *idd)
        /* Bounds check the result. */
        if (period > IOC4_CALIBRATE_LOW_LIMIT ||
            period < IOC4_CALIBRATE_HIGH_LIMIT) {
-               printk(KERN_INFO
-                      "IOC4 %s: Clock calibration failed.  Assuming"
-                      "PCI clock is %d ns.\n",
-                      pci_name(idd->idd_pdev),
+               printk("failed. Assuming PCI clock ticks are %d ns.\n",
                       IOC4_CALIBRATE_DEFAULT / IOC4_EXTINT_COUNT_DIVISOR);
                period = IOC4_CALIBRATE_DEFAULT;
        } else {
-               printk(KERN_DEBUG
-                      "IOC4 %s: PCI clock is %ld ns.\n",
-                      pci_name(idd->idd_pdev),
+               printk("succeeded. PCI clock ticks are %ld ns.\n",
                       period / IOC4_EXTINT_COUNT_DIVISOR);
        }
 
@@ -224,51 +226,6 @@ ioc4_clock_calibrate(struct ioc4_driver_data *idd)
        idd->count_period = period;
 }
 
-/* There are three variants of IOC4 cards: IO9, IO10, and PCI-RT.
- * Each brings out different combinations of IOC4 signals, thus.
- * the IOC4 subdrivers need to know to which we're attached.
- *
- * We look for the presence of a SCSI (IO9) or SATA (IO10) controller
- * on the same PCI bus at slot number 3 to differentiate IO9 from IO10.
- * If neither is present, it's a PCI-RT.
- */
-static unsigned int
-ioc4_variant(struct ioc4_driver_data *idd)
-{
-       struct pci_dev *pdev = NULL;
-       int found = 0;
-
-       /* IO9: Look for a QLogic ISP 12160 at the same bus and slot 3. */
-       do {
-               pdev = pci_get_device(PCI_VENDOR_ID_QLOGIC,
-                                     PCI_DEVICE_ID_QLOGIC_ISP12160, pdev);
-               if (pdev &&
-                   idd->idd_pdev->bus->number == pdev->bus->number &&
-                   3 == PCI_SLOT(pdev->devfn))
-                       found = 1;
-               pci_dev_put(pdev);
-       } while (pdev && !found);
-       if (NULL != pdev)
-               return IOC4_VARIANT_IO9;
-
-       /* IO10: Look for a Vitesse VSC 7174 at the same bus and slot 3. */
-       pdev = NULL;
-       do {
-               pdev = pci_get_device(PCI_VENDOR_ID_VITESSE,
-                                     PCI_DEVICE_ID_VITESSE_VSC7174, pdev);
-               if (pdev &&
-                   idd->idd_pdev->bus->number == pdev->bus->number &&
-                   3 == PCI_SLOT(pdev->devfn))
-                       found = 1;
-               pci_dev_put(pdev);
-       } while (pdev && !found);
-       if (NULL != pdev)
-               return IOC4_VARIANT_IO10;
-
-       /* PCI-RT: No SCSI/SATA controller will be present */
-       return IOC4_VARIANT_PCI_RT;
-}
-
 /* Adds a new instance of an IOC4 card */
 static int
 ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
@@ -333,13 +290,6 @@ ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
 
        /* Failsafe portion of per-IOC4 initialization */
 
-       /* Detect card variant */
-       idd->idd_variant = ioc4_variant(idd);
-       printk(KERN_INFO "IOC4 %s: %s card detected.\n", pci_name(pdev),
-              idd->idd_variant == IOC4_VARIANT_IO9 ? "IO9" :
-              idd->idd_variant == IOC4_VARIANT_PCI_RT ? "PCI-RT" :
-              idd->idd_variant == IOC4_VARIANT_IO10 ? "IO10" : "unknown");
-
        /* Initialize IOC4 */
        pci_read_config_dword(idd->idd_pdev, PCI_COMMAND, &pcmd);
        pci_write_config_dword(idd->idd_pdev, PCI_COMMAND,
@@ -362,11 +312,12 @@ ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
        /* Track PCI-device specific data */
        idd->idd_serial_data = NULL;
        pci_set_drvdata(idd->idd_pdev, idd);
-
-       mutex_lock(&ioc4_mutex);
+       down_write(&ioc4_devices_rwsem);
        list_add_tail(&idd->idd_list, &ioc4_devices);
+       up_write(&ioc4_devices_rwsem);
 
        /* Add this IOC4 to all submodules */
+       down_read(&ioc4_submodules_rwsem);
        list_for_each_entry(is, &ioc4_submodules, is_list) {
                if (is->is_probe && is->is_probe(idd)) {
                        printk(KERN_WARNING
@@ -376,7 +327,7 @@ ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
                               pci_name(idd->idd_pdev));
                }
        }
-       mutex_unlock(&ioc4_mutex);
+       up_read(&ioc4_submodules_rwsem);
 
        return 0;
 
@@ -400,7 +351,7 @@ ioc4_remove(struct pci_dev *pdev)
        idd = pci_get_drvdata(pdev);
 
        /* Remove this IOC4 from all submodules */
-       mutex_lock(&ioc4_mutex);
+       down_read(&ioc4_submodules_rwsem);
        list_for_each_entry(is, &ioc4_submodules, is_list) {
                if (is->is_remove && is->is_remove(idd)) {
                        printk(KERN_WARNING
@@ -410,7 +361,7 @@ ioc4_remove(struct pci_dev *pdev)
                               pci_name(idd->idd_pdev));
                }
        }
-       mutex_unlock(&ioc4_mutex);
+       up_read(&ioc4_submodules_rwsem);
 
        /* Release resources */
        iounmap(idd->idd_misc_regs);
@@ -426,9 +377,9 @@ ioc4_remove(struct pci_dev *pdev)
        pci_disable_device(pdev);
 
        /* Remove and free driver data */
-       mutex_lock(&ioc4_mutex);
+       down_write(&ioc4_devices_rwsem);
        list_del(&idd->idd_list);
-       mutex_unlock(&ioc4_mutex);
+       up_write(&ioc4_devices_rwsem);
        kfree(idd);
 }
 
@@ -438,7 +389,7 @@ static struct pci_device_id ioc4_id_table[] = {
        {0}
 };
 
-static struct pci_driver ioc4_driver = {
+static struct pci_driver __devinitdata ioc4_driver = {
        .name = "IOC4",
        .id_table = ioc4_id_table,
        .probe = ioc4_probe,