All of lore.kernel.org
 help / color / mirror / Atom feed
From: Gregory CLEMENT <gregory.clement-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
To: jean-jacques hiblot
	<jjhiblot-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Cc: jean-jacques hiblot <jean-jacques.hiblot-qU79poH1Kb0@public.gmane.org>
Subject: Re: [PATCH v2 4/4] i2c: i2c-ibm-iic: Implements a polling mode
Date: Fri, 29 Nov 2013 22:39:53 +0100	[thread overview]
Message-ID: <529909A9.8060000@free-electrons.com> (raw)
In-Reply-To: <1385110686-4226-5-git-send-email-jean-jacques.hiblot-qU79poH1Kb0@public.gmane.org>

On 22/11/2013 09:58, jean-jacques hiblot wrote:
> When no valid interrupt is defined for the controller, use polling to handle
> the transfers.
> The polling mode can also be forced with the "iic_force_poll" module parameter.
> 
> Signed-off-by: jean-jacques hiblot <jjhiblot-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> ---
>  drivers/i2c/busses/i2c-ibm_iic.c | 89 ++++++++++++++++++++++++++++++++--------
>  drivers/i2c/busses/i2c-ibm_iic.h |  1 +
>  2 files changed, 73 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
> index a3f3f1b..1dde6e1 100644
> --- a/drivers/i2c/busses/i2c-ibm_iic.c
> +++ b/drivers/i2c/busses/i2c-ibm_iic.c
> @@ -334,11 +334,45 @@ static irqreturn_t iic_handler(int irq, void *dev_id)
>  }
>  
>  /*
> + * Polling used when interrupt can't be used
> + */
> +static int poll_for_end_of_transfer(struct ibm_iic_private *dev, u32 timeout)
> +{
> +	struct iic_regs __iomem *iic = dev->vaddr;
> +	u32 status;
> +	unsigned long end = jiffies + timeout;
> +
> +	while ((dev->transfer_complete == 0) &&
> +	   time_after(end, jiffies) &&
> +	   !signal_pending(current)) {
> +		status = in_8(&iic->sts);
> +		/* check if the transfer is done or an error occured */
occurred

> +		if ((status & (STS_ERR | STS_SCMP)) || !(status & STS_PT))
> +			iic_xfer_bytes(dev);
> +		/* The transfer is not complete,
> +		 * calling schedule relaxes the CPU load and allows to know
> +		 * if the process is being signaled (for abortion)
> +		 */
nitpick: wrong muliline comment style

> +		if (dev->transfer_complete == 0)
> +			schedule();
> +	}
> +
> +	if (signal_pending(current))
> +		return -ERESTARTSYS;
> +
> +	if (dev->transfer_complete == 0)
> +		return 0;
> +
> +	return 1;
> +}
> +
> +/*
>   * Try to abort active transfer.
>   */
>  static void iic_abort_xfer(struct ibm_iic_private *dev)
>  {
>  	struct device *device = dev->adap.dev.parent;
> +	struct iic_regs __iomem *iic = dev->vaddr;
>  	unsigned long end;
>  
>  	DBG(dev, "aborting transfer\n");
> @@ -346,8 +380,17 @@ static void iic_abort_xfer(struct ibm_iic_private *dev)
>  	end = jiffies + 10;
>  	dev->abort = 1;
>  
> -	while (time_after(end, jiffies) && !dev->transfer_complete)
> -		schedule();
> +	while (time_after(end, jiffies) && !dev->transfer_complete) {
> +		u32 sts;
> +		if (dev->use_polling) {
> +			sts = in_8(&iic->sts);
> +			/* check if the transfer is done or an error occured */
> +			if ((sts & (STS_ERR | STS_SCMP)) || !(sts & STS_PT))
> +				iic_xfer_bytes(dev);
> +		}
> +		if (dev->transfer_complete == 0)
> +			schedule();
> +	}
>  
>  	if (!dev->transfer_complete) {
>  		dev_err(device, "abort operation failed\n");
> @@ -379,7 +422,8 @@ static int iic_xfer_bytes(struct ibm_iic_private *dev)
>  	if (dev->status == -ECANCELED) {
>  		DBG(dev, "abort completed\n");
>  		dev->transfer_complete = 1;
> -		complete(&dev->iic_compl);
> +		if (!dev->use_polling)
> +			complete(&dev->iic_compl);
>  		return dev->status;
>  	}
>  
> @@ -398,7 +442,8 @@ static int iic_xfer_bytes(struct ibm_iic_private *dev)
>  
>  		dev->status = -EIO;
>  		dev->transfer_complete = 1;
> -		complete(&dev->iic_compl);
> +		if (!dev->use_polling)
> +			complete(&dev->iic_compl);
>  		return dev->status;
>  	}
>  
> @@ -426,7 +471,8 @@ static int iic_xfer_bytes(struct ibm_iic_private *dev)
>  		if (dev->current_msg == dev->num_msgs) {
>  			DBG2(dev, "end of transfer\n");
>  			dev->transfer_complete = 1;
> -			complete(&dev->iic_compl);
> +			if (!dev->use_polling)
> +				complete(&dev->iic_compl);
>  			return dev->status;
>  		}
>  		pm++;
> @@ -617,23 +663,28 @@ static int iic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
>  	/* Load slave address */
>  	iic_address(dev, &msgs[0]);
>  
> -	init_completion(&dev->iic_compl);
> +	if (!dev->use_polling)
> +		init_completion(&dev->iic_compl);
>  
>  	/* start the transfer */
>  	ret = iic_xfer_bytes(dev);
>  
>  	if (ret == 0) {
> -		/* enable the interrupts */
> -		out_8(&iic->mdcntl, MDCNTL_EINT);
> -		/*  unmask the interrupts */
> -		out_8(&iic->intmsk,	INTRMSK_EIMTC | INTRMSK_EITA  |
> -					INTRMSK_EIIC | INTRMSK_EIHE);
> -		/*  wait for the transfer to complete */
> -		ret = wait_for_completion_interruptible_timeout(
> -			&dev->iic_compl, num * HZ);
> -		/* we don't mask the interrupts here because we may
> -		* need them to abort the transfer gracefully
> -		*/
> +		if (dev->use_polling) {
> +			ret = poll_for_end_of_transfer(dev, num * HZ);
> +		} else {
> +			/* enable the interrupts */
> +			out_8(&iic->mdcntl, MDCNTL_EINT);
> +			/*  unmask the interrupts */
> +			out_8(&iic->intmsk,	INTRMSK_EIMTC | INTRMSK_EITA  |
> +						INTRMSK_EIIC | INTRMSK_EIHE);
> +			/*  wait for the transfer to complete */
> +			ret = wait_for_completion_interruptible_timeout(
> +				&dev->iic_compl, num * HZ);
> +			/* we don't mask the interrupts here because we may
> +			* need them to abort the transfer gracefully
> +			*/
> +		}
>  	}
>  
>  	if (ret == 0) {
> @@ -699,6 +750,8 @@ static int iic_request_irq(struct platform_device *ofdev,
>  	struct device_node *np = ofdev->dev.of_node;
>  	int irq;
>  
> +	dev->use_polling = 1;
> +
>  	if (iic_force_poll)
>  		return 0;
>  
> @@ -718,6 +771,8 @@ static int iic_request_irq(struct platform_device *ofdev,
>  		return 0;
>  	}
>  
> +	dev->use_polling = 0;
> +
>  	return irq;
>  }
>  
> diff --git a/drivers/i2c/busses/i2c-ibm_iic.h b/drivers/i2c/busses/i2c-ibm_iic.h
> index 0ee28a9..523cfc1 100644
> --- a/drivers/i2c/busses/i2c-ibm_iic.h
> +++ b/drivers/i2c/busses/i2c-ibm_iic.h
> @@ -58,6 +58,7 @@ struct ibm_iic_private {
>  	int transfer_complete;
>  	int status;
>  	int abort;
> +	int use_polling;
>  	struct completion iic_compl;
>  };
>  
> 


-- 
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com

      parent reply	other threads:[~2013-11-29 21:39 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-11-22  8:58 [PATCH v2 0/4] i2c : i2c-ibm-iic : use interrupts to perform the data transfer jean-jacques hiblot
     [not found] ` <1385110686-4226-1-git-send-email-jean-jacques.hiblot-qU79poH1Kb0@public.gmane.org>
2013-11-22  8:58   ` [PATCH v2 1/4] i2c: i2c-ibm-iic: cleanup jean-jacques hiblot
     [not found]     ` <1385110686-4226-2-git-send-email-jean-jacques.hiblot-qU79poH1Kb0@public.gmane.org>
2013-11-22 15:15       ` Gregory CLEMENT
2013-11-22  8:58   ` [PATCH v2 2/4] i2c: i2c-ibm-iic: perform the transfer in the interrupt handler jean-jacques hiblot
     [not found]     ` <1385110686-4226-3-git-send-email-jean-jacques.hiblot-qU79poH1Kb0@public.gmane.org>
2013-11-22 15:16       ` Gregory CLEMENT
     [not found]         ` <528F7547.2070308-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
2013-11-25  8:24           ` Jean-Jacques Hiblot
2013-11-22  8:58   ` [PATCH v2 3/4] i2c: i2c-ibm-iic: Implements transfer abortion jean-jacques hiblot
     [not found]     ` <1385110686-4226-4-git-send-email-jean-jacques.hiblot-qU79poH1Kb0@public.gmane.org>
2013-11-29 21:38       ` Gregory CLEMENT
2013-11-22  8:58   ` [PATCH v2 4/4] i2c: i2c-ibm-iic: Implements a polling mode jean-jacques hiblot
     [not found]     ` <1385110686-4226-5-git-send-email-jean-jacques.hiblot-qU79poH1Kb0@public.gmane.org>
2013-11-29 21:39       ` Gregory CLEMENT [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=529909A9.8060000@free-electrons.com \
    --to=gregory.clement-wi1+55scjutkeb57/3fjtnbpr1lh4cv8@public.gmane.org \
    --cc=jean-jacques.hiblot-qU79poH1Kb0@public.gmane.org \
    --cc=jjhiblot-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \
    --cc=linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.