linux/drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/* 10G controller driver for Samsung SoCs
   3 *
   4 * Copyright (C) 2013 Samsung Electronics Co., Ltd.
   5 *              http://www.samsung.com
   6 *
   7 * Author: Siva Reddy Kallam <siva.kallam@samsung.com>
   8 */
   9
  10#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  11
  12#include <linux/bitops.h>
  13#include <linux/export.h>
  14#include <linux/io.h>
  15#include <linux/netdevice.h>
  16#include <linux/phy.h>
  17
  18#include "sxgbe_common.h"
  19#include "sxgbe_dma.h"
  20#include "sxgbe_desc.h"
  21
  22/* DMA TX descriptor ring initialization */
  23static void sxgbe_init_tx_desc(struct sxgbe_tx_norm_desc *p)
  24{
  25        p->tdes23.tx_rd_des23.own_bit = 0;
  26}
  27
  28static void sxgbe_tx_desc_enable_tse(struct sxgbe_tx_norm_desc *p, u8 is_tse,
  29                                     u32 total_hdr_len, u32 tcp_hdr_len,
  30                                     u32 tcp_payload_len)
  31{
  32        p->tdes23.tx_rd_des23.tse_bit = is_tse;
  33        p->tdes23.tx_rd_des23.buf1_size = total_hdr_len;
  34        p->tdes23.tx_rd_des23.tcp_hdr_len = tcp_hdr_len / 4;
  35        p->tdes23.tx_rd_des23.tx_pkt_len.tcp_payload_len  = tcp_payload_len;
  36}
  37
  38/* Assign buffer lengths for descriptor */
  39static void sxgbe_prepare_tx_desc(struct sxgbe_tx_norm_desc *p, u8 is_fd,
  40                                  int buf1_len, int pkt_len, int cksum)
  41{
  42        p->tdes23.tx_rd_des23.first_desc = is_fd;
  43        p->tdes23.tx_rd_des23.buf1_size = buf1_len;
  44
  45        p->tdes23.tx_rd_des23.tx_pkt_len.pkt_len.total_pkt_len = pkt_len;
  46
  47        if (cksum)
  48                p->tdes23.tx_rd_des23.cksum_ctl = cic_full;
  49}
  50
  51/* Set VLAN control information */
  52static void sxgbe_tx_vlanctl_desc(struct sxgbe_tx_norm_desc *p, int vlan_ctl)
  53{
  54        p->tdes23.tx_rd_des23.vlan_tag_ctl = vlan_ctl;
  55}
  56
  57/* Set the owner of Normal descriptor */
  58static void sxgbe_set_tx_owner(struct sxgbe_tx_norm_desc *p)
  59{
  60        p->tdes23.tx_rd_des23.own_bit = 1;
  61}
  62
  63/* Get the owner of Normal descriptor */
  64static int sxgbe_get_tx_owner(struct sxgbe_tx_norm_desc *p)
  65{
  66        return p->tdes23.tx_rd_des23.own_bit;
  67}
  68
  69/* Invoked by the xmit function to close the tx descriptor */
  70static void sxgbe_close_tx_desc(struct sxgbe_tx_norm_desc *p)
  71{
  72        p->tdes23.tx_rd_des23.last_desc = 1;
  73        p->tdes23.tx_rd_des23.int_on_com = 1;
  74}
  75
  76/* Clean the tx descriptor as soon as the tx irq is received */
  77static void sxgbe_release_tx_desc(struct sxgbe_tx_norm_desc *p)
  78{
  79        memset(p, 0, sizeof(*p));
  80}
  81
  82/* Clear interrupt on tx frame completion. When this bit is
  83 * set an interrupt happens as soon as the frame is transmitted
  84 */
  85static void sxgbe_clear_tx_ic(struct sxgbe_tx_norm_desc *p)
  86{
  87        p->tdes23.tx_rd_des23.int_on_com = 0;
  88}
  89
  90/* Last tx segment reports the transmit status */
  91static int sxgbe_get_tx_ls(struct sxgbe_tx_norm_desc *p)
  92{
  93        return p->tdes23.tx_rd_des23.last_desc;
  94}
  95
  96/* Get the buffer size from the descriptor */
  97static int sxgbe_get_tx_len(struct sxgbe_tx_norm_desc *p)
  98{
  99        return p->tdes23.tx_rd_des23.buf1_size;
 100}
 101
 102/* Set tx timestamp enable bit */
 103static void sxgbe_tx_enable_tstamp(struct sxgbe_tx_norm_desc *p)
 104{
 105        p->tdes23.tx_rd_des23.timestmp_enable = 1;
 106}
 107
 108/* get tx timestamp status */
 109static int sxgbe_get_tx_timestamp_status(struct sxgbe_tx_norm_desc *p)
 110{
 111        return p->tdes23.tx_rd_des23.timestmp_enable;
 112}
 113
 114/* TX Context Descripto Specific */
 115static void sxgbe_tx_ctxt_desc_set_ctxt(struct sxgbe_tx_ctxt_desc *p)
 116{
 117        p->ctxt_bit = 1;
 118}
 119
 120/* Set the owner of TX context descriptor */
 121static void sxgbe_tx_ctxt_desc_set_owner(struct sxgbe_tx_ctxt_desc *p)
 122{
 123        p->own_bit = 1;
 124}
 125
 126/* Get the owner of TX context descriptor */
 127static int sxgbe_tx_ctxt_desc_get_owner(struct sxgbe_tx_ctxt_desc *p)
 128{
 129        return p->own_bit;
 130}
 131
 132/* Set TX mss in TX context Descriptor */
 133static void sxgbe_tx_ctxt_desc_set_mss(struct sxgbe_tx_ctxt_desc *p, u16 mss)
 134{
 135        p->maxseg_size = mss;
 136}
 137
 138/* Get TX mss from TX context Descriptor */
 139static int sxgbe_tx_ctxt_desc_get_mss(struct sxgbe_tx_ctxt_desc *p)
 140{
 141        return p->maxseg_size;
 142}
 143
 144/* Set TX tcmssv in TX context Descriptor */
 145static void sxgbe_tx_ctxt_desc_set_tcmssv(struct sxgbe_tx_ctxt_desc *p)
 146{
 147        p->tcmssv = 1;
 148}
 149
 150/* Reset TX ostc in TX context Descriptor */
 151static void sxgbe_tx_ctxt_desc_reset_ostc(struct sxgbe_tx_ctxt_desc *p)
 152{
 153        p->ostc = 0;
 154}
 155
 156/* Set IVLAN information */
 157static void sxgbe_tx_ctxt_desc_set_ivlantag(struct sxgbe_tx_ctxt_desc *p,
 158                                            int is_ivlanvalid, int ivlan_tag,
 159                                            int ivlan_ctl)
 160{
 161        if (is_ivlanvalid) {
 162                p->ivlan_tag_valid = is_ivlanvalid;
 163                p->ivlan_tag = ivlan_tag;
 164                p->ivlan_tag_ctl = ivlan_ctl;
 165        }
 166}
 167
 168/* Return IVLAN Tag */
 169static int sxgbe_tx_ctxt_desc_get_ivlantag(struct sxgbe_tx_ctxt_desc *p)
 170{
 171        return p->ivlan_tag;
 172}
 173
 174/* Set VLAN Tag */
 175static void sxgbe_tx_ctxt_desc_set_vlantag(struct sxgbe_tx_ctxt_desc *p,
 176                                           int is_vlanvalid, int vlan_tag)
 177{
 178        if (is_vlanvalid) {
 179                p->vltag_valid = is_vlanvalid;
 180                p->vlan_tag = vlan_tag;
 181        }
 182}
 183
 184/* Return VLAN Tag */
 185static int sxgbe_tx_ctxt_desc_get_vlantag(struct sxgbe_tx_ctxt_desc *p)
 186{
 187        return p->vlan_tag;
 188}
 189
 190/* Set Time stamp */
 191static void sxgbe_tx_ctxt_desc_set_tstamp(struct sxgbe_tx_ctxt_desc *p,
 192                                          u8 ostc_enable, u64 tstamp)
 193{
 194        if (ostc_enable) {
 195                p->ostc = ostc_enable;
 196                p->tstamp_lo = (u32) tstamp;
 197                p->tstamp_hi = (u32) (tstamp>>32);
 198        }
 199}
 200/* Close TX context descriptor */
 201static void sxgbe_tx_ctxt_desc_close(struct sxgbe_tx_ctxt_desc *p)
 202{
 203        p->own_bit = 1;
 204}
 205
 206/* WB status of context descriptor */
 207static int sxgbe_tx_ctxt_desc_get_cde(struct sxgbe_tx_ctxt_desc *p)
 208{
 209        return p->ctxt_desc_err;
 210}
 211
 212/* DMA RX descriptor ring initialization */
 213static void sxgbe_init_rx_desc(struct sxgbe_rx_norm_desc *p, int disable_rx_ic,
 214                               int mode, int end)
 215{
 216        p->rdes23.rx_rd_des23.own_bit = 1;
 217        if (disable_rx_ic)
 218                p->rdes23.rx_rd_des23.int_on_com = disable_rx_ic;
 219}
 220
 221/* Get RX own bit */
 222static int sxgbe_get_rx_owner(struct sxgbe_rx_norm_desc *p)
 223{
 224        return p->rdes23.rx_rd_des23.own_bit;
 225}
 226
 227/* Set RX own bit */
 228static void sxgbe_set_rx_owner(struct sxgbe_rx_norm_desc *p)
 229{
 230        p->rdes23.rx_rd_des23.own_bit = 1;
 231}
 232
 233/* Set Interrupt on completion bit */
 234static void sxgbe_set_rx_int_on_com(struct sxgbe_rx_norm_desc *p)
 235{
 236        p->rdes23.rx_rd_des23.int_on_com = 1;
 237}
 238
 239/* Get the receive frame size */
 240static int sxgbe_get_rx_frame_len(struct sxgbe_rx_norm_desc *p)
 241{
 242        return p->rdes23.rx_wb_des23.pkt_len;
 243}
 244
 245/* Return first Descriptor status */
 246static int sxgbe_get_rx_fd_status(struct sxgbe_rx_norm_desc *p)
 247{
 248        return p->rdes23.rx_wb_des23.first_desc;
 249}
 250
 251/* Return Last Descriptor status */
 252static int sxgbe_get_rx_ld_status(struct sxgbe_rx_norm_desc *p)
 253{
 254        return p->rdes23.rx_wb_des23.last_desc;
 255}
 256
 257
 258/* Return the RX status looking at the WB fields */
 259static int sxgbe_rx_wbstatus(struct sxgbe_rx_norm_desc *p,
 260                             struct sxgbe_extra_stats *x, int *checksum)
 261{
 262        int status = 0;
 263
 264        *checksum = CHECKSUM_UNNECESSARY;
 265        if (p->rdes23.rx_wb_des23.err_summary) {
 266                switch (p->rdes23.rx_wb_des23.err_l2_type) {
 267                case RX_GMII_ERR:
 268                        status = -EINVAL;
 269                        x->rx_code_gmii_err++;
 270                        break;
 271                case RX_WATCHDOG_ERR:
 272                        status = -EINVAL;
 273                        x->rx_watchdog_err++;
 274                        break;
 275                case RX_CRC_ERR:
 276                        status = -EINVAL;
 277                        x->rx_crc_err++;
 278                        break;
 279                case RX_GAINT_ERR:
 280                        status = -EINVAL;
 281                        x->rx_gaint_pkt_err++;
 282                        break;
 283                case RX_IP_HDR_ERR:
 284                        *checksum = CHECKSUM_NONE;
 285                        x->ip_hdr_err++;
 286                        break;
 287                case RX_PAYLOAD_ERR:
 288                        *checksum = CHECKSUM_NONE;
 289                        x->ip_payload_err++;
 290                        break;
 291                case RX_OVERFLOW_ERR:
 292                        status = -EINVAL;
 293                        x->overflow_error++;
 294                        break;
 295                default:
 296                        pr_err("Invalid Error type\n");
 297                        break;
 298                }
 299        } else {
 300                switch (p->rdes23.rx_wb_des23.err_l2_type) {
 301                case RX_LEN_PKT:
 302                        x->len_pkt++;
 303                        break;
 304                case RX_MACCTL_PKT:
 305                        x->mac_ctl_pkt++;
 306                        break;
 307                case RX_DCBCTL_PKT:
 308                        x->dcb_ctl_pkt++;
 309                        break;
 310                case RX_ARP_PKT:
 311                        x->arp_pkt++;
 312                        break;
 313                case RX_OAM_PKT:
 314                        x->oam_pkt++;
 315                        break;
 316                case RX_UNTAG_PKT:
 317                        x->untag_okt++;
 318                        break;
 319                case RX_OTHER_PKT:
 320                        x->other_pkt++;
 321                        break;
 322                case RX_SVLAN_PKT:
 323                        x->svlan_tag_pkt++;
 324                        break;
 325                case RX_CVLAN_PKT:
 326                        x->cvlan_tag_pkt++;
 327                        break;
 328                case RX_DVLAN_OCVLAN_ICVLAN_PKT:
 329                        x->dvlan_ocvlan_icvlan_pkt++;
 330                        break;
 331                case RX_DVLAN_OSVLAN_ISVLAN_PKT:
 332                        x->dvlan_osvlan_isvlan_pkt++;
 333                        break;
 334                case RX_DVLAN_OSVLAN_ICVLAN_PKT:
 335                        x->dvlan_osvlan_icvlan_pkt++;
 336                        break;
 337                case RX_DVLAN_OCVLAN_ISVLAN_PKT:
 338                        x->dvlan_ocvlan_icvlan_pkt++;
 339                        break;
 340                default:
 341                        pr_err("Invalid L2 Packet type\n");
 342                        break;
 343                }
 344        }
 345
 346        /* L3/L4 Pkt type */
 347        switch (p->rdes23.rx_wb_des23.layer34_pkt_type) {
 348        case RX_NOT_IP_PKT:
 349                x->not_ip_pkt++;
 350                break;
 351        case RX_IPV4_TCP_PKT:
 352                x->ip4_tcp_pkt++;
 353                break;
 354        case RX_IPV4_UDP_PKT:
 355                x->ip4_udp_pkt++;
 356                break;
 357        case RX_IPV4_ICMP_PKT:
 358                x->ip4_icmp_pkt++;
 359                break;
 360        case RX_IPV4_UNKNOWN_PKT:
 361                x->ip4_unknown_pkt++;
 362                break;
 363        case RX_IPV6_TCP_PKT:
 364                x->ip6_tcp_pkt++;
 365                break;
 366        case RX_IPV6_UDP_PKT:
 367                x->ip6_udp_pkt++;
 368                break;
 369        case RX_IPV6_ICMP_PKT:
 370                x->ip6_icmp_pkt++;
 371                break;
 372        case RX_IPV6_UNKNOWN_PKT:
 373                x->ip6_unknown_pkt++;
 374                break;
 375        default:
 376                pr_err("Invalid L3/L4 Packet type\n");
 377                break;
 378        }
 379
 380        /* Filter */
 381        if (p->rdes23.rx_wb_des23.vlan_filter_match)
 382                x->vlan_filter_match++;
 383
 384        if (p->rdes23.rx_wb_des23.sa_filter_fail) {
 385                status = -EINVAL;
 386                x->sa_filter_fail++;
 387        }
 388        if (p->rdes23.rx_wb_des23.da_filter_fail) {
 389                status = -EINVAL;
 390                x->da_filter_fail++;
 391        }
 392        if (p->rdes23.rx_wb_des23.hash_filter_pass)
 393                x->hash_filter_pass++;
 394
 395        if (p->rdes23.rx_wb_des23.l3_filter_match)
 396                x->l3_filter_match++;
 397
 398        if (p->rdes23.rx_wb_des23.l4_filter_match)
 399                x->l4_filter_match++;
 400
 401        return status;
 402}
 403
 404/* Get own bit of context descriptor */
 405static int sxgbe_get_rx_ctxt_owner(struct sxgbe_rx_ctxt_desc *p)
 406{
 407        return p->own_bit;
 408}
 409
 410/* Set own bit for context descriptor */
 411static void sxgbe_set_ctxt_rx_owner(struct sxgbe_rx_ctxt_desc *p)
 412{
 413        p->own_bit = 1;
 414}
 415
 416
 417/* Return the reception status looking at Context control information */
 418static void sxgbe_rx_ctxt_wbstatus(struct sxgbe_rx_ctxt_desc *p,
 419                                   struct sxgbe_extra_stats *x)
 420{
 421        if (p->tstamp_dropped)
 422                x->timestamp_dropped++;
 423
 424        /* ptp */
 425        if (p->ptp_msgtype == RX_NO_PTP)
 426                x->rx_msg_type_no_ptp++;
 427        else if (p->ptp_msgtype == RX_PTP_SYNC)
 428                x->rx_ptp_type_sync++;
 429        else if (p->ptp_msgtype == RX_PTP_FOLLOW_UP)
 430                x->rx_ptp_type_follow_up++;
 431        else if (p->ptp_msgtype == RX_PTP_DELAY_REQ)
 432                x->rx_ptp_type_delay_req++;
 433        else if (p->ptp_msgtype == RX_PTP_DELAY_RESP)
 434                x->rx_ptp_type_delay_resp++;
 435        else if (p->ptp_msgtype == RX_PTP_PDELAY_REQ)
 436                x->rx_ptp_type_pdelay_req++;
 437        else if (p->ptp_msgtype == RX_PTP_PDELAY_RESP)
 438                x->rx_ptp_type_pdelay_resp++;
 439        else if (p->ptp_msgtype == RX_PTP_PDELAY_FOLLOW_UP)
 440                x->rx_ptp_type_pdelay_follow_up++;
 441        else if (p->ptp_msgtype == RX_PTP_ANNOUNCE)
 442                x->rx_ptp_announce++;
 443        else if (p->ptp_msgtype == RX_PTP_MGMT)
 444                x->rx_ptp_mgmt++;
 445        else if (p->ptp_msgtype == RX_PTP_SIGNAL)
 446                x->rx_ptp_signal++;
 447        else if (p->ptp_msgtype == RX_PTP_RESV_MSG)
 448                x->rx_ptp_resv_msg_type++;
 449}
 450
 451/* Get rx timestamp status */
 452static int sxgbe_get_rx_ctxt_tstamp_status(struct sxgbe_rx_ctxt_desc *p)
 453{
 454        if ((p->tstamp_hi == 0xffffffff) && (p->tstamp_lo == 0xffffffff)) {
 455                pr_err("Time stamp corrupted\n");
 456                return 0;
 457        }
 458
 459        return p->tstamp_available;
 460}
 461
 462
 463static u64 sxgbe_get_rx_timestamp(struct sxgbe_rx_ctxt_desc *p)
 464{
 465        u64 ns;
 466
 467        ns = p->tstamp_lo;
 468        ns |= ((u64)p->tstamp_hi) << 32;
 469
 470        return ns;
 471}
 472
 473static const struct sxgbe_desc_ops desc_ops = {
 474        .init_tx_desc                   = sxgbe_init_tx_desc,
 475        .tx_desc_enable_tse             = sxgbe_tx_desc_enable_tse,
 476        .prepare_tx_desc                = sxgbe_prepare_tx_desc,
 477        .tx_vlanctl_desc                = sxgbe_tx_vlanctl_desc,
 478        .set_tx_owner                   = sxgbe_set_tx_owner,
 479        .get_tx_owner                   = sxgbe_get_tx_owner,
 480        .close_tx_desc                  = sxgbe_close_tx_desc,
 481        .release_tx_desc                = sxgbe_release_tx_desc,
 482        .clear_tx_ic                    = sxgbe_clear_tx_ic,
 483        .get_tx_ls                      = sxgbe_get_tx_ls,
 484        .get_tx_len                     = sxgbe_get_tx_len,
 485        .tx_enable_tstamp               = sxgbe_tx_enable_tstamp,
 486        .get_tx_timestamp_status        = sxgbe_get_tx_timestamp_status,
 487        .tx_ctxt_desc_set_ctxt          = sxgbe_tx_ctxt_desc_set_ctxt,
 488        .tx_ctxt_desc_set_owner         = sxgbe_tx_ctxt_desc_set_owner,
 489        .get_tx_ctxt_owner              = sxgbe_tx_ctxt_desc_get_owner,
 490        .tx_ctxt_desc_set_mss           = sxgbe_tx_ctxt_desc_set_mss,
 491        .tx_ctxt_desc_get_mss           = sxgbe_tx_ctxt_desc_get_mss,
 492        .tx_ctxt_desc_set_tcmssv        = sxgbe_tx_ctxt_desc_set_tcmssv,
 493        .tx_ctxt_desc_reset_ostc        = sxgbe_tx_ctxt_desc_reset_ostc,
 494        .tx_ctxt_desc_set_ivlantag      = sxgbe_tx_ctxt_desc_set_ivlantag,
 495        .tx_ctxt_desc_get_ivlantag      = sxgbe_tx_ctxt_desc_get_ivlantag,
 496        .tx_ctxt_desc_set_vlantag       = sxgbe_tx_ctxt_desc_set_vlantag,
 497        .tx_ctxt_desc_get_vlantag       = sxgbe_tx_ctxt_desc_get_vlantag,
 498        .tx_ctxt_set_tstamp             = sxgbe_tx_ctxt_desc_set_tstamp,
 499        .close_tx_ctxt_desc             = sxgbe_tx_ctxt_desc_close,
 500        .get_tx_ctxt_cde                = sxgbe_tx_ctxt_desc_get_cde,
 501        .init_rx_desc                   = sxgbe_init_rx_desc,
 502        .get_rx_owner                   = sxgbe_get_rx_owner,
 503        .set_rx_owner                   = sxgbe_set_rx_owner,
 504        .set_rx_int_on_com              = sxgbe_set_rx_int_on_com,
 505        .get_rx_frame_len               = sxgbe_get_rx_frame_len,
 506        .get_rx_fd_status               = sxgbe_get_rx_fd_status,
 507        .get_rx_ld_status               = sxgbe_get_rx_ld_status,
 508        .rx_wbstatus                    = sxgbe_rx_wbstatus,
 509        .get_rx_ctxt_owner              = sxgbe_get_rx_ctxt_owner,
 510        .set_rx_ctxt_owner              = sxgbe_set_ctxt_rx_owner,
 511        .rx_ctxt_wbstatus               = sxgbe_rx_ctxt_wbstatus,
 512        .get_rx_ctxt_tstamp_status      = sxgbe_get_rx_ctxt_tstamp_status,
 513        .get_timestamp                  = sxgbe_get_rx_timestamp,
 514};
 515
 516const struct sxgbe_desc_ops *sxgbe_get_desc_ops(void)
 517{
 518        return &desc_ops;
 519}
 520