]> err.no Git - linux-2.6/blobdiff - drivers/ata/pata_it821x.c
libata: PCI device should be powered up before being accessed
[linux-2.6] / drivers / ata / pata_it821x.c
index 988ef736b936ca7db206d62fbc6a9809bbdcff76..6bdbb7140dfa522daf5b7bcccb1d0b290e7c79d1 100644 (file)
@@ -105,7 +105,7 @@ struct it821x_dev
 
 /*
  *     We allow users to force the card into non raid mode without
- *     flashing the alternative BIOS. This is also neccessary right now
+ *     flashing the alternative BIOS. This is also necessary right now
  *     for embedded platforms that cannot run a PC BIOS but are using this
  *     device.
  */
@@ -383,7 +383,7 @@ static void it821x_passthru_bmdma_stop(struct ata_queued_cmd *qc)
  *     @ap: ATA port
  *     @device: Device number (not pointer)
  *
- *     Device selection hook. If neccessary perform clock switching
+ *     Device selection hook. If necessary perform clock switching
  */
 
 static void it821x_passthru_dev_select(struct ata_port *ap,
@@ -430,7 +430,7 @@ static unsigned int it821x_smart_qc_issue_prot(struct ata_queued_cmd *qc)
                        return ata_qc_issue_prot(qc);
        }
        printk(KERN_DEBUG "it821x: can't process command 0x%02X\n", qc->tf.command);
-       return AC_ERR_INVALID;
+       return AC_ERR_DEV;
 }
 
 /**
@@ -516,6 +516,37 @@ static void it821x_dev_config(struct ata_device *adev)
                        printk("(%dK stripe)", adev->id[146]);
                printk(".\n");
        }
+       /* This is a controller firmware triggered funny, don't
+          report the drive faulty! */
+       adev->horkage &= ~ATA_HORKAGE_DIAGNOSTIC;
+}
+
+/**
+ *     it821x_ident_hack       -       Hack identify data up
+ *     @ap: Port
+ *
+ *     Walk the devices on this firmware driven port and slightly
+ *     mash the identify data to stop us and common tools trying to
+ *     use features not firmware supported. The firmware itself does
+ *     some masking (eg SMART) but not enough.
+ *
+ *     This is a bit of an abuse of the cable method, but it is the
+ *     only method called at the right time. We could modify the libata
+ *     core specifically for ident hacking but while we have one offender
+ *     it seems better to keep the fallout localised.
+ */
+
+static int it821x_ident_hack(struct ata_port *ap)
+{
+       struct ata_device *adev;
+       ata_link_for_each_dev(adev, &ap->link) {
+               if (ata_dev_enabled(adev)) {
+                       adev->id[84] &= ~(1 << 6);      /* No FUA */
+                       adev->id[85] &= ~(1 << 10);     /* No HPA */
+                       adev->id[76] = 0;               /* No NCQ/AN etc */
+               }
+       }
+       return ata_cable_unknown(ap);
 }
 
 
@@ -533,7 +564,7 @@ static int it821x_check_atapi_dma(struct ata_queued_cmd *qc)
        struct it821x_dev *itdev = ap->private_data;
 
        /* Only use dma for transfers to/from the media. */
-       if (qc->nbytes < 2048)
+       if (ata_qc_raw_nbytes(qc) < 2048)
                return -EOPNOTSUPP;
 
        /* No ATAPI DMA in smart mode */
@@ -634,7 +665,7 @@ static struct ata_port_operations it821x_smart_port_ops = {
        .thaw           = ata_bmdma_thaw,
        .error_handler  = ata_bmdma_error_handler,
        .post_internal_cmd = ata_bmdma_post_internal_cmd,
-       .cable_detect   = ata_cable_unknown,
+       .cable_detect   = it821x_ident_hack,
 
        .bmdma_setup    = ata_bmdma_setup,
        .bmdma_start    = ata_bmdma_start,
@@ -728,6 +759,11 @@ static int it821x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
 
        const struct ata_port_info *ppi[] = { NULL, NULL };
        static char *mode[2] = { "pass through", "smart" };
+       int rc;
+
+       rc = pcim_enable_device(pdev);
+       if (rc)
+               return rc;
 
        /* Force the card into bypass mode if so requested */
        if (it8212_noraid) {
@@ -749,10 +785,17 @@ static int it821x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
 #ifdef CONFIG_PM
 static int it821x_reinit_one(struct pci_dev *pdev)
 {
+       struct ata_host *host = dev_get_drvdata(&pdev->dev);
+       int rc;
+
+       rc = ata_pci_device_do_resume(pdev);
+       if (rc)
+               return rc;
        /* Resume - turn raid back off if need be */
        if (it8212_noraid)
                it821x_disable_raid(pdev);
-       return ata_pci_device_resume(pdev);
+       ata_host_resume(host);
+       return rc;
 }
 #endif