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

Commit 4c718423 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull libata fixes from Tejun Heo:
 "Nothing too interesting.  All fixes are ahci_platform related"

* 'for-3.16-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata:
  ahci_xgene: fix the dma state machine lockup for the IDENTIFY DEVICE PIO mode command.
  libahci: export ahci_qc_issue() and ahci_start_fix_rx()
  ata: ahci_imx: warn when disabling ahci link
  ahci: disable ncq feature for hisilicon sata
  ahci: imx: manage only sata_ref_clk in imx_sata_enable[disable]
  libahci_platform: Fail when PHY required but PHY support disabled
parents 40f61237 2a0bdff6
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -371,7 +371,9 @@ int ahci_do_softreset(struct ata_link *link, unsigned int *class,
		      int pmp, unsigned long deadline,
		      int (*check_ready)(struct ata_link *link));

unsigned int ahci_qc_issue(struct ata_queued_cmd *qc);
int ahci_stop_engine(struct ata_port *ap);
void ahci_start_fis_rx(struct ata_port *ap);
void ahci_start_engine(struct ata_port *ap);
int ahci_check_ready(struct ata_link *link);
int ahci_kick_engine(struct ata_port *ap);
+34 −4
Original line number Diff line number Diff line
@@ -58,6 +58,8 @@ enum ahci_imx_type {
struct imx_ahci_priv {
	struct platform_device *ahci_pdev;
	enum ahci_imx_type type;
	struct clk *sata_clk;
	struct clk *sata_ref_clk;
	struct clk *ahb_clk;
	struct regmap *gpr;
	bool no_device;
@@ -224,7 +226,7 @@ static int imx_sata_enable(struct ahci_host_priv *hpriv)
			return ret;
	}

	ret = ahci_platform_enable_clks(hpriv);
	ret = clk_prepare_enable(imxpriv->sata_ref_clk);
	if (ret < 0)
		goto disable_regulator;

@@ -291,7 +293,7 @@ static void imx_sata_disable(struct ahci_host_priv *hpriv)
				   !IMX6Q_GPR13_SATA_MPLL_CLK_EN);
	}

	ahci_platform_disable_clks(hpriv);
	clk_disable_unprepare(imxpriv->sata_ref_clk);

	if (hpriv->target_pwr)
		regulator_disable(hpriv->target_pwr);
@@ -324,6 +326,9 @@ static void ahci_imx_error_handler(struct ata_port *ap)
	writel(reg_val | IMX_P0PHYCR_TEST_PDDQ, mmio + IMX_P0PHYCR);
	imx_sata_disable(hpriv);
	imxpriv->no_device = true;

	dev_info(ap->dev, "no device found, disabling link.\n");
	dev_info(ap->dev, "pass " MODULE_PARAM_PREFIX ".hotplug=1 to enable hotplug\n");
}

static int ahci_imx_softreset(struct ata_link *link, unsigned int *class,
@@ -385,6 +390,19 @@ static int imx_ahci_probe(struct platform_device *pdev)
	imxpriv->no_device = false;
	imxpriv->first_time = true;
	imxpriv->type = (enum ahci_imx_type)of_id->data;

	imxpriv->sata_clk = devm_clk_get(dev, "sata");
	if (IS_ERR(imxpriv->sata_clk)) {
		dev_err(dev, "can't get sata clock.\n");
		return PTR_ERR(imxpriv->sata_clk);
	}

	imxpriv->sata_ref_clk = devm_clk_get(dev, "sata_ref");
	if (IS_ERR(imxpriv->sata_ref_clk)) {
		dev_err(dev, "can't get sata_ref clock.\n");
		return PTR_ERR(imxpriv->sata_ref_clk);
	}

	imxpriv->ahb_clk = devm_clk_get(dev, "ahb");
	if (IS_ERR(imxpriv->ahb_clk)) {
		dev_err(dev, "can't get ahb clock.\n");
@@ -407,10 +425,14 @@ static int imx_ahci_probe(struct platform_device *pdev)

	hpriv->plat_data = imxpriv;

	ret = imx_sata_enable(hpriv);
	ret = clk_prepare_enable(imxpriv->sata_clk);
	if (ret)
		return ret;

	ret = imx_sata_enable(hpriv);
	if (ret)
		goto disable_clk;

	/*
	 * Configure the HWINIT bits of the HOST_CAP and HOST_PORTS_IMPL,
	 * and IP vendor specific register IMX_TIMER1MS.
@@ -435,16 +457,24 @@ static int imx_ahci_probe(struct platform_device *pdev)
	ret = ahci_platform_init_host(pdev, hpriv, &ahci_imx_port_info,
				      0, 0, 0);
	if (ret)
		imx_sata_disable(hpriv);
		goto disable_sata;

	return 0;

disable_sata:
	imx_sata_disable(hpriv);
disable_clk:
	clk_disable_unprepare(imxpriv->sata_clk);
	return ret;
}

static void ahci_imx_host_stop(struct ata_host *host)
{
	struct ahci_host_priv *hpriv = host->private_data;
	struct imx_ahci_priv *imxpriv = hpriv->plat_data;

	imx_sata_disable(hpriv);
	clk_disable_unprepare(imxpriv->sata_clk);
}

#ifdef CONFIG_PM_SLEEP
+1 −1
Original line number Diff line number Diff line
@@ -58,7 +58,7 @@ static int ahci_probe(struct platform_device *pdev)
	}

	if (of_device_is_compatible(dev->of_node, "hisilicon,hisi-ahci"))
		hflags |= AHCI_HFLAG_NO_FBS;
		hflags |= AHCI_HFLAG_NO_FBS | AHCI_HFLAG_NO_NCQ;

	rc = ahci_platform_init_host(pdev, hpriv, &ahci_port_info,
				     hflags, 0, 0);
+47 −13
Original line number Diff line number Diff line
@@ -78,6 +78,7 @@
struct xgene_ahci_context {
	struct ahci_host_priv *hpriv;
	struct device *dev;
	u8 last_cmd[MAX_AHCI_CHN_PERCTR]; /* tracking the last command issued*/
	void __iomem *csr_core;		/* Core CSR address of IP */
	void __iomem *csr_diag;		/* Diag CSR address of IP */
	void __iomem *csr_axi;		/* AXI CSR address of IP */
@@ -97,6 +98,50 @@ static int xgene_ahci_init_memram(struct xgene_ahci_context *ctx)
	return 0;
}

/**
 * xgene_ahci_restart_engine - Restart the dma engine.
 * @ap : ATA port of interest
 *
 * Restarts the dma engine inside the controller.
 */
static int xgene_ahci_restart_engine(struct ata_port *ap)
{
	struct ahci_host_priv *hpriv = ap->host->private_data;

	ahci_stop_engine(ap);
	ahci_start_fis_rx(ap);
	hpriv->start_engine(ap);

	return 0;
}

/**
 * xgene_ahci_qc_issue - Issue commands to the device
 * @qc: Command to issue
 *
 * Due to Hardware errata for IDENTIFY DEVICE command, the controller cannot
 * clear the BSY bit after receiving the PIO setup FIS. This results in the dma
 * state machine goes into the CMFatalErrorUpdate state and locks up. By
 * restarting the dma engine, it removes the controller out of lock up state.
 */
static unsigned int xgene_ahci_qc_issue(struct ata_queued_cmd *qc)
{
	struct ata_port *ap = qc->ap;
	struct ahci_host_priv *hpriv = ap->host->private_data;
	struct xgene_ahci_context *ctx = hpriv->plat_data;
	int rc = 0;

	if (unlikely(ctx->last_cmd[ap->port_no] == ATA_CMD_ID_ATA))
		xgene_ahci_restart_engine(ap);

	rc = ahci_qc_issue(qc);

	/* Save the last command issued */
	ctx->last_cmd[ap->port_no] = qc->tf.command;

	return rc;
}

/**
 * xgene_ahci_read_id - Read ID data from the specified device
 * @dev: device
@@ -104,14 +149,12 @@ static int xgene_ahci_init_memram(struct xgene_ahci_context *ctx)
 * @id: data buffer
 *
 * This custom read ID function is required due to the fact that the HW
 * does not support DEVSLP and the controller state machine may get stuck
 * after processing the ID query command.
 * does not support DEVSLP.
 */
static unsigned int xgene_ahci_read_id(struct ata_device *dev,
				       struct ata_taskfile *tf, u16 *id)
{
	u32 err_mask;
	void __iomem *port_mmio = ahci_port_base(dev->link->ap);

	err_mask = ata_do_dev_read_id(dev, tf, id);
	if (err_mask)
@@ -133,16 +176,6 @@ static unsigned int xgene_ahci_read_id(struct ata_device *dev,
	 */
	id[ATA_ID_FEATURE_SUPP] &= ~(1 << 8);

	/*
	 * Due to HW errata, restart the port if no other command active.
	 * Otherwise the controller may get stuck.
	 */
	if (!readl(port_mmio + PORT_CMD_ISSUE)) {
		writel(PORT_CMD_FIS_RX, port_mmio + PORT_CMD);
		readl(port_mmio + PORT_CMD);	/* Force a barrier */
		writel(PORT_CMD_FIS_RX | PORT_CMD_START, port_mmio + PORT_CMD);
		readl(port_mmio + PORT_CMD);	/* Force a barrier */
	}
	return 0;
}

@@ -300,6 +333,7 @@ static struct ata_port_operations xgene_ahci_ops = {
	.host_stop = xgene_ahci_host_stop,
	.hardreset = xgene_ahci_hardreset,
	.read_id = xgene_ahci_read_id,
	.qc_issue = xgene_ahci_qc_issue,
};

static const struct ata_port_info xgene_ahci_port_info = {
+4 −3
Original line number Diff line number Diff line
@@ -68,7 +68,6 @@ static ssize_t ahci_transmit_led_message(struct ata_port *ap, u32 state,

static int ahci_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val);
static int ahci_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val);
static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc);
static bool ahci_qc_fill_rtf(struct ata_queued_cmd *qc);
static int ahci_port_start(struct ata_port *ap);
static void ahci_port_stop(struct ata_port *ap);
@@ -620,7 +619,7 @@ int ahci_stop_engine(struct ata_port *ap)
}
EXPORT_SYMBOL_GPL(ahci_stop_engine);

static void ahci_start_fis_rx(struct ata_port *ap)
void ahci_start_fis_rx(struct ata_port *ap)
{
	void __iomem *port_mmio = ahci_port_base(ap);
	struct ahci_host_priv *hpriv = ap->host->private_data;
@@ -646,6 +645,7 @@ static void ahci_start_fis_rx(struct ata_port *ap)
	/* flush */
	readl(port_mmio + PORT_CMD);
}
EXPORT_SYMBOL_GPL(ahci_start_fis_rx);

static int ahci_stop_fis_rx(struct ata_port *ap)
{
@@ -1945,7 +1945,7 @@ irqreturn_t ahci_interrupt(int irq, void *dev_instance)
}
EXPORT_SYMBOL_GPL(ahci_interrupt);

static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc)
unsigned int ahci_qc_issue(struct ata_queued_cmd *qc)
{
	struct ata_port *ap = qc->ap;
	void __iomem *port_mmio = ahci_port_base(ap);
@@ -1974,6 +1974,7 @@ static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc)

	return 0;
}
EXPORT_SYMBOL_GPL(ahci_qc_issue);

static bool ahci_qc_fill_rtf(struct ata_queued_cmd *qc)
{
Loading