Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Copyright(c) 2007 - 2008 Intel Corporation. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Maintained at www.Open-FCoE.org
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  * Target Discovery
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  * This block discovers all FC-4 remote ports, including FCP initiators. It
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  * also handles RSCN events and re-discovery if necessary.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16)  * DISC LOCKING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18)  * The disc mutex is can be locked when acquiring rport locks, but may not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19)  * be held when acquiring the lport lock. Refer to fc_lport.c for more
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20)  * details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #include <linux/timer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) #include <linux/rculist.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) #include <asm/unaligned.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) #include <scsi/fc/fc_gs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) #include <scsi/libfc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) #include "fc_libfc.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) #define FC_DISC_RETRY_LIMIT	3	/* max retries */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) #define FC_DISC_RETRY_DELAY	500UL	/* (msecs) delay */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) static void fc_disc_gpn_ft_req(struct fc_disc *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) static void fc_disc_gpn_ft_resp(struct fc_seq *, struct fc_frame *, void *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) static void fc_disc_done(struct fc_disc *, enum fc_disc_event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) static void fc_disc_timeout(struct work_struct *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) static int fc_disc_single(struct fc_lport *, struct fc_disc_port *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) static void fc_disc_restart(struct fc_disc *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48)  * fc_disc_stop_rports() - Delete all the remote ports associated with the lport
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49)  * @disc: The discovery job to stop remote ports on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) static void fc_disc_stop_rports(struct fc_disc *disc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	struct fc_rport_priv *rdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	lockdep_assert_held(&disc->disc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	list_for_each_entry(rdata, &disc->rports, peers) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 		if (kref_get_unless_zero(&rdata->kref)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 			fc_rport_logoff(rdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 			kref_put(&rdata->kref, fc_rport_destroy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66)  * fc_disc_recv_rscn_req() - Handle Registered State Change Notification (RSCN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67)  * @disc:  The discovery object to which the RSCN applies
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68)  * @fp:	   The RSCN frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) static void fc_disc_recv_rscn_req(struct fc_disc *disc, struct fc_frame *fp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	struct fc_lport *lport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	struct fc_els_rscn *rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	struct fc_els_rscn_page *pp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	struct fc_seq_els_data rjt_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	unsigned int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	int redisc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	enum fc_els_rscn_ev_qual ev_qual;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	enum fc_els_rscn_addr_fmt fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	LIST_HEAD(disc_ports);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	struct fc_disc_port *dp, *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	lockdep_assert_held(&disc->disc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	lport = fc_disc_lport(disc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	FC_DISC_DBG(disc, "Received an RSCN event\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	/* make sure the frame contains an RSCN message */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	rp = fc_frame_payload_get(fp, sizeof(*rp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	if (!rp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 		goto reject;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	/* make sure the page length is as expected (4 bytes) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	if (rp->rscn_page_len != sizeof(*pp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 		goto reject;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	/* get the RSCN payload length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	len = ntohs(rp->rscn_plen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	if (len < sizeof(*rp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 		goto reject;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	/* make sure the frame contains the expected payload */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	rp = fc_frame_payload_get(fp, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	if (!rp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 		goto reject;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	/* payload must be a multiple of the RSCN page size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	len -= sizeof(*rp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	if (len % sizeof(*pp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 		goto reject;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	for (pp = (void *)(rp + 1); len > 0; len -= sizeof(*pp), pp++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 		ev_qual = pp->rscn_page_flags >> ELS_RSCN_EV_QUAL_BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 		ev_qual &= ELS_RSCN_EV_QUAL_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 		fmt = pp->rscn_page_flags >> ELS_RSCN_ADDR_FMT_BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 		fmt &= ELS_RSCN_ADDR_FMT_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 		 * if we get an address format other than port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 		 * (area, domain, fabric), then do a full discovery
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 		switch (fmt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 		case ELS_ADDR_FMT_PORT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 			FC_DISC_DBG(disc, "Port address format for port "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 				    "(%6.6x)\n", ntoh24(pp->rscn_fid));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 			dp = kzalloc(sizeof(*dp), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 			if (!dp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 				redisc = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 			dp->lp = lport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 			dp->port_id = ntoh24(pp->rscn_fid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 			list_add_tail(&dp->peers, &disc_ports);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 		case ELS_ADDR_FMT_AREA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 		case ELS_ADDR_FMT_DOM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 		case ELS_ADDR_FMT_FAB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 			FC_DISC_DBG(disc, "Address format is (%d)\n", fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 			redisc = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	fc_seq_els_rsp_send(fp, ELS_LS_ACC, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	 * If not doing a complete rediscovery, do GPN_ID on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	 * the individual ports mentioned in the list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	 * If any of these get an error, do a full rediscovery.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	 * In any case, go through the list and free the entries.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	list_for_each_entry_safe(dp, next, &disc_ports, peers) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 		list_del(&dp->peers);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 		if (!redisc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 			redisc = fc_disc_single(lport, dp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 		kfree(dp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	if (redisc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 		FC_DISC_DBG(disc, "RSCN received: rediscovering\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 		fc_disc_restart(disc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 		FC_DISC_DBG(disc, "RSCN received: not rediscovering. "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 			    "redisc %d state %d in_prog %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 			    redisc, lport->state, disc->pending);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	fc_frame_free(fp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) reject:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	FC_DISC_DBG(disc, "Received a bad RSCN frame\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	rjt_data.reason = ELS_RJT_LOGIC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	rjt_data.explan = ELS_EXPL_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	fc_seq_els_rsp_send(fp, ELS_LS_RJT, &rjt_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	fc_frame_free(fp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)  * fc_disc_recv_req() - Handle incoming requests
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)  * @lport: The local port receiving the request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)  * @fp:	   The request frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)  * Locking Note: This function is called from the EM and will lock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)  *		 the disc_mutex before calling the handler for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)  *		 request.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) static void fc_disc_recv_req(struct fc_lport *lport, struct fc_frame *fp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	u8 op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 	struct fc_disc *disc = &lport->disc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 	op = fc_frame_payload_op(fp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	switch (op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	case ELS_RSCN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 		mutex_lock(&disc->disc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 		fc_disc_recv_rscn_req(disc, fp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 		mutex_unlock(&disc->disc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 		FC_DISC_DBG(disc, "Received an unsupported request, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 			    "the opcode is (%x)\n", op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 		fc_frame_free(fp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)  * fc_disc_restart() - Restart discovery
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)  * @disc: The discovery object to be restarted
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) static void fc_disc_restart(struct fc_disc *disc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	lockdep_assert_held(&disc->disc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 	if (!disc->disc_callback)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 	FC_DISC_DBG(disc, "Restarting discovery\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 	disc->requested = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	if (disc->pending)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 	 * Advance disc_id.  This is an arbitrary non-zero number that will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	 * match the value in the fc_rport_priv after discovery for all
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 	 * freshly-discovered remote ports.  Avoid wrapping to zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 	disc->disc_id = (disc->disc_id + 2) | 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	disc->retry_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	fc_disc_gpn_ft_req(disc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)  * fc_disc_start() - Start discovery on a local port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)  * @lport:	   The local port to have discovery started on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)  * @disc_callback: Callback function to be called when discovery is complete
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) static void fc_disc_start(void (*disc_callback)(struct fc_lport *,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 						enum fc_disc_event),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 			  struct fc_lport *lport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 	struct fc_disc *disc = &lport->disc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 	 * At this point we may have a new disc job or an existing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 	 * one. Either way, let's lock when we make changes to it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	 * and send the GPN_FT request.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	mutex_lock(&disc->disc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	disc->disc_callback = disc_callback;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	fc_disc_restart(disc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 	mutex_unlock(&disc->disc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)  * fc_disc_done() - Discovery has been completed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)  * @disc:  The discovery context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)  * @event: The discovery completion status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) static void fc_disc_done(struct fc_disc *disc, enum fc_disc_event event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 	struct fc_lport *lport = fc_disc_lport(disc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	struct fc_rport_priv *rdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 	lockdep_assert_held(&disc->disc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 	FC_DISC_DBG(disc, "Discovery complete\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	disc->pending = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	if (disc->requested) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 		fc_disc_restart(disc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	 * Go through all remote ports.	 If they were found in the latest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 	 * discovery, reverify or log them in.	Otherwise, log them out.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 	 * Skip ports which were never discovered.  These are the dNS port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 	 * and ports which were created by PLOGI.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 	 * We don't need to use the _rcu variant here as the rport list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 	 * is protected by the disc mutex which is already held on entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	list_for_each_entry(rdata, &disc->rports, peers) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 		if (!kref_get_unless_zero(&rdata->kref))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 		if (rdata->disc_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 			if (rdata->disc_id == disc->disc_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 				fc_rport_login(rdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 				fc_rport_logoff(rdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 		kref_put(&rdata->kref, fc_rport_destroy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 	mutex_unlock(&disc->disc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 	disc->disc_callback(lport, event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	mutex_lock(&disc->disc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)  * fc_disc_error() - Handle error on dNS request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)  * @disc: The discovery context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)  * @fp:	  The error code encoded as a frame pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) static void fc_disc_error(struct fc_disc *disc, struct fc_frame *fp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 	struct fc_lport *lport = fc_disc_lport(disc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 	unsigned long delay = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	FC_DISC_DBG(disc, "Error %d, retries %d/%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 		    PTR_ERR_OR_ZERO(fp), disc->retry_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 		    FC_DISC_RETRY_LIMIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 	if (!fp || PTR_ERR(fp) == -FC_EX_TIMEOUT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 		 * Memory allocation failure, or the exchange timed out,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 		 * retry after delay.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 		if (disc->retry_count < FC_DISC_RETRY_LIMIT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 			/* go ahead and retry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 			if (!fp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 				delay = msecs_to_jiffies(FC_DISC_RETRY_DELAY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 			else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 				delay = msecs_to_jiffies(lport->e_d_tov);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 				/* timeout faster first time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 				if (!disc->retry_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 					delay /= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 			disc->retry_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 			schedule_delayed_work(&disc->disc_work, delay);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 		} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 			fc_disc_done(disc, DISC_EV_FAILED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 	} else if (PTR_ERR(fp) == -FC_EX_CLOSED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 		 * if discovery fails due to lport reset, clear
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 		 * pending flag so that subsequent discovery can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 		 * continue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 		disc->pending = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)  * fc_disc_gpn_ft_req() - Send Get Port Names by FC-4 type (GPN_FT) request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)  * @disc: The discovery context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) static void fc_disc_gpn_ft_req(struct fc_disc *disc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 	struct fc_frame *fp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 	struct fc_lport *lport = fc_disc_lport(disc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 	lockdep_assert_held(&disc->disc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 	WARN_ON(!fc_lport_test_ready(lport));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 	disc->pending = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 	disc->requested = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 	disc->buf_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 	disc->seq_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 	fp = fc_frame_alloc(lport,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 			    sizeof(struct fc_ct_hdr) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 			    sizeof(struct fc_ns_gid_ft));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 	if (!fp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 		goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 	if (lport->tt.elsct_send(lport, 0, fp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 				 FC_NS_GPN_FT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 				 fc_disc_gpn_ft_resp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 				 disc, 3 * lport->r_a_tov))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 	fc_disc_error(disc, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)  * fc_disc_gpn_ft_parse() - Parse the body of the dNS GPN_FT response.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)  * @disc:  The discovery context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)  * @buf:   The GPN_FT response buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)  * @len:   The size of response buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)  * Goes through the list of IDs and names resulting from a request.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 	struct fc_lport *lport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 	struct fc_gpn_ft_resp *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 	char *bp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 	size_t plen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 	size_t tlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 	int error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 	struct fc_rport_identifiers ids;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 	struct fc_rport_priv *rdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 	lport = fc_disc_lport(disc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 	disc->seq_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 	 * Handle partial name record left over from previous call.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 	bp = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 	plen = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 	np = (struct fc_gpn_ft_resp *)bp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 	tlen = disc->buf_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 	disc->buf_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 	if (tlen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 		WARN_ON(tlen >= sizeof(*np));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 		plen = sizeof(*np) - tlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 		WARN_ON(plen <= 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 		WARN_ON(plen >= sizeof(*np));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 		if (plen > len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 			plen = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 		np = &disc->partial_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 		memcpy((char *)np + tlen, bp, plen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 		 * Set bp so that the loop below will advance it to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 		 * first valid full name element.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 		bp -= tlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 		len += tlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 		plen += tlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 		disc->buf_len = (unsigned char) plen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 		if (plen == sizeof(*np))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 			disc->buf_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 	 * Handle full name records, including the one filled from above.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 	 * Normally, np == bp and plen == len, but from the partial case above,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 	 * bp, len describe the overall buffer, and np, plen describe the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 	 * partial buffer, which if would usually be full now.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 	 * After the first time through the loop, things return to "normal".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 	while (plen >= sizeof(*np)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 		ids.port_id = ntoh24(np->fp_fid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 		ids.port_name = ntohll(np->fp_wwpn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 		if (ids.port_id != lport->port_id &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 		    ids.port_name != lport->wwpn) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 			rdata = fc_rport_create(lport, ids.port_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 			if (rdata) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 				rdata->ids.port_name = ids.port_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 				rdata->disc_id = disc->disc_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 				printk(KERN_WARNING "libfc: Failed to allocate "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 				       "memory for the newly discovered port "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 				       "(%6.6x)\n", ids.port_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 				error = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 		if (np->fp_flags & FC_NS_FID_LAST) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 			fc_disc_done(disc, DISC_EV_SUCCESS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 			len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 		len -= sizeof(*np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 		bp += sizeof(*np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 		np = (struct fc_gpn_ft_resp *)bp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 		plen = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 	 * Save any partial record at the end of the buffer for next time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 	if (error == 0 && len > 0 && len < sizeof(*np)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 		if (np != &disc->partial_buf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 			FC_DISC_DBG(disc, "Partial buffer remains "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 				    "for discovery\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 			memcpy(&disc->partial_buf, np, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 		disc->buf_len = (unsigned char) len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 	return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)  * fc_disc_timeout() - Handler for discovery timeouts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)  * @work: Structure holding discovery context that needs to retry discovery
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) static void fc_disc_timeout(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 	struct fc_disc *disc = container_of(work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 					    struct fc_disc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 					    disc_work.work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 	mutex_lock(&disc->disc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 	fc_disc_gpn_ft_req(disc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 	mutex_unlock(&disc->disc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)  * fc_disc_gpn_ft_resp() - Handle a response frame from Get Port Names (GPN_FT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)  * @sp:	    The sequence that the GPN_FT response was received on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)  * @fp:	    The GPN_FT response frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)  * @disc_arg: The discovery context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)  * Locking Note: This function is called without disc mutex held, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)  *		 should do all its processing with the mutex held
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 				void *disc_arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 	struct fc_disc *disc = disc_arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 	struct fc_ct_hdr *cp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 	struct fc_frame_header *fh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 	enum fc_disc_event event = DISC_EV_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 	unsigned int seq_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 	unsigned int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 	int error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 	mutex_lock(&disc->disc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 	FC_DISC_DBG(disc, "Received a GPN_FT response\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 	if (IS_ERR(fp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 		fc_disc_error(disc, fp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 		mutex_unlock(&disc->disc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 	WARN_ON(!fc_frame_is_linear(fp));	/* buffer must be contiguous */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 	fh = fc_frame_header_get(fp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 	len = fr_len(fp) - sizeof(*fh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 	seq_cnt = ntohs(fh->fh_seq_cnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 	if (fr_sof(fp) == FC_SOF_I3 && seq_cnt == 0 && disc->seq_count == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 		cp = fc_frame_payload_get(fp, sizeof(*cp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 		if (!cp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 			FC_DISC_DBG(disc, "GPN_FT response too short, len %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) 				    fr_len(fp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 			event = DISC_EV_FAILED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 		} else if (ntohs(cp->ct_cmd) == FC_FS_ACC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 			/* Accepted, parse the response. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 			len -= sizeof(*cp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 			error = fc_disc_gpn_ft_parse(disc, cp + 1, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 		} else if (ntohs(cp->ct_cmd) == FC_FS_RJT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 			FC_DISC_DBG(disc, "GPN_FT rejected reason %x exp %x "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) 				    "(check zoning)\n", cp->ct_reason,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 				    cp->ct_explan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) 			event = DISC_EV_FAILED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 			if (cp->ct_reason == FC_FS_RJT_UNABL &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 			    cp->ct_explan == FC_FS_EXP_FTNR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 				event = DISC_EV_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) 			FC_DISC_DBG(disc, "GPN_FT unexpected response code "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 				    "%x\n", ntohs(cp->ct_cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 			event = DISC_EV_FAILED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 	} else if (fr_sof(fp) == FC_SOF_N3 && seq_cnt == disc->seq_count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 		error = fc_disc_gpn_ft_parse(disc, fh + 1, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) 		FC_DISC_DBG(disc, "GPN_FT unexpected frame - out of sequence? "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 			    "seq_cnt %x expected %x sof %x eof %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 			    seq_cnt, disc->seq_count, fr_sof(fp), fr_eof(fp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 		event = DISC_EV_FAILED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 	if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 		fc_disc_error(disc, ERR_PTR(error));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 	else if (event != DISC_EV_NONE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 		fc_disc_done(disc, event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 	fc_frame_free(fp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 	mutex_unlock(&disc->disc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)  * fc_disc_gpn_id_resp() - Handle a response frame from Get Port Names (GPN_ID)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)  * @sp:	       The sequence the GPN_ID is on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)  * @fp:	       The response frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)  * @rdata_arg: The remote port that sent the GPN_ID response
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)  * Locking Note: This function is called without disc mutex held.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) static void fc_disc_gpn_id_resp(struct fc_seq *sp, struct fc_frame *fp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) 				void *rdata_arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) 	struct fc_rport_priv *rdata = rdata_arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 	struct fc_rport_priv *new_rdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) 	struct fc_lport *lport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) 	struct fc_disc *disc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 	struct fc_ct_hdr *cp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 	struct fc_ns_gid_pn *pn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) 	u64 port_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) 	lport = rdata->local_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 	disc = &lport->disc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) 	if (PTR_ERR(fp) == -FC_EX_CLOSED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) 	if (IS_ERR(fp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 		mutex_lock(&disc->disc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 		fc_disc_restart(disc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 		mutex_unlock(&disc->disc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) 	cp = fc_frame_payload_get(fp, sizeof(*cp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) 	if (!cp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 		goto redisc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 	if (ntohs(cp->ct_cmd) == FC_FS_ACC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 		if (fr_len(fp) < sizeof(struct fc_frame_header) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) 		    sizeof(*cp) + sizeof(*pn))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 			goto redisc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) 		pn = (struct fc_ns_gid_pn *)(cp + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) 		port_name = get_unaligned_be64(&pn->fn_wwpn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) 		mutex_lock(&rdata->rp_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) 		if (rdata->ids.port_name == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) 			rdata->ids.port_name = port_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) 		else if (rdata->ids.port_name != port_name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) 			FC_DISC_DBG(disc, "GPN_ID accepted.  WWPN changed. "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) 				    "Port-id %6.6x wwpn %16.16llx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 				    rdata->ids.port_id, port_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) 			mutex_unlock(&rdata->rp_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) 			fc_rport_logoff(rdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) 			mutex_lock(&lport->disc.disc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) 			new_rdata = fc_rport_create(lport, rdata->ids.port_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) 			mutex_unlock(&lport->disc.disc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) 			if (new_rdata) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) 				new_rdata->disc_id = disc->disc_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) 				fc_rport_login(new_rdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) 			goto free_fp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) 		rdata->disc_id = disc->disc_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) 		mutex_unlock(&rdata->rp_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) 		fc_rport_login(rdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) 	} else if (ntohs(cp->ct_cmd) == FC_FS_RJT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) 		FC_DISC_DBG(disc, "GPN_ID rejected reason %x exp %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) 			    cp->ct_reason, cp->ct_explan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) 		fc_rport_logoff(rdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) 		FC_DISC_DBG(disc, "GPN_ID unexpected response code %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) 			    ntohs(cp->ct_cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) redisc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) 		mutex_lock(&disc->disc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) 		fc_disc_restart(disc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) 		mutex_unlock(&disc->disc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) free_fp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) 	fc_frame_free(fp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) 	kref_put(&rdata->kref, fc_rport_destroy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)  * fc_disc_gpn_id_req() - Send Get Port Names by ID (GPN_ID) request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)  * @lport: The local port to initiate discovery on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)  * @rdata: remote port private data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)  * On failure, an error code is returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) static int fc_disc_gpn_id_req(struct fc_lport *lport,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) 			      struct fc_rport_priv *rdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) 	struct fc_frame *fp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) 	lockdep_assert_held(&lport->disc.disc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) 	fp = fc_frame_alloc(lport, sizeof(struct fc_ct_hdr) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) 			    sizeof(struct fc_ns_fid));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) 	if (!fp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) 	if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, FC_NS_GPN_ID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) 				  fc_disc_gpn_id_resp, rdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) 				  3 * lport->r_a_tov))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) 	kref_get(&rdata->kref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)  * fc_disc_single() - Discover the directory information for a single target
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)  * @lport: The local port the remote port is associated with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)  * @dp:	   The port to rediscover
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) static int fc_disc_single(struct fc_lport *lport, struct fc_disc_port *dp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) 	struct fc_rport_priv *rdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) 	lockdep_assert_held(&lport->disc.disc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) 	rdata = fc_rport_create(lport, dp->port_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) 	if (!rdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) 	rdata->disc_id = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) 	return fc_disc_gpn_id_req(lport, rdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)  * fc_disc_stop() - Stop discovery for a given lport
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)  * @lport: The local port that discovery should stop on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) static void fc_disc_stop(struct fc_lport *lport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) 	struct fc_disc *disc = &lport->disc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) 	if (disc->pending)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) 		cancel_delayed_work_sync(&disc->disc_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) 	mutex_lock(&disc->disc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) 	fc_disc_stop_rports(disc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) 	mutex_unlock(&disc->disc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)  * fc_disc_stop_final() - Stop discovery for a given lport
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)  * @lport: The lport that discovery should stop on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701)  * This function will block until discovery has been
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702)  * completely stopped and all rports have been deleted.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) static void fc_disc_stop_final(struct fc_lport *lport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) 	fc_disc_stop(lport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) 	fc_rport_flush_queue();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)  * fc_disc_config() - Configure the discovery layer for a local port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)  * @lport: The local port that needs the discovery layer to be configured
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713)  * @priv: Private data structre for users of the discovery layer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) void fc_disc_config(struct fc_lport *lport, void *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) 	struct fc_disc *disc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) 	if (!lport->tt.disc_start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) 		lport->tt.disc_start = fc_disc_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) 	if (!lport->tt.disc_stop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) 		lport->tt.disc_stop = fc_disc_stop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) 	if (!lport->tt.disc_stop_final)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) 		lport->tt.disc_stop_final = fc_disc_stop_final;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) 	if (!lport->tt.disc_recv_req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) 		lport->tt.disc_recv_req = fc_disc_recv_req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) 	disc = &lport->disc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) 	disc->priv = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) EXPORT_SYMBOL(fc_disc_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)  * fc_disc_init() - Initialize the discovery layer for a local port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)  * @lport: The local port that needs the discovery layer to be initialized
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) void fc_disc_init(struct fc_lport *lport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) 	struct fc_disc *disc = &lport->disc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) 	INIT_DELAYED_WORK(&disc->disc_work, fc_disc_timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) 	mutex_init(&disc->disc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) 	INIT_LIST_HEAD(&disc->rports);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) EXPORT_SYMBOL(fc_disc_init);