* [OpenFCoE PATCH] Don't use netdev for FCoE if pause is not correctly set, even for VLANs.
@ 2007-12-05 0:52 Joe Eykholt
0 siblings, 0 replies; only message in thread
From: Joe Eykholt @ 2007-12-05 0:52 UTC (permalink / raw)
To: linux-scsi
Don't use netdev for FCoE if pause is not correctly set, even for VLANs.
This modifies the previous tests to require that the underlying net-dev
supports the ethtool get_pauseparam operation.
NICs that are 10/100/1000 must have pause autonegotiation turned on.
All NICs must have RX and TX pause on. If not, they are treated as if
there is no link.
Signed-off-by: Joe Eykholt <fcoe@eykholt.com>
---
drivers/scsi/ofc/fcoe/fcoe_def.h | 1
drivers/scsi/ofc/fcoe/fcoe_if.c | 90 ++++++++++++++++++++++----------------
drivers/scsi/ofc/fcoe/fcoeinit.c | 66 ++++++++--------------------
3 files changed, 71 insertions(+), 86 deletions(-)
diff --git a/drivers/scsi/ofc/fcoe/fcoe_def.h b/drivers/scsi/ofc/fcoe/fcoe_def.h
index 0c71dc7..6550c73 100644
--- a/drivers/scsi/ofc/fcoe/fcoe_def.h
+++ b/drivers/scsi/ofc/fcoe/fcoe_def.h
@@ -109,6 +109,7 @@ int fcoe_create_interface(struct fcoe_info *, void *);
int fcoe_xmit(struct fcdev *, struct fc_frame *);
int fcoe_rcv(struct sk_buff *, struct net_device *,
struct packet_type *, struct net_device *);
+int fcoe_link_ok(struct fcdev *);
struct fc_frame *fcoe_frame_alloc(size_t);
void fcoe_put_dev(struct fcdev *dev);
struct fcoe_softc *fcoe_find_fcdev(char *);
diff --git a/drivers/scsi/ofc/fcoe/fcoe_if.c b/drivers/scsi/ofc/fcoe/fcoe_if.c
index d87ede1..fd3c7a7 100644
--- a/drivers/scsi/ofc/fcoe/fcoe_if.c
+++ b/drivers/scsi/ofc/fcoe/fcoe_if.c
@@ -160,6 +160,48 @@ int fcoe_destroy_interface(struct fcdev *fd)
}
/*
+ * Return non-zero if link is OK for use by FCoE.
+ * Any permanently-disqualifying conditions have been previously checked.
+ * This checks pause settings, which can change with link.
+ * This also updates the speed setting, which may change with link for 100/1000.
+ */
+int fcoe_link_ok(struct fcdev *fdev)
+{
+ struct fcoe_softc *fc = (struct fcoe_softc *)fdev->drv_priv;
+ struct net_device *dev = fc->real_dev;
+ struct ethtool_pauseparam pause = { ETHTOOL_GPAUSEPARAM };
+ struct ethtool_cmd ecmd = { ETHTOOL_GSET };
+ int rc = 0;
+
+ if ((dev->flags & IFF_UP) && netif_carrier_ok(dev)) {
+ dev->ethtool_ops->get_pauseparam(dev, &pause);
+ if (dev->ethtool_ops->get_settings) {
+ dev->ethtool_ops->get_settings(dev, &ecmd);
+ fdev->fd_speed_support &=
+ ~(OFC_SPEED_1GBIT | OFC_SPEED_10GBIT);
+ if (ecmd.supported & (SUPPORTED_1000baseT_Half |
+ SUPPORTED_1000baseT_Full))
+ fdev->fd_speed_support |= OFC_SPEED_1GBIT;
+ if (ecmd.supported & SUPPORTED_10000baseT_Full)
+ fdev->fd_speed_support |= OFC_SPEED_10GBIT;
+ if (ecmd.speed == SPEED_1000)
+ fdev->fd_speed = OFC_SPEED_1GBIT;
+ if (ecmd.speed == SPEED_10000)
+ fdev->fd_speed = OFC_SPEED_10GBIT;
+
+ /*
+ * for 10 G (and faster), ignore autoneg requirement.
+ */
+ if (ecmd.speed >= SPEED_10000)
+ pause.autoneg = 1;
+ }
+ if (pause.autoneg && pause.tx_pause && pause.rx_pause)
+ rc = 1;
+ }
+ return rc;
+}
+
+/*
* This function creates the fcoe interface
* create struct fcdev which is a shared structure between opefc
* and transport level protocol.
@@ -171,8 +213,6 @@ int fcoe_create_interface(struct fcoe_info *fci, void *ptr)
struct fcoe_cfg *cfg = ptr;
struct fcoe_softc *fc;
struct fcoe_dev_stats *p;
- struct ethtool_pauseparam pauseparam = { ETHTOOL_GPAUSEPARAM };
- struct ethtool_cmd ecmd = { ETHTOOL_GSET };
int rc = 0;
int i;
#ifdef HAVE_SET_RX_MODE
@@ -207,12 +247,6 @@ int fcoe_create_interface(struct fcoe_info *fci, void *ptr)
goto out;
}
- fdev->fd_link_status = TRANS_LINK_DOWN;
- if ((fc->real_dev->flags & IFF_UP) != 0 &&
- netif_carrier_ok(fc->real_dev)) {
- fdev->fd_link_status = TRANS_LINK_UP;
- }
-
/*
* Do not support for bonding device
*/
@@ -224,38 +258,16 @@ int fcoe_create_interface(struct fcoe_info *fci, void *ptr)
}
/*
- * if it is not a vlan driver then do more check */
- if (!(fc->real_dev->priv_flags & IFF_802_1Q_VLAN)) {
-
- if (!fc->real_dev->ethtool_ops) {
- rc = -EOPNOTSUPP;
- goto out;
- }
- if (!fc->real_dev->ethtool_ops->get_pauseparam) {
- rc = -EOPNOTSUPP;
- goto out;
- }
- fc->real_dev->ethtool_ops->get_pauseparam(fc->real_dev,
- &pauseparam);
- if (!pauseparam.rx_pause || !pauseparam.tx_pause) {
- rc = -EOPNOTSUPP;
- goto out;
- }
- if (fc->real_dev->ethtool_ops->get_settings) {
- fc->real_dev->ethtool_ops->get_settings(fc->real_dev,
- &ecmd);
- if (ecmd.
- supported & (SUPPORTED_1000baseT_Half |
- SUPPORTED_1000baseT_Full))
- fdev->fd_speed_support |= OFC_SPEED_1GBIT;
- if (ecmd.supported & SUPPORTED_10000baseT_Full)
- fdev->fd_speed_support |= OFC_SPEED_10GBIT;
- if (ecmd.speed == SPEED_1000)
- fdev->fd_speed = OFC_SPEED_1GBIT;
- if (ecmd.speed == SPEED_10000)
- fdev->fd_speed = OFC_SPEED_10GBIT;
- }
+ * Require support for get_pauseparam ethtool op.
+ */
+ if (!fc->real_dev->ethtool_ops ||
+ !fc->real_dev->ethtool_ops->get_pauseparam) {
+ rc = -EOPNOTSUPP;
+ goto out;
}
+ fdev->fd_link_status = TRANS_LINK_DOWN;
+ if (fcoe_link_ok(fdev))
+ fdev->fd_link_status = TRANS_LINK_UP;
if (fc->real_dev->features & NETIF_F_SG)
fdev->capabilities = TRANS_C_SG;
diff --git a/drivers/scsi/ofc/fcoe/fcoeinit.c b/drivers/scsi/ofc/fcoe/fcoeinit.c
index 182a9b1..3b80946 100644
--- a/drivers/scsi/ofc/fcoe/fcoeinit.c
+++ b/drivers/scsi/ofc/fcoe/fcoeinit.c
@@ -170,7 +170,6 @@ static void fcoe_dev_cleanup(void)
* This function is called by the ethernet driver
* this is called in case of link change event
*/
-
static int fcoe_device_notification(struct notifier_block *notifier,
ulong event, void *ptr)
{
@@ -179,7 +178,7 @@ static int fcoe_device_notification(struct notifier_block *notifier,
struct fcdev *fc_dev = NULL;
struct fcoe_dev_stats *stats;
struct fcoe_info *fci = &fcoei;
- struct ethtool_pauseparam pauseparam = { ETHTOOL_GPAUSEPARAM };
+ int new_status;
int rc;
read_lock(&fci->fcoe_hostlist_lock);
@@ -190,67 +189,40 @@ static int fcoe_device_notification(struct notifier_block *notifier,
}
}
read_unlock(&fci->fcoe_hostlist_lock);
-
if (fc_dev == NULL) {
rc = NOTIFY_DONE;
goto out;
}
+ new_status = fc_dev->fd_link_status;
switch (event) {
case NETDEV_DOWN:
- fc_dev->fd_link_status = TRANS_LINK_DOWN;
- /* notify upper layer about link down */
- openfc_linkdown(fc_dev);
- stats = fc_dev->dev_stats[smp_processor_id()];
- stats->LinkFailureCount++;
- fcoe_clean_pending_queue(fc_dev);
- rc = NOTIFY_OK;
+ case NETDEV_GOING_DOWN:
+ new_status = TRANS_LINK_DOWN;
break;
case NETDEV_UP:
- fc_dev->fd_link_status = TRANS_LINK_UP;
- /* notify upper layer about link up */
- if (netif_carrier_ok(real_dev)) {
- if ((real_dev->priv_flags & IFF_802_1Q_VLAN) == 0) {
- real_dev->ethtool_ops->get_pauseparam(fc->
- real_dev,
- &pauseparam);
- if (!pauseparam.rx_pause
- || !pauseparam.tx_pause) {
- rc = NOTIFY_OK;
- goto out;
- }
- }
- openfc_linkup(fc_dev);
- }
- rc = NOTIFY_OK;
- break;
case NETDEV_CHANGE:
- if (netif_carrier_ok(real_dev)) {
- if ((real_dev->priv_flags & IFF_802_1Q_VLAN) == 0) {
- real_dev->ethtool_ops->get_pauseparam(fc->
- real_dev,
- &pauseparam);
- if (!pauseparam.rx_pause
- || !pauseparam.tx_pause) {
- rc = NOTIFY_OK;
- goto out;
- }
- }
- if (fc->real_dev->flags & IFF_UP)
- openfc_linkup(fc_dev);
- } else {
- openfc_linkdown(fc_dev);
- fcoe_clean_pending_queue(fc_dev);
- }
- rc = NOTIFY_OK;
+ new_status = TRANS_LINK_DOWN;
+ if (fcoe_link_ok(fc_dev))
+ new_status = TRANS_LINK_UP;
break;
case NETDEV_REGISTER:
- case NETDEV_GOING_DOWN:
rc = NOTIFY_OK;
break;
default:
- SA_LOG("unknow event %d call", event);
+ SA_LOG("unknown event %d call", event);
rc = NOTIFY_OK;
}
+ if (fc_dev->fd_link_status != new_status) {
+ fc_dev->fd_link_status = new_status;
+ if (new_status == TRANS_LINK_UP) {
+ openfc_linkup(fc_dev);
+ } else {
+ stats = fc_dev->dev_stats[smp_processor_id()];
+ stats->LinkFailureCount++;
+ openfc_linkdown(fc_dev);
+ fcoe_clean_pending_queue(fc_dev);
+ }
+ }
out:
return rc;
}
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2007-12-05 0:52 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-12-05 0:52 [OpenFCoE PATCH] Don't use netdev for FCoE if pause is not correctly set, even for VLANs Joe Eykholt
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).