- patches.apparmor/remove_suid_new_case_in_2.6.22.diff: Merge fix.
[linux-flexiantxendom0-3.2.10.git] / drivers / net / irda / smsc-ircc2.c
index 31c6233..9043bf4 100644 (file)
@@ -79,11 +79,17 @@ MODULE_AUTHOR("Daniele Peri <peri@csai.unipa.it>");
 MODULE_DESCRIPTION("SMC IrCC SIR/FIR controller driver");
 MODULE_LICENSE("GPL");
 
-static int ircc_dma = 255;
+static int smsc_nopnp;
+module_param_named(nopnp, smsc_nopnp, bool, 0);
+MODULE_PARM_DESC(nopnp, "Do not use PNP to detect controller settings");
+
+#define DMA_INVAL 255
+static int ircc_dma = DMA_INVAL;
 module_param(ircc_dma, int, 0);
 MODULE_PARM_DESC(ircc_dma, "DMA channel");
 
-static int ircc_irq = 255;
+#define IRQ_INVAL 255
+static int ircc_irq = IRQ_INVAL;
 module_param(ircc_irq, int, 0);
 MODULE_PARM_DESC(ircc_irq, "IRQ line");
 
@@ -315,6 +321,7 @@ static struct smsc_chip __initdata lpc_chips_flat[] =
 {
        /* Base address 0x2E or 0x4E */
        { "47N227",     KEY55_1|FIR|SERx4,      0x5a, 0x00 },
+       { "47N227",     KEY55_1|FIR|SERx4,      0x7a, 0x00 },
        { "47N267",     KEY55_1|FIR|SERx4,      0x5e, 0x00 },
        { NULL }
 };
@@ -359,7 +366,6 @@ static inline void register_bank(int iobase, int bank)
                iobase + IRCC_MASTER);
 }
 
-#ifdef CONFIG_PNP
 /* PNP hotplug support */
 static const struct pnp_device_id smsc_ircc_pnp_table[] = {
        { .id = "SMCf010", .driver_data = 0 },
@@ -367,7 +373,35 @@ static const struct pnp_device_id smsc_ircc_pnp_table[] = {
        { }
 };
 MODULE_DEVICE_TABLE(pnp, smsc_ircc_pnp_table);
-#endif
+
+static int pnp_driver_registered;
+
+static int __init smsc_ircc_pnp_probe(struct pnp_dev *dev,
+                                     const struct pnp_device_id *dev_id)
+{
+       unsigned int firbase, sirbase;
+       u8 dma, irq;
+
+       if (!(pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) &&
+             pnp_dma_valid(dev, 0) && pnp_irq_valid(dev, 0)))
+               return -EINVAL;
+
+       sirbase = pnp_port_start(dev, 0);
+       firbase = pnp_port_start(dev, 1);
+       dma = pnp_dma(dev, 0);
+       irq = pnp_irq(dev, 0);
+
+       if (smsc_ircc_open(firbase, sirbase, dma, irq))
+               return -ENODEV;
+
+       return 0;
+}
+
+static struct pnp_driver smsc_ircc_pnp_driver = {
+       .name           = "smsc-ircc2",
+       .id_table       = smsc_ircc_pnp_table,
+       .probe          = smsc_ircc_pnp_probe,
+};
 
 
 /*******************************************************************************
@@ -378,6 +412,35 @@ MODULE_DEVICE_TABLE(pnp, smsc_ircc_pnp_table);
  *
  *******************************************************************************/
 
+static int __init smsc_ircc_legacy_probe(void)
+{
+       int ret = 0;
+
+       if (ircc_fir > 0 && ircc_sir > 0) {
+               IRDA_MESSAGE(" Overriding FIR address 0x%04x\n", ircc_fir);
+               IRDA_MESSAGE(" Overriding SIR address 0x%04x\n", ircc_sir);
+
+               if (smsc_ircc_open(ircc_fir, ircc_sir, ircc_dma, ircc_irq))
+                       ret = -ENODEV;
+       } else {
+               ret = -ENODEV;
+
+               /* try user provided configuration register base address */
+               if (ircc_cfg > 0) {
+                       IRDA_MESSAGE(" Overriding configuration address "
+                                    "0x%04x\n", ircc_cfg);
+                       if (!smsc_superio_fdc(ircc_cfg))
+                               ret = 0;
+                       if (!smsc_superio_lpc(ircc_cfg))
+                               ret = 0;
+               }
+
+               if (smsc_ircc_look_for_chips() > 0)
+                       ret = 0;
+       }
+       return ret;
+}
+
 /*
  * Function smsc_ircc_init ()
  *
@@ -405,31 +468,20 @@ static int __init smsc_ircc_init(void)
 
        dev_count = 0;
 
-       if (ircc_fir > 0 && ircc_sir > 0) {
-               IRDA_MESSAGE(" Overriding FIR address 0x%04x\n", ircc_fir);
-               IRDA_MESSAGE(" Overriding SIR address 0x%04x\n", ircc_sir);
-
-               if (smsc_ircc_open(ircc_fir, ircc_sir, ircc_dma, ircc_irq))
-                       ret = -ENODEV;
+       if (smsc_nopnp || !pnp_platform_devices ||
+           ircc_cfg || ircc_fir || ircc_sir ||
+           ircc_dma != DMA_INVAL || ircc_irq != IRQ_INVAL) {
+               ret = smsc_ircc_legacy_probe();
        } else {
-               ret = -ENODEV;
-
-               /* try user provided configuration register base address */
-               if (ircc_cfg > 0) {
-                       IRDA_MESSAGE(" Overriding configuration address "
-                                    "0x%04x\n", ircc_cfg);
-                       if (!smsc_superio_fdc(ircc_cfg))
-                               ret = 0;
-                       if (!smsc_superio_lpc(ircc_cfg))
-                               ret = 0;
-               }
-
-               if (smsc_ircc_look_for_chips() > 0)
-                       ret = 0;
+               if (pnp_register_driver(&smsc_ircc_pnp_driver) == 0)
+                       pnp_driver_registered = 1;
        }
 
-       if (ret)
+       if (ret) {
+               if (pnp_driver_registered)
+                       pnp_unregister_driver(&smsc_ircc_pnp_driver);
                platform_driver_unregister(&smsc_ircc_driver);
+       }
 
        return ret;
 }
@@ -645,7 +697,7 @@ static void smsc_ircc_setup_io(struct smsc_ircc_cb *self,
        self->io.fifo_size = SMSC_IRCC2_FIFO_SIZE;
        self->io.speed = SMSC_IRCC2_C_IRDA_FALLBACK_SPEED;
 
-       if (irq < 255) {
+       if (irq != IRQ_INVAL) {
                if (irq != chip_irq)
                        IRDA_MESSAGE("%s, Overriding IRQ - chip says %d, using %d\n",
                                     driver_name, chip_irq, irq);
@@ -653,7 +705,7 @@ static void smsc_ircc_setup_io(struct smsc_ircc_cb *self,
        } else
                self->io.irq = chip_irq;
 
-       if (dma < 255) {
+       if (dma != DMA_INVAL) {
                if (dma != chip_dma)
                        IRDA_MESSAGE("%s, Overriding DMA - chip says %d, using %d\n",
                                     driver_name, chip_dma, dma);
@@ -1161,7 +1213,7 @@ static int smsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev)
                self->new_speed = speed;
        }
 
-       memcpy(self->tx_buff.head, skb->data, skb->len);
+       skb_copy_from_linear_data(skb, self->tx_buff.head, skb->len);
 
        self->tx_buff.len = skb->len;
        self->tx_buff.data = self->tx_buff.head;
@@ -1412,7 +1464,7 @@ static void smsc_ircc_dma_receive_complete(struct smsc_ircc_cb *self)
        self->stats.rx_bytes += len;
 
        skb->dev = self->netdev;
-       skb->mac.raw  = skb->data;
+       skb_reset_mac_header(skb);
        skb->protocol = htons(ETH_P_IRDA);
        netif_rx(skb);
 }
@@ -1839,6 +1891,9 @@ static void __exit smsc_ircc_cleanup(void)
                        smsc_ircc_close(dev_self[i]);
        }
 
+       if (pnp_driver_registered)
+               pnp_unregister_driver(&smsc_ircc_pnp_driver);
+
        platform_driver_unregister(&smsc_ircc_driver);
 }
 
@@ -2835,9 +2890,9 @@ static int __init smsc_ircc_preconfigure_subsystems(unsigned short ircc_cfg,
                                        tmpconf.fir_io = ircc_fir;
                                if (ircc_sir != 0)
                                        tmpconf.sir_io = ircc_sir;
-                               if (ircc_dma != 0xff)
+                               if (ircc_dma != DMA_INVAL)
                                        tmpconf.fir_dma = ircc_dma;
-                               if (ircc_irq != 0xff)
+                               if (ircc_irq != IRQ_INVAL)
                                        tmpconf.fir_irq = ircc_irq;
 
                                IRDA_MESSAGE("Detected unconfigured %s SMSC IrDA chip, pre-configuring device.\n", conf->name);