]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/commitdiff
Automatic merge of rsync://rsync.kernel.org/pub/scm/linux/kernel/git/torvalds/linux...
author <jgarzik@pretzel.yyz.us> <>
Tue, 31 May 2005 15:50:32 +0000 (11:50 -0400)
committerJeff Garzik <jgarzik@pobox.com>
Tue, 31 May 2005 15:50:32 +0000 (11:50 -0400)
1  2 
drivers/scsi/ahci.c

diff --combined drivers/scsi/ahci.c
index 5e2a1e8b9039a995b04b064a35f5e25f7039529a,fc5263c6b10267b2869cf8b3a1967b97490b392b..ee53b227c01ee6fad0a6064af7062514db2321da
@@@ -32,6 -32,7 +32,7 @@@
  #include <linux/delay.h>
  #include <linux/interrupt.h>
  #include <linux/sched.h>
+ #include <linux/dma-mapping.h>
  #include "scsi.h"
  #include <scsi/scsi_host.h>
  #include <linux/libata.h>
@@@ -152,7 -153,6 +153,7 @@@ struct ahci_sg 
  
  struct ahci_host_priv {
        unsigned long           flags;
 +      unsigned int            have_msi; /* is PCI MSI enabled? */
        u32                     cap;    /* cache of HOST_CAP register */
        u32                     port_map; /* cache of HOST_PORTS_IMPL reg */
  };
@@@ -183,7 -183,6 +184,7 @@@ static void ahci_qc_prep(struct ata_que
  static u8 ahci_check_status(struct ata_port *ap);
  static u8 ahci_check_err(struct ata_port *ap);
  static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc);
 +static void ahci_remove_one (struct pci_dev *pdev);
  
  static Scsi_Host_Template ahci_sht = {
        .module                 = THIS_MODULE,
@@@ -273,7 -272,7 +274,7 @@@ static struct pci_driver ahci_pci_drive
        .name                   = DRV_NAME,
        .id_table               = ahci_pci_tbl,
        .probe                  = ahci_init_one,
 -      .remove                 = ata_pci_remove_one,
 +      .remove                 = ahci_remove_one,
  };
  
  
@@@ -291,6 -290,8 +292,8 @@@ static void ahci_host_stop(struct ata_h
  {
        struct ahci_host_priv *hpriv = host_set->private_data;
        kfree(hpriv);
+       ata_host_stop(host_set);
  }
  
  static int ahci_port_start(struct ata_port *ap)
@@@ -878,19 -879,15 +881,19 @@@ static int ahci_host_init(struct ata_pr
  }
  
  /* move to PCI layer, integrate w/ MSI stuff */
 -static void pci_enable_intx(struct pci_dev *pdev)
 +static void pci_intx(struct pci_dev *pdev, int enable)
  {
 -      u16 pci_command;
 +      u16 pci_command, new;
  
        pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
 -      if (pci_command & PCI_COMMAND_INTX_DISABLE) {
 -              pci_command &= ~PCI_COMMAND_INTX_DISABLE;
 +
 +      if (enable)
 +              new = pci_command & ~PCI_COMMAND_INTX_DISABLE;
 +      else
 +              new = pci_command | PCI_COMMAND_INTX_DISABLE;
 +
 +      if (new != pci_command)
                pci_write_config_word(pdev, PCI_COMMAND, pci_command);
 -      }
  }
  
  static void ahci_print_info(struct ata_probe_ent *probe_ent)
@@@ -972,7 -969,7 +975,7 @@@ static int ahci_init_one (struct pci_de
        unsigned long base;
        void *mmio_base;
        unsigned int board_idx = (unsigned int) ent->driver_data;
 -      int pci_dev_busy = 0;
 +      int have_msi, pci_dev_busy = 0;
        int rc;
  
        VPRINTK("ENTER\n");
                goto err_out;
        }
  
 -      pci_enable_intx(pdev);
 +      if (pci_enable_msi(pdev) == 0)
 +              have_msi = 1;
 +      else {
 +              pci_intx(pdev, 1);
 +              have_msi = 0;
 +      }
  
        probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
        if (probe_ent == NULL) {
                rc = -ENOMEM;
 -              goto err_out_regions;
 +              goto err_out_msi;
        }
  
        memset(probe_ent, 0, sizeof(*probe_ent));
        probe_ent->mmio_base = mmio_base;
        probe_ent->private_data = hpriv;
  
 +      hpriv->have_msi = have_msi;
 +
        /* initialize adapter */
        rc = ahci_host_init(probe_ent);
        if (rc)
@@@ -1054,11 -1044,7 +1057,11 @@@ err_out_iounmap
        iounmap(mmio_base);
  err_out_free_ent:
        kfree(probe_ent);
 -err_out_regions:
 +err_out_msi:
 +      if (have_msi)
 +              pci_disable_msi(pdev);
 +      else
 +              pci_intx(pdev, 0);
        pci_release_regions(pdev);
  err_out:
        if (!pci_dev_busy)
        return rc;
  }
  
 +static void ahci_remove_one (struct pci_dev *pdev)
 +{
 +      struct device *dev = pci_dev_to_dev(pdev);
 +      struct ata_host_set *host_set = dev_get_drvdata(dev);
 +      struct ahci_host_priv *hpriv = host_set->private_data;
 +      struct ata_port *ap;
 +      unsigned int i;
 +      int have_msi;
 +
 +      for (i = 0; i < host_set->n_ports; i++) {
 +              ap = host_set->ports[i];
 +
 +              scsi_remove_host(ap->host);
 +      }
 +
 +      have_msi = hpriv->have_msi;
 +      free_irq(host_set->irq, host_set);
 +      host_set->ops->host_stop(host_set);
 +      iounmap(host_set->mmio_base);
 +
 +      for (i = 0; i < host_set->n_ports; i++) {
 +              ap = host_set->ports[i];
 +
 +              ata_scsi_release(ap->host);
 +              scsi_host_put(ap->host);
 +      }
 +
 +      if (have_msi)
 +              pci_disable_msi(pdev);
 +      else
 +              pci_intx(pdev, 0);
 +      pci_release_regions(pdev);
 +      kfree(host_set);
 +      pci_disable_device(pdev);
 +      dev_set_drvdata(dev, NULL);
 +}
  
  static int __init ahci_init(void)
  {