aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm_pci.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
index 9d318ce2c993..0d44a6907dd2 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
@@ -149,6 +149,27 @@ ahc_linux_pci_dev_remove(struct pci_dev *pdev)
149 ahc_free(ahc); 149 ahc_free(ahc);
150} 150}
151 151
152static void
153ahc_linux_pci_inherit_flags(struct ahc_softc *ahc)
154{
155 struct pci_dev *pdev = ahc->dev_softc, *master_pdev;
156 unsigned int master_devfn = PCI_DEVFN(PCI_SLOT(pdev->devfn), 0);
157
158 master_pdev = pci_get_slot(pdev->bus, master_devfn);
159 if (master_pdev) {
160 struct ahc_softc *master = pci_get_drvdata(master_pdev);
161 if (master) {
162 ahc->flags &= ~AHC_BIOS_ENABLED;
163 ahc->flags |= master->flags & AHC_BIOS_ENABLED;
164
165 ahc->flags &= ~AHC_PRIMARY_CHANNEL;
166 ahc->flags |= master->flags & AHC_PRIMARY_CHANNEL;
167 } else
168 printk(KERN_ERR "aic7xxx: no multichannel peer found!\n");
169 pci_dev_put(master_pdev);
170 }
171}
172
152static int 173static int
153ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 174ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
154{ 175{
@@ -203,6 +224,14 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
203 ahc_free(ahc); 224 ahc_free(ahc);
204 return (-error); 225 return (-error);
205 } 226 }
227
228 /*
229 * Second Function PCI devices need to inherit some
230 * settings from function 0.
231 */
232 if ((ahc->features & AHC_MULTI_FUNC) && PCI_FUNC(pdev->devfn) != 0)
233 ahc_linux_pci_inherit_flags(ahc);
234
206 pci_set_drvdata(pdev, ahc); 235 pci_set_drvdata(pdev, ahc);
207 ahc_linux_register_host(ahc, &aic7xxx_driver_template); 236 ahc_linux_register_host(ahc, &aic7xxx_driver_template);
208 return (0); 237 return (0);