in ethernet/freescale/ucc_geth.c [2258:2908]
static int ucc_geth_startup(struct ucc_geth_private *ugeth)
{
struct ucc_geth_82xx_address_filtering_pram __iomem *p_82xx_addr_filt;
struct ucc_geth_init_pram __iomem *p_init_enet_pram;
struct ucc_fast_private *uccf;
struct ucc_geth_info *ug_info;
struct ucc_fast_info *uf_info;
struct ucc_fast __iomem *uf_regs;
struct ucc_geth __iomem *ug_regs;
int ret_val = -EINVAL;
u32 remoder = UCC_GETH_REMODER_INIT;
u32 init_enet_pram_offset, cecr_subblock, command;
u32 ifstat, i, j, size, l2qt, l3qt;
u16 temoder = UCC_GETH_TEMODER_INIT;
u8 function_code = 0;
u8 __iomem *endOfRing;
u8 numThreadsRxNumerical, numThreadsTxNumerical;
s32 rx_glbl_pram_offset, tx_glbl_pram_offset;
ugeth_vdbg("%s: IN", __func__);
uccf = ugeth->uccf;
ug_info = ugeth->ug_info;
uf_info = &ug_info->uf_info;
uf_regs = uccf->uf_regs;
ug_regs = ugeth->ug_regs;
numThreadsRxNumerical = ucc_geth_thread_count(ug_info->numThreadsRx);
if (!numThreadsRxNumerical) {
if (netif_msg_ifup(ugeth))
pr_err("Bad number of Rx threads value\n");
return -EINVAL;
}
numThreadsTxNumerical = ucc_geth_thread_count(ug_info->numThreadsTx);
if (!numThreadsTxNumerical) {
if (netif_msg_ifup(ugeth))
pr_err("Bad number of Tx threads value\n");
return -EINVAL;
}
/* Calculate rx_extended_features */
ugeth->rx_non_dynamic_extended_features = ug_info->ipCheckSumCheck ||
ug_info->ipAddressAlignment ||
(ug_info->numStationAddresses !=
UCC_GETH_NUM_OF_STATION_ADDRESSES_1);
ugeth->rx_extended_features = ugeth->rx_non_dynamic_extended_features ||
(ug_info->vlanOperationTagged != UCC_GETH_VLAN_OPERATION_TAGGED_NOP) ||
(ug_info->vlanOperationNonTagged !=
UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP);
init_default_reg_vals(&uf_regs->upsmr,
&ug_regs->maccfg1, &ug_regs->maccfg2);
/* Set UPSMR */
/* For more details see the hardware spec. */
init_rx_parameters(ug_info->bro,
ug_info->rsh, ug_info->pro, &uf_regs->upsmr);
/* We're going to ignore other registers for now, */
/* except as needed to get up and running */
/* Set MACCFG1 */
/* For more details see the hardware spec. */
init_flow_control_params(ug_info->aufc,
ug_info->receiveFlowControl,
ug_info->transmitFlowControl,
ug_info->pausePeriod,
ug_info->extensionField,
&uf_regs->upsmr,
&ug_regs->uempr, &ug_regs->maccfg1);
setbits32(&ug_regs->maccfg1, MACCFG1_ENABLE_RX | MACCFG1_ENABLE_TX);
/* Set IPGIFG */
/* For more details see the hardware spec. */
ret_val = init_inter_frame_gap_params(ug_info->nonBackToBackIfgPart1,
ug_info->nonBackToBackIfgPart2,
ug_info->
miminumInterFrameGapEnforcement,
ug_info->backToBackInterFrameGap,
&ug_regs->ipgifg);
if (ret_val != 0) {
if (netif_msg_ifup(ugeth))
pr_err("IPGIFG initialization parameter too large\n");
return ret_val;
}
/* Set HAFDUP */
/* For more details see the hardware spec. */
ret_val = init_half_duplex_params(ug_info->altBeb,
ug_info->backPressureNoBackoff,
ug_info->noBackoff,
ug_info->excessDefer,
ug_info->altBebTruncation,
ug_info->maxRetransmission,
ug_info->collisionWindow,
&ug_regs->hafdup);
if (ret_val != 0) {
if (netif_msg_ifup(ugeth))
pr_err("Half Duplex initialization parameter too large\n");
return ret_val;
}
/* Set IFSTAT */
/* For more details see the hardware spec. */
/* Read only - resets upon read */
ifstat = in_be32(&ug_regs->ifstat);
/* Clear UEMPR */
/* For more details see the hardware spec. */
out_be32(&ug_regs->uempr, 0);
/* Set UESCR */
/* For more details see the hardware spec. */
init_hw_statistics_gathering_mode((ug_info->statisticsMode &
UCC_GETH_STATISTICS_GATHERING_MODE_HARDWARE),
0, &uf_regs->upsmr, &ug_regs->uescr);
ret_val = ucc_geth_alloc_tx(ugeth);
if (ret_val != 0)
return ret_val;
ret_val = ucc_geth_alloc_rx(ugeth);
if (ret_val != 0)
return ret_val;
/*
* Global PRAM
*/
/* Tx global PRAM */
/* Allocate global tx parameter RAM page */
tx_glbl_pram_offset =
qe_muram_alloc(sizeof(struct ucc_geth_tx_global_pram),
UCC_GETH_TX_GLOBAL_PRAM_ALIGNMENT);
if (tx_glbl_pram_offset < 0) {
if (netif_msg_ifup(ugeth))
pr_err("Can not allocate DPRAM memory for p_tx_glbl_pram\n");
return -ENOMEM;
}
ugeth->p_tx_glbl_pram = qe_muram_addr(tx_glbl_pram_offset);
/* Fill global PRAM */
/* TQPTR */
/* Size varies with number of Tx threads */
ugeth->thread_dat_tx_offset =
qe_muram_alloc(numThreadsTxNumerical *
sizeof(struct ucc_geth_thread_data_tx) +
32 * (numThreadsTxNumerical == 1),
UCC_GETH_THREAD_DATA_ALIGNMENT);
if (IS_ERR_VALUE(ugeth->thread_dat_tx_offset)) {
if (netif_msg_ifup(ugeth))
pr_err("Can not allocate DPRAM memory for p_thread_data_tx\n");
return -ENOMEM;
}
ugeth->p_thread_data_tx =
(struct ucc_geth_thread_data_tx __iomem *) qe_muram_addr(ugeth->
thread_dat_tx_offset);
out_be32(&ugeth->p_tx_glbl_pram->tqptr, ugeth->thread_dat_tx_offset);
/* vtagtable */
for (i = 0; i < UCC_GETH_TX_VTAG_TABLE_ENTRY_MAX; i++)
out_be32(&ugeth->p_tx_glbl_pram->vtagtable[i],
ug_info->vtagtable[i]);
/* iphoffset */
for (i = 0; i < TX_IP_OFFSET_ENTRY_MAX; i++)
out_8(&ugeth->p_tx_glbl_pram->iphoffset[i],
ug_info->iphoffset[i]);
/* SQPTR */
/* Size varies with number of Tx queues */
ugeth->send_q_mem_reg_offset =
qe_muram_alloc(ucc_geth_tx_queues(ug_info) *
sizeof(struct ucc_geth_send_queue_qd),
UCC_GETH_SEND_QUEUE_QUEUE_DESCRIPTOR_ALIGNMENT);
if (IS_ERR_VALUE(ugeth->send_q_mem_reg_offset)) {
if (netif_msg_ifup(ugeth))
pr_err("Can not allocate DPRAM memory for p_send_q_mem_reg\n");
return -ENOMEM;
}
ugeth->p_send_q_mem_reg =
(struct ucc_geth_send_queue_mem_region __iomem *) qe_muram_addr(ugeth->
send_q_mem_reg_offset);
out_be32(&ugeth->p_tx_glbl_pram->sqptr, ugeth->send_q_mem_reg_offset);
/* Setup the table */
/* Assume BD rings are already established */
for (i = 0; i < ucc_geth_tx_queues(ug_info); i++) {
endOfRing =
ugeth->p_tx_bd_ring[i] + (ug_info->bdRingLenTx[i] -
1) * sizeof(struct qe_bd);
out_be32(&ugeth->p_send_q_mem_reg->sqqd[i].bd_ring_base,
(u32) virt_to_phys(ugeth->p_tx_bd_ring[i]));
out_be32(&ugeth->p_send_q_mem_reg->sqqd[i].
last_bd_completed_address,
(u32) virt_to_phys(endOfRing));
}
/* schedulerbasepointer */
if (ucc_geth_tx_queues(ug_info) > 1) {
/* scheduler exists only if more than 1 tx queue */
ugeth->scheduler_offset =
qe_muram_alloc(sizeof(struct ucc_geth_scheduler),
UCC_GETH_SCHEDULER_ALIGNMENT);
if (IS_ERR_VALUE(ugeth->scheduler_offset)) {
if (netif_msg_ifup(ugeth))
pr_err("Can not allocate DPRAM memory for p_scheduler\n");
return -ENOMEM;
}
ugeth->p_scheduler =
(struct ucc_geth_scheduler __iomem *) qe_muram_addr(ugeth->
scheduler_offset);
out_be32(&ugeth->p_tx_glbl_pram->schedulerbasepointer,
ugeth->scheduler_offset);
/* Set values in scheduler */
out_be32(&ugeth->p_scheduler->mblinterval,
ug_info->mblinterval);
out_be16(&ugeth->p_scheduler->nortsrbytetime,
ug_info->nortsrbytetime);
out_8(&ugeth->p_scheduler->fracsiz, ug_info->fracsiz);
out_8(&ugeth->p_scheduler->strictpriorityq,
ug_info->strictpriorityq);
out_8(&ugeth->p_scheduler->txasap, ug_info->txasap);
out_8(&ugeth->p_scheduler->extrabw, ug_info->extrabw);
for (i = 0; i < NUM_TX_QUEUES; i++)
out_8(&ugeth->p_scheduler->weightfactor[i],
ug_info->weightfactor[i]);
/* Set pointers to cpucount registers in scheduler */
ugeth->p_cpucount[0] = &(ugeth->p_scheduler->cpucount0);
ugeth->p_cpucount[1] = &(ugeth->p_scheduler->cpucount1);
ugeth->p_cpucount[2] = &(ugeth->p_scheduler->cpucount2);
ugeth->p_cpucount[3] = &(ugeth->p_scheduler->cpucount3);
ugeth->p_cpucount[4] = &(ugeth->p_scheduler->cpucount4);
ugeth->p_cpucount[5] = &(ugeth->p_scheduler->cpucount5);
ugeth->p_cpucount[6] = &(ugeth->p_scheduler->cpucount6);
ugeth->p_cpucount[7] = &(ugeth->p_scheduler->cpucount7);
}
/* schedulerbasepointer */
/* TxRMON_PTR (statistics) */
if (ug_info->
statisticsMode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX) {
ugeth->tx_fw_statistics_pram_offset =
qe_muram_alloc(sizeof
(struct ucc_geth_tx_firmware_statistics_pram),
UCC_GETH_TX_STATISTICS_ALIGNMENT);
if (IS_ERR_VALUE(ugeth->tx_fw_statistics_pram_offset)) {
if (netif_msg_ifup(ugeth))
pr_err("Can not allocate DPRAM memory for p_tx_fw_statistics_pram\n");
return -ENOMEM;
}
ugeth->p_tx_fw_statistics_pram =
(struct ucc_geth_tx_firmware_statistics_pram __iomem *)
qe_muram_addr(ugeth->tx_fw_statistics_pram_offset);
}
/* temoder */
/* Already has speed set */
if (ucc_geth_tx_queues(ug_info) > 1)
temoder |= TEMODER_SCHEDULER_ENABLE;
if (ug_info->ipCheckSumGenerate)
temoder |= TEMODER_IP_CHECKSUM_GENERATE;
temoder |= ((ucc_geth_tx_queues(ug_info) - 1) << TEMODER_NUM_OF_QUEUES_SHIFT);
out_be16(&ugeth->p_tx_glbl_pram->temoder, temoder);
/* Function code register value to be used later */
function_code = UCC_BMR_BO_BE | UCC_BMR_GBL;
/* Required for QE */
/* function code register */
out_be32(&ugeth->p_tx_glbl_pram->tstate, ((u32) function_code) << 24);
/* Rx global PRAM */
/* Allocate global rx parameter RAM page */
rx_glbl_pram_offset =
qe_muram_alloc(sizeof(struct ucc_geth_rx_global_pram),
UCC_GETH_RX_GLOBAL_PRAM_ALIGNMENT);
if (rx_glbl_pram_offset < 0) {
if (netif_msg_ifup(ugeth))
pr_err("Can not allocate DPRAM memory for p_rx_glbl_pram\n");
return -ENOMEM;
}
ugeth->p_rx_glbl_pram = qe_muram_addr(rx_glbl_pram_offset);
/* Fill global PRAM */
/* RQPTR */
/* Size varies with number of Rx threads */
ugeth->thread_dat_rx_offset =
qe_muram_alloc(numThreadsRxNumerical *
sizeof(struct ucc_geth_thread_data_rx),
UCC_GETH_THREAD_DATA_ALIGNMENT);
if (IS_ERR_VALUE(ugeth->thread_dat_rx_offset)) {
if (netif_msg_ifup(ugeth))
pr_err("Can not allocate DPRAM memory for p_thread_data_rx\n");
return -ENOMEM;
}
ugeth->p_thread_data_rx =
(struct ucc_geth_thread_data_rx __iomem *) qe_muram_addr(ugeth->
thread_dat_rx_offset);
out_be32(&ugeth->p_rx_glbl_pram->rqptr, ugeth->thread_dat_rx_offset);
/* typeorlen */
out_be16(&ugeth->p_rx_glbl_pram->typeorlen, ug_info->typeorlen);
/* rxrmonbaseptr (statistics) */
if (ug_info->
statisticsMode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX) {
ugeth->rx_fw_statistics_pram_offset =
qe_muram_alloc(sizeof
(struct ucc_geth_rx_firmware_statistics_pram),
UCC_GETH_RX_STATISTICS_ALIGNMENT);
if (IS_ERR_VALUE(ugeth->rx_fw_statistics_pram_offset)) {
if (netif_msg_ifup(ugeth))
pr_err("Can not allocate DPRAM memory for p_rx_fw_statistics_pram\n");
return -ENOMEM;
}
ugeth->p_rx_fw_statistics_pram =
(struct ucc_geth_rx_firmware_statistics_pram __iomem *)
qe_muram_addr(ugeth->rx_fw_statistics_pram_offset);
}
/* intCoalescingPtr */
/* Size varies with number of Rx queues */
ugeth->rx_irq_coalescing_tbl_offset =
qe_muram_alloc(ucc_geth_rx_queues(ug_info) *
sizeof(struct ucc_geth_rx_interrupt_coalescing_entry)
+ 4, UCC_GETH_RX_INTERRUPT_COALESCING_ALIGNMENT);
if (IS_ERR_VALUE(ugeth->rx_irq_coalescing_tbl_offset)) {
if (netif_msg_ifup(ugeth))
pr_err("Can not allocate DPRAM memory for p_rx_irq_coalescing_tbl\n");
return -ENOMEM;
}
ugeth->p_rx_irq_coalescing_tbl =
(struct ucc_geth_rx_interrupt_coalescing_table __iomem *)
qe_muram_addr(ugeth->rx_irq_coalescing_tbl_offset);
out_be32(&ugeth->p_rx_glbl_pram->intcoalescingptr,
ugeth->rx_irq_coalescing_tbl_offset);
/* Fill interrupt coalescing table */
for (i = 0; i < ucc_geth_rx_queues(ug_info); i++) {
out_be32(&ugeth->p_rx_irq_coalescing_tbl->coalescingentry[i].
interruptcoalescingmaxvalue,
ug_info->interruptcoalescingmaxvalue[i]);
out_be32(&ugeth->p_rx_irq_coalescing_tbl->coalescingentry[i].
interruptcoalescingcounter,
ug_info->interruptcoalescingmaxvalue[i]);
}
/* MRBLR */
init_max_rx_buff_len(uf_info->max_rx_buf_length,
&ugeth->p_rx_glbl_pram->mrblr);
/* MFLR */
out_be16(&ugeth->p_rx_glbl_pram->mflr, ug_info->maxFrameLength);
/* MINFLR */
init_min_frame_len(ug_info->minFrameLength,
&ugeth->p_rx_glbl_pram->minflr,
&ugeth->p_rx_glbl_pram->mrblr);
/* MAXD1 */
out_be16(&ugeth->p_rx_glbl_pram->maxd1, ug_info->maxD1Length);
/* MAXD2 */
out_be16(&ugeth->p_rx_glbl_pram->maxd2, ug_info->maxD2Length);
/* l2qt */
l2qt = 0;
for (i = 0; i < UCC_GETH_VLAN_PRIORITY_MAX; i++)
l2qt |= (ug_info->l2qt[i] << (28 - 4 * i));
out_be32(&ugeth->p_rx_glbl_pram->l2qt, l2qt);
/* l3qt */
for (j = 0; j < UCC_GETH_IP_PRIORITY_MAX; j += 8) {
l3qt = 0;
for (i = 0; i < 8; i++)
l3qt |= (ug_info->l3qt[j + i] << (28 - 4 * i));
out_be32(&ugeth->p_rx_glbl_pram->l3qt[j/8], l3qt);
}
/* vlantype */
out_be16(&ugeth->p_rx_glbl_pram->vlantype, ug_info->vlantype);
/* vlantci */
out_be16(&ugeth->p_rx_glbl_pram->vlantci, ug_info->vlantci);
/* ecamptr */
out_be32(&ugeth->p_rx_glbl_pram->ecamptr, ug_info->ecamptr);
/* RBDQPTR */
/* Size varies with number of Rx queues */
ugeth->rx_bd_qs_tbl_offset =
qe_muram_alloc(ucc_geth_rx_queues(ug_info) *
(sizeof(struct ucc_geth_rx_bd_queues_entry) +
sizeof(struct ucc_geth_rx_prefetched_bds)),
UCC_GETH_RX_BD_QUEUES_ALIGNMENT);
if (IS_ERR_VALUE(ugeth->rx_bd_qs_tbl_offset)) {
if (netif_msg_ifup(ugeth))
pr_err("Can not allocate DPRAM memory for p_rx_bd_qs_tbl\n");
return -ENOMEM;
}
ugeth->p_rx_bd_qs_tbl =
(struct ucc_geth_rx_bd_queues_entry __iomem *) qe_muram_addr(ugeth->
rx_bd_qs_tbl_offset);
out_be32(&ugeth->p_rx_glbl_pram->rbdqptr, ugeth->rx_bd_qs_tbl_offset);
/* Setup the table */
/* Assume BD rings are already established */
for (i = 0; i < ucc_geth_rx_queues(ug_info); i++) {
out_be32(&ugeth->p_rx_bd_qs_tbl[i].externalbdbaseptr,
(u32) virt_to_phys(ugeth->p_rx_bd_ring[i]));
/* rest of fields handled by QE */
}
/* remoder */
/* Already has speed set */
if (ugeth->rx_extended_features)
remoder |= REMODER_RX_EXTENDED_FEATURES;
if (ug_info->rxExtendedFiltering)
remoder |= REMODER_RX_EXTENDED_FILTERING;
if (ug_info->dynamicMaxFrameLength)
remoder |= REMODER_DYNAMIC_MAX_FRAME_LENGTH;
if (ug_info->dynamicMinFrameLength)
remoder |= REMODER_DYNAMIC_MIN_FRAME_LENGTH;
remoder |=
ug_info->vlanOperationTagged << REMODER_VLAN_OPERATION_TAGGED_SHIFT;
remoder |=
ug_info->
vlanOperationNonTagged << REMODER_VLAN_OPERATION_NON_TAGGED_SHIFT;
remoder |= ug_info->rxQoSMode << REMODER_RX_QOS_MODE_SHIFT;
remoder |= ((ucc_geth_rx_queues(ug_info) - 1) << REMODER_NUM_OF_QUEUES_SHIFT);
if (ug_info->ipCheckSumCheck)
remoder |= REMODER_IP_CHECKSUM_CHECK;
if (ug_info->ipAddressAlignment)
remoder |= REMODER_IP_ADDRESS_ALIGNMENT;
out_be32(&ugeth->p_rx_glbl_pram->remoder, remoder);
/* Note that this function must be called */
/* ONLY AFTER p_tx_fw_statistics_pram */
/* andp_UccGethRxFirmwareStatisticsPram are allocated ! */
init_firmware_statistics_gathering_mode((ug_info->
statisticsMode &
UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX),
(ug_info->statisticsMode &
UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX),
&ugeth->p_tx_glbl_pram->txrmonbaseptr,
ugeth->tx_fw_statistics_pram_offset,
&ugeth->p_rx_glbl_pram->rxrmonbaseptr,
ugeth->rx_fw_statistics_pram_offset,
&ugeth->p_tx_glbl_pram->temoder,
&ugeth->p_rx_glbl_pram->remoder);
/* function code register */
out_8(&ugeth->p_rx_glbl_pram->rstate, function_code);
/* initialize extended filtering */
if (ug_info->rxExtendedFiltering) {
if (!ug_info->extendedFilteringChainPointer) {
if (netif_msg_ifup(ugeth))
pr_err("Null Extended Filtering Chain Pointer\n");
return -EINVAL;
}
/* Allocate memory for extended filtering Mode Global
Parameters */
ugeth->exf_glbl_param_offset =
qe_muram_alloc(sizeof(struct ucc_geth_exf_global_pram),
UCC_GETH_RX_EXTENDED_FILTERING_GLOBAL_PARAMETERS_ALIGNMENT);
if (IS_ERR_VALUE(ugeth->exf_glbl_param_offset)) {
if (netif_msg_ifup(ugeth))
pr_err("Can not allocate DPRAM memory for p_exf_glbl_param\n");
return -ENOMEM;
}
ugeth->p_exf_glbl_param =
(struct ucc_geth_exf_global_pram __iomem *) qe_muram_addr(ugeth->
exf_glbl_param_offset);
out_be32(&ugeth->p_rx_glbl_pram->exfGlobalParam,
ugeth->exf_glbl_param_offset);
out_be32(&ugeth->p_exf_glbl_param->l2pcdptr,
(u32) ug_info->extendedFilteringChainPointer);
} else { /* initialize 82xx style address filtering */
/* Init individual address recognition registers to disabled */
for (j = 0; j < NUM_OF_PADDRS; j++)
ugeth_82xx_filtering_clear_addr_in_paddr(ugeth, (u8) j);
p_82xx_addr_filt =
(struct ucc_geth_82xx_address_filtering_pram __iomem *) ugeth->
p_rx_glbl_pram->addressfiltering;
ugeth_82xx_filtering_clear_all_addr_in_hash(ugeth,
ENET_ADDR_TYPE_GROUP);
ugeth_82xx_filtering_clear_all_addr_in_hash(ugeth,
ENET_ADDR_TYPE_INDIVIDUAL);
}
/*
* Initialize UCC at QE level
*/
command = QE_INIT_TX_RX;
/* Allocate shadow InitEnet command parameter structure.
* This is needed because after the InitEnet command is executed,
* the structure in DPRAM is released, because DPRAM is a premium
* resource.
* This shadow structure keeps a copy of what was done so that the
* allocated resources can be released when the channel is freed.
*/
if (!(ugeth->p_init_enet_param_shadow =
kzalloc(sizeof(struct ucc_geth_init_pram), GFP_KERNEL))) {
if (netif_msg_ifup(ugeth))
pr_err("Can not allocate memory for p_UccInitEnetParamShadows\n");
return -ENOMEM;
}
/* Fill shadow InitEnet command parameter structure */
ugeth->p_init_enet_param_shadow->resinit1 =
ENET_INIT_PARAM_MAGIC_RES_INIT1;
ugeth->p_init_enet_param_shadow->resinit2 =
ENET_INIT_PARAM_MAGIC_RES_INIT2;
ugeth->p_init_enet_param_shadow->resinit3 =
ENET_INIT_PARAM_MAGIC_RES_INIT3;
ugeth->p_init_enet_param_shadow->resinit4 =
ENET_INIT_PARAM_MAGIC_RES_INIT4;
ugeth->p_init_enet_param_shadow->resinit5 =
ENET_INIT_PARAM_MAGIC_RES_INIT5;
ugeth->p_init_enet_param_shadow->rgftgfrxglobal |=
((u32) ug_info->numThreadsRx) << ENET_INIT_PARAM_RGF_SHIFT;
ugeth->p_init_enet_param_shadow->rgftgfrxglobal |=
((u32) ug_info->numThreadsTx) << ENET_INIT_PARAM_TGF_SHIFT;
ugeth->p_init_enet_param_shadow->rgftgfrxglobal |=
rx_glbl_pram_offset | ug_info->riscRx;
if ((ug_info->largestexternallookupkeysize !=
QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_NONE) &&
(ug_info->largestexternallookupkeysize !=
QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_8_BYTES) &&
(ug_info->largestexternallookupkeysize !=
QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_16_BYTES)) {
if (netif_msg_ifup(ugeth))
pr_err("Invalid largest External Lookup Key Size\n");
return -EINVAL;
}
ugeth->p_init_enet_param_shadow->largestexternallookupkeysize =
ug_info->largestexternallookupkeysize;
size = sizeof(struct ucc_geth_thread_rx_pram);
if (ug_info->rxExtendedFiltering) {
size += THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING;
if (ug_info->largestexternallookupkeysize ==
QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_8_BYTES)
size +=
THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_8;
if (ug_info->largestexternallookupkeysize ==
QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_16_BYTES)
size +=
THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_16;
}
if ((ret_val = fill_init_enet_entries(ugeth, &(ugeth->
p_init_enet_param_shadow->rxthread[0]),
(u8) (numThreadsRxNumerical + 1)
/* Rx needs one extra for terminator */
, size, UCC_GETH_THREAD_RX_PRAM_ALIGNMENT,
ug_info->riscRx, 1)) != 0) {
if (netif_msg_ifup(ugeth))
pr_err("Can not fill p_init_enet_param_shadow\n");
return ret_val;
}
ugeth->p_init_enet_param_shadow->txglobal =
tx_glbl_pram_offset | ug_info->riscTx;
if ((ret_val =
fill_init_enet_entries(ugeth,
&(ugeth->p_init_enet_param_shadow->
txthread[0]), numThreadsTxNumerical,
sizeof(struct ucc_geth_thread_tx_pram),
UCC_GETH_THREAD_TX_PRAM_ALIGNMENT,
ug_info->riscTx, 0)) != 0) {
if (netif_msg_ifup(ugeth))
pr_err("Can not fill p_init_enet_param_shadow\n");
return ret_val;
}
/* Load Rx bds with buffers */
for (i = 0; i < ucc_geth_rx_queues(ug_info); i++) {
if ((ret_val = rx_bd_buffer_set(ugeth, (u8) i)) != 0) {
if (netif_msg_ifup(ugeth))
pr_err("Can not fill Rx bds with buffers\n");
return ret_val;
}
}
/* Allocate InitEnet command parameter structure */
init_enet_pram_offset = qe_muram_alloc(sizeof(struct ucc_geth_init_pram), 4);
if (IS_ERR_VALUE(init_enet_pram_offset)) {
if (netif_msg_ifup(ugeth))
pr_err("Can not allocate DPRAM memory for p_init_enet_pram\n");
return -ENOMEM;
}
p_init_enet_pram =
(struct ucc_geth_init_pram __iomem *) qe_muram_addr(init_enet_pram_offset);
/* Copy shadow InitEnet command parameter structure into PRAM */
out_8(&p_init_enet_pram->resinit1,
ugeth->p_init_enet_param_shadow->resinit1);
out_8(&p_init_enet_pram->resinit2,
ugeth->p_init_enet_param_shadow->resinit2);
out_8(&p_init_enet_pram->resinit3,
ugeth->p_init_enet_param_shadow->resinit3);
out_8(&p_init_enet_pram->resinit4,
ugeth->p_init_enet_param_shadow->resinit4);
out_be16(&p_init_enet_pram->resinit5,
ugeth->p_init_enet_param_shadow->resinit5);
out_8(&p_init_enet_pram->largestexternallookupkeysize,
ugeth->p_init_enet_param_shadow->largestexternallookupkeysize);
out_be32(&p_init_enet_pram->rgftgfrxglobal,
ugeth->p_init_enet_param_shadow->rgftgfrxglobal);
for (i = 0; i < ENET_INIT_PARAM_MAX_ENTRIES_RX; i++)
out_be32(&p_init_enet_pram->rxthread[i],
ugeth->p_init_enet_param_shadow->rxthread[i]);
out_be32(&p_init_enet_pram->txglobal,
ugeth->p_init_enet_param_shadow->txglobal);
for (i = 0; i < ENET_INIT_PARAM_MAX_ENTRIES_TX; i++)
out_be32(&p_init_enet_pram->txthread[i],
ugeth->p_init_enet_param_shadow->txthread[i]);
/* Issue QE command */
cecr_subblock =
ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num);
qe_issue_cmd(command, cecr_subblock, QE_CR_PROTOCOL_ETHERNET,
init_enet_pram_offset);
/* Free InitEnet command parameter */
qe_muram_free(init_enet_pram_offset);
return 0;
}