⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qeth_main.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
	QETH_DBF_TEXT(trace,5,"irqtlet");	channel = (struct qeth_channel *) data;	iob = channel->iob;	index = channel->buf_no;	card = CARD_FROM_CDEV(channel->ccwdev);	while (iob[index].state == BUF_STATE_PROCESSED) {		if (iob[index].callback !=NULL) {			iob[index].callback(channel,iob + index);		}		index = (index + 1) % QETH_CMD_BUFFER_NO;	}	channel->buf_no = index;	wake_up(&card->wait_q);}static int qeth_stop_card(struct qeth_card *, int);static int__qeth_set_offline(struct ccwgroup_device *cgdev, int recovery_mode){	struct qeth_card *card = (struct qeth_card *) cgdev->dev.driver_data;	int rc = 0, rc2 = 0, rc3 = 0;	enum qeth_card_states recover_flag;	QETH_DBF_TEXT(setup, 3, "setoffl");	QETH_DBF_HEX(setup, 3, &card, sizeof(void *));		netif_carrier_off(card->dev);	recover_flag = card->state;	if (qeth_stop_card(card, recovery_mode) == -ERESTARTSYS){		PRINT_WARN("Stopping card %s interrupted by user!\n",			   CARD_BUS_ID(card));		return -ERESTARTSYS;	}	rc  = ccw_device_set_offline(CARD_DDEV(card));	rc2 = ccw_device_set_offline(CARD_WDEV(card));	rc3 = ccw_device_set_offline(CARD_RDEV(card));	if (!rc)		rc = (rc2) ? rc2 : rc3;	if (rc)		QETH_DBF_TEXT_(setup, 2, "1err%d", rc);	if (recover_flag == CARD_STATE_UP)		card->state = CARD_STATE_RECOVER;	qeth_notify_processes();	return 0;}static intqeth_set_offline(struct ccwgroup_device *cgdev){	return  __qeth_set_offline(cgdev, 0);}static intqeth_wait_for_threads(struct qeth_card *card, unsigned long threads);static voidqeth_remove_device(struct ccwgroup_device *cgdev){	struct qeth_card *card = (struct qeth_card *) cgdev->dev.driver_data;	unsigned long flags;	QETH_DBF_TEXT(setup, 3, "rmdev");	QETH_DBF_HEX(setup, 3, &card, sizeof(void *));	if (!card)		return;	if (qeth_wait_for_threads(card, 0xffffffff))		return;	if (cgdev->state == CCWGROUP_ONLINE){		card->use_hard_stop = 1;		qeth_set_offline(cgdev);	}	/* remove form our internal list */	write_lock_irqsave(&qeth_card_list.rwlock, flags);	list_del(&card->list);	write_unlock_irqrestore(&qeth_card_list.rwlock, flags);	if (card->dev)		unregister_netdev(card->dev);	qeth_remove_device_attributes(&cgdev->dev);	qeth_free_card(card);	cgdev->dev.driver_data = NULL;	put_device(&cgdev->dev);}static intqeth_register_addr_entry(struct qeth_card *, struct qeth_ipaddr *);static intqeth_deregister_addr_entry(struct qeth_card *, struct qeth_ipaddr *);/** * Add/remove address to/from card's ip list, i.e. try to add or remove * reference to/from an IP address that is already registered on the card. * Returns: * 	0  address was on card and its reference count has been adjusted, * 	   but is still > 0, so nothing has to be done * 	   also returns 0 if card was not on card and the todo was to delete * 	   the address -> there is also nothing to be done * 	1  address was not on card and the todo is to add it to the card's ip * 	   list * 	-1 address was on card and its reference count has been decremented * 	   to <= 0 by the todo -> address must be removed from card */static int__qeth_ref_ip_on_card(struct qeth_card *card, struct qeth_ipaddr *todo,		      struct qeth_ipaddr **__addr){	struct qeth_ipaddr *addr;	int found = 0;	list_for_each_entry(addr, &card->ip_list, entry) {		if (card->options.layer2) {			if ((addr->type == todo->type) &&			    (memcmp(&addr->mac, &todo->mac, 				    OSA_ADDR_LEN) == 0)) {				found = 1;				break;			}			continue;		} 		if ((addr->proto     == QETH_PROT_IPV4)  &&		    (todo->proto     == QETH_PROT_IPV4)  &&		    (addr->type      == todo->type)      &&		    (addr->u.a4.addr == todo->u.a4.addr) &&		    (addr->u.a4.mask == todo->u.a4.mask)) {			found = 1;			break;		}		if ((addr->proto       == QETH_PROT_IPV6)     &&		    (todo->proto       == QETH_PROT_IPV6)     &&		    (addr->type        == todo->type)         &&		    (addr->u.a6.pfxlen == todo->u.a6.pfxlen)  &&		    (memcmp(&addr->u.a6.addr, &todo->u.a6.addr,			    sizeof(struct in6_addr)) == 0)) {			found = 1;			break;		}	}	if (found) {		addr->users += todo->users;		if (addr->users <= 0){			*__addr = addr;			return -1;		} else {			/* for VIPA and RXIP limit refcount to 1 */			if (addr->type != QETH_IP_TYPE_NORMAL)				addr->users = 1;			return 0;		}	}	if (todo->users > 0) {		/* for VIPA and RXIP limit refcount to 1 */		if (todo->type != QETH_IP_TYPE_NORMAL)			todo->users = 1;		return 1;	} else		return 0;}static inline int__qeth_address_exists_in_list(struct list_head *list, struct qeth_ipaddr *addr,		              int same_type){	struct qeth_ipaddr *tmp;	list_for_each_entry(tmp, list, entry) {		if ((tmp->proto     == QETH_PROT_IPV4)            &&		    (addr->proto    == QETH_PROT_IPV4)            &&		    ((same_type && (tmp->type == addr->type)) ||		     (!same_type && (tmp->type != addr->type))  ) &&		    (tmp->u.a4.addr == addr->u.a4.addr)             ){			return 1;		}		if ((tmp->proto  == QETH_PROT_IPV6)               &&		    (addr->proto == QETH_PROT_IPV6)               &&		    ((same_type && (tmp->type == addr->type)) ||		     (!same_type && (tmp->type != addr->type))  ) &&		    (memcmp(&tmp->u.a6.addr, &addr->u.a6.addr,			    sizeof(struct in6_addr)) == 0)          ) {			return 1;		}	}	return 0;}/* * Add IP to be added to todo list. If there is already an "add todo" * in this list we just incremenent the reference count. * Returns 0 if we  just incremented reference count. */static int__qeth_insert_ip_todo(struct qeth_card *card, struct qeth_ipaddr *addr, int add){	struct qeth_ipaddr *tmp, *t;	int found = 0;	list_for_each_entry_safe(tmp, t, card->ip_tbd_list, entry) {		if ((addr->type == QETH_IP_TYPE_DEL_ALL_MC) &&		    (tmp->type == QETH_IP_TYPE_DEL_ALL_MC))			return 0;		if (card->options.layer2) {			if ((tmp->type	== addr->type)	&&			    (tmp->is_multicast == addr->is_multicast) &&			    (memcmp(&tmp->mac, &addr->mac, 				    OSA_ADDR_LEN) == 0)) {				found = 1;				break;			}			continue;		} 	 		if ((tmp->proto        == QETH_PROT_IPV4)     &&		    (addr->proto       == QETH_PROT_IPV4)     &&		    (tmp->type         == addr->type)         &&		    (tmp->is_multicast == addr->is_multicast) &&		    (tmp->u.a4.addr    == addr->u.a4.addr)    &&		    (tmp->u.a4.mask    == addr->u.a4.mask)) {			found = 1;			break;		}		if ((tmp->proto        == QETH_PROT_IPV6)      &&		    (addr->proto       == QETH_PROT_IPV6)      &&		    (tmp->type         == addr->type)          &&		    (tmp->is_multicast == addr->is_multicast)  &&		    (tmp->u.a6.pfxlen  == addr->u.a6.pfxlen)   &&		    (memcmp(&tmp->u.a6.addr, &addr->u.a6.addr,			    sizeof(struct in6_addr)) == 0)) {			found = 1;			break;		}	}	if (found){		if (addr->users != 0)			tmp->users += addr->users;		else			tmp->users += add? 1:-1;		if (tmp->users == 0) {			list_del(&tmp->entry);			kfree(tmp);		}		return 0;	} else {		if (addr->type == QETH_IP_TYPE_DEL_ALL_MC)			list_add(&addr->entry, card->ip_tbd_list);		else {			if (addr->users == 0)				addr->users += add? 1:-1;			if (add && (addr->type == QETH_IP_TYPE_NORMAL) &&			    qeth_is_addr_covered_by_ipato(card, addr)){				QETH_DBF_TEXT(trace, 2, "tkovaddr");				addr->set_flags |= QETH_IPA_SETIP_TAKEOVER_FLAG;			}			list_add_tail(&addr->entry, card->ip_tbd_list);		}		return 1;	}}/** * Remove IP address from list */static intqeth_delete_ip(struct qeth_card *card, struct qeth_ipaddr *addr){	unsigned long flags;	int rc = 0;	QETH_DBF_TEXT(trace, 4, "delip");	if (card->options.layer2)		QETH_DBF_HEX(trace, 4, &addr->mac, 6);	else if (addr->proto == QETH_PROT_IPV4)		QETH_DBF_HEX(trace, 4, &addr->u.a4.addr, 4);	else {		QETH_DBF_HEX(trace, 4, &addr->u.a6.addr, 8);		QETH_DBF_HEX(trace, 4, ((char *)&addr->u.a6.addr) + 8, 8);	}	spin_lock_irqsave(&card->ip_lock, flags);	rc = __qeth_insert_ip_todo(card, addr, 0);	spin_unlock_irqrestore(&card->ip_lock, flags);	return rc;}static intqeth_add_ip(struct qeth_card *card, struct qeth_ipaddr *addr){	unsigned long flags;	int rc = 0;	QETH_DBF_TEXT(trace, 4, "addip");	if (card->options.layer2)		QETH_DBF_HEX(trace, 4, &addr->mac, 6);	else if (addr->proto == QETH_PROT_IPV4)		QETH_DBF_HEX(trace, 4, &addr->u.a4.addr, 4);	else {		QETH_DBF_HEX(trace, 4, &addr->u.a6.addr, 8);		QETH_DBF_HEX(trace, 4, ((char *)&addr->u.a6.addr) + 8, 8);	}	spin_lock_irqsave(&card->ip_lock, flags);	rc = __qeth_insert_ip_todo(card, addr, 1);	spin_unlock_irqrestore(&card->ip_lock, flags);	return rc;}static inline void__qeth_delete_all_mc(struct qeth_card *card, unsigned long *flags){	struct qeth_ipaddr *addr, *tmp;	int rc;again:	list_for_each_entry_safe(addr, tmp, &card->ip_list, entry) {		if (addr->is_multicast) {			spin_unlock_irqrestore(&card->ip_lock, *flags);			rc = qeth_deregister_addr_entry(card, addr);			spin_lock_irqsave(&card->ip_lock, *flags);			if (!rc) {				list_del(&addr->entry);				kfree(addr);				goto again;			}		}	}}static voidqeth_set_ip_addr_list(struct qeth_card *card){	struct list_head *tbd_list;	struct qeth_ipaddr *todo, *addr;	unsigned long flags;	int rc;	QETH_DBF_TEXT(trace, 2, "sdiplist");	QETH_DBF_HEX(trace, 2, &card, sizeof(void *));	spin_lock_irqsave(&card->ip_lock, flags);	tbd_list = card->ip_tbd_list;	card->ip_tbd_list = kmalloc(sizeof(struct list_head), GFP_ATOMIC);	if (!card->ip_tbd_list) {		QETH_DBF_TEXT(trace, 0, "silnomem");		card->ip_tbd_list = tbd_list;		spin_unlock_irqrestore(&card->ip_lock, flags);		return;	} else		INIT_LIST_HEAD(card->ip_tbd_list);	while (!list_empty(tbd_list)){		todo = list_entry(tbd_list->next, struct qeth_ipaddr, entry);		list_del(&todo->entry);		if (todo->type == QETH_IP_TYPE_DEL_ALL_MC){			__qeth_delete_all_mc(card, &flags);			kfree(todo);			continue;		}		rc = __qeth_ref_ip_on_card(card, todo, &addr);		if (rc == 0) {			/* nothing to be done; only adjusted refcount */			kfree(todo);		} else if (rc == 1) {			/* new entry to be added to on-card list */			spin_unlock_irqrestore(&card->ip_lock, flags);			rc = qeth_register_addr_entry(card, todo);			spin_lock_irqsave(&card->ip_lock, flags);			if (!rc)				list_add_tail(&todo->entry, &card->ip_list);			else				kfree(todo);		} else if (rc == -1) {			/* on-card entry to be removed */			list_del_init(&addr->entry);			spin_unlock_irqrestore(&card->ip_lock, flags);			rc = qeth_deregister_addr_entry(card, addr);			spin_lock_irqsave(&card->ip_lock, flags);			if (!rc)				kfree(addr);			else				list_add_tail(&addr->entry, &card->ip_list);			kfree(todo);		}	}	spin_unlock_irqrestore(&card->ip_lock, flags);	kfree(tbd_list);}static void qeth_delete_mc_addresses(struct qeth_card *);static void qeth_add_multicast_ipv4(struct qeth_card *);static void qeth_layer2_add_multicast(struct qeth_card *);#ifdef CONFIG_QETH_IPV6static void qeth_add_multicast_ipv6(struct qeth_card *);#endifstatic inline intqeth_set_thread_start_bit(struct qeth_card *card, unsigned long thread){	unsigned long flags;	spin_lock_irqsave(&card->thread_mask_lock, flags);	if ( !(card->thread_allowed_mask & thread) ||	      (card->thread_start_mask & thread) ) {		spin_unlock_irqrestore(&card->thread_mask_lock, flags);		return -EPERM;	}	card->thread_start_mask |= thread;	spin_unlock_irqrestore(&card->thread_mask_lock, flags);	return 0;}static voidqeth_clear_thread_start_bit(struct qeth_card *card, unsigned long thread){	unsigned long flags;	spin_lock_irqsave(&card->thread_mask_lock, flags);	card->thread_start_mask &= ~thread;	spin_unlock_irqrestore(&card->thread_mask_lock, flags);	wake_up(&card->wait_q);}static voidqeth_clear_thread_running_bit(struct qeth_card *card, unsigned long thread){	unsigned long flags;	spin_lock_irqsave(&card->thread_mask_lock, flags);	card->thread_running_mask &= ~thread;	spin_unlock_irqrestore(&card->thread_mask_lock, flags);	wake_up(&card->wait_q);}static inline int__qeth_do_run_thread(struct qeth_card *card, unsigned long thread){	unsigned long flags;	int rc = 0;	spin_lock_irqsave(&card->thread_mask_lock, flags);	if (card->thread_start_mask & thread){		if ((card->thread_allowed_mask & thread) &&		    !(card->thread_running_mask & thread)){			rc = 1;			card->thread_start_mask &= ~thread;			card->thread_running_mask |= thread;		} else			rc = -EPERM;	}	spin_unlock_irqrestore(&card->thread_mask_lock, flags);	return rc;}static intqeth_do_run_thread(struct qeth_card *card, unsigned long thread){	int rc = 0;	wait_event(card->wait_q,		   (rc = __qeth_do_run_thread(card, thread)) >= 0);	return rc;}static intqeth_register_ip_addresses(void *ptr){	struct qeth_card *card;	card = (struct qeth_card *) ptr;	daemonize("qeth_reg_ip");	QETH_DBF_TEXT(trace,4,"regipth1");	if (!qeth_do_run_thread(card, QETH_SET_IP_THREAD))		return 0;	QETH_DBF_TEXT(trace,4,"regipth2");	qeth_set_ip_addr_list(card);	qeth_clear_thread_running_bit(card, QETH_SET_IP_THREAD);	return 0;}/* * Drive the SET_PROMISC_MODE thread */static intqeth_set_promisc_mode(void *ptr){	struct qeth_card *card = (struct qeth_card *) ptr;	daemonize("qeth_setprm");	QETH_DBF_TEXT(trace,4,"setprm1");	if (!qeth_do_run_thread(card, QETH_SET_PROMISC_MODE_THREAD))		return 0;	QETH_DBF_TEXT(trace,4,"setprm2");	qeth_setadp_promisc_mode(card);	qeth_clear_thread_running_bit(card, QETH_SET_PROMISC_MODE_THREAD);	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -