rx_utils.c (6281B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * File: rx_utils.c 8 * Purpose: 9 * Requires: 10 */ 11 12 13 #include <shared/bsl.h> 14 15 #include <sal/core/boot.h> 16 #include <sal/core/dpc.h> 17 #include <shared/bsl.h> 18 19 #include <soc/drv.h> 20 #include <soc/error.h> 21 #include <soc/debug.h> 22 #include <soc/mem.h> 23 #include <soc/dma.h> 24 25 #include <soc/rx.h> 26 27 #if defined(BCM_CMICM_SUPPORT) 28 #include <soc/cmicm.h> 29 #endif 30 31 int 32 soc_rx_queue_channel_set(int unit, int queue_id, 33 int chan_id) 34 { 35 #ifdef BCM_KATANA_SUPPORT 36 uint32 i = 0; 37 #endif 38 #if defined(BCM_CMICM_SUPPORT) || defined(BCM_CMICX_SUPPORT) 39 uint32 ix; 40 uint32 chan_id_max = SOC_RX_CHANNELS; 41 uint32 soc_rx_channels = SOC_RX_CHANNELS; 42 uint32 reg_addr = 0, reg_val; 43 int cmc; 44 int pci_cmc = SOC_PCI_CMC(unit); 45 uint32 chan_off = 0; 46 int startq = 0; 47 int numq, endq, countq; 48 int start_chan_id; 49 50 soc_dma_max_rx_channels_get(unit, &chan_id_max); 51 soc_rx_channels = chan_id_max; 52 53 if (0 != SOC_CMCS_NUM(unit)) { 54 chan_id_max *= SOC_CMCS_NUM(unit); 55 } 56 57 if (SOC_WARM_BOOT(unit)) { 58 return SOC_E_NONE; 59 } 60 if ((chan_id < 0) || (chan_id >= chan_id_max)) { 61 /* Verify the chan id */ 62 return SOC_E_PARAM; 63 } else if (queue_id >= NUM_CPU_COSQ(unit)) { 64 return SOC_E_PARAM; 65 } 66 67 if(soc_feature(unit, soc_feature_cmicm) || 68 soc_feature(unit, soc_feature_cmicx)) { 69 /* We institute the normalizing assumption that the 70 * channels are numbered first in the PCI CMC, then in order of the 71 * ARM CMCs. This is why we have the shuffling steps below. 72 */ 73 if (chan_id < soc_rx_channels) { 74 cmc = pci_cmc; 75 } else { 76 cmc = SOC_ARM_CMC(unit, ((chan_id / soc_rx_channels) - 1)); 77 /* compute start queue number for any CMC */ 78 startq = NUM_CPU_ARM_COSQ(unit, pci_cmc); 79 for (ix = 0; ix < cmc; ix++) { 80 startq += (ix != pci_cmc) ? NUM_CPU_ARM_COSQ(unit, ix) : 0; 81 } 82 } 83 84 numq = NUM_CPU_ARM_COSQ(unit, cmc); 85 start_chan_id = (cmc != pci_cmc) ? cmc * soc_rx_channels : 0; 86 87 if (queue_id < 0) { /* All COS Queues */ 88 /* validate the queue range of CMC is in the valid range 89 * for this CMC 90 */ 91 SHR_BITCOUNT_RANGE(CPU_ARM_QUEUE_BITMAP(unit, cmc), 92 countq, startq, numq); 93 if (numq != countq) { 94 return SOC_E_PARAM; 95 } 96 97 /* We know chan_id != -1 from the parameter check at the 98 * start of the function */ 99 endq = startq + NUM_CPU_ARM_COSQ(unit, cmc); 100 for (ix = start_chan_id; ix < (start_chan_id + soc_rx_channels); ix++) { 101 /* set CMIC_CMCx_CHy_COS_CTRL_RX_0/1 based on CMC's start 102 * and end queue number 103 */ 104 chan_off = ix % soc_rx_channels; 105 reg_val = 0; 106 if (ix == (uint32)chan_id) { 107 reg_val |= (endq < 32) ? 108 ((uint32)1 << endq) - 1 : 0xffffffff; 109 reg_val &= (startq < 32) ? 110 ~(((uint32)1 << startq) - 1) : 0; 111 } 112 113 /* 114 * Hard Code queue_id to 0 to ensure we get back COS_CTRL_RX_0 115 * register address. 116 */ 117 soc_dma_cos_ctrl_reg_addr_get(unit, cmc, chan_off, 118 0, ®_addr); 119 120 /* Incoporate the reserved queues (if any on this device) 121 * into the CMIC programming, */ 122 reg_val |= CPU_ARM_RSVD_QUEUE_BITMAP(unit,cmc)[0]; 123 soc_pci_write(unit, reg_addr, reg_val); 124 125 /* 126 * Hard Code queue_id to 32 to ensure we get back COS_CTRL_RX_1 127 * register address. 128 */ 129 soc_dma_cos_ctrl_reg_addr_get(unit, cmc, chan_off, 130 32, ®_addr); 131 132 #if defined(BCM_KATANA_SUPPORT) 133 if (SOC_IS_KATANAX(unit)) { 134 /* 135 * Katana queues have been disabled to prevent packets 136 * that cannot egress from reaching the CMIC. At this 137 * point those queues can be enabled. 138 */ 139 for (i = startq; i < endq; i++) { 140 reg_val = 0; 141 soc_reg_field_set(unit, 142 THDO_QUEUE_DISABLE_CFG2r, ®_val, QUEUE_NUMf, i); 143 SOC_IF_ERROR_RETURN( 144 WRITE_THDO_QUEUE_DISABLE_CFG2r(unit, reg_val)); 145 reg_val = 0; 146 soc_reg_field_set(unit, 147 THDO_QUEUE_DISABLE_CFG1r, ®_val, QUEUE_WRf, 1); 148 SOC_IF_ERROR_RETURN( 149 WRITE_THDO_QUEUE_DISABLE_CFG1r(unit, reg_val)); 150 } 151 } 152 #endif /*BCM_KATANA_SUPPORT */ 153 reg_val = 0; 154 /* Incoporate the reserved queues (if any on this device) 155 * into the CMIC programming, */ 156 reg_val |= CPU_ARM_RSVD_QUEUE_BITMAP(unit,cmc)[1]; 157 158 if (ix == (uint32)chan_id) { 159 reg_val |= ((endq >= 32) && (endq < 64)) ? 160 (((uint32)1 << (endq % 32)) - 1) : 161 ((endq < 32) ? 0 : 0xffffffff); 162 reg_val &= (startq >= 32) ? 163 ~(((uint32)1 << (startq % 32)) - 1) : 0xffffffff; 164 if (SOC_IS_TD2P_TT2P(unit)) { 165 soc_pci_write(unit, reg_addr, reg_val); 166 } 167 168 } 169 if (!SOC_IS_TD2P_TT2P(unit)) { 170 soc_pci_write(unit, reg_addr, reg_val); 171 } 172 } 173 } else { 174 return SOC_E_PARAM; 175 } 176 } else 177 #endif 178 { 179 return SOC_E_PARAM; 180 } 181 return SOC_E_NONE; 182 } 183