aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorJeff Garzik <jgarzik@pobox.com>2005-05-12 15:03:42 -0400
committerJeff Garzik <jgarzik@pobox.com>2005-05-12 15:03:42 -0400
commit907f4678c114a125fe4584758681c31bf3d627da (patch)
tree630fac16df73c923db4ae4dd1ab8a24b1a8a4688 /drivers/scsi
parent88d7bd8cb9eb8d64bf7997600b0d64f7834047c5 (diff)
[libata ahci] support PCI MSI interrupt vector
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/ahci.c73
1 files changed, 63 insertions, 10 deletions
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index da5bd33d982d..5e2a1e8b9039 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -152,6 +152,7 @@ struct ahci_sg {
152 152
153struct ahci_host_priv { 153struct ahci_host_priv {
154 unsigned long flags; 154 unsigned long flags;
155 unsigned int have_msi; /* is PCI MSI enabled? */
155 u32 cap; /* cache of HOST_CAP register */ 156 u32 cap; /* cache of HOST_CAP register */
156 u32 port_map; /* cache of HOST_PORTS_IMPL reg */ 157 u32 port_map; /* cache of HOST_PORTS_IMPL reg */
157}; 158};
@@ -182,6 +183,7 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc);
182static u8 ahci_check_status(struct ata_port *ap); 183static u8 ahci_check_status(struct ata_port *ap);
183static u8 ahci_check_err(struct ata_port *ap); 184static u8 ahci_check_err(struct ata_port *ap);
184static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc); 185static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc);
186static void ahci_remove_one (struct pci_dev *pdev);
185 187
186static Scsi_Host_Template ahci_sht = { 188static Scsi_Host_Template ahci_sht = {
187 .module = THIS_MODULE, 189 .module = THIS_MODULE,
@@ -271,7 +273,7 @@ static struct pci_driver ahci_pci_driver = {
271 .name = DRV_NAME, 273 .name = DRV_NAME,
272 .id_table = ahci_pci_tbl, 274 .id_table = ahci_pci_tbl,
273 .probe = ahci_init_one, 275 .probe = ahci_init_one,
274 .remove = ata_pci_remove_one, 276 .remove = ahci_remove_one,
275}; 277};
276 278
277 279
@@ -876,15 +878,19 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent)
876} 878}
877 879
878/* move to PCI layer, integrate w/ MSI stuff */ 880/* move to PCI layer, integrate w/ MSI stuff */
879static void pci_enable_intx(struct pci_dev *pdev) 881static void pci_intx(struct pci_dev *pdev, int enable)
880{ 882{
881 u16 pci_command; 883 u16 pci_command, new;
882 884
883 pci_read_config_word(pdev, PCI_COMMAND, &pci_command); 885 pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
884 if (pci_command & PCI_COMMAND_INTX_DISABLE) { 886
885 pci_command &= ~PCI_COMMAND_INTX_DISABLE; 887 if (enable)
888 new = pci_command & ~PCI_COMMAND_INTX_DISABLE;
889 else
890 new = pci_command | PCI_COMMAND_INTX_DISABLE;
891
892 if (new != pci_command)
886 pci_write_config_word(pdev, PCI_COMMAND, pci_command); 893 pci_write_config_word(pdev, PCI_COMMAND, pci_command);
887 }
888} 894}
889 895
890static void ahci_print_info(struct ata_probe_ent *probe_ent) 896static void ahci_print_info(struct ata_probe_ent *probe_ent)
@@ -966,7 +972,7 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
966 unsigned long base; 972 unsigned long base;
967 void *mmio_base; 973 void *mmio_base;
968 unsigned int board_idx = (unsigned int) ent->driver_data; 974 unsigned int board_idx = (unsigned int) ent->driver_data;
969 int pci_dev_busy = 0; 975 int have_msi, pci_dev_busy = 0;
970 int rc; 976 int rc;
971 977
972 VPRINTK("ENTER\n"); 978 VPRINTK("ENTER\n");
@@ -984,12 +990,17 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
984 goto err_out; 990 goto err_out;
985 } 991 }
986 992
987 pci_enable_intx(pdev); 993 if (pci_enable_msi(pdev) == 0)
994 have_msi = 1;
995 else {
996 pci_intx(pdev, 1);
997 have_msi = 0;
998 }
988 999
989 probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL); 1000 probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
990 if (probe_ent == NULL) { 1001 if (probe_ent == NULL) {
991 rc = -ENOMEM; 1002 rc = -ENOMEM;
992 goto err_out_regions; 1003 goto err_out_msi;
993 } 1004 }
994 1005
995 memset(probe_ent, 0, sizeof(*probe_ent)); 1006 memset(probe_ent, 0, sizeof(*probe_ent));
@@ -1022,6 +1033,8 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
1022 probe_ent->mmio_base = mmio_base; 1033 probe_ent->mmio_base = mmio_base;
1023 probe_ent->private_data = hpriv; 1034 probe_ent->private_data = hpriv;
1024 1035
1036 hpriv->have_msi = have_msi;
1037
1025 /* initialize adapter */ 1038 /* initialize adapter */
1026 rc = ahci_host_init(probe_ent); 1039 rc = ahci_host_init(probe_ent);
1027 if (rc) 1040 if (rc)
@@ -1041,7 +1054,11 @@ err_out_iounmap:
1041 iounmap(mmio_base); 1054 iounmap(mmio_base);
1042err_out_free_ent: 1055err_out_free_ent:
1043 kfree(probe_ent); 1056 kfree(probe_ent);
1044err_out_regions: 1057err_out_msi:
1058 if (have_msi)
1059 pci_disable_msi(pdev);
1060 else
1061 pci_intx(pdev, 0);
1045 pci_release_regions(pdev); 1062 pci_release_regions(pdev);
1046err_out: 1063err_out:
1047 if (!pci_dev_busy) 1064 if (!pci_dev_busy)
@@ -1049,6 +1066,42 @@ err_out:
1049 return rc; 1066 return rc;
1050} 1067}
1051 1068
1069static void ahci_remove_one (struct pci_dev *pdev)
1070{
1071 struct device *dev = pci_dev_to_dev(pdev);
1072 struct ata_host_set *host_set = dev_get_drvdata(dev);
1073 struct ahci_host_priv *hpriv = host_set->private_data;
1074 struct ata_port *ap;
1075 unsigned int i;
1076 int have_msi;
1077
1078 for (i = 0; i < host_set->n_ports; i++) {
1079 ap = host_set->ports[i];
1080
1081 scsi_remove_host(ap->host);
1082 }
1083
1084 have_msi = hpriv->have_msi;
1085 free_irq(host_set->irq, host_set);
1086 host_set->ops->host_stop(host_set);
1087 iounmap(host_set->mmio_base);
1088
1089 for (i = 0; i < host_set->n_ports; i++) {
1090 ap = host_set->ports[i];
1091
1092 ata_scsi_release(ap->host);
1093 scsi_host_put(ap->host);
1094 }
1095
1096 if (have_msi)
1097 pci_disable_msi(pdev);
1098 else
1099 pci_intx(pdev, 0);
1100 pci_release_regions(pdev);
1101 kfree(host_set);
1102 pci_disable_device(pdev);
1103 dev_set_drvdata(dev, NULL);
1104}
1052 1105
1053static int __init ahci_init(void) 1106static int __init ahci_init(void)
1054{ 1107{