@@ -3085,6 +3085,95 @@ lpfc_cmpl_els_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
3085
3085
lpfc_nlp_put (free_ndlp );
3086
3086
}
3087
3087
3088
+ /**
3089
+ * lpfc_reg_fab_ctrl_node - RPI register the fabric controller node.
3090
+ * @vport: pointer to lpfc_vport data structure.
3091
+ * @fc_ndlp: pointer to the fabric controller (0xfffffd) node.
3092
+ *
3093
+ * This routine registers the rpi assigned to the fabric controller
3094
+ * NPort_ID (0xfffffd) with the port and moves the node to UNMAPPED
3095
+ * state triggering a registration with the SCSI transport.
3096
+ *
3097
+ * This routine is single out because the fabric controller node
3098
+ * does not receive a PLOGI. This routine is consumed by the
3099
+ * SCR and RDF ELS commands. Callers are expected to qualify
3100
+ * with SLI4 first.
3101
+ **/
3102
+ static int
3103
+ lpfc_reg_fab_ctrl_node (struct lpfc_vport * vport , struct lpfc_nodelist * fc_ndlp )
3104
+ {
3105
+ int rc = 0 ;
3106
+ struct lpfc_hba * phba = vport -> phba ;
3107
+ struct lpfc_nodelist * ns_ndlp ;
3108
+ LPFC_MBOXQ_t * mbox ;
3109
+ struct lpfc_dmabuf * mp ;
3110
+
3111
+ if (fc_ndlp -> nlp_flag & NLP_RPI_REGISTERED )
3112
+ return rc ;
3113
+
3114
+ ns_ndlp = lpfc_findnode_did (vport , NameServer_DID );
3115
+ if (!ns_ndlp )
3116
+ return - ENODEV ;
3117
+
3118
+ lpfc_printf_vlog (vport , KERN_INFO , LOG_NODE ,
3119
+ "0935 %s: Reg FC RPI x%x on FC DID x%x NSSte: x%x\n" ,
3120
+ __func__ , fc_ndlp -> nlp_rpi , fc_ndlp -> nlp_DID ,
3121
+ ns_ndlp -> nlp_state );
3122
+ if (ns_ndlp -> nlp_state != NLP_STE_UNMAPPED_NODE )
3123
+ return - ENODEV ;
3124
+
3125
+ mbox = mempool_alloc (phba -> mbox_mem_pool , GFP_KERNEL );
3126
+ if (!mbox ) {
3127
+ lpfc_printf_vlog (vport , KERN_ERR , LOG_NODE ,
3128
+ "0936 %s: no memory for reg_login "
3129
+ "Data: x%x x%x x%x x%x\n" , __func__ ,
3130
+ fc_ndlp -> nlp_DID , fc_ndlp -> nlp_state ,
3131
+ fc_ndlp -> nlp_flag , fc_ndlp -> nlp_rpi );
3132
+ return - ENOMEM ;
3133
+ }
3134
+ rc = lpfc_reg_rpi (phba , vport -> vpi , fc_ndlp -> nlp_DID ,
3135
+ (u8 * )& vport -> fc_sparam , mbox , fc_ndlp -> nlp_rpi );
3136
+ if (rc ) {
3137
+ rc = - EACCES ;
3138
+ goto out ;
3139
+ }
3140
+
3141
+ fc_ndlp -> nlp_flag |= NLP_REG_LOGIN_SEND ;
3142
+ mbox -> mbox_cmpl = lpfc_mbx_cmpl_fc_reg_login ;
3143
+ mbox -> ctx_ndlp = lpfc_nlp_get (fc_ndlp );
3144
+ if (!mbox -> ctx_ndlp ) {
3145
+ rc = - ENOMEM ;
3146
+ goto out_mem ;
3147
+ }
3148
+
3149
+ mbox -> vport = vport ;
3150
+ rc = lpfc_sli_issue_mbox (phba , mbox , MBX_NOWAIT );
3151
+ if (rc == MBX_NOT_FINISHED ) {
3152
+ rc = - ENODEV ;
3153
+ lpfc_nlp_put (fc_ndlp );
3154
+ goto out_mem ;
3155
+ }
3156
+ /* Success path. Exit. */
3157
+ lpfc_nlp_set_state (vport , fc_ndlp ,
3158
+ NLP_STE_REG_LOGIN_ISSUE );
3159
+ return 0 ;
3160
+
3161
+ out_mem :
3162
+ fc_ndlp -> nlp_flag &= ~NLP_REG_LOGIN_SEND ;
3163
+ mp = (struct lpfc_dmabuf * )mbox -> ctx_buf ;
3164
+ lpfc_mbuf_free (phba , mp -> virt , mp -> phys );
3165
+ kfree (mp );
3166
+
3167
+ out :
3168
+ mempool_free (mbox , phba -> mbox_mem_pool );
3169
+ lpfc_printf_vlog (vport , KERN_ERR , LOG_NODE ,
3170
+ "0938 %s: failed to format reg_login "
3171
+ "Data: x%x x%x x%x x%x\n" , __func__ ,
3172
+ fc_ndlp -> nlp_DID , fc_ndlp -> nlp_state ,
3173
+ fc_ndlp -> nlp_flag , fc_ndlp -> nlp_rpi );
3174
+ return rc ;
3175
+ }
3176
+
3088
3177
/**
3089
3178
* lpfc_cmpl_els_disc_cmd - Completion callback function for Discovery ELS cmd
3090
3179
* @phba: pointer to lpfc hba data structure.
@@ -3231,10 +3320,18 @@ lpfc_issue_els_scr(struct lpfc_vport *vport, uint8_t retry)
3231
3320
3232
3321
elsiocb = lpfc_prep_els_iocb (vport , 1 , cmdsize , retry , ndlp ,
3233
3322
ndlp -> nlp_DID , ELS_CMD_SCR );
3234
-
3235
3323
if (!elsiocb )
3236
3324
return 1 ;
3237
3325
3326
+ if (phba -> sli_rev == LPFC_SLI_REV4 ) {
3327
+ rc = lpfc_reg_fab_ctrl_node (vport , ndlp );
3328
+ if (rc ) {
3329
+ lpfc_printf_vlog (vport , KERN_ERR , LOG_NODE ,
3330
+ "0937 %s: Failed to reg fc node, rc %d\n" ,
3331
+ __func__ , rc );
3332
+ return 1 ;
3333
+ }
3334
+ }
3238
3335
pcmd = (uint8_t * ) (((struct lpfc_dmabuf * ) elsiocb -> context2 )-> virt );
3239
3336
3240
3337
* ((uint32_t * ) (pcmd )) = ELS_CMD_SCR ;
@@ -3522,6 +3619,17 @@ lpfc_issue_els_rdf(struct lpfc_vport *vport, uint8_t retry)
3522
3619
if (!elsiocb )
3523
3620
return - ENOMEM ;
3524
3621
3622
+ if (phba -> sli_rev == LPFC_SLI_REV4 &&
3623
+ !(ndlp -> nlp_flag & NLP_RPI_REGISTERED )) {
3624
+ lpfc_printf_vlog (vport , KERN_ERR , LOG_NODE ,
3625
+ "0939 %s: FC_NODE x%x RPI x%x flag x%x "
3626
+ "ste x%x type x%x Not registered\n" ,
3627
+ __func__ , ndlp -> nlp_DID , ndlp -> nlp_rpi ,
3628
+ ndlp -> nlp_flag , ndlp -> nlp_state ,
3629
+ ndlp -> nlp_type );
3630
+ return - ENODEV ;
3631
+ }
3632
+
3525
3633
/* Configure the payload for the supported FPIN events. */
3526
3634
prdf = (struct lpfc_els_rdf_req * )
3527
3635
(((struct lpfc_dmabuf * )elsiocb -> context2 )-> virt );
@@ -4396,7 +4504,6 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
4396
4504
struct lpfc_nodelist * ndlp = (struct lpfc_nodelist * ) cmdiocb -> context1 ;
4397
4505
struct lpfc_vport * vport = cmdiocb -> vport ;
4398
4506
IOCB_t * irsp ;
4399
- u32 xpt_flags = 0 , did_mask = 0 ;
4400
4507
4401
4508
irsp = & rspiocb -> iocb ;
4402
4509
lpfc_debugfs_disc_trc (vport , LPFC_DISC_TRC_ELS_RSP ,
@@ -4409,23 +4516,27 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
4409
4516
ndlp -> nlp_DID , kref_read (& ndlp -> kref ), ndlp -> nlp_flag ,
4410
4517
ndlp -> nlp_state , ndlp -> nlp_rpi );
4411
4518
4519
+ /* This clause allows the LOGO ACC to complete and free resources
4520
+ * for the Fabric Domain Controller. It does deliberately skip
4521
+ * the unreg_rpi and release rpi because some fabrics send RDP
4522
+ * requests after logging out from the initiator.
4523
+ */
4524
+ if (ndlp -> nlp_type & NLP_FABRIC &&
4525
+ ((ndlp -> nlp_DID & WELL_KNOWN_DID_MASK ) != WELL_KNOWN_DID_MASK ))
4526
+ goto out ;
4527
+
4412
4528
if (ndlp -> nlp_state == NLP_STE_NPR_NODE ) {
4413
4529
/* NPort Recovery mode or node is just allocated */
4414
4530
if (!lpfc_nlp_not_used (ndlp )) {
4415
4531
/* A LOGO is completing and the node is in NPR state.
4416
4532
* If this a fabric node that cleared its transport
4417
4533
* registration, release the rpi.
4418
4534
*/
4419
- xpt_flags = SCSI_XPT_REGD | NVME_XPT_REGD ;
4420
- did_mask = ndlp -> nlp_DID & Fabric_DID_MASK ;
4421
- if (did_mask == Fabric_DID_MASK &&
4422
- !(ndlp -> fc4_xpt_flags & xpt_flags )) {
4423
- spin_lock_irq (& ndlp -> lock );
4424
- ndlp -> nlp_flag &= ~NLP_NPR_2B_DISC ;
4425
- if (phba -> sli_rev == LPFC_SLI_REV4 )
4426
- ndlp -> nlp_flag |= NLP_RELEASE_RPI ;
4427
- spin_unlock_irq (& ndlp -> lock );
4428
- }
4535
+ spin_lock_irq (& ndlp -> lock );
4536
+ ndlp -> nlp_flag &= ~NLP_NPR_2B_DISC ;
4537
+ if (phba -> sli_rev == LPFC_SLI_REV4 )
4538
+ ndlp -> nlp_flag |= NLP_RELEASE_RPI ;
4539
+ spin_unlock_irq (& ndlp -> lock );
4429
4540
lpfc_unreg_rpi (vport , ndlp );
4430
4541
} else {
4431
4542
/* Indicate the node has already released, should
@@ -4434,7 +4545,7 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
4434
4545
cmdiocb -> context1 = NULL ;
4435
4546
}
4436
4547
}
4437
-
4548
+ out :
4438
4549
/*
4439
4550
* The driver received a LOGO from the rport and has ACK'd it.
4440
4551
* At this point, the driver is done so release the IOCB
0 commit comments