From 3661aa99d82ed06e3781964d43d89be1050593c0 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Thu, 19 Mar 2015 14:36:37 +0100 Subject: ata: sata_mv: add proper definitions for LP_PHY_CTL register values Commit 9013d64e661fc ("ata: sata_mv: fix disk hotplug for Armada 370/XP SoCs") added some manipulation of the LP_PHY_CTL register, but using magic values. This commit changes the code to use proper definitions for the LP_PHY_CTL register, which allows to document what the different bits are doing. Signed-off-by: Thomas Petazzoni Acked-by: Simon Guinot Signed-off-by: Tejun Heo diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index f8c33e3..0281785 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -306,6 +306,11 @@ enum { MV5_PHY_CTL = 0x0C, SATA_IFCFG = 0x050, LP_PHY_CTL = 0x058, + LP_PHY_CTL_PIN_PU_PLL = (1 << 0), + LP_PHY_CTL_PIN_PU_RX = (1 << 1), + LP_PHY_CTL_PIN_PU_TX = (1 << 2), + LP_PHY_CTL_GEN_TX_3G = (1 << 5), + LP_PHY_CTL_GEN_RX_3G = (1 << 9), MV_M2_PREAMP_MASK = 0x7e0, @@ -1391,10 +1396,17 @@ static int mv_scr_write(struct ata_link *link, unsigned int sc_reg_in, u32 val) /* * Set PHY speed according to SControl speed. */ - if ((val & 0xf0) == 0x10) - writelfl(0x7, lp_phy_addr); - else - writelfl(0x227, lp_phy_addr); + u32 lp_phy_val = + LP_PHY_CTL_PIN_PU_PLL | + LP_PHY_CTL_PIN_PU_RX | + LP_PHY_CTL_PIN_PU_TX; + + if ((val & 0xf0) != 0x10) + lp_phy_val |= + LP_PHY_CTL_GEN_TX_3G | + LP_PHY_CTL_GEN_RX_3G; + + writelfl(lp_phy_val, lp_phy_addr); } } writelfl(val, addr); -- cgit v0.10.2 From 92b5bf989547b36c75231e4c24d0e2c351d3a0bc Mon Sep 17 00:00:00 2001 From: Feng Kan Date: Wed, 18 Mar 2015 17:03:55 -0700 Subject: sata: xgene: add ACPI support for APM X-Gene SATA ports This adds ACPI support for the APM X-Gene SATA ports. When the system boots using ACPI table, the SATA ports are able to configure using the values supplied by the ACPI table rather than the DTS. Signed-off-by: Feng Kan Reviewed-by: Hanjun Guo Reviewed-by: Mika Westerberg Acked-by: Rafael J. Wysocki Signed-off-by: Tejun Heo diff --git a/drivers/ata/ahci_xgene.c b/drivers/ata/ahci_xgene.c index 2e8bb60..2b78510 100644 --- a/drivers/ata/ahci_xgene.c +++ b/drivers/ata/ahci_xgene.c @@ -22,6 +22,7 @@ * NOTE: PM support is not currently available. * */ +#include #include #include #include @@ -718,6 +719,14 @@ disable_resources: return rc; } +#ifdef CONFIG_ACPI +static const struct acpi_device_id xgene_ahci_acpi_match[] = { + { "APMC0D0D", }, + { } +}; +MODULE_DEVICE_TABLE(acpi, xgene_ahci_acpi_match); +#endif + static const struct of_device_id xgene_ahci_of_match[] = { {.compatible = "apm,xgene-ahci"}, {}, @@ -730,6 +739,7 @@ static struct platform_driver xgene_ahci_driver = { .driver = { .name = DRV_NAME, .of_match_table = xgene_ahci_of_match, + .acpi_match_table = ACPI_PTR(xgene_ahci_acpi_match), }, }; -- cgit v0.10.2 From d578514b271e7c8cab8d6910075a2d137a9f0df8 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 3 Mar 2015 21:21:58 +0200 Subject: sata_dwc_460ex: join messages back It it better to have full message on one line. It simplifies to search for line in the code by message when debugging. Note that the lines which will be removed by sequential patch are not fixed here. There is no functional change. Signed-off-by: Andy Shevchenko Signed-off-by: Tejun Heo diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index fdb0f28..7bc0c12 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -392,14 +392,15 @@ static const char *get_dma_dir_descript(int dma_dir) static void sata_dwc_tf_dump(struct ata_taskfile *tf) { - dev_vdbg(host_pvt.dwc_dev, "taskfile cmd: 0x%02x protocol: %s flags:" - "0x%lx device: %x\n", tf->command, - get_prot_descript(tf->protocol), tf->flags, tf->device); - dev_vdbg(host_pvt.dwc_dev, "feature: 0x%02x nsect: 0x%x lbal: 0x%x " - "lbam: 0x%x lbah: 0x%x\n", tf->feature, tf->nsect, tf->lbal, - tf->lbam, tf->lbah); - dev_vdbg(host_pvt.dwc_dev, "hob_feature: 0x%02x hob_nsect: 0x%x " - "hob_lbal: 0x%x hob_lbam: 0x%x hob_lbah: 0x%x\n", + dev_vdbg(host_pvt.dwc_dev, + "taskfile cmd: 0x%02x protocol: %s flags: 0x%lx device: %x\n", + tf->command, get_prot_descript(tf->protocol), tf->flags, + tf->device); + dev_vdbg(host_pvt.dwc_dev, + "feature: 0x%02x nsect: 0x%x lbal: 0x%x lbam: 0x%x lbah: 0x%x\n", + tf->feature, tf->nsect, tf->lbal, tf->lbam, tf->lbah); + dev_vdbg(host_pvt.dwc_dev, + "hob_feature: 0x%02x hob_nsect: 0x%x hob_lbal: 0x%x hob_lbam: 0x%x hob_lbah: 0x%x\n", tf->hob_feature, tf->hob_nsect, tf->hob_lbal, tf->hob_lbam, tf->hob_lbah); } @@ -1003,8 +1004,9 @@ static irqreturn_t sata_dwc_isr(int irq, void *dev_instance) /* DEV interrupt w/ no active qc? */ if (unlikely(!qc || (qc->tf.flags & ATA_TFLAG_POLLING))) { - dev_err(ap->dev, "%s interrupt with no active qc " - "qc=%p\n", __func__, qc); + dev_err(ap->dev, + "%s interrupt with no active qc qc=%p\n", + __func__, qc); ap->ops->sff_check_status(ap); handled = 1; goto DONE; @@ -1034,9 +1036,9 @@ DRVSTILLBUSY: host_pvt.dma_interrupt_count++; if (hsdevp->dma_pending[tag] == \ SATA_DWC_DMA_PENDING_NONE) { - dev_err(ap->dev, "%s: DMA not pending " - "intpr=0x%08x status=0x%08x pending" - "=%d\n", __func__, intpr, status, + dev_err(ap->dev, + "%s: DMA not pending intpr=0x%08x status=0x%08x pending=%d\n", + __func__, intpr, status, hsdevp->dma_pending[tag]); } @@ -1068,17 +1070,17 @@ DRVSTILLBUSY: if (sactive != 0 || (host_pvt.sata_dwc_sactive_issued) > 1 || \ tag_mask > 1) { - dev_dbg(ap->dev, "%s NCQ:sactive=0x%08x sactive_issued=0x%08x" - "tag_mask=0x%08x\n", __func__, sactive, - host_pvt.sata_dwc_sactive_issued, tag_mask); + dev_dbg(ap->dev, + "%s NCQ:sactive=0x%08x sactive_issued=0x%08x tag_mask=0x%08x\n", + __func__, sactive, host_pvt.sata_dwc_sactive_issued, + tag_mask); } if ((tag_mask | (host_pvt.sata_dwc_sactive_issued)) != \ (host_pvt.sata_dwc_sactive_issued)) { - dev_warn(ap->dev, "Bad tag mask? sactive=0x%08x " - "(host_pvt.sata_dwc_sactive_issued)=0x%08x tag_mask" - "=0x%08x\n", sactive, host_pvt.sata_dwc_sactive_issued, - tag_mask); + dev_warn(ap->dev, + "Bad tag mask? sactive=0x%08x (host_pvt.sata_dwc_sactive_issued)=0x%08x tag_mask=0x%08x\n", + sactive, host_pvt.sata_dwc_sactive_issued, tag_mask); } /* read just to clear ... not bad if currently still busy */ @@ -1142,8 +1144,9 @@ STILLBUSY: */ sactive2 = core_scr_read(SCR_ACTIVE); if (sactive2 != sactive) { - dev_dbg(ap->dev, "More completed - sactive=0x%x sactive2" - "=0x%x\n", sactive, sactive2); + dev_dbg(ap->dev, + "More completed - sactive=0x%x sactive2=0x%x\n", + sactive, sactive2); } handled = 1; @@ -1169,11 +1172,10 @@ static void sata_dwc_clear_dmacr(struct sata_dwc_device_port *hsdevp, u8 tag) * This should not happen, it indicates the driver is out of * sync. If it does happen, clear dmacr anyway. */ - dev_err(host_pvt.dwc_dev, "%s DMA protocol RX and" - "TX DMA not pending tag=0x%02x pending=%d" - " dmacr: 0x%08x\n", __func__, tag, - hsdevp->dma_pending[tag], - in_le32(&(hsdev->sata_dwc_regs->dmacr))); + dev_err(host_pvt.dwc_dev, + "%s DMA protocol RX and TX DMA not pending tag=0x%02x pending=%d dmacr: 0x%08x\n", + __func__, tag, hsdevp->dma_pending[tag], + in_le32(&hsdev->sata_dwc_regs->dmacr)); out_le32(&(hsdev->sata_dwc_regs->dmacr), SATA_DWC_DMACR_TXRXCH_CLEAR); } @@ -1195,8 +1197,9 @@ static void sata_dwc_dma_xfer_complete(struct ata_port *ap, u32 check_status) #ifdef DEBUG_NCQ if (tag > 0) { - dev_info(ap->dev, "%s tag=%u cmd=0x%02x dma dir=%s proto=%s " - "dmacr=0x%08x\n", __func__, qc->tag, qc->tf.command, + dev_info(ap->dev, + "%s tag=%u cmd=0x%02x dma dir=%s proto=%s dmacr=0x%08x\n", + __func__, qc->tag, qc->tf.command, get_dma_dir_descript(qc->dma_dir), get_prot_descript(qc->tf.protocol), in_le32(&(hsdev->sata_dwc_regs->dmacr))); @@ -1205,8 +1208,9 @@ static void sata_dwc_dma_xfer_complete(struct ata_port *ap, u32 check_status) if (ata_is_dma(qc->tf.protocol)) { if (hsdevp->dma_pending[tag] == SATA_DWC_DMA_PENDING_NONE) { - dev_err(ap->dev, "%s DMA protocol RX and TX DMA not " - "pending dmacr: 0x%08x\n", __func__, + dev_err(ap->dev, + "%s DMA protocol RX and TX DMA not pending dmacr: 0x%08x\n", + __func__, in_le32(&(hsdev->sata_dwc_regs->dmacr))); } @@ -1232,9 +1236,9 @@ static int sata_dwc_qc_complete(struct ata_port *ap, struct ata_queued_cmd *qc, dev_err(ap->dev, "TX DMA PENDING\n"); else if (hsdevp->dma_pending[tag] == SATA_DWC_DMA_PENDING_RX) dev_err(ap->dev, "RX DMA PENDING\n"); - dev_dbg(ap->dev, "QC complete cmd=0x%02x status=0x%02x ata%u:" - " protocol=%d\n", qc->tf.command, status, ap->print_id, - qc->tf.protocol); + dev_dbg(ap->dev, + "QC complete cmd=0x%02x status=0x%02x ata%u: protocol=%d\n", + qc->tf.command, status, ap->print_id, qc->tf.protocol); /* clear active bit */ mask = (~(qcmd_tag_to_mask(tag))); @@ -1458,14 +1462,15 @@ static void sata_dwc_bmdma_start_by_tag(struct ata_queued_cmd *qc, u8 tag) else hsdevp->dma_pending[tag] = SATA_DWC_DMA_PENDING_RX; } else { - dev_err(ap->dev, "%s: Command not pending cmd_issued=%d " - "(tag=%d) DMA NOT started\n", __func__, - hsdevp->cmd_issued[tag], tag); + dev_err(ap->dev, + "%s: Command not pending cmd_issued=%d (tag=%d) DMA NOT started\n", + __func__, hsdevp->cmd_issued[tag], tag); start_dma = 0; } - dev_dbg(ap->dev, "%s qc=%p tag: %x cmd: 0x%02x dma_dir: %s " - "start_dma? %x\n", __func__, qc, tag, qc->tf.command, + dev_dbg(ap->dev, + "%s qc=%p tag: %x cmd: 0x%02x dma_dir: %s start_dma? %x\n", + __func__, qc, tag, qc->tf.command, get_dma_dir_descript(qc->dma_dir), start_dma); sata_dwc_tf_dump(&(qc->tf)); @@ -1540,8 +1545,8 @@ static unsigned int sata_dwc_qc_issue(struct ata_queued_cmd *qc) #ifdef DEBUG_NCQ if (qc->tag > 0 || ap->link.sactive > 1) - dev_info(ap->dev, "%s ap id=%d cmd(0x%02x)=%s qc tag=%d " - "prot=%s ap active_tag=0x%08x ap sactive=0x%08x\n", + dev_info(ap->dev, + "%s ap id=%d cmd(0x%02x)=%s qc tag=%d prot=%s ap active_tag=0x%08x ap sactive=0x%08x\n", __func__, ap->print_id, qc->tf.command, ata_get_cmd_descript(qc->tf.command), qc->tag, get_prot_descript(qc->tf.protocol), @@ -1557,9 +1562,9 @@ static unsigned int sata_dwc_qc_issue(struct ata_queued_cmd *qc) sactive |= (0x00000001 << tag); core_scr_write(SCR_ACTIVE, sactive); - dev_dbg(qc->ap->dev, "%s: tag=%d ap->link.sactive = 0x%08x " - "sactive=0x%08x\n", __func__, tag, qc->ap->link.sactive, - sactive); + dev_dbg(qc->ap->dev, + "%s: tag=%d ap->link.sactive = 0x%08x sactive=0x%08x\n", + __func__, tag, qc->ap->link.sactive, sactive); ap->ops->sff_tf_load(ap, &qc->tf); sata_dwc_exec_command_by_tag(ap, &qc->tf, qc->tag, @@ -1693,8 +1698,8 @@ static int sata_dwc_probe(struct platform_device *ofdev) /* Ioremap SATA registers */ base = of_iomap(np, 0); if (!base) { - dev_err(&ofdev->dev, "ioremap failed for SATA register" - " address\n"); + dev_err(&ofdev->dev, + "ioremap failed for SATA register address\n"); return -ENODEV; } hsdev->reg_base = base; @@ -1726,8 +1731,8 @@ static int sata_dwc_probe(struct platform_device *ofdev) /* Get physical SATA DMA register base address */ host_pvt.sata_dma_regs = (void *)of_iomap(np, 1); if (!(host_pvt.sata_dma_regs)) { - dev_err(&ofdev->dev, "ioremap failed for AHBDMA register" - " address\n"); + dev_err(&ofdev->dev, + "ioremap failed for AHBDMA register address\n"); err = -ENODEV; goto error_iomap; } @@ -1809,5 +1814,5 @@ module_platform_driver(sata_dwc_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Mark Miesfeld "); -MODULE_DESCRIPTION("DesignWare Cores SATA controller low lever driver"); +MODULE_DESCRIPTION("DesignWare Cores SATA controller low level driver"); MODULE_VERSION(DRV_VERSION); -- cgit v0.10.2 From 8b3444852a2b58129ee68a8dd69fef81ceb902a1 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 3 Mar 2015 22:41:21 +0200 Subject: sata_dwc_460ex: move to generic DMA driver The SATA implementation based on two actually different devices, i.e. SATA and DMA controllers. For Synopsys DesignWare DMA we have already a generic implementation of the driver. Thus, the patch converts the code to use DMAEngine framework and dw_dmac driver. In future it will be better to split the devices inside DTS as well like it's done on other platforms. Signed-off-by: Andy Shevchenko Signed-off-by: Tejun Heo diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 7bc0c12..08cd63f 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -36,11 +36,16 @@ #include #include #include + #include "libata.h" #include #include +/* Supported DMA engine drivers */ +#include +#include + /* These two are defined in "libata.h" */ #undef DRV_NAME #undef DRV_VERSION @@ -60,153 +65,9 @@ #define NO_IRQ 0 #endif -/* SATA DMA driver Globals */ -#define DMA_NUM_CHANS 1 -#define DMA_NUM_CHAN_REGS 8 - -/* SATA DMA Register definitions */ #define AHB_DMA_BRST_DFLT 64 /* 16 data items burst length*/ -struct dmareg { - u32 low; /* Low bits 0-31 */ - u32 high; /* High bits 32-63 */ -}; - -/* DMA Per Channel registers */ -struct dma_chan_regs { - struct dmareg sar; /* Source Address */ - struct dmareg dar; /* Destination address */ - struct dmareg llp; /* Linked List Pointer */ - struct dmareg ctl; /* Control */ - struct dmareg sstat; /* Source Status not implemented in core */ - struct dmareg dstat; /* Destination Status not implemented in core*/ - struct dmareg sstatar; /* Source Status Address not impl in core */ - struct dmareg dstatar; /* Destination Status Address not implemente */ - struct dmareg cfg; /* Config */ - struct dmareg sgr; /* Source Gather */ - struct dmareg dsr; /* Destination Scatter */ -}; - -/* Generic Interrupt Registers */ -struct dma_interrupt_regs { - struct dmareg tfr; /* Transfer Interrupt */ - struct dmareg block; /* Block Interrupt */ - struct dmareg srctran; /* Source Transfer Interrupt */ - struct dmareg dsttran; /* Dest Transfer Interrupt */ - struct dmareg error; /* Error */ -}; - -struct ahb_dma_regs { - struct dma_chan_regs chan_regs[DMA_NUM_CHAN_REGS]; - struct dma_interrupt_regs interrupt_raw; /* Raw Interrupt */ - struct dma_interrupt_regs interrupt_status; /* Interrupt Status */ - struct dma_interrupt_regs interrupt_mask; /* Interrupt Mask */ - struct dma_interrupt_regs interrupt_clear; /* Interrupt Clear */ - struct dmareg statusInt; /* Interrupt combined*/ - struct dmareg rq_srcreg; /* Src Trans Req */ - struct dmareg rq_dstreg; /* Dst Trans Req */ - struct dmareg rq_sgl_srcreg; /* Sngl Src Trans Req*/ - struct dmareg rq_sgl_dstreg; /* Sngl Dst Trans Req*/ - struct dmareg rq_lst_srcreg; /* Last Src Trans Req*/ - struct dmareg rq_lst_dstreg; /* Last Dst Trans Req*/ - struct dmareg dma_cfg; /* DMA Config */ - struct dmareg dma_chan_en; /* DMA Channel Enable*/ - struct dmareg dma_id; /* DMA ID */ - struct dmareg dma_test; /* DMA Test */ - struct dmareg res1; /* reserved */ - struct dmareg res2; /* reserved */ - /* - * DMA Comp Params - * Param 6 = dma_param[0], Param 5 = dma_param[1], - * Param 4 = dma_param[2] ... - */ - struct dmareg dma_params[6]; -}; - -/* Data structure for linked list item */ -struct lli { - u32 sar; /* Source Address */ - u32 dar; /* Destination address */ - u32 llp; /* Linked List Pointer */ - struct dmareg ctl; /* Control */ - struct dmareg dstat; /* Destination Status */ -}; - -enum { - SATA_DWC_DMAC_LLI_SZ = (sizeof(struct lli)), - SATA_DWC_DMAC_LLI_NUM = 256, - SATA_DWC_DMAC_LLI_TBL_SZ = (SATA_DWC_DMAC_LLI_SZ * \ - SATA_DWC_DMAC_LLI_NUM), - SATA_DWC_DMAC_TWIDTH_BYTES = 4, - SATA_DWC_DMAC_CTRL_TSIZE_MAX = (0x00000800 * \ - SATA_DWC_DMAC_TWIDTH_BYTES), -}; - -/* DMA Register Operation Bits */ enum { - DMA_EN = 0x00000001, /* Enable AHB DMA */ - DMA_CTL_LLP_SRCEN = 0x10000000, /* Blk chain enable Src */ - DMA_CTL_LLP_DSTEN = 0x08000000, /* Blk chain enable Dst */ -}; - -#define DMA_CTL_BLK_TS(size) ((size) & 0x000000FFF) /* Blk Transfer size */ -#define DMA_CHANNEL(ch) (0x00000001 << (ch)) /* Select channel */ - /* Enable channel */ -#define DMA_ENABLE_CHAN(ch) ((0x00000001 << (ch)) | \ - ((0x000000001 << (ch)) << 8)) - /* Disable channel */ -#define DMA_DISABLE_CHAN(ch) (0x00000000 | ((0x000000001 << (ch)) << 8)) - /* Transfer Type & Flow Controller */ -#define DMA_CTL_TTFC(type) (((type) & 0x7) << 20) -#define DMA_CTL_SMS(num) (((num) & 0x3) << 25) /* Src Master Select */ -#define DMA_CTL_DMS(num) (((num) & 0x3) << 23)/* Dst Master Select */ - /* Src Burst Transaction Length */ -#define DMA_CTL_SRC_MSIZE(size) (((size) & 0x7) << 14) - /* Dst Burst Transaction Length */ -#define DMA_CTL_DST_MSIZE(size) (((size) & 0x7) << 11) - /* Source Transfer Width */ -#define DMA_CTL_SRC_TRWID(size) (((size) & 0x7) << 4) - /* Destination Transfer Width */ -#define DMA_CTL_DST_TRWID(size) (((size) & 0x7) << 1) - -/* Assign HW handshaking interface (x) to destination / source peripheral */ -#define DMA_CFG_HW_HS_DEST(int_num) (((int_num) & 0xF) << 11) -#define DMA_CFG_HW_HS_SRC(int_num) (((int_num) & 0xF) << 7) -#define DMA_CFG_HW_CH_PRIOR(int_num) (((int_num) & 0xF) << 5) -#define DMA_LLP_LMS(addr, master) (((addr) & 0xfffffffc) | (master)) - -/* - * This define is used to set block chaining disabled in the control low - * register. It is already in little endian format so it can be &'d dirctly. - * It is essentially: cpu_to_le32(~(DMA_CTL_LLP_SRCEN | DMA_CTL_LLP_DSTEN)) - */ -enum { - DMA_CTL_LLP_DISABLE_LE32 = 0xffffffe7, - DMA_CTL_TTFC_P2M_DMAC = 0x00000002, /* Per to mem, DMAC cntr */ - DMA_CTL_TTFC_M2P_PER = 0x00000003, /* Mem to per, peripheral cntr */ - DMA_CTL_SINC_INC = 0x00000000, /* Source Address Increment */ - DMA_CTL_SINC_DEC = 0x00000200, - DMA_CTL_SINC_NOCHANGE = 0x00000400, - DMA_CTL_DINC_INC = 0x00000000, /* Destination Address Increment */ - DMA_CTL_DINC_DEC = 0x00000080, - DMA_CTL_DINC_NOCHANGE = 0x00000100, - DMA_CTL_INT_EN = 0x00000001, /* Interrupt Enable */ - -/* Channel Configuration Register high bits */ - DMA_CFG_FCMOD_REQ = 0x00000001, /* Flow Control - request based */ - DMA_CFG_PROTCTL = (0x00000003 << 2),/* Protection Control */ - -/* Channel Configuration Register low bits */ - DMA_CFG_RELD_DST = 0x80000000, /* Reload Dest / Src Addr */ - DMA_CFG_RELD_SRC = 0x40000000, - DMA_CFG_HS_SELSRC = 0x00000800, /* Software handshake Src/ Dest */ - DMA_CFG_HS_SELDST = 0x00000400, - DMA_CFG_FIFOEMPTY = (0x00000001 << 9), /* FIFO Empty bit */ - -/* Channel Linked List Pointer Register */ - DMA_LLP_AHBMASTER1 = 0, /* List Master Select */ - DMA_LLP_AHBMASTER2 = 1, - SATA_DWC_MAX_PORTS = 1, SATA_DWC_SCR_OFFSET = 0x24, @@ -287,7 +148,7 @@ struct sata_dwc_device { struct ata_host *host; u8 __iomem *reg_base; struct sata_dwc_regs *sata_dwc_regs; /* DW Synopsys SATA specific */ - int irq_dma; + struct dw_dma_chip *dma; }; #define SATA_DWC_QCMD_MAX 32 @@ -295,10 +156,13 @@ struct sata_dwc_device { struct sata_dwc_device_port { struct sata_dwc_device *hsdev; int cmd_issued[SATA_DWC_QCMD_MAX]; - struct lli *llit[SATA_DWC_QCMD_MAX]; /* DMA LLI table */ - dma_addr_t llit_dma[SATA_DWC_QCMD_MAX]; - u32 dma_chan[SATA_DWC_QCMD_MAX]; int dma_pending[SATA_DWC_QCMD_MAX]; + + /* DMA info */ + struct dw_dma_slave *dws; + struct dma_chan *chan; + struct dma_async_tx_descriptor *desc[SATA_DWC_QCMD_MAX]; + u32 dma_interrupt_count; }; /* @@ -330,14 +194,18 @@ struct sata_dwc_host_priv { void __iomem *scr_addr_sstatus; u32 sata_dwc_sactive_issued ; u32 sata_dwc_sactive_queued ; - u32 dma_interrupt_count; - struct ahb_dma_regs *sata_dma_regs; struct device *dwc_dev; - int dma_channel; }; static struct sata_dwc_host_priv host_pvt; +static struct dw_dma_slave sata_dwc_dma_dws = { + .src_id = 0, + .dst_id = 0, + .src_master = 0, + .dst_master = 1, +}; + /* * Prototypes */ @@ -347,12 +215,6 @@ static int sata_dwc_qc_complete(struct ata_port *ap, struct ata_queued_cmd *qc, static void sata_dwc_dma_xfer_complete(struct ata_port *ap, u32 check_status); static void sata_dwc_port_stop(struct ata_port *ap); static void sata_dwc_clear_dmacr(struct sata_dwc_device_port *hsdevp, u8 tag); -static int dma_dwc_init(struct sata_dwc_device *hsdev, int irq); -static void dma_dwc_exit(struct sata_dwc_device *hsdev); -static int dma_dwc_xfer_setup(struct scatterlist *sg, int num_elems, - struct lli *lli, dma_addr_t dma_lli, - void __iomem *addr, int dir); -static void dma_dwc_xfer_start(int dma_ch); static const char *get_prot_descript(u8 protocol) { @@ -405,76 +267,8 @@ static void sata_dwc_tf_dump(struct ata_taskfile *tf) tf->hob_lbah); } -/* - * Function: get_burst_length_encode - * arguments: datalength: length in bytes of data - * returns value to be programmed in register corresponding to data length - * This value is effectively the log(base 2) of the length - */ -static int get_burst_length_encode(int datalength) -{ - int items = datalength >> 2; /* div by 4 to get lword count */ - - if (items >= 64) - return 5; - - if (items >= 32) - return 4; - - if (items >= 16) - return 3; - - if (items >= 8) - return 2; - - if (items >= 4) - return 1; - - return 0; -} - -static void clear_chan_interrupts(int c) +static void dma_dwc_xfer_done(void *hsdev_instance) { - out_le32(&(host_pvt.sata_dma_regs->interrupt_clear.tfr.low), - DMA_CHANNEL(c)); - out_le32(&(host_pvt.sata_dma_regs->interrupt_clear.block.low), - DMA_CHANNEL(c)); - out_le32(&(host_pvt.sata_dma_regs->interrupt_clear.srctran.low), - DMA_CHANNEL(c)); - out_le32(&(host_pvt.sata_dma_regs->interrupt_clear.dsttran.low), - DMA_CHANNEL(c)); - out_le32(&(host_pvt.sata_dma_regs->interrupt_clear.error.low), - DMA_CHANNEL(c)); -} - -/* - * Function: dma_request_channel - * arguments: None - * returns channel number if available else -1 - * This function assigns the next available DMA channel from the list to the - * requester - */ -static int dma_request_channel(void) -{ - /* Check if the channel is not currently in use */ - if (!(in_le32(&(host_pvt.sata_dma_regs->dma_chan_en.low)) & - DMA_CHANNEL(host_pvt.dma_channel))) - return host_pvt.dma_channel; - dev_err(host_pvt.dwc_dev, "%s Channel %d is currently in use\n", - __func__, host_pvt.dma_channel); - return -1; -} - -/* - * Function: dma_dwc_interrupt - * arguments: irq, dev_id, pt_regs - * returns channel number if available else -1 - * Interrupt Handler for DW AHB SATA DMA - */ -static irqreturn_t dma_dwc_interrupt(int irq, void *hsdev_instance) -{ - int chan; - u32 tfr_reg, err_reg; unsigned long flags; struct sata_dwc_device *hsdev = hsdev_instance; struct ata_host *host = (struct ata_host *)hsdev->host; @@ -488,341 +282,65 @@ static irqreturn_t dma_dwc_interrupt(int irq, void *hsdev_instance) hsdevp = HSDEVP_FROM_AP(ap); tag = ap->link.active_tag; - tfr_reg = in_le32(&(host_pvt.sata_dma_regs->interrupt_status.tfr\ - .low)); - err_reg = in_le32(&(host_pvt.sata_dma_regs->interrupt_status.error\ - .low)); - - dev_dbg(ap->dev, "eot=0x%08x err=0x%08x pending=%d active port=%d\n", - tfr_reg, err_reg, hsdevp->dma_pending[tag], port); - - chan = host_pvt.dma_channel; - if (chan >= 0) { - /* Check for end-of-transfer interrupt. */ - if (tfr_reg & DMA_CHANNEL(chan)) { - /* - * Each DMA command produces 2 interrupts. Only - * complete the command after both interrupts have been - * seen. (See sata_dwc_isr()) - */ - host_pvt.dma_interrupt_count++; - sata_dwc_clear_dmacr(hsdevp, tag); - - if (hsdevp->dma_pending[tag] == - SATA_DWC_DMA_PENDING_NONE) { - dev_err(ap->dev, "DMA not pending eot=0x%08x " - "err=0x%08x tag=0x%02x pending=%d\n", - tfr_reg, err_reg, tag, - hsdevp->dma_pending[tag]); - } - - if ((host_pvt.dma_interrupt_count % 2) == 0) - sata_dwc_dma_xfer_complete(ap, 1); - - /* Clear the interrupt */ - out_le32(&(host_pvt.sata_dma_regs->interrupt_clear\ - .tfr.low), - DMA_CHANNEL(chan)); - } - - /* Check for error interrupt. */ - if (err_reg & DMA_CHANNEL(chan)) { - /* TODO Need error handler ! */ - dev_err(ap->dev, "error interrupt err_reg=0x%08x\n", - err_reg); - - /* Clear the interrupt. */ - out_le32(&(host_pvt.sata_dma_regs->interrupt_clear\ - .error.low), - DMA_CHANNEL(chan)); - } - } - spin_unlock_irqrestore(&host->lock, flags); - return IRQ_HANDLED; -} - -/* - * Function: dma_request_interrupts - * arguments: hsdev - * returns status - * This function registers ISR for a particular DMA channel interrupt - */ -static int dma_request_interrupts(struct sata_dwc_device *hsdev, int irq) -{ - int retval = 0; - int chan = host_pvt.dma_channel; - - if (chan >= 0) { - /* Unmask error interrupt */ - out_le32(&(host_pvt.sata_dma_regs)->interrupt_mask.error.low, - DMA_ENABLE_CHAN(chan)); - - /* Unmask end-of-transfer interrupt */ - out_le32(&(host_pvt.sata_dma_regs)->interrupt_mask.tfr.low, - DMA_ENABLE_CHAN(chan)); - } - - retval = request_irq(irq, dma_dwc_interrupt, 0, "SATA DMA", hsdev); - if (retval) { - dev_err(host_pvt.dwc_dev, "%s: could not get IRQ %d\n", - __func__, irq); - return -ENODEV; - } - - /* Mark this interrupt as requested */ - hsdev->irq_dma = irq; - return 0; -} - -/* - * Function: map_sg_to_lli - * The Synopsis driver has a comment proposing that better performance - * is possible by only enabling interrupts on the last item in the linked list. - * However, it seems that could be a problem if an error happened on one of the - * first items. The transfer would halt, but no error interrupt would occur. - * Currently this function sets interrupts enabled for each linked list item: - * DMA_CTL_INT_EN. - */ -static int map_sg_to_lli(struct scatterlist *sg, int num_elems, - struct lli *lli, dma_addr_t dma_lli, - void __iomem *dmadr_addr, int dir) -{ - int i, idx = 0; - int fis_len = 0; - dma_addr_t next_llp; - int bl; - int sms_val, dms_val; - - sms_val = 0; - dms_val = 1 + host_pvt.dma_channel; - dev_dbg(host_pvt.dwc_dev, - "%s: sg=%p nelem=%d lli=%p dma_lli=0x%pad dmadr=0x%p\n", - __func__, sg, num_elems, lli, &dma_lli, dmadr_addr); - - bl = get_burst_length_encode(AHB_DMA_BRST_DFLT); - - for (i = 0; i < num_elems; i++, sg++) { - u32 addr, offset; - u32 sg_len, len; - - addr = (u32) sg_dma_address(sg); - sg_len = sg_dma_len(sg); - - dev_dbg(host_pvt.dwc_dev, "%s: elem=%d sg_addr=0x%x sg_len" - "=%d\n", __func__, i, addr, sg_len); - - while (sg_len) { - if (idx >= SATA_DWC_DMAC_LLI_NUM) { - /* The LLI table is not large enough. */ - dev_err(host_pvt.dwc_dev, "LLI table overrun " - "(idx=%d)\n", idx); - break; - } - len = (sg_len > SATA_DWC_DMAC_CTRL_TSIZE_MAX) ? - SATA_DWC_DMAC_CTRL_TSIZE_MAX : sg_len; - - offset = addr & 0xffff; - if ((offset + sg_len) > 0x10000) - len = 0x10000 - offset; - - /* - * Make sure a LLI block is not created that will span - * 8K max FIS boundary. If the block spans such a FIS - * boundary, there is a chance that a DMA burst will - * cross that boundary -- this results in an error in - * the host controller. - */ - if (fis_len + len > 8192) { - dev_dbg(host_pvt.dwc_dev, "SPLITTING: fis_len=" - "%d(0x%x) len=%d(0x%x)\n", fis_len, - fis_len, len, len); - len = 8192 - fis_len; - fis_len = 0; - } else { - fis_len += len; - } - if (fis_len == 8192) - fis_len = 0; - - /* - * Set DMA addresses and lower half of control register - * based on direction. - */ - if (dir == DMA_FROM_DEVICE) { - lli[idx].dar = cpu_to_le32(addr); - lli[idx].sar = cpu_to_le32((u32)dmadr_addr); - - lli[idx].ctl.low = cpu_to_le32( - DMA_CTL_TTFC(DMA_CTL_TTFC_P2M_DMAC) | - DMA_CTL_SMS(sms_val) | - DMA_CTL_DMS(dms_val) | - DMA_CTL_SRC_MSIZE(bl) | - DMA_CTL_DST_MSIZE(bl) | - DMA_CTL_SINC_NOCHANGE | - DMA_CTL_SRC_TRWID(2) | - DMA_CTL_DST_TRWID(2) | - DMA_CTL_INT_EN | - DMA_CTL_LLP_SRCEN | - DMA_CTL_LLP_DSTEN); - } else { /* DMA_TO_DEVICE */ - lli[idx].sar = cpu_to_le32(addr); - lli[idx].dar = cpu_to_le32((u32)dmadr_addr); - - lli[idx].ctl.low = cpu_to_le32( - DMA_CTL_TTFC(DMA_CTL_TTFC_M2P_PER) | - DMA_CTL_SMS(dms_val) | - DMA_CTL_DMS(sms_val) | - DMA_CTL_SRC_MSIZE(bl) | - DMA_CTL_DST_MSIZE(bl) | - DMA_CTL_DINC_NOCHANGE | - DMA_CTL_SRC_TRWID(2) | - DMA_CTL_DST_TRWID(2) | - DMA_CTL_INT_EN | - DMA_CTL_LLP_SRCEN | - DMA_CTL_LLP_DSTEN); - } - - dev_dbg(host_pvt.dwc_dev, "%s setting ctl.high len: " - "0x%08x val: 0x%08x\n", __func__, - len, DMA_CTL_BLK_TS(len / 4)); - - /* Program the LLI CTL high register */ - lli[idx].ctl.high = cpu_to_le32(DMA_CTL_BLK_TS\ - (len / 4)); - - /* Program the next pointer. The next pointer must be - * the physical address, not the virtual address. - */ - next_llp = (dma_lli + ((idx + 1) * sizeof(struct \ - lli))); - - /* The last 2 bits encode the list master select. */ - next_llp = DMA_LLP_LMS(next_llp, DMA_LLP_AHBMASTER2); - - lli[idx].llp = cpu_to_le32(next_llp); - idx++; - sg_len -= len; - addr += len; - } - } - /* - * The last next ptr has to be zero and the last control low register - * has to have LLP_SRC_EN and LLP_DST_EN (linked list pointer source - * and destination enable) set back to 0 (disabled.) This is what tells - * the core that this is the last item in the linked list. + * Each DMA command produces 2 interrupts. Only + * complete the command after both interrupts have been + * seen. (See sata_dwc_isr()) */ - if (idx) { - lli[idx-1].llp = 0x00000000; - lli[idx-1].ctl.low &= DMA_CTL_LLP_DISABLE_LE32; + hsdevp->dma_interrupt_count++; + sata_dwc_clear_dmacr(hsdevp, tag); - /* Flush cache to memory */ - dma_cache_sync(NULL, lli, (sizeof(struct lli) * idx), - DMA_BIDIRECTIONAL); + if (hsdevp->dma_pending[tag] == SATA_DWC_DMA_PENDING_NONE) { + dev_err(ap->dev, "DMA not pending tag=0x%02x pending=%d\n", + tag, hsdevp->dma_pending[tag]); } - return idx; -} + if ((hsdevp->dma_interrupt_count % 2) == 0) + sata_dwc_dma_xfer_complete(ap, 1); -/* - * Function: dma_dwc_xfer_start - * arguments: Channel number - * Return : None - * Enables the DMA channel - */ -static void dma_dwc_xfer_start(int dma_ch) -{ - /* Enable the DMA channel */ - out_le32(&(host_pvt.sata_dma_regs->dma_chan_en.low), - in_le32(&(host_pvt.sata_dma_regs->dma_chan_en.low)) | - DMA_ENABLE_CHAN(dma_ch)); + spin_unlock_irqrestore(&host->lock, flags); } -static int dma_dwc_xfer_setup(struct scatterlist *sg, int num_elems, - struct lli *lli, dma_addr_t dma_lli, - void __iomem *addr, int dir) +static struct dma_async_tx_descriptor *dma_dwc_xfer_setup(struct ata_queued_cmd *qc) { - int dma_ch; - int num_lli; - /* Acquire DMA channel */ - dma_ch = dma_request_channel(); - if (dma_ch == -1) { - dev_err(host_pvt.dwc_dev, "%s: dma channel unavailable\n", - __func__); - return -EAGAIN; + struct ata_port *ap = qc->ap; + struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap); + struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap); + dma_addr_t addr = (dma_addr_t)&hsdev->sata_dwc_regs->dmadr; + struct dma_slave_config sconf; + struct dma_async_tx_descriptor *desc; + + if (qc->dma_dir == DMA_DEV_TO_MEM) { + sconf.src_addr = addr; + sconf.device_fc = true; + } else { /* DMA_MEM_TO_DEV */ + sconf.dst_addr = addr; + sconf.device_fc = false; } - /* Convert SG list to linked list of items (LLIs) for AHB DMA */ - num_lli = map_sg_to_lli(sg, num_elems, lli, dma_lli, addr, dir); - - dev_dbg(host_pvt.dwc_dev, "%s sg: 0x%p, count: %d lli: %p dma_lli:" - " 0x%0xlx addr: %p lli count: %d\n", __func__, sg, num_elems, - lli, (u32)dma_lli, addr, num_lli); - - clear_chan_interrupts(dma_ch); - - /* Program the CFG register. */ - out_le32(&(host_pvt.sata_dma_regs->chan_regs[dma_ch].cfg.high), - DMA_CFG_HW_HS_SRC(dma_ch) | DMA_CFG_HW_HS_DEST(dma_ch) | - DMA_CFG_PROTCTL | DMA_CFG_FCMOD_REQ); - out_le32(&(host_pvt.sata_dma_regs->chan_regs[dma_ch].cfg.low), - DMA_CFG_HW_CH_PRIOR(dma_ch)); - - /* Program the address of the linked list */ - out_le32(&(host_pvt.sata_dma_regs->chan_regs[dma_ch].llp.low), - DMA_LLP_LMS(dma_lli, DMA_LLP_AHBMASTER2)); - - /* Program the CTL register with src enable / dst enable */ - out_le32(&(host_pvt.sata_dma_regs->chan_regs[dma_ch].ctl.low), - DMA_CTL_LLP_SRCEN | DMA_CTL_LLP_DSTEN); - return dma_ch; -} - -/* - * Function: dma_dwc_exit - * arguments: None - * returns status - * This function exits the SATA DMA driver - */ -static void dma_dwc_exit(struct sata_dwc_device *hsdev) -{ - dev_dbg(host_pvt.dwc_dev, "%s:\n", __func__); - if (host_pvt.sata_dma_regs) { - iounmap((void __iomem *)host_pvt.sata_dma_regs); - host_pvt.sata_dma_regs = NULL; - } + sconf.direction = qc->dma_dir; + sconf.src_maxburst = AHB_DMA_BRST_DFLT; + sconf.dst_maxburst = AHB_DMA_BRST_DFLT; + sconf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + sconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; - if (hsdev->irq_dma) { - free_irq(hsdev->irq_dma, hsdev); - hsdev->irq_dma = 0; - } -} + dmaengine_slave_config(hsdevp->chan, &sconf); -/* - * Function: dma_dwc_init - * arguments: hsdev - * returns status - * This function initializes the SATA DMA driver - */ -static int dma_dwc_init(struct sata_dwc_device *hsdev, int irq) -{ - int err; + /* Convert SG list to linked list of items (LLIs) for AHB DMA */ + desc = dmaengine_prep_slave_sg(hsdevp->chan, qc->sg, qc->n_elem, + qc->dma_dir, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); - err = dma_request_interrupts(hsdev, irq); - if (err) { - dev_err(host_pvt.dwc_dev, "%s: dma_request_interrupts returns" - " %d\n", __func__, err); - return err; - } + if (!desc) + return NULL; - /* Enabe DMA */ - out_le32(&(host_pvt.sata_dma_regs->dma_cfg.low), DMA_EN); + desc->callback = dma_dwc_xfer_done; + desc->callback_param = hsdev; - dev_notice(host_pvt.dwc_dev, "DMA initialized\n"); - dev_dbg(host_pvt.dwc_dev, "SATA DMA registers=0x%p\n", host_pvt.\ - sata_dma_regs); + dev_dbg(host_pvt.dwc_dev, "%s sg: 0x%p, count: %d addr: %pad\n", + __func__, qc->sg, qc->n_elem, &addr); - return 0; + return desc; } static int sata_dwc_scr_read(struct ata_link *link, unsigned int scr, u32 *val) @@ -892,21 +410,18 @@ static void sata_dwc_error_intr(struct ata_port *ap, struct ata_queued_cmd *qc; u32 serror; u8 status, tag; - u32 err_reg; ata_ehi_clear_desc(ehi); serror = core_scr_read(SCR_ERROR); status = ap->ops->sff_check_status(ap); - err_reg = in_le32(&(host_pvt.sata_dma_regs->interrupt_status.error.\ - low)); tag = ap->link.active_tag; - dev_err(ap->dev, "%s SCR_ERROR=0x%08x intpr=0x%08x status=0x%08x " - "dma_intp=%d pending=%d issued=%d dma_err_status=0x%08x\n", - __func__, serror, intpr, status, host_pvt.dma_interrupt_count, - hsdevp->dma_pending[tag], hsdevp->cmd_issued[tag], err_reg); + dev_err(ap->dev, + "%s SCR_ERROR=0x%08x intpr=0x%08x status=0x%08x dma_intp=%d pending=%d issued=%d", + __func__, serror, intpr, status, hsdevp->dma_interrupt_count, + hsdevp->dma_pending[tag], hsdevp->cmd_issued[tag]); /* Clear error register and interrupt bit */ clear_serror(); @@ -1033,7 +548,7 @@ DRVSTILLBUSY: * operation done interrupt. The command should be * completed only after both interrupts are seen. */ - host_pvt.dma_interrupt_count++; + hsdevp->dma_interrupt_count++; if (hsdevp->dma_pending[tag] == \ SATA_DWC_DMA_PENDING_NONE) { dev_err(ap->dev, @@ -1042,7 +557,7 @@ DRVSTILLBUSY: hsdevp->dma_pending[tag]); } - if ((host_pvt.dma_interrupt_count % 2) == 0) + if ((hsdevp->dma_interrupt_count % 2) == 0) sata_dwc_dma_xfer_complete(ap, 1); } else if (ata_is_pio(qc->tf.protocol)) { ata_sff_hsm_move(ap, qc, status, 0); @@ -1116,12 +631,12 @@ DRVSTILLBUSY: dev_dbg(ap->dev, "%s NCQ command, protocol: %s\n", __func__, get_prot_descript(qc->tf.protocol)); if (ata_is_dma(qc->tf.protocol)) { - host_pvt.dma_interrupt_count++; + hsdevp->dma_interrupt_count++; if (hsdevp->dma_pending[tag] == \ SATA_DWC_DMA_PENDING_NONE) dev_warn(ap->dev, "%s: DMA not pending?\n", __func__); - if ((host_pvt.dma_interrupt_count % 2) == 0) + if ((hsdevp->dma_interrupt_count % 2) == 0) sata_dwc_dma_xfer_complete(ap, 1); } else { if (unlikely(sata_dwc_qc_complete(ap, qc, 1))) @@ -1269,6 +784,18 @@ static void sata_dwc_enable_interrupts(struct sata_dwc_device *hsdev) in_le32(&hsdev->sata_dwc_regs->errmr)); } +static bool sata_dwc_dma_filter(struct dma_chan *chan, void *param) +{ + struct sata_dwc_device_port *hsdevp = param; + struct dw_dma_slave *dws = hsdevp->dws; + + if (dws->dma_dev != chan->device->dev) + return false; + + chan->private = dws; + return true; +} + static void sata_dwc_setup_port(struct ata_ioports *port, unsigned long base) { port->cmd_addr = (void __iomem *)base + 0x00; @@ -1303,6 +830,7 @@ static int sata_dwc_port_start(struct ata_port *ap) struct sata_dwc_device *hsdev; struct sata_dwc_device_port *hsdevp = NULL; struct device *pdev; + dma_cap_mask_t mask; int i; hsdev = HSDEV_FROM_AP(ap); @@ -1326,29 +854,27 @@ static int sata_dwc_port_start(struct ata_port *ap) } hsdevp->hsdev = hsdev; + hsdevp->dws = &sata_dwc_dma_dws; + hsdevp->dws->dma_dev = host_pvt.dwc_dev; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + + /* Acquire DMA channel */ + hsdevp->chan = dma_request_channel(mask, sata_dwc_dma_filter, hsdevp); + if (!hsdevp->chan) { + dev_err(host_pvt.dwc_dev, "%s: dma channel unavailable\n", + __func__); + err = -EAGAIN; + goto CLEANUP_ALLOC; + } + for (i = 0; i < SATA_DWC_QCMD_MAX; i++) hsdevp->cmd_issued[i] = SATA_DWC_CMD_ISSUED_NOT; ap->bmdma_prd = NULL; /* set these so libata doesn't use them */ ap->bmdma_prd_dma = 0; - /* - * DMA - Assign scatter gather LLI table. We can't use the libata - * version since it's PRD is IDE PCI specific. - */ - for (i = 0; i < SATA_DWC_QCMD_MAX; i++) { - hsdevp->llit[i] = dma_alloc_coherent(pdev, - SATA_DWC_DMAC_LLI_TBL_SZ, - &(hsdevp->llit_dma[i]), - GFP_ATOMIC); - if (!hsdevp->llit[i]) { - dev_err(ap->dev, "%s: dma_alloc_coherent failed\n", - __func__); - err = -ENOMEM; - goto CLEANUP_ALLOC; - } - } - if (ap->port_no == 0) { dev_dbg(ap->dev, "%s: clearing TXCHEN, RXCHEN in DMAC\n", __func__); @@ -1377,22 +903,14 @@ CLEANUP: static void sata_dwc_port_stop(struct ata_port *ap) { - int i; - struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap); struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap); dev_dbg(ap->dev, "%s: ap->id = %d\n", __func__, ap->print_id); - if (hsdevp && hsdev) { - /* deallocate LLI table */ - for (i = 0; i < SATA_DWC_QCMD_MAX; i++) { - dma_free_coherent(ap->host->dev, - SATA_DWC_DMAC_LLI_TBL_SZ, - hsdevp->llit[i], hsdevp->llit_dma[i]); - } + dmaengine_terminate_all(hsdevp->chan); + dma_release_channel(hsdevp->chan); - kfree(hsdevp); - } + kfree(hsdevp); ap->private_data = NULL; } @@ -1448,12 +966,12 @@ static void sata_dwc_bmdma_setup(struct ata_queued_cmd *qc) static void sata_dwc_bmdma_start_by_tag(struct ata_queued_cmd *qc, u8 tag) { int start_dma; - u32 reg, dma_chan; + u32 reg; struct sata_dwc_device *hsdev = HSDEV_FROM_QC(qc); struct ata_port *ap = qc->ap; struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap); + struct dma_async_tx_descriptor *desc = hsdevp->desc[tag]; int dir = qc->dma_dir; - dma_chan = hsdevp->dma_chan[tag]; if (hsdevp->cmd_issued[tag] != SATA_DWC_CMD_ISSUED_NOT) { start_dma = 1; @@ -1489,7 +1007,8 @@ static void sata_dwc_bmdma_start_by_tag(struct ata_queued_cmd *qc, u8 tag) SATA_DWC_DMACR_RXCHEN); /* Enable AHB DMA transfer on the specified channel */ - dma_dwc_xfer_start(dma_chan); + dmaengine_submit(desc); + dma_async_issue_pending(hsdevp->chan); } } @@ -1515,26 +1034,21 @@ static void sata_dwc_bmdma_start(struct ata_queued_cmd *qc) */ static void sata_dwc_qc_prep_by_tag(struct ata_queued_cmd *qc, u8 tag) { - struct scatterlist *sg = qc->sg; + struct dma_async_tx_descriptor *desc; struct ata_port *ap = qc->ap; - int dma_chan; - struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap); struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap); dev_dbg(ap->dev, "%s: port=%d dma dir=%s n_elem=%d\n", __func__, ap->port_no, get_dma_dir_descript(qc->dma_dir), qc->n_elem); - dma_chan = dma_dwc_xfer_setup(sg, qc->n_elem, hsdevp->llit[tag], - hsdevp->llit_dma[tag], - (void __iomem *)&hsdev->sata_dwc_regs->dmadr, - qc->dma_dir); - if (dma_chan < 0) { - dev_err(ap->dev, "%s: dma_dwc_xfer_setup returns err %d\n", - __func__, dma_chan); + desc = dma_dwc_xfer_setup(qc); + if (!desc) { + dev_err(ap->dev, "%s: dma_dwc_xfer_setup returns NULL\n", + __func__); return; } - hsdevp->dma_chan[tag] = dma_chan; + hsdevp->desc[tag] = desc; } static unsigned int sata_dwc_qc_issue(struct ata_queued_cmd *qc) @@ -1678,7 +1192,6 @@ static int sata_dwc_probe(struct platform_device *ofdev) struct ata_port_info pi = sata_dwc_port_info[0]; const struct ata_port_info *ppi[] = { &pi, NULL }; struct device_node *np = ofdev->dev.of_node; - u32 dma_chan; /* Allocate DWC SATA device */ host = ata_host_alloc_pinfo(&ofdev->dev, ppi, SATA_DWC_MAX_PORTS); @@ -1688,13 +1201,6 @@ static int sata_dwc_probe(struct platform_device *ofdev) host->private_data = hsdev; - if (of_property_read_u32(np, "dma-channel", &dma_chan)) { - dev_warn(&ofdev->dev, "no dma-channel property set." - " Use channel 0\n"); - dma_chan = 0; - } - host_pvt.dma_channel = dma_chan; - /* Ioremap SATA registers */ base = of_iomap(np, 0); if (!base) { @@ -1721,16 +1227,16 @@ static int sata_dwc_probe(struct platform_device *ofdev) idr, ver[0], ver[1], ver[2]); /* Get SATA DMA interrupt number */ - irq = irq_of_parse_and_map(np, 1); - if (irq == NO_IRQ) { + hsdev->dma->irq = irq_of_parse_and_map(np, 1); + if (hsdev->dma->irq == NO_IRQ) { dev_err(&ofdev->dev, "no SATA DMA irq\n"); err = -ENODEV; goto error_iomap; } /* Get physical SATA DMA register base address */ - host_pvt.sata_dma_regs = (void *)of_iomap(np, 1); - if (!(host_pvt.sata_dma_regs)) { + hsdev->dma->regs = of_iomap(np, 1); + if (!hsdev->dma->regs) { dev_err(&ofdev->dev, "ioremap failed for AHBDMA register address\n"); err = -ENODEV; @@ -1740,8 +1246,10 @@ static int sata_dwc_probe(struct platform_device *ofdev) /* Save dev for later use in dev_xxx() routines */ host_pvt.dwc_dev = &ofdev->dev; + hsdev->dma->dev = &ofdev->dev; + /* Initialize AHB DMAC */ - err = dma_dwc_init(hsdev, irq); + err = dw_dma_probe(hsdev->dma, NULL); if (err) goto error_dma_iomap; @@ -1770,9 +1278,9 @@ static int sata_dwc_probe(struct platform_device *ofdev) error_out: /* Free SATA DMA resources */ - dma_dwc_exit(hsdev); + dw_dma_remove(hsdev->dma); error_dma_iomap: - iounmap((void __iomem *)host_pvt.sata_dma_regs); + iounmap(hsdev->dma->regs); error_iomap: iounmap(base); return err; @@ -1787,9 +1295,9 @@ static int sata_dwc_remove(struct platform_device *ofdev) ata_host_detach(host); /* Free SATA DMA resources */ - dma_dwc_exit(hsdev); + dw_dma_remove(hsdev->dma); - iounmap((void __iomem *)host_pvt.sata_dma_regs); + iounmap(hsdev->dma->regs); iounmap(hsdev->reg_base); dev_dbg(&ofdev->dev, "done\n"); return 0; -- cgit v0.10.2 From db7a657f3c2de202e8d648b03bc25bcd9a4de1d8 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 3 Mar 2015 22:41:22 +0200 Subject: sata_dwc_460ex: re-use hsdev->dev instead of dwc_dev This patch re-uses hsdev->dev which is allocated on heap. Therefore, the private structure, which is global variable, is reduced by one field. In one case ap->dev is used and there it seems to be right decision. Signed-off-by: Andy Shevchenko Signed-off-by: Tejun Heo diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 08cd63f..5ab4849 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -194,7 +194,6 @@ struct sata_dwc_host_priv { void __iomem *scr_addr_sstatus; u32 sata_dwc_sactive_issued ; u32 sata_dwc_sactive_queued ; - struct device *dwc_dev; }; static struct sata_dwc_host_priv host_pvt; @@ -252,16 +251,16 @@ static const char *get_dma_dir_descript(int dma_dir) } } -static void sata_dwc_tf_dump(struct ata_taskfile *tf) +static void sata_dwc_tf_dump(struct ata_port *ap, struct ata_taskfile *tf) { - dev_vdbg(host_pvt.dwc_dev, + dev_vdbg(ap->dev, "taskfile cmd: 0x%02x protocol: %s flags: 0x%lx device: %x\n", tf->command, get_prot_descript(tf->protocol), tf->flags, tf->device); - dev_vdbg(host_pvt.dwc_dev, + dev_vdbg(ap->dev, "feature: 0x%02x nsect: 0x%x lbal: 0x%x lbam: 0x%x lbah: 0x%x\n", tf->feature, tf->nsect, tf->lbal, tf->lbam, tf->lbah); - dev_vdbg(host_pvt.dwc_dev, + dev_vdbg(ap->dev, "hob_feature: 0x%02x hob_nsect: 0x%x hob_lbal: 0x%x hob_lbam: 0x%x hob_lbah: 0x%x\n", tf->hob_feature, tf->hob_nsect, tf->hob_lbal, tf->hob_lbam, tf->hob_lbah); @@ -337,7 +336,7 @@ static struct dma_async_tx_descriptor *dma_dwc_xfer_setup(struct ata_queued_cmd desc->callback = dma_dwc_xfer_done; desc->callback_param = hsdev; - dev_dbg(host_pvt.dwc_dev, "%s sg: 0x%p, count: %d addr: %pad\n", + dev_dbg(hsdev->dev, "%s sg: 0x%p, count: %d addr: %pad\n", __func__, qc->sg, qc->n_elem, &addr); return desc; @@ -687,7 +686,7 @@ static void sata_dwc_clear_dmacr(struct sata_dwc_device_port *hsdevp, u8 tag) * This should not happen, it indicates the driver is out of * sync. If it does happen, clear dmacr anyway. */ - dev_err(host_pvt.dwc_dev, + dev_err(hsdev->dev, "%s DMA protocol RX and TX DMA not pending tag=0x%02x pending=%d dmacr: 0x%08x\n", __func__, tag, hsdevp->dma_pending[tag], in_le32(&hsdev->sata_dwc_regs->dmacr)); @@ -779,7 +778,7 @@ static void sata_dwc_enable_interrupts(struct sata_dwc_device *hsdev) */ out_le32(&hsdev->sata_dwc_regs->errmr, SATA_DWC_SERROR_ERR_BITS); - dev_dbg(host_pvt.dwc_dev, "%s: INTMR = 0x%08x, ERRMR = 0x%08x\n", + dev_dbg(hsdev->dev, "%s: INTMR = 0x%08x, ERRMR = 0x%08x\n", __func__, in_le32(&hsdev->sata_dwc_regs->intmr), in_le32(&hsdev->sata_dwc_regs->errmr)); } @@ -855,7 +854,7 @@ static int sata_dwc_port_start(struct ata_port *ap) hsdevp->hsdev = hsdev; hsdevp->dws = &sata_dwc_dma_dws; - hsdevp->dws->dma_dev = host_pvt.dwc_dev; + hsdevp->dws->dma_dev = hsdev->dev; dma_cap_zero(mask); dma_cap_set(DMA_SLAVE, mask); @@ -863,7 +862,7 @@ static int sata_dwc_port_start(struct ata_port *ap) /* Acquire DMA channel */ hsdevp->chan = dma_request_channel(mask, sata_dwc_dma_filter, hsdevp); if (!hsdevp->chan) { - dev_err(host_pvt.dwc_dev, "%s: dma channel unavailable\n", + dev_err(hsdev->dev, "%s: dma channel unavailable\n", __func__); err = -EAGAIN; goto CLEANUP_ALLOC; @@ -990,7 +989,7 @@ static void sata_dwc_bmdma_start_by_tag(struct ata_queued_cmd *qc, u8 tag) "%s qc=%p tag: %x cmd: 0x%02x dma_dir: %s start_dma? %x\n", __func__, qc, tag, qc->tf.command, get_dma_dir_descript(qc->dma_dir), start_dma); - sata_dwc_tf_dump(&(qc->tf)); + sata_dwc_tf_dump(ap, &qc->tf); if (start_dma) { reg = core_scr_read(SCR_ERROR); @@ -1244,7 +1243,7 @@ static int sata_dwc_probe(struct platform_device *ofdev) } /* Save dev for later use in dev_xxx() routines */ - host_pvt.dwc_dev = &ofdev->dev; + hsdev->dev = &ofdev->dev; hsdev->dma->dev = &ofdev->dev; -- cgit v0.10.2 From 3a02824396c1df1db422d067b0fdcac724f44dd6 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 24 Mar 2015 14:14:18 -0400 Subject: libata: remove ATA_FLAG_LOWTAG sata_sil24 for some reason pukes when tags are allocated round-robin which helps tag ordered controllers. To work around the issue, 72dd299d5039 ("libata: allow sata_sil24 to opt-out of tag ordered submission") introduced ATA_FLAG_LOWTAG which tells libata tag allocation to do lowest-first. However, with the recent switch to blk-mq tag allocation, the liata tag allocation code path is no longer used and the workaround is now implemented in the block layer and selected by setting scsi_host_template->tag_alloc_policy to BLK_TAG_ALLOC_FIFO. See 9269e23496dd ("libata: make sata_sil24 use fifo tag allocator"). This leaves ATA_FLAG_LOWTAG withoout any actual user. Remove it. Signed-off-by: Tejun Heo Cc: Shaohua Li Cc: Dan Williams diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index b061ba2..fd9be17 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -4240,10 +4240,7 @@ int ata_sas_allocate_tag(struct ata_port *ap) unsigned int i, tag; for (i = 0, tag = ap->sas_last_tag + 1; i < max_queue; i++, tag++) { - if (ap->flags & ATA_FLAG_LOWTAG) - tag = 1; - else - tag = tag < max_queue ? tag : 0; + tag = tag < max_queue ? tag : 0; /* the last tag is reserved for internal command. */ if (tag == ATA_TAG_INTERNAL) diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c index ba2667f..5242897 100644 --- a/drivers/ata/sata_sil24.c +++ b/drivers/ata/sata_sil24.c @@ -246,7 +246,7 @@ enum { /* host flags */ SIL24_COMMON_FLAGS = ATA_FLAG_SATA | ATA_FLAG_PIO_DMA | ATA_FLAG_NCQ | ATA_FLAG_ACPI_SATA | - ATA_FLAG_AN | ATA_FLAG_PMP | ATA_FLAG_LOWTAG, + ATA_FLAG_AN | ATA_FLAG_PMP, SIL24_FLAG_PCIX_IRQ_WOC = (1 << 24), /* IRQ loss errata on PCI-X */ IRQ_STAT_4PORTS = 0xf, diff --git a/include/linux/libata.h b/include/linux/libata.h index fc03efa..ebe132a 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -231,7 +231,6 @@ enum { ATA_FLAG_SW_ACTIVITY = (1 << 22), /* driver supports sw activity * led */ ATA_FLAG_NO_DIPM = (1 << 23), /* host not happy with DIPM */ - ATA_FLAG_LOWTAG = (1 << 24), /* host wants lowest available tag */ /* bits 24:31 of ap->flags are reserved for LLD specific flags */ -- cgit v0.10.2 From 9faa643855df6f673f08543576c759b82dd270d3 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 27 Mar 2015 16:46:30 +0100 Subject: libata: use READ_LOG_DMA_EXT If READ_LOG_DMA_EXT is supported we should try to use it for reading the log pages. Signed-off-by: Hannes Reinecke Signed-off-by: Tejun Heo diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index d2029a4..d35d7a7 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -1510,13 +1510,18 @@ unsigned int ata_read_log_page(struct ata_device *dev, u8 log, DPRINTK("read log page - log 0x%x, page 0x%x\n", log, page); ata_tf_init(dev, &tf); - tf.command = ATA_CMD_READ_LOG_EXT; + if (dev->dma_mode && ata_id_has_read_log_dma_ext(dev->id)) { + tf.command = ATA_CMD_READ_LOG_DMA_EXT; + tf.protocol = ATA_PROT_DMA; + } else { + tf.command = ATA_CMD_READ_LOG_EXT; + tf.protocol = ATA_PROT_PIO; + } tf.lbal = log; tf.lbam = page; tf.nsect = sectors; tf.hob_nsect = sectors >> 8; tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_LBA48 | ATA_TFLAG_DEVICE; - tf.protocol = ATA_PROT_PIO; err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE, buf, sectors * ATA_SECT_SIZE, 0); diff --git a/include/linux/ata.h b/include/linux/ata.h index 1648026..681520f 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -696,6 +696,13 @@ static inline bool ata_id_wcache_enabled(const u16 *id) return id[ATA_ID_CFS_ENABLE_1] & (1 << 5); } +static inline bool ata_id_has_read_log_dma_ext(const u16 *id) +{ + if (!(id[ATA_ID_CFS_ENABLE_2] & (1 << 15))) + return false; + return id[ATA_ID_COMMAND_SET_3] & (1 << 3); +} + /** * ata_id_major_version - get ATA level of drive * @id: Identify data -- cgit v0.10.2 From 825e2d878319faf75a0cd432fa92f290f6ffd130 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 27 Mar 2015 16:46:31 +0100 Subject: libata: whitespace cleanup in ata_get_cmd_descript() Signed-off-by: Hannes Reinecke Signed-off-by: Tejun Heo diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index d35d7a7..50ffd4e 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -2294,27 +2294,27 @@ const char *ata_get_cmd_descript(u8 command) const char *text; } cmd_descr[] = { { ATA_CMD_DEV_RESET, "DEVICE RESET" }, - { ATA_CMD_CHK_POWER, "CHECK POWER MODE" }, - { ATA_CMD_STANDBY, "STANDBY" }, - { ATA_CMD_IDLE, "IDLE" }, - { ATA_CMD_EDD, "EXECUTE DEVICE DIAGNOSTIC" }, - { ATA_CMD_DOWNLOAD_MICRO, "DOWNLOAD MICROCODE" }, + { ATA_CMD_CHK_POWER, "CHECK POWER MODE" }, + { ATA_CMD_STANDBY, "STANDBY" }, + { ATA_CMD_IDLE, "IDLE" }, + { ATA_CMD_EDD, "EXECUTE DEVICE DIAGNOSTIC" }, + { ATA_CMD_DOWNLOAD_MICRO, "DOWNLOAD MICROCODE" }, { ATA_CMD_DOWNLOAD_MICRO_DMA, "DOWNLOAD MICROCODE DMA" }, { ATA_CMD_NOP, "NOP" }, - { ATA_CMD_FLUSH, "FLUSH CACHE" }, - { ATA_CMD_FLUSH_EXT, "FLUSH CACHE EXT" }, - { ATA_CMD_ID_ATA, "IDENTIFY DEVICE" }, - { ATA_CMD_ID_ATAPI, "IDENTIFY PACKET DEVICE" }, - { ATA_CMD_SERVICE, "SERVICE" }, - { ATA_CMD_READ, "READ DMA" }, - { ATA_CMD_READ_EXT, "READ DMA EXT" }, - { ATA_CMD_READ_QUEUED, "READ DMA QUEUED" }, - { ATA_CMD_READ_STREAM_EXT, "READ STREAM EXT" }, + { ATA_CMD_FLUSH, "FLUSH CACHE" }, + { ATA_CMD_FLUSH_EXT, "FLUSH CACHE EXT" }, + { ATA_CMD_ID_ATA, "IDENTIFY DEVICE" }, + { ATA_CMD_ID_ATAPI, "IDENTIFY PACKET DEVICE" }, + { ATA_CMD_SERVICE, "SERVICE" }, + { ATA_CMD_READ, "READ DMA" }, + { ATA_CMD_READ_EXT, "READ DMA EXT" }, + { ATA_CMD_READ_QUEUED, "READ DMA QUEUED" }, + { ATA_CMD_READ_STREAM_EXT, "READ STREAM EXT" }, { ATA_CMD_READ_STREAM_DMA_EXT, "READ STREAM DMA EXT" }, - { ATA_CMD_WRITE, "WRITE DMA" }, - { ATA_CMD_WRITE_EXT, "WRITE DMA EXT" }, - { ATA_CMD_WRITE_QUEUED, "WRITE DMA QUEUED EXT" }, - { ATA_CMD_WRITE_STREAM_EXT, "WRITE STREAM EXT" }, + { ATA_CMD_WRITE, "WRITE DMA" }, + { ATA_CMD_WRITE_EXT, "WRITE DMA EXT" }, + { ATA_CMD_WRITE_QUEUED, "WRITE DMA QUEUED EXT" }, + { ATA_CMD_WRITE_STREAM_EXT, "WRITE STREAM EXT" }, { ATA_CMD_WRITE_STREAM_DMA_EXT, "WRITE STREAM DMA EXT" }, { ATA_CMD_WRITE_FUA_EXT, "WRITE DMA FUA EXT" }, { ATA_CMD_WRITE_QUEUED_FUA_EXT, "WRITE DMA QUEUED FUA EXT" }, @@ -2330,7 +2330,7 @@ const char *ata_get_cmd_descript(u8 command) { ATA_CMD_READ_MULTI_EXT, "READ MULTIPLE EXT" }, { ATA_CMD_WRITE_MULTI, "WRITE MULTIPLE" }, { ATA_CMD_WRITE_MULTI_EXT, "WRITE MULTIPLE EXT" }, - { ATA_CMD_WRITE_MULTI_FUA_EXT, "WRITE MULTIPLE FUA EXT" }, + { ATA_CMD_WRITE_MULTI_FUA_EXT, "WRITE MULTIPLE FUA EXT" }, { ATA_CMD_SET_FEATURES, "SET FEATURES" }, { ATA_CMD_SET_MULTI, "SET MULTIPLE MODE" }, { ATA_CMD_VERIFY, "READ VERIFY SECTOR(S)" }, @@ -2347,12 +2347,12 @@ const char *ata_get_cmd_descript(u8 command) { ATA_CMD_READ_LOG_EXT, "READ LOG EXT" }, { ATA_CMD_WRITE_LOG_EXT, "WRITE LOG EXT" }, { ATA_CMD_READ_LOG_DMA_EXT, "READ LOG DMA EXT" }, - { ATA_CMD_WRITE_LOG_DMA_EXT, "WRITE LOG DMA EXT" }, + { ATA_CMD_WRITE_LOG_DMA_EXT, "WRITE LOG DMA EXT" }, { ATA_CMD_TRUSTED_NONDATA, "TRUSTED NON-DATA" }, { ATA_CMD_TRUSTED_RCV, "TRUSTED RECEIVE" }, - { ATA_CMD_TRUSTED_RCV_DMA, "TRUSTED RECEIVE DMA" }, + { ATA_CMD_TRUSTED_RCV_DMA, "TRUSTED RECEIVE DMA" }, { ATA_CMD_TRUSTED_SND, "TRUSTED SEND" }, - { ATA_CMD_TRUSTED_SND_DMA, "TRUSTED SEND DMA" }, + { ATA_CMD_TRUSTED_SND_DMA, "TRUSTED SEND DMA" }, { ATA_CMD_PMP_READ, "READ BUFFER" }, { ATA_CMD_PMP_READ_DMA, "READ BUFFER DMA" }, { ATA_CMD_PMP_WRITE, "WRITE BUFFER" }, @@ -2369,12 +2369,12 @@ const char *ata_get_cmd_descript(u8 command) { ATA_CMD_MEDIA_LOCK, "DOOR LOCK" }, { ATA_CMD_MEDIA_UNLOCK, "DOOR UNLOCK" }, { ATA_CMD_DSM, "DATA SET MANAGEMENT" }, - { ATA_CMD_CHK_MED_CRD_TYP, "CHECK MEDIA CARD TYPE" }, - { ATA_CMD_CFA_REQ_EXT_ERR, "CFA REQUEST EXTENDED ERROR" }, + { ATA_CMD_CHK_MED_CRD_TYP, "CHECK MEDIA CARD TYPE" }, + { ATA_CMD_CFA_REQ_EXT_ERR, "CFA REQUEST EXTENDED ERROR" }, { ATA_CMD_CFA_WRITE_NE, "CFA WRITE SECTORS WITHOUT ERASE" }, { ATA_CMD_CFA_TRANS_SECT, "CFA TRANSLATE SECTOR" }, { ATA_CMD_CFA_ERASE, "CFA ERASE SECTORS" }, - { ATA_CMD_CFA_WRITE_MULT_NE, "CFA WRITE MULTIPLE WITHOUT ERASE" }, + { ATA_CMD_CFA_WRITE_MULT_NE, "CFA WRITE MULTIPLE WITHOUT ERASE" }, { ATA_CMD_REQ_SENSE_DATA, "REQUEST SENSE DATA EXT" }, { ATA_CMD_SANITIZE_DEVICE, "SANITIZE DEVICE" }, { ATA_CMD_READ_LONG, "READ LONG (with retries)" }, -- cgit v0.10.2 From 8ae720449fca4b1d0294c0a0204c0c45556a3e61 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 27 Mar 2015 16:46:32 +0100 Subject: libata: whitespace fixes in ata_to_sense_error() Signed-off-by: Hannes Reinecke Signed-off-by: Tejun Heo diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index fd9be17..25d8b64 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -849,40 +849,59 @@ static void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, /* Based on the 3ware driver translation table */ static const unsigned char sense_table[][4] = { /* BBD|ECC|ID|MAR */ - {0xd1, ABORTED_COMMAND, 0x00, 0x00}, // Device busy Aborted command + {0xd1, ABORTED_COMMAND, 0x00, 0x00}, + // Device busy Aborted command /* BBD|ECC|ID */ - {0xd0, ABORTED_COMMAND, 0x00, 0x00}, // Device busy Aborted command + {0xd0, ABORTED_COMMAND, 0x00, 0x00}, + // Device busy Aborted command /* ECC|MC|MARK */ - {0x61, HARDWARE_ERROR, 0x00, 0x00}, // Device fault Hardware error + {0x61, HARDWARE_ERROR, 0x00, 0x00}, + // Device fault Hardware error /* ICRC|ABRT */ /* NB: ICRC & !ABRT is BBD */ - {0x84, ABORTED_COMMAND, 0x47, 0x00}, // Data CRC error SCSI parity error + {0x84, ABORTED_COMMAND, 0x47, 0x00}, + // Data CRC error SCSI parity error /* MC|ID|ABRT|TRK0|MARK */ - {0x37, NOT_READY, 0x04, 0x00}, // Unit offline Not ready + {0x37, NOT_READY, 0x04, 0x00}, + // Unit offline Not ready /* MCR|MARK */ - {0x09, NOT_READY, 0x04, 0x00}, // Unrecovered disk error Not ready + {0x09, NOT_READY, 0x04, 0x00}, + // Unrecovered disk error Not ready /* Bad address mark */ - {0x01, MEDIUM_ERROR, 0x13, 0x00}, // Address mark not found Address mark not found for data field - /* TRK0 */ - {0x02, HARDWARE_ERROR, 0x00, 0x00}, // Track 0 not found Hardware error + {0x01, MEDIUM_ERROR, 0x13, 0x00}, + // Address mark not found for data field + /* TRK0 - Track 0 not found */ + {0x02, HARDWARE_ERROR, 0x00, 0x00}, + // Hardware error /* Abort: 0x04 is not translated here, see below */ /* Media change request */ - {0x08, NOT_READY, 0x04, 0x00}, // Media change request FIXME: faking offline - /* SRV/IDNF */ - {0x10, ILLEGAL_REQUEST, 0x21, 0x00}, // ID not found Logical address out of range - /* MC */ - {0x20, UNIT_ATTENTION, 0x28, 0x00}, // Media Changed Not ready to ready change, medium may have changed - /* ECC */ - {0x40, MEDIUM_ERROR, 0x11, 0x04}, // Uncorrectable ECC error Unrecovered read error + {0x08, NOT_READY, 0x04, 0x00}, + // FIXME: faking offline + /* SRV/IDNF - ID not found */ + {0x10, ILLEGAL_REQUEST, 0x21, 0x00}, + // Logical address out of range + /* MC - Media Changed */ + {0x20, UNIT_ATTENTION, 0x28, 0x00}, + // Not ready to ready change, medium may have changed + /* ECC - Uncorrectable ECC error */ + {0x40, MEDIUM_ERROR, 0x11, 0x04}, + // Unrecovered read error /* BBD - block marked bad */ - {0x80, MEDIUM_ERROR, 0x11, 0x04}, // Block marked bad Medium error, unrecovered read error + {0x80, MEDIUM_ERROR, 0x11, 0x04}, + // Block marked bad Medium error, unrecovered read error {0xFF, 0xFF, 0xFF, 0xFF}, // END mark }; static const unsigned char stat_table[][4] = { /* Must be first because BUSY means no other bits valid */ - {0x80, ABORTED_COMMAND, 0x47, 0x00}, // Busy, fake parity for now - {0x20, HARDWARE_ERROR, 0x44, 0x00}, // Device fault, internal target failure - {0x08, ABORTED_COMMAND, 0x47, 0x00}, // Timed out in xfer, fake parity for now - {0x04, RECOVERED_ERROR, 0x11, 0x00}, // Recovered ECC error Medium error, recovered + {0x80, ABORTED_COMMAND, 0x47, 0x00}, + // Busy, fake parity for now + {0x40, ILLEGAL_REQUEST, 0x21, 0x04}, + // Device ready, unaligned write command + {0x20, HARDWARE_ERROR, 0x44, 0x00}, + // Device fault, internal target failure + {0x08, ABORTED_COMMAND, 0x47, 0x00}, + // Timed out in xfer, fake parity for now + {0x04, RECOVERED_ERROR, 0x11, 0x00}, + // Recovered ECC error Medium error, recovered {0xFF, 0xFF, 0xFF, 0xFF}, // END mark }; -- cgit v0.10.2 From 27f00e53af72702d3a9e6f75590e66fe04914149 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 27 Mar 2015 16:46:33 +0100 Subject: ide,ata: Rename ATA_IDX to ATA_SENSE ATA-8 defines bit 1 as 'ATA_SENSE', not 'ATA_IDX'. Signed-off-by: Hannes Reinecke Signed-off-by: Tejun Heo diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 25d8b64..b96e3b7 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -804,7 +804,7 @@ static void ata_dump_status(unsigned id, struct ata_taskfile *tf) if (stat & 0x10) printk("SeekComplete "); if (stat & 0x08) printk("DataRequest "); if (stat & 0x04) printk("CorrectedError "); - if (stat & 0x02) printk("Index "); + if (stat & 0x02) printk("Sense "); if (stat & 0x01) printk("Error "); printk("}\n"); diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c index d9c9829..e1180fa 100644 --- a/drivers/ide/ide-lib.c +++ b/drivers/ide/ide-lib.c @@ -148,8 +148,8 @@ u8 ide_dump_status(ide_drive_t *drive, const char *msg, u8 stat) printk(KERN_CONT "DataRequest "); if (stat & ATA_CORR) printk(KERN_CONT "CorrectedError "); - if (stat & ATA_IDX) - printk(KERN_CONT "Index "); + if (stat & ATA_SENSE) + printk(KERN_CONT "Sense "); if (stat & ATA_ERR) printk(KERN_CONT "Error "); } diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index a3d3b17..0b63fac 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -273,7 +273,7 @@ int ide_dev_read_id(ide_drive_t *drive, u8 cmd, u16 *id, int irq_ctx) (hwif->host_flags & IDE_HFLAG_BROKEN_ALTSTATUS) == 0) { a = tp_ops->read_altstatus(hwif); s = tp_ops->read_status(hwif); - if ((a ^ s) & ~ATA_IDX) + if ((a ^ s) & ~ATA_SENSE) /* ancient Seagate drives, broken interfaces */ printk(KERN_INFO "%s: probing with STATUS(0x%02x) " "instead of ALTSTATUS(0x%02x)\n", diff --git a/include/linux/ata.h b/include/linux/ata.h index 681520f..e3cb41c 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -177,7 +177,7 @@ enum { ATA_DSC = (1 << 4), /* drive seek complete */ ATA_DRQ = (1 << 3), /* data request i/o */ ATA_CORR = (1 << 2), /* corrected data error */ - ATA_IDX = (1 << 1), /* index */ + ATA_SENSE = (1 << 1), /* sense code available */ ATA_ERR = (1 << 0), /* have an error */ ATA_SRST = (1 << 2), /* software reset */ ATA_ICRC = (1 << 7), /* interface CRC error */ -- cgit v0.10.2 From 1308d7f0107b264b480e7048dc345fc6b7408e7e Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 27 Mar 2015 16:46:34 +0100 Subject: libata: use status bit definitions in ata_dump_status() Use the bit definitions for better readability. Signed-off-by: Hannes Reinecke Signed-off-by: Tejun Heo diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index b96e3b7..bb57d81 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -799,26 +799,27 @@ static void ata_dump_status(unsigned id, struct ata_taskfile *tf) if (stat & ATA_BUSY) { printk("Busy }\n"); /* Data is not valid in this case */ } else { - if (stat & 0x40) printk("DriveReady "); - if (stat & 0x20) printk("DeviceFault "); - if (stat & 0x10) printk("SeekComplete "); - if (stat & 0x08) printk("DataRequest "); - if (stat & 0x04) printk("CorrectedError "); - if (stat & 0x02) printk("Sense "); - if (stat & 0x01) printk("Error "); + if (stat & ATA_DRDY) printk("DriveReady "); + if (stat & ATA_DF) printk("DeviceFault "); + if (stat & ATA_DSC) printk("SeekComplete "); + if (stat & ATA_DRQ) printk("DataRequest "); + if (stat & ATA_CORR) printk("CorrectedError "); + if (stat & ATA_SENSE) printk("Sense "); + if (stat & ATA_ERR) printk("Error "); printk("}\n"); if (err) { printk(KERN_WARNING "ata%u: error=0x%02x { ", id, err); - if (err & 0x04) printk("DriveStatusError "); - if (err & 0x80) { - if (err & 0x04) printk("BadCRC "); + if (err & ATA_ABORTED) printk("DriveStatusError "); + if (err & ATA_ICRC) { + if (err & ATA_ABORTED) + printk("BadCRC "); else printk("Sector "); } - if (err & 0x40) printk("UncorrectableError "); - if (err & 0x10) printk("SectorIdNotFound "); - if (err & 0x02) printk("TrackZeroNotFound "); - if (err & 0x01) printk("AddrMarkNotFound "); + if (err & ATA_UNC) printk("UncorrectableError "); + if (err & ATA_IDNF) printk("SectorIdNotFound "); + if (err & ATA_TRK0NF) printk("TrackZeroNotFound "); + if (err & ATA_AMNF) printk("AddrMarkNotFound "); printk("}\n"); } } -- cgit v0.10.2 From 42b966fbf35da9c87f08d98f9b8978edf9e717cf Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 27 Mar 2015 16:46:35 +0100 Subject: libata: Implement NCQ autosense Some newer devices support NCQ autosense (cf ACS-4), so we should be using it to retrieve the sense code and speed up recovery. Signed-off-by: Hannes Reinecke Signed-off-by: Tejun Heo diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 50ffd4e..c9b1994 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -1580,6 +1580,8 @@ static int ata_eh_read_log_10h(struct ata_device *dev, tf->hob_lbah = buf[10]; tf->nsect = buf[12]; tf->hob_nsect = buf[13]; + if (ata_id_has_ncq_autosense(dev->id)) + tf->auxiliary = buf[14] << 16 | buf[15] << 8 | buf[16]; return 0; } @@ -1777,6 +1779,18 @@ void ata_eh_analyze_ncq_error(struct ata_link *link) memcpy(&qc->result_tf, &tf, sizeof(tf)); qc->result_tf.flags = ATA_TFLAG_ISADDR | ATA_TFLAG_LBA | ATA_TFLAG_LBA48; qc->err_mask |= AC_ERR_DEV | AC_ERR_NCQ; + if (qc->result_tf.auxiliary) { + char sense_key, asc, ascq; + + sense_key = (qc->result_tf.auxiliary >> 16) & 0xff; + asc = (qc->result_tf.auxiliary >> 8) & 0xff; + ascq = qc->result_tf.auxiliary & 0xff; + ata_dev_dbg(dev, "NCQ Autosense %02x/%02x/%02x\n", + sense_key, asc, ascq); + ata_scsi_set_sense(qc->scsicmd, sense_key, asc, ascq); + qc->flags |= ATA_QCFLAG_SENSE_VALID; + } + ehc->i.err_mask &= ~AC_ERR_DEV; } @@ -1806,6 +1820,10 @@ static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc, return ATA_EH_RESET; } + /* Set by NCQ autosense */ + if (qc->flags & ATA_QCFLAG_SENSE_VALID) + return 0; + if (stat & (ATA_ERR | ATA_DF)) qc->err_mask |= AC_ERR_DEV; else diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index bb57d81..3ac5be3 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -270,8 +270,11 @@ DEVICE_ATTR(unload_heads, S_IRUGO | S_IWUSR, ata_scsi_park_show, ata_scsi_park_store); EXPORT_SYMBOL_GPL(dev_attr_unload_heads); -static void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq) +void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq) { + if (!cmd) + return; + cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION; scsi_build_sense_buffer(0, cmd->sense_buffer, sk, asc, ascq); @@ -1777,7 +1780,9 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) ((cdb[2] & 0x20) || need_sense)) { ata_gen_passthru_sense(qc); } else { - if (!need_sense) { + if (qc->flags & ATA_QCFLAG_SENSE_VALID) { + cmd->result = SAM_STAT_CHECK_CONDITION; + } else if (!need_sense) { cmd->result = SAM_STAT_GOOD; } else { /* TODO: decide which descriptor format to use diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index f840ca1..8cfdd96 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -137,6 +137,7 @@ extern int ata_scsi_add_hosts(struct ata_host *host, struct scsi_host_template *sht); extern void ata_scsi_scan_host(struct ata_port *ap, int sync); extern int ata_scsi_offline_dev(struct ata_device *dev); +extern void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq); extern void ata_scsi_media_change_notify(struct ata_device *dev); extern void ata_scsi_hotplug(struct work_struct *work); extern void ata_schedule_scsi_eh(struct Scsi_Host *shost); diff --git a/include/linux/ata.h b/include/linux/ata.h index e3cb41c..0c65526 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -525,6 +525,8 @@ struct ata_bmdma_prd { #define ata_id_cdb_intr(id) (((id)[ATA_ID_CONFIG] & 0x60) == 0x20) #define ata_id_has_da(id) ((id)[ATA_ID_SATA_CAPABILITY_2] & (1 << 4)) #define ata_id_has_devslp(id) ((id)[ATA_ID_FEATURE_SUPP] & (1 << 8)) +#define ata_id_has_ncq_autosense(id) \ + ((id)[ATA_ID_FEATURE_SUPP] & (1 << 7)) static inline bool ata_id_has_hipm(const u16 *id) { -- cgit v0.10.2 From fe7173c206de63fc28475ee6ae42ff95c05692de Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 27 Mar 2015 16:46:36 +0100 Subject: libata: Implement support for sense data reporting ACS-4 defines a sense data reporting feature set. This patch implements support for it. Signed-off-by: Hannes Reinecke Signed-off-by: Tejun Heo diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 4c35f08..aebb7e3 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -2144,6 +2144,24 @@ static int ata_dev_config_ncq(struct ata_device *dev, return 0; } +static void ata_dev_config_sense_reporting(struct ata_device *dev) +{ + unsigned int err_mask; + + if (!ata_id_has_sense_reporting(dev->id)) + return; + + if (ata_id_sense_reporting_enabled(dev->id)) + return; + + err_mask = ata_dev_set_feature(dev, SETFEATURE_SENSE_DATA, 0x1); + if (err_mask) { + ata_dev_dbg(dev, + "failed to enable Sense Data Reporting, Emask 0x%x\n", + err_mask); + } +} + /** * ata_dev_configure - Configure the specified ATA/ATAPI device * @dev: Target device to configure @@ -2366,7 +2384,7 @@ int ata_dev_configure(struct ata_device *dev) dev->devslp_timing[i] = sata_setting[j]; } } - + ata_dev_config_sense_reporting(dev); dev->cdb_len = 16; } diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index c9b1994..9fa81d9 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -1618,6 +1618,70 @@ unsigned int atapi_eh_tur(struct ata_device *dev, u8 *r_sense_key) } /** + * ata_eh_request_sense - perform REQUEST_SENSE_DATA_EXT + * @dev: device to perform REQUEST_SENSE_SENSE_DATA_EXT to + * @sense_buf: result sense data buffer (SCSI_SENSE_BUFFERSIZE bytes long) + * @dfl_sense_key: default sense key to use + * + * Perform REQUEST_SENSE_DATA_EXT after the device reported CHECK + * SENSE. This function is EH helper. + * + * LOCKING: + * Kernel thread context (may sleep). + * + * RETURNS: + * encoded sense data on success, 0 on failure or if sense data + * is not available. + */ +static u32 ata_eh_request_sense(struct ata_queued_cmd *qc, + struct scsi_cmnd *cmd) +{ + struct ata_device *dev = qc->dev; + struct ata_taskfile tf; + unsigned int err_mask; + + if (!cmd) + return 0; + + DPRINTK("ATA request sense\n"); + ata_dev_warn(dev, "request sense\n"); + if (!ata_id_sense_reporting_enabled(dev->id)) { + ata_dev_warn(qc->dev, "sense data reporting disabled\n"); + return 0; + } + ata_tf_init(dev, &tf); + + tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; + tf.flags |= ATA_TFLAG_LBA | ATA_TFLAG_LBA48; + tf.command = ATA_CMD_REQ_SENSE_DATA; + tf.protocol = ATA_PROT_NODATA; + + err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0); + /* + * ACS-4 states: + * The device may set the SENSE DATA AVAILABLE bit to one in the + * STATUS field and clear the ERROR bit to zero in the STATUS field + * to indicate that the command returned completion without an error + * and the sense data described in table 306 is available. + * + * IOW the 'ATA_SENSE' bit might not be set even though valid + * sense data is available. + * So check for both. + */ + if ((tf.command & ATA_SENSE) || + tf.lbah != 0 || tf.lbam != 0 || tf.lbal != 0) { + ata_scsi_set_sense(cmd, tf.lbah, tf.lbam, tf.lbal); + qc->flags |= ATA_QCFLAG_SENSE_VALID; + ata_dev_warn(dev, "sense data %02x/%02x/%02x\n", + tf.lbah, tf.lbam, tf.lbal); + } else { + ata_dev_warn(dev, "request sense failed stat %02x emask %x\n", + tf.command, err_mask); + } + return err_mask; +} + +/** * atapi_eh_request_sense - perform ATAPI REQUEST_SENSE * @dev: device to perform REQUEST_SENSE to * @sense_buf: result sense data buffer (SCSI_SENSE_BUFFERSIZE bytes long) @@ -1820,7 +1884,22 @@ static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc, return ATA_EH_RESET; } - /* Set by NCQ autosense */ + /* + * Sense data reporting does not work if the + * device fault bit is set. + */ + if ((stat & ATA_SENSE) && !(stat & ATA_DF) && + !(qc->flags & ATA_QCFLAG_SENSE_VALID)) { + if (!(qc->ap->pflags & ATA_PFLAG_FROZEN)) { + tmp = ata_eh_request_sense(qc, qc->scsicmd); + if (tmp) + qc->err_mask |= tmp; + } else { + ata_dev_warn(qc->dev, "sense data available but port frozen\n"); + } + } + + /* Set by NCQ autosense or request sense above */ if (qc->flags & ATA_QCFLAG_SENSE_VALID) return 0; @@ -2566,14 +2645,15 @@ static void ata_eh_link_report(struct ata_link *link) #ifdef CONFIG_ATA_VERBOSE_ERROR if (res->command & (ATA_BUSY | ATA_DRDY | ATA_DF | ATA_DRQ | - ATA_ERR)) { + ATA_SENSE | ATA_ERR)) { if (res->command & ATA_BUSY) ata_dev_err(qc->dev, "status: { Busy }\n"); else - ata_dev_err(qc->dev, "status: { %s%s%s%s}\n", + ata_dev_err(qc->dev, "status: { %s%s%s%s%s}\n", res->command & ATA_DRDY ? "DRDY " : "", res->command & ATA_DF ? "DF " : "", res->command & ATA_DRQ ? "DRQ " : "", + res->command & ATA_SENSE ? "SENSE " : "", res->command & ATA_ERR ? "ERR " : ""); } diff --git a/include/linux/ata.h b/include/linux/ata.h index 0c65526..b666b77 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -94,6 +94,8 @@ enum { ATA_ID_SECTOR_SIZE = 106, ATA_ID_WWN = 108, ATA_ID_LOGICAL_SECTOR_SIZE = 117, /* and 118 */ + ATA_ID_COMMAND_SET_3 = 119, + ATA_ID_COMMAND_SET_4 = 120, ATA_ID_LAST_LUN = 126, ATA_ID_DLF = 128, ATA_ID_CSFO = 129, @@ -382,6 +384,8 @@ enum { SATA_SSP = 0x06, /* Software Settings Preservation */ SATA_DEVSLP = 0x09, /* Device Sleep */ + SETFEATURE_SENSE_DATA = 0xC3, /* Sense Data Reporting feature */ + /* feature values for SET_MAX */ ATA_SET_MAX_ADDR = 0x00, ATA_SET_MAX_PASSWD = 0x01, @@ -705,6 +709,20 @@ static inline bool ata_id_has_read_log_dma_ext(const u16 *id) return id[ATA_ID_COMMAND_SET_3] & (1 << 3); } +static inline bool ata_id_has_sense_reporting(const u16 *id) +{ + if (!(id[ATA_ID_CFS_ENABLE_2] & (1 << 15))) + return false; + return id[ATA_ID_COMMAND_SET_3] & (1 << 6); +} + +static inline bool ata_id_sense_reporting_enabled(const u16 *id) +{ + if (!(id[ATA_ID_CFS_ENABLE_2] & (1 << 15))) + return false; + return id[ATA_ID_COMMAND_SET_4] & (1 << 6); +} + /** * ata_id_major_version - get ATA level of drive * @id: Identify data -- cgit v0.10.2 From a1524f226a02aa6edebd90ae0752e97cfd78b159 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 27 Mar 2015 16:46:37 +0100 Subject: libata-eh: Set 'information' field for autosense If NCQ autosense or the sense data reporting feature is enabled the LBA of the offending command should be stored in the sense data 'information' field. Signed-off-by: Hannes Reinecke Signed-off-by: Tejun Heo diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index aebb7e3..ff57367 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -691,11 +691,11 @@ static int ata_rwcmd_protocol(struct ata_taskfile *tf, struct ata_device *dev) * RETURNS: * Block address read from @tf. */ -u64 ata_tf_read_block(struct ata_taskfile *tf, struct ata_device *dev) +u64 ata_tf_read_block(const struct ata_taskfile *tf, struct ata_device *dev) { u64 block = 0; - if (tf->flags & ATA_TFLAG_LBA) { + if (!dev || tf->flags & ATA_TFLAG_LBA) { if (tf->flags & ATA_TFLAG_LBA48) { block |= (u64)tf->hob_lbah << 40; block |= (u64)tf->hob_lbam << 32; diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 9fa81d9..77ef43e 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -1852,6 +1852,7 @@ void ata_eh_analyze_ncq_error(struct ata_link *link) ata_dev_dbg(dev, "NCQ Autosense %02x/%02x/%02x\n", sense_key, asc, ascq); ata_scsi_set_sense(qc->scsicmd, sense_key, asc, ascq); + ata_scsi_set_sense_information(qc->scsicmd, &qc->result_tf); qc->flags |= ATA_QCFLAG_SENSE_VALID; } @@ -1894,6 +1895,8 @@ static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc, tmp = ata_eh_request_sense(qc, qc->scsicmd); if (tmp) qc->err_mask |= tmp; + else + ata_scsi_set_sense_information(qc->scsicmd, tf); } else { ata_dev_warn(qc->dev, "sense data available but port frozen\n"); } diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 3ac5be3..3131adc 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -280,6 +280,18 @@ void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq) scsi_build_sense_buffer(0, cmd->sense_buffer, sk, asc, ascq); } +void ata_scsi_set_sense_information(struct scsi_cmnd *cmd, + const struct ata_taskfile *tf) +{ + u64 information; + + if (!cmd) + return; + + information = ata_tf_read_block(tf, NULL); + scsi_set_sense_information(cmd->sense_buffer, information); +} + static ssize_t ata_scsi_em_message_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index 8cfdd96..a998a17 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -67,7 +67,8 @@ extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev, int tag); extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev, u64 block, u32 n_block, unsigned int tf_flags, unsigned int tag); -extern u64 ata_tf_read_block(struct ata_taskfile *tf, struct ata_device *dev); +extern u64 ata_tf_read_block(const struct ata_taskfile *tf, + struct ata_device *dev); extern unsigned ata_exec_internal(struct ata_device *dev, struct ata_taskfile *tf, const u8 *cdb, int dma_dir, void *buf, unsigned int buflen, @@ -138,6 +139,8 @@ extern int ata_scsi_add_hosts(struct ata_host *host, extern void ata_scsi_scan_host(struct ata_port *ap, int sync); extern int ata_scsi_offline_dev(struct ata_device *dev); extern void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq); +extern void ata_scsi_set_sense_information(struct scsi_cmnd *cmd, + const struct ata_taskfile *tf); extern void ata_scsi_media_change_notify(struct ata_device *dev); extern void ata_scsi_hotplug(struct work_struct *work); extern void ata_schedule_scsi_eh(struct Scsi_Host *shost); diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 4cdaffc..c95a4e9 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -2586,3 +2587,33 @@ void scsi_build_sense_buffer(int desc, u8 *buf, u8 key, u8 asc, u8 ascq) } } EXPORT_SYMBOL(scsi_build_sense_buffer); + +/** + * scsi_set_sense_information - set the information field in a + * formatted sense data buffer + * @buf: Where to build sense data + * @info: 64-bit information value to be set + * + **/ +void scsi_set_sense_information(u8 *buf, u64 info) +{ + if ((buf[0] & 0x7f) == 0x72) { + u8 *ucp, len; + + len = buf[7]; + ucp = (char *)scsi_sense_desc_find(buf, len + 8, 0); + if (!ucp) { + buf[7] = len + 0xa; + ucp = buf + 8 + len; + } + ucp[0] = 0; + ucp[1] = 0xa; + ucp[2] = 0x80; /* Valid bit */ + ucp[3] = 0; + put_unaligned_be64(info, &ucp[4]); + } else if ((buf[0] & 0x7f) == 0x70) { + buf[0] |= 0x80; + put_unaligned_be64(info, &buf[3]); + } +} +EXPORT_SYMBOL(scsi_set_sense_information); diff --git a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h index 1e1421b..5a4bb5b 100644 --- a/include/scsi/scsi_eh.h +++ b/include/scsi/scsi_eh.h @@ -59,6 +59,7 @@ extern int scsi_get_sense_info_fld(const u8 * sense_buffer, int sb_len, u64 * info_out); extern void scsi_build_sense_buffer(int desc, u8 *buf, u8 key, u8 asc, u8 ascq); +extern void scsi_set_sense_information(u8 *buf, u64 info); extern int scsi_ioctl_reset(struct scsi_device *, int __user *); -- cgit v0.10.2 From 255c03d15a29a3ccb7a40d247f02bf38ba3f3592 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 27 Mar 2015 16:46:38 +0100 Subject: libata: Add tracepoints Add some tracepoints for ata_qc_issue, ata_qc_complete, and ata_eh_link_autopsy. Signed-off-by: Hannes Reinecke Signed-off-by: Tejun Heo diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile index ae41107..b67e995 100644 --- a/drivers/ata/Makefile +++ b/drivers/ata/Makefile @@ -111,7 +111,8 @@ obj-$(CONFIG_ATA_GENERIC) += ata_generic.o # Should be last libata driver obj-$(CONFIG_PATA_LEGACY) += pata_legacy.o -libata-y := libata-core.o libata-scsi.o libata-eh.o libata-transport.o +libata-y := libata-core.o libata-scsi.o libata-eh.o \ + libata-transport.o libata-trace.o libata-$(CONFIG_ATA_SFF) += libata-sff.o libata-$(CONFIG_SATA_PMP) += libata-pmp.o libata-$(CONFIG_ATA_ACPI) += libata-acpi.o diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index ff57367..be1722a 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -70,6 +70,9 @@ #include #include +#define CREATE_TRACE_POINTS +#include + #include "libata.h" #include "libata-transport.h" @@ -4904,6 +4907,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc) */ if (unlikely(ata_tag_internal(qc->tag))) { fill_result_tf(qc); + trace_ata_qc_complete_internal(qc); __ata_qc_complete(qc); return; } @@ -4914,6 +4918,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc) */ if (unlikely(qc->flags & ATA_QCFLAG_FAILED)) { fill_result_tf(qc); + trace_ata_qc_complete_failed(qc); ata_qc_schedule_eh(qc); return; } @@ -4924,6 +4929,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc) if (qc->flags & ATA_QCFLAG_RESULT_TF) fill_result_tf(qc); + trace_ata_qc_complete_done(qc); /* Some commands need post-processing after successful * completion. */ @@ -5071,7 +5077,7 @@ void ata_qc_issue(struct ata_queued_cmd *qc) } ap->ops->qc_prep(qc); - + trace_ata_qc_issue(qc); qc->err_mask |= ap->ops->qc_issue(qc); if (unlikely(qc->err_mask)) goto err; diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 77ef43e..07f41be 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -46,6 +46,7 @@ #include +#include #include "libata.h" enum { @@ -2291,6 +2292,7 @@ static void ata_eh_link_autopsy(struct ata_link *link) all_err_mask |= qc->err_mask; if (qc->flags & ATA_QCFLAG_IO) eflags |= ATA_EFLAG_IS_IO; + trace_ata_eh_link_autopsy_qc(qc); } /* enforce default EH actions */ @@ -2325,7 +2327,7 @@ static void ata_eh_link_autopsy(struct ata_link *link) eflags |= ATA_EFLAG_DUBIOUS_XFER; ehc->i.action |= ata_eh_speed_down(dev, eflags, all_err_mask); } - + trace_ata_eh_link_autopsy(dev, ehc->i.action, all_err_mask); DPRINTK("EXIT\n"); } diff --git a/drivers/ata/libata-trace.c b/drivers/ata/libata-trace.c new file mode 100644 index 0000000..fd30b8c --- /dev/null +++ b/drivers/ata/libata-trace.c @@ -0,0 +1,151 @@ +/* + * libata-trace.c - trace functions for libata + * + * Copyright 2015 Hannes Reinecke + * Copyright 2015 SUSE Linux GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include + +const char * +libata_trace_parse_status(struct trace_seq *p, unsigned char status) +{ + const char *ret = trace_seq_buffer_ptr(p); + + trace_seq_printf(p, "{ "); + if (status & ATA_BUSY) + trace_seq_printf(p, "BUSY "); + if (status & ATA_DRDY) + trace_seq_printf(p, "DRDY "); + if (status & ATA_DF) + trace_seq_printf(p, "DF "); + if (status & ATA_DSC) + trace_seq_printf(p, "DSC "); + if (status & ATA_DRQ) + trace_seq_printf(p, "DRQ "); + if (status & ATA_CORR) + trace_seq_printf(p, "CORR "); + if (status & ATA_SENSE) + trace_seq_printf(p, "SENSE "); + if (status & ATA_ERR) + trace_seq_printf(p, "ERR "); + trace_seq_putc(p, '}'); + trace_seq_putc(p, 0); + + return ret; +} + +const char * +libata_trace_parse_eh_action(struct trace_seq *p, unsigned int eh_action) +{ + const char *ret = trace_seq_buffer_ptr(p); + + trace_seq_printf(p, "%x", eh_action); + if (eh_action) { + trace_seq_printf(p, "{ "); + if (eh_action & ATA_EH_REVALIDATE) + trace_seq_printf(p, "REVALIDATE "); + if (eh_action & (ATA_EH_SOFTRESET | ATA_EH_HARDRESET)) + trace_seq_printf(p, "RESET "); + else if (eh_action & ATA_EH_SOFTRESET) + trace_seq_printf(p, "SOFTRESET "); + else if (eh_action & ATA_EH_HARDRESET) + trace_seq_printf(p, "HARDRESET "); + if (eh_action & ATA_EH_ENABLE_LINK) + trace_seq_printf(p, "ENABLE_LINK "); + if (eh_action & ATA_EH_PARK) + trace_seq_printf(p, "PARK "); + trace_seq_putc(p, '}'); + } + trace_seq_putc(p, 0); + + return ret; +} + +const char * +libata_trace_parse_eh_err_mask(struct trace_seq *p, unsigned int eh_err_mask) +{ + const char *ret = trace_seq_buffer_ptr(p); + + trace_seq_printf(p, "%x", eh_err_mask); + if (eh_err_mask) { + trace_seq_printf(p, "{ "); + if (eh_err_mask & AC_ERR_DEV) + trace_seq_printf(p, "DEV "); + if (eh_err_mask & AC_ERR_HSM) + trace_seq_printf(p, "HSM "); + if (eh_err_mask & AC_ERR_TIMEOUT) + trace_seq_printf(p, "TIMEOUT "); + if (eh_err_mask & AC_ERR_MEDIA) + trace_seq_printf(p, "MEDIA "); + if (eh_err_mask & AC_ERR_ATA_BUS) + trace_seq_printf(p, "ATA_BUS "); + if (eh_err_mask & AC_ERR_HOST_BUS) + trace_seq_printf(p, "HOST_BUS "); + if (eh_err_mask & AC_ERR_SYSTEM) + trace_seq_printf(p, "SYSTEM "); + if (eh_err_mask & AC_ERR_INVALID) + trace_seq_printf(p, "INVALID "); + if (eh_err_mask & AC_ERR_OTHER) + trace_seq_printf(p, "OTHER "); + if (eh_err_mask & AC_ERR_NODEV_HINT) + trace_seq_printf(p, "NODEV_HINT "); + if (eh_err_mask & AC_ERR_NCQ) + trace_seq_printf(p, "NCQ "); + trace_seq_putc(p, '}'); + } + trace_seq_putc(p, 0); + + return ret; +} + +const char * +libata_trace_parse_qc_flags(struct trace_seq *p, unsigned int qc_flags) +{ + const char *ret = trace_seq_buffer_ptr(p); + + trace_seq_printf(p, "%x", qc_flags); + if (qc_flags) { + trace_seq_printf(p, "{ "); + if (qc_flags & ATA_QCFLAG_ACTIVE) + trace_seq_printf(p, "ACTIVE "); + if (qc_flags & ATA_QCFLAG_DMAMAP) + trace_seq_printf(p, "DMAMAP "); + if (qc_flags & ATA_QCFLAG_IO) + trace_seq_printf(p, "IO "); + if (qc_flags & ATA_QCFLAG_RESULT_TF) + trace_seq_printf(p, "RESULT_TF "); + if (qc_flags & ATA_QCFLAG_CLEAR_EXCL) + trace_seq_printf(p, "CLEAR_EXCL "); + if (qc_flags & ATA_QCFLAG_QUIET) + trace_seq_printf(p, "QUIET "); + if (qc_flags & ATA_QCFLAG_RETRY) + trace_seq_printf(p, "RETRY "); + if (qc_flags & ATA_QCFLAG_FAILED) + trace_seq_printf(p, "FAILED "); + if (qc_flags & ATA_QCFLAG_SENSE_VALID) + trace_seq_printf(p, "SENSE_VALID "); + if (qc_flags & ATA_QCFLAG_EH_SCHEDULED) + trace_seq_printf(p, "EH_SCHEDULED "); + trace_seq_putc(p, '}'); + } + trace_seq_putc(p, 0); + + return ret; +} diff --git a/include/trace/events/libata.h b/include/trace/events/libata.h new file mode 100644 index 0000000..8b0fbd9 --- /dev/null +++ b/include/trace/events/libata.h @@ -0,0 +1,325 @@ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM libata + +#if !defined(_TRACE_LIBATA_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_LIBATA_H + +#include +#include +#include +#include + +#define ata_opcode_name(opcode) { opcode, #opcode } +#define show_opcode_name(val) \ + __print_symbolic(val, \ + ata_opcode_name(ATA_CMD_DEV_RESET), \ + ata_opcode_name(ATA_CMD_CHK_POWER), \ + ata_opcode_name(ATA_CMD_STANDBY), \ + ata_opcode_name(ATA_CMD_IDLE), \ + ata_opcode_name(ATA_CMD_EDD), \ + ata_opcode_name(ATA_CMD_DOWNLOAD_MICRO), \ + ata_opcode_name(ATA_CMD_DOWNLOAD_MICRO_DMA), \ + ata_opcode_name(ATA_CMD_NOP), \ + ata_opcode_name(ATA_CMD_FLUSH), \ + ata_opcode_name(ATA_CMD_FLUSH_EXT), \ + ata_opcode_name(ATA_CMD_ID_ATA), \ + ata_opcode_name(ATA_CMD_ID_ATAPI), \ + ata_opcode_name(ATA_CMD_SERVICE), \ + ata_opcode_name(ATA_CMD_READ), \ + ata_opcode_name(ATA_CMD_READ_EXT), \ + ata_opcode_name(ATA_CMD_READ_QUEUED), \ + ata_opcode_name(ATA_CMD_READ_STREAM_EXT), \ + ata_opcode_name(ATA_CMD_READ_STREAM_DMA_EXT), \ + ata_opcode_name(ATA_CMD_WRITE), \ + ata_opcode_name(ATA_CMD_WRITE_EXT), \ + ata_opcode_name(ATA_CMD_WRITE_QUEUED), \ + ata_opcode_name(ATA_CMD_WRITE_STREAM_EXT), \ + ata_opcode_name(ATA_CMD_WRITE_STREAM_DMA_EXT), \ + ata_opcode_name(ATA_CMD_WRITE_FUA_EXT), \ + ata_opcode_name(ATA_CMD_WRITE_QUEUED_FUA_EXT), \ + ata_opcode_name(ATA_CMD_FPDMA_READ), \ + ata_opcode_name(ATA_CMD_FPDMA_WRITE), \ + ata_opcode_name(ATA_CMD_FPDMA_SEND), \ + ata_opcode_name(ATA_CMD_FPDMA_RECV), \ + ata_opcode_name(ATA_CMD_PIO_READ), \ + ata_opcode_name(ATA_CMD_PIO_READ_EXT), \ + ata_opcode_name(ATA_CMD_PIO_WRITE), \ + ata_opcode_name(ATA_CMD_PIO_WRITE_EXT), \ + ata_opcode_name(ATA_CMD_READ_MULTI), \ + ata_opcode_name(ATA_CMD_READ_MULTI_EXT), \ + ata_opcode_name(ATA_CMD_WRITE_MULTI), \ + ata_opcode_name(ATA_CMD_WRITE_MULTI_EXT), \ + ata_opcode_name(ATA_CMD_WRITE_MULTI_FUA_EXT), \ + ata_opcode_name(ATA_CMD_SET_FEATURES), \ + ata_opcode_name(ATA_CMD_SET_MULTI), \ + ata_opcode_name(ATA_CMD_PACKET), \ + ata_opcode_name(ATA_CMD_VERIFY), \ + ata_opcode_name(ATA_CMD_VERIFY_EXT), \ + ata_opcode_name(ATA_CMD_WRITE_UNCORR_EXT), \ + ata_opcode_name(ATA_CMD_STANDBYNOW1), \ + ata_opcode_name(ATA_CMD_IDLEIMMEDIATE), \ + ata_opcode_name(ATA_CMD_SLEEP), \ + ata_opcode_name(ATA_CMD_INIT_DEV_PARAMS), \ + ata_opcode_name(ATA_CMD_READ_NATIVE_MAX), \ + ata_opcode_name(ATA_CMD_READ_NATIVE_MAX_EXT), \ + ata_opcode_name(ATA_CMD_SET_MAX), \ + ata_opcode_name(ATA_CMD_SET_MAX_EXT), \ + ata_opcode_name(ATA_CMD_READ_LOG_EXT), \ + ata_opcode_name(ATA_CMD_WRITE_LOG_EXT), \ + ata_opcode_name(ATA_CMD_READ_LOG_DMA_EXT), \ + ata_opcode_name(ATA_CMD_WRITE_LOG_DMA_EXT), \ + ata_opcode_name(ATA_CMD_TRUSTED_NONDATA), \ + ata_opcode_name(ATA_CMD_TRUSTED_RCV), \ + ata_opcode_name(ATA_CMD_TRUSTED_RCV_DMA), \ + ata_opcode_name(ATA_CMD_TRUSTED_SND), \ + ata_opcode_name(ATA_CMD_TRUSTED_SND_DMA), \ + ata_opcode_name(ATA_CMD_PMP_READ), \ + ata_opcode_name(ATA_CMD_PMP_READ_DMA), \ + ata_opcode_name(ATA_CMD_PMP_WRITE), \ + ata_opcode_name(ATA_CMD_PMP_WRITE_DMA), \ + ata_opcode_name(ATA_CMD_CONF_OVERLAY), \ + ata_opcode_name(ATA_CMD_SEC_SET_PASS), \ + ata_opcode_name(ATA_CMD_SEC_UNLOCK), \ + ata_opcode_name(ATA_CMD_SEC_ERASE_PREP), \ + ata_opcode_name(ATA_CMD_SEC_ERASE_UNIT), \ + ata_opcode_name(ATA_CMD_SEC_FREEZE_LOCK), \ + ata_opcode_name(ATA_CMD_SEC_DISABLE_PASS), \ + ata_opcode_name(ATA_CMD_CONFIG_STREAM), \ + ata_opcode_name(ATA_CMD_SMART), \ + ata_opcode_name(ATA_CMD_MEDIA_LOCK), \ + ata_opcode_name(ATA_CMD_MEDIA_UNLOCK), \ + ata_opcode_name(ATA_CMD_DSM), \ + ata_opcode_name(ATA_CMD_CHK_MED_CRD_TYP), \ + ata_opcode_name(ATA_CMD_CFA_REQ_EXT_ERR), \ + ata_opcode_name(ATA_CMD_CFA_WRITE_NE), \ + ata_opcode_name(ATA_CMD_CFA_TRANS_SECT), \ + ata_opcode_name(ATA_CMD_CFA_ERASE), \ + ata_opcode_name(ATA_CMD_CFA_WRITE_MULT_NE), \ + ata_opcode_name(ATA_CMD_REQ_SENSE_DATA), \ + ata_opcode_name(ATA_CMD_SANITIZE_DEVICE), \ + ata_opcode_name(ATA_CMD_RESTORE), \ + ata_opcode_name(ATA_CMD_READ_LONG), \ + ata_opcode_name(ATA_CMD_READ_LONG_ONCE), \ + ata_opcode_name(ATA_CMD_WRITE_LONG), \ + ata_opcode_name(ATA_CMD_WRITE_LONG_ONCE)) + +#define ata_error_name(result) { result, #result } +#define show_error_name(val) \ + __print_symbolic(val, \ + ata_error_name(ATA_ICRC), \ + ata_error_name(ATA_UNC), \ + ata_error_name(ATA_MC), \ + ata_error_name(ATA_IDNF), \ + ata_error_name(ATA_MCR), \ + ata_error_name(ATA_ABORTED), \ + ata_error_name(ATA_TRK0NF), \ + ata_error_name(ATA_AMNF)) + +#define ata_protocol_name(proto) { proto, #proto } +#define show_protocol_name(val) \ + __print_symbolic(val, \ + ata_protocol_name(ATA_PROT_UNKNOWN), \ + ata_protocol_name(ATA_PROT_NODATA), \ + ata_protocol_name(ATA_PROT_PIO), \ + ata_protocol_name(ATA_PROT_DMA), \ + ata_protocol_name(ATA_PROT_NCQ), \ + ata_protocol_name(ATAPI_PROT_NODATA), \ + ata_protocol_name(ATAPI_PROT_PIO), \ + ata_protocol_name(ATAPI_PROT_DMA)) + +const char *libata_trace_parse_status(struct trace_seq*, unsigned char); +#define __parse_status(s) libata_trace_parse_status(p, s) + +const char *libata_trace_parse_eh_action(struct trace_seq *, unsigned int); +#define __parse_eh_action(a) libata_trace_parse_eh_action(p, a) + +const char *libata_trace_parse_eh_err_mask(struct trace_seq *, unsigned int); +#define __parse_eh_err_mask(m) libata_trace_parse_eh_err_mask(p, m) + +const char *libata_trace_parse_qc_flags(struct trace_seq *, unsigned int); +#define __parse_qc_flags(f) libata_trace_parse_qc_flags(p, f) + +TRACE_EVENT(ata_qc_issue, + + TP_PROTO(struct ata_queued_cmd *qc), + + TP_ARGS(qc), + + TP_STRUCT__entry( + __field( unsigned int, ata_port ) + __field( unsigned int, ata_dev ) + __field( unsigned int, tag ) + __field( unsigned char, cmd ) + __field( unsigned char, dev ) + __field( unsigned char, lbal ) + __field( unsigned char, lbam ) + __field( unsigned char, lbah ) + __field( unsigned char, nsect ) + __field( unsigned char, feature ) + __field( unsigned char, hob_lbal ) + __field( unsigned char, hob_lbam ) + __field( unsigned char, hob_lbah ) + __field( unsigned char, hob_nsect ) + __field( unsigned char, hob_feature ) + __field( unsigned char, ctl ) + __field( unsigned char, proto ) + __field( unsigned long, flags ) + ), + + TP_fast_assign( + __entry->ata_port = qc->ap->print_id; + __entry->ata_dev = qc->dev->link->pmp + qc->dev->devno; + __entry->tag = qc->tag; + __entry->proto = qc->tf.protocol; + __entry->cmd = qc->tf.command; + __entry->dev = qc->tf.device; + __entry->lbal = qc->tf.lbal; + __entry->lbam = qc->tf.lbam; + __entry->lbah = qc->tf.lbah; + __entry->hob_lbal = qc->tf.hob_lbal; + __entry->hob_lbam = qc->tf.hob_lbam; + __entry->hob_lbah = qc->tf.hob_lbah; + __entry->feature = qc->tf.feature; + __entry->hob_feature = qc->tf.hob_feature; + __entry->nsect = qc->tf.nsect; + __entry->hob_nsect = qc->tf.hob_nsect; + ), + + TP_printk("ata_port=%u ata_dev=%u tag=%d proto=%s cmd=%s " \ + " tf=(%02x/%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x/%02x)", + __entry->ata_port, __entry->ata_dev, __entry->tag, + show_protocol_name(__entry->proto), + show_opcode_name(__entry->cmd), + __entry->cmd, __entry->feature, __entry->nsect, + __entry->lbal, __entry->lbam, __entry->lbah, + __entry->hob_feature, __entry->hob_nsect, + __entry->hob_lbal, __entry->hob_lbam, __entry->hob_lbah, + __entry->dev) +); + +DECLARE_EVENT_CLASS(ata_qc_complete_template, + + TP_PROTO(struct ata_queued_cmd *qc), + + TP_ARGS(qc), + + TP_STRUCT__entry( + __field( unsigned int, ata_port ) + __field( unsigned int, ata_dev ) + __field( unsigned int, tag ) + __field( unsigned char, status ) + __field( unsigned char, dev ) + __field( unsigned char, lbal ) + __field( unsigned char, lbam ) + __field( unsigned char, lbah ) + __field( unsigned char, nsect ) + __field( unsigned char, error ) + __field( unsigned char, hob_lbal ) + __field( unsigned char, hob_lbam ) + __field( unsigned char, hob_lbah ) + __field( unsigned char, hob_nsect ) + __field( unsigned char, hob_feature ) + __field( unsigned char, ctl ) + __field( unsigned long, flags ) + ), + + TP_fast_assign( + __entry->ata_port = qc->ap->print_id; + __entry->ata_dev = qc->dev->link->pmp + qc->dev->devno; + __entry->tag = qc->tag; + __entry->status = qc->result_tf.command; + __entry->dev = qc->result_tf.device; + __entry->lbal = qc->result_tf.lbal; + __entry->lbam = qc->result_tf.lbam; + __entry->lbah = qc->result_tf.lbah; + __entry->hob_lbal = qc->result_tf.hob_lbal; + __entry->hob_lbam = qc->result_tf.hob_lbam; + __entry->hob_lbah = qc->result_tf.hob_lbah; + __entry->error = qc->result_tf.feature; + __entry->hob_feature = qc->result_tf.hob_feature; + __entry->nsect = qc->result_tf.nsect; + __entry->hob_nsect = qc->result_tf.hob_nsect; + ), + + TP_printk("ata_port=%u ata_dev=%u tag=%d flags=%s status=%s " \ + " res=(%02x/%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x/%02x)", + __entry->ata_port, __entry->ata_dev, __entry->tag, + __parse_qc_flags(__entry->flags), + __parse_status(__entry->status), + __entry->status, __entry->error, __entry->nsect, + __entry->lbal, __entry->lbam, __entry->lbah, + __entry->hob_feature, __entry->hob_nsect, + __entry->hob_lbal, __entry->hob_lbam, __entry->hob_lbah, + __entry->dev) +); + +DEFINE_EVENT(ata_qc_complete_template, ata_qc_complete_internal, + TP_PROTO(struct ata_queued_cmd *qc), + TP_ARGS(qc)); + +DEFINE_EVENT(ata_qc_complete_template, ata_qc_complete_failed, + TP_PROTO(struct ata_queued_cmd *qc), + TP_ARGS(qc)); + +DEFINE_EVENT(ata_qc_complete_template, ata_qc_complete_done, + TP_PROTO(struct ata_queued_cmd *qc), + TP_ARGS(qc)); + +TRACE_EVENT(ata_eh_link_autopsy, + + TP_PROTO(struct ata_device *dev, unsigned int eh_action, unsigned int eh_err_mask), + + TP_ARGS(dev, eh_action, eh_err_mask), + + TP_STRUCT__entry( + __field( unsigned int, ata_port ) + __field( unsigned int, ata_dev ) + __field( unsigned int, eh_action ) + __field( unsigned int, eh_err_mask) + ), + + TP_fast_assign( + __entry->ata_port = dev->link->ap->print_id; + __entry->ata_dev = dev->link->pmp + dev->devno; + __entry->eh_action = eh_action; + __entry->eh_err_mask = eh_err_mask; + ), + + TP_printk("ata_port=%u ata_dev=%u eh_action=%s err_mask=%s", + __entry->ata_port, __entry->ata_dev, + __parse_eh_action(__entry->eh_action), + __parse_eh_err_mask(__entry->eh_err_mask)) +); + +TRACE_EVENT(ata_eh_link_autopsy_qc, + + TP_PROTO(struct ata_queued_cmd *qc), + + TP_ARGS(qc), + + TP_STRUCT__entry( + __field( unsigned int, ata_port ) + __field( unsigned int, ata_dev ) + __field( unsigned int, tag ) + __field( unsigned int, qc_flags ) + __field( unsigned int, eh_err_mask) + ), + + TP_fast_assign( + __entry->ata_port = qc->ap->print_id; + __entry->ata_dev = qc->dev->link->pmp + qc->dev->devno; + __entry->tag = qc->tag; + __entry->qc_flags = qc->flags; + __entry->eh_err_mask = qc->err_mask; + ), + + TP_printk("ata_port=%u ata_dev=%u tag=%d flags=%s err_mask=%s", + __entry->ata_port, __entry->ata_dev, __entry->tag, + __parse_qc_flags(__entry->qc_flags), + __parse_eh_err_mask(__entry->eh_err_mask)) +); + +#endif /* _TRACE_LIBATA_H */ + +/* This part must be outside protection */ +#include -- cgit v0.10.2 From 8d5fe8d5eda6854a4c7f5e1b98f3d884f0604137 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 30 Mar 2015 13:30:25 +0300 Subject: sata_dwc_460ex: indent an if statement We shuffled some code around in 8b3444852a2b ('sata_dwc_460ex: move to generic DMA driver') an accidentally deleted a tab character here. It causes a Smatch warning "if statement not indented". Signed-off-by: Dan Carpenter Reviewed-by: Andy Shevchenko Signed-off-by: Tejun Heo diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 5ab4849..9020349 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -295,7 +295,7 @@ static void dma_dwc_xfer_done(void *hsdev_instance) } if ((hsdevp->dma_interrupt_count % 2) == 0) - sata_dwc_dma_xfer_complete(ap, 1); + sata_dwc_dma_xfer_complete(ap, 1); spin_unlock_irqrestore(&host->lock, flags); } -- cgit v0.10.2 From b6305d62234642a37fa1a68d15e741cfc3428c45 Mon Sep 17 00:00:00 2001 From: Peter Griffin Date: Tue, 31 Mar 2015 18:37:12 +0100 Subject: ahci: st: Update the DT example for how to obtain the PHY. The example is wrong in that the phys property should take a phandle to the phy port. Also with the changing over to generic PHY type constants we also update that as well. Signed-off-by: Peter Griffin Acked-by: Rob Herring Acked-by: Lee Jones Signed-off-by: Tejun Heo diff --git a/Documentation/devicetree/bindings/ata/ahci-st.txt b/Documentation/devicetree/bindings/ata/ahci-st.txt index 0574a77..1331202 100644 --- a/Documentation/devicetree/bindings/ata/ahci-st.txt +++ b/Documentation/devicetree/bindings/ata/ahci-st.txt @@ -11,7 +11,7 @@ Required properties: - reset-names : Associated names must be; "pwr-dwn" and "sw-rst" - clocks : The phandle for the clock - clock-names : Associated name must be; "ahci_clk" - - phys : The phandle for the PHY device + - phys : The phandle for the PHY port - phy-names : Associated name must be; "ahci_phy" Example: @@ -21,7 +21,7 @@ Example: reg = <0xfe380000 0x1000>; interrupts = ; interrupt-names = "hostc"; - phys = <&miphy365x_phy MIPHY_PORT_0 MIPHY_TYPE_SATA>; + phys = <&phy_port0 PHY_TYPE_SATA>; phy-names = "ahci_phy"; resets = <&powerdown STIH416_SATA0_POWERDOWN>, <&softreset STIH416_SATA0_SOFTRESET>; -- cgit v0.10.2 From 9a8340bfeb03c5fc20b39aa533b164844ef582f9 Mon Sep 17 00:00:00 2001 From: Peter Griffin Date: Tue, 31 Mar 2015 08:35:07 +0100 Subject: ahci: st: Update the ahci_st DT documentation As part of testing ahci_st driver working on stih407 I noticed several things wrong in the DT documentation: - 1) Compatible string doesn't match the driver code 2) pwr-rst reset isn't documented (but exists in the driver) 3) some whitespace issues (spaces not tabs) Also add in a stih407 family example into the doc. Signed-off-by: Peter Griffin Acked-by: Lee Jones Acked-by: Maxime Coquelin Signed-off-by: Tejun Heo diff --git a/Documentation/devicetree/bindings/ata/ahci-st.txt b/Documentation/devicetree/bindings/ata/ahci-st.txt index 1331202..e1d01df 100644 --- a/Documentation/devicetree/bindings/ata/ahci-st.txt +++ b/Documentation/devicetree/bindings/ata/ahci-st.txt @@ -3,29 +3,48 @@ STMicroelectronics STi SATA controller This binding describes a SATA device. Required properties: - - compatible : Must be "st,sti-ahci" + - compatible : Must be "st,ahci" - reg : Physical base addresses and length of register sets - interrupts : Interrupt associated with the SATA device - interrupt-names : Associated name must be; "hostc" - - resets : The power-down and soft-reset lines of SATA IP - - reset-names : Associated names must be; "pwr-dwn" and "sw-rst" - clocks : The phandle for the clock - clock-names : Associated name must be; "ahci_clk" - phys : The phandle for the PHY port - phy-names : Associated name must be; "ahci_phy" +Optional properties: + - resets : The power-down, soft-reset and power-reset lines of SATA IP + - reset-names : Associated names must be; "pwr-dwn", "sw-rst" and "pwr-rst" + Example: + /* Example for stih416 */ sata0: sata@fe380000 { - compatible = "st,sti-ahci"; - reg = <0xfe380000 0x1000>; - interrupts = ; - interrupt-names = "hostc"; - phys = <&phy_port0 PHY_TYPE_SATA>; - phy-names = "ahci_phy"; - resets = <&powerdown STIH416_SATA0_POWERDOWN>, + compatible = "st,ahci"; + reg = <0xfe380000 0x1000>; + interrupts = ; + interrupt-names = "hostc"; + phys = <&phy_port0 PHY_TYPE_SATA>; + phy-names = "ahci_phy"; + resets = <&powerdown STIH416_SATA0_POWERDOWN>, <&softreset STIH416_SATA0_SOFTRESET>; - reset-names = "pwr-dwn", "sw-rst"; - clocks = <&clk_s_a0_ls CLK_ICN_REG>; - clock-names = "ahci_clk"; + reset-names = "pwr-dwn", "sw-rst"; + clocks = <&clk_s_a0_ls CLK_ICN_REG>; + clock-names = "ahci_clk"; + }; + + /* Example for stih407 family silicon */ + sata0: sata@9b20000 { + compatible = "st,ahci"; + reg = <0x9b20000 0x1000>; + interrupts = ; + interrupt-names = "hostc"; + phys = <&phy_port0 PHY_TYPE_SATA>; + phy-names = "ahci_phy"; + resets = <&powerdown STIH407_SATA0_POWERDOWN>, + <&softreset STIH407_SATA0_SOFTRESET>, + <&softreset STIH407_SATA0_PWR_SOFTRESET>; + reset-names = "pwr-dwn", "sw-rst", "pwr-rst"; + clocks = <&clk_s_c0_flexgen CLK_ICN_REG>; + clock-names = "ahci_clk"; }; -- cgit v0.10.2 From 9a1e75e11a8d09c5cba022e1ac04b0785354f708 Mon Sep 17 00:00:00 2001 From: Peter Griffin Date: Tue, 31 Mar 2015 08:35:09 +0100 Subject: ahci: st: st_configure_oob must be called after IP is clocked. Currently the ahci_st driver will hang the system on probe, as the st_configure_oob function does some register writes before the IP is clocked. This patch moves the function call to after ahci_platform_enable_resources (which enables the IP clock), and resolves the hang. Addtionally st_ahci_configure_oob should be called in the st_ahci_resume function, so we also rectify that ensuring it is also called after the IP clock has been enabled. Signed-off-by: Peter Griffin Acked-by: Lee Jones Acked-by: Maxime Coquelin Signed-off-by: Tejun Heo diff --git a/drivers/ata/ahci_st.c b/drivers/ata/ahci_st.c index bc971af..ea0ff00 100644 --- a/drivers/ata/ahci_st.c +++ b/drivers/ata/ahci_st.c @@ -68,8 +68,6 @@ static int st_ahci_deassert_resets(struct device *dev) } } - st_ahci_configure_oob(drv_data->hpriv->mmio); - if (drv_data->sw_rst) { err = reset_control_deassert(drv_data->sw_rst); if (err) { @@ -172,6 +170,8 @@ static int st_ahci_probe(struct platform_device *pdev) if (err) return err; + st_ahci_configure_oob(drv_data->hpriv->mmio); + err = ahci_platform_init_host(pdev, hpriv, &st_ahci_port_info, &ahci_platform_sht); if (err) { @@ -222,6 +222,8 @@ static int st_ahci_resume(struct device *dev) return err; } + st_ahci_configure_oob(drv_data->hpriv->mmio); + return ahci_platform_resume_host(dev); } #endif -- cgit v0.10.2 From c54c719b558e0eb3ba60b1390aeb47ed25ff4352 Mon Sep 17 00:00:00 2001 From: Quentin Lambert Date: Wed, 8 Apr 2015 14:34:10 +0200 Subject: ata: remove deprecated use of pci api Replace occurences of the pci api by appropriate call to the dma api. A simplified version of the semantic patch that finds this problem is as follows: (http://coccinelle.lip6.fr) @deprecated@ idexpression id; position p; @@ ( pci_dma_supported@p ( id, ...) | pci_alloc_consistent@p ( id, ...) ) @bad1@ idexpression id; position deprecated.p; @@ ...when != &id->dev when != pci_get_drvdata ( id ) when != pci_enable_device ( id ) ( pci_dma_supported@p ( id, ...) | pci_alloc_consistent@p ( id, ...) ) @depends on !bad1@ idexpression id; expression direction; position deprecated.p; @@ ( - pci_dma_supported@p ( id, + dma_supported ( &id->dev, ... + , GFP_ATOMIC ) | - pci_alloc_consistent@p ( id, + dma_alloc_coherent ( &id->dev, ... + , GFP_ATOMIC ) ) Signed-off-by: Quentin Lambert Signed-off-by: Tejun Heo diff --git a/drivers/ata/acard-ahci.c b/drivers/ata/acard-ahci.c index c962886d..12489ce 100644 --- a/drivers/ata/acard-ahci.c +++ b/drivers/ata/acard-ahci.c @@ -181,10 +181,10 @@ static int acard_ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac) int rc; if (using_dac && - !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { - rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); + !dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) { + rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64)); if (rc) { - rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); + rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); if (rc) { dev_err(&pdev->dev, "64-bit DMA enable failed\n"); @@ -192,12 +192,12 @@ static int acard_ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac) } } } else { - rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); if (rc) { dev_err(&pdev->dev, "32-bit DMA enable failed\n"); return rc; } - rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); + rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); if (rc) { dev_err(&pdev->dev, "32-bit consistent DMA enable failed\n"); diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 33bb06e..c7a92a7 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -738,10 +738,10 @@ static int ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac) return 0; if (using_dac && - !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { - rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); + !dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) { + rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64)); if (rc) { - rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); + rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); if (rc) { dev_err(&pdev->dev, "64-bit DMA enable failed\n"); @@ -749,12 +749,12 @@ static int ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac) } } } else { - rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); if (rc) { dev_err(&pdev->dev, "32-bit DMA enable failed\n"); return rc; } - rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); + rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); if (rc) { dev_err(&pdev->dev, "32-bit consistent DMA enable failed\n"); diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 2e86e3b..cdf6215 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -3220,11 +3220,11 @@ void ata_pci_bmdma_init(struct ata_host *host) * ->sff_irq_clear method. Try to initialize bmdma_addr * regardless of dma masks. */ - rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); + rc = dma_set_mask(&pdev->dev, ATA_DMA_MASK); if (rc) ata_bmdma_nodma(host, "failed to set dma mask"); if (!rc) { - rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); + rc = dma_set_coherent_mask(&pdev->dev, ATA_DMA_MASK); if (rc) ata_bmdma_nodma(host, "failed to set consistent dma mask"); diff --git a/drivers/ata/pata_atp867x.c b/drivers/ata/pata_atp867x.c index a705cfc..3ea50dc 100644 --- a/drivers/ata/pata_atp867x.c +++ b/drivers/ata/pata_atp867x.c @@ -475,11 +475,11 @@ static int atp867x_ata_pci_sff_init_host(struct ata_host *host) atp867x_fixup(host); - rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); + rc = dma_set_mask(&pdev->dev, ATA_DMA_MASK); if (rc) return rc; - rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); + rc = dma_set_coherent_mask(&pdev->dev, ATA_DMA_MASK); return rc; } diff --git a/drivers/ata/pata_cs5520.c b/drivers/ata/pata_cs5520.c index d65cb9d..4cb2407 100644 --- a/drivers/ata/pata_cs5520.c +++ b/drivers/ata/pata_cs5520.c @@ -164,11 +164,11 @@ static int cs5520_init_one(struct pci_dev *pdev, const struct pci_device_id *id) return -ENODEV; } - if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) { + if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(32))) { printk(KERN_ERR DRV_NAME ": unable to configure DMA mask.\n"); return -ENODEV; } - if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) { + if (dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32))) { printk(KERN_ERR DRV_NAME ": unable to configure consistent DMA mask.\n"); return -ENODEV; } diff --git a/drivers/ata/pata_hpt3x3.c b/drivers/ata/pata_hpt3x3.c index d019cdd..b2fc023 100644 --- a/drivers/ata/pata_hpt3x3.c +++ b/drivers/ata/pata_hpt3x3.c @@ -221,10 +221,10 @@ static int hpt3x3_init_one(struct pci_dev *pdev, const struct pci_device_id *id) if (rc) return rc; host->iomap = pcim_iomap_table(pdev); - rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); + rc = dma_set_mask(&pdev->dev, ATA_DMA_MASK); if (rc) return rc; - rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); + rc = dma_set_coherent_mask(&pdev->dev, ATA_DMA_MASK); if (rc) return rc; diff --git a/drivers/ata/pata_ninja32.c b/drivers/ata/pata_ninja32.c index efb272d..633aa29 100644 --- a/drivers/ata/pata_ninja32.c +++ b/drivers/ata/pata_ninja32.c @@ -122,10 +122,10 @@ static int ninja32_init_one(struct pci_dev *dev, const struct pci_device_id *id) return rc; host->iomap = pcim_iomap_table(dev); - rc = pci_set_dma_mask(dev, ATA_DMA_MASK); + rc = dma_set_mask(&dev->dev, ATA_DMA_MASK); if (rc) return rc; - rc = pci_set_consistent_dma_mask(dev, ATA_DMA_MASK); + rc = dma_set_coherent_mask(&dev->dev, ATA_DMA_MASK); if (rc) return rc; pci_set_master(dev); diff --git a/drivers/ata/pata_pdc2027x.c b/drivers/ata/pata_pdc2027x.c index dca8251..d9ef9e2 100644 --- a/drivers/ata/pata_pdc2027x.c +++ b/drivers/ata/pata_pdc2027x.c @@ -730,11 +730,11 @@ static int pdc2027x_init_one(struct pci_dev *pdev, return rc; host->iomap = pcim_iomap_table(pdev); - rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); + rc = dma_set_mask(&pdev->dev, ATA_DMA_MASK); if (rc) return rc; - rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); + rc = dma_set_coherent_mask(&pdev->dev, ATA_DMA_MASK); if (rc) return rc; diff --git a/drivers/ata/pata_scc.c b/drivers/ata/pata_scc.c index 7f4cb76..5cd60d6 100644 --- a/drivers/ata/pata_scc.c +++ b/drivers/ata/pata_scc.c @@ -1029,10 +1029,10 @@ static int scc_host_init(struct ata_host *host) if (rc) return rc; - rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); + rc = dma_set_mask(&pdev->dev, ATA_DMA_MASK); if (rc) return rc; - rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); + rc = dma_set_coherent_mask(&pdev->dev, ATA_DMA_MASK); if (rc) return rc; diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c index f597edc..c14071b 100644 --- a/drivers/ata/pata_sil680.c +++ b/drivers/ata/pata_sil680.c @@ -374,10 +374,10 @@ static int sil680_init_one(struct pci_dev *pdev, const struct pci_device_id *id) host->iomap = pcim_iomap_table(pdev); /* Setup DMA masks */ - rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); + rc = dma_set_mask(&pdev->dev, ATA_DMA_MASK); if (rc) return rc; - rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); + rc = dma_set_coherent_mask(&pdev->dev, ATA_DMA_MASK); if (rc) return rc; pci_set_master(pdev); diff --git a/drivers/ata/pdc_adma.c b/drivers/ata/pdc_adma.c index f10631b..64d682c 100644 --- a/drivers/ata/pdc_adma.c +++ b/drivers/ata/pdc_adma.c @@ -593,12 +593,12 @@ static int adma_set_dma_masks(struct pci_dev *pdev, void __iomem *mmio_base) { int rc; - rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); if (rc) { dev_err(&pdev->dev, "32-bit DMA enable failed\n"); return rc; } - rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); + rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); if (rc) { dev_err(&pdev->dev, "32-bit consistent DMA enable failed\n"); return rc; diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c index 0698278..e81a821 100644 --- a/drivers/ata/sata_inic162x.c +++ b/drivers/ata/sata_inic162x.c @@ -856,13 +856,13 @@ static int inic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) } /* Set dma_mask. This devices doesn't support 64bit addressing. */ - rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); if (rc) { dev_err(&pdev->dev, "32-bit DMA enable failed\n"); return rc; } - rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); + rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); if (rc) { dev_err(&pdev->dev, "32-bit consistent DMA enable failed\n"); return rc; diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 0281785..bd74ee5 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -4320,10 +4320,10 @@ static int pci_go_64(struct pci_dev *pdev) { int rc; - if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { - rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); + if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) { + rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64)); if (rc) { - rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); + rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); if (rc) { dev_err(&pdev->dev, "64-bit DMA enable failed\n"); @@ -4331,12 +4331,12 @@ static int pci_go_64(struct pci_dev *pdev) } } } else { - rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); if (rc) { dev_err(&pdev->dev, "32-bit DMA enable failed\n"); return rc; } - rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); + rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); if (rc) { dev_err(&pdev->dev, "32-bit consistent DMA enable failed\n"); diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index 1db6f5c..7ece85f 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c @@ -756,10 +756,10 @@ static int nv_adma_slave_config(struct scsi_device *sdev) blk_queue_bounce_limit(sdev1->request_queue, ATA_DMA_MASK); - pci_set_dma_mask(pdev, ATA_DMA_MASK); + dma_set_mask(&pdev->dev, ATA_DMA_MASK); } else { /** This shouldn't fail as it was set to this value before */ - pci_set_dma_mask(pdev, pp->adma_dma_mask); + dma_set_mask(&pdev->dev, pp->adma_dma_mask); if (sdev0) blk_queue_bounce_limit(sdev0->request_queue, pp->adma_dma_mask); @@ -1133,10 +1133,10 @@ static int nv_adma_port_start(struct ata_port *ap) /* Ensure DMA mask is set to 32-bit before allocating legacy PRD and pad buffers */ - rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); if (rc) return rc; - rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); + rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); if (rc) return rc; @@ -1161,8 +1161,8 @@ static int nv_adma_port_start(struct ata_port *ap) These are allowed to fail since we store the value that ends up being used to set as the bounce limit in slave_config later if needed. */ - pci_set_dma_mask(pdev, DMA_BIT_MASK(64)); - pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); + dma_set_mask(&pdev->dev, DMA_BIT_MASK(64)); + dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64)); pp->adma_dma_mask = *dev->dma_mask; mem = dmam_alloc_coherent(dev, NV_ADMA_PORT_PRIV_DMA_SZ, diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c index 3638887..0fa211e 100644 --- a/drivers/ata/sata_promise.c +++ b/drivers/ata/sata_promise.c @@ -1246,10 +1246,10 @@ static int pdc_ata_init_one(struct pci_dev *pdev, /* initialize adapter */ pdc_host_init(host); - rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); + rc = dma_set_mask(&pdev->dev, ATA_DMA_MASK); if (rc) return rc; - rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); + rc = dma_set_coherent_mask(&pdev->dev, ATA_DMA_MASK); if (rc) return rc; diff --git a/drivers/ata/sata_qstor.c b/drivers/ata/sata_qstor.c index 9a6bd4c..af987a4 100644 --- a/drivers/ata/sata_qstor.c +++ b/drivers/ata/sata_qstor.c @@ -557,10 +557,10 @@ static int qs_set_dma_masks(struct pci_dev *pdev, void __iomem *mmio_base) int rc, have_64bit_bus = (bus_info & QS_HPHY_64BIT); if (have_64bit_bus && - !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { - rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); + !dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) { + rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64)); if (rc) { - rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); + rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); if (rc) { dev_err(&pdev->dev, "64-bit DMA enable failed\n"); @@ -568,12 +568,12 @@ static int qs_set_dma_masks(struct pci_dev *pdev, void __iomem *mmio_base) } } } else { - rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); if (rc) { dev_err(&pdev->dev, "32-bit DMA enable failed\n"); return rc; } - rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); + rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); if (rc) { dev_err(&pdev->dev, "32-bit consistent DMA enable failed\n"); diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c index 40b76b2..dea6edcb 100644 --- a/drivers/ata/sata_sil.c +++ b/drivers/ata/sata_sil.c @@ -770,10 +770,10 @@ static int sil_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) return rc; host->iomap = pcim_iomap_table(pdev); - rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); + rc = dma_set_mask(&pdev->dev, ATA_DMA_MASK); if (rc) return rc; - rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); + rc = dma_set_coherent_mask(&pdev->dev, ATA_DMA_MASK); if (rc) return rc; diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c index 5242897..4b1995e 100644 --- a/drivers/ata/sata_sil24.c +++ b/drivers/ata/sata_sil24.c @@ -1312,10 +1312,10 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) host->iomap = iomap; /* configure and activate the device */ - if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { - rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); + if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) { + rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64)); if (rc) { - rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); + rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); if (rc) { dev_err(&pdev->dev, "64-bit DMA enable failed\n"); @@ -1323,12 +1323,12 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) } } } else { - rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); if (rc) { dev_err(&pdev->dev, "32-bit DMA enable failed\n"); return rc; } - rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); + rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); if (rc) { dev_err(&pdev->dev, "32-bit consistent DMA enable failed\n"); diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c index c630fa8..ff8307b 100644 --- a/drivers/ata/sata_svw.c +++ b/drivers/ata/sata_svw.c @@ -496,10 +496,10 @@ static int k2_sata_init_one(struct pci_dev *pdev, const struct pci_device_id *en ata_port_pbar_desc(ap, 5, offset, "port"); } - rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); + rc = dma_set_mask(&pdev->dev, ATA_DMA_MASK); if (rc) return rc; - rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); + rc = dma_set_coherent_mask(&pdev->dev, ATA_DMA_MASK); if (rc) return rc; diff --git a/drivers/ata/sata_sx4.c b/drivers/ata/sata_sx4.c index 39b5de6..3a18a8a 100644 --- a/drivers/ata/sata_sx4.c +++ b/drivers/ata/sata_sx4.c @@ -1476,10 +1476,10 @@ static int pdc_sata_init_one(struct pci_dev *pdev, } /* configure and activate */ - rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); + rc = dma_set_mask(&pdev->dev, ATA_DMA_MASK); if (rc) return rc; - rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); + rc = dma_set_coherent_mask(&pdev->dev, ATA_DMA_MASK); if (rc) return rc; diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c index 47bf894..17d31fc 100644 --- a/drivers/ata/sata_via.c +++ b/drivers/ata/sata_via.c @@ -502,10 +502,10 @@ static int vt6421_prepare_host(struct pci_dev *pdev, struct ata_host **r_host) for (i = 0; i < host->n_ports; i++) vt6421_init_addrs(host->ports[i]); - rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); + rc = dma_set_mask(&pdev->dev, ATA_DMA_MASK); if (rc) return rc; - rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); + rc = dma_set_coherent_mask(&pdev->dev, ATA_DMA_MASK); if (rc) return rc; diff --git a/drivers/ata/sata_vsc.c b/drivers/ata/sata_vsc.c index 29e847a..183eb52 100644 --- a/drivers/ata/sata_vsc.c +++ b/drivers/ata/sata_vsc.c @@ -387,10 +387,10 @@ static int vsc_sata_init_one(struct pci_dev *pdev, /* * Use 32 bit DMA mask, because 64 bit address support is poor. */ - rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); if (rc) return rc; - rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); + rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); if (rc) return rc; -- cgit v0.10.2