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]

 



 
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:

@@ -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;
 };

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.

> @@ -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.

@@ -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.

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

[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