Lines Matching +full:single +full:- +full:tt
1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright(c) 2007 - 2008 Intel Corporation. All rights reserved.
5 * Maintained at www.Open-FCoE.org
11 * This block discovers all FC-4 remote ports, including FCP initiators. It
12 * also handles RSCN events and re-discovery if necessary.
48 * fc_disc_stop_rports() - Delete all the remote ports associated with the lport
55 lockdep_assert_held(&disc->disc_mutex); in fc_disc_stop_rports()
57 list_for_each_entry(rdata, &disc->rports, peers) { in fc_disc_stop_rports()
58 if (kref_get_unless_zero(&rdata->kref)) { in fc_disc_stop_rports()
60 kref_put(&rdata->kref, fc_rport_destroy); in fc_disc_stop_rports()
66 * fc_disc_recv_rscn_req() - Handle Registered State Change Notification (RSCN)
83 lockdep_assert_held(&disc->disc_mutex); in fc_disc_recv_rscn_req()
94 if (rp->rscn_page_len != sizeof(*pp)) in fc_disc_recv_rscn_req()
97 len = ntohs(rp->rscn_plen); in fc_disc_recv_rscn_req()
105 len -= sizeof(*rp); in fc_disc_recv_rscn_req()
109 for (pp = (void *)(rp + 1); len > 0; len -= sizeof(*pp), pp++) { in fc_disc_recv_rscn_req()
110 ev_qual = pp->rscn_page_flags >> ELS_RSCN_EV_QUAL_BIT; in fc_disc_recv_rscn_req()
112 fmt = pp->rscn_page_flags >> ELS_RSCN_ADDR_FMT_BIT; in fc_disc_recv_rscn_req()
121 "(%6.6x)\n", ntoh24(pp->rscn_fid)); in fc_disc_recv_rscn_req()
127 dp->lp = lport; in fc_disc_recv_rscn_req()
128 dp->port_id = ntoh24(pp->rscn_fid); in fc_disc_recv_rscn_req()
129 list_add_tail(&dp->peers, &disc_ports); in fc_disc_recv_rscn_req()
149 list_del(&dp->peers); in fc_disc_recv_rscn_req()
160 redisc, lport->state, disc->pending); in fc_disc_recv_rscn_req()
173 * fc_disc_recv_req() - Handle incoming requests
184 struct fc_disc *disc = &lport->disc; in fc_disc_recv_req()
189 mutex_lock(&disc->disc_mutex); in fc_disc_recv_req()
191 mutex_unlock(&disc->disc_mutex); in fc_disc_recv_req()
202 * fc_disc_restart() - Restart discovery
207 lockdep_assert_held(&disc->disc_mutex); in fc_disc_restart()
209 if (!disc->disc_callback) in fc_disc_restart()
214 disc->requested = 1; in fc_disc_restart()
215 if (disc->pending) in fc_disc_restart()
219 * Advance disc_id. This is an arbitrary non-zero number that will in fc_disc_restart()
221 * freshly-discovered remote ports. Avoid wrapping to zero. in fc_disc_restart()
223 disc->disc_id = (disc->disc_id + 2) | 1; in fc_disc_restart()
224 disc->retry_count = 0; in fc_disc_restart()
229 * fc_disc_start() - Start discovery on a local port
237 struct fc_disc *disc = &lport->disc; in fc_disc_start()
244 mutex_lock(&disc->disc_mutex); in fc_disc_start()
245 disc->disc_callback = disc_callback; in fc_disc_start()
247 mutex_unlock(&disc->disc_mutex); in fc_disc_start()
251 * fc_disc_done() - Discovery has been completed
260 lockdep_assert_held(&disc->disc_mutex); in fc_disc_done()
263 disc->pending = 0; in fc_disc_done()
264 if (disc->requested) { in fc_disc_done()
278 list_for_each_entry(rdata, &disc->rports, peers) { in fc_disc_done()
279 if (!kref_get_unless_zero(&rdata->kref)) in fc_disc_done()
281 if (rdata->disc_id) { in fc_disc_done()
282 if (rdata->disc_id == disc->disc_id) in fc_disc_done()
287 kref_put(&rdata->kref, fc_rport_destroy); in fc_disc_done()
289 mutex_unlock(&disc->disc_mutex); in fc_disc_done()
290 disc->disc_callback(lport, event); in fc_disc_done()
291 mutex_lock(&disc->disc_mutex); in fc_disc_done()
295 * fc_disc_error() - Handle error on dNS request
305 PTR_ERR_OR_ZERO(fp), disc->retry_count, in fc_disc_error()
308 if (!fp || PTR_ERR(fp) == -FC_EX_TIMEOUT) { in fc_disc_error()
313 if (disc->retry_count < FC_DISC_RETRY_LIMIT) { in fc_disc_error()
318 delay = msecs_to_jiffies(lport->e_d_tov); in fc_disc_error()
321 if (!disc->retry_count) in fc_disc_error()
324 disc->retry_count++; in fc_disc_error()
325 schedule_delayed_work(&disc->disc_work, delay); in fc_disc_error()
328 } else if (PTR_ERR(fp) == -FC_EX_CLOSED) { in fc_disc_error()
334 disc->pending = 0; in fc_disc_error()
339 * fc_disc_gpn_ft_req() - Send Get Port Names by FC-4 type (GPN_FT) request
347 lockdep_assert_held(&disc->disc_mutex); in fc_disc_gpn_ft_req()
351 disc->pending = 1; in fc_disc_gpn_ft_req()
352 disc->requested = 0; in fc_disc_gpn_ft_req()
354 disc->buf_len = 0; in fc_disc_gpn_ft_req()
355 disc->seq_count = 0; in fc_disc_gpn_ft_req()
362 if (lport->tt.elsct_send(lport, 0, fp, in fc_disc_gpn_ft_req()
365 disc, 3 * lport->r_a_tov)) in fc_disc_gpn_ft_req()
372 * fc_disc_gpn_ft_parse() - Parse the body of the dNS GPN_FT response.
391 disc->seq_count++; in fc_disc_gpn_ft_parse()
399 tlen = disc->buf_len; in fc_disc_gpn_ft_parse()
400 disc->buf_len = 0; in fc_disc_gpn_ft_parse()
403 plen = sizeof(*np) - tlen; in fc_disc_gpn_ft_parse()
408 np = &disc->partial_buf; in fc_disc_gpn_ft_parse()
415 bp -= tlen; in fc_disc_gpn_ft_parse()
418 disc->buf_len = (unsigned char) plen; in fc_disc_gpn_ft_parse()
420 disc->buf_len = 0; in fc_disc_gpn_ft_parse()
431 ids.port_id = ntoh24(np->fp_fid); in fc_disc_gpn_ft_parse()
432 ids.port_name = ntohll(np->fp_wwpn); in fc_disc_gpn_ft_parse()
434 if (ids.port_id != lport->port_id && in fc_disc_gpn_ft_parse()
435 ids.port_name != lport->wwpn) { in fc_disc_gpn_ft_parse()
438 rdata->ids.port_name = ids.port_name; in fc_disc_gpn_ft_parse()
439 rdata->disc_id = disc->disc_id; in fc_disc_gpn_ft_parse()
444 error = -ENOMEM; in fc_disc_gpn_ft_parse()
448 if (np->fp_flags & FC_NS_FID_LAST) { in fc_disc_gpn_ft_parse()
453 len -= sizeof(*np); in fc_disc_gpn_ft_parse()
463 if (np != &disc->partial_buf) { in fc_disc_gpn_ft_parse()
466 memcpy(&disc->partial_buf, np, len); in fc_disc_gpn_ft_parse()
468 disc->buf_len = (unsigned char) len; in fc_disc_gpn_ft_parse()
474 * fc_disc_timeout() - Handler for discovery timeouts
482 mutex_lock(&disc->disc_mutex); in fc_disc_timeout()
484 mutex_unlock(&disc->disc_mutex); in fc_disc_timeout()
488 * fc_disc_gpn_ft_resp() - Handle a response frame from Get Port Names (GPN_FT)
507 mutex_lock(&disc->disc_mutex); in fc_disc_gpn_ft_resp()
512 mutex_unlock(&disc->disc_mutex); in fc_disc_gpn_ft_resp()
518 len = fr_len(fp) - sizeof(*fh); in fc_disc_gpn_ft_resp()
519 seq_cnt = ntohs(fh->fh_seq_cnt); in fc_disc_gpn_ft_resp()
520 if (fr_sof(fp) == FC_SOF_I3 && seq_cnt == 0 && disc->seq_count == 0) { in fc_disc_gpn_ft_resp()
526 } else if (ntohs(cp->ct_cmd) == FC_FS_ACC) { in fc_disc_gpn_ft_resp()
529 len -= sizeof(*cp); in fc_disc_gpn_ft_resp()
531 } else if (ntohs(cp->ct_cmd) == FC_FS_RJT) { in fc_disc_gpn_ft_resp()
533 "(check zoning)\n", cp->ct_reason, in fc_disc_gpn_ft_resp()
534 cp->ct_explan); in fc_disc_gpn_ft_resp()
536 if (cp->ct_reason == FC_FS_RJT_UNABL && in fc_disc_gpn_ft_resp()
537 cp->ct_explan == FC_FS_EXP_FTNR) in fc_disc_gpn_ft_resp()
541 "%x\n", ntohs(cp->ct_cmd)); in fc_disc_gpn_ft_resp()
544 } else if (fr_sof(fp) == FC_SOF_N3 && seq_cnt == disc->seq_count) { in fc_disc_gpn_ft_resp()
547 FC_DISC_DBG(disc, "GPN_FT unexpected frame - out of sequence? " in fc_disc_gpn_ft_resp()
549 seq_cnt, disc->seq_count, fr_sof(fp), fr_eof(fp)); in fc_disc_gpn_ft_resp()
557 mutex_unlock(&disc->disc_mutex); in fc_disc_gpn_ft_resp()
561 * fc_disc_gpn_id_resp() - Handle a response frame from Get Port Names (GPN_ID)
579 lport = rdata->local_port; in fc_disc_gpn_id_resp()
580 disc = &lport->disc; in fc_disc_gpn_id_resp()
582 if (PTR_ERR(fp) == -FC_EX_CLOSED) in fc_disc_gpn_id_resp()
585 mutex_lock(&disc->disc_mutex); in fc_disc_gpn_id_resp()
587 mutex_unlock(&disc->disc_mutex); in fc_disc_gpn_id_resp()
594 if (ntohs(cp->ct_cmd) == FC_FS_ACC) { in fc_disc_gpn_id_resp()
599 port_name = get_unaligned_be64(&pn->fn_wwpn); in fc_disc_gpn_id_resp()
600 mutex_lock(&rdata->rp_mutex); in fc_disc_gpn_id_resp()
601 if (rdata->ids.port_name == -1) in fc_disc_gpn_id_resp()
602 rdata->ids.port_name = port_name; in fc_disc_gpn_id_resp()
603 else if (rdata->ids.port_name != port_name) { in fc_disc_gpn_id_resp()
605 "Port-id %6.6x wwpn %16.16llx\n", in fc_disc_gpn_id_resp()
606 rdata->ids.port_id, port_name); in fc_disc_gpn_id_resp()
607 mutex_unlock(&rdata->rp_mutex); in fc_disc_gpn_id_resp()
609 mutex_lock(&lport->disc.disc_mutex); in fc_disc_gpn_id_resp()
610 new_rdata = fc_rport_create(lport, rdata->ids.port_id); in fc_disc_gpn_id_resp()
611 mutex_unlock(&lport->disc.disc_mutex); in fc_disc_gpn_id_resp()
613 new_rdata->disc_id = disc->disc_id; in fc_disc_gpn_id_resp()
618 rdata->disc_id = disc->disc_id; in fc_disc_gpn_id_resp()
619 mutex_unlock(&rdata->rp_mutex); in fc_disc_gpn_id_resp()
621 } else if (ntohs(cp->ct_cmd) == FC_FS_RJT) { in fc_disc_gpn_id_resp()
623 cp->ct_reason, cp->ct_explan); in fc_disc_gpn_id_resp()
627 ntohs(cp->ct_cmd)); in fc_disc_gpn_id_resp()
629 mutex_lock(&disc->disc_mutex); in fc_disc_gpn_id_resp()
631 mutex_unlock(&disc->disc_mutex); in fc_disc_gpn_id_resp()
636 kref_put(&rdata->kref, fc_rport_destroy); in fc_disc_gpn_id_resp()
640 * fc_disc_gpn_id_req() - Send Get Port Names by ID (GPN_ID) request
651 lockdep_assert_held(&lport->disc.disc_mutex); in fc_disc_gpn_id_req()
655 return -ENOMEM; in fc_disc_gpn_id_req()
656 if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, FC_NS_GPN_ID, in fc_disc_gpn_id_req()
658 3 * lport->r_a_tov)) in fc_disc_gpn_id_req()
659 return -ENOMEM; in fc_disc_gpn_id_req()
660 kref_get(&rdata->kref); in fc_disc_gpn_id_req()
665 * fc_disc_single() - Discover the directory information for a single target
673 lockdep_assert_held(&lport->disc.disc_mutex); in fc_disc_single()
675 rdata = fc_rport_create(lport, dp->port_id); in fc_disc_single()
677 return -ENOMEM; in fc_disc_single()
678 rdata->disc_id = 0; in fc_disc_single()
683 * fc_disc_stop() - Stop discovery for a given lport
688 struct fc_disc *disc = &lport->disc; in fc_disc_stop()
690 if (disc->pending) in fc_disc_stop()
691 cancel_delayed_work_sync(&disc->disc_work); in fc_disc_stop()
692 mutex_lock(&disc->disc_mutex); in fc_disc_stop()
694 mutex_unlock(&disc->disc_mutex); in fc_disc_stop()
698 * fc_disc_stop_final() - Stop discovery for a given lport
711 * fc_disc_config() - Configure the discovery layer for a local port
719 if (!lport->tt.disc_start) in fc_disc_config()
720 lport->tt.disc_start = fc_disc_start; in fc_disc_config()
722 if (!lport->tt.disc_stop) in fc_disc_config()
723 lport->tt.disc_stop = fc_disc_stop; in fc_disc_config()
725 if (!lport->tt.disc_stop_final) in fc_disc_config()
726 lport->tt.disc_stop_final = fc_disc_stop_final; in fc_disc_config()
728 if (!lport->tt.disc_recv_req) in fc_disc_config()
729 lport->tt.disc_recv_req = fc_disc_recv_req; in fc_disc_config()
731 disc = &lport->disc; in fc_disc_config()
733 disc->priv = priv; in fc_disc_config()
738 * fc_disc_init() - Initialize the discovery layer for a local port
743 struct fc_disc *disc = &lport->disc; in fc_disc_init()
745 INIT_DELAYED_WORK(&disc->disc_work, fc_disc_timeout); in fc_disc_init()
746 mutex_init(&disc->disc_mutex); in fc_disc_init()
747 INIT_LIST_HEAD(&disc->rports); in fc_disc_init()