linux/drivers/net/ethernet/huawei/hinic/hinic_hw_if.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Huawei HiNIC PCI Express Linux driver
   4 * Copyright(c) 2017 Huawei Technologies Co., Ltd
   5 */
   6
   7#include <linux/pci.h>
   8#include <linux/device.h>
   9#include <linux/errno.h>
  10#include <linux/io.h>
  11#include <linux/types.h>
  12#include <linux/bitops.h>
  13#include <linux/delay.h>
  14
  15#include "hinic_hw_csr.h"
  16#include "hinic_hw_if.h"
  17
  18#define PCIE_ATTR_ENTRY         0
  19
  20#define VALID_MSIX_IDX(attr, msix_index) ((msix_index) < (attr)->num_irqs)
  21
  22#define WAIT_HWIF_READY_TIMEOUT 10000
  23
  24#define HINIC_SELFTEST_RESULT 0x883C
  25
  26/**
  27 * hinic_msix_attr_set - set message attribute for msix entry
  28 * @hwif: the HW interface of a pci function device
  29 * @msix_index: msix_index
  30 * @pending_limit: the maximum pending interrupt events (unit 8)
  31 * @coalesc_timer: coalesc period for interrupt (unit 8 us)
  32 * @lli_timer: replenishing period for low latency credit (unit 8 us)
  33 * @lli_credit_limit: maximum credits for low latency msix messages (unit 8)
  34 * @resend_timer: maximum wait for resending msix (unit coalesc period)
  35 *
  36 * Return 0 - Success, negative - Failure
  37 **/
  38int hinic_msix_attr_set(struct hinic_hwif *hwif, u16 msix_index,
  39                        u8 pending_limit, u8 coalesc_timer,
  40                        u8 lli_timer, u8 lli_credit_limit,
  41                        u8 resend_timer)
  42{
  43        u32 msix_ctrl, addr;
  44
  45        if (!VALID_MSIX_IDX(&hwif->attr, msix_index))
  46                return -EINVAL;
  47
  48        msix_ctrl = HINIC_MSIX_ATTR_SET(pending_limit, PENDING_LIMIT)   |
  49                    HINIC_MSIX_ATTR_SET(coalesc_timer, COALESC_TIMER)   |
  50                    HINIC_MSIX_ATTR_SET(lli_timer, LLI_TIMER)           |
  51                    HINIC_MSIX_ATTR_SET(lli_credit_limit, LLI_CREDIT)   |
  52                    HINIC_MSIX_ATTR_SET(resend_timer, RESEND_TIMER);
  53
  54        addr = HINIC_CSR_MSIX_CTRL_ADDR(msix_index);
  55
  56        hinic_hwif_write_reg(hwif, addr, msix_ctrl);
  57        return 0;
  58}
  59
  60/**
  61 * hinic_msix_attr_get - get message attribute of msix entry
  62 * @hwif: the HW interface of a pci function device
  63 * @msix_index: msix_index
  64 * @pending_limit: the maximum pending interrupt events (unit 8)
  65 * @coalesc_timer: coalesc period for interrupt (unit 8 us)
  66 * @lli_timer: replenishing period for low latency credit (unit 8 us)
  67 * @lli_credit_limit: maximum credits for low latency msix messages (unit 8)
  68 * @resend_timer: maximum wait for resending msix (unit coalesc period)
  69 *
  70 * Return 0 - Success, negative - Failure
  71 **/
  72int hinic_msix_attr_get(struct hinic_hwif *hwif, u16 msix_index,
  73                        u8 *pending_limit, u8 *coalesc_timer,
  74                        u8 *lli_timer, u8 *lli_credit_limit,
  75                        u8 *resend_timer)
  76{
  77        u32 addr, val;
  78
  79        if (!VALID_MSIX_IDX(&hwif->attr, msix_index))
  80                return -EINVAL;
  81
  82        addr = HINIC_CSR_MSIX_CTRL_ADDR(msix_index);
  83        val  = hinic_hwif_read_reg(hwif, addr);
  84
  85        *pending_limit    = HINIC_MSIX_ATTR_GET(val, PENDING_LIMIT);
  86        *coalesc_timer    = HINIC_MSIX_ATTR_GET(val, COALESC_TIMER);
  87        *lli_timer        = HINIC_MSIX_ATTR_GET(val, LLI_TIMER);
  88        *lli_credit_limit = HINIC_MSIX_ATTR_GET(val, LLI_CREDIT);
  89        *resend_timer     = HINIC_MSIX_ATTR_GET(val, RESEND_TIMER);
  90        return 0;
  91}
  92
  93/**
  94 * hinic_msix_attr_cnt_clear - clear message attribute counters for msix entry
  95 * @hwif: the HW interface of a pci function device
  96 * @msix_index: msix_index
  97 *
  98 * Return 0 - Success, negative - Failure
  99 **/
 100int hinic_msix_attr_cnt_clear(struct hinic_hwif *hwif, u16 msix_index)
 101{
 102        u32 msix_ctrl, addr;
 103
 104        if (!VALID_MSIX_IDX(&hwif->attr, msix_index))
 105                return -EINVAL;
 106
 107        msix_ctrl = HINIC_MSIX_CNT_SET(1, RESEND_TIMER);
 108        addr = HINIC_CSR_MSIX_CNT_ADDR(msix_index);
 109
 110        hinic_hwif_write_reg(hwif, addr, msix_ctrl);
 111        return 0;
 112}
 113
 114/**
 115 * hinic_set_pf_action - set action on pf channel
 116 * @hwif: the HW interface of a pci function device
 117 * @action: action on pf channel
 118 *
 119 * Return 0 - Success, negative - Failure
 120 **/
 121void hinic_set_pf_action(struct hinic_hwif *hwif, enum hinic_pf_action action)
 122{
 123        u32 attr5;
 124
 125        if (HINIC_IS_VF(hwif))
 126                return;
 127
 128        attr5 = hinic_hwif_read_reg(hwif, HINIC_CSR_FUNC_ATTR5_ADDR);
 129        attr5 = HINIC_FA5_CLEAR(attr5, PF_ACTION);
 130        attr5 |= HINIC_FA5_SET(action, PF_ACTION);
 131
 132        hinic_hwif_write_reg(hwif, HINIC_CSR_FUNC_ATTR5_ADDR, attr5);
 133}
 134
 135enum hinic_outbound_state hinic_outbound_state_get(struct hinic_hwif *hwif)
 136{
 137        u32 attr4 = hinic_hwif_read_reg(hwif, HINIC_CSR_FUNC_ATTR4_ADDR);
 138
 139        return HINIC_FA4_GET(attr4, OUTBOUND_STATE);
 140}
 141
 142void hinic_outbound_state_set(struct hinic_hwif *hwif,
 143                              enum hinic_outbound_state outbound_state)
 144{
 145        u32 attr4 = hinic_hwif_read_reg(hwif, HINIC_CSR_FUNC_ATTR4_ADDR);
 146
 147        attr4 = HINIC_FA4_CLEAR(attr4, OUTBOUND_STATE);
 148        attr4 |= HINIC_FA4_SET(outbound_state, OUTBOUND_STATE);
 149
 150        hinic_hwif_write_reg(hwif, HINIC_CSR_FUNC_ATTR4_ADDR, attr4);
 151}
 152
 153enum hinic_db_state hinic_db_state_get(struct hinic_hwif *hwif)
 154{
 155        u32 attr4 = hinic_hwif_read_reg(hwif, HINIC_CSR_FUNC_ATTR4_ADDR);
 156
 157        return HINIC_FA4_GET(attr4, DB_STATE);
 158}
 159
 160void hinic_db_state_set(struct hinic_hwif *hwif,
 161                        enum hinic_db_state db_state)
 162{
 163        u32 attr4 = hinic_hwif_read_reg(hwif, HINIC_CSR_FUNC_ATTR4_ADDR);
 164
 165        attr4 = HINIC_FA4_CLEAR(attr4, DB_STATE);
 166        attr4 |= HINIC_FA4_SET(db_state, DB_STATE);
 167
 168        hinic_hwif_write_reg(hwif, HINIC_CSR_FUNC_ATTR4_ADDR, attr4);
 169}
 170
 171void hinic_set_msix_state(struct hinic_hwif *hwif, u16 msix_idx,
 172                          enum hinic_msix_state flag)
 173{
 174        u32 offset = msix_idx * HINIC_PCI_MSIX_ENTRY_SIZE +
 175                        HINIC_PCI_MSIX_ENTRY_VECTOR_CTRL;
 176        u32 mask_bits;
 177
 178        mask_bits = readl(hwif->intr_regs_base + offset);
 179        mask_bits &= ~HINIC_PCI_MSIX_ENTRY_CTRL_MASKBIT;
 180
 181        if (flag)
 182                mask_bits |= HINIC_PCI_MSIX_ENTRY_CTRL_MASKBIT;
 183
 184        writel(mask_bits, hwif->intr_regs_base + offset);
 185}
 186
 187/**
 188 * hwif_ready - test if the HW is ready for use
 189 * @hwif: the HW interface of a pci function device
 190 *
 191 * Return 0 - Success, negative - Failure
 192 **/
 193static int hwif_ready(struct hinic_hwif *hwif)
 194{
 195        u32 addr, attr1;
 196
 197        addr   = HINIC_CSR_FUNC_ATTR1_ADDR;
 198        attr1  = hinic_hwif_read_reg(hwif, addr);
 199
 200        if (!HINIC_FA1_GET(attr1, MGMT_INIT_STATUS))
 201                return -EBUSY;
 202
 203        if (HINIC_IS_VF(hwif)) {
 204                if (!HINIC_FA1_GET(attr1, PF_INIT_STATUS))
 205                        return -EBUSY;
 206        }
 207
 208        return 0;
 209}
 210
 211static int wait_hwif_ready(struct hinic_hwif *hwif)
 212{
 213        unsigned long timeout = 0;
 214
 215        do {
 216                if (!hwif_ready(hwif))
 217                        return 0;
 218
 219                usleep_range(999, 1000);
 220                timeout++;
 221        } while (timeout <= WAIT_HWIF_READY_TIMEOUT);
 222
 223        dev_err(&hwif->pdev->dev, "Wait for hwif timeout\n");
 224
 225        return -EBUSY;
 226}
 227
 228/**
 229 * set_hwif_attr - set the attributes in the relevant members in hwif
 230 * @hwif: the HW interface of a pci function device
 231 * @attr0: the first attribute that was read from the hw
 232 * @attr1: the second attribute that was read from the hw
 233 * @attr2: the third attribute that was read from the hw
 234 **/
 235static void set_hwif_attr(struct hinic_hwif *hwif, u32 attr0, u32 attr1,
 236                          u32 attr2)
 237{
 238        hwif->attr.func_idx     = HINIC_FA0_GET(attr0, FUNC_IDX);
 239        hwif->attr.pf_idx       = HINIC_FA0_GET(attr0, PF_IDX);
 240        hwif->attr.pci_intf_idx = HINIC_FA0_GET(attr0, PCI_INTF_IDX);
 241        hwif->attr.func_type    = HINIC_FA0_GET(attr0, FUNC_TYPE);
 242
 243        hwif->attr.num_aeqs = BIT(HINIC_FA1_GET(attr1, AEQS_PER_FUNC));
 244        hwif->attr.num_ceqs = BIT(HINIC_FA1_GET(attr1, CEQS_PER_FUNC));
 245        hwif->attr.num_irqs = BIT(HINIC_FA1_GET(attr1, IRQS_PER_FUNC));
 246        hwif->attr.num_dma_attr = BIT(HINIC_FA1_GET(attr1, DMA_ATTR_PER_FUNC));
 247        hwif->attr.global_vf_id_of_pf = HINIC_FA2_GET(attr2,
 248                                                      GLOBAL_VF_ID_OF_PF);
 249}
 250
 251/**
 252 * read_hwif_attr - read the attributes and set members in hwif
 253 * @hwif: the HW interface of a pci function device
 254 **/
 255static void read_hwif_attr(struct hinic_hwif *hwif)
 256{
 257        u32 addr, attr0, attr1, attr2;
 258
 259        addr   = HINIC_CSR_FUNC_ATTR0_ADDR;
 260        attr0  = hinic_hwif_read_reg(hwif, addr);
 261
 262        addr   = HINIC_CSR_FUNC_ATTR1_ADDR;
 263        attr1  = hinic_hwif_read_reg(hwif, addr);
 264
 265        addr   = HINIC_CSR_FUNC_ATTR2_ADDR;
 266        attr2  = hinic_hwif_read_reg(hwif, addr);
 267
 268        set_hwif_attr(hwif, attr0, attr1, attr2);
 269}
 270
 271/**
 272 * set_ppf - try to set hwif as ppf and set the type of hwif in this case
 273 * @hwif: the HW interface of a pci function device
 274 **/
 275static void set_ppf(struct hinic_hwif *hwif)
 276{
 277        struct hinic_func_attr *attr = &hwif->attr;
 278        u32 addr, val, ppf_election;
 279
 280        /* Read Modify Write */
 281        addr = HINIC_CSR_PPF_ELECTION_ADDR(HINIC_HWIF_PCI_INTF(hwif));
 282
 283        val = hinic_hwif_read_reg(hwif, addr);
 284        val = HINIC_PPF_ELECTION_CLEAR(val, IDX);
 285
 286        ppf_election = HINIC_PPF_ELECTION_SET(HINIC_HWIF_FUNC_IDX(hwif), IDX);
 287
 288        val |= ppf_election;
 289        hinic_hwif_write_reg(hwif, addr, val);
 290
 291        /* check PPF */
 292        val = hinic_hwif_read_reg(hwif, addr);
 293
 294        attr->ppf_idx = HINIC_PPF_ELECTION_GET(val, IDX);
 295        if (attr->ppf_idx == HINIC_HWIF_FUNC_IDX(hwif))
 296                attr->func_type = HINIC_PPF;
 297}
 298
 299/**
 300 * set_dma_attr - set the dma attributes in the HW
 301 * @hwif: the HW interface of a pci function device
 302 * @entry_idx: the entry index in the dma table
 303 * @st: PCIE TLP steering tag
 304 * @at: PCIE TLP AT field
 305 * @ph: PCIE TLP Processing Hint field
 306 * @no_snooping: PCIE TLP No snooping
 307 * @tph_en: PCIE TLP Processing Hint Enable
 308 **/
 309static void set_dma_attr(struct hinic_hwif *hwif, u32 entry_idx,
 310                         u8 st, u8 at, u8 ph,
 311                         enum hinic_pcie_nosnoop no_snooping,
 312                         enum hinic_pcie_tph tph_en)
 313{
 314        u32 addr, val, dma_attr_entry;
 315
 316        /* Read Modify Write */
 317        addr = HINIC_CSR_DMA_ATTR_ADDR(entry_idx);
 318
 319        val = hinic_hwif_read_reg(hwif, addr);
 320        val = HINIC_DMA_ATTR_CLEAR(val, ST)             &
 321              HINIC_DMA_ATTR_CLEAR(val, AT)             &
 322              HINIC_DMA_ATTR_CLEAR(val, PH)             &
 323              HINIC_DMA_ATTR_CLEAR(val, NO_SNOOPING)    &
 324              HINIC_DMA_ATTR_CLEAR(val, TPH_EN);
 325
 326        dma_attr_entry = HINIC_DMA_ATTR_SET(st, ST)                     |
 327                         HINIC_DMA_ATTR_SET(at, AT)                     |
 328                         HINIC_DMA_ATTR_SET(ph, PH)                     |
 329                         HINIC_DMA_ATTR_SET(no_snooping, NO_SNOOPING)   |
 330                         HINIC_DMA_ATTR_SET(tph_en, TPH_EN);
 331
 332        val |= dma_attr_entry;
 333        hinic_hwif_write_reg(hwif, addr, val);
 334}
 335
 336/**
 337 * dma_attr_init - initialize the default dma attributes
 338 * @hwif: the HW interface of a pci function device
 339 **/
 340static void dma_attr_init(struct hinic_hwif *hwif)
 341{
 342        set_dma_attr(hwif, PCIE_ATTR_ENTRY, HINIC_PCIE_ST_DISABLE,
 343                     HINIC_PCIE_AT_DISABLE, HINIC_PCIE_PH_DISABLE,
 344                     HINIC_PCIE_SNOOP, HINIC_PCIE_TPH_DISABLE);
 345}
 346
 347u16 hinic_glb_pf_vf_offset(struct hinic_hwif *hwif)
 348{
 349        if (!hwif)
 350                return 0;
 351
 352        return hwif->attr.global_vf_id_of_pf;
 353}
 354
 355u16 hinic_global_func_id_hw(struct hinic_hwif *hwif)
 356{
 357        u32 addr, attr0;
 358
 359        addr   = HINIC_CSR_FUNC_ATTR0_ADDR;
 360        attr0  = hinic_hwif_read_reg(hwif, addr);
 361
 362        return HINIC_FA0_GET(attr0, FUNC_IDX);
 363}
 364
 365u16 hinic_pf_id_of_vf_hw(struct hinic_hwif *hwif)
 366{
 367        u32 addr, attr0;
 368
 369        addr   = HINIC_CSR_FUNC_ATTR0_ADDR;
 370        attr0  = hinic_hwif_read_reg(hwif, addr);
 371
 372        return HINIC_FA0_GET(attr0, PF_IDX);
 373}
 374
 375static void __print_selftest_reg(struct hinic_hwif *hwif)
 376{
 377        u32 addr, attr0, attr1;
 378
 379        addr   = HINIC_CSR_FUNC_ATTR1_ADDR;
 380        attr1  = hinic_hwif_read_reg(hwif, addr);
 381
 382        if (attr1 == HINIC_PCIE_LINK_DOWN) {
 383                dev_err(&hwif->pdev->dev, "PCIE is link down\n");
 384                return;
 385        }
 386
 387        addr   = HINIC_CSR_FUNC_ATTR0_ADDR;
 388        attr0  = hinic_hwif_read_reg(hwif, addr);
 389        if (HINIC_FA0_GET(attr0, FUNC_TYPE) != HINIC_VF &&
 390            !HINIC_FA0_GET(attr0, PCI_INTF_IDX))
 391                dev_err(&hwif->pdev->dev, "Selftest reg: 0x%08x\n",
 392                        hinic_hwif_read_reg(hwif, HINIC_SELFTEST_RESULT));
 393}
 394
 395/**
 396 * hinic_init_hwif - initialize the hw interface
 397 * @hwif: the HW interface of a pci function device
 398 * @pdev: the pci device for accessing PCI resources
 399 *
 400 * Return 0 - Success, negative - Failure
 401 **/
 402int hinic_init_hwif(struct hinic_hwif *hwif, struct pci_dev *pdev)
 403{
 404        int err;
 405
 406        hwif->pdev = pdev;
 407
 408        hwif->cfg_regs_bar = pci_ioremap_bar(pdev, HINIC_PCI_CFG_REGS_BAR);
 409        if (!hwif->cfg_regs_bar) {
 410                dev_err(&pdev->dev, "Failed to map configuration regs\n");
 411                return -ENOMEM;
 412        }
 413
 414        hwif->intr_regs_base = pci_ioremap_bar(pdev, HINIC_PCI_INTR_REGS_BAR);
 415        if (!hwif->intr_regs_base) {
 416                dev_err(&pdev->dev, "Failed to map configuration regs\n");
 417                err = -ENOMEM;
 418                goto err_map_intr_bar;
 419        }
 420
 421        err = wait_hwif_ready(hwif);
 422        if (err) {
 423                dev_err(&pdev->dev, "HW interface is not ready\n");
 424                __print_selftest_reg(hwif);
 425                goto err_hwif_ready;
 426        }
 427
 428        read_hwif_attr(hwif);
 429
 430        if (HINIC_IS_PF(hwif))
 431                set_ppf(hwif);
 432
 433        /* No transactionss before DMA is initialized */
 434        dma_attr_init(hwif);
 435        return 0;
 436
 437err_hwif_ready:
 438        iounmap(hwif->intr_regs_base);
 439
 440err_map_intr_bar:
 441        iounmap(hwif->cfg_regs_bar);
 442
 443        return err;
 444}
 445
 446/**
 447 * hinic_free_hwif - free the HW interface
 448 * @hwif: the HW interface of a pci function device
 449 **/
 450void hinic_free_hwif(struct hinic_hwif *hwif)
 451{
 452        iounmap(hwif->intr_regs_base);
 453        iounmap(hwif->cfg_regs_bar);
 454}
 455