linux/drivers/scsi/csiostor/csio_hw_t4.c
<<
>>
Prefs
   1/*
   2 * This file is part of the Chelsio FCoE driver for Linux.
   3 *
   4 * Copyright (c) 2008-2013 Chelsio Communications, Inc. All rights reserved.
   5 *
   6 * This software is available to you under a choice of one of two
   7 * licenses.  You may choose to be licensed under the terms of the GNU
   8 * General Public License (GPL) Version 2, available from the file
   9 * OpenIB.org BSD license below:
  10 *
  11 *     Redistribution and use in source and binary forms, with or
  12 *     without modification, are permitted provided that the following
  13 *     conditions are met:
  14 *
  15 *      - Redistributions of source code must retain the above
  16 *        copyright notice, this list of conditions and the following
  17 *      - Redistributions in binary form must reproduce the above
  18 *        copyright notice, this list of conditions and the following
  19 *        disclaimer in the documentation and/or other materials
  20 *        provided with the distribution.
  21 *
  22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  23 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  24 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  25 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  26 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  27 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  28 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  29 * SOFTWARE.
  30 */
  31
  32#include "csio_hw.h"
  33#include "csio_init.h"
  34
  35/*
  36 * Return the specified PCI-E Configuration Space register from our Physical
  37 * Function.  We try first via a Firmware LDST Command since we prefer to let
  38 * the firmware own all of these registers, but if that fails we go for it
  39 * directly ourselves.
  40 */
  41static uint32_t
  42csio_t4_read_pcie_cfg4(struct csio_hw *hw, int reg)
  43{
  44        u32 val = 0;
  45        struct csio_mb *mbp;
  46        int rv;
  47        struct fw_ldst_cmd *ldst_cmd;
  48
  49        mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
  50        if (!mbp) {
  51                CSIO_INC_STATS(hw, n_err_nomem);
  52                pci_read_config_dword(hw->pdev, reg, &val);
  53                return val;
  54        }
  55
  56        csio_mb_ldst(hw, mbp, CSIO_MB_DEFAULT_TMO, reg);
  57        rv = csio_mb_issue(hw, mbp);
  58
  59        /*
  60         * If the LDST Command suucceeded, exctract the returned register
  61         * value.  Otherwise read it directly ourself.
  62         */
  63        if (rv == 0) {
  64                ldst_cmd = (struct fw_ldst_cmd *)(mbp->mb);
  65                val = ntohl(ldst_cmd->u.pcie.data[0]);
  66        } else
  67                pci_read_config_dword(hw->pdev, reg, &val);
  68
  69        mempool_free(mbp, hw->mb_mempool);
  70
  71        return val;
  72}
  73
  74static int
  75csio_t4_set_mem_win(struct csio_hw *hw, uint32_t win)
  76{
  77        u32 bar0;
  78        u32 mem_win_base;
  79
  80        /*
  81         * Truncation intentional: we only read the bottom 32-bits of the
  82         * 64-bit BAR0/BAR1 ...  We use the hardware backdoor mechanism to
  83         * read BAR0 instead of using pci_resource_start() because we could be
  84         * operating from within a Virtual Machine which is trapping our
  85         * accesses to our Configuration Space and we need to set up the PCI-E
  86         * Memory Window decoders with the actual addresses which will be
  87         * coming across the PCI-E link.
  88         */
  89        bar0 = csio_t4_read_pcie_cfg4(hw, PCI_BASE_ADDRESS_0);
  90        bar0 &= PCI_BASE_ADDRESS_MEM_MASK;
  91
  92        mem_win_base = bar0 + MEMWIN_BASE;
  93
  94        /*
  95         * Set up memory window for accessing adapter memory ranges.  (Read
  96         * back MA register to ensure that changes propagate before we attempt
  97         * to use the new values.)
  98         */
  99        csio_wr_reg32(hw, mem_win_base | BIR(0) |
 100                          WINDOW(ilog2(MEMWIN_APERTURE) - 10),
 101                          PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, win));
 102        csio_rd_reg32(hw,
 103                      PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, win));
 104        return 0;
 105}
 106
 107/*
 108 * Interrupt handler for the PCIE module.
 109 */
 110static void
 111csio_t4_pcie_intr_handler(struct csio_hw *hw)
 112{
 113        static struct intr_info sysbus_intr_info[] = {
 114                { RNPP, "RXNP array parity error", -1, 1 },
 115                { RPCP, "RXPC array parity error", -1, 1 },
 116                { RCIP, "RXCIF array parity error", -1, 1 },
 117                { RCCP, "Rx completions control array parity error", -1, 1 },
 118                { RFTP, "RXFT array parity error", -1, 1 },
 119                { 0, NULL, 0, 0 }
 120        };
 121        static struct intr_info pcie_port_intr_info[] = {
 122                { TPCP, "TXPC array parity error", -1, 1 },
 123                { TNPP, "TXNP array parity error", -1, 1 },
 124                { TFTP, "TXFT array parity error", -1, 1 },
 125                { TCAP, "TXCA array parity error", -1, 1 },
 126                { TCIP, "TXCIF array parity error", -1, 1 },
 127                { RCAP, "RXCA array parity error", -1, 1 },
 128                { OTDD, "outbound request TLP discarded", -1, 1 },
 129                { RDPE, "Rx data parity error", -1, 1 },
 130                { TDUE, "Tx uncorrectable data error", -1, 1 },
 131                { 0, NULL, 0, 0 }
 132        };
 133
 134        static struct intr_info pcie_intr_info[] = {
 135                { MSIADDRLPERR, "MSI AddrL parity error", -1, 1 },
 136                { MSIADDRHPERR, "MSI AddrH parity error", -1, 1 },
 137                { MSIDATAPERR, "MSI data parity error", -1, 1 },
 138                { MSIXADDRLPERR, "MSI-X AddrL parity error", -1, 1 },
 139                { MSIXADDRHPERR, "MSI-X AddrH parity error", -1, 1 },
 140                { MSIXDATAPERR, "MSI-X data parity error", -1, 1 },
 141                { MSIXDIPERR, "MSI-X DI parity error", -1, 1 },
 142                { PIOCPLPERR, "PCI PIO completion FIFO parity error", -1, 1 },
 143                { PIOREQPERR, "PCI PIO request FIFO parity error", -1, 1 },
 144                { TARTAGPERR, "PCI PCI target tag FIFO parity error", -1, 1 },
 145                { CCNTPERR, "PCI CMD channel count parity error", -1, 1 },
 146                { CREQPERR, "PCI CMD channel request parity error", -1, 1 },
 147                { CRSPPERR, "PCI CMD channel response parity error", -1, 1 },
 148                { DCNTPERR, "PCI DMA channel count parity error", -1, 1 },
 149                { DREQPERR, "PCI DMA channel request parity error", -1, 1 },
 150                { DRSPPERR, "PCI DMA channel response parity error", -1, 1 },
 151                { HCNTPERR, "PCI HMA channel count parity error", -1, 1 },
 152                { HREQPERR, "PCI HMA channel request parity error", -1, 1 },
 153                { HRSPPERR, "PCI HMA channel response parity error", -1, 1 },
 154                { CFGSNPPERR, "PCI config snoop FIFO parity error", -1, 1 },
 155                { FIDPERR, "PCI FID parity error", -1, 1 },
 156                { INTXCLRPERR, "PCI INTx clear parity error", -1, 1 },
 157                { MATAGPERR, "PCI MA tag parity error", -1, 1 },
 158                { PIOTAGPERR, "PCI PIO tag parity error", -1, 1 },
 159                { RXCPLPERR, "PCI Rx completion parity error", -1, 1 },
 160                { RXWRPERR, "PCI Rx write parity error", -1, 1 },
 161                { RPLPERR, "PCI replay buffer parity error", -1, 1 },
 162                { PCIESINT, "PCI core secondary fault", -1, 1 },
 163                { PCIEPINT, "PCI core primary fault", -1, 1 },
 164                { UNXSPLCPLERR, "PCI unexpected split completion error", -1,
 165                  0 },
 166                { 0, NULL, 0, 0 }
 167        };
 168
 169        int fat;
 170        fat = csio_handle_intr_status(hw,
 171                                      PCIE_CORE_UTL_SYSTEM_BUS_AGENT_STATUS,
 172                                      sysbus_intr_info) +
 173              csio_handle_intr_status(hw,
 174                                      PCIE_CORE_UTL_PCI_EXPRESS_PORT_STATUS,
 175                                      pcie_port_intr_info) +
 176              csio_handle_intr_status(hw, PCIE_INT_CAUSE, pcie_intr_info);
 177        if (fat)
 178                csio_hw_fatal_err(hw);
 179}
 180
 181/*
 182 * csio_t4_flash_cfg_addr - return the address of the flash configuration file
 183 * @hw: the HW module
 184 *
 185 * Return the address within the flash where the Firmware Configuration
 186 * File is stored.
 187 */
 188static unsigned int
 189csio_t4_flash_cfg_addr(struct csio_hw *hw)
 190{
 191        return FLASH_CFG_OFFSET;
 192}
 193
 194/*
 195 *      csio_t4_mc_read - read from MC through backdoor accesses
 196 *      @hw: the hw module
 197 *      @idx: not used for T4 adapter
 198 *      @addr: address of first byte requested
 199 *      @data: 64 bytes of data containing the requested address
 200 *      @ecc: where to store the corresponding 64-bit ECC word
 201 *
 202 *      Read 64 bytes of data from MC starting at a 64-byte-aligned address
 203 *      that covers the requested address @addr.  If @parity is not %NULL it
 204 *      is assigned the 64-bit ECC word for the read data.
 205 */
 206static int
 207csio_t4_mc_read(struct csio_hw *hw, int idx, uint32_t addr, __be32 *data,
 208                uint64_t *ecc)
 209{
 210        int i;
 211
 212        if (csio_rd_reg32(hw, MC_BIST_CMD) & START_BIST)
 213                return -EBUSY;
 214        csio_wr_reg32(hw, addr & ~0x3fU, MC_BIST_CMD_ADDR);
 215        csio_wr_reg32(hw, 64, MC_BIST_CMD_LEN);
 216        csio_wr_reg32(hw, 0xc, MC_BIST_DATA_PATTERN);
 217        csio_wr_reg32(hw, BIST_OPCODE(1) | START_BIST | BIST_CMD_GAP(1),
 218                      MC_BIST_CMD);
 219        i = csio_hw_wait_op_done_val(hw, MC_BIST_CMD, START_BIST,
 220                                     0, 10, 1, NULL);
 221        if (i)
 222                return i;
 223
 224#define MC_DATA(i) MC_BIST_STATUS_REG(MC_BIST_STATUS_RDATA, i)
 225
 226        for (i = 15; i >= 0; i--)
 227                *data++ = htonl(csio_rd_reg32(hw, MC_DATA(i)));
 228        if (ecc)
 229                *ecc = csio_rd_reg64(hw, MC_DATA(16));
 230#undef MC_DATA
 231        return 0;
 232}
 233
 234/*
 235 *      csio_t4_edc_read - read from EDC through backdoor accesses
 236 *      @hw: the hw module
 237 *      @idx: which EDC to access
 238 *      @addr: address of first byte requested
 239 *      @data: 64 bytes of data containing the requested address
 240 *      @ecc: where to store the corresponding 64-bit ECC word
 241 *
 242 *      Read 64 bytes of data from EDC starting at a 64-byte-aligned address
 243 *      that covers the requested address @addr.  If @parity is not %NULL it
 244 *      is assigned the 64-bit ECC word for the read data.
 245 */
 246static int
 247csio_t4_edc_read(struct csio_hw *hw, int idx, uint32_t addr, __be32 *data,
 248                uint64_t *ecc)
 249{
 250        int i;
 251
 252        idx *= EDC_STRIDE;
 253        if (csio_rd_reg32(hw, EDC_BIST_CMD + idx) & START_BIST)
 254                return -EBUSY;
 255        csio_wr_reg32(hw, addr & ~0x3fU, EDC_BIST_CMD_ADDR + idx);
 256        csio_wr_reg32(hw, 64, EDC_BIST_CMD_LEN + idx);
 257        csio_wr_reg32(hw, 0xc, EDC_BIST_DATA_PATTERN + idx);
 258        csio_wr_reg32(hw, BIST_OPCODE(1) | BIST_CMD_GAP(1) | START_BIST,
 259                      EDC_BIST_CMD + idx);
 260        i = csio_hw_wait_op_done_val(hw, EDC_BIST_CMD + idx, START_BIST,
 261                                     0, 10, 1, NULL);
 262        if (i)
 263                return i;
 264
 265#define EDC_DATA(i) (EDC_BIST_STATUS_REG(EDC_BIST_STATUS_RDATA, i) + idx)
 266
 267        for (i = 15; i >= 0; i--)
 268                *data++ = htonl(csio_rd_reg32(hw, EDC_DATA(i)));
 269        if (ecc)
 270                *ecc = csio_rd_reg64(hw, EDC_DATA(16));
 271#undef EDC_DATA
 272        return 0;
 273}
 274
 275/*
 276 * csio_t4_memory_rw - read/write EDC 0, EDC 1 or MC via PCIE memory window
 277 * @hw: the csio_hw
 278 * @win: PCI-E memory Window to use
 279 * @mtype: memory type: MEM_EDC0, MEM_EDC1, MEM_MC0 (or MEM_MC) or MEM_MC1
 280 * @addr: address within indicated memory type
 281 * @len: amount of memory to transfer
 282 * @buf: host memory buffer
 283 * @dir: direction of transfer 1 => read, 0 => write
 284 *
 285 * Reads/writes an [almost] arbitrary memory region in the firmware: the
 286 * firmware memory address, length and host buffer must be aligned on
 287 * 32-bit boudaries.  The memory is transferred as a raw byte sequence
 288 * from/to the firmware's memory.  If this memory contains data
 289 * structures which contain multi-byte integers, it's the callers
 290 * responsibility to perform appropriate byte order conversions.
 291 */
 292static int
 293csio_t4_memory_rw(struct csio_hw *hw, u32 win, int mtype, u32 addr,
 294                u32 len, uint32_t *buf, int dir)
 295{
 296        u32 pos, start, offset, memoffset, bar0;
 297        u32 edc_size, mc_size, mem_reg, mem_aperture, mem_base;
 298
 299        /*
 300         * Argument sanity checks ...
 301         */
 302        if ((addr & 0x3) || (len & 0x3))
 303                return -EINVAL;
 304
 305        /* Offset into the region of memory which is being accessed
 306         * MEM_EDC0 = 0
 307         * MEM_EDC1 = 1
 308         * MEM_MC   = 2 -- T4
 309         */
 310        edc_size  = EDRAM_SIZE_GET(csio_rd_reg32(hw, MA_EDRAM0_BAR));
 311        if (mtype != MEM_MC1)
 312                memoffset = (mtype * (edc_size * 1024 * 1024));
 313        else {
 314                mc_size = EXT_MEM_SIZE_GET(csio_rd_reg32(hw,
 315                                                         MA_EXT_MEMORY_BAR));
 316                memoffset = (MEM_MC0 * edc_size + mc_size) * 1024 * 1024;
 317        }
 318
 319        /* Determine the PCIE_MEM_ACCESS_OFFSET */
 320        addr = addr + memoffset;
 321
 322        /*
 323         * Each PCI-E Memory Window is programmed with a window size -- or
 324         * "aperture" -- which controls the granularity of its mapping onto
 325         * adapter memory.  We need to grab that aperture in order to know
 326         * how to use the specified window.  The window is also programmed
 327         * with the base address of the Memory Window in BAR0's address
 328         * space.  For T4 this is an absolute PCI-E Bus Address.  For T5
 329         * the address is relative to BAR0.
 330         */
 331        mem_reg = csio_rd_reg32(hw,
 332                        PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, win));
 333        mem_aperture = 1 << (WINDOW(mem_reg) + 10);
 334        mem_base = GET_PCIEOFST(mem_reg) << 10;
 335
 336        bar0 = csio_t4_read_pcie_cfg4(hw, PCI_BASE_ADDRESS_0);
 337        bar0 &= PCI_BASE_ADDRESS_MEM_MASK;
 338        mem_base -= bar0;
 339
 340        start = addr & ~(mem_aperture-1);
 341        offset = addr - start;
 342
 343        csio_dbg(hw, "csio_t4_memory_rw: mem_reg: 0x%x, mem_aperture: 0x%x\n",
 344                 mem_reg, mem_aperture);
 345        csio_dbg(hw, "csio_t4_memory_rw: mem_base: 0x%x, mem_offset: 0x%x\n",
 346                 mem_base, memoffset);
 347        csio_dbg(hw, "csio_t4_memory_rw: bar0: 0x%x, start:0x%x, offset:0x%x\n",
 348                 bar0, start, offset);
 349        csio_dbg(hw, "csio_t4_memory_rw: mtype: %d, addr: 0x%x, len: %d\n",
 350                 mtype, addr, len);
 351
 352        for (pos = start; len > 0; pos += mem_aperture, offset = 0) {
 353                /*
 354                 * Move PCI-E Memory Window to our current transfer
 355                 * position.  Read it back to ensure that changes propagate
 356                 * before we attempt to use the new value.
 357                 */
 358                csio_wr_reg32(hw, pos,
 359                        PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_OFFSET, win));
 360                csio_rd_reg32(hw,
 361                        PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_OFFSET, win));
 362
 363                while (offset < mem_aperture && len > 0) {
 364                        if (dir)
 365                                *buf++ = csio_rd_reg32(hw, mem_base + offset);
 366                        else
 367                                csio_wr_reg32(hw, *buf++, mem_base + offset);
 368
 369                        offset += sizeof(__be32);
 370                        len -= sizeof(__be32);
 371                }
 372        }
 373        return 0;
 374}
 375
 376/*
 377 * csio_t4_dfs_create_ext_mem - setup debugfs for MC to read the values
 378 * @hw: the csio_hw
 379 *
 380 * This function creates files in the debugfs with external memory region MC.
 381 */
 382static void
 383csio_t4_dfs_create_ext_mem(struct csio_hw *hw)
 384{
 385        u32 size;
 386        int i = csio_rd_reg32(hw, MA_TARGET_MEM_ENABLE);
 387        if (i & EXT_MEM_ENABLE) {
 388                size = csio_rd_reg32(hw, MA_EXT_MEMORY_BAR);
 389                csio_add_debugfs_mem(hw, "mc", MEM_MC,
 390                                     EXT_MEM_SIZE_GET(size));
 391        }
 392}
 393
 394/* T4 adapter specific function */
 395struct csio_hw_chip_ops t4_ops = {
 396        .chip_set_mem_win               = csio_t4_set_mem_win,
 397        .chip_pcie_intr_handler         = csio_t4_pcie_intr_handler,
 398        .chip_flash_cfg_addr            = csio_t4_flash_cfg_addr,
 399        .chip_mc_read                   = csio_t4_mc_read,
 400        .chip_edc_read                  = csio_t4_edc_read,
 401        .chip_memory_rw                 = csio_t4_memory_rw,
 402        .chip_dfs_create_ext_mem        = csio_t4_dfs_create_ext_mem,
 403};
 404