AHCI PCI MSI support, update 1
PATCH 1/1 AHCI PCI MSI support, update 1
I just updated the AHCI PCI MSI support patch to support the latest ->host_stop() semantics changes that just made it into upstream.
This patch, until its merged, may always be found in the 'ahci-msi' branch of rsync://rsync.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev.git
drivers/scsi/ahci.c +64 -11
@@ -39,7 +39,7 @@#include <asm/io.h> #define DRV_NAME "ahci" -#define DRV_VERSION "1.00" +#define DRV_VERSION "1.01"enum {
@@ -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,6 +184,7 @@ static void ahci_qc_prep(struct ata_queustatic 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 ,
@@ -272,7 +274,7 @@ static struct pci_driver ahci_pci_driver .name = DRV_NAME, .id_table = ahci_pci_tbl, .probe = ahci_init_one, - .remove = ata_pci_remove_one, + .remove = ahci_remove_one, };
@@ -879,15 +881,19 @@ static int ahci_host_init(struct ata_pro }/* 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)
@@ -969,7 +975,7 @@ static int ahci_init_one (struct pci_devunsigned 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" );
@@ -987,12 +993,17 @@ static int ahci_init_one (struct pci_dev 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));
@@ -1025,6 +1036,8 @@ static int ahci_init_one (struct pci_dev 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)
@@ -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)
@@ -1052,6 +1069,42 @@ err_out: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); + +for (i =0 ; i < host_set->n_ports; i++) { + ap = host_set->ports[i]; + +ata_scsi_release (ap->host); +scsi_host_put (ap->host); + } + + host_set->ops->host_stop (host_set); +kfree (host_set); + +if (have_msi) +pci_disable_msi (pdev); +else +pci_intx (pdev,0 ); +pci_release_regions (pdev); +pci_disable_device (pdev); +dev_set_drvdata (dev,NULL ); +}static int __init ahci_init (void ) {
Quoted 7 lines · Jeff Garzik
I just updated the AHCI PCI MSI support patch to support the latest ->host_stop() semantics changes that just made it into upstream.
This patch, until its merged, may always be found in the 'ahci-msi' branch of rsync://rsync.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev.git
Tested on an ich6 based system, with this ahci controller:
centera:~ # lspci -s 0000:00:1f.2 -v
0000:00:1f.2 IDE interface: Intel Corp. I/O Controller Hub SATA cc=raid (rev 03) (prog-if 8f [Master SecP SecO PriP PriO])
Subsystem: Tyan Computer: Unknown device 5150
Flags: bus master, 66Mhz, medium devsel, latency 0, IRQ 169
I/O ports at e900
I/O ports at ea00 [size=4]
I/O ports at eb00 [size=8]
I/O ports at ec00 [size=4]
I/O ports at ed00 [size=16]
Memory at d03c3000 (32-bit, non-prefetchable) [size=1K]
Capabilities: [70] Power Management version 2And system boots and works fine, MSI isn't enabled of course.
Also tested on an ich7 based system (945G express chipset), with this ahci controller:
nelson:~ # lspci -s 0000:00:1f.2 -v
0000:00:1f.2 Class 0106: Intel Corporation I/O Controller Hub SATA cc=AHCI (rev 01) (prog-if 01)
Subsystem: Intel Corporation: Unknown device e302
Flags: bus master, 66Mhz, medium devsel, latency 0, IRQ 201
I/O ports at 40d8 [size=8]
I/O ports at 40f4 [size=4]
I/O ports at 40d0 [size=8]
I/O ports at 40f0 [size=4]
I/O ports at 4020 [size=32]
Memory at 48304000 (32-bit, non-prefetchable) [size=1K]
Capabilities: [80] Message Signalled Interrupts: 64bit- Queue=0/0 Enable+
Capabilities: [70] Power Management version 2
Capabilities: [a8] #12 [0010]System boots and works fine (typing this message here), MSI is enabled. I double checked with an added printk :-)
So that's at least one ACK for you. Now running NCQ and MSI enabled ahci, I'm not sure SATA gets any better!
Signature · 1 line
Jens Axboe
Quoted 2 lines · Jens Axboe
System boots and works fine (typing this message here), MSI is enabled. I double checked with an added printk :-)
Any chance you could post a full /proc/interrupts output for this box?
Quoted 2 lines
So that's at least one ACK for you. Now running NCQ and MSI enabled ahci, I'm not sure SATA gets any better!
<grin>
Thanks,
Jeff
Quoted 5 lines · Jeff Garzik
Quoted 2 lines · Jens Axboe
System boots and works fine (typing this message here), MSI is enabled. I double checked with an added printk :-)
Any chance you could post a full
/proc/interruptsoutput for this box?
Sure:
CPU0 CPU1
0: 349415 330112 IO-APIC-edge timer 4: 10 0 IO-APIC-edge serial 8: 0 0 IO-APIC-edge rtc 9: 0 0 IO-APIC-level acpi 14: 2 0 IO-APIC-edge ide0 169: 0 0 IO-APIC-level uhci_hcd:usb4 177: 2565 0 IO-APIC-level eth0 185: 6932 7195 IO-APIC-level uhci_hcd:usb3 201: 8991 5154 PCI-MSI libata 209: 3 0 IO-APIC-level ehci_hcd:usb1, uhci_hcd:usb2 217: 0 0 IO-APIC-level uhci_hcd:usb5 225: 345 51 IO-APIC-level HDA Intel NMI: 150 83 LOC: 671016 671636 ERR: 1 MIS: 0
Signature · 1 line
Jens Axboe