* [PATCH 00/22] Open-FCoE Features for 2.6.32
@ 2009-07-30 0:03 Robert Love
2009-07-30 0:03 ` [PATCH 01/22] fcoe: Fix validation of mac address when checking for spma support Robert Love
` (21 more replies)
0 siblings, 22 replies; 23+ messages in thread
From: Robert Love @ 2009-07-30 0:03 UTC (permalink / raw)
To: James.Bottomley, linux-scsi
The following series contains the first set of features for libfc, libfcoe and fcoe.
The largest change is to share an Exchange Manager amongst virtual interfaces (VLANs) on a physical interface. This will change will also help with NPIV support which should come in a later patch set.
Other than that, there are a lot of miscellaneous fixes and improvements to all three modules.
---
Joe Eykholt (10):
libfc: fix: cancel rport retry timer
libfc: fc_rport_logoff should not drop the lock
libfc: rename rport state "NONE" to "DELETE".
libfc: fix WARNING from fc_seq_start_next on closed exchanges
libfc: in fc_lport_destroy, flush rports after turning off link
libfc: stop login after fabric logoff
libfc: rename lport NONE state to DISABLED
fcoe: stop delivery of received frames before doing lport_destroy()
libfc: change debug messages to give host number.
libfc: remove extra semicolons from debug macros
Robert Love (1):
libfc: Remove the FC_EM_DBG macro
Vasu Dev (5):
fcoe: removes phys_dev and renames real_dev to netdev.
fcoe, libfc: adds offload EM per eth device with only single xid range per EM
fcoe: modifies fcoe_hostlist_lock uses as prep work to add shared offload EM
fcoe, fnic, libfc: modifies current code paths to use EM anchor list
fcoe, libfc: adds exchange manager(EM) anchor list per lport and related APIs
Yi Zou (6):
libfc: Remove page flags check for sglist
libfc: Remove FC_FRAME_SG_LEN in fc_fcp_send_data
fcoe: Remove ifdef for NETIF_F_FCOE_CRC and NETIF_F_FSO
fcoe: Call dev_ethtool_get_settings() in fcoe_link_ok
libfcoe: Set fip_flags according to fcf and lport's capability of SPMA support
fcoe: Fix validation of mac address when checking for spma support
drivers/scsi/fcoe/fcoe.c | 250 +++++++++++++++++++-----------
drivers/scsi/fcoe/fcoe.h | 8 -
drivers/scsi/fcoe/libfcoe.c | 14 +-
drivers/scsi/fnic/fnic_fcs.c | 2
drivers/scsi/fnic/fnic_main.c | 20 +-
drivers/scsi/libfc/fc_exch.c | 337 ++++++++++++++++++++++-------------------
drivers/scsi/libfc/fc_fcp.c | 29 ----
drivers/scsi/libfc/fc_lport.c | 61 ++++++-
drivers/scsi/libfc/fc_rport.c | 83 ++++++----
include/scsi/fc_frame.h | 7 -
include/scsi/libfc.h | 126 +++++++--------
11 files changed, 518 insertions(+), 419 deletions(-)
--
//Rob
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH 01/22] fcoe: Fix validation of mac address when checking for spma support
2009-07-30 0:03 [PATCH 00/22] Open-FCoE Features for 2.6.32 Robert Love
@ 2009-07-30 0:03 ` Robert Love
2009-07-30 0:03 ` [PATCH 02/22] libfcoe: Set fip_flags according to fcf and lport's capability of SPMA support Robert Love
` (20 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Robert Love @ 2009-07-30 0:03 UTC (permalink / raw)
To: James.Bottomley, linux-scsi; +Cc: Yi Zou, Robert Love
From: Yi Zou <yi.zou@intel.com>
Fix this bug of validating the wrong mac address while checking for SAN MAC
address support from LLD as we should check ha->addr not ctlr.ctl_src_addr.
Signed-off-by: Yi Zou <yi.zou@intel.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---
drivers/scsi/fcoe/fcoe.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 0a5609b..b7dfc6e 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -329,7 +329,7 @@ static int fcoe_netdev_config(struct fc_lport *lp, struct net_device *netdev)
rcu_read_lock();
for_each_dev_addr(netdev, ha) {
if ((ha->type == NETDEV_HW_ADDR_T_SAN) &&
- (is_valid_ether_addr(fc->ctlr.ctl_src_addr))) {
+ (is_valid_ether_addr(ha->addr))) {
memcpy(fc->ctlr.ctl_src_addr, ha->addr, ETH_ALEN);
fc->ctlr.spma = 1;
break;
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 02/22] libfcoe: Set fip_flags according to fcf and lport's capability of SPMA support
2009-07-30 0:03 [PATCH 00/22] Open-FCoE Features for 2.6.32 Robert Love
2009-07-30 0:03 ` [PATCH 01/22] fcoe: Fix validation of mac address when checking for spma support Robert Love
@ 2009-07-30 0:03 ` Robert Love
2009-07-30 0:04 ` [PATCH 03/22] fcoe: Call dev_ethtool_get_settings() in fcoe_link_ok Robert Love
` (19 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Robert Love @ 2009-07-30 0:03 UTC (permalink / raw)
To: James.Bottomley, linux-scsi; +Cc: Yi Zou, Robert Love
From: Yi Zou <yi.zou@intel.com>
When encap the els for FIP, set the fip_flags according to the FCF and lport's
capability of supporting SPMA or FPMA or both.
Signed-off-by: Yi Zou <yi.zou@intel.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---
drivers/scsi/fcoe/libfcoe.c | 12 +++++++++---
1 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c
index d6ed3f8..78caa6b 100644
--- a/drivers/scsi/fcoe/libfcoe.c
+++ b/drivers/scsi/fcoe/libfcoe.c
@@ -413,10 +413,18 @@ static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip,
struct fip_mac_desc *mac;
struct fcoe_fcf *fcf;
size_t dlen;
+ u16 fip_flags;
fcf = fip->sel_fcf;
if (!fcf)
return -ENODEV;
+
+ /* set flags according to both FCF and lport's capability on SPMA */
+ fip_flags = fcf->flags;
+ fip_flags &= fip->spma ? FIP_FL_SPMA | FIP_FL_FPMA : FIP_FL_FPMA;
+ if (!fip_flags)
+ return -ENODEV;
+
dlen = sizeof(struct fip_encaps) + skb->len; /* len before push */
cap = (struct fip_encaps_head *)skb_push(skb, sizeof(*cap));
@@ -429,9 +437,7 @@ static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip,
cap->fip.fip_op = htons(FIP_OP_LS);
cap->fip.fip_subcode = FIP_SC_REQ;
cap->fip.fip_dl_len = htons((dlen + sizeof(*mac)) / FIP_BPW);
- cap->fip.fip_flags = htons(FIP_FL_FPMA);
- if (fip->spma)
- cap->fip.fip_flags |= htons(FIP_FL_SPMA);
+ cap->fip.fip_flags = htons(fip_flags);
cap->encaps.fd_desc.fip_dtype = dtype;
cap->encaps.fd_desc.fip_dlen = dlen / FIP_BPW;
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 03/22] fcoe: Call dev_ethtool_get_settings() in fcoe_link_ok
2009-07-30 0:03 [PATCH 00/22] Open-FCoE Features for 2.6.32 Robert Love
2009-07-30 0:03 ` [PATCH 01/22] fcoe: Fix validation of mac address when checking for spma support Robert Love
2009-07-30 0:03 ` [PATCH 02/22] libfcoe: Set fip_flags according to fcf and lport's capability of SPMA support Robert Love
@ 2009-07-30 0:04 ` Robert Love
2009-07-30 0:04 ` [PATCH 04/22] libfc: remove extra semicolons from debug macros Robert Love
` (18 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Robert Love @ 2009-07-30 0:04 UTC (permalink / raw)
To: James.Bottomley, linux-scsi; +Cc: Yi Zou, Robert Love
From: Yi Zou <yi.zou@intel.com>
No need to check phys_dev here, just call dev_ethtool_get_settings() directly
will take care of this.
Signed-off-by: Yi Zou <yi.zou@intel.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---
drivers/scsi/fcoe/fcoe.c | 38 +++++++++++++++++---------------------
1 files changed, 17 insertions(+), 21 deletions(-)
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index b7dfc6e..8160126 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -1635,29 +1635,25 @@ int fcoe_link_ok(struct fc_lport *lp)
struct fcoe_softc *fc = lport_priv(lp);
struct net_device *dev = fc->real_dev;
struct ethtool_cmd ecmd = { ETHTOOL_GSET };
- int rc = 0;
- if ((dev->flags & IFF_UP) && netif_carrier_ok(dev)) {
- dev = fc->phys_dev;
- if (dev->ethtool_ops->get_settings) {
- dev->ethtool_ops->get_settings(dev, &ecmd);
- lp->link_supported_speeds &=
- ~(FC_PORTSPEED_1GBIT | FC_PORTSPEED_10GBIT);
- if (ecmd.supported & (SUPPORTED_1000baseT_Half |
- SUPPORTED_1000baseT_Full))
- lp->link_supported_speeds |= FC_PORTSPEED_1GBIT;
- if (ecmd.supported & SUPPORTED_10000baseT_Full)
- lp->link_supported_speeds |=
- FC_PORTSPEED_10GBIT;
- if (ecmd.speed == SPEED_1000)
- lp->link_speed = FC_PORTSPEED_1GBIT;
- if (ecmd.speed == SPEED_10000)
- lp->link_speed = FC_PORTSPEED_10GBIT;
- }
- } else
- rc = -1;
+ if ((dev->flags & IFF_UP) && netif_carrier_ok(dev) &&
+ (!dev_ethtool_get_settings(dev, &ecmd))) {
+ lp->link_supported_speeds &=
+ ~(FC_PORTSPEED_1GBIT | FC_PORTSPEED_10GBIT);
+ if (ecmd.supported & (SUPPORTED_1000baseT_Half |
+ SUPPORTED_1000baseT_Full))
+ lp->link_supported_speeds |= FC_PORTSPEED_1GBIT;
+ if (ecmd.supported & SUPPORTED_10000baseT_Full)
+ lp->link_supported_speeds |=
+ FC_PORTSPEED_10GBIT;
+ if (ecmd.speed == SPEED_1000)
+ lp->link_speed = FC_PORTSPEED_1GBIT;
+ if (ecmd.speed == SPEED_10000)
+ lp->link_speed = FC_PORTSPEED_10GBIT;
- return rc;
+ return 0;
+ }
+ return -1;
}
/**
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 04/22] libfc: remove extra semicolons from debug macros
2009-07-30 0:03 [PATCH 00/22] Open-FCoE Features for 2.6.32 Robert Love
` (2 preceding siblings ...)
2009-07-30 0:04 ` [PATCH 03/22] fcoe: Call dev_ethtool_get_settings() in fcoe_link_ok Robert Love
@ 2009-07-30 0:04 ` Robert Love
2009-07-30 0:04 ` [PATCH 05/22] libfc: change debug messages to give host number Robert Love
` (17 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Robert Love @ 2009-07-30 0:04 UTC (permalink / raw)
To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love
From: Joe Eykholt <jeykholt@cisco.com>
This is unlikely to cause any problems, but the libfc debug macros
introduce extra undesirable semicolons.
Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---
include/scsi/libfc.h | 20 ++++++++++----------
1 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index b92584a..ef04a2c 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -51,22 +51,22 @@ do { \
do { \
CMD; \
} while (0); \
-} while (0);
+} while (0)
#define FC_LIBFC_DBG(fmt, args...) \
FC_CHECK_LOGGING(FC_LIBFC_LOGGING, \
- printk(KERN_INFO "libfc: " fmt, ##args);)
+ printk(KERN_INFO "libfc: " fmt, ##args))
#define FC_LPORT_DBG(lport, fmt, args...) \
FC_CHECK_LOGGING(FC_LPORT_LOGGING, \
printk(KERN_INFO "lport: %6x: " fmt, \
- fc_host_port_id(lport->host), ##args);)
+ fc_host_port_id(lport->host), ##args))
#define FC_DISC_DBG(disc, fmt, args...) \
FC_CHECK_LOGGING(FC_DISC_LOGGING, \
printk(KERN_INFO "disc: %6x: " fmt, \
fc_host_port_id(disc->lport->host), \
- ##args);)
+ ##args))
#define FC_RPORT_DBG(rport, fmt, args...) \
do { \
@@ -75,31 +75,31 @@ do { \
FC_CHECK_LOGGING(FC_RPORT_LOGGING, \
printk(KERN_INFO "rport: %6x: %6x: " fmt, \
fc_host_port_id(lport->host), \
- rport->port_id, ##args);) \
-} while (0);
+ rport->port_id, ##args)); \
+} while (0)
#define FC_FCP_DBG(pkt, fmt, args...) \
FC_CHECK_LOGGING(FC_FCP_LOGGING, \
printk(KERN_INFO "fcp: %6x: %6x: " fmt, \
fc_host_port_id(pkt->lp->host), \
- pkt->rport->port_id, ##args);)
+ pkt->rport->port_id, ##args))
#define FC_EM_DBG(em, fmt, args...) \
FC_CHECK_LOGGING(FC_EM_LOGGING, \
printk(KERN_INFO "em: %6x: " fmt, \
fc_host_port_id(em->lp->host), \
- ##args);)
+ ##args))
#define FC_EXCH_DBG(exch, fmt, args...) \
FC_CHECK_LOGGING(FC_EXCH_LOGGING, \
printk(KERN_INFO "exch: %6x: %4x: " fmt, \
fc_host_port_id(exch->lp->host), \
- exch->xid, ##args);)
+ exch->xid, ##args))
#define FC_SCSI_DBG(lport, fmt, args...) \
FC_CHECK_LOGGING(FC_SCSI_LOGGING, \
printk(KERN_INFO "scsi: %6x: " fmt, \
- fc_host_port_id(lport->host), ##args);)
+ fc_host_port_id(lport->host), ##args))
/*
* libfc error codes
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 05/22] libfc: change debug messages to give host number.
2009-07-30 0:03 [PATCH 00/22] Open-FCoE Features for 2.6.32 Robert Love
` (3 preceding siblings ...)
2009-07-30 0:04 ` [PATCH 04/22] libfc: remove extra semicolons from debug macros Robert Love
@ 2009-07-30 0:04 ` Robert Love
2009-07-30 0:04 ` [PATCH 06/22] fcoe: stop delivery of received frames before doing lport_destroy() Robert Love
` (16 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Robert Love @ 2009-07-30 0:04 UTC (permalink / raw)
To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love
From: Joe Eykholt <jeykholt@cisco.com>
libfc debug messages currently show 'lport: <fc-id>:'
wher <fc-id> is the hex assigned port-id. When the lport
is logged off, that will be zero, so its hard to distinguish
which instance is involved. The FC-ID can change
if the port is re-patched or changes VSANs.
Two lports may even have the same FC-ID if connected to isolated SANs.
Change the debug messages to print the SCSI host number "hostN:",
which will not change for the life of the lport.
Still show the FC_ID on lport messages.
Also, add a macro to FC_RPORT_ID_DBG for rport debugging where there's
no rdata structure involved. It takes the lport and port_id as parameters.
Use this in fc_rport_recv_plogi_req() and fc_rport_recv_logo_req().
Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---
include/scsi/libfc.h | 36 ++++++++++++++++++++----------------
1 files changed, 20 insertions(+), 16 deletions(-)
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index ef04a2c..efdb6ba 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -59,47 +59,51 @@ do { \
#define FC_LPORT_DBG(lport, fmt, args...) \
FC_CHECK_LOGGING(FC_LPORT_LOGGING, \
- printk(KERN_INFO "lport: %6x: " fmt, \
- fc_host_port_id(lport->host), ##args))
+ printk(KERN_INFO "host%u: lport %6x: " fmt, \
+ (lport)->host->host_no, \
+ fc_host_port_id((lport)->host), ##args))
#define FC_DISC_DBG(disc, fmt, args...) \
FC_CHECK_LOGGING(FC_DISC_LOGGING, \
- printk(KERN_INFO "disc: %6x: " fmt, \
- fc_host_port_id(disc->lport->host), \
+ printk(KERN_INFO "host%u: disc: " fmt, \
+ (disc)->lport->host->host_no, \
##args))
+#define FC_RPORT_ID_DBG(lport, port_id, fmt, args...) \
+ FC_CHECK_LOGGING(FC_RPORT_LOGGING, \
+ printk(KERN_INFO "host%u: rport %6x: " fmt, \
+ (lport)->host->host_no, \
+ (port_id), ##args))
+
#define FC_RPORT_DBG(rport, fmt, args...) \
do { \
struct fc_rport_libfc_priv *rdata = rport->dd_data; \
struct fc_lport *lport = rdata->local_port; \
- FC_CHECK_LOGGING(FC_RPORT_LOGGING, \
- printk(KERN_INFO "rport: %6x: %6x: " fmt, \
- fc_host_port_id(lport->host), \
- rport->port_id, ##args)); \
+ FC_RPORT_ID_DBG(lport, rport->port_id, fmt, ##args); \
} while (0)
#define FC_FCP_DBG(pkt, fmt, args...) \
FC_CHECK_LOGGING(FC_FCP_LOGGING, \
- printk(KERN_INFO "fcp: %6x: %6x: " fmt, \
- fc_host_port_id(pkt->lp->host), \
+ printk(KERN_INFO "host%u: fcp: %6x: " fmt, \
+ (pkt)->lp->host->host_no, \
pkt->rport->port_id, ##args))
#define FC_EM_DBG(em, fmt, args...) \
FC_CHECK_LOGGING(FC_EM_LOGGING, \
- printk(KERN_INFO "em: %6x: " fmt, \
- fc_host_port_id(em->lp->host), \
+ printk(KERN_INFO "host%u: em: " fmt, \
+ (em)->lp->host->host_no, \
##args))
#define FC_EXCH_DBG(exch, fmt, args...) \
FC_CHECK_LOGGING(FC_EXCH_LOGGING, \
- printk(KERN_INFO "exch: %6x: %4x: " fmt, \
- fc_host_port_id(exch->lp->host), \
+ printk(KERN_INFO "host%u: xid %4x: " fmt, \
+ (exch)->lp->host->host_no, \
exch->xid, ##args))
#define FC_SCSI_DBG(lport, fmt, args...) \
FC_CHECK_LOGGING(FC_SCSI_LOGGING, \
- printk(KERN_INFO "scsi: %6x: " fmt, \
- fc_host_port_id(lport->host), ##args))
+ printk(KERN_INFO "host%u: scsi: " fmt, \
+ (lport)->host->host_no, ##args))
/*
* libfc error codes
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 06/22] fcoe: stop delivery of received frames before doing lport_destroy()
2009-07-30 0:03 [PATCH 00/22] Open-FCoE Features for 2.6.32 Robert Love
` (4 preceding siblings ...)
2009-07-30 0:04 ` [PATCH 05/22] libfc: change debug messages to give host number Robert Love
@ 2009-07-30 0:04 ` Robert Love
2009-07-30 0:04 ` [PATCH 07/22] libfc: rename lport NONE state to DISABLED Robert Love
` (15 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Robert Love @ 2009-07-30 0:04 UTC (permalink / raw)
To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love
From: Joe Eykholt <jeykholt@cisco.com>
To be more sure that no more input arrives at the local port as
it is being destroyed, clean the queues in the per-cpu receive
threads.
Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---
drivers/scsi/fcoe/fcoe.c | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 8160126..14a4017 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -466,6 +466,9 @@ static int fcoe_if_destroy(struct net_device *netdev)
/* tear-down the FCoE controller */
fcoe_ctlr_destroy(&fc->ctlr);
+ /* Free queued packets for the per-CPU receive threads */
+ fcoe_percpu_clean(lp);
+
/* Cleanup the fc_lport */
fc_lport_destroy(lp);
fc_fcp_destroy(lp);
@@ -478,9 +481,6 @@ static int fcoe_if_destroy(struct net_device *netdev)
if (lp->emp)
fc_exch_mgr_free(lp->emp);
- /* Free the per-CPU receive threads */
- fcoe_percpu_clean(lp);
-
/* Free existing skbs */
fcoe_clean_pending_queue(lp);
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 07/22] libfc: rename lport NONE state to DISABLED
2009-07-30 0:03 [PATCH 00/22] Open-FCoE Features for 2.6.32 Robert Love
` (5 preceding siblings ...)
2009-07-30 0:04 ` [PATCH 06/22] fcoe: stop delivery of received frames before doing lport_destroy() Robert Love
@ 2009-07-30 0:04 ` Robert Love
2009-07-30 0:04 ` [PATCH 08/22] libfc: stop login after fabric logoff Robert Love
` (14 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Robert Love @ 2009-07-30 0:04 UTC (permalink / raw)
To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love
From: Joe Eykholt <jeykholt@cisco.com>
The state NONE was meant to be invalid, but has been used as
the initial state. Rename it to be DISABLED, as more descriptive.
Further patches will make it the like the RESET state, except
it won't transition to FLOGI until fc_lport_fabric_login() is called.
Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---
drivers/scsi/libfc/fc_exch.c | 2 +-
drivers/scsi/libfc/fc_lport.c | 12 ++++++------
include/scsi/libfc.h | 2 +-
3 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index 145ab9b..e6d82d7 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -1875,7 +1875,7 @@ void fc_exch_recv(struct fc_lport *lp, struct fc_exch_mgr *mp,
u32 f_ctl;
/* lport lock ? */
- if (!lp || !mp || (lp->state == LPORT_ST_NONE)) {
+ if (!lp || !mp || lp->state == LPORT_ST_DISABLED) {
FC_LPORT_DBG(lp, "Receiving frames for an lport that "
"has not been initialized correctly\n");
fc_frame_free(fp);
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index 745fa55..3b28190 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -113,7 +113,7 @@ static void fc_lport_enter_ready(struct fc_lport *);
static void fc_lport_enter_logo(struct fc_lport *);
static const char *fc_lport_state_names[] = {
- [LPORT_ST_NONE] = "none",
+ [LPORT_ST_DISABLED] = "disabled",
[LPORT_ST_FLOGI] = "FLOGI",
[LPORT_ST_DNS] = "dNS",
[LPORT_ST_RPN_ID] = "RPN_ID",
@@ -550,7 +550,7 @@ int fc_fabric_login(struct fc_lport *lport)
int rc = -1;
mutex_lock(&lport->lp_mutex);
- if (lport->state == LPORT_ST_NONE) {
+ if (lport->state == LPORT_ST_DISABLED) {
fc_lport_enter_reset(lport);
rc = 0;
}
@@ -637,7 +637,7 @@ EXPORT_SYMBOL(fc_fabric_logoff);
int fc_lport_destroy(struct fc_lport *lport)
{
mutex_lock(&lport->lp_mutex);
- lport->state = LPORT_ST_NONE;
+ lport->state = LPORT_ST_DISABLED;
lport->link_up = 0;
lport->tt.frame_send = fc_frame_drop;
mutex_unlock(&lport->lp_mutex);
@@ -992,7 +992,7 @@ static void fc_lport_error(struct fc_lport *lport, struct fc_frame *fp)
schedule_delayed_work(&lport->retry_work, delay);
} else {
switch (lport->state) {
- case LPORT_ST_NONE:
+ case LPORT_ST_DISABLED:
case LPORT_ST_READY:
case LPORT_ST_RESET:
case LPORT_ST_RPN_ID:
@@ -1316,7 +1316,7 @@ static void fc_lport_timeout(struct work_struct *work)
mutex_lock(&lport->lp_mutex);
switch (lport->state) {
- case LPORT_ST_NONE:
+ case LPORT_ST_DISABLED:
case LPORT_ST_READY:
case LPORT_ST_RESET:
WARN_ON(1);
@@ -1550,7 +1550,7 @@ int fc_lport_config(struct fc_lport *lport)
INIT_DELAYED_WORK(&lport->retry_work, fc_lport_timeout);
mutex_init(&lport->lp_mutex);
- fc_lport_state_enter(lport, LPORT_ST_NONE);
+ fc_lport_state_enter(lport, LPORT_ST_DISABLED);
fc_lport_add_fc4_type(lport, FC_TYPE_FCP);
fc_lport_add_fc4_type(lport, FC_TYPE_CT);
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index efdb6ba..b5c9b28 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -129,7 +129,7 @@ do { \
* FC HBA status
*/
enum fc_lport_state {
- LPORT_ST_NONE = 0,
+ LPORT_ST_DISABLED = 0,
LPORT_ST_FLOGI,
LPORT_ST_DNS,
LPORT_ST_RPN_ID,
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 08/22] libfc: stop login after fabric logoff
2009-07-30 0:03 [PATCH 00/22] Open-FCoE Features for 2.6.32 Robert Love
` (6 preceding siblings ...)
2009-07-30 0:04 ` [PATCH 07/22] libfc: rename lport NONE state to DISABLED Robert Love
@ 2009-07-30 0:04 ` Robert Love
2009-07-30 0:04 ` [PATCH 09/22] libfc: in fc_lport_destroy, flush rports after turning off link Robert Love
` (13 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Robert Love @ 2009-07-30 0:04 UTC (permalink / raw)
To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love
From: Joe Eykholt <jeykholt@cisco.com>
When removing the fcoe module, several lports were being shut down
through fc_lport_fabric_logoff().
Occasionally, one would enter reset state before fc_lport_destroy()
was called, and since link_up was still true, it would log back in.
If we just clear link_up earlier, then we wouldn't be accepting LOGO
requests from other initiators while we are shutting down.
Fix by changing the LOGO response handler to enter DISABLED instead
of RESET. Add an fc_lport_enter_disabled() function which does
what fc_lport_enter_reset() did, except it doesn't proceed to FLOGI state.
Move the code that was common between fc_lport_enter_reset() and
fc_lport_enter_disabled() into a new fc_lport_reset_locked() function.
Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---
drivers/scsi/libfc/fc_lport.c | 42 +++++++++++++++++++++++++++++++++--------
1 files changed, 34 insertions(+), 8 deletions(-)
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index 3b28190..7bb451a 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -930,19 +930,14 @@ int fc_lport_reset(struct fc_lport *lport)
EXPORT_SYMBOL(fc_lport_reset);
/**
- * fc_rport_enter_reset() - Reset the local port
+ * fc_lport_reset_locked() - Reset the local port
* @lport: Fibre Channel local port to be reset
*
* Locking Note: The lport lock is expected to be held before calling
* this routine.
*/
-static void fc_lport_enter_reset(struct fc_lport *lport)
+static void fc_lport_reset_locked(struct fc_lport *lport)
{
- FC_LPORT_DBG(lport, "Entered RESET state from %s state\n",
- fc_lport_state(lport));
-
- fc_lport_state_enter(lport, LPORT_ST_RESET);
-
if (lport->dns_rp)
lport->tt.rport_logoff(lport->dns_rp);
@@ -956,12 +951,43 @@ static void fc_lport_enter_reset(struct fc_lport *lport)
lport->tt.exch_mgr_reset(lport, 0, 0);
fc_host_fabric_name(lport->host) = 0;
fc_host_port_id(lport->host) = 0;
+}
+
+/**
+ * fc_lport_enter_reset() - Reset the local port
+ * @lport: Fibre Channel local port to be reset
+ *
+ * Locking Note: The lport lock is expected to be held before calling
+ * this routine.
+ */
+static void fc_lport_enter_reset(struct fc_lport *lport)
+{
+ FC_LPORT_DBG(lport, "Entered RESET state from %s state\n",
+ fc_lport_state(lport));
+ fc_lport_state_enter(lport, LPORT_ST_RESET);
+ fc_lport_reset_locked(lport);
if (lport->link_up)
fc_lport_enter_flogi(lport);
}
/**
+ * fc_lport_enter_disabled() - disable the local port
+ * @lport: Fibre Channel local port to be reset
+ *
+ * Locking Note: The lport lock is expected to be held before calling
+ * this routine.
+ */
+static void fc_lport_enter_disabled(struct fc_lport *lport)
+{
+ FC_LPORT_DBG(lport, "Entered disabled state from %s state\n",
+ fc_lport_state(lport));
+
+ fc_lport_state_enter(lport, LPORT_ST_DISABLED);
+ fc_lport_reset_locked(lport);
+}
+
+/**
* fc_lport_error() - Handler for any errors
* @lport: The fc_lport object
* @fp: The frame pointer
@@ -1382,7 +1408,7 @@ static void fc_lport_logo_resp(struct fc_seq *sp, struct fc_frame *fp,
op = fc_frame_payload_op(fp);
if (op == ELS_LS_ACC)
- fc_lport_enter_reset(lport);
+ fc_lport_enter_disabled(lport);
else
fc_lport_error(lport, fp);
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 09/22] libfc: in fc_lport_destroy, flush rports after turning off link
2009-07-30 0:03 [PATCH 00/22] Open-FCoE Features for 2.6.32 Robert Love
` (7 preceding siblings ...)
2009-07-30 0:04 ` [PATCH 08/22] libfc: stop login after fabric logoff Robert Love
@ 2009-07-30 0:04 ` Robert Love
2009-07-30 0:04 ` [PATCH 10/22] libfc: fix WARNING from fc_seq_start_next on closed exchanges Robert Love
` (12 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Robert Love @ 2009-07-30 0:04 UTC (permalink / raw)
To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love
From: Joe Eykholt <jeykholt@cisco.com>
During an fcoe module unload, we saw a problem where fc_rport_work()
finds the lport has been freed. The rdata points to an area
containing 0x6b6b6b6b... the pool poison value from kmem_free().
In fcoe_if_destroy() we call fc_fabric_logoff() then fc_lport_destroy().
fc_fabric_logoff() flushes the remote port work, but we're still receiving
requests, and an RSCN or PLOGI arrives which creates more rports.
Note that although the LLD also checks link_up, it doesn't do it
under the lport mutex, so it can deliver frames to
fc_lport_recv_req() even after link_up is cleared.
So, re-check link_up there.
We need to flush the rports by calling disc_stop_final()
after we clear link_up.
Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---
drivers/scsi/libfc/fc_lport.c | 6 +++++-
1 files changed, 5 insertions(+), 1 deletions(-)
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index 7bb451a..a430335 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -643,6 +643,7 @@ int fc_lport_destroy(struct fc_lport *lport)
mutex_unlock(&lport->lp_mutex);
lport->tt.fcp_abort_io(lport);
+ lport->tt.disc_stop_final(lport);
lport->tt.exch_mgr_reset(lport, 0, 0);
return 0;
}
@@ -844,7 +845,10 @@ static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp,
* RSCN here. These don't require a session.
* Even if we had a session, it might not be ready.
*/
- if (fh->fh_type == FC_TYPE_ELS && fh->fh_r_ctl == FC_RCTL_ELS_REQ) {
+ if (!lport->link_up)
+ fc_frame_free(fp);
+ else if (fh->fh_type == FC_TYPE_ELS &&
+ fh->fh_r_ctl == FC_RCTL_ELS_REQ) {
/*
* Check opcode.
*/
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 10/22] libfc: fix WARNING from fc_seq_start_next on closed exchanges
2009-07-30 0:03 [PATCH 00/22] Open-FCoE Features for 2.6.32 Robert Love
` (8 preceding siblings ...)
2009-07-30 0:04 ` [PATCH 09/22] libfc: in fc_lport_destroy, flush rports after turning off link Robert Love
@ 2009-07-30 0:04 ` Robert Love
2009-07-30 0:04 ` [PATCH 11/22] libfc: rename rport state "NONE" to "DELETE" Robert Love
` (11 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Robert Love @ 2009-07-30 0:04 UTC (permalink / raw)
To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love
From: Joe Eykholt <jeykholt@cisco.com>
We saw periodic messages like:
WARNING: at drivers/scsi/libfc/fc_exch.c:825 fc_seq_start_next+0x30/0x4b
This was due to trying to allocate a sequence in a request handler
when the exchange had been reset.
Delete the WARN_ON.
Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---
drivers/scsi/libfc/fc_exch.c | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index e6d82d7..cab5499 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -822,7 +822,6 @@ struct fc_seq *fc_seq_start_next(struct fc_seq *sp)
struct fc_exch *ep = fc_seq_exch(sp);
spin_lock_bh(&ep->ex_lock);
- WARN_ON((ep->esb_stat & ESB_ST_COMPLETE) != 0);
sp = fc_seq_start_next_locked(sp);
spin_unlock_bh(&ep->ex_lock);
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 11/22] libfc: rename rport state "NONE" to "DELETE".
2009-07-30 0:03 [PATCH 00/22] Open-FCoE Features for 2.6.32 Robert Love
` (9 preceding siblings ...)
2009-07-30 0:04 ` [PATCH 10/22] libfc: fix WARNING from fc_seq_start_next on closed exchanges Robert Love
@ 2009-07-30 0:04 ` Robert Love
2009-07-30 0:04 ` [PATCH 12/22] libfc: fc_rport_logoff should not drop the lock Robert Love
` (10 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Robert Love @ 2009-07-30 0:04 UTC (permalink / raw)
To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love
From: Joe Eykholt <jeykholt@cisco.com>
State RPORT_ST_NONE was intented to be an invalid state (0), never used.
This was a misguided attempt to be sure it was always initialized.
Having an extra state meaning nothing requires switch statements to
have a case covering that state.
State NONE has been used instead to mean the remote port is being deleted.
Changing the name to RPORT_ST_DELETE.
Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---
drivers/scsi/libfc/fc_rport.c | 28 ++++++++++++++--------------
include/scsi/libfc.h | 2 +-
2 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index 7162385..bf7364f 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -77,13 +77,13 @@ static void fc_rport_error_retry(struct fc_rport *, struct fc_frame *);
static void fc_rport_work(struct work_struct *);
static const char *fc_rport_state_names[] = {
- [RPORT_ST_NONE] = "None",
[RPORT_ST_INIT] = "Init",
[RPORT_ST_PLOGI] = "PLOGI",
[RPORT_ST_PRLI] = "PRLI",
[RPORT_ST_RTV] = "RTV",
[RPORT_ST_READY] = "Ready",
[RPORT_ST_LOGO] = "LOGO",
+ [RPORT_ST_DELETE] = "Delete",
};
static void fc_rport_rogue_destroy(struct device *dev)
@@ -326,8 +326,8 @@ int fc_rport_logoff(struct fc_rport *rport)
FC_RPORT_DBG(rport, "Remove port\n");
- if (rdata->rp_state == RPORT_ST_NONE) {
- FC_RPORT_DBG(rport, "Port in NONE state, not removing\n");
+ if (rdata->rp_state == RPORT_ST_DELETE) {
+ FC_RPORT_DBG(rport, "Port in Delete state, not removing\n");
mutex_unlock(&rdata->rp_mutex);
goto out;
}
@@ -335,10 +335,10 @@ int fc_rport_logoff(struct fc_rport *rport)
fc_rport_enter_logo(rport);
/*
- * Change the state to NONE so that we discard
+ * Change the state to Delete so that we discard
* the response.
*/
- fc_rport_state_enter(rport, RPORT_ST_NONE);
+ fc_rport_state_enter(rport, RPORT_ST_DELETE);
mutex_unlock(&rdata->rp_mutex);
@@ -405,7 +405,7 @@ static void fc_rport_timeout(struct work_struct *work)
break;
case RPORT_ST_READY:
case RPORT_ST_INIT:
- case RPORT_ST_NONE:
+ case RPORT_ST_DELETE:
break;
}
@@ -433,14 +433,14 @@ static void fc_rport_error(struct fc_rport *rport, struct fc_frame *fp)
case RPORT_ST_PRLI:
case RPORT_ST_LOGO:
rdata->event = RPORT_EV_FAILED;
- fc_rport_state_enter(rport, RPORT_ST_NONE);
+ fc_rport_state_enter(rport, RPORT_ST_DELETE);
queue_work(rport_event_queue,
&rdata->event_work);
break;
case RPORT_ST_RTV:
fc_rport_enter_ready(rport);
break;
- case RPORT_ST_NONE:
+ case RPORT_ST_DELETE:
case RPORT_ST_READY:
case RPORT_ST_INIT:
break;
@@ -652,7 +652,7 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp,
} else {
FC_RPORT_DBG(rport, "Bad ELS response for PRLI command\n");
rdata->event = RPORT_EV_FAILED;
- fc_rport_state_enter(rport, RPORT_ST_NONE);
+ fc_rport_state_enter(rport, RPORT_ST_DELETE);
queue_work(rport_event_queue, &rdata->event_work);
}
@@ -703,7 +703,7 @@ static void fc_rport_logo_resp(struct fc_seq *sp, struct fc_frame *fp,
} else {
FC_RPORT_DBG(rport, "Bad ELS response for LOGO command\n");
rdata->event = RPORT_EV_LOGO;
- fc_rport_state_enter(rport, RPORT_ST_NONE);
+ fc_rport_state_enter(rport, RPORT_ST_DELETE);
queue_work(rport_event_queue, &rdata->event_work);
}
@@ -1012,7 +1012,7 @@ static void fc_rport_recv_plogi_req(struct fc_rport *rport,
"- ignored for now\n", rdata->rp_state);
/* XXX TBD - should reset */
break;
- case RPORT_ST_NONE:
+ case RPORT_ST_DELETE:
default:
FC_RPORT_DBG(rport, "Received PLOGI in unexpected "
"state %d\n", rdata->rp_state);
@@ -1238,7 +1238,7 @@ static void fc_rport_recv_prlo_req(struct fc_rport *rport, struct fc_seq *sp,
FC_RPORT_DBG(rport, "Received PRLO request while in state %s\n",
fc_rport_state(rport));
- if (rdata->rp_state == RPORT_ST_NONE) {
+ if (rdata->rp_state == RPORT_ST_DELETE) {
fc_frame_free(fp);
return;
}
@@ -1271,13 +1271,13 @@ static void fc_rport_recv_logo_req(struct fc_rport *rport, struct fc_seq *sp,
FC_RPORT_DBG(rport, "Received LOGO request while in state %s\n",
fc_rport_state(rport));
- if (rdata->rp_state == RPORT_ST_NONE) {
+ if (rdata->rp_state == RPORT_ST_DELETE) {
fc_frame_free(fp);
return;
}
rdata->event = RPORT_EV_LOGO;
- fc_rport_state_enter(rport, RPORT_ST_NONE);
+ fc_rport_state_enter(rport, RPORT_ST_DELETE);
queue_work(rport_event_queue, &rdata->event_work);
lport->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL);
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index b5c9b28..04db7a9 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -147,13 +147,13 @@ enum fc_disc_event {
};
enum fc_rport_state {
- RPORT_ST_NONE = 0,
RPORT_ST_INIT, /* initialized */
RPORT_ST_PLOGI, /* waiting for PLOGI completion */
RPORT_ST_PRLI, /* waiting for PRLI completion */
RPORT_ST_RTV, /* waiting for RTV completion */
RPORT_ST_READY, /* ready for use */
RPORT_ST_LOGO, /* port logout sent */
+ RPORT_ST_DELETE, /* port being deleted */
};
enum fc_rport_trans_state {
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 12/22] libfc: fc_rport_logoff should not drop the lock
2009-07-30 0:03 [PATCH 00/22] Open-FCoE Features for 2.6.32 Robert Love
` (10 preceding siblings ...)
2009-07-30 0:04 ` [PATCH 11/22] libfc: rename rport state "NONE" to "DELETE" Robert Love
@ 2009-07-30 0:04 ` Robert Love
2009-07-30 0:04 ` [PATCH 13/22] libfc: fix: cancel rport retry timer Robert Love
` (9 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Robert Love @ 2009-07-30 0:04 UTC (permalink / raw)
To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love
From: Joe Eykholt <jeykholt@cisco.com>
fc_rport_logoff drops the rport lock in order to cancel work
that may be pending. This is undesirable as the state can
completely change, and the caller may not expect that the
lock could've been dropped.
If there is work pending, it will acquire the rdata mutex and
so we're protected and can change the event from READY to DELETE.
Queue the work only if there is no event already pending.
There were a couple other cases where the state was set to
DELETE and work queued, even though the state may have already
been DELETE. Fix these using a common function fc_rport_enter_delete().
Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---
drivers/scsi/libfc/fc_rport.c | 60 ++++++++++++++++++++++++++---------------
1 files changed, 38 insertions(+), 22 deletions(-)
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index bf7364f..a86df0b 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -230,6 +230,7 @@ static void fc_rport_work(struct work_struct *work)
ids.port_name = rport->port_name;
ids.node_name = rport->node_name;
+ rdata->event = RPORT_EV_NONE;
mutex_unlock(&rdata->rp_mutex);
new_rport = fc_remote_port_add(lport->host, 0, &ids);
@@ -311,6 +312,37 @@ int fc_rport_login(struct fc_rport *rport)
}
/**
+ * fc_rport_enter_delete() - schedule a remote port to be deleted.
+ * @rport: Fibre Channel remote port
+ * @event: event to report as the reason for deletion
+ *
+ * Locking Note: Called with the rport lock held.
+ *
+ * Allow state change into DELETE only once.
+ *
+ * Call queue_work only if there's no event already pending.
+ * Set the new event so that the old pending event will not occur.
+ * Since we have the mutex, even if fc_rport_work() is already started,
+ * it'll see the new event.
+ */
+static void fc_rport_enter_delete(struct fc_rport *rport,
+ enum fc_rport_event event)
+{
+ struct fc_rport_libfc_priv *rdata = rport->dd_data;
+
+ if (rdata->rp_state == RPORT_ST_DELETE)
+ return;
+
+ FC_RPORT_DBG(rport, "Delete port\n");
+
+ fc_rport_state_enter(rport, RPORT_ST_DELETE);
+
+ if (rdata->event == RPORT_EV_NONE)
+ queue_work(rport_event_queue, &rdata->event_work);
+ rdata->event = event;
+}
+
+/**
* fc_rport_logoff() - Logoff and remove an rport
* @rport: Fibre Channel remote port to be removed
*
@@ -338,17 +370,7 @@ int fc_rport_logoff(struct fc_rport *rport)
* Change the state to Delete so that we discard
* the response.
*/
- fc_rport_state_enter(rport, RPORT_ST_DELETE);
-
- mutex_unlock(&rdata->rp_mutex);
-
- cancel_delayed_work_sync(&rdata->retry_work);
-
- mutex_lock(&rdata->rp_mutex);
-
- rdata->event = RPORT_EV_STOP;
- queue_work(rport_event_queue, &rdata->event_work);
-
+ fc_rport_enter_delete(rport, RPORT_EV_STOP);
mutex_unlock(&rdata->rp_mutex);
out:
@@ -370,8 +392,9 @@ static void fc_rport_enter_ready(struct fc_rport *rport)
FC_RPORT_DBG(rport, "Port is Ready\n");
+ if (rdata->event == RPORT_EV_NONE)
+ queue_work(rport_event_queue, &rdata->event_work);
rdata->event = RPORT_EV_CREATED;
- queue_work(rport_event_queue, &rdata->event_work);
}
/**
@@ -432,10 +455,7 @@ static void fc_rport_error(struct fc_rport *rport, struct fc_frame *fp)
case RPORT_ST_PLOGI:
case RPORT_ST_PRLI:
case RPORT_ST_LOGO:
- rdata->event = RPORT_EV_FAILED;
- fc_rport_state_enter(rport, RPORT_ST_DELETE);
- queue_work(rport_event_queue,
- &rdata->event_work);
+ fc_rport_enter_delete(rport, RPORT_EV_FAILED);
break;
case RPORT_ST_RTV:
fc_rport_enter_ready(rport);
@@ -651,9 +671,7 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp,
} else {
FC_RPORT_DBG(rport, "Bad ELS response for PRLI command\n");
- rdata->event = RPORT_EV_FAILED;
- fc_rport_state_enter(rport, RPORT_ST_DELETE);
- queue_work(rport_event_queue, &rdata->event_work);
+ fc_rport_enter_delete(rport, RPORT_EV_FAILED);
}
out:
@@ -702,9 +720,7 @@ static void fc_rport_logo_resp(struct fc_seq *sp, struct fc_frame *fp,
fc_rport_enter_rtv(rport);
} else {
FC_RPORT_DBG(rport, "Bad ELS response for LOGO command\n");
- rdata->event = RPORT_EV_LOGO;
- fc_rport_state_enter(rport, RPORT_ST_DELETE);
- queue_work(rport_event_queue, &rdata->event_work);
+ fc_rport_enter_delete(rport, RPORT_EV_LOGO);
}
out:
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 13/22] libfc: fix: cancel rport retry timer
2009-07-30 0:03 [PATCH 00/22] Open-FCoE Features for 2.6.32 Robert Love
` (11 preceding siblings ...)
2009-07-30 0:04 ` [PATCH 12/22] libfc: fc_rport_logoff should not drop the lock Robert Love
@ 2009-07-30 0:04 ` Robert Love
2009-07-30 0:05 ` [PATCH 14/22] fcoe, libfc: adds exchange manager(EM) anchor list per lport and related APIs Robert Love
` (8 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Robert Love @ 2009-07-30 0:04 UTC (permalink / raw)
To: James.Bottomley, linux-scsi; +Cc: Joe Eykholt, Robert Love
From: Joe Eykholt <jeykholt@cisco.com>
The timer for rport retries wasn't getting canceled, and
would occasionally go off after the module was unloaded.
Add logic to cancel the timer in fc_rport_work().
Since we cancel the timer before deleting the rdata,
it is no longer necessary to do a get_device() for the pending timer.
Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---
drivers/scsi/libfc/fc_rport.c | 3 +--
1 files changed, 1 insertions(+), 2 deletions(-)
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index a86df0b..90cc90d 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -276,6 +276,7 @@ static void fc_rport_work(struct work_struct *work)
mutex_unlock(&rdata->rp_mutex);
if (rport_ops->event_callback)
rport_ops->event_callback(lport, rport, event);
+ cancel_delayed_work_sync(&rdata->retry_work);
if (trans_state == FC_PORTSTATE_ROGUE)
put_device(&rport->dev);
else {
@@ -433,7 +434,6 @@ static void fc_rport_timeout(struct work_struct *work)
}
mutex_unlock(&rdata->rp_mutex);
- put_device(&rport->dev);
}
/**
@@ -494,7 +494,6 @@ static void fc_rport_error_retry(struct fc_rport *rport, struct fc_frame *fp)
/* no additional delay on exchange timeouts */
if (PTR_ERR(fp) == -FC_EX_TIMEOUT)
delay = 0;
- get_device(&rport->dev);
schedule_delayed_work(&rdata->retry_work, delay);
return;
}
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 14/22] fcoe, libfc: adds exchange manager(EM) anchor list per lport and related APIs
2009-07-30 0:03 [PATCH 00/22] Open-FCoE Features for 2.6.32 Robert Love
` (12 preceding siblings ...)
2009-07-30 0:04 ` [PATCH 13/22] libfc: fix: cancel rport retry timer Robert Love
@ 2009-07-30 0:05 ` Robert Love
2009-07-30 0:05 ` [PATCH 15/22] libfc: Remove the FC_EM_DBG macro Robert Love
` (7 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Robert Love @ 2009-07-30 0:05 UTC (permalink / raw)
To: James.Bottomley, linux-scsi; +Cc: Vasu Dev, Robert Love
From: Vasu Dev <vasu.dev@intel.com>
Adds EM list using a anchor struct fc_exch_mgr_anchor, anchor is used
to allow same EM instance sharing across more than one lport on a eth
device, this implementation is per discussed design posted at
http://www.open-fcoe.org/pipermail/devel/2009-June/002566.html.
The shared EM is required for multiple lports on eth device when
using multiple VLANs or NPIV.
Adds fc_exch_mgr_add API to add a EM to the lport and fc_exch_mgr_del
API to delete previously added EM.
Also adds function fc_exch_mgr_destroy() to destroy allocated EM.
The kref is added to the EM to keep track of EM usage count, the EM is
destroyed when no longer in use upon kref reaching to zero.
The caller can specify match function to fc_exch_mgr_add, this
will be used in determining exchange allocation from its EM or not.
Moved calling of fcoe_em_config below fcoe_libfc_config calling,
so that list head lp->ema_list is initialized before configuring
EM.
Signed-off-by: Vasu Dev <vasu.dev@intel.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---
drivers/scsi/fcoe/fcoe.c | 14 ++++++------
drivers/scsi/libfc/fc_exch.c | 48 +++++++++++++++++++++++++++++++++++++++++
drivers/scsi/libfc/fc_lport.c | 1 +
include/scsi/libfc.h | 24 +++++++++++++++++++++
4 files changed, 80 insertions(+), 7 deletions(-)
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 14a4017..719a99d 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -603,18 +603,18 @@ static int fcoe_if_create(struct net_device *netdev)
goto out_netdev_cleanup;
}
- /* lport exch manager allocation */
- rc = fcoe_em_config(lp);
+ /* Initialize the library */
+ rc = fcoe_libfc_config(lp, &fcoe_libfc_fcn_templ);
if (rc) {
- FCOE_NETDEV_DBG(netdev, "Could not configure the EM for the "
+ FCOE_NETDEV_DBG(netdev, "Could not configure libfc for the "
"interface\n");
- goto out_netdev_cleanup;
+ goto out_lp_destroy;
}
- /* Initialize the library */
- rc = fcoe_libfc_config(lp, &fcoe_libfc_fcn_templ);
+ /* lport exch manager allocation */
+ rc = fcoe_em_config(lp);
if (rc) {
- FCOE_NETDEV_DBG(netdev, "Could not configure libfc for the "
+ FCOE_NETDEV_DBG(netdev, "Could not configure the EM for the "
"interface\n");
goto out_lp_destroy;
}
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index cab5499..f1fa2b1 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -55,6 +55,7 @@ static struct kmem_cache *fc_em_cachep; /* cache for exchanges */
*/
struct fc_exch_mgr {
enum fc_class class; /* default class for sequences */
+ struct kref kref; /* exchange mgr reference count */
spinlock_t em_lock; /* exchange manager lock,
must be taken before ex_lock */
u16 last_xid; /* last allocated exchange ID */
@@ -84,6 +85,12 @@ struct fc_exch_mgr {
};
#define fc_seq_exch(sp) container_of(sp, struct fc_exch, seq)
+struct fc_exch_mgr_anchor {
+ struct list_head ema_list;
+ struct fc_exch_mgr *mp;
+ bool (*match)(struct fc_frame *);
+};
+
static void fc_exch_rrq(struct fc_exch *);
static void fc_seq_ls_acc(struct fc_seq *);
static void fc_seq_ls_rjt(struct fc_seq *, enum fc_els_rjt_reason,
@@ -1729,6 +1736,47 @@ reject:
fc_frame_free(fp);
}
+struct fc_exch_mgr_anchor *fc_exch_mgr_add(struct fc_lport *lport,
+ struct fc_exch_mgr *mp,
+ bool (*match)(struct fc_frame *))
+{
+ struct fc_exch_mgr_anchor *ema;
+
+ ema = kmalloc(sizeof(*ema), GFP_ATOMIC);
+ if (!ema)
+ return ema;
+
+ ema->mp = mp;
+ ema->match = match;
+ /* add EM anchor to EM anchors list */
+ list_add_tail(&ema->ema_list, &lport->ema_list);
+ kref_get(&mp->kref);
+ return ema;
+}
+EXPORT_SYMBOL(fc_exch_mgr_add);
+
+static void fc_exch_mgr_destroy(struct kref *kref)
+{
+ struct fc_exch_mgr *mp = container_of(kref, struct fc_exch_mgr, kref);
+
+ /*
+ * The total exch count must be zero
+ * before freeing exchange manager.
+ */
+ WARN_ON(mp->total_exches != 0);
+ mempool_destroy(mp->ep_pool);
+ kfree(mp);
+}
+
+void fc_exch_mgr_del(struct fc_exch_mgr_anchor *ema)
+{
+ /* remove EM anchor from EM anchors list */
+ list_del(&ema->ema_list);
+ kref_put(&ema->mp->kref, fc_exch_mgr_destroy);
+ kfree(ema);
+}
+EXPORT_SYMBOL(fc_exch_mgr_del);
+
struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lp,
enum fc_class class,
u16 min_xid, u16 max_xid)
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index a430335..ca8ea26 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -1618,6 +1618,7 @@ int fc_lport_init(struct fc_lport *lport)
if (lport->link_supported_speeds & FC_PORTSPEED_10GBIT)
fc_host_supported_speeds(lport->host) |= FC_PORTSPEED_10GBIT;
+ INIT_LIST_HEAD(&lport->ema_list);
return 0;
}
EXPORT_SYMBOL(fc_lport_init);
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index 04db7a9..b381b1c 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -348,6 +348,7 @@ static inline bool fc_fcp_is_read(const struct fc_fcp_pkt *fsp)
*/
struct fc_exch_mgr;
+struct fc_exch_mgr_anchor;
/*
* Sequence.
@@ -709,6 +710,7 @@ struct fc_lport {
/* Associations */
struct Scsi_Host *host;
struct fc_exch_mgr *emp;
+ struct list_head ema_list;
struct fc_rport *dns_rp;
struct fc_rport *ptp_rp;
void *scsi_priv;
@@ -964,6 +966,28 @@ int fc_elsct_init(struct fc_lport *lp);
int fc_exch_init(struct fc_lport *lp);
/*
+ * Adds Exchange Manager (EM) mp to lport.
+ *
+ * Adds specified mp to lport using struct fc_exch_mgr_anchor,
+ * the struct fc_exch_mgr_anchor allows same EM sharing by
+ * more than one lport with their specified match function,
+ * the match function is used in allocating exchange from
+ * added mp.
+ */
+struct fc_exch_mgr_anchor *fc_exch_mgr_add(struct fc_lport *lport,
+ struct fc_exch_mgr *mp,
+ bool (*match)(struct fc_frame *));
+
+/*
+ * Deletes Exchange Manager (EM) from lport by removing
+ * its anchor ema from lport.
+ *
+ * If removed anchor ema was the last user of its associated EM
+ * then also destroys associated EM.
+ */
+void fc_exch_mgr_del(struct fc_exch_mgr_anchor *ema);
+
+/*
* Allocates an Exchange Manager (EM).
*
* The EM manages exchanges for their allocation and
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 15/22] libfc: Remove the FC_EM_DBG macro
2009-07-30 0:03 [PATCH 00/22] Open-FCoE Features for 2.6.32 Robert Love
` (13 preceding siblings ...)
2009-07-30 0:05 ` [PATCH 14/22] fcoe, libfc: adds exchange manager(EM) anchor list per lport and related APIs Robert Love
@ 2009-07-30 0:05 ` Robert Love
2009-07-30 0:05 ` [PATCH 16/22] fcoe, fnic, libfc: modifies current code paths to use EM anchor list Robert Love
` (6 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Robert Love @ 2009-07-30 0:05 UTC (permalink / raw)
To: James.Bottomley, linux-scsi; +Cc: Robert Love
Currently there is a 1:1 relationship between the lport
and exchange manager. This macro takes an EM as an argument
and determines the lport from it. However, later patches
will use an EM list per lport, so we will no longer have
this 1:1 relationship- this macro must change.
The FC_EM_DBG macro is rarely used. There are four callers,
two can use FC_LPORT_DBG instead and two can be removed
since they're not necessary. This patch makes those changes
and removes the macro.
Signed-off-by: Robert Love <robert.w.love@intel.com>
---
drivers/scsi/libfc/fc_exch.c | 13 ++++++-------
include/scsi/libfc.h | 6 ------
2 files changed, 6 insertions(+), 13 deletions(-)
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index f1fa2b1..3ad7f88 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -1129,7 +1129,7 @@ static void fc_exch_recv_req(struct fc_lport *lp, struct fc_exch_mgr *mp,
lp->tt.lport_recv(lp, sp, fp);
fc_exch_release(ep); /* release from lookup */
} else {
- FC_EM_DBG(mp, "exch/seq lookup failed: reject %x\n", reject);
+ FC_LPORT_DBG(lp, "exch/seq lookup failed: reject %x\n", reject);
fc_frame_free(fp);
}
}
@@ -1235,13 +1235,12 @@ static void fc_exch_recv_resp(struct fc_exch_mgr *mp, struct fc_frame *fp)
struct fc_seq *sp;
sp = fc_seq_lookup_orig(mp, fp); /* doesn't hold sequence */
- if (!sp) {
+
+ if (!sp)
atomic_inc(&mp->stats.xid_not_found);
- FC_EM_DBG(mp, "seq lookup failed\n");
- } else {
+ else
atomic_inc(&mp->stats.non_bls_resp);
- FC_EM_DBG(mp, "non-BLS response to sequence");
- }
+
fc_frame_free(fp);
}
@@ -1950,7 +1949,7 @@ void fc_exch_recv(struct fc_lport *lp, struct fc_exch_mgr *mp,
fc_exch_recv_req(lp, mp, fp);
break;
default:
- FC_EM_DBG(mp, "dropping invalid frame (eof %x)", fr_eof(fp));
+ FC_LPORT_DBG(lp, "dropping invalid frame (eof %x)", fr_eof(fp));
fc_frame_free(fp);
break;
}
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index b381b1c..f1bde91 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -88,12 +88,6 @@ do { \
(pkt)->lp->host->host_no, \
pkt->rport->port_id, ##args))
-#define FC_EM_DBG(em, fmt, args...) \
- FC_CHECK_LOGGING(FC_EM_LOGGING, \
- printk(KERN_INFO "host%u: em: " fmt, \
- (em)->lp->host->host_no, \
- ##args))
-
#define FC_EXCH_DBG(exch, fmt, args...) \
FC_CHECK_LOGGING(FC_EXCH_LOGGING, \
printk(KERN_INFO "host%u: xid %4x: " fmt, \
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 16/22] fcoe, fnic, libfc: modifies current code paths to use EM anchor list
2009-07-30 0:03 [PATCH 00/22] Open-FCoE Features for 2.6.32 Robert Love
` (14 preceding siblings ...)
2009-07-30 0:05 ` [PATCH 15/22] libfc: Remove the FC_EM_DBG macro Robert Love
@ 2009-07-30 0:05 ` Robert Love
2009-07-30 0:05 ` [PATCH 17/22] fcoe: modifies fcoe_hostlist_lock uses as prep work to add shared offload EM Robert Love
` (5 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Robert Love @ 2009-07-30 0:05 UTC (permalink / raw)
To: James.Bottomley, linux-scsi; +Cc: Vasu Dev, Robert Love
From: Vasu Dev <vasu.dev@intel.com>
Modifies current code to use EM anchor list in EM allocation, EM free,
EM reset, exch allocation and exch lookup code paths.
1. Modifies fc_exch_mgr_alloc to accept EM match function and then
have allocated EM added to the lport using fc_exch_mgr_add API
while also updating EM kref for newly added EM.
2. Updates fc_exch_mgr_free API to accept only lport pointer instead
EM and then have this API free all EMs of the lport from EM anchor
list.
3. Removes single lport pointer link from the EM, which was used in
associating lport pointer in newly allocated exchange. Instead have
lport pointer passed along new exchange allocation call path and
then store passed lport pointer in newly allocated exchange, this
will allow a single EM instance to be used across more than one
lport and used in EM reset to reset only lport specific exchanges.
4. Modifies fc_exch_mgr_reset to reset all EMs from the EM anchor list
of the lport, adds additional exch lport pointer (ep->lp) check for
shared EM case to reset exchange specific to a lport requested reset.
5. Updates exch allocation API fc_exch_alloc to use EM anchor list and
its anchor match func pointer. The fc_exch_alloc will walk the list
of EMs until it finds a match, a match will be either null match
func pointer or call to match function returning true value.
6. Updates fc_exch_recv to accept incoming frame on local port using
only lport pointer and frame pointer without specifying EM instance
of incoming frame. Instead modified fc_exch_recv to locate EM for the
incoming frame by matching xid of incoming frame against a EM xid range.
This change was required to use EM list in libfc Rx path and after this
change the lport fc_exch_mgr pointer emp is not needed anymore, so
removed emp pointer.
7. Updates fnic for removed lport emp pointer and above modified libfc APIs
fc_exch_recv, fc_exch_mgr_alloc and fc_exch_mgr_free.
8. Removes exch_get and exch_put from libfc_function_template as these
are no longer needed with EM anchor list and its match function use.
Also removes its default function fc_exch_get.
A defect this patch introduced regarding the libfc initialization order in
the fnic driver was fixed by Joe Eykholt <jeykholt@cisco.com>.
Signed-off-by: Vasu Dev <vasu.dev@intel.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---
drivers/scsi/fcoe/fcoe.c | 16 +--
drivers/scsi/fcoe/libfcoe.c | 2
drivers/scsi/fnic/fnic_fcs.c | 2
drivers/scsi/fnic/fnic_main.c | 20 ++--
drivers/scsi/libfc/fc_exch.c | 191 +++++++++++++++++++++++++----------------
include/scsi/libfc.h | 48 ++--------
6 files changed, 142 insertions(+), 137 deletions(-)
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 719a99d..ebf2e20 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -423,11 +423,8 @@ static int fcoe_shost_config(struct fc_lport *lp, struct Scsi_Host *shost,
*/
static inline int fcoe_em_config(struct fc_lport *lp)
{
- BUG_ON(lp->emp);
-
- lp->emp = fc_exch_mgr_alloc(lp, FC_CLASS_3,
- FCOE_MIN_XID, FCOE_MAX_XID);
- if (!lp->emp)
+ if (!fc_exch_mgr_alloc(lp, FC_CLASS_3, FCOE_MIN_XID,
+ FCOE_MAX_XID, NULL))
return -ENOMEM;
return 0;
@@ -478,8 +475,7 @@ static int fcoe_if_destroy(struct net_device *netdev)
scsi_remove_host(lp->host);
/* There are no more rports or I/O, free the EM */
- if (lp->emp)
- fc_exch_mgr_free(lp->emp);
+ fc_exch_mgr_free(lp);
/* Free existing skbs */
fcoe_clean_pending_queue(lp);
@@ -634,7 +630,7 @@ static int fcoe_if_create(struct net_device *netdev)
return rc;
out_lp_destroy:
- fc_exch_mgr_free(lp->emp); /* Free the EM */
+ fc_exch_mgr_free(lp);
out_netdev_cleanup:
fcoe_netdev_cleanup(fc);
out_host_put:
@@ -1277,7 +1273,7 @@ int fcoe_percpu_receive_thread(void *arg)
fh = fc_frame_header_get(fp);
if (fh->fh_r_ctl == FC_RCTL_DD_SOL_DATA &&
fh->fh_type == FC_TYPE_FCP) {
- fc_exch_recv(lp, lp->emp, fp);
+ fc_exch_recv(lp, fp);
continue;
}
if (fr_flags(fp) & FCPHF_CRC_UNCHECKED) {
@@ -1298,7 +1294,7 @@ int fcoe_percpu_receive_thread(void *arg)
fc_frame_free(fp);
continue;
}
- fc_exch_recv(lp, lp->emp, fp);
+ fc_exch_recv(lp, fp);
}
return 0;
}
diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c
index 78caa6b..4db719d 100644
--- a/drivers/scsi/fcoe/libfcoe.c
+++ b/drivers/scsi/fcoe/libfcoe.c
@@ -885,7 +885,7 @@ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb)
stats->RxFrames++;
stats->RxWords += skb->len / FIP_BPW;
- fc_exch_recv(lp, lp->emp, fp);
+ fc_exch_recv(lp, fp);
return;
len_err:
diff --git a/drivers/scsi/fnic/fnic_fcs.c b/drivers/scsi/fnic/fnic_fcs.c
index 07e6eed..50db3e3 100644
--- a/drivers/scsi/fnic/fnic_fcs.c
+++ b/drivers/scsi/fnic/fnic_fcs.c
@@ -115,7 +115,7 @@ void fnic_handle_frame(struct work_struct *work)
}
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
- fc_exch_recv(lp, lp->emp, fp);
+ fc_exch_recv(lp, fp);
}
}
diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c
index 2c266c0..71c7bbe 100644
--- a/drivers/scsi/fnic/fnic_main.c
+++ b/drivers/scsi/fnic/fnic_main.c
@@ -671,14 +671,6 @@ static int __devinit fnic_probe(struct pci_dev *pdev,
lp->link_up = 0;
lp->tt = fnic_transport_template;
- lp->emp = fc_exch_mgr_alloc(lp, FC_CLASS_3,
- FCPIO_HOST_EXCH_RANGE_START,
- FCPIO_HOST_EXCH_RANGE_END);
- if (!lp->emp) {
- err = -ENOMEM;
- goto err_out_remove_scsi_host;
- }
-
lp->max_retry_count = fnic->config.flogi_retries;
lp->max_rport_retry_count = fnic->config.plogi_retries;
lp->service_params = (FCP_SPPF_INIT_FCN | FCP_SPPF_RD_XRDY_DIS |
@@ -693,12 +685,18 @@ static int __devinit fnic_probe(struct pci_dev *pdev,
fc_set_wwnn(lp, fnic->config.node_wwn);
fc_set_wwpn(lp, fnic->config.port_wwn);
- fc_exch_init(lp);
fc_lport_init(lp);
+ fc_exch_init(lp);
fc_elsct_init(lp);
fc_rport_init(lp);
fc_disc_init(lp);
+ if (!fc_exch_mgr_alloc(lp, FC_CLASS_3, FCPIO_HOST_EXCH_RANGE_START,
+ FCPIO_HOST_EXCH_RANGE_END, NULL)) {
+ err = -ENOMEM;
+ goto err_out_remove_scsi_host;
+ }
+
fc_lport_config(lp);
if (fc_set_mfs(lp, fnic->config.maxdatafieldsize +
@@ -738,7 +736,7 @@ static int __devinit fnic_probe(struct pci_dev *pdev,
return 0;
err_out_free_exch_mgr:
- fc_exch_mgr_free(lp->emp);
+ fc_exch_mgr_free(lp);
err_out_remove_scsi_host:
fc_remove_host(fnic->lport->host);
scsi_remove_host(fnic->lport->host);
@@ -827,7 +825,7 @@ static void __devexit fnic_remove(struct pci_dev *pdev)
fc_remove_host(fnic->lport->host);
scsi_remove_host(fnic->lport->host);
- fc_exch_mgr_free(fnic->lport->emp);
+ fc_exch_mgr_free(fnic->lport);
vnic_dev_notify_unset(fnic->vdev);
fnic_free_vnic_resources(fnic);
fnic_free_intr(fnic);
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index 3ad7f88..324589a 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -65,7 +65,6 @@ struct fc_exch_mgr {
u16 last_read; /* last xid allocated for read */
u32 total_exches; /* total allocated exchanges */
struct list_head ex_list; /* allocated exchanges list */
- struct fc_lport *lp; /* fc device instance */
mempool_t *ep_pool; /* reserve ep's */
/*
@@ -275,8 +274,6 @@ static void fc_exch_release(struct fc_exch *ep)
mp = ep->em;
if (ep->destructor)
ep->destructor(&ep->seq, ep->arg);
- if (ep->lp->tt.exch_put)
- ep->lp->tt.exch_put(ep->lp, mp, ep->xid);
WARN_ON(!(ep->esb_stat & ESB_ST_COMPLETE));
mempool_free(ep, mp->ep_pool);
}
@@ -513,17 +510,20 @@ static u16 fc_em_alloc_xid(struct fc_exch_mgr *mp, const struct fc_frame *fp)
return xid;
}
-/*
- * fc_exch_alloc - allocate an exchange.
- * @mp : ptr to the exchange manager
- * @xid: input xid
+/**
+ * fc_exch_em_alloc() - allocate an exchange from a specified EM.
+ * @lport: ptr to the local port
+ * @mp: ptr to the exchange manager
+ * @fp: ptr to the FC frame
+ * @xid: input xid
*
* if xid is supplied zero then assign next free exchange ID
* from exchange manager, otherwise use supplied xid.
* Returns with exch lock held.
*/
-struct fc_exch *fc_exch_alloc(struct fc_exch_mgr *mp,
- struct fc_frame *fp, u16 xid)
+static struct fc_exch *fc_exch_em_alloc(struct fc_lport *lport,
+ struct fc_exch_mgr *mp,
+ struct fc_frame *fp, u16 xid)
{
struct fc_exch *ep;
@@ -566,7 +566,7 @@ struct fc_exch *fc_exch_alloc(struct fc_exch_mgr *mp,
*/
ep->oxid = ep->xid = xid;
ep->em = mp;
- ep->lp = mp->lp;
+ ep->lp = lport;
ep->f_ctl = FC_FC_FIRST_SEQ; /* next seq is first seq */
ep->rxid = FC_XID_UNKNOWN;
ep->class = mp->class;
@@ -579,6 +579,31 @@ err:
mempool_free(ep, mp->ep_pool);
return NULL;
}
+
+/**
+ * fc_exch_alloc() - allocate an exchange.
+ * @lport: ptr to the local port
+ * @fp: ptr to the FC frame
+ *
+ * This function walks the list of the exchange manager(EM)
+ * anchors to select a EM for new exchange allocation. The
+ * EM is selected having either a NULL match function pointer
+ * or call to match function returning true.
+ */
+struct fc_exch *fc_exch_alloc(struct fc_lport *lport, struct fc_frame *fp)
+{
+ struct fc_exch_mgr_anchor *ema;
+ struct fc_exch *ep;
+
+ list_for_each_entry(ema, &lport->ema_list, ema_list) {
+ if (!ema->match || ema->match(fp)) {
+ ep = fc_exch_em_alloc(lport, ema->mp, fp, 0);
+ if (ep)
+ return ep;
+ }
+ }
+ return NULL;
+}
EXPORT_SYMBOL(fc_exch_alloc);
/*
@@ -617,12 +642,14 @@ EXPORT_SYMBOL(fc_exch_done);
* Allocate a new exchange as responder.
* Sets the responder ID in the frame header.
*/
-static struct fc_exch *fc_exch_resp(struct fc_exch_mgr *mp, struct fc_frame *fp)
+static struct fc_exch *fc_exch_resp(struct fc_lport *lport,
+ struct fc_exch_mgr *mp,
+ struct fc_frame *fp)
{
struct fc_exch *ep;
struct fc_frame_header *fh;
- ep = mp->lp->tt.exch_get(mp->lp, fp);
+ ep = fc_exch_alloc(lport, fp);
if (ep) {
ep->class = fc_frame_class(fp);
@@ -648,7 +675,7 @@ static struct fc_exch *fc_exch_resp(struct fc_exch_mgr *mp, struct fc_frame *fp)
ep->esb_stat &= ~ESB_ST_SEQ_INIT;
fc_exch_hold(ep); /* hold for caller */
- spin_unlock_bh(&ep->ex_lock); /* lock from exch_get */
+ spin_unlock_bh(&ep->ex_lock); /* lock from fc_exch_alloc */
}
return ep;
}
@@ -658,7 +685,8 @@ static struct fc_exch *fc_exch_resp(struct fc_exch_mgr *mp, struct fc_frame *fp)
* If fc_pf_rjt_reason is FC_RJT_NONE then this function will have a hold
* on the ep that should be released by the caller.
*/
-static enum fc_pf_rjt_reason fc_seq_lookup_recip(struct fc_exch_mgr *mp,
+static enum fc_pf_rjt_reason fc_seq_lookup_recip(struct fc_lport *lport,
+ struct fc_exch_mgr *mp,
struct fc_frame *fp)
{
struct fc_frame_header *fh = fc_frame_header_get(fp);
@@ -712,7 +740,7 @@ static enum fc_pf_rjt_reason fc_seq_lookup_recip(struct fc_exch_mgr *mp,
reject = FC_RJT_RX_ID;
goto rel;
}
- ep = fc_exch_resp(mp, fp);
+ ep = fc_exch_resp(lport, mp, fp);
if (!ep) {
reject = FC_RJT_EXCH_EST; /* XXX */
goto out;
@@ -1103,7 +1131,7 @@ static void fc_exch_recv_req(struct fc_lport *lp, struct fc_exch_mgr *mp,
enum fc_pf_rjt_reason reject;
fr_seq(fp) = NULL;
- reject = fc_seq_lookup_recip(mp, fp);
+ reject = fc_seq_lookup_recip(lp, mp, fp);
if (reject == FC_RJT_NONE) {
sp = fr_seq(fp); /* sequence will be held */
ep = fc_seq_exch(sp);
@@ -1467,29 +1495,34 @@ void fc_exch_mgr_reset(struct fc_lport *lp, u32 sid, u32 did)
{
struct fc_exch *ep;
struct fc_exch *next;
- struct fc_exch_mgr *mp = lp->emp;
+ struct fc_exch_mgr *mp;
+ struct fc_exch_mgr_anchor *ema;
- spin_lock_bh(&mp->em_lock);
+ list_for_each_entry(ema, &lp->ema_list, ema_list) {
+ mp = ema->mp;
+ spin_lock_bh(&mp->em_lock);
restart:
- list_for_each_entry_safe(ep, next, &mp->ex_list, ex_list) {
- if ((sid == 0 || sid == ep->sid) &&
- (did == 0 || did == ep->did)) {
- fc_exch_hold(ep);
- spin_unlock_bh(&mp->em_lock);
-
- fc_exch_reset(ep);
-
- fc_exch_release(ep);
- spin_lock_bh(&mp->em_lock);
-
- /*
- * must restart loop incase while lock was down
- * multiple eps were released.
- */
- goto restart;
+ list_for_each_entry_safe(ep, next, &mp->ex_list, ex_list) {
+ if ((lp == ep->lp) &&
+ (sid == 0 || sid == ep->sid) &&
+ (did == 0 || did == ep->did)) {
+ fc_exch_hold(ep);
+ spin_unlock_bh(&mp->em_lock);
+
+ fc_exch_reset(ep);
+
+ fc_exch_release(ep);
+ spin_lock_bh(&mp->em_lock);
+
+ /*
+ * must restart loop incase while lock
+ * was down multiple eps were released.
+ */
+ goto restart;
+ }
}
+ spin_unlock_bh(&mp->em_lock);
}
- spin_unlock_bh(&mp->em_lock);
}
EXPORT_SYMBOL(fc_exch_mgr_reset);
@@ -1778,7 +1811,8 @@ EXPORT_SYMBOL(fc_exch_mgr_del);
struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lp,
enum fc_class class,
- u16 min_xid, u16 max_xid)
+ u16 min_xid, u16 max_xid,
+ bool (*match)(struct fc_frame *))
{
struct fc_exch_mgr *mp;
size_t len;
@@ -1803,7 +1837,6 @@ struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lp,
mp->class = class;
mp->total_exches = 0;
mp->exches = (struct fc_exch **)(mp + 1);
- mp->lp = lp;
/* adjust em exch xid range for offload */
mp->min_xid = min_xid;
mp->max_xid = max_xid;
@@ -1826,6 +1859,18 @@ struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lp,
if (!mp->ep_pool)
goto free_mp;
+ kref_init(&mp->kref);
+ if (!fc_exch_mgr_add(lp, mp, match)) {
+ mempool_destroy(mp->ep_pool);
+ goto free_mp;
+ }
+
+ /*
+ * Above kref_init() sets mp->kref to 1 and then
+ * call to fc_exch_mgr_add incremented mp->kref again,
+ * so adjust that extra increment.
+ */
+ kref_put(&mp->kref, fc_exch_mgr_destroy);
return mp;
free_mp:
@@ -1834,27 +1879,15 @@ free_mp:
}
EXPORT_SYMBOL(fc_exch_mgr_alloc);
-void fc_exch_mgr_free(struct fc_exch_mgr *mp)
+void fc_exch_mgr_free(struct fc_lport *lport)
{
- WARN_ON(!mp);
- /*
- * The total exch count must be zero
- * before freeing exchange manager.
- */
- WARN_ON(mp->total_exches != 0);
- mempool_destroy(mp->ep_pool);
- kfree(mp);
+ struct fc_exch_mgr_anchor *ema, *next;
+
+ list_for_each_entry_safe(ema, next, &lport->ema_list, ema_list)
+ fc_exch_mgr_del(ema);
}
EXPORT_SYMBOL(fc_exch_mgr_free);
-struct fc_exch *fc_exch_get(struct fc_lport *lp, struct fc_frame *fp)
-{
- if (!lp || !lp->emp)
- return NULL;
-
- return fc_exch_alloc(lp->emp, fp, 0);
-}
-EXPORT_SYMBOL(fc_exch_get);
struct fc_seq *fc_exch_seq_send(struct fc_lport *lp,
struct fc_frame *fp,
@@ -1869,7 +1902,7 @@ struct fc_seq *fc_exch_seq_send(struct fc_lport *lp,
struct fc_frame_header *fh;
int rc = 1;
- ep = lp->tt.exch_get(lp, fp);
+ ep = fc_exch_alloc(lp, fp);
if (!ep) {
fc_frame_free(fp);
return NULL;
@@ -1914,24 +1947,44 @@ EXPORT_SYMBOL(fc_exch_seq_send);
/*
* Receive a frame
*/
-void fc_exch_recv(struct fc_lport *lp, struct fc_exch_mgr *mp,
- struct fc_frame *fp)
+void fc_exch_recv(struct fc_lport *lp, struct fc_frame *fp)
{
struct fc_frame_header *fh = fc_frame_header_get(fp);
- u32 f_ctl;
+ struct fc_exch_mgr_anchor *ema;
+ u32 f_ctl, found = 0;
+ u16 oxid;
/* lport lock ? */
- if (!lp || !mp || lp->state == LPORT_ST_DISABLED) {
+ if (!lp || lp->state == LPORT_ST_DISABLED) {
FC_LPORT_DBG(lp, "Receiving frames for an lport that "
"has not been initialized correctly\n");
fc_frame_free(fp);
return;
}
+ f_ctl = ntoh24(fh->fh_f_ctl);
+ oxid = ntohs(fh->fh_ox_id);
+ if (f_ctl & FC_FC_EX_CTX) {
+ list_for_each_entry(ema, &lp->ema_list, ema_list) {
+ if ((oxid >= ema->mp->min_xid) &&
+ (oxid <= ema->mp->max_xid)) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found) {
+ FC_LPORT_DBG(lp, "Received response for out "
+ "of range oxid:%hx\n", oxid);
+ fc_frame_free(fp);
+ return;
+ }
+ } else
+ ema = list_entry(lp->ema_list.prev, typeof(*ema), ema_list);
+
/*
* If frame is marked invalid, just drop it.
*/
- f_ctl = ntoh24(fh->fh_f_ctl);
switch (fr_eof(fp)) {
case FC_EOF_T:
if (f_ctl & FC_FC_END_SEQ)
@@ -1939,34 +1992,24 @@ void fc_exch_recv(struct fc_lport *lp, struct fc_exch_mgr *mp,
/* fall through */
case FC_EOF_N:
if (fh->fh_type == FC_TYPE_BLS)
- fc_exch_recv_bls(mp, fp);
+ fc_exch_recv_bls(ema->mp, fp);
else if ((f_ctl & (FC_FC_EX_CTX | FC_FC_SEQ_CTX)) ==
FC_FC_EX_CTX)
- fc_exch_recv_seq_resp(mp, fp);
+ fc_exch_recv_seq_resp(ema->mp, fp);
else if (f_ctl & FC_FC_SEQ_CTX)
- fc_exch_recv_resp(mp, fp);
+ fc_exch_recv_resp(ema->mp, fp);
else
- fc_exch_recv_req(lp, mp, fp);
+ fc_exch_recv_req(lp, ema->mp, fp);
break;
default:
FC_LPORT_DBG(lp, "dropping invalid frame (eof %x)", fr_eof(fp));
fc_frame_free(fp);
- break;
}
}
EXPORT_SYMBOL(fc_exch_recv);
int fc_exch_init(struct fc_lport *lp)
{
- if (!lp->tt.exch_get) {
- /*
- * exch_put() should be NULL if
- * exch_get() is NULL
- */
- WARN_ON(lp->tt.exch_put);
- lp->tt.exch_get = fc_exch_get;
- }
-
if (!lp->tt.seq_start_next)
lp->tt.seq_start_next = fc_seq_start_next;
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index f1bde91..c2b928c 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -518,25 +518,6 @@ struct libfc_function_template {
void (*exch_done)(struct fc_seq *sp);
/*
- * Assigns a EM and a free XID for an new exchange and then
- * allocates a new exchange and sequence pair.
- * The fp can be used to determine free XID.
- *
- * STATUS: OPTIONAL
- */
- struct fc_exch *(*exch_get)(struct fc_lport *lp, struct fc_frame *fp);
-
- /*
- * Release previously assigned XID by exch_get API.
- * The LLD may implement this if XID is assigned by LLD
- * in exch_get().
- *
- * STATUS: OPTIONAL
- */
- void (*exch_put)(struct fc_lport *lp, struct fc_exch_mgr *mp,
- u16 ex_id);
-
- /*
* Start a new sequence on the same exchange/sequence tuple.
*
* STATUS: OPTIONAL
@@ -703,7 +684,6 @@ struct fc_lport {
/* Associations */
struct Scsi_Host *host;
- struct fc_exch_mgr *emp;
struct list_head ema_list;
struct fc_rport *dns_rp;
struct fc_rport *ptp_rp;
@@ -996,27 +976,25 @@ void fc_exch_mgr_del(struct fc_exch_mgr_anchor *ema);
* a new exchange.
* The LLD may choose to have multiple EMs,
* e.g. one EM instance per CPU receive thread in LLD.
- * The LLD can use exch_get() of struct libfc_function_template
- * to specify XID for a new exchange within
- * a specified EM instance.
*
- * The em_idx to uniquely identify an EM instance.
+ * Specified match function is used in allocating exchanges
+ * from newly allocated EM.
*/
struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lp,
enum fc_class class,
u16 min_xid,
- u16 max_xid);
+ u16 max_xid,
+ bool (*match)(struct fc_frame *));
/*
- * Free an exchange manager.
+ * Free all exchange managers of a lport.
*/
-void fc_exch_mgr_free(struct fc_exch_mgr *mp);
+void fc_exch_mgr_free(struct fc_lport *lport);
/*
* Receive a frame on specified local port and exchange manager.
*/
-void fc_exch_recv(struct fc_lport *lp, struct fc_exch_mgr *mp,
- struct fc_frame *fp);
+void fc_exch_recv(struct fc_lport *lp, struct fc_frame *fp);
/*
* This function is for exch_seq_send function pointer in
@@ -1058,19 +1036,9 @@ int fc_seq_exch_abort(const struct fc_seq *req_sp, unsigned int timer_msec);
void fc_exch_done(struct fc_seq *sp);
/*
- * Assigns a EM and XID for a frame and then allocates
- * a new exchange and sequence pair.
- * The fp can be used to determine free XID.
- */
-struct fc_exch *fc_exch_get(struct fc_lport *lp, struct fc_frame *fp);
-
-/*
* Allocate a new exchange and sequence pair.
- * if ex_id is zero then next free exchange id
- * from specified exchange manger mp will be assigned.
*/
-struct fc_exch *fc_exch_alloc(struct fc_exch_mgr *mp,
- struct fc_frame *fp, u16 ex_id);
+struct fc_exch *fc_exch_alloc(struct fc_lport *lport, struct fc_frame *fp);
/*
* Start a new sequence on the same exchange as the supplied sequence.
*/
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 17/22] fcoe: modifies fcoe_hostlist_lock uses as prep work to add shared offload EM
2009-07-30 0:03 [PATCH 00/22] Open-FCoE Features for 2.6.32 Robert Love
` (15 preceding siblings ...)
2009-07-30 0:05 ` [PATCH 16/22] fcoe, fnic, libfc: modifies current code paths to use EM anchor list Robert Love
@ 2009-07-30 0:05 ` Robert Love
2009-07-30 0:05 ` [PATCH 18/22] fcoe, libfc: adds offload EM per eth device with only single xid range per EM Robert Love
` (4 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Robert Love @ 2009-07-30 0:05 UTC (permalink / raw)
To: James.Bottomley, linux-scsi; +Cc: Vasu Dev, Robert Love
From: Vasu Dev <vasu.dev@intel.com>
Modifies fcoe_hostlist_lock uses such that a new EM allocation in
fcoe_em_config and adding new fcoe_softc using fcoe_hostlist_add
are atomic, this is to ensure that a shared offload EM gets allocated
only once per eth device for its all lports.
Signed-off-by: Vasu Dev <vasu.dev@intel.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---
drivers/scsi/fcoe/fcoe.c | 26 ++++++++++++++++++--------
1 files changed, 18 insertions(+), 8 deletions(-)
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index ebf2e20..86410b9 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -419,6 +419,8 @@ static int fcoe_shost_config(struct fc_lport *lp, struct Scsi_Host *shost,
* fcoe_em_config() - allocates em for this lport
* @lp: the port that em is to allocated for
*
+ * Called with write fcoe_hostlist_lock held.
+ *
* Returns : 0 on success
*/
static inline int fcoe_em_config(struct fc_lport *lp)
@@ -607,6 +609,13 @@ static int fcoe_if_create(struct net_device *netdev)
goto out_lp_destroy;
}
+ /*
+ * fcoe_em_alloc() and fcoe_hostlist_add() both
+ * need to be atomic under fcoe_hostlist_lock
+ * since fcoe_em_alloc() looks for an existing EM
+ * instance on host list updated by fcoe_hostlist_add().
+ */
+ write_lock(&fcoe_hostlist_lock);
/* lport exch manager allocation */
rc = fcoe_em_config(lp);
if (rc) {
@@ -617,6 +626,7 @@ static int fcoe_if_create(struct net_device *netdev)
/* add to lports list */
fcoe_hostlist_add(lp);
+ write_unlock(&fcoe_hostlist_lock);
lp->boot_time = jiffies;
@@ -1720,6 +1730,8 @@ int fcoe_reset(struct Scsi_Host *shost)
* fcoe_hostlist_lookup_softc() - find the corresponding lport by a given device
* @dev: this is currently ptr to net_device
*
+ * Called with fcoe_hostlist_lock held.
+ *
* Returns: NULL or the located fcoe_softc
*/
static struct fcoe_softc *
@@ -1727,14 +1739,10 @@ fcoe_hostlist_lookup_softc(const struct net_device *dev)
{
struct fcoe_softc *fc;
- read_lock(&fcoe_hostlist_lock);
list_for_each_entry(fc, &fcoe_hostlist, list) {
- if (fc->real_dev == dev) {
- read_unlock(&fcoe_hostlist_lock);
+ if (fc->real_dev == dev)
return fc;
- }
}
- read_unlock(&fcoe_hostlist_lock);
return NULL;
}
@@ -1748,7 +1756,9 @@ struct fc_lport *fcoe_hostlist_lookup(const struct net_device *netdev)
{
struct fcoe_softc *fc;
+ read_lock(&fcoe_hostlist_lock);
fc = fcoe_hostlist_lookup_softc(netdev);
+ read_unlock(&fcoe_hostlist_lock);
return (fc) ? fc->ctlr.lp : NULL;
}
@@ -1757,6 +1767,8 @@ struct fc_lport *fcoe_hostlist_lookup(const struct net_device *netdev)
* fcoe_hostlist_add() - Add a lport to lports list
* @lp: ptr to the fc_lport to be added
*
+ * Called with write fcoe_hostlist_lock held.
+ *
* Returns: 0 for success
*/
int fcoe_hostlist_add(const struct fc_lport *lp)
@@ -1766,9 +1778,7 @@ int fcoe_hostlist_add(const struct fc_lport *lp)
fc = fcoe_hostlist_lookup_softc(fcoe_netdev(lp));
if (!fc) {
fc = lport_priv(lp);
- write_lock_bh(&fcoe_hostlist_lock);
list_add_tail(&fc->list, &fcoe_hostlist);
- write_unlock_bh(&fcoe_hostlist_lock);
}
return 0;
}
@@ -1783,9 +1793,9 @@ int fcoe_hostlist_remove(const struct fc_lport *lp)
{
struct fcoe_softc *fc;
+ write_lock_bh(&fcoe_hostlist_lock);
fc = fcoe_hostlist_lookup_softc(fcoe_netdev(lp));
BUG_ON(!fc);
- write_lock_bh(&fcoe_hostlist_lock);
list_del(&fc->list);
write_unlock_bh(&fcoe_hostlist_lock);
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 18/22] fcoe, libfc: adds offload EM per eth device with only single xid range per EM
2009-07-30 0:03 [PATCH 00/22] Open-FCoE Features for 2.6.32 Robert Love
` (16 preceding siblings ...)
2009-07-30 0:05 ` [PATCH 17/22] fcoe: modifies fcoe_hostlist_lock uses as prep work to add shared offload EM Robert Love
@ 2009-07-30 0:05 ` Robert Love
2009-07-30 0:05 ` [PATCH 19/22] fcoe: Remove ifdef for NETIF_F_FCOE_CRC and NETIF_F_FSO Robert Love
` (3 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Robert Love @ 2009-07-30 0:05 UTC (permalink / raw)
To: James.Bottomley, linux-scsi; +Cc: Vasu Dev, Robert Love
From: Vasu Dev <vasu.dev@intel.com>
Updates fcoe_em_config to allocate a single instance of sharable offload
EM for supported lp->lro_xid per eth device, and then share this EM
for subsequently more lports creation on same eth device (e.g when using
VLAN).
Adds tiny fcoe_oem_match function for offload EM to return true for read
types IO to have read IO exchanges allocated from offload shared EM.
Removes fc_em_alloc_xid function completely which was needed to manage
two xid ranges within a EM, this is not needed any more with allocation
of separate sharable offload EM per eth device. Instead this patch adds
simple xid allocation logic to manage single xid range.
Adds fc_exch_em_alloc with mp->next_xid as cursor to allocate new xid
from single xid range of EM, uses mp->next_xid instead removed mp->last_xid
which slightly increase probability of finding empty xid on exch allocation.
Removes restriction of not allowing use of xid zero along with changing
two xid range change to single xid range.
Makes fc_fcp_ddp_setup calling conditional to only xid allocated from
shared offload EM.
Signed-off-by: Vasu Dev <vasu.dev@intel.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---
drivers/scsi/fcoe/fcoe.c | 67 +++++++++++++++++++++++++++++-
drivers/scsi/fcoe/fcoe.h | 3 +
drivers/scsi/libfc/fc_exch.c | 94 ++++++++----------------------------------
3 files changed, 85 insertions(+), 79 deletions(-)
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 86410b9..0306aa9 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -415,6 +415,17 @@ static int fcoe_shost_config(struct fc_lport *lp, struct Scsi_Host *shost,
return 0;
}
+/*
+ * fcoe_oem_match() - match for read types IO
+ * @fp: the fc_frame for new IO.
+ *
+ * Returns : true for read types IO, otherwise returns false.
+ */
+bool fcoe_oem_match(struct fc_frame *fp)
+{
+ return fc_fcp_is_read(fr_fsp(fp));
+}
+
/**
* fcoe_em_config() - allocates em for this lport
* @lp: the port that em is to allocated for
@@ -425,9 +436,61 @@ static int fcoe_shost_config(struct fc_lport *lp, struct Scsi_Host *shost,
*/
static inline int fcoe_em_config(struct fc_lport *lp)
{
- if (!fc_exch_mgr_alloc(lp, FC_CLASS_3, FCOE_MIN_XID,
- FCOE_MAX_XID, NULL))
+ struct fcoe_softc *fc = lport_priv(lp);
+ struct fcoe_softc *oldfc = NULL;
+ u16 min_xid = FCOE_MIN_XID;
+ u16 max_xid = FCOE_MAX_XID;
+
+ /*
+ * Check if need to allocate an em instance for
+ * offload exchange ids to be shared across all VN_PORTs/lport.
+ */
+ if (!lp->lro_enabled || !lp->lro_xid || (lp->lro_xid >= max_xid)) {
+ lp->lro_xid = 0;
+ goto skip_oem;
+ }
+
+ /*
+ * Reuse existing offload em instance in case
+ * it is already allocated on phys_dev.
+ */
+ list_for_each_entry(oldfc, &fcoe_hostlist, list) {
+ if (oldfc->phys_dev == fc->phys_dev) {
+ fc->oem = oldfc->oem;
+ break;
+ }
+ }
+
+ if (fc->oem) {
+ if (!fc_exch_mgr_add(lp, fc->oem, fcoe_oem_match)) {
+ printk(KERN_ERR "fcoe_em_config: failed to add "
+ "offload em:%p on interface:%s\n",
+ fc->oem, fc->real_dev->name);
+ return -ENOMEM;
+ }
+ } else {
+ fc->oem = fc_exch_mgr_alloc(lp, FC_CLASS_3,
+ FCOE_MIN_XID, lp->lro_xid,
+ fcoe_oem_match);
+ if (!fc->oem) {
+ printk(KERN_ERR "fcoe_em_config: failed to allocate "
+ "em for offload exches on interface:%s\n",
+ fc->real_dev->name);
+ return -ENOMEM;
+ }
+ }
+
+ /*
+ * Exclude offload EM xid range from next EM xid range.
+ */
+ min_xid += lp->lro_xid + 1;
+
+skip_oem:
+ if (!fc_exch_mgr_alloc(lp, FC_CLASS_3, min_xid, max_xid, NULL)) {
+ printk(KERN_ERR "fcoe_em_config: failed to "
+ "allocate em on interface %s\n", fc->real_dev->name);
return -ENOMEM;
+ }
return 0;
}
diff --git a/drivers/scsi/fcoe/fcoe.h b/drivers/scsi/fcoe/fcoe.h
index 0d724fa..6905efc 100644
--- a/drivers/scsi/fcoe/fcoe.h
+++ b/drivers/scsi/fcoe/fcoe.h
@@ -37,7 +37,7 @@
#define FCOE_MAX_OUTSTANDING_COMMANDS 1024
-#define FCOE_MIN_XID 0x0001 /* the min xid supported by fcoe_sw */
+#define FCOE_MIN_XID 0x0000 /* the min xid supported by fcoe_sw */
#define FCOE_MAX_XID 0x07ef /* the max xid supported by fcoe_sw */
unsigned int fcoe_debug_logging;
@@ -81,6 +81,7 @@ struct fcoe_softc {
struct list_head list;
struct net_device *real_dev;
struct net_device *phys_dev; /* device with ethtool_ops */
+ struct fc_exch_mgr *oem; /* offload exchange manger */
struct packet_type fcoe_packet_type;
struct packet_type fip_packet_type;
struct sk_buff_head fcoe_pending_queue;
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index 324589a..11ddd11 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -58,7 +58,7 @@ struct fc_exch_mgr {
struct kref kref; /* exchange mgr reference count */
spinlock_t em_lock; /* exchange manager lock,
must be taken before ex_lock */
- u16 last_xid; /* last allocated exchange ID */
+ u16 next_xid; /* next possible free exchange ID */
u16 min_xid; /* min exchange ID */
u16 max_xid; /* max exchange ID */
u16 max_read; /* max exchange ID for read */
@@ -464,68 +464,21 @@ static struct fc_seq *fc_seq_alloc(struct fc_exch *ep, u8 seq_id)
return sp;
}
-/*
- * fc_em_alloc_xid - returns an xid based on request type
- * @lp : ptr to associated lport
- * @fp : ptr to the assocated frame
- *
- * check the associated fc_fsp_pkt to get scsi command type and
- * command direction to decide from which range this exch id
- * will be allocated from.
- *
- * Returns : 0 or an valid xid
- */
-static u16 fc_em_alloc_xid(struct fc_exch_mgr *mp, const struct fc_frame *fp)
-{
- u16 xid, min, max;
- u16 *plast;
- struct fc_exch *ep = NULL;
-
- if (mp->max_read) {
- if (fc_fcp_is_read(fr_fsp(fp))) {
- min = mp->min_xid;
- max = mp->max_read;
- plast = &mp->last_read;
- } else {
- min = mp->max_read + 1;
- max = mp->max_xid;
- plast = &mp->last_xid;
- }
- } else {
- min = mp->min_xid;
- max = mp->max_xid;
- plast = &mp->last_xid;
- }
- xid = *plast;
- do {
- xid = (xid == max) ? min : xid + 1;
- ep = mp->exches[xid - mp->min_xid];
- } while ((ep != NULL) && (xid != *plast));
-
- if (unlikely(ep))
- xid = 0;
- else
- *plast = xid;
-
- return xid;
-}
-
/**
* fc_exch_em_alloc() - allocate an exchange from a specified EM.
* @lport: ptr to the local port
* @mp: ptr to the exchange manager
- * @fp: ptr to the FC frame
- * @xid: input xid
*
- * if xid is supplied zero then assign next free exchange ID
- * from exchange manager, otherwise use supplied xid.
- * Returns with exch lock held.
+ * Returns pointer to allocated fc_exch with exch lock held.
*/
static struct fc_exch *fc_exch_em_alloc(struct fc_lport *lport,
- struct fc_exch_mgr *mp,
- struct fc_frame *fp, u16 xid)
+ struct fc_exch_mgr *mp)
{
struct fc_exch *ep;
+ u16 min, max, xid;
+
+ min = mp->min_xid;
+ max = mp->max_xid;
/* allocate memory for exchange */
ep = mempool_alloc(mp->ep_pool, GFP_ATOMIC);
@@ -536,15 +489,14 @@ static struct fc_exch *fc_exch_em_alloc(struct fc_lport *lport,
memset(ep, 0, sizeof(*ep));
spin_lock_bh(&mp->em_lock);
- /* alloc xid if input xid 0 */
- if (!xid) {
- /* alloc a new xid */
- xid = fc_em_alloc_xid(mp, fp);
- if (!xid) {
- printk(KERN_WARNING "libfc: Failed to allocate an exhange\n");
+ xid = mp->next_xid;
+ /* alloc a new xid */
+ while (mp->exches[xid - min]) {
+ xid = (xid == max) ? min : xid + 1;
+ if (xid == mp->next_xid)
goto err;
- }
}
+ mp->next_xid = (xid == max) ? min : xid + 1;
fc_exch_hold(ep); /* hold for exch in mp */
spin_lock_init(&ep->ex_lock);
@@ -597,7 +549,7 @@ struct fc_exch *fc_exch_alloc(struct fc_lport *lport, struct fc_frame *fp)
list_for_each_entry(ema, &lport->ema_list, ema_list) {
if (!ema->match || ema->match(fp)) {
- ep = fc_exch_em_alloc(lport, ema->mp, fp, 0);
+ ep = fc_exch_em_alloc(lport, ema->mp);
if (ep)
return ep;
}
@@ -1817,7 +1769,7 @@ struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lp,
struct fc_exch_mgr *mp;
size_t len;
- if (max_xid <= min_xid || min_xid == 0 || max_xid == FC_XID_UNKNOWN) {
+ if (max_xid <= min_xid || max_xid == FC_XID_UNKNOWN) {
FC_LPORT_DBG(lp, "Invalid min_xid 0x:%x and max_xid 0x:%x\n",
min_xid, max_xid);
return NULL;
@@ -1826,7 +1778,6 @@ struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lp,
/*
* Memory need for EM
*/
-#define xid_ok(i, m1, m2) (((i) >= (m1)) && ((i) <= (m2)))
len = (max_xid - min_xid + 1) * (sizeof(struct fc_exch *));
len += sizeof(struct fc_exch_mgr);
@@ -1840,17 +1791,7 @@ struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lp,
/* adjust em exch xid range for offload */
mp->min_xid = min_xid;
mp->max_xid = max_xid;
- mp->last_xid = min_xid - 1;
- mp->max_read = 0;
- mp->last_read = 0;
- if (lp->lro_enabled && xid_ok(lp->lro_xid, min_xid, max_xid)) {
- mp->max_read = lp->lro_xid;
- mp->last_read = min_xid - 1;
- mp->last_xid = mp->max_read;
- } else {
- /* disable lro if no xid control over read */
- lp->lro_enabled = 0;
- }
+ mp->next_xid = min_xid;
INIT_LIST_HEAD(&mp->ex_list);
spin_lock_init(&mp->em_lock);
@@ -1922,7 +1863,8 @@ struct fc_seq *fc_exch_seq_send(struct fc_lport *lp,
fc_exch_setup_hdr(ep, fp, ep->f_ctl);
sp->cnt++;
- fc_fcp_ddp_setup(fr_fsp(fp), ep->xid);
+ if (ep->xid <= lp->lro_xid)
+ fc_fcp_ddp_setup(fr_fsp(fp), ep->xid);
if (unlikely(lp->tt.frame_send(lp, fp)))
goto err;
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 19/22] fcoe: Remove ifdef for NETIF_F_FCOE_CRC and NETIF_F_FSO
2009-07-30 0:03 [PATCH 00/22] Open-FCoE Features for 2.6.32 Robert Love
` (17 preceding siblings ...)
2009-07-30 0:05 ` [PATCH 18/22] fcoe, libfc: adds offload EM per eth device with only single xid range per EM Robert Love
@ 2009-07-30 0:05 ` Robert Love
2009-07-30 0:05 ` [PATCH 20/22] libfc: Remove FC_FRAME_SG_LEN in fc_fcp_send_data Robert Love
` (2 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Robert Love @ 2009-07-30 0:05 UTC (permalink / raw)
To: James.Bottomley, linux-scsi; +Cc: Yi Zou, Robert Love
From: Yi Zou <yi.zou@intel.com>
Remove the extra ifdef for NETIF_F_FSO and NETIF_F_FCOE_CRC since they are
already defined in the current kernel as in include/linux/netdevice.h.
Signed-off-by: Yi Zou <yi.zou@intel.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---
drivers/scsi/fcoe/fcoe.c | 6 ------
1 files changed, 0 insertions(+), 6 deletions(-)
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 0306aa9..ad21e87 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -300,20 +300,16 @@ static int fcoe_netdev_config(struct fc_lport *lp, struct net_device *netdev)
if (fc->real_dev->features & NETIF_F_SG)
lp->sg_supp = 1;
-#ifdef NETIF_F_FCOE_CRC
if (netdev->features & NETIF_F_FCOE_CRC) {
lp->crc_offload = 1;
FCOE_NETDEV_DBG(netdev, "Supports FCCRC offload\n");
}
-#endif
-#ifdef NETIF_F_FSO
if (netdev->features & NETIF_F_FSO) {
lp->seq_offload = 1;
lp->lso_max = netdev->gso_max_size;
FCOE_NETDEV_DBG(netdev, "Supports LSO for max len 0x%x\n",
lp->lso_max);
}
-#endif
if (netdev->fcoe_ddp_xid) {
lp->lro_enabled = 1;
lp->lro_xid = netdev->fcoe_ddp_xid;
@@ -1205,7 +1201,6 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp)
FC_FCOE_ENCAPS_VER(hp, FC_FCOE_VER);
hp->fcoe_sof = sof;
-#ifdef NETIF_F_FSO
/* fcoe lso, mss is in max_payload which is non-zero for FCP data */
if (lp->seq_offload && fr_max_payload(fp)) {
skb_shinfo(skb)->gso_type = SKB_GSO_FCOE;
@@ -1214,7 +1209,6 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp)
skb_shinfo(skb)->gso_type = 0;
skb_shinfo(skb)->gso_size = 0;
}
-#endif
/* update tx stats: regardless if LLD fails */
stats = fc_lport_get_stats(lp);
stats->TxFrames++;
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 20/22] libfc: Remove FC_FRAME_SG_LEN in fc_fcp_send_data
2009-07-30 0:03 [PATCH 00/22] Open-FCoE Features for 2.6.32 Robert Love
` (18 preceding siblings ...)
2009-07-30 0:05 ` [PATCH 19/22] fcoe: Remove ifdef for NETIF_F_FCOE_CRC and NETIF_F_FSO Robert Love
@ 2009-07-30 0:05 ` Robert Love
2009-07-30 0:05 ` [PATCH 21/22] libfc: Remove page flags check for sglist Robert Love
2009-07-30 0:05 ` [PATCH 22/22] fcoe: removes phys_dev and renames real_dev to netdev Robert Love
21 siblings, 0 replies; 23+ messages in thread
From: Robert Love @ 2009-07-30 0:05 UTC (permalink / raw)
To: James.Bottomley, linux-scsi; +Cc: Yi Zou, Robert Love
From: Yi Zou <yi.zou@intel.com>
FC_FRAME_SG_LEN is 4 which is too small when offload is enabled. Actually, the
WARN_ON() in fc_fcp_send_data() should be:
WARN_ON(skb_shinfo(fp_skb(fp))->nr_frags > MAX_SKB_FRAGS);
But since we will not get anything more than 64K anyway, so there is no need
to do this anyway here. Therefore, I am getting rid of FC_FRAME_SG_LEN here
and the WARN_ON here.
Signed-off-by: Yi Zou <yi.zou@intel.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---
drivers/scsi/libfc/fc_fcp.c | 2 --
include/scsi/fc_frame.h | 7 -------
2 files changed, 0 insertions(+), 9 deletions(-)
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index e303e0d..2069edf 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -569,8 +569,6 @@ static int fc_fcp_send_data(struct fc_fcp_pkt *fsp, struct fc_seq *seq,
}
sg_bytes = min(tlen, sg->length - offset);
if (using_sg) {
- WARN_ON(skb_shinfo(fp_skb(fp))->nr_frags >
- FC_FRAME_SG_LEN);
get_page(sg_page(sg));
skb_fill_page_desc(fp_skb(fp),
skb_shinfo(fp_skb(fp))->nr_frags,
diff --git a/include/scsi/fc_frame.h b/include/scsi/fc_frame.h
index 5951105..c35d238 100644
--- a/include/scsi/fc_frame.h
+++ b/include/scsi/fc_frame.h
@@ -37,13 +37,6 @@
#define FC_FRAME_HEADROOM 32 /* headroom for VLAN + FCoE headers */
#define FC_FRAME_TAILROOM 8 /* trailer space for FCoE */
-/*
- * Information about an individual fibre channel frame received or to be sent.
- * The buffer may be in up to 4 additional non-contiguous sections,
- * but the linear section must hold the frame header.
- */
-#define FC_FRAME_SG_LEN 4 /* scatter/gather list maximum length */
-
#define fp_skb(fp) (&((fp)->skb))
#define fr_hdr(fp) ((fp)->skb.data)
#define fr_len(fp) ((fp)->skb.len)
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 21/22] libfc: Remove page flags check for sglist
2009-07-30 0:03 [PATCH 00/22] Open-FCoE Features for 2.6.32 Robert Love
` (19 preceding siblings ...)
2009-07-30 0:05 ` [PATCH 20/22] libfc: Remove FC_FRAME_SG_LEN in fc_fcp_send_data Robert Love
@ 2009-07-30 0:05 ` Robert Love
2009-07-30 0:05 ` [PATCH 22/22] fcoe: removes phys_dev and renames real_dev to netdev Robert Love
21 siblings, 0 replies; 23+ messages in thread
From: Robert Love @ 2009-07-30 0:05 UTC (permalink / raw)
To: James.Bottomley, linux-scsi; +Cc: Yi Zou, Robert Love
From: Yi Zou <yi.zou@intel.com>
I don't believe this check is needed any more in the current kernel, which,
if I understand correctly, is for compound page where only the first page
is supposed to get ref-counted.
Signed-off-by: Yi Zou <yi.zou@intel.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---
drivers/scsi/libfc/fc_fcp.c | 27 ---------------------------
1 files changed, 0 insertions(+), 27 deletions(-)
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index 2069edf..7d5ffcb 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -507,33 +507,6 @@ static int fc_fcp_send_data(struct fc_fcp_pkt *fsp, struct fc_seq *seq,
f_ctl = FC_FC_REL_OFF;
WARN_ON(!seq);
- /*
- * If a get_page()/put_page() will fail, don't use sg lists
- * in the fc_frame structure.
- *
- * The put_page() may be long after the I/O has completed
- * in the case of FCoE, since the network driver does it
- * via free_skb(). See the test in free_pages_check().
- *
- * Test this case with 'dd </dev/zero >/dev/st0 bs=64k'.
- */
- if (using_sg) {
- for (sg = scsi_sglist(sc); sg; sg = sg_next(sg)) {
- if (page_count(sg_page(sg)) == 0 ||
- (sg_page(sg)->flags & (1 << PG_lru |
- 1 << PG_private |
- 1 << PG_locked |
- 1 << PG_active |
- 1 << PG_slab |
- 1 << PG_swapcache |
- 1 << PG_writeback |
- 1 << PG_reserved |
- 1 << PG_buddy))) {
- using_sg = 0;
- break;
- }
- }
- }
sg = scsi_sglist(sc);
while (remaining > 0 && sg) {
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 22/22] fcoe: removes phys_dev and renames real_dev to netdev.
2009-07-30 0:03 [PATCH 00/22] Open-FCoE Features for 2.6.32 Robert Love
` (20 preceding siblings ...)
2009-07-30 0:05 ` [PATCH 21/22] libfc: Remove page flags check for sglist Robert Love
@ 2009-07-30 0:05 ` Robert Love
21 siblings, 0 replies; 23+ messages in thread
From: Robert Love @ 2009-07-30 0:05 UTC (permalink / raw)
To: James.Bottomley, linux-scsi; +Cc: Vasu Dev, Robert Love
From: Vasu Dev <vasu.dev@intel.com>
The phys_dev was used only to locate common offload EM instance for all
FCoE instances on a eth devices in function fcoe_em_config, so just updated
fcoe_em_config to look for actual real eth device in locating common offload
EM instance and then no need to store phys_dev in fcoe_softc, so removes
phys_dev from fcoe_softc also.
Renames fcoe_softc real_dev to netdev and updates all its uses to use netdev.
So effectively no functional change, use of single netdev instead phys_dev
and real_dev saves one pointer memory in fcoe_softc, also real_dev used here
was confusing with vlan driver terminology since real_dev in vlan driver is
referred to physical eth device.
Signed-off-by: Vasu Dev <vasu.dev@intel.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---
drivers/scsi/fcoe/fcoe.c | 93 ++++++++++++++++++++++++----------------------
drivers/scsi/fcoe/fcoe.h | 5 +-
2 files changed, 51 insertions(+), 47 deletions(-)
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index ad21e87..757aa28 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -159,7 +159,7 @@ static int fcoe_fip_recv(struct sk_buff *skb, struct net_device *dev,
*/
static void fcoe_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb)
{
- skb->dev = fcoe_from_ctlr(fip)->real_dev;
+ skb->dev = fcoe_from_ctlr(fip)->netdev;
dev_queue_xmit(skb);
}
@@ -179,8 +179,8 @@ static void fcoe_update_src_mac(struct fcoe_ctlr *fip, u8 *old, u8 *new)
fc = fcoe_from_ctlr(fip);
rtnl_lock();
if (!is_zero_ether_addr(old))
- dev_unicast_delete(fc->real_dev, old);
- dev_unicast_add(fc->real_dev, new);
+ dev_unicast_delete(fc->netdev, old);
+ dev_unicast_add(fc->netdev, new);
rtnl_unlock();
}
@@ -231,12 +231,12 @@ void fcoe_netdev_cleanup(struct fcoe_softc *fc)
/* Delete secondary MAC addresses */
rtnl_lock();
memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN);
- dev_unicast_delete(fc->real_dev, flogi_maddr);
+ dev_unicast_delete(fc->netdev, flogi_maddr);
if (!is_zero_ether_addr(fc->ctlr.data_src_addr))
- dev_unicast_delete(fc->real_dev, fc->ctlr.data_src_addr);
+ dev_unicast_delete(fc->netdev, fc->ctlr.data_src_addr);
if (fc->ctlr.spma)
- dev_unicast_delete(fc->real_dev, fc->ctlr.ctl_src_addr);
- dev_mc_delete(fc->real_dev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0);
+ dev_unicast_delete(fc->netdev, fc->ctlr.ctl_src_addr);
+ dev_mc_delete(fc->netdev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0);
rtnl_unlock();
}
@@ -272,17 +272,12 @@ static int fcoe_netdev_config(struct fc_lport *lp, struct net_device *netdev)
/* Setup lport private data to point to fcoe softc */
fc = lport_priv(lp);
fc->ctlr.lp = lp;
- fc->real_dev = netdev;
- fc->phys_dev = netdev;
-
- /* Require support for get_pauseparam ethtool op. */
- if (netdev->priv_flags & IFF_802_1Q_VLAN)
- fc->phys_dev = vlan_dev_real_dev(netdev);
+ fc->netdev = netdev;
/* Do not support for bonding device */
- if ((fc->real_dev->priv_flags & IFF_MASTER_ALB) ||
- (fc->real_dev->priv_flags & IFF_SLAVE_INACTIVE) ||
- (fc->real_dev->priv_flags & IFF_MASTER_8023AD)) {
+ if ((netdev->priv_flags & IFF_MASTER_ALB) ||
+ (netdev->priv_flags & IFF_SLAVE_INACTIVE) ||
+ (netdev->priv_flags & IFF_MASTER_8023AD)) {
return -EOPNOTSUPP;
}
@@ -291,13 +286,13 @@ static int fcoe_netdev_config(struct fc_lport *lp, struct net_device *netdev)
* user-configured limit. If the MFS is too low, fcoe_link_ok()
* will return 0, so do this first.
*/
- mfs = fc->real_dev->mtu - (sizeof(struct fcoe_hdr) +
- sizeof(struct fcoe_crc_eof));
+ mfs = netdev->mtu - (sizeof(struct fcoe_hdr) +
+ sizeof(struct fcoe_crc_eof));
if (fc_set_mfs(lp, mfs))
return -EINVAL;
/* offload features support */
- if (fc->real_dev->features & NETIF_F_SG)
+ if (netdev->features & NETIF_F_SG)
lp->sg_supp = 1;
if (netdev->features & NETIF_F_FCOE_CRC) {
@@ -335,13 +330,13 @@ static int fcoe_netdev_config(struct fc_lport *lp, struct net_device *netdev)
/* setup Source Mac Address */
if (!fc->ctlr.spma)
- memcpy(fc->ctlr.ctl_src_addr, fc->real_dev->dev_addr,
- fc->real_dev->addr_len);
+ memcpy(fc->ctlr.ctl_src_addr, netdev->dev_addr,
+ fc->netdev->addr_len);
- wwnn = fcoe_wwn_from_mac(fc->real_dev->dev_addr, 1, 0);
+ wwnn = fcoe_wwn_from_mac(netdev->dev_addr, 1, 0);
fc_set_wwnn(lp, wwnn);
/* XXX - 3rd arg needs to be vlan id */
- wwpn = fcoe_wwn_from_mac(fc->real_dev->dev_addr, 2, 0);
+ wwpn = fcoe_wwn_from_mac(netdev->dev_addr, 2, 0);
fc_set_wwpn(lp, wwpn);
/*
@@ -351,10 +346,10 @@ static int fcoe_netdev_config(struct fc_lport *lp, struct net_device *netdev)
*/
rtnl_lock();
memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN);
- dev_unicast_add(fc->real_dev, flogi_maddr);
+ dev_unicast_add(netdev, flogi_maddr);
if (fc->ctlr.spma)
- dev_unicast_add(fc->real_dev, fc->ctlr.ctl_src_addr);
- dev_mc_add(fc->real_dev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0);
+ dev_unicast_add(netdev, fc->ctlr.ctl_src_addr);
+ dev_mc_add(netdev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0);
rtnl_unlock();
/*
@@ -363,12 +358,12 @@ static int fcoe_netdev_config(struct fc_lport *lp, struct net_device *netdev)
*/
fc->fcoe_packet_type.func = fcoe_rcv;
fc->fcoe_packet_type.type = __constant_htons(ETH_P_FCOE);
- fc->fcoe_packet_type.dev = fc->real_dev;
+ fc->fcoe_packet_type.dev = netdev;
dev_add_pack(&fc->fcoe_packet_type);
fc->fip_packet_type.func = fcoe_fip_recv;
fc->fip_packet_type.type = htons(ETH_P_FIP);
- fc->fip_packet_type.dev = fc->real_dev;
+ fc->fip_packet_type.dev = netdev;
dev_add_pack(&fc->fip_packet_type);
return 0;
@@ -434,6 +429,7 @@ static inline int fcoe_em_config(struct fc_lport *lp)
{
struct fcoe_softc *fc = lport_priv(lp);
struct fcoe_softc *oldfc = NULL;
+ struct net_device *old_real_dev, *cur_real_dev;
u16 min_xid = FCOE_MIN_XID;
u16 max_xid = FCOE_MAX_XID;
@@ -448,10 +444,20 @@ static inline int fcoe_em_config(struct fc_lport *lp)
/*
* Reuse existing offload em instance in case
- * it is already allocated on phys_dev.
+ * it is already allocated on real eth device
*/
+ if (fc->netdev->priv_flags & IFF_802_1Q_VLAN)
+ cur_real_dev = vlan_dev_real_dev(fc->netdev);
+ else
+ cur_real_dev = fc->netdev;
+
list_for_each_entry(oldfc, &fcoe_hostlist, list) {
- if (oldfc->phys_dev == fc->phys_dev) {
+ if (oldfc->netdev->priv_flags & IFF_802_1Q_VLAN)
+ old_real_dev = vlan_dev_real_dev(oldfc->netdev);
+ else
+ old_real_dev = oldfc->netdev;
+
+ if (cur_real_dev == old_real_dev) {
fc->oem = oldfc->oem;
break;
}
@@ -461,7 +467,7 @@ static inline int fcoe_em_config(struct fc_lport *lp)
if (!fc_exch_mgr_add(lp, fc->oem, fcoe_oem_match)) {
printk(KERN_ERR "fcoe_em_config: failed to add "
"offload em:%p on interface:%s\n",
- fc->oem, fc->real_dev->name);
+ fc->oem, fc->netdev->name);
return -ENOMEM;
}
} else {
@@ -471,7 +477,7 @@ static inline int fcoe_em_config(struct fc_lport *lp)
if (!fc->oem) {
printk(KERN_ERR "fcoe_em_config: failed to allocate "
"em for offload exches on interface:%s\n",
- fc->real_dev->name);
+ fc->netdev->name);
return -ENOMEM;
}
}
@@ -484,7 +490,7 @@ static inline int fcoe_em_config(struct fc_lport *lp)
skip_oem:
if (!fc_exch_mgr_alloc(lp, FC_CLASS_3, min_xid, max_xid, NULL)) {
printk(KERN_ERR "fcoe_em_config: failed to "
- "allocate em on interface %s\n", fc->real_dev->name);
+ "allocate em on interface %s\n", fc->netdev->name);
return -ENOMEM;
}
@@ -548,7 +554,7 @@ static int fcoe_if_destroy(struct net_device *netdev)
fc_lport_free_stats(lp);
/* Release the net_device and Scsi_Host */
- dev_put(fc->real_dev);
+ dev_put(netdev);
scsi_host_put(lp->host);
return 0;
@@ -1179,7 +1185,7 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp)
skb_reset_network_header(skb);
skb->mac_len = elen;
skb->protocol = htons(ETH_P_FCOE);
- skb->dev = fc->real_dev;
+ skb->dev = fc->netdev;
/* fill up mac and fcoe headers */
eh = eth_hdr(skb);
@@ -1454,7 +1460,7 @@ static int fcoe_device_notification(struct notifier_block *notifier,
ulong event, void *ptr)
{
struct fc_lport *lp = NULL;
- struct net_device *real_dev = ptr;
+ struct net_device *netdev = ptr;
struct fcoe_softc *fc;
struct fcoe_dev_stats *stats;
u32 link_possible = 1;
@@ -1463,7 +1469,7 @@ static int fcoe_device_notification(struct notifier_block *notifier,
read_lock(&fcoe_hostlist_lock);
list_for_each_entry(fc, &fcoe_hostlist, list) {
- if (fc->real_dev == real_dev) {
+ if (fc->netdev == netdev) {
lp = fc->ctlr.lp;
break;
}
@@ -1483,16 +1489,15 @@ static int fcoe_device_notification(struct notifier_block *notifier,
case NETDEV_CHANGE:
break;
case NETDEV_CHANGEMTU:
- mfs = fc->real_dev->mtu -
- (sizeof(struct fcoe_hdr) +
- sizeof(struct fcoe_crc_eof));
+ mfs = netdev->mtu - (sizeof(struct fcoe_hdr) +
+ sizeof(struct fcoe_crc_eof));
if (mfs >= FC_MIN_MAX_FRAME)
fc_set_mfs(lp, mfs);
break;
case NETDEV_REGISTER:
break;
default:
- FCOE_NETDEV_DBG(real_dev, "Unknown event %ld "
+ FCOE_NETDEV_DBG(netdev, "Unknown event %ld "
"from netdev netlink\n", event);
}
if (link_possible && !fcoe_link_ok(lp))
@@ -1696,7 +1701,7 @@ MODULE_PARM_DESC(destroy, "Destroy fcoe port");
int fcoe_link_ok(struct fc_lport *lp)
{
struct fcoe_softc *fc = lport_priv(lp);
- struct net_device *dev = fc->real_dev;
+ struct net_device *dev = fc->netdev;
struct ethtool_cmd ecmd = { ETHTOOL_GSET };
if ((dev->flags & IFF_UP) && netif_carrier_ok(dev) &&
@@ -1797,7 +1802,7 @@ fcoe_hostlist_lookup_softc(const struct net_device *dev)
struct fcoe_softc *fc;
list_for_each_entry(fc, &fcoe_hostlist, list) {
- if (fc->real_dev == dev)
+ if (fc->netdev == dev)
return fc;
}
return NULL;
@@ -1916,7 +1921,7 @@ static void __exit fcoe_exit(void)
/* releases the associated fcoe hosts */
list_for_each_entry_safe(fc, tmp, &fcoe_hostlist, list)
- fcoe_if_destroy(fc->real_dev);
+ fcoe_if_destroy(fc->netdev);
unregister_hotcpu_notifier(&fcoe_cpu_notifier);
diff --git a/drivers/scsi/fcoe/fcoe.h b/drivers/scsi/fcoe/fcoe.h
index 6905efc..5ae8ca7 100644
--- a/drivers/scsi/fcoe/fcoe.h
+++ b/drivers/scsi/fcoe/fcoe.h
@@ -79,8 +79,7 @@ struct fcoe_percpu_s {
*/
struct fcoe_softc {
struct list_head list;
- struct net_device *real_dev;
- struct net_device *phys_dev; /* device with ethtool_ops */
+ struct net_device *netdev;
struct fc_exch_mgr *oem; /* offload exchange manger */
struct packet_type fcoe_packet_type;
struct packet_type fip_packet_type;
@@ -95,7 +94,7 @@ struct fcoe_softc {
static inline struct net_device *fcoe_netdev(
const struct fc_lport *lp)
{
- return ((struct fcoe_softc *)lport_priv(lp))->real_dev;
+ return ((struct fcoe_softc *)lport_priv(lp))->netdev;
}
#endif /* _FCOE_H_ */
^ permalink raw reply related [flat|nested] 23+ messages in thread
end of thread, other threads:[~2009-07-30 0:05 UTC | newest]
Thread overview: 23+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-07-30 0:03 [PATCH 00/22] Open-FCoE Features for 2.6.32 Robert Love
2009-07-30 0:03 ` [PATCH 01/22] fcoe: Fix validation of mac address when checking for spma support Robert Love
2009-07-30 0:03 ` [PATCH 02/22] libfcoe: Set fip_flags according to fcf and lport's capability of SPMA support Robert Love
2009-07-30 0:04 ` [PATCH 03/22] fcoe: Call dev_ethtool_get_settings() in fcoe_link_ok Robert Love
2009-07-30 0:04 ` [PATCH 04/22] libfc: remove extra semicolons from debug macros Robert Love
2009-07-30 0:04 ` [PATCH 05/22] libfc: change debug messages to give host number Robert Love
2009-07-30 0:04 ` [PATCH 06/22] fcoe: stop delivery of received frames before doing lport_destroy() Robert Love
2009-07-30 0:04 ` [PATCH 07/22] libfc: rename lport NONE state to DISABLED Robert Love
2009-07-30 0:04 ` [PATCH 08/22] libfc: stop login after fabric logoff Robert Love
2009-07-30 0:04 ` [PATCH 09/22] libfc: in fc_lport_destroy, flush rports after turning off link Robert Love
2009-07-30 0:04 ` [PATCH 10/22] libfc: fix WARNING from fc_seq_start_next on closed exchanges Robert Love
2009-07-30 0:04 ` [PATCH 11/22] libfc: rename rport state "NONE" to "DELETE" Robert Love
2009-07-30 0:04 ` [PATCH 12/22] libfc: fc_rport_logoff should not drop the lock Robert Love
2009-07-30 0:04 ` [PATCH 13/22] libfc: fix: cancel rport retry timer Robert Love
2009-07-30 0:05 ` [PATCH 14/22] fcoe, libfc: adds exchange manager(EM) anchor list per lport and related APIs Robert Love
2009-07-30 0:05 ` [PATCH 15/22] libfc: Remove the FC_EM_DBG macro Robert Love
2009-07-30 0:05 ` [PATCH 16/22] fcoe, fnic, libfc: modifies current code paths to use EM anchor list Robert Love
2009-07-30 0:05 ` [PATCH 17/22] fcoe: modifies fcoe_hostlist_lock uses as prep work to add shared offload EM Robert Love
2009-07-30 0:05 ` [PATCH 18/22] fcoe, libfc: adds offload EM per eth device with only single xid range per EM Robert Love
2009-07-30 0:05 ` [PATCH 19/22] fcoe: Remove ifdef for NETIF_F_FCOE_CRC and NETIF_F_FSO Robert Love
2009-07-30 0:05 ` [PATCH 20/22] libfc: Remove FC_FRAME_SG_LEN in fc_fcp_send_data Robert Love
2009-07-30 0:05 ` [PATCH 21/22] libfc: Remove page flags check for sglist Robert Love
2009-07-30 0:05 ` [PATCH 22/22] fcoe: removes phys_dev and renames real_dev to netdev Robert Love
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox