1 /*
2  *  drivers/s390/misc/chandev.c
3  *
4  *    Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
5  *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
6  *
7  *  Generic channel device initialisation support.
8  */
9 #define TRUE 1
10 #define FALSE 0
11 #define __KERNEL_SYSCALLS__
12 #include <linux/module.h>
13 #include <linux/config.h>
14 #include <linux/types.h>
15 #include <linux/ctype.h>
16 #include <asm/uaccess.h>
17 #include <linux/slab.h>
18 #include <asm/irq.h>
19 #include <linux/init.h>
20 #include <linux/unistd.h>
21 #include <asm/chandev.h>
22 #include <linux/proc_fs.h>
23 #include <linux/vmalloc.h>
24 #include <asm/s390dyn.h>
25 #include <asm/queue.h>
26 #include <linux/kmod.h>
27 #ifndef MIN
28 #define MIN(a,b) ((a<b)?a:b)
29 #endif
30 #ifndef MAX
31 #define MAX(a,b) ((a>b)?a:b)
32 #endif
33 
34 
35 
36 typedef struct chandev_model_info chandev_model_info;
37 struct chandev_model_info
38 {
39 	struct chandev_model_info *next;
40 	chandev_type chan_type;
41 	s32 cu_type;      /* control unit type  -1 = don't care */
42 	s16 cu_model;     /* control unit model -1 = don't care */
43 	s32 dev_type;     /* device type -1 = don't care */
44 	s16 dev_model;    /* device model -1 = don't care */
45 	u8  max_port_no;
46 	int auto_msck_recovery;
47 	u8  default_checksum_received_ip_pkts;
48 	u8  default_use_hw_stats; /* where available e.g. lcs */
49 	devreg_t drinfo;
50 };
51 
52 typedef struct chandev chandev;
53 struct chandev
54 {
55 	struct chandev *next;
56 	chandev_model_info *model_info;
57 	chandev_subchannel_info sch;
58 	int owned;
59 };
60 
61 typedef struct chandev_noauto_range chandev_noauto_range;
62 struct chandev_noauto_range
63 {
64 	struct chandev_noauto_range *next;
65 	u16     lo_devno;
66 	u16     hi_devno;
67 };
68 
69 typedef struct chandev_force chandev_force;
70 struct chandev_force
71 {
72 	struct chandev_force *next;
73 	chandev_type chan_type;
74 	s32     devif_num; /* -1 don't care, -2 we are forcing a range e.g. tr0 implies 0 */
75         u16     read_lo_devno;
76 	u16     write_hi_devno;
77 	u16     data_devno; /* only used by gigabit ethernet */
78 	s32     memory_usage_in_k;
79         s16     port_protocol_no; /* where available e.g. lcs,-1 don't care */
80 	u8      checksum_received_ip_pkts;
81 	u8      use_hw_stats; /* where available e.g. lcs */
82 	/* claw specific stuff */
83 	chandev_claw_info  claw;
84 };
85 
86 typedef struct chandev_probelist chandev_probelist;
87 struct chandev_probelist
88 {
89 	struct chandev_probelist            *next;
90 	chandev_probefunc                   probefunc;
91 	chandev_shutdownfunc                shutdownfunc;
92 	chandev_msck_notification_func      msck_notfunc;
93 	chandev_type                        chan_type;
94 	int                                 devices_found;
95 };
96 
97 
98 
99 #define default_msck_bits ((1<<(chandev_status_not_oper-1))|(1<<(chandev_status_no_path-1))|(1<<(chandev_status_revalidate-1))|(1<<(chandev_status_gone-1)))
100 
101 
102 static char *msck_status_strs[]=
103 {
104 	"good",
105 	"not_operational",
106 	"no_path",
107 	"revalidate",
108 	"device_gone"
109 };
110 
111 typedef struct chandev_msck_range chandev_msck_range;
112 struct chandev_msck_range
113 {
114 	struct chandev_msck_range *next;
115 	u16     lo_devno;
116 	u16     hi_devno;
117 	int      auto_msck_recovery;
118 };
119 
120 static chandev_msck_range *chandev_msck_range_head=NULL;
121 
122 typedef struct chandev_irqinfo chandev_irqinfo;
123 struct chandev_irqinfo
124 {
125 	chandev_irqinfo         *next;
126 	chandev_subchannel_info sch;
127 	chandev_msck_status     msck_status;
128 	void                    (*handler)(int, void *, struct pt_regs *);
129 	unsigned long           irqflags;
130 	void                    *dev_id;
131 	char                    devname[0];
132 };
133 
134 
135 chandev_irqinfo *chandev_irqinfo_head=NULL;
136 
137 typedef struct chandev_parms chandev_parms;
138 struct chandev_parms
139 {
140 	chandev_parms      *next;
141 	chandev_type       chan_type;
142 	u16                lo_devno;
143 	u16                hi_devno;
144 	char               parmstr[0];
145 };
146 
147 static chandev_type chandev_persistent=0;
148 
149 chandev_parms *chandev_parms_head=NULL;
150 
151 
152 typedef struct chandev_activelist chandev_activelist;
153 struct chandev_activelist
154 {
155 	struct chandev_activelist        *next;
156 	chandev_irqinfo                  *read_irqinfo;
157 	chandev_irqinfo                  *write_irqinfo;
158 	chandev_irqinfo                  *data_irqinfo;
159 	chandev_probefunc                probefunc;
160 	chandev_shutdownfunc             shutdownfunc;
161 	chandev_msck_notification_func   msck_notfunc;
162 	chandev_unregfunc                unreg_dev;
163 	chandev_type                     chan_type;
164 	u8                               port_no;
165 	chandev_category                 category;
166 	s32                              memory_usage_in_k;
167 	void                             *dev_ptr;
168 	char                             devname[0];
169 };
170 
171 
172 
173 static chandev_model_info *chandev_models_head=NULL;
174 /* The only reason chandev_head is a queue is so that net devices */
175 /* will be by default named in the order of their irqs */
176 static qheader chandev_head={NULL,NULL};
177 static chandev_noauto_range *chandev_noauto_head=NULL;
178 static chandev_force *chandev_force_head=NULL;
179 static chandev_probelist *chandev_probelist_head=NULL;
180 static chandev_activelist *chandev_activelist_head=NULL;
181 #if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)
182 int chandev_use_devno_names=FALSE;
183 #endif
184 static int chandev_cautious_auto_detect=TRUE;
185 static atomic_t chandev_conf_read=ATOMIC_INIT(FALSE);
186 static atomic_t chandev_initialised=ATOMIC_INIT(FALSE);
187 
188 
189 static unsigned long chandev_last_machine_check;
190 
191 
192 static struct tq_struct chandev_msck_task_tq;
193 static atomic_t chandev_msck_thread_lock;
194 static atomic_t chandev_new_msck;
195 static unsigned long chandev_last_startmsck_list_update;
196 
197 
198 typedef enum
199 {
200 	chandev_start,
201 	chandev_first_tag=chandev_start,
202 	chandev_msck,
203 	chandev_num_notify_tags
204 } chandev_userland_notify_tag;
205 
206 static char *userland_notify_strs[]=
207 {
208 	"start",
209 	"machine_check"
210 };
211 
212 typedef struct chandev_userland_notify_list chandev_userland_notify_list;
213 struct chandev_userland_notify_list
214 {
215 	chandev_userland_notify_list    *next;
216 	chandev_userland_notify_tag      tag;
217 	chandev_msck_status              prev_status;
218 	chandev_msck_status              curr_status;
219 	char                      devname[0];
220 };
221 
222 
223 static chandev_userland_notify_list *chandev_userland_notify_head=NULL;
224 
225 
226 
227 
228 static void chandev_read_conf_if_necessary(void);
229 static void chandev_read_conf(void);
230 
231 #if LINUX_VERSION_CODE >=KERNEL_VERSION(2,3,0)
232 typedef struct net_device  net_device;
233 #else
234 typedef struct device  net_device;
235 
init_waitqueue_head(wait_queue_head_t * q)236 static inline void init_waitqueue_head(wait_queue_head_t *q)
237 {
238 	*q=NULL;
239 }
240 #endif
241 
242 #if LINUX_VERSION_CODE<KERNEL_VERSION(2,3,45)
netif_stop_queue(net_device * dev)243 static __inline__ void netif_stop_queue(net_device *dev)
244 {
245 	dev->tbusy=1;
246 }
247 
netif_start_queue(net_device * dev)248 static __inline__ void netif_start_queue(net_device *dev)
249 {
250 	dev->tbusy=0;
251 }
252 #endif
253 
254 
255 
256 #define CHANDEV_INVALID_LOCK_OWNER            -1
257 static long                 chandev_lock_owner;
258 static int                  chandev_lock_cnt;
259 static spinlock_t           chandev_spinlock;
260 #define CHANDEV_LOCK_DEBUG 0
261 #if CHANDEV_LOCK_DEBUG && !defined(CONFIG_ARCH_S390X)
262 #define CHANDEV_BACKTRACE_LOOPCNT 10
263 void                        *chandev_first_lock_addr[CHANDEV_BACKTRACE_LOOPCNT],
264 	                    *chandev_last_lock_addr[CHANDEV_BACKTRACE_LOOPCNT],
265 	                    *chandev_last_unlock_addr[CHANDEV_BACKTRACE_LOOPCNT];
266 #define CHANDEV_BACKTRACE(variable) \
267 memset((variable),0,sizeof(void *)*CHANDEV_BACKTRACE_LOOPCNT); \
268 (variable)[0]=__builtin_return_address(0); \
269 if(((long)variable[0])&0x80000000)         \
270 {                                          \
271 (variable)[1]=__builtin_return_address(1); \
272 if(((long)variable[1])&0x80000000)         \
273 {                                          \
274 (variable)[2]=__builtin_return_address(2); \
275 if(((long)variable[2])&0x80000000)         \
276 {                                          \
277 (variable)[3]=__builtin_return_address(3); \
278 if(((long)variable[3])&0x80000000)         \
279 {                                          \
280 (variable)[4]=__builtin_return_address(4); \
281 if(((long)variable[4])&0x80000000)         \
282 {                                          \
283 (variable)[5]=__builtin_return_address(5); \
284 if(((long)variable[5])&0x80000000)         \
285 {                                          \
286 (variable)[6]=__builtin_return_address(6); \
287 if(((long)variable[6])&0x80000000)         \
288 {                                          \
289 (variable)[7]=__builtin_return_address(7); \
290 if(((long)variable[7])&0x80000000)         \
291 {                                          \
292 (variable)[8]=__builtin_return_address(8); \
293 if(((long)variable[8])&0x80000000)         \
294 {                                          \
295 (variable)[9]=__builtin_return_address(9); \
296 } \
297 } \
298 } \
299 } \
300 } \
301 } \
302 } \
303 } \
304 }
305 #else
306 #define CHANDEV_BACKTRACE(variable)
307 #endif
308 
309 
310 
311 typedef struct chandev_not_oper_struct chandev_not_oper_struct;
312 
313 struct  chandev_not_oper_struct
314 {
315 	chandev_not_oper_struct *next;
316 	int irq;
317 	int status;
318 };
319 
320 
321 /* May as well try to keep machine checks in the order they happen so
322  * we use qheader for chandev_not_oper_head instead of list.
323  */
324 static qheader chandev_not_oper_head={NULL,NULL};
325 static spinlock_t           chandev_not_oper_spinlock;
326 
327 #define chandev_interrupt_check() \
328 if(in_interrupt())                \
329      printk(KERN_WARNING __FUNCTION__ " called under interrupt this shouldn't happen\n")
330 
331 
332 #define for_each(variable,head) \
333 for((variable)=(head);(variable)!=NULL;(variable)=(variable)->next)
334 
335 #define for_each_allow_delete(variable,nextmember,head) \
336 for((variable)=(head),(nextmember)=((head) ? (head)->next:NULL); \
337 (variable)!=NULL; (variable)=(nextmember),(nextmember)=((nextmember) ? (nextmember->next) : NULL))
338 
339 #define for_each_allow_delete2(variable,nextmember,head) \
340 for((variable)=(head);(variable)!=NULL;(variable)=(nextmember))
341 
342 
chandev_lock(void)343 static void chandev_lock(void)
344 {
345 	eieio();
346 	chandev_interrupt_check();
347 	if(chandev_lock_owner!=(long)current)
348 	{
349 		while(!spin_trylock(&chandev_spinlock))
350 			schedule();
351 		chandev_lock_cnt=1;
352 		chandev_lock_owner=(long)current;
353 		CHANDEV_BACKTRACE(chandev_first_lock_addr)
354 	}
355 	else
356 	{
357 		chandev_lock_cnt++;
358 		CHANDEV_BACKTRACE(chandev_last_lock_addr)
359 	}
360 	if(chandev_lock_cnt<0||chandev_lock_cnt>100)
361 	{
362 		printk("odd lock_cnt %d lcs_chan_lock",chandev_lock_cnt);
363 		chandev_lock_cnt=1;
364 	}
365 }
366 
chandev_full_unlock(void)367 static int chandev_full_unlock(void)
368 {
369 	int ret_lock_cnt=chandev_lock_cnt;
370 	chandev_lock_cnt=0;
371 	chandev_lock_owner=CHANDEV_INVALID_LOCK_OWNER;
372 	spin_unlock(&chandev_spinlock);
373 	return(ret_lock_cnt);
374 }
375 
chandev_unlock(void)376 static void chandev_unlock(void)
377 {
378 	if(chandev_lock_owner!=(long)current)
379 		printk("chandev_unlock: current=%lx"
380 		      " chandev_lock_owner=%lx chandev_lock_cnt=%d\n",
381 		      (long)current,
382 		      chandev_lock_owner,
383 		      chandev_lock_cnt);
384 	CHANDEV_BACKTRACE(chandev_last_unlock_addr)
385 	if(--chandev_lock_cnt==0)
386 	{
387 		chandev_lock_owner=CHANDEV_INVALID_LOCK_OWNER;
388 		spin_unlock(&chandev_spinlock);
389 	}
390 	if(chandev_lock_cnt<0)
391 	{
392 		printk("odd lock_cnt=%d in chan_unlock",chandev_lock_cnt);
393 		chandev_full_unlock();
394 	}
395 
396 }
397 
398 
399 
chandev_alloc(size_t size)400 void *chandev_alloc(size_t size)
401 {
402 	void *mem=kmalloc(size,GFP_ATOMIC);
403 	if(mem)
404 		memset(mem,0,size);
405 	return(mem);
406 }
407 
chandev_add_to_list(list ** listhead,void * member)408 static void chandev_add_to_list(list **listhead,void *member)
409 {
410 	chandev_lock();
411 	add_to_list(listhead,member);
412 	chandev_unlock();
413 }
414 
chandev_queuemember(qheader * qhead,void * member)415 static void chandev_queuemember(qheader *qhead,void *member)
416 {
417 	chandev_lock();
418 	enqueue_tail(qhead,(queue *)member);
419 	chandev_unlock();
420 }
421 
chandev_remove_from_list(list ** listhead,list * member)422 static int chandev_remove_from_list(list **listhead,list *member)
423 {
424 	int retval;
425 
426 	chandev_lock();
427 	retval=remove_from_list(listhead,member);
428 	chandev_unlock();
429 	return(retval);
430 }
431 
chandev_remove_from_queue(qheader * qhead,queue * member)432 static int chandev_remove_from_queue(qheader *qhead,queue *member)
433 {
434 	int retval;
435 
436 	chandev_lock();
437 	retval=remove_from_queue(qhead,member);
438 	chandev_unlock();
439 	return(retval);
440 }
441 
442 
443 
chandev_free_listmember(list ** listhead,list * member)444 void chandev_free_listmember(list **listhead,list *member)
445 {
446 	chandev_lock();
447 	if(member)
448 	{
449 		if(chandev_remove_from_list(listhead,member))
450 			kfree(member);
451 		else
452 			printk(KERN_CRIT"chandev_free_listmember detected nonexistant"
453 			       "listmember listhead=%p member %p\n",listhead,member);
454 	}
455 	chandev_unlock();
456 }
457 
chandev_free_queuemember(qheader * qhead,queue * member)458 void chandev_free_queuemember(qheader *qhead,queue *member)
459 {
460 	chandev_lock();
461 	if(member)
462 	{
463 		if(chandev_remove_from_queue(qhead,member))
464 			kfree(member);
465 		else
466 			printk(KERN_CRIT"chandev_free_queuemember detected nonexistant"
467 			       "queuemember qhead=%p member %p\n",qhead,member);
468 	}
469 	chandev_unlock();
470 }
471 
472 
473 
chandev_free_all_list(list ** listhead)474 void chandev_free_all_list(list **listhead)
475 {
476 	list *head;
477 
478 	chandev_lock();
479 	while((head=remove_listhead(listhead)))
480 		kfree(head);
481 	chandev_unlock();
482 }
483 
chandev_free_all_queue(qheader * qhead)484 void chandev_free_all_queue(qheader *qhead)
485 {
486 	chandev_lock();
487 	while(qhead->head)
488 		chandev_free_queuemember(qhead,qhead->head);
489 	chandev_unlock();
490 }
491 
chandev_wait_for_root_fs(void)492 static void chandev_wait_for_root_fs(void)
493 {
494 	wait_queue_head_t      wait;
495 
496 	init_waitqueue_head(&wait);
497 	/* We need to wait till there is a root filesystem */
498 	while(init_task.fs->root==NULL)
499 	{
500 		sleep_on_timeout(&wait,HZ);
501 	}
502 }
503 
504 /* We are now hotplug compliant i.e. */
505 /* we typically get called in /sbin/hotplug chandev our parameters */
chandev_exec_start_script(void * unused)506 static int chandev_exec_start_script(void *unused)
507 {
508 
509 	char **argv,*tempname;
510 	int retval=-ENOMEM;
511 	int argc,loopcnt;
512 	size_t allocsize;
513 	chandev_userland_notify_list *member;
514 	wait_queue_head_t      wait;
515 	int                    have_tag[chandev_num_notify_tags]={FALSE,};
516 	chandev_userland_notify_tag tagidx;
517 	static char * envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
518 
519 	init_waitqueue_head(&wait);
520 	strcpy(current->comm,"chandev_script");
521 
522 	for(loopcnt=0;loopcnt<10&&(jiffies-chandev_last_startmsck_list_update)<HZ;loopcnt++)
523 	{
524 		sleep_on_timeout(&wait,HZ);
525 	}
526 	if(!chandev_userland_notify_head)
527 		return(0);
528 	chandev_lock();
529 	argc=2;
530 	for(tagidx=chandev_first_tag;tagidx<chandev_num_notify_tags;tagidx++)
531 	{
532 		for_each(member,chandev_userland_notify_head)
533 		{
534 			if(member->tag==tagidx)
535 			{
536 				switch(tagidx)
537 				{
538 				case chandev_start:
539 					argc++;
540 					break;
541 				case chandev_msck:
542 					argc+=3;
543 					break;
544 				default:
545 				}
546 				if(have_tag[tagidx]==FALSE)
547 					argc++;
548 				have_tag[tagidx]=TRUE;
549 
550 			}
551 		}
552 	}
553 	allocsize=(argc+1)*sizeof(char *);
554         /* Warning possible stack overflow */
555 	/* We can't kmalloc the parameters here as execve will */
556 	/* not return if successful */
557 	argv=alloca(allocsize);
558 	if(argv)
559 	{
560 		memset(argv,0,allocsize);
561 		argv[0]=hotplug_path;
562 		argv[1]="chandev";
563 		argc=2;
564 		for(tagidx=chandev_first_tag;tagidx<chandev_num_notify_tags;tagidx++)
565 		{
566 			if(have_tag[tagidx])
567 			{
568 				argv[argc++]=userland_notify_strs[tagidx];
569 				for_each(member,chandev_userland_notify_head)
570 				{
571 					if(member->tag==tagidx)
572 					{
573 						tempname=alloca(strlen(member->devname)+1);
574 						if(tempname)
575 						{
576 							strcpy(tempname,member->devname);
577 							argv[argc++]=tempname;
578 						}
579 						else
580 							goto Fail;
581 						if(member->tag==chandev_msck)
582 						{
583 							argv[argc++]=msck_status_strs[member->prev_status];
584 							argv[argc++]=msck_status_strs[member->curr_status];
585 						}
586 					}
587 				}
588 			}
589 		}
590 		chandev_free_all_list((list **)&chandev_userland_notify_head);
591 		chandev_unlock();
592 		chandev_wait_for_root_fs();
593 		/* We are basically execve'ing here there normally is no */
594 		/* return */
595 		retval=exec_usermodehelper(hotplug_path, argv, envp);
596 		goto Fail2;
597 	}
598  Fail:
599 
600 	chandev_unlock();
601  Fail2:
602 	return(retval);
603 }
604 
605 
chandev_allocstr(const char * str,size_t offset)606 void *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 
chandev_add_to_userland_notify_list(chandev_userland_notify_tag tag,char * devname,chandev_msck_status prev_status,chandev_msck_status curr_status)618 static int chandev_add_to_userland_notify_list(chandev_userland_notify_tag tag,
619 char *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 
chandev_oper_func(int irq,devreg_t * dreg)661 int 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 
chandev_not_oper_handler(int irq,int status)672 static 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 
chandev_get_irqinfo_by_irq(int irq)695 chandev_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 
chandev_get_by_irq(int irq)704 chandev *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 
chandev_get_activelist_by_irq(int irq)716 chandev_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 
chandev_remove_irqinfo_by_irq(unsigned int irq)731 void 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 
chandev_add_schib_info(int irq,chandev_subchannel_info * sch)765 int 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 
chandev_request_irq(unsigned int irq,void (* handler)(int,void *,struct pt_regs *),unsigned long irqflags,const char * devname,void * dev_id)778 int 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. */
chandev_free_irq(unsigned int irq,void * dev_id)834 void 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 */
chandev_free_irq_by_irqinfo(chandev_irqinfo * irqinfo)852 void 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 
chandev_sprint_type_model(char * buff,s32 type,s16 model)860 void 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 
chandev_sprint_devinfo(char * buff,s32 cu_type,s16 cu_model,s32 dev_type,s16 dev_model)873 void 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 
chandev_remove_parms(chandev_type chan_type,int exact_match,int lo_devno)879 void 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 
chandev_add_parms(chandev_type chan_type,u16 lo_devno,u16 hi_devno,char * parmstr)895 void 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 
chandev_add_model(chandev_type chan_type,s32 cu_type,s16 cu_model,s32 dev_type,s16 dev_model,u8 max_port_no,int auto_msck_recovery,u8 default_checksum_received_ip_pkts,u8 default_use_hw_stats)917 void 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 
chandev_remove(chandev * member)972 void chandev_remove(chandev *member)
973 {
974 	chandev_free_queuemember(&chandev_head,(queue *)member);
975 }
976 
977 
chandev_remove_all(void)978 void chandev_remove_all(void)
979 {
980 	chandev_free_all_queue(&chandev_head);
981 }
982 
chandev_remove_model(chandev_model_info * model)983 void 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 
chandev_remove_all_models(void)997 void 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 
chandev_del_model(s32 cu_type,s16 cu_model,s32 dev_type,s16 dev_model)1005 void 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 
chandev_init_default_models(void)1019 static 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 
chandev_del_noauto(u16 devno)1047 void 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 
chandev_del_msck(u16 devno)1057 void 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 
chandev_add(s390_dev_info_t * newdevinfo,chandev_model_info * newmodelinfo)1068 void 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 
chandev_unregister_probe(chandev_probefunc probefunc)1087 void 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 
chandev_unregister_probe_by_chan_type(chandev_type chan_type)1099 void 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 
chandev_reset(void)1113 void 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 
chandev_is_chandev(int irq,s390_dev_info_t * devinfo,chandev_force ** forceinfo,chandev_model_info ** ret_model)1129 int 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 
chandev_collect_devices(void)1179 void 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 
chandev_add_force(chandev_type chan_type,s32 devif_num,u16 read_lo_devno,u16 write_hi_devno,u16 data_devno,s32 memory_usage_in_k,s16 port_protocol_no,u8 checksum_received_ip_pkts,u8 use_hw_stats,char * host_name,char * adapter_name,char * api_type)1207 int chandev_add_force(chandev_type chan_type,s32 devif_num,u16 read_lo_devno,
1208 u16 write_hi_devno,u16 data_devno,s32 memory_usage_in_k,s16 port_protocol_no,u8 checksum_received_ip_pkts,
1209 u8 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 
chandev_del_force(int read_lo_devno)1257 void 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 
chandev_shutdown(chandev_activelist * curr_device)1272 void 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 
chandev_shutdown_all(void)1306 void chandev_shutdown_all(void)
1307 {
1308 	while(chandev_activelist_head)
1309 		chandev_shutdown(chandev_activelist_head);
1310 }
chandev_shutdown_by_name(char * devname)1311 void 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 
chandev_active(u16 devno)1325 static 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 
chandev_shutdown_by_devno(u16 devno)1339 void 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 
chandev_pack_args(char * str)1351 int 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 
1383 typedef enum
1384 {
1385 	isnull=0,
1386 	isstr=1,
1387 	isnum=2,
1388 	iscomma=4,
1389 } chandev_strval;
1390 
chandev_strcmp(char * teststr,char ** str,long * endlong)1391 chandev_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 
chandev_initdevice(chandev_probeinfo * probeinfo,void * dev_ptr,u8 port_no,char * devname,chandev_category category,chandev_unregfunc unreg_dev)1417 int 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 
chandev_build_device_name(chandev_probeinfo * probeinfo,char * destnamebuff,char * basename,int buildfullname)1469 char *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)
chandev_init_netdev(chandev_probeinfo * probeinfo,char * basename,struct net_device * dev,int sizeof_priv,struct net_device * (* init_netdevfunc)(struct net_device * dev,int sizeof_priv))1513 struct net_device *chandev_init_netdev(chandev_probeinfo *probeinfo,char *basename,
1514 struct net_device *dev, int sizeof_priv,
1515 struct net_device *(*init_netdevfunc)(struct net_device *dev, int sizeof_priv))
1516 #else
1517 struct device *chandev_init_netdev(chandev_probeinfo *probeinfo,char *basename,
1518 struct device *dev, int sizeof_priv,
1519 struct 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)
chandev_initnetdevice(chandev_probeinfo * probeinfo,u8 port_no,struct net_device * dev,int sizeof_priv,char * basename,struct net_device * (* init_netdevfunc)(struct net_device * dev,int sizeof_priv),void (* unreg_netdevfunc)(struct net_device * dev))1578 struct net_device *chandev_initnetdevice(chandev_probeinfo *probeinfo,u8 port_no,
1579 struct net_device *dev, int sizeof_priv, char *basename,
1580 struct net_device *(*init_netdevfunc)(struct net_device *dev, int sizeof_priv),
1581 void (*unreg_netdevfunc)(struct net_device *dev))
1582 #else
1583 struct device *chandev_initnetdevice(chandev_probeinfo *probeinfo,u8 port_no,
1584 struct device *dev, int sizeof_priv, char *basename,
1585 struct device *(*init_netdevfunc)(struct device *dev, int sizeof_priv),
1586 void (*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 
chandev_compare_chpid_info(chandev_subchannel_info * chan1,chandev_subchannel_info * chan2)1622 int 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 
chandev_compare_cu_dev_info(chandev_subchannel_info * chan1,chandev_subchannel_info * chan2)1627 int 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 
chandev_compare_subchannel_info(chandev_subchannel_info * chan1,chandev_subchannel_info * chan2)1635 int 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 
chandev_doprobe(chandev_force * force,chandev * read,chandev * write,chandev * data)1647 int chandev_doprobe(chandev_force *force,chandev *read,
1648 chandev *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 
chandev_request_irq_from_irqinfo(chandev_irqinfo * irqinfo,chandev * this_chandev)1788 int 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 
chandev_irqallocerr(chandev_irqinfo * irqinfo,int err)1804 void 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 
chandev_call_notification_func(chandev_activelist * curr_device,chandev_irqinfo * curr_irqinfo,chandev_msck_status prevstatus)1810 void chandev_call_notification_func(chandev_activelist *curr_device,chandev_irqinfo *curr_irqinfo,
1811 chandev_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 
chandev_find_eligible_channels(chandev * first_chandev_to_check,chandev ** read,chandev ** write,chandev ** data,chandev ** next,chandev_type chan_type)1845 int 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 
chandev_get_free_chandev_by_devno(int devno)1912 chandev *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 
chandev_probe(void)1929 void 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 
chandev_not_oper_func(int irq,int status)2096 static 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 
chandev_msck_thread(void * unused)2136 static 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 
chandev_msck_task(void * unused)2175 static 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 
2186 static 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 
2221 typedef 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 
chandev_add_noauto(u16 lo_devno,u16 hi_devno)2259 void 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 
chandev_add_msck_range(u16 lo_devno,u16 hi_devno,int auto_msck_recovery)2272 void 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 
2287 static 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 */
2293 typedef long chandev_int;
2294 #else
2295 typedef 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  */
chandev_get_option(char ** str,chandev_int * pint)2309 static 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 
chandev_get_options(char * str,int nints,chandev_int * ints)2325 static 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  */
chandev_get_string(char ** instr,char ** outstr)2352 static 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 
chandev_setup(int in_read_conf,char * instr,char * errstr,int lineno)2381 static 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 				break;
2474 			case del_auto_msck_stridx*stridx_mult:
2475 			case (del_auto_msck_stridx*stridx_mult)|iscomma:
2476 				switch(ints[0])
2477 				{
2478 				case 0:
2479 					chandev_free_all_list((list **)&chandev_msck_range_head);
2480 					break;
2481 				case 1:
2482 					chandev_del_msck(ints[1]);
2483 				default:
2484 					goto BadArgs;
2485 				}
2486 				break;
2487 			case del_noauto_stridx*stridx_mult:
2488 				chandev_free_all_list((list **)&chandev_noauto_head);
2489 				break;
2490 			case (del_noauto_stridx*stridx_mult)|iscomma:
2491 				if(ints[0]==1)
2492 					chandev_del_noauto(ints[1]);
2493 				else
2494 					goto BadArgs;
2495 				break;
2496 			case (qeth_stridx*stridx_mult)|isnum|iscomma:
2497 				if(ints[0]<3||ints[0]>7)
2498 					goto BadArgs;
2499 				chandev_add_force(chandev_type_qeth,endlong,ints[1],ints[2],
2500 						  ints[3],ints[4],ints[5],ints[6],ints[7],
2501 						  NULL,NULL,NULL);
2502 				break;
2503 			case (ctc_stridx*stridx_mult)|isnum|iscomma:
2504 			case (escon_stridx*stridx_mult)|isnum|iscomma:
2505 			case (lcs_stridx*stridx_mult)|isnum|iscomma:
2506 			case (osad_stridx*stridx_mult)|isnum|iscomma:
2507 			case (ctc_stridx*stridx_mult)|iscomma:
2508 			case (escon_stridx*stridx_mult)|iscomma:
2509 			case (lcs_stridx*stridx_mult)|iscomma:
2510 			case (osad_stridx*stridx_mult)|iscomma:
2511 				switch(val&~(isnum|iscomma))
2512 				{
2513 				case (ctc_stridx*stridx_mult):
2514 					chan_type=chandev_type_ctc;
2515 					break;
2516 				case (escon_stridx*stridx_mult):
2517 					chan_type=chandev_type_escon;
2518 					break;
2519 				case (lcs_stridx*stridx_mult):
2520 					chan_type=chandev_type_lcs;
2521 					break;
2522 				case (osad_stridx*stridx_mult):
2523 					chan_type=chandev_type_osad;
2524 					break;
2525 				case (qeth_stridx*stridx_mult):
2526 					chan_type=chandev_type_qeth;
2527 					break;
2528 				default:
2529 					goto BadArgs;
2530 				}
2531 				if((val&isnum)==0)
2532 					endlong=-2;
2533 				if(ints[0]<2||ints[0]>6)
2534 					goto BadArgs;
2535 				chandev_add_force(chan_type,endlong,ints[1],ints[2],
2536 						  0,ints[3],ints[4],ints[5],ints[6],
2537 						  NULL,NULL,NULL);
2538 				break;
2539 			case (claw_stridx*stridx_mult)|isnum|iscomma:
2540 			case (claw_stridx*stridx_mult)|iscomma:
2541 				if(ints[0]>=2&&ints[0]<=5)
2542 				{
2543 					char    *host_name,*adapter_name,*api_type;
2544 					char    *clawstr=alloca(strlen(currstr)+1);
2545 
2546 					strcpy(clawstr,currstr);
2547 					if(!(chandev_get_string(&clawstr,&host_name)==2&&
2548 					     chandev_get_string(&clawstr,&adapter_name)==2&&
2549 					     chandev_get_string(&clawstr,&api_type)==1&&
2550 					     chandev_add_force(chandev_type_claw,
2551 							       endlong,ints[1],ints[2],0,
2552 							       ints[3],0,ints[4],ints[5],
2553 							       host_name,adapter_name,api_type)==0))
2554 						goto BadArgs;
2555 
2556 				}
2557 				else
2558 					goto BadArgs;
2559 				break;
2560 			case (del_parms_stridx*stridx_mult):
2561 				ints[1]=-1;
2562 			case (del_parms_stridx*stridx_mult)|iscomma:
2563 				if(ints[0]==0)
2564 					ints[1]=-1;
2565 				if(ints[0]<=1)
2566 					ints[2]=FALSE;
2567 				if(ints[0]<=2)
2568 					ints[3]=-1;
2569 				if(ints[0]>3)
2570 					goto BadArgs;
2571 				chandev_remove_parms(ints[1],ints[2],ints[3]);
2572 				break;
2573 			case (del_force_stridx*stridx_mult)|iscomma:
2574 				if(ints[0]!=1)
2575 					goto BadArgs;
2576 				chandev_del_force(ints[1]);
2577 				break;
2578 			case (del_force_stridx*stridx_mult):
2579 				chandev_del_force(-1);
2580 				break;
2581 #if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)
2582 			case (use_devno_names_stridx*stridx_mult):
2583 				chandev_use_devno_names=TRUE;
2584 				break;
2585 			case (dont_use_devno_names_stridx*stridx_mult):
2586 				chandev_use_devno_names=FALSE;
2587 				break;
2588 #endif
2589 			case (cautious_auto_detect_stridx*stridx_mult):
2590 				chandev_cautious_auto_detect=TRUE;
2591 				break;
2592 			case (non_cautious_auto_detect_stridx*stridx_mult):
2593 				chandev_cautious_auto_detect=FALSE;
2594 				break;
2595 			case (add_model_stridx*stridx_mult)|iscomma:
2596 				if(ints[0]<3)
2597 					goto BadArgs;
2598 				if(ints[0]==3)
2599 					ints[4]=-1;
2600 				if(ints[0]<=4)
2601 					ints[5]=-1;
2602 				if(ints[0]<=5)
2603 					ints[6]=-1;
2604 				if(ints[0]<=6)
2605 					ints[7]=default_msck_bits;
2606 				if(ints[0]<=7)
2607 					ints[8]=FALSE;
2608 				if(ints[0]<=8)
2609 					ints[9]=FALSE;
2610 				ints[0]=7;
2611 				chandev_add_model(ints[1],ints[2],ints[3],
2612 						  ints[4],ints[5],ints[6],ints[7],ints[8],ints[9]);
2613 				break;
2614 			case (del_model_stridx*stridx_mult)|iscomma:
2615 				if(ints[0]<2||ints[0]>4)
2616 					goto BadArgs;
2617 				if(ints[0]<3)
2618 					ints[3]=-2;
2619 				if(ints[0]<4)
2620 					ints[4]=-2;
2621 				ints[0]=4;
2622 				chandev_del_model(ints[1],ints[2],ints[3],ints[4]);
2623 				break;
2624 			case del_all_models_stridx*stridx_mult:
2625 				chandev_remove_all_models();
2626 				break;
2627 			case reset_conf_stridx*stridx_mult:
2628 				chandev_reset();
2629 				chandev_init_default_models();
2630 				break;
2631 			case reset_conf_clean_stridx*stridx_mult:
2632 				chandev_reset();
2633 				break;
2634 			case shutdown_stridx*stridx_mult:
2635 				chandev_shutdown_all();
2636 				break;
2637 			case (shutdown_stridx*stridx_mult)|iscomma:
2638 				switch(ints[0])
2639 				{
2640 				case 0:
2641 					if(strlen(str))
2642 						chandev_shutdown_by_name(str);
2643 					else
2644 						goto BadArgs;
2645 					break;
2646 				case 1:
2647 					chandev_shutdown_by_devno(ints[1]);
2648 					break;
2649 				default:
2650 					goto BadArgs;
2651 				}
2652 				break;
2653 			case reprobe_stridx*stridx_mult:
2654 				chandev_probe();
2655 				break;
2656 			case unregister_probe_stridx*stridx_mult:
2657 				chandev_free_all_list((list **)&chandev_probelist_head);
2658 				break;
2659 			case (unregister_probe_stridx*stridx_mult)|iscomma:
2660 				if(ints[0]!=1)
2661 					goto BadArgs;
2662 				chandev_unregister_probe((chandev_probefunc)ints[1]);
2663 				break;
2664 			case (unregister_probe_by_chan_type_stridx*stridx_mult)|iscomma:
2665 				if(ints[0]!=1)
2666 					goto BadArgs;
2667 				chandev_unregister_probe_by_chan_type((chandev_type)ints[1]);
2668 				break;
2669 			case read_conf_stridx*stridx_mult:
2670 				if(in_read_conf)
2671 				{
2672 					printk("attempt to recursively call read_conf\n");
2673 					goto BadArgs;
2674 				}
2675 				chandev_read_conf();
2676 				break;
2677 			case dont_read_conf_stridx*stridx_mult:
2678 				atomic_set(&chandev_conf_read,TRUE);
2679 				break;
2680 			case (persist_stridx*stridx_mult)|iscomma:
2681 				if(ints[0]==1)
2682 					chandev_persistent=ints[1];
2683 				else
2684 					goto BadArgs;
2685 				break;
2686 			default:
2687 				goto BadArgs;
2688 			}
2689 		}
2690 		else
2691 			goto BadArgs;
2692 	NextOption:
2693 		if(cnt<strcnt)
2694 		{
2695 			/* eat up stuff till next string */
2696 			while(*(currstr++));
2697 		}
2698 	}
2699 	retval=1;
2700  BadArgs:
2701 	if(!retval)
2702 	{
2703 		printk("chandev_setup %s %s",(val==0 ? "unknown verb":"bad argument"),instr);
2704 		if(errstr)
2705 		{
2706 			printk("%s %d interpreted as %s",errstr,lineno,interpretstr);
2707 			if(strcnt>1)
2708 			{
2709 				if(cnt==strcnt)
2710 					printk(" after the last semicolon\n");
2711 				else
2712 					printk(" before semicolon no %d",cnt);
2713 			}
2714 		}
2715 		printk(".\n Type man chandev for more info.\n\n");
2716 	}
2717 	return(retval);
2718 }
2719 #define CHANDEV_KEYWORD "chandev="
chandev_setup_bootargs(char * str,int paramno)2720 static int chandev_setup_bootargs(char *str,int paramno)
2721 {
2722 	int len;
2723 
2724 	char *copystr;
2725 	for(len=0;str[len]!=0&&!isspace(str[len]);len++);
2726 	copystr=alloca(len+1);
2727 	strncpy(copystr,str,len);
2728 	copystr[len]=0;
2729 	if(chandev_setup(FALSE,copystr,"at "CHANDEV_KEYWORD" bootparam no",paramno)==0)
2730 		return(0);
2731 	return(len);
2732 
2733 }
2734 
2735 /*
2736   We can't parse using a __setup function as kmalloc isn't available
2737   at this time.
2738  */
chandev_parse_args(void)2739 static void __init chandev_parse_args(void)
2740 {
2741 #define CHANDEV_KEYWORD "chandev="
2742 	extern char saved_command_line[];
2743 	int cnt,len,paramno=1;
2744 
2745 	len=strlen(saved_command_line)-sizeof(CHANDEV_KEYWORD);
2746 	for(cnt=0;cnt<len;cnt++)
2747 	{
2748 		if(strncmp(&saved_command_line[cnt],CHANDEV_KEYWORD,
2749 			   sizeof(CHANDEV_KEYWORD)-1)==0)
2750 		{
2751 			cnt+=(sizeof(CHANDEV_KEYWORD)-1);
2752 			cnt+=chandev_setup_bootargs(&saved_command_line[cnt],paramno);
2753 			paramno++;
2754 		}
2755 	}
2756 }
2757 
chandev_do_setup(int in_read_conf,char * buff,int size)2758 int chandev_do_setup(int in_read_conf,char *buff,int size)
2759 {
2760 	int curr,comment=FALSE,newline=FALSE,oldnewline=TRUE;
2761 	char *startline=NULL,*endbuff=&buff[size];
2762 
2763 	int lineno=0;
2764 
2765 	*endbuff=0;
2766 	for(;buff<=endbuff;curr++,buff++)
2767 	{
2768 		if(*buff==0xa||*buff==0xc||*buff==0)
2769 		{
2770 			if(*buff==0xa||*buff==0)
2771 				lineno++;
2772 			*buff=0;
2773 			newline=TRUE;
2774 		}
2775 		else
2776 		{
2777 			newline=FALSE;
2778 			if(*buff=='#')
2779 				comment=TRUE;
2780 		}
2781 		if(comment==TRUE)
2782 			*buff=0;
2783 		if(startline==NULL&&isalpha(*buff))
2784 			startline=buff;
2785 		if(startline&&(buff>startline)&&(oldnewline==FALSE)&&(newline==TRUE))
2786 		{
2787 			if((chandev_setup(in_read_conf,startline," on line no",lineno))==0)
2788 				return(-EINVAL);
2789 			startline=NULL;
2790 		}
2791 		if(newline)
2792 			comment=FALSE;
2793 	        oldnewline=newline;
2794 	}
2795 	return(0);
2796 }
2797 
2798 
chandev_read_conf(void)2799 static void chandev_read_conf(void)
2800 {
2801 #define CHANDEV_FILE "/etc/chandev.conf"
2802 	struct stat statbuf;
2803 	char        *buff;
2804 	int         curr,left,len,fd;
2805 	mm_segment_t oldfs;
2806 
2807 	/* if called from chandev_register_and_probe &
2808 	   the driver is compiled into the kernel the
2809 	   parameters will need to be passed in from
2810 	   the kernel boot parameter line as the root
2811 	   fs is not mounted yet, we can't wait here.
2812 	*/
2813 	if(in_interrupt()||current->fs->root==NULL)
2814 		return;
2815 	atomic_set(&chandev_conf_read,TRUE);
2816 	oldfs = get_fs();
2817 	set_fs(KERNEL_DS);
2818 	if(stat(CHANDEV_FILE,&statbuf)==0)
2819 	{
2820 		set_fs(USER_DS);
2821 		buff=vmalloc(statbuf.st_size+1);
2822 		if(buff)
2823 		{
2824 			set_fs(KERNEL_DS);
2825 			if((fd=open(CHANDEV_FILE,O_RDONLY,0))!=-1)
2826 			{
2827 				curr=0;
2828 				left=statbuf.st_size;
2829 				while((len=read(fd,&buff[curr],left))>0)
2830 				{
2831 					curr+=len;
2832 					left-=len;
2833 				}
2834 				close(fd);
2835 			}
2836 			set_fs(USER_DS);
2837 			chandev_do_setup(TRUE,buff,statbuf.st_size);
2838 			vfree(buff);
2839 		}
2840 	}
2841 	set_fs(oldfs);
2842 }
2843 
chandev_read_conf_if_necessary(void)2844 static void chandev_read_conf_if_necessary(void)
2845 {
2846 	if(in_interrupt()||current->fs->root==NULL)
2847 		return;
2848 	if(!atomic_compare_and_swap(FALSE,TRUE,&chandev_conf_read))
2849 		chandev_read_conf();
2850 }
2851 
2852 #ifdef CONFIG_PROC_FS
2853 #define chandev_printf(exitchan,args...)     \
2854 splen=sprintf(spbuff,##args);                \
2855 spoffset+=splen;                             \
2856 if(spoffset>offset) {                        \
2857        spbuff+=splen;                        \
2858        currlen+=splen;                       \
2859 }                                            \
2860 if(currlen>=length)                          \
2861        goto exitchan;
2862 
sprintf_msck(char * buff,int auto_msck_recovery)2863 void sprintf_msck(char *buff,int auto_msck_recovery)
2864 {
2865 	chandev_msck_status idx;
2866 	int first_time=TRUE;
2867 	buff[0]=0;
2868 	for(idx=chandev_status_first_msck;idx<chandev_status_last_msck;idx++)
2869 	{
2870 		if((1<<(idx-1))&auto_msck_recovery)
2871 		{
2872 			buff+=sprintf(buff,"%s%s",(first_time ? "":","),
2873 				      msck_status_strs[idx]);
2874 			first_time=FALSE;
2875 		}
2876 	}
2877 }
2878 
chandev_read_proc(char * page,char ** start,off_t offset,int length,int * eof,void * data)2879 static int chandev_read_proc(char *page, char **start, off_t offset,
2880 			  int length, int *eof, void *data)
2881 {
2882 	char *spbuff=*start=page;
2883 	int    currlen=0,splen=0;
2884 	off_t  spoffset=0;
2885 	chandev_model_info *curr_model;
2886 	chandev_noauto_range *curr_noauto;
2887 	chandev_force *curr_force;
2888 	chandev_activelist *curr_device;
2889 	chandev_probelist  *curr_probe;
2890 	chandev_msck_range *curr_msck_range;
2891 	s390_dev_info_t   curr_devinfo;
2892 	int pass,chandevs_detected,curr_irq,loopcnt;
2893 	chandev_irqinfo *read_irqinfo,*write_irqinfo,*data_irqinfo;
2894 	char buff[3][80];
2895 
2896 	chandev_lock();
2897 	chandev_printf(chan_exit,"\n%s\n"
2898 		       "*'s for cu/dev type/models indicate don't cares\n",chandev_keydescript);
2899 	chandev_printf(chan_exit,"\ncautious_auto_detect: %s\n",chandev_cautious_auto_detect ? "on":"off");
2900 	chandev_printf(chan_exit,"\npersist = 0x%02x\n",chandev_persistent);
2901 #if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)
2902 	chandev_printf(chan_exit,"\nuse_devno_names: %s\n\n",chandev_use_devno_names ? "on":"off");
2903 #endif
2904 
2905 	if(chandev_models_head)
2906 	{
2907 		chandev_printf(chan_exit,"Channels enabled for detection\n");
2908 		chandev_printf(chan_exit,"  chan     cu      cu     dev   dev    max     checksum  use hw  auto recovery\n");
2909 		chandev_printf(chan_exit,"  type    type    model  type  model  port_no. received   stats      type\n");
2910 		chandev_printf(chan_exit,"==============================================================================\n");
2911 		for_each(curr_model,chandev_models_head)
2912 		{
2913 
2914 
2915 			chandev_sprint_devinfo(buff[0],curr_model->cu_type,
2916 					       curr_model->cu_model,
2917 					       curr_model->dev_type,
2918 					       curr_model->dev_model);
2919 			sprintf_msck(buff[1],curr_model->auto_msck_recovery);
2920 			chandev_printf(chan_exit,"  0x%02x  %s%3d %s     %s     %s\n",
2921 				       curr_model->chan_type,buff[0],
2922 				       (int)curr_model->max_port_no,
2923 				       curr_model->default_checksum_received_ip_pkts ? "yes":"no ",
2924 				       curr_model->default_use_hw_stats ? "yes":"no ",
2925 				       buff[1]);
2926 		}
2927 	}
2928 
2929 	if(chandev_noauto_head)
2930 	{
2931 		chandev_printf(chan_exit,"\nNo auto devno ranges\n");
2932 		chandev_printf(chan_exit,"   From        To   \n");
2933 		chandev_printf(chan_exit,"====================\n");
2934 		for_each(curr_noauto,chandev_noauto_head)
2935 		{
2936 			chandev_printf(chan_exit,"  0x%04x     0x%04x\n",
2937 				       curr_noauto->lo_devno,
2938 				       curr_noauto->hi_devno);
2939 		}
2940 	}
2941 	if(chandev_msck_range_head)
2942 	{
2943 
2944 		chandev_printf(chan_exit,"\nAutomatic machine check recovery devno ranges\n");
2945 		chandev_printf(chan_exit,"   From        To   automatic recovery type\n");
2946 		chandev_printf(chan_exit,"===========================================\n");
2947 		for_each(curr_msck_range,chandev_msck_range_head)
2948 		{
2949 			sprintf_msck(buff[0],curr_msck_range->auto_msck_recovery);
2950 			chandev_printf(chan_exit,"  0x%04x     0x%04x %s\n",
2951 				       curr_msck_range->lo_devno,
2952 				       curr_msck_range->hi_devno,buff[0])
2953 		}
2954 	}
2955 	if(chandev_force_head)
2956 	{
2957 		chandev_printf(chan_exit,"\nForced devices\n");
2958 		chandev_printf(chan_exit,"  chan defif read   write  data   memory      port         ip    hw   host       adapter   api\n");
2959 		chandev_printf(chan_exit,"  type  num  devno  devno  devno  usage(k) protocol no.  chksum stats name        name     name\n");
2960 		chandev_printf(chan_exit,"===============================================================================================\n");
2961 		for_each(curr_force,chandev_force_head)
2962 		{
2963 			if(curr_force->memory_usage_in_k==0)
2964 				strcpy(buff[0],"default");
2965 			else
2966 				sprintf(buff[0],"%6d",curr_force->memory_usage_in_k);
2967 			chandev_printf(chan_exit,"  0x%02x  %3d  0x%04x 0x%04x 0x%04x %7s       %3d       %1d    %1d%s",
2968 				       (int)curr_force->chan_type,(int)curr_force->devif_num,
2969 				       (int)curr_force->read_lo_devno,(int)curr_force->write_hi_devno,
2970 				       (int)curr_force->data_devno,buff[0],
2971 				       (int)curr_force->port_protocol_no,(int)curr_force->checksum_received_ip_pkts,
2972 				       (int)curr_force->use_hw_stats,curr_force->chan_type==chandev_type_claw ? "":"\n");
2973 			if(curr_force->chan_type==chandev_type_claw)
2974 			{
2975 				chandev_printf(chan_exit," %9s %9s %9s\n",
2976 					       curr_force->claw.host_name,
2977 					       curr_force->claw.adapter_name,
2978 					       curr_force->claw.api_type);
2979 			}
2980 
2981 		}
2982 	}
2983 	if(chandev_probelist_head)
2984 	{
2985 #if CONFIG_ARCH_S390X
2986 		chandev_printf(chan_exit,"\nRegistered probe functions\n"
2987 			       		 "probefunc            shutdownfunc        msck_notfunc        chan  devices devices\n"
2988                                          "                                                             type   found  active\n"
2989 			                 "==================================================================================\n");
2990 #else
2991 		chandev_printf(chan_exit,"\nRegistered probe functions\n"
2992 			                 "probefunc   shutdownfunc   msck_notfunc   chan  devices devices\n"
2993                                          "                                          type   found  active\n"
2994 			                 "===============================================================\n");
2995 #endif
2996 		for_each(curr_probe,chandev_probelist_head)
2997 		{
2998 			int devices_active=0;
2999 			for_each(curr_device,chandev_activelist_head)
3000 			{
3001 				if(curr_device->probefunc==curr_probe->probefunc)
3002 					devices_active++;
3003 			}
3004 			chandev_printf(chan_exit,"0x%p   0x%p   0x%p       0x%02x     %d      %d\n",
3005 				       curr_probe->probefunc,
3006 				       curr_probe->shutdownfunc,
3007 				       curr_probe->msck_notfunc,
3008 				       curr_probe->chan_type,
3009 				       curr_probe->devices_found,
3010 				       devices_active);
3011 		}
3012 	}
3013 	if(chandev_activelist_head)
3014 	{
3015 		unsigned long long total_memory_usage_in_k=0;
3016 		chandev_printf(chan_exit,
3017 			       "\nInitialised Devices\n"
3018 			       " read   write  data  read   write  data  chan port  dev     dev         memory   read msck    write msck    data msck\n"
3019 			       " irq     irq    irq  devno  devno  devno type no.   ptr     name        usage(k)  status       status        status\n"
3020 			       "=====================================================================================================================\n");
3021 		/* We print this list backwards for cosmetic reasons */
3022 		for(curr_device=chandev_activelist_head;
3023 		    curr_device->next!=NULL;curr_device=curr_device->next);
3024 		while(curr_device)
3025 		{
3026 			read_irqinfo=curr_device->read_irqinfo;
3027 			write_irqinfo=curr_device->write_irqinfo;
3028 			data_irqinfo=curr_device->data_irqinfo;
3029 			if(data_irqinfo)
3030 			{
3031 				sprintf(buff[0],"0x%04x",data_irqinfo->sch.irq);
3032 				sprintf(buff[1],"0x%04x",(int)data_irqinfo->sch.devno);
3033 			}
3034 			else
3035 			{
3036 				strcpy(buff[0],"  n/a ");
3037 				strcpy(buff[1],"  n/a ");
3038 			}
3039 			if(curr_device->memory_usage_in_k<0)
3040 			{
3041 				sprintf(buff[2],"%d",(int)-curr_device->memory_usage_in_k);
3042 				total_memory_usage_in_k-=curr_device->memory_usage_in_k;
3043 			}
3044 			else
3045 				strcpy(buff[2],"  n/a ");
3046 			chandev_printf(chan_exit,
3047 				       "0x%04x 0x%04x %s 0x%04x 0x%04x %s 0x%02x %2d 0x%p %-10s  %6s   %-12s %-12s %-12s\n",
3048 				       read_irqinfo->sch.irq,
3049 				       write_irqinfo->sch.irq,
3050 				       buff[0],
3051 				       (int)read_irqinfo->sch.devno,
3052 				       (int)write_irqinfo->sch.devno,
3053 				       buff[1],
3054 				       curr_device->chan_type,(int)curr_device->port_no,
3055 				       curr_device->dev_ptr,curr_device->devname,
3056 				       buff[2],
3057 				       msck_status_strs[read_irqinfo->msck_status],
3058 				       msck_status_strs[write_irqinfo->msck_status],
3059 				       data_irqinfo ? msck_status_strs[data_irqinfo->msck_status] :
3060 				       "not applicable");
3061 			get_prev((list *)chandev_activelist_head,
3062 				 (list *)curr_device,
3063 				 (list **)&curr_device);
3064 		}
3065 		chandev_printf(chan_exit,"\nTotal device memory usage %Luk.\n",total_memory_usage_in_k);
3066 	}
3067 	chandevs_detected=FALSE;
3068 	for(pass=FALSE;pass<=TRUE;pass++)
3069 	{
3070 		if(pass&&chandevs_detected)
3071 		{
3072 			chandev_printf(chan_exit,"\nchannels detected\n");
3073 			chandev_printf(chan_exit,"              chan    cu    cu   dev    dev                          in chandev\n");
3074 			chandev_printf(chan_exit,"  irq  devno  type   type  model type  model pim      chpids         use  reg.\n");
3075 			chandev_printf(chan_exit,"===============================================================================\n");
3076 		}
3077 		for(curr_irq=get_irq_first(),loopcnt=0;curr_irq>=0; curr_irq=get_irq_next(curr_irq),loopcnt++)
3078 		{
3079 			if(loopcnt>0x10000)
3080 			{
3081 				printk(KERN_ERR"chandev_read_proc detected infinite loop bug in get_irq_next\n");
3082 				goto chan_error;
3083 			}
3084 			if(chandev_is_chandev(curr_irq,&curr_devinfo,&curr_force,&curr_model))
3085 			{
3086 				schib_t *curr_schib;
3087 				curr_schib=s390_get_schib(curr_irq);
3088 				chandevs_detected=TRUE;
3089 				if(pass)
3090 				{
3091 					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",
3092 						       curr_irq,curr_devinfo.devno,
3093 						       ( curr_force ? curr_force->chan_type :
3094 						       ( curr_model ? curr_model->chan_type :
3095 							 chandev_type_none )),
3096 						       (int)curr_devinfo.sid_data.cu_type,
3097 						       (int)curr_devinfo.sid_data.cu_model,
3098 						       (int)curr_devinfo.sid_data.dev_type,
3099 						       (int)curr_devinfo.sid_data.dev_model,
3100 						       (int)(curr_schib ? curr_schib->pmcw.pim : 0),
3101 						       *(long long *)(curr_schib ? &curr_schib->pmcw.chpid[0] : 0),
3102 						       (curr_devinfo.status&DEVSTAT_DEVICE_OWNED) ? "yes":"no ",
3103 						       (chandev_get_irqinfo_by_irq(curr_irq) ? "yes":"no "));
3104 
3105 
3106 				}
3107 
3108 			}
3109 
3110 		}
3111 	}
3112 	if(chandev_parms_head)
3113 	{
3114 		chandev_parms      *curr_parms;
3115 
3116 		chandev_printf(chan_exit,"\n driver specific parameters\n");
3117 		chandev_printf(chan_exit,"chan    lo    hi      driver\n");
3118 		chandev_printf(chan_exit,"type  devno  devno  parameters\n");
3119 		chandev_printf(chan_exit,"=============================================================================\n");
3120 		for_each(curr_parms,chandev_parms_head)
3121 		{
3122 			chandev_printf(chan_exit,"0x%02x 0x%04x 0x%04x  %s\n",
3123 				       curr_parms->chan_type,(int)curr_parms->lo_devno,
3124 				       (int)curr_parms->hi_devno,curr_parms->parmstr);
3125 		}
3126 	}
3127  chan_error:
3128 	*eof=TRUE;
3129  chan_exit:
3130 	if(currlen>length) {
3131 		/* rewind to previous printf so that we are correctly
3132 		 * aligned if we get called to print another page.
3133                  */
3134 		currlen-=splen;
3135 	}
3136 	chandev_unlock();
3137 	return(currlen);
3138 }
3139 
3140 
chandev_write_proc(struct file * file,const char * buffer,unsigned long count,void * data)3141 static int chandev_write_proc(struct file *file, const char *buffer,
3142 			   unsigned long count, void *data)
3143 {
3144 	int         rc;
3145 	char        *buff;
3146 
3147 	if(count > 65536)
3148 		count = 65536;
3149 
3150 	buff=vmalloc(count+1);
3151 	if(buff)
3152 	{
3153 		rc = copy_from_user(buff,buffer,count);
3154 		if (rc)
3155 			goto chandev_write_exit;
3156 		chandev_do_setup(FALSE,buff,count);
3157 		rc=count;
3158 	chandev_write_exit:
3159 		vfree(buff);
3160 		return rc;
3161 	}
3162 	else
3163 		return -ENOMEM;
3164 	return(0);
3165 }
3166 
chandev_create_proc(void)3167 static void __init chandev_create_proc(void)
3168 {
3169 	struct proc_dir_entry *dir_entry=
3170 		create_proc_entry("chandev",0644,
3171 				  &proc_root);
3172 	if(dir_entry)
3173 	{
3174 		dir_entry->read_proc=&chandev_read_proc;
3175 		dir_entry->write_proc=&chandev_write_proc;
3176 	}
3177 }
3178 
3179 
3180 #endif
3181 #if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)
3182 static
3183 #endif
chandev_init(void)3184 int __init chandev_init(void)
3185 {
3186 	atomic_set(&chandev_initialised,TRUE);
3187 	chandev_parse_args();
3188 	chandev_init_default_models();
3189 #if CONFIG_PROC_FS
3190 	chandev_create_proc();
3191 #endif
3192 	chandev_msck_task_tq.routine=
3193 		chandev_msck_task;
3194 #if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)
3195 	INIT_LIST_HEAD(&chandev_msck_task_tq.list);
3196 	chandev_msck_task_tq.sync=0;
3197 #endif
3198 	chandev_msck_task_tq.data=NULL;
3199 	chandev_last_startmsck_list_update=chandev_last_machine_check=jiffies-HZ;
3200 	atomic_set(&chandev_msck_thread_lock,1);
3201 	chandev_lock_owner=CHANDEV_INVALID_LOCK_OWNER;
3202 	chandev_lock_cnt=0;
3203 	spin_lock_init(&chandev_spinlock);
3204 	spin_lock_init(&chandev_not_oper_spinlock);
3205 	atomic_set(&chandev_new_msck,FALSE);
3206 	return(0);
3207 }
3208 #if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)
3209 __initcall(chandev_init);
3210 #endif
3211 
chandev_register_and_probe(chandev_probefunc probefunc,chandev_shutdownfunc shutdownfunc,chandev_msck_notification_func msck_notfunc,chandev_type chan_type)3212 int chandev_register_and_probe(chandev_probefunc probefunc,
3213 			       chandev_shutdownfunc shutdownfunc,
3214 			       chandev_msck_notification_func msck_notfunc,
3215 			       chandev_type chan_type)
3216 {
3217 	chandev_probelist *new_probe,*curr_probe;
3218 	/* Avoid chicked & egg situations where we may be called before we */
3219 	/* are initialised. */
3220 
3221 	chandev_interrupt_check();
3222 	if(!atomic_compare_and_swap(FALSE,TRUE,&chandev_initialised))
3223 		chandev_init();
3224 	chandev_lock();
3225 	for_each(curr_probe,chandev_probelist_head)
3226 	{
3227 		if(curr_probe->probefunc==probefunc)
3228 		{
3229 			chandev_unlock();
3230 			printk("chandev_register_and_probe detected duplicate probefunc %p"
3231 			       " for chan_type  0x%02x \n",probefunc,chan_type);
3232 			return (-EPERM);
3233 		}
3234 	}
3235 	chandev_unlock();
3236 	if((new_probe=chandev_alloc(sizeof(chandev_probelist))))
3237 	{
3238 		new_probe->probefunc=probefunc;
3239 		new_probe->shutdownfunc=shutdownfunc;
3240 		new_probe->msck_notfunc=msck_notfunc;
3241 		new_probe->chan_type=chan_type;
3242 		new_probe->devices_found=0;
3243 		chandev_add_to_list((list **)&chandev_probelist_head,new_probe);
3244 		chandev_probe();
3245 	}
3246 	return(new_probe ? new_probe->devices_found:-ENOMEM);
3247 }
3248 
chandev_unregister(chandev_probefunc probefunc,int call_shutdown)3249 void chandev_unregister(chandev_probefunc probefunc,int call_shutdown)
3250 {
3251 	chandev_probelist *curr_probe;
3252 	chandev_activelist *curr_device,*next_device;
3253 
3254 	chandev_interrupt_check();
3255 	chandev_lock();
3256 	for_each(curr_probe,chandev_probelist_head)
3257 	{
3258 		if(curr_probe->probefunc==probefunc)
3259 		{
3260 			for_each_allow_delete(curr_device,next_device,chandev_activelist_head)
3261 				if(curr_device->probefunc==probefunc&&call_shutdown)
3262 					chandev_shutdown(curr_device);
3263 			chandev_free_listmember((list **)&chandev_probelist_head,
3264 						(list *)curr_probe);
3265 			break;
3266 		}
3267 	}
3268 	chandev_unlock();
3269 }
3270 
3271 
chandev_persist(chandev_type chan_type)3272 int chandev_persist(chandev_type chan_type)
3273 {
3274 	return((chandev_persistent&chan_type) ? TRUE:FALSE);
3275 }
3276 
3277 EXPORT_SYMBOL(chandev_register_and_probe);
3278 EXPORT_SYMBOL(chandev_request_irq);
3279 EXPORT_SYMBOL(chandev_unregister);
3280 EXPORT_SYMBOL(chandev_initdevice);
3281 EXPORT_SYMBOL(chandev_build_device_name);
3282 EXPORT_SYMBOL(chandev_initnetdevice);
3283 EXPORT_SYMBOL(chandev_init_netdev);
3284 EXPORT_SYMBOL(chandev_use_devno_names);
3285 EXPORT_SYMBOL(chandev_free_irq);
3286 EXPORT_SYMBOL(chandev_add_model);
3287 EXPORT_SYMBOL(chandev_del_model);
3288 EXPORT_SYMBOL(chandev_persist);
3289 
3290