linux/drivers/net/wireless/ath/ath11k/hal.c
<<
>>
Prefs
   1// SPDX-License-Identifier: BSD-3-Clause-Clear
   2/*
   3 * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
   4 */
   5#include <linux/dma-mapping.h>
   6#include "hal_tx.h"
   7#include "debug.h"
   8#include "hal_desc.h"
   9#include "hif.h"
  10
  11static const struct hal_srng_config hw_srng_config[] = {
  12        /* TODO: max_rings can populated by querying HW capabilities */
  13        { /* REO_DST */
  14                .start_ring_id = HAL_SRNG_RING_ID_REO2SW1,
  15                .max_rings = 4,
  16                .entry_size = sizeof(struct hal_reo_dest_ring) >> 2,
  17                .lmac_ring = false,
  18                .ring_dir = HAL_SRNG_DIR_DST,
  19                .reg_start = {
  20                        HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_RING_BASE_LSB,
  21                        HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_RING_HP,
  22                },
  23                .reg_size = {
  24                        HAL_REO2_RING_BASE_LSB - HAL_REO1_RING_BASE_LSB,
  25                        HAL_REO2_RING_HP - HAL_REO1_RING_HP,
  26                },
  27                .max_size = HAL_REO_REO2SW1_RING_BASE_MSB_RING_SIZE,
  28        },
  29        { /* REO_EXCEPTION */
  30                /* Designating REO2TCL ring as exception ring. This ring is
  31                 * similar to other REO2SW rings though it is named as REO2TCL.
  32                 * Any of theREO2SW rings can be used as exception ring.
  33                 */
  34                .start_ring_id = HAL_SRNG_RING_ID_REO2TCL,
  35                .max_rings = 1,
  36                .entry_size = sizeof(struct hal_reo_dest_ring) >> 2,
  37                .lmac_ring = false,
  38                .ring_dir = HAL_SRNG_DIR_DST,
  39                .reg_start = {
  40                        HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_TCL_RING_BASE_LSB,
  41                        HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_TCL_RING_HP,
  42                },
  43                .max_size = HAL_REO_REO2TCL_RING_BASE_MSB_RING_SIZE,
  44        },
  45        { /* REO_REINJECT */
  46                .start_ring_id = HAL_SRNG_RING_ID_SW2REO,
  47                .max_rings = 1,
  48                .entry_size = sizeof(struct hal_reo_entrance_ring) >> 2,
  49                .lmac_ring = false,
  50                .ring_dir = HAL_SRNG_DIR_SRC,
  51                .reg_start = {
  52                        HAL_SEQ_WCSS_UMAC_REO_REG + HAL_SW2REO_RING_BASE_LSB,
  53                        HAL_SEQ_WCSS_UMAC_REO_REG + HAL_SW2REO_RING_HP,
  54                },
  55                .max_size = HAL_REO_SW2REO_RING_BASE_MSB_RING_SIZE,
  56        },
  57        { /* REO_CMD */
  58                .start_ring_id = HAL_SRNG_RING_ID_REO_CMD,
  59                .max_rings = 1,
  60                .entry_size = (sizeof(struct hal_tlv_hdr) +
  61                        sizeof(struct hal_reo_get_queue_stats)) >> 2,
  62                .lmac_ring = false,
  63                .ring_dir = HAL_SRNG_DIR_SRC,
  64                .reg_start = {
  65                        HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_CMD_RING_BASE_LSB,
  66                        HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_CMD_HP,
  67                },
  68                .max_size = HAL_REO_CMD_RING_BASE_MSB_RING_SIZE,
  69        },
  70        { /* REO_STATUS */
  71                .start_ring_id = HAL_SRNG_RING_ID_REO_STATUS,
  72                .max_rings = 1,
  73                .entry_size = (sizeof(struct hal_tlv_hdr) +
  74                        sizeof(struct hal_reo_get_queue_stats_status)) >> 2,
  75                .lmac_ring = false,
  76                .ring_dir = HAL_SRNG_DIR_DST,
  77                .reg_start = {
  78                        HAL_SEQ_WCSS_UMAC_REO_REG +
  79                                HAL_REO_STATUS_RING_BASE_LSB,
  80                        HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_STATUS_HP,
  81                },
  82                .max_size = HAL_REO_STATUS_RING_BASE_MSB_RING_SIZE,
  83        },
  84        { /* TCL_DATA */
  85                .start_ring_id = HAL_SRNG_RING_ID_SW2TCL1,
  86                .max_rings = 3,
  87                .entry_size = (sizeof(struct hal_tlv_hdr) +
  88                             sizeof(struct hal_tcl_data_cmd)) >> 2,
  89                .lmac_ring = false,
  90                .ring_dir = HAL_SRNG_DIR_SRC,
  91                .reg_start = {
  92                        HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL1_RING_BASE_LSB,
  93                        HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL1_RING_HP,
  94                },
  95                .reg_size = {
  96                        HAL_TCL2_RING_BASE_LSB - HAL_TCL1_RING_BASE_LSB,
  97                        HAL_TCL2_RING_HP - HAL_TCL1_RING_HP,
  98                },
  99                .max_size = HAL_SW2TCL1_RING_BASE_MSB_RING_SIZE,
 100        },
 101        { /* TCL_CMD */
 102                .start_ring_id = HAL_SRNG_RING_ID_SW2TCL_CMD,
 103                .max_rings = 1,
 104                .entry_size = (sizeof(struct hal_tlv_hdr) +
 105                             sizeof(struct hal_tcl_gse_cmd)) >> 2,
 106                .lmac_ring =  false,
 107                .ring_dir = HAL_SRNG_DIR_SRC,
 108                .reg_start = {
 109                        HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL_RING_BASE_LSB,
 110                        HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL_RING_HP,
 111                },
 112                .max_size = HAL_SW2TCL1_CMD_RING_BASE_MSB_RING_SIZE,
 113        },
 114        { /* TCL_STATUS */
 115                .start_ring_id = HAL_SRNG_RING_ID_TCL_STATUS,
 116                .max_rings = 1,
 117                .entry_size = (sizeof(struct hal_tlv_hdr) +
 118                             sizeof(struct hal_tcl_status_ring)) >> 2,
 119                .lmac_ring = false,
 120                .ring_dir = HAL_SRNG_DIR_DST,
 121                .reg_start = {
 122                        HAL_SEQ_WCSS_UMAC_TCL_REG +
 123                                HAL_TCL_STATUS_RING_BASE_LSB,
 124                        HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL_STATUS_RING_HP,
 125                },
 126                .max_size = HAL_TCL_STATUS_RING_BASE_MSB_RING_SIZE,
 127        },
 128        { /* CE_SRC */
 129                .start_ring_id = HAL_SRNG_RING_ID_CE0_SRC,
 130                .max_rings = 12,
 131                .entry_size = sizeof(struct hal_ce_srng_src_desc) >> 2,
 132                .lmac_ring = false,
 133                .ring_dir = HAL_SRNG_DIR_SRC,
 134                .reg_start = {
 135                        (HAL_SEQ_WCSS_UMAC_CE0_SRC_REG +
 136                         HAL_CE_DST_RING_BASE_LSB),
 137                        HAL_SEQ_WCSS_UMAC_CE0_SRC_REG + HAL_CE_DST_RING_HP,
 138                },
 139                .reg_size = {
 140                        (HAL_SEQ_WCSS_UMAC_CE1_SRC_REG -
 141                         HAL_SEQ_WCSS_UMAC_CE0_SRC_REG),
 142                        (HAL_SEQ_WCSS_UMAC_CE1_SRC_REG -
 143                         HAL_SEQ_WCSS_UMAC_CE0_SRC_REG),
 144                },
 145                .max_size = HAL_CE_SRC_RING_BASE_MSB_RING_SIZE,
 146        },
 147        { /* CE_DST */
 148                .start_ring_id = HAL_SRNG_RING_ID_CE0_DST,
 149                .max_rings = 12,
 150                .entry_size = sizeof(struct hal_ce_srng_dest_desc) >> 2,
 151                .lmac_ring = false,
 152                .ring_dir = HAL_SRNG_DIR_SRC,
 153                .reg_start = {
 154                        (HAL_SEQ_WCSS_UMAC_CE0_DST_REG +
 155                         HAL_CE_DST_RING_BASE_LSB),
 156                        HAL_SEQ_WCSS_UMAC_CE0_DST_REG + HAL_CE_DST_RING_HP,
 157                },
 158                .reg_size = {
 159                        (HAL_SEQ_WCSS_UMAC_CE1_DST_REG -
 160                         HAL_SEQ_WCSS_UMAC_CE0_DST_REG),
 161                        (HAL_SEQ_WCSS_UMAC_CE1_DST_REG -
 162                         HAL_SEQ_WCSS_UMAC_CE0_DST_REG),
 163                },
 164                .max_size = HAL_CE_DST_RING_BASE_MSB_RING_SIZE,
 165        },
 166        { /* CE_DST_STATUS */
 167                .start_ring_id = HAL_SRNG_RING_ID_CE0_DST_STATUS,
 168                .max_rings = 12,
 169                .entry_size = sizeof(struct hal_ce_srng_dst_status_desc) >> 2,
 170                .lmac_ring = false,
 171                .ring_dir = HAL_SRNG_DIR_DST,
 172                .reg_start = {
 173                        (HAL_SEQ_WCSS_UMAC_CE0_DST_REG +
 174                         HAL_CE_DST_STATUS_RING_BASE_LSB),
 175                        (HAL_SEQ_WCSS_UMAC_CE0_DST_REG +
 176                         HAL_CE_DST_STATUS_RING_HP),
 177                },
 178                .reg_size = {
 179                        (HAL_SEQ_WCSS_UMAC_CE1_DST_REG -
 180                         HAL_SEQ_WCSS_UMAC_CE0_DST_REG),
 181                        (HAL_SEQ_WCSS_UMAC_CE1_DST_REG -
 182                         HAL_SEQ_WCSS_UMAC_CE0_DST_REG),
 183                },
 184                .max_size = HAL_CE_DST_STATUS_RING_BASE_MSB_RING_SIZE,
 185        },
 186        { /* WBM_IDLE_LINK */
 187                .start_ring_id = HAL_SRNG_RING_ID_WBM_IDLE_LINK,
 188                .max_rings = 1,
 189                .entry_size = sizeof(struct hal_wbm_link_desc) >> 2,
 190                .lmac_ring = false,
 191                .ring_dir = HAL_SRNG_DIR_SRC,
 192                .reg_start = {
 193                        (HAL_SEQ_WCSS_UMAC_WBM_REG +
 194                         HAL_WBM_IDLE_LINK_RING_BASE_LSB),
 195                        (HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_IDLE_LINK_RING_HP),
 196                },
 197                .max_size = HAL_WBM_IDLE_LINK_RING_BASE_MSB_RING_SIZE,
 198        },
 199        { /* SW2WBM_RELEASE */
 200                .start_ring_id = HAL_SRNG_RING_ID_WBM_SW_RELEASE,
 201                .max_rings = 1,
 202                .entry_size = sizeof(struct hal_wbm_release_ring) >> 2,
 203                .lmac_ring = false,
 204                .ring_dir = HAL_SRNG_DIR_SRC,
 205                .reg_start = {
 206                        (HAL_SEQ_WCSS_UMAC_WBM_REG +
 207                         HAL_WBM_RELEASE_RING_BASE_LSB),
 208                        (HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_RELEASE_RING_HP),
 209                },
 210                .max_size = HAL_SW2WBM_RELEASE_RING_BASE_MSB_RING_SIZE,
 211        },
 212        { /* WBM2SW_RELEASE */
 213                .start_ring_id = HAL_SRNG_RING_ID_WBM2SW0_RELEASE,
 214                .max_rings = 4,
 215                .entry_size = sizeof(struct hal_wbm_release_ring) >> 2,
 216                .lmac_ring = false,
 217                .ring_dir = HAL_SRNG_DIR_DST,
 218                .reg_start = {
 219                        (HAL_SEQ_WCSS_UMAC_WBM_REG +
 220                         HAL_WBM0_RELEASE_RING_BASE_LSB),
 221                        (HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM0_RELEASE_RING_HP),
 222                },
 223                .reg_size = {
 224                        (HAL_WBM1_RELEASE_RING_BASE_LSB -
 225                         HAL_WBM0_RELEASE_RING_BASE_LSB),
 226                        (HAL_WBM1_RELEASE_RING_HP - HAL_WBM0_RELEASE_RING_HP),
 227                },
 228                .max_size = HAL_WBM2SW_RELEASE_RING_BASE_MSB_RING_SIZE,
 229        },
 230        { /* RXDMA_BUF */
 231                .start_ring_id = HAL_SRNG_RING_ID_WMAC1_SW2RXDMA0_BUF,
 232                .max_rings = 2,
 233                .entry_size = sizeof(struct hal_wbm_buffer_ring) >> 2,
 234                .lmac_ring = true,
 235                .ring_dir = HAL_SRNG_DIR_SRC,
 236                .max_size = HAL_RXDMA_RING_MAX_SIZE,
 237        },
 238        { /* RXDMA_DST */
 239                .start_ring_id = HAL_SRNG_RING_ID_WMAC1_RXDMA2SW0,
 240                .max_rings = 1,
 241                .entry_size = sizeof(struct hal_reo_entrance_ring) >> 2,
 242                .lmac_ring = true,
 243                .ring_dir = HAL_SRNG_DIR_DST,
 244                .max_size = HAL_RXDMA_RING_MAX_SIZE,
 245        },
 246        { /* RXDMA_MONITOR_BUF */
 247                .start_ring_id = HAL_SRNG_RING_ID_WMAC1_SW2RXDMA2_BUF,
 248                .max_rings = 1,
 249                .entry_size = sizeof(struct hal_wbm_buffer_ring) >> 2,
 250                .lmac_ring = true,
 251                .ring_dir = HAL_SRNG_DIR_SRC,
 252                .max_size = HAL_RXDMA_RING_MAX_SIZE,
 253        },
 254        { /* RXDMA_MONITOR_STATUS */
 255                .start_ring_id = HAL_SRNG_RING_ID_WMAC1_SW2RXDMA1_STATBUF,
 256                .max_rings = 1,
 257                .entry_size = sizeof(struct hal_wbm_buffer_ring) >> 2,
 258                .lmac_ring = true,
 259                .ring_dir = HAL_SRNG_DIR_SRC,
 260                .max_size = HAL_RXDMA_RING_MAX_SIZE,
 261        },
 262        { /* RXDMA_MONITOR_DST */
 263                .start_ring_id = HAL_SRNG_RING_ID_WMAC1_RXDMA2SW1,
 264                .max_rings = 1,
 265                .entry_size = sizeof(struct hal_reo_entrance_ring) >> 2,
 266                .lmac_ring = true,
 267                .ring_dir = HAL_SRNG_DIR_DST,
 268                .max_size = HAL_RXDMA_RING_MAX_SIZE,
 269        },
 270        { /* RXDMA_MONITOR_DESC */
 271                .start_ring_id = HAL_SRNG_RING_ID_WMAC1_SW2RXDMA1_DESC,
 272                .max_rings = 1,
 273                .entry_size = sizeof(struct hal_wbm_buffer_ring) >> 2,
 274                .lmac_ring = true,
 275                .ring_dir = HAL_SRNG_DIR_SRC,
 276                .max_size = HAL_RXDMA_RING_MAX_SIZE,
 277        },
 278        { /* RXDMA DIR BUF */
 279                .start_ring_id = HAL_SRNG_RING_ID_RXDMA_DIR_BUF,
 280                .max_rings = 1,
 281                .entry_size = 8 >> 2, /* TODO: Define the struct */
 282                .lmac_ring = true,
 283                .ring_dir = HAL_SRNG_DIR_SRC,
 284                .max_size = HAL_RXDMA_RING_MAX_SIZE,
 285        },
 286};
 287
 288static int ath11k_hal_alloc_cont_rdp(struct ath11k_base *ab)
 289{
 290        struct ath11k_hal *hal = &ab->hal;
 291        size_t size;
 292
 293        size = sizeof(u32) * HAL_SRNG_RING_ID_MAX;
 294        hal->rdp.vaddr = dma_alloc_coherent(ab->dev, size, &hal->rdp.paddr,
 295                                            GFP_KERNEL);
 296        if (!hal->rdp.vaddr)
 297                return -ENOMEM;
 298
 299        return 0;
 300}
 301
 302static void ath11k_hal_free_cont_rdp(struct ath11k_base *ab)
 303{
 304        struct ath11k_hal *hal = &ab->hal;
 305        size_t size;
 306
 307        if (!hal->rdp.vaddr)
 308                return;
 309
 310        size = sizeof(u32) * HAL_SRNG_RING_ID_MAX;
 311        dma_free_coherent(ab->dev, size,
 312                          hal->rdp.vaddr, hal->rdp.paddr);
 313        hal->rdp.vaddr = NULL;
 314}
 315
 316static int ath11k_hal_alloc_cont_wrp(struct ath11k_base *ab)
 317{
 318        struct ath11k_hal *hal = &ab->hal;
 319        size_t size;
 320
 321        size = sizeof(u32) * HAL_SRNG_NUM_LMAC_RINGS;
 322        hal->wrp.vaddr = dma_alloc_coherent(ab->dev, size, &hal->wrp.paddr,
 323                                            GFP_KERNEL);
 324        if (!hal->wrp.vaddr)
 325                return -ENOMEM;
 326
 327        return 0;
 328}
 329
 330static void ath11k_hal_free_cont_wrp(struct ath11k_base *ab)
 331{
 332        struct ath11k_hal *hal = &ab->hal;
 333        size_t size;
 334
 335        if (!hal->wrp.vaddr)
 336                return;
 337
 338        size = sizeof(u32) * HAL_SRNG_NUM_LMAC_RINGS;
 339        dma_free_coherent(ab->dev, size,
 340                          hal->wrp.vaddr, hal->wrp.paddr);
 341        hal->wrp.vaddr = NULL;
 342}
 343
 344static void ath11k_hal_ce_dst_setup(struct ath11k_base *ab,
 345                                    struct hal_srng *srng, int ring_num)
 346{
 347        const struct hal_srng_config *srng_config = &hw_srng_config[HAL_CE_DST];
 348        u32 addr;
 349        u32 val;
 350
 351        addr = HAL_CE_DST_RING_CTRL +
 352               srng_config->reg_start[HAL_SRNG_REG_GRP_R0] +
 353               ring_num * srng_config->reg_size[HAL_SRNG_REG_GRP_R0];
 354
 355        val = ath11k_hif_read32(ab, addr);
 356        val &= ~HAL_CE_DST_R0_DEST_CTRL_MAX_LEN;
 357        val |= FIELD_PREP(HAL_CE_DST_R0_DEST_CTRL_MAX_LEN,
 358                          srng->u.dst_ring.max_buffer_length);
 359        ath11k_hif_write32(ab, addr, val);
 360}
 361
 362static void ath11k_hal_srng_dst_hw_init(struct ath11k_base *ab,
 363                                        struct hal_srng *srng)
 364{
 365        struct ath11k_hal *hal = &ab->hal;
 366        u32 val;
 367        u64 hp_addr;
 368        u32 reg_base;
 369
 370        reg_base = srng->hwreg_base[HAL_SRNG_REG_GRP_R0];
 371
 372        if (srng->flags & HAL_SRNG_FLAGS_MSI_INTR) {
 373                ath11k_hif_write32(ab, reg_base +
 374                                   HAL_REO1_RING_MSI1_BASE_LSB_OFFSET,
 375                                   (u32)srng->msi_addr);
 376
 377                val = FIELD_PREP(HAL_REO1_RING_MSI1_BASE_MSB_ADDR,
 378                                 ((u64)srng->msi_addr >>
 379                                  HAL_ADDR_MSB_REG_SHIFT)) |
 380                      HAL_REO1_RING_MSI1_BASE_MSB_MSI1_ENABLE;
 381                ath11k_hif_write32(ab, reg_base +
 382                                       HAL_REO1_RING_MSI1_BASE_MSB_OFFSET, val);
 383
 384                ath11k_hif_write32(ab,
 385                                   reg_base + HAL_REO1_RING_MSI1_DATA_OFFSET,
 386                                   srng->msi_data);
 387        }
 388
 389        ath11k_hif_write32(ab, reg_base, (u32)srng->ring_base_paddr);
 390
 391        val = FIELD_PREP(HAL_REO1_RING_BASE_MSB_RING_BASE_ADDR_MSB,
 392                         ((u64)srng->ring_base_paddr >>
 393                          HAL_ADDR_MSB_REG_SHIFT)) |
 394              FIELD_PREP(HAL_REO1_RING_BASE_MSB_RING_SIZE,
 395                         (srng->entry_size * srng->num_entries));
 396        ath11k_hif_write32(ab, reg_base + HAL_REO1_RING_BASE_MSB_OFFSET, val);
 397
 398        val = FIELD_PREP(HAL_REO1_RING_ID_RING_ID, srng->ring_id) |
 399              FIELD_PREP(HAL_REO1_RING_ID_ENTRY_SIZE, srng->entry_size);
 400        ath11k_hif_write32(ab, reg_base + HAL_REO1_RING_ID_OFFSET, val);
 401
 402        /* interrupt setup */
 403        val = FIELD_PREP(HAL_REO1_RING_PRDR_INT_SETUP_INTR_TMR_THOLD,
 404                         (srng->intr_timer_thres_us >> 3));
 405
 406        val |= FIELD_PREP(HAL_REO1_RING_PRDR_INT_SETUP_BATCH_COUNTER_THOLD,
 407                          (srng->intr_batch_cntr_thres_entries *
 408                           srng->entry_size));
 409
 410        ath11k_hif_write32(ab,
 411                           reg_base + HAL_REO1_RING_PRODUCER_INT_SETUP_OFFSET,
 412                           val);
 413
 414        hp_addr = hal->rdp.paddr +
 415                  ((unsigned long)srng->u.dst_ring.hp_addr -
 416                   (unsigned long)hal->rdp.vaddr);
 417        ath11k_hif_write32(ab, reg_base + HAL_REO1_RING_HP_ADDR_LSB_OFFSET,
 418                           hp_addr & HAL_ADDR_LSB_REG_MASK);
 419        ath11k_hif_write32(ab, reg_base + HAL_REO1_RING_HP_ADDR_MSB_OFFSET,
 420                           hp_addr >> HAL_ADDR_MSB_REG_SHIFT);
 421
 422        /* Initialize head and tail pointers to indicate ring is empty */
 423        reg_base = srng->hwreg_base[HAL_SRNG_REG_GRP_R2];
 424        ath11k_hif_write32(ab, reg_base, 0);
 425        ath11k_hif_write32(ab, reg_base + HAL_REO1_RING_TP_OFFSET, 0);
 426        *srng->u.dst_ring.hp_addr = 0;
 427
 428        reg_base = srng->hwreg_base[HAL_SRNG_REG_GRP_R0];
 429        val = 0;
 430        if (srng->flags & HAL_SRNG_FLAGS_DATA_TLV_SWAP)
 431                val |= HAL_REO1_RING_MISC_DATA_TLV_SWAP;
 432        if (srng->flags & HAL_SRNG_FLAGS_RING_PTR_SWAP)
 433                val |= HAL_REO1_RING_MISC_HOST_FW_SWAP;
 434        if (srng->flags & HAL_SRNG_FLAGS_MSI_SWAP)
 435                val |= HAL_REO1_RING_MISC_MSI_SWAP;
 436        val |= HAL_REO1_RING_MISC_SRNG_ENABLE;
 437
 438        ath11k_hif_write32(ab, reg_base + HAL_REO1_RING_MISC_OFFSET, val);
 439}
 440
 441static void ath11k_hal_srng_src_hw_init(struct ath11k_base *ab,
 442                                        struct hal_srng *srng)
 443{
 444        struct ath11k_hal *hal = &ab->hal;
 445        u32 val;
 446        u64 tp_addr;
 447        u32 reg_base;
 448
 449        reg_base = srng->hwreg_base[HAL_SRNG_REG_GRP_R0];
 450
 451        if (srng->flags & HAL_SRNG_FLAGS_MSI_INTR) {
 452                ath11k_hif_write32(ab, reg_base +
 453                                    HAL_TCL1_RING_MSI1_BASE_LSB_OFFSET,
 454                                   (u32)srng->msi_addr);
 455
 456                val = FIELD_PREP(HAL_TCL1_RING_MSI1_BASE_MSB_ADDR,
 457                                 ((u64)srng->msi_addr >>
 458                                  HAL_ADDR_MSB_REG_SHIFT)) |
 459                      HAL_TCL1_RING_MSI1_BASE_MSB_MSI1_ENABLE;
 460                ath11k_hif_write32(ab, reg_base +
 461                                       HAL_TCL1_RING_MSI1_BASE_MSB_OFFSET,
 462                                   val);
 463
 464                ath11k_hif_write32(ab, reg_base +
 465                                       HAL_TCL1_RING_MSI1_DATA_OFFSET,
 466                                   srng->msi_data);
 467        }
 468
 469        ath11k_hif_write32(ab, reg_base, (u32)srng->ring_base_paddr);
 470
 471        val = FIELD_PREP(HAL_TCL1_RING_BASE_MSB_RING_BASE_ADDR_MSB,
 472                         ((u64)srng->ring_base_paddr >>
 473                          HAL_ADDR_MSB_REG_SHIFT)) |
 474              FIELD_PREP(HAL_TCL1_RING_BASE_MSB_RING_SIZE,
 475                         (srng->entry_size * srng->num_entries));
 476        ath11k_hif_write32(ab, reg_base + HAL_TCL1_RING_BASE_MSB_OFFSET, val);
 477
 478        val = FIELD_PREP(HAL_REO1_RING_ID_ENTRY_SIZE, srng->entry_size);
 479        ath11k_hif_write32(ab, reg_base + HAL_TCL1_RING_ID_OFFSET, val);
 480
 481        /* interrupt setup */
 482        /* NOTE: IPQ8074 v2 requires the interrupt timer threshold in the
 483         * unit of 8 usecs instead of 1 usec (as required by v1).
 484         */
 485        val = FIELD_PREP(HAL_TCL1_RING_CONSR_INT_SETUP_IX0_INTR_TMR_THOLD,
 486                         srng->intr_timer_thres_us);
 487
 488        val |= FIELD_PREP(HAL_TCL1_RING_CONSR_INT_SETUP_IX0_BATCH_COUNTER_THOLD,
 489                          (srng->intr_batch_cntr_thres_entries *
 490                           srng->entry_size));
 491
 492        ath11k_hif_write32(ab,
 493                           reg_base + HAL_TCL1_RING_CONSR_INT_SETUP_IX0_OFFSET,
 494                           val);
 495
 496        val = 0;
 497        if (srng->flags & HAL_SRNG_FLAGS_LOW_THRESH_INTR_EN) {
 498                val |= FIELD_PREP(HAL_TCL1_RING_CONSR_INT_SETUP_IX1_LOW_THOLD,
 499                                  srng->u.src_ring.low_threshold);
 500        }
 501        ath11k_hif_write32(ab,
 502                           reg_base + HAL_TCL1_RING_CONSR_INT_SETUP_IX1_OFFSET,
 503                           val);
 504
 505        if (srng->ring_id != HAL_SRNG_RING_ID_WBM_IDLE_LINK) {
 506                tp_addr = hal->rdp.paddr +
 507                          ((unsigned long)srng->u.src_ring.tp_addr -
 508                           (unsigned long)hal->rdp.vaddr);
 509                ath11k_hif_write32(ab,
 510                                   reg_base + HAL_TCL1_RING_TP_ADDR_LSB_OFFSET,
 511                                   tp_addr & HAL_ADDR_LSB_REG_MASK);
 512                ath11k_hif_write32(ab,
 513                                   reg_base + HAL_TCL1_RING_TP_ADDR_MSB_OFFSET,
 514                                   tp_addr >> HAL_ADDR_MSB_REG_SHIFT);
 515        }
 516
 517        /* Initialize head and tail pointers to indicate ring is empty */
 518        reg_base = srng->hwreg_base[HAL_SRNG_REG_GRP_R2];
 519        ath11k_hif_write32(ab, reg_base, 0);
 520        ath11k_hif_write32(ab, reg_base + HAL_TCL1_RING_TP_OFFSET, 0);
 521        *srng->u.src_ring.tp_addr = 0;
 522
 523        reg_base = srng->hwreg_base[HAL_SRNG_REG_GRP_R0];
 524        val = 0;
 525        if (srng->flags & HAL_SRNG_FLAGS_DATA_TLV_SWAP)
 526                val |= HAL_TCL1_RING_MISC_DATA_TLV_SWAP;
 527        if (srng->flags & HAL_SRNG_FLAGS_RING_PTR_SWAP)
 528                val |= HAL_TCL1_RING_MISC_HOST_FW_SWAP;
 529        if (srng->flags & HAL_SRNG_FLAGS_MSI_SWAP)
 530                val |= HAL_TCL1_RING_MISC_MSI_SWAP;
 531
 532        /* Loop count is not used for SRC rings */
 533        val |= HAL_TCL1_RING_MISC_MSI_LOOPCNT_DISABLE;
 534
 535        val |= HAL_TCL1_RING_MISC_SRNG_ENABLE;
 536
 537        ath11k_hif_write32(ab, reg_base + HAL_TCL1_RING_MISC_OFFSET, val);
 538}
 539
 540static void ath11k_hal_srng_hw_init(struct ath11k_base *ab,
 541                                    struct hal_srng *srng)
 542{
 543        if (srng->ring_dir == HAL_SRNG_DIR_SRC)
 544                ath11k_hal_srng_src_hw_init(ab, srng);
 545        else
 546                ath11k_hal_srng_dst_hw_init(ab, srng);
 547}
 548
 549static int ath11k_hal_srng_get_ring_id(struct ath11k_base *ab,
 550                                       enum hal_ring_type type,
 551                                       int ring_num, int mac_id)
 552{
 553        const struct hal_srng_config *srng_config = &hw_srng_config[type];
 554        int ring_id;
 555
 556        if (ring_num >= srng_config->max_rings) {
 557                ath11k_warn(ab, "invalid ring number :%d\n", ring_num);
 558                return -EINVAL;
 559        }
 560
 561        ring_id = srng_config->start_ring_id + ring_num;
 562        if (srng_config->lmac_ring)
 563                ring_id += mac_id * HAL_SRNG_RINGS_PER_LMAC;
 564
 565        if (WARN_ON(ring_id >= HAL_SRNG_RING_ID_MAX))
 566                return -EINVAL;
 567
 568        return ring_id;
 569}
 570
 571int ath11k_hal_srng_get_entrysize(u32 ring_type)
 572{
 573        const struct hal_srng_config *srng_config;
 574
 575        if (WARN_ON(ring_type >= HAL_MAX_RING_TYPES))
 576                return -EINVAL;
 577
 578        srng_config = &hw_srng_config[ring_type];
 579
 580        return (srng_config->entry_size << 2);
 581}
 582
 583int ath11k_hal_srng_get_max_entries(u32 ring_type)
 584{
 585        const struct hal_srng_config *srng_config;
 586
 587        if (WARN_ON(ring_type >= HAL_MAX_RING_TYPES))
 588                return -EINVAL;
 589
 590        srng_config = &hw_srng_config[ring_type];
 591
 592        return (srng_config->max_size / srng_config->entry_size);
 593}
 594
 595void ath11k_hal_srng_get_params(struct ath11k_base *ab, struct hal_srng *srng,
 596                                struct hal_srng_params *params)
 597{
 598        params->ring_base_paddr = srng->ring_base_paddr;
 599        params->ring_base_vaddr = srng->ring_base_vaddr;
 600        params->num_entries = srng->num_entries;
 601        params->intr_timer_thres_us = srng->intr_timer_thres_us;
 602        params->intr_batch_cntr_thres_entries =
 603                srng->intr_batch_cntr_thres_entries;
 604        params->low_threshold = srng->u.src_ring.low_threshold;
 605        params->flags = srng->flags;
 606}
 607
 608dma_addr_t ath11k_hal_srng_get_hp_addr(struct ath11k_base *ab,
 609                                       struct hal_srng *srng)
 610{
 611        if (!(srng->flags & HAL_SRNG_FLAGS_LMAC_RING))
 612                return 0;
 613
 614        if (srng->ring_dir == HAL_SRNG_DIR_SRC)
 615                return ab->hal.wrp.paddr +
 616                       ((unsigned long)srng->u.src_ring.hp_addr -
 617                        (unsigned long)ab->hal.wrp.vaddr);
 618        else
 619                return ab->hal.rdp.paddr +
 620                       ((unsigned long)srng->u.dst_ring.hp_addr -
 621                         (unsigned long)ab->hal.rdp.vaddr);
 622}
 623
 624dma_addr_t ath11k_hal_srng_get_tp_addr(struct ath11k_base *ab,
 625                                       struct hal_srng *srng)
 626{
 627        if (!(srng->flags & HAL_SRNG_FLAGS_LMAC_RING))
 628                return 0;
 629
 630        if (srng->ring_dir == HAL_SRNG_DIR_SRC)
 631                return ab->hal.rdp.paddr +
 632                       ((unsigned long)srng->u.src_ring.tp_addr -
 633                        (unsigned long)ab->hal.rdp.vaddr);
 634        else
 635                return ab->hal.wrp.paddr +
 636                       ((unsigned long)srng->u.dst_ring.tp_addr -
 637                        (unsigned long)ab->hal.wrp.vaddr);
 638}
 639
 640u32 ath11k_hal_ce_get_desc_size(enum hal_ce_desc type)
 641{
 642        switch (type) {
 643        case HAL_CE_DESC_SRC:
 644                return sizeof(struct hal_ce_srng_src_desc);
 645        case HAL_CE_DESC_DST:
 646                return sizeof(struct hal_ce_srng_dest_desc);
 647        case HAL_CE_DESC_DST_STATUS:
 648                return sizeof(struct hal_ce_srng_dst_status_desc);
 649        }
 650
 651        return 0;
 652}
 653
 654void ath11k_hal_ce_src_set_desc(void *buf, dma_addr_t paddr, u32 len, u32 id,
 655                                u8 byte_swap_data)
 656{
 657        struct hal_ce_srng_src_desc *desc = (struct hal_ce_srng_src_desc *)buf;
 658
 659        desc->buffer_addr_low = paddr & HAL_ADDR_LSB_REG_MASK;
 660        desc->buffer_addr_info =
 661                FIELD_PREP(HAL_CE_SRC_DESC_ADDR_INFO_ADDR_HI,
 662                           ((u64)paddr >> HAL_ADDR_MSB_REG_SHIFT)) |
 663                FIELD_PREP(HAL_CE_SRC_DESC_ADDR_INFO_BYTE_SWAP,
 664                           byte_swap_data) |
 665                FIELD_PREP(HAL_CE_SRC_DESC_ADDR_INFO_GATHER, 0) |
 666                FIELD_PREP(HAL_CE_SRC_DESC_ADDR_INFO_LEN, len);
 667        desc->meta_info = FIELD_PREP(HAL_CE_SRC_DESC_META_INFO_DATA, id);
 668}
 669
 670void ath11k_hal_ce_dst_set_desc(void *buf, dma_addr_t paddr)
 671{
 672        struct hal_ce_srng_dest_desc *desc =
 673                (struct hal_ce_srng_dest_desc *)buf;
 674
 675        desc->buffer_addr_low = paddr & HAL_ADDR_LSB_REG_MASK;
 676        desc->buffer_addr_info =
 677                FIELD_PREP(HAL_CE_DEST_DESC_ADDR_INFO_ADDR_HI,
 678                           ((u64)paddr >> HAL_ADDR_MSB_REG_SHIFT));
 679}
 680
 681u32 ath11k_hal_ce_dst_status_get_length(void *buf)
 682{
 683        struct hal_ce_srng_dst_status_desc *desc =
 684                (struct hal_ce_srng_dst_status_desc *)buf;
 685        u32 len;
 686
 687        len = FIELD_GET(HAL_CE_DST_STATUS_DESC_FLAGS_LEN, desc->flags);
 688        desc->flags &= ~HAL_CE_DST_STATUS_DESC_FLAGS_LEN;
 689
 690        return len;
 691}
 692
 693void ath11k_hal_set_link_desc_addr(struct hal_wbm_link_desc *desc, u32 cookie,
 694                                   dma_addr_t paddr)
 695{
 696        desc->buf_addr_info.info0 = FIELD_PREP(BUFFER_ADDR_INFO0_ADDR,
 697                                               (paddr & HAL_ADDR_LSB_REG_MASK));
 698        desc->buf_addr_info.info1 = FIELD_PREP(BUFFER_ADDR_INFO1_ADDR,
 699                                               ((u64)paddr >> HAL_ADDR_MSB_REG_SHIFT)) |
 700                                    FIELD_PREP(BUFFER_ADDR_INFO1_RET_BUF_MGR, 1) |
 701                                    FIELD_PREP(BUFFER_ADDR_INFO1_SW_COOKIE, cookie);
 702}
 703
 704u32 *ath11k_hal_srng_dst_peek(struct ath11k_base *ab, struct hal_srng *srng)
 705{
 706        lockdep_assert_held(&srng->lock);
 707
 708        if (srng->u.dst_ring.tp != srng->u.dst_ring.cached_hp)
 709                return (srng->ring_base_vaddr + srng->u.dst_ring.tp);
 710
 711        return NULL;
 712}
 713
 714u32 *ath11k_hal_srng_dst_get_next_entry(struct ath11k_base *ab,
 715                                        struct hal_srng *srng)
 716{
 717        u32 *desc;
 718
 719        lockdep_assert_held(&srng->lock);
 720
 721        if (srng->u.dst_ring.tp == srng->u.dst_ring.cached_hp)
 722                return NULL;
 723
 724        desc = srng->ring_base_vaddr + srng->u.dst_ring.tp;
 725
 726        srng->u.dst_ring.tp = (srng->u.dst_ring.tp + srng->entry_size) %
 727                              srng->ring_size;
 728
 729        return desc;
 730}
 731
 732int ath11k_hal_srng_dst_num_free(struct ath11k_base *ab, struct hal_srng *srng,
 733                                 bool sync_hw_ptr)
 734{
 735        u32 tp, hp;
 736
 737        lockdep_assert_held(&srng->lock);
 738
 739        tp = srng->u.dst_ring.tp;
 740
 741        if (sync_hw_ptr) {
 742                hp = *srng->u.dst_ring.hp_addr;
 743                srng->u.dst_ring.cached_hp = hp;
 744        } else {
 745                hp = srng->u.dst_ring.cached_hp;
 746        }
 747
 748        if (hp >= tp)
 749                return (hp - tp) / srng->entry_size;
 750        else
 751                return (srng->ring_size - tp + hp) / srng->entry_size;
 752}
 753
 754/* Returns number of available entries in src ring */
 755int ath11k_hal_srng_src_num_free(struct ath11k_base *ab, struct hal_srng *srng,
 756                                 bool sync_hw_ptr)
 757{
 758        u32 tp, hp;
 759
 760        lockdep_assert_held(&srng->lock);
 761
 762        hp = srng->u.src_ring.hp;
 763
 764        if (sync_hw_ptr) {
 765                tp = *srng->u.src_ring.tp_addr;
 766                srng->u.src_ring.cached_tp = tp;
 767        } else {
 768                tp = srng->u.src_ring.cached_tp;
 769        }
 770
 771        if (tp > hp)
 772                return ((tp - hp) / srng->entry_size) - 1;
 773        else
 774                return ((srng->ring_size - hp + tp) / srng->entry_size) - 1;
 775}
 776
 777u32 *ath11k_hal_srng_src_get_next_entry(struct ath11k_base *ab,
 778                                        struct hal_srng *srng)
 779{
 780        u32 *desc;
 781        u32 next_hp;
 782
 783        lockdep_assert_held(&srng->lock);
 784
 785        /* TODO: Using % is expensive, but we have to do this since size of some
 786         * SRNG rings is not power of 2 (due to descriptor sizes). Need to see
 787         * if separate function is defined for rings having power of 2 ring size
 788         * (TCL2SW, REO2SW, SW2RXDMA and CE rings) so that we can avoid the
 789         * overhead of % by using mask (with &).
 790         */
 791        next_hp = (srng->u.src_ring.hp + srng->entry_size) % srng->ring_size;
 792
 793        if (next_hp == srng->u.src_ring.cached_tp)
 794                return NULL;
 795
 796        desc = srng->ring_base_vaddr + srng->u.src_ring.hp;
 797        srng->u.src_ring.hp = next_hp;
 798
 799        /* TODO: Reap functionality is not used by all rings. If particular
 800         * ring does not use reap functionality, we need not update reap_hp
 801         * with next_hp pointer. Need to make sure a separate function is used
 802         * before doing any optimization by removing below code updating
 803         * reap_hp.
 804         */
 805        srng->u.src_ring.reap_hp = next_hp;
 806
 807        return desc;
 808}
 809
 810u32 *ath11k_hal_srng_src_reap_next(struct ath11k_base *ab,
 811                                   struct hal_srng *srng)
 812{
 813        u32 *desc;
 814        u32 next_reap_hp;
 815
 816        lockdep_assert_held(&srng->lock);
 817
 818        next_reap_hp = (srng->u.src_ring.reap_hp + srng->entry_size) %
 819                       srng->ring_size;
 820
 821        if (next_reap_hp == srng->u.src_ring.cached_tp)
 822                return NULL;
 823
 824        desc = srng->ring_base_vaddr + next_reap_hp;
 825        srng->u.src_ring.reap_hp = next_reap_hp;
 826
 827        return desc;
 828}
 829
 830u32 *ath11k_hal_srng_src_get_next_reaped(struct ath11k_base *ab,
 831                                         struct hal_srng *srng)
 832{
 833        u32 *desc;
 834
 835        lockdep_assert_held(&srng->lock);
 836
 837        if (srng->u.src_ring.hp == srng->u.src_ring.reap_hp)
 838                return NULL;
 839
 840        desc = srng->ring_base_vaddr + srng->u.src_ring.hp;
 841        srng->u.src_ring.hp = (srng->u.src_ring.hp + srng->entry_size) %
 842                              srng->ring_size;
 843
 844        return desc;
 845}
 846
 847u32 *ath11k_hal_srng_src_peek(struct ath11k_base *ab, struct hal_srng *srng)
 848{
 849        lockdep_assert_held(&srng->lock);
 850
 851        if (((srng->u.src_ring.hp + srng->entry_size) % srng->ring_size) ==
 852            srng->u.src_ring.cached_tp)
 853                return NULL;
 854
 855        return srng->ring_base_vaddr + srng->u.src_ring.hp;
 856}
 857
 858void ath11k_hal_srng_access_begin(struct ath11k_base *ab, struct hal_srng *srng)
 859{
 860        lockdep_assert_held(&srng->lock);
 861
 862        if (srng->ring_dir == HAL_SRNG_DIR_SRC)
 863                srng->u.src_ring.cached_tp =
 864                        *(volatile u32 *)srng->u.src_ring.tp_addr;
 865        else
 866                srng->u.dst_ring.cached_hp = *srng->u.dst_ring.hp_addr;
 867}
 868
 869/* Update cached ring head/tail pointers to HW. ath11k_hal_srng_access_begin()
 870 * should have been called before this.
 871 */
 872void ath11k_hal_srng_access_end(struct ath11k_base *ab, struct hal_srng *srng)
 873{
 874        lockdep_assert_held(&srng->lock);
 875
 876        /* TODO: See if we need a write memory barrier here */
 877        if (srng->flags & HAL_SRNG_FLAGS_LMAC_RING) {
 878                /* For LMAC rings, ring pointer updates are done through FW and
 879                 * hence written to a shared memory location that is read by FW
 880                 */
 881                if (srng->ring_dir == HAL_SRNG_DIR_SRC) {
 882                        srng->u.src_ring.last_tp =
 883                                *(volatile u32 *)srng->u.src_ring.tp_addr;
 884                        *srng->u.src_ring.hp_addr = srng->u.src_ring.hp;
 885                } else {
 886                        srng->u.dst_ring.last_hp = *srng->u.dst_ring.hp_addr;
 887                        *srng->u.dst_ring.tp_addr = srng->u.dst_ring.tp;
 888                }
 889        } else {
 890                if (srng->ring_dir == HAL_SRNG_DIR_SRC) {
 891                        srng->u.src_ring.last_tp =
 892                                *(volatile u32 *)srng->u.src_ring.tp_addr;
 893                        ath11k_hif_write32(ab,
 894                                           (unsigned long)srng->u.src_ring.hp_addr -
 895                                           (unsigned long)ab->mem,
 896                                           srng->u.src_ring.hp);
 897                } else {
 898                        srng->u.dst_ring.last_hp = *srng->u.dst_ring.hp_addr;
 899                        ath11k_hif_write32(ab,
 900                                           (unsigned long)srng->u.dst_ring.tp_addr -
 901                                           (unsigned long)ab->mem,
 902                                           srng->u.dst_ring.tp);
 903                }
 904        }
 905
 906        srng->timestamp = jiffies;
 907}
 908
 909void ath11k_hal_setup_link_idle_list(struct ath11k_base *ab,
 910                                     struct hal_wbm_idle_scatter_list *sbuf,
 911                                     u32 nsbufs, u32 tot_link_desc,
 912                                     u32 end_offset)
 913{
 914        struct ath11k_buffer_addr *link_addr;
 915        int i;
 916        u32 reg_scatter_buf_sz = HAL_WBM_IDLE_SCATTER_BUF_SIZE / 64;
 917
 918        link_addr = (void *)sbuf[0].vaddr + HAL_WBM_IDLE_SCATTER_BUF_SIZE;
 919
 920        for (i = 1; i < nsbufs; i++) {
 921                link_addr->info0 = sbuf[i].paddr & HAL_ADDR_LSB_REG_MASK;
 922                link_addr->info1 = FIELD_PREP(
 923                                HAL_WBM_SCATTERED_DESC_MSB_BASE_ADDR_39_32,
 924                                (u64)sbuf[i].paddr >> HAL_ADDR_MSB_REG_SHIFT) |
 925                                FIELD_PREP(
 926                                HAL_WBM_SCATTERED_DESC_MSB_BASE_ADDR_MATCH_TAG,
 927                                BASE_ADDR_MATCH_TAG_VAL);
 928
 929                link_addr = (void *)sbuf[i].vaddr +
 930                             HAL_WBM_IDLE_SCATTER_BUF_SIZE;
 931        }
 932
 933        ath11k_hif_write32(ab,
 934                           HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_R0_IDLE_LIST_CONTROL_ADDR,
 935                           FIELD_PREP(HAL_WBM_SCATTER_BUFFER_SIZE, reg_scatter_buf_sz) |
 936                           FIELD_PREP(HAL_WBM_LINK_DESC_IDLE_LIST_MODE, 0x1));
 937        ath11k_hif_write32(ab,
 938                           HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_R0_IDLE_LIST_SIZE_ADDR,
 939                           FIELD_PREP(HAL_WBM_SCATTER_RING_SIZE_OF_IDLE_LINK_DESC_LIST,
 940                                      reg_scatter_buf_sz * nsbufs));
 941        ath11k_hif_write32(ab,
 942                           HAL_SEQ_WCSS_UMAC_WBM_REG +
 943                           HAL_WBM_SCATTERED_RING_BASE_LSB,
 944                           FIELD_PREP(BUFFER_ADDR_INFO0_ADDR,
 945                                      sbuf[0].paddr & HAL_ADDR_LSB_REG_MASK));
 946        ath11k_hif_write32(ab,
 947                           HAL_SEQ_WCSS_UMAC_WBM_REG +
 948                           HAL_WBM_SCATTERED_RING_BASE_MSB,
 949                           FIELD_PREP(
 950                                HAL_WBM_SCATTERED_DESC_MSB_BASE_ADDR_39_32,
 951                                (u64)sbuf[0].paddr >> HAL_ADDR_MSB_REG_SHIFT) |
 952                                FIELD_PREP(
 953                                HAL_WBM_SCATTERED_DESC_MSB_BASE_ADDR_MATCH_TAG,
 954                                BASE_ADDR_MATCH_TAG_VAL));
 955
 956        /* Setup head and tail pointers for the idle list */
 957        ath11k_hif_write32(ab,
 958                           HAL_SEQ_WCSS_UMAC_WBM_REG +
 959                           HAL_WBM_SCATTERED_DESC_PTR_HEAD_INFO_IX0,
 960                           FIELD_PREP(BUFFER_ADDR_INFO0_ADDR,
 961                                      sbuf[nsbufs - 1].paddr));
 962        ath11k_hif_write32(ab,
 963                           HAL_SEQ_WCSS_UMAC_WBM_REG +
 964                           HAL_WBM_SCATTERED_DESC_PTR_HEAD_INFO_IX1,
 965                           FIELD_PREP(
 966                                HAL_WBM_SCATTERED_DESC_MSB_BASE_ADDR_39_32,
 967                                ((u64)sbuf[nsbufs - 1].paddr >>
 968                                 HAL_ADDR_MSB_REG_SHIFT)) |
 969                           FIELD_PREP(HAL_WBM_SCATTERED_DESC_HEAD_P_OFFSET_IX1,
 970                                      (end_offset >> 2)));
 971        ath11k_hif_write32(ab,
 972                           HAL_SEQ_WCSS_UMAC_WBM_REG +
 973                           HAL_WBM_SCATTERED_DESC_PTR_HEAD_INFO_IX0,
 974                           FIELD_PREP(BUFFER_ADDR_INFO0_ADDR,
 975                                      sbuf[0].paddr));
 976
 977        ath11k_hif_write32(ab,
 978                           HAL_SEQ_WCSS_UMAC_WBM_REG +
 979                           HAL_WBM_SCATTERED_DESC_PTR_TAIL_INFO_IX0,
 980                           FIELD_PREP(BUFFER_ADDR_INFO0_ADDR,
 981                                      sbuf[0].paddr));
 982        ath11k_hif_write32(ab,
 983                           HAL_SEQ_WCSS_UMAC_WBM_REG +
 984                           HAL_WBM_SCATTERED_DESC_PTR_TAIL_INFO_IX1,
 985                           FIELD_PREP(
 986                                HAL_WBM_SCATTERED_DESC_MSB_BASE_ADDR_39_32,
 987                                ((u64)sbuf[0].paddr >> HAL_ADDR_MSB_REG_SHIFT)) |
 988                           FIELD_PREP(HAL_WBM_SCATTERED_DESC_TAIL_P_OFFSET_IX1,
 989                                      0));
 990        ath11k_hif_write32(ab,
 991                           HAL_SEQ_WCSS_UMAC_WBM_REG +
 992                           HAL_WBM_SCATTERED_DESC_PTR_HP_ADDR,
 993                           2 * tot_link_desc);
 994
 995        /* Enable the SRNG */
 996        ath11k_hif_write32(ab,
 997                           HAL_SEQ_WCSS_UMAC_WBM_REG +
 998                           HAL_WBM_IDLE_LINK_RING_MISC_ADDR, 0x40);
 999}
1000
1001int ath11k_hal_srng_setup(struct ath11k_base *ab, enum hal_ring_type type,
1002                          int ring_num, int mac_id,
1003                          struct hal_srng_params *params)
1004{
1005        struct ath11k_hal *hal = &ab->hal;
1006        const struct hal_srng_config *srng_config = &hw_srng_config[type];
1007        struct hal_srng *srng;
1008        int ring_id;
1009        u32 lmac_idx;
1010        int i;
1011        u32 reg_base;
1012
1013        ring_id = ath11k_hal_srng_get_ring_id(ab, type, ring_num, mac_id);
1014        if (ring_id < 0)
1015                return ring_id;
1016
1017        srng = &hal->srng_list[ring_id];
1018
1019        srng->ring_id = ring_id;
1020        srng->ring_dir = srng_config->ring_dir;
1021        srng->ring_base_paddr = params->ring_base_paddr;
1022        srng->ring_base_vaddr = params->ring_base_vaddr;
1023        srng->entry_size = srng_config->entry_size;
1024        srng->num_entries = params->num_entries;
1025        srng->ring_size = srng->entry_size * srng->num_entries;
1026        srng->intr_batch_cntr_thres_entries =
1027                                params->intr_batch_cntr_thres_entries;
1028        srng->intr_timer_thres_us = params->intr_timer_thres_us;
1029        srng->flags = params->flags;
1030        srng->initialized = 1;
1031        spin_lock_init(&srng->lock);
1032
1033        for (i = 0; i < HAL_SRNG_NUM_REG_GRP; i++) {
1034                srng->hwreg_base[i] = srng_config->reg_start[i] +
1035                                      (ring_num * srng_config->reg_size[i]);
1036        }
1037
1038        memset(srng->ring_base_vaddr, 0,
1039               (srng->entry_size * srng->num_entries) << 2);
1040
1041        /* TODO: Add comments on these swap configurations */
1042        if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN))
1043                srng->flags |= HAL_SRNG_FLAGS_MSI_SWAP | HAL_SRNG_FLAGS_DATA_TLV_SWAP |
1044                               HAL_SRNG_FLAGS_RING_PTR_SWAP;
1045
1046        reg_base = srng->hwreg_base[HAL_SRNG_REG_GRP_R2];
1047
1048        if (srng->ring_dir == HAL_SRNG_DIR_SRC) {
1049                srng->u.src_ring.hp = 0;
1050                srng->u.src_ring.cached_tp = 0;
1051                srng->u.src_ring.reap_hp = srng->ring_size - srng->entry_size;
1052                srng->u.src_ring.tp_addr = (void *)(hal->rdp.vaddr + ring_id);
1053                srng->u.src_ring.low_threshold = params->low_threshold *
1054                                                 srng->entry_size;
1055                if (srng_config->lmac_ring) {
1056                        lmac_idx = ring_id - HAL_SRNG_RING_ID_LMAC1_ID_START;
1057                        srng->u.src_ring.hp_addr = (void *)(hal->wrp.vaddr +
1058                                                   lmac_idx);
1059                        srng->flags |= HAL_SRNG_FLAGS_LMAC_RING;
1060                } else {
1061                        srng->u.src_ring.hp_addr =
1062                                (u32 *)((unsigned long)ab->mem + reg_base);
1063                }
1064        } else {
1065                /* During initialization loop count in all the descriptors
1066                 * will be set to zero, and HW will set it to 1 on completing
1067                 * descriptor update in first loop, and increments it by 1 on
1068                 * subsequent loops (loop count wraps around after reaching
1069                 * 0xffff). The 'loop_cnt' in SW ring state is the expected
1070                 * loop count in descriptors updated by HW (to be processed
1071                 * by SW).
1072                 */
1073                srng->u.dst_ring.loop_cnt = 1;
1074                srng->u.dst_ring.tp = 0;
1075                srng->u.dst_ring.cached_hp = 0;
1076                srng->u.dst_ring.hp_addr = (void *)(hal->rdp.vaddr + ring_id);
1077                if (srng_config->lmac_ring) {
1078                        /* For LMAC rings, tail pointer updates will be done
1079                         * through FW by writing to a shared memory location
1080                         */
1081                        lmac_idx = ring_id - HAL_SRNG_RING_ID_LMAC1_ID_START;
1082                        srng->u.dst_ring.tp_addr = (void *)(hal->wrp.vaddr +
1083                                                   lmac_idx);
1084                        srng->flags |= HAL_SRNG_FLAGS_LMAC_RING;
1085                } else {
1086                        srng->u.dst_ring.tp_addr =
1087                                (u32 *)((unsigned long)ab->mem + reg_base +
1088                                        (HAL_REO1_RING_TP - HAL_REO1_RING_HP));
1089                }
1090        }
1091
1092        if (srng_config->lmac_ring)
1093                return ring_id;
1094
1095        ath11k_hal_srng_hw_init(ab, srng);
1096
1097        if (type == HAL_CE_DST) {
1098                srng->u.dst_ring.max_buffer_length = params->max_buffer_len;
1099                ath11k_hal_ce_dst_setup(ab, srng, ring_num);
1100        }
1101
1102        return ring_id;
1103}
1104
1105int ath11k_hal_srng_init(struct ath11k_base *ab)
1106{
1107        struct ath11k_hal *hal = &ab->hal;
1108        int ret;
1109
1110        memset(hal, 0, sizeof(*hal));
1111
1112        hal->srng_config = hw_srng_config;
1113
1114        ret = ath11k_hal_alloc_cont_rdp(ab);
1115        if (ret)
1116                goto err_hal;
1117
1118        ret = ath11k_hal_alloc_cont_wrp(ab);
1119        if (ret)
1120                goto err_free_cont_rdp;
1121
1122        return 0;
1123
1124err_free_cont_rdp:
1125        ath11k_hal_free_cont_rdp(ab);
1126
1127err_hal:
1128        return ret;
1129}
1130
1131void ath11k_hal_srng_deinit(struct ath11k_base *ab)
1132{
1133        ath11k_hal_free_cont_rdp(ab);
1134        ath11k_hal_free_cont_wrp(ab);
1135}
1136
1137void ath11k_hal_dump_srng_stats(struct ath11k_base *ab)
1138{
1139        struct hal_srng *srng;
1140        struct ath11k_ext_irq_grp *irq_grp;
1141        struct ath11k_ce_pipe *ce_pipe;
1142        int i;
1143
1144        ath11k_err(ab, "Last interrupt received for each CE:\n");
1145        for (i = 0; i < CE_COUNT; i++) {
1146                ce_pipe = &ab->ce.ce_pipe[i];
1147
1148                if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR)
1149                        continue;
1150
1151                ath11k_err(ab, "CE_id %d pipe_num %d %ums before\n",
1152                           i, ce_pipe->pipe_num,
1153                           jiffies_to_msecs(jiffies - ce_pipe->timestamp));
1154        }
1155
1156        ath11k_err(ab, "\nLast interrupt received for each group:\n");
1157        for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
1158                irq_grp = &ab->ext_irq_grp[i];
1159                ath11k_err(ab, "group_id %d %ums before\n",
1160                           irq_grp->grp_id,
1161                           jiffies_to_msecs(jiffies - irq_grp->timestamp));
1162        }
1163
1164        for (i = 0; i < HAL_SRNG_RING_ID_MAX; i++) {
1165                srng = &ab->hal.srng_list[i];
1166
1167                if (!srng->initialized)
1168                        continue;
1169
1170                if (srng->ring_dir == HAL_SRNG_DIR_SRC)
1171                        ath11k_err(ab,
1172                                   "src srng id %u hp %u, reap_hp %u, cur tp %u, cached tp %u last tp %u napi processed before %ums\n",
1173                                   srng->ring_id, srng->u.src_ring.hp,
1174                                   srng->u.src_ring.reap_hp,
1175                                   *srng->u.src_ring.tp_addr, srng->u.src_ring.cached_tp,
1176                                   srng->u.src_ring.last_tp,
1177                                   jiffies_to_msecs(jiffies - srng->timestamp));
1178                else if (srng->ring_dir == HAL_SRNG_DIR_DST)
1179                        ath11k_err(ab,
1180                                   "dst srng id %u tp %u, cur hp %u, cached hp %u last hp %u napi processed before %ums\n",
1181                                   srng->ring_id, srng->u.dst_ring.tp,
1182                                   *srng->u.dst_ring.hp_addr,
1183                                   srng->u.dst_ring.cached_hp,
1184                                   srng->u.dst_ring.last_hp,
1185                                   jiffies_to_msecs(jiffies - srng->timestamp));
1186        }
1187}
1188