linux/drivers/net/ethernet/microchip/sparx5/sparx5_fdma.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/* Microchip Sparx5 Switch driver
   3 *
   4 * Copyright (c) 2021 Microchip Technology Inc. and its subsidiaries.
   5 *
   6 * The Sparx5 Chip Register Model can be browsed at this location:
   7 * https://github.com/microchip-ung/sparx-5_reginfo
   8 */
   9
  10#include <linux/types.h>
  11#include <linux/skbuff.h>
  12#include <linux/netdevice.h>
  13#include <linux/interrupt.h>
  14#include <linux/ip.h>
  15#include <linux/dma-mapping.h>
  16
  17#include "sparx5_main_regs.h"
  18#include "sparx5_main.h"
  19#include "sparx5_port.h"
  20
  21#define FDMA_XTR_CHANNEL                6
  22#define FDMA_INJ_CHANNEL                0
  23
  24#define FDMA_DCB_INFO_DATAL(x)          ((x) & GENMASK(15, 0))
  25#define FDMA_DCB_INFO_TOKEN             BIT(17)
  26#define FDMA_DCB_INFO_INTR              BIT(18)
  27#define FDMA_DCB_INFO_SW(x)             (((x) << 24) & GENMASK(31, 24))
  28
  29#define FDMA_DCB_STATUS_BLOCKL(x)       ((x) & GENMASK(15, 0))
  30#define FDMA_DCB_STATUS_SOF             BIT(16)
  31#define FDMA_DCB_STATUS_EOF             BIT(17)
  32#define FDMA_DCB_STATUS_INTR            BIT(18)
  33#define FDMA_DCB_STATUS_DONE            BIT(19)
  34#define FDMA_DCB_STATUS_BLOCKO(x)       (((x) << 20) & GENMASK(31, 20))
  35#define FDMA_DCB_INVALID_DATA           0x1
  36
  37#define FDMA_XTR_BUFFER_SIZE            2048
  38#define FDMA_WEIGHT                     4
  39
  40/* Frame DMA DCB format
  41 *
  42 * +---------------------------+
  43 * |         Next Ptr          |
  44 * +---------------------------+
  45 * |   Reserved  |    Info     |
  46 * +---------------------------+
  47 * |         Data0 Ptr         |
  48 * +---------------------------+
  49 * |   Reserved  |    Status0  |
  50 * +---------------------------+
  51 * |         Data1 Ptr         |
  52 * +---------------------------+
  53 * |   Reserved  |    Status1  |
  54 * +---------------------------+
  55 * |         Data2 Ptr         |
  56 * +---------------------------+
  57 * |   Reserved  |    Status2  |
  58 * |-------------|-------------|
  59 * |                           |
  60 * |                           |
  61 * |                           |
  62 * |                           |
  63 * |                           |
  64 * |---------------------------|
  65 * |         Data14 Ptr        |
  66 * +-------------|-------------+
  67 * |   Reserved  |    Status14 |
  68 * +-------------|-------------+
  69 */
  70
  71/* For each hardware DB there is an entry in this list and when the HW DB
  72 * entry is used, this SW DB entry is moved to the back of the list
  73 */
  74struct sparx5_db {
  75        struct list_head list;
  76        void *cpu_addr;
  77};
  78
  79static void sparx5_fdma_rx_add_dcb(struct sparx5_rx *rx,
  80                                   struct sparx5_rx_dcb_hw *dcb,
  81                                   u64 nextptr)
  82{
  83        int idx = 0;
  84
  85        /* Reset the status of the DB */
  86        for (idx = 0; idx < FDMA_RX_DCB_MAX_DBS; ++idx) {
  87                struct sparx5_db_hw *db = &dcb->db[idx];
  88
  89                db->status = FDMA_DCB_STATUS_INTR;
  90        }
  91        dcb->nextptr = FDMA_DCB_INVALID_DATA;
  92        dcb->info = FDMA_DCB_INFO_DATAL(FDMA_XTR_BUFFER_SIZE);
  93        rx->last_entry->nextptr = nextptr;
  94        rx->last_entry = dcb;
  95}
  96
  97static void sparx5_fdma_tx_add_dcb(struct sparx5_tx *tx,
  98                                   struct sparx5_tx_dcb_hw *dcb,
  99                                   u64 nextptr)
 100{
 101        int idx = 0;
 102
 103        /* Reset the status of the DB */
 104        for (idx = 0; idx < FDMA_TX_DCB_MAX_DBS; ++idx) {
 105                struct sparx5_db_hw *db = &dcb->db[idx];
 106
 107                db->status = FDMA_DCB_STATUS_DONE;
 108        }
 109        dcb->nextptr = FDMA_DCB_INVALID_DATA;
 110        dcb->info = FDMA_DCB_INFO_DATAL(FDMA_XTR_BUFFER_SIZE);
 111}
 112
 113static void sparx5_fdma_rx_activate(struct sparx5 *sparx5, struct sparx5_rx *rx)
 114{
 115        /* Write the buffer address in the LLP and LLP1 regs */
 116        spx5_wr(((u64)rx->dma) & GENMASK(31, 0), sparx5,
 117                FDMA_DCB_LLP(rx->channel_id));
 118        spx5_wr(((u64)rx->dma) >> 32, sparx5, FDMA_DCB_LLP1(rx->channel_id));
 119
 120        /* Set the number of RX DBs to be used, and DB end-of-frame interrupt */
 121        spx5_wr(FDMA_CH_CFG_CH_DCB_DB_CNT_SET(FDMA_RX_DCB_MAX_DBS) |
 122                FDMA_CH_CFG_CH_INTR_DB_EOF_ONLY_SET(1) |
 123                FDMA_CH_CFG_CH_INJ_PORT_SET(XTR_QUEUE),
 124                sparx5, FDMA_CH_CFG(rx->channel_id));
 125
 126        /* Set the RX Watermark to max */
 127        spx5_rmw(FDMA_XTR_CFG_XTR_FIFO_WM_SET(31), FDMA_XTR_CFG_XTR_FIFO_WM,
 128                 sparx5,
 129                 FDMA_XTR_CFG);
 130
 131        /* Start RX fdma */
 132        spx5_rmw(FDMA_PORT_CTRL_XTR_STOP_SET(0), FDMA_PORT_CTRL_XTR_STOP,
 133                 sparx5, FDMA_PORT_CTRL(0));
 134
 135        /* Enable RX channel DB interrupt */
 136        spx5_rmw(BIT(rx->channel_id),
 137                 BIT(rx->channel_id) & FDMA_INTR_DB_ENA_INTR_DB_ENA,
 138                 sparx5, FDMA_INTR_DB_ENA);
 139
 140        /* Activate the RX channel */
 141        spx5_wr(BIT(rx->channel_id), sparx5, FDMA_CH_ACTIVATE);
 142}
 143
 144static void sparx5_fdma_rx_deactivate(struct sparx5 *sparx5, struct sparx5_rx *rx)
 145{
 146        /* Dectivate the RX channel */
 147        spx5_rmw(0, BIT(rx->channel_id) & FDMA_CH_ACTIVATE_CH_ACTIVATE,
 148                 sparx5, FDMA_CH_ACTIVATE);
 149
 150        /* Disable RX channel DB interrupt */
 151        spx5_rmw(0, BIT(rx->channel_id) & FDMA_INTR_DB_ENA_INTR_DB_ENA,
 152                 sparx5, FDMA_INTR_DB_ENA);
 153
 154        /* Stop RX fdma */
 155        spx5_rmw(FDMA_PORT_CTRL_XTR_STOP_SET(1), FDMA_PORT_CTRL_XTR_STOP,
 156                 sparx5, FDMA_PORT_CTRL(0));
 157}
 158
 159static void sparx5_fdma_tx_activate(struct sparx5 *sparx5, struct sparx5_tx *tx)
 160{
 161        /* Write the buffer address in the LLP and LLP1 regs */
 162        spx5_wr(((u64)tx->dma) & GENMASK(31, 0), sparx5,
 163                FDMA_DCB_LLP(tx->channel_id));
 164        spx5_wr(((u64)tx->dma) >> 32, sparx5, FDMA_DCB_LLP1(tx->channel_id));
 165
 166        /* Set the number of TX DBs to be used, and DB end-of-frame interrupt */
 167        spx5_wr(FDMA_CH_CFG_CH_DCB_DB_CNT_SET(FDMA_TX_DCB_MAX_DBS) |
 168                FDMA_CH_CFG_CH_INTR_DB_EOF_ONLY_SET(1) |
 169                FDMA_CH_CFG_CH_INJ_PORT_SET(INJ_QUEUE),
 170                sparx5, FDMA_CH_CFG(tx->channel_id));
 171
 172        /* Start TX fdma */
 173        spx5_rmw(FDMA_PORT_CTRL_INJ_STOP_SET(0), FDMA_PORT_CTRL_INJ_STOP,
 174                 sparx5, FDMA_PORT_CTRL(0));
 175
 176        /* Activate the channel */
 177        spx5_wr(BIT(tx->channel_id), sparx5, FDMA_CH_ACTIVATE);
 178}
 179
 180static void sparx5_fdma_tx_deactivate(struct sparx5 *sparx5, struct sparx5_tx *tx)
 181{
 182        /* Disable the channel */
 183        spx5_rmw(0, BIT(tx->channel_id) & FDMA_CH_ACTIVATE_CH_ACTIVATE,
 184                 sparx5, FDMA_CH_ACTIVATE);
 185}
 186
 187static void sparx5_fdma_rx_reload(struct sparx5 *sparx5, struct sparx5_rx *rx)
 188{
 189        /* Reload the RX channel */
 190        spx5_wr(BIT(rx->channel_id), sparx5, FDMA_CH_RELOAD);
 191}
 192
 193static void sparx5_fdma_tx_reload(struct sparx5 *sparx5, struct sparx5_tx *tx)
 194{
 195        /* Reload the TX channel */
 196        spx5_wr(BIT(tx->channel_id), sparx5, FDMA_CH_RELOAD);
 197}
 198
 199static struct sk_buff *sparx5_fdma_rx_alloc_skb(struct sparx5_rx *rx)
 200{
 201        return __netdev_alloc_skb(rx->ndev, FDMA_XTR_BUFFER_SIZE,
 202                                  GFP_ATOMIC);
 203}
 204
 205static bool sparx5_fdma_rx_get_frame(struct sparx5 *sparx5, struct sparx5_rx *rx)
 206{
 207        struct sparx5_db_hw *db_hw;
 208        unsigned int packet_size;
 209        struct sparx5_port *port;
 210        struct sk_buff *new_skb;
 211        struct frame_info fi;
 212        struct sk_buff *skb;
 213        dma_addr_t dma_addr;
 214
 215        /* Check if the DCB is done */
 216        db_hw = &rx->dcb_entries[rx->dcb_index].db[rx->db_index];
 217        if (unlikely(!(db_hw->status & FDMA_DCB_STATUS_DONE)))
 218                return false;
 219        skb = rx->skb[rx->dcb_index][rx->db_index];
 220        /* Replace the DB entry with a new SKB */
 221        new_skb = sparx5_fdma_rx_alloc_skb(rx);
 222        if (unlikely(!new_skb))
 223                return false;
 224        /* Map the new skb data and set the new skb */
 225        dma_addr = virt_to_phys(new_skb->data);
 226        rx->skb[rx->dcb_index][rx->db_index] = new_skb;
 227        db_hw->dataptr = dma_addr;
 228        packet_size = FDMA_DCB_STATUS_BLOCKL(db_hw->status);
 229        skb_put(skb, packet_size);
 230        /* Now do the normal processing of the skb */
 231        sparx5_ifh_parse((u32 *)skb->data, &fi);
 232        /* Map to port netdev */
 233        port = fi.src_port < SPX5_PORTS ?  sparx5->ports[fi.src_port] : NULL;
 234        if (!port || !port->ndev) {
 235                dev_err(sparx5->dev, "Data on inactive port %d\n", fi.src_port);
 236                sparx5_xtr_flush(sparx5, XTR_QUEUE);
 237                return false;
 238        }
 239        skb->dev = port->ndev;
 240        skb_pull(skb, IFH_LEN * sizeof(u32));
 241        if (likely(!(skb->dev->features & NETIF_F_RXFCS)))
 242                skb_trim(skb, skb->len - ETH_FCS_LEN);
 243        skb->protocol = eth_type_trans(skb, skb->dev);
 244        /* Everything we see on an interface that is in the HW bridge
 245         * has already been forwarded
 246         */
 247        if (test_bit(port->portno, sparx5->bridge_mask))
 248                skb->offload_fwd_mark = 1;
 249        skb->dev->stats.rx_bytes += skb->len;
 250        skb->dev->stats.rx_packets++;
 251        rx->packets++;
 252        netif_receive_skb(skb);
 253        return true;
 254}
 255
 256static int sparx5_fdma_napi_callback(struct napi_struct *napi, int weight)
 257{
 258        struct sparx5_rx *rx = container_of(napi, struct sparx5_rx, napi);
 259        struct sparx5 *sparx5 = container_of(rx, struct sparx5, rx);
 260        int counter = 0;
 261
 262        while (counter < weight && sparx5_fdma_rx_get_frame(sparx5, rx)) {
 263                struct sparx5_rx_dcb_hw *old_dcb;
 264
 265                rx->db_index++;
 266                counter++;
 267                /* Check if the DCB can be reused */
 268                if (rx->db_index != FDMA_RX_DCB_MAX_DBS)
 269                        continue;
 270                /* As the DCB  can be reused, just advance the dcb_index
 271                 * pointer and set the nextptr in the DCB
 272                 */
 273                rx->db_index = 0;
 274                old_dcb = &rx->dcb_entries[rx->dcb_index];
 275                rx->dcb_index++;
 276                rx->dcb_index &= FDMA_DCB_MAX - 1;
 277                sparx5_fdma_rx_add_dcb(rx, old_dcb,
 278                                       rx->dma +
 279                                       ((unsigned long)old_dcb -
 280                                        (unsigned long)rx->dcb_entries));
 281        }
 282        if (counter < weight) {
 283                napi_complete_done(&rx->napi, counter);
 284                spx5_rmw(BIT(rx->channel_id),
 285                         BIT(rx->channel_id) & FDMA_INTR_DB_ENA_INTR_DB_ENA,
 286                         sparx5, FDMA_INTR_DB_ENA);
 287        }
 288        if (counter)
 289                sparx5_fdma_rx_reload(sparx5, rx);
 290        return counter;
 291}
 292
 293static struct sparx5_tx_dcb_hw *sparx5_fdma_next_dcb(struct sparx5_tx *tx,
 294                                                     struct sparx5_tx_dcb_hw *dcb)
 295{
 296        struct sparx5_tx_dcb_hw *next_dcb;
 297
 298        next_dcb = dcb;
 299        next_dcb++;
 300        /* Handle wrap-around */
 301        if ((unsigned long)next_dcb >=
 302            ((unsigned long)tx->first_entry + FDMA_DCB_MAX * sizeof(*dcb)))
 303                next_dcb = tx->first_entry;
 304        return next_dcb;
 305}
 306
 307int sparx5_fdma_xmit(struct sparx5 *sparx5, u32 *ifh, struct sk_buff *skb)
 308{
 309        struct sparx5_tx_dcb_hw *next_dcb_hw;
 310        struct sparx5_tx *tx = &sparx5->tx;
 311        static bool first_time = true;
 312        struct sparx5_db_hw *db_hw;
 313        struct sparx5_db *db;
 314
 315        next_dcb_hw = sparx5_fdma_next_dcb(tx, tx->curr_entry);
 316        db_hw = &next_dcb_hw->db[0];
 317        if (!(db_hw->status & FDMA_DCB_STATUS_DONE))
 318                tx->dropped++;
 319        db = list_first_entry(&tx->db_list, struct sparx5_db, list);
 320        list_move_tail(&db->list, &tx->db_list);
 321        next_dcb_hw->nextptr = FDMA_DCB_INVALID_DATA;
 322        tx->curr_entry->nextptr = tx->dma +
 323                ((unsigned long)next_dcb_hw -
 324                 (unsigned long)tx->first_entry);
 325        tx->curr_entry = next_dcb_hw;
 326        memset(db->cpu_addr, 0, FDMA_XTR_BUFFER_SIZE);
 327        memcpy(db->cpu_addr, ifh, IFH_LEN * 4);
 328        memcpy(db->cpu_addr + IFH_LEN * 4, skb->data, skb->len);
 329        db_hw->status = FDMA_DCB_STATUS_SOF |
 330                        FDMA_DCB_STATUS_EOF |
 331                        FDMA_DCB_STATUS_BLOCKO(0) |
 332                        FDMA_DCB_STATUS_BLOCKL(skb->len + IFH_LEN * 4 + 4);
 333        if (first_time) {
 334                sparx5_fdma_tx_activate(sparx5, tx);
 335                first_time = false;
 336        } else {
 337                sparx5_fdma_tx_reload(sparx5, tx);
 338        }
 339        return NETDEV_TX_OK;
 340}
 341
 342static int sparx5_fdma_rx_alloc(struct sparx5 *sparx5)
 343{
 344        struct sparx5_rx *rx = &sparx5->rx;
 345        struct sparx5_rx_dcb_hw *dcb;
 346        int idx, jdx;
 347        int size;
 348
 349        size = sizeof(struct sparx5_rx_dcb_hw) * FDMA_DCB_MAX;
 350        size = ALIGN(size, PAGE_SIZE);
 351        rx->dcb_entries = devm_kzalloc(sparx5->dev, size, GFP_KERNEL);
 352        if (!rx->dcb_entries)
 353                return -ENOMEM;
 354        rx->dma = virt_to_phys(rx->dcb_entries);
 355        rx->last_entry = rx->dcb_entries;
 356        rx->db_index = 0;
 357        rx->dcb_index = 0;
 358        /* Now for each dcb allocate the db */
 359        for (idx = 0; idx < FDMA_DCB_MAX; ++idx) {
 360                dcb = &rx->dcb_entries[idx];
 361                dcb->info = 0;
 362                /* For each db allocate an skb and map skb data pointer to the DB
 363                 * dataptr. In this way when the frame is received the skb->data
 364                 * will contain the frame, so no memcpy is needed
 365                 */
 366                for (jdx = 0; jdx < FDMA_RX_DCB_MAX_DBS; ++jdx) {
 367                        struct sparx5_db_hw *db_hw = &dcb->db[jdx];
 368                        dma_addr_t dma_addr;
 369                        struct sk_buff *skb;
 370
 371                        skb = sparx5_fdma_rx_alloc_skb(rx);
 372                        if (!skb)
 373                                return -ENOMEM;
 374
 375                        dma_addr = virt_to_phys(skb->data);
 376                        db_hw->dataptr = dma_addr;
 377                        db_hw->status = 0;
 378                        rx->skb[idx][jdx] = skb;
 379                }
 380                sparx5_fdma_rx_add_dcb(rx, dcb, rx->dma + sizeof(*dcb) * idx);
 381        }
 382        netif_napi_add(rx->ndev, &rx->napi, sparx5_fdma_napi_callback, FDMA_WEIGHT);
 383        napi_enable(&rx->napi);
 384        sparx5_fdma_rx_activate(sparx5, rx);
 385        return 0;
 386}
 387
 388static int sparx5_fdma_tx_alloc(struct sparx5 *sparx5)
 389{
 390        struct sparx5_tx *tx = &sparx5->tx;
 391        struct sparx5_tx_dcb_hw *dcb;
 392        int idx, jdx;
 393        int size;
 394
 395        size = sizeof(struct sparx5_tx_dcb_hw) * FDMA_DCB_MAX;
 396        size = ALIGN(size, PAGE_SIZE);
 397        tx->curr_entry = devm_kzalloc(sparx5->dev, size, GFP_KERNEL);
 398        if (!tx->curr_entry)
 399                return -ENOMEM;
 400        tx->dma = virt_to_phys(tx->curr_entry);
 401        tx->first_entry = tx->curr_entry;
 402        INIT_LIST_HEAD(&tx->db_list);
 403        /* Now for each dcb allocate the db */
 404        for (idx = 0; idx < FDMA_DCB_MAX; ++idx) {
 405                dcb = &tx->curr_entry[idx];
 406                dcb->info = 0;
 407                /* TX databuffers must be 16byte aligned */
 408                for (jdx = 0; jdx < FDMA_TX_DCB_MAX_DBS; ++jdx) {
 409                        struct sparx5_db_hw *db_hw = &dcb->db[jdx];
 410                        struct sparx5_db *db;
 411                        dma_addr_t phys;
 412                        void *cpu_addr;
 413
 414                        cpu_addr = devm_kzalloc(sparx5->dev,
 415                                                FDMA_XTR_BUFFER_SIZE,
 416                                                GFP_KERNEL);
 417                        if (!cpu_addr)
 418                                return -ENOMEM;
 419                        phys = virt_to_phys(cpu_addr);
 420                        db_hw->dataptr = phys;
 421                        db_hw->status = 0;
 422                        db = devm_kzalloc(sparx5->dev, sizeof(*db), GFP_KERNEL);
 423                        db->cpu_addr = cpu_addr;
 424                        list_add_tail(&db->list, &tx->db_list);
 425                }
 426                sparx5_fdma_tx_add_dcb(tx, dcb, tx->dma + sizeof(*dcb) * idx);
 427                /* Let the curr_entry to point to the last allocated entry */
 428                if (idx == FDMA_DCB_MAX - 1)
 429                        tx->curr_entry = dcb;
 430        }
 431        return 0;
 432}
 433
 434static void sparx5_fdma_rx_init(struct sparx5 *sparx5,
 435                                struct sparx5_rx *rx, int channel)
 436{
 437        int idx;
 438
 439        rx->channel_id = channel;
 440        /* Fetch a netdev for SKB and NAPI use, any will do */
 441        for (idx = 0; idx < SPX5_PORTS; ++idx) {
 442                struct sparx5_port *port = sparx5->ports[idx];
 443
 444                if (port && port->ndev) {
 445                        rx->ndev = port->ndev;
 446                        break;
 447                }
 448        }
 449}
 450
 451static void sparx5_fdma_tx_init(struct sparx5 *sparx5,
 452                                struct sparx5_tx *tx, int channel)
 453{
 454        tx->channel_id = channel;
 455}
 456
 457irqreturn_t sparx5_fdma_handler(int irq, void *args)
 458{
 459        struct sparx5 *sparx5 = args;
 460        u32 db = 0, err = 0;
 461
 462        db = spx5_rd(sparx5, FDMA_INTR_DB);
 463        err = spx5_rd(sparx5, FDMA_INTR_ERR);
 464        /* Clear interrupt */
 465        if (db) {
 466                spx5_wr(0, sparx5, FDMA_INTR_DB_ENA);
 467                spx5_wr(db, sparx5, FDMA_INTR_DB);
 468                napi_schedule(&sparx5->rx.napi);
 469        }
 470        if (err) {
 471                u32 err_type = spx5_rd(sparx5, FDMA_ERRORS);
 472
 473                dev_err_ratelimited(sparx5->dev,
 474                                    "ERR: int: %#x, type: %#x\n",
 475                                    err, err_type);
 476                spx5_wr(err, sparx5, FDMA_INTR_ERR);
 477                spx5_wr(err_type, sparx5, FDMA_ERRORS);
 478        }
 479        return IRQ_HANDLED;
 480}
 481
 482static void sparx5_fdma_injection_mode(struct sparx5 *sparx5)
 483{
 484        const int byte_swap = 1;
 485        int portno;
 486        int urgency;
 487
 488        /* Change mode to fdma extraction and injection */
 489        spx5_wr(QS_XTR_GRP_CFG_MODE_SET(2) |
 490                QS_XTR_GRP_CFG_STATUS_WORD_POS_SET(1) |
 491                QS_XTR_GRP_CFG_BYTE_SWAP_SET(byte_swap),
 492                sparx5, QS_XTR_GRP_CFG(XTR_QUEUE));
 493        spx5_wr(QS_INJ_GRP_CFG_MODE_SET(2) |
 494                QS_INJ_GRP_CFG_BYTE_SWAP_SET(byte_swap),
 495                sparx5, QS_INJ_GRP_CFG(INJ_QUEUE));
 496
 497        /* CPU ports capture setup */
 498        for (portno = SPX5_PORT_CPU_0; portno <= SPX5_PORT_CPU_1; portno++) {
 499                /* ASM CPU port: No preamble, IFH, enable padding */
 500                spx5_wr(ASM_PORT_CFG_PAD_ENA_SET(1) |
 501                        ASM_PORT_CFG_NO_PREAMBLE_ENA_SET(1) |
 502                        ASM_PORT_CFG_INJ_FORMAT_CFG_SET(1), /* 1 = IFH */
 503                        sparx5, ASM_PORT_CFG(portno));
 504
 505                /* Reset WM cnt to unclog queued frames */
 506                spx5_rmw(DSM_DEV_TX_STOP_WM_CFG_DEV_TX_CNT_CLR_SET(1),
 507                         DSM_DEV_TX_STOP_WM_CFG_DEV_TX_CNT_CLR,
 508                         sparx5,
 509                         DSM_DEV_TX_STOP_WM_CFG(portno));
 510
 511                /* Set Disassembler Stop Watermark level */
 512                spx5_rmw(DSM_DEV_TX_STOP_WM_CFG_DEV_TX_STOP_WM_SET(100),
 513                         DSM_DEV_TX_STOP_WM_CFG_DEV_TX_STOP_WM,
 514                         sparx5,
 515                         DSM_DEV_TX_STOP_WM_CFG(portno));
 516
 517                /* Enable port in queue system */
 518                urgency = sparx5_port_fwd_urg(sparx5, SPEED_2500);
 519                spx5_rmw(QFWD_SWITCH_PORT_MODE_PORT_ENA_SET(1) |
 520                         QFWD_SWITCH_PORT_MODE_FWD_URGENCY_SET(urgency),
 521                         QFWD_SWITCH_PORT_MODE_PORT_ENA |
 522                         QFWD_SWITCH_PORT_MODE_FWD_URGENCY,
 523                         sparx5,
 524                         QFWD_SWITCH_PORT_MODE(portno));
 525
 526                /* Disable Disassembler buffer underrun watchdog
 527                 * to avoid truncated packets in XTR
 528                 */
 529                spx5_rmw(DSM_BUF_CFG_UNDERFLOW_WATCHDOG_DIS_SET(1),
 530                         DSM_BUF_CFG_UNDERFLOW_WATCHDOG_DIS,
 531                         sparx5,
 532                         DSM_BUF_CFG(portno));
 533
 534                /* Disabling frame aging */
 535                spx5_rmw(HSCH_PORT_MODE_AGE_DIS_SET(1),
 536                         HSCH_PORT_MODE_AGE_DIS,
 537                         sparx5,
 538                         HSCH_PORT_MODE(portno));
 539        }
 540}
 541
 542int sparx5_fdma_start(struct sparx5 *sparx5)
 543{
 544        int err;
 545
 546        /* Reset FDMA state */
 547        spx5_wr(FDMA_CTRL_NRESET_SET(0), sparx5, FDMA_CTRL);
 548        spx5_wr(FDMA_CTRL_NRESET_SET(1), sparx5, FDMA_CTRL);
 549
 550        /* Force ACP caching but disable read/write allocation */
 551        spx5_rmw(CPU_PROC_CTRL_ACP_CACHE_FORCE_ENA_SET(1) |
 552                 CPU_PROC_CTRL_ACP_AWCACHE_SET(0) |
 553                 CPU_PROC_CTRL_ACP_ARCACHE_SET(0),
 554                 CPU_PROC_CTRL_ACP_CACHE_FORCE_ENA |
 555                 CPU_PROC_CTRL_ACP_AWCACHE |
 556                 CPU_PROC_CTRL_ACP_ARCACHE,
 557                 sparx5, CPU_PROC_CTRL);
 558
 559        sparx5_fdma_injection_mode(sparx5);
 560        sparx5_fdma_rx_init(sparx5, &sparx5->rx, FDMA_XTR_CHANNEL);
 561        sparx5_fdma_tx_init(sparx5, &sparx5->tx, FDMA_INJ_CHANNEL);
 562        err = sparx5_fdma_rx_alloc(sparx5);
 563        if (err) {
 564                dev_err(sparx5->dev, "Could not allocate RX buffers: %d\n", err);
 565                return err;
 566        }
 567        err = sparx5_fdma_tx_alloc(sparx5);
 568        if (err) {
 569                dev_err(sparx5->dev, "Could not allocate TX buffers: %d\n", err);
 570                return err;
 571        }
 572        return err;
 573}
 574
 575static u32 sparx5_fdma_port_ctrl(struct sparx5 *sparx5)
 576{
 577        return spx5_rd(sparx5, FDMA_PORT_CTRL(0));
 578}
 579
 580int sparx5_fdma_stop(struct sparx5 *sparx5)
 581{
 582        u32 val;
 583
 584        napi_disable(&sparx5->rx.napi);
 585        /* Stop the fdma and channel interrupts */
 586        sparx5_fdma_rx_deactivate(sparx5, &sparx5->rx);
 587        sparx5_fdma_tx_deactivate(sparx5, &sparx5->tx);
 588        /* Wait for the RX channel to stop */
 589        read_poll_timeout(sparx5_fdma_port_ctrl, val,
 590                          FDMA_PORT_CTRL_XTR_BUF_IS_EMPTY_GET(val) == 0,
 591                          500, 10000, 0, sparx5);
 592        return 0;
 593}
 594