aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
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 fc5263c6b102..ee53b227c01e 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -153,6 +153,7 @@ struct ahci_sg {
153 153
154struct ahci_host_priv { 154struct ahci_host_priv {
155 unsigned long flags; 155 unsigned long flags;
156 unsigned int have_msi; /* is PCI MSI enabled? */
156 u32 cap; /* cache of HOST_CAP register */ 157 u32 cap; /* cache of HOST_CAP register */
157 u32 port_map; /* cache of HOST_PORTS_IMPL reg */ 158 u32 port_map; /* cache of HOST_PORTS_IMPL reg */
158}; 159};
@@ -183,6 +184,7 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc);
183static u8 ahci_check_status(struct ata_port *ap); 184static u8 ahci_check_status(struct ata_port *ap);
184static u8 ahci_check_err(struct ata_port *ap); 185static u8 ahci_check_err(struct ata_port *ap);
185static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc); 186static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc);
187static void ahci_remove_one (struct pci_dev *pdev);
186 188
187static Scsi_Host_Template ahci_sht = { 189static Scsi_Host_Template ahci_sht = {
188 .module = THIS_MODULE, 190 .module = THIS_MODULE,
@@ -272,7 +274,7 @@ static struct pci_driver ahci_pci_driver = {
272 .name = DRV_NAME, 274 .name = DRV_NAME,
273 .id_table = ahci_pci_tbl, 275 .id_table = ahci_pci_tbl,
274 .probe = ahci_init_one, 276 .probe = ahci_init_one,
275 .remove = ata_pci_remove_one, 277 .remove = ahci_remove_one,
276}; 278};
277 279
278 280
@@ -879,15 +881,19 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent)
879} 881}
880 882
881/* move to PCI layer, integrate w/ MSI stuff */ 883/* move to PCI layer, integrate w/ MSI stuff */
882static void pci_enable_intx(struct pci_dev *pdev) 884static void pci_intx(struct pci_dev *pdev, int enable)
883{ 885{
884 u16 pci_command; 886 u16 pci_command, new;
885 887
886 pci_read_config_word(pdev, PCI_COMMAND, &pci_command); 888 pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
887 if (pci_command & PCI_COMMAND_INTX_DISABLE) { 889
888 pci_command &= ~PCI_COMMAND_INTX_DISABLE; 890 if (enable)
891 new = pci_command & ~PCI_COMMAND_INTX_DISABLE;
892 else
893 new = pci_command | PCI_COMMAND_INTX_DISABLE;
894
895 if (new != pci_command)
889 pci_write_config_word(pdev, PCI_COMMAND, pci_command); 896 pci_write_config_word(pdev, PCI_COMMAND, pci_command);
890 }
891} 897}
892 898
893static void ahci_print_info(struct ata_probe_ent *probe_ent) 899static void ahci_print_info(struct ata_probe_ent *probe_ent)
@@ -969,7 +975,7 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
969 unsigned long base; 975 unsigned long base;
970 void *mmio_base; 976 void *mmio_base;
971 unsigned int board_idx = (unsigned int) ent->driver_data; 977 unsigned int board_idx = (unsigned int) ent->driver_data;
972 int pci_dev_busy = 0; 978 int have_msi, pci_dev_busy = 0;
973 int rc; 979 int rc;
974 980
975 VPRINTK("ENTER\n"); 981 VPRINTK("ENTER\n");
@@ -987,12 +993,17 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
987 goto err_out; 993 goto err_out;
988 } 994 }
989 995
990 pci_enable_intx(pdev); 996 if (pci_enable_msi(pdev) == 0)
997 have_msi = 1;
998 else {
999 pci_intx(pdev, 1);
1000 have_msi = 0;
1001 }
991 1002
992 probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL); 1003 probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
993 if (probe_ent == NULL) { 1004 if (probe_ent == NULL) {
994 rc = -ENOMEM; 1005 rc = -ENOMEM;
995 goto err_out_regions; 1006 goto err_out_msi;
996 } 1007 }
997 1008
998 memset(probe_ent, 0, sizeof(*probe_ent)); 1009 memset(probe_ent, 0, sizeof(*probe_ent));
@@ -1025,6 +1036,8 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
1025 probe_ent->mmio_base = mmio_base; 1036 probe_ent->mmio_base = mmio_base;
1026 probe_ent->private_data = hpriv; 1037 probe_ent->private_data = hpriv;
1027 1038
1039 hpriv->have_msi = have_msi;
1040
1028 /* initialize adapter */ 1041 /* initialize adapter */
1029 rc = ahci_host_init(probe_ent); 1042 rc = ahci_host_init(probe_ent);
1030 if (rc) 1043 if (rc)
@@ -1044,7 +1057,11 @@ err_out_iounmap:
1044 iounmap(mmio_base); 1057 iounmap(mmio_base);
1045err_out_free_ent: 1058err_out_free_ent:
1046 kfree(probe_ent); 1059 kfree(probe_ent);
1047err_out_regions: 1060err_out_msi:
1061 if (have_msi)
1062 pci_disable_msi(pdev);
1063 else
1064 pci_intx(pdev, 0);
1048 pci_release_regions(pdev); 1065 pci_release_regions(pdev);
1049err_out: 1066err_out:
1050 if (!pci_dev_busy) 1067 if (!pci_dev_busy)
@@ -1052,6 +1069,42 @@ err_out:
1052 return rc; 1069 return rc;
1053} 1070}
1054 1071
1072static void ahci_remove_one (struct pci_dev *pdev)
1073{
1074 struct device *dev = pci_dev_to_dev(pdev);
1075 struct ata_host_set *host_set = dev_get_drvdata(dev);
1076 struct ahci_host_priv *hpriv = host_set->private_data;
1077 struct ata_port *ap;
1078 unsigned int i;
1079 int have_msi;
1080
1081 for (i = 0; i < host_set->n_ports; i++) {
1082 ap = host_set->ports[i];
1083
1084 scsi_remove_host(ap->host);
1085 }
1086
1087 have_msi = hpriv->have_msi;
1088 free_irq(host_set->irq, host_set);
1089 host_set->ops->host_stop(host_set);
1090 iounmap(host_set->mmio_base);
1091
1092 for (i = 0; i < host_set->n_ports; i++) {
1093 ap = host_set->ports[i];
1094
1095 ata_scsi_release(ap->host);
1096 scsi_host_put(ap->host);
1097 }
1098
1099 if (have_msi)
1100 pci_disable_msi(pdev);
1101 else
1102 pci_intx(pdev, 0);
1103 pci_release_regions(pdev);
1104 kfree(host_set);
1105 pci_disable_device(pdev);
1106 dev_set_drvdata(dev, NULL);
1107}
1055 1108
1056static int __init ahci_init(void) 1109static int __init ahci_init(void)
1057{ 1110{