Re: [PATCH 10/10] omap mailbox: OMAP4 Mailbox-driver Patch to support tasklet implementation

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: "ext C.A, Subramaniam" <subramaniam.ca@xxxxxx>
Subject: RE: [PATCH 10/10] omap mailbox: OMAP4 Mailbox-driver Patch to support tasklet implementation
Date: Thu, 10 Sep 2009 13:46:53 +0200

> 
>  
> Hi Hiroshi,
> 
> > -----Original Message-----
> > From: Hiroshi DOYU [mailto:Hiroshi.DOYU@xxxxxxxxx] 
> > Sent: Wednesday, September 09, 2009 2:32 PM
> > To: C.A, Subramaniam
> > Cc: linux-omap@xxxxxxxxxxxxxxx; tony@xxxxxxxxxxx; 
> > rmk@xxxxxxxxxxxxxxxx; Kanigeri, Hari; Gupta, Ramesh
> > Subject: Re: [PATCH 10/10] omap mailbox: OMAP4 Mailbox-driver 
> > Patch to support tasklet implementation
> > 
> > Hi Subbu,
> > 
> > From: "ext C.A, Subramaniam" <subramaniam.ca@xxxxxx>
> > Subject: RE: [PATCH 10/10] omap mailbox: OMAP4 Mailbox-driver 
> > Patch to support tasklet implementation
> > Date: Tue, 8 Sep 2009 19:43:48 +0200
> > 
> > [...]
> > 
> > > > As I described in the comment on [PATCH 8/10], I think 
> > that it would 
> > > > be better to keep "mach-omap2/mailbox.c" simple and to add some 
> > > > additional logic on "plat-omap/mailbox.c".
> > > > 
> > > > Would it be possbile to move this tasklet implementation to 
> > > > "plat-omap/mailbox.c"?
> > > 
> > > The implementation of the tasklet itself is maintained in 
> > > plat-omap/mailbox.c Since, I wanted to maintain a separate 
> > tasklet for 
> > > each mailbox instance used to send messages from MPU, I had to 
> > > associate the the tasklet to the mailbox. Hence, the 
> > changes were done 
> > > in mach-omap2/mailbox.c
> > > 
> > > Please give your comments on this approach.
> > 
> > Wouldn't just converting work_queue to tasklet work like below?
> > 
> > (I havne't tested this at all, though...)
> > 
> > diff --git a/arch/arm/plat-omap/include/mach/mailbox.h 
> > b/arch/arm/plat-omap/include/mach/mailbox.h
> > index b7a6991..1f4e53e 100644
> > --- a/arch/arm/plat-omap/include/mach/mailbox.h
> > +++ b/arch/arm/plat-omap/include/mach/mailbox.h
> > @@ -52,6 +52,8 @@ struct omap_mbox {
> >  
> >  	struct omap_mbox_queue	*txq, *rxq;
> >  
> > +	struct tasklet_struct	tx_tasklet;
> > +
> >  	struct omap_mbox_ops	*ops;
> >  
> >  	mbox_msg_t		seq_snd, seq_rcv;
> 
> Moved the tasklet structure to the omap_mbox_queue as follows:

This is better.

> 
> @@ -40,7 +43,8 @@ struct omap_mbox_ops {
>  struct omap_mbox_queue {
>  	spinlock_t		lock;
>  	struct request_queue	*queue;
> -	struct work_struct	work;
> +	struct work_struct	rx_work;
> +	struct tasklet_struct	tx_tasklet;
>  	int	(*callback)(void *);
>  	struct omap_mbox	*mbox;
>  };


I think that "rx_/tx_" prefix may not be necessary if you add tasklet
feature in "omap_mbox_queue" as followed since "omap_mbox_queue" can
be considered as s/w queue which can evoke workqueue/tasklet
accordingly.


+	struct work_struct	work;
+	struct tasklet_struct	tasklet;
 	int	(*callback)(void *);
 	struct omap_mbox	*mbox;
 };


> 
> Also chagned the omap_mbox_msg_send(). Removed the struct omap_msg_tx_data.
> 
>  
>  int omap_mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg)
>  {
> -	struct omap_msg_tx_data *tx_data;
> +
>  	struct request *rq;
>  	struct request_queue *q = mbox->txq->queue;
>  
> -	tx_data = kmalloc(sizeof(*tx_data), GFP_ATOMIC);
> -	if (unlikely(!tx_data))
> -		return -ENOMEM;
> -
>  	rq = blk_get_request(q, WRITE, GFP_ATOMIC);
> -	if (unlikely(!rq)) {
> -		kfree(tx_data);
> +	if (unlikely(!rq))
>  		return -ENOMEM;
> -	}
>  
> -	tx_data->msg = msg;
> -	rq->end_io = omap_msg_tx_end_io;
> -	blk_insert_request(q, rq, 0, tx_data);
> +	blk_insert_request(q, rq, 0, (void *) msg);
> +	tasklet_schedule(&mbox->txq->tx_tasklet);
>  
> -	schedule_work(&mbox->txq->work);
>  	return 0;
>  }
>  EXPORT_SYMBOL(omap_mbox_msg_send);
> 
> > diff --git a/arch/arm/plat-omap/mailbox.c 
> > b/arch/arm/plat-omap/mailbox.c index 40424ed..37267ca 100644
> > --- a/arch/arm/plat-omap/mailbox.c
> > +++ b/arch/arm/plat-omap/mailbox.c
> > @@ -184,22 +184,17 @@ int omap_mbox_msg_send(struct omap_mbox 
> > *mbox, mbox_msg_t msg, void* arg)  }  
> > EXPORT_SYMBOL(omap_mbox_msg_send);
> >  
> > -static void mbox_tx_work(struct work_struct *work)
> > +static void mbox_tx_tasklet(unsigned long data)
> >  {
> >  	int ret;
> >  	struct request *rq;
> > -	struct omap_mbox_queue *mq = container_of(work,
> > -				struct omap_mbox_queue, work);
> > -	struct omap_mbox *mbox = mq->queue->queuedata;
> > + 	struct omap_mbox *mbox = (struct omap_mbox *)data;
> >  	struct request_queue *q = mbox->txq->queue;
> >  
> >  	while (1) {
> >  		struct omap_msg_tx_data *tx_data;
> >  
> > -		spin_lock(q->queue_lock);
> >  		rq = blk_fetch_request(q);
> > -		spin_unlock(q->queue_lock);
> > -
> >  		if (!rq)
> >  			break;
> >  
> > @@ -208,15 +203,10 @@ static void mbox_tx_work(struct 
> > work_struct *work)
> >  		ret = __mbox_msg_send(mbox, tx_data->msg, tx_data->arg);
> >  		if (ret) {
> >  			enable_mbox_irq(mbox, IRQ_TX);
> > -			spin_lock(q->queue_lock);
> >  			blk_requeue_request(q, rq);
> > -			spin_unlock(q->queue_lock);
> >  			return;
> >  		}
> > -
> > -		spin_lock(q->queue_lock);
> >  		__blk_end_request_all(rq, 0);
> > -		spin_unlock(q->queue_lock);
> >  	}
> >  }
> >  
> 
> Changed the mbox_tx_tasklet as follows:
> 
> -static void mbox_tx_work(struct work_struct *work)
> +static void mbox_tx_tasklet(unsigned long tx_data)
>  {
>  	int ret;
>  	struct request *rq;
> -	struct omap_mbox_queue *mq = container_of(work,
> -				struct omap_mbox_queue, work);
> -	struct omap_mbox *mbox = mq->queue->queuedata;
> +	struct omap_mbox *mbox = (struct omap_mbox *)tx_data;
>  	struct request_queue *q = mbox->txq->queue;
>  
>  	while (1) {
> -		struct omap_msg_tx_data *tx_data;
>  
> -		spin_lock(q->queue_lock);
>  		rq = blk_fetch_request(q);
> -		spin_unlock(q->queue_lock);
>  
>  		if (!rq)
>  			break;
>  
> -		tx_data = rq->special;
> -
> -		ret = __mbox_msg_send(mbox, tx_data->msg);
> +		ret = __mbox_msg_send(mbox, (mbox_msg_t)rq->special);
>  		if (ret) {
>  			omap_mbox_enable_irq(mbox, IRQ_TX);
> -			spin_lock(q->queue_lock);
>  			blk_requeue_request(q, rq);
> -			spin_unlock(q->queue_lock);
>  			return;
>  		}
> -
> -		spin_lock(q->queue_lock);
> -		__blk_end_request_all(rq, 0);
> -		spin_unlock(q->queue_lock);
> +		/* FIXME: We get a WARN_ON() if __blk_end_request_all()
> +		* is used. Not sure if we can remove the queue locks
> +		* for blk_requeue_request() and blk_fetch_request()
> +		* calls as well.*/
> +		blk_end_request_all(rq, 0);
>  	}
>  }
> 
> While testing I got a WARN_ON() using the __blk_end_request_all(). 
> Tried using the blk_end_request_all() instead, and that worked fine. 
> Is it safe to remove the spin lock protection for all the calls 
> inside the tasklet function as you had suggested?
> Please comment.

I think that it's safe since it's being executed in tasklet context,
no preemption.

Which WARN_ON() did you get?

> 
> > @@ -266,7 +256,7 @@ static void __mbox_tx_interrupt(struct 
> > omap_mbox *mbox)  {
> >  	disable_mbox_irq(mbox, IRQ_TX);
> >  	ack_mbox_irq(mbox, IRQ_TX);
> > -	schedule_work(&mbox->txq->work);
> > +	tasklet_schedule(&mbox->tx_tasklet);
> >  }
> >  
> >  static void __mbox_rx_interrupt(struct omap_mbox *mbox) @@ 
> > -434,7 +424,9 @@ static int omap_mbox_init(struct omap_mbox *mbox)
> >  		goto fail_request_irq;
> >  	}
> >
> 
> Changes in the names used for work queue (rx_work) and tasklet as
> tx_tasklet.

As I explained above, the prefix 'tx_/rx_' isn't necessary.

> 
> @@ -157,7 +132,7 @@ static void mbox_tx_work(struct work_struct *work)
>  static void mbox_rx_work(struct work_struct *work)
>  {
>  	struct omap_mbox_queue *mq =
> -			container_of(work, struct omap_mbox_queue, work);
> +			container_of(work, struct omap_mbox_queue, rx_work);
>  	struct omap_mbox *mbox = mq->queue->queuedata;
>  	struct request_queue *q = mbox->rxq->queue;
>  	struct request *rq;
> @@ -192,7 +167,7 @@ static void __mbox_tx_interrupt(struct omap_mbox *mbox)
>  {
>  	omap_mbox_disable_irq(mbox, IRQ_TX);
>  	ack_mbox_irq(mbox, IRQ_TX);
> -	schedule_work(&mbox->txq->work);
> +	tasklet_schedule(&mbox->txq->tx_tasklet);
>  }
>  
>  static void __mbox_rx_interrupt(struct omap_mbox *mbox)
> @@ -217,7 +192,7 @@ static void __mbox_rx_interrupt(struct omap_mbox *mbox)
>  	/* no more messages in the fifo. clear IRQ source. */
>  	ack_mbox_irq(mbox, IRQ_RX);
>  nomem:
> -	schedule_work(&mbox->rxq->work);
> +	schedule_work(&mbox->rxq->rx_work);
>  }
> 
>   
> > -	mq = mbox_queue_alloc(mbox, mbox_txq_fn, mbox_tx_work);
> > +	tasklet_init(&mbox->tx_tasklet, mbox_tx_tasklet, 
> > (unsigned long)mbox);
> > +
> > +	mq = mbox_queue_alloc(mbox, mbox_txq_fn, NULL);
> >  	if (!mq) {
> >  		ret = -ENOMEM;
> >  		goto fail_alloc_txq;
> > 
> > 
> 
> Changed the signature of the mbox_queue_alloc function. 
> The work queue / tasklet initialization is done in the 
> omap_mbox_startup() function.

why?

>
> static struct omap_mbox_queue *mbox_queue_alloc(struct omap_mbox *mbox,
> -					request_fn_proc *proc,
> -					void (*work) (struct work_struct *))
> +					request_fn_proc *proc)
>  {
>  	struct request_queue *q;
>  	struct omap_mbox_queue *mq;
> @@ -252,8 +226,6 @@ static struct omap_mbox_queue *mbox_queue_alloc(struct omap_mbox *mbox,
>  	q->queuedata = mbox;
>  	mq->queue = q;
>  
> -	INIT_WORK(&mq->work, work);
> -
>  	return mq;
>  error:
>  	kfree(mq);
> @@ -292,18 +264,22 @@ static int omap_mbox_startup(struct omap_mbox *mbox)
>  		goto fail_request_irq;
>  	}
>  
> -	mq = mbox_queue_alloc(mbox, mbox_txq_fn, mbox_tx_work);
> +	mq = mbox_queue_alloc(mbox, mbox_txq_fn);
>  	if (!mq) {
>  		ret = -ENOMEM;
>  		goto fail_alloc_txq;
>  	}
> +
> +	tasklet_init(&mq->tx_tasklet, mbox_tx_tasklet, (unsigned long)mbox);
>  	mbox->txq = mq;
>  
> -	mq = mbox_queue_alloc(mbox, mbox_rxq_fn, mbox_rx_work);
> +	mq = mbox_queue_alloc(mbox, mbox_rxq_fn);
>  	if (!mq) {
>  		ret = -ENOMEM;
>  		goto fail_alloc_rxq;
>  	}
> +
> +	INIT_WORK(&mq->rx_work, mbox_rx_work);
>  	mbox->rxq = mq;
>  
>  	return 0;
> --
> 
> Please give your comments on the changes.
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Arm (vger)]     [ARM Kernel]     [ARM MSM]     [Linux Tegra]     [Linux WPAN Networking]     [Linux Wireless Networking]     [Maemo Users]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux