lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <535E0674.4060707@realsil.com.cn>
Date:	Mon, 28 Apr 2014 15:42:44 +0800
From:	micky <micky_ching@...lsil.com.cn>
To:	<chris@...ntf.net>, <ulf.hansson@...aro.org>,
	<sameo@...ux.intel.com>
CC:	<lee.jones@...aro.org>, <gregkh@...uxfoundation.org>,
	<dan.carpenter@...cle.com>, <devel@...uxdriverproject.org>,
	<linux-kernel@...r.kernel.org>, <linux-mmc@...r.kernel.org>,
	<rogerable@...ltek.com>, <wei_wang@...lsil.com.cn>
Subject: Re: [PATCH] mmc: rtsx: Revert "mmc: rtsx: add support for pre_reqand post_req"

Hi Chris and Ulf,

Since the original commit is merged into kernel 3.15-rc, we want this patch
apply to the 3.15-rc to avoid cause serious problem.

Is there any thing I need do?

Best Regards.
micky.

On 04/28/2014 03:36 PM, micky_ching@...lsil.com.cn wrote:
> From: Micky Ching <micky_ching@...lsil.com.cn>
>
> This reverts commit c42deffd5b53c9e583d83c7964854ede2f12410d.
>
> commit <mmc: rtsx: add support for pre_req and post_req> did use
> mutex_unlock() in tasklet, but mutex_unlock() can't used in
> tasklet(atomic context). The driver need use mutex to avoid concurrency,
> so we can't use tasklet here, the patch need to be removed.
>
> The spinlock host->lock and pcr->lock may deadlock, one way to solve the
> deadlock is remove host->lock in sd_isr_done_transfer(), but if using
> workqueue the we can avoid using the spinlock and also avoid the problem.
>
> Signed-off-by: Micky Ching <micky_ching@...lsil.com.cn>
> ---
>   drivers/mfd/rtsx_pcr.c            |  132 ++++--------
>   drivers/mmc/host/rtsx_pci_sdmmc.c |  418 ++++++-------------------------------
>   include/linux/mfd/rtsx_common.h   |    1 -
>   include/linux/mfd/rtsx_pci.h      |    6 -
>   4 files changed, 109 insertions(+), 448 deletions(-)
>
> diff --git a/drivers/mfd/rtsx_pcr.c b/drivers/mfd/rtsx_pcr.c
> index c9de3d5..1d15735 100644
> --- a/drivers/mfd/rtsx_pcr.c
> +++ b/drivers/mfd/rtsx_pcr.c
> @@ -338,28 +338,58 @@ int rtsx_pci_transfer_data(struct rtsx_pcr *pcr, struct scatterlist *sglist,
>   		int num_sg, bool read, int timeout)
>   {
>   	struct completion trans_done;
> -	int err = 0, count;
> +	u8 dir;
> +	int err = 0, i, count;
>   	long timeleft;
>   	unsigned long flags;
> +	struct scatterlist *sg;
> +	enum dma_data_direction dma_dir;
> +	u32 val;
> +	dma_addr_t addr;
> +	unsigned int len;
> +
> +	dev_dbg(&(pcr->pci->dev), "--> %s: num_sg = %d\n", __func__, num_sg);
> +
> +	/* don't transfer data during abort processing */
> +	if (pcr->remove_pci)
> +		return -EINVAL;
> +
> +	if ((sglist == NULL) || (num_sg <= 0))
> +		return -EINVAL;
>   
> -	count = rtsx_pci_dma_map_sg(pcr, sglist, num_sg, read);
> +	if (read) {
> +		dir = DEVICE_TO_HOST;
> +		dma_dir = DMA_FROM_DEVICE;
> +	} else {
> +		dir = HOST_TO_DEVICE;
> +		dma_dir = DMA_TO_DEVICE;
> +	}
> +
> +	count = dma_map_sg(&(pcr->pci->dev), sglist, num_sg, dma_dir);
>   	if (count < 1) {
>   		dev_err(&(pcr->pci->dev), "scatterlist map failed\n");
>   		return -EINVAL;
>   	}
>   	dev_dbg(&(pcr->pci->dev), "DMA mapping count: %d\n", count);
>   
> +	val = ((u32)(dir & 0x01) << 29) | TRIG_DMA | ADMA_MODE;
> +	pcr->sgi = 0;
> +	for_each_sg(sglist, sg, count, i) {
> +		addr = sg_dma_address(sg);
> +		len = sg_dma_len(sg);
> +		rtsx_pci_add_sg_tbl(pcr, addr, len, i == count - 1);
> +	}
>   
>   	spin_lock_irqsave(&pcr->lock, flags);
>   
>   	pcr->done = &trans_done;
>   	pcr->trans_result = TRANS_NOT_READY;
>   	init_completion(&trans_done);
> +	rtsx_pci_writel(pcr, RTSX_HDBAR, pcr->host_sg_tbl_addr);
> +	rtsx_pci_writel(pcr, RTSX_HDBCTLR, val);
>   
>   	spin_unlock_irqrestore(&pcr->lock, flags);
>   
> -	rtsx_pci_dma_transfer(pcr, sglist, count, read);
> -
>   	timeleft = wait_for_completion_interruptible_timeout(
>   			&trans_done, msecs_to_jiffies(timeout));
>   	if (timeleft <= 0) {
> @@ -383,7 +413,7 @@ out:
>   	pcr->done = NULL;
>   	spin_unlock_irqrestore(&pcr->lock, flags);
>   
> -	rtsx_pci_dma_unmap_sg(pcr, sglist, num_sg, read);
> +	dma_unmap_sg(&(pcr->pci->dev), sglist, num_sg, dma_dir);
>   
>   	if ((err < 0) && (err != -ENODEV))
>   		rtsx_pci_stop_cmd(pcr);
> @@ -395,73 +425,6 @@ out:
>   }
>   EXPORT_SYMBOL_GPL(rtsx_pci_transfer_data);
>   
> -int rtsx_pci_dma_map_sg(struct rtsx_pcr *pcr, struct scatterlist *sglist,
> -		int num_sg, bool read)
> -{
> -	enum dma_data_direction dir = read ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
> -
> -	if (pcr->remove_pci)
> -		return -EINVAL;
> -
> -	if ((sglist == NULL) || num_sg < 1)
> -		return -EINVAL;
> -
> -	return dma_map_sg(&(pcr->pci->dev), sglist, num_sg, dir);
> -}
> -EXPORT_SYMBOL_GPL(rtsx_pci_dma_map_sg);
> -
> -int rtsx_pci_dma_unmap_sg(struct rtsx_pcr *pcr, struct scatterlist *sglist,
> -		int num_sg, bool read)
> -{
> -	enum dma_data_direction dir = read ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
> -
> -	if (pcr->remove_pci)
> -		return -EINVAL;
> -
> -	if (sglist == NULL || num_sg < 1)
> -		return -EINVAL;
> -
> -	dma_unmap_sg(&(pcr->pci->dev), sglist, num_sg, dir);
> -	return num_sg;
> -}
> -EXPORT_SYMBOL_GPL(rtsx_pci_dma_unmap_sg);
> -
> -int rtsx_pci_dma_transfer(struct rtsx_pcr *pcr, struct scatterlist *sglist,
> -		int sg_count, bool read)
> -{
> -	struct scatterlist *sg;
> -	dma_addr_t addr;
> -	unsigned int len;
> -	int i;
> -	u32 val;
> -	u8 dir = read ? DEVICE_TO_HOST : HOST_TO_DEVICE;
> -	unsigned long flags;
> -
> -	if (pcr->remove_pci)
> -		return -EINVAL;
> -
> -	if ((sglist == NULL) || (sg_count < 1))
> -		return -EINVAL;
> -
> -	val = ((u32)(dir & 0x01) << 29) | TRIG_DMA | ADMA_MODE;
> -	pcr->sgi = 0;
> -	for_each_sg(sglist, sg, sg_count, i) {
> -		addr = sg_dma_address(sg);
> -		len = sg_dma_len(sg);
> -		rtsx_pci_add_sg_tbl(pcr, addr, len, i == sg_count - 1);
> -	}
> -
> -	spin_lock_irqsave(&pcr->lock, flags);
> -
> -	rtsx_pci_writel(pcr, RTSX_HDBAR, pcr->host_sg_tbl_addr);
> -	rtsx_pci_writel(pcr, RTSX_HDBCTLR, val);
> -
> -	spin_unlock_irqrestore(&pcr->lock, flags);
> -
> -	return 0;
> -}
> -EXPORT_SYMBOL_GPL(rtsx_pci_dma_transfer);
> -
>   int rtsx_pci_read_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len)
>   {
>   	int err;
> @@ -873,8 +836,6 @@ static irqreturn_t rtsx_pci_isr(int irq, void *dev_id)
>   	int_reg = rtsx_pci_readl(pcr, RTSX_BIPR);
>   	/* Clear interrupt flag */
>   	rtsx_pci_writel(pcr, RTSX_BIPR, int_reg);
> -	dev_dbg(&pcr->pci->dev, "=========== BIPR 0x%8x ==========\n", int_reg);
> -
>   	if ((int_reg & pcr->bier) == 0) {
>   		spin_unlock(&pcr->lock);
>   		return IRQ_NONE;
> @@ -905,28 +866,17 @@ static irqreturn_t rtsx_pci_isr(int irq, void *dev_id)
>   	}
>   
>   	if (int_reg & (NEED_COMPLETE_INT | DELINK_INT)) {
> -		if (int_reg & (TRANS_FAIL_INT | DELINK_INT))
> +		if (int_reg & (TRANS_FAIL_INT | DELINK_INT)) {
>   			pcr->trans_result = TRANS_RESULT_FAIL;
> -		else if (int_reg & TRANS_OK_INT)
> +			if (pcr->done)
> +				complete(pcr->done);
> +		} else if (int_reg & TRANS_OK_INT) {
>   			pcr->trans_result = TRANS_RESULT_OK;
> -
> -		if (pcr->done)
> -			complete(pcr->done);
> -
> -		if (int_reg & SD_EXIST) {
> -			struct rtsx_slot *slot = &pcr->slots[RTSX_SD_CARD];
> -			if (slot && slot->done_transfer)
> -				slot->done_transfer(slot->p_dev);
> -		}
> -
> -		if (int_reg & MS_EXIST) {
> -			struct rtsx_slot *slot = &pcr->slots[RTSX_SD_CARD];
> -			if (slot && slot->done_transfer)
> -				slot->done_transfer(slot->p_dev);
> +			if (pcr->done)
> +				complete(pcr->done);
>   		}
>   	}
>   
> -
>   	if (pcr->card_inserted || pcr->card_removed)
>   		schedule_delayed_work(&pcr->carddet_work,
>   				msecs_to_jiffies(200));
> diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c
> index 5fb994f..0b9ded1 100644
> --- a/drivers/mmc/host/rtsx_pci_sdmmc.c
> +++ b/drivers/mmc/host/rtsx_pci_sdmmc.c
> @@ -31,28 +31,14 @@
>   #include <linux/mfd/rtsx_pci.h>
>   #include <asm/unaligned.h>
>   
> -struct realtek_next {
> -	unsigned int	sg_count;
> -	s32		cookie;
> -};
> -
>   struct realtek_pci_sdmmc {
>   	struct platform_device	*pdev;
>   	struct rtsx_pcr		*pcr;
>   	struct mmc_host		*mmc;
>   	struct mmc_request	*mrq;
> -	struct mmc_command	*cmd;
> -	struct mmc_data		*data;
> -
> -	spinlock_t		lock;
> -	struct timer_list	timer;
> -	struct tasklet_struct	cmd_tasklet;
> -	struct tasklet_struct	data_tasklet;
> -	struct tasklet_struct	finish_tasklet;
> -
> -	u8			rsp_type;
> -	u8			rsp_len;
> -	int			sg_count;
> +
> +	struct mutex		host_mutex;
> +
>   	u8			ssc_depth;
>   	unsigned int		clock;
>   	bool			vpclk;
> @@ -62,13 +48,8 @@ struct realtek_pci_sdmmc {
>   	int			power_state;
>   #define SDMMC_POWER_ON		1
>   #define SDMMC_POWER_OFF		0
> -
> -	struct realtek_next	next_data;
>   };
>   
> -static int sd_start_multi_rw(struct realtek_pci_sdmmc *host,
> -		struct mmc_request *mrq);
> -
>   static inline struct device *sdmmc_dev(struct realtek_pci_sdmmc *host)
>   {
>   	return &(host->pdev->dev);
> @@ -105,95 +86,6 @@ static void sd_print_debug_regs(struct realtek_pci_sdmmc *host)
>   #define sd_print_debug_regs(host)
>   #endif /* DEBUG */
>   
> -static void sd_isr_done_transfer(struct platform_device *pdev)
> -{
> -	struct realtek_pci_sdmmc *host = platform_get_drvdata(pdev);
> -
> -	spin_lock(&host->lock);
> -	if (host->cmd)
> -		tasklet_schedule(&host->cmd_tasklet);
> -	if (host->data)
> -		tasklet_schedule(&host->data_tasklet);
> -	spin_unlock(&host->lock);
> -}
> -
> -static void sd_request_timeout(unsigned long host_addr)
> -{
> -	struct realtek_pci_sdmmc *host = (struct realtek_pci_sdmmc *)host_addr;
> -	unsigned long flags;
> -
> -	spin_lock_irqsave(&host->lock, flags);
> -
> -	if (!host->mrq) {
> -		dev_err(sdmmc_dev(host), "error: no request exist\n");
> -		goto out;
> -	}
> -
> -	if (host->cmd)
> -		host->cmd->error = -ETIMEDOUT;
> -	if (host->data)
> -		host->data->error = -ETIMEDOUT;
> -
> -	dev_dbg(sdmmc_dev(host), "timeout for request\n");
> -
> -out:
> -	tasklet_schedule(&host->finish_tasklet);
> -	spin_unlock_irqrestore(&host->lock, flags);
> -}
> -
> -static void sd_finish_request(unsigned long host_addr)
> -{
> -	struct realtek_pci_sdmmc *host = (struct realtek_pci_sdmmc *)host_addr;
> -	struct rtsx_pcr *pcr = host->pcr;
> -	struct mmc_request *mrq;
> -	struct mmc_command *cmd;
> -	struct mmc_data *data;
> -	unsigned long flags;
> -	bool any_error;
> -
> -	spin_lock_irqsave(&host->lock, flags);
> -
> -	del_timer(&host->timer);
> -	mrq = host->mrq;
> -	if (!mrq) {
> -		dev_err(sdmmc_dev(host), "error: no request need finish\n");
> -		goto out;
> -	}
> -
> -	cmd = mrq->cmd;
> -	data = mrq->data;
> -
> -	any_error = (mrq->sbc && mrq->sbc->error) ||
> -		(mrq->stop && mrq->stop->error) ||
> -		(cmd && cmd->error) || (data && data->error);
> -
> -	if (any_error) {
> -		rtsx_pci_stop_cmd(pcr);
> -		sd_clear_error(host);
> -	}
> -
> -	if (data) {
> -		if (any_error)
> -			data->bytes_xfered = 0;
> -		else
> -			data->bytes_xfered = data->blocks * data->blksz;
> -
> -		if (!data->host_cookie)
> -			rtsx_pci_dma_unmap_sg(pcr, data->sg, data->sg_len,
> -					data->flags & MMC_DATA_READ);
> -
> -	}
> -
> -	host->mrq = NULL;
> -	host->cmd = NULL;
> -	host->data = NULL;
> -
> -out:
> -	spin_unlock_irqrestore(&host->lock, flags);
> -	mutex_unlock(&pcr->pcr_mutex);
> -	mmc_request_done(host->mmc, mrq);
> -}
> -
>   static int sd_read_data(struct realtek_pci_sdmmc *host, u8 *cmd, u16 byte_cnt,
>   		u8 *buf, int buf_len, int timeout)
>   {
> @@ -311,7 +203,8 @@ static int sd_write_data(struct realtek_pci_sdmmc *host, u8 *cmd, u16 byte_cnt,
>   	return 0;
>   }
>   
> -static void sd_send_cmd(struct realtek_pci_sdmmc *host, struct mmc_command *cmd)
> +static void sd_send_cmd_get_rsp(struct realtek_pci_sdmmc *host,
> +		struct mmc_command *cmd)
>   {
>   	struct rtsx_pcr *pcr = host->pcr;
>   	u8 cmd_idx = (u8)cmd->opcode;
> @@ -319,14 +212,11 @@ static void sd_send_cmd(struct realtek_pci_sdmmc *host, struct mmc_command *cmd)
>   	int err = 0;
>   	int timeout = 100;
>   	int i;
> +	u8 *ptr;
> +	int stat_idx = 0;
>   	u8 rsp_type;
>   	int rsp_len = 5;
> -	unsigned long flags;
> -
> -	if (host->cmd)
> -		dev_err(sdmmc_dev(host), "error: cmd already exist\n");
> -
> -	host->cmd = cmd;
> +	bool clock_toggled = false;
>   
>   	dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD %d, arg = 0x%08x\n",
>   			__func__, cmd_idx, arg);
> @@ -361,8 +251,6 @@ static void sd_send_cmd(struct realtek_pci_sdmmc *host, struct mmc_command *cmd)
>   		err = -EINVAL;
>   		goto out;
>   	}
> -	host->rsp_type = rsp_type;
> -	host->rsp_len = rsp_len;
>   
>   	if (rsp_type == SD_RSP_TYPE_R1b)
>   		timeout = 3000;
> @@ -372,6 +260,8 @@ static void sd_send_cmd(struct realtek_pci_sdmmc *host, struct mmc_command *cmd)
>   				0xFF, SD_CLK_TOGGLE_EN);
>   		if (err < 0)
>   			goto out;
> +
> +		clock_toggled = true;
>   	}
>   
>   	rtsx_pci_init_cmd(pcr);
> @@ -395,60 +285,25 @@ static void sd_send_cmd(struct realtek_pci_sdmmc *host, struct mmc_command *cmd)
>   		/* Read data from ping-pong buffer */
>   		for (i = PPBUF_BASE2; i < PPBUF_BASE2 + 16; i++)
>   			rtsx_pci_add_cmd(pcr, READ_REG_CMD, (u16)i, 0, 0);
> +		stat_idx = 16;
>   	} else if (rsp_type != SD_RSP_TYPE_R0) {
>   		/* Read data from SD_CMDx registers */
>   		for (i = SD_CMD0; i <= SD_CMD4; i++)
>   			rtsx_pci_add_cmd(pcr, READ_REG_CMD, (u16)i, 0, 0);
> +		stat_idx = 5;
>   	}
>   
>   	rtsx_pci_add_cmd(pcr, READ_REG_CMD, SD_STAT1, 0, 0);
>   
> -	mod_timer(&host->timer, jiffies + msecs_to_jiffies(timeout));
> -
> -	spin_lock_irqsave(&pcr->lock, flags);
> -	pcr->trans_result = TRANS_NOT_READY;
> -	rtsx_pci_send_cmd_no_wait(pcr);
> -	spin_unlock_irqrestore(&pcr->lock, flags);
> -
> -	return;
> -
> -out:
> -	cmd->error = err;
> -	tasklet_schedule(&host->finish_tasklet);
> -}
> -
> -static void sd_get_rsp(unsigned long host_addr)
> -{
> -	struct realtek_pci_sdmmc *host = (struct realtek_pci_sdmmc *)host_addr;
> -	struct rtsx_pcr *pcr = host->pcr;
> -	struct mmc_command *cmd;
> -	int i, err = 0, stat_idx;
> -	u8 *ptr, rsp_type;
> -	unsigned long flags;
> -
> -	spin_lock_irqsave(&host->lock, flags);
> -
> -	cmd = host->cmd;
> -	host->cmd = NULL;
> -
> -	if (!cmd) {
> -		dev_err(sdmmc_dev(host), "error: cmd not exist\n");
> +	err = rtsx_pci_send_cmd(pcr, timeout);
> +	if (err < 0) {
> +		sd_print_debug_regs(host);
> +		sd_clear_error(host);
> +		dev_dbg(sdmmc_dev(host),
> +			"rtsx_pci_send_cmd error (err = %d)\n", err);
>   		goto out;
>   	}
>   
> -	spin_lock(&pcr->lock);
> -	if (pcr->trans_result == TRANS_NO_DEVICE)
> -		err = -ENODEV;
> -	else if (pcr->trans_result != TRANS_RESULT_OK)
> -		err = -EINVAL;
> -	spin_unlock(&pcr->lock);
> -
> -	if (err < 0)
> -		goto out;
> -
> -	rsp_type = host->rsp_type;
> -	stat_idx = host->rsp_len;
> -
>   	if (rsp_type == SD_RSP_TYPE_R0) {
>   		err = 0;
>   		goto out;
> @@ -485,106 +340,26 @@ static void sd_get_rsp(unsigned long host_addr)
>   				cmd->resp[0]);
>   	}
>   
> -	if (cmd == host->mrq->sbc) {
> -		sd_send_cmd(host, host->mrq->cmd);
> -		spin_unlock_irqrestore(&host->lock, flags);
> -		return;
> -	}
> -
> -	if (cmd == host->mrq->stop)
> -		goto out;
> -
> -	if (cmd->data) {
> -		sd_start_multi_rw(host, host->mrq);
> -		spin_unlock_irqrestore(&host->lock, flags);
> -		return;
> -	}
> -
>   out:
>   	cmd->error = err;
>   
> -	tasklet_schedule(&host->finish_tasklet);
> -	spin_unlock_irqrestore(&host->lock, flags);
> -}
> -
> -static int sd_pre_dma_transfer(struct realtek_pci_sdmmc *host,
> -			struct mmc_data *data, struct realtek_next *next)
> -{
> -	struct rtsx_pcr *pcr = host->pcr;
> -	int read = data->flags & MMC_DATA_READ;
> -	int sg_count = 0;
> -
> -	if (!next && data->host_cookie &&
> -		data->host_cookie != host->next_data.cookie) {
> -		dev_err(sdmmc_dev(host),
> -			"error: invalid cookie data[%d] host[%d]\n",
> -			data->host_cookie, host->next_data.cookie);
> -		data->host_cookie = 0;
> -	}
> -
> -	if (next || (!next && data->host_cookie != host->next_data.cookie))
> -		sg_count = rtsx_pci_dma_map_sg(pcr,
> -				data->sg, data->sg_len, read);
> -	else
> -		sg_count = host->next_data.sg_count;
> -
> -	if (next) {
> -		next->sg_count = sg_count;
> -		if (++next->cookie < 0)
> -			next->cookie = 1;
> -		data->host_cookie = next->cookie;
> -	}
> -
> -	return sg_count;
> -}
> -
> -static void sdmmc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq,
> -		bool is_first_req)
> -{
> -	struct realtek_pci_sdmmc *host = mmc_priv(mmc);
> -	struct mmc_data *data = mrq->data;
> -
> -	if (data->host_cookie) {
> -		dev_err(sdmmc_dev(host),
> -			"error: descard already cookie data[%d]\n",
> -			data->host_cookie);
> -		data->host_cookie = 0;
> -	}
> -
> -	dev_dbg(sdmmc_dev(host), "dma sg prepared: %d\n",
> -		sd_pre_dma_transfer(host, data, &host->next_data));
> -}
> -
> -static void sdmmc_post_req(struct mmc_host *mmc, struct mmc_request *mrq,
> -		int err)
> -{
> -	struct realtek_pci_sdmmc *host = mmc_priv(mmc);
> -	struct rtsx_pcr *pcr = host->pcr;
> -	struct mmc_data *data = mrq->data;
> -	int read = data->flags & MMC_DATA_READ;
> -
> -	rtsx_pci_dma_unmap_sg(pcr, data->sg, data->sg_len, read);
> -	data->host_cookie = 0;
> +	if (err && clock_toggled)
> +		rtsx_pci_write_register(pcr, SD_BUS_STAT,
> +				SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0);
>   }
>   
> -static int sd_start_multi_rw(struct realtek_pci_sdmmc *host,
> -		struct mmc_request *mrq)
> +static int sd_rw_multi(struct realtek_pci_sdmmc *host, struct mmc_request *mrq)
>   {
>   	struct rtsx_pcr *pcr = host->pcr;
>   	struct mmc_host *mmc = host->mmc;
>   	struct mmc_card *card = mmc->card;
>   	struct mmc_data *data = mrq->data;
>   	int uhs = mmc_card_uhs(card);
> -	int read = data->flags & MMC_DATA_READ;
> +	int read = (data->flags & MMC_DATA_READ) ? 1 : 0;
>   	u8 cfg2, trans_mode;
>   	int err;
>   	size_t data_len = data->blksz * data->blocks;
>   
> -	if (host->data)
> -		dev_err(sdmmc_dev(host), "error: data already exist\n");
> -
> -	host->data = data;
> -
>   	if (read) {
>   		cfg2 = SD_CALCULATE_CRC7 | SD_CHECK_CRC16 |
>   			SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_0;
> @@ -635,54 +410,15 @@ static int sd_start_multi_rw(struct realtek_pci_sdmmc *host,
>   	rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, SD_TRANSFER,
>   			SD_TRANSFER_END, SD_TRANSFER_END);
>   
> -	mod_timer(&host->timer, jiffies + 10 * HZ);
>   	rtsx_pci_send_cmd_no_wait(pcr);
>   
> -	err = rtsx_pci_dma_transfer(pcr, data->sg, host->sg_count, read);
> -	if (err < 0) {
> -		data->error = err;
> -		tasklet_schedule(&host->finish_tasklet);
> -	}
> -	return 0;
> -}
> -
> -static void sd_finish_multi_rw(unsigned long host_addr)
> -{
> -	struct realtek_pci_sdmmc *host = (struct realtek_pci_sdmmc *)host_addr;
> -	struct rtsx_pcr *pcr = host->pcr;
> -	struct mmc_data *data;
> -	int err = 0;
> -	unsigned long flags;
> -
> -	spin_lock_irqsave(&host->lock, flags);
> -
> -	if (!host->data) {
> -		dev_err(sdmmc_dev(host), "error: no data exist\n");
> -		goto out;
> -	}
> -
> -	data = host->data;
> -	host->data = NULL;
> -
> -	if (pcr->trans_result == TRANS_NO_DEVICE)
> -		err = -ENODEV;
> -	else if (pcr->trans_result != TRANS_RESULT_OK)
> -		err = -EINVAL;
> -
> +	err = rtsx_pci_transfer_data(pcr, data->sg, data->sg_len, read, 10000);
>   	if (err < 0) {
> -		data->error = err;
> -		goto out;
> -	}
> -
> -	if (!host->mrq->sbc && data->stop) {
> -		sd_send_cmd(host, data->stop);
> -		spin_unlock_irqrestore(&host->lock, flags);
> -		return;
> +		sd_clear_error(host);
> +		return err;
>   	}
>   
> -out:
> -	tasklet_schedule(&host->finish_tasklet);
> -	spin_unlock_irqrestore(&host->lock, flags);
> +	return 0;
>   }
>   
>   static inline void sd_enable_initial_mode(struct realtek_pci_sdmmc *host)
> @@ -901,13 +637,6 @@ static int sd_tuning_rx(struct realtek_pci_sdmmc *host, u8 opcode)
>   	return 0;
>   }
>   
> -static inline bool sd_use_muti_rw(struct mmc_command *cmd)
> -{
> -	return mmc_op_multi(cmd->opcode) ||
> -		(cmd->opcode == MMC_READ_SINGLE_BLOCK) ||
> -		(cmd->opcode == MMC_WRITE_BLOCK);
> -}
> -
>   static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
>   {
>   	struct realtek_pci_sdmmc *host = mmc_priv(mmc);
> @@ -916,14 +645,6 @@ static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
>   	struct mmc_data *data = mrq->data;
>   	unsigned int data_size = 0;
>   	int err;
> -	unsigned long flags;
> -
> -	mutex_lock(&pcr->pcr_mutex);
> -	spin_lock_irqsave(&host->lock, flags);
> -
> -	if (host->mrq)
> -		dev_err(sdmmc_dev(host), "error: request already exist\n");
> -	host->mrq = mrq;
>   
>   	if (host->eject) {
>   		cmd->error = -ENOMEDIUM;
> @@ -936,6 +657,8 @@ static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
>   		goto finish;
>   	}
>   
> +	mutex_lock(&pcr->pcr_mutex);
> +
>   	rtsx_pci_start_run(pcr);
>   
>   	rtsx_pci_switch_clock(pcr, host->clock, host->ssc_depth,
> @@ -944,28 +667,46 @@ static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
>   	rtsx_pci_write_register(pcr, CARD_SHARE_MODE,
>   			CARD_SHARE_MASK, CARD_SHARE_48_SD);
>   
> +	mutex_lock(&host->host_mutex);
> +	host->mrq = mrq;
> +	mutex_unlock(&host->host_mutex);
> +
>   	if (mrq->data)
>   		data_size = data->blocks * data->blksz;
>   
> -	if (sd_use_muti_rw(cmd))
> -		host->sg_count = sd_pre_dma_transfer(host, data, NULL);
> +	if (!data_size || mmc_op_multi(cmd->opcode) ||
> +			(cmd->opcode == MMC_READ_SINGLE_BLOCK) ||
> +			(cmd->opcode == MMC_WRITE_BLOCK)) {
> +		sd_send_cmd_get_rsp(host, cmd);
>   
> -	if (!data_size || sd_use_muti_rw(cmd)) {
> -		if (mrq->sbc)
> -			sd_send_cmd(host, mrq->sbc);
> -		else
> -			sd_send_cmd(host, cmd);
> -		spin_unlock_irqrestore(&host->lock, flags);
> +		if (!cmd->error && data_size) {
> +			sd_rw_multi(host, mrq);
> +
> +			if (mmc_op_multi(cmd->opcode) && mrq->stop)
> +				sd_send_cmd_get_rsp(host, mrq->stop);
> +		}
>   	} else {
> -		spin_unlock_irqrestore(&host->lock, flags);
>   		sd_normal_rw(host, mrq);
> -		tasklet_schedule(&host->finish_tasklet);
>   	}
> -	return;
> +
> +	if (mrq->data) {
> +		if (cmd->error || data->error)
> +			data->bytes_xfered = 0;
> +		else
> +			data->bytes_xfered = data->blocks * data->blksz;
> +	}
> +
> +	mutex_unlock(&pcr->pcr_mutex);
>   
>   finish:
> -	tasklet_schedule(&host->finish_tasklet);
> -	spin_unlock_irqrestore(&host->lock, flags);
> +	if (cmd->error)
> +		dev_dbg(sdmmc_dev(host), "cmd->error = %d\n", cmd->error);
> +
> +	mutex_lock(&host->host_mutex);
> +	host->mrq = NULL;
> +	mutex_unlock(&host->host_mutex);
> +
> +	mmc_request_done(mmc, mrq);
>   }
>   
>   static int sd_set_bus_width(struct realtek_pci_sdmmc *host,
> @@ -1400,8 +1141,6 @@ out:
>   }
>   
>   static const struct mmc_host_ops realtek_pci_sdmmc_ops = {
> -	.pre_req = sdmmc_pre_req,
> -	.post_req = sdmmc_post_req,
>   	.request = sdmmc_request,
>   	.set_ios = sdmmc_set_ios,
>   	.get_ro = sdmmc_get_ro,
> @@ -1465,7 +1204,6 @@ static int rtsx_pci_sdmmc_drv_probe(struct platform_device *pdev)
>   	struct realtek_pci_sdmmc *host;
>   	struct rtsx_pcr *pcr;
>   	struct pcr_handle *handle = pdev->dev.platform_data;
> -	unsigned long host_addr;
>   
>   	if (!handle)
>   		return -ENXIO;
> @@ -1489,15 +1227,8 @@ static int rtsx_pci_sdmmc_drv_probe(struct platform_device *pdev)
>   	pcr->slots[RTSX_SD_CARD].p_dev = pdev;
>   	pcr->slots[RTSX_SD_CARD].card_event = rtsx_pci_sdmmc_card_event;
>   
> -	host_addr = (unsigned long)host;
> -	host->next_data.cookie = 1;
> -	setup_timer(&host->timer, sd_request_timeout, host_addr);
> -	tasklet_init(&host->cmd_tasklet, sd_get_rsp, host_addr);
> -	tasklet_init(&host->data_tasklet, sd_finish_multi_rw, host_addr);
> -	tasklet_init(&host->finish_tasklet, sd_finish_request, host_addr);
> -	spin_lock_init(&host->lock);
> +	mutex_init(&host->host_mutex);
>   
> -	pcr->slots[RTSX_SD_CARD].done_transfer = sd_isr_done_transfer;
>   	realtek_init_host(host);
>   
>   	mmc_add_host(mmc);
> @@ -1510,8 +1241,6 @@ static int rtsx_pci_sdmmc_drv_remove(struct platform_device *pdev)
>   	struct realtek_pci_sdmmc *host = platform_get_drvdata(pdev);
>   	struct rtsx_pcr *pcr;
>   	struct mmc_host *mmc;
> -	struct mmc_request *mrq;
> -	unsigned long flags;
>   
>   	if (!host)
>   		return 0;
> @@ -1519,33 +1248,22 @@ static int rtsx_pci_sdmmc_drv_remove(struct platform_device *pdev)
>   	pcr = host->pcr;
>   	pcr->slots[RTSX_SD_CARD].p_dev = NULL;
>   	pcr->slots[RTSX_SD_CARD].card_event = NULL;
> -	pcr->slots[RTSX_SD_CARD].done_transfer = NULL;
>   	mmc = host->mmc;
> -	mrq = host->mrq;
>   
> -	spin_lock_irqsave(&host->lock, flags);
> +	mutex_lock(&host->host_mutex);
>   	if (host->mrq) {
>   		dev_dbg(&(pdev->dev),
>   			"%s: Controller removed during transfer\n",
>   			mmc_hostname(mmc));
>   
> -		if (mrq->sbc)
> -			mrq->sbc->error = -ENOMEDIUM;
> -		if (mrq->cmd)
> -			mrq->cmd->error = -ENOMEDIUM;
> -		if (mrq->stop)
> -			mrq->stop->error = -ENOMEDIUM;
> -		if (mrq->data)
> -			mrq->data->error = -ENOMEDIUM;
> +		rtsx_pci_complete_unfinished_transfer(pcr);
>   
> -		tasklet_schedule(&host->finish_tasklet);
> +		host->mrq->cmd->error = -ENOMEDIUM;
> +		if (host->mrq->stop)
> +			host->mrq->stop->error = -ENOMEDIUM;
> +		mmc_request_done(mmc, host->mrq);
>   	}
> -	spin_unlock_irqrestore(&host->lock, flags);
> -
> -	del_timer_sync(&host->timer);
> -	tasklet_kill(&host->cmd_tasklet);
> -	tasklet_kill(&host->data_tasklet);
> -	tasklet_kill(&host->finish_tasklet);
> +	mutex_unlock(&host->host_mutex);
>   
>   	mmc_remove_host(mmc);
>   	host->eject = true;
> diff --git a/include/linux/mfd/rtsx_common.h b/include/linux/mfd/rtsx_common.h
> index 7c36cc5..443176e 100644
> --- a/include/linux/mfd/rtsx_common.h
> +++ b/include/linux/mfd/rtsx_common.h
> @@ -45,7 +45,6 @@ struct platform_device;
>   struct rtsx_slot {
>   	struct platform_device	*p_dev;
>   	void			(*card_event)(struct platform_device *p_dev);
> -	void			(*done_transfer)(struct platform_device *p_dev);
>   };
>   
>   #endif
> diff --git a/include/linux/mfd/rtsx_pci.h b/include/linux/mfd/rtsx_pci.h
> index 8d6bbd6..a383597 100644
> --- a/include/linux/mfd/rtsx_pci.h
> +++ b/include/linux/mfd/rtsx_pci.h
> @@ -943,12 +943,6 @@ void rtsx_pci_send_cmd_no_wait(struct rtsx_pcr *pcr);
>   int rtsx_pci_send_cmd(struct rtsx_pcr *pcr, int timeout);
>   int rtsx_pci_transfer_data(struct rtsx_pcr *pcr, struct scatterlist *sglist,
>   		int num_sg, bool read, int timeout);
> -int rtsx_pci_dma_map_sg(struct rtsx_pcr *pcr, struct scatterlist *sglist,
> -		int num_sg, bool read);
> -int rtsx_pci_dma_unmap_sg(struct rtsx_pcr *pcr, struct scatterlist *sglist,
> -		int num_sg, bool read);
> -int rtsx_pci_dma_transfer(struct rtsx_pcr *pcr, struct scatterlist *sglist,
> -		int sg_count, bool read);
>   int rtsx_pci_read_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len);
>   int rtsx_pci_write_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len);
>   int rtsx_pci_card_pull_ctl_enable(struct rtsx_pcr *pcr, int card);

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ