aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/libfc/fc_disc.c47
-rw-r--r--include/scsi/libfc.h3
2 files changed, 37 insertions, 13 deletions
diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c
index f6762a52147d..ddf494424ff4 100644
--- a/drivers/scsi/libfc/fc_disc.c
+++ b/drivers/scsi/libfc/fc_disc.c
@@ -221,17 +221,19 @@ static void fc_disc_recv_req(struct fc_seq *sp, struct fc_frame *fp,
221 */ 221 */
222static void fc_disc_restart(struct fc_disc *disc) 222static void fc_disc_restart(struct fc_disc *disc)
223{ 223{
224 struct fc_rport_priv *rdata, *next;
225 struct fc_lport *lport = disc->lport;
226
227 FC_DISC_DBG(disc, "Restarting discovery\n"); 224 FC_DISC_DBG(disc, "Restarting discovery\n");
228 225
229 list_for_each_entry_safe(rdata, next, &disc->rports, peers)
230 lport->tt.rport_logoff(rdata);
231
232 disc->requested = 1; 226 disc->requested = 1;
233 if (!disc->pending) 227 if (disc->pending)
234 fc_disc_gpn_ft_req(disc); 228 return;
229
230 /*
231 * Advance disc_id. This is an arbitrary non-zero number that will
232 * match the value in the fc_rport_priv after discovery for all
233 * freshly-discovered remote ports. Avoid wrapping to zero.
234 */
235 disc->disc_id = (disc->disc_id + 2) | 1;
236 fc_disc_gpn_ft_req(disc);
235} 237}
236 238
237/** 239/**
@@ -278,6 +280,7 @@ static void fc_disc_start(void (*disc_callback)(struct fc_lport *,
278 } 280 }
279 kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy); 281 kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy);
280 } else { 282 } else {
283 disc->disc_id = (disc->disc_id + 2) | 1;
281 fc_disc_gpn_ft_req(disc); /* get ports by FC-4 type */ 284 fc_disc_gpn_ft_req(disc); /* get ports by FC-4 type */
282 } 285 }
283 286
@@ -345,13 +348,30 @@ static int fc_disc_new_target(struct fc_disc *disc,
345static void fc_disc_done(struct fc_disc *disc, enum fc_disc_event event) 348static void fc_disc_done(struct fc_disc *disc, enum fc_disc_event event)
346{ 349{
347 struct fc_lport *lport = disc->lport; 350 struct fc_lport *lport = disc->lport;
351 struct fc_rport_priv *rdata;
348 352
349 FC_DISC_DBG(disc, "Discovery complete\n"); 353 FC_DISC_DBG(disc, "Discovery complete\n");
350 354
351 if (disc->requested) 355 disc->pending = 0;
352 fc_disc_gpn_ft_req(disc); 356 if (disc->requested) {
353 else 357 fc_disc_restart(disc);
354 disc->pending = 0; 358 return;
359 }
360
361 /*
362 * Go through all remote ports. If they were found in the latest
363 * discovery, reverify or log them in. Otherwise, log them out.
364 * Skip ports which were never discovered. These are the dNS port
365 * and ports which were created by PLOGI.
366 */
367 list_for_each_entry(rdata, &disc->rports, peers) {
368 if (!rdata->disc_id)
369 continue;
370 if (rdata->disc_id == disc->disc_id)
371 lport->tt.rport_login(rdata);
372 else
373 lport->tt.rport_logoff(rdata);
374 }
355 375
356 mutex_unlock(&disc->disc_mutex); 376 mutex_unlock(&disc->disc_mutex);
357 disc->disc_callback(lport, event); 377 disc->disc_callback(lport, event);
@@ -496,7 +516,7 @@ static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len)
496 ids.port_name != lport->wwpn) { 516 ids.port_name != lport->wwpn) {
497 rdata = lport->tt.rport_create(lport, &ids); 517 rdata = lport->tt.rport_create(lport, &ids);
498 if (rdata) 518 if (rdata)
499 lport->tt.rport_login(rdata); 519 rdata->disc_id = disc->disc_id;
500 else 520 else
501 printk(KERN_WARNING "libfc: Failed to allocate " 521 printk(KERN_WARNING "libfc: Failed to allocate "
502 "memory for the newly discovered port " 522 "memory for the newly discovered port "
@@ -640,6 +660,7 @@ static void fc_disc_single(struct fc_disc *disc, struct fc_disc_port *dp)
640 660
641 rdata = lport->tt.rport_create(lport, &dp->ids); 661 rdata = lport->tt.rport_create(lport, &dp->ids);
642 if (rdata) { 662 if (rdata) {
663 rdata->disc_id = disc->disc_id;
643 kfree(dp); 664 kfree(dp);
644 lport->tt.rport_login(rdata); 665 lport->tt.rport_login(rdata);
645 } 666 }
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index 093b0439a2cf..517dce5c8d0d 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -202,6 +202,7 @@ struct fc_rport_libfc_priv {
202 * @ids: remote port identifiers and roles 202 * @ids: remote port identifiers and roles
203 * @flags: REC and RETRY supported flags 203 * @flags: REC and RETRY supported flags
204 * @max_seq: maximum number of concurrent sequences 204 * @max_seq: maximum number of concurrent sequences
205 * @disc_id: discovery identifier
205 * @maxframe_size: maximum frame size 206 * @maxframe_size: maximum frame size
206 * @retries: retry count in current state 207 * @retries: retry count in current state
207 * @e_d_tov: error detect timeout value (in msec) 208 * @e_d_tov: error detect timeout value (in msec)
@@ -218,6 +219,7 @@ struct fc_rport_priv {
218 struct fc_rport_identifiers ids; 219 struct fc_rport_identifiers ids;
219 u16 flags; 220 u16 flags;
220 u16 max_seq; 221 u16 max_seq;
222 u16 disc_id;
221 u16 maxframe_size; 223 u16 maxframe_size;
222 unsigned int retries; 224 unsigned int retries;
223 unsigned int e_d_tov; 225 unsigned int e_d_tov;
@@ -678,6 +680,7 @@ struct fc_disc {
678 unsigned char requested; 680 unsigned char requested;
679 unsigned short seq_count; 681 unsigned short seq_count;
680 unsigned char buf_len; 682 unsigned char buf_len;
683 u16 disc_id;
681 684
682 void (*disc_callback)(struct fc_lport *, 685 void (*disc_callback)(struct fc_lport *,
683 enum fc_disc_event); 686 enum fc_disc_event);