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