This is extension of Yi's patches to modify the following:

1. Input parameter for create/destroy/enable/disable will be a
buffer containing "if_name:drv_name".

2. Eliminate match() callback in the fcoe_transport structure and
introduce a new structure containing the mapping of fcoe_transport &
netdev (fcoe_netdev_mapping), and a list of these structures
(fcoe_netdev list).

3. During fcoe_transport_create(), the lookup will be based on the
"drv_name" to fetch the fcoe_transport structure. The pointers to netdev
obtained from "if_name" and the fcoe_transport structure are saved in
'fcoe_netdev_mapping' and added to the 'fcoe_netdev' list.  Subsequent
destroy/disable/enable will lookup fcoe_netdev_list using netdev as the
key and obtain fcoe_transport structure, and call ft->destroy,
ft->disable and ft->enable.

Signed-off-by: Bhanu Prakash Gollapudi <[email protected]>
---
 drivers/scsi/fcoe/libfcoe.h           |    2 +-
 drivers/scsi/fcoe/libfcoe_transport.c |  200 ++++++++++++++++++++++++--------
 include/scsi/libfcoe.h                |   14 ++-
 3 files changed, 162 insertions(+), 54 deletions(-)

diff --git a/drivers/scsi/fcoe/libfcoe.h b/drivers/scsi/fcoe/libfcoe.h
index 21ff0bb..8289291 100644
--- a/drivers/scsi/fcoe/libfcoe.h
+++ b/drivers/scsi/fcoe/libfcoe.h
@@ -26,6 +26,6 @@ do {                                                  \
 #define LIBFCOE_TRANSPORT_DBG(fmt, args...)                            \
        LIBFCOE_CHECK_LOGGING(LIBFCOE_TRANSPORT_LOGGING,                \
                              printk(KERN_INFO "%s: " fmt,              \
-                             __func__, ##args);)
+                                    __func__, ##args);)
 
 #endif /* _FCOE_LIBFCOE_H_ */
diff --git a/drivers/scsi/fcoe/libfcoe_transport.c 
b/drivers/scsi/fcoe/libfcoe_transport.c
index 8fd29ea..03c1d2a 100644
--- a/drivers/scsi/fcoe/libfcoe_transport.c
+++ b/drivers/scsi/fcoe/libfcoe_transport.c
@@ -33,11 +33,13 @@ MODULE_LICENSE("GPL v2");
 static int fcoe_transport_create(const char *, struct kernel_param *);
 static int fcoe_transport_destroy(const char *, struct kernel_param *);
 static int fcoe_transport_show(char *buffer, const struct kernel_param *kp);
-static struct fcoe_transport *fcoe_transport_lookup(struct net_device *device);
+static struct fcoe_transport *fcoe_transport_lookup(const char *drv_name);
+static struct fcoe_transport *fcoe_netdev_map_lookup(struct net_device 
*device);
 static int fcoe_transport_enable(const char *, struct kernel_param *);
 static int fcoe_transport_disable(const char *, struct kernel_param *);
 
 static LIST_HEAD(fcoe_transports);
+static LIST_HEAD(fcoe_netdevs);
 static DEFINE_MUTEX(ft_mutex);
 
 unsigned int libfcoe_debug_logging;
@@ -71,40 +73,23 @@ module_param_call(disable, fcoe_transport_disable, NULL, 
NULL, S_IWUSR);
 __MODULE_PARM_TYPE(disable, "string");
 MODULE_PARM_DESC(disable, " Disables fcoe on a ethernet interface.");
 
-static struct net_device *fcoe_if_to_netdev(const char *buffer)
-{
-       char *cp;
-       char ifname[IFNAMSIZ + 2];
-
-       if (buffer) {
-               strlcpy(ifname, buffer, IFNAMSIZ);
-               cp = ifname + strlen(ifname);
-               while (--cp >= ifname && *cp == '\n')
-                       *cp = '\0';
-               return dev_get_by_name(&init_net, ifname);
-       }
-       return NULL;
-}
-
-
 /**
- * fcoe_transport_lookup - find an fcoe transport that supports the netdev
- * @ft: The fcoe transport to be attached
+ * fcoe_transport_lookup - find an fcoe transport that matches drv_name
  *
  * Returns : ptr to the fcoe transport that supports this netdev or NULL
  * if not found.
  *
  * The ft_mutex should be held when this is called
  */
-static struct fcoe_transport *fcoe_transport_lookup(struct net_device *netdev)
+static struct fcoe_transport *fcoe_transport_lookup(const char *drv_name)
 {
-       struct fcoe_transport *ft;
+       struct fcoe_transport *ft = NULL;
+
+       list_for_each_entry(ft, &fcoe_transports, list) {
+               if (strcmp(drv_name, ft->name) == 0)
+                       break;
+       }
 
-       list_for_each_entry(ft, &fcoe_transports, list)
-               if (ft->match && ft->match(netdev))
-                       goto ft_match;
-       ft = NULL;
-ft_match:
        return ft;
 }
 
@@ -121,17 +106,12 @@ int fcoe_transport_attach(struct fcoe_transport *ft)
        mutex_lock(&ft_mutex);
        if (ft->attached) {
                LIBFCOE_TRANSPORT_DBG("transport %s already attached\n",
-                       ft->name);
+                                      ft->name);
                rc = -EEXIST;
                goto out_attach;
        }
 
-       /* Add vendor specific transport to the head */
-       if (ft->is_vendor)
-               list_add(&ft->list, &fcoe_transports);
-       else
-               list_add_tail(&ft->list, &fcoe_transports);
-
+       list_add_tail(&ft->list, &fcoe_transports);
        ft->attached = true;
        LIBFCOE_TRANSPORT_DBG("attaching transport %s\n", ft->name);
 
@@ -197,12 +177,101 @@ static int __exit fcoe_transport_exit(void)
        mutex_lock(&ft_mutex);
        list_for_each_entry(ft, &fcoe_transports, list) {
                LIBFCOE_TRANSPORT_DBG("transport going away with "
-                       "attached transport %s\n", ft->name);
+                         "attached transport %s\n", ft->name);
        }
        mutex_unlock(&ft_mutex);
        return 0;
 }
 
+
+static int fcoe_add_netdev_mapping(struct net_device *netdev,
+                                       struct fcoe_transport *ft)
+{
+       struct fcoe_netdev_mapping *nm;
+
+       nm = kmalloc(sizeof(*nm), GFP_KERNEL);
+       if (!nm) {
+               printk(KERN_ERR "Unable to allocate netdev_mapping");
+               return -ENOMEM;
+       }
+
+       nm->netdev = netdev;
+       nm->ft = ft;
+
+       list_add(&nm->list, &fcoe_netdevs);
+       return 0;
+}
+
+
+static void fcoe_del_netdev_mapping(struct net_device *netdev)
+{
+       struct fcoe_netdev_mapping *nm = NULL, *tmp;
+
+       list_for_each_entry_safe(nm, tmp, &fcoe_netdevs, list) {
+               if (nm->netdev == netdev) {
+                       list_del(&nm->list);
+                       break;
+               }
+       }
+
+       kfree(nm);
+}
+
+
+/**
+ * fcoe_netdev_map_lookup - find the fcoe transport that matches the netdev on 
which
+ * it was created
+ *
+ * Returns : ptr to the fcoe transport that supports this netdev or NULL
+ * if not found.
+ *
+ * The ft_mutex should be held when this is called
+ */
+static struct fcoe_transport *fcoe_netdev_map_lookup(struct net_device *netdev)
+{
+       struct fcoe_transport *ft = NULL;
+       struct fcoe_netdev_mapping *nm;
+
+       list_for_each_entry(nm, &fcoe_netdevs, list) {
+               if (netdev == nm->netdev) {
+                       ft = nm->ft;
+                       break;
+               }
+       }
+
+       return ft;
+}
+
+int fcoe_parse_buffer(const char *buffer, char *ifname, char *drv_name)
+{
+       char copy[IFNAMSIZ * 2 + 2];
+       char *token;
+       char *index = copy;
+
+       strlcpy(copy, buffer, sizeof(copy));
+
+       /* Parse ifname */
+       token = strsep(&index, ":");
+       if (!token || !*token)
+               goto parse_fail;
+
+       strlcpy(ifname, token, IFNAMSIZ + 1);
+
+       /* Parse drv_name.
+        * strsep will handle the drv_name NULL case
+        */
+       token = strsep(&index, ":");
+       if (!token || !*token)
+               goto parse_fail;
+
+       strlcpy(drv_name, token, IFNAMSIZ + 1);
+
+       return 0;
+
+parse_fail:
+       return -1;
+}
+
 /**
  * fcoe_transport_create() - Create a fcoe interface
  * @buffer: The name of the Ethernet interface to create on
@@ -220,6 +289,10 @@ static int fcoe_transport_create(const char *buffer, 
struct kernel_param *kp)
        struct fcoe_transport *ft = NULL;
        enum fip_state fip_mode = (enum fip_state)(long)kp->arg;
 
+       /* Reserve extra space to not overflow in case the input is bad */
+       char ifname[IFNAMSIZ * 2 + 2];
+       char drv_name[IFNAMSIZ * 2 + 2];
+
        if (!mutex_trylock(&ft_mutex))
                return restart_syscall();
 
@@ -232,18 +305,24 @@ static int fcoe_transport_create(const char *buffer, 
struct kernel_param *kp)
        if (THIS_MODULE->state != MODULE_STATE_LIVE)
                goto out_nodev;
 #endif
-       /* TODO: module ref gets when transport gets registered */
-       netdev = fcoe_if_to_netdev(buffer);
+
+       if (fcoe_parse_buffer(buffer, ifname, drv_name))
+               goto out_nodev;
+
+       netdev = dev_get_by_name(&init_net, ifname);
        if (!netdev)
                goto out_nodev;
 
-       /* TODO: pass to transport */
-       ft = fcoe_transport_lookup(netdev);
+       ft = fcoe_transport_lookup(drv_name);
        if (!ft)
                goto out_putdev;
 
+       rc = fcoe_add_netdev_mapping(netdev, ft);
+       if (rc)
+               goto out_putdev;
+
        /* pass to transport create */
-       rc = ft->create(netdev, fip_mode);
+       rc = ft->create ? ft->create(netdev, fip_mode) : -ENODEV;
 
 out_putdev:
        dev_put(netdev);
@@ -273,6 +352,10 @@ static int fcoe_transport_destroy(const char *buffer, 
struct kernel_param *kp)
        struct net_device *netdev = NULL;
        struct fcoe_transport *ft = NULL;
 
+       /* Reserve extra space to not overflow in case the input is bad */
+       char ifname[IFNAMSIZ * 2 + 2];
+       char drv_name[IFNAMSIZ * 2 + 2];
+
        if (!mutex_trylock(&ft_mutex))
                return restart_syscall();
 
@@ -286,17 +369,20 @@ static int fcoe_transport_destroy(const char *buffer, 
struct kernel_param *kp)
                goto out_nodev;
 #endif
 
-       netdev = fcoe_if_to_netdev(buffer);
+       if (fcoe_parse_buffer(buffer, ifname, drv_name))
+               goto out_nodev;
+
+       netdev = dev_get_by_name(&init_net, ifname);
        if (!netdev)
                goto out_nodev;
 
-       /* TODO: pass to transport */
-       ft = fcoe_transport_lookup(netdev);
+       ft = fcoe_netdev_map_lookup(netdev);
        if (!ft)
                goto out_putdev;
 
-       /* pass to transport create */
-       rc = ft->destroy(netdev);
+       /* pass to transport destroy */
+       rc = ft->destroy ? ft->destroy(netdev) : -ENODEV;
+       fcoe_del_netdev_mapping(netdev);
 
 out_putdev:
        dev_put(netdev);
@@ -325,6 +411,10 @@ static int fcoe_transport_disable(const char *buffer, 
struct kernel_param *kp)
        struct net_device *netdev = NULL;
        struct fcoe_transport *ft = NULL;
 
+       /* Reserve extra space to not overflow in case the input is bad */
+       char ifname[IFNAMSIZ * 2 + 2];
+       char drv_name[IFNAMSIZ * 2 + 2];
+
        if (!mutex_trylock(&ft_mutex))
                return restart_syscall();
 
@@ -338,15 +428,18 @@ static int fcoe_transport_disable(const char *buffer, 
struct kernel_param *kp)
                goto out_nodev;
 #endif
 
-       netdev = fcoe_if_to_netdev(buffer);
+       if (fcoe_parse_buffer(buffer, ifname, drv_name))
+               goto out_nodev;
+
+       netdev = dev_get_by_name(&init_net, ifname);
        if (!netdev)
                goto out_nodev;
 
-       ft = fcoe_transport_lookup(netdev);
+       ft = fcoe_netdev_map_lookup(netdev);
        if (!ft)
                goto out_putdev;
 
-       rc = ft->disable(netdev);
+       rc = ft->disable ? ft->disable(netdev) : -ENODEV;
 
 out_putdev:
        dev_put(netdev);
@@ -370,6 +463,10 @@ static int fcoe_transport_enable(const char *buffer, 
struct kernel_param *kp)
        struct net_device *netdev = NULL;
        struct fcoe_transport *ft = NULL;
 
+       /* Reserve extra space to not overflow in case the input is bad */
+       char ifname[IFNAMSIZ * 2 + 2];
+       char drv_name[IFNAMSIZ * 2 + 2];
+
        if (!mutex_trylock(&ft_mutex))
                return restart_syscall();
 
@@ -383,15 +480,18 @@ static int fcoe_transport_enable(const char *buffer, 
struct kernel_param *kp)
                goto out_nodev;
 #endif
 
-       netdev = fcoe_if_to_netdev(buffer);
+       if (fcoe_parse_buffer(buffer, ifname, drv_name))
+               goto out_nodev;
+
+       netdev = dev_get_by_name(&init_net, ifname);
        if (!netdev)
                goto out_nodev;
 
-       ft = fcoe_transport_lookup(netdev);
+       ft = fcoe_netdev_map_lookup(netdev);
        if (!ft)
                goto out_putdev;
 
-       rc = ft->enable(netdev);
+       rc = ft->enable ? ft->enable(netdev) : -ENODEV;
 
 out_putdev:
        dev_put(netdev);
diff --git a/include/scsi/libfcoe.h b/include/scsi/libfcoe.h
index 79a64ec..3594f30 100644
--- a/include/scsi/libfcoe.h
+++ b/include/scsi/libfcoe.h
@@ -245,7 +245,6 @@ static inline bool is_fip_mode(struct fcoe_ctlr *fip)
 /* struct fcoe_transport - The FCoE transport interface
  * @name:      a vendor specific name for their FCoE transport driver
  * @attached:  whether this transport is already attached
- * @is_vendor: whether from vendor or the default Open-FCoE fcoe driver
  * @list:      list linkage to all attached transports
  * @match:     handler to allow the transport to match up a given netdev
  * @create:    handler to sysfs entry of create for FCoE instances
@@ -256,15 +255,24 @@ static inline bool is_fip_mode(struct fcoe_ctlr *fip)
 struct fcoe_transport {
        char name[IFNAMSIZ];
        bool attached;
-       bool is_vendor;
        struct list_head list;
-       bool (*match) (struct net_device *device);
        int (*create) (struct net_device *device, enum fip_state fip_mode);
        int (*destroy) (struct net_device *device);
        int (*enable) (struct net_device *device);
        int (*disable) (struct net_device *device);
 };
 
+
+/**
+ * struct netdev_list
+ * A mapping from netdevice to fcoe_transport
+ */
+struct fcoe_netdev_mapping {
+       struct list_head list;
+       struct net_device *netdev;
+       struct fcoe_transport *ft;
+};
+
 /* fcoe transports registration and deregistration */
 int fcoe_transport_attach(struct fcoe_transport *ft);
 int fcoe_transport_detach(struct fcoe_transport *ft);
-- 
1.7.0.6




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

Reply via email to