📄 chandev.c
字号:
newdevice->chan_type=probeinfo->chan_type; newdevice->dev_ptr=dev_ptr; newdevice->port_no=port_no; newdevice->memory_usage_in_k=probeinfo->memory_usage_in_k; newdevice->category=category; newdevice->unreg_dev=unreg_dev; probeinfo->newdevice=newdevice; return(0); } chandev_unlock(); return(-ENOMEM);}char *chandev_build_device_name(chandev_probeinfo *probeinfo,char *destnamebuff,char *basename,int buildfullname){ if (chandev_use_devno_names&&(!probeinfo->device_forced||probeinfo->devif_num==-1)) sprintf(destnamebuff,"%s%04x",basename,(int)probeinfo->read.devno); else { if(probeinfo->devif_num==-1) { if(buildfullname) { int idx,len=strlen(basename); chandev_activelist *curr_device; for(idx=0;idx<0xffff;idx++) { for_each(curr_device,chandev_activelist_head) { if(strncmp(curr_device->devname,basename,len)==0) { char numbuff[10]; sprintf(numbuff,"%d",idx); if(strcmp(&curr_device->devname[len],numbuff)==0) goto next_idx; } } sprintf(destnamebuff,"%s%d",basename,idx); return(destnamebuff); next_idx: } printk("chandev_build_device_name was usable to build a unique name for %s\n",basename); return(NULL); } else sprintf(destnamebuff,"%s%%d",basename); } else { sprintf(destnamebuff,"%s%d",basename,(int)probeinfo->devif_num); } } return(destnamebuff);}#if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)struct net_device *chandev_init_netdev(chandev_probeinfo *probeinfo,char *basename,struct net_device *dev, int sizeof_priv,struct net_device *(*init_netdevfunc)(struct net_device *dev, int sizeof_priv))#elsestruct device *chandev_init_netdev(chandev_probeinfo *probeinfo,char *basename,struct device *dev, int sizeof_priv,struct device *(*init_netdevfunc)(struct device *dev, int sizeof_priv))#endif{#if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0) struct net_device *retdevice=NULL; int new_device = FALSE;#else struct device *retdevice=NULL;#endif chandev_interrupt_check(); if (!init_netdevfunc) { printk("init_netdevfunc=NULL in chandev_init_netdev, it should not be valid.\n"); return NULL; }#if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0) /* Allocate a device if one is not provided. */ if (dev == NULL) { /* ensure 32-byte alignment of the private area */ int alloc_size = sizeof (*dev) + sizeof_priv + 31; dev = (struct net_device *) kmalloc (alloc_size, GFP_KERNEL); if (dev == NULL) { printk(KERN_ERR "chandev_initnetdevice: Unable to allocate device memory.\n"); return NULL; } memset(dev, 0, alloc_size); if (sizeof_priv) dev->priv = (void *) (((long)(dev + 1) + 31) & ~31); new_device=TRUE; } chandev_build_device_name(probeinfo,dev->name,basename,FALSE);#endif retdevice=init_netdevfunc(dev,sizeof_priv);#if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0) /* Register device if necessary */ /* we need to do this as init_netdev doesn't call register_netdevice */ /* for already allocated devices */ if (retdevice && new_device) register_netdev(retdevice);#endif#if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0) /* We allocated it, so we should free it on error */ if (!retdevice && new_device) kfree(dev);#endif return retdevice;}#if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)struct net_device *chandev_initnetdevice(chandev_probeinfo *probeinfo,u8 port_no,struct net_device *dev, int sizeof_priv, char *basename, struct net_device *(*init_netdevfunc)(struct net_device *dev, int sizeof_priv),void (*unreg_netdevfunc)(struct net_device *dev))#elsestruct device *chandev_initnetdevice(chandev_probeinfo *probeinfo,u8 port_no,struct device *dev, int sizeof_priv, char *basename,struct device *(*init_netdevfunc)(struct device *dev, int sizeof_priv),void (*unreg_netdevfunc)(struct device *dev))#endif{#if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0) struct net_device *retdevice=NULL; int new_device=(dev==NULL);#else struct device *retdevice=NULL;#endif if (!unreg_netdevfunc) { printk("unreg_netdevfunc=NULL in chandev_initnetdevice, it should not be valid.\n"); return NULL; } chandev_interrupt_check(); retdevice=chandev_init_netdev(probeinfo,basename,dev,sizeof_priv,init_netdevfunc); if (retdevice) { if (chandev_initdevice(probeinfo,retdevice,port_no,retdevice->name, chandev_category_network_device,(chandev_unregfunc)unreg_netdevfunc)) { unreg_netdevfunc(retdevice);#if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0) /* We allocated it, so we should free it on error */ if(new_device) kfree(dev);#endif retdevice = NULL; } } return retdevice;}int chandev_compare_chpid_info(chandev_subchannel_info *chan1,chandev_subchannel_info *chan2){ return (chan1->pim!=chan2->pim || *chan1->chpid!=*chan2->chpid);}int chandev_compare_cu_dev_info(chandev_subchannel_info *chan1,chandev_subchannel_info *chan2){ return ((chan1->cu_type != chan2->cu_type)|| (chan1->cu_model != chan2->cu_model)|| (chan1->dev_type != chan2->dev_type)|| (chan1->dev_model != chan2->dev_model));}int chandev_compare_subchannel_info(chandev_subchannel_info *chan1,chandev_subchannel_info *chan2){ return((chan1->devno == chan2->devno) && (chan1->cu_type == chan2->cu_type) && (chan1->cu_model == chan2->cu_model) && (chan1->dev_type == chan2->dev_type) && (chan1->dev_model == chan2->dev_model) && (chan1->pim == chan2->pim) && (*chan1->chpid == *chan2->chpid));}int chandev_doprobe(chandev_force *force,chandev *read,chandev *write,chandev *data){ chandev_probelist *probe; chandev_model_info *model_info; chandev_probeinfo probeinfo; int rc=-1,hint=-1; chandev_activelist *newdevice; chandev_probefunc probefunc; chandev_parms *curr_parms; chandev_model_info dummy_model_info; memset(&probeinfo,0,sizeof(probeinfo)); memset(&dummy_model_info,0,sizeof(dummy_model_info)); probeinfo.device_forced=(force!=NULL); probeinfo.chpid_info_inconsistent=chandev_compare_chpid_info(&read->sch,&write->sch)|| (data&&chandev_compare_chpid_info(&read->sch,&data->sch)); probeinfo.cu_dev_info_inconsistent=chandev_compare_cu_dev_info(&read->sch,&write->sch)|| (data&&chandev_compare_cu_dev_info(&read->sch,&data->sch)); if(read->model_info) model_info=read->model_info; else { dummy_model_info.chan_type=chandev_type_none; dummy_model_info.max_port_no=16; model_info=&dummy_model_info; } for_each(probe,chandev_probelist_head) { if(force) probeinfo.chan_type = ( probe->chan_type & force->chan_type ); else { if(chandev_cautious_auto_detect) probeinfo.chan_type = ( probe->chan_type == model_info->chan_type ? probe->chan_type : chandev_type_none ); else probeinfo.chan_type = ( probe->chan_type & model_info->chan_type ); } if(probeinfo.chan_type && (force || ( !probeinfo.cu_dev_info_inconsistent && ((probe->chan_type&(chandev_type_ctc|chandev_type_escon)) || !probeinfo.chpid_info_inconsistent)))) {#if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0) if(chandev_use_devno_names) probeinfo.devif_num=read->sch.devno; else#endif probeinfo.devif_num=-1; probeinfo.read=read->sch; probeinfo.write=write->sch; if(data) { probeinfo.data=data->sch; probeinfo.data_exists=TRUE; } probeinfo.max_port_no=(force&&(force->port_protocol_no!=-1) ? force->port_protocol_no : model_info->max_port_no); for_each(curr_parms,chandev_parms_head) { if(probe->chan_type==curr_parms->chan_type&& read->sch.devno>=curr_parms->lo_devno&& read->sch.devno<=curr_parms->hi_devno) { probeinfo.parmstr=curr_parms->parmstr; break; } } if(force) { if(force->chan_type==chandev_type_claw) memcpy(&probeinfo.claw,&force->claw,sizeof(chandev_claw_info)); probeinfo.port_protocol_no=force->port_protocol_no; if(force->devif_num==-1&&force->devif_num==-2) probeinfo.devif_num=-1; else probeinfo.devif_num=force->devif_num; probeinfo.memory_usage_in_k=force->memory_usage_in_k; probeinfo.checksum_received_ip_pkts=force->checksum_received_ip_pkts; probeinfo.use_hw_stats=force->use_hw_stats; } else { probeinfo.port_protocol_no=0; probeinfo.checksum_received_ip_pkts=model_info->default_checksum_received_ip_pkts; probeinfo.use_hw_stats=model_info->default_use_hw_stats; probeinfo.memory_usage_in_k=0; if(probe->chan_type&chandev_type_lcs) { hint=(read->sch.devno&0xFF)>>1; if(hint>model_info->max_port_no) { /* The card is possibly emulated e.g P/390 */ /* or possibly configured to use a shared */ /* port configured by osa-sf. */ hint=0; } } } probeinfo.hint_port_no=hint; probefunc=probe->probefunc; rc=probefunc(&probeinfo); if(rc==0) { newdevice=probeinfo.newdevice; if(newdevice) { newdevice->probefunc=probe->probefunc; newdevice->shutdownfunc=probe->shutdownfunc; newdevice->msck_notfunc=probe->msck_notfunc; probe->devices_found++; chandev_add_to_list((list **)&chandev_activelist_head, newdevice); chandev_add_to_userland_notify_list(chandev_start, newdevice->devname,chandev_status_good,chandev_status_good); } else { printk("chandev_initdevice either failed or wasn't called for device read_irq=0x%04x\n",probeinfo.read.irq); } break; } } } chandev_remove(read); chandev_remove(write); if(data) chandev_remove(data); return(rc);}int chandev_request_irq_from_irqinfo(chandev_irqinfo *irqinfo,chandev *this_chandev){ int retval=s390_request_irq_special(irqinfo->sch.irq, irqinfo->handler, chandev_not_oper_handler, irqinfo->irqflags, irqinfo->devname, irqinfo->dev_id); if(retval==0) { irqinfo->msck_status=chandev_status_good; this_chandev->owned=TRUE; } return(retval);}void chandev_irqallocerr(chandev_irqinfo *irqinfo,int err){ printk("chandev_probe failed to realloc irq=%d for %s err=%d\n",irqinfo->sch.irq,irqinfo->devname,err);}void chandev_call_notification_func(chandev_activelist *curr_device,chandev_irqinfo *curr_irqinfo,chandev_msck_status prevstatus){ if(curr_irqinfo->msck_status!=prevstatus) { chandev_msck_status new_msck_status=curr_irqinfo->msck_status; if(curr_irqinfo->msck_status==chandev_status_good) { if(curr_device->read_irqinfo->msck_status==chandev_status_good&& curr_device->write_irqinfo->msck_status==chandev_status_good) { if(curr_device->data_irqinfo) { if(curr_device->data_irqinfo->msck_status==chandev_status_good) new_msck_status=chandev_status_all_chans_good; } else new_msck_status=chandev_status_all_chans_good; } } if(curr_device->msck_notfunc) { curr_device->msck_notfunc(curr_device->dev_ptr, curr_irqinfo->sch.irq, prevstatus,new_msck_status); } if(new_msck_status!=chandev_status_good) { /* No point in sending a machine check if only one channel is good */ chandev_add_to_userland_notify_list(chandev_msck,curr_device->devname, prevstatus,curr_irqinfo->msck_status); } }}int chandev_find_eligible_channels(chandev *first_chandev_to_check, chandev **read,chandev **write,chandev **data,chandev **next, chandev_type chan_type){ chandev *curr_chandev; int eligible_found=FALSE,changed; *next=first_chandev_to_check->next; *read=*write=*data=NULL; for_each(curr_chandev,first_chandev_to_check) if((curr_chandev->sch.devno&1)==0&&curr_chandev->model_info->chan_type!=chandev_type_claw) { *read=curr_chandev; if(chan_type==chandev_type_none) chan_type=(*read)->model_info->chan_type; break; } if(*read) { for_each(curr_chandev,(chandev *)chandev_head.head) if((((*read)->sch.devno|1)==curr_chandev->sch.devno)&& (chandev_compare_cu_dev_info(&(*read)->sch,&curr_chandev->sch)==0)&& ((chan_type&(chandev_type_ctc|chandev_type_escon))|| chandev_compare_chpid_info(&(*read)->sch,&curr_chandev->sch)==0)) { *write=curr_chandev; break; } } if((chan_type&chandev_type_qeth)) { if(*write) { for_each(curr_chandev,(chandev *)chandev_head.head) if((curr_chandev!=*read&&curr_chandev!=*write)&& (chandev_compare_cu_dev_info(&(*read)->sch,&curr_chandev->sch)==0)&& (chandev_compare_chpid_info(&(*read)->sch,&curr_chandev->sch)==0)) { *data=curr_chandev; break; } if(*data) eligible_found=TRUE; } } else if(*write) eligible_found=TRUE; if(eligible_found) { do { changed=FALSE; if(*next&& ((*read&&(*read==*next))|| (*write&&(*write==*next))|| (*data&&(*data==*next)))) { *next=(*next)->next; changed=TRUE; } }while(changed==TRUE); } return(eligible_found);}chandev *chandev_get_free_chandev_by_devno(int devno){ chandev *curr_chandev; if(devno==-1) return(NULL); for_each(curr_chandev,(chandev *)chandev_head.head) if(curr_chandev->sch.devno==devno) { if(chandev_active(devno)) return(NULL); else return(curr_chandev); } return(NULL);}void chandev_probe(void){ chandev *read_chandev,*write_chandev,*data_chandev,*curr_chandev,*next_chandev; chandev_force *curr_force; chandev_noauto_range *curr_noauto; chandev_activelist *curr_device; chandev_irqinfo *curr_irqinfo; s390_dev_info_t curr_devinfo; int err; int auto_msck_recovery; chandev_msck_status prevstatus; chandev_msck_range *curr_msck_range; chandev_interrupt_check(); chandev_read_conf_if_necessary(); chandev_collect_devices(); chandev_lock(); for_each(curr_irqinfo,chandev_irqinfo_head) { if((curr_device=chandev_get_activelist_by_irq(curr_irqinfo->sch.irq))) { prevstatus=curr_irqinfo->msck_status; if(curr_irqinfo->msck_status!=chandev_status_good) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -