aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx/qla_os.c
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 /drivers/scsi/qla2xxx/qla_os.c
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 'drivers/scsi/qla2xxx/qla_os.c')
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c21
1 files changed, 13 insertions, 8 deletions
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index b899282a856e..c58c9d97b041 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -348,11 +348,13 @@ qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
348{ 348{
349 scsi_qla_host_t *ha = to_qla_host(cmd->device->host); 349 scsi_qla_host_t *ha = to_qla_host(cmd->device->host);
350 fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; 350 fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
351 struct fc_rport *rport = starget_to_rport(scsi_target(cmd->device));
351 srb_t *sp; 352 srb_t *sp;
352 int rval; 353 int rval;
353 354
354 if (!fcport) { 355 rval = fc_remote_port_chkready(rport);
355 cmd->result = DID_NO_CONNECT << 16; 356 if (rval) {
357 cmd->result = rval;
356 goto qc_fail_command; 358 goto qc_fail_command;
357 } 359 }
358 360
@@ -401,11 +403,13 @@ qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
401{ 403{
402 scsi_qla_host_t *ha = to_qla_host(cmd->device->host); 404 scsi_qla_host_t *ha = to_qla_host(cmd->device->host);
403 fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; 405 fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
406 struct fc_rport *rport = starget_to_rport(scsi_target(cmd->device));
404 srb_t *sp; 407 srb_t *sp;
405 int rval; 408 int rval;
406 409
407 if (!fcport) { 410 rval = fc_remote_port_chkready(rport);
408 cmd->result = DID_NO_CONNECT << 16; 411 if (rval) {
412 cmd->result = rval;
409 goto qc24_fail_command; 413 goto qc24_fail_command;
410 } 414 }
411 415
@@ -1041,10 +1045,10 @@ qla2xxx_slave_alloc(struct scsi_device *sdev)
1041{ 1045{
1042 struct fc_rport *rport = starget_to_rport(scsi_target(sdev)); 1046 struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
1043 1047
1044 if (!rport) 1048 if (!rport || fc_remote_port_chkready(rport))
1045 return -ENXIO; 1049 return -ENXIO;
1046 1050
1047 sdev->hostdata = rport->dd_data; 1051 sdev->hostdata = *(fc_port_t **)rport->dd_data;
1048 1052
1049 return 0; 1053 return 0;
1050} 1054}
@@ -1636,7 +1640,8 @@ void qla2x00_mark_device_lost(scsi_qla_host_t *ha, fc_port_t *fcport,
1636 int do_login) 1640 int do_login)
1637{ 1641{
1638 if (atomic_read(&fcport->state) == FCS_ONLINE && fcport->rport) 1642 if (atomic_read(&fcport->state) == FCS_ONLINE && fcport->rport)
1639 fc_remote_port_block(fcport->rport); 1643 schedule_work(&fcport->rport_del_work);
1644
1640 /* 1645 /*
1641 * We may need to retry the login, so don't change the state of the 1646 * We may need to retry the login, so don't change the state of the
1642 * port but do the retries. 1647 * port but do the retries.
@@ -1697,7 +1702,7 @@ qla2x00_mark_all_devices_lost(scsi_qla_host_t *ha)
1697 if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD) 1702 if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD)
1698 continue; 1703 continue;
1699 if (atomic_read(&fcport->state) == FCS_ONLINE && fcport->rport) 1704 if (atomic_read(&fcport->state) == FCS_ONLINE && fcport->rport)
1700 fc_remote_port_block(fcport->rport); 1705 schedule_work(&fcport->rport_del_work);
1701 atomic_set(&fcport->state, FCS_DEVICE_LOST); 1706 atomic_set(&fcport->state, FCS_DEVICE_LOST);
1702 } 1707 }
1703} 1708}