aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/aic7xxx/aic79xx_osm_pci.c')
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm_pci.c79
1 files changed, 34 insertions, 45 deletions
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
index 7cfb2eb2b868..390b53852d4b 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
@@ -92,27 +92,31 @@ struct pci_driver aic79xx_pci_driver = {
92static void 92static void
93ahd_linux_pci_dev_remove(struct pci_dev *pdev) 93ahd_linux_pci_dev_remove(struct pci_dev *pdev)
94{ 94{
95 struct ahd_softc *ahd; 95 struct ahd_softc *ahd = pci_get_drvdata(pdev);
96 u_long l; 96 u_long s;
97 97
98 /* 98 ahd_lock(ahd, &s);
99 * We should be able to just perform 99 ahd_intr_enable(ahd, FALSE);
100 * the free directly, but check our 100 ahd_unlock(ahd, &s);
101 * list for extra sanity. 101 ahd_free(ahd);
102 */ 102}
103 ahd_list_lock(&l); 103
104 ahd = ahd_find_softc((struct ahd_softc *)pci_get_drvdata(pdev)); 104static void
105 if (ahd != NULL) { 105ahd_linux_pci_inherit_flags(struct ahd_softc *ahd)
106 u_long s; 106{
107 107 struct pci_dev *pdev = ahd->dev_softc, *master_pdev;
108 TAILQ_REMOVE(&ahd_tailq, ahd, links); 108 unsigned int master_devfn = PCI_DEVFN(PCI_SLOT(pdev->devfn), 0);
109 ahd_list_unlock(&l); 109
110 ahd_lock(ahd, &s); 110 master_pdev = pci_get_slot(pdev->bus, master_devfn);
111 ahd_intr_enable(ahd, FALSE); 111 if (master_pdev) {
112 ahd_unlock(ahd, &s); 112 struct ahd_softc *master = pci_get_drvdata(master_pdev);
113 ahd_free(ahd); 113 if (master) {
114 } else 114 ahd->flags &= ~AHD_BIOS_ENABLED;
115 ahd_list_unlock(&l); 115 ahd->flags |= master->flags & AHD_BIOS_ENABLED;
116 } else
117 printk(KERN_ERR "aic79xx: no multichannel peer found!\n");
118 pci_dev_put(master_pdev);
119 }
116} 120}
117 121
118static int 122static int
@@ -125,22 +129,6 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
125 char *name; 129 char *name;
126 int error; 130 int error;
127 131
128 /*
129 * Some BIOSen report the same device multiple times.
130 */
131 TAILQ_FOREACH(ahd, &ahd_tailq, links) {
132 struct pci_dev *probed_pdev;
133
134 probed_pdev = ahd->dev_softc;
135 if (probed_pdev->bus->number == pdev->bus->number
136 && probed_pdev->devfn == pdev->devfn)
137 break;
138 }
139 if (ahd != NULL) {
140 /* Skip duplicate. */
141 return (-ENODEV);
142 }
143
144 pci = pdev; 132 pci = pdev;
145 entry = ahd_find_pci_device(pci); 133 entry = ahd_find_pci_device(pci);
146 if (entry == NULL) 134 if (entry == NULL)
@@ -190,16 +178,17 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
190 ahd_free(ahd); 178 ahd_free(ahd);
191 return (-error); 179 return (-error);
192 } 180 }
181
182 /*
183 * Second Function PCI devices need to inherit some
184 * * settings from function 0.
185 */
186 if ((ahd->features & AHD_MULTI_FUNC) && PCI_FUNC(pdev->devfn) != 0)
187 ahd_linux_pci_inherit_flags(ahd);
188
193 pci_set_drvdata(pdev, ahd); 189 pci_set_drvdata(pdev, ahd);
194 if (aic79xx_detect_complete) { 190
195#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) 191 ahd_linux_register_host(ahd, &aic79xx_driver_template);
196 ahd_linux_register_host(ahd, &aic79xx_driver_template);
197#else
198 printf("aic79xx: ignoring PCI device found after "
199 "initialization\n");
200 return (-ENODEV);
201#endif
202 }
203 return (0); 192 return (0);
204} 193}
205 194