ahci: definition of ahci_start_fis_rx() and ahci_stop_fis_rx()
PATCH 1/5 ahci: definition of ahci_start_fis_rx() and ahci_stop_fis_rx()
Put the "start/stop FIS RX" operation into ahci_start_fis_rx() and
ahci_stop_fis_rx().
Signed-off-by Forrest Zhao <[email protected]>
Signed-off-by Hannes Reinecke <[email protected]>
Signed-off-by Jens Axboe <[email protected]>
---
drivers/scsi/ahci.c | 75 ++++++++++++++++++++++++++++++++++++++++++++ +++++++ 1 files changed, 75 insertions(+), 0 deletions(-)
e8b302fd248ec99f6c4cf99c468b467f585e7818
drivers/scsi/ahci.c +58 -0
@@ -207,6 +207,10 @@ static int ahci_port_start(struct ata_postatic void ahci_port_stop (struct ata_port *ap);static int ahci_start_engine (void __iomem *port_mmio);static int ahci_stop_engine (void __iomem *port_mmio); +static void ahci_start_fis_rx (void __iomem *port_mmio, +struct ahci_port_priv *pp, +struct ahci_host_priv *hpriv); +static int ahci_stop_fis_rx (void __iomem *port_mmio);static void ahci_tf_read (struct ata_port *ap,struct ata_taskfile *tf);static void ahci_qc_prep (struct ata_queued_cmd *qc);static u8 ahci_check_status (struct ata_port *ap);
@@ -570,6 +574,77 @@ static int ahci_start_engine(void __iomereturn 0 ; } +static int ahci_stop_fis_rx (void __iomem *port_mmio) +{ +u32 tmp; + +/* +* Get current status +*/ + tmp =readl (port_mmio +PORT_CMD ); + +/* Check if FIS RX is already disabled */ +if ((tmp &PORT_CMD_FIS_RX ) ==0 ) +return 0 ; + +/* +* AHCI Rev 1.1 section 10.3.2 +* Software shall not clear PxCMD.FRE while +* PxCMD.ST or PxCMD.CR is set to '1' +*/ +if (tmp & (PORT_CMD_LIST_ON |PORT_CMD_START )) { +return -EPERM ; + } + +/* +* Disable FIS reception +* +* AHCI Rev 1.1 Section 10.1.2: +* If PxCMD.FRE is set to '1', software should clear it +* to '0' and wait at least 500 milliseconds for PxCMD.FR +* to return '0' when read. If PxCMD.FR does not clear +* '0' correctly, then software may attempt a port reset +* of a full HBA reset to recover. +*/ + tmp &= ~(PORT_CMD_FIS_RX ); +writel (tmp, port_mmio +PORT_CMD ); + + tmp =ata_wait_register (port_mmio +PORT_CMD ,PORT_CMD_FIS_ON , +PORT_CMD_FIS_ON ,1 ,1000 ); +if (tmp &PORT_CMD_FIS_ON ) +return -EBUSY ; + +return 0 ; +} + +static void ahci_start_fis_rx (void __iomem *port_mmio, +struct ahci_port_priv *pp, +struct ahci_host_priv *hpriv) +{ +u32 tmp; + +/* +* Set FIS registers +*/ +if (hpriv->cap &HOST_CAP_64 ) + writel((pp->cmd_slot_dma >> 16) >> 16, port_mmio +
PORT_LST_ADDR_HI);
+ writel(pp->cmd_slot_dma & 0xffffffff, port_mmio +PORT_LST_ADDR);
+ readl(port_mmio + PORT_LST_ADDR); /* flush */
+
+ if (hpriv->cap & HOST_CAP_64)
+ writel((pp->rx_fis_dma >> 16) >> 16, port_mmio +PORT_FIS_ADDR_HI);
+ writel(pp->rx_fis_dma & 0xffffffff, port_mmio + PORT_FIS_ADDR);
+ readl(port_mmio + PORT_FIS_ADDR); /* flush */
+
+ /*
+ * Enable FIS reception
+ */
+ tmp = readl(port_mmio + PORT_CMD);
+ tmp |= PORT_CMD_FIS_RX;
+ writel(tmp, port_mmio + PORT_CMD);
+ readl(port_mmio + PORT_CMD); /* flush */
+}
+
static unsigned int ahci_dev_classify(struct ata_port *ap)
{
void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr;Signature · 1 line
1.2.6