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)
82 lockdep_assert_held(&disc->disc_mutex); in fc_disc_recv_rscn_req()
93 if (rp->rscn_page_len != sizeof(*pp)) in fc_disc_recv_rscn_req()
96 len = ntohs(rp->rscn_plen); in fc_disc_recv_rscn_req()
104 len -= sizeof(*rp); in fc_disc_recv_rscn_req()
108 for (pp = (void *)(rp + 1); len > 0; len -= sizeof(*pp), pp++) { in fc_disc_recv_rscn_req()
109 fmt = pp->rscn_page_flags >> ELS_RSCN_ADDR_FMT_BIT; in fc_disc_recv_rscn_req()
118 "(%6.6x)\n", ntoh24(pp->rscn_fid)); in fc_disc_recv_rscn_req()
124 dp->lp = lport; in fc_disc_recv_rscn_req()
125 dp->port_id = ntoh24(pp->rscn_fid); in fc_disc_recv_rscn_req()
126 list_add_tail(&dp->peers, &disc_ports); in fc_disc_recv_rscn_req()
146 list_del(&dp->peers); in fc_disc_recv_rscn_req()
157 redisc, lport->state, disc->pending); in fc_disc_recv_rscn_req()
170 * fc_disc_recv_req() - Handle incoming requests
181 struct fc_disc *disc = &lport->disc; in fc_disc_recv_req()
186 mutex_lock(&disc->disc_mutex); in fc_disc_recv_req()
188 mutex_unlock(&disc->disc_mutex); in fc_disc_recv_req()
199 * fc_disc_restart() - Restart discovery
204 lockdep_assert_held(&disc->disc_mutex); in fc_disc_restart()
206 if (!disc->disc_callback) in fc_disc_restart()
211 disc->requested = 1; in fc_disc_restart()
212 if (disc->pending) in fc_disc_restart()
216 * Advance disc_id. This is an arbitrary non-zero number that will in fc_disc_restart()
218 * freshly-discovered remote ports. Avoid wrapping to zero. in fc_disc_restart()
220 disc->disc_id = (disc->disc_id + 2) | 1; in fc_disc_restart()
221 disc->retry_count = 0; in fc_disc_restart()
226 * fc_disc_start() - Start discovery on a local port
234 struct fc_disc *disc = &lport->disc; in fc_disc_start()
241 mutex_lock(&disc->disc_mutex); in fc_disc_start()
242 disc->disc_callback = disc_callback; in fc_disc_start()
244 mutex_unlock(&disc->disc_mutex); in fc_disc_start()
248 * fc_disc_done() - Discovery has been completed
257 lockdep_assert_held(&disc->disc_mutex); in fc_disc_done()
260 disc->pending = 0; in fc_disc_done()
261 if (disc->requested) { in fc_disc_done()
275 list_for_each_entry(rdata, &disc->rports, peers) { in fc_disc_done()
276 if (!kref_get_unless_zero(&rdata->kref)) in fc_disc_done()
278 if (rdata->disc_id) { in fc_disc_done()
279 if (rdata->disc_id == disc->disc_id) in fc_disc_done()
284 kref_put(&rdata->kref, fc_rport_destroy); in fc_disc_done()
286 mutex_unlock(&disc->disc_mutex); in fc_disc_done()
287 disc->disc_callback(lport, event); in fc_disc_done()
288 mutex_lock(&disc->disc_mutex); in fc_disc_done()
292 * fc_disc_error() - Handle error on dNS request
302 PTR_ERR_OR_ZERO(fp), disc->retry_count, in fc_disc_error()
305 if (!fp || PTR_ERR(fp) == -FC_EX_TIMEOUT) { in fc_disc_error()
310 if (disc->retry_count < FC_DISC_RETRY_LIMIT) { in fc_disc_error()
315 delay = msecs_to_jiffies(lport->e_d_tov); in fc_disc_error()
318 if (!disc->retry_count) in fc_disc_error()
321 disc->retry_count++; in fc_disc_error()
322 schedule_delayed_work(&disc->disc_work, delay); in fc_disc_error()
325 } else if (PTR_ERR(fp) == -FC_EX_CLOSED) { in fc_disc_error()
331 disc->pending = 0; in fc_disc_error()
336 * fc_disc_gpn_ft_req() - Send Get Port Names by FC-4 type (GPN_FT) request
344 lockdep_assert_held(&disc->disc_mutex); in fc_disc_gpn_ft_req()
348 disc->pending = 1; in fc_disc_gpn_ft_req()
349 disc->requested = 0; in fc_disc_gpn_ft_req()
351 disc->buf_len = 0; in fc_disc_gpn_ft_req()
352 disc->seq_count = 0; in fc_disc_gpn_ft_req()
359 if (lport->tt.elsct_send(lport, 0, fp, in fc_disc_gpn_ft_req()
362 disc, 3 * lport->r_a_tov)) in fc_disc_gpn_ft_req()
369 * fc_disc_gpn_ft_parse() - Parse the body of the dNS GPN_FT response.
388 disc->seq_count++; in fc_disc_gpn_ft_parse()
396 tlen = disc->buf_len; in fc_disc_gpn_ft_parse()
397 disc->buf_len = 0; in fc_disc_gpn_ft_parse()
400 plen = sizeof(*np) - tlen; in fc_disc_gpn_ft_parse()
405 np = &disc->partial_buf; in fc_disc_gpn_ft_parse()
412 bp -= tlen; in fc_disc_gpn_ft_parse()
415 disc->buf_len = (unsigned char) plen; in fc_disc_gpn_ft_parse()
417 disc->buf_len = 0; in fc_disc_gpn_ft_parse()
428 ids.port_id = ntoh24(np->fp_fid); in fc_disc_gpn_ft_parse()
429 ids.port_name = ntohll(np->fp_wwpn); in fc_disc_gpn_ft_parse()
431 if (ids.port_id != lport->port_id && in fc_disc_gpn_ft_parse()
432 ids.port_name != lport->wwpn) { in fc_disc_gpn_ft_parse()
435 rdata->ids.port_name = ids.port_name; in fc_disc_gpn_ft_parse()
436 rdata->disc_id = disc->disc_id; in fc_disc_gpn_ft_parse()
441 error = -ENOMEM; in fc_disc_gpn_ft_parse()
445 if (np->fp_flags & FC_NS_FID_LAST) { in fc_disc_gpn_ft_parse()
450 len -= sizeof(*np); in fc_disc_gpn_ft_parse()
460 if (np != &disc->partial_buf) { in fc_disc_gpn_ft_parse()
463 memcpy(&disc->partial_buf, np, len); in fc_disc_gpn_ft_parse()
465 disc->buf_len = (unsigned char) len; in fc_disc_gpn_ft_parse()
471 * fc_disc_timeout() - Handler for discovery timeouts
479 mutex_lock(&disc->disc_mutex); in fc_disc_timeout()
481 mutex_unlock(&disc->disc_mutex); in fc_disc_timeout()
485 * fc_disc_gpn_ft_resp() - Handle a response frame from Get Port Names (GPN_FT)
504 mutex_lock(&disc->disc_mutex); in fc_disc_gpn_ft_resp()
509 mutex_unlock(&disc->disc_mutex); in fc_disc_gpn_ft_resp()
515 len = fr_len(fp) - sizeof(*fh); in fc_disc_gpn_ft_resp()
516 seq_cnt = ntohs(fh->fh_seq_cnt); in fc_disc_gpn_ft_resp()
517 if (fr_sof(fp) == FC_SOF_I3 && seq_cnt == 0 && disc->seq_count == 0) { in fc_disc_gpn_ft_resp()
523 } else if (ntohs(cp->ct_cmd) == FC_FS_ACC) { in fc_disc_gpn_ft_resp()
526 len -= sizeof(*cp); in fc_disc_gpn_ft_resp()
528 } else if (ntohs(cp->ct_cmd) == FC_FS_RJT) { in fc_disc_gpn_ft_resp()
530 "(check zoning)\n", cp->ct_reason, in fc_disc_gpn_ft_resp()
531 cp->ct_explan); in fc_disc_gpn_ft_resp()
533 if (cp->ct_reason == FC_FS_RJT_UNABL && in fc_disc_gpn_ft_resp()
534 cp->ct_explan == FC_FS_EXP_FTNR) in fc_disc_gpn_ft_resp()
538 "%x\n", ntohs(cp->ct_cmd)); in fc_disc_gpn_ft_resp()
541 } else if (fr_sof(fp) == FC_SOF_N3 && seq_cnt == disc->seq_count) { in fc_disc_gpn_ft_resp()
544 FC_DISC_DBG(disc, "GPN_FT unexpected frame - out of sequence? " in fc_disc_gpn_ft_resp()
546 seq_cnt, disc->seq_count, fr_sof(fp), fr_eof(fp)); in fc_disc_gpn_ft_resp()
554 mutex_unlock(&disc->disc_mutex); in fc_disc_gpn_ft_resp()
558 * fc_disc_gpn_id_resp() - Handle a response frame from Get Port Names (GPN_ID)
576 lport = rdata->local_port; in fc_disc_gpn_id_resp()
577 disc = &lport->disc; in fc_disc_gpn_id_resp()
579 if (PTR_ERR(fp) == -FC_EX_CLOSED) in fc_disc_gpn_id_resp()
582 mutex_lock(&disc->disc_mutex); in fc_disc_gpn_id_resp()
584 mutex_unlock(&disc->disc_mutex); in fc_disc_gpn_id_resp()
591 if (ntohs(cp->ct_cmd) == FC_FS_ACC) { in fc_disc_gpn_id_resp()
596 port_name = get_unaligned_be64(&pn->fn_wwpn); in fc_disc_gpn_id_resp()
597 mutex_lock(&rdata->rp_mutex); in fc_disc_gpn_id_resp()
598 if (rdata->ids.port_name == -1) in fc_disc_gpn_id_resp()
599 rdata->ids.port_name = port_name; in fc_disc_gpn_id_resp()
600 else if (rdata->ids.port_name != port_name) { in fc_disc_gpn_id_resp()
602 "Port-id %6.6x wwpn %16.16llx\n", in fc_disc_gpn_id_resp()
603 rdata->ids.port_id, port_name); in fc_disc_gpn_id_resp()
604 mutex_unlock(&rdata->rp_mutex); in fc_disc_gpn_id_resp()
606 mutex_lock(&lport->disc.disc_mutex); in fc_disc_gpn_id_resp()
607 new_rdata = fc_rport_create(lport, rdata->ids.port_id); in fc_disc_gpn_id_resp()
608 mutex_unlock(&lport->disc.disc_mutex); in fc_disc_gpn_id_resp()
610 new_rdata->disc_id = disc->disc_id; in fc_disc_gpn_id_resp()
615 rdata->disc_id = disc->disc_id; in fc_disc_gpn_id_resp()
616 mutex_unlock(&rdata->rp_mutex); in fc_disc_gpn_id_resp()
618 } else if (ntohs(cp->ct_cmd) == FC_FS_RJT) { in fc_disc_gpn_id_resp()
620 cp->ct_reason, cp->ct_explan); in fc_disc_gpn_id_resp()
624 ntohs(cp->ct_cmd)); in fc_disc_gpn_id_resp()
626 mutex_lock(&disc->disc_mutex); in fc_disc_gpn_id_resp()
628 mutex_unlock(&disc->disc_mutex); in fc_disc_gpn_id_resp()
633 kref_put(&rdata->kref, fc_rport_destroy); in fc_disc_gpn_id_resp()
637 * fc_disc_gpn_id_req() - Send Get Port Names by ID (GPN_ID) request
648 lockdep_assert_held(&lport->disc.disc_mutex); in fc_disc_gpn_id_req()
652 return -ENOMEM; in fc_disc_gpn_id_req()
653 if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, FC_NS_GPN_ID, in fc_disc_gpn_id_req()
655 3 * lport->r_a_tov)) in fc_disc_gpn_id_req()
656 return -ENOMEM; in fc_disc_gpn_id_req()
657 kref_get(&rdata->kref); in fc_disc_gpn_id_req()
662 * fc_disc_single() - Discover the directory information for a single target
670 lockdep_assert_held(&lport->disc.disc_mutex); in fc_disc_single()
672 rdata = fc_rport_create(lport, dp->port_id); in fc_disc_single()
674 return -ENOMEM; in fc_disc_single()
675 rdata->disc_id = 0; in fc_disc_single()
680 * fc_disc_stop() - Stop discovery for a given lport
685 struct fc_disc *disc = &lport->disc; in fc_disc_stop()
687 if (disc->pending) in fc_disc_stop()
688 cancel_delayed_work_sync(&disc->disc_work); in fc_disc_stop()
689 mutex_lock(&disc->disc_mutex); in fc_disc_stop()
691 mutex_unlock(&disc->disc_mutex); in fc_disc_stop()
695 * fc_disc_stop_final() - Stop discovery for a given lport
708 * fc_disc_config() - Configure the discovery layer for a local port
716 if (!lport->tt.disc_start) in fc_disc_config()
717 lport->tt.disc_start = fc_disc_start; in fc_disc_config()
719 if (!lport->tt.disc_stop) in fc_disc_config()
720 lport->tt.disc_stop = fc_disc_stop; in fc_disc_config()
722 if (!lport->tt.disc_stop_final) in fc_disc_config()
723 lport->tt.disc_stop_final = fc_disc_stop_final; in fc_disc_config()
725 if (!lport->tt.disc_recv_req) in fc_disc_config()
726 lport->tt.disc_recv_req = fc_disc_recv_req; in fc_disc_config()
728 disc = &lport->disc; in fc_disc_config()
730 disc->priv = priv; in fc_disc_config()
735 * fc_disc_init() - Initialize the discovery layer for a local port
740 struct fc_disc *disc = &lport->disc; in fc_disc_init()
742 INIT_DELAYED_WORK(&disc->disc_work, fc_disc_timeout); in fc_disc_init()
743 mutex_init(&disc->disc_mutex); in fc_disc_init()
744 INIT_LIST_HEAD(&disc->rports); in fc_disc_init()