Exemplo n.º 1
0
static int mmc_ext_csd_open(struct inode *inode, struct file *filp)
{
    struct mmc_card *card = inode->i_private;
    char *buf;
    ssize_t n = 0;
    u8 *ext_csd;
    int err, i;

    buf = kmalloc(EXT_CSD_STR_LEN + 1, GFP_KERNEL);
    if (!buf)
        return -ENOMEM;

    mmc_get_card(card);
    err = mmc_get_ext_csd(card, &ext_csd);
    mmc_put_card(card);
    if (err)
        goto out_free;

    for (i = 0; i < 512; i++)
        n += sprintf(buf + n, "%02x", ext_csd[i]);
    n += sprintf(buf + n, "\n");
    BUG_ON(n != EXT_CSD_STR_LEN);

    filp->private_data = buf;
    kfree(ext_csd);
    return 0;

out_free:
    kfree(buf);
    return err;
}
Exemplo n.º 2
0
static void mmc_mq_recovery_handler(struct work_struct *work)
{
	struct mmc_queue *mq = container_of(work, struct mmc_queue,
					    recovery_work);
	struct request_queue *q = mq->queue;

	mmc_get_card(mq->card, &mq->ctx);

	mq->in_recovery = true;

	if (mq->use_cqe)
		mmc_blk_cqe_recovery(mq);
	else
		mmc_blk_mq_recovery(mq);

	mq->in_recovery = false;

	spin_lock_irq(&mq->lock);
	mq->recovery_needed = false;
	spin_unlock_irq(&mq->lock);

	mmc_put_card(mq->card, &mq->ctx);

	blk_mq_run_hw_queues(q, true);
}
Exemplo n.º 3
0
int mmc_erase_blks(int dev_id, u32 addr, u32 size, int bootarea)
{
    unsigned long ret;
    int i, j, result = 0;
    u8 val;
    u8 *ext_csd;    
    u32 blknr;
    u32 total_blks;
    struct mmc_card *card;

    if (!size)
        return 0;

    if (addr % MMC_BLOCK_SIZE)
        return MMC_ERR_FAILED;

    card    = mmc_get_card(dev_id);
    ext_csd = &card->raw_ext_csd[0];    

    if (bootarea && !mmc_card_sd(card) && card->ext_csd.part_en) {
        /* configure to specified partition */
        val = (ext_csd[EXT_CSD_PART_CFG] & ~0x7) | EXT_CSD_PART_CFG_BOOT_PART_1;
        if (mmc_set_part_config(card, val) != MMC_ERR_NONE) {
            result = -__LINE__;
            goto done;
        }
    }
    blknr      = addr / MMC_BLOCK_SIZE;
    total_blks = (size + MMC_BLOCK_SIZE - 1) / MMC_BLOCK_SIZE;

    if (mmc_erase_start(card, blknr * MMC_BLOCK_SIZE) != MMC_ERR_NONE) {
        result = -__LINE__;
        goto done;
    }
    if (mmc_erase_end(card, (blknr + total_blks) * MMC_BLOCK_SIZE) != MMC_ERR_NONE) {
        result = -__LINE__;
        goto done;
    }
    if (mmc_erase(card, MMC_ERASE_NORMAL) != MMC_ERR_NONE) {
        result = -__LINE__;
        goto done;        
    }

done:
    if (bootarea && !mmc_card_sd(card) && card->ext_csd.part_en) {
        /* configure to user partition */
        val = (ext_csd[EXT_CSD_PART_CFG] & ~0x7) | EXT_CSD_PART_CFG_DEFT_PART;
        if (mmc_set_part_config(card, val) != MMC_ERR_NONE)
            result = -__LINE__;
    }

    if (!result) {
        printf("[SD%d] Erase %d blocks (%d bytes) from 0x%x successfully\n", 
            dev_id, total_blks, total_blks * MMC_BLOCK_SIZE, blknr * MMC_BLOCK_SIZE);
    } else {
        printf("[SD%d] Erase %d blocks (%d bytes) from 0x%x failed %d\n", 
            dev_id, total_blks, total_blks * MMC_BLOCK_SIZE, blknr * MMC_BLOCK_SIZE, result);
    }    
    return result;
}
Exemplo n.º 4
0
int mmc_readback_blks(int dev_id, unsigned long addr, int blks, int bootarea)
{
    int i, j, result = 0;
    u8 val;
    u8 *ext_csd;
    unsigned long blknr = addr / MMC_BLOCK_SIZE;
    unsigned char *buf = (unsigned char*)MMC_BUF_ADDR;
    struct mmc_card *card;
    struct mmc_host *host;

    host = mmc_get_host(dev_id);
    card = mmc_get_card(dev_id);
    ext_csd = &card->raw_ext_csd[0];

    if (bootarea && !mmc_card_sd(card)) {
        /* configure to specified partition */
        val = (ext_csd[EXT_CSD_PART_CFG] & ~0x7) | EXT_CSD_PART_CFG_BOOT_PART_1;
        if (mmc_set_part_config(card, val) != MMC_ERR_NONE) {
            result = -__LINE__;
            goto done;
        }
        if (mmc_read_ext_csd(host, card) != MMC_ERR_NONE) {
            result = -__LINE__;
            goto done;
        }
    }

    printf("[SD%d] Dump %d blks from 0x%x (FLASH)\n", dev_id, blks, 
        blknr * MMC_BLOCK_SIZE);
    for (i = 0; i < blks; i++) {
        memset(buf, 0, MMC_BLOCK_SIZE);
        if (MMC_ERR_NONE != mmc_block_read(dev_id, blknr + i, 1, (unsigned long*)buf)) {
            printf("\n[SD%d] Read from %dth block error\n", dev_id, blknr + i);
            break;
        }
        
        for (j = 0; j < MMC_BLOCK_SIZE; j++) {
            if (j % 16 == 0)
                printf("\n%xh: ", (blknr + i) * MMC_BLOCK_SIZE + j);
            printf("%x ",  buf[j]);
        }
        printf("\n");
        buf += MMC_BLOCK_SIZE;
    }
done:

    if (bootarea && !mmc_card_sd(card)) {
        /* configure to user partition */
        val = (ext_csd[EXT_CSD_PART_CFG] & ~0x7) | EXT_CSD_PART_CFG_DEFT_PART;
        if (mmc_set_part_config(card, val) != MMC_ERR_NONE)
            result = -__LINE__;
        if (mmc_read_ext_csd(host, card) != MMC_ERR_NONE) {
            result = -__LINE__;
        }
    }  

    return result;
}
Exemplo n.º 5
0
int mmc_boot_up_test(int id, int reset, u32 freq, int in_idle)
{
    int err = MMC_ERR_FAILED;
    struct mmc_host *host;
    struct mmc_card *card;

    host = mmc_get_host(id);
    card = mmc_get_card(id);
    mmc_init_host(host, id);

    if (in_idle) {
        printf("[EMMC] Card is in idle mode \n");
        /* card in idle mode */
        //mmc_go_idle(host);
        mmc_init_card(host, card);
        /* note: requires delay before issue boot reset command */
        mdelay(5);
    } else {
        /* card not in idle mode */
        printf("[EMMC] Card is not in idle mode \n");
    }

    msdc_emmc_boot_reset(host, reset);
    
    err = msdc_emmc_boot_start(host, freq, 0, EMMC_BOOT_RST_CMD_MODE, 0);
    if (err) {
        printf("[EMMC] Boot Error: %d\n", err);
        goto done;
    }
    err = msdc_emmc_boot_read(host, 128 * 1024, MMC_BUF_ADDR);
    msdc_emmc_boot_stop(host, EMMC_BOOT_RST_CMD_MODE);
    if (err) {
        printf("[EMMC] Boot Read Error: %d\n", err);
        goto done;
    }

done:
    if (!err) {
        int i, j;
        char *buf = (char*)MMC_BUF_ADDR;
        for (i = 0; i < 16; i++) {            
            for (j = 0; j < MMC_BLOCK_SIZE; j++) {
                if (j % 16 == 0)
                    printf("\n%xh: ", i * MMC_BLOCK_SIZE + j);
                printf("%x ",  buf[j]);
            }
            printf("\n");
            buf += MMC_BLOCK_SIZE;
        }
    }
    return err;
}
Exemplo n.º 6
0
static int mmc_dbg_card_status_get(void *data, u64 *val)
{
	struct mmc_card	*card = data;
	u32		status;
	int		ret;

	mmc_get_card(card);

	ret = mmc_send_status(data, &status);
	if (!ret)
		*val = status;

	mmc_put_card(card);

	return ret;
}
Exemplo n.º 7
0
int mmc_boot_enable(int id, int bootpart)
{
    int err = MMC_ERR_FAILED;
    struct mmc_host *host;
    struct mmc_card *card;

    host = mmc_get_host(id);
    card = mmc_get_card(id);

    err = mmc_boot_config(card, EXT_CSD_PART_CFG_EN_ACK,
        bootpart, EXT_CSD_BOOT_BUS_WIDTH_1, EXT_CSD_BOOT_BUS_MODE_DEFT);
    if (err != 0)
        goto done;
    err = mmc_read_ext_csd(host, card);
done:
    return err;
}
Exemplo n.º 8
0
int mmc_download_part(int dev_id, char *part_name, int bootarea)
{
    int ret = -1;
    struct mmc_card *card;
    struct mmc_host *host;
    part_t *part = mt6573_part_get_partition(part_name);

    mmc_download_addr = 0;
    mmc_download_size = 0;
    mmc_image_addr = 0;

    host = mmc_get_host(dev_id);
    card = mmc_get_card(dev_id);

    if (part) {
        printf("[SD%d] Waiting for '%s' image loading from ICE...\n", dev_id, part_name);
        while (!mmc_download_size); /* Wait for loading image from ICE */
        ret = mmc_download(dev_id, mmc_image_addr, mmc_download_size, 
            part->startblk * BLK_SIZE, bootarea);
        if (ret != 0)
            goto done;
        if (bootarea) {
            /* set reset signal function */
            //ret = mmc_set_reset_func(card, 1);
            //if (ret != 0)
            //    goto done;
            /* set boot config */
            ret = mmc_boot_config(card, EXT_CSD_PART_CFG_EN_ACK,
                EXT_CSD_PART_CFG_EN_BOOT_PART_1, EXT_CSD_BOOT_BUS_WIDTH_1, 
                EXT_CSD_BOOT_BUS_MODE_DEFT);
            if (ret != 0)
                goto done;
            ret = mmc_read_ext_csd(host, card);
        }
    }
done:
    return ret;
}
Exemplo n.º 9
0
int mmc_test_mem_card(struct mmc_test_config *cfg)
{
    int id, count, forever;
    int ret, chk_result, tid = 0, result = 0;
    unsigned int chunks, chunk_blks, left_blks, pass = 0, fail = 0;
    unsigned int total_blks;
    unsigned int i, j;
    unsigned int blksz;
    unsigned int clkhz;    
    char pattern = 0;
    char *buf;
    unsigned long blknr;
    struct mmc_host *host;
    struct mmc_card *card;

    id    = cfg->id;
    count = cfg->count;
    buf   = cfg->buf;
    blknr = cfg->blknr;
    blksz = cfg->blksz;

    chk_result = cfg->chk_result;
    chunk_blks = cfg->chunk_blks;
    total_blks = (cfg->total_size + blksz - 1) / blksz;
    forever    = (count == -1) ? 1 : 0;

    host = mmc_get_host(id);
    card = mmc_get_card(id);

    while (forever || count--) {
        printf("[TST] ==============================================\n");
        printf("[TST] BEGIN: %d/%d, No Stop(%d)\n", 
            (cfg->count != -1) ? cfg->count - count : 0, 
            (cfg->count != -1) ? cfg->count : 0, forever);
        printf("[TST] ----------------------------------------------\n");
        printf("[TST] Mode    : %d\n", cfg->mode);
        printf("[TST] Clock   : %d kHz\n", cfg->clock / 1000);
        printf("[TST] BusWidth: %d bits\n", cfg->buswidth);
        printf("[TST] BurstSz : %d bytes\n", 0x1 << cfg->burstsz);
        printf("[TST] BlkAddr : %xh\n", blknr);
        printf("[TST] BlkSize : %dbytes\n", blksz);
        printf("[TST] TstBlks : %d\n", total_blks);
#if defined(BB_MT6575)
        printf("[TST] AutoCMD : 12(%d), 23(%d)\n", 
            (cfg->autocmd & MSDC_AUTOCMD12) ? 1 : 0, 
            (cfg->autocmd & MSDC_AUTOCMD23) ? 1 : 0);
#endif
        printf("[TST] ----------------------------------------------\n");


        if (mmc_init_host(host, id) != 0) {
            result = -__LINE__;
            goto failure;
        }
        if (mmc_init_card(host, card) != 0) {
            result = -__LINE__;
            goto failure;
        }
#if defined(BB_MT6575)
        msdc_set_dma(host, (u8)cfg->burstsz, (u32)cfg->flags);
        msdc_set_autocmd(host, cfg->autocmd, 1);
#endif

        /* change uhs-1 mode */
#if 0        
        if (mmc_card_uhs1(card)) {
            if (mmc_switch_uhs1(host, card, cfg->uhsmode) != 0) {
                result = -__LINE__;
                goto failure;
            }
        }
#endif

        /* change clock */
        if (cfg->clock) {
            clkhz = card->maxhz < cfg->clock ? card->maxhz : cfg->clock;
            mmc_set_clock(host, mmc_card_ddr(card), clkhz); 
        }
        if (mmc_card_sd(card) && cfg->buswidth == HOST_BUS_WIDTH_8) {
            printf("[TST] SD card doesn't support 8-bit bus width (SKIP)\n");
            result = MMC_ERR_NONE;
        }
        if (mmc_set_bus_width(host, card, cfg->buswidth) != 0) {
            result = -__LINE__;
            goto failure;
        }

        /* cmd16 is illegal while card is in ddr mode */
        if (!(mmc_card_mmc(card) && mmc_card_ddr(card))) {
            if (mmc_set_blk_length(host, blksz) != 0) {
                result = -__LINE__;
                goto failure;            
            }
        }

#if defined(BB_MT6575)
        if (cfg->piobits) {
            printf("[TST] PIO bits: %d\n", cfg->piobits);
            msdc_set_pio_bits(host, cfg->piobits);
        }
#endif
        tid = result = 0;        

        if (mmc_erase_start(card, blknr * blksz) != MMC_ERR_NONE) {
            result = -__LINE__;
            goto failure;
        }
        if (mmc_erase_end(card, (blknr + total_blks) * blksz) != MMC_ERR_NONE) {
            result = -__LINE__;
            goto failure;
        }
        if (mmc_erase(card, MMC_ERASE_NORMAL) != MMC_ERR_NONE) {
            result = -__LINE__;
            goto failure;        
        }
        printf("[TST] 0x%x - 0x%x Erased\n", blknr * blksz, 
            (blknr + total_blks) * blksz);

        mmc_send_status(host, card, &status);

        if (cfg->tst_single) {
            /* single block write */
            for (i = 0; i < total_blks; i++) {
                pattern = (i + count) % 256;
                memset(buf, pattern, blksz);
                ret = mmc_block_write(id, blknr + i, 1, (unsigned long*)buf);
                if (ret != MMC_ERR_NONE) {
                    printf("test single block write failed (%d)\n", i);
                    result = -__LINE__;
                    goto failure;
                }
            }

            printf(TC_MSG, host->id, result == 0 ? "PASS" : "FAIL", tid++, 
                "test single block write\n");

            if (result)
                break;
            
            /* single block read */
            for (i = 0; i < total_blks && !result; i++) {
                pattern = (i + count) % 256;
                /* populate buffer with different pattern */
                memset(buf, pattern + 1, blksz);
                ret = mmc_block_read(id, blknr + i, 1, (unsigned long*)buf);
                if (ret != MMC_ERR_NONE) {
                    result = -__LINE__;
                    goto failure;
                }
                if (chk_result) {
                    for (j = 0; j < blksz; j++) {
                        if (buf[j] != pattern) {
                            result = -__LINE__;
                            goto failure;
                        }
                    }
                }
            }
            printf(TC_MSG, host->id, result == 0 ? "PASS" : "FAIL", tid++, 
                "test single block read\n");

            if (result) {
                printf("[SD%d]\t\tread back pattern(0x%.2x) failed\n", 
                    id, pattern);
                goto failure;
            }
        }

        mmc_send_status(host, card, &status);
        
        if (cfg->tst_multiple) {
            /* multiple block write */
            chunks = total_blks / chunk_blks;
            left_blks = total_blks % chunk_blks;   
            for (i = 0; i < chunks; i++) {
                pattern = (i + count) % 256;
                memset(buf, pattern, blksz * chunk_blks);
                ret = mmc_block_write(id, blknr + i * chunk_blks, 
                    chunk_blks, (unsigned long*)buf);
                if (ret != MMC_ERR_NONE) {
                    result = -__LINE__;
                    goto failure;
                }
            }
            
            if (!result && left_blks) {
                pattern = (i + count) % 256;
                memset(buf, pattern, blksz * left_blks);
                ret = mmc_block_write(id, blknr + chunks * chunk_blks, 
                    left_blks, (unsigned long*)buf);
                if (ret != MMC_ERR_NONE) {
                    result = -__LINE__;
                    goto failure;
                }
            }

            printf(TC_MSG, host->id, result == 0 ? "PASS" : "FAIL", tid++, 
                "test multiple block write\n");

            if (result)
                goto failure;

            /* multiple block read */
            for (i = 0; i < chunks; i++) {
                pattern = (i + count) % 256;
                /* populate buffer with different pattern */
                memset(buf, pattern + 1, blksz);
                ret = mmc_block_read(id, blknr + i * chunk_blks, 
                    chunk_blks, (unsigned long*)buf);
                if (ret != MMC_ERR_NONE) {
                    printf("[SD%d]\t\tread %d blks failed(ret = %d blks)\n",
                        host->id, chunk_blks, ret);
                    result = -__LINE__;
                    goto failure;
                }
                if (chk_result) {
                    for (j = 0; j < chunk_blks * blksz; j++) {
                        if (buf[j] == pattern)
                            continue;
                        result = -__LINE__;
                        printf("[SD%d]\t\t%xh = %x (!= %x)\n",
                            host->id, blknr + i * chunk_blks + j, buf[j], pattern);
                        goto failure;
                    }
                }
            }

            if (!result && left_blks) {
                pattern = i % 256;
                /* populate buffer with different pattern */
                memset(buf, pattern + 1, blksz);
                ret = mmc_block_read(id, blknr + chunks * chunk_blks, 
                    left_blks, (unsigned long*)buf);
                if (ret != MMC_ERR_NONE) {
                    printf("[SD%d]\t\tread %d blks failed(ret = %d blks)\n",
                        host->id, left_blks, ret);
                    result = -__LINE__;
                    goto failure;
                }
                if (chk_result) {
                    for (j = 0; j < left_blks * blksz; j++) {
                        if (buf[j] == pattern)
                            continue;
                        printf("[SD%d]\t\t%xh = %x (!= %x)\n",
                            host->id, blknr + chunks * chunk_blks + j, buf[j], pattern);
                        result = -__LINE__;
                        goto failure;
                    }
                }
            }

            printf(TC_MSG, host->id, result == 0 ? "PASS" : "FAIL", tid++, 
                "test multiple block read\n");

            if (result)
                goto failure;
        }

        mmc_send_status(host, card, &status);

        if (cfg->tst_interleave) {
            /* multiple block write */
            chunks = total_blks / chunk_blks;
            left_blks = total_blks % chunk_blks;   
            for (i = 0; i < chunks; i++) {
                pattern = (i + count) % 256;
                memset(buf, pattern, blksz * chunk_blks);
                ret = mmc_block_write(id, blknr + i * chunk_blks, 
                    chunk_blks, (unsigned long*)buf);
                if (ret != MMC_ERR_NONE) {
                    result = -__LINE__;
                    goto failure;
                }

                /* populate buffer with different pattern */
                memset(buf, pattern + 1, blksz * chunk_blks);
                ret = mmc_block_read(id, blknr + i * chunk_blks, 
                    chunk_blks, (unsigned long*)buf);
                if (ret != MMC_ERR_NONE) {
                    result = -__LINE__;
                    goto failure;
                }
                if (chk_result) {
                    for (j = 0; j < chunk_blks * blksz; j++) {
                        if (buf[j] == pattern) 
                            continue;
                        result = -__LINE__;
                        goto failure;
                    }
                }                
            }           

            if (!result && left_blks) {
                pattern = (i + count) % 256;
                memset(buf, pattern, blksz * left_blks);
                ret = mmc_block_write(id, blknr + chunks * chunk_blks, 
                    left_blks, (unsigned long*)buf);
                if (ret != MMC_ERR_NONE) {
                    result = -__LINE__;
                    goto failure;
                }

                /* populate buffer with different pattern */
                memset(buf, pattern + 1, blksz * left_blks);
                ret = mmc_block_read(id, blknr + chunks * chunk_blks, 
                    left_blks, (unsigned long*)buf);
                if (ret != MMC_ERR_NONE) {
                    result = -__LINE__;
                    break;
                }
                if (chk_result) {
                    for (j = 0; j < left_blks * blksz; j++) {
                        if (buf[j] == pattern)
                            continue;
                        result = -__LINE__;
                        goto failure;
                    }
                }
            }

            printf(TC_MSG, host->id, result == 0 ? "PASS" : "FAIL", tid++, 
                "test multiple block interleave write-read\n");

            if (result)
                goto failure;
        }
        if (cfg->desc) {
            printf("[TST] ----------------------------------------------\n");
            printf("[TST] Report - %s \n", cfg->desc);
            printf("[TST] ----------------------------------------------\n");
        }
        mmc_prof_dump(id);

failure:
        if (result) {
            printf("[SD%d] mmc test failed (%d)\n", host->id, result);
            fail++;
        } else {
            pass++;
        }
        printf("[TST] ----------------------------------------------\n");
        printf("[TST] Test Result: TOTAL(%d/%d), PASS(%d), FAIL(%d) \n", 
            cfg->count - count, cfg->count, pass, fail);
        printf("[TST] ----------------------------------------------\n");    
    	//mdelay(1000);
    }

    return result;
}
Exemplo n.º 10
0
int mmc_download(int dev_id, u32 imgaddr, u32 size, u32 addr, int bootarea)
{
    int ret;
    int i, j, result = 0;
    u8 val;
    u8 *ext_csd;    
    uchar *buf, *chkbuf;
    u32 chunks, chunk_blks = 128, left_blks, blknr;
    u32 total_blks;
    struct mmc_card *card;

    if (!size)
        return 0;

    if (addr % MMC_BLOCK_SIZE)
        return MMC_ERR_FAILED;

    card    = mmc_get_card(dev_id);
    ext_csd = &card->raw_ext_csd[0];    

    if (bootarea && !mmc_card_sd(card) && card->ext_csd.part_en) {
        /* configure to specified partition */
        val = (ext_csd[EXT_CSD_PART_CFG] & ~0x7) | EXT_CSD_PART_CFG_BOOT_PART_1;
        if (mmc_set_part_config(card, val) != MMC_ERR_NONE) {
            result = -__LINE__;
            goto done;
        }
    }

    blknr      = addr / MMC_BLOCK_SIZE;
    total_blks = (size + MMC_BLOCK_SIZE - 1) / MMC_BLOCK_SIZE;

    /* multiple block write */
    chunks    = total_blks / chunk_blks;
    left_blks = total_blks % chunk_blks;  
    buf       = (uchar*)imgaddr;
    chkbuf    = (uchar*)MMC_BUF_ADDR;

    for (i = 0; i < chunks; i++) {
        ret = mmc_block_write(dev_id, blknr + i * chunk_blks, 
            chunk_blks, (unsigned long*)buf);
        if (ret != MMC_ERR_NONE) {
            result = -__LINE__;
            goto done;
        }
        ret = mmc_block_read(dev_id, blknr + i * chunk_blks,
            chunk_blks, (unsigned long*)chkbuf);
        if (ret != MMC_ERR_NONE) {
            result = -__LINE__;
            goto done;
        }

        for (j = 0; j < chunk_blks * MMC_BLOCK_SIZE; j++) {
            if (buf[j] == chkbuf[j])
                continue;
            result = -__LINE__;
            goto done;
        }
        printf("[SD%d] Write %3d blocks from 0x%.8x(RAM) to 0x%.8x(FLASH).\n",
            dev_id, chunk_blks, (unsigned int)buf, 
            (blknr + i * chunk_blks) * MMC_BLOCK_SIZE);

        buf += (chunk_blks * MMC_BLOCK_SIZE);
    }
    
    if (left_blks) {
        ret = mmc_block_write(dev_id, blknr + chunks * chunk_blks, 
            left_blks, (unsigned long*)buf);
        if (ret != MMC_ERR_NONE) {
            result = -__LINE__;
            goto done;
        }
        ret = mmc_block_read(dev_id, blknr + chunks * chunk_blks,
            left_blks, (unsigned long*)chkbuf);
        if (ret != MMC_ERR_NONE) {
            result = -__LINE__;
            goto done;
        }
        for (j = 0; j < left_blks * MMC_BLOCK_SIZE; j++) {
            if (buf[j] == chkbuf[j])
                continue;
            printf("[SD%d] chkbuf[%d] = %xh (!= %xh) \n", dev_id,
                j, chkbuf[j], buf[j]);
            result = -__LINE__;
            goto done;
        }
        printf("[SD%d] Write %3d blocks from 0x%.8x(RAM) to 0x%.8x(FLASH).\n",
            dev_id, left_blks, (unsigned int)buf, 
            (blknr + chunks * chunk_blks) * MMC_BLOCK_SIZE);
    }

done:
    if (bootarea && !mmc_card_sd(card) && card->ext_csd.part_en) {
        /* configure to user partition */
        val = (ext_csd[EXT_CSD_PART_CFG] & ~0x7) | EXT_CSD_PART_CFG_DEFT_PART;
        if (mmc_set_part_config(card, val) != MMC_ERR_NONE)
            result = -__LINE__;
    }

    if (!result) {
        printf("[SD%d] Download %d blocks (%d bytes) to 0x%.8x successfully\n", 
            dev_id, total_blks, total_blks * MMC_BLOCK_SIZE, blknr * MMC_BLOCK_SIZE);
    } else {
        printf("[SD%d] Download %d blocks (%d bytes) to 0x%.8x failed %d\n", 
            dev_id, total_blks, total_blks * MMC_BLOCK_SIZE, blknr * MMC_BLOCK_SIZE, result);
    }    
    return result;
}
Exemplo n.º 11
0
static blk_status_t mmc_mq_queue_rq(struct blk_mq_hw_ctx *hctx,
				    const struct blk_mq_queue_data *bd)
{
	struct request *req = bd->rq;
	struct request_queue *q = req->q;
	struct mmc_queue *mq = q->queuedata;
	struct mmc_card *card = mq->card;
	struct mmc_host *host = card->host;
	enum mmc_issue_type issue_type;
	enum mmc_issued issued;
	bool get_card, cqe_retune_ok;
	int ret;

	if (mmc_card_removed(mq->card)) {
		req->rq_flags |= RQF_QUIET;
		return BLK_STS_IOERR;
	}

	issue_type = mmc_issue_type(mq, req);

	spin_lock_irq(&mq->lock);

	if (mq->recovery_needed || mq->busy) {
		spin_unlock_irq(&mq->lock);
		return BLK_STS_RESOURCE;
	}

	switch (issue_type) {
	case MMC_ISSUE_DCMD:
		if (mmc_cqe_dcmd_busy(mq)) {
			mq->cqe_busy |= MMC_CQE_DCMD_BUSY;
			spin_unlock_irq(&mq->lock);
			return BLK_STS_RESOURCE;
		}
		break;
	case MMC_ISSUE_ASYNC:
		break;
	default:
		/*
		 * Timeouts are handled by mmc core, and we don't have a host
		 * API to abort requests, so we can't handle the timeout anyway.
		 * However, when the timeout happens, blk_mq_complete_request()
		 * no longer works (to stop the request disappearing under us).
		 * To avoid racing with that, set a large timeout.
		 */
		req->timeout = 600 * HZ;
		break;
	}

	/* Parallel dispatch of requests is not supported at the moment */
	mq->busy = true;

	mq->in_flight[issue_type] += 1;
	get_card = (mmc_tot_in_flight(mq) == 1);
	cqe_retune_ok = (mmc_cqe_qcnt(mq) == 1);

	spin_unlock_irq(&mq->lock);

	if (!(req->rq_flags & RQF_DONTPREP)) {
		req_to_mmc_queue_req(req)->retries = 0;
		req->rq_flags |= RQF_DONTPREP;
	}

	if (get_card)
		mmc_get_card(card, &mq->ctx);

	if (mq->use_cqe) {
		host->retune_now = host->need_retune && cqe_retune_ok &&
				   !host->hold_retune;
	}

	blk_mq_start_request(req);

	issued = mmc_blk_mq_issue_rq(mq, req);

	switch (issued) {
	case MMC_REQ_BUSY:
		ret = BLK_STS_RESOURCE;
		break;
	case MMC_REQ_FAILED_TO_START:
		ret = BLK_STS_IOERR;
		break;
	default:
		ret = BLK_STS_OK;
		break;
	}

	if (issued != MMC_REQ_STARTED) {
		bool put_card = false;

		spin_lock_irq(&mq->lock);
		mq->in_flight[issue_type] -= 1;
		if (mmc_tot_in_flight(mq) == 0)
			put_card = true;
		mq->busy = false;
		spin_unlock_irq(&mq->lock);
		if (put_card)
			mmc_put_card(card, &mq->ctx);
	} else {
		WRITE_ONCE(mq->busy, false);
	}

	return ret;
}