Commit baaa7805 authored by Mikhail Karpenko's avatar Mikhail Karpenko
Browse files

WIP: system recognizes sda1

dma_sync_sg_for_[cpu,device] were added. Driver crashes on reading large
block of data.
parent 61fe8442
Loading
Loading
Loading
Loading
+26 −2
Original line number Diff line number Diff line
@@ -134,6 +134,9 @@ address must be aligned to a 128-byte cache line, indicated by bits 06:00 being
	//libahci_debug_saxigp1_save(ap, 0x3000);
	//libahci_debug_saxigp1_save(ap, 0x3000);

	dev_info(dev, "flags (ATA_FLAG_xxx): %u", ap->flags);
	dev_info(dev, "pflags (ATA_PFLAG_xxx): %u", ap->pflags);

	dev_info(dev, "ahci_elphel.c: Calling  ahci_port_resume()");
	return ahci_port_resume(ap);
}
@@ -222,7 +225,6 @@ static int elphel_drv_probe(struct platform_device *pdev)
	//printk(KERN_DEBUG, "back converted mmio virt addr: %p\n", vaddr);
	printk(KERN_DEBUG "======");


	ret = ahci_platform_init_host(pdev, hpriv, &ahci_elphel_port_info,
			&ahci_platform_sht);
	if (ret) {
@@ -248,12 +250,28 @@ static unsigned int elphel_read_id(struct ata_device *dev, struct ata_taskfile *
{
	u32 err_mask;
	struct device *d = &dev->tdev;
	int i, len;
	char *msg_str;

	err_mask = ata_do_dev_read_id(dev, tf, id);
	if (err_mask)
		return err_mask;

	dev_info(d, "elphel_read_id(): issue identify command finished");
	dev_info(d, "elphel_read_id(): issue identify command finished\n");
	/*dev_info(d, "dump IDENTIFY:\n");
	msg_str = kzalloc(PAGE_SIZE, GFP_KERNEL);
	if (!msg_str)
		return 0;
	len = 0;
	for (i = 0; i < ATA_ID_WORDS; i++) {
		if ((i % 16) == 0 && i != 0) {
			dev_info(d, "%s\n", msg_str);
			len = 0;
		}
		len += snprintf(msg_str + len, PAGE_SIZE - len, "0x%04x ", id[i]);
	}
	// print last string
	dev_info(d, "%s\n", msg_str);*/

	return 0;
}
@@ -265,6 +283,7 @@ static struct ata_port_operations ahci_elphel_ops = {
};

static const struct ata_port_info ahci_elphel_port_info = {
		AHCI_HFLAGS(AHCI_HFLAG_NO_NCQ),
		.flags			= AHCI_FLAG_COMMON,
		.pio_mask		= ATA_PIO4,
		.udma_mask		= ATA_UDMA6,
@@ -273,6 +292,11 @@ static const struct ata_port_info ahci_elphel_port_info = {

static struct scsi_host_template ahci_platform_sht = {
		AHCI_SHT(DRV_NAME),
		.can_queue			= 1,
		.sg_tablesize		= AHCI_MAX_SG,
		.dma_boundary		= AHCI_DMA_BOUNDARY,
		.shost_attrs		= ahci_shost_attrs,
		.sdev_attrs			= ahci_sdev_attrs,
};

static const struct of_device_id ahci_elphel_of_match[] = {
+24 −8
Original line number Diff line number Diff line
@@ -1493,14 +1493,14 @@ void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
	pp->cmd_slot[tag].tbl_addr = cpu_to_le32((cmd_tbl_dma & 0xffffffff)); // All data correct

	pp->cmd_slot[tag].tbl_addr_hi = cpu_to_le32((cmd_tbl_dma >> 16) >> 16);
/*

	if (msg_str != NULL) {
		len = snprintf(msg_str, LIBAHCI_DEBUG_BUFSZ, "\tfill command slot %u: DW0 = 0x%08x, DW1 = 0x%08x, DW2 = 0x%08x, DW3 = 0x%08x",
				tag, pp->cmd_slot[tag].opts, pp->cmd_slot[tag].status, pp->cmd_slot[tag].tbl_addr, pp->cmd_slot[tag].tbl_addr_hi);
		libahci_debug_event(NULL, msg_str, len);
		kfree(msg_str);
	}
*/

}
EXPORT_SYMBOL_GPL(ahci_fill_cmd_slot);

@@ -1965,7 +1965,9 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc)
	u32 elhel_dbg_buf[128];
	int elphel_i;

	/*
	// elphel test: set tag = 0, change to qc->tag in functions below
	//unsigned int tag = 0;

	int len;
	char *msg_str = kzalloc(LIBAHCI_DEBUG_BUFSZ, GFP_KERNEL);
	if (msg_str != NULL) {
@@ -1973,7 +1975,7 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc)
		libahci_debug_event(ap, msg_str, len);
		kfree(msg_str);
	}
*/

	/*
	 * Fill in command table information.  First, the header,
	 * a SATA Register - Host to Device command FIS.
@@ -1985,6 +1987,7 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc)
//	dma_sync_single_for_cpu(qc->dev, pp->cmd_tbl_dma - 4096, AHCI_CMD_TBL_AR_SZ + 4096, DMA_TO_DEVICE);
	dma_sync_single_for_cpu(qc->dev, pp->cmd_tbl_dma, AHCI_CMD_TBL_AR_SZ, DMA_TO_DEVICE);
	cmd_tbl = pp->cmd_tbl + qc->tag * AHCI_CMD_TBL_SZ;
	//cmd_tbl = pp->cmd_tbl + tag * AHCI_CMD_TBL_SZ;

//	elphel_dbg_ptr = (u32*) cmd_tbl;

@@ -2017,12 +2020,21 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc)
//		libahci_debug_dump_region(ap, (const u32 *)(cmd_tbl + AHCI_CMD_TBL_CDB), 4, "\tthis is ATAPI command, dump ACMD region: ");
	}

//	libahci_debug_dump_region(ap, (const u32 *)cmd_tbl, cmd_fis_len, "\twrite H2D register FIS; dump: ");
	libahci_debug_dump_region(ap, (const u32 *)cmd_tbl, cmd_fis_len, "\twrite H2D register FIS; dump: ");

	n_elem = 0;
	if (qc->flags & ATA_QCFLAG_DMAMAP)
	if (qc->flags & ATA_QCFLAG_DMAMAP) {
		n_elem = ahci_fill_sg(qc, cmd_tbl);

		if (qc->dma_dir == DMA_TO_DEVICE) {
			dev_info(&qc->dev->tdev, "%s: dma_sync_sg_for_device, qc->dma_dir: %d", __func__, qc->dma_dir);
			dma_sync_sg_for_device(&qc->dev->tdev, qc->sg, qc->n_elem, qc->dma_dir);
		} else if (qc->dma_dir == DMA_FROM_DEVICE) {
			dev_info(&qc->dev->tdev, "%s: dma_sync_sg_for_cpu, qc->dma_dir: %d", __func__, qc->dma_dir);
			dma_sync_sg_for_cpu(&qc->dev->tdev, qc->sg, qc->n_elem, qc->dma_dir);
		}
	}

	/*
	 * Fill in command slot information.
	 */
@@ -2033,6 +2045,7 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc)
		opts |= AHCI_CMD_ATAPI | AHCI_CMD_PREFETCH;

	ahci_fill_cmd_slot(pp, qc->tag, opts);
	//ahci_fill_cmd_slot(pp, tag, opts);

	// Elphel move to ahci_elphel.c. See if the SG dma should also be handed to dma here
	dma_sync_single_for_device(qc->dev, pp->cmd_tbl_dma, AHCI_CMD_TBL_AR_SZ, DMA_TO_DEVICE);
@@ -2427,6 +2440,8 @@ unsigned int ahci_qc_issue(struct ata_queued_cmd *qc)
	void __iomem *port_mmio = ahci_port_base(ap);
	struct ahci_port_priv *pp = ap->private_data;

	// elphel test: set tag = 0
	//unsigned int tag = 0;
	int len;
	char *msg_str = kzalloc(LIBAHCI_DEBUG_BUFSZ, GFP_KERNEL);
	if (msg_str != NULL) {
@@ -2443,10 +2458,12 @@ unsigned int ahci_qc_issue(struct ata_queued_cmd *qc)
	if (qc->tf.protocol == ATA_PROT_NCQ) {
		if (msg_str != NULL) {
			len = snprintf(msg_str, LIBAHCI_DEBUG_BUFSZ, "\twrite port %u register PxSACT, value: 0x%08x", ap->port_no, (1 << qc->tag));
			//len = snprintf(msg_str, LIBAHCI_DEBUG_BUFSZ, "\twrite port %u register PxSACT, value: 0x%08x", ap->port_no, (1 << tag));
			libahci_debug_event(ap, msg_str, len);
		}

		writel(1 << qc->tag, port_mmio + PORT_SCR_ACT);
		//writel(1 << tag, port_mmio + PORT_SCR_ACT);
	}

	if (pp->fbs_enabled && pp->fbs_last_dev != qc->dev->link->pmp) {
@@ -2461,9 +2478,8 @@ unsigned int ahci_qc_issue(struct ata_queued_cmd *qc)
		pp->fbs_last_dev = qc->dev->link->pmp;
	}

	//libahci_debug_wait_flag();

	writel(1 << qc->tag, port_mmio + PORT_CMD_ISSUE);
	//writel(1 << tag, port_mmio + PORT_CMD_ISSUE);

	ahci_sw_activity(qc->dev->link);

+2 −0
Original line number Diff line number Diff line
@@ -698,7 +698,9 @@ static ssize_t libahci_debug_load(struct file *f, const char __user *buff, size_
 */
void libahci_debug_wait_flag(void)
{
	char *msg_str = "waiting for flag to be written to debugfs";
	printk(KERN_DEBUG "%s Waiting for flag to be written to debugfs", MARKER);
	libahci_debug_event(NULL, msg_str, sizeof(*msg_str));
	while (load_flag == false) {
		/*set_current_state(TASK_INTERRUPTIBLE);
		schedule_timeout(msecs_to_jiffies(100));*/
+10 −0
Original line number Diff line number Diff line
@@ -4893,6 +4893,16 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
	 * not synchronize with interrupt handler.  Only PIO task is
	 * taken care of.
	 */

	dev_info(&qc->dev->tdev, "%s: qc->dma_dir: %d", __func__, qc->dma_dir);
	if (qc->dma_dir == DMA_TO_DEVICE) {
		dev_info(&qc->dev->tdev, "%s: dma_sync_sg_for_device, qc->dma_dir: %d", __func__, qc->dma_dir);
		dma_sync_sg_for_device(&qc->dev->tdev, qc->sg, qc->n_elem, qc->dma_dir);
	} else if (qc->dma_dir == DMA_FROM_DEVICE) {
		dev_info(&qc->dev->tdev, "%s: dma_sync_sg_for_cpu, qc->dma_dir: %d", __func__, qc->dma_dir);
		dma_sync_sg_for_cpu(&qc->dev->tdev, qc->sg, qc->n_elem, qc->dma_dir);
	}

	if (ap->ops->error_handler) {
		struct ata_device *dev = qc->dev;
		struct ata_eh_info *ehi = &dev->link->eh_info;
+4 −0
Original line number Diff line number Diff line
@@ -2556,6 +2556,10 @@ static void ata_eh_link_report(struct ata_link *link)
			res->device, qc->err_mask, ata_err_string(qc->err_mask),
			qc->err_mask & AC_ERR_NCQ ? " <F>" : "");

		// elphel test: crash driver here to stop its execution and preserve memory state
		//u32 *tmp_str = NULL;
		//ata_dev_err(qc->dev, "test: %u", *tmp_str);

#ifdef CONFIG_ATA_VERBOSE_ERROR
		if (res->command & (ATA_BUSY | ATA_DRDY | ATA_DF | ATA_DRQ |
				    ATA_ERR)) {