scsi: qla2xxx: Update BPM enablement semantics.
commit e4e3a2ce95
("scsi: qla2xxx: Add ability to autodetect SFP
type") takes a heavy handed approach to BPM (Buffer Plus Management)
enablement:
1) During hardware initialization, if an LR-capable transceiver is
recognized, the driver schedules a disruptive post-initialization
chip-reset (ISP-ABORT) to allow the BPM settings to be sent to the
firmware. This chip-reset will result in (short-term) path-loss to
all fc-rports and their attached SCSI devices.
2) LR-detection is triggered during any link-up event, resulting in a
refresh and potential chip-reset
Based on firmware-team guidance, upon LR-capable transceiver
recognition, the driver's hardware initialization code will now
re-execute firmware with the new BPM settings, then continue on with
driver initialization. To address the second issue, the driver
performs LR-capable detection upon the driver receiving a
transceiver-insertion asynchronous event from firmware. No short-term
path loss is needed with this new semantic.
Link: https://lore.kernel.org/r/20200226224022.24518-10-hmadhani@marvell.com
Signed-off-by: Himanshu Madhani <hmadhani@marvell.com>
Signed-off-by: Andrew Vasquez <andrewv@marvell.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
ce1ee122e0
commit
b0f18eee6f
@ -1049,6 +1049,7 @@ static inline bool qla2xxx_is_valid_mbs(unsigned int mbs)
|
||||
#define MBA_TEMPERATURE_ALERT 0x8070 /* Temperature Alert */
|
||||
#define MBA_DPORT_DIAGNOSTICS 0x8080 /* D-port Diagnostics */
|
||||
#define MBA_TRANS_INSERT 0x8130 /* Transceiver Insertion */
|
||||
#define MBA_TRANS_REMOVE 0x8131 /* Transceiver Removal */
|
||||
#define MBA_FW_INIT_FAILURE 0x8401 /* Firmware initialization failure */
|
||||
#define MBA_MIRROR_LUN_CHANGE 0x8402 /* Mirror LUN State Change
|
||||
Notification */
|
||||
@ -3802,8 +3803,8 @@ struct qla_hw_data {
|
||||
uint32_t fw_started:1;
|
||||
uint32_t fw_init_done:1;
|
||||
|
||||
uint32_t detected_lr_sfp:1;
|
||||
uint32_t using_lr_setting:1;
|
||||
uint32_t lr_detected:1;
|
||||
|
||||
uint32_t rida_fmt2:1;
|
||||
uint32_t purge_mbox:1;
|
||||
uint32_t n2n_bigger:1;
|
||||
@ -3812,7 +3813,7 @@ struct qla_hw_data {
|
||||
} flags;
|
||||
|
||||
uint16_t max_exchg;
|
||||
uint16_t long_range_distance; /* 32G & above */
|
||||
uint16_t lr_distance; /* 32G & above */
|
||||
#define LR_DISTANCE_5K 1
|
||||
#define LR_DISTANCE_10K 0
|
||||
|
||||
@ -4971,11 +4972,14 @@ struct sff_8247_a0 {
|
||||
u8 resv2[128];
|
||||
};
|
||||
|
||||
#define AUTO_DETECT_SFP_SUPPORT(_vha)\
|
||||
(ql2xautodetectsfp && !_vha->vp_idx && \
|
||||
(IS_QLA25XX(_vha->hw) || IS_QLA81XX(_vha->hw) ||\
|
||||
IS_QLA83XX(_vha->hw) || IS_QLA27XX(_vha->hw) || \
|
||||
IS_QLA28XX(_vha->hw)))
|
||||
/* BPM -- Buffer Plus Management support. */
|
||||
#define IS_BPM_CAPABLE(ha) \
|
||||
(IS_QLA25XX(ha) || IS_QLA81XX(ha) || IS_QLA83XX(ha) || \
|
||||
IS_QLA27XX(ha) || IS_QLA28XX(ha))
|
||||
#define IS_BPM_RANGE_CAPABLE(ha) \
|
||||
(IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))
|
||||
#define IS_BPM_ENABLED(vha) \
|
||||
(ql2xautodetectsfp && !vha->vp_idx && IS_BPM_CAPABLE(vha->hw))
|
||||
|
||||
#define FLASH_SEMAPHORE_REGISTER_ADDR 0x00101016
|
||||
|
||||
|
@ -1867,9 +1867,8 @@ struct access_chip_rsp_84xx {
|
||||
|
||||
/* LR Distance bit positions */
|
||||
#define LR_DIST_NV_POS 2
|
||||
#define LR_DIST_NV_MASK 0xf
|
||||
#define LR_DIST_FW_POS 12
|
||||
#define LR_DIST_FW_SHIFT (LR_DIST_FW_POS - LR_DIST_NV_POS)
|
||||
#define LR_DIST_FW_FIELD(x) ((x) << LR_DIST_FW_SHIFT & 0xf000)
|
||||
|
||||
/* FAC semaphore defines */
|
||||
#define FAC_SEMAPHORE_UNLOCK 0
|
||||
|
@ -109,7 +109,7 @@ int qla24xx_async_notify_ack(scsi_qla_host_t *, fc_port_t *,
|
||||
int qla24xx_post_newsess_work(struct scsi_qla_host *, port_id_t *, u8 *, u8*,
|
||||
void *, u8);
|
||||
int qla24xx_fcport_handle_login(struct scsi_qla_host *, fc_port_t *);
|
||||
int qla24xx_detect_sfp(scsi_qla_host_t *vha);
|
||||
int qla24xx_detect_sfp(scsi_qla_host_t *);
|
||||
int qla24xx_post_gpdb_work(struct scsi_qla_host *, fc_port_t *, u8);
|
||||
|
||||
extern void qla28xx_get_aux_images(struct scsi_qla_host *,
|
||||
|
@ -3550,53 +3550,77 @@ static void qla2xxx_print_sfp_info(struct scsi_qla_host *vha)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return Code:
|
||||
* QLA_SUCCESS: no action
|
||||
* QLA_INTERFACE_ERROR: SFP is not there.
|
||||
* QLA_FUNCTION_FAILED: detected New SFP
|
||||
/**
|
||||
* qla24xx_detect_sfp()
|
||||
*
|
||||
* @vha: adapter state pointer.
|
||||
*
|
||||
* @return
|
||||
* 0 -- Configure firmware to use short-range settings -- normal
|
||||
* buffer-to-buffer credits.
|
||||
*
|
||||
* 1 -- Configure firmware to use long-range settings -- extra
|
||||
* buffer-to-buffer credits should be allocated with
|
||||
* ha->lr_distance containing distance settings from NVRAM or SFP
|
||||
* (if supported).
|
||||
*/
|
||||
int
|
||||
qla24xx_detect_sfp(scsi_qla_host_t *vha)
|
||||
{
|
||||
int rc = QLA_SUCCESS;
|
||||
int rc, used_nvram;
|
||||
struct sff_8247_a0 *a;
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
struct nvram_81xx *nv = ha->nvram;
|
||||
#define LR_DISTANCE_UNKNOWN 2
|
||||
static const char * const types[] = { "Short", "Long" };
|
||||
static const char * const lengths[] = { "(10km)", "(5km)", "" };
|
||||
u8 ll = 0;
|
||||
|
||||
if (!AUTO_DETECT_SFP_SUPPORT(vha))
|
||||
/* Seed with NVRAM settings. */
|
||||
used_nvram = 0;
|
||||
ha->flags.lr_detected = 0;
|
||||
if (IS_BPM_RANGE_CAPABLE(ha) &&
|
||||
(nv->enhanced_features & NEF_LR_DIST_ENABLE)) {
|
||||
used_nvram = 1;
|
||||
ha->flags.lr_detected = 1;
|
||||
ha->lr_distance =
|
||||
(nv->enhanced_features >> LR_DIST_NV_POS)
|
||||
& LR_DIST_NV_MASK;
|
||||
}
|
||||
|
||||
if (!IS_BPM_ENABLED(vha))
|
||||
goto out;
|
||||
|
||||
/* Determine SR/LR capabilities of SFP/Transceiver. */
|
||||
rc = qla2x00_read_sfp_dev(vha, NULL, 0);
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
used_nvram = 0;
|
||||
a = (struct sff_8247_a0 *)vha->hw->sfp_data;
|
||||
qla2xxx_print_sfp_info(vha);
|
||||
|
||||
if (a->fc_ll_cc7 & FC_LL_VL || a->fc_ll_cc7 & FC_LL_L) {
|
||||
/* long range */
|
||||
ha->flags.detected_lr_sfp = 1;
|
||||
ha->flags.lr_detected = 0;
|
||||
ll = a->fc_ll_cc7;
|
||||
if (ll & FC_LL_VL || ll & FC_LL_L) {
|
||||
/* Long range, track length. */
|
||||
ha->flags.lr_detected = 1;
|
||||
|
||||
if (a->length_km > 5 || a->length_100m > 50)
|
||||
ha->long_range_distance = LR_DISTANCE_10K;
|
||||
ha->lr_distance = LR_DISTANCE_10K;
|
||||
else
|
||||
ha->long_range_distance = LR_DISTANCE_5K;
|
||||
|
||||
if (ha->flags.detected_lr_sfp != ha->flags.using_lr_setting)
|
||||
ql_dbg(ql_dbg_async, vha, 0x507b,
|
||||
"Detected Long Range SFP.\n");
|
||||
} else {
|
||||
/* short range */
|
||||
ha->flags.detected_lr_sfp = 0;
|
||||
if (ha->flags.using_lr_setting)
|
||||
ql_dbg(ql_dbg_async, vha, 0x5084,
|
||||
"Detected Short Range SFP.\n");
|
||||
ha->lr_distance = LR_DISTANCE_5K;
|
||||
}
|
||||
|
||||
if (!vha->flags.init_done)
|
||||
rc = QLA_SUCCESS;
|
||||
out:
|
||||
return rc;
|
||||
ql_dbg(ql_dbg_async, vha, 0x507b,
|
||||
"SFP detect: %s-Range SFP %s (nvr=%x ll=%x lr=%x lrd=%x).\n",
|
||||
types[ha->flags.lr_detected],
|
||||
ha->flags.lr_detected ? lengths[ha->lr_distance] :
|
||||
lengths[LR_DISTANCE_UNKNOWN],
|
||||
used_nvram, ll, ha->flags.lr_detected, ha->lr_distance);
|
||||
return ha->flags.lr_detected;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -3614,6 +3638,7 @@ qla2x00_setup_chip(scsi_qla_host_t *vha)
|
||||
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
|
||||
unsigned long flags;
|
||||
uint16_t fw_major_version;
|
||||
int done_once = 0;
|
||||
|
||||
if (IS_P3P_TYPE(ha)) {
|
||||
rval = ha->isp_ops->load_risc(vha, &srisc_address);
|
||||
@ -3634,6 +3659,7 @@ qla2x00_setup_chip(scsi_qla_host_t *vha)
|
||||
|
||||
qla81xx_mpi_sync(vha);
|
||||
|
||||
execute_fw_with_lr:
|
||||
/* Load firmware sequences */
|
||||
rval = ha->isp_ops->load_risc(vha, &srisc_address);
|
||||
if (rval == QLA_SUCCESS) {
|
||||
@ -3655,7 +3681,15 @@ qla2x00_setup_chip(scsi_qla_host_t *vha)
|
||||
rval = qla2x00_execute_fw(vha, srisc_address);
|
||||
/* Retrieve firmware information. */
|
||||
if (rval == QLA_SUCCESS) {
|
||||
qla24xx_detect_sfp(vha);
|
||||
/* Enable BPM support? */
|
||||
if (!done_once++ && qla24xx_detect_sfp(vha)) {
|
||||
ql_dbg(ql_dbg_init, vha, 0x00ca,
|
||||
"Re-starting firmware -- BPM.\n");
|
||||
/* Best-effort - re-init. */
|
||||
ha->isp_ops->reset_chip(vha);
|
||||
ha->isp_ops->chip_diag(vha);
|
||||
goto execute_fw_with_lr;
|
||||
}
|
||||
|
||||
if ((IS_QLA83XX(ha) || IS_QLA27XX(ha) ||
|
||||
IS_QLA28XX(ha)) &&
|
||||
@ -3932,6 +3966,10 @@ qla24xx_update_fw_options(scsi_qla_host_t *vha)
|
||||
if (ql2xrdpenable)
|
||||
ha->fw_options[1] |= ADD_FO1_ENABLE_PUREX_IOCB;
|
||||
|
||||
/* Enable Async 8130/8131 events -- transceiver insertion/removal */
|
||||
if (IS_BPM_RANGE_CAPABLE(ha))
|
||||
ha->fw_options[3] |= BIT_10;
|
||||
|
||||
ql_dbg(ql_dbg_init, vha, 0x00e8,
|
||||
"%s, add FW options 1-3 = 0x%04x 0x%04x 0x%04x mode %x\n",
|
||||
__func__, ha->fw_options[1], ha->fw_options[2],
|
||||
|
@ -960,10 +960,6 @@ skip_rio:
|
||||
vha->flags.management_server_logged_in = 0;
|
||||
qla2x00_post_aen_work(vha, FCH_EVT_LINKUP, ha->link_data_rate);
|
||||
|
||||
if (AUTO_DETECT_SFP_SUPPORT(vha)) {
|
||||
set_bit(DETECT_SFP_CHANGE, &vha->dpc_flags);
|
||||
qla2xxx_wake_dpc(vha);
|
||||
}
|
||||
break;
|
||||
|
||||
case MBA_LOOP_DOWN: /* Loop Down Event */
|
||||
@ -1436,6 +1432,11 @@ global_port_update:
|
||||
case MBA_TRANS_INSERT:
|
||||
ql_dbg(ql_dbg_async, vha, 0x5091,
|
||||
"Transceiver Insertion: %04x\n", mb[1]);
|
||||
set_bit(DETECT_SFP_CHANGE, &vha->dpc_flags);
|
||||
break;
|
||||
|
||||
case MBA_TRANS_REMOVE:
|
||||
ql_dbg(ql_dbg_async, vha, 0x5091, "Transceiver Removal\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -643,28 +643,6 @@ qla2x00_load_ram(scsi_qla_host_t *vha, dma_addr_t req_dma, uint32_t risc_addr,
|
||||
}
|
||||
|
||||
#define NVME_ENABLE_FLAG BIT_3
|
||||
static inline uint16_t qla25xx_set_sfp_lr_dist(struct qla_hw_data *ha)
|
||||
{
|
||||
uint16_t mb4 = BIT_0;
|
||||
|
||||
if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))
|
||||
mb4 |= ha->long_range_distance << LR_DIST_FW_POS;
|
||||
|
||||
return mb4;
|
||||
}
|
||||
|
||||
static inline uint16_t qla25xx_set_nvr_lr_dist(struct qla_hw_data *ha)
|
||||
{
|
||||
uint16_t mb4 = BIT_0;
|
||||
|
||||
if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
|
||||
struct nvram_81xx *nv = ha->nvram;
|
||||
|
||||
mb4 |= LR_DIST_FW_FIELD(nv->enhanced_features);
|
||||
}
|
||||
|
||||
return mb4;
|
||||
}
|
||||
|
||||
/*
|
||||
* qla2x00_execute_fw
|
||||
@ -701,25 +679,13 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr)
|
||||
mcp->mb[3] = 0;
|
||||
mcp->mb[4] = 0;
|
||||
mcp->mb[11] = 0;
|
||||
ha->flags.using_lr_setting = 0;
|
||||
if (IS_QLA25XX(ha) || IS_QLA81XX(ha) || IS_QLA83XX(ha) ||
|
||||
IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
|
||||
if (ql2xautodetectsfp) {
|
||||
if (ha->flags.detected_lr_sfp) {
|
||||
mcp->mb[4] |=
|
||||
qla25xx_set_sfp_lr_dist(ha);
|
||||
ha->flags.using_lr_setting = 1;
|
||||
}
|
||||
} else {
|
||||
struct nvram_81xx *nv = ha->nvram;
|
||||
/* set LR distance if specified in nvram */
|
||||
if (nv->enhanced_features &
|
||||
NEF_LR_DIST_ENABLE) {
|
||||
mcp->mb[4] |=
|
||||
qla25xx_set_nvr_lr_dist(ha);
|
||||
ha->flags.using_lr_setting = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Enable BPM? */
|
||||
if (ha->flags.lr_detected) {
|
||||
mcp->mb[4] = BIT_0;
|
||||
if (IS_BPM_RANGE_CAPABLE(ha))
|
||||
mcp->mb[4] |=
|
||||
ha->lr_distance << LR_DIST_FW_POS;
|
||||
}
|
||||
|
||||
if (ql2xnvmeenable && (IS_QLA27XX(ha) || IS_QLA28XX(ha)))
|
||||
|
@ -3462,13 +3462,6 @@ skip_dpc:
|
||||
if (test_bit(UNLOADING, &base_vha->dpc_flags))
|
||||
return -ENODEV;
|
||||
|
||||
if (ha->flags.detected_lr_sfp) {
|
||||
ql_log(ql_log_info, base_vha, 0xffff,
|
||||
"Reset chip to pick up LR SFP setting\n");
|
||||
set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags);
|
||||
qla2xxx_wake_dpc(base_vha);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
probe_failed:
|
||||
@ -6881,13 +6874,14 @@ qla2x00_do_dpc(void *data)
|
||||
}
|
||||
|
||||
if (test_and_clear_bit(DETECT_SFP_CHANGE,
|
||||
&base_vha->dpc_flags) &&
|
||||
!test_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags)) {
|
||||
qla24xx_detect_sfp(base_vha);
|
||||
|
||||
if (ha->flags.detected_lr_sfp !=
|
||||
ha->flags.using_lr_setting)
|
||||
set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags);
|
||||
&base_vha->dpc_flags)) {
|
||||
/* Semantic:
|
||||
* - NO-OP -- await next ISP-ABORT. Preferred method
|
||||
* to minimize disruptions that will occur
|
||||
* when a forced chip-reset occurs.
|
||||
* - Force -- ISP-ABORT scheduled.
|
||||
*/
|
||||
/* set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags); */
|
||||
}
|
||||
|
||||
if (test_and_clear_bit
|
||||
|
Loading…
Reference in New Issue
Block a user