static void sata_dwc_exec_command_by_tag(struct ata_port *ap, struct ata_taskfile *tf, u8 tag, u32 cmd_issued) { unsigned long flags; struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap); dev_dbg(ap->dev, "%s cmd(0x%02x): %s tag=%d\n", __func__, tf->command, ata_get_cmd_descript(tf->command), tag); spin_lock_irqsave(&ap->host->lock, flags); hsdevp->cmd_issued[tag] = cmd_issued; spin_unlock_irqrestore(&ap->host->lock, flags); clear_serror(); ata_sff_exec_command(ap, tf); }
static void sata_dwc_error_intr(struct ata_port *ap, struct sata_dwc_device *hsdev, uint intpr) { struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap); struct ata_eh_info *ehi = &ap->link.eh_info; unsigned int err_mask = 0, action = 0; 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); clear_serror(); clear_interrupt_bit(hsdev, SATA_DWC_INTPR_ERR); err_mask |= AC_ERR_HOST_BUS; action |= ATA_EH_RESET; ehi->serror |= serror; ehi->action |= action; qc = ata_qc_from_tag(ap, tag); if (qc) qc->err_mask |= err_mask; else ehi->err_mask |= err_mask; ata_port_abort(ap); }
/* * Function : sata_dwc_exec_command_by_tag * arguments : ata_port *ap, ata_taskfile *tf, u8 tag, u32 cmd_issued * Return value : None * This function keeps track of individual command tag ids and calls * ata_exec_command in libata */ static void sata_dwc_exec_command_by_tag(struct ata_port *ap, struct ata_taskfile *tf, u8 tag, u32 cmd_issued) { unsigned long flags; struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap); dev_dbg(ap->dev, "%s cmd(0x%02x): %s tag=%d\n", __func__, tf->command, ata_get_cmd_descript(tf->command), tag); spin_lock_irqsave(&ap->host->lock, flags); hsdevp->cmd_issued[tag] = cmd_issued; spin_unlock_irqrestore(&ap->host->lock, flags); /* * Clear SError before executing a new command. * sata_dwc_scr_write and read can not be used here. Clearing the PM * managed SError register for the disk needs to be done before the * task file is loaded. */ clear_serror(); ata_sff_exec_command(ap, tf); }
static int sata_dwc_port_start(struct ata_port *ap) { int err = 0; struct sata_dwc_device *hsdev; struct sata_dwc_device_port *hsdevp = NULL; struct device *pdev; int i; hsdev = HSDEV_FROM_AP(ap); dev_dbg(ap->dev, "%s: port_no=%d\n", __func__, ap->port_no); hsdev->host = ap->host; pdev = ap->host->dev; if (!pdev) { dev_err(ap->dev, "%s: no ap->host->dev\n", __func__); err = -ENODEV; goto CLEANUP; } hsdevp = kzalloc(sizeof(*hsdevp), GFP_KERNEL); if (!hsdevp) { dev_err(ap->dev, "%s: kmalloc failed for hsdevp\n", __func__); err = -ENOMEM; goto CLEANUP; } hsdevp->hsdev = hsdev; for (i = 0; i < SATA_DWC_QCMD_MAX; i++) hsdevp->cmd_issued[i] = SATA_DWC_CMD_ISSUED_NOT; ap->bmdma_prd = 0; ap->bmdma_prd_dma = 0; 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__); out_le32(&hsdev->sata_dwc_regs->dmacr, SATA_DWC_DMACR_TXRXCH_CLEAR); dev_dbg(ap->dev, "%s: setting burst size in DBTSR\n", __func__); out_le32(&hsdev->sata_dwc_regs->dbtsr, (SATA_DWC_DBTSR_MWR(AHB_DMA_BRST_DFLT) | SATA_DWC_DBTSR_MRD(AHB_DMA_BRST_DFLT))); } clear_serror(); ap->private_data = hsdevp; dev_dbg(ap->dev, "%s: done\n", __func__); return 0; CLEANUP_ALLOC: kfree(hsdevp); CLEANUP: dev_dbg(ap->dev, "%s: fail. ap->id = %d\n", __func__, ap->print_id); return err; }
/* * Function : sata_dwc_port_start * arguments : struct ata_ioports *port * Return value : returns 0 if success, error code otherwise * This function allocates the scatter gather LLI table for AHB DMA */ static int sata_dwc_port_start(struct ata_port *ap) { int err = 0; struct sata_dwc_device *hsdev; struct sata_dwc_device_port *hsdevp = NULL; struct device *pdev; int i; hsdev = HSDEV_FROM_AP(ap); dev_dbg(ap->dev, "%s: port_no=%d\n", __func__, ap->port_no); hsdev->host = ap->host; pdev = ap->host->dev; if (!pdev) { dev_err(ap->dev, "%s: no ap->host->dev\n", __func__); err = -ENODEV; goto CLEANUP; } /* Allocate Port Struct */ hsdevp = kzalloc(sizeof(*hsdevp), GFP_KERNEL); if (!hsdevp) { dev_err(ap->dev, "%s: kmalloc failed for hsdevp\n", __func__); err = -ENOMEM; goto CLEANUP; } hsdevp->hsdev = hsdev; for (i = 0; i < SATA_DWC_QCMD_MAX; i++) hsdevp->cmd_issued[i] = SATA_DWC_CMD_ISSUED_NOT; ap->bmdma_prd = 0; /* 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__); out_le32(&hsdev->sata_dwc_regs->dmacr, SATA_DWC_DMACR_TXRXCH_CLEAR); dev_dbg(ap->dev, "%s: setting burst size in DBTSR\n", __func__); out_le32(&hsdev->sata_dwc_regs->dbtsr, (SATA_DWC_DBTSR_MWR(AHB_DMA_BRST_DFLT) | SATA_DWC_DBTSR_MRD(AHB_DMA_BRST_DFLT))); } /* Clear any error bits before libata starts issuing commands */ clear_serror(); ap->private_data = hsdevp; dev_dbg(ap->dev, "%s: done\n", __func__); return 0; CLEANUP_ALLOC: kfree(hsdevp); CLEANUP: dev_dbg(ap->dev, "%s: fail. ap->id = %d\n", __func__, ap->print_id); return err; }