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

📄 qeth_main.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
static intqeth_recover(void *ptr){	struct qeth_card *card;	int rc = 0;	card = (struct qeth_card *) ptr;	daemonize("qeth_recover");	QETH_DBF_TEXT(trace,2,"recover1");	QETH_DBF_HEX(trace, 2, &card, sizeof(void *));	if (!qeth_do_run_thread(card, QETH_RECOVER_THREAD))		return 0;	QETH_DBF_TEXT(trace,2,"recover2");	PRINT_WARN("Recovery of device %s started ...\n",		   CARD_BUS_ID(card));	card->use_hard_stop = 1;	__qeth_set_offline(card->gdev,1);	rc = __qeth_set_online(card->gdev,1);	if (!rc)		PRINT_INFO("Device %s successfully recovered!\n",			   CARD_BUS_ID(card));	else		PRINT_INFO("Device %s could not be recovered!\n",			   CARD_BUS_ID(card));	/* don't run another scheduled recovery */	qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);	qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);	return 0;}voidqeth_schedule_recovery(struct qeth_card *card){	QETH_DBF_TEXT(trace,2,"startrec");	if (qeth_set_thread_start_bit(card, QETH_RECOVER_THREAD) == 0)		schedule_work(&card->kernel_thread_starter);}static intqeth_do_start_thread(struct qeth_card *card, unsigned long thread){	unsigned long flags;	int rc = 0;	spin_lock_irqsave(&card->thread_mask_lock, flags);	QETH_DBF_TEXT_(trace, 4, "  %02x%02x%02x",			(u8) card->thread_start_mask,			(u8) card->thread_allowed_mask,			(u8) card->thread_running_mask);	rc = (card->thread_start_mask & thread);	spin_unlock_irqrestore(&card->thread_mask_lock, flags);	return rc;}static voidqeth_start_kernel_thread(struct qeth_card *card){	QETH_DBF_TEXT(trace , 2, "strthrd");	if (card->read.state != CH_STATE_UP &&	    card->write.state != CH_STATE_UP)		return;	if (qeth_do_start_thread(card, QETH_SET_IP_THREAD))		kernel_thread(qeth_register_ip_addresses, (void *)card,SIGCHLD);	if (qeth_do_start_thread(card, QETH_SET_PROMISC_MODE_THREAD))		kernel_thread(qeth_set_promisc_mode, (void *)card, SIGCHLD);	if (qeth_do_start_thread(card, QETH_RECOVER_THREAD))		kernel_thread(qeth_recover, (void *) card, SIGCHLD);}static voidqeth_set_intial_options(struct qeth_card *card){	card->options.route4.type = NO_ROUTER;#ifdef CONFIG_QETH_IPV6	card->options.route6.type = NO_ROUTER;#endif /* QETH_IPV6 */	card->options.checksum_type = QETH_CHECKSUM_DEFAULT;	card->options.broadcast_mode = QETH_TR_BROADCAST_ALLRINGS;	card->options.macaddr_mode = QETH_TR_MACADDR_NONCANONICAL;	card->options.fake_broadcast = 0;	card->options.add_hhlen = DEFAULT_ADD_HHLEN;	card->options.fake_ll = 0;	if (card->info.type == QETH_CARD_TYPE_OSN)		card->options.layer2 = 1;	else		card->options.layer2 = 0;}/** * initialize channels ,card and all state machines */static intqeth_setup_card(struct qeth_card *card){	QETH_DBF_TEXT(setup, 2, "setupcrd");	QETH_DBF_HEX(setup, 2, &card, sizeof(void *));	card->read.state  = CH_STATE_DOWN;	card->write.state = CH_STATE_DOWN;	card->data.state  = CH_STATE_DOWN;	card->state = CARD_STATE_DOWN;	card->lan_online = 0;	card->use_hard_stop = 0;	card->dev = NULL;#ifdef CONFIG_QETH_VLAN	spin_lock_init(&card->vlanlock);	card->vlangrp = NULL;#endif	spin_lock_init(&card->lock);	spin_lock_init(&card->ip_lock);	spin_lock_init(&card->thread_mask_lock);	card->thread_start_mask = 0;	card->thread_allowed_mask = 0;	card->thread_running_mask = 0;	INIT_WORK(&card->kernel_thread_starter,		  (void *)qeth_start_kernel_thread,card);	INIT_LIST_HEAD(&card->ip_list);	card->ip_tbd_list = kmalloc(sizeof(struct list_head), GFP_KERNEL);	if (!card->ip_tbd_list) {		QETH_DBF_TEXT(setup, 0, "iptbdnom");		return -ENOMEM;	}	INIT_LIST_HEAD(card->ip_tbd_list);	INIT_LIST_HEAD(&card->cmd_waiter_list);	init_waitqueue_head(&card->wait_q);	/* intial options */	qeth_set_intial_options(card);	/* IP address takeover */	INIT_LIST_HEAD(&card->ipato.entries);	card->ipato.enabled = 0;	card->ipato.invert4 = 0;	card->ipato.invert6 = 0;	/* init QDIO stuff */	qeth_init_qdio_info(card);	return 0;}static intis_1920_device (struct qeth_card *card){	int single_queue = 0;	struct ccw_device *ccwdev;	struct channelPath_dsc {		u8 flags;		u8 lsn;		u8 desc;		u8 chpid;		u8 swla;		u8 zeroes;		u8 chla;		u8 chpp;	} *chp_dsc;	QETH_DBF_TEXT(setup, 2, "chk_1920");	ccwdev = card->data.ccwdev;	chp_dsc = (struct channelPath_dsc *)ccw_device_get_chp_desc(ccwdev, 0);	if (chp_dsc != NULL) {		/* CHPP field bit 6 == 1 -> single queue */		single_queue = ((chp_dsc->chpp & 0x02) == 0x02);		kfree(chp_dsc);	}	QETH_DBF_TEXT_(setup, 2, "rc:%x", single_queue);	return single_queue;}static intqeth_determine_card_type(struct qeth_card *card){	int i = 0;	QETH_DBF_TEXT(setup, 2, "detcdtyp");	card->qdio.do_prio_queueing = QETH_PRIOQ_DEFAULT;	card->qdio.default_out_queue = QETH_DEFAULT_QUEUE;	while (known_devices[i][4]) {		if ((CARD_RDEV(card)->id.dev_type == known_devices[i][2]) &&		    (CARD_RDEV(card)->id.dev_model == known_devices[i][3])) {			card->info.type = known_devices[i][4];			card->qdio.no_out_queues = known_devices[i][8];			card->info.is_multicast_different = known_devices[i][9];			if (is_1920_device(card)) {				PRINT_INFO("Priority Queueing not able "					   "due to hardware limitations!\n");				card->qdio.no_out_queues = 1;				card->qdio.default_out_queue = 0;			} 			return 0;		}		i++;	}	card->info.type = QETH_CARD_TYPE_UNKNOWN;	PRINT_ERR("unknown card type on device %s\n", CARD_BUS_ID(card));	return -ENOENT;}static intqeth_probe_device(struct ccwgroup_device *gdev){	struct qeth_card *card;	struct device *dev;	unsigned long flags;	int rc;	QETH_DBF_TEXT(setup, 2, "probedev");	dev = &gdev->dev;	if (!get_device(dev))		return -ENODEV;	QETH_DBF_TEXT_(setup, 2, "%s", gdev->dev.bus_id);		card = qeth_alloc_card();	if (!card) {		put_device(dev);		QETH_DBF_TEXT_(setup, 2, "1err%d", -ENOMEM);		return -ENOMEM;	}	card->read.ccwdev  = gdev->cdev[0];	card->write.ccwdev = gdev->cdev[1];	card->data.ccwdev  = gdev->cdev[2];	gdev->dev.driver_data = card;	card->gdev = gdev;	gdev->cdev[0]->handler = qeth_irq;	gdev->cdev[1]->handler = qeth_irq;	gdev->cdev[2]->handler = qeth_irq;	if ((rc = qeth_determine_card_type(card))){		PRINT_WARN("%s: not a valid card type\n", __func__);		QETH_DBF_TEXT_(setup, 2, "3err%d", rc);		put_device(dev);		qeth_free_card(card);		return rc;	}			    	if ((rc = qeth_setup_card(card))){		QETH_DBF_TEXT_(setup, 2, "2err%d", rc);		put_device(dev);		qeth_free_card(card);		return rc;	}	rc = qeth_create_device_attributes(dev);	if (rc) {		put_device(dev);		qeth_free_card(card);		return rc;	}	/* insert into our internal list */	write_lock_irqsave(&qeth_card_list.rwlock, flags);	list_add_tail(&card->list, &qeth_card_list.list);	write_unlock_irqrestore(&qeth_card_list.rwlock, flags);	return rc;}static intqeth_get_unitaddr(struct qeth_card *card){ 	int length;	char *prcd;	int rc;	QETH_DBF_TEXT(setup, 2, "getunit");	rc = read_conf_data(CARD_DDEV(card), (void **) &prcd, &length);	if (rc) {		PRINT_ERR("read_conf_data for device %s returned %i\n",			  CARD_DDEV_ID(card), rc);		return rc;	}	card->info.chpid = prcd[30];	card->info.unit_addr2 = prcd[31];	card->info.cula = prcd[63];	card->info.guestlan = ((prcd[0x10] == _ascebc['V']) &&			       (prcd[0x11] == _ascebc['M']));	return 0;}static voidqeth_init_tokens(struct qeth_card *card){	card->token.issuer_rm_w = 0x00010103UL;	card->token.cm_filter_w = 0x00010108UL;	card->token.cm_connection_w = 0x0001010aUL;	card->token.ulp_filter_w = 0x0001010bUL;	card->token.ulp_connection_w = 0x0001010dUL;}static inline __u16raw_devno_from_bus_id(char *id){        id += (strlen(id) - 4);        return (__u16) simple_strtoul(id, &id, 16);}/** * setup channel */static voidqeth_setup_ccw(struct qeth_channel *channel,unsigned char *iob, __u32 len){	struct qeth_card *card;	QETH_DBF_TEXT(trace, 4, "setupccw");	card = CARD_FROM_CDEV(channel->ccwdev);	if (channel == &card->read)		memcpy(&channel->ccw, READ_CCW, sizeof(struct ccw1));	else		memcpy(&channel->ccw, WRITE_CCW, sizeof(struct ccw1));	channel->ccw.count = len;	channel->ccw.cda = (__u32) __pa(iob);}/** * get free buffer for ccws (IDX activation, lancmds,ipassists...) */static struct qeth_cmd_buffer *__qeth_get_buffer(struct qeth_channel *channel){	__u8 index;	QETH_DBF_TEXT(trace, 6, "getbuff");	index = channel->io_buf_no;	do {		if (channel->iob[index].state == BUF_STATE_FREE) {			channel->iob[index].state = BUF_STATE_LOCKED;			channel->io_buf_no = (channel->io_buf_no + 1) %				QETH_CMD_BUFFER_NO;			memset(channel->iob[index].data, 0, QETH_BUFSIZE);			return channel->iob + index;		}		index = (index + 1) % QETH_CMD_BUFFER_NO;	} while(index != channel->io_buf_no);	return NULL;}/** * release command buffer */static voidqeth_release_buffer(struct qeth_channel *channel, struct qeth_cmd_buffer *iob){	unsigned long flags;	QETH_DBF_TEXT(trace, 6, "relbuff");	spin_lock_irqsave(&channel->iob_lock, flags);	memset(iob->data, 0, QETH_BUFSIZE);	iob->state = BUF_STATE_FREE;	iob->callback = qeth_send_control_data_cb;	iob->rc = 0;	spin_unlock_irqrestore(&channel->iob_lock, flags);}static struct qeth_cmd_buffer *qeth_get_buffer(struct qeth_channel *channel){	struct qeth_cmd_buffer *buffer = NULL;	unsigned long flags;	spin_lock_irqsave(&channel->iob_lock, flags);	buffer = __qeth_get_buffer(channel);	spin_unlock_irqrestore(&channel->iob_lock, flags);	return buffer;}static struct qeth_cmd_buffer *qeth_wait_for_buffer(struct qeth_channel *channel){	struct qeth_cmd_buffer *buffer;	wait_event(channel->wait_q,		   ((buffer = qeth_get_buffer(channel)) != NULL));	return buffer;}static voidqeth_clear_cmd_buffers(struct qeth_channel *channel){	int cnt = 0;	for (cnt=0; cnt < QETH_CMD_BUFFER_NO; cnt++)		qeth_release_buffer(channel,&channel->iob[cnt]);	channel->buf_no = 0;	channel->io_buf_no = 0;}/** * start IDX for read and write channel */static intqeth_idx_activate_get_answer(struct qeth_channel *channel,			      void (*idx_reply_cb)(struct qeth_channel *,						   struct qeth_cmd_buffer *)){	struct qeth_cmd_buffer *iob;	unsigned long flags;	int rc;	struct qeth_card *card;	QETH_DBF_TEXT(setup, 2, "idxanswr");	card = CARD_FROM_CDEV(channel->ccwdev);	iob = qeth_get_buffer(channel);	iob->callback = idx_reply_cb;	memcpy(&channel->ccw, READ_CCW, sizeof(struct ccw1));	channel->ccw.count = QETH_BUFSIZE;	channel->ccw.cda = (__u32) __pa(iob->data);	wait_event(card->wait_q,		   atomic_compare_and_swap(0,1,&channel->irq_pending) == 0);	QETH_DBF_TEXT(setup, 6, "noirqpnd");	spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);	rc = ccw_device_start(channel->ccwdev,			      &channel->ccw,(addr_t) iob, 0, 0);	spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);	if (rc) {		PRINT_ERR("qeth: Error2 in activating channel rc=%d\n",rc);		QETH_DBF_TEXT_(setup, 2, "2err%d", rc);		atomic_set(&channel->irq_pending, 0);		wake_up(&card->wait_q);		return rc;	}	rc = wait_event_interruptible_timeout(card->wait_q,			 channel->state == CH_STATE_UP, QETH_TIMEOUT);	if (rc == -ERESTARTSYS)		return rc;	if (channel->state != CH_STATE_UP){		rc = -ETIME;		QETH_DBF_TEXT_(setup, 2, "3err%d", rc);		qeth_clear_cmd_buffers(channel);	} else		rc = 0;	return rc;}static intqeth_idx_activate_channel(struct qeth_channel *channel,			   void (*idx_reply_cb)(struct qeth_channel *,						struct qeth_cmd_buffer *)){	struct qeth_card *card;	struct qeth_cmd_buffer *iob;	unsigned long flags;	__u16 temp;	int rc;	card = CARD_FROM_CDEV(channel->ccwdev);	QETH_DBF_TEXT(setup, 2, "idxactch");	iob = qeth_get_buffer(channel);	iob->callback = idx_reply_cb;	memcpy(&channel->ccw, WRITE_CCW, sizeof(struct ccw1));	channel->ccw.count = IDX_ACTIVATE_SIZE;	channel->ccw.cda = (__u32) __pa(iob->data);	if (channel == &card->write) {		memcpy(iob->data, IDX_ACTIVATE_WRITE, IDX_ACTIVATE_SIZE);		memcpy(QETH_TRANSPORT_HEADER_SEQ_NO(iob->data),		       &card->seqno.trans_hdr, QETH_SEQ_NO_LENGTH);		card->seqno.trans_hdr++;	} else {		memcpy(iob->data, IDX_ACTIVATE_READ, IDX_ACTIVATE_SIZE);		memcpy(QETH_TRANSPORT_HEADER_SEQ_NO(iob->data),		       &card->seqno.trans_hdr, QETH_SEQ_NO_LENGTH);	}	memcpy(QETH_IDX_ACT_ISSUER_RM_TOKEN(iob->data),	       &card->token.issuer_rm_w,QETH_MPC_TOKEN_LENGTH);	memcpy(QETH_IDX_ACT_FUNC_LEVEL(iob->data),	       &card->info.func_level,sizeof(__u16));	temp = raw_devno_from_bus_id(CARD_DDEV_ID(card));	memcpy(QETH_IDX_ACT_QDIO_DEV_CUA(iob->data), &temp, 2);	temp = (card->info.cula << 8) + card->info.unit_addr2;	memcpy(QETH_IDX_ACT_QDIO_DEV_REALADDR(iob->data), &temp, 2);	wait_event(card->wait_q,		   atomic_compare_and_swap(0,1,&channel->irq_pending) == 0);	QETH_DBF_TEXT(setup, 6, "noirqpnd");	spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);	rc = ccw_device_start(channel->ccwdev,			      &channel->ccw,(addr_t) iob, 0, 0);	spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);	if (rc) {		PRINT_ERR("qeth: Error1 in activating channel. rc=%d\n",rc);		QETH_DBF_TEXT_(setup, 2, "1err%d", rc);		atomic_set(&channel->irq_pending, 0);		wake_up(&card->wait_q);		return rc;	}	rc = wait_event_interruptible_timeout(card->wait_q,			channel->state == CH_STATE_ACTIVATING, QETH_TIMEOUT);	if (rc == -ERESTARTSYS)

⌨️ 快捷键说明

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