diff options
Diffstat (limited to 'drivers/scsi/aic7xxx/aic79xx_osm_pci.c')
-rw-r--r-- | drivers/scsi/aic7xxx/aic79xx_osm_pci.c | 82 |
1 files changed, 34 insertions, 48 deletions
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c index 91daf0c7fb10..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) |
@@ -177,15 +165,12 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
177 | if (memsize >= 0x8000000000ULL | 165 | if (memsize >= 0x8000000000ULL |
178 | && pci_set_dma_mask(pdev, DMA_64BIT_MASK) == 0) { | 166 | && pci_set_dma_mask(pdev, DMA_64BIT_MASK) == 0) { |
179 | ahd->flags |= AHD_64BIT_ADDRESSING; | 167 | ahd->flags |= AHD_64BIT_ADDRESSING; |
180 | ahd->platform_data->hw_dma_mask = DMA_64BIT_MASK; | ||
181 | } else if (memsize > 0x80000000 | 168 | } else if (memsize > 0x80000000 |
182 | && pci_set_dma_mask(pdev, mask_39bit) == 0) { | 169 | && pci_set_dma_mask(pdev, mask_39bit) == 0) { |
183 | ahd->flags |= AHD_39BIT_ADDRESSING; | 170 | ahd->flags |= AHD_39BIT_ADDRESSING; |
184 | ahd->platform_data->hw_dma_mask = mask_39bit; | ||
185 | } | 171 | } |
186 | } else { | 172 | } else { |
187 | pci_set_dma_mask(pdev, DMA_32BIT_MASK); | 173 | pci_set_dma_mask(pdev, DMA_32BIT_MASK); |
188 | ahd->platform_data->hw_dma_mask = DMA_32BIT_MASK; | ||
189 | } | 174 | } |
190 | ahd->dev_softc = pci; | 175 | ahd->dev_softc = pci; |
191 | error = ahd_pci_config(ahd, entry); | 176 | error = ahd_pci_config(ahd, entry); |
@@ -193,16 +178,17 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
193 | ahd_free(ahd); | 178 | ahd_free(ahd); |
194 | return (-error); | 179 | return (-error); |
195 | } | 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 | |||
196 | pci_set_drvdata(pdev, ahd); | 189 | pci_set_drvdata(pdev, ahd); |
197 | if (aic79xx_detect_complete) { | 190 | |
198 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) | 191 | ahd_linux_register_host(ahd, &aic79xx_driver_template); |
199 | ahd_linux_register_host(ahd, &aic79xx_driver_template); | ||
200 | #else | ||
201 | printf("aic79xx: ignoring PCI device found after " | ||
202 | "initialization\n"); | ||
203 | return (-ENODEV); | ||
204 | #endif | ||
205 | } | ||
206 | return (0); | 192 | return (0); |
207 | } | 193 | } |
208 | 194 | ||