xref: /openbmc/linux/drivers/scsi/libfc/fc_disc.c (revision b8bb76713ec50df2f11efee386e16f93d51e1076)
1 /*
2  * Copyright(c) 2007 - 2008 Intel Corporation. All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms and conditions of the GNU General Public License,
6  * version 2, as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope it will be useful, but WITHOUT
9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
11  * more details.
12  *
13  * You should have received a copy of the GNU General Public License along with
14  * this program; if not, write to the Free Software Foundation, Inc.,
15  * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
16  *
17  * Maintained at www.Open-FCoE.org
18  */
19 
20 /*
21  * Target Discovery
22  *
23  * This block discovers all FC-4 remote ports, including FCP initiators. It
24  * also handles RSCN events and re-discovery if necessary.
25  */
26 
27 /*
28  * DISC LOCKING
29  *
30  * The disc mutex is can be locked when acquiring rport locks, but may not
31  * be held when acquiring the lport lock. Refer to fc_lport.c for more
32  * details.
33  */
34 
35 #include <linux/timer.h>
36 #include <linux/err.h>
37 #include <asm/unaligned.h>
38 
39 #include <scsi/fc/fc_gs.h>
40 
41 #include <scsi/libfc.h>
42 
43 #define FC_DISC_RETRY_LIMIT	3	/* max retries */
44 #define FC_DISC_RETRY_DELAY	500UL	/* (msecs) delay */
45 
46 #define	FC_DISC_DELAY		3
47 
48 static int fc_disc_debug;
49 
50 #define FC_DEBUG_DISC(fmt...)			\
51 	do {					\
52 		if (fc_disc_debug)		\
53 			FC_DBG(fmt);		\
54 	} while (0)
55 
56 static void fc_disc_gpn_ft_req(struct fc_disc *);
57 static void fc_disc_gpn_ft_resp(struct fc_seq *, struct fc_frame *, void *);
58 static int fc_disc_new_target(struct fc_disc *, struct fc_rport *,
59 			      struct fc_rport_identifiers *);
60 static void fc_disc_del_target(struct fc_disc *, struct fc_rport *);
61 static void fc_disc_done(struct fc_disc *);
62 static void fc_disc_timeout(struct work_struct *);
63 static void fc_disc_single(struct fc_disc *, struct fc_disc_port *);
64 static void fc_disc_restart(struct fc_disc *);
65 
66 /**
67  * fc_disc_lookup_rport() - lookup a remote port by port_id
68  * @lport: Fibre Channel host port instance
69  * @port_id: remote port port_id to match
70  */
71 struct fc_rport *fc_disc_lookup_rport(const struct fc_lport *lport,
72 				      u32 port_id)
73 {
74 	const struct fc_disc *disc = &lport->disc;
75 	struct fc_rport *rport, *found = NULL;
76 	struct fc_rport_libfc_priv *rdata;
77 	int disc_found = 0;
78 
79 	list_for_each_entry(rdata, &disc->rports, peers) {
80 		rport = PRIV_TO_RPORT(rdata);
81 		if (rport->port_id == port_id) {
82 			disc_found = 1;
83 			found = rport;
84 			break;
85 		}
86 	}
87 
88 	if (!disc_found)
89 		found = NULL;
90 
91 	return found;
92 }
93 
94 /**
95  * fc_disc_stop_rports() - delete all the remote ports associated with the lport
96  * @disc: The discovery job to stop rports on
97  *
98  * Locking Note: This function expects that the lport mutex is locked before
99  * calling it.
100  */
101 void fc_disc_stop_rports(struct fc_disc *disc)
102 {
103 	struct fc_lport *lport;
104 	struct fc_rport *rport;
105 	struct fc_rport_libfc_priv *rdata, *next;
106 
107 	lport = disc->lport;
108 
109 	mutex_lock(&disc->disc_mutex);
110 	list_for_each_entry_safe(rdata, next, &disc->rports, peers) {
111 		rport = PRIV_TO_RPORT(rdata);
112 		list_del(&rdata->peers);
113 		lport->tt.rport_logoff(rport);
114 	}
115 
116 	mutex_unlock(&disc->disc_mutex);
117 }
118 
119 /**
120  * fc_disc_rport_callback() - Event handler for rport events
121  * @lport: The lport which is receiving the event
122  * @rport: The rport which the event has occured on
123  * @event: The event that occured
124  *
125  * Locking Note: The rport lock should not be held when calling
126  *		 this function.
127  */
128 static void fc_disc_rport_callback(struct fc_lport *lport,
129 				   struct fc_rport *rport,
130 				   enum fc_rport_event event)
131 {
132 	struct fc_rport_libfc_priv *rdata = rport->dd_data;
133 	struct fc_disc *disc = &lport->disc;
134 	int found = 0;
135 
136 	FC_DEBUG_DISC("Received a %d event for port (%6x)\n", event,
137 		      rport->port_id);
138 
139 	if (event == RPORT_EV_CREATED) {
140 		if (disc) {
141 			found = 1;
142 			mutex_lock(&disc->disc_mutex);
143 			list_add_tail(&rdata->peers, &disc->rports);
144 			mutex_unlock(&disc->disc_mutex);
145 		}
146 	}
147 
148 	if (!found)
149 		FC_DEBUG_DISC("The rport (%6x) is not maintained "
150 			      "by the discovery layer\n", rport->port_id);
151 }
152 
153 /**
154  * fc_disc_recv_rscn_req() - Handle Registered State Change Notification (RSCN)
155  * @sp: Current sequence of the RSCN exchange
156  * @fp: RSCN Frame
157  * @lport: Fibre Channel host port instance
158  *
159  * Locking Note: This function expects that the disc_mutex is locked
160  *		 before it is called.
161  */
162 static void fc_disc_recv_rscn_req(struct fc_seq *sp, struct fc_frame *fp,
163 				  struct fc_disc *disc)
164 {
165 	struct fc_lport *lport;
166 	struct fc_rport *rport;
167 	struct fc_rport_libfc_priv *rdata;
168 	struct fc_els_rscn *rp;
169 	struct fc_els_rscn_page *pp;
170 	struct fc_seq_els_data rjt_data;
171 	unsigned int len;
172 	int redisc = 0;
173 	enum fc_els_rscn_ev_qual ev_qual;
174 	enum fc_els_rscn_addr_fmt fmt;
175 	LIST_HEAD(disc_ports);
176 	struct fc_disc_port *dp, *next;
177 
178 	lport = disc->lport;
179 
180 	FC_DEBUG_DISC("Received an RSCN event on port (%6x)\n",
181 		      fc_host_port_id(lport->host));
182 
183 	/* make sure the frame contains an RSCN message */
184 	rp = fc_frame_payload_get(fp, sizeof(*rp));
185 	if (!rp)
186 		goto reject;
187 	/* make sure the page length is as expected (4 bytes) */
188 	if (rp->rscn_page_len != sizeof(*pp))
189 		goto reject;
190 	/* get the RSCN payload length */
191 	len = ntohs(rp->rscn_plen);
192 	if (len < sizeof(*rp))
193 		goto reject;
194 	/* make sure the frame contains the expected payload */
195 	rp = fc_frame_payload_get(fp, len);
196 	if (!rp)
197 		goto reject;
198 	/* payload must be a multiple of the RSCN page size */
199 	len -= sizeof(*rp);
200 	if (len % sizeof(*pp))
201 		goto reject;
202 
203 	for (pp = (void *)(rp + 1); len > 0; len -= sizeof(*pp), pp++) {
204 		ev_qual = pp->rscn_page_flags >> ELS_RSCN_EV_QUAL_BIT;
205 		ev_qual &= ELS_RSCN_EV_QUAL_MASK;
206 		fmt = pp->rscn_page_flags >> ELS_RSCN_ADDR_FMT_BIT;
207 		fmt &= ELS_RSCN_ADDR_FMT_MASK;
208 		/*
209 		 * if we get an address format other than port
210 		 * (area, domain, fabric), then do a full discovery
211 		 */
212 		switch (fmt) {
213 		case ELS_ADDR_FMT_PORT:
214 			FC_DEBUG_DISC("Port address format for port (%6x)\n",
215 				      ntoh24(pp->rscn_fid));
216 			dp = kzalloc(sizeof(*dp), GFP_KERNEL);
217 			if (!dp) {
218 				redisc = 1;
219 				break;
220 			}
221 			dp->lp = lport;
222 			dp->ids.port_id = ntoh24(pp->rscn_fid);
223 			dp->ids.port_name = -1;
224 			dp->ids.node_name = -1;
225 			dp->ids.roles = FC_RPORT_ROLE_UNKNOWN;
226 			list_add_tail(&dp->peers, &disc_ports);
227 			break;
228 		case ELS_ADDR_FMT_AREA:
229 		case ELS_ADDR_FMT_DOM:
230 		case ELS_ADDR_FMT_FAB:
231 		default:
232 			FC_DEBUG_DISC("Address format is (%d)\n", fmt);
233 			redisc = 1;
234 			break;
235 		}
236 	}
237 	lport->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL);
238 	if (redisc) {
239 		FC_DEBUG_DISC("RSCN received: rediscovering\n");
240 		fc_disc_restart(disc);
241 	} else {
242 		FC_DEBUG_DISC("RSCN received: not rediscovering. "
243 			      "redisc %d state %d in_prog %d\n",
244 			      redisc, lport->state, disc->pending);
245 		list_for_each_entry_safe(dp, next, &disc_ports, peers) {
246 			list_del(&dp->peers);
247 			rport = lport->tt.rport_lookup(lport, dp->ids.port_id);
248 			if (rport) {
249 				rdata = rport->dd_data;
250 				list_del(&rdata->peers);
251 				lport->tt.rport_logoff(rport);
252 			}
253 			fc_disc_single(disc, dp);
254 		}
255 	}
256 	fc_frame_free(fp);
257 	return;
258 reject:
259 	FC_DEBUG_DISC("Received a bad RSCN frame\n");
260 	rjt_data.fp = NULL;
261 	rjt_data.reason = ELS_RJT_LOGIC;
262 	rjt_data.explan = ELS_EXPL_NONE;
263 	lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data);
264 	fc_frame_free(fp);
265 }
266 
267 /**
268  * fc_disc_recv_req() - Handle incoming requests
269  * @sp: Current sequence of the request exchange
270  * @fp: The frame
271  * @lport: The FC local port
272  *
273  * Locking Note: This function is called from the EM and will lock
274  *		 the disc_mutex before calling the handler for the
275  *		 request.
276  */
277 static void fc_disc_recv_req(struct fc_seq *sp, struct fc_frame *fp,
278 			     struct fc_lport *lport)
279 {
280 	u8 op;
281 	struct fc_disc *disc = &lport->disc;
282 
283 	op = fc_frame_payload_op(fp);
284 	switch (op) {
285 	case ELS_RSCN:
286 		mutex_lock(&disc->disc_mutex);
287 		fc_disc_recv_rscn_req(sp, fp, disc);
288 		mutex_unlock(&disc->disc_mutex);
289 		break;
290 	default:
291 		FC_DBG("Received an unsupported request. opcode (%x)\n", op);
292 		break;
293 	}
294 }
295 
296 /**
297  * fc_disc_restart() - Restart discovery
298  * @lport: FC discovery context
299  *
300  * Locking Note: This function expects that the disc mutex
301  *		 is already locked.
302  */
303 static void fc_disc_restart(struct fc_disc *disc)
304 {
305 	struct fc_rport *rport;
306 	struct fc_rport_libfc_priv *rdata, *next;
307 	struct fc_lport *lport = disc->lport;
308 
309 	FC_DEBUG_DISC("Restarting discovery for port (%6x)\n",
310 		      fc_host_port_id(lport->host));
311 
312 	list_for_each_entry_safe(rdata, next, &disc->rports, peers) {
313 		rport = PRIV_TO_RPORT(rdata);
314 		FC_DEBUG_DISC("list_del(%6x)\n", rport->port_id);
315 		list_del(&rdata->peers);
316 		lport->tt.rport_logoff(rport);
317 	}
318 
319 	disc->requested = 1;
320 	if (!disc->pending)
321 		fc_disc_gpn_ft_req(disc);
322 }
323 
324 /**
325  * fc_disc_start() - Fibre Channel Target discovery
326  * @lport: FC local port
327  *
328  * Returns non-zero if discovery cannot be started.
329  */
330 static void fc_disc_start(void (*disc_callback)(struct fc_lport *,
331 						enum fc_disc_event),
332 			  struct fc_lport *lport)
333 {
334 	struct fc_rport *rport;
335 	struct fc_rport_identifiers ids;
336 	struct fc_disc *disc = &lport->disc;
337 
338 	/*
339 	 * At this point we may have a new disc job or an existing
340 	 * one. Either way, let's lock when we make changes to it
341 	 * and send the GPN_FT request.
342 	 */
343 	mutex_lock(&disc->disc_mutex);
344 
345 	disc->disc_callback = disc_callback;
346 
347 	/*
348 	 * If not ready, or already running discovery, just set request flag.
349 	 */
350 	disc->requested = 1;
351 
352 	if (disc->pending) {
353 		mutex_unlock(&disc->disc_mutex);
354 		return;
355 	}
356 
357 	/*
358 	 * Handle point-to-point mode as a simple discovery
359 	 * of the remote port. Yucky, yucky, yuck, yuck!
360 	 */
361 	rport = disc->lport->ptp_rp;
362 	if (rport) {
363 		ids.port_id = rport->port_id;
364 		ids.port_name = rport->port_name;
365 		ids.node_name = rport->node_name;
366 		ids.roles = FC_RPORT_ROLE_UNKNOWN;
367 		get_device(&rport->dev);
368 
369 		if (!fc_disc_new_target(disc, rport, &ids)) {
370 			disc->event = DISC_EV_SUCCESS;
371 			fc_disc_done(disc);
372 		}
373 		put_device(&rport->dev);
374 	} else {
375 		fc_disc_gpn_ft_req(disc);	/* get ports by FC-4 type */
376 	}
377 
378 	mutex_unlock(&disc->disc_mutex);
379 }
380 
381 static struct fc_rport_operations fc_disc_rport_ops = {
382 	.event_callback = fc_disc_rport_callback,
383 };
384 
385 /**
386  * fc_disc_new_target() - Handle new target found by discovery
387  * @lport: FC local port
388  * @rport: The previous FC remote port (NULL if new remote port)
389  * @ids: Identifiers for the new FC remote port
390  *
391  * Locking Note: This function expects that the disc_mutex is locked
392  *		 before it is called.
393  */
394 static int fc_disc_new_target(struct fc_disc *disc,
395 			      struct fc_rport *rport,
396 			      struct fc_rport_identifiers *ids)
397 {
398 	struct fc_lport *lport = disc->lport;
399 	struct fc_rport_libfc_priv *rdata;
400 	int error = 0;
401 
402 	if (rport && ids->port_name) {
403 		if (rport->port_name == -1) {
404 			/*
405 			 * Set WWN and fall through to notify of create.
406 			 */
407 			fc_rport_set_name(rport, ids->port_name,
408 					  rport->node_name);
409 		} else if (rport->port_name != ids->port_name) {
410 			/*
411 			 * This is a new port with the same FCID as
412 			 * a previously-discovered port.  Presumably the old
413 			 * port logged out and a new port logged in and was
414 			 * assigned the same FCID.  This should be rare.
415 			 * Delete the old one and fall thru to re-create.
416 			 */
417 			fc_disc_del_target(disc, rport);
418 			rport = NULL;
419 		}
420 	}
421 	if (((ids->port_name != -1) || (ids->port_id != -1)) &&
422 	    ids->port_id != fc_host_port_id(lport->host) &&
423 	    ids->port_name != lport->wwpn) {
424 		if (!rport) {
425 			rport = lport->tt.rport_lookup(lport, ids->port_id);
426 			if (!rport) {
427 				struct fc_disc_port dp;
428 				dp.lp = lport;
429 				dp.ids.port_id = ids->port_id;
430 				dp.ids.port_name = ids->port_name;
431 				dp.ids.node_name = ids->node_name;
432 				dp.ids.roles = ids->roles;
433 				rport = lport->tt.rport_create(&dp);
434 			}
435 			if (!rport)
436 				error = -ENOMEM;
437 		}
438 		if (rport) {
439 			rdata = rport->dd_data;
440 			rdata->ops = &fc_disc_rport_ops;
441 			rdata->rp_state = RPORT_ST_INIT;
442 			lport->tt.rport_login(rport);
443 		}
444 	}
445 	return error;
446 }
447 
448 /**
449  * fc_disc_del_target() - Delete a target
450  * @disc: FC discovery context
451  * @rport: The remote port to be removed
452  */
453 static void fc_disc_del_target(struct fc_disc *disc, struct fc_rport *rport)
454 {
455 	struct fc_lport *lport = disc->lport;
456 	struct fc_rport_libfc_priv *rdata = rport->dd_data;
457 	list_del(&rdata->peers);
458 	lport->tt.rport_logoff(rport);
459 }
460 
461 /**
462  * fc_disc_done() - Discovery has been completed
463  * @disc: FC discovery context
464  */
465 static void fc_disc_done(struct fc_disc *disc)
466 {
467 	struct fc_lport *lport = disc->lport;
468 
469 	FC_DEBUG_DISC("Discovery complete for port (%6x)\n",
470 		      fc_host_port_id(lport->host));
471 
472 	disc->disc_callback(lport, disc->event);
473 	disc->event = DISC_EV_NONE;
474 
475 	if (disc->requested)
476 		fc_disc_gpn_ft_req(disc);
477 	else
478 		disc->pending = 0;
479 }
480 
481 /**
482  * fc_disc_error() - Handle error on dNS request
483  * @disc: FC discovery context
484  * @fp: The frame pointer
485  */
486 static void fc_disc_error(struct fc_disc *disc, struct fc_frame *fp)
487 {
488 	struct fc_lport *lport = disc->lport;
489 	unsigned long delay = 0;
490 	if (fc_disc_debug)
491 		FC_DBG("Error %ld, retries %d/%d\n",
492 		       PTR_ERR(fp), disc->retry_count,
493 		       FC_DISC_RETRY_LIMIT);
494 
495 	if (!fp || PTR_ERR(fp) == -FC_EX_TIMEOUT) {
496 		/*
497 		 * Memory allocation failure, or the exchange timed out,
498 		 * retry after delay.
499 		 */
500 		if (disc->retry_count < FC_DISC_RETRY_LIMIT) {
501 			/* go ahead and retry */
502 			if (!fp)
503 				delay = msecs_to_jiffies(FC_DISC_RETRY_DELAY);
504 			else {
505 				delay = msecs_to_jiffies(lport->e_d_tov);
506 
507 				/* timeout faster first time */
508 				if (!disc->retry_count)
509 					delay /= 4;
510 			}
511 			disc->retry_count++;
512 			schedule_delayed_work(&disc->disc_work, delay);
513 		} else {
514 			/* exceeded retries */
515 			disc->event = DISC_EV_FAILED;
516 			fc_disc_done(disc);
517 		}
518 	}
519 }
520 
521 /**
522  * fc_disc_gpn_ft_req() - Send Get Port Names by FC-4 type (GPN_FT) request
523  * @lport: FC discovery context
524  *
525  * Locking Note: This function expects that the disc_mutex is locked
526  *		 before it is called.
527  */
528 static void fc_disc_gpn_ft_req(struct fc_disc *disc)
529 {
530 	struct fc_frame *fp;
531 	struct fc_lport *lport = disc->lport;
532 
533 	WARN_ON(!fc_lport_test_ready(lport));
534 
535 	disc->pending = 1;
536 	disc->requested = 0;
537 
538 	disc->buf_len = 0;
539 	disc->seq_count = 0;
540 	fp = fc_frame_alloc(lport,
541 			    sizeof(struct fc_ct_hdr) +
542 			    sizeof(struct fc_ns_gid_ft));
543 	if (!fp)
544 		goto err;
545 
546 	if (lport->tt.elsct_send(lport, NULL, fp,
547 				 FC_NS_GPN_FT,
548 				 fc_disc_gpn_ft_resp,
549 				 disc, lport->e_d_tov))
550 		return;
551 err:
552 	fc_disc_error(disc, fp);
553 }
554 
555 /**
556  * fc_disc_gpn_ft_parse() - Parse the list of IDs and names resulting from a request
557  * @lport: Fibre Channel host port instance
558  * @buf: GPN_FT response buffer
559  * @len: size of response buffer
560  */
561 static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len)
562 {
563 	struct fc_lport *lport;
564 	struct fc_gpn_ft_resp *np;
565 	char *bp;
566 	size_t plen;
567 	size_t tlen;
568 	int error = 0;
569 	struct fc_disc_port dp;
570 	struct fc_rport *rport;
571 	struct fc_rport_libfc_priv *rdata;
572 
573 	lport = disc->lport;
574 
575 	/*
576 	 * Handle partial name record left over from previous call.
577 	 */
578 	bp = buf;
579 	plen = len;
580 	np = (struct fc_gpn_ft_resp *)bp;
581 	tlen = disc->buf_len;
582 	if (tlen) {
583 		WARN_ON(tlen >= sizeof(*np));
584 		plen = sizeof(*np) - tlen;
585 		WARN_ON(plen <= 0);
586 		WARN_ON(plen >= sizeof(*np));
587 		if (plen > len)
588 			plen = len;
589 		np = &disc->partial_buf;
590 		memcpy((char *)np + tlen, bp, plen);
591 
592 		/*
593 		 * Set bp so that the loop below will advance it to the
594 		 * first valid full name element.
595 		 */
596 		bp -= tlen;
597 		len += tlen;
598 		plen += tlen;
599 		disc->buf_len = (unsigned char) plen;
600 		if (plen == sizeof(*np))
601 			disc->buf_len = 0;
602 	}
603 
604 	/*
605 	 * Handle full name records, including the one filled from above.
606 	 * Normally, np == bp and plen == len, but from the partial case above,
607 	 * bp, len describe the overall buffer, and np, plen describe the
608 	 * partial buffer, which if would usually be full now.
609 	 * After the first time through the loop, things return to "normal".
610 	 */
611 	while (plen >= sizeof(*np)) {
612 		dp.lp = lport;
613 		dp.ids.port_id = ntoh24(np->fp_fid);
614 		dp.ids.port_name = ntohll(np->fp_wwpn);
615 		dp.ids.node_name = -1;
616 		dp.ids.roles = FC_RPORT_ROLE_UNKNOWN;
617 
618 		if ((dp.ids.port_id != fc_host_port_id(lport->host)) &&
619 		    (dp.ids.port_name != lport->wwpn)) {
620 			rport = lport->tt.rport_create(&dp);
621 			if (rport) {
622 				rdata = rport->dd_data;
623 				rdata->ops = &fc_disc_rport_ops;
624 				rdata->local_port = lport;
625 				lport->tt.rport_login(rport);
626 			} else
627 				FC_DBG("Failed to allocate memory for "
628 				       "the newly discovered port (%6x)\n",
629 				       dp.ids.port_id);
630 		}
631 
632 		if (np->fp_flags & FC_NS_FID_LAST) {
633 			disc->event = DISC_EV_SUCCESS;
634 			fc_disc_done(disc);
635 			len = 0;
636 			break;
637 		}
638 		len -= sizeof(*np);
639 		bp += sizeof(*np);
640 		np = (struct fc_gpn_ft_resp *)bp;
641 		plen = len;
642 	}
643 
644 	/*
645 	 * Save any partial record at the end of the buffer for next time.
646 	 */
647 	if (error == 0 && len > 0 && len < sizeof(*np)) {
648 		if (np != &disc->partial_buf) {
649 			FC_DEBUG_DISC("Partial buffer remains "
650 				      "for discovery by (%6x)\n",
651 				      fc_host_port_id(lport->host));
652 			memcpy(&disc->partial_buf, np, len);
653 		}
654 		disc->buf_len = (unsigned char) len;
655 	} else {
656 		disc->buf_len = 0;
657 	}
658 	return error;
659 }
660 
661 /**
662  * fc_disc_timeout() - Retry handler for the disc component
663  * @work: Structure holding disc obj that needs retry discovery
664  *
665  * Handle retry of memory allocation for remote ports.
666  */
667 static void fc_disc_timeout(struct work_struct *work)
668 {
669 	struct fc_disc *disc = container_of(work,
670 					    struct fc_disc,
671 					    disc_work.work);
672 	mutex_lock(&disc->disc_mutex);
673 	if (disc->requested && !disc->pending)
674 		fc_disc_gpn_ft_req(disc);
675 	mutex_unlock(&disc->disc_mutex);
676 }
677 
678 /**
679  * fc_disc_gpn_ft_resp() - Handle a response frame from Get Port Names (GPN_FT)
680  * @sp: Current sequence of GPN_FT exchange
681  * @fp: response frame
682  * @lp_arg: Fibre Channel host port instance
683  *
684  * Locking Note: This function expects that the disc_mutex is locked
685  *		 before it is called.
686  */
687 static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp,
688 				void *disc_arg)
689 {
690 	struct fc_disc *disc = disc_arg;
691 	struct fc_ct_hdr *cp;
692 	struct fc_frame_header *fh;
693 	unsigned int seq_cnt;
694 	void *buf = NULL;
695 	unsigned int len;
696 	int error;
697 
698 	FC_DEBUG_DISC("Received a GPN_FT response on port (%6x)\n",
699 		      fc_host_port_id(disc->lport->host));
700 
701 	if (IS_ERR(fp)) {
702 		fc_disc_error(disc, fp);
703 		return;
704 	}
705 
706 	WARN_ON(!fc_frame_is_linear(fp));	/* buffer must be contiguous */
707 	fh = fc_frame_header_get(fp);
708 	len = fr_len(fp) - sizeof(*fh);
709 	seq_cnt = ntohs(fh->fh_seq_cnt);
710 	if (fr_sof(fp) == FC_SOF_I3 && seq_cnt == 0 &&
711 	    disc->seq_count == 0) {
712 		cp = fc_frame_payload_get(fp, sizeof(*cp));
713 		if (!cp) {
714 			FC_DBG("GPN_FT response too short, len %d\n",
715 			       fr_len(fp));
716 		} else if (ntohs(cp->ct_cmd) == FC_FS_ACC) {
717 
718 			/* Accepted, parse the response. */
719 			buf = cp + 1;
720 			len -= sizeof(*cp);
721 		} else if (ntohs(cp->ct_cmd) == FC_FS_RJT) {
722 			FC_DBG("GPN_FT rejected reason %x exp %x "
723 			       "(check zoning)\n", cp->ct_reason,
724 			       cp->ct_explan);
725 			disc->event = DISC_EV_FAILED;
726 			fc_disc_done(disc);
727 		} else {
728 			FC_DBG("GPN_FT unexpected response code %x\n",
729 			       ntohs(cp->ct_cmd));
730 		}
731 	} else if (fr_sof(fp) == FC_SOF_N3 &&
732 		   seq_cnt == disc->seq_count) {
733 		buf = fh + 1;
734 	} else {
735 		FC_DBG("GPN_FT unexpected frame - out of sequence? "
736 		       "seq_cnt %x expected %x sof %x eof %x\n",
737 		       seq_cnt, disc->seq_count, fr_sof(fp), fr_eof(fp));
738 	}
739 	if (buf) {
740 		error = fc_disc_gpn_ft_parse(disc, buf, len);
741 		if (error)
742 			fc_disc_error(disc, fp);
743 		else
744 			disc->seq_count++;
745 	}
746 	fc_frame_free(fp);
747 }
748 
749 /**
750  * fc_disc_single() - Discover the directory information for a single target
751  * @lport: FC local port
752  * @dp: The port to rediscover
753  *
754  * Locking Note: This function expects that the disc_mutex is locked
755  *		 before it is called.
756  */
757 static void fc_disc_single(struct fc_disc *disc, struct fc_disc_port *dp)
758 {
759 	struct fc_lport *lport;
760 	struct fc_rport *rport;
761 	struct fc_rport *new_rport;
762 	struct fc_rport_libfc_priv *rdata;
763 
764 	lport = disc->lport;
765 
766 	if (dp->ids.port_id == fc_host_port_id(lport->host))
767 		goto out;
768 
769 	rport = lport->tt.rport_lookup(lport, dp->ids.port_id);
770 	if (rport)
771 		fc_disc_del_target(disc, rport);
772 
773 	new_rport = lport->tt.rport_create(dp);
774 	if (new_rport) {
775 		rdata = new_rport->dd_data;
776 		rdata->ops = &fc_disc_rport_ops;
777 		kfree(dp);
778 		lport->tt.rport_login(new_rport);
779 	}
780 	return;
781 out:
782 	kfree(dp);
783 }
784 
785 /**
786  * fc_disc_stop() - Stop discovery for a given lport
787  * @lport: The lport that discovery should stop for
788  */
789 void fc_disc_stop(struct fc_lport *lport)
790 {
791 	struct fc_disc *disc = &lport->disc;
792 
793 	if (disc) {
794 		cancel_delayed_work_sync(&disc->disc_work);
795 		fc_disc_stop_rports(disc);
796 	}
797 }
798 
799 /**
800  * fc_disc_stop_final() - Stop discovery for a given lport
801  * @lport: The lport that discovery should stop for
802  *
803  * This function will block until discovery has been
804  * completely stopped and all rports have been deleted.
805  */
806 void fc_disc_stop_final(struct fc_lport *lport)
807 {
808 	fc_disc_stop(lport);
809 	lport->tt.rport_flush_queue();
810 }
811 
812 /**
813  * fc_disc_init() - Initialize the discovery block
814  * @lport: FC local port
815  */
816 int fc_disc_init(struct fc_lport *lport)
817 {
818 	struct fc_disc *disc;
819 
820 	if (!lport->tt.disc_start)
821 		lport->tt.disc_start = fc_disc_start;
822 
823 	if (!lport->tt.disc_stop)
824 		lport->tt.disc_stop = fc_disc_stop;
825 
826 	if (!lport->tt.disc_stop_final)
827 		lport->tt.disc_stop_final = fc_disc_stop_final;
828 
829 	if (!lport->tt.disc_recv_req)
830 		lport->tt.disc_recv_req = fc_disc_recv_req;
831 
832 	if (!lport->tt.rport_lookup)
833 		lport->tt.rport_lookup = fc_disc_lookup_rport;
834 
835 	disc = &lport->disc;
836 	INIT_DELAYED_WORK(&disc->disc_work, fc_disc_timeout);
837 	mutex_init(&disc->disc_mutex);
838 	INIT_LIST_HEAD(&disc->rports);
839 
840 	disc->lport = lport;
841 	disc->delay = FC_DISC_DELAY;
842 	disc->event = DISC_EV_NONE;
843 
844 	return 0;
845 }
846 EXPORT_SYMBOL(fc_disc_init);
847