Commit 0c6df6a6 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

IBM PCI Hotplug driver: polling thread locking cleanup

removed a lot of bizzare polling locking logic, causing the driver to not sleep
for 2 seconds with some locks held.  This improves userspace interaction by
a few orders of magnitude :)
parent 3da9cf28
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
#define get_ctrl_revision(sl, rev) ibmphp_hpc_readslot (sl, READ_REVLEVEL, rev) #define get_ctrl_revision(sl, rev) ibmphp_hpc_readslot (sl, READ_REVLEVEL, rev)
#define get_hpc_options(sl, opt) ibmphp_hpc_readslot (sl, READ_HPCOPTIONS, opt) #define get_hpc_options(sl, opt) ibmphp_hpc_readslot (sl, READ_HPCOPTIONS, opt)
#define DRIVER_VERSION "0.2" #define DRIVER_VERSION "0.3"
#define DRIVER_DESC "IBM Hot Plug PCI Controller Driver" #define DRIVER_DESC "IBM Hot Plug PCI Controller Driver"
int ibmphp_debug; int ibmphp_debug;
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* *
* Written By: Jyoti Shah, IBM Corporation * Written By: Jyoti Shah, IBM Corporation
* *
* Copyright (c) 2001,2001 IBM Corp. * Copyright (c) 2001-2002 IBM Corp.
* *
* All rights reserved. * All rights reserved.
* *
...@@ -27,7 +27,6 @@ ...@@ -27,7 +27,6 @@
* *
*/ */
//#include <linux/delay.h>
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/time.h> #include <linux/time.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -35,9 +34,6 @@ ...@@ -35,9 +34,6 @@
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include "ibmphp.h" #include "ibmphp.h"
#define POLL_NO 0x01
#define POLL_YES 0x00
static int to_debug = FALSE; static int to_debug = FALSE;
#define debug_polling(fmt, arg...) do { if (to_debug) debug (fmt, arg); } while (0) #define debug_polling(fmt, arg...) do { if (to_debug) debug (fmt, arg); } while (0)
...@@ -98,19 +94,15 @@ static int to_debug = FALSE; ...@@ -98,19 +94,15 @@ static int to_debug = FALSE;
// if bits 20,22,25,26,27,29,30 are OFF return TRUE // if bits 20,22,25,26,27,29,30 are OFF return TRUE
#define HPC_I2CSTATUS_CHECK(s) ((u8)((s & 0x00000A76) ? FALSE : TRUE)) #define HPC_I2CSTATUS_CHECK(s) ((u8)((s & 0x00000A76) ? FALSE : TRUE))
// return code 0:poll slots, 1-POLL_LATCH_CNT:poll latch register
#define INCREMENT_POLLCNT(i) ((i < POLL_LATCH_CNT) ? i++ : (i=0))
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// global variables // global variables
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
static int ibmphp_shutdown; static int ibmphp_shutdown;
static int tid_poll; static int tid_poll;
static int stop_polling; // 2 values: poll, don't poll
static struct semaphore sem_hpcaccess; // lock access to HPC static struct semaphore sem_hpcaccess; // lock access to HPC
static struct semaphore semOperations; // lock all operations and static struct semaphore semOperations; // lock all operations and
// access to data structures // access to data structures
static struct semaphore sem_exit; // make sure polling thread goes away static struct semaphore sem_exit; // make sure polling thread goes away
static struct semaphore sem_poll; // make sure poll is idle
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// local function prototypes // local function prototypes
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
...@@ -141,8 +133,6 @@ void ibmphp_hpc_initvars (void) ...@@ -141,8 +133,6 @@ void ibmphp_hpc_initvars (void)
init_MUTEX (&sem_hpcaccess); init_MUTEX (&sem_hpcaccess);
init_MUTEX (&semOperations); init_MUTEX (&semOperations);
init_MUTEX_LOCKED (&sem_exit); init_MUTEX_LOCKED (&sem_exit);
init_MUTEX_LOCKED (&sem_poll);
stop_polling = POLL_YES;
to_debug = FALSE; to_debug = FALSE;
ibmphp_shutdown = FALSE; ibmphp_shutdown = FALSE;
tid_poll = 0; tid_poll = 0;
...@@ -710,11 +700,6 @@ void free_hpc_access (void) ...@@ -710,11 +700,6 @@ void free_hpc_access (void)
void ibmphp_lock_operations (void) void ibmphp_lock_operations (void)
{ {
down (&semOperations); down (&semOperations);
stop_polling = POLL_NO;
to_debug = TRUE;
/* waiting for polling to actually stop */
down (&sem_poll);
} }
/*---------------------------------------------------------------------- /*----------------------------------------------------------------------
...@@ -723,8 +708,6 @@ void ibmphp_lock_operations (void) ...@@ -723,8 +708,6 @@ void ibmphp_lock_operations (void)
void ibmphp_unlock_operations (void) void ibmphp_unlock_operations (void)
{ {
debug ("%s - Entry\n", __FUNCTION__); debug ("%s - Entry\n", __FUNCTION__);
stop_polling = POLL_YES;
to_debug = FALSE;
up (&semOperations); up (&semOperations);
debug ("%s - Exit\n", __FUNCTION__); debug ("%s - Exit\n", __FUNCTION__);
} }
...@@ -732,34 +715,30 @@ void ibmphp_unlock_operations (void) ...@@ -732,34 +715,30 @@ void ibmphp_unlock_operations (void)
/*---------------------------------------------------------------------- /*----------------------------------------------------------------------
* Name: poll_hpc() * Name: poll_hpc()
*---------------------------------------------------------------------*/ *---------------------------------------------------------------------*/
#define POLL_LATCH_REGISTER 0
#define POLL_SLOTS 1
#define POLL_SLEEP 2
static void poll_hpc (void) static void poll_hpc (void)
{ {
struct slot myslot, *pslot = NULL; struct slot myslot;
struct slot *pslot = NULL;
struct list_head *pslotlist; struct list_head *pslotlist;
int rc; int rc;
int poll_state = POLL_LATCH_REGISTER;
u8 oldlatchlow = 0x00; u8 oldlatchlow = 0x00;
u8 curlatchlow = 0x00; u8 curlatchlow = 0x00;
int pollcnt = 0; int poll_count = 0;
u8 ctrl_count = 0x00; u8 ctrl_count = 0x00;
debug ("poll_hpc - Entry\n"); debug ("%s - Entry\n", __FUNCTION__);
while (!ibmphp_shutdown) { while (!ibmphp_shutdown) {
if (stop_polling) { /* try to get the lock to do some kind of harware access */
debug ("poll_hpc - stop_polling\n"); down (&semOperations);
up (&sem_poll);
/* to prevent deadlock */
if (ibmphp_shutdown)
break;
/* to make the thread sleep */
down (&semOperations);
up (&semOperations);
debug ("poll_hpc - after stop_polling sleep\n");
} else {
if (pollcnt) {
// only poll the latch register
oldlatchlow = curlatchlow;
switch (poll_state) {
case POLL_LATCH_REGISTER:
oldlatchlow = curlatchlow;
ctrl_count = 0x00; ctrl_count = 0x00;
list_for_each (pslotlist, &ibmphp_slot_head) { list_for_each (pslotlist, &ibmphp_slot_head) {
if (ctrl_count >= ibmphp_get_total_controllers()) if (ctrl_count >= ibmphp_get_total_controllers())
...@@ -773,14 +752,16 @@ static void poll_hpc (void) ...@@ -773,14 +752,16 @@ static void poll_hpc (void)
&curlatchlow); &curlatchlow);
if (oldlatchlow != curlatchlow) if (oldlatchlow != curlatchlow)
process_changeinlatch (oldlatchlow, process_changeinlatch (oldlatchlow,
curlatchlow, pslot->ctrl); curlatchlow,
pslot->ctrl);
} }
} }
} }
} else { poll_state = POLL_SLOTS;
break;
case POLL_SLOTS:
list_for_each (pslotlist, &ibmphp_slot_head) { list_for_each (pslotlist, &ibmphp_slot_head) {
if (stop_polling)
break;
pslot = list_entry (pslotlist, struct slot, ibm_slot_list); pslot = list_entry (pslotlist, struct slot, ibm_slot_list);
// make a copy of the old status // make a copy of the old status
memcpy ((void *) &myslot, (void *) pslot, memcpy ((void *) &myslot, (void *) pslot,
...@@ -791,31 +772,45 @@ static void poll_hpc (void) ...@@ -791,31 +772,45 @@ static void poll_hpc (void)
process_changeinstatus (pslot, &myslot); process_changeinstatus (pslot, &myslot);
} }
if (!stop_polling) { ctrl_count = 0x00;
ctrl_count = 0x00; list_for_each (pslotlist, &ibmphp_slot_head) {
list_for_each (pslotlist, &ibmphp_slot_head) { if (ctrl_count >= ibmphp_get_total_controllers())
if (ctrl_count >= ibmphp_get_total_controllers()) break;
break; pslot = list_entry (pslotlist, struct slot, ibm_slot_list);
pslot = if (pslot->ctrl->ctlr_relative_id == ctrl_count) {
list_entry (pslotlist, struct slot, ctrl_count++;
ibm_slot_list); if (READ_SLOT_LATCH (pslot->ctrl))
if (pslot->ctrl->ctlr_relative_id == ctrl_count) { rc = ibmphp_hpc_readslot (pslot,
ctrl_count++; READ_SLOTLATCHLOWREG,
if (READ_SLOT_LATCH (pslot->ctrl)) &curlatchlow);
rc = ibmphp_hpc_readslot (pslot,
READ_SLOTLATCHLOWREG,
&curlatchlow);
}
} }
} }
} ++poll_count;
INCREMENT_POLLCNT (pollcnt); if (poll_count >= POLL_LATCH_CNT) {
long_delay (POLL_INTERVAL_SEC * HZ); // snooze poll_count = 0;
poll_state = POLL_SLEEP;
}
break;
case POLL_SLEEP:
/* don't sleep with a lock on the hardware */
up (&semOperations);
long_delay (POLL_INTERVAL_SEC * HZ);
down (&semOperations);
poll_state = POLL_LATCH_REGISTER;
break;
} }
/* give up the harware semaphore */
up (&semOperations);
/* sleep for a short time just for good measure */
set_current_state (TASK_INTERRUPTIBLE);
schedule_timeout (HZ/10);
} }
up (&sem_poll);
up (&sem_exit); up (&sem_exit);
debug ("poll_hpc - Exit\n"); debug ("%s - Exit\n", __FUNCTION__);
} }
...@@ -1083,7 +1078,6 @@ void ibmphp_hpc_stop_poll_thread (void) ...@@ -1083,7 +1078,6 @@ void ibmphp_hpc_stop_poll_thread (void)
// cleanup // cleanup
free_hpc_access (); free_hpc_access ();
ibmphp_unlock_operations (); ibmphp_unlock_operations ();
up (&sem_poll);
up (&sem_exit); up (&sem_exit);
debug ("ibmphp_hpc_stop_poll_thread - Exit\n"); debug ("ibmphp_hpc_stop_poll_thread - Exit\n");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment