Commit 41a5311465b9de6d18e78b733a2c6e1b33e89be8

Authored by Bjorn Helgaas
Committed by Linus Torvalds
1 parent d57d973101

PNP SMCf010 quirk: work around Toshiba Portege 4000 ACPI issues

When we enable the SMCf010 IR device, the Toshiba Portege 4000 BIOS claims
the device is working, but it really isn't configured correctly.  The BIOS
*will* configure it, but only if we call _SRS after (1) reversing the order
of the SIR and FIR I/O port regions and (2) changing the IRQ from
active-high to active-low.

This patch addresses the 2.6.22 regression:
    "no irda0 interface (2.6.21 was OK), smsc does not find chip"

I tested this on a Portege 4000.  The smsc-ircc2 driver correctly detects
the device, and "irattach irda0 -s && irdadump" shows transmitted and
received packets.

Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
Cc: Andrey Borzenkov <arvidjaar@mail.ru>
Cc: Samuel Ortiz <samuel@sortiz.org>
Cc: "Linus Walleij (LD/EAB)" <linus.walleij@ericsson.com>
Cc: Michal Piotrowski <michal.k.k.piotrowski@gmail.com>
Cc: Adam Belay <ambx1@neo.rr.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 1 changed file with 54 additions and 9 deletions Side-by-side Diff

drivers/pnp/quirks.c
... ... @@ -136,11 +136,10 @@
136 136  
137 137 static void quirk_smc_enable(struct pnp_dev *dev)
138 138 {
139   - /*
140   - * If the BIOS left the device disabled, or it is enabled and
141   - * responding correctly, we're in good shape.
142   - */
143   - if (!dev->active || quirk_smc_fir_enabled(dev))
  139 + struct resource fir, sir, irq;
  140 +
  141 + pnp_activate_dev(dev);
  142 + if (quirk_smc_fir_enabled(dev))
144 143 return;
145 144  
146 145 /*
147 146  
148 147  
... ... @@ -152,16 +151,62 @@
152 151 * this. Fortunately, they do fix things up if we auto-configure
153 152 * the device using its _PRS and _SRS methods.
154 153 */
155   - dev_err(&dev->dev, "%s device not responding, auto-configuring "
156   - "resources\n", dev->id->id);
  154 + dev_err(&dev->dev, "%s not responding at SIR 0x%lx, FIR 0x%lx; "
  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 159 pnp_disable_dev(dev);
159 160 pnp_init_resource_table(&dev->res);
160 161 pnp_auto_config_dev(dev);
161 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 + }
162 169  
163   - if (!quirk_smc_fir_enabled(dev))
164   - dev_err(&dev->dev, "giving up; try \"smsc-ircc2.nopnp\"\n");
  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 + }
  207 +
  208 + dev_err(&dev->dev, "giving up; try \"smsc-ircc2.nopnp\" and "
  209 + "email bjorn.helgaas@hp.com\n");
165 210 }
166 211  
167 212