1 // SPDX-License-Identifier: GPL-2.0-only 2 /******************************************************************************* 3 This contains the functions to handle the normal descriptors. 4 5 Copyright (C) 2007-2009 STMicroelectronics Ltd 6 7 8 Author: Giuseppe Cavallaro <peppe.cavallaro@st.com> 9 *******************************************************************************/ 10 11 #include <linux/stmmac.h> 12 #include "common.h" 13 #include "descs_com.h" 14 15 static int ndesc_get_tx_status(struct stmmac_extra_stats *x, 16 struct dma_desc *p, void __iomem *ioaddr) 17 { 18 u32 tdes0 = le32_to_cpu(p->des0); 19 u32 tdes1 = le32_to_cpu(p->des1); 20 int ret = tx_done; 21 22 /* Get tx owner first */ 23 if (unlikely(tdes0 & TDES0_OWN)) 24 return tx_dma_own; 25 26 /* Verify tx error by looking at the last segment. */ 27 if (likely(!(tdes1 & TDES1_LAST_SEGMENT))) 28 return tx_not_ls; 29 30 if (unlikely(tdes0 & TDES0_ERROR_SUMMARY)) { 31 if (unlikely(tdes0 & TDES0_UNDERFLOW_ERROR)) { 32 x->tx_underflow++; 33 } 34 if (unlikely(tdes0 & TDES0_NO_CARRIER)) { 35 x->tx_carrier++; 36 } 37 if (unlikely(tdes0 & TDES0_LOSS_CARRIER)) { 38 x->tx_losscarrier++; 39 } 40 if (unlikely((tdes0 & TDES0_EXCESSIVE_DEFERRAL) || 41 (tdes0 & TDES0_EXCESSIVE_COLLISIONS) || 42 (tdes0 & TDES0_LATE_COLLISION))) { 43 x->tx_collision += 44 FIELD_GET(TDES0_COLLISION_COUNT_MASK, tdes0); 45 } 46 ret = tx_err; 47 } 48 49 if (tdes0 & TDES0_VLAN_FRAME) 50 x->tx_vlan++; 51 52 if (unlikely(tdes0 & TDES0_DEFERRED)) 53 x->tx_deferred++; 54 55 return ret; 56 } 57 58 static int ndesc_get_tx_len(struct dma_desc *p) 59 { 60 return (le32_to_cpu(p->des1) & RDES1_BUFFER1_SIZE_MASK); 61 } 62 63 /* This function verifies if each incoming frame has some errors 64 * and, if required, updates the multicast statistics. 65 * In case of success, it returns good_frame because the GMAC device 66 * is supposed to be able to compute the csum in HW. */ 67 static int ndesc_get_rx_status(struct stmmac_extra_stats *x, 68 struct dma_desc *p) 69 { 70 u32 rdes0 = le32_to_cpu(p->des0); 71 int ret = good_frame; 72 73 if (unlikely(rdes0 & RDES0_OWN)) 74 return dma_own; 75 76 if (unlikely(!(rdes0 & RDES0_LAST_DESCRIPTOR))) { 77 x->rx_length++; 78 return discard_frame; 79 } 80 81 if (unlikely(rdes0 & RDES0_ERROR_SUMMARY)) { 82 if (unlikely(rdes0 & RDES0_DESCRIPTOR_ERROR)) 83 x->rx_desc++; 84 if (unlikely(rdes0 & RDES0_SA_FILTER_FAIL)) 85 x->sa_filter_fail++; 86 if (unlikely(rdes0 & RDES0_OVERFLOW_ERROR)) 87 x->overflow_error++; 88 if (unlikely(rdes0 & RDES0_IPC_CSUM_ERROR)) 89 x->ipc_csum_error++; 90 if (unlikely(rdes0 & RDES0_COLLISION)) { 91 x->rx_collision++; 92 } 93 if (unlikely(rdes0 & RDES0_CRC_ERROR)) { 94 x->rx_crc_errors++; 95 } 96 ret = discard_frame; 97 } 98 if (unlikely(rdes0 & RDES0_DRIBBLING)) 99 x->dribbling_bit++; 100 101 if (unlikely(rdes0 & RDES0_LENGTH_ERROR)) { 102 x->rx_length++; 103 ret = discard_frame; 104 } 105 if (unlikely(rdes0 & RDES0_MII_ERROR)) { 106 x->rx_mii++; 107 ret = discard_frame; 108 } 109 #ifdef STMMAC_VLAN_TAG_USED 110 if (rdes0 & RDES0_VLAN_TAG) 111 x->vlan_tag++; 112 #endif 113 return ret; 114 } 115 116 static void ndesc_init_rx_desc(struct dma_desc *p, int disable_rx_ic, int mode, 117 int end, int bfsize) 118 { 119 int bfsize1; 120 121 p->des0 |= cpu_to_le32(RDES0_OWN); 122 123 bfsize1 = min(bfsize, BUF_SIZE_2KiB - 1); 124 p->des1 |= cpu_to_le32(bfsize1 & RDES1_BUFFER1_SIZE_MASK); 125 126 if (mode == STMMAC_CHAIN_MODE) 127 ndesc_rx_set_on_chain(p, end); 128 else 129 ndesc_rx_set_on_ring(p, end, bfsize); 130 131 if (disable_rx_ic) 132 p->des1 |= cpu_to_le32(RDES1_DISABLE_IC); 133 } 134 135 static void ndesc_init_tx_desc(struct dma_desc *p, int mode, int end) 136 { 137 p->des0 &= cpu_to_le32(~TDES0_OWN); 138 if (mode == STMMAC_CHAIN_MODE) 139 ndesc_tx_set_on_chain(p); 140 else 141 ndesc_end_tx_desc_on_ring(p, end); 142 } 143 144 static int ndesc_get_tx_owner(struct dma_desc *p) 145 { 146 return (le32_to_cpu(p->des0) & TDES0_OWN) >> 31; 147 } 148 149 static void ndesc_set_tx_owner(struct dma_desc *p) 150 { 151 p->des0 |= cpu_to_le32(TDES0_OWN); 152 } 153 154 static void ndesc_set_rx_owner(struct dma_desc *p, int disable_rx_ic) 155 { 156 p->des0 |= cpu_to_le32(RDES0_OWN); 157 } 158 159 static int ndesc_get_tx_ls(struct dma_desc *p) 160 { 161 return (le32_to_cpu(p->des1) & TDES1_LAST_SEGMENT) >> 30; 162 } 163 164 static void ndesc_release_tx_desc(struct dma_desc *p, int mode) 165 { 166 int ter = (le32_to_cpu(p->des1) & TDES1_END_RING) >> 25; 167 168 memset(p, 0, offsetof(struct dma_desc, des2)); 169 if (mode == STMMAC_CHAIN_MODE) 170 ndesc_tx_set_on_chain(p); 171 else 172 ndesc_end_tx_desc_on_ring(p, ter); 173 } 174 175 static void ndesc_prepare_tx_desc(struct dma_desc *p, int is_fs, int len, 176 bool csum_flag, int mode, bool tx_own, 177 bool ls, unsigned int tot_pkt_len) 178 { 179 u32 tdes1 = le32_to_cpu(p->des1); 180 181 if (is_fs) 182 tdes1 |= TDES1_FIRST_SEGMENT; 183 else 184 tdes1 &= ~TDES1_FIRST_SEGMENT; 185 186 tdes1 = u32_replace_bits(tdes1, csum_flag ? TX_CIC_FULL : 0, 187 TDES1_CHECKSUM_INSERTION_MASK); 188 189 if (ls) 190 tdes1 |= TDES1_LAST_SEGMENT; 191 192 p->des1 = cpu_to_le32(tdes1); 193 194 if (mode == STMMAC_CHAIN_MODE) 195 norm_set_tx_desc_len_on_chain(p, len); 196 else 197 norm_set_tx_desc_len_on_ring(p, len); 198 199 if (tx_own) 200 p->des0 |= cpu_to_le32(TDES0_OWN); 201 } 202 203 static void ndesc_set_tx_ic(struct dma_desc *p) 204 { 205 p->des1 |= cpu_to_le32(TDES1_INTERRUPT); 206 } 207 208 static int ndesc_get_rx_frame_len(struct dma_desc *p, int rx_coe_type) 209 { 210 unsigned int csum = 0; 211 212 /* The type-1 checksum offload engines append the checksum at 213 * the end of frame and the two bytes of checksum are added in 214 * the length. 215 * Adjust for that in the framelen for type-1 checksum offload 216 * engines 217 */ 218 if (rx_coe_type == STMMAC_RX_COE_TYPE1) 219 csum = 2; 220 221 return FIELD_GET(RDES0_FRAME_LEN_MASK, le32_to_cpu(p->des0)) - csum; 222 } 223 224 static void ndesc_enable_tx_timestamp(struct dma_desc *p) 225 { 226 p->des1 |= cpu_to_le32(TDES1_TIME_STAMP_ENABLE); 227 } 228 229 static int ndesc_get_tx_timestamp_status(struct dma_desc *p) 230 { 231 return (le32_to_cpu(p->des0) & TDES0_TIME_STAMP_STATUS) >> 17; 232 } 233 234 static void ndesc_get_timestamp(void *desc, u32 ats, u64 *ts) 235 { 236 struct dma_desc *p = (struct dma_desc *)desc; 237 u64 ns; 238 239 ns = le32_to_cpu(p->des2); 240 /* convert high/sec time stamp value to nanosecond */ 241 ns += le32_to_cpu(p->des3) * 1000000000ULL; 242 243 *ts = ns; 244 } 245 246 static int ndesc_get_rx_timestamp_status(void *desc, void *next_desc, u32 ats) 247 { 248 struct dma_desc *p = (struct dma_desc *)desc; 249 250 if ((le32_to_cpu(p->des2) == 0xffffffff) && 251 (le32_to_cpu(p->des3) == 0xffffffff)) 252 /* timestamp is corrupted, hence don't store it */ 253 return 0; 254 else 255 return 1; 256 } 257 258 static void ndesc_display_ring(void *head, unsigned int size, bool rx, 259 dma_addr_t dma_rx_phy, unsigned int desc_size) 260 { 261 struct dma_desc *p = (struct dma_desc *)head; 262 dma_addr_t dma_addr; 263 int i; 264 265 pr_info("%s descriptor ring:\n", rx ? "RX" : "TX"); 266 267 for (i = 0; i < size; i++) { 268 u64 x; 269 dma_addr = dma_rx_phy + i * sizeof(*p); 270 271 x = *(u64 *)p; 272 pr_info("%03d [%pad]: 0x%x 0x%x 0x%x 0x%x", 273 i, &dma_addr, 274 (unsigned int)x, (unsigned int)(x >> 32), 275 p->des2, p->des3); 276 p++; 277 } 278 pr_info("\n"); 279 } 280 281 static void ndesc_set_addr(struct dma_desc *p, dma_addr_t addr) 282 { 283 p->des2 = cpu_to_le32(addr); 284 } 285 286 static void ndesc_clear(struct dma_desc *p) 287 { 288 p->des2 = 0; 289 } 290 291 const struct stmmac_desc_ops ndesc_ops = { 292 .tx_status = ndesc_get_tx_status, 293 .rx_status = ndesc_get_rx_status, 294 .get_tx_len = ndesc_get_tx_len, 295 .init_rx_desc = ndesc_init_rx_desc, 296 .init_tx_desc = ndesc_init_tx_desc, 297 .get_tx_owner = ndesc_get_tx_owner, 298 .release_tx_desc = ndesc_release_tx_desc, 299 .prepare_tx_desc = ndesc_prepare_tx_desc, 300 .set_tx_ic = ndesc_set_tx_ic, 301 .get_tx_ls = ndesc_get_tx_ls, 302 .set_tx_owner = ndesc_set_tx_owner, 303 .set_rx_owner = ndesc_set_rx_owner, 304 .get_rx_frame_len = ndesc_get_rx_frame_len, 305 .enable_tx_timestamp = ndesc_enable_tx_timestamp, 306 .get_tx_timestamp_status = ndesc_get_tx_timestamp_status, 307 .get_timestamp = ndesc_get_timestamp, 308 .get_rx_timestamp_status = ndesc_get_rx_timestamp_status, 309 .display_ring = ndesc_display_ring, 310 .set_addr = ndesc_set_addr, 311 .clear = ndesc_clear, 312 }; 313