[PATCH 2.6.13-rc6] improve start/stop code for worker thread in cpqfcTS driver

From: Rolf Eike Beer
Date: Tue Aug 16 2005 - 10:07:30 EST


Use pid of worker thread and struct completion for signaling end of worker
thread (code more or less taken from drivers/net/8139too.c). For the moment
the return code of the start/stop functions is ignored, this will change
once the init/exit code is changed to use 2.6 driver model.

Signed-off-by: Rolf Eike Beer <eike-kernel@xxxxxxxxx>

diff -aup linux-2.6.13-rc6/drivers/scsi/cpqfcTSinit.c linux-2.6.13-rc6-eike/drivers/scsi/cpqfcTSinit.c
--- linux-2.6.13-rc6/drivers/scsi/cpqfcTSinit.c 2005-08-16 16:42:14.000000000 +0200
+++ linux-2.6.13-rc6-eike/drivers/scsi/cpqfcTSinit.c 2005-08-16 16:34:02.000000000 +0200
@@ -204,32 +204,35 @@ static void Cpqfc_initHBAdata(CPQFCHBA *
}
}

-
-/* (borrowed from linux/drivers/scsi/hosts.c) */
-static void launch_FCworker_thread(struct Scsi_Host *HostAdapter)
+static int launch_FCworker_thread(struct Scsi_Host *HostAdapter)
{
- DECLARE_MUTEX_LOCKED(sem);
-
- CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *)HostAdapter->hostdata;
-
- ENTER("launch_FC_worker_thread");
-
- cpqfcHBAdata->notify_wt = &sem;
-
- /* must unlock before kernel_thread(), for it may cause a reschedule. */
- spin_unlock_irq(HostAdapter->host_lock);
- kernel_thread((int (*)(void *))cpqfcTSWorkerThread,
- (void *) HostAdapter, 0);
- /*
- * Now wait for the kernel error thread to initialize itself
-
- */
- down (&sem);
- spin_lock_irq(HostAdapter->host_lock);
- cpqfcHBAdata->notify_wt = NULL;
-
- LEAVE("launch_FC_worker_thread");
-
+ DECLARE_MUTEX_LOCKED(sem);
+
+ CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *)HostAdapter->hostdata;
+
+ ENTER(__function__);
+
+ cpqfcHBAdata->notify_wt = &sem;
+
+ /* must unlock before kernel_thread(), for it may cause a reschedule. */
+ spin_unlock_irq(HostAdapter->host_lock);
+ cpqfcHBAdata->thr_pid = -1;
+ cpqfcHBAdata->time_to_die = 0;
+ cpqfcHBAdata->thr_pid = kernel_thread(cpqfcTSWorkerThread, HostAdapter, 0);
+ if (cpqfcHBAdata->thr_pid) {
+ printk(KERN_ERR DEV_NAME " can't start worker thread\n");
+ return cpqfcHBAdata->thr_pid;
+ } else {
+ /*
+ * Now wait for the kernel error thread to initialize itself
+ */
+ down (&sem);
+ spin_lock_irq(HostAdapter->host_lock);
+ cpqfcHBAdata->notify_wt = NULL;
+ }
+
+ LEAVE(__function__);
+ return 0;
}


@@ -317,9 +320,8 @@ int cpqfcTS_detect(Scsi_Host_Template *S
// each HBA on the PCI bus(ses)).
cpqfcHBAdata = (CPQFCHBA *)HostAdapter->hostdata;

- // make certain our data struct is clear
- memset( cpqfcHBAdata, 0, sizeof( CPQFCHBA ) );
-
+ memset(cpqfcHBAdata, 0, sizeof(*cpqfcHBAdata));
+ init_completion(&cpqfcHBAdata->thr_exited);

// initialize our HBA info
cpqfcHBAdata->HBAnum = NumberOfAdapters;
@@ -712,6 +714,25 @@ int cpqfcTS_ioctl( struct scsi_device *S
return result;
}

+static int
+cpqfcTS_kill_worker(CPQFCHBA *hba)
+{
+ int ret = 0;
+
+ if(hba->thr_pid >= 0) {
+ hba->time_to_die = 1;
+ wmb();
+ ret = kill_proc(hba->thr_pid, SIGTERM, 1);
+ if (ret) {
+ printk(KERN_ERR DEV_NAME " unable to signal thread %i\n",
+ hba->thr_pid);
+ } else {
+ wait_for_completion(&hba->thr_exited);
+ hba->thr_pid = -1;
+ }
+ }
+ return ret;
+}

/* "Release" the Host Bus Adapter...
disable interrupts, stop the HBA, release the interrupt,
@@ -731,18 +752,7 @@ int cpqfcTS_release(struct Scsi_Host *Ho
DEBUG_PCI( printk(" disable hardware, destroy queues, free mem\n"));
cpqfcHBAdata->fcChip.ResetTachyon( cpqfcHBAdata, CLEAR_FCPORTS);

- // kill kernel thread
- if( cpqfcHBAdata->worker_thread ) // (only if exists)
- {
- DECLARE_MUTEX_LOCKED(sem); // synchronize thread kill
-
- cpqfcHBAdata->notify_wt = &sem;
- DEBUG_PCI( printk(" killing kernel thread\n"));
- send_sig( SIGKILL, cpqfcHBAdata->worker_thread, 1);
- down( &sem);
- cpqfcHBAdata->notify_wt = NULL;
-
- }
+ cpqfcTS_kill_worker(cpqfcHBAdata);

cpqfc_free_private_data_pool(cpqfcHBAdata);
// free Linux resources
diff -aup linux-2.6.13-rc6/drivers/scsi/cpqfcTSstructs.h linux-2.6.13-rc6-eike/drivers/scsi/cpqfcTSstructs.h
--- linux-2.6.13-rc6/drivers/scsi/cpqfcTSstructs.h 2005-08-16 16:42:14.000000000 +0200
+++ linux-2.6.13-rc6-eike/drivers/scsi/cpqfcTSstructs.h 2005-08-16 16:28:53.000000000 +0200
@@ -829,7 +829,7 @@ int CpqTsReadWriteWWN(void*, int ReadWri
int CpqTsReadWriteNVRAM(void*, void* data, int ReadWrite);

void cpqfcTS_WorkTask( struct Scsi_Host *HostAdapter);
-void cpqfcTSWorkerThread( void *host);
+extern int cpqfcTSWorkerThread(void *host);

int cpqfcTS_GetNVRAM_data( UCHAR *wwnbuf, UCHAR *buf );
ULONG cpqfcTS_ReadNVRAM( void* GPIOin, void* GPIOout , USHORT count,
@@ -937,7 +937,10 @@ typedef struct
// logouts, FC protocol timeouts, etc.
int fcStatsTime; // Statistics delta reporting time

- struct task_struct *worker_thread; // our kernel thread
+ pid_t thr_pid; /* pid of worker thread */
+ struct completion thr_exited; /* exit status of worker thread */
+ int time_to_die; /* flag for worker thread to exit */
+
int PortDiscDone; // set by SendLogins(), cleared by LDn

struct semaphore *TachFrozen;
diff -aup linux-2.6.13-rc6/drivers/scsi/cpqfcTSworker.c linux-2.6.13-rc6-eike/drivers/scsi/cpqfcTSworker.c
--- linux-2.6.13-rc6/drivers/scsi/cpqfcTSworker.c 2005-08-16 16:42:14.000000000 +0200
+++ linux-2.6.13-rc6-eike/drivers/scsi/cpqfcTSworker.c 2005-08-16 16:45:13.000000000 +0200
@@ -147,7 +147,7 @@ static void IssueReportLunsCommand(

// (see scsi_error.c comments on kernel task creation)

-void cpqfcTSWorkerThread( void *host)
+int cpqfcTSWorkerThread(void *host)
{
struct Scsi_Host *HostAdapter = (struct Scsi_Host*)host;
CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *)HostAdapter->hostdata;
@@ -169,10 +169,7 @@ void cpqfcTSWorkerThread( void *host)
cpqfcHBAdata->fcQueReady = &fcQueReady; // primary wait point
cpqfcHBAdata->TYOBcomplete = &fcTYOBcomplete;
cpqfcHBAdata->TachFrozen = &TachFrozen;
-
-
- cpqfcHBAdata->worker_thread = current;
-
+
unlock_kernel();

if( cpqfcHBAdata->notify_wt != NULL )
@@ -184,7 +181,9 @@ void cpqfcTSWorkerThread( void *host)

down_interruptible( &fcQueReady); // wait for something to do

- if (signal_pending(current) )
+ if (signal_pending(current))
+ flush_signals(current);
+ if (cpqfcHBAdata->time_to_die)
break;

PCI_TRACE( 0x90)
@@ -225,12 +224,9 @@ void cpqfcTSWorkerThread( void *host)
// Now, complete any Cmnd we Q'd up while BoardLock was held

CompleteBoardLockCmnd( cpqfcHBAdata);
-
-
}
- // hopefully, the signal was for our module exit...
- if( cpqfcHBAdata->notify_wt != NULL )
- up( cpqfcHBAdata->notify_wt); // yep, we're outta here
+
+ complete_and_exit(&cpqfcHBAdata->thr_exited, 0);
}


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