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.
  * @vport: pointer to a host virtual N_Port data structure.
                         "0214 RSCN received Data: x%x x%x x%x x%x\n",
                         vport->fc_flag, payload_len, *lp,
                         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++)
                fc_host_post_event(shost, fc_get_event_number(),
                        FCH_EVT_RSCN, lp[i]);
                        fc_get_event_number(),
                        sizeof(lsrjt_event),
                        (char *)&lsrjt_event,
-                       SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX);
+                       LPFC_NL_VENDOR_ID);
                return;
        }
        if ((rspiocbp->iocb.ulpStatus == IOSTAT_NPORT_BSY) ||
                        fc_get_event_number(),
                        sizeof(fabric_event),
                        (char *)&fabric_event,
-                       SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX);
+                       LPFC_NL_VENDOR_ID);
                return;
        }
 
 static void
 lpfc_send_els_event(struct lpfc_vport *vport,
                    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);
 
-       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:
-               els_data.subcategory = LPFC_EVENT_PLOGI_RCV;
+               els_data->subcategory = LPFC_EVENT_PLOGI_RCV;
                break;
        case ELS_CMD_PRLO:
-               els_data.subcategory = LPFC_EVENT_PRLO_RCV;
+               els_data->subcategory = LPFC_EVENT_PRLO_RCV;
                break;
        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;
        default:
                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;
 }
                phba->fc_stat.elsRcvPLOGI++;
                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 (!(phba->pport->fc_flag & FC_PT2PT) ||
                                (phba->pport->fc_flag & FC_PT2PT_PLOGI)) {
                        did, vport->port_state, ndlp->nlp_flag);
 
                phba->fc_stat.elsRcvLOGO++;
+               lpfc_send_els_event(vport, ndlp, payload);
                if (vport->port_state < LPFC_DISC_AUTH) {
                        rjt_err = LSRJT_UNABLE_TPC;
                        break;
                        did, vport->port_state, ndlp->nlp_flag);
 
                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) {
                        rjt_err = LSRJT_UNABLE_TPC;
                        break;
                        "RCV ADISC:       did:x%x/ste:x%x flg:x%x",
                        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++;
                if (vport->port_state < LPFC_DISC_AUTH) {
                        rjt_err = LSRJT_UNABLE_TPC;