linux/drivers/scsi/qla2xxx/qla_inline.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0-only */
   2/*
   3 * QLogic Fibre Channel HBA Driver
   4 * Copyright (c)  2003-2014 QLogic Corporation
   5 */
   6
   7#include "qla_target.h"
   8/**
   9 * qla24xx_calc_iocbs() - Determine number of Command Type 3 and
  10 * Continuation Type 1 IOCBs to allocate.
  11 *
  12 * @vha: HA context
  13 * @dsds: number of data segment descriptors needed
  14 *
  15 * Returns the number of IOCB entries needed to store @dsds.
  16 */
  17static inline uint16_t
  18qla24xx_calc_iocbs(scsi_qla_host_t *vha, uint16_t dsds)
  19{
  20        uint16_t iocbs;
  21
  22        iocbs = 1;
  23        if (dsds > 1) {
  24                iocbs += (dsds - 1) / 5;
  25                if ((dsds - 1) % 5)
  26                        iocbs++;
  27        }
  28        return iocbs;
  29}
  30
  31/*
  32 * qla2x00_debounce_register
  33 *      Debounce register.
  34 *
  35 * Input:
  36 *      port = register address.
  37 *
  38 * Returns:
  39 *      register value.
  40 */
  41static __inline__ uint16_t
  42qla2x00_debounce_register(volatile __le16 __iomem *addr)
  43{
  44        volatile uint16_t first;
  45        volatile uint16_t second;
  46
  47        do {
  48                first = rd_reg_word(addr);
  49                barrier();
  50                cpu_relax();
  51                second = rd_reg_word(addr);
  52        } while (first != second);
  53
  54        return (first);
  55}
  56
  57static inline void
  58qla2x00_poll(struct rsp_que *rsp)
  59{
  60        struct qla_hw_data *ha = rsp->hw;
  61
  62        if (IS_P3P_TYPE(ha))
  63                qla82xx_poll(0, rsp);
  64        else
  65                ha->isp_ops->intr_handler(0, rsp);
  66}
  67
  68static inline uint8_t *
  69host_to_fcp_swap(uint8_t *fcp, uint32_t bsize)
  70{
  71       uint32_t *ifcp = (uint32_t *) fcp;
  72       uint32_t *ofcp = (uint32_t *) fcp;
  73       uint32_t iter = bsize >> 2;
  74
  75       for (; iter ; iter--)
  76               *ofcp++ = swab32(*ifcp++);
  77
  78       return fcp;
  79}
  80
  81static inline void
  82host_to_adap(uint8_t *src, uint8_t *dst, uint32_t bsize)
  83{
  84        uint32_t *isrc = (uint32_t *) src;
  85        __le32 *odest = (__le32 *) dst;
  86        uint32_t iter = bsize >> 2;
  87
  88        for ( ; iter--; isrc++)
  89                *odest++ = cpu_to_le32(*isrc);
  90}
  91
  92static inline void
  93qla2x00_clean_dsd_pool(struct qla_hw_data *ha, struct crc_context *ctx)
  94{
  95        struct dsd_dma *dsd, *tdsd;
  96
  97        /* clean up allocated prev pool */
  98        list_for_each_entry_safe(dsd, tdsd, &ctx->dsd_list, list) {
  99                dma_pool_free(ha->dl_dma_pool, dsd->dsd_addr,
 100                    dsd->dsd_list_dma);
 101                list_del(&dsd->list);
 102                kfree(dsd);
 103        }
 104        INIT_LIST_HEAD(&ctx->dsd_list);
 105}
 106
 107static inline void
 108qla2x00_set_fcport_disc_state(fc_port_t *fcport, int state)
 109{
 110        int old_val;
 111        uint8_t shiftbits, mask;
 112
 113        /* This will have to change when the max no. of states > 16 */
 114        shiftbits = 4;
 115        mask = (1 << shiftbits) - 1;
 116
 117        fcport->disc_state = state;
 118        while (1) {
 119                old_val = atomic_read(&fcport->shadow_disc_state);
 120                if (old_val == atomic_cmpxchg(&fcport->shadow_disc_state,
 121                    old_val, (old_val << shiftbits) | state)) {
 122                        ql_dbg(ql_dbg_disc, fcport->vha, 0x2134,
 123                            "FCPort %8phC disc_state transition: %s to %s - portid=%06x.\n",
 124                            fcport->port_name, port_dstate_str[old_val & mask],
 125                            port_dstate_str[state], fcport->d_id.b24);
 126                        return;
 127                }
 128        }
 129}
 130
 131static inline int
 132qla2x00_hba_err_chk_enabled(srb_t *sp)
 133{
 134        /*
 135         * Uncomment when corresponding SCSI changes are done.
 136         *
 137        if (!sp->cmd->prot_chk)
 138                return 0;
 139         *
 140         */
 141        switch (scsi_get_prot_op(GET_CMD_SP(sp))) {
 142        case SCSI_PROT_READ_STRIP:
 143        case SCSI_PROT_WRITE_INSERT:
 144                if (ql2xenablehba_err_chk >= 1)
 145                        return 1;
 146                break;
 147        case SCSI_PROT_READ_PASS:
 148        case SCSI_PROT_WRITE_PASS:
 149                if (ql2xenablehba_err_chk >= 2)
 150                        return 1;
 151                break;
 152        case SCSI_PROT_READ_INSERT:
 153        case SCSI_PROT_WRITE_STRIP:
 154                return 1;
 155        }
 156        return 0;
 157}
 158
 159static inline int
 160qla2x00_reset_active(scsi_qla_host_t *vha)
 161{
 162        scsi_qla_host_t *base_vha = pci_get_drvdata(vha->hw->pdev);
 163
 164        /* Test appropriate base-vha and vha flags. */
 165        return test_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags) ||
 166            test_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags) ||
 167            test_bit(ISP_ABORT_RETRY, &base_vha->dpc_flags) ||
 168            test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
 169            test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags);
 170}
 171
 172static inline int
 173qla2x00_chip_is_down(scsi_qla_host_t *vha)
 174{
 175        return (qla2x00_reset_active(vha) || !vha->hw->flags.fw_started);
 176}
 177
 178static void qla2xxx_init_sp(srb_t *sp, scsi_qla_host_t *vha,
 179                            struct qla_qpair *qpair, fc_port_t *fcport)
 180{
 181        memset(sp, 0, sizeof(*sp));
 182        sp->fcport = fcport;
 183        sp->iocbs = 1;
 184        sp->vha = vha;
 185        sp->qpair = qpair;
 186        sp->cmd_type = TYPE_SRB;
 187        INIT_LIST_HEAD(&sp->elem);
 188}
 189
 190static inline srb_t *
 191qla2xxx_get_qpair_sp(scsi_qla_host_t *vha, struct qla_qpair *qpair,
 192    fc_port_t *fcport, gfp_t flag)
 193{
 194        srb_t *sp = NULL;
 195        uint8_t bail;
 196
 197        QLA_QPAIR_MARK_BUSY(qpair, bail);
 198        if (unlikely(bail))
 199                return NULL;
 200
 201        sp = mempool_alloc(qpair->srb_mempool, flag);
 202        if (sp)
 203                qla2xxx_init_sp(sp, vha, qpair, fcport);
 204        else
 205                QLA_QPAIR_MARK_NOT_BUSY(qpair);
 206        return sp;
 207}
 208
 209void qla2xxx_rel_done_warning(srb_t *sp, int res);
 210void qla2xxx_rel_free_warning(srb_t *sp);
 211
 212static inline void
 213qla2xxx_rel_qpair_sp(struct qla_qpair *qpair, srb_t *sp)
 214{
 215        sp->qpair = NULL;
 216        sp->done = qla2xxx_rel_done_warning;
 217        sp->free = qla2xxx_rel_free_warning;
 218        mempool_free(sp, qpair->srb_mempool);
 219        QLA_QPAIR_MARK_NOT_BUSY(qpair);
 220}
 221
 222static inline srb_t *
 223qla2x00_get_sp(scsi_qla_host_t *vha, fc_port_t *fcport, gfp_t flag)
 224{
 225        srb_t *sp = NULL;
 226        uint8_t bail;
 227        struct qla_qpair *qpair;
 228
 229        QLA_VHA_MARK_BUSY(vha, bail);
 230        if (unlikely(bail))
 231                return NULL;
 232
 233        qpair = vha->hw->base_qpair;
 234        sp = qla2xxx_get_qpair_sp(vha, qpair, fcport, flag);
 235        if (!sp)
 236                goto done;
 237
 238        sp->vha = vha;
 239done:
 240        if (!sp)
 241                QLA_VHA_MARK_NOT_BUSY(vha);
 242        return sp;
 243}
 244
 245static inline void
 246qla2x00_rel_sp(srb_t *sp)
 247{
 248        QLA_VHA_MARK_NOT_BUSY(sp->vha);
 249        qla2xxx_rel_qpair_sp(sp->qpair, sp);
 250}
 251
 252static inline int
 253qla2x00_gid_list_size(struct qla_hw_data *ha)
 254{
 255        if (IS_QLAFX00(ha))
 256                return sizeof(uint32_t) * 32;
 257        else
 258                return sizeof(struct gid_list_info) * ha->max_fibre_devices;
 259}
 260
 261static inline void
 262qla2x00_handle_mbx_completion(struct qla_hw_data *ha, int status)
 263{
 264        if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
 265            (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
 266                set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
 267                clear_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags);
 268                complete(&ha->mbx_intr_comp);
 269        }
 270}
 271
 272static inline void
 273qla2x00_set_retry_delay_timestamp(fc_port_t *fcport, uint16_t sts_qual)
 274{
 275        u8 scope;
 276        u16 qual;
 277#define SQ_SCOPE_MASK           0xc000 /* SAM-6 rev5 5.3.2 */
 278#define SQ_SCOPE_SHIFT          14
 279#define SQ_QUAL_MASK            0x3fff
 280
 281#define SQ_MAX_WAIT_SEC         60 /* Max I/O hold off time in seconds. */
 282#define SQ_MAX_WAIT_TIME        (SQ_MAX_WAIT_SEC * 10) /* in 100ms. */
 283
 284        if (!sts_qual) /* Common case. */
 285                return;
 286
 287        scope = (sts_qual & SQ_SCOPE_MASK) >> SQ_SCOPE_SHIFT;
 288        /* Handle only scope 1 or 2, which is for I-T nexus. */
 289        if (scope != 1 && scope != 2)
 290                return;
 291
 292        /* Skip processing, if retry delay timer is already in effect. */
 293        if (fcport->retry_delay_timestamp &&
 294            time_before(jiffies, fcport->retry_delay_timestamp))
 295                return;
 296
 297        qual = sts_qual & SQ_QUAL_MASK;
 298        if (qual < 1 || qual > 0x3fef)
 299                return;
 300        qual = min(qual, (u16)SQ_MAX_WAIT_TIME);
 301
 302        /* qual is expressed in 100ms increments. */
 303        fcport->retry_delay_timestamp = jiffies + (qual * HZ / 10);
 304
 305        ql_log(ql_log_warn, fcport->vha, 0x5101,
 306               "%8phC: I/O throttling requested (status qualifier = %04xh), holding off I/Os for %ums.\n",
 307               fcport->port_name, sts_qual, qual * 100);
 308}
 309
 310static inline bool
 311qla_is_exch_offld_enabled(struct scsi_qla_host *vha)
 312{
 313        if (qla_ini_mode_enabled(vha) &&
 314            (vha->ql2xiniexchg > FW_DEF_EXCHANGES_CNT))
 315                return true;
 316        else if (qla_tgt_mode_enabled(vha) &&
 317            (vha->ql2xexchoffld > FW_DEF_EXCHANGES_CNT))
 318                return true;
 319        else if (qla_dual_mode_enabled(vha) &&
 320            ((vha->ql2xiniexchg + vha->ql2xexchoffld) > FW_DEF_EXCHANGES_CNT))
 321                return true;
 322        else
 323                return false;
 324}
 325
 326static inline void
 327qla_cpu_update(struct qla_qpair *qpair, uint16_t cpuid)
 328{
 329        qpair->cpuid = cpuid;
 330
 331        if (!list_empty(&qpair->hints_list)) {
 332                struct qla_qpair_hint *h;
 333
 334                list_for_each_entry(h, &qpair->hints_list, hint_elem)
 335                        h->cpuid = qpair->cpuid;
 336        }
 337}
 338
 339static inline struct qla_qpair_hint *
 340qla_qpair_to_hint(struct qla_tgt *tgt, struct qla_qpair *qpair)
 341{
 342        struct qla_qpair_hint *h;
 343        u16 i;
 344
 345        for (i = 0; i < tgt->ha->max_qpairs + 1; i++) {
 346                h = &tgt->qphints[i];
 347                if (h->qpair == qpair)
 348                        return h;
 349        }
 350
 351        return NULL;
 352}
 353
 354static inline void
 355qla_83xx_start_iocbs(struct qla_qpair *qpair)
 356{
 357        struct req_que *req = qpair->req;
 358
 359        req->ring_index++;
 360        if (req->ring_index == req->length) {
 361                req->ring_index = 0;
 362                req->ring_ptr = req->ring;
 363        } else
 364                req->ring_ptr++;
 365
 366        wrt_reg_dword(req->req_q_in, req->ring_index);
 367}
 368
 369static inline int
 370qla2xxx_get_fc4_priority(struct scsi_qla_host *vha)
 371{
 372        uint32_t data;
 373
 374        data =
 375            ((uint8_t *)vha->hw->nvram)[NVRAM_DUAL_FCP_NVME_FLAG_OFFSET];
 376
 377
 378        return (data >> 6) & BIT_0 ? FC4_PRIORITY_FCP : FC4_PRIORITY_NVME;
 379}
 380
 381enum {
 382        RESOURCE_NONE,
 383        RESOURCE_INI,
 384};
 385
 386static inline int
 387qla_get_iocbs(struct qla_qpair *qp, struct iocb_resource *iores)
 388{
 389        u16 iocbs_used, i;
 390        struct qla_hw_data *ha = qp->vha->hw;
 391
 392        if (!ql2xenforce_iocb_limit) {
 393                iores->res_type = RESOURCE_NONE;
 394                return 0;
 395        }
 396
 397        if ((iores->iocb_cnt + qp->fwres.iocbs_used) < qp->fwres.iocbs_qp_limit) {
 398                qp->fwres.iocbs_used += iores->iocb_cnt;
 399                return 0;
 400        } else {
 401                /* no need to acquire qpair lock. It's just rough calculation */
 402                iocbs_used = ha->base_qpair->fwres.iocbs_used;
 403                for (i = 0; i < ha->max_qpairs; i++) {
 404                        if (ha->queue_pair_map[i])
 405                                iocbs_used += ha->queue_pair_map[i]->fwres.iocbs_used;
 406                }
 407
 408                if ((iores->iocb_cnt + iocbs_used) < qp->fwres.iocbs_limit) {
 409                        qp->fwres.iocbs_used += iores->iocb_cnt;
 410                        return 0;
 411                } else {
 412                        iores->res_type = RESOURCE_NONE;
 413                        return -ENOSPC;
 414                }
 415        }
 416}
 417
 418static inline void
 419qla_put_iocbs(struct qla_qpair *qp, struct iocb_resource *iores)
 420{
 421        switch (iores->res_type) {
 422        case RESOURCE_NONE:
 423                break;
 424        default:
 425                if (qp->fwres.iocbs_used >= iores->iocb_cnt) {
 426                        qp->fwres.iocbs_used -= iores->iocb_cnt;
 427                } else {
 428                        // should not happen
 429                        qp->fwres.iocbs_used = 0;
 430                }
 431                break;
 432        }
 433        iores->res_type = RESOURCE_NONE;
 434}
 435
 436#define ISP_REG_DISCONNECT 0xffffffffU
 437/**************************************************************************
 438 * qla2x00_isp_reg_stat
 439 *
 440 * Description:
 441 *        Read the host status register of ISP before aborting the command.
 442 *
 443 * Input:
 444 *       ha = pointer to host adapter structure.
 445 *
 446 *
 447 * Returns:
 448 *       Either true or false.
 449 *
 450 * Note: Return true if there is register disconnect.
 451 **************************************************************************/
 452static inline
 453uint32_t qla2x00_isp_reg_stat(struct qla_hw_data *ha)
 454{
 455        struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
 456        struct device_reg_82xx __iomem *reg82 = &ha->iobase->isp82;
 457
 458        if (IS_P3P_TYPE(ha))
 459                return ((rd_reg_dword(&reg82->host_int)) == ISP_REG_DISCONNECT);
 460        else
 461                return ((rd_reg_dword(&reg->host_status)) ==
 462                        ISP_REG_DISCONNECT);
 463}
 464
 465static inline
 466bool qla_pci_disconnected(struct scsi_qla_host *vha,
 467                          struct device_reg_24xx __iomem *reg)
 468{
 469        uint32_t stat;
 470        bool ret = false;
 471
 472        stat = rd_reg_dword(&reg->host_status);
 473        if (stat == 0xffffffff) {
 474                ql_log(ql_log_info, vha, 0x8041,
 475                       "detected PCI disconnect.\n");
 476                qla_schedule_eeh_work(vha);
 477                ret = true;
 478        }
 479        return ret;
 480}
 481
 482static inline bool
 483fcport_is_smaller(fc_port_t *fcport)
 484{
 485        if (wwn_to_u64(fcport->port_name) <
 486                wwn_to_u64(fcport->vha->port_name))
 487                return true;
 488        else
 489                return false;
 490}
 491
 492static inline bool
 493fcport_is_bigger(fc_port_t *fcport)
 494{
 495        return !fcport_is_smaller(fcport);
 496}
 497