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