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

📄 ucc_geth.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	uccf->stopped_rx = 1;	return 0;}static int ugeth_restart_tx(struct ucc_geth_private *ugeth){	struct ucc_fast_private *uccf;	u32 cecr_subblock;	uccf = ugeth->uccf;	cecr_subblock =	    ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num);	qe_issue_cmd(QE_RESTART_TX, cecr_subblock, QE_CR_PROTOCOL_ETHERNET, 0);	uccf->stopped_tx = 0;	return 0;}static int ugeth_restart_rx(struct ucc_geth_private *ugeth){	struct ucc_fast_private *uccf;	u32 cecr_subblock;	uccf = ugeth->uccf;	cecr_subblock =	    ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num);	qe_issue_cmd(QE_RESTART_RX, cecr_subblock, QE_CR_PROTOCOL_ETHERNET,		     0);	uccf->stopped_rx = 0;	return 0;}static int ugeth_enable(struct ucc_geth_private *ugeth, enum comm_dir mode){	struct ucc_fast_private *uccf;	int enabled_tx, enabled_rx;	uccf = ugeth->uccf;	/* check if the UCC number is in range. */	if (ugeth->ug_info->uf_info.ucc_num >= UCC_MAX_NUM) {		if (netif_msg_probe(ugeth))			ugeth_err("%s: ucc_num out of range.", __FUNCTION__);		return -EINVAL;	}	enabled_tx = uccf->enabled_tx;	enabled_rx = uccf->enabled_rx;	/* Get Tx and Rx going again, in case this channel was actively	disabled. */	if ((mode & COMM_DIR_TX) && (!enabled_tx) && uccf->stopped_tx)		ugeth_restart_tx(ugeth);	if ((mode & COMM_DIR_RX) && (!enabled_rx) && uccf->stopped_rx)		ugeth_restart_rx(ugeth);	ucc_fast_enable(uccf, mode);	/* OK to do even if not disabled */	return 0;}static int ugeth_disable(struct ucc_geth_private * ugeth, enum comm_dir mode){	struct ucc_fast_private *uccf;	uccf = ugeth->uccf;	/* check if the UCC number is in range. */	if (ugeth->ug_info->uf_info.ucc_num >= UCC_MAX_NUM) {		if (netif_msg_probe(ugeth))			ugeth_err("%s: ucc_num out of range.", __FUNCTION__);		return -EINVAL;	}	/* Stop any transmissions */	if ((mode & COMM_DIR_TX) && uccf->enabled_tx && !uccf->stopped_tx)		ugeth_graceful_stop_tx(ugeth);	/* Stop any receptions */	if ((mode & COMM_DIR_RX) && uccf->enabled_rx && !uccf->stopped_rx)		ugeth_graceful_stop_rx(ugeth);	ucc_fast_disable(ugeth->uccf, mode); /* OK to do even if not enabled */	return 0;}static void ugeth_dump_regs(struct ucc_geth_private *ugeth){#ifdef DEBUG	ucc_fast_dump_regs(ugeth->uccf);	dump_regs(ugeth);	dump_bds(ugeth);#endif}#ifdef CONFIG_UGETH_FILTERINGstatic int ugeth_ext_filtering_serialize_tad(struct ucc_geth_tad_params *					     p_UccGethTadParams,					     struct qe_fltr_tad *qe_fltr_tad){	u16 temp;	/* Zero serialized TAD */	memset(qe_fltr_tad, 0, QE_FLTR_TAD_SIZE);	qe_fltr_tad->serialized[0] |= UCC_GETH_TAD_V;	/* Must have this */	if (p_UccGethTadParams->rx_non_dynamic_extended_features_mode ||	    (p_UccGethTadParams->vtag_op != UCC_GETH_VLAN_OPERATION_TAGGED_NOP)	    || (p_UccGethTadParams->vnontag_op !=		UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP)	    )		qe_fltr_tad->serialized[0] |= UCC_GETH_TAD_EF;	if (p_UccGethTadParams->reject_frame)		qe_fltr_tad->serialized[0] |= UCC_GETH_TAD_REJ;	temp =	    (u16) (((u16) p_UccGethTadParams->		    vtag_op) << UCC_GETH_TAD_VTAG_OP_SHIFT);	qe_fltr_tad->serialized[0] |= (u8) (temp >> 8);	/* upper bits */	qe_fltr_tad->serialized[1] |= (u8) (temp & 0x00ff);	/* lower bits */	if (p_UccGethTadParams->vnontag_op ==	    UCC_GETH_VLAN_OPERATION_NON_TAGGED_Q_TAG_INSERT)		qe_fltr_tad->serialized[1] |= UCC_GETH_TAD_V_NON_VTAG_OP;	qe_fltr_tad->serialized[1] |=	    p_UccGethTadParams->rqos << UCC_GETH_TAD_RQOS_SHIFT;	qe_fltr_tad->serialized[2] |=	    p_UccGethTadParams->vpri << UCC_GETH_TAD_V_PRIORITY_SHIFT;	/* upper bits */	qe_fltr_tad->serialized[2] |= (u8) (p_UccGethTadParams->vid >> 8);	/* lower bits */	qe_fltr_tad->serialized[3] |= (u8) (p_UccGethTadParams->vid & 0x00ff);	return 0;}static struct enet_addr_container_t    *ugeth_82xx_filtering_get_match_addr_in_hash(struct ucc_geth_private *ugeth,						 struct enet_addr *p_enet_addr){	struct enet_addr_container *enet_addr_cont;	struct list_head *p_lh;	u16 i, num;	int32_t j;	u8 *p_counter;	if ((*p_enet_addr)[0] & ENET_GROUP_ADDR) {		p_lh = &ugeth->group_hash_q;		p_counter = &(ugeth->numGroupAddrInHash);	} else {		p_lh = &ugeth->ind_hash_q;		p_counter = &(ugeth->numIndAddrInHash);	}	if (!p_lh)		return NULL;	num = *p_counter;	for (i = 0; i < num; i++) {		enet_addr_cont =		    (struct enet_addr_container *)		    ENET_ADDR_CONT_ENTRY(dequeue(p_lh));		for (j = ENET_NUM_OCTETS_PER_ADDRESS - 1; j >= 0; j--) {			if ((*p_enet_addr)[j] != (enet_addr_cont->address)[j])				break;			if (j == 0)				return enet_addr_cont;	/* Found */		}		enqueue(p_lh, &enet_addr_cont->node);	/* Put it back */	}	return NULL;}static int ugeth_82xx_filtering_add_addr_in_hash(struct ucc_geth_private *ugeth,						 struct enet_addr *p_enet_addr){	enum ucc_geth_enet_address_recognition_location location;	struct enet_addr_container *enet_addr_cont;	struct list_head *p_lh;	u8 i;	u32 limit;	u8 *p_counter;	if ((*p_enet_addr)[0] & ENET_GROUP_ADDR) {		p_lh = &ugeth->group_hash_q;		limit = ugeth->ug_info->maxGroupAddrInHash;		location =		    UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_GROUP_HASH;		p_counter = &(ugeth->numGroupAddrInHash);	} else {		p_lh = &ugeth->ind_hash_q;		limit = ugeth->ug_info->maxIndAddrInHash;		location =		    UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_INDIVIDUAL_HASH;		p_counter = &(ugeth->numIndAddrInHash);	}	if ((enet_addr_cont =	     ugeth_82xx_filtering_get_match_addr_in_hash(ugeth, p_enet_addr))) {		list_add(p_lh, &enet_addr_cont->node);	/* Put it back */		return 0;	}	if ((!p_lh) || (!(*p_counter < limit)))		return -EBUSY;	if (!(enet_addr_cont = get_enet_addr_container()))		return -ENOMEM;	for (i = 0; i < ENET_NUM_OCTETS_PER_ADDRESS; i++)		(enet_addr_cont->address)[i] = (*p_enet_addr)[i];	enet_addr_cont->location = location;	enqueue(p_lh, &enet_addr_cont->node);	/* Put it back */	++(*p_counter);	hw_add_addr_in_hash(ugeth, enet_addr_cont->address);	return 0;}static int ugeth_82xx_filtering_clear_addr_in_hash(struct ucc_geth_private *ugeth,						   struct enet_addr *p_enet_addr){	struct ucc_geth_82xx_address_filtering_pram *p_82xx_addr_filt;	struct enet_addr_container *enet_addr_cont;	struct ucc_fast_private *uccf;	enum comm_dir comm_dir;	u16 i, num;	struct list_head *p_lh;	u32 *addr_h, *addr_l;	u8 *p_counter;	uccf = ugeth->uccf;	p_82xx_addr_filt =	    (struct ucc_geth_82xx_address_filtering_pram *) ugeth->p_rx_glbl_pram->	    addressfiltering;	if (!	    (enet_addr_cont =	     ugeth_82xx_filtering_get_match_addr_in_hash(ugeth, p_enet_addr)))		return -ENOENT;	/* It's been found and removed from the CQ. */	/* Now destroy its container */	put_enet_addr_container(enet_addr_cont);	if ((*p_enet_addr)[0] & ENET_GROUP_ADDR) {		addr_h = &(p_82xx_addr_filt->gaddr_h);		addr_l = &(p_82xx_addr_filt->gaddr_l);		p_lh = &ugeth->group_hash_q;		p_counter = &(ugeth->numGroupAddrInHash);	} else {		addr_h = &(p_82xx_addr_filt->iaddr_h);		addr_l = &(p_82xx_addr_filt->iaddr_l);		p_lh = &ugeth->ind_hash_q;		p_counter = &(ugeth->numIndAddrInHash);	}	comm_dir = 0;	if (uccf->enabled_tx)		comm_dir |= COMM_DIR_TX;	if (uccf->enabled_rx)		comm_dir |= COMM_DIR_RX;	if (comm_dir)		ugeth_disable(ugeth, comm_dir);	/* Clear the hash table. */	out_be32(addr_h, 0x00000000);	out_be32(addr_l, 0x00000000);	/* Add all remaining CQ elements back into hash */	num = --(*p_counter);	for (i = 0; i < num; i++) {		enet_addr_cont =		    (struct enet_addr_container *)		    ENET_ADDR_CONT_ENTRY(dequeue(p_lh));		hw_add_addr_in_hash(ugeth, enet_addr_cont->address);		enqueue(p_lh, &enet_addr_cont->node);	/* Put it back */	}	if (comm_dir)		ugeth_enable(ugeth, comm_dir);	return 0;}#endif /* CONFIG_UGETH_FILTERING */static int ugeth_82xx_filtering_clear_all_addr_in_hash(struct ucc_geth_private *						       ugeth,						       enum enet_addr_type						       enet_addr_type){	struct ucc_geth_82xx_address_filtering_pram *p_82xx_addr_filt;	struct ucc_fast_private *uccf;	enum comm_dir comm_dir;	struct list_head *p_lh;	u16 i, num;	u32 *addr_h, *addr_l;	u8 *p_counter;	uccf = ugeth->uccf;	p_82xx_addr_filt =	    (struct ucc_geth_82xx_address_filtering_pram *) ugeth->p_rx_glbl_pram->	    addressfiltering;	if (enet_addr_type == ENET_ADDR_TYPE_GROUP) {		addr_h = &(p_82xx_addr_filt->gaddr_h);		addr_l = &(p_82xx_addr_filt->gaddr_l);		p_lh = &ugeth->group_hash_q;		p_counter = &(ugeth->numGroupAddrInHash);	} else if (enet_addr_type == ENET_ADDR_TYPE_INDIVIDUAL) {		addr_h = &(p_82xx_addr_filt->iaddr_h);		addr_l = &(p_82xx_addr_filt->iaddr_l);		p_lh = &ugeth->ind_hash_q;		p_counter = &(ugeth->numIndAddrInHash);	} else		return -EINVAL;	comm_dir = 0;	if (uccf->enabled_tx)		comm_dir |= COMM_DIR_TX;	if (uccf->enabled_rx)		comm_dir |= COMM_DIR_RX;	if (comm_dir)		ugeth_disable(ugeth, comm_dir);	/* Clear the hash table. */	out_be32(addr_h, 0x00000000);	out_be32(addr_l, 0x00000000);	if (!p_lh)		return 0;	num = *p_counter;	/* Delete all remaining CQ elements */	for (i = 0; i < num; i++)		put_enet_addr_container(ENET_ADDR_CONT_ENTRY(dequeue(p_lh)));	*p_counter = 0;	if (comm_dir)		ugeth_enable(ugeth, comm_dir);	return 0;}#ifdef CONFIG_UGETH_FILTERINGstatic int ugeth_82xx_filtering_add_addr_in_paddr(struct ucc_geth_private *ugeth,						  struct enet_addr *p_enet_addr,						  u8 paddr_num){	int i;	if ((*p_enet_addr)[0] & ENET_GROUP_ADDR)		ugeth_warn		    ("%s: multicast address added to paddr will have no "		     "effect - is this what you wanted?",		     __FUNCTION__);	ugeth->indAddrRegUsed[paddr_num] = 1;	/* mark this paddr as used */	/* store address in our database */	for (i = 0; i < ENET_NUM_OCTETS_PER_ADDRESS; i++)		ugeth->paddr[paddr_num][i] = (*p_enet_addr)[i];	/* put in hardware */	return hw_add_addr_in_paddr(ugeth, p_enet_addr, paddr_num);}#endif /* CONFIG_UGETH_FILTERING */static int ugeth_82xx_filtering_clear_addr_in_paddr(struct ucc_geth_private *ugeth,						    u8 paddr_num){	ugeth->indAddrRegUsed[paddr_num] = 0; /* mark this paddr as not used */	return hw_clear_addr_in_paddr(ugeth, paddr_num);/* clear in hardware */}static void ucc_geth_memclean(struct ucc_geth_private *ugeth){	u16 i, j;	u8 *bd;	if (!ugeth)		return;	if (ugeth->uccf)		ucc_fast_free(ugeth->uccf);	if (ugeth->p_thread_data_tx) {		qe_muram_free(ugeth->thread_dat_tx_offset);		ugeth->p_thread_data_tx = NULL;	}	if (ugeth->p_thread_data_rx) {		qe_muram_free(ugeth->thread_dat_rx_offset);		ugeth->p_thread_data_rx = NULL;	}	if (ugeth->p_exf_glbl_param) {		qe_muram_free(ugeth->exf_glbl_param_offset);		ugeth->p_exf_glbl_param = NULL;	}	if (ugeth->p_rx_glbl_pram) {		qe_muram_free(ugeth->rx_glbl_pram_offset);		ugeth->p_rx_glbl_pram = NULL;	}	if (ugeth->p_tx_glbl_pram) {		qe_muram_free(ugeth->tx_glbl_pram_offset);		ugeth->p_tx_glbl_pram = NULL;	}	if (ugeth->p_send_q_mem_reg) {		qe_muram_free(ugeth->send_q_mem_reg_offset);		ugeth->p_send_q_mem_reg = NULL;	}	if (ugeth->p_scheduler) {		qe_muram_free(ugeth->scheduler_offset);		ugeth->p_schedul

⌨️ 快捷键说明

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