diff options
Diffstat (limited to 'drivers/scsi/aic7xxx/aic79xx_osm_pci.c')
-rw-r--r-- | drivers/scsi/aic7xxx/aic79xx_osm_pci.c | 79 |
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 = { | |||
92 | static void | 92 | static void |
93 | ahd_linux_pci_dev_remove(struct pci_dev *pdev) | 93 | ahd_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)); | 104 | static void |
105 | if (ahd != NULL) { | 105 | ahd_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 | ||
118 | static int | 122 | static 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 | ||