diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /drivers/scsi/libfc/fc_rport.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/scsi/libfc/fc_rport.c')
-rw-r--r-- | drivers/scsi/libfc/fc_rport.c | 413 |
1 files changed, 276 insertions, 137 deletions
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 03ea6748e7ee..b37d0ff28b35 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c | |||
@@ -47,6 +47,7 @@ | |||
47 | #include <linux/kernel.h> | 47 | #include <linux/kernel.h> |
48 | #include <linux/spinlock.h> | 48 | #include <linux/spinlock.h> |
49 | #include <linux/interrupt.h> | 49 | #include <linux/interrupt.h> |
50 | #include <linux/slab.h> | ||
50 | #include <linux/rcupdate.h> | 51 | #include <linux/rcupdate.h> |
51 | #include <linux/timer.h> | 52 | #include <linux/timer.h> |
52 | #include <linux/workqueue.h> | 53 | #include <linux/workqueue.h> |
@@ -55,6 +56,8 @@ | |||
55 | #include <scsi/libfc.h> | 56 | #include <scsi/libfc.h> |
56 | #include <scsi/fc_encode.h> | 57 | #include <scsi/fc_encode.h> |
57 | 58 | ||
59 | #include "fc_libfc.h" | ||
60 | |||
58 | struct workqueue_struct *rport_event_queue; | 61 | struct workqueue_struct *rport_event_queue; |
59 | 62 | ||
60 | static void fc_rport_enter_plogi(struct fc_rport_priv *); | 63 | static void fc_rport_enter_plogi(struct fc_rport_priv *); |
@@ -86,12 +89,13 @@ static const char *fc_rport_state_names[] = { | |||
86 | [RPORT_ST_LOGO] = "LOGO", | 89 | [RPORT_ST_LOGO] = "LOGO", |
87 | [RPORT_ST_ADISC] = "ADISC", | 90 | [RPORT_ST_ADISC] = "ADISC", |
88 | [RPORT_ST_DELETE] = "Delete", | 91 | [RPORT_ST_DELETE] = "Delete", |
92 | [RPORT_ST_RESTART] = "Restart", | ||
89 | }; | 93 | }; |
90 | 94 | ||
91 | /** | 95 | /** |
92 | * fc_rport_lookup() - lookup a remote port by port_id | 96 | * fc_rport_lookup() - Lookup a remote port by port_id |
93 | * @lport: Fibre Channel host port instance | 97 | * @lport: The local port to lookup the remote port on |
94 | * @port_id: remote port port_id to match | 98 | * @port_id: The remote port ID to look up |
95 | */ | 99 | */ |
96 | static struct fc_rport_priv *fc_rport_lookup(const struct fc_lport *lport, | 100 | static struct fc_rport_priv *fc_rport_lookup(const struct fc_lport *lport, |
97 | u32 port_id) | 101 | u32 port_id) |
@@ -99,16 +103,17 @@ static struct fc_rport_priv *fc_rport_lookup(const struct fc_lport *lport, | |||
99 | struct fc_rport_priv *rdata; | 103 | struct fc_rport_priv *rdata; |
100 | 104 | ||
101 | list_for_each_entry(rdata, &lport->disc.rports, peers) | 105 | list_for_each_entry(rdata, &lport->disc.rports, peers) |
102 | if (rdata->ids.port_id == port_id && | 106 | if (rdata->ids.port_id == port_id) |
103 | rdata->rp_state != RPORT_ST_DELETE) | ||
104 | return rdata; | 107 | return rdata; |
105 | return NULL; | 108 | return NULL; |
106 | } | 109 | } |
107 | 110 | ||
108 | /** | 111 | /** |
109 | * fc_rport_create() - Create a new remote port | 112 | * fc_rport_create() - Create a new remote port |
110 | * @lport: The local port that the new remote port is for | 113 | * @lport: The local port this remote port will be associated with |
111 | * @port_id: The port ID for the new remote port | 114 | * @ids: The identifiers for the new remote port |
115 | * | ||
116 | * The remote port will start in the INIT state. | ||
112 | * | 117 | * |
113 | * Locking note: must be called with the disc_mutex held. | 118 | * Locking note: must be called with the disc_mutex held. |
114 | */ | 119 | */ |
@@ -147,8 +152,8 @@ static struct fc_rport_priv *fc_rport_create(struct fc_lport *lport, | |||
147 | } | 152 | } |
148 | 153 | ||
149 | /** | 154 | /** |
150 | * fc_rport_destroy() - free a remote port after last reference is released. | 155 | * fc_rport_destroy() - Free a remote port after last reference is released |
151 | * @kref: pointer to kref inside struct fc_rport_priv | 156 | * @kref: The remote port's kref |
152 | */ | 157 | */ |
153 | static void fc_rport_destroy(struct kref *kref) | 158 | static void fc_rport_destroy(struct kref *kref) |
154 | { | 159 | { |
@@ -159,8 +164,8 @@ static void fc_rport_destroy(struct kref *kref) | |||
159 | } | 164 | } |
160 | 165 | ||
161 | /** | 166 | /** |
162 | * fc_rport_state() - return a string for the state the rport is in | 167 | * fc_rport_state() - Return a string identifying the remote port's state |
163 | * @rdata: remote port private data | 168 | * @rdata: The remote port |
164 | */ | 169 | */ |
165 | static const char *fc_rport_state(struct fc_rport_priv *rdata) | 170 | static const char *fc_rport_state(struct fc_rport_priv *rdata) |
166 | { | 171 | { |
@@ -173,9 +178,9 @@ static const char *fc_rport_state(struct fc_rport_priv *rdata) | |||
173 | } | 178 | } |
174 | 179 | ||
175 | /** | 180 | /** |
176 | * fc_set_rport_loss_tmo() - Set the remote port loss timeout in seconds. | 181 | * fc_set_rport_loss_tmo() - Set the remote port loss timeout |
177 | * @rport: Pointer to Fibre Channel remote port structure | 182 | * @rport: The remote port that gets a new timeout value |
178 | * @timeout: timeout in seconds | 183 | * @timeout: The new timeout value (in seconds) |
179 | */ | 184 | */ |
180 | void fc_set_rport_loss_tmo(struct fc_rport *rport, u32 timeout) | 185 | void fc_set_rport_loss_tmo(struct fc_rport *rport, u32 timeout) |
181 | { | 186 | { |
@@ -187,9 +192,11 @@ void fc_set_rport_loss_tmo(struct fc_rport *rport, u32 timeout) | |||
187 | EXPORT_SYMBOL(fc_set_rport_loss_tmo); | 192 | EXPORT_SYMBOL(fc_set_rport_loss_tmo); |
188 | 193 | ||
189 | /** | 194 | /** |
190 | * fc_plogi_get_maxframe() - Get max payload from the common service parameters | 195 | * fc_plogi_get_maxframe() - Get the maximum payload from the common service |
191 | * @flp: FLOGI payload structure | 196 | * parameters in a FLOGI frame |
192 | * @maxval: upper limit, may be less than what is in the service parameters | 197 | * @flp: The FLOGI payload |
198 | * @maxval: The maximum frame size upper limit; this may be less than what | ||
199 | * is in the service parameters | ||
193 | */ | 200 | */ |
194 | static unsigned int fc_plogi_get_maxframe(struct fc_els_flogi *flp, | 201 | static unsigned int fc_plogi_get_maxframe(struct fc_els_flogi *flp, |
195 | unsigned int maxval) | 202 | unsigned int maxval) |
@@ -210,9 +217,9 @@ static unsigned int fc_plogi_get_maxframe(struct fc_els_flogi *flp, | |||
210 | } | 217 | } |
211 | 218 | ||
212 | /** | 219 | /** |
213 | * fc_rport_state_enter() - Change the rport's state | 220 | * fc_rport_state_enter() - Change the state of a remote port |
214 | * @rdata: The rport whose state should change | 221 | * @rdata: The remote port whose state should change |
215 | * @new: The new state of the rport | 222 | * @new: The new state |
216 | * | 223 | * |
217 | * Locking Note: Called with the rport lock held | 224 | * Locking Note: Called with the rport lock held |
218 | */ | 225 | */ |
@@ -224,17 +231,22 @@ static void fc_rport_state_enter(struct fc_rport_priv *rdata, | |||
224 | rdata->rp_state = new; | 231 | rdata->rp_state = new; |
225 | } | 232 | } |
226 | 233 | ||
234 | /** | ||
235 | * fc_rport_work() - Handler for remote port events in the rport_event_queue | ||
236 | * @work: Handle to the remote port being dequeued | ||
237 | */ | ||
227 | static void fc_rport_work(struct work_struct *work) | 238 | static void fc_rport_work(struct work_struct *work) |
228 | { | 239 | { |
229 | u32 port_id; | 240 | u32 port_id; |
230 | struct fc_rport_priv *rdata = | 241 | struct fc_rport_priv *rdata = |
231 | container_of(work, struct fc_rport_priv, event_work); | 242 | container_of(work, struct fc_rport_priv, event_work); |
232 | struct fc_rport_libfc_priv *rp; | 243 | struct fc_rport_libfc_priv *rpriv; |
233 | enum fc_rport_event event; | 244 | enum fc_rport_event event; |
234 | struct fc_lport *lport = rdata->local_port; | 245 | struct fc_lport *lport = rdata->local_port; |
235 | struct fc_rport_operations *rport_ops; | 246 | struct fc_rport_operations *rport_ops; |
236 | struct fc_rport_identifiers ids; | 247 | struct fc_rport_identifiers ids; |
237 | struct fc_rport *rport; | 248 | struct fc_rport *rport; |
249 | int restart = 0; | ||
238 | 250 | ||
239 | mutex_lock(&rdata->rp_mutex); | 251 | mutex_lock(&rdata->rp_mutex); |
240 | event = rdata->event; | 252 | event = rdata->event; |
@@ -265,12 +277,12 @@ static void fc_rport_work(struct work_struct *work) | |||
265 | rport->maxframe_size = rdata->maxframe_size; | 277 | rport->maxframe_size = rdata->maxframe_size; |
266 | rport->supported_classes = rdata->supported_classes; | 278 | rport->supported_classes = rdata->supported_classes; |
267 | 279 | ||
268 | rp = rport->dd_data; | 280 | rpriv = rport->dd_data; |
269 | rp->local_port = lport; | 281 | rpriv->local_port = lport; |
270 | rp->rp_state = rdata->rp_state; | 282 | rpriv->rp_state = rdata->rp_state; |
271 | rp->flags = rdata->flags; | 283 | rpriv->flags = rdata->flags; |
272 | rp->e_d_tov = rdata->e_d_tov; | 284 | rpriv->e_d_tov = rdata->e_d_tov; |
273 | rp->r_a_tov = rdata->r_a_tov; | 285 | rpriv->r_a_tov = rdata->r_a_tov; |
274 | mutex_unlock(&rdata->rp_mutex); | 286 | mutex_unlock(&rdata->rp_mutex); |
275 | 287 | ||
276 | if (rport_ops && rport_ops->event_callback) { | 288 | if (rport_ops && rport_ops->event_callback) { |
@@ -287,8 +299,20 @@ static void fc_rport_work(struct work_struct *work) | |||
287 | mutex_unlock(&rdata->rp_mutex); | 299 | mutex_unlock(&rdata->rp_mutex); |
288 | 300 | ||
289 | if (port_id != FC_FID_DIR_SERV) { | 301 | if (port_id != FC_FID_DIR_SERV) { |
302 | /* | ||
303 | * We must drop rp_mutex before taking disc_mutex. | ||
304 | * Re-evaluate state to allow for restart. | ||
305 | * A transition to RESTART state must only happen | ||
306 | * while disc_mutex is held and rdata is on the list. | ||
307 | */ | ||
290 | mutex_lock(&lport->disc.disc_mutex); | 308 | mutex_lock(&lport->disc.disc_mutex); |
291 | list_del(&rdata->peers); | 309 | mutex_lock(&rdata->rp_mutex); |
310 | if (rdata->rp_state == RPORT_ST_RESTART) | ||
311 | restart = 1; | ||
312 | else | ||
313 | list_del(&rdata->peers); | ||
314 | rdata->event = RPORT_EV_NONE; | ||
315 | mutex_unlock(&rdata->rp_mutex); | ||
292 | mutex_unlock(&lport->disc.disc_mutex); | 316 | mutex_unlock(&lport->disc.disc_mutex); |
293 | } | 317 | } |
294 | 318 | ||
@@ -305,14 +329,20 @@ static void fc_rport_work(struct work_struct *work) | |||
305 | lport->tt.exch_mgr_reset(lport, port_id, 0); | 329 | lport->tt.exch_mgr_reset(lport, port_id, 0); |
306 | 330 | ||
307 | if (rport) { | 331 | if (rport) { |
308 | rp = rport->dd_data; | 332 | rpriv = rport->dd_data; |
309 | rp->rp_state = RPORT_ST_DELETE; | 333 | rpriv->rp_state = RPORT_ST_DELETE; |
310 | mutex_lock(&rdata->rp_mutex); | 334 | mutex_lock(&rdata->rp_mutex); |
311 | rdata->rport = NULL; | 335 | rdata->rport = NULL; |
312 | mutex_unlock(&rdata->rp_mutex); | 336 | mutex_unlock(&rdata->rp_mutex); |
313 | fc_remote_port_delete(rport); | 337 | fc_remote_port_delete(rport); |
314 | } | 338 | } |
315 | kref_put(&rdata->kref, lport->tt.rport_destroy); | 339 | if (restart) { |
340 | mutex_lock(&rdata->rp_mutex); | ||
341 | FC_RPORT_DBG(rdata, "work restart\n"); | ||
342 | fc_rport_enter_plogi(rdata); | ||
343 | mutex_unlock(&rdata->rp_mutex); | ||
344 | } else | ||
345 | kref_put(&rdata->kref, lport->tt.rport_destroy); | ||
316 | break; | 346 | break; |
317 | 347 | ||
318 | default: | 348 | default: |
@@ -323,7 +353,7 @@ static void fc_rport_work(struct work_struct *work) | |||
323 | 353 | ||
324 | /** | 354 | /** |
325 | * fc_rport_login() - Start the remote port login state machine | 355 | * fc_rport_login() - Start the remote port login state machine |
326 | * @rdata: private remote port | 356 | * @rdata: The remote port to be logged in to |
327 | * | 357 | * |
328 | * Locking Note: Called without the rport lock held. This | 358 | * Locking Note: Called without the rport lock held. This |
329 | * function will hold the rport lock, call an _enter_* | 359 | * function will hold the rport lock, call an _enter_* |
@@ -342,6 +372,12 @@ int fc_rport_login(struct fc_rport_priv *rdata) | |||
342 | FC_RPORT_DBG(rdata, "ADISC port\n"); | 372 | FC_RPORT_DBG(rdata, "ADISC port\n"); |
343 | fc_rport_enter_adisc(rdata); | 373 | fc_rport_enter_adisc(rdata); |
344 | break; | 374 | break; |
375 | case RPORT_ST_RESTART: | ||
376 | break; | ||
377 | case RPORT_ST_DELETE: | ||
378 | FC_RPORT_DBG(rdata, "Restart deleted port\n"); | ||
379 | fc_rport_state_enter(rdata, RPORT_ST_RESTART); | ||
380 | break; | ||
345 | default: | 381 | default: |
346 | FC_RPORT_DBG(rdata, "Login to port\n"); | 382 | FC_RPORT_DBG(rdata, "Login to port\n"); |
347 | fc_rport_enter_plogi(rdata); | 383 | fc_rport_enter_plogi(rdata); |
@@ -353,9 +389,9 @@ int fc_rport_login(struct fc_rport_priv *rdata) | |||
353 | } | 389 | } |
354 | 390 | ||
355 | /** | 391 | /** |
356 | * fc_rport_enter_delete() - schedule a remote port to be deleted. | 392 | * fc_rport_enter_delete() - Schedule a remote port to be deleted |
357 | * @rdata: private remote port | 393 | * @rdata: The remote port to be deleted |
358 | * @event: event to report as the reason for deletion | 394 | * @event: The event to report as the reason for deletion |
359 | * | 395 | * |
360 | * Locking Note: Called with the rport lock held. | 396 | * Locking Note: Called with the rport lock held. |
361 | * | 397 | * |
@@ -382,8 +418,8 @@ static void fc_rport_enter_delete(struct fc_rport_priv *rdata, | |||
382 | } | 418 | } |
383 | 419 | ||
384 | /** | 420 | /** |
385 | * fc_rport_logoff() - Logoff and remove an rport | 421 | * fc_rport_logoff() - Logoff and remove a remote port |
386 | * @rdata: private remote port | 422 | * @rdata: The remote port to be logged off of |
387 | * | 423 | * |
388 | * Locking Note: Called without the rport lock held. This | 424 | * Locking Note: Called without the rport lock held. This |
389 | * function will hold the rport lock, call an _enter_* | 425 | * function will hold the rport lock, call an _enter_* |
@@ -397,26 +433,27 @@ int fc_rport_logoff(struct fc_rport_priv *rdata) | |||
397 | 433 | ||
398 | if (rdata->rp_state == RPORT_ST_DELETE) { | 434 | if (rdata->rp_state == RPORT_ST_DELETE) { |
399 | FC_RPORT_DBG(rdata, "Port in Delete state, not removing\n"); | 435 | FC_RPORT_DBG(rdata, "Port in Delete state, not removing\n"); |
400 | mutex_unlock(&rdata->rp_mutex); | ||
401 | goto out; | 436 | goto out; |
402 | } | 437 | } |
403 | 438 | ||
404 | fc_rport_enter_logo(rdata); | 439 | if (rdata->rp_state == RPORT_ST_RESTART) |
440 | FC_RPORT_DBG(rdata, "Port in Restart state, deleting\n"); | ||
441 | else | ||
442 | fc_rport_enter_logo(rdata); | ||
405 | 443 | ||
406 | /* | 444 | /* |
407 | * Change the state to Delete so that we discard | 445 | * Change the state to Delete so that we discard |
408 | * the response. | 446 | * the response. |
409 | */ | 447 | */ |
410 | fc_rport_enter_delete(rdata, RPORT_EV_STOP); | 448 | fc_rport_enter_delete(rdata, RPORT_EV_STOP); |
411 | mutex_unlock(&rdata->rp_mutex); | ||
412 | |||
413 | out: | 449 | out: |
450 | mutex_unlock(&rdata->rp_mutex); | ||
414 | return 0; | 451 | return 0; |
415 | } | 452 | } |
416 | 453 | ||
417 | /** | 454 | /** |
418 | * fc_rport_enter_ready() - The rport is ready | 455 | * fc_rport_enter_ready() - Transition to the RPORT_ST_READY state |
419 | * @rdata: private remote port | 456 | * @rdata: The remote port that is ready |
420 | * | 457 | * |
421 | * Locking Note: The rport lock is expected to be held before calling | 458 | * Locking Note: The rport lock is expected to be held before calling |
422 | * this routine. | 459 | * this routine. |
@@ -433,8 +470,8 @@ static void fc_rport_enter_ready(struct fc_rport_priv *rdata) | |||
433 | } | 470 | } |
434 | 471 | ||
435 | /** | 472 | /** |
436 | * fc_rport_timeout() - Handler for the retry_work timer. | 473 | * fc_rport_timeout() - Handler for the retry_work timer |
437 | * @work: The work struct of the fc_rport_priv | 474 | * @work: Handle to the remote port that has timed out |
438 | * | 475 | * |
439 | * Locking Note: Called without the rport lock held. This | 476 | * Locking Note: Called without the rport lock held. This |
440 | * function will hold the rport lock, call an _enter_* | 477 | * function will hold the rport lock, call an _enter_* |
@@ -466,6 +503,7 @@ static void fc_rport_timeout(struct work_struct *work) | |||
466 | case RPORT_ST_READY: | 503 | case RPORT_ST_READY: |
467 | case RPORT_ST_INIT: | 504 | case RPORT_ST_INIT: |
468 | case RPORT_ST_DELETE: | 505 | case RPORT_ST_DELETE: |
506 | case RPORT_ST_RESTART: | ||
469 | break; | 507 | break; |
470 | } | 508 | } |
471 | 509 | ||
@@ -474,8 +512,8 @@ static void fc_rport_timeout(struct work_struct *work) | |||
474 | 512 | ||
475 | /** | 513 | /** |
476 | * fc_rport_error() - Error handler, called once retries have been exhausted | 514 | * fc_rport_error() - Error handler, called once retries have been exhausted |
477 | * @rdata: private remote port | 515 | * @rdata: The remote port the error is happened on |
478 | * @fp: The frame pointer | 516 | * @fp: The error code encapsulated in a frame pointer |
479 | * | 517 | * |
480 | * Locking Note: The rport lock is expected to be held before | 518 | * Locking Note: The rport lock is expected to be held before |
481 | * calling this routine | 519 | * calling this routine |
@@ -499,6 +537,7 @@ static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp) | |||
499 | fc_rport_enter_logo(rdata); | 537 | fc_rport_enter_logo(rdata); |
500 | break; | 538 | break; |
501 | case RPORT_ST_DELETE: | 539 | case RPORT_ST_DELETE: |
540 | case RPORT_ST_RESTART: | ||
502 | case RPORT_ST_READY: | 541 | case RPORT_ST_READY: |
503 | case RPORT_ST_INIT: | 542 | case RPORT_ST_INIT: |
504 | break; | 543 | break; |
@@ -506,9 +545,9 @@ static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp) | |||
506 | } | 545 | } |
507 | 546 | ||
508 | /** | 547 | /** |
509 | * fc_rport_error_retry() - Error handler when retries are desired | 548 | * fc_rport_error_retry() - Handler for remote port state retries |
510 | * @rdata: private remote port data | 549 | * @rdata: The remote port whose state is to be retried |
511 | * @fp: The frame pointer | 550 | * @fp: The error code encapsulated in a frame pointer |
512 | * | 551 | * |
513 | * If the error was an exchange timeout retry immediately, | 552 | * If the error was an exchange timeout retry immediately, |
514 | * otherwise wait for E_D_TOV. | 553 | * otherwise wait for E_D_TOV. |
@@ -540,10 +579,10 @@ static void fc_rport_error_retry(struct fc_rport_priv *rdata, | |||
540 | } | 579 | } |
541 | 580 | ||
542 | /** | 581 | /** |
543 | * fc_rport_plogi_recv_resp() - Handle incoming ELS PLOGI response | 582 | * fc_rport_plogi_recv_resp() - Handler for ELS PLOGI responses |
544 | * @sp: current sequence in the PLOGI exchange | 583 | * @sp: The sequence the PLOGI is on |
545 | * @fp: response frame | 584 | * @fp: The PLOGI response frame |
546 | * @rdata_arg: private remote port data | 585 | * @rdata_arg: The remote port that sent the PLOGI response |
547 | * | 586 | * |
548 | * Locking Note: This function will be called without the rport lock | 587 | * Locking Note: This function will be called without the rport lock |
549 | * held, but it will lock, call an _enter_* function or fc_rport_error | 588 | * held, but it will lock, call an _enter_* function or fc_rport_error |
@@ -585,7 +624,7 @@ static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp, | |||
585 | 624 | ||
586 | tov = ntohl(plp->fl_csp.sp_e_d_tov); | 625 | tov = ntohl(plp->fl_csp.sp_e_d_tov); |
587 | if (ntohs(plp->fl_csp.sp_features) & FC_SP_FT_EDTR) | 626 | if (ntohs(plp->fl_csp.sp_features) & FC_SP_FT_EDTR) |
588 | tov /= 1000; | 627 | tov /= 1000000; |
589 | if (tov > rdata->e_d_tov) | 628 | if (tov > rdata->e_d_tov) |
590 | rdata->e_d_tov = tov; | 629 | rdata->e_d_tov = tov; |
591 | csp_seq = ntohs(plp->fl_csp.sp_tot_seq); | 630 | csp_seq = ntohs(plp->fl_csp.sp_tot_seq); |
@@ -606,8 +645,8 @@ err: | |||
606 | } | 645 | } |
607 | 646 | ||
608 | /** | 647 | /** |
609 | * fc_rport_enter_plogi() - Send Port Login (PLOGI) request to peer | 648 | * fc_rport_enter_plogi() - Send Port Login (PLOGI) request |
610 | * @rdata: private remote port data | 649 | * @rdata: The remote port to send a PLOGI to |
611 | * | 650 | * |
612 | * Locking Note: The rport lock is expected to be held before calling | 651 | * Locking Note: The rport lock is expected to be held before calling |
613 | * this routine. | 652 | * this routine. |
@@ -631,17 +670,18 @@ static void fc_rport_enter_plogi(struct fc_rport_priv *rdata) | |||
631 | rdata->e_d_tov = lport->e_d_tov; | 670 | rdata->e_d_tov = lport->e_d_tov; |
632 | 671 | ||
633 | if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_PLOGI, | 672 | if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_PLOGI, |
634 | fc_rport_plogi_resp, rdata, lport->e_d_tov)) | 673 | fc_rport_plogi_resp, rdata, |
635 | fc_rport_error_retry(rdata, fp); | 674 | 2 * lport->r_a_tov)) |
675 | fc_rport_error_retry(rdata, NULL); | ||
636 | else | 676 | else |
637 | kref_get(&rdata->kref); | 677 | kref_get(&rdata->kref); |
638 | } | 678 | } |
639 | 679 | ||
640 | /** | 680 | /** |
641 | * fc_rport_prli_resp() - Process Login (PRLI) response handler | 681 | * fc_rport_prli_resp() - Process Login (PRLI) response handler |
642 | * @sp: current sequence in the PRLI exchange | 682 | * @sp: The sequence the PRLI response was on |
643 | * @fp: response frame | 683 | * @fp: The PRLI response frame |
644 | * @rdata_arg: private remote port data | 684 | * @rdata_arg: The remote port that sent the PRLI response |
645 | * | 685 | * |
646 | * Locking Note: This function will be called without the rport lock | 686 | * Locking Note: This function will be called without the rport lock |
647 | * held, but it will lock, call an _enter_* function or fc_rport_error | 687 | * held, but it will lock, call an _enter_* function or fc_rport_error |
@@ -710,10 +750,10 @@ err: | |||
710 | } | 750 | } |
711 | 751 | ||
712 | /** | 752 | /** |
713 | * fc_rport_logo_resp() - Logout (LOGO) response handler | 753 | * fc_rport_logo_resp() - Handler for logout (LOGO) responses |
714 | * @sp: current sequence in the LOGO exchange | 754 | * @sp: The sequence the LOGO was on |
715 | * @fp: response frame | 755 | * @fp: The LOGO response frame |
716 | * @rdata_arg: private remote port data | 756 | * @rdata_arg: The remote port that sent the LOGO response |
717 | * | 757 | * |
718 | * Locking Note: This function will be called without the rport lock | 758 | * Locking Note: This function will be called without the rport lock |
719 | * held, but it will lock, call an _enter_* function or fc_rport_error | 759 | * held, but it will lock, call an _enter_* function or fc_rport_error |
@@ -756,8 +796,8 @@ err: | |||
756 | } | 796 | } |
757 | 797 | ||
758 | /** | 798 | /** |
759 | * fc_rport_enter_prli() - Send Process Login (PRLI) request to peer | 799 | * fc_rport_enter_prli() - Send Process Login (PRLI) request |
760 | * @rdata: private remote port data | 800 | * @rdata: The remote port to send the PRLI request to |
761 | * | 801 | * |
762 | * Locking Note: The rport lock is expected to be held before calling | 802 | * Locking Note: The rport lock is expected to be held before calling |
763 | * this routine. | 803 | * this routine. |
@@ -792,17 +832,18 @@ static void fc_rport_enter_prli(struct fc_rport_priv *rdata) | |||
792 | } | 832 | } |
793 | 833 | ||
794 | if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_PRLI, | 834 | if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_PRLI, |
795 | fc_rport_prli_resp, rdata, lport->e_d_tov)) | 835 | fc_rport_prli_resp, rdata, |
796 | fc_rport_error_retry(rdata, fp); | 836 | 2 * lport->r_a_tov)) |
837 | fc_rport_error_retry(rdata, NULL); | ||
797 | else | 838 | else |
798 | kref_get(&rdata->kref); | 839 | kref_get(&rdata->kref); |
799 | } | 840 | } |
800 | 841 | ||
801 | /** | 842 | /** |
802 | * fc_rport_els_rtv_resp() - Request Timeout Value response handler | 843 | * fc_rport_els_rtv_resp() - Handler for Request Timeout Value (RTV) responses |
803 | * @sp: current sequence in the RTV exchange | 844 | * @sp: The sequence the RTV was on |
804 | * @fp: response frame | 845 | * @fp: The RTV response frame |
805 | * @rdata_arg: private remote port data | 846 | * @rdata_arg: The remote port that sent the RTV response |
806 | * | 847 | * |
807 | * Many targets don't seem to support this. | 848 | * Many targets don't seem to support this. |
808 | * | 849 | * |
@@ -865,8 +906,8 @@ err: | |||
865 | } | 906 | } |
866 | 907 | ||
867 | /** | 908 | /** |
868 | * fc_rport_enter_rtv() - Send Request Timeout Value (RTV) request to peer | 909 | * fc_rport_enter_rtv() - Send Request Timeout Value (RTV) request |
869 | * @rdata: private remote port data | 910 | * @rdata: The remote port to send the RTV request to |
870 | * | 911 | * |
871 | * Locking Note: The rport lock is expected to be held before calling | 912 | * Locking Note: The rport lock is expected to be held before calling |
872 | * this routine. | 913 | * this routine. |
@@ -888,15 +929,16 @@ static void fc_rport_enter_rtv(struct fc_rport_priv *rdata) | |||
888 | } | 929 | } |
889 | 930 | ||
890 | if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_RTV, | 931 | if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_RTV, |
891 | fc_rport_rtv_resp, rdata, lport->e_d_tov)) | 932 | fc_rport_rtv_resp, rdata, |
892 | fc_rport_error_retry(rdata, fp); | 933 | 2 * lport->r_a_tov)) |
934 | fc_rport_error_retry(rdata, NULL); | ||
893 | else | 935 | else |
894 | kref_get(&rdata->kref); | 936 | kref_get(&rdata->kref); |
895 | } | 937 | } |
896 | 938 | ||
897 | /** | 939 | /** |
898 | * fc_rport_enter_logo() - Send Logout (LOGO) request to peer | 940 | * fc_rport_enter_logo() - Send a logout (LOGO) request |
899 | * @rdata: private remote port data | 941 | * @rdata: The remote port to send the LOGO request to |
900 | * | 942 | * |
901 | * Locking Note: The rport lock is expected to be held before calling | 943 | * Locking Note: The rport lock is expected to be held before calling |
902 | * this routine. | 944 | * this routine. |
@@ -918,24 +960,25 @@ static void fc_rport_enter_logo(struct fc_rport_priv *rdata) | |||
918 | } | 960 | } |
919 | 961 | ||
920 | if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_LOGO, | 962 | if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_LOGO, |
921 | fc_rport_logo_resp, rdata, lport->e_d_tov)) | 963 | fc_rport_logo_resp, rdata, |
922 | fc_rport_error_retry(rdata, fp); | 964 | 2 * lport->r_a_tov)) |
965 | fc_rport_error_retry(rdata, NULL); | ||
923 | else | 966 | else |
924 | kref_get(&rdata->kref); | 967 | kref_get(&rdata->kref); |
925 | } | 968 | } |
926 | 969 | ||
927 | /** | 970 | /** |
928 | * fc_rport_els_adisc_resp() - Address Discovery response handler | 971 | * fc_rport_els_adisc_resp() - Handler for Address Discovery (ADISC) responses |
929 | * @sp: current sequence in the ADISC exchange | 972 | * @sp: The sequence the ADISC response was on |
930 | * @fp: response frame | 973 | * @fp: The ADISC response frame |
931 | * @rdata_arg: remote port private. | 974 | * @rdata_arg: The remote port that sent the ADISC response |
932 | * | 975 | * |
933 | * Locking Note: This function will be called without the rport lock | 976 | * Locking Note: This function will be called without the rport lock |
934 | * held, but it will lock, call an _enter_* function or fc_rport_error | 977 | * held, but it will lock, call an _enter_* function or fc_rport_error |
935 | * and then unlock the rport. | 978 | * and then unlock the rport. |
936 | */ | 979 | */ |
937 | static void fc_rport_adisc_resp(struct fc_seq *sp, struct fc_frame *fp, | 980 | static void fc_rport_adisc_resp(struct fc_seq *sp, struct fc_frame *fp, |
938 | void *rdata_arg) | 981 | void *rdata_arg) |
939 | { | 982 | { |
940 | struct fc_rport_priv *rdata = rdata_arg; | 983 | struct fc_rport_priv *rdata = rdata_arg; |
941 | struct fc_els_adisc *adisc; | 984 | struct fc_els_adisc *adisc; |
@@ -983,8 +1026,8 @@ err: | |||
983 | } | 1026 | } |
984 | 1027 | ||
985 | /** | 1028 | /** |
986 | * fc_rport_enter_adisc() - Send Address Discover (ADISC) request to peer | 1029 | * fc_rport_enter_adisc() - Send Address Discover (ADISC) request |
987 | * @rdata: remote port private data | 1030 | * @rdata: The remote port to send the ADISC request to |
988 | * | 1031 | * |
989 | * Locking Note: The rport lock is expected to be held before calling | 1032 | * Locking Note: The rport lock is expected to be held before calling |
990 | * this routine. | 1033 | * this routine. |
@@ -1005,17 +1048,18 @@ static void fc_rport_enter_adisc(struct fc_rport_priv *rdata) | |||
1005 | return; | 1048 | return; |
1006 | } | 1049 | } |
1007 | if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_ADISC, | 1050 | if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_ADISC, |
1008 | fc_rport_adisc_resp, rdata, lport->e_d_tov)) | 1051 | fc_rport_adisc_resp, rdata, |
1009 | fc_rport_error_retry(rdata, fp); | 1052 | 2 * lport->r_a_tov)) |
1053 | fc_rport_error_retry(rdata, NULL); | ||
1010 | else | 1054 | else |
1011 | kref_get(&rdata->kref); | 1055 | kref_get(&rdata->kref); |
1012 | } | 1056 | } |
1013 | 1057 | ||
1014 | /** | 1058 | /** |
1015 | * fc_rport_recv_adisc_req() - Handle incoming Address Discovery (ADISC) Request | 1059 | * fc_rport_recv_adisc_req() - Handler for Address Discovery (ADISC) requests |
1016 | * @rdata: remote port private | 1060 | * @rdata: The remote port that sent the ADISC request |
1017 | * @sp: current sequence in the ADISC exchange | 1061 | * @sp: The sequence the ADISC request was on |
1018 | * @in_fp: ADISC request frame | 1062 | * @in_fp: The ADISC request frame |
1019 | * | 1063 | * |
1020 | * Locking Note: Called with the lport and rport locks held. | 1064 | * Locking Note: Called with the lport and rport locks held. |
1021 | */ | 1065 | */ |
@@ -1056,10 +1100,82 @@ drop: | |||
1056 | } | 1100 | } |
1057 | 1101 | ||
1058 | /** | 1102 | /** |
1059 | * fc_rport_recv_els_req() - handle a validated ELS request. | 1103 | * fc_rport_recv_rls_req() - Handle received Read Link Status request |
1060 | * @lport: Fibre Channel local port | 1104 | * @rdata: The remote port that sent the RLS request |
1061 | * @sp: current sequence in the PLOGI exchange | 1105 | * @sp: The sequence that the RLS was on |
1062 | * @fp: response frame | 1106 | * @rx_fp: The PRLI request frame |
1107 | * | ||
1108 | * Locking Note: The rport lock is expected to be held before calling | ||
1109 | * this function. | ||
1110 | */ | ||
1111 | static void fc_rport_recv_rls_req(struct fc_rport_priv *rdata, | ||
1112 | struct fc_seq *sp, struct fc_frame *rx_fp) | ||
1113 | |||
1114 | { | ||
1115 | struct fc_lport *lport = rdata->local_port; | ||
1116 | struct fc_frame *fp; | ||
1117 | struct fc_exch *ep = fc_seq_exch(sp); | ||
1118 | struct fc_els_rls *rls; | ||
1119 | struct fc_els_rls_resp *rsp; | ||
1120 | struct fc_els_lesb *lesb; | ||
1121 | struct fc_seq_els_data rjt_data; | ||
1122 | struct fc_host_statistics *hst; | ||
1123 | u32 f_ctl; | ||
1124 | |||
1125 | FC_RPORT_DBG(rdata, "Received RLS request while in state %s\n", | ||
1126 | fc_rport_state(rdata)); | ||
1127 | |||
1128 | rls = fc_frame_payload_get(rx_fp, sizeof(*rls)); | ||
1129 | if (!rls) { | ||
1130 | rjt_data.reason = ELS_RJT_PROT; | ||
1131 | rjt_data.explan = ELS_EXPL_INV_LEN; | ||
1132 | goto out_rjt; | ||
1133 | } | ||
1134 | |||
1135 | fp = fc_frame_alloc(lport, sizeof(*rsp)); | ||
1136 | if (!fp) { | ||
1137 | rjt_data.reason = ELS_RJT_UNAB; | ||
1138 | rjt_data.explan = ELS_EXPL_INSUF_RES; | ||
1139 | goto out_rjt; | ||
1140 | } | ||
1141 | |||
1142 | rsp = fc_frame_payload_get(fp, sizeof(*rsp)); | ||
1143 | memset(rsp, 0, sizeof(*rsp)); | ||
1144 | rsp->rls_cmd = ELS_LS_ACC; | ||
1145 | lesb = &rsp->rls_lesb; | ||
1146 | if (lport->tt.get_lesb) { | ||
1147 | /* get LESB from LLD if it supports it */ | ||
1148 | lport->tt.get_lesb(lport, lesb); | ||
1149 | } else { | ||
1150 | fc_get_host_stats(lport->host); | ||
1151 | hst = &lport->host_stats; | ||
1152 | lesb->lesb_link_fail = htonl(hst->link_failure_count); | ||
1153 | lesb->lesb_sync_loss = htonl(hst->loss_of_sync_count); | ||
1154 | lesb->lesb_sig_loss = htonl(hst->loss_of_signal_count); | ||
1155 | lesb->lesb_prim_err = htonl(hst->prim_seq_protocol_err_count); | ||
1156 | lesb->lesb_inv_word = htonl(hst->invalid_tx_word_count); | ||
1157 | lesb->lesb_inv_crc = htonl(hst->invalid_crc_count); | ||
1158 | } | ||
1159 | |||
1160 | sp = lport->tt.seq_start_next(sp); | ||
1161 | f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ | FC_FC_END_SEQ; | ||
1162 | fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid, | ||
1163 | FC_TYPE_ELS, f_ctl, 0); | ||
1164 | lport->tt.seq_send(lport, sp, fp); | ||
1165 | goto out; | ||
1166 | |||
1167 | out_rjt: | ||
1168 | rjt_data.fp = NULL; | ||
1169 | lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data); | ||
1170 | out: | ||
1171 | fc_frame_free(rx_fp); | ||
1172 | } | ||
1173 | |||
1174 | /** | ||
1175 | * fc_rport_recv_els_req() - Handler for validated ELS requests | ||
1176 | * @lport: The local port that received the ELS request | ||
1177 | * @sp: The sequence that the ELS request was on | ||
1178 | * @fp: The ELS request frame | ||
1063 | * | 1179 | * |
1064 | * Handle incoming ELS requests that require port login. | 1180 | * Handle incoming ELS requests that require port login. |
1065 | * The ELS opcode has already been validated by the caller. | 1181 | * The ELS opcode has already been validated by the caller. |
@@ -1117,6 +1233,9 @@ static void fc_rport_recv_els_req(struct fc_lport *lport, | |||
1117 | els_data.fp = fp; | 1233 | els_data.fp = fp; |
1118 | lport->tt.seq_els_rsp_send(sp, ELS_REC, &els_data); | 1234 | lport->tt.seq_els_rsp_send(sp, ELS_REC, &els_data); |
1119 | break; | 1235 | break; |
1236 | case ELS_RLS: | ||
1237 | fc_rport_recv_rls_req(rdata, sp, fp); | ||
1238 | break; | ||
1120 | default: | 1239 | default: |
1121 | fc_frame_free(fp); /* can't happen */ | 1240 | fc_frame_free(fp); /* can't happen */ |
1122 | break; | 1241 | break; |
@@ -1131,10 +1250,10 @@ reject: | |||
1131 | } | 1250 | } |
1132 | 1251 | ||
1133 | /** | 1252 | /** |
1134 | * fc_rport_recv_req() - Handle a received ELS request from a rport | 1253 | * fc_rport_recv_req() - Handler for requests |
1135 | * @sp: current sequence in the PLOGI exchange | 1254 | * @sp: The sequence the request was on |
1136 | * @fp: response frame | 1255 | * @fp: The request frame |
1137 | * @lport: Fibre Channel local port | 1256 | * @lport: The local port that received the request |
1138 | * | 1257 | * |
1139 | * Locking Note: Called with the lport lock held. | 1258 | * Locking Note: Called with the lport lock held. |
1140 | */ | 1259 | */ |
@@ -1161,6 +1280,7 @@ void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame *fp, | |||
1161 | case ELS_ADISC: | 1280 | case ELS_ADISC: |
1162 | case ELS_RRQ: | 1281 | case ELS_RRQ: |
1163 | case ELS_REC: | 1282 | case ELS_REC: |
1283 | case ELS_RLS: | ||
1164 | fc_rport_recv_els_req(lport, sp, fp); | 1284 | fc_rport_recv_els_req(lport, sp, fp); |
1165 | break; | 1285 | break; |
1166 | default: | 1286 | default: |
@@ -1174,10 +1294,10 @@ void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame *fp, | |||
1174 | } | 1294 | } |
1175 | 1295 | ||
1176 | /** | 1296 | /** |
1177 | * fc_rport_recv_plogi_req() - Handle incoming Port Login (PLOGI) request | 1297 | * fc_rport_recv_plogi_req() - Handler for Port Login (PLOGI) requests |
1178 | * @lport: local port | 1298 | * @lport: The local port that received the PLOGI request |
1179 | * @sp: current sequence in the PLOGI exchange | 1299 | * @sp: The sequence that the PLOGI request was on |
1180 | * @fp: PLOGI request frame | 1300 | * @rx_fp: The PLOGI request frame |
1181 | * | 1301 | * |
1182 | * Locking Note: The rport lock is held before calling this function. | 1302 | * Locking Note: The rport lock is held before calling this function. |
1183 | */ | 1303 | */ |
@@ -1248,6 +1368,7 @@ static void fc_rport_recv_plogi_req(struct fc_lport *lport, | |||
1248 | } | 1368 | } |
1249 | break; | 1369 | break; |
1250 | case RPORT_ST_PRLI: | 1370 | case RPORT_ST_PRLI: |
1371 | case RPORT_ST_RTV: | ||
1251 | case RPORT_ST_READY: | 1372 | case RPORT_ST_READY: |
1252 | case RPORT_ST_ADISC: | 1373 | case RPORT_ST_ADISC: |
1253 | FC_RPORT_DBG(rdata, "Received PLOGI in logged-in state %d " | 1374 | FC_RPORT_DBG(rdata, "Received PLOGI in logged-in state %d " |
@@ -1255,11 +1376,14 @@ static void fc_rport_recv_plogi_req(struct fc_lport *lport, | |||
1255 | /* XXX TBD - should reset */ | 1376 | /* XXX TBD - should reset */ |
1256 | break; | 1377 | break; |
1257 | case RPORT_ST_DELETE: | 1378 | case RPORT_ST_DELETE: |
1258 | default: | 1379 | case RPORT_ST_LOGO: |
1259 | FC_RPORT_DBG(rdata, "Received PLOGI in unexpected state %d\n", | 1380 | case RPORT_ST_RESTART: |
1260 | rdata->rp_state); | 1381 | FC_RPORT_DBG(rdata, "Received PLOGI in state %s - send busy\n", |
1261 | fc_frame_free(rx_fp); | 1382 | fc_rport_state(rdata)); |
1262 | goto out; | 1383 | mutex_unlock(&rdata->rp_mutex); |
1384 | rjt_data.reason = ELS_RJT_BUSY; | ||
1385 | rjt_data.explan = ELS_EXPL_NONE; | ||
1386 | goto reject; | ||
1263 | } | 1387 | } |
1264 | 1388 | ||
1265 | /* | 1389 | /* |
@@ -1295,10 +1419,10 @@ reject: | |||
1295 | } | 1419 | } |
1296 | 1420 | ||
1297 | /** | 1421 | /** |
1298 | * fc_rport_recv_prli_req() - Handle incoming Process Login (PRLI) request | 1422 | * fc_rport_recv_prli_req() - Handler for process login (PRLI) requests |
1299 | * @rdata: private remote port data | 1423 | * @rdata: The remote port that sent the PRLI request |
1300 | * @sp: current sequence in the PRLI exchange | 1424 | * @sp: The sequence that the PRLI was on |
1301 | * @fp: PRLI request frame | 1425 | * @rx_fp: The PRLI request frame |
1302 | * | 1426 | * |
1303 | * Locking Note: The rport lock is exected to be held before calling | 1427 | * Locking Note: The rport lock is exected to be held before calling |
1304 | * this function. | 1428 | * this function. |
@@ -1402,7 +1526,7 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata, | |||
1402 | break; | 1526 | break; |
1403 | case FC_TYPE_FCP: | 1527 | case FC_TYPE_FCP: |
1404 | fcp_parm = ntohl(rspp->spp_params); | 1528 | fcp_parm = ntohl(rspp->spp_params); |
1405 | if (fcp_parm * FCP_SPPF_RETRY) | 1529 | if (fcp_parm & FCP_SPPF_RETRY) |
1406 | rdata->flags |= FC_RP_FLAGS_RETRY; | 1530 | rdata->flags |= FC_RP_FLAGS_RETRY; |
1407 | rdata->supported_classes = FC_COS_CLASS3; | 1531 | rdata->supported_classes = FC_COS_CLASS3; |
1408 | if (fcp_parm & FCP_SPPF_INIT_FCN) | 1532 | if (fcp_parm & FCP_SPPF_INIT_FCN) |
@@ -1452,10 +1576,10 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata, | |||
1452 | } | 1576 | } |
1453 | 1577 | ||
1454 | /** | 1578 | /** |
1455 | * fc_rport_recv_prlo_req() - Handle incoming Process Logout (PRLO) request | 1579 | * fc_rport_recv_prlo_req() - Handler for process logout (PRLO) requests |
1456 | * @rdata: private remote port data | 1580 | * @rdata: The remote port that sent the PRLO request |
1457 | * @sp: current sequence in the PRLO exchange | 1581 | * @sp: The sequence that the PRLO was on |
1458 | * @fp: PRLO request frame | 1582 | * @fp: The PRLO request frame |
1459 | * | 1583 | * |
1460 | * Locking Note: The rport lock is exected to be held before calling | 1584 | * Locking Note: The rport lock is exected to be held before calling |
1461 | * this function. | 1585 | * this function. |
@@ -1482,10 +1606,10 @@ static void fc_rport_recv_prlo_req(struct fc_rport_priv *rdata, | |||
1482 | } | 1606 | } |
1483 | 1607 | ||
1484 | /** | 1608 | /** |
1485 | * fc_rport_recv_logo_req() - Handle incoming Logout (LOGO) request | 1609 | * fc_rport_recv_logo_req() - Handler for logout (LOGO) requests |
1486 | * @lport: local port. | 1610 | * @lport: The local port that received the LOGO request |
1487 | * @sp: current sequence in the LOGO exchange | 1611 | * @sp: The sequence that the LOGO request was on |
1488 | * @fp: LOGO request frame | 1612 | * @fp: The LOGO request frame |
1489 | * | 1613 | * |
1490 | * Locking Note: The rport lock is exected to be held before calling | 1614 | * Locking Note: The rport lock is exected to be held before calling |
1491 | * this function. | 1615 | * this function. |
@@ -1510,14 +1634,14 @@ static void fc_rport_recv_logo_req(struct fc_lport *lport, | |||
1510 | FC_RPORT_DBG(rdata, "Received LOGO request while in state %s\n", | 1634 | FC_RPORT_DBG(rdata, "Received LOGO request while in state %s\n", |
1511 | fc_rport_state(rdata)); | 1635 | fc_rport_state(rdata)); |
1512 | 1636 | ||
1637 | fc_rport_enter_delete(rdata, RPORT_EV_LOGO); | ||
1638 | |||
1513 | /* | 1639 | /* |
1514 | * If the remote port was created due to discovery, | 1640 | * If the remote port was created due to discovery, set state |
1515 | * log back in. It may have seen a stale RSCN about us. | 1641 | * to log back in. It may have seen a stale RSCN about us. |
1516 | */ | 1642 | */ |
1517 | if (rdata->rp_state != RPORT_ST_DELETE && rdata->disc_id) | 1643 | if (rdata->disc_id) |
1518 | fc_rport_enter_plogi(rdata); | 1644 | fc_rport_state_enter(rdata, RPORT_ST_RESTART); |
1519 | else | ||
1520 | fc_rport_enter_delete(rdata, RPORT_EV_LOGO); | ||
1521 | mutex_unlock(&rdata->rp_mutex); | 1645 | mutex_unlock(&rdata->rp_mutex); |
1522 | } else | 1646 | } else |
1523 | FC_RPORT_ID_DBG(lport, sid, | 1647 | FC_RPORT_ID_DBG(lport, sid, |
@@ -1526,11 +1650,18 @@ static void fc_rport_recv_logo_req(struct fc_lport *lport, | |||
1526 | fc_frame_free(fp); | 1650 | fc_frame_free(fp); |
1527 | } | 1651 | } |
1528 | 1652 | ||
1653 | /** | ||
1654 | * fc_rport_flush_queue() - Flush the rport_event_queue | ||
1655 | */ | ||
1529 | static void fc_rport_flush_queue(void) | 1656 | static void fc_rport_flush_queue(void) |
1530 | { | 1657 | { |
1531 | flush_workqueue(rport_event_queue); | 1658 | flush_workqueue(rport_event_queue); |
1532 | } | 1659 | } |
1533 | 1660 | ||
1661 | /** | ||
1662 | * fc_rport_init() - Initialize the remote port layer for a local port | ||
1663 | * @lport: The local port to initialize the remote port layer for | ||
1664 | */ | ||
1534 | int fc_rport_init(struct fc_lport *lport) | 1665 | int fc_rport_init(struct fc_lport *lport) |
1535 | { | 1666 | { |
1536 | if (!lport->tt.rport_lookup) | 1667 | if (!lport->tt.rport_lookup) |
@@ -1558,25 +1689,33 @@ int fc_rport_init(struct fc_lport *lport) | |||
1558 | } | 1689 | } |
1559 | EXPORT_SYMBOL(fc_rport_init); | 1690 | EXPORT_SYMBOL(fc_rport_init); |
1560 | 1691 | ||
1561 | int fc_setup_rport(void) | 1692 | /** |
1693 | * fc_setup_rport() - Initialize the rport_event_queue | ||
1694 | */ | ||
1695 | int fc_setup_rport() | ||
1562 | { | 1696 | { |
1563 | rport_event_queue = create_singlethread_workqueue("fc_rport_eq"); | 1697 | rport_event_queue = create_singlethread_workqueue("fc_rport_eq"); |
1564 | if (!rport_event_queue) | 1698 | if (!rport_event_queue) |
1565 | return -ENOMEM; | 1699 | return -ENOMEM; |
1566 | return 0; | 1700 | return 0; |
1567 | } | 1701 | } |
1568 | EXPORT_SYMBOL(fc_setup_rport); | ||
1569 | 1702 | ||
1570 | void fc_destroy_rport(void) | 1703 | /** |
1704 | * fc_destroy_rport() - Destroy the rport_event_queue | ||
1705 | */ | ||
1706 | void fc_destroy_rport() | ||
1571 | { | 1707 | { |
1572 | destroy_workqueue(rport_event_queue); | 1708 | destroy_workqueue(rport_event_queue); |
1573 | } | 1709 | } |
1574 | EXPORT_SYMBOL(fc_destroy_rport); | ||
1575 | 1710 | ||
1711 | /** | ||
1712 | * fc_rport_terminate_io() - Stop all outstanding I/O on a remote port | ||
1713 | * @rport: The remote port whose I/O should be terminated | ||
1714 | */ | ||
1576 | void fc_rport_terminate_io(struct fc_rport *rport) | 1715 | void fc_rport_terminate_io(struct fc_rport *rport) |
1577 | { | 1716 | { |
1578 | struct fc_rport_libfc_priv *rp = rport->dd_data; | 1717 | struct fc_rport_libfc_priv *rpriv = rport->dd_data; |
1579 | struct fc_lport *lport = rp->local_port; | 1718 | struct fc_lport *lport = rpriv->local_port; |
1580 | 1719 | ||
1581 | lport->tt.exch_mgr_reset(lport, 0, rport->port_id); | 1720 | lport->tt.exch_mgr_reset(lport, 0, rport->port_id); |
1582 | lport->tt.exch_mgr_reset(lport, rport->port_id, 0); | 1721 | lport->tt.exch_mgr_reset(lport, rport->port_id, 0); |