Merge branch 'cpumask-cleanups' of git://git.kernel.org/pub/scm/linux/kernel/git...
[sfrench/cifs-2.6.git] / drivers / scsi / fcoe / fcoe.c
index 51c24b37c60acbce0e84dd7b2c2df7ba2f9f97d5..10be9f36a4cc01b3ce9ce14a0d78f88dd1a6a30a 100644 (file)
@@ -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 = {
@@ -544,6 +552,23 @@ static void fcoe_queue_timer(ulong lport)
        fcoe_check_wait_queue((struct fc_lport *)lport, NULL);
 }
 
+/**
+ * fcoe_get_wwn() - Get the world wide name from LLD if it supports it
+ * @netdev: the associated net device
+ * @wwn: the output WWN
+ * @type: the type of WWN (WWPN or WWNN)
+ *
+ * Returns: 0 for success
+ */
+static int fcoe_get_wwn(struct net_device *netdev, u64 *wwn, int type)
+{
+       const struct net_device_ops *ops = netdev->netdev_ops;
+
+       if (ops->ndo_fcoe_get_wwn)
+               return ops->ndo_fcoe_get_wwn(netdev, wwn, type);
+       return -EINVAL;
+}
+
 /**
  * fcoe_netdev_config() - Set up net devive for SW FCoE
  * @lport:  The local port that is associated with the net device
@@ -611,9 +636,13 @@ static int fcoe_netdev_config(struct fc_lport *lport, struct net_device *netdev)
                 */
                if (netdev->priv_flags & IFF_802_1Q_VLAN)
                        vid = vlan_dev_vlan_id(netdev);
-               wwnn = fcoe_wwn_from_mac(fcoe->ctlr.ctl_src_addr, 1, 0);
+
+               if (fcoe_get_wwn(netdev, &wwnn, NETDEV_FCOE_WWNN))
+                       wwnn = fcoe_wwn_from_mac(fcoe->ctlr.ctl_src_addr, 1, 0);
                fc_set_wwnn(lport, wwnn);
-               wwpn = fcoe_wwn_from_mac(fcoe->ctlr.ctl_src_addr, 2, vid);
+               if (fcoe_get_wwn(netdev, &wwpn, NETDEV_FCOE_WWPN))
+                       wwpn = fcoe_wwn_from_mac(fcoe->ctlr.ctl_src_addr,
+                                                2, vid);
                fc_set_wwpn(lport, wwpn);
        }
 
@@ -1837,6 +1866,104 @@ static struct net_device *fcoe_if_to_netdev(const char *buffer)
        return NULL;
 }
 
+/**
+ * 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);
+       rtnl_unlock();
+
+       if (fcoe)
+               fc_fabric_logoff(fcoe->ctlr.lp);
+       else
+               rc = -ENODEV;
+
+       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);
+       rtnl_unlock();
+
+       if (fcoe)
+               rc = fc_fabric_login(fcoe->ctlr.lp);
+       else
+               rc = -ENODEV;
+
+       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