]> rtime.felk.cvut.cz Git - lisovros/linux_canprio.git/blobdiff - drivers/ide/pci/it821x.c
ide: it821x in pass-through mode segfaults in 2.6.26-stable
[lisovros/linux_canprio.git] / drivers / ide / pci / it821x.c
index 1597f0cc1bf1ced36b76caa3b7e264f563f5a3f0..cbf647202994d2c273fd8a3d9d6cf38eac29fe54 100644 (file)
@@ -418,7 +418,7 @@ static void it821x_set_dma_mode(ide_drive_t *drive, const u8 speed)
 }
 
 /**
- *     ata66_it821x    -       check for 80 pin cable
+ *     it821x_cable_detect     -       cable detection
  *     @hwif: interface to check
  *
  *     Check for the presence of an ATA66 capable cable on the
@@ -426,7 +426,7 @@ static void it821x_set_dma_mode(ide_drive_t *drive, const u8 speed)
  *     the needed logic onboard.
  */
 
-static u8 __devinit ata66_it821x(ide_hwif_t *hwif)
+static u8 __devinit it821x_cable_detect(ide_hwif_t *hwif)
 {
        /* The reference driver also only does disk side */
        return ATA_CBL_PATA80;
@@ -511,6 +511,17 @@ static void __devinit it821x_quirkproc(ide_drive_t *drive)
 
 }
 
+static struct ide_dma_ops it821x_pass_through_dma_ops = {
+       .dma_host_set           = ide_dma_host_set,
+       .dma_setup              = ide_dma_setup,
+       .dma_exec_cmd           = ide_dma_exec_cmd,
+       .dma_start              = it821x_dma_start,
+       .dma_end                = it821x_dma_end,
+       .dma_test_irq           = ide_dma_test_irq,
+       .dma_timeout            = ide_dma_timeout,
+       .dma_lost_irq           = ide_dma_lost_irq,
+};
+
 /**
  *     init_hwif_it821x        -       set up hwif structs
  *     @hwif: interface to set up
@@ -523,16 +534,10 @@ static void __devinit it821x_quirkproc(ide_drive_t *drive)
 static void __devinit init_hwif_it821x(ide_hwif_t *hwif)
 {
        struct pci_dev *dev = to_pci_dev(hwif->dev);
-       struct it821x_dev *idev = kzalloc(sizeof(struct it821x_dev), GFP_KERNEL);
+       struct it821x_dev **itdevs = (struct it821x_dev **)pci_get_drvdata(dev);
+       struct it821x_dev *idev = itdevs[hwif->channel];
        u8 conf;
 
-       hwif->quirkproc = &it821x_quirkproc;
-
-       if (idev == NULL) {
-               printk(KERN_ERR "it821x: out of memory, falling back to legacy behaviour.\n");
-               return;
-       }
-
        ide_set_hwifdata(hwif, idev);
 
        pci_read_config_byte(dev, 0x50, &conf);
@@ -567,17 +572,11 @@ static void __devinit init_hwif_it821x(ide_hwif_t *hwif)
        }
 
        if (idev->smart == 0) {
-               hwif->set_pio_mode = &it821x_set_pio_mode;
-               hwif->set_dma_mode = &it821x_set_dma_mode;
-
                /* MWDMA/PIO clock switching for pass through mode */
-               hwif->dma_start = &it821x_dma_start;
-               hwif->ide_dma_end = &it821x_dma_end;
+               hwif->dma_ops = &it821x_pass_through_dma_ops;
        } else
                hwif->host_flags |= IDE_HFLAG_NO_SET_MODE;
 
-       hwif->cable_detect = ata66_it821x;
-
        if (hwif->dma_base == 0)
                return;
 
@@ -617,13 +616,20 @@ static unsigned int __devinit init_chipset_it821x(struct pci_dev *dev, const cha
        return 0;
 }
 
+static const struct ide_port_ops it821x_port_ops = {
+       /* it821x_set_{pio,dma}_mode() are only used in pass-through mode */
+       .set_pio_mode           = it821x_set_pio_mode,
+       .set_dma_mode           = it821x_set_dma_mode,
+       .quirkproc              = it821x_quirkproc,
+       .cable_detect           = it821x_cable_detect,
+};
 
 #define DECLARE_ITE_DEV(name_str)                      \
        {                                               \
                .name           = name_str,             \
                .init_chipset   = init_chipset_it821x,  \
                .init_hwif      = init_hwif_it821x,     \
-               .host_flags     = IDE_HFLAG_BOOTABLE,   \
+               .port_ops       = &it821x_port_ops,     \
                .pio_mask       = ATA_PIO4,             \
        }
 
@@ -642,6 +648,22 @@ static const struct ide_port_info it821x_chipsets[] __devinitdata = {
 
 static int __devinit it821x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
+       struct it821x_dev *itdevs[2] = { NULL, NULL} , *itdev;
+       unsigned int i;
+
+       for (i = 0; i < 2; i++) {
+               itdev = kzalloc(sizeof(*itdev), GFP_KERNEL);
+               if (itdev == NULL) {
+                       kfree(itdevs[0]);
+                       printk(KERN_ERR "it821x: out of memory\n");
+                       return -ENOMEM;
+               }
+
+               itdevs[i] = itdev;
+       }
+
+       pci_set_drvdata(dev, itdevs);
+
        return ide_setup_pci_device(dev, &it821x_chipsets[id->driver_data]);
 }
 
@@ -667,7 +689,7 @@ static int __init it821x_ide_init(void)
 module_init(it821x_ide_init);
 
 module_param_named(noraid, it8212_noraid, int, S_IRUGO);
-MODULE_PARM_DESC(it8212_noraid, "Force card into bypass mode");
+MODULE_PARM_DESC(noraid, "Force card into bypass mode");
 
 MODULE_AUTHOR("Alan Cox");
 MODULE_DESCRIPTION("PCI driver module for the ITE 821x");