diff options
Diffstat (limited to 'drivers/pnp/quirks.c')
-rw-r--r-- | drivers/pnp/quirks.c | 63 |
1 files changed, 54 insertions, 9 deletions
diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c index 967a8e22b2da..7c3236690cc3 100644 --- a/drivers/pnp/quirks.c +++ b/drivers/pnp/quirks.c | |||
@@ -136,11 +136,10 @@ static int quirk_smc_fir_enabled(struct pnp_dev *dev) | |||
136 | 136 | ||
137 | static void quirk_smc_enable(struct pnp_dev *dev) | 137 | static void quirk_smc_enable(struct pnp_dev *dev) |
138 | { | 138 | { |
139 | /* | 139 | struct resource fir, sir, irq; |
140 | * If the BIOS left the device disabled, or it is enabled and | 140 | |
141 | * responding correctly, we're in good shape. | 141 | pnp_activate_dev(dev); |
142 | */ | 142 | if (quirk_smc_fir_enabled(dev)) |
143 | if (!dev->active || quirk_smc_fir_enabled(dev)) | ||
144 | return; | 143 | return; |
145 | 144 | ||
146 | /* | 145 | /* |
@@ -152,16 +151,62 @@ static void quirk_smc_enable(struct pnp_dev *dev) | |||
152 | * this. Fortunately, they do fix things up if we auto-configure | 151 | * this. Fortunately, they do fix things up if we auto-configure |
153 | * the device using its _PRS and _SRS methods. | 152 | * the device using its _PRS and _SRS methods. |
154 | */ | 153 | */ |
155 | dev_err(&dev->dev, "%s device not responding, auto-configuring " | 154 | dev_err(&dev->dev, "%s not responding at SIR 0x%lx, FIR 0x%lx; " |
156 | "resources\n", dev->id->id); | 155 | "auto-configuring\n", dev->id->id, |
156 | (unsigned long) pnp_port_start(dev, 0), | ||
157 | (unsigned long) pnp_port_start(dev, 1)); | ||
157 | 158 | ||
158 | pnp_disable_dev(dev); | 159 | pnp_disable_dev(dev); |
159 | pnp_init_resource_table(&dev->res); | 160 | pnp_init_resource_table(&dev->res); |
160 | pnp_auto_config_dev(dev); | 161 | pnp_auto_config_dev(dev); |
161 | pnp_activate_dev(dev); | 162 | pnp_activate_dev(dev); |
163 | if (quirk_smc_fir_enabled(dev)) { | ||
164 | dev_err(&dev->dev, "responds at SIR 0x%lx, FIR 0x%lx\n", | ||
165 | (unsigned long) pnp_port_start(dev, 0), | ||
166 | (unsigned long) pnp_port_start(dev, 1)); | ||
167 | return; | ||
168 | } | ||
169 | |||
170 | /* | ||
171 | * The Toshiba Portege 4000 _CRS reports the FIR region first, | ||
172 | * followed by the SIR region. The BIOS will configure the bridge, | ||
173 | * but only if we call _SRS with SIR first, then FIR. It also | ||
174 | * reports the IRQ as active high, when it is really active low. | ||
175 | */ | ||
176 | dev_err(&dev->dev, "not responding at SIR 0x%lx, FIR 0x%lx; " | ||
177 | "swapping SIR/FIR and reconfiguring\n", | ||
178 | (unsigned long) pnp_port_start(dev, 0), | ||
179 | (unsigned long) pnp_port_start(dev, 1)); | ||
180 | |||
181 | /* | ||
182 | * Clear IORESOURCE_AUTO so pnp_activate_dev() doesn't reassign | ||
183 | * these resources any more. | ||
184 | */ | ||
185 | fir = dev->res.port_resource[0]; | ||
186 | sir = dev->res.port_resource[1]; | ||
187 | fir.flags &= ~IORESOURCE_AUTO; | ||
188 | sir.flags &= ~IORESOURCE_AUTO; | ||
189 | |||
190 | irq = dev->res.irq_resource[0]; | ||
191 | irq.flags &= ~IORESOURCE_AUTO; | ||
192 | irq.flags &= ~IORESOURCE_BITS; | ||
193 | irq.flags |= IORESOURCE_IRQ_LOWEDGE; | ||
194 | |||
195 | pnp_disable_dev(dev); | ||
196 | dev->res.port_resource[0] = sir; | ||
197 | dev->res.port_resource[1] = fir; | ||
198 | dev->res.irq_resource[0] = irq; | ||
199 | pnp_activate_dev(dev); | ||
200 | |||
201 | if (quirk_smc_fir_enabled(dev)) { | ||
202 | dev_err(&dev->dev, "responds at SIR 0x%lx, FIR 0x%lx\n", | ||
203 | (unsigned long) pnp_port_start(dev, 0), | ||
204 | (unsigned long) pnp_port_start(dev, 1)); | ||
205 | return; | ||
206 | } | ||
162 | 207 | ||
163 | if (!quirk_smc_fir_enabled(dev)) | 208 | dev_err(&dev->dev, "giving up; try \"smsc-ircc2.nopnp\" and " |
164 | dev_err(&dev->dev, "giving up; try \"smsc-ircc2.nopnp\"\n"); | 209 | "email bjorn.helgaas@hp.com\n"); |
165 | } | 210 | } |
166 | 211 | ||
167 | 212 | ||