@@ -220,6 +220,90 @@ static int __nvme_fc_del_ctrl(struct nvme_fc_ctrl *);
220
220
static void __nvme_fc_delete_hw_queue (struct nvme_fc_ctrl * ,
221
221
struct nvme_fc_queue * , unsigned int );
222
222
223
+ static void
224
+ nvme_fc_free_lport (struct kref * ref )
225
+ {
226
+ struct nvme_fc_lport * lport =
227
+ container_of (ref , struct nvme_fc_lport , ref );
228
+ unsigned long flags ;
229
+
230
+ WARN_ON (lport -> localport .port_state != FC_OBJSTATE_DELETED );
231
+ WARN_ON (!list_empty (& lport -> endp_list ));
232
+
233
+ /* remove from transport list */
234
+ spin_lock_irqsave (& nvme_fc_lock , flags );
235
+ list_del (& lport -> port_list );
236
+ spin_unlock_irqrestore (& nvme_fc_lock , flags );
237
+
238
+ /* let the LLDD know we've finished tearing it down */
239
+ lport -> ops -> localport_delete (& lport -> localport );
240
+
241
+ ida_simple_remove (& nvme_fc_local_port_cnt , lport -> localport .port_num );
242
+ ida_destroy (& lport -> endp_cnt );
243
+
244
+ put_device (lport -> dev );
245
+
246
+ kfree (lport );
247
+ }
248
+
249
+ static void
250
+ nvme_fc_lport_put (struct nvme_fc_lport * lport )
251
+ {
252
+ kref_put (& lport -> ref , nvme_fc_free_lport );
253
+ }
254
+
255
+ static int
256
+ nvme_fc_lport_get (struct nvme_fc_lport * lport )
257
+ {
258
+ return kref_get_unless_zero (& lport -> ref );
259
+ }
260
+
261
+
262
+ static struct nvme_fc_lport *
263
+ nvme_fc_attach_to_unreg_lport (struct nvme_fc_port_info * pinfo )
264
+ {
265
+ struct nvme_fc_lport * lport ;
266
+ unsigned long flags ;
267
+
268
+ spin_lock_irqsave (& nvme_fc_lock , flags );
269
+
270
+ list_for_each_entry (lport , & nvme_fc_lport_list , port_list ) {
271
+ if (lport -> localport .node_name != pinfo -> node_name ||
272
+ lport -> localport .port_name != pinfo -> port_name )
273
+ continue ;
274
+
275
+ if (lport -> localport .port_state != FC_OBJSTATE_DELETED ) {
276
+ lport = ERR_PTR (- EEXIST );
277
+ goto out_done ;
278
+ }
279
+
280
+ if (!nvme_fc_lport_get (lport )) {
281
+ /*
282
+ * fails if ref cnt already 0. If so,
283
+ * act as if lport already deleted
284
+ */
285
+ lport = NULL ;
286
+ goto out_done ;
287
+ }
288
+
289
+ /* resume the lport */
290
+
291
+ lport -> localport .port_role = pinfo -> port_role ;
292
+ lport -> localport .port_id = pinfo -> port_id ;
293
+ lport -> localport .port_state = FC_OBJSTATE_ONLINE ;
294
+
295
+ spin_unlock_irqrestore (& nvme_fc_lock , flags );
296
+
297
+ return lport ;
298
+ }
299
+
300
+ lport = NULL ;
301
+
302
+ out_done :
303
+ spin_unlock_irqrestore (& nvme_fc_lock , flags );
304
+
305
+ return lport ;
306
+ }
223
307
224
308
/**
225
309
* nvme_fc_register_localport - transport entry point called by an
@@ -257,6 +341,28 @@ nvme_fc_register_localport(struct nvme_fc_port_info *pinfo,
257
341
goto out_reghost_failed ;
258
342
}
259
343
344
+ /*
345
+ * look to see if there is already a localport that had been
346
+ * deregistered and in the process of waiting for all the
347
+ * references to fully be removed. If the references haven't
348
+ * expired, we can simply re-enable the localport. Remoteports
349
+ * and controller reconnections should resume naturally.
350
+ */
351
+ newrec = nvme_fc_attach_to_unreg_lport (pinfo );
352
+
353
+ /* found an lport, but something about its state is bad */
354
+ if (IS_ERR (newrec )) {
355
+ ret = PTR_ERR (newrec );
356
+ goto out_reghost_failed ;
357
+
358
+ /* found existing lport, which was resumed */
359
+ } else if (newrec ) {
360
+ * portptr = & newrec -> localport ;
361
+ return 0 ;
362
+ }
363
+
364
+ /* nothing found - allocate a new localport struct */
365
+
260
366
newrec = kmalloc ((sizeof (* newrec ) + template -> local_priv_sz ),
261
367
GFP_KERNEL );
262
368
if (!newrec ) {
@@ -310,44 +416,6 @@ nvme_fc_register_localport(struct nvme_fc_port_info *pinfo,
310
416
}
311
417
EXPORT_SYMBOL_GPL (nvme_fc_register_localport );
312
418
313
- static void
314
- nvme_fc_free_lport (struct kref * ref )
315
- {
316
- struct nvme_fc_lport * lport =
317
- container_of (ref , struct nvme_fc_lport , ref );
318
- unsigned long flags ;
319
-
320
- WARN_ON (lport -> localport .port_state != FC_OBJSTATE_DELETED );
321
- WARN_ON (!list_empty (& lport -> endp_list ));
322
-
323
- /* remove from transport list */
324
- spin_lock_irqsave (& nvme_fc_lock , flags );
325
- list_del (& lport -> port_list );
326
- spin_unlock_irqrestore (& nvme_fc_lock , flags );
327
-
328
- /* let the LLDD know we've finished tearing it down */
329
- lport -> ops -> localport_delete (& lport -> localport );
330
-
331
- ida_simple_remove (& nvme_fc_local_port_cnt , lport -> localport .port_num );
332
- ida_destroy (& lport -> endp_cnt );
333
-
334
- put_device (lport -> dev );
335
-
336
- kfree (lport );
337
- }
338
-
339
- static void
340
- nvme_fc_lport_put (struct nvme_fc_lport * lport )
341
- {
342
- kref_put (& lport -> ref , nvme_fc_free_lport );
343
- }
344
-
345
- static int
346
- nvme_fc_lport_get (struct nvme_fc_lport * lport )
347
- {
348
- return kref_get_unless_zero (& lport -> ref );
349
- }
350
-
351
419
/**
352
420
* nvme_fc_unregister_localport - transport entry point called by an
353
421
* LLDD to deregister/remove a previously
@@ -2731,6 +2799,7 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,
2731
2799
ret = blk_mq_alloc_tag_set (& ctrl -> admin_tag_set );
2732
2800
if (ret )
2733
2801
goto out_free_queues ;
2802
+ ctrl -> ctrl .admin_tagset = & ctrl -> admin_tag_set ;
2734
2803
2735
2804
ctrl -> ctrl .admin_q = blk_mq_init_queue (& ctrl -> admin_tag_set );
2736
2805
if (IS_ERR (ctrl -> ctrl .admin_q )) {
0 commit comments