linux-old/drivers/s390/s390dyn.c
<<
>>
Prefs
   1/*
   2 *  arch/s390/kernel/s390dyn.c
   3 *   S/390 dynamic device attachment
   4 *
   5 *  S390 version
   6 *    Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
   7 *    Author(s): Ingo Adlung (adlung@de.ibm.com)
   8 */
   9
  10#include <linux/module.h>
  11#include <linux/init.h>
  12#include <linux/smp_lock.h>
  13
  14#include <asm/irq.h>
  15#include <asm/s390io.h>
  16#include <asm/s390dyn.h>
  17
  18static struct list_head devreg_anchor = LIST_HEAD_INIT(devreg_anchor);
  19static spinlock_t  dyn_lock           = SPIN_LOCK_UNLOCKED;
  20
  21static inline int s390_device_register_internal(devreg_t *drinfo)
  22{
  23        struct list_head *p;
  24
  25        list_for_each(p, &devreg_anchor) {
  26                devreg_t *pdevreg = list_entry(p, devreg_t, list);
  27                
  28                if (pdevreg == drinfo)
  29                        return -EINVAL;
  30                /*
  31                 * We don't allow multiple drivers to register
  32                 * for the same device number
  33                 */
  34                if (pdevreg->ci.devno == drinfo->ci.devno &&
  35                    (pdevreg->flag & DEVREG_TYPE_DEVNO) &&
  36                    (drinfo->flag & DEVREG_TYPE_DEVNO))
  37                        return -EBUSY;
  38
  39                if (drinfo->flag == (DEVREG_TYPE_DEVCHARS | 
  40                                     DEVREG_EXACT_MATCH) &&
  41                    !memcmp(&drinfo->ci.hc, &pdevreg->ci.hc,
  42                            sizeof(devreg_hc_t))) 
  43                        return -EBUSY;
  44        }
  45
  46        /*
  47         * no collision found, enqueue
  48         */
  49        list_add (&drinfo->list, &devreg_anchor);
  50        
  51        return 0;
  52}
  53
  54int s390_device_register( devreg_t *drinfo )
  55{
  56        unsigned long flags;
  57        int ret;
  58
  59        if (drinfo == NULL ||
  60            !(drinfo->flag & (DEVREG_TYPE_DEVNO | DEVREG_TYPE_DEVCHARS)))
  61                return -EINVAL;
  62
  63        spin_lock_irqsave (&dyn_lock, flags);   
  64        ret = s390_device_register_internal(drinfo);
  65        spin_unlock_irqrestore( &dyn_lock, flags );     
  66        
  67        return ret;
  68}
  69
  70static inline int s390_device_unregister_internal(devreg_t *dreg)
  71{
  72        struct list_head *p;
  73
  74        list_for_each(p, &devreg_anchor) {
  75                devreg_t *pdevreg = list_entry(p, devreg_t, list);
  76
  77                if (pdevreg == dreg) {
  78                        list_del (&dreg->list);
  79                        return 0;
  80                }
  81        }
  82        return -EINVAL;
  83}
  84
  85int s390_device_unregister(devreg_t *dreg)
  86{
  87        unsigned long  flags;
  88        int ret;
  89
  90        if (dreg == NULL)
  91                return -EINVAL;
  92
  93        spin_lock_irqsave(&dyn_lock, flags);    
  94        ret = s390_device_unregister_internal(dreg);
  95        spin_unlock_irqrestore(&dyn_lock, flags);       
  96        
  97        return ret;
  98}
  99
 100static inline devreg_t *s390_search_devreg_internal(ioinfo_t *ioinfo)
 101{
 102        struct list_head *p;
 103        
 104        list_for_each(p, &devreg_anchor) {
 105                devreg_t *pdevreg = list_entry(p, devreg_t, list);
 106                senseid_t *sid;
 107                int flag;
 108
 109                flag = pdevreg->flag;
 110                sid = &ioinfo->senseid;
 111                if (flag & DEVREG_TYPE_DEVNO) {
 112                        if (ioinfo->ui.flags.dval != 1 ||
 113                            ioinfo->devno != pdevreg->ci.devno)
 114                                continue;
 115                } else if (flag & DEVREG_TYPE_DEVCHARS) {
 116                        if ( (flag & DEVREG_MATCH_CU_TYPE) &&
 117                             pdevreg->ci.hc.ctype != sid->cu_type )
 118                                continue;
 119                        if ( (flag & DEVREG_MATCH_CU_MODEL) &&
 120                             pdevreg->ci.hc.cmode != sid->cu_model )
 121                                continue;
 122                        if ( (flag & DEVREG_MATCH_DEV_TYPE) &&
 123                             pdevreg->ci.hc.dtype != sid->dev_type )
 124                                continue;
 125                        if ( (flag & DEVREG_MATCH_DEV_MODEL) &&
 126                             pdevreg->ci.hc.dmode != sid->dev_model )
 127                                continue;
 128                } else {
 129                        continue;
 130                }
 131                
 132                return pdevreg;
 133        }
 134        return NULL;
 135}
 136
 137devreg_t * s390_search_devreg( ioinfo_t *ioinfo )
 138{
 139        unsigned long  flags;
 140        devreg_t *pdevreg;
 141
 142        if (ioinfo == NULL)
 143                return NULL;
 144
 145        spin_lock_irqsave(&dyn_lock, flags);    
 146        pdevreg = s390_search_devreg_internal(ioinfo);
 147        spin_unlock_irqrestore(&dyn_lock, flags);       
 148        
 149        return pdevreg;
 150}
 151
 152EXPORT_SYMBOL(s390_device_register);
 153EXPORT_SYMBOL(s390_device_unregister);
 154
 155
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.