root/drivers/net/ethernet/stmicro/stmmac/norm_desc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ndesc_get_tx_status
  2. ndesc_get_tx_len
  3. ndesc_get_rx_status
  4. ndesc_init_rx_desc
  5. ndesc_init_tx_desc
  6. ndesc_get_tx_owner
  7. ndesc_set_tx_owner
  8. ndesc_set_rx_owner
  9. ndesc_get_tx_ls
  10. ndesc_release_tx_desc
  11. ndesc_prepare_tx_desc
  12. ndesc_set_tx_ic
  13. ndesc_get_rx_frame_len
  14. ndesc_enable_tx_timestamp
  15. ndesc_get_tx_timestamp_status
  16. ndesc_get_timestamp
  17. ndesc_get_rx_timestamp_status
  18. ndesc_display_ring
  19. ndesc_get_addr
  20. ndesc_set_addr
  21. ndesc_clear

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

/* [<][>][^][v][top][bottom][index][help] */