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