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