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);
}
示例#3
0
/*
 * 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;
}
示例#5
0
/*
 * 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;
}