diff options
-rw-r--r-- | drivers/scsi/libfc/fc_disc.c | 47 | ||||
-rw-r--r-- | include/scsi/libfc.h | 3 |
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 | */ |
222 | static void fc_disc_restart(struct fc_disc *disc) | 222 | static 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, | |||
345 | static void fc_disc_done(struct fc_disc *disc, enum fc_disc_event event) | 348 | static 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); |