Commit 7ace27ae authored by Krishna Gudipati's avatar Krishna Gudipati Committed by James Bottomley
Browse files

[SCSI] bfa: Add support for IO throttling at port level



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

Signed-off-by: default avatarSudarsana Reddy Kalluru <skalluru@brocade.com>
Signed-off-by: default avatarKrishna Gudipati <kgudipat@brocade.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 6894f013
Loading
Loading
Loading
Loading
+7 −2
Original line number Diff line number Diff line
@@ -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);
}

+13 −0
Original line number Diff line number Diff line
@@ -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
 */
+101 −4
Original line number Diff line number Diff line
@@ -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;
}
+8 −1
Original line number Diff line number Diff line
@@ -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__ */
+5 −1
Original line number Diff line number Diff line
@@ -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;
	}
}
Loading