The user could temporarily disable a fcoe interface
and then enable it again with this added interface,
the fcoemon util can use this to temporarily disable
fcoe when its DCB state is not operational.

The fcoe enable/disable is tracked by added enabled
field to lport and then current lport reset functionality
is used to enable and disable all VN_PORTs on a eth
interface.

Adds sysfs module param enable and disable for this and
updates adjacent other module param description to be
consistent and more accurate. The older description had
double "fcoe" word with less meaningful netdev reference
to user/admin.

Signed-off-by: Vasu Dev <[email protected]>
---

 drivers/scsi/fcoe/fcoe.c      |  122 ++++++++++++++++++++++++++++++++++++++++-
 drivers/scsi/libfc/fc_lport.c |    2 -
 include/scsi/libfc.h          |    4 +
 3 files changed, 124 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index a30ffaa..6e314d8 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -101,6 +101,8 @@ static int fcoe_cpu_callback(struct notifier_block *, 
unsigned long, void *);
 
 static int fcoe_create(const char *, struct kernel_param *);
 static int fcoe_destroy(const char *, struct kernel_param *);
+static int fcoe_enable(const char *, struct kernel_param *);
+static int fcoe_disable(const char *, struct kernel_param *);
 
 static struct fc_seq *fcoe_elsct_send(struct fc_lport *,
                                      u32 did, struct fc_frame *,
@@ -115,10 +117,16 @@ static void fcoe_get_lesb(struct fc_lport *, struct 
fc_els_lesb *);
 
 module_param_call(create, fcoe_create, NULL, NULL, S_IWUSR);
 __MODULE_PARM_TYPE(create, "string");
-MODULE_PARM_DESC(create, "Create fcoe fcoe using net device passed in.");
+MODULE_PARM_DESC(create, " Creates fcoe instance on a ethernet interface");
 module_param_call(destroy, fcoe_destroy, NULL, NULL, S_IWUSR);
 __MODULE_PARM_TYPE(destroy, "string");
-MODULE_PARM_DESC(destroy, "Destroy fcoe fcoe");
+MODULE_PARM_DESC(destroy, " Destroys fcoe instance on a ethernet interface");
+module_param_call(enable, fcoe_enable, NULL, NULL, S_IWUSR);
+__MODULE_PARM_TYPE(enable, "string");
+MODULE_PARM_DESC(enable, " Enables fcoe on a ethernet interface.");
+module_param_call(disable, fcoe_disable, NULL, NULL, S_IWUSR);
+__MODULE_PARM_TYPE(disable, "string");
+MODULE_PARM_DESC(disable, " Disables fcoe on a ethernet interface.");
 
 /* notification function for packets from net device */
 static struct notifier_block fcoe_notifier = {
@@ -509,6 +517,7 @@ static u8 *fcoe_get_src_mac(struct fc_lport *lport)
 static int fcoe_lport_config(struct fc_lport *lport)
 {
        lport->link_up = 0;
+       lport->enabled = 1;
        lport->qfull = 0;
        lport->max_retry_count = 3;
        lport->max_rport_retry_count = 3;
@@ -1838,6 +1847,115 @@ static struct net_device *fcoe_if_to_netdev(const char 
*buffer)
 }
 
 /**
+ * fcoe_disable() - Disables a FCoE interface
+ * @buffer: The name of the Ethernet interface to be disabled
+ * @kp:            The associated kernel parameter
+ *
+ * Called from sysfs.
+ *
+ * Returns: 0 for success
+ */
+static int fcoe_disable(const char *buffer, struct kernel_param *kp)
+{
+       struct fcoe_interface *fcoe;
+       struct net_device *netdev;
+       int rc = 0;
+
+       mutex_lock(&fcoe_config_mutex);
+#ifdef CONFIG_FCOE_MODULE
+       /*
+        * Make sure the module has been initialized, and is not about to be
+        * removed.  Module paramter sysfs files are writable before the
+        * module_init function is called and after module_exit.
+        */
+       if (THIS_MODULE->state != MODULE_STATE_LIVE) {
+               rc = -ENODEV;
+               goto out_nodev;
+       }
+#endif
+
+       netdev = fcoe_if_to_netdev(buffer);
+       if (!netdev) {
+               rc = -ENODEV;
+               goto out_nodev;
+       }
+
+       rtnl_lock();
+       fcoe = fcoe_hostlist_lookup_port(netdev);
+       if (!fcoe) {
+               rtnl_unlock();
+               rc = -ENODEV;
+               goto out_putdev;
+       }
+       rtnl_unlock();
+       if (fcoe->ctlr.lp->enabled) {
+               fcoe->ctlr.lp->enabled = 0;
+               fc_lport_reset(fcoe->ctlr.lp);
+       } else
+               FCOE_NETDEV_DBG(netdev, "Interface is already disabled\n");
+
+out_putdev:
+       dev_put(netdev);
+out_nodev:
+       mutex_unlock(&fcoe_config_mutex);
+       return rc;
+}
+
+/**
+ * fcoe_enable() - Enables a FCoE interface
+ * @buffer: The name of the Ethernet interface to be enabled
+ * @kp:     The associated kernel parameter
+ *
+ * Called from sysfs.
+ *
+ * Returns: 0 for success
+ */
+static int fcoe_enable(const char *buffer, struct kernel_param *kp)
+{
+       struct fcoe_interface *fcoe;
+       struct net_device *netdev;
+       int rc = 0;
+
+       mutex_lock(&fcoe_config_mutex);
+#ifdef CONFIG_FCOE_MODULE
+       /*
+        * Make sure the module has been initialized, and is not about to be
+        * removed.  Module paramter sysfs files are writable before the
+        * module_init function is called and after module_exit.
+        */
+       if (THIS_MODULE->state != MODULE_STATE_LIVE) {
+               rc = -ENODEV;
+               goto out_nodev;
+       }
+#endif
+
+       netdev = fcoe_if_to_netdev(buffer);
+       if (!netdev) {
+               rc = -ENODEV;
+               goto out_nodev;
+       }
+
+       rtnl_lock();
+       fcoe = fcoe_hostlist_lookup_port(netdev);
+       if (!fcoe) {
+               rtnl_unlock();
+               rc = -ENODEV;
+               goto out_putdev;
+       }
+       rtnl_unlock();
+       if (!fcoe->ctlr.lp->enabled) {
+               fcoe->ctlr.lp->enabled = 1;
+               fc_lport_reset(fcoe->ctlr.lp);
+       } else
+               FCOE_NETDEV_DBG(netdev, "Interface is already enabled\n");
+out_putdev:
+       dev_put(netdev);
+out_nodev:
+       mutex_unlock(&fcoe_config_mutex);
+       return rc;
+}
+
+/**
  * fcoe_destroy() - Destroy a FCoE interface
  * @buffer: The name of the Ethernet interface to be destroyed
  * @kp:            The associated kernel parameter
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index bbf4152..5276ed6 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -976,7 +976,7 @@ static void fc_lport_enter_reset(struct fc_lport *lport)
        fc_lport_state_enter(lport, LPORT_ST_RESET);
        fc_vports_linkchange(lport);
        fc_lport_reset_locked(lport);
-       if (lport->link_up)
+       if (lport->link_up && lport->enabled)
                fc_lport_enter_flogi(lport);
 }
 
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index 4b912ee..6baa003 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -768,6 +768,7 @@ struct fc_disc {
  * @vport:                 Parent vport if VN_Port
  * @tt:                    Libfc function template
  * @link_up:               Link state (1 = link up, 0 = link down)
+ * @enabled:               enabled (1 = enabled, 0 = disabled)
  * @qfull:                 Queue state (1 queue is full, 0 queue is not full)
  * @state:                 Identifies the state
  * @boot_time:             Timestamp indicating when the local port came online
@@ -813,12 +814,13 @@ struct fc_lport {
        /* Operational Information */
        struct libfc_function_template tt;
        u8                             link_up;
+       u8                             enabled;
        u8                             qfull;
+       u8                             retry_count;
        enum fc_lport_state            state;
        unsigned long                  boot_time;
        struct fc_host_statistics      host_stats;
        struct fcoe_dev_stats          *dev_stats;
-       u8                             retry_count;
 
        /* Fabric information */
        u64                            wwpn;

_______________________________________________
devel mailing list
[email protected]
http://www.open-fcoe.org/mailman/listinfo/devel

Reply via email to