public inbox for linux-scsi@vger.kernel.org
 help / color / mirror / Atom feed
From: Christoph Hellwig <hch@infradead.org>
To: "Smart, James" <James.Smart@Emulex.com>
Cc: "'linux-scsi@vger.kernel.org'" <linux-scsi@vger.kernel.org>
Subject: Re: [(re)Announce] Emulex LightPulse Device Driver
Date: Tue, 18 May 2004 13:08:28 +0100	[thread overview]
Message-ID: <20040518130828.B9363@infradead.org> (raw)
In-Reply-To: <3356669BBE90C448AD4645C843E2BF28034F92F0@xbl.ma.emulex.com>; from James.Smart@Emulex.com on Sun, May 09, 2004 at 12:33:35AM -0400

Okay, I took a look at the tasklet handling and have re-arranged it a litte:

 - unused member task_discq_cnt of lpfcHBA_t removed
 - lpfc_discq_tasklet merged into lpfc_discq_post_event and streamlined
 - splice the list in lpfc_tasklet to shorten lock holding (and irq disabling)
   time
 - use list_for_each_entry to be readable
 - split into subfunctions

I'm still far less than happy with the whole tasklet code, though:

 - lpfc_discq_post_event allocates a structure for every event from irq
   kontext.  Look at qla2xxx how to embedd the lists into the actual
   object to solve this (OTOH qla2xxx is much much nicer in that respect
   anyway as there's only one type of object queued up from the isr to
   the dpc thread)
 - usage of tasklet itself is questionable, you probably want a kernel-thread
   ala qla2xxx so it's always in usercontext, making your life much easier
   in many places
 - phba->tasklet_running is a mess.  You couldn't care less whether the
   tasklet is running but rather you want to know whether you're called from
   it.


diff -urp lpfcdriver-2.6-8.0.1/lpfc.h lpfcdriver-2.6-8.0.1.hch/lpfc.h
--- lpfcdriver-2.6-8.0.1/lpfc.h	2004-05-16 20:03:37.000000000 +0200
+++ lpfcdriver-2.6-8.0.1.hch/lpfc.h	2004-05-18 13:23:37.491363504 +0200
@@ -399,7 +399,6 @@ typedef struct lpfcHBA {
 	spinlock_t            task_lock;
 	struct tasklet_struct task_run;
 	struct list_head      task_disc;
-	uint16_t              task_discq_cnt;
 	uint16_t	      tasklet_running;
 
 	atomic_t cmnds_in_flight;
diff -urp lpfcdriver-2.6-8.0.1/lpfc_fcp.c lpfcdriver-2.6-8.0.1.hch/lpfc_fcp.c
--- lpfcdriver-2.6-8.0.1/lpfc_fcp.c	2004-05-16 20:03:37.000000000 +0200
+++ lpfcdriver-2.6-8.0.1.hch/lpfc_fcp.c	2004-05-18 13:55:23.843553920 +0200
@@ -2097,111 +2097,98 @@ lpfc_sleep(lpfcHBA_t * phba, void *wait_
 		return (ETIMEDOUT);
 }
 
-void
-lpfc_discq_tasklet(lpfcHBA_t * phba, LPFC_DISC_EVT_t * evtp)
+int
+lpfc_discq_post_event(lpfcHBA_t * phba, void *arg1, void *arg2, uint32_t evt)
 {
-	unsigned long flags;
+	LPFC_DISC_EVT_t	*evtp;
+	unsigned long	flags;
+
+	/*
+	 * All Mailbox completions and LPFC_ELS_RING rcv ring events will be
+	 * queued to tasklet for processing
+	 */
+	evtp = kmalloc(sizeof(LPFC_DISC_EVT_t), GFP_ATOMIC);
+	if (unlikely(!evtp))
+		return 0;
+
+	evtp->evt_arg1  = arg1;
+	evtp->evt_arg2  = arg2;
+	evtp->evt       = evt;
 
-	/* Queue the cmnd to the iodone tasklet to be scheduled later */
 	spin_lock_irqsave(&phba->task_lock, flags);
 	list_add_tail(&evtp->evt_listp, &phba->task_disc);
-	phba->task_discq_cnt++;
 	spin_unlock_irqrestore(&phba->task_lock, flags);
+
 	tasklet_schedule(&phba->task_run);
-	return;
+	return 1;
 }
 
-int
-lpfc_discq_post_event(lpfcHBA_t * phba, void *arg1, void *arg2, uint32_t evt)
+static void
+lpfc_process_evt_mbox(lpfcHBA_t *phba, LPFC_MBOXQ_t *pmb)
+{
+	pmb->mbox_cmpl(phba, pmb);
+}
+
+static void
+lpfc_process_evt_iocb(lpfcHBA_t *phba, LPFC_IOCBQ_t *cmdiocbp,
+		LPFC_RING_MASK_t *func, LPFC_IOCBQ_t *saveq)
 {
-	LPFC_DISC_EVT_t  *evtp;
+	LPFC_IOCBQ_t		*rspiocbp, *tmp;
 
-	/* All Mailbox completions and LPFC_ELS_RING rcv ring events will be
-	 * queued to tasklet for processing
-	 */
-	evtp = (LPFC_DISC_EVT_t *) kmalloc(sizeof(LPFC_DISC_EVT_t), GFP_ATOMIC);
-	if(evtp == 0) {
-		return (0);
+	if (func) {
+		func->lpfc_sli_rcv_unsol_event(phba,
+				&phba->sli.ring[LPFC_ELS_RING], saveq);
+	} else {
+		cmdiocbp->iocb_cmpl(phba, cmdiocbp, saveq);
 	}
-	evtp->evt_arg1  = arg1;
-	evtp->evt_arg2  = arg2;
-	evtp->evt       = evt;
-	evtp->evt_listp.next = 0;
-	evtp->evt_listp.prev = 0;
-	lpfc_discq_tasklet(phba, evtp);
-	return (1);
+
+	/* free up iocb buffer chain for command just processed */
+	list_for_each_entry_safe(rspiocbp, tmp, &saveq->list, list) {
+		list_del(&rspiocbp->list);
+		mempool_free(rspiocbp, phba->iocb_mem_pool);
+	}
+
+	mempool_free(saveq, phba->iocb_mem_pool);
 }
 
 void
 lpfc_tasklet(unsigned long p)
 {
-	lpfcHBA_t        * phba = (lpfcHBA_t *)p;
-	LPFC_SLI_t       * psli;
-	LPFC_DISC_EVT_t  * evtp;
-	struct list_head * pos, * pos_tmp;
-	struct list_head * cur, * next;
-	LPFC_MBOXQ_t     * pmb;
-	LPFC_IOCBQ_t     * cmdiocbp;
-	LPFC_IOCBQ_t     * rspiocbp;
-	LPFC_IOCBQ_t     * saveq;
-	LPFC_RING_MASK_t * func;
-	unsigned long      flags;
+	lpfcHBA_t	*phba = (lpfcHBA_t *)p;
+	LPFC_DISC_EVT_t	*evtp, *evtp_tmp;
+	unsigned long	flags;
+	LIST_HEAD	(local_task_q);
 
-	psli = &phba->sli;
 	spin_lock_irqsave(&phba->task_lock, flags);
+	list_splice_init(&phba->task_disc, &local_task_q);
+	spin_unlock_irqrestore(&phba->task_lock, flags);
+
 	/* check discovery event list */
-	list_for_each_safe(pos, pos_tmp, &phba->task_disc) {
-		evtp = list_entry(pos, LPFC_DISC_EVT_t, evt_listp);
+	list_for_each_entry_safe(evtp, evtp_tmp, &local_task_q, evt_listp) {
 		list_del(&evtp->evt_listp);
-		phba->task_discq_cnt--;
-		spin_unlock_irqrestore(&phba->task_lock, flags);
 
-		spin_lock_irqsave(&(phba->drvrlock), flags);
-		phba->tasklet_running += 1;
-		switch(evtp->evt) {
+		spin_lock_irqsave(&phba->drvrlock, flags);
+		phba->tasklet_running++;
+		switch (evtp->evt) {
 		case LPFC_EVT_MBOX:
-			pmb = (LPFC_MBOXQ_t *)(evtp->evt_arg1);
-			(pmb->mbox_cmpl) (phba, pmb);
+			lpfc_process_evt_mbox(phba, evtp->evt_arg1);
 			break;
 		case LPFC_EVT_SOL_IOCB:
-			cmdiocbp = (LPFC_IOCBQ_t *)(evtp->evt_arg1);
-			saveq = (LPFC_IOCBQ_t *)(evtp->evt_arg2);
-			(cmdiocbp->iocb_cmpl) (phba, cmdiocbp, saveq);
-			/* Free up iocb buffer chain for command just
-			   processed */
-			list_for_each_safe(cur, next, &saveq->list) {
-				rspiocbp = list_entry(cur, LPFC_IOCBQ_t, list);
-				list_del(&rspiocbp->list);
-				mempool_free( rspiocbp, phba->iocb_mem_pool);
-			}
-			mempool_free( saveq, phba->iocb_mem_pool);
+			lpfc_process_evt_iocb(phba, evtp->evt_arg1,
+					NULL, evtp->evt_arg2);
 			break;
 		case LPFC_EVT_UNSOL_IOCB:
-			func = (LPFC_RING_MASK_t *)(evtp->evt_arg1);
-			saveq = (LPFC_IOCBQ_t *)(evtp->evt_arg2);
-			(func->lpfc_sli_rcv_unsol_event) (phba, 
-	 		&psli->ring[LPFC_ELS_RING], saveq);
-			/* Free up iocb buffer chain for command just
-			   processed */
-			list_for_each_safe(cur, next, &saveq->list) {
-				rspiocbp = list_entry(cur, LPFC_IOCBQ_t, list);
-				list_del(&rspiocbp->list);
-				mempool_free( rspiocbp, phba->iocb_mem_pool);
-			}
-			mempool_free( saveq, phba->iocb_mem_pool);
+			lpfc_process_evt_iocb(phba, NULL,
+					evtp->evt_arg1, evtp->evt_arg2);
 			break;
 		}
-		phba->tasklet_running -= 1;
-		spin_unlock_irqrestore(&(phba->drvrlock), flags);
+		phba->tasklet_running--;
+		spin_unlock_irqrestore(&phba->drvrlock, flags);
 
-		spin_lock_irqsave(&phba->task_lock, flags);
 		kfree(evtp);
 	}
-	spin_unlock_irqrestore(&phba->task_lock, flags);
-	return;
 }
 
-
 module_init(lpfc_init);
 module_exit(lpfc_exit);
 MODULE_LICENSE("GPL");

  parent reply	other threads:[~2004-05-18 12:08 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-05-09  4:33 [(re)Announce] Emulex LightPulse Device Driver Smart, James
2004-05-09  8:20 ` Christoph Hellwig
2004-05-09  8:51   ` Christoph Hellwig
2004-05-10 16:34 ` Matthew Wilcox
2004-05-18 11:59 ` Christoph Hellwig
2004-05-18 12:08 ` Christoph Hellwig [this message]
  -- strict thread matches above, loose matches on Subject: below --
2004-05-10 16:47 Smart, James
2004-05-13 21:21 David.Egolf
2004-05-13 21:26 ` Christoph Hellwig
2004-05-14 19:51 Smart, James
2004-05-14 20:03 ` 'Christoph Hellwig'
2004-05-17 21:25 Smart, James
2004-05-18  9:58 ` 'Christoph Hellwig'
2004-05-18 13:00 Smart, James
2004-05-18 13:04 Smart, James
2004-05-18 13:07 ` 'Christoph Hellwig'
2004-05-18 13:08 Smart, James
2004-05-18 13:09 Smart, James

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=20040518130828.B9363@infradead.org \
    --to=hch@infradead.org \
    --cc=James.Smart@Emulex.com \
    --cc=linux-scsi@vger.kernel.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox