diff options
author | Daniel Hillenbrand <codeworkx@cyanogenmod.org> | 2013-06-04 01:33:22 +0200 |
---|---|---|
committer | Daniel Hillenbrand <codeworkx@cyanogenmod.org> | 2013-06-04 12:54:26 +0200 |
commit | 55bb2048feb59f2190f704c2a4df81b557b55c7a (patch) | |
tree | cbb680a60770fb762e5b27c502ad71c2366bf604 /drivers/mmc/card/block.c | |
parent | 3d8b293a4f5042cd9fdc4009a40f6483371cd489 (diff) | |
download | kernel_samsung_smdk4412-55bb2048feb59f2190f704c2a4df81b557b55c7a.zip kernel_samsung_smdk4412-55bb2048feb59f2190f704c2a4df81b557b55c7a.tar.gz kernel_samsung_smdk4412-55bb2048feb59f2190f704c2a4df81b557b55c7a.tar.bz2 |
smdk4412: bulk update from i9300 update 9
Change-Id: Icd3e7b601f3f4c8b3dcf053fed5819fb7caf5296
Diffstat (limited to 'drivers/mmc/card/block.c')
-rw-r--r-- | drivers/mmc/card/block.c | 118 |
1 files changed, 111 insertions, 7 deletions
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 7027962..f49e92c 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -60,6 +60,9 @@ MODULE_ALIAS("mmc:block"); #define MMC_IOCTL_GET_SECTOR_COUNT _IOR(MMC_IOCTL_BASE, 100, int) #define MMC_IOCTL_GET_SECTOR_SIZE _IOR(MMC_IOCTL_BASE, 101, int) #define MMC_IOCTL_GET_BLOCK_SIZE _IOR(MMC_IOCTL_BASE, 102, int) +#define MMC_IOCTL_SET_RETRY_AKE_PROCESS _IOR(MMC_IOCTL_BASE, 104, int) + +static int cprm_ake_retry_flag; #endif #ifdef MOVI_DEBUG @@ -329,6 +332,47 @@ out: return ERR_PTR(err); } +struct scatterlist *mmc_blk_get_sg(struct mmc_card *card, + unsigned char *buf, int *sg_len, int size) +{ + struct scatterlist *sg; + struct scatterlist *sl; + int total_sec_cnt, sec_cnt; + int max_seg_size, len; + + sl = kmalloc(sizeof(struct scatterlist) * card->host->max_segs, GFP_KERNEL); + if (!sl) { + return NULL; + } + + sg = (struct scatterlist *)sl; + sg_init_table(sg, card->host->max_segs); + + total_sec_cnt = size; + max_seg_size = card->host->max_seg_size; + + len = 0; + while (total_sec_cnt) { + if (total_sec_cnt < max_seg_size) + sec_cnt = total_sec_cnt; + else + sec_cnt = max_seg_size; + sg_set_page(sg, virt_to_page(buf), sec_cnt, offset_in_page(buf)); + buf = buf + sec_cnt; + total_sec_cnt = total_sec_cnt - sec_cnt; + len++; + if (total_sec_cnt == 0) + break; + sg = sg_next(sg); + } + + if (sg) + sg_mark_end(sg); + + *sg_len = len; + + return sl; +} static int mmc_blk_ioctl_cmd(struct block_device *bdev, struct mmc_ioc_cmd __user *ic_ptr) { @@ -338,7 +382,7 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev, struct mmc_command cmd = {0}; struct mmc_data data = {0}; struct mmc_request mrq = {0}; - struct scatterlist sg; + struct scatterlist *sg = 0; int err = 0; /* @@ -369,13 +413,22 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev, cmd.arg = idata->ic.arg; cmd.flags = idata->ic.flags; + if( cmd.opcode == MMC_IOC_CLOCK ) + { + mmc_set_clock(card->host, cmd.arg); + err = 0; + goto cmd_done; + } + if (idata->buf_bytes) { - data.sg = &sg; - data.sg_len = 1; + int len; data.blksz = idata->ic.blksz; data.blocks = idata->ic.blocks; - sg_init_one(data.sg, idata->buf, idata->buf_bytes); + sg = mmc_blk_get_sg(card, idata->buf, &len, idata->buf_bytes); + + data.sg = sg; + data.sg_len = len; if (idata->ic.write_flag) data.flags = MMC_DATA_WRITE; @@ -456,6 +509,9 @@ cmd_rel_host: cmd_done: if (md) mmc_blk_put(md); + if (sg) + kfree(sg); + kfree(idata->buf); kfree(idata); return err; @@ -467,6 +523,8 @@ static int mmc_blk_ioctl(struct block_device *bdev, fmode_t mode, #ifdef MMC_ENABLE_CPRM struct mmc_blk_data *md = bdev->bd_disk->private_data; struct mmc_card *card = md->queue.card; + static int i; + static unsigned long temp_arg[16] = {0}; #endif int ret = -EINVAL; if (cmd == MMC_IOC_CMD) @@ -476,6 +534,10 @@ static int mmc_blk_ioctl(struct block_device *bdev, fmode_t mode, printk(KERN_DEBUG " %s ], %x ", __func__, cmd); switch (cmd) { + case MMC_IOCTL_SET_RETRY_AKE_PROCESS: + cprm_ake_retry_flag = 1; + ret = 0; + break; case MMC_IOCTL_GET_SECTOR_COUNT: { int size = 0; @@ -498,9 +560,54 @@ static int mmc_blk_ioctl(struct block_device *bdev, fmode_t mode, struct cprm_request *req = (struct cprm_request *)arg; printk(KERN_DEBUG "[%s]: cmd [%x]\n", __func__, cmd); + if (cmd == ACMD43) { + printk(KERN_DEBUG"storing acmd43 arg[%d] = %ul\n" + , i, (unsigned int)req->arg); + temp_arg[i] = req->arg; + i++; + if(i >= 16){ + printk(KERN_DEBUG"reset acmd43 i = %d\n", + i); + i = 0; + } + } + + + if (cmd == ACMD45 && cprm_ake_retry_flag == 1) { + cprm_ake_retry_flag = 0; + printk(KERN_DEBUG"ACMD45.. I'll call ACMD43 and ACMD44 first\n"); + + for (i = 0; i < 16; i++) { + printk(KERN_DEBUG"calling ACMD43 with arg[%d] = %ul\n", + i, (unsigned int)temp_arg[i]); + if (stub_sendcmd(card, + ACMD43, temp_arg[i], + 512, NULL) < 0) { + + printk(KERN_DEBUG"error ACMD43 %d\n", i); + return -EINVAL; + } + } + + + printk(KERN_DEBUG"calling ACMD44\n"); + if (stub_sendcmd(card, ACMD44, 0, 8, NULL) < 0) + { + + printk(KERN_DEBUG"error in ACMD44 %d\n", + i); + return -EINVAL; + } + + } return stub_sendcmd(card, req->cmd, req->arg, \ req->len, req->buff); } + break; + + default: + printk(KERN_DEBUG"%s: Invalid ioctl command\n", __func__); + break; } #endif return ret; @@ -2372,9 +2479,6 @@ static int mmc_blk_probe(struct mmc_card *card) md->disk->disk_name, mmc_card_id(card), mmc_card_name(card), cap_str, md->read_only ? "(ro)" : ""); - if (mmc_blk_alloc_parts(card, md)) - goto out; - mmc_set_drvdata(card, md); mmc_fixup_device(card, blk_fixups); |