aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx
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
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')
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h3
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c26
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c21
-rw-r--r--drivers/scsi/qla2xxx/qla_rscn.c3
4 files changed, 40 insertions, 13 deletions
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index fc3234c3625b..7096945ea234 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -21,6 +21,7 @@
21#include <linux/spinlock.h> 21#include <linux/spinlock.h>
22#include <linux/completion.h> 22#include <linux/completion.h>
23#include <linux/interrupt.h> 23#include <linux/interrupt.h>
24#include <linux/workqueue.h>
24#include <asm/semaphore.h> 25#include <asm/semaphore.h>
25 26
26#include <scsi/scsi.h> 27#include <scsi/scsi.h>
@@ -1665,6 +1666,8 @@ typedef struct fc_port {
1665 1666
1666 struct fc_rport *rport; 1667 struct fc_rport *rport;
1667 u32 supported_classes; 1668 u32 supported_classes;
1669 struct work_struct rport_add_work;
1670 struct work_struct rport_del_work;
1668} fc_port_t; 1671} fc_port_t;
1669 1672
1670/* 1673/*
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index ce7e712ebe8d..290a6b92616c 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -1668,6 +1668,24 @@ qla2x00_nvram_config(scsi_qla_host_t *ha)
1668 return (rval); 1668 return (rval);
1669} 1669}
1670 1670
1671static void
1672qla2x00_rport_add(void *data)
1673{
1674 fc_port_t *fcport = data;
1675
1676 qla2x00_reg_remote_port(fcport->ha, fcport);
1677}
1678
1679static void
1680qla2x00_rport_del(void *data)
1681{
1682 fc_port_t *fcport = data;
1683
1684 if (fcport->rport)
1685 fc_remote_port_delete(fcport->rport);
1686 fcport->rport = NULL;
1687}
1688
1671/** 1689/**
1672 * qla2x00_alloc_fcport() - Allocate a generic fcport. 1690 * qla2x00_alloc_fcport() - Allocate a generic fcport.
1673 * @ha: HA context 1691 * @ha: HA context
@@ -1693,6 +1711,8 @@ qla2x00_alloc_fcport(scsi_qla_host_t *ha, gfp_t flags)
1693 atomic_set(&fcport->state, FCS_UNCONFIGURED); 1711 atomic_set(&fcport->state, FCS_UNCONFIGURED);
1694 fcport->flags = FCF_RLC_SUPPORT; 1712 fcport->flags = FCF_RLC_SUPPORT;
1695 fcport->supported_classes = FC_COS_UNSPECIFIED; 1713 fcport->supported_classes = FC_COS_UNSPECIFIED;
1714 INIT_WORK(&fcport->rport_add_work, qla2x00_rport_add, fcport);
1715 INIT_WORK(&fcport->rport_del_work, qla2x00_rport_del, fcport);
1696 1716
1697 return (fcport); 1717 return (fcport);
1698} 1718}
@@ -2056,8 +2076,8 @@ qla2x00_reg_remote_port(scsi_qla_host_t *ha, fc_port_t *fcport)
2056 struct fc_rport *rport; 2076 struct fc_rport *rport;
2057 2077
2058 if (fcport->rport) { 2078 if (fcport->rport) {
2059 fc_remote_port_unblock(fcport->rport); 2079 fc_remote_port_delete(fcport->rport);
2060 return; 2080 fcport->rport = NULL;
2061 } 2081 }
2062 2082
2063 rport_ids.node_name = wwn_to_u64(fcport->node_name); 2083 rport_ids.node_name = wwn_to_u64(fcport->node_name);
@@ -2071,7 +2091,7 @@ qla2x00_reg_remote_port(scsi_qla_host_t *ha, fc_port_t *fcport)
2071 "Unable to allocate fc remote port!\n"); 2091 "Unable to allocate fc remote port!\n");
2072 return; 2092 return;
2073 } 2093 }
2074 rport->dd_data = fcport; 2094 *((fc_port_t **)rport->dd_data) = fcport;
2075 rport->supported_classes = fcport->supported_classes; 2095 rport->supported_classes = fcport->supported_classes;
2076 2096
2077 rport_ids.roles = FC_RPORT_ROLE_UNKNOWN; 2097 rport_ids.roles = FC_RPORT_ROLE_UNKNOWN;
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}
diff --git a/drivers/scsi/qla2xxx/qla_rscn.c b/drivers/scsi/qla2xxx/qla_rscn.c
index 3e53f62d640d..2c3342108dd8 100644
--- a/drivers/scsi/qla2xxx/qla_rscn.c
+++ b/drivers/scsi/qla2xxx/qla_rscn.c
@@ -320,8 +320,7 @@ qla2x00_update_login_fcport(scsi_qla_host_t *ha, struct mbx_entry *mbxstat,
320 fcport->flags &= ~FCF_FAILOVER_NEEDED; 320 fcport->flags &= ~FCF_FAILOVER_NEEDED;
321 fcport->iodesc_idx_sent = IODESC_INVALID_INDEX; 321 fcport->iodesc_idx_sent = IODESC_INVALID_INDEX;
322 atomic_set(&fcport->state, FCS_ONLINE); 322 atomic_set(&fcport->state, FCS_ONLINE);
323 if (fcport->rport) 323 schedule_work(&fcport->rport_add_work);
324 fc_remote_port_unblock(fcport->rport);
325} 324}
326 325
327 326