[prev in list] [next in list] [prev in thread] [next in thread] 

List:       lm-sensors
Subject:    [lm-sensors] [patch 0/2] hwmon: add a superio_locks coordinator
From:       jim.cromie () gmail ! com (Jim Cromie)
Date:       2006-01-27 5:47:10
Message-ID: 43D9B3DE.3030208 () gmail ! com
[Download RAW message or body]


this 2 part patch-set adds a superio_locks module to hwmon.
The module makes it simple for a driver using a Super-IO chip
to obtain a shared lock, and thereby coordinate with any other users
of that chip, without knowing who they are.

I went for a simple helper approach:

- provides an array of lock-structs (mod-param sets size),
    which are handed out upon request.

- does *not* search for super-IO ports,
    it expects drivers to know what ports are on the chips theyre 
written for,
    and to request them specifically.
    (forex: pc87360 must be at 2e or 4e)

- supports driver doing the 'search'
    driver makes 1 call to get_superio_gate_any() to:
       check several command-addresses, for several device ids
       save the return value, which is the gate* (locks are in gates)
    assumes data-addr is *always* command-addr + 1

- allocates a lock for 1st requester of a (sio-port,device-id) pair, if 
found
    2nd requester shares that lock.
    ie its a singleton

- doesnt / cannot protect against rogue driver
    (I wouldnt know how)

- drivers are expected to do their own locking, unlocking
   driver chooses efficiency vs long-lock-time

- superio lock structure (gate) is exposed in header
    allow user-drivers to get inside it
    sioaddr and devid are both useful to driver logic.

So, the API:

struct superio_gate {
       struct semaphore sema;  /* lock is here, for no-offset cast */
       int sioaddr;            /* this port's cmd-address */
       int devid;            /* device id found by 1st user */
};
 
struct superio_gate* get_sio_gate(int sioaddr, int devid_addr, int 
devid_val);
struct superio_gate* get_sio_gate_any(u8 sioaddr[], int devid_addr, u8 
devid_val[]);
void sio_lock(struct superio_gate*);
void sio_unlock(struct superio_gate*);
int  sio_inb(struct superio_gate*, int reg);
void sio_outb(struct superio_gate*, int reg, int val );
void sio_exit(struct superio_gate*);


users will do:
    struct superio_gate* gate = get_sio_gate_any( sioaddrs, devid_addr, 
wanted_ids );

and then either:
   superio_lock(gate);
   lock_mutex(&gate->mutex);

Once users have taken the lock, they can use (with some prep in latter 
examples)
   superio_inb(gate->sioaddr);
   superio_inb(mysioaddr);
   sio_inb(gate);
   inb(..)



2nd patch converts pc87360 to use it.   This patch has 2 versions;
    diff.uselocks.alpha-hilock
    diff.uselocks.alpha-lolock

the lolock version puts the lock-unlock pair around the low level routines;
pc87360_write_value, pc87360_read_value.  This is the way to do it
if your priority is short lock times.

the hilock version puts the locking in users of those routines,
which means less locking, but holds the lock much longer,
(thru a full scan of all sensor-attrs)






[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic