Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d3c39d14 authored by Jeff Garzik's avatar Jeff Garzik Committed by Jeff Garzik
Browse files

Automatic merge of /spare/repo/libata-dev branch ahci-msi

parents 8be3de3f 4b0060f4
Loading
Loading
Loading
Loading
+67 −13
Original line number Diff line number Diff line
@@ -39,7 +39,7 @@
#include <asm/io.h>

#define DRV_NAME	"ahci"
#define DRV_VERSION	"1.00"
#define DRV_VERSION	"1.01"


enum {
@@ -134,6 +134,9 @@ enum {
	PORT_CMD_ICC_ACTIVE	= (0x1 << 28), /* Put i/f in active state */
	PORT_CMD_ICC_PARTIAL	= (0x2 << 28), /* Put i/f in partial state */
	PORT_CMD_ICC_SLUMBER	= (0x6 << 28), /* Put i/f in slumber state */

	/* hpriv->flags bits */
	AHCI_FLAG_MSI		= (1 << 0),
};

struct ahci_cmd_hdr {
@@ -183,6 +186,7 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc);
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,
@@ -272,7 +276,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,
};


@@ -795,8 +799,6 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent)
				return rc;
			}
		}

		hpriv->flags |= HOST_CAP_64;
	} else {
		rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
		if (rc) {
@@ -879,16 +881,20 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent)
}

/* 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_dev *pdev, const struct pci_device_id *ent)
	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");
@@ -987,12 +993,17 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
		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,9 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
	probe_ent->mmio_base = mmio_base;
	probe_ent->private_data = hpriv;

	if (have_msi)
		hpriv->flags |= AHCI_FLAG_MSI;

	/* initialize adapter */
	rc = ahci_host_init(probe_ent);
	if (rc)
@@ -1044,7 +1058,11 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
	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 +1070,42 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
	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->flags & AHCI_FLAG_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)
{