📄 ucc_geth.c
字号:
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 + -