File: /usr/src/linux/drivers/s390/misc/chandev.c

1     /*
2      *  drivers/s390/misc/chandev.c
3      *
4      *    Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
5      *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
6      * 
7      *  Generic channel device initialisation support. 
8      */
9     #define TRUE 1
10     #define FALSE 0
11     #define __KERNEL_SYSCALLS__
12     #include <linux/module.h>
13     #include <linux/config.h>
14     #include <linux/types.h>
15     #include <linux/ctype.h>
16     #include <asm/uaccess.h>
17     #include <linux/slab.h>
18     #include <asm/irq.h>
19     #include <linux/init.h>
20     #include <linux/unistd.h>
21     #include <asm/chandev.h>
22     #include <linux/proc_fs.h>
23     #include <linux/vmalloc.h>
24     #include <asm/s390dyn.h>
25     #include <asm/queue.h>
26     #include <linux/kmod.h>
27     #ifndef MIN
28     #define MIN(a,b) ((a<b)?a:b)
29     #endif
30     #ifndef MAX
31     #define MAX(a,b) ((a>b)?a:b)
32     #endif
33     
34     
35     
36     typedef struct chandev_model_info chandev_model_info;
37     struct chandev_model_info
38     {
39     	struct chandev_model_info *next;
40     	chandev_type chan_type;
41     	s32 cu_type;      /* control unit type  -1 = don't care */
42     	s16 cu_model;     /* control unit model -1 = don't care */
43     	s32 dev_type;     /* device type -1 = don't care */
44     	s16 dev_model;    /* device model -1 = don't care */
45     	u8  max_port_no;
46     	int auto_msck_recovery;
47     	u8  default_checksum_received_ip_pkts;
48     	u8  default_use_hw_stats; /* where available e.g. lcs */
49     	devreg_t drinfo;
50     };
51     
52     typedef struct chandev chandev;
53     struct chandev
54     {
55     	struct chandev *next;
56     	chandev_model_info *model_info;
57     	chandev_subchannel_info sch;
58     	int owned;
59     };
60     
61     typedef struct chandev_noauto_range chandev_noauto_range;
62     struct chandev_noauto_range
63     {
64     	struct chandev_noauto_range *next;
65     	u16     lo_devno;
66     	u16     hi_devno;
67     };
68     
69     typedef struct chandev_force chandev_force;
70     struct chandev_force
71     {
72     	struct chandev_force *next;
73     	chandev_type chan_type;
74     	s32     devif_num; /* -1 don't care, -2 we are forcing a range e.g. tr0 implies 0 */
75             u16     read_lo_devno;
76     	u16     write_hi_devno;
77     	u16     data_devno; /* only used by gigabit ethernet */
78     	s32     memory_usage_in_k;
79             s16     port_protocol_no; /* where available e.g. lcs,-1 don't care */
80     	u8      checksum_received_ip_pkts;
81     	u8      use_hw_stats; /* where available e.g. lcs */
82     	/* claw specific stuff */
83     	chandev_claw_info  claw;
84     };
85     
86     typedef struct chandev_probelist chandev_probelist;
87     struct chandev_probelist
88     {
89     	struct chandev_probelist            *next;
90     	chandev_probefunc                   probefunc;
91     	chandev_shutdownfunc                shutdownfunc;
92     	chandev_msck_notification_func      msck_notfunc;
93     	chandev_type                        chan_type;
94     	int                                 devices_found;
95     };
96     
97     
98     
99     #define default_msck_bits ((1<<(chandev_status_not_oper-1))|(1<<(chandev_status_no_path-1))|(1<<(chandev_status_revalidate-1))|(1<<(chandev_status_gone-1)))
100     
101     
102     static char *msck_status_strs[]=
103     {
104     	"good",
105     	"not_operational",
106     	"no_path",
107     	"revalidate",
108     	"device_gone"
109     };
110     
111     typedef struct chandev_msck_range chandev_msck_range;
112     struct chandev_msck_range
113     {
114     	struct chandev_msck_range *next;
115     	u16     lo_devno;
116     	u16     hi_devno;
117     	int      auto_msck_recovery;
118     };
119     
120     static chandev_msck_range *chandev_msck_range_head=NULL;
121     
122     typedef struct chandev_irqinfo chandev_irqinfo;
123     struct chandev_irqinfo
124     {
125     	chandev_irqinfo         *next;
126     	chandev_subchannel_info sch;
127     	chandev_msck_status     msck_status;
128     	void                    (*handler)(int, void *, struct pt_regs *);
129     	unsigned long           irqflags;
130     	void                    *dev_id;
131     	char                    devname[0];
132     };
133     
134     
135     chandev_irqinfo *chandev_irqinfo_head=NULL;
136     
137     typedef struct chandev_parms chandev_parms;
138     struct chandev_parms
139     {
140     	chandev_parms      *next;
141     	chandev_type       chan_type;
142     	u16                lo_devno;
143     	u16                hi_devno;
144     	char               parmstr[0];
145     };
146     
147     static chandev_type chandev_persistent=0; 
148     
149     chandev_parms *chandev_parms_head=NULL;
150     
151     
152     typedef struct chandev_activelist chandev_activelist;
153     struct chandev_activelist
154     {
155     	struct chandev_activelist        *next;
156     	chandev_irqinfo                  *read_irqinfo;
157     	chandev_irqinfo                  *write_irqinfo;
158     	chandev_irqinfo                  *data_irqinfo;
159     	chandev_probefunc                probefunc;
160     	chandev_shutdownfunc             shutdownfunc;
161     	chandev_msck_notification_func   msck_notfunc;
162     	chandev_unregfunc                unreg_dev;
163     	chandev_type                     chan_type;
164     	u8                               port_no;
165     	chandev_category                 category;
166     	s32                              memory_usage_in_k;
167     	void                             *dev_ptr;
168     	char                             devname[0];
169     };
170     
171     
172     
173     static chandev_model_info *chandev_models_head=NULL;
174     /* The only reason chandev_head is a queue is so that net devices */
175     /* will be by default named in the order of their irqs */
176     static qheader chandev_head={NULL,NULL};
177     static chandev_noauto_range *chandev_noauto_head=NULL;
178     static chandev_force *chandev_force_head=NULL;
179     static chandev_probelist *chandev_probelist_head=NULL;
180     static chandev_activelist *chandev_activelist_head=NULL;
181     #if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)
182     int chandev_use_devno_names=FALSE;
183     #endif
184     static int chandev_cautious_auto_detect=TRUE;
185     static atomic_t chandev_conf_read=ATOMIC_INIT(FALSE);
186     static atomic_t chandev_initialised=ATOMIC_INIT(FALSE);
187     
188     
189     static unsigned long chandev_last_machine_check;
190     
191     
192     static struct tq_struct chandev_msck_task_tq;
193     static atomic_t chandev_msck_thread_lock;
194     static atomic_t chandev_new_msck;
195     static unsigned long chandev_last_startmsck_list_update;
196     
197     
198     typedef enum
199     {
200     	chandev_start,
201     	chandev_first_tag=chandev_start,
202     	chandev_msck,
203     	chandev_num_notify_tags
204     } chandev_userland_notify_tag;
205     
206     static char *userland_notify_strs[]=
207     {
208     	"start",
209     	"machine_check"
210     };
211     
212     typedef struct chandev_userland_notify_list chandev_userland_notify_list;
213     struct chandev_userland_notify_list
214     {
215     	chandev_userland_notify_list    *next;
216     	chandev_userland_notify_tag      tag;
217     	chandev_msck_status              prev_status;
218     	chandev_msck_status              curr_status;
219     	char                      devname[0];
220     };
221     
222     
223     static chandev_userland_notify_list *chandev_userland_notify_head=NULL;
224     
225     
226     
227     
228     static void chandev_read_conf_if_necessary(void);
229     static void chandev_read_conf(void);
230     
231     #if LINUX_VERSION_CODE >=KERNEL_VERSION(2,3,0)
232     typedef struct net_device  net_device;
233     #else
234     typedef struct device  net_device;
235     
236     static inline void init_waitqueue_head(wait_queue_head_t *q)
237     {
238     	*q=NULL;
239     }
240     #endif
241     
242     #if LINUX_VERSION_CODE<KERNEL_VERSION(2,3,45)
243     static __inline__ void netif_stop_queue(net_device *dev)
244     {
245     	dev->tbusy=1;
246     }
247     
248     static __inline__ void netif_start_queue(net_device *dev)
249     {
250     	dev->tbusy=0;
251     }
252     #endif
253     
254     
255     
256     #define CHANDEV_INVALID_LOCK_OWNER            -1
257     static long                 chandev_lock_owner;
258     static int                  chandev_lock_cnt; 
259     static spinlock_t           chandev_spinlock;
260     #define CHANDEV_LOCK_DEBUG 0
261     #if CHANDEV_LOCK_DEBUG && !defined(CONFIG_ARCH_S390X)
262     #define CHANDEV_BACKTRACE_LOOPCNT 10
263     void                        *chandev_first_lock_addr[CHANDEV_BACKTRACE_LOOPCNT],
264     	                    *chandev_last_lock_addr[CHANDEV_BACKTRACE_LOOPCNT],
265     	                    *chandev_last_unlock_addr[CHANDEV_BACKTRACE_LOOPCNT];
266     #define CHANDEV_BACKTRACE(variable) \
267     memset((variable),0,sizeof(void *)*CHANDEV_BACKTRACE_LOOPCNT); \
268     (variable)[0]=__builtin_return_address(0); \
269     if(((long)variable[0])&0x80000000)         \
270     {                                          \
271     (variable)[1]=__builtin_return_address(1); \
272     if(((long)variable[1])&0x80000000)         \
273     {                                          \
274     (variable)[2]=__builtin_return_address(2); \
275     if(((long)variable[2])&0x80000000)         \
276     {                                          \
277     (variable)[3]=__builtin_return_address(3); \
278     if(((long)variable[3])&0x80000000)         \
279     {                                          \
280     (variable)[4]=__builtin_return_address(4); \
281     if(((long)variable[4])&0x80000000)         \
282     {                                          \
283     (variable)[5]=__builtin_return_address(5); \
284     if(((long)variable[5])&0x80000000)         \
285     {                                          \
286     (variable)[6]=__builtin_return_address(6); \
287     if(((long)variable[6])&0x80000000)         \
288     {                                          \
289     (variable)[7]=__builtin_return_address(7); \
290     if(((long)variable[7])&0x80000000)         \
291     {                                          \
292     (variable)[8]=__builtin_return_address(8); \
293     if(((long)variable[8])&0x80000000)         \
294     {                                          \
295     (variable)[9]=__builtin_return_address(9); \
296     } \
297     } \
298     } \
299     } \
300     } \
301     } \
302     } \
303     } \
304     }
305     #else
306     #define CHANDEV_BACKTRACE(variable)
307     #endif
308     
309     
310     
311     typedef struct chandev_not_oper_struct chandev_not_oper_struct;
312     
313     struct  chandev_not_oper_struct
314     {
315     	chandev_not_oper_struct *next;
316     	int irq;
317     	int status;
318     };
319     
320     
321     /* May as well try to keep machine checks in the order they happen so
322      * we use qheader for chandev_not_oper_head instead of list.
323      */
324     static qheader chandev_not_oper_head={NULL,NULL};
325     static spinlock_t           chandev_not_oper_spinlock;
326     
327     #define chandev_interrupt_check() \
328     if(in_interrupt())                \
329          printk(KERN_WARNING __FUNCTION__ " called under interrupt this shouldn't happen\n")
330     
331     
332     #define for_each(variable,head) \
333     for((variable)=(head);(variable)!=NULL;(variable)=(variable)->next)
334     
335     #define for_each_allow_delete(variable,nextmember,head) \
336     for((variable)=(head),(nextmember)=((head) ? (head)->next:NULL); \
337     (variable)!=NULL; (variable)=(nextmember),(nextmember)=((nextmember) ? (nextmember->next) : NULL))
338     
339     #define for_each_allow_delete2(variable,nextmember,head) \
340     for((variable)=(head);(variable)!=NULL;(variable)=(nextmember))
341     
342     
343     static void chandev_lock(void)
344     {
345     	eieio();
346     	chandev_interrupt_check();
347     	if(chandev_lock_owner!=(long)current)
348     	{
349     		while(!spin_trylock(&chandev_spinlock))
350     			schedule();
351     		chandev_lock_cnt=1;
352     		chandev_lock_owner=(long)current;
353     		CHANDEV_BACKTRACE(chandev_first_lock_addr)
354     	}
355     	else
356     	{
357     		chandev_lock_cnt++;
358     		CHANDEV_BACKTRACE(chandev_last_lock_addr)
359     	}
360     	if(chandev_lock_cnt<0||chandev_lock_cnt>100)
361     	{
362     		printk("odd lock_cnt %d lcs_chan_lock",chandev_lock_cnt);
363     		chandev_lock_cnt=1;
364     	}
365     }
366     
367     static int chandev_full_unlock(void)
368     {
369     	int ret_lock_cnt=chandev_lock_cnt;
370     	chandev_lock_cnt=0;
371     	chandev_lock_owner=CHANDEV_INVALID_LOCK_OWNER;
372     	spin_unlock(&chandev_spinlock);
373     	return(ret_lock_cnt);
374     }
375     
376     static void chandev_unlock(void)
377     {
378     	if(chandev_lock_owner!=(long)current)
379     		printk("chandev_unlock: current=%lx"
380     		      " chandev_lock_owner=%lx chandev_lock_cnt=%d\n",
381     		      (long)current,
382     		      chandev_lock_owner,
383     		      chandev_lock_cnt);
384     	CHANDEV_BACKTRACE(chandev_last_unlock_addr)
385     	if(--chandev_lock_cnt==0)
386     	{
387     		chandev_lock_owner=CHANDEV_INVALID_LOCK_OWNER;
388     		spin_unlock(&chandev_spinlock);
389     	}
390     	if(chandev_lock_cnt<0)
391     	{
392     		printk("odd lock_cnt=%d in chan_unlock",chandev_lock_cnt);
393     		chandev_full_unlock();
394     	}
395     
396     }
397     
398     
399     
400     void *chandev_alloc(size_t size)
401     {
402     	void *mem=kmalloc(size,GFP_ATOMIC);
403     	if(mem)
404     		memset(mem,0,size);
405     	return(mem);
406     }
407     
408     static void chandev_add_to_list(list **listhead,void *member)
409     {
410     	chandev_lock();
411     	add_to_list(listhead,member);
412     	chandev_unlock();
413     }
414     
415     static void chandev_queuemember(qheader *qhead,void *member)
416     {
417     	chandev_lock();
418     	enqueue_tail(qhead,(queue *)member);
419     	chandev_unlock();
420     }
421     
422     static int chandev_remove_from_list(list **listhead,list *member)
423     {
424     	int retval;
425     
426     	chandev_lock();
427     	retval=remove_from_list(listhead,member);
428     	chandev_unlock();
429     	return(retval);
430     }
431     
432     static int chandev_remove_from_queue(qheader *qhead,queue *member)
433     {
434     	int retval;
435     	
436     	chandev_lock();
437     	retval=remove_from_queue(qhead,member);
438     	chandev_unlock();
439     	return(retval);
440     }
441     
442     
443     
444     void chandev_free_listmember(list **listhead,list *member)
445     {
446     	chandev_lock();
447     	if(member)
448     	{
449     		if(chandev_remove_from_list(listhead,member))
450     			kfree(member);
451     		else
452     			printk(KERN_CRIT"chandev_free_listmember detected nonexistant"
453     			       "listmember listhead=%p member %p\n",listhead,member);
454     	}
455     	chandev_unlock();
456     }
457     
458     void chandev_free_queuemember(qheader *qhead,queue *member)
459     {
460     	chandev_lock();
461     	if(member)
462     	{
463     		if(chandev_remove_from_queue(qhead,member))
464     			kfree(member);
465     		else
466     			printk(KERN_CRIT"chandev_free_queuemember detected nonexistant"
467     			       "queuemember qhead=%p member %p\n",qhead,member);
468     	}
469     	chandev_unlock();
470     }
471     
472     
473     
474     void chandev_free_all_list(list **listhead)
475     {
476     	list *head;
477     
478     	chandev_lock();
479     	while((head=remove_listhead(listhead)))
480     		kfree(head);
481     	chandev_unlock();
482     }
483     
484     void chandev_free_all_queue(qheader *qhead)
485     {
486     	chandev_lock();
487     	while(qhead->head)
488     		chandev_free_queuemember(qhead,qhead->head);
489     	chandev_unlock();
490     }
491     
492     static void chandev_wait_for_root_fs(void)
493     {
494     	wait_queue_head_t      wait;
495     
496     	init_waitqueue_head(&wait);
497     	/* We need to wait till there is a root filesystem */
498     	while(init_task.fs->root==NULL)
499     	{
500     		sleep_on_timeout(&wait,HZ);
501     	}
502     }
503     
504     /* We are now hotplug compliant i.e. */
505     /* we typically get called in /sbin/hotplug chandev our parameters */
506     static int chandev_exec_start_script(void *unused)
507     {
508     	
509     	char **argv,*tempname;
510     	int retval=-ENOMEM;
511     	int argc,loopcnt;
512     	size_t allocsize;
513     	chandev_userland_notify_list *member;
514     	wait_queue_head_t      wait;
515     	int                    have_tag[chandev_num_notify_tags]={FALSE,};
516     	chandev_userland_notify_tag tagidx;
517     	static char * envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
518     	
519     	init_waitqueue_head(&wait);
520     	strcpy(current->comm,"chandev_script");
521     
522     	for(loopcnt=0;loopcnt<10&&(jiffies-chandev_last_startmsck_list_update)<HZ;loopcnt++)
523     	{
524     		sleep_on_timeout(&wait,HZ);
525     	}
526     	if(!chandev_userland_notify_head)
527     		return(0);
528     	chandev_lock();
529     	argc=2;
530     	for(tagidx=chandev_first_tag;tagidx<chandev_num_notify_tags;tagidx++)
531     	{
532     		for_each(member,chandev_userland_notify_head)
533     		{
534     			if(member->tag==tagidx)
535     			{
536     				switch(tagidx)
537     				{
538     				case chandev_start:
539     					argc++;
540     					break;
541     				case chandev_msck:
542     					argc+=3;
543     					break;
544     				default:
545     				}
546     				if(have_tag[tagidx]==FALSE)
547     					argc++;
548     				have_tag[tagidx]=TRUE;
549     
550     			}
551     		}
552     	}
553     	allocsize=(argc+1)*sizeof(char *);
554             /* Warning possible stack overflow */
555     	/* We can't kmalloc the parameters here as execve will */
556     	/* not return if successful */
557     	argv=alloca(allocsize);
558     	if(argv)
559     	{
560     		memset(argv,0,allocsize);
561     		argv[0]=hotplug_path;
562     		argv[1]="chandev";
563     		argc=2;
564     		for(tagidx=chandev_first_tag;tagidx<chandev_num_notify_tags;tagidx++)
565     		{
566     			if(have_tag[tagidx])
567     			{
568     				argv[argc++]=userland_notify_strs[tagidx];
569     				for_each(member,chandev_userland_notify_head)
570     				{
571     					if(member->tag==tagidx)
572     					{
573     						tempname=alloca(strlen(member->devname)+1);
574     						if(tempname)
575     						{
576     							strcpy(tempname,member->devname);
577     							argv[argc++]=tempname;
578     						}
579     						else
580     							goto Fail;
581     						if(member->tag==chandev_msck)
582     						{
583     							argv[argc++]=msck_status_strs[member->prev_status];
584     							argv[argc++]=msck_status_strs[member->curr_status];
585     						}
586     					}
587     				}
588     			}
589     		}
590     		chandev_free_all_list((list **)&chandev_userland_notify_head);
591     		chandev_unlock();
592     		chandev_wait_for_root_fs();
593     		/* We are basically execve'ing here there normally is no */
594     		/* return */
595     		retval=exec_usermodehelper(hotplug_path, argv, envp);
596     		goto Fail2;
597     	}
598      Fail:
599     	
600     	chandev_unlock();
601      Fail2:
602     	/* We don't really need to report /sbin/hotplug not existing */
603     	if(retval!=-ENOENT)
604     	   printk("chandev_exec_start_script failed retval=%d\n",retval);
605     	return(retval);
606     }
607     
608     
609     void *chandev_allocstr(const char *str,size_t offset)
610     {
611     	char *member;
612     
613     	if((member=chandev_alloc(offset+strlen(str)+1)))
614     	{
615     		strcpy(&member[offset],str);
616     	}
617     	return((void *)member);
618     }
619     
620     
621     static int chandev_add_to_userland_notify_list(chandev_userland_notify_tag tag,
622     char *devname, chandev_msck_status prev_status,chandev_msck_status curr_status)
623     {
624     	chandev_userland_notify_list *member,*nextmember;
625     	int pid;
626     	
627     	chandev_lock();
628     	/* remove operations still outstanding for this device */
629     	for_each_allow_delete(member,nextmember,chandev_userland_notify_head)
630     		if(strcmp(member->devname,devname)==0)
631     			chandev_free_listmember((list **)&chandev_userland_notify_head,(list *)member);
632     	
633     
634     	if((member=chandev_allocstr(devname,offsetof(chandev_userland_notify_list,devname))))
635     	{
636     		member->tag=tag;
637     		member->prev_status=prev_status;
638     		member->curr_status=curr_status;
639     		add_to_list((list **)&chandev_userland_notify_head,(list *)member);
640     		chandev_last_startmsck_list_update=jiffies;
641     		chandev_unlock();
642     		pid = kernel_thread(chandev_exec_start_script,NULL,SIGCHLD);
643     		if(pid<0)
644     		{
645     			printk("error making kernel thread for chandev_exec_start_script\n");
646     			return(pid);
647     		}
648     		else
649     			return(0);
650     
651     	}
652     	else
653     	{
654     		chandev_unlock();
655     		printk("chandev_add_to_startmscklist memory allocation failed devname=%s\n",devname);
656     		return(-ENOMEM);
657     	}
658     }
659     
660     
661     
662     
663     
664     int chandev_oper_func(int irq,devreg_t *dreg)
665     {
666     	chandev_last_machine_check=jiffies;
667     	if(atomic_dec_and_test(&chandev_msck_thread_lock))
668     	{
669     		schedule_task(&chandev_msck_task_tq);
670     	}
671     	atomic_set(&chandev_new_msck,TRUE);
672     	return(0);
673     }
674     
675     static void chandev_not_oper_handler(int irq,int status )
676     {
677     	chandev_not_oper_struct *new_not_oper;
678     
679     	chandev_last_machine_check=jiffies;
680     	if((new_not_oper=kmalloc(sizeof(chandev_not_oper_struct),GFP_ATOMIC)))
681     	{
682     		new_not_oper->irq=irq;
683     		new_not_oper->status=status;
684     		spin_lock(&chandev_not_oper_spinlock);
685     		enqueue_tail(&chandev_not_oper_head,(queue *)new_not_oper);
686     		spin_unlock(&chandev_not_oper_spinlock);
687     		if(atomic_dec_and_test(&chandev_msck_thread_lock))
688     		{
689     			schedule_task(&chandev_msck_task_tq);
690     		}
691     	}
692     	else
693     		printk("chandev_not_oper_handler failed to allocate memory & "
694     		       "lost a not operational interrupt %d %x",
695     		       irq,status);
696     }
697     
698     chandev_irqinfo *chandev_get_irqinfo_by_irq(int irq)
699     {
700     	chandev_irqinfo *curr_irqinfo;
701     	for_each(curr_irqinfo,chandev_irqinfo_head)
702     		if(irq==curr_irqinfo->sch.irq)
703     			return(curr_irqinfo);
704     	return(NULL);
705     }
706     
707     chandev *chandev_get_by_irq(int irq)
708     {
709     	chandev *curr_chandev;
710     
711     	for_each(curr_chandev,(chandev *)chandev_head.head)
712     		if(curr_chandev->sch.irq==irq)
713     		{
714     			return(curr_chandev);
715     		}
716     	return(NULL);
717     }
718     
719     chandev_activelist *chandev_get_activelist_by_irq(int irq)
720     {
721     	chandev_activelist *curr_device;
722     
723     	for_each(curr_device,chandev_activelist_head)
724     	{
725     			if(curr_device->read_irqinfo->sch.irq==irq||
726     			   curr_device->write_irqinfo->sch.irq==irq||
727     			   (curr_device->data_irqinfo&&curr_device->data_irqinfo->sch.irq==irq))
728     				return(curr_device);
729     	}
730     	return(NULL);
731     }
732     
733     
734     void chandev_remove_irqinfo_by_irq(unsigned int irq)
735     {
736     	chandev_irqinfo *remove_irqinfo;
737     	chandev_activelist *curr_device;
738     
739     	chandev_lock();
740     	/* remove any orphan irqinfo left lying around. */
741             if((remove_irqinfo=chandev_get_irqinfo_by_irq(irq)))
742     	{
743     		for_each(curr_device,chandev_activelist_head)
744     		{
745     			if(curr_device->read_irqinfo==remove_irqinfo)
746     			{
747     				curr_device->read_irqinfo=NULL;
748     				break;
749     			}
750     			if(curr_device->write_irqinfo==remove_irqinfo)
751     			{
752     				curr_device->write_irqinfo=NULL;
753     				break;
754     			}
755     			if(curr_device->data_irqinfo&&curr_device->data_irqinfo==remove_irqinfo)
756     			{
757     				curr_device->data_irqinfo=NULL;
758     				break;
759     			}
760     		}
761     		chandev_free_listmember((list **)&chandev_irqinfo_head,
762     					 (list *)remove_irqinfo);
763     	}
764     	chandev_unlock();
765     	
766     }
767     
768     int chandev_add_schib_info(int irq,chandev_subchannel_info *sch)
769     {
770     	schib_t *new_schib;
771     	
772     	if((new_schib=s390_get_schib(irq)))
773     	{
774     		sch->pim=new_schib->pmcw.pim;
775     		memcpy(&sch->chpid,&new_schib->pmcw.chpid,sizeof(sch->chpid));
776     		return(0);
777     	}
778     	return(-ENODEV);
779     }
780     
781     int chandev_request_irq(unsigned int   irq,
782                           void           (*handler)(int, void *, struct pt_regs *),
783                           unsigned long  irqflags,
784                           const char    *devname,
785                           void          *dev_id)
786     {
787     	chandev_irqinfo *new_irqinfo;
788     	chandev_activelist *curr_device;
789     	s390_dev_info_t         devinfo;
790     	int          retval;
791     	
792     
793     	chandev_lock();
794     	if((curr_device=chandev_get_activelist_by_irq(irq)))
795     	{
796     		printk("chandev_request_irq failed devname=%s irq=%d "
797     		       "it already belongs to %s shutdown this device first.\n",
798     		       devname,irq,curr_device->devname);
799     		chandev_unlock();
800     		return(-EPERM);
801     	}
802     	/* remove any orphan irqinfo left lying around. */
803     	chandev_remove_irqinfo_by_irq(irq);
804     	chandev_unlock();
805     	if((new_irqinfo=chandev_allocstr(devname,offsetof(chandev_irqinfo,devname))))
806     	{
807     		
808     		if((retval=get_dev_info_by_irq(irq,&devinfo))||
809     		   (retval=s390_request_irq_special(irq,handler,
810     						chandev_not_oper_handler,
811     						irqflags,devname,dev_id)))
812     			kfree(new_irqinfo);
813     		else
814     		{
815     			new_irqinfo->msck_status=chandev_status_good;
816     			new_irqinfo->sch.devno=devinfo.devno;
817     			new_irqinfo->sch.irq=irq;
818     			new_irqinfo->sch.cu_type=devinfo.sid_data.cu_type; /* control unit type */
819     			new_irqinfo->sch.cu_model=devinfo.sid_data.cu_model; /* control unit model */
820     			new_irqinfo->sch.dev_type=devinfo.sid_data.dev_type; /* device type */
821     			new_irqinfo->sch.dev_model=devinfo.sid_data.dev_model; /* device model */
822     			chandev_add_schib_info(irq,&new_irqinfo->sch);
823     			new_irqinfo->handler=handler;
824     			new_irqinfo->dev_id=dev_id;
825     			chandev_add_to_list((list **)&chandev_irqinfo_head,new_irqinfo);
826     		}
827     	}
828     	else
829     	{
830     		printk("chandev_request_irq memory allocation failed devname=%s irq=%d\n",devname,irq);
831     		retval=-ENOMEM;
832     	}
833     	return(retval);
834     }
835     
836     /* This should be safe to call even multiple times. */
837     void chandev_free_irq(unsigned int irq, void *dev_id)
838     {
839     	s390_dev_info_t devinfo;
840     	int err;
841     	
842     	/* remove any orphan irqinfo left lying around. */
843     	chandev_remove_irqinfo_by_irq(irq);
844     	if((err=get_dev_info_by_irq(irq,&devinfo)))
845     	{
846     		printk("chandev_free_irq get_dev_info_by_irq reported err=%X on irq %d\n"
847     		       "should not happen\n",err,irq);
848     		return;
849     	 }
850     	if(devinfo.status&DEVSTAT_DEVICE_OWNED)
851     	   free_irq(irq,dev_id);
852     }
853     
854     /* This should be safe even if chandev_free_irq is already called by the device */
855     void chandev_free_irq_by_irqinfo(chandev_irqinfo *irqinfo)
856     {
857     	if(irqinfo)
858     		chandev_free_irq(irqinfo->sch.irq,irqinfo->dev_id);
859     }
860     
861     
862     
863     void chandev_sprint_type_model(char *buff,s32 type,s16 model)
864     {
865     	if(type==-1)
866     		strcpy(buff,"    *    ");
867     	else
868     		sprintf(buff," 0x%04x  ",(int)type);
869     	buff+=strlen(buff);
870     	if(model==-1)
871     		strcpy(buff,"    *   ");
872     	else
873     		sprintf(buff," 0x%02x  ",(int)model);
874     }
875     
876     void chandev_sprint_devinfo(char *buff,s32 cu_type,s16 cu_model,s32 dev_type,s16 dev_model)
877     {
878     	chandev_sprint_type_model(buff,cu_type,cu_model);
879     	chandev_sprint_type_model(&buff[strlen(buff)],dev_type,dev_model);
880     }
881     
882     void chandev_remove_parms(chandev_type chan_type,int exact_match,int lo_devno)
883     {
884     	chandev_parms      *curr_parms,*next_parms;
885     
886     	chandev_lock();
887     	for_each_allow_delete(curr_parms,next_parms,chandev_parms_head)
888     	{
889     		if(((chan_type&(curr_parms->chan_type)&&!exact_match)||
890     		   (chan_type==(curr_parms->chan_type)&&exact_match))&&
891     		   (lo_devno==-1||lo_devno==curr_parms->lo_devno))
892     			chandev_free_listmember((list **)&chandev_parms_head,(list *)curr_parms);
893     	}
894     	chandev_unlock();
895     }
896     
897     
898     void chandev_add_parms(chandev_type chan_type,u16 lo_devno,u16 hi_devno,char *parmstr)
899     {
900     	chandev_parms      *parms;
901     
902     	if(lo_devno>hi_devno)
903     	{
904     		printk("chandev_add_parms detected bad device range lo_devno=0x%04x  hi_devno=0x%04x\n,",
905     		       (int)lo_devno,(int)hi_devno);
906     		return;
907     	}
908     	chandev_lock();
909     	for_each(parms,chandev_parms_head)
910     	{
911     		if(chan_type&(parms->chan_type))
912     		{
913     			u16 lomax=MAX(parms->lo_devno,lo_devno),
914     				himin=MIN(parms->hi_devno,lo_devno);
915     			if(lomax<=himin)
916     			{
917     				chandev_unlock();
918     				printk("chandev_add_parms detected overlapping "
919     				       "parameter definitions for chan_type=0x%02x"
920     				       " lo_devno=0x%04x  hi_devno=0x%04x\n,"
921     				       " do a del_parms.",chan_type,(int)lo_devno,(int)hi_devno);
922     				return;
923     			}
924     		}
925     	}
926     	chandev_unlock();
927     	if((parms=chandev_allocstr(parmstr,offsetof(chandev_parms,parmstr))))
928     	{
929     		parms->chan_type=chan_type;
930     		parms->lo_devno=lo_devno;
931     		parms->hi_devno=hi_devno;
932     		chandev_add_to_list((list **)&chandev_parms_head,(void *)parms);
933     	}
934     	else
935     		printk("chandev_add_parms memory request failed\n");
936     }
937     
938     
939     void chandev_add_model(chandev_type chan_type,s32 cu_type,s16 cu_model,
940     		       s32 dev_type,s16 dev_model,u8 max_port_no,int auto_msck_recovery,
941     		       u8 default_checksum_received_ip_pkts,u8 default_use_hw_stats)
942     {
943     	chandev_model_info *newmodel;
944     	int                err;
945     	char buff[40];
946     
947     	if((newmodel=chandev_alloc(sizeof(chandev_model_info))))
948     	{
949     		devreg_t *drinfo=&newmodel->drinfo;
950     		newmodel->chan_type=chan_type;
951     		newmodel->cu_type=cu_type;
952     		newmodel->cu_model=cu_model;
953     		newmodel->dev_type=dev_type;
954     		newmodel->dev_model=dev_model;
955     		newmodel->max_port_no=max_port_no;
956     		newmodel->auto_msck_recovery=auto_msck_recovery;
957     		newmodel->default_checksum_received_ip_pkts=default_checksum_received_ip_pkts;
958     		newmodel->default_use_hw_stats=default_use_hw_stats; /* where available e.g. lcs */
959     		if(cu_type==-1&&dev_type==-1)
960     		{
961     			chandev_sprint_devinfo(buff,newmodel->cu_type,newmodel->cu_model,
962     					       newmodel->dev_type,newmodel->dev_model);
963     			printk(KERN_INFO"can't call s390_device_register for this device chan_type/chan_model/dev_type/dev_model %s\n",buff);
964     			kfree(newmodel);
965     			return;
966     		}
967     		drinfo->flag=DEVREG_TYPE_DEVCHARS;
968     		if(cu_type!=-1)
969     			drinfo->flag|=DEVREG_MATCH_CU_TYPE;
970     		if(cu_model!=-1)
971     			drinfo->flag|=DEVREG_MATCH_CU_MODEL;
972     		if(dev_type!=-1)
973     			drinfo->flag|=DEVREG_MATCH_DEV_TYPE;
974     		if(dev_model!=-1)
975     			drinfo->flag|=DEVREG_MATCH_DEV_MODEL;
976     		drinfo->ci.hc.ctype=cu_type;
977     		drinfo->ci.hc.cmode=cu_model;
978     		drinfo->ci.hc.dtype=dev_type;
979     		drinfo->ci.hc.dmode=dev_model;
980     		drinfo->oper_func=chandev_oper_func;
981     		if((err=s390_device_register(&newmodel->drinfo)))
982     		{
983     			chandev_sprint_devinfo(buff,newmodel->cu_type,newmodel->cu_model,
984     					       newmodel->dev_type,newmodel->dev_model);
985     			printk("s390_device_register failed in chandev_add_model"
986     			       " this is nothing to worry about chan_type/chan_model/dev_type/dev_model %s\n",buff);
987     			drinfo->oper_func=NULL;
988     		}
989     		chandev_add_to_list((list **)&chandev_models_head,newmodel);
990     	}
991     }
992     
993     
994     void chandev_remove(chandev *member)
995     {
996     	chandev_free_queuemember(&chandev_head,(queue *)member);
997     }
998     
999     
1000     void chandev_remove_all(void)
1001     {
1002     	chandev_free_all_queue(&chandev_head);
1003     }
1004     
1005     void chandev_remove_model(chandev_model_info *model)
1006     {
1007     	chandev *curr_chandev,*next_chandev;
1008     
1009     	chandev_lock();
1010     	for_each_allow_delete(curr_chandev,next_chandev,(chandev *)chandev_head.head)
1011     		if(curr_chandev->model_info==model)
1012     			chandev_remove(curr_chandev);
1013     	if(model->drinfo.oper_func)
1014     		s390_device_unregister(&model->drinfo);
1015     	chandev_free_listmember((list **)&chandev_models_head,(list *)model);
1016     	chandev_unlock();
1017     }
1018     
1019     void chandev_remove_all_models(void)
1020     {
1021     	chandev_lock();
1022     	while(chandev_models_head)
1023     		chandev_remove_model(chandev_models_head);
1024     	chandev_unlock();
1025     }
1026     
1027     void chandev_del_model(s32 cu_type,s16 cu_model,s32 dev_type,s16 dev_model)
1028     {
1029     	chandev_model_info *curr_model,*next_model;
1030     	
1031     	chandev_lock();
1032     	for_each_allow_delete(curr_model,next_model,chandev_models_head)
1033     		if((curr_model->cu_type==cu_type||cu_type==-1)&&
1034     		   (curr_model->cu_model==cu_model||cu_model==-1)&&
1035     		   (curr_model->dev_type==dev_type||dev_type==-1)&&
1036     		   (curr_model->dev_model==dev_model||dev_model==-1))
1037     			chandev_remove_model(curr_model);			
1038     	chandev_unlock();
1039     }
1040     
1041     static void chandev_init_default_models(void)
1042     {
1043     	/* Usually P390/Planter 3172 emulation assume maximum 16 to be safe. */
1044     	chandev_add_model(chandev_type_lcs,0x3088,0x1,-1,-1,15,default_msck_bits,FALSE,FALSE);	
1045     
1046     	/* 3172/2216 Paralell the 2216 allows 16 ports per card the */
1047     	/* the original 3172 only allows 4 we will assume the max of 16 */
1048     	chandev_add_model(chandev_type_lcs|chandev_type_ctc,0x3088,0x8,-1,-1,15,default_msck_bits,FALSE,FALSE);
1049     
1050     	/* 3172/2216 Escon serial the 2216 allows 16 ports per card the */
1051     	/* the original 3172 only allows 4 we will assume the max of 16 */
1052     	chandev_add_model(chandev_type_lcs|chandev_type_escon,0x3088,0x1F,-1,-1,15,default_msck_bits,FALSE,FALSE);
1053     
1054     	/* Only 2 ports allowed on OSA2 cards model 0x60 */
1055     	chandev_add_model(chandev_type_lcs,0x3088,0x60,-1,-1,1,default_msck_bits,FALSE,FALSE);
1056     	/* qeth gigabit ethernet */
1057     	chandev_add_model(chandev_type_qeth,0x1731,0x1,0x1732,0x1,0,default_msck_bits,FALSE,FALSE);
1058     	chandev_add_model(chandev_type_qeth,0x1731,0x5,0x1732,0x5,0,default_msck_bits,FALSE,FALSE);
1059     	/* Osa-D we currently aren't too emotionally involved with this */
1060     	chandev_add_model(chandev_type_osad,0x3088,0x62,-1,-1,0,default_msck_bits,FALSE,FALSE);
1061     	/* claw */
1062     	chandev_add_model(chandev_type_claw,0x3088,0x61,-1,-1,0,default_msck_bits,FALSE,FALSE);
1063     }
1064     
1065     
1066     void chandev_del_noauto(u16 devno)
1067     {
1068     	chandev_noauto_range *curr_noauto,*next_noauto;
1069     	chandev_lock();
1070     	for_each_allow_delete(curr_noauto,next_noauto,chandev_noauto_head)
1071     		if(curr_noauto->lo_devno<=devno&&curr_noauto->hi_devno>=devno)
1072     			chandev_free_listmember((list **)&chandev_noauto_head,(list *)curr_noauto); 
1073     	chandev_unlock();
1074     }
1075     
1076     void chandev_del_msck(u16 devno)
1077     {
1078     	chandev_msck_range *curr_msck_range,*next_msck_range;
1079     	chandev_lock();
1080     	for_each_allow_delete(curr_msck_range,next_msck_range,chandev_msck_range_head)
1081     		if(curr_msck_range->lo_devno<=devno&&curr_msck_range->hi_devno>=devno)
1082     			chandev_free_listmember((list **)&chandev_msck_range_head,(list *)curr_msck_range); 
1083     	chandev_unlock();
1084     }
1085     
1086     
1087     void chandev_add(s390_dev_info_t  *newdevinfo,chandev_model_info *newmodelinfo)
1088     {
1089     	chandev *new_chandev=NULL;
1090     
1091     	if((new_chandev=chandev_alloc(sizeof(chandev))))
1092     	{
1093     		new_chandev->model_info=newmodelinfo;
1094     		new_chandev->sch.devno=newdevinfo->devno;
1095     		new_chandev->sch.irq=newdevinfo->irq;
1096     		new_chandev->sch.cu_type=newdevinfo->sid_data.cu_type; /* control unit type */
1097     		new_chandev->sch.cu_model=newdevinfo->sid_data.cu_model; /* control unit model */
1098     		new_chandev->sch.dev_type=newdevinfo->sid_data.dev_type; /* device type */
1099     		new_chandev->sch.dev_model=newdevinfo->sid_data.dev_model; /* device model */
1100     		chandev_add_schib_info(newdevinfo->irq,&new_chandev->sch);
1101     		new_chandev->owned=(newdevinfo->status&DEVSTAT_DEVICE_OWNED ? TRUE:FALSE);
1102     		chandev_queuemember(&chandev_head,new_chandev);
1103     	}
1104     }
1105     
1106     void chandev_unregister_probe(chandev_probefunc probefunc)
1107     {
1108     	chandev_probelist *curr_probe,*next_probe;
1109     
1110     	chandev_lock();
1111     	for_each_allow_delete(curr_probe,next_probe,chandev_probelist_head)
1112     		if(curr_probe->probefunc==probefunc)
1113     			chandev_free_listmember((list **)&chandev_probelist_head,
1114     						(list *)curr_probe);
1115     	chandev_unlock();
1116     }
1117     
1118     void chandev_unregister_probe_by_chan_type(chandev_type chan_type)
1119     {
1120     	chandev_probelist *curr_probe,*next_probe;
1121     
1122     	chandev_lock();
1123     	for_each_allow_delete(curr_probe,next_probe,chandev_probelist_head)
1124     		if(curr_probe->chan_type==chan_type)
1125     			chandev_free_listmember((list **)&chandev_probelist_head,
1126     						(list *)curr_probe);
1127     	chandev_unlock();
1128     }
1129     
1130     
1131     
1132     void chandev_reset(void)
1133     {
1134     	chandev_lock();
1135     	chandev_remove_all_models();
1136     	chandev_free_all_list((list **)&chandev_noauto_head);
1137     	chandev_free_all_list((list **)&chandev_msck_range_head);
1138     	chandev_free_all_list((list **)&chandev_force_head);
1139     	chandev_remove_parms(-1,FALSE,-1);
1140     #if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)
1141     	chandev_use_devno_names=FALSE;
1142     #endif
1143     	chandev_unlock();
1144     }
1145     
1146     
1147     int chandev_is_chandev(int irq,s390_dev_info_t *devinfo,chandev_force **forceinfo,chandev_model_info **ret_model)
1148     {
1149     	chandev_force *curr_force;
1150     	chandev_model_info *curr_model=NULL;
1151     	int err;
1152     	int retval=FALSE;
1153     
1154     	if(forceinfo)
1155     		*forceinfo=NULL;
1156     	if(ret_model)
1157     		*ret_model=NULL;
1158     	if((err=get_dev_info_by_irq(irq,devinfo)))
1159     	{
1160     		printk("chandev_is_chandev get_dev_info_by_irq reported err=%X on irq %d\n"
1161     		       "should not happen\n",err,irq);
1162     			return FALSE;
1163     	}
1164     	chandev_lock();
1165     	
1166     	for_each(curr_model,chandev_models_head)
1167     	{
1168     		if(((curr_model->cu_type==devinfo->sid_data.cu_type)||(curr_model->cu_type==-1))&&
1169     		   ((curr_model->cu_model==devinfo->sid_data.cu_model)||(curr_model->cu_model==-1))&&
1170     		   ((curr_model->dev_type==devinfo->sid_data.dev_type)||(curr_model->dev_type==-1))&&
1171     		   ((curr_model->dev_model==devinfo->sid_data.dev_model)||(curr_model->dev_model==-1)))
1172     		{
1173     			retval=TRUE;
1174     			if(ret_model)
1175     				*ret_model=curr_model;
1176     			break;
1177     		}
1178     	}
1179     	for_each(curr_force,chandev_force_head)
1180     	{
1181     		if(((curr_force->read_lo_devno==devinfo->devno)&&
1182     		   (curr_force->write_hi_devno==devinfo->devno)&&
1183     		    (curr_force->devif_num!=-2))||
1184     		   ((curr_force->read_lo_devno>=devinfo->devno)&&
1185     		    (curr_force->write_hi_devno<=devinfo->devno)&&
1186     		    (curr_force->devif_num==-2)))
1187     		{
1188     			if(forceinfo)
1189     				*forceinfo=curr_force;
1190     			break;
1191     		}
1192     	}
1193     	chandev_unlock();
1194     	return(retval);
1195     }
1196     
1197     void chandev_collect_devices(void)
1198     {
1199     	int curr_irq,loopcnt=0;
1200     	s390_dev_info_t   curr_devinfo;
1201     	chandev_model_info *curr_model;
1202          
1203     
1204     	for(curr_irq=get_irq_first();curr_irq>=0; curr_irq=get_irq_next(curr_irq))
1205     	{
1206     		/* check read chandev
1207     		 * we had to do the cu_model check also because ctc devices
1208     		 * have the same cutype & after asking some people
1209     		 * the model numbers are given out pseudo randomly so
1210     		 * we can't just take a range of them also the dev_type & models are 0
1211     		 */
1212     		loopcnt++;
1213     		if(loopcnt>0x10000)
1214     		{
1215     			printk(KERN_ERR"chandev_collect_devices detected infinite loop bug in get_irq_next\n");
1216     			break;
1217     		}
1218     		chandev_lock();
1219     		if(chandev_is_chandev(curr_irq,&curr_devinfo,NULL,&curr_model))
1220     			chandev_add(&curr_devinfo,curr_model);
1221     		chandev_unlock();
1222     	}
1223     }
1224     
1225     int chandev_add_force(chandev_type chan_type,s32 devif_num,u16 read_lo_devno,
1226     u16 write_hi_devno,u16 data_devno,s32 memory_usage_in_k,s16 port_protocol_no,u8 checksum_received_ip_pkts,
1227     u8 use_hw_stats,char *host_name,char *adapter_name,char *api_type)
1228     {
1229     	chandev_force *new_chandev_force;
1230     	
1231     	if(devif_num==-2&&read_lo_devno>write_hi_devno)
1232     	{
1233     		printk("chandev_add_force detected bad device range lo_devno=0x%04x  hi_devno=0x%04x\n,",
1234     		       (int)read_lo_devno,(int)write_hi_devno);
1235     		return(-1);
1236     	}
1237     	if(memory_usage_in_k<0)
1238     	{
1239     		printk("chandev_add_force memory_usage_in_k is bad\n");
1240     		return(-1);
1241     	}
1242     	if(chan_type==chandev_type_claw)
1243     	{
1244     		int host_name_len=strlen(host_name),
1245     			adapter_name_len=strlen(adapter_name),
1246     			api_type_len=strlen(api_type);
1247     		if(host_name_len>=CLAW_NAMELEN||host_name_len==0||
1248     		   adapter_name_len>=CLAW_NAMELEN||adapter_name_len==0||
1249     		   api_type_len>=CLAW_NAMELEN||api_type_len==0)
1250     			return(-1);
1251     	}
1252     	if((new_chandev_force=chandev_alloc(sizeof(chandev_force))))
1253     	{
1254     		new_chandev_force->chan_type=chan_type;
1255     		new_chandev_force->devif_num=devif_num;
1256     		new_chandev_force->read_lo_devno=read_lo_devno;
1257     		new_chandev_force->write_hi_devno=write_hi_devno;
1258     		new_chandev_force->data_devno=data_devno;
1259     		new_chandev_force->memory_usage_in_k=memory_usage_in_k;
1260     		new_chandev_force->port_protocol_no=port_protocol_no;
1261     		new_chandev_force->checksum_received_ip_pkts=checksum_received_ip_pkts;
1262     		new_chandev_force->use_hw_stats=use_hw_stats;
1263     		
1264     		if(chan_type==chandev_type_claw)
1265     		{
1266     			strcpy(new_chandev_force->claw.host_name,host_name);
1267     			strcpy(new_chandev_force->claw.adapter_name,adapter_name);
1268     			strcpy(new_chandev_force->claw.api_type,api_type);
1269     		}
1270     		chandev_add_to_list((list **)&chandev_force_head,new_chandev_force);
1271     	}
1272     	return(0);
1273     }
1274     
1275     void chandev_del_force(int read_lo_devno)
1276     {
1277     	chandev_force *curr_force,*next_force;
1278     	
1279     	chandev_lock();
1280     	for_each_allow_delete(curr_force,next_force,chandev_force_head)
1281     	{
1282     		if(curr_force->read_lo_devno==read_lo_devno||read_lo_devno==-1)
1283     			chandev_free_listmember((list **)&chandev_force_head,
1284     						(list *)curr_force);
1285     	}
1286     	chandev_unlock();
1287     }
1288     
1289     
1290     void chandev_shutdown(chandev_activelist *curr_device)
1291     {
1292     	int err=0;
1293     	chandev_lock();
1294     
1295     
1296     	/* unregister_netdev calls the dev->close so we shouldn't do this */
1297     	/* this otherwise we crash */
1298     	if(curr_device->unreg_dev)
1299     	{
1300     		curr_device->unreg_dev(curr_device->dev_ptr);
1301     		curr_device->unreg_dev=NULL;
1302     	}
1303     	if(curr_device->shutdownfunc)
1304     	{
1305     		err=curr_device->shutdownfunc(curr_device->dev_ptr);
1306     	}
1307     	if(err)
1308     		printk("chandev_shutdown unable to fully shutdown & unload %s err=%d\n"
1309     		       "probably some upper layer still requires the device to exist\n",
1310     		       curr_device->devname,err);
1311     	else
1312     	{
1313     		
1314     		chandev_free_irq_by_irqinfo(curr_device->read_irqinfo);
1315     		chandev_free_irq_by_irqinfo(curr_device->write_irqinfo);
1316     		if(curr_device->data_irqinfo)
1317     			chandev_free_irq_by_irqinfo(curr_device->data_irqinfo);
1318     		chandev_free_listmember((list **)&chandev_activelist_head,
1319     				(list *)curr_device);
1320     	}
1321     	chandev_unlock();
1322     }
1323     
1324     void chandev_shutdown_all(void)
1325     {
1326     	while(chandev_activelist_head)
1327     		chandev_shutdown(chandev_activelist_head);
1328     }
1329     void chandev_shutdown_by_name(char *devname)
1330     {
1331     	chandev_activelist *curr_device;
1332     
1333     	chandev_lock();
1334     	for_each(curr_device,chandev_activelist_head)
1335     		if(strcmp(devname,curr_device->devname)==0)
1336     		{
1337     			chandev_shutdown(curr_device);
1338     			break;
1339     		}
1340     	chandev_unlock();
1341     }
1342     
1343     static chandev_activelist *chandev_active(u16 devno)
1344     {
1345     	chandev_activelist *curr_device;
1346     
1347     	for_each(curr_device,chandev_activelist_head)
1348     		if(curr_device->read_irqinfo->sch.devno==devno||
1349     		   curr_device->write_irqinfo->sch.devno==devno||
1350     		   (curr_device->data_irqinfo&&curr_device->data_irqinfo->sch.devno==devno))
1351     		{
1352     			return(curr_device);
1353     		}
1354     	return(NULL);
1355     }
1356     
1357     void chandev_shutdown_by_devno(u16 devno)
1358     {
1359     	chandev_activelist *curr_device;
1360     
1361     	chandev_lock();
1362     	curr_device=chandev_active(devno);
1363     	if(curr_device)
1364     		chandev_shutdown(curr_device);
1365     	chandev_unlock();
1366     }
1367     
1368     
1369     int chandev_pack_args(char *str)
1370     {
1371     	char *newstr=str,*next;
1372     	int strcnt=1;
1373     
1374     	while(*str)
1375     	{
1376     		next=str+1;
1377     		/*remove dead spaces */
1378     		if(isspace(*str)&&isspace(*next))
1379     		{
1380     			str++;
1381     			continue;
1382     		}
1383     		if(isspace(*str))
1384     		{
1385     			*str=',';
1386     			goto pack_dn;
1387     		}
1388     		if(((*str)==';')&&(*next))
1389     		{
1390     			strcnt++;
1391     			*str=0;
1392     		}
1393     	pack_dn:
1394     		*newstr++=*str++;
1395     		
1396     	}
1397     	*newstr=0;
1398     	return(strcnt);
1399     }
1400     
1401     typedef enum
1402     { 
1403     	isnull=0,
1404     	isstr=1,
1405     	isnum=2,
1406     	iscomma=4,
1407     } chandev_strval;
1408     
1409     chandev_strval chandev_strcmp(char *teststr,char **str,long *endlong)
1410     {
1411     	char *cur;
1412     	chandev_strval  retval=isnull;
1413     
1414     	int len=strlen(teststr);
1415     	if(strncmp(teststr,*str,len)==0)
1416     	{
1417     		*str+=len;
1418     		retval=isstr;
1419     		cur=*str;
1420     		*endlong=simple_strtol(cur,str,0);
1421     		if(cur!=*str)
1422     			retval|=isnum;
1423     		if(**str==',')
1424     		{
1425     			retval|=iscomma;
1426     			*str+=1;
1427     		}
1428     		else if(**str!=0)
1429     			retval=isnull;
1430     	}
1431     	return(retval);
1432     }
1433     
1434     
1435     int chandev_initdevice(chandev_probeinfo *probeinfo,void *dev_ptr,u8 port_no,char *devname,chandev_category category,chandev_unregfunc unreg_dev)
1436     {
1437     	chandev_activelist *newdevice,*curr_device;
1438     
1439     	chandev_interrupt_check();
1440     	if(probeinfo->newdevice!=NULL)
1441     	{
1442     		printk("probeinfo->newdevice!=NULL in chandev_initdevice for %s",devname);
1443     		return(-EPERM);
1444     	}
1445     
1446     
1447     	chandev_lock();
1448     	for_each(curr_device,chandev_activelist_head)
1449     	{
1450     		if(strcmp(curr_device->devname,devname)==0)
1451     		{
1452     			printk("chandev_initdevice detected duplicate devicename %s\n",devname);
1453     			chandev_unlock();
1454     			return(-EPERM);
1455     		}
1456     	}
1457     	if((newdevice=chandev_allocstr(devname,offsetof(chandev_activelist,devname))))
1458     	{
1459     		newdevice->read_irqinfo=chandev_get_irqinfo_by_irq(probeinfo->read.irq);
1460     		newdevice->write_irqinfo=chandev_get_irqinfo_by_irq(probeinfo->write.irq);
1461     		if(probeinfo->data_exists)
1462     			newdevice->data_irqinfo=chandev_get_irqinfo_by_irq(probeinfo->data.irq);
1463     		chandev_unlock();
1464     		if(newdevice->read_irqinfo==NULL||newdevice->write_irqinfo==NULL||
1465     		   (probeinfo->data_exists&&newdevice->data_irqinfo==NULL))
1466     		{
1467     			printk("chandev_initdevice, it appears that chandev_request_irq was not "
1468     			       "called for devname=%s read_irq=%d write_irq=%d data_irq=%d\n",
1469     			       devname,probeinfo->read.irq,probeinfo->write.irq,probeinfo->data.irq);
1470     			kfree(newdevice);
1471     			return(-EPERM);
1472     		}
1473     		newdevice->chan_type=probeinfo->chan_type;		
1474     		newdevice->dev_ptr=dev_ptr;
1475     		newdevice->port_no=port_no;
1476     		newdevice->memory_usage_in_k=probeinfo->memory_usage_in_k;
1477     		newdevice->category=category;
1478     		newdevice->unreg_dev=unreg_dev;
1479     		probeinfo->newdevice=newdevice;
1480     		return(0);
1481     	}
1482     	chandev_unlock();
1483     	return(-ENOMEM);
1484     }
1485     
1486     
1487     char *chandev_build_device_name(chandev_probeinfo *probeinfo,char *destnamebuff,char *basename,int buildfullname)
1488     {
1489     	if (chandev_use_devno_names&&(!probeinfo->device_forced||probeinfo->devif_num==-1)) 
1490     		sprintf(destnamebuff,"%s%04x",basename,(int)probeinfo->read.devno);
1491     	else
1492     	{
1493     		if(probeinfo->devif_num==-1)
1494     		{
1495     			if(buildfullname)
1496     			{
1497     				int idx,len=strlen(basename);
1498     				
1499     				chandev_activelist *curr_device;
1500     				for(idx=0;idx<0xffff;idx++)
1501     				{
1502     					for_each(curr_device,chandev_activelist_head)
1503     					{
1504     						if(strncmp(curr_device->devname,basename,len)==0)
1505     						{
1506     							char numbuff[10];
1507     							sprintf(numbuff,"%d",idx);
1508     							if(strcmp(&curr_device->devname[len],numbuff)==0)
1509     								goto next_idx;
1510     						}
1511     					}
1512     					sprintf(destnamebuff,"%s%d",basename,idx);
1513     					return(destnamebuff);
1514     				next_idx:
1515     				}
1516     				printk("chandev_build_device_name was usable to build a unique name for %s\n",basename);
1517     				return(NULL);
1518     			}
1519     			else
1520     				sprintf(destnamebuff,"%s%%d",basename);
1521     		}
1522     		else
1523     		{
1524     			sprintf(destnamebuff,"%s%d",basename,(int)probeinfo->devif_num);
1525     		}
1526     	}
1527     	return(destnamebuff);
1528     }
1529     
1530     #if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)
1531     struct net_device *chandev_init_netdev(chandev_probeinfo *probeinfo,char *basename,
1532     struct net_device *dev, int sizeof_priv,
1533     struct net_device *(*init_netdevfunc)(struct net_device *dev, int sizeof_priv))
1534     #else
1535     struct device *chandev_init_netdev(chandev_probeinfo *probeinfo,char *basename,
1536     struct device *dev, int sizeof_priv,
1537     struct device *(*init_netdevfunc)(struct device *dev, int sizeof_priv))
1538     #endif
1539     {
1540     #if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)
1541     	struct net_device *retdevice=NULL;
1542     	int new_device = FALSE;
1543     #else
1544     	struct device *retdevice=NULL;
1545     #endif
1546     	
1547     
1548     	chandev_interrupt_check();
1549     	if (!init_netdevfunc) 
1550     	{
1551     		printk("init_netdevfunc=NULL in chandev_init_netdev, it should not be valid.\n");
1552     		return NULL;
1553     	}
1554     #if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)
1555     	/* Allocate a device if one is not provided. */
1556             if (dev == NULL) 
1557     	{
1558     		/* ensure 32-byte alignment of the private area */
1559     		int alloc_size = sizeof (*dev) + sizeof_priv + 31;
1560     
1561     		dev = (struct net_device *) kmalloc (alloc_size, GFP_KERNEL);
1562     		if (dev == NULL) 
1563     		{
1564     			printk(KERN_ERR "chandev_initnetdevice: Unable to allocate device memory.\n");
1565     			return NULL;
1566     		}
1567     
1568     		memset(dev, 0, alloc_size);
1569     
1570     		if (sizeof_priv)
1571     			dev->priv = (void *) (((long)(dev + 1) + 31) & ~31);
1572     		new_device=TRUE;
1573     	}
1574     	chandev_build_device_name(probeinfo,dev->name,basename,FALSE);
1575     #endif
1576     	retdevice=init_netdevfunc(dev,sizeof_priv);
1577     #if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)
1578     	/* Register device if necessary */
1579     	/* we need to do this as init_netdev doesn't call register_netdevice */
1580     	/* for already allocated devices */
1581     	if (retdevice && new_device)
1582     		register_netdev(retdevice);
1583     #endif
1584     #if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)
1585     	/* We allocated it, so we should free it on error */
1586     	if (!retdevice && new_device) 
1587     		kfree(dev);
1588     #endif
1589     	return retdevice;
1590     }
1591     
1592     
1593     
1594     
1595     #if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)
1596     struct net_device *chandev_initnetdevice(chandev_probeinfo *probeinfo,u8 port_no,
1597     struct net_device *dev, int sizeof_priv, char *basename, 
1598     struct net_device *(*init_netdevfunc)(struct net_device *dev, int sizeof_priv),
1599     void (*unreg_netdevfunc)(struct net_device *dev))
1600     #else
1601     struct device *chandev_initnetdevice(chandev_probeinfo *probeinfo,u8 port_no,
1602     struct device *dev, int sizeof_priv, char *basename,
1603     struct device *(*init_netdevfunc)(struct device *dev, int sizeof_priv),
1604     void (*unreg_netdevfunc)(struct device *dev))
1605     #endif
1606     {
1607     #if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)
1608     	struct net_device *retdevice=NULL;
1609     	int new_device=(dev==NULL);
1610     #else
1611     	struct device *retdevice=NULL;
1612     #endif
1613     
1614     	if (!unreg_netdevfunc) 
1615     	{
1616     		printk("unreg_netdevfunc=NULL in chandev_initnetdevice, it should not be valid.\n");
1617     		return NULL;
1618     	}
1619     	chandev_interrupt_check();
1620     	retdevice=chandev_init_netdev(probeinfo,basename,dev,sizeof_priv,init_netdevfunc);
1621     	if (retdevice) 
1622     	{
1623     		if (chandev_initdevice(probeinfo,retdevice,port_no,retdevice->name,
1624     				      chandev_category_network_device,(chandev_unregfunc)unreg_netdevfunc)) 
1625     		{
1626     			unreg_netdevfunc(retdevice);
1627     #if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)
1628     			/* We allocated it, so we should free it on error */
1629     			if(new_device)
1630     				kfree(dev);
1631     #endif
1632     
1633     			retdevice = NULL;
1634     		}
1635     	}
1636     	return retdevice;
1637     }
1638     
1639     
1640     int chandev_compare_chpid_info(chandev_subchannel_info *chan1,chandev_subchannel_info *chan2)
1641     {
1642     	return (chan1->pim!=chan2->pim || *chan1->chpid!=*chan2->chpid);
1643     }
1644     
1645     int chandev_compare_cu_dev_info(chandev_subchannel_info *chan1,chandev_subchannel_info *chan2)
1646     {
1647     	return ((chan1->cu_type != chan2->cu_type)||
1648     		(chan1->cu_model != chan2->cu_model)||
1649     		(chan1->dev_type != chan2->dev_type)||
1650     		(chan1->dev_model != chan2->dev_model));
1651     }
1652     
1653     int chandev_compare_subchannel_info(chandev_subchannel_info *chan1,chandev_subchannel_info *chan2)
1654     {
1655     	return((chan1->devno == chan2->devno) &&
1656     	       (chan1->cu_type == chan2->cu_type) &&
1657     	       (chan1->cu_model == chan2->cu_model) &&
1658     	       (chan1->dev_type == chan2->dev_type) &&
1659     	       (chan1->dev_model == chan2->dev_model) &&
1660     	       (chan1->pim == chan2->pim) &&
1661     	       (*chan1->chpid == *chan2->chpid));
1662     }
1663     
1664     
1665     int chandev_doprobe(chandev_force *force,chandev *read,
1666     chandev *write,chandev *data)
1667     {
1668     	chandev_probelist *probe;
1669     	chandev_model_info *model_info;
1670     	chandev_probeinfo probeinfo;
1671     	int               rc=-1,hint=-1;
1672     	chandev_activelist *newdevice;
1673     	chandev_probefunc  probefunc;
1674     	chandev_parms      *curr_parms;
1675     	chandev_model_info dummy_model_info;
1676     
1677     	memset(&probeinfo,0,sizeof(probeinfo));
1678     	memset(&dummy_model_info,0,sizeof(dummy_model_info));
1679     	probeinfo.device_forced=(force!=NULL);
1680     	probeinfo.chpid_info_inconsistent=chandev_compare_chpid_info(&read->sch,&write->sch)||
1681     		 (data&&chandev_compare_chpid_info(&read->sch,&data->sch));
1682     	probeinfo.cu_dev_info_inconsistent=chandev_compare_cu_dev_info(&read->sch,&write->sch)||
1683     		 (data&&chandev_compare_cu_dev_info(&read->sch,&data->sch));
1684     	if(read->model_info)
1685     		model_info=read->model_info;
1686     	else
1687     	{
1688     		dummy_model_info.chan_type=chandev_type_none;
1689     		dummy_model_info.max_port_no=16;
1690     		model_info=&dummy_model_info;
1691     	}
1692     	for_each(probe,chandev_probelist_head)
1693     	{
1694     		if(force)
1695     			probeinfo.chan_type = ( probe->chan_type & force->chan_type );
1696     		else
1697     		{
1698     			if(chandev_cautious_auto_detect)
1699     				probeinfo.chan_type = ( probe->chan_type == model_info->chan_type ? 
1700     						       probe->chan_type : chandev_type_none );
1701     			else
1702     				probeinfo.chan_type = ( probe->chan_type & model_info->chan_type );
1703     		}
1704     		if(probeinfo.chan_type && (force || ( !probeinfo.cu_dev_info_inconsistent &&
1705     		  ((probe->chan_type&(chandev_type_ctc|chandev_type_escon)) ||
1706     		   !probeinfo.chpid_info_inconsistent))))
1707     		{
1708     #if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)
1709     			if(chandev_use_devno_names)
1710     				probeinfo.devif_num=read->sch.devno;
1711     			else
1712     #endif
1713     				probeinfo.devif_num=-1;
1714     			probeinfo.read=read->sch;
1715     			probeinfo.write=write->sch;
1716     			if(data)
1717     			{
1718     				probeinfo.data=data->sch;
1719     				probeinfo.data_exists=TRUE;
1720     			}
1721     			probeinfo.max_port_no=(force&&(force->port_protocol_no!=-1) ? 
1722     			      force->port_protocol_no : model_info->max_port_no);
1723     			for_each(curr_parms,chandev_parms_head)
1724     			{
1725     				if(probe->chan_type==curr_parms->chan_type&&
1726     				   read->sch.devno>=curr_parms->lo_devno&&
1727     					read->sch.devno<=curr_parms->hi_devno)
1728     				{
1729     					probeinfo.parmstr=curr_parms->parmstr;
1730     					break;
1731     				}
1732     			}
1733     			if(force)
1734     			{
1735     				if(force->chan_type==chandev_type_claw)
1736     					memcpy(&probeinfo.claw,&force->claw,sizeof(chandev_claw_info));
1737     				probeinfo.port_protocol_no=force->port_protocol_no;
1738     				if(force->devif_num==-1&&force->devif_num==-2)
1739     					probeinfo.devif_num=-1;
1740     				else
1741     					probeinfo.devif_num=force->devif_num;
1742     				probeinfo.memory_usage_in_k=force->memory_usage_in_k;
1743     				probeinfo.checksum_received_ip_pkts=force->checksum_received_ip_pkts;
1744     				probeinfo.use_hw_stats=force->use_hw_stats;
1745     			}
1746     			else
1747     			{
1748     				probeinfo.port_protocol_no=0;
1749     				probeinfo.checksum_received_ip_pkts=model_info->default_checksum_received_ip_pkts;
1750     				probeinfo.use_hw_stats=model_info->default_use_hw_stats;
1751     				probeinfo.memory_usage_in_k=0;
1752     				if(probe->chan_type&chandev_type_lcs)
1753     				{
1754     					hint=(read->sch.devno&0xFF)>>1;
1755     					if(hint>model_info->max_port_no)
1756     					{
1757     				/* The card is possibly emulated e.g P/390 */
1758     				/* or possibly configured to use a shared */
1759     				/* port configured by osa-sf. */
1760     						hint=0;
1761     					}
1762     				}
1763     			}
1764     			probeinfo.hint_port_no=hint;
1765     			probefunc=probe->probefunc;
1766     			rc=probefunc(&probeinfo);
1767     			if(rc==0)
1768     			{
1769     				newdevice=probeinfo.newdevice;
1770     				if(newdevice)
1771     				{
1772     					newdevice->probefunc=probe->probefunc;
1773     					newdevice->shutdownfunc=probe->shutdownfunc;
1774     					newdevice->msck_notfunc=probe->msck_notfunc;
1775     					probe->devices_found++;
1776     					chandev_add_to_list((list **)&chandev_activelist_head,
1777     							    newdevice);
1778     					chandev_add_to_userland_notify_list(chandev_start,
1779     								      newdevice->devname,chandev_status_good,chandev_status_good);
1780     				}
1781     				else
1782     				{
1783     					printk("chandev_initdevice either failed or wasn't called for device read_irq=0x%04x\n",probeinfo.read.irq);
1784     				}
1785     				break;
1786     				
1787     			}
1788     		}
1789     	}
1790     	chandev_remove(read);
1791     	chandev_remove(write);
1792     	if(data)
1793     		chandev_remove(data);
1794     	return(rc);
1795     }
1796     
1797     
1798     int chandev_request_irq_from_irqinfo(chandev_irqinfo *irqinfo,chandev *this_chandev)
1799     {
1800     	int retval=s390_request_irq_special(irqinfo->sch.irq,
1801     				   irqinfo->handler,
1802     				   chandev_not_oper_handler,
1803     				   irqinfo->irqflags,
1804     				   irqinfo->devname,
1805     				   irqinfo->dev_id);
1806     	if(retval==0)
1807     	{
1808     		irqinfo->msck_status=chandev_status_good;
1809     		this_chandev->owned=TRUE;
1810     	}
1811     	return(retval);
1812     }
1813     
1814     void chandev_irqallocerr(chandev_irqinfo *irqinfo,int err)
1815     {
1816     	printk("chandev_probe failed to realloc irq=%d for %s err=%d\n",irqinfo->sch.irq,irqinfo->devname,err);
1817     }
1818     
1819     
1820     void chandev_call_notification_func(chandev_activelist *curr_device,chandev_irqinfo *curr_irqinfo,
1821     chandev_msck_status prevstatus)
1822     {
1823     	if(curr_irqinfo->msck_status!=prevstatus)
1824     	{
1825     		chandev_msck_status new_msck_status=curr_irqinfo->msck_status;
1826     		if(curr_irqinfo->msck_status==chandev_status_good)
1827     		{
1828     			if(curr_device->read_irqinfo->msck_status==chandev_status_good&&
1829     			   curr_device->write_irqinfo->msck_status==chandev_status_good)
1830     			{
1831     				if(curr_device->data_irqinfo)
1832     				{
1833     					if(curr_device->data_irqinfo->msck_status==chandev_status_good)
1834     						new_msck_status=chandev_status_all_chans_good;
1835     				}
1836     				else
1837     					new_msck_status=chandev_status_all_chans_good;
1838     			}
1839     		}
1840     		if(curr_device->msck_notfunc)
1841     		{
1842     			curr_device->msck_notfunc(curr_device->dev_ptr,
1843     					      curr_irqinfo->sch.irq,
1844     					      prevstatus,new_msck_status);
1845     		}
1846     		if(new_msck_status!=chandev_status_good)
1847     		{
1848     			/* No point in sending a machine check if only one channel is good */
1849     			chandev_add_to_userland_notify_list(chandev_msck,curr_device->devname,
1850     						      prevstatus,curr_irqinfo->msck_status);
1851     		}
1852     	}
1853     }
1854     
1855     int chandev_find_eligible_channels(chandev *first_chandev_to_check,
1856     			       chandev **read,chandev **write,chandev **data,chandev **next,
1857     				   chandev_type chan_type)
1858     {
1859     	chandev *curr_chandev;
1860     	int eligible_found=FALSE,changed;
1861     	
1862     	*next=first_chandev_to_check->next;
1863     	*read=*write=*data=NULL;
1864     	for_each(curr_chandev,first_chandev_to_check)
1865     		if((curr_chandev->sch.devno&1)==0&&curr_chandev->model_info->chan_type!=chandev_type_claw)
1866     		{
1867     			*read=curr_chandev;
1868     			if(chan_type==chandev_type_none)
1869     				chan_type=(*read)->model_info->chan_type;
1870     			break;
1871     		}
1872     	if(*read)
1873     	{
1874     		for_each(curr_chandev,(chandev *)chandev_head.head)
1875     			if((((*read)->sch.devno|1)==curr_chandev->sch.devno)&&
1876     			   (chandev_compare_cu_dev_info(&(*read)->sch,&curr_chandev->sch)==0)&&
1877     			   ((chan_type&(chandev_type_ctc|chandev_type_escon))||
1878     			    chandev_compare_chpid_info(&(*read)->sch,&curr_chandev->sch)==0))
1879     			{
1880     				*write=curr_chandev;
1881     				break;
1882     			}
1883     	}
1884     	if((chan_type&chandev_type_qeth))
1885     	{
1886     		if(*write)
1887     		{
1888     			for_each(curr_chandev,(chandev *)chandev_head.head)
1889     				if((curr_chandev!=*read&&curr_chandev!=*write)&&
1890     				   (chandev_compare_cu_dev_info(&(*read)->sch,&curr_chandev->sch)==0)&&
1891     				   (chandev_compare_chpid_info(&(*read)->sch,&curr_chandev->sch)==0))
1892     				{
1893     					*data=curr_chandev;
1894     					break;
1895     				}
1896     			if(*data)
1897     				eligible_found=TRUE;
1898     		}
1899     		
1900     	}
1901     	else
1902     		if(*write)
1903     			eligible_found=TRUE;
1904     	if(eligible_found)
1905     	{
1906     		do
1907     		{
1908     			changed=FALSE;
1909     			if(*next&&
1910     			   ((*read&&(*read==*next))||
1911     			   (*write&&(*write==*next))||
1912     			   (*data&&(*data==*next))))
1913     			{
1914     				*next=(*next)->next;
1915     				changed=TRUE;
1916     			}
1917     		}while(changed==TRUE);
1918     	}
1919     	return(eligible_found);
1920     }
1921     
1922     chandev *chandev_get_free_chandev_by_devno(int devno)
1923     {
1924     	chandev *curr_chandev;
1925     	if(devno==-1)
1926     		return(NULL);
1927     	for_each(curr_chandev,(chandev *)chandev_head.head)
1928     		if(curr_chandev->sch.devno==devno)
1929     		{
1930     			if(chandev_active(devno))
1931     				return(NULL);
1932     			else
1933     				return(curr_chandev);
1934     		}
1935     	return(NULL);
1936     
1937     }
1938     
1939     void chandev_probe(void)
1940     {
1941     	chandev *read_chandev,*write_chandev,*data_chandev,*curr_chandev,*next_chandev;
1942     	chandev_force *curr_force;
1943     	chandev_noauto_range *curr_noauto;
1944     	chandev_activelist *curr_device;
1945     	chandev_irqinfo *curr_irqinfo;
1946     	s390_dev_info_t curr_devinfo;
1947     	int  err;
1948     	int auto_msck_recovery;
1949     	chandev_msck_status prevstatus;
1950     	chandev_msck_range *curr_msck_range;
1951     
1952     
1953     	chandev_interrupt_check();
1954     	chandev_read_conf_if_necessary();
1955     	chandev_collect_devices();
1956     	chandev_lock();
1957     	for_each(curr_irqinfo,chandev_irqinfo_head)
1958     	{
1959     		if((curr_device=chandev_get_activelist_by_irq(curr_irqinfo->sch.irq)))
1960     		{
1961     			prevstatus=curr_irqinfo->msck_status;
1962     			if(curr_irqinfo->msck_status!=chandev_status_good)
1963     			{
1964     				curr_chandev=chandev_get_by_irq(curr_irqinfo->sch.irq);
1965     				if(curr_chandev)
1966     				{
1967     					auto_msck_recovery=curr_chandev->model_info->
1968     						auto_msck_recovery;
1969     				}
1970     				else
1971     					goto remove;
1972     				for_each(curr_msck_range,chandev_msck_range_head)
1973     				{
1974     					if(curr_msck_range->lo_devno<=
1975     					   curr_irqinfo->sch.devno&&
1976     					   curr_msck_range->hi_devno>=
1977     					   curr_irqinfo->sch.devno)
1978     					{
1979     						auto_msck_recovery=
1980     							curr_msck_range->
1981     							auto_msck_recovery;
1982     						break;
1983     					}
1984     				}
1985     				if((1<<(curr_irqinfo->msck_status-1))&auto_msck_recovery)
1986     				{
1987     					if(curr_irqinfo->msck_status==chandev_status_revalidate)
1988     					{
1989     						if((get_dev_info_by_irq(curr_irqinfo->sch.irq,&curr_devinfo)==0))
1990     						{
1991     							curr_irqinfo->sch.devno=curr_devinfo.devno;
1992     							curr_irqinfo->msck_status=chandev_status_good;
1993     						}
1994     					}
1995     					else
1996     					{
1997     						if(curr_chandev)
1998     						{
1999     							/* Has the device reappeared */
2000     							if(chandev_compare_subchannel_info(
2001     								&curr_chandev->sch,
2002     								&curr_device->read_irqinfo->sch)||
2003     							   chandev_compare_subchannel_info(
2004     								&curr_chandev->sch,
2005     								&curr_device->write_irqinfo->sch)||
2006     							   (curr_device->data_irqinfo&&
2007     							    chandev_compare_subchannel_info(
2008     								    &curr_chandev->sch,
2009     								    &curr_device->data_irqinfo->sch)))
2010     							{
2011     								if((err=chandev_request_irq_from_irqinfo(curr_irqinfo,curr_chandev))==0)
2012     									curr_irqinfo->msck_status=chandev_status_good;
2013     								else
2014     									chandev_irqallocerr(curr_irqinfo,err);
2015     							}
2016     					
2017     						}
2018     					}
2019     				}
2020     			}
2021     			chandev_call_notification_func(curr_device,curr_irqinfo,prevstatus);
2022     		}
2023     		/* This is required because the device can go & come back */
2024                     /* even before we realize it is gone owing to the waits in our kernel threads */
2025     		/* & the device will be marked as not owned but its status will be good */
2026                     /* & an attempt to accidently reprobe it may be done. */ 
2027     		remove:
2028     		chandev_remove(chandev_get_by_irq(curr_irqinfo->sch.irq));
2029     		
2030     	}
2031     	/* extra sanity */
2032     	for_each_allow_delete(curr_chandev,next_chandev,(chandev *)chandev_head.head)
2033     		if(curr_chandev->owned)
2034     			chandev_remove(curr_chandev);
2035     	for_each(curr_force,chandev_force_head)
2036     	{
2037     		if(curr_force->devif_num==-2)
2038     		{
2039     			for_each_allow_delete2(curr_chandev,next_chandev,(chandev *)chandev_head.head)
2040     			{
2041     				if(chandev_find_eligible_channels(curr_chandev,&read_chandev,
2042     								  &write_chandev,&data_chandev,
2043     								  &next_chandev,
2044     								  curr_force->chan_type));
2045     				{
2046     					if((curr_force->read_lo_devno>=read_chandev->sch.devno)&&
2047     					   (curr_force->write_hi_devno<=read_chandev->sch.devno)&&
2048     					   (curr_force->read_lo_devno>=write_chandev->sch.devno)&&
2049     					   (curr_force->write_hi_devno<=write_chandev->sch.devno)&&
2050     					   (!data_chandev||(data_chandev&&
2051     					   (curr_force->read_lo_devno>=data_chandev->sch.devno)&&
2052     					   (curr_force->write_hi_devno<=data_chandev->sch.devno))))
2053     						chandev_doprobe(curr_force,read_chandev,write_chandev,
2054     								data_chandev);
2055     				}
2056     			}
2057     		}
2058     		else
2059     		{
2060     			read_chandev=chandev_get_free_chandev_by_devno(curr_force->read_lo_devno);
2061     			if(read_chandev)
2062     			{
2063     				write_chandev=chandev_get_free_chandev_by_devno(curr_force->write_hi_devno);
2064     				if(write_chandev)
2065     				{
2066     					if(curr_force->chan_type==chandev_type_qeth)
2067     					{
2068     
2069     						data_chandev=chandev_get_free_chandev_by_devno(curr_force->data_devno);
2070     						if(data_chandev==NULL)
2071     							printk("chandev_probe unable to force gigabit_ethernet driver invalid device  no 0x%04x given\n",curr_force->data_devno);
2072     					}
2073     					else
2074     						data_chandev=NULL;
2075     					chandev_doprobe(curr_force,read_chandev,write_chandev,
2076     							data_chandev);
2077     				}
2078     			}
2079     		}
2080     	}
2081     	for_each_allow_delete(curr_chandev,next_chandev,(chandev *)chandev_head.head)
2082     	{
2083     		for_each(curr_noauto,chandev_noauto_head)
2084     		{
2085     			if(curr_chandev->sch.devno>=curr_noauto->lo_devno&&
2086     			   curr_chandev->sch.devno<=curr_noauto->hi_devno)
2087     			{
2088     				chandev_remove(curr_chandev);
2089     				break;
2090     			}
2091     		}
2092     	}
2093     	for_each_allow_delete2(curr_chandev,next_chandev,(chandev *)chandev_head.head)
2094     	{
2095     		if(chandev_find_eligible_channels(curr_chandev,&read_chandev,
2096     						  &write_chandev,&data_chandev,
2097     						  &next_chandev,
2098     						  chandev_type_none))
2099     			chandev_doprobe(NULL,read_chandev,write_chandev,
2100     					data_chandev);
2101     	}
2102     	chandev_remove_all();
2103     	chandev_unlock();
2104     }
2105     
2106     static void chandev_not_oper_func(int irq,int status)
2107     {
2108     	chandev_irqinfo *curr_irqinfo;
2109     	chandev_activelist *curr_device;
2110     	
2111     	chandev_lock();
2112     	for_each(curr_irqinfo,chandev_irqinfo_head)
2113     		if(curr_irqinfo->sch.irq==irq)
2114     		{
2115     			chandev_msck_status prevstatus=curr_irqinfo->msck_status;
2116     			switch(status)
2117     			{
2118     				/* Currently defined but not used in kernel */
2119     				/* Despite being in specs */
2120     			case DEVSTAT_NOT_OPER:
2121     				curr_irqinfo->msck_status=chandev_status_not_oper;
2122     				break;
2123     #ifdef DEVSTAT_NO_PATH
2124     				/* Kernel hasn't this defined currently. */
2125     				/* Despite being in specs */
2126     			case DEVSTAT_NO_PATH:
2127     				curr_irqinfo->msck_status=chandev_status_no_path;
2128     				break;
2129     #endif
2130     			case DEVSTAT_REVALIDATE:
2131     				curr_irqinfo->msck_status=chandev_status_revalidate;
2132     				break;
2133     			case DEVSTAT_DEVICE_GONE:
2134     				curr_irqinfo->msck_status=chandev_status_gone;
2135     				break;
2136                             }
2137                             if((curr_device=chandev_get_activelist_by_irq(irq)))
2138     					chandev_call_notification_func(curr_device,curr_irqinfo,prevstatus);
2139      			else
2140     				printk("chandev_not_oper_func received channel check for unowned irq %d",irq);
2141     		}
2142     	chandev_unlock();
2143     }
2144     
2145     
2146     static int chandev_msck_thread(void *unused)
2147     {
2148     	int loopcnt,not_oper_probe_required=FALSE;
2149     	wait_queue_head_t    wait;
2150     	chandev_not_oper_struct *new_not_oper;
2151     
2152     	/* This loop exists because machine checks tend to come in groups & we have
2153                to wait for the other devnos to appear also */
2154     	init_waitqueue_head(&wait);
2155     	for(loopcnt=0;loopcnt<10||(jiffies-chandev_last_machine_check)<HZ;loopcnt++)
2156     	{
2157     		sleep_on_timeout(&wait,HZ);
2158     	}
2159     	atomic_set(&chandev_msck_thread_lock,1);
2160     	while(!atomic_compare_and_swap(TRUE,FALSE,&chandev_new_msck));
2161     	{
2162     		chandev_probe();
2163     	}
2164     	while(TRUE)
2165     	{
2166     		
2167     		unsigned long        flags; 
2168     		spin_lock_irqsave(&chandev_not_oper_spinlock,flags);
2169     		new_not_oper=(chandev_not_oper_struct *)dequeue_head(&chandev_not_oper_head);
2170     		spin_unlock_irqrestore(&chandev_not_oper_spinlock,flags);
2171     		if(new_not_oper)
2172     		{
2173     			chandev_not_oper_func(new_not_oper->irq,new_not_oper->status);
2174     			not_oper_probe_required=TRUE;
2175     			kfree(new_not_oper);
2176     		}
2177     		else
2178     			break;
2179     	}
2180     	if(not_oper_probe_required)
2181     		chandev_probe();
2182     	return(0);
2183     }
2184     
2185     static void chandev_msck_task(void *unused)
2186     {
2187     	if(kernel_thread(chandev_msck_thread,NULL,SIGCHLD)<0)
2188     	{
2189     		atomic_set(&chandev_msck_thread_lock,1);
2190     		printk("error making chandev_msck_thread kernel thread\n");
2191     	}
2192     }
2193     
2194     
2195     
2196     static char *argstrs[]=
2197     {
2198     	"noauto",
2199     	"del_noauto",
2200     	"ctc",
2201     	"escon",
2202     	"lcs",
2203     	"osad",
2204     	"qeth",
2205     	"claw",
2206     	"add_parms",
2207     	"del_parms",
2208     	"del_force",
2209     #if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)
2210     	"use_devno_names",
2211     	"dont_use_devno_names",
2212     #endif
2213     	"cautious_auto_detect",
2214     	"non_cautious_auto_detect",
2215     	"add_model",
2216     	"del_model",
2217     	"auto_msck",
2218     	"del_auto_msck",
2219     	"del_all_models",
2220     	"reset_conf_clean",
2221     	"reset_conf",
2222     	"shutdown",
2223     	"reprobe",
2224     	"unregister_probe",
2225     	"unregister_probe_by_chan_type",
2226     	"read_conf",
2227     	"dont_read_conf",
2228     	"persistent"
2229     };
2230     
2231     typedef enum
2232     {
2233     	stridx_mult=256,
2234     	first_stridx=0,
2235     	noauto_stridx=first_stridx,
2236     	del_noauto_stridx,
2237     	ctc_stridx,
2238     	escon_stridx,
2239     	lcs_stridx,
2240     	osad_stridx,
2241             qeth_stridx,
2242     	claw_stridx,
2243     	add_parms_stridx,
2244     	del_parms_stridx,
2245     	del_force_stridx,
2246     #if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)
2247     	use_devno_names_stridx,
2248     	dont_use_devno_names_stridx,
2249     #endif
2250     	cautious_auto_detect_stridx,
2251     	non_cautious_auto_detect_stridx,
2252     	add_model_stridx,
2253     	del_model_stridx,
2254     	auto_msck_stridx,
2255     	del_auto_msck_stridx,
2256     	del_all_models_stridx,
2257     	reset_conf_clean_stridx,
2258     	reset_conf_stridx,
2259     	shutdown_stridx,
2260     	reprobe_stridx,
2261     	unregister_probe_stridx,
2262     	unregister_probe_by_chan_type_stridx,
2263     	read_conf_stridx,
2264     	dont_read_conf_stridx,
2265     	persistent_stridx,
2266     	last_stridx,
2267     } chandev_str_enum;
2268     
2269     void chandev_add_noauto(u16 lo_devno,u16 hi_devno)
2270     {
2271     	chandev_noauto_range *new_range;
2272     
2273     	if((new_range=chandev_alloc(sizeof(chandev_noauto_range))))
2274     	{
2275     		new_range->lo_devno=lo_devno;
2276     		new_range->hi_devno=hi_devno;
2277     		chandev_add_to_list((list **)&chandev_noauto_head,new_range);
2278     	}
2279     }
2280     
2281     
2282     void chandev_add_msck_range(u16 lo_devno,u16 hi_devno,int auto_msck_recovery)
2283     {
2284     	chandev_msck_range *new_range;
2285     
2286     	if((new_range=chandev_alloc(sizeof(chandev_msck_range))))
2287     	{
2288     		new_range->lo_devno=lo_devno;
2289     		new_range->hi_devno=hi_devno;
2290     		new_range->auto_msck_recovery=auto_msck_recovery;
2291     		chandev_add_to_list((list **)&chandev_msck_range_head,new_range);
2292     	}
2293     }
2294     
2295     
2296     
2297     static char chandev_keydescript[]=
2298     "\nchan_type key bitfield ctc=0x1,escon=0x2,lcs=0x4,osad=0x8,qeth=0x10,claw=0x20\n";
2299     
2300     
2301     #if  CONFIG_ARCH_S390X
2302     /* We need this as we sometimes use this to evaluate pointers */
2303     typedef long chandev_int; 
2304     #else
2305     typedef int chandev_int;
2306     #endif
2307     
2308     
2309     #if (LINUX_VERSION_CODE<KERNEL_VERSION(2,3,0)) || (CONFIG_ARCH_S390X)
2310     /*
2311      * Read an int from an option string; if available accept a subsequent
2312      * comma as well.
2313      *
2314      * Return values:
2315      * 0 : no int in string
2316      * 1 : int found, no subsequent comma
2317      * 2 : int found including a subsequent comma
2318      */
2319     static chandev_int chandev_get_option(char **str,chandev_int *pint)
2320     {
2321         char *cur = *str;
2322     
2323         if (!cur || !(*cur)) return 0;
2324         *pint = simple_strtol(cur,str,0);
2325         if (cur==*str) return 0;
2326         if (**str==',') {
2327             (*str)++;
2328             return 2;
2329         }
2330     
2331         return 1;
2332     }
2333     
2334     
2335     static char *chandev_get_options(char *str, int nints, chandev_int *ints)
2336     {
2337     	int res,i=1;
2338     
2339     	while (i<nints) 
2340     	{
2341     		res = chandev_get_option(&str, ints+i);
2342     		if (res==0) break;
2343     		i++;
2344     		if (res==1) break;
2345     	}
2346     	ints[0] = i-1;
2347     	return(str);
2348     }
2349     #else
2350     #define chandev_get_option get_option
2351     #define chandev_get_options get_options
2352     #endif
2353     /*
2354      * Read an string from an option string; if available accept a subsequent
2355      * comma as well & set this comma to a null character when returning the string.
2356      *
2357      * Return values:
2358      * 0 : no string found
2359      * 1 : string found, no subsequent comma
2360      * 2 : string found including a subsequent comma
2361      */
2362     static int chandev_get_string(char **instr,char **outstr)
2363     {
2364     	char *cur = *instr;
2365     
2366     	if (!cur ||*cur==0)
2367     	{
2368     		*outstr=NULL;
2369     		return 0;
2370     	}
2371     	*outstr=*instr;
2372     	for(;;)
2373     	{
2374     		if(*(++cur)==',')
2375     		{
2376     			*cur=0;
2377     			*instr=cur+1;
2378     			return 2;
2379     		}
2380     		else if(*cur==0)
2381     		{
2382     			*instr=cur+1;
2383     			return 1;
2384     		}
2385     	}
2386     }
2387     
2388     
2389     
2390     
2391     static int chandev_setup(char *instr,char *errstr,int lineno)
2392     {
2393     	chandev_strval   val=isnull;
2394     	chandev_str_enum stridx;
2395     	long             endlong;
2396     	chandev_type     chan_type;
2397     	char             *str,*currstr,*interpretstr=NULL;
2398     	int              cnt,strcnt;
2399     	int              retval=0;
2400     #define CHANDEV_MAX_EXTRA_INTS 12
2401     	chandev_int ints[CHANDEV_MAX_EXTRA_INTS+1];
2402     	currstr=alloca(strlen(instr)+1);
2403     	strcpy(currstr,instr);
2404     	strcnt=chandev_pack_args(currstr);
2405     	for(cnt=1;cnt<=strcnt;cnt++)
2406     	{
2407     		interpretstr=currstr;
2408     		memset(ints,0,sizeof(ints));
2409     		for(stridx=first_stridx;stridx<last_stridx;stridx++)
2410     		{
2411     			str=currstr;
2412     			if((val=chandev_strcmp(argstrs[stridx],&str,&endlong)))
2413     				break;
2414     		}
2415     		currstr=str;
2416     		if(val)
2417     		{
2418     			val=(((chandev_strval)stridx)*stridx_mult)+(val&~isstr);
2419     			switch(val)
2420     			{
2421     			case (add_parms_stridx*stridx_mult)|iscomma:
2422     				currstr=chandev_get_options(currstr,4,ints);
2423     				if(*currstr&&ints[0]>=1)
2424     				{
2425     					if(ints[0]==1)
2426     					{
2427     						ints[2]=0;
2428     						ints[3]=0xffff;
2429     					}
2430     					else if(ints[0]==2)
2431     						ints[3]=ints[2];
2432     					chandev_add_parms(ints[1],ints[2],ints[3],currstr);
2433     //					currstr=currstr+strlen(currstr)+1;
2434     					continue;
2435     				}
2436     				else
2437     					goto BadArgs;
2438     				break;
2439     			case (claw_stridx*stridx_mult)|isnum|iscomma:
2440     			case (claw_stridx*stridx_mult)|iscomma:
2441     				currstr=chandev_get_options(str,6,ints);
2442     				break;
2443     			default:
2444     				if(val&iscomma)
2445     					currstr=chandev_get_options(str,CHANDEV_MAX_EXTRA_INTS,ints);
2446     				break;
2447     			}
2448     			switch(val)
2449     			{
2450     			case noauto_stridx*stridx_mult:
2451     			case (noauto_stridx*stridx_mult)|iscomma:
2452     				switch(ints[0])
2453     				{
2454     				case 0: 
2455     					chandev_free_all_list((list **)&chandev_noauto_head);
2456     					chandev_add_noauto(0,0xffff);
2457     					break;
2458     				case 1:
2459     					ints[2]=ints[1];
2460     				case 2:
2461     					chandev_add_noauto(ints[1],ints[2]);
2462     					break;
2463     				default:
2464     					goto BadArgs;
2465     				}
2466     				break;
2467     			case (auto_msck_stridx*stridx_mult)|iscomma:
2468     				switch(ints[0])
2469     				{
2470     				case 1:
2471     					chandev_free_all_list((list **)&chandev_msck_range_head);
2472     					chandev_add_msck_range(0,0xffff,ints[1]);
2473     					break;
2474     				case 2:
2475     					chandev_add_msck_range(ints[1],ints[1],ints[2]);
2476     					break;
2477     				case 3:
2478     					chandev_add_msck_range(ints[1],ints[2],ints[3]);
2479     					break;
2480     				default:
2481     					goto BadArgs;
2482     					
2483     				}
2484     			case del_auto_msck_stridx*stridx_mult:
2485     			case (del_auto_msck_stridx*stridx_mult)|iscomma:
2486     				switch(ints[0])
2487     				{
2488     				case 0:
2489     					chandev_free_all_list((list **)&chandev_msck_range_head);
2490     					break;
2491     				case 1:
2492     					chandev_del_msck(ints[1]);
2493     				default:
2494     					goto BadArgs;
2495     				}
2496     			case del_noauto_stridx*stridx_mult:
2497     				chandev_free_all_list((list **)&chandev_noauto_head);
2498     				break;
2499     			case (del_noauto_stridx*stridx_mult)|iscomma:
2500     				if(ints[0]==1)
2501     					chandev_del_noauto(ints[1]);
2502     				else
2503     					goto BadArgs;
2504     				break;
2505     			case (qeth_stridx*stridx_mult)|isnum|iscomma:
2506     				if(ints[0]<3||ints[0]>7)
2507     					goto BadArgs;
2508     				chandev_add_force(chandev_type_qeth,endlong,ints[1],ints[2],
2509     						  ints[3],ints[4],ints[5],ints[6],ints[7],
2510     						  NULL,NULL,NULL);
2511     				break;
2512     			case (ctc_stridx*stridx_mult)|isnum|iscomma:
2513     			case (escon_stridx*stridx_mult)|isnum|iscomma:
2514     			case (lcs_stridx*stridx_mult)|isnum|iscomma:
2515     			case (osad_stridx*stridx_mult)|isnum|iscomma:
2516     			case (ctc_stridx*stridx_mult)|iscomma:
2517     			case (escon_stridx*stridx_mult)|iscomma:
2518     			case (lcs_stridx*stridx_mult)|iscomma:
2519     			case (osad_stridx*stridx_mult)|iscomma:
2520     				switch(val&~(isnum|iscomma))
2521     				{
2522     				case (ctc_stridx*stridx_mult):
2523     					chan_type=chandev_type_ctc;
2524     					break;
2525     				case (escon_stridx*stridx_mult):
2526     					chan_type=chandev_type_escon;
2527     					break;
2528     				case (lcs_stridx*stridx_mult):
2529     					chan_type=chandev_type_lcs;
2530     					break;
2531     				case (osad_stridx*stridx_mult):
2532     					chan_type=chandev_type_osad;
2533     					break;
2534     				case (qeth_stridx*stridx_mult):
2535     					chan_type=chandev_type_qeth;
2536     					break;
2537     				default:
2538     					goto BadArgs;
2539     				}
2540     				if((val&isnum)==0)
2541     					endlong=-2;
2542     				if(ints[0]<2||ints[0]>6)
2543     					goto BadArgs;
2544     				chandev_add_force(chan_type,endlong,ints[1],ints[2],
2545     						  0,ints[3],ints[4],ints[5],ints[6],
2546     						  NULL,NULL,NULL);
2547     				break;
2548     			case (claw_stridx*stridx_mult)|isnum|iscomma:
2549     			case (claw_stridx*stridx_mult)|iscomma:
2550     				if(ints[0]>=2&&ints[0]<=5)
2551     				{
2552     					char    *host_name,*adapter_name,*api_type;
2553     					char    *clawstr=alloca(strlen(currstr)+1);
2554     					
2555     					strcpy(clawstr,currstr);
2556     					if(!(chandev_get_string(&clawstr,&host_name)==2&&
2557     					     chandev_get_string(&clawstr,&adapter_name)==2&&
2558     					     chandev_get_string(&clawstr,&api_type)==1&&
2559     					     chandev_add_force(chandev_type_claw,
2560     							       endlong,ints[1],ints[2],0,
2561     							       ints[3],0,ints[4],ints[5],
2562     							       host_name,adapter_name,api_type)==0))
2563     						goto BadArgs;
2564     						
2565     				}
2566     				else
2567     					goto BadArgs;
2568     				break;
2569     			case (del_parms_stridx*stridx_mult):
2570     				ints[1]=-1;
2571     			case (del_parms_stridx*stridx_mult)|iscomma:
2572     				if(ints[0]==0)
2573     					ints[1]=-1;
2574     				if(ints[0]<=1)
2575     					ints[2]=FALSE;
2576     				if(ints[0]<=2)
2577     					ints[3]=-1;
2578     				if(ints[0]>3)
2579     					goto BadArgs;
2580     				chandev_remove_parms(ints[1],ints[2],ints[3]);
2581     				break;
2582     			case (del_force_stridx*stridx_mult)|iscomma:
2583     				if(ints[0]!=1)
2584     					goto BadArgs;
2585     				chandev_del_force(ints[1]);
2586     				break;
2587     			case (del_force_stridx*stridx_mult):
2588     				chandev_del_force(-1);
2589     				break;
2590     #if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)
2591     			case (use_devno_names_stridx*stridx_mult):
2592     				chandev_use_devno_names=TRUE;
2593     				break;
2594     			case (dont_use_devno_names_stridx*stridx_mult):
2595     				chandev_use_devno_names=FALSE;
2596     				break;
2597     #endif
2598     			case (cautious_auto_detect_stridx*stridx_mult):
2599     				chandev_cautious_auto_detect=TRUE;
2600     				break;
2601     			case (non_cautious_auto_detect_stridx*stridx_mult):
2602     				chandev_cautious_auto_detect=FALSE;
2603     				break;
2604     			case (add_model_stridx*stridx_mult)|iscomma:
2605     				if(ints[0]<3)
2606     					goto BadArgs;
2607     				if(ints[0]==3)
2608     					ints[4]=-1;
2609     				if(ints[0]<=4)
2610     					ints[5]=-1;
2611     				if(ints[0]<=5)
2612     					ints[6]=-1;
2613     				if(ints[0]<=6)
2614     					ints[7]=default_msck_bits;
2615     				if(ints[0]<=7)
2616     					ints[8]=FALSE;
2617     				if(ints[0]<=8)
2618     					ints[9]=FALSE;
2619     				ints[0]=7;
2620     				chandev_add_model(ints[1],ints[2],ints[3],
2621     						  ints[4],ints[5],ints[6],ints[7],ints[8],ints[9]);
2622     				break;
2623     			case (del_model_stridx*stridx_mult)|iscomma:
2624     				if(ints[0]<2||ints[0]>4)
2625     					goto BadArgs;
2626     				if(ints[0]<3)
2627     					ints[3]=-2;
2628     				if(ints[0]<4)
2629     					ints[4]=-2;
2630     				ints[0]=4;
2631     				chandev_del_model(ints[1],ints[2],ints[3],ints[4]);
2632     				break;
2633     			case del_all_models_stridx*stridx_mult:
2634     				chandev_remove_all_models();
2635     				break;
2636     			case reset_conf_stridx*stridx_mult:
2637     				chandev_reset();
2638     				chandev_init_default_models();
2639     				break;
2640     			case reset_conf_clean_stridx*stridx_mult:
2641     				chandev_reset();
2642     				break;
2643     			case shutdown_stridx*stridx_mult:
2644     				chandev_shutdown_all();
2645     				break;
2646     			case (shutdown_stridx*stridx_mult)|iscomma:
2647     				switch(ints[0])
2648     				{
2649     				case 0:
2650     					if(strlen(str))
2651     						chandev_shutdown_by_name(str);
2652     					else
2653     						goto BadArgs;
2654     					break;
2655     				case 1:
2656     					chandev_shutdown_by_devno(ints[1]);
2657     					break;
2658     				default:
2659     					goto BadArgs;
2660     				}
2661     				break;
2662     			case reprobe_stridx*stridx_mult:
2663     				chandev_probe();
2664     				break;
2665     			case unregister_probe_stridx*stridx_mult:
2666     				chandev_free_all_list((list **)&chandev_probelist_head);
2667     				break;
2668     			case (unregister_probe_stridx*stridx_mult)|iscomma:
2669     				if(ints[0]!=1)
2670     					goto BadArgs;
2671     				chandev_unregister_probe((chandev_probefunc)ints[1]);
2672     				break;
2673     			case (unregister_probe_by_chan_type_stridx*stridx_mult)|iscomma:
2674     				if(ints[0]!=1)
2675     					goto BadArgs;
2676     				chandev_unregister_probe_by_chan_type((chandev_type)ints[1]);
2677     				break;
2678     			case read_conf_stridx*stridx_mult:
2679     				chandev_read_conf();
2680     				break;
2681     			case dont_read_conf_stridx*stridx_mult:
2682     				atomic_set(&chandev_conf_read,TRUE);
2683     				break;
2684     			case (persistent_stridx*stridx_mult)|iscomma:
2685     				if(ints[0]==1)
2686     					chandev_persistent=ints[1];
2687     				else
2688     					goto BadArgs;
2689     				break;
2690     			default:
2691     				goto BadArgs;
2692     			}
2693     		}
2694     		else
2695     			goto BadArgs;
2696     		if(cnt<strcnt)
2697     		{
2698     			/* eat up stuff till next string */
2699     			while(*(currstr++));
2700     		}
2701     	}
2702     	retval=1;
2703      BadArgs:
2704     	if(!retval)
2705     	{
2706     		printk("chandev_setup %s %s",(val==0 ? "unknown verb":"bad argument"),instr);
2707     		if(errstr)
2708     		{
2709     			printk("%s %d interpreted as %s",errstr,lineno,interpretstr);
2710     			if(strcnt>1)
2711     			{
2712     				if(cnt==strcnt)
2713     					printk(" after the last semicolon\n");
2714     				else
2715     					printk(" before semicolon no %d",cnt);
2716     			}
2717     		}
2718     		printk(".\n Type man chandev for more info.\n\n");
2719     	}
2720     	return(retval);
2721     }
2722     #define CHANDEV_KEYWORD "chandev="
2723     static int chandev_setup_bootargs(char *str,int paramno)
2724     {
2725     	int len;
2726     
2727     	char *copystr;
2728     	for(len=0;str[len]!=0&&!isspace(str[len]);len++);
2729     	copystr=alloca(len+1);
2730     	strncpy(copystr,str,len);
2731     	copystr[len]=0;
2732     	if(chandev_setup(copystr,"at "CHANDEV_KEYWORD" bootparam no",paramno)==0)
2733     		return(0);
2734     	return(len);
2735     
2736     }
2737     
2738     /*
2739       We can't parse using a __setup function as kmalloc isn't available
2740       at this time.
2741      */
2742     static void __init chandev_parse_args(void)
2743     {
2744     #define CHANDEV_KEYWORD "chandev="
2745     	extern char saved_command_line[];
2746     	int cnt,len,paramno=1;
2747     
2748     	len=strlen(saved_command_line)-sizeof(CHANDEV_KEYWORD);
2749     	for(cnt=0;cnt<len;cnt++)
2750     	{
2751     		if(strncmp(&saved_command_line[cnt],CHANDEV_KEYWORD,
2752     			   sizeof(CHANDEV_KEYWORD)-1)==0)
2753     		{
2754     			cnt+=(sizeof(CHANDEV_KEYWORD)-1);	
2755     			cnt+=chandev_setup_bootargs(&saved_command_line[cnt],paramno);
2756     			paramno++;
2757     		}
2758     	}
2759     }
2760     
2761     int chandev_do_setup(char *buff,int size)
2762     {
2763     	int curr,comment=FALSE,newline=FALSE,oldnewline=TRUE;
2764     	char *startline=NULL,*endbuff=&buff[size];
2765     
2766     	int lineno=0;
2767     
2768     	*endbuff=0;
2769     	for(;buff<=endbuff;curr++,buff++)
2770     	{
2771     		if(*buff==0xa||*buff==0xc||*buff==0)
2772     		{
2773     			if(*buff==0xa||*buff==0)
2774     				lineno++;
2775     			*buff=0;
2776     			newline=TRUE;
2777     		}
2778     		else
2779     		{ 
2780     			newline=FALSE;
2781     			if(*buff=='#')
2782     				comment=TRUE;
2783     		}
2784     		if(comment==TRUE)
2785     			*buff=0;
2786     		if(startline==NULL&&isalpha(*buff))
2787     			startline=buff;
2788     		if(startline&&(buff>startline)&&(oldnewline==FALSE)&&(newline==TRUE))
2789     		{
2790     			if((chandev_setup(startline," on line no",lineno))==0)
2791     				return(-EINVAL);
2792     			startline=NULL;
2793     		}
2794     		if(newline)
2795     			comment=FALSE;
2796     	        oldnewline=newline;
2797     	}
2798     	return(0);
2799     }
2800     
2801     
2802     static void chandev_read_conf(void)
2803     {
2804     #define CHANDEV_FILE "/etc/chandev.conf"
2805     	struct stat statbuf;
2806     	char        *buff;
2807     	int         curr,left,len,fd;
2808     
2809     	/* if called from chandev_register_and_probe & 
2810     	   the driver is compiled into the kernel the
2811     	   parameters will need to be passed in from
2812     	   the kernel boot parameter line as the root
2813     	   fs is not mounted yet, we can't wait here.
2814     	*/
2815     	if(in_interrupt()||current->fs->root==NULL)
2816     		return;
2817     	atomic_set(&chandev_conf_read,TRUE);
2818     	set_fs(KERNEL_DS);
2819     	if(stat(CHANDEV_FILE,&statbuf)==0)
2820     	{
2821     		set_fs(USER_DS);
2822     		buff=vmalloc(statbuf.st_size+1);
2823     		if(buff)
2824     		{
2825     			set_fs(KERNEL_DS);
2826     			if((fd=open(CHANDEV_FILE,O_RDONLY,0))!=-1)
2827     			{
2828     				curr=0;
2829     				left=statbuf.st_size;
2830     				while((len=read(fd,&buff[curr],left))>0)
2831     				{
2832     					curr+=len;
2833     					left-=len;
2834     				}
2835     				close(fd);
2836     			}
2837     			set_fs(USER_DS);
2838     			chandev_do_setup(buff,statbuf.st_size);
2839     			vfree(buff);
2840     		}
2841     	}
2842     	set_fs(USER_DS);
2843     }
2844     
2845     static void chandev_read_conf_if_necessary(void)
2846     {
2847     	if(in_interrupt()||current->fs->root==NULL)
2848     		return;
2849     	if(!atomic_compare_and_swap(FALSE,TRUE,&chandev_conf_read))
2850     		chandev_read_conf();
2851     }
2852     
2853     #ifdef CONFIG_PROC_FS
2854     #define chandev_printf(exitchan,args...)     \
2855     splen=sprintf(spbuff,##args);                \
2856     spoffset+=splen;                             \
2857     if(spoffset>offset) {                        \
2858            spbuff+=splen;                        \
2859            currlen+=splen;                       \
2860     }                                            \
2861     if(currlen>=length)                          \
2862            goto exitchan;
2863     
2864     void sprintf_msck(char *buff,int auto_msck_recovery)
2865     {
2866     	chandev_msck_status idx;
2867     	int first_time=TRUE;
2868     	buff[0]=0;
2869     	for(idx=chandev_status_first_msck;idx<chandev_status_last_msck;idx++)
2870     	{
2871     		if((1<<(idx-1))&auto_msck_recovery)
2872     		{
2873     			buff+=sprintf(buff,"%s%s",(first_time ? "":","),
2874     				      msck_status_strs[idx]);
2875     			first_time=FALSE;
2876     		}
2877     	}
2878     }
2879     
2880     static int chandev_read_proc(char *page, char **start, off_t offset,
2881     			  int length, int *eof, void *data)
2882     {
2883     	char *spbuff=*start=page;
2884     	int    currlen=0,splen=0;
2885     	off_t  spoffset=0;
2886     	chandev_model_info *curr_model;
2887     	chandev_noauto_range *curr_noauto;
2888     	chandev_force *curr_force;
2889     	chandev_activelist *curr_device;
2890     	chandev_probelist  *curr_probe;
2891     	chandev_msck_range *curr_msck_range;
2892     	s390_dev_info_t   curr_devinfo;
2893     	int pass,chandevs_detected,curr_irq,loopcnt;
2894     	chandev_irqinfo *read_irqinfo,*write_irqinfo,*data_irqinfo;
2895     	char buff[3][80];    
2896     
2897     	chandev_lock();
2898     	chandev_printf(chan_exit,"\n%s\n"
2899     		       "*'s for cu/dev type/models indicate don't cares\n",chandev_keydescript);
2900     	chandev_printf(chan_exit,"\ncautious_auto_detect: %s\n",chandev_cautious_auto_detect ? "on":"off");
2901     	chandev_printf(chan_exit,"\nchandev_persistent = 0x%02x\n",chandev_persistent);
2902     #if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)
2903     	chandev_printf(chan_exit,"\nuse_devno_names: %s\n\n",chandev_use_devno_names ? "on":"off");
2904     #endif
2905     	
2906     	if(chandev_models_head)
2907     	{
2908     		chandev_printf(chan_exit,"Channels enabled for detection\n");      
2909     		chandev_printf(chan_exit,"  chan     cu      cu     dev   dev    max     checksum  use hw  auto recovery\n");
2910     		chandev_printf(chan_exit,"  type    type    model  type  model  port_no. received   stats      type\n");
2911     		chandev_printf(chan_exit,"==============================================================================\n");
2912     		for_each(curr_model,chandev_models_head)
2913     		{
2914     			
2915     			
2916     			chandev_sprint_devinfo(buff[0],curr_model->cu_type,
2917     					       curr_model->cu_model,
2918     					       curr_model->dev_type,
2919     					       curr_model->dev_model);
2920     			sprintf_msck(buff[1],curr_model->auto_msck_recovery);
2921     			chandev_printf(chan_exit,"  0x%02x  %s%3d %s     %s     %s\n",
2922     				       curr_model->chan_type,buff[0],
2923     				       (int)curr_model->max_port_no,
2924     				       curr_model->default_checksum_received_ip_pkts ? "yes":"no ",
2925     				       curr_model->default_use_hw_stats ? "yes":"no ",
2926     				       buff[1]);         
2927     		}
2928     	}
2929             
2930     	if(chandev_noauto_head)
2931     	{
2932     		chandev_printf(chan_exit,"\nNo auto devno ranges\n");
2933     		chandev_printf(chan_exit,"   From        To   \n");
2934     		chandev_printf(chan_exit,"====================\n");
2935     		for_each(curr_noauto,chandev_noauto_head)
2936     		{
2937     			chandev_printf(chan_exit,"  0x%04x     0x%04x\n",
2938     				       curr_noauto->lo_devno,
2939     				       curr_noauto->hi_devno);
2940     		}
2941     	}
2942     	if(chandev_msck_range_head)
2943     	{
2944     		
2945     		chandev_printf(chan_exit,"\nAutomatic machine check recovery devno ranges\n");
2946     		chandev_printf(chan_exit,"   From        To   automatic recovery type\n");
2947     		chandev_printf(chan_exit,"===========================================\n");
2948     		for_each(curr_msck_range,chandev_msck_range_head)
2949     		{
2950     			sprintf_msck(buff[0],curr_msck_range->auto_msck_recovery);
2951     			chandev_printf(chan_exit,"  0x%04x     0x%04x %s\n",
2952     				       curr_msck_range->lo_devno,
2953     				       curr_msck_range->hi_devno,buff[0])
2954     		}
2955     	}
2956     	if(chandev_force_head)
2957     	{
2958     		chandev_printf(chan_exit,"\nForced devices\n");
2959     		chandev_printf(chan_exit,"  chan defif read   write  data   memory      port         ip    hw   host       adapter   api\n");
2960     		chandev_printf(chan_exit,"  type  num  devno  devno  devno  usage(k) protocol no.  chksum stats name        name     name\n");
2961     		chandev_printf(chan_exit,"===============================================================================================\n");
2962     		for_each(curr_force,chandev_force_head)
2963     		{
2964     			if(curr_force->memory_usage_in_k==0)
2965     				strcpy(buff[0],"default");
2966     			else
2967     				sprintf(buff[0],"%6d",curr_force->memory_usage_in_k);
2968     			chandev_printf(chan_exit,"  0x%02x  %3d  0x%04x 0x%04x 0x%04x %7s       %3d       %1d    %1d%s",
2969     				       (int)curr_force->chan_type,(int)curr_force->devif_num,
2970     				       (int)curr_force->read_lo_devno,(int)curr_force->write_hi_devno,
2971     				       (int)curr_force->data_devno,buff[0],
2972     				       (int)curr_force->port_protocol_no,(int)curr_force->checksum_received_ip_pkts,
2973     				       (int)curr_force->use_hw_stats,curr_force->chan_type==chandev_type_claw ? "":"\n");
2974     			if(curr_force->chan_type==chandev_type_claw)
2975     			{
2976     				chandev_printf(chan_exit," %9s %9s %9s\n",
2977     					       curr_force->claw.host_name,
2978     					       curr_force->claw.adapter_name,
2979     					       curr_force->claw.api_type);
2980     			}
2981     
2982     		}
2983     	}
2984     	if(chandev_probelist_head)
2985     	{
2986     #if CONFIG_ARCH_S390X
2987     		chandev_printf(chan_exit,"\nRegistered probe functions\n"
2988     			       		 "probefunc            shutdownfunc        msck_notfunc        chan  devices devices\n"
2989                                              "                                                             type   found  active\n"
2990     			                 "==================================================================================\n");
2991     #else
2992     		chandev_printf(chan_exit,"\nRegistered probe functions\n"
2993     			                 "probefunc   shutdownfunc   msck_notfunc   chan  devices devices\n"
2994                                              "                                          type   found  active\n"
2995     			                 "===============================================================\n");
2996     #endif
2997     		for_each(curr_probe,chandev_probelist_head)
2998     		{
2999     			int devices_active=0;
3000     			for_each(curr_device,chandev_activelist_head)
3001     			{
3002     				if(curr_device->probefunc==curr_probe->probefunc)
3003     					devices_active++;
3004     			}
3005     			chandev_printf(chan_exit,"0x%p   0x%p   0x%p       0x%02x     %d      %d\n",
3006     				       curr_probe->probefunc,
3007     				       curr_probe->shutdownfunc,
3008     				       curr_probe->msck_notfunc,
3009     				       curr_probe->chan_type,
3010     				       curr_probe->devices_found,
3011     				       devices_active);
3012     		}
3013     	}
3014     	if(chandev_activelist_head)
3015     	{
3016     		unsigned long long total_memory_usage_in_k=0;
3017     		chandev_printf(chan_exit,
3018     			       "\nInitialised Devices\n"
3019     			       " read   write  data  read   write  data  chan port  dev     dev         memory   read msck    write msck    data msck\n"
3020     			       " irq     irq    irq  devno  devno  devno type no.   ptr     name        usage(k)  status       status        status\n"
3021     			       "=====================================================================================================================\n");
3022     		/* We print this list backwards for cosmetic reasons */
3023     		for(curr_device=chandev_activelist_head;
3024     		    curr_device->next!=NULL;curr_device=curr_device->next);
3025     		while(curr_device)
3026     		{
3027     			read_irqinfo=curr_device->read_irqinfo;
3028     			write_irqinfo=curr_device->write_irqinfo;
3029     			data_irqinfo=curr_device->data_irqinfo;
3030     			if(data_irqinfo)
3031     			{
3032     				sprintf(buff[0],"0x%04x",data_irqinfo->sch.irq);
3033     				sprintf(buff[1],"0x%04x",(int)data_irqinfo->sch.devno);
3034     			}
3035     			else
3036     			{
3037     				strcpy(buff[0],"  n/a ");
3038     				strcpy(buff[1],"  n/a ");
3039     			}
3040     			if(curr_device->memory_usage_in_k<0)
3041     			{
3042     				sprintf(buff[2],"%d",(int)-curr_device->memory_usage_in_k);
3043     				total_memory_usage_in_k-=curr_device->memory_usage_in_k;
3044     			}
3045     			else
3046     				strcpy(buff[2],"  n/a ");
3047     			chandev_printf(chan_exit,
3048     				       "0x%04x 0x%04x %s 0x%04x 0x%04x %s 0x%02x %2d 0x%p %-10s  %6s   %-12s %-12s %-12s\n",
3049     				       read_irqinfo->sch.irq,
3050     				       write_irqinfo->sch.irq,
3051     				       buff[0],
3052     				       (int)read_irqinfo->sch.devno,
3053     				       (int)write_irqinfo->sch.devno,
3054     				       buff[1],
3055     				       curr_device->chan_type,(int)curr_device->port_no,
3056     				       curr_device->dev_ptr,curr_device->devname,
3057     				       buff[2],
3058     				       msck_status_strs[read_irqinfo->msck_status],
3059     				       msck_status_strs[write_irqinfo->msck_status],
3060     				       data_irqinfo ? msck_status_strs[data_irqinfo->msck_status] :
3061     				       "not applicable");
3062     			get_prev((list *)chandev_activelist_head,
3063     				 (list *)curr_device,
3064     				 (list **)&curr_device);
3065     		}
3066     		chandev_printf(chan_exit,"\nTotal device memory usage %Luk.\n",total_memory_usage_in_k);
3067     	}
3068     	chandevs_detected=FALSE;
3069     	for(pass=FALSE;pass<=TRUE;pass++)
3070     	{
3071     		if(pass&&chandevs_detected)
3072     		{
3073     			chandev_printf(chan_exit,"\nchannels detected\n");
3074     			chandev_printf(chan_exit,"              chan    cu    cu   dev    dev                          in chandev\n");
3075     			chandev_printf(chan_exit,"  irq  devno  type   type  model type  model pim      chpids         use  reg.\n");
3076     			chandev_printf(chan_exit,"===============================================================================\n");
3077     		}
3078     		for(curr_irq=get_irq_first(),loopcnt=0;curr_irq>=0; curr_irq=get_irq_next(curr_irq),loopcnt++)
3079     		{
3080     			if(loopcnt>0x10000)
3081     			{
3082     				printk(KERN_ERR"chandev_read_proc detected infinite loop bug in get_irq_next\n");
3083     				goto chan_error;
3084     			}
3085     			if(chandev_is_chandev(curr_irq,&curr_devinfo,&curr_force,&curr_model))
3086     			{
3087     				schib_t *curr_schib;
3088     				curr_schib=s390_get_schib(curr_irq);
3089     				chandevs_detected=TRUE;
3090     				if(pass)
3091     				{
3092     					chandev_printf(chan_exit,"0x%04x 0x%04x 0x%02x  0x%04x 0x%02x  0x%04x 0x%02x 0x%02x 0x%016Lx  %-5s %-5s\n",
3093     						       curr_irq,curr_devinfo.devno,
3094     						       ( curr_force ? curr_force->chan_type : 
3095     						       ( curr_model ? curr_model->chan_type : 
3096     							 chandev_type_none )),
3097     						       (int)curr_devinfo.sid_data.cu_type,
3098     						       (int)curr_devinfo.sid_data.cu_model,
3099     						       (int)curr_devinfo.sid_data.dev_type,
3100     						       (int)curr_devinfo.sid_data.dev_model,
3101     						       (int)(curr_schib ? curr_schib->pmcw.pim : 0),
3102     						       *(long long *)(curr_schib ? &curr_schib->pmcw.chpid[0] : 0),
3103     						       (curr_devinfo.status&DEVSTAT_DEVICE_OWNED) ? "yes":"no ",
3104     						       (chandev_get_irqinfo_by_irq(curr_irq) ? "yes":"no "));
3105     						       
3106     						       
3107     				}
3108     					
3109     			}
3110     
3111     		}
3112     	}
3113     	if(chandev_parms_head)
3114     	{
3115     		chandev_parms      *curr_parms;
3116     
3117     		chandev_printf(chan_exit,"\n driver specific parameters\n");
3118     		chandev_printf(chan_exit,"chan    lo    hi      driver\n");
3119     		chandev_printf(chan_exit,"type  devno  devno  parameters\n");
3120     		chandev_printf(chan_exit,"=============================================================================\n");
3121     		for_each(curr_parms,chandev_parms_head)
3122     		{
3123     			chandev_printf(chan_exit,"0x%02x 0x%04x 0x%04x  %s\n",
3124     				       curr_parms->chan_type,(int)curr_parms->lo_devno,
3125     				       (int)curr_parms->hi_devno,curr_parms->parmstr);
3126     		}
3127     	}
3128      chan_error:
3129     	*eof=TRUE;
3130      chan_exit:
3131     	if(currlen>length) {
3132     		/* rewind to previous printf so that we are correctly
3133     		 * aligned if we get called to print another page.
3134                      */
3135     		currlen-=splen;
3136     	}
3137     	chandev_unlock();
3138     	return(currlen);
3139     }
3140     
3141     
3142     static int chandev_write_proc(struct file *file, const char *buffer,
3143     			   unsigned long count, void *data)
3144     {
3145     	int         rc;
3146     	char        *buff;
3147     	
3148     	buff=vmalloc(count+1);
3149     	if(buff)
3150     	{
3151     		rc = copy_from_user(buff,buffer,count);
3152     		if (rc)
3153     			goto chandev_write_exit;
3154     		chandev_do_setup(buff,count);
3155     		rc=count;
3156     	chandev_write_exit:
3157     		vfree(buff);
3158     		return rc;
3159     	}
3160     	else
3161     		return -ENOMEM;
3162     	return(0);
3163     }
3164     
3165     static void __init chandev_create_proc(void)
3166     {
3167     	struct proc_dir_entry *dir_entry=
3168     		create_proc_entry("chandev",0644,
3169     				  &proc_root);
3170     	if(dir_entry)
3171     	{
3172     		dir_entry->read_proc=&chandev_read_proc;
3173     		dir_entry->write_proc=&chandev_write_proc;
3174     	}
3175     }
3176     
3177     
3178     #endif
3179     #if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)
3180     static  
3181     #endif
3182     int __init chandev_init(void)
3183     {
3184     	atomic_set(&chandev_initialised,TRUE);
3185     	chandev_parse_args();
3186     	chandev_init_default_models();
3187     #if CONFIG_PROC_FS
3188     	chandev_create_proc();
3189     #endif
3190     	chandev_msck_task_tq.routine=
3191     		chandev_msck_task;
3192     #if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)
3193     	INIT_LIST_HEAD(&chandev_msck_task_tq.list);
3194     	chandev_msck_task_tq.sync=0;
3195     #endif
3196     	chandev_msck_task_tq.data=NULL;
3197     	chandev_last_startmsck_list_update=chandev_last_machine_check=jiffies-HZ;
3198     	atomic_set(&chandev_msck_thread_lock,1);
3199     	chandev_lock_owner=CHANDEV_INVALID_LOCK_OWNER;
3200     	chandev_lock_cnt=0;
3201     	spin_lock_init(&chandev_spinlock);
3202     	spin_lock_init(&chandev_not_oper_spinlock);
3203     	atomic_set(&chandev_new_msck,FALSE);
3204     	return(0);
3205     }
3206     #if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)
3207     __initcall(chandev_init);
3208     #endif
3209     
3210     int chandev_register_and_probe(chandev_probefunc probefunc,
3211     			       chandev_shutdownfunc shutdownfunc,
3212     			       chandev_msck_notification_func msck_notfunc,
3213     			       chandev_type chan_type)
3214     {
3215     	chandev_probelist *new_probe;
3216     	/* Avoid chicked & egg situations where we may be called before we */
3217     	/* are initialised. */
3218     
3219     	chandev_interrupt_check();
3220     	if(!atomic_compare_and_swap(FALSE,TRUE,&chandev_initialised))
3221     		chandev_init();
3222     	if((new_probe=chandev_alloc(sizeof(chandev_probelist))))
3223     	{
3224     		new_probe->probefunc=probefunc;
3225     		new_probe->shutdownfunc=shutdownfunc;
3226     		new_probe->msck_notfunc=msck_notfunc;
3227     		new_probe->chan_type=chan_type;
3228     		new_probe->devices_found=0;
3229     		chandev_add_to_list((list **)&chandev_probelist_head,new_probe);
3230     		chandev_probe();
3231     	}
3232     	return(new_probe ? new_probe->devices_found:0);
3233     }
3234     
3235     void chandev_unregister(chandev_probefunc probefunc,int call_shutdown)
3236     {
3237     	chandev_probelist *curr_probe=NULL;
3238     	chandev_activelist *curr_device,*next_device;
3239     	
3240     	chandev_interrupt_check();
3241     	chandev_lock();
3242     	for_each(curr_probe,chandev_probelist_head)
3243     	{
3244     		if(curr_probe->probefunc==probefunc)
3245     		{
3246     			for_each_allow_delete(curr_device,next_device,chandev_activelist_head)
3247     				if(curr_device->probefunc==probefunc&&call_shutdown)
3248     					chandev_shutdown(curr_device);
3249     			chandev_free_listmember((list **)&chandev_probelist_head,
3250     						(list *)curr_probe);
3251     			break;
3252     		}
3253     	}
3254     	chandev_unlock();
3255     }
3256     
3257     
3258     int chandev_persist(chandev_type chan_type)
3259     {
3260     	return((chandev_persistent&chan_type) ? TRUE:FALSE);
3261     }
3262     
3263     EXPORT_SYMBOL(chandev_register_and_probe);
3264     EXPORT_SYMBOL(chandev_request_irq);
3265     EXPORT_SYMBOL(chandev_unregister);
3266     EXPORT_SYMBOL(chandev_initdevice);
3267     EXPORT_SYMBOL(chandev_build_device_name);
3268     EXPORT_SYMBOL(chandev_initnetdevice);
3269     EXPORT_SYMBOL(chandev_init_netdev);
3270     EXPORT_SYMBOL(chandev_use_devno_names);
3271     EXPORT_SYMBOL(chandev_free_irq);
3272     EXPORT_SYMBOL(chandev_add_model);
3273     EXPORT_SYMBOL(chandev_del_model);
3274     EXPORT_SYMBOL(chandev_persist);
3275     
3276