aboutsummaryrefslogtreecommitdiffstats
path: root/include/scsi
diff options
context:
space:
mode:
authorJames.Smart@Emulex.Com <James.Smart@Emulex.Com>2005-10-18 12:03:35 -0400
committerJames Bottomley <jejb@mulgrave.(none)>2005-10-28 22:20:07 -0400
commit19a7b4aebf9ad435c69a7e39930338499af4d152 (patch)
tree6d1c4cbc822009c8facb219dcd955d52070655d1 /include/scsi
parent422c0d61d591cbfb70f029e13505fb437e169d68 (diff)
[SCSI] update fc_transport for removal of block/unblock functions
We recently went back to implement a board reset. When we perform the reset, we wanted to tear down the internal data structures and rebuild them. Unfortunately, when it came to the rport structure, things were odd. If we deleted them, the scsi targets and sdevs would be torn down. Not a good thing for a temporary reset. We could block the rports, but we either maintain the internal structures to keep the rport reference (perhaps even replicating what's in the transport), or we have to fatten the fc transport with new search routines to find the rport (and deal with a case of a dangling rport that the driver forgets). It dawned on me that we had actually reached this state incorrectly. When the fc transport first started, we did the block/unblock first, then added the rport interface. The purpose of block/unblock is to hide the temporary disappearance of the rport (e.g. being deleted, then readded). Why are we making the driver do the block/unblock ? We should be making the transport have only an rport add/delete, and the let the transport handle the block/unblock. So... This patch removes the existing fc_remote_port_block/unblock functions. It moves the block/unblock functionality into the fc_remote_port_add/delete functions. Updates for the lpfc driver are included. Qlogic driver updates are also enclosed, thanks to the contributions of Andrew Vasquez. [Note: the qla2xxx changes are relative to the scsi-misc-2.6 tree as of this morning - which does not include the recent patches sent by Andrew]. The zfcp driver does not use the block/unblock functions. One last comment: The resulting behavior feels very clean. The LLDD is concerned only with add/delete, which corresponds to the physical disappearance. However, the fact that the scsi target and sdevs are not immediately torn down after the LLDD calls delete causes an interesting scenario... the midlayer can call the xxx_slave_alloc and xxx_queuecommand functions with a sdev that is at the location the rport used to be. The driver must validate the device exists when it first enters these functions. In thinking about it, this has always been the case for the LLDD and these routines. The existing drivers already check for existence. However, this highlights that simple validation via data structure dereferencing needs to be watched. To deal with this, a new transport function, fc_remote_port_chkready() was created that LLDDs should call when they first enter these two routines. It validates the rport state, and returns a scsi result which could be returned. In addition to solving the above, it also creates consistent behavior from the LLDD's when the block and deletes are occuring. Rejections fixed up and Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'include/scsi')
-rw-r--r--include/scsi/scsi_transport_fc.h31
1 files changed, 29 insertions, 2 deletions
diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
index 4496b32972e..319ff7a60df 100644
--- a/include/scsi/scsi_transport_fc.h
+++ b/include/scsi/scsi_transport_fc.h
@@ -28,6 +28,7 @@
28#define SCSI_TRANSPORT_FC_H 28#define SCSI_TRANSPORT_FC_H
29 29
30#include <linux/config.h> 30#include <linux/config.h>
31#include <scsi/scsi.h>
31 32
32struct scsi_transport_template; 33struct scsi_transport_template;
33 34
@@ -429,6 +430,34 @@ struct fc_function_template {
429}; 430};
430 431
431 432
433/**
434 * fc_remote_port_chkready - called to validate the remote port state
435 * prior to initiating io to the port.
436 *
437 * Returns a scsi result code that can be returned by the LLDD.
438 *
439 * @rport: remote port to be checked
440 **/
441static inline int
442fc_remote_port_chkready(struct fc_rport *rport)
443{
444 int result;
445
446 switch (rport->port_state) {
447 case FC_PORTSTATE_ONLINE:
448 result = 0;
449 break;
450 case FC_PORTSTATE_BLOCKED:
451 result = DID_BUS_BUSY << 16;
452 break;
453 default:
454 result = DID_NO_CONNECT << 16;
455 break;
456 }
457 return result;
458}
459
460
432struct scsi_transport_template *fc_attach_transport( 461struct scsi_transport_template *fc_attach_transport(
433 struct fc_function_template *); 462 struct fc_function_template *);
434void fc_release_transport(struct scsi_transport_template *); 463void fc_release_transport(struct scsi_transport_template *);
@@ -437,8 +466,6 @@ struct fc_rport *fc_remote_port_add(struct Scsi_Host *shost,
437 int channel, struct fc_rport_identifiers *ids); 466 int channel, struct fc_rport_identifiers *ids);
438void fc_remote_port_delete(struct fc_rport *rport); 467void fc_remote_port_delete(struct fc_rport *rport);
439void fc_remote_port_rolechg(struct fc_rport *rport, u32 roles); 468void fc_remote_port_rolechg(struct fc_rport *rport, u32 roles);
440int fc_remote_port_block(struct fc_rport *rport);
441void fc_remote_port_unblock(struct fc_rport *rport);
442int scsi_is_fc_rport(const struct device *); 469int scsi_is_fc_rport(const struct device *);
443 470
444static inline u64 wwn_to_u64(u8 *wwn) 471static inline u64 wwn_to_u64(u8 *wwn)