diff options
author | James Smart <James.Smart@Emulex.Com> | 2008-08-24 21:49:45 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-10-13 09:28:53 -0400 |
commit | 90160e010b6f3a91a9bb044bbe6723731e6f366c (patch) | |
tree | 8320400d5bed96f1976cef88adcad647fcb48f9e /drivers/scsi/lpfc/lpfc_vport.c | |
parent | e59058c44025d71c9b7f260076a932935d3bba95 (diff) |
[SCSI] lpfc 8.2.8 : Miscellaneous Discovery Fixes
Miscellaneous Discovery fixes:
- Fix rejection followed by acceptance in handling RPL and RPS
unsolicited events
- Fix for vport delete crash
- Fix PLOGI vs ADISC race condition
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_vport.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_vport.c | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c index 109f89d98830..ad0f65313878 100644 --- a/drivers/scsi/lpfc/lpfc_vport.c +++ b/drivers/scsi/lpfc/lpfc_vport.c | |||
@@ -204,6 +204,77 @@ lpfc_unique_wwpn(struct lpfc_hba *phba, struct lpfc_vport *new_vport) | |||
204 | return 1; | 204 | return 1; |
205 | } | 205 | } |
206 | 206 | ||
207 | /** | ||
208 | * lpfc_discovery_wait: Wait for driver discovery to quiesce. | ||
209 | * @vport: The virtual port for which this call is being executed. | ||
210 | * | ||
211 | * This driver calls this routine specifically from lpfc_vport_delete | ||
212 | * to enforce a synchronous execution of vport | ||
213 | * delete relative to discovery activities. The | ||
214 | * lpfc_vport_delete routine should not return until it | ||
215 | * can reasonably guarantee that discovery has quiesced. | ||
216 | * Post FDISC LOGO, the driver must wait until its SAN teardown is | ||
217 | * complete and all resources recovered before allowing | ||
218 | * cleanup. | ||
219 | * | ||
220 | * This routine does not require any locks held. | ||
221 | **/ | ||
222 | static void lpfc_discovery_wait(struct lpfc_vport *vport) | ||
223 | { | ||
224 | struct lpfc_hba *phba = vport->phba; | ||
225 | uint32_t wait_flags = 0; | ||
226 | unsigned long wait_time_max; | ||
227 | unsigned long start_time; | ||
228 | |||
229 | wait_flags = FC_RSCN_MODE | FC_RSCN_DISCOVERY | FC_NLP_MORE | | ||
230 | FC_RSCN_DEFERRED | FC_NDISC_ACTIVE | FC_DISC_TMO; | ||
231 | |||
232 | /* | ||
233 | * The time constraint on this loop is a balance between the | ||
234 | * fabric RA_TOV value and dev_loss tmo. The driver's | ||
235 | * devloss_tmo is 10 giving this loop a 3x multiplier minimally. | ||
236 | */ | ||
237 | wait_time_max = msecs_to_jiffies(((phba->fc_ratov * 3) + 3) * 1000); | ||
238 | wait_time_max += jiffies; | ||
239 | start_time = jiffies; | ||
240 | while (time_before(jiffies, wait_time_max)) { | ||
241 | if ((vport->num_disc_nodes > 0) || | ||
242 | (vport->fc_flag & wait_flags) || | ||
243 | ((vport->port_state > LPFC_VPORT_FAILED) && | ||
244 | (vport->port_state < LPFC_VPORT_READY))) { | ||
245 | lpfc_printf_log(phba, KERN_INFO, LOG_VPORT, | ||
246 | "1833 Vport discovery quiesce Wait:" | ||
247 | " vpi x%x state x%x fc_flags x%x" | ||
248 | " num_nodes x%x, waiting 1000 msecs" | ||
249 | " total wait msecs x%x\n", | ||
250 | vport->vpi, vport->port_state, | ||
251 | vport->fc_flag, vport->num_disc_nodes, | ||
252 | jiffies_to_msecs(jiffies - start_time)); | ||
253 | msleep(1000); | ||
254 | } else { | ||
255 | /* Base case. Wait variants satisfied. Break out */ | ||
256 | lpfc_printf_log(phba, KERN_INFO, LOG_VPORT, | ||
257 | "1834 Vport discovery quiesced:" | ||
258 | " vpi x%x state x%x fc_flags x%x" | ||
259 | " wait msecs x%x\n", | ||
260 | vport->vpi, vport->port_state, | ||
261 | vport->fc_flag, | ||
262 | jiffies_to_msecs(jiffies | ||
263 | - start_time)); | ||
264 | break; | ||
265 | } | ||
266 | } | ||
267 | |||
268 | if (time_after(jiffies, wait_time_max)) | ||
269 | lpfc_printf_log(phba, KERN_ERR, LOG_VPORT, | ||
270 | "1835 Vport discovery quiesce failed:" | ||
271 | " vpi x%x state x%x fc_flags x%x" | ||
272 | " wait msecs x%x\n", | ||
273 | vport->vpi, vport->port_state, | ||
274 | vport->fc_flag, | ||
275 | jiffies_to_msecs(jiffies - start_time)); | ||
276 | } | ||
277 | |||
207 | int | 278 | int |
208 | lpfc_vport_create(struct fc_vport *fc_vport, bool disable) | 279 | lpfc_vport_create(struct fc_vport *fc_vport, bool disable) |
209 | { | 280 | { |
@@ -602,6 +673,9 @@ lpfc_vport_delete(struct fc_vport *fc_vport) | |||
602 | timeout = schedule_timeout(timeout); | 673 | timeout = schedule_timeout(timeout); |
603 | } | 674 | } |
604 | 675 | ||
676 | if (!(phba->pport->load_flag & FC_UNLOADING)) | ||
677 | lpfc_discovery_wait(vport); | ||
678 | |||
605 | skip_logo: | 679 | skip_logo: |
606 | lpfc_cleanup(vport); | 680 | lpfc_cleanup(vport); |
607 | lpfc_sli_host_down(vport); | 681 | lpfc_sli_host_down(vport); |