|
@@ -3886,6 +3886,49 @@ lpfc_rscn_recovery_check(struct lpfc_vport *vport)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * lpfc_send_rscn_event: Send an RSCN event to management application.
|
|
|
|
+ * @vport: pointer to a host virtual N_Port data structure.
|
|
|
|
+ * @cmdiocb: pointer to lpfc command iocb data structure.
|
|
|
|
+ *
|
|
|
|
+ * lpfc_send_rscn_event sends an RSCN netlink event to management
|
|
|
|
+ * applications.
|
|
|
|
+ */
|
|
|
|
+static void
|
|
|
|
+lpfc_send_rscn_event(struct lpfc_vport *vport,
|
|
|
|
+ struct lpfc_iocbq *cmdiocb)
|
|
|
|
+{
|
|
|
|
+ struct lpfc_dmabuf *pcmd;
|
|
|
|
+ struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
|
|
|
|
+ uint32_t *payload_ptr;
|
|
|
|
+ uint32_t payload_len;
|
|
|
|
+ struct lpfc_rscn_event_header *rscn_event_data;
|
|
|
|
+
|
|
|
|
+ pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
|
|
|
|
+ payload_ptr = (uint32_t *) pcmd->virt;
|
|
|
|
+ payload_len = be32_to_cpu(*payload_ptr & ~ELS_CMD_MASK);
|
|
|
|
+
|
|
|
|
+ rscn_event_data = kmalloc(sizeof(struct lpfc_rscn_event_header) +
|
|
|
|
+ payload_len, GFP_KERNEL);
|
|
|
|
+ if (!rscn_event_data) {
|
|
|
|
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
|
|
|
|
+ "0147 Failed to allocate memory for RSCN event\n");
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ rscn_event_data->event_type = FC_REG_RSCN_EVENT;
|
|
|
|
+ rscn_event_data->payload_length = payload_len;
|
|
|
|
+ memcpy(rscn_event_data->rscn_payload, payload_ptr,
|
|
|
|
+ payload_len);
|
|
|
|
+
|
|
|
|
+ fc_host_post_vendor_event(shost,
|
|
|
|
+ fc_get_event_number(),
|
|
|
|
+ sizeof(struct lpfc_els_event_header) + payload_len,
|
|
|
|
+ (char *)rscn_event_data,
|
|
|
|
+ LPFC_NL_VENDOR_ID);
|
|
|
|
+
|
|
|
|
+ kfree(rscn_event_data);
|
|
|
|
+}
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* lpfc_els_rcv_rscn: Process an unsolicited rscn iocb.
|
|
* lpfc_els_rcv_rscn: Process an unsolicited rscn iocb.
|
|
* @vport: pointer to a host virtual N_Port data structure.
|
|
* @vport: pointer to a host virtual N_Port data structure.
|
|
@@ -3933,6 +3976,10 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
|
|
"0214 RSCN received Data: x%x x%x x%x x%x\n",
|
|
"0214 RSCN received Data: x%x x%x x%x x%x\n",
|
|
vport->fc_flag, payload_len, *lp,
|
|
vport->fc_flag, payload_len, *lp,
|
|
vport->fc_rscn_id_cnt);
|
|
vport->fc_rscn_id_cnt);
|
|
|
|
+
|
|
|
|
+ /* Send an RSCN event to the management application */
|
|
|
|
+ lpfc_send_rscn_event(vport, cmdiocb);
|
|
|
|
+
|
|
for (i = 0; i < payload_len/sizeof(uint32_t); i++)
|
|
for (i = 0; i < payload_len/sizeof(uint32_t); i++)
|
|
fc_host_post_event(shost, fc_get_event_number(),
|
|
fc_host_post_event(shost, fc_get_event_number(),
|
|
FCH_EVT_RSCN, lp[i]);
|
|
FCH_EVT_RSCN, lp[i]);
|
|
@@ -5128,7 +5175,7 @@ lpfc_send_els_failure_event(struct lpfc_hba *phba,
|
|
fc_get_event_number(),
|
|
fc_get_event_number(),
|
|
sizeof(lsrjt_event),
|
|
sizeof(lsrjt_event),
|
|
(char *)&lsrjt_event,
|
|
(char *)&lsrjt_event,
|
|
- SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX);
|
|
|
|
|
|
+ LPFC_NL_VENDOR_ID);
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
if ((rspiocbp->iocb.ulpStatus == IOSTAT_NPORT_BSY) ||
|
|
if ((rspiocbp->iocb.ulpStatus == IOSTAT_NPORT_BSY) ||
|
|
@@ -5146,7 +5193,7 @@ lpfc_send_els_failure_event(struct lpfc_hba *phba,
|
|
fc_get_event_number(),
|
|
fc_get_event_number(),
|
|
sizeof(fabric_event),
|
|
sizeof(fabric_event),
|
|
(char *)&fabric_event,
|
|
(char *)&fabric_event,
|
|
- SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX);
|
|
|
|
|
|
+ LPFC_NL_VENDOR_ID);
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -5164,32 +5211,68 @@ lpfc_send_els_failure_event(struct lpfc_hba *phba,
|
|
static void
|
|
static void
|
|
lpfc_send_els_event(struct lpfc_vport *vport,
|
|
lpfc_send_els_event(struct lpfc_vport *vport,
|
|
struct lpfc_nodelist *ndlp,
|
|
struct lpfc_nodelist *ndlp,
|
|
- uint32_t cmd)
|
|
|
|
|
|
+ uint32_t *payload)
|
|
{
|
|
{
|
|
- struct lpfc_els_event_header els_data;
|
|
|
|
|
|
+ struct lpfc_els_event_header *els_data = NULL;
|
|
|
|
+ struct lpfc_logo_event *logo_data = NULL;
|
|
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
|
|
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
|
|
|
|
|
|
- els_data.event_type = FC_REG_ELS_EVENT;
|
|
|
|
- switch (cmd) {
|
|
|
|
|
|
+ if (*payload == ELS_CMD_LOGO) {
|
|
|
|
+ logo_data = kmalloc(sizeof(struct lpfc_logo_event), GFP_KERNEL);
|
|
|
|
+ if (!logo_data) {
|
|
|
|
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
|
|
|
|
+ "0148 Failed to allocate memory "
|
|
|
|
+ "for LOGO event\n");
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ els_data = &logo_data->header;
|
|
|
|
+ } else {
|
|
|
|
+ els_data = kmalloc(sizeof(struct lpfc_els_event_header),
|
|
|
|
+ GFP_KERNEL);
|
|
|
|
+ if (!els_data) {
|
|
|
|
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
|
|
|
|
+ "0149 Failed to allocate memory "
|
|
|
|
+ "for ELS event\n");
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ els_data->event_type = FC_REG_ELS_EVENT;
|
|
|
|
+ switch (*payload) {
|
|
case ELS_CMD_PLOGI:
|
|
case ELS_CMD_PLOGI:
|
|
- els_data.subcategory = LPFC_EVENT_PLOGI_RCV;
|
|
|
|
|
|
+ els_data->subcategory = LPFC_EVENT_PLOGI_RCV;
|
|
break;
|
|
break;
|
|
case ELS_CMD_PRLO:
|
|
case ELS_CMD_PRLO:
|
|
- els_data.subcategory = LPFC_EVENT_PRLO_RCV;
|
|
|
|
|
|
+ els_data->subcategory = LPFC_EVENT_PRLO_RCV;
|
|
break;
|
|
break;
|
|
case ELS_CMD_ADISC:
|
|
case ELS_CMD_ADISC:
|
|
- els_data.subcategory = LPFC_EVENT_ADISC_RCV;
|
|
|
|
|
|
+ els_data->subcategory = LPFC_EVENT_ADISC_RCV;
|
|
|
|
+ break;
|
|
|
|
+ case ELS_CMD_LOGO:
|
|
|
|
+ els_data->subcategory = LPFC_EVENT_LOGO_RCV;
|
|
|
|
+ /* Copy the WWPN in the LOGO payload */
|
|
|
|
+ memcpy(logo_data->logo_wwpn, &payload[2],
|
|
|
|
+ sizeof(struct lpfc_name));
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
- memcpy(els_data.wwpn, &ndlp->nlp_portname, sizeof(struct lpfc_name));
|
|
|
|
- memcpy(els_data.wwnn, &ndlp->nlp_nodename, sizeof(struct lpfc_name));
|
|
|
|
- fc_host_post_vendor_event(shost,
|
|
|
|
- fc_get_event_number(),
|
|
|
|
- sizeof(els_data),
|
|
|
|
- (char *)&els_data,
|
|
|
|
- SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX);
|
|
|
|
|
|
+ memcpy(els_data->wwpn, &ndlp->nlp_portname, sizeof(struct lpfc_name));
|
|
|
|
+ memcpy(els_data->wwnn, &ndlp->nlp_nodename, sizeof(struct lpfc_name));
|
|
|
|
+ if (*payload == ELS_CMD_LOGO) {
|
|
|
|
+ fc_host_post_vendor_event(shost,
|
|
|
|
+ fc_get_event_number(),
|
|
|
|
+ sizeof(struct lpfc_logo_event),
|
|
|
|
+ (char *)logo_data,
|
|
|
|
+ LPFC_NL_VENDOR_ID);
|
|
|
|
+ kfree(logo_data);
|
|
|
|
+ } else {
|
|
|
|
+ fc_host_post_vendor_event(shost,
|
|
|
|
+ fc_get_event_number(),
|
|
|
|
+ sizeof(struct lpfc_els_event_header),
|
|
|
|
+ (char *)els_data,
|
|
|
|
+ LPFC_NL_VENDOR_ID);
|
|
|
|
+ kfree(els_data);
|
|
|
|
+ }
|
|
|
|
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
@@ -5296,7 +5379,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
|
|
phba->fc_stat.elsRcvPLOGI++;
|
|
phba->fc_stat.elsRcvPLOGI++;
|
|
ndlp = lpfc_plogi_confirm_nport(phba, payload, ndlp);
|
|
ndlp = lpfc_plogi_confirm_nport(phba, payload, ndlp);
|
|
|
|
|
|
- lpfc_send_els_event(vport, ndlp, cmd);
|
|
|
|
|
|
+ lpfc_send_els_event(vport, ndlp, payload);
|
|
if (vport->port_state < LPFC_DISC_AUTH) {
|
|
if (vport->port_state < LPFC_DISC_AUTH) {
|
|
if (!(phba->pport->fc_flag & FC_PT2PT) ||
|
|
if (!(phba->pport->fc_flag & FC_PT2PT) ||
|
|
(phba->pport->fc_flag & FC_PT2PT_PLOGI)) {
|
|
(phba->pport->fc_flag & FC_PT2PT_PLOGI)) {
|
|
@@ -5334,6 +5417,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
|
|
did, vport->port_state, ndlp->nlp_flag);
|
|
did, vport->port_state, ndlp->nlp_flag);
|
|
|
|
|
|
phba->fc_stat.elsRcvLOGO++;
|
|
phba->fc_stat.elsRcvLOGO++;
|
|
|
|
+ lpfc_send_els_event(vport, ndlp, payload);
|
|
if (vport->port_state < LPFC_DISC_AUTH) {
|
|
if (vport->port_state < LPFC_DISC_AUTH) {
|
|
rjt_err = LSRJT_UNABLE_TPC;
|
|
rjt_err = LSRJT_UNABLE_TPC;
|
|
break;
|
|
break;
|
|
@@ -5346,7 +5430,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
|
|
did, vport->port_state, ndlp->nlp_flag);
|
|
did, vport->port_state, ndlp->nlp_flag);
|
|
|
|
|
|
phba->fc_stat.elsRcvPRLO++;
|
|
phba->fc_stat.elsRcvPRLO++;
|
|
- lpfc_send_els_event(vport, ndlp, cmd);
|
|
|
|
|
|
+ lpfc_send_els_event(vport, ndlp, payload);
|
|
if (vport->port_state < LPFC_DISC_AUTH) {
|
|
if (vport->port_state < LPFC_DISC_AUTH) {
|
|
rjt_err = LSRJT_UNABLE_TPC;
|
|
rjt_err = LSRJT_UNABLE_TPC;
|
|
break;
|
|
break;
|
|
@@ -5364,7 +5448,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
|
|
"RCV ADISC: did:x%x/ste:x%x flg:x%x",
|
|
"RCV ADISC: did:x%x/ste:x%x flg:x%x",
|
|
did, vport->port_state, ndlp->nlp_flag);
|
|
did, vport->port_state, ndlp->nlp_flag);
|
|
|
|
|
|
- lpfc_send_els_event(vport, ndlp, cmd);
|
|
|
|
|
|
+ lpfc_send_els_event(vport, ndlp, payload);
|
|
phba->fc_stat.elsRcvADISC++;
|
|
phba->fc_stat.elsRcvADISC++;
|
|
if (vport->port_state < LPFC_DISC_AUTH) {
|
|
if (vport->port_state < LPFC_DISC_AUTH) {
|
|
rjt_err = LSRJT_UNABLE_TPC;
|
|
rjt_err = LSRJT_UNABLE_TPC;
|