From: Krishna Gudipati <kgudi...@brocade.com>

Change details:
        - Add capability to limit the number of exchanges on a port to
          avoid queue-full conditions from the target side.

Signed-off-by: Sudarsana Reddy Kalluru <skall...@brocade.com>
Signed-off-by: Krishna Gudipati <kgudi...@brocade.com>
---
 drivers/scsi/bfa/bfa_core.c      |    9 +++-
 drivers/scsi/bfa/bfa_defs_svc.h  |   13 +++++
 drivers/scsi/bfa/bfa_fcpim.c     |  105 ++++++++++++++++++++++++++++++++++++--
 drivers/scsi/bfa/bfa_fcpim.h     |    9 +++-
 drivers/scsi/bfa/bfa_fcs_rport.c |    6 ++-
 drivers/scsi/bfa/bfa_ioc.h       |    3 +
 drivers/scsi/bfa/bfad_bsg.c      |   36 +++++++++++++
 drivers/scsi/bfa/bfad_bsg.h      |    9 +++
 8 files changed, 182 insertions(+), 8 deletions(-)

diff --git a/drivers/scsi/bfa/bfa_core.c b/drivers/scsi/bfa/bfa_core.c
index 837879d..eb29628 100644
--- a/drivers/scsi/bfa/bfa_core.c
+++ b/drivers/scsi/bfa/bfa_core.c
@@ -983,7 +983,8 @@ bfa_iocfc_send_cfg(void *bfa_arg)
                cfg_info->single_msix_vec = 1;
        cfg_info->endian_sig = BFI_IOC_ENDIAN_SIG;
        cfg_info->num_cqs = cfg->fwcfg.num_cqs;
-       cfg_info->num_ioim_reqs = cpu_to_be16(cfg->fwcfg.num_ioim_reqs);
+       cfg_info->num_ioim_reqs = cpu_to_be16(bfa_fcpim_get_throttle_cfg(bfa,
+                                              cfg->fwcfg.num_ioim_reqs));
        cfg_info->num_fwtio_reqs = cpu_to_be16(cfg->fwcfg.num_fwtio_reqs);
 
        bfa_dma_be_addr_set(cfg_info->cfgrsp_addr, iocfc->cfgrsp_dma.pa);
@@ -1245,10 +1246,14 @@ bfa_iocfc_qreg(struct bfa_s *bfa, struct 
bfi_iocfc_qreg_s *qreg)
 static void
 bfa_iocfc_res_recfg(struct bfa_s *bfa, struct bfa_iocfc_fwcfg_s *fwcfg)
 {
+       struct bfa_iocfc_s      *iocfc   = &bfa->iocfc;
+       struct bfi_iocfc_cfg_s  *cfg_info = iocfc->cfginfo;
+
        bfa_fcxp_res_recfg(bfa, fwcfg->num_fcxp_reqs);
        bfa_uf_res_recfg(bfa, fwcfg->num_uf_bufs);
        bfa_rport_res_recfg(bfa, fwcfg->num_rports);
-       bfa_fcp_res_recfg(bfa, fwcfg->num_ioim_reqs);
+       bfa_fcp_res_recfg(bfa, cpu_to_be16(cfg_info->num_ioim_reqs),
+                         fwcfg->num_ioim_reqs);
        bfa_tskim_res_recfg(bfa, fwcfg->num_tskim_reqs);
 }
 
diff --git a/drivers/scsi/bfa/bfa_defs_svc.h b/drivers/scsi/bfa/bfa_defs_svc.h
index 18e4f6b..0e37e23 100644
--- a/drivers/scsi/bfa/bfa_defs_svc.h
+++ b/drivers/scsi/bfa/bfa_defs_svc.h
@@ -875,6 +875,19 @@ struct bfa_lunmask_cfg_s {
        struct bfa_lun_mask_s   lun_list[MAX_LUN_MASK_CFG];
 };
 
+struct bfa_throttle_cfg_s {
+       u16     is_valid;
+       u16     value;
+       u32     rsvd;
+};
+
+struct bfa_defs_fcpim_throttle_s {
+       u16     max_value;
+       u16     cur_value;
+       u16     cfg_value;
+       u16     rsvd;
+};
+
 /*
  *      Physical port configuration
  */
diff --git a/drivers/scsi/bfa/bfa_fcpim.c b/drivers/scsi/bfa/bfa_fcpim.c
index 4118d84..27b5609 100644
--- a/drivers/scsi/bfa/bfa_fcpim.c
+++ b/drivers/scsi/bfa/bfa_fcpim.c
@@ -3703,6 +3703,7 @@ bfa_fcp_attach(struct bfa_s *bfa, void *bfad, struct 
bfa_iocfc_cfg_s *cfg,
        struct bfa_mem_dma_s *seg_ptr;
        u16     idx, nsegs, num_io_req;
 
+       fcp->max_ioim_reqs = cfg->fwcfg.num_ioim_reqs;
        fcp->num_ioim_reqs = cfg->fwcfg.num_ioim_reqs;
        fcp->num_fwtio_reqs  = cfg->fwcfg.num_fwtio_reqs;
        fcp->num_itns   = cfg->fwcfg.num_rports;
@@ -3725,6 +3726,7 @@ bfa_fcp_attach(struct bfa_s *bfa, void *bfad, struct 
bfa_iocfc_cfg_s *cfg,
                bfa_iocfc_set_snsbase(bfa, idx, fcp->snsbase[idx].pa);
        }
 
+       fcp->throttle_update_required = 1;
        bfa_fcpim_attach(fcp, bfad, cfg, pcidev);
 
        bfa_iotag_attach(fcp);
@@ -3763,23 +3765,33 @@ bfa_fcp_iocdisable(struct bfa_s *bfa)
 {
        struct bfa_fcp_mod_s *fcp = BFA_FCP_MOD(bfa);
 
-       /* Enqueue unused ioim resources to free_q */
-       list_splice_tail_init(&fcp->iotag_unused_q, &fcp->iotag_ioim_free_q);
-
        bfa_fcpim_iocdisable(fcp);
 }
 
 void
-bfa_fcp_res_recfg(struct bfa_s *bfa, u16 num_ioim_fw)
+bfa_fcp_res_recfg(struct bfa_s *bfa, u16 num_ioim_fw, u16 max_ioim_fw)
 {
        struct bfa_fcp_mod_s    *mod = BFA_FCP_MOD(bfa);
        struct list_head        *qe;
        int     i;
 
+       /* Update io throttle value only once during driver load time */
+       if (!mod->throttle_update_required)
+               return;
+
        for (i = 0; i < (mod->num_ioim_reqs - num_ioim_fw); i++) {
                bfa_q_deq_tail(&mod->iotag_ioim_free_q, &qe);
                list_add_tail(qe, &mod->iotag_unused_q);
        }
+
+       if (mod->num_ioim_reqs != num_ioim_fw) {
+               bfa_trc(bfa, mod->num_ioim_reqs);
+               bfa_trc(bfa, num_ioim_fw);
+       }
+
+       mod->max_ioim_reqs = max_ioim_fw;
+       mod->num_ioim_reqs = num_ioim_fw;
+       mod->throttle_update_required = 0;
 }
 
 void
@@ -3837,3 +3849,88 @@ bfa_iotag_attach(struct bfa_fcp_mod_s *fcp)
 
        bfa_mem_kva_curp(fcp) = (u8 *) iotag;
 }
+
+
+/**
+ * To send config req, first try to use throttle value from flash
+ * If 0, then use driver parameter
+ * We need to use min(flash_val, drv_val) because
+ * memory allocation was done based on this cfg'd value
+ */
+u16
+bfa_fcpim_get_throttle_cfg(struct bfa_s *bfa, u16 drv_cfg_param)
+{
+       u16 tmp;
+       struct bfa_fcp_mod_s *fcp = BFA_FCP_MOD(bfa);
+
+       /*
+        * If throttle value from flash is already in effect after driver is
+        * loaded then until next load, always return current value instead
+        * of actual flash value
+        */
+       if (!fcp->throttle_update_required)
+               return (u16)fcp->num_ioim_reqs;
+
+       tmp = bfa_dconf_read_data_valid(bfa) ? bfa_fcpim_read_throttle(bfa) : 0;
+       if (!tmp || (tmp > drv_cfg_param))
+               tmp = drv_cfg_param;
+
+       return tmp;
+}
+
+bfa_status_t
+bfa_fcpim_write_throttle(struct bfa_s *bfa, u16 value)
+{
+       if (!bfa_dconf_get_min_cfg(bfa)) {
+               BFA_DCONF_MOD(bfa)->dconf->throttle_cfg.value = value;
+               BFA_DCONF_MOD(bfa)->dconf->throttle_cfg.is_valid = 1;
+               return BFA_STATUS_OK;
+       }
+
+       return BFA_STATUS_FAILED;
+}
+
+u16
+bfa_fcpim_read_throttle(struct bfa_s *bfa)
+{
+       struct bfa_throttle_cfg_s *throttle_cfg =
+                       &(BFA_DCONF_MOD(bfa)->dconf->throttle_cfg);
+
+       return ((!bfa_dconf_get_min_cfg(bfa)) ?
+              ((throttle_cfg->is_valid == 1) ? (throttle_cfg->value) : 0) : 0);
+}
+
+bfa_status_t
+bfa_fcpim_throttle_set(struct bfa_s *bfa, u16 value)
+{
+       /* in min cfg no commands should run. */
+       if ((bfa_dconf_get_min_cfg(bfa) == BFA_TRUE) ||
+           (!bfa_dconf_read_data_valid(bfa)))
+               return BFA_STATUS_FAILED;
+
+       bfa_fcpim_write_throttle(bfa, value);
+
+       return bfa_dconf_update(bfa);
+}
+
+bfa_status_t
+bfa_fcpim_throttle_get(struct bfa_s *bfa, void *buf)
+{
+       struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
+       struct bfa_defs_fcpim_throttle_s throttle;
+
+       if ((bfa_dconf_get_min_cfg(bfa) == BFA_TRUE) ||
+           (!bfa_dconf_read_data_valid(bfa)))
+               return BFA_STATUS_FAILED;
+
+       memset(&throttle, 0, sizeof(struct bfa_defs_fcpim_throttle_s));
+
+       throttle.cur_value = (u16)(fcpim->fcp->num_ioim_reqs);
+       throttle.cfg_value = bfa_fcpim_read_throttle(bfa);
+       if (!throttle.cfg_value)
+               throttle.cfg_value = throttle.cur_value;
+       throttle.max_value = (u16)(fcpim->fcp->max_ioim_reqs);
+       memcpy(buf, &throttle, sizeof(struct bfa_defs_fcpim_throttle_s));
+
+       return BFA_STATUS_OK;
+}
diff --git a/drivers/scsi/bfa/bfa_fcpim.h b/drivers/scsi/bfa/bfa_fcpim.h
index b81d51c..e693af6 100644
--- a/drivers/scsi/bfa/bfa_fcpim.h
+++ b/drivers/scsi/bfa/bfa_fcpim.h
@@ -42,7 +42,7 @@ void bfa_itn_create(struct bfa_s *bfa, struct bfa_rport_s 
*rport,
                void (*isr)(struct bfa_s *bfa, struct bfi_msg_s *m));
 void bfa_itn_isr(struct bfa_s *bfa, struct bfi_msg_s *m);
 void bfa_iotag_attach(struct bfa_fcp_mod_s *fcp);
-void bfa_fcp_res_recfg(struct bfa_s *bfa, u16 num_ioim_fw);
+void bfa_fcp_res_recfg(struct bfa_s *bfa, u16 num_ioim_fw, u16 max_ioim_fw);
 
 #define BFA_FCP_MOD(_hal)      (&(_hal)->modules.fcp_mod)
 #define BFA_MEM_FCP_KVA(__bfa) (&(BFA_FCP_MOD(__bfa)->kva_seg))
@@ -150,6 +150,7 @@ struct bfa_fcp_mod_s {
        struct list_head        iotag_unused_q; /* unused IO resources*/
        struct bfa_iotag_s      *iotag_arr;
        struct bfa_itn_s        *itn_arr;
+       int                     max_ioim_reqs;
        int                     num_ioim_reqs;
        int                     num_fwtio_reqs;
        int                     num_itns;
@@ -157,6 +158,7 @@ struct bfa_fcp_mod_s {
        struct bfa_fcpim_s      fcpim;
        struct bfa_mem_dma_s    dma_seg[BFA_FCP_DMA_SEGS];
        struct bfa_mem_kva_s    kva_seg;
+       int                     throttle_update_required;
 };
 
 /*
@@ -418,5 +420,10 @@ bfa_status_t       bfa_fcpim_lunmask_delete(struct bfa_s 
*bfa, u16 vf_id,
 bfa_status_t   bfa_fcpim_lunmask_add(struct bfa_s *bfa, u16 vf_id,
                                wwn_t *pwwn, wwn_t rpwwn, struct scsi_lun lun);
 bfa_status_t   bfa_fcpim_lunmask_clear(struct bfa_s *bfa);
+u16            bfa_fcpim_read_throttle(struct bfa_s *bfa);
+bfa_status_t   bfa_fcpim_write_throttle(struct bfa_s *bfa, u16 value);
+bfa_status_t   bfa_fcpim_throttle_set(struct bfa_s *bfa, u16 value);
+bfa_status_t   bfa_fcpim_throttle_get(struct bfa_s *bfa, void *buf);
+u16     bfa_fcpim_get_throttle_cfg(struct bfa_s *bfa, u16 drv_cfg_param);
 
 #endif /* __BFA_FCPIM_H__ */
diff --git a/drivers/scsi/bfa/bfa_fcs_rport.c b/drivers/scsi/bfa/bfa_fcs_rport.c
index e90800d..58ac643 100644
--- a/drivers/scsi/bfa/bfa_fcs_rport.c
+++ b/drivers/scsi/bfa/bfa_fcs_rport.c
@@ -3026,6 +3026,9 @@ bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport,
        struct bfa_rport_qos_attr_s qos_attr;
        struct bfa_fcs_lport_s *port = rport->port;
        bfa_port_speed_t rport_speed = rport->rpf.rpsc_speed;
+       struct bfa_port_attr_s port_attr;
+
+       bfa_fcport_get_attr(rport->fcs->bfa, &port_attr);
 
        memset(rport_attr, 0, sizeof(struct bfa_rport_attr_s));
        memset(&qos_attr, 0, sizeof(struct bfa_rport_qos_attr_s));
@@ -3056,7 +3059,8 @@ bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport,
                        rport_speed =
                                bfa_fcport_get_ratelim_speed(rport->fcs->bfa);
 
-               if (rport_speed < bfa_fcs_lport_get_rport_max_speed(port))
+               if ((bfa_fcs_lport_get_rport_max_speed(port) !=
+                   BFA_PORT_SPEED_UNKNOWN) && (rport_speed < port_attr.speed))
                        rport_attr->trl_enforced = BFA_TRUE;
        }
 }
diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h
index 47038da..6d772b4 100644
--- a/drivers/scsi/bfa/bfa_ioc.h
+++ b/drivers/scsi/bfa/bfa_ioc.h
@@ -716,6 +716,7 @@ struct bfa_dconf_hdr_s {
 struct bfa_dconf_s {
        struct bfa_dconf_hdr_s          hdr;
        struct bfa_lunmask_cfg_s        lun_mask;
+       struct bfa_throttle_cfg_s       throttle_cfg;
 };
 #pragma pack()
 
@@ -738,6 +739,8 @@ struct bfa_dconf_mod_s {
 #define bfa_dconf_read_data_valid(__bfa)       \
        (BFA_DCONF_MOD(__bfa)->read_data_valid)
 #define BFA_DCONF_UPDATE_TOV   5000    /* memtest timeout in msec */
+#define bfa_dconf_get_min_cfg(__bfa)   \
+       (BFA_DCONF_MOD(__bfa)->min_cfg)
 
 void   bfa_dconf_modinit(struct bfa_s *bfa);
 void   bfa_dconf_modexit(struct bfa_s *bfa);
diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c
index 90c40e4..6e1478a 100644
--- a/drivers/scsi/bfa/bfad_bsg.c
+++ b/drivers/scsi/bfa/bfad_bsg.c
@@ -2547,6 +2547,36 @@ bfad_iocmd_fcpim_cfg_lunmask(struct bfad_s *bfad, void 
*cmd, unsigned int v_cmd)
        return 0;
 }
 
+int
+bfad_iocmd_fcpim_throttle_query(struct bfad_s *bfad, void *cmd)
+{
+       struct bfa_bsg_fcpim_throttle_s *iocmd =
+                       (struct bfa_bsg_fcpim_throttle_s *)cmd;
+       unsigned long   flags;
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       iocmd->status = bfa_fcpim_throttle_get(&bfad->bfa,
+                               (void *)&iocmd->throttle);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+       return 0;
+}
+
+int
+bfad_iocmd_fcpim_throttle_set(struct bfad_s *bfad, void *cmd)
+{
+       struct bfa_bsg_fcpim_throttle_s *iocmd =
+                       (struct bfa_bsg_fcpim_throttle_s *)cmd;
+       unsigned long   flags;
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       iocmd->status = bfa_fcpim_throttle_set(&bfad->bfa,
+                               iocmd->throttle.cfg_value);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+       return 0;
+}
+
 static int
 bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd,
                unsigned int payload_len)
@@ -2881,6 +2911,12 @@ bfad_iocmd_handler(struct bfad_s *bfad, unsigned int 
cmd, void *iocmd,
        case IOCMD_FCPIM_LUNMASK_DELETE:
                rc = bfad_iocmd_fcpim_cfg_lunmask(bfad, iocmd, cmd);
                break;
+       case IOCMD_FCPIM_THROTTLE_QUERY:
+               rc = bfad_iocmd_fcpim_throttle_query(bfad, iocmd);
+               break;
+       case IOCMD_FCPIM_THROTTLE_SET:
+               rc = bfad_iocmd_fcpim_throttle_set(bfad, iocmd);
+               break;
        default:
                rc = -EINVAL;
                break;
diff --git a/drivers/scsi/bfa/bfad_bsg.h b/drivers/scsi/bfa/bfad_bsg.h
index b67a229..37922b9 100644
--- a/drivers/scsi/bfa/bfad_bsg.h
+++ b/drivers/scsi/bfa/bfad_bsg.h
@@ -145,6 +145,8 @@ enum {
        IOCMD_DIAG_DPORT_DISABLE,
        IOCMD_DIAG_DPORT_GET_STATE,
        IOCMD_QOS_SET_BW,
+       IOCMD_FCPIM_THROTTLE_QUERY,
+       IOCMD_FCPIM_THROTTLE_SET
 };
 
 struct bfa_bsg_gen_s {
@@ -740,6 +742,13 @@ struct bfa_bsg_fcpim_lunmask_s {
        struct scsi_lun lun;
 };
 
+struct bfa_bsg_fcpim_throttle_s {
+       bfa_status_t    status;
+       u16             bfad_num;
+       u16             vf_id;
+       struct bfa_defs_fcpim_throttle_s throttle;
+};
+
 struct bfa_bsg_fcpt_s {
        bfa_status_t    status;
        u16             vf_id;
-- 
1.7.3.rc1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to