]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/net/ethernet/mellanox/mlxsw/core.c
Merge tag 'powerpc-4.12-2' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc...
[karo-tx-linux.git] / drivers / net / ethernet / mellanox / mlxsw / core.c
index a4c07841aaf6254c844eb8d8512687b447928ba8..affe84eb4bff5717e5ddba4835395a8a8989f8ca 100644 (file)
@@ -40,9 +40,6 @@
 #include <linux/export.h>
 #include <linux/err.h>
 #include <linux/if_link.h>
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-#include <linux/u64_stats_sync.h>
 #include <linux/netdevice.h>
 #include <linux/completion.h>
 #include <linux/skbuff.h>
@@ -74,23 +71,9 @@ static DEFINE_SPINLOCK(mlxsw_core_driver_list_lock);
 
 static const char mlxsw_core_driver_name[] = "mlxsw_core";
 
-static struct dentry *mlxsw_core_dbg_root;
-
 static struct workqueue_struct *mlxsw_wq;
 static struct workqueue_struct *mlxsw_owq;
 
-struct mlxsw_core_pcpu_stats {
-       u64                     trap_rx_packets[MLXSW_TRAP_ID_MAX];
-       u64                     trap_rx_bytes[MLXSW_TRAP_ID_MAX];
-       u64                     port_rx_packets[MLXSW_PORT_MAX_PORTS];
-       u64                     port_rx_bytes[MLXSW_PORT_MAX_PORTS];
-       struct u64_stats_sync   syncp;
-       u32                     trap_rx_dropped[MLXSW_TRAP_ID_MAX];
-       u32                     port_rx_dropped[MLXSW_PORT_MAX_PORTS];
-       u32                     trap_rx_invalid;
-       u32                     port_rx_invalid;
-};
-
 struct mlxsw_core_port {
        struct devlink_port devlink_port;
        void *port_driver_priv;
@@ -121,23 +104,48 @@ struct mlxsw_core {
                spinlock_t trans_list_lock; /* protects trans_list writes */
                bool use_emad;
        } emad;
-       struct mlxsw_core_pcpu_stats __percpu *pcpu_stats;
-       struct dentry *dbg_dir;
-       struct {
-               struct debugfs_blob_wrapper vsd_blob;
-               struct debugfs_blob_wrapper psid_blob;
-       } dbg;
        struct {
                u8 *mapping; /* lag_id+port_index to local_port mapping */
        } lag;
        struct mlxsw_res res;
        struct mlxsw_hwmon *hwmon;
        struct mlxsw_thermal *thermal;
-       struct mlxsw_core_port ports[MLXSW_PORT_MAX_PORTS];
+       struct mlxsw_core_port *ports;
+       unsigned int max_ports;
        unsigned long driver_priv[0];
        /* driver_priv has to be always the last item */
 };
 
+#define MLXSW_PORT_MAX_PORTS_DEFAULT   0x40
+
+static int mlxsw_ports_init(struct mlxsw_core *mlxsw_core)
+{
+       /* Switch ports are numbered from 1 to queried value */
+       if (MLXSW_CORE_RES_VALID(mlxsw_core, MAX_SYSTEM_PORT))
+               mlxsw_core->max_ports = MLXSW_CORE_RES_GET(mlxsw_core,
+                                                          MAX_SYSTEM_PORT) + 1;
+       else
+               mlxsw_core->max_ports = MLXSW_PORT_MAX_PORTS_DEFAULT + 1;
+
+       mlxsw_core->ports = kcalloc(mlxsw_core->max_ports,
+                                   sizeof(struct mlxsw_core_port), GFP_KERNEL);
+       if (!mlxsw_core->ports)
+               return -ENOMEM;
+
+       return 0;
+}
+
+static void mlxsw_ports_fini(struct mlxsw_core *mlxsw_core)
+{
+       kfree(mlxsw_core->ports);
+}
+
+unsigned int mlxsw_core_max_ports(const struct mlxsw_core *mlxsw_core)
+{
+       return mlxsw_core->max_ports;
+}
+EXPORT_SYMBOL(mlxsw_core_max_ports);
+
 void *mlxsw_core_driver_priv(struct mlxsw_core *mlxsw_core)
 {
        return mlxsw_core->driver_priv;
@@ -703,91 +711,6 @@ err_out:
  * Core functions
  *****************/
 
-static int mlxsw_core_rx_stats_dbg_read(struct seq_file *file, void *data)
-{
-       struct mlxsw_core *mlxsw_core = file->private;
-       struct mlxsw_core_pcpu_stats *p;
-       u64 rx_packets, rx_bytes;
-       u64 tmp_rx_packets, tmp_rx_bytes;
-       u32 rx_dropped, rx_invalid;
-       unsigned int start;
-       int i;
-       int j;
-       static const char hdr[] =
-               "     NUM   RX_PACKETS     RX_BYTES RX_DROPPED\n";
-
-       seq_printf(file, hdr);
-       for (i = 0; i < MLXSW_TRAP_ID_MAX; i++) {
-               rx_packets = 0;
-               rx_bytes = 0;
-               rx_dropped = 0;
-               for_each_possible_cpu(j) {
-                       p = per_cpu_ptr(mlxsw_core->pcpu_stats, j);
-                       do {
-                               start = u64_stats_fetch_begin(&p->syncp);
-                               tmp_rx_packets = p->trap_rx_packets[i];
-                               tmp_rx_bytes = p->trap_rx_bytes[i];
-                       } while (u64_stats_fetch_retry(&p->syncp, start));
-
-                       rx_packets += tmp_rx_packets;
-                       rx_bytes += tmp_rx_bytes;
-                       rx_dropped += p->trap_rx_dropped[i];
-               }
-               seq_printf(file, "trap %3d %12llu %12llu %10u\n",
-                          i, rx_packets, rx_bytes, rx_dropped);
-       }
-       rx_invalid = 0;
-       for_each_possible_cpu(j) {
-               p = per_cpu_ptr(mlxsw_core->pcpu_stats, j);
-               rx_invalid += p->trap_rx_invalid;
-       }
-       seq_printf(file, "trap INV                           %10u\n",
-                  rx_invalid);
-
-       for (i = 0; i < MLXSW_PORT_MAX_PORTS; i++) {
-               rx_packets = 0;
-               rx_bytes = 0;
-               rx_dropped = 0;
-               for_each_possible_cpu(j) {
-                       p = per_cpu_ptr(mlxsw_core->pcpu_stats, j);
-                       do {
-                               start = u64_stats_fetch_begin(&p->syncp);
-                               tmp_rx_packets = p->port_rx_packets[i];
-                               tmp_rx_bytes = p->port_rx_bytes[i];
-                       } while (u64_stats_fetch_retry(&p->syncp, start));
-
-                       rx_packets += tmp_rx_packets;
-                       rx_bytes += tmp_rx_bytes;
-                       rx_dropped += p->port_rx_dropped[i];
-               }
-               seq_printf(file, "port %3d %12llu %12llu %10u\n",
-                          i, rx_packets, rx_bytes, rx_dropped);
-       }
-       rx_invalid = 0;
-       for_each_possible_cpu(j) {
-               p = per_cpu_ptr(mlxsw_core->pcpu_stats, j);
-               rx_invalid += p->port_rx_invalid;
-       }
-       seq_printf(file, "port INV                           %10u\n",
-                  rx_invalid);
-       return 0;
-}
-
-static int mlxsw_core_rx_stats_dbg_open(struct inode *inode, struct file *f)
-{
-       struct mlxsw_core *mlxsw_core = inode->i_private;
-
-       return single_open(f, mlxsw_core_rx_stats_dbg_read, mlxsw_core);
-}
-
-static const struct file_operations mlxsw_core_rx_stats_dbg_ops = {
-       .owner = THIS_MODULE,
-       .open = mlxsw_core_rx_stats_dbg_open,
-       .release = single_release,
-       .read = seq_read,
-       .llseek = seq_lseek
-};
-
 int mlxsw_core_driver_register(struct mlxsw_driver *mlxsw_driver)
 {
        spin_lock(&mlxsw_core_driver_list_lock);
@@ -835,39 +758,13 @@ static void mlxsw_core_driver_put(const char *kind)
        spin_unlock(&mlxsw_core_driver_list_lock);
 }
 
-static int mlxsw_core_debugfs_init(struct mlxsw_core *mlxsw_core)
-{
-       const struct mlxsw_bus_info *bus_info = mlxsw_core->bus_info;
-
-       mlxsw_core->dbg_dir = debugfs_create_dir(bus_info->device_name,
-                                                mlxsw_core_dbg_root);
-       if (!mlxsw_core->dbg_dir)
-               return -ENOMEM;
-       debugfs_create_file("rx_stats", S_IRUGO, mlxsw_core->dbg_dir,
-                           mlxsw_core, &mlxsw_core_rx_stats_dbg_ops);
-       mlxsw_core->dbg.vsd_blob.data = (void *) &bus_info->vsd;
-       mlxsw_core->dbg.vsd_blob.size = sizeof(bus_info->vsd);
-       debugfs_create_blob("vsd", S_IRUGO, mlxsw_core->dbg_dir,
-                           &mlxsw_core->dbg.vsd_blob);
-       mlxsw_core->dbg.psid_blob.data = (void *) &bus_info->psid;
-       mlxsw_core->dbg.psid_blob.size = sizeof(bus_info->psid);
-       debugfs_create_blob("psid", S_IRUGO, mlxsw_core->dbg_dir,
-                           &mlxsw_core->dbg.psid_blob);
-       return 0;
-}
-
-static void mlxsw_core_debugfs_fini(struct mlxsw_core *mlxsw_core)
-{
-       debugfs_remove_recursive(mlxsw_core->dbg_dir);
-}
-
 static int mlxsw_devlink_port_split(struct devlink *devlink,
                                    unsigned int port_index,
                                    unsigned int count)
 {
        struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
 
-       if (port_index >= MLXSW_PORT_MAX_PORTS)
+       if (port_index >= mlxsw_core->max_ports)
                return -EINVAL;
        if (!mlxsw_core->driver->port_split)
                return -EOPNOTSUPP;
@@ -879,7 +776,7 @@ static int mlxsw_devlink_port_unsplit(struct devlink *devlink,
 {
        struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
 
-       if (port_index >= MLXSW_PORT_MAX_PORTS)
+       if (port_index >= mlxsw_core->max_ports)
                return -EINVAL;
        if (!mlxsw_core->driver->port_unsplit)
                return -EOPNOTSUPP;
@@ -1101,18 +998,15 @@ int mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info,
        mlxsw_core->bus_priv = bus_priv;
        mlxsw_core->bus_info = mlxsw_bus_info;
 
-       mlxsw_core->pcpu_stats =
-               netdev_alloc_pcpu_stats(struct mlxsw_core_pcpu_stats);
-       if (!mlxsw_core->pcpu_stats) {
-               err = -ENOMEM;
-               goto err_alloc_stats;
-       }
-
        err = mlxsw_bus->init(bus_priv, mlxsw_core, mlxsw_driver->profile,
                              &mlxsw_core->res);
        if (err)
                goto err_bus_init;
 
+       err = mlxsw_ports_init(mlxsw_core);
+       if (err)
+               goto err_ports_init;
+
        if (MLXSW_CORE_RES_VALID(mlxsw_core, MAX_LAG) &&
            MLXSW_CORE_RES_VALID(mlxsw_core, MAX_LAG_MEMBERS)) {
                alloc_size = sizeof(u8) *
@@ -1148,15 +1042,8 @@ int mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info,
                        goto err_driver_init;
        }
 
-       err = mlxsw_core_debugfs_init(mlxsw_core);
-       if (err)
-               goto err_debugfs_init;
-
        return 0;
 
-err_debugfs_init:
-       if (mlxsw_core->driver->fini)
-               mlxsw_core->driver->fini(mlxsw_core);
 err_driver_init:
        mlxsw_thermal_fini(mlxsw_core->thermal);
 err_thermal_init:
@@ -1167,10 +1054,10 @@ err_devlink_register:
 err_emad_init:
        kfree(mlxsw_core->lag.mapping);
 err_alloc_lag_mapping:
+       mlxsw_ports_fini(mlxsw_core);
+err_ports_init:
        mlxsw_bus->fini(bus_priv);
 err_bus_init:
-       free_percpu(mlxsw_core->pcpu_stats);
-err_alloc_stats:
        devlink_free(devlink);
 err_devlink_alloc:
        mlxsw_core_driver_put(device_kind);
@@ -1183,15 +1070,14 @@ void mlxsw_core_bus_device_unregister(struct mlxsw_core *mlxsw_core)
        const char *device_kind = mlxsw_core->bus_info->device_kind;
        struct devlink *devlink = priv_to_devlink(mlxsw_core);
 
-       mlxsw_core_debugfs_fini(mlxsw_core);
        if (mlxsw_core->driver->fini)
                mlxsw_core->driver->fini(mlxsw_core);
        mlxsw_thermal_fini(mlxsw_core->thermal);
        devlink_unregister(devlink);
        mlxsw_emad_fini(mlxsw_core);
        kfree(mlxsw_core->lag.mapping);
+       mlxsw_ports_fini(mlxsw_core);
        mlxsw_core->bus->fini(mlxsw_core->bus_priv);
-       free_percpu(mlxsw_core->pcpu_stats);
        devlink_free(devlink);
        mlxsw_core_driver_put(device_kind);
 }
@@ -1639,7 +1525,6 @@ void mlxsw_core_skb_receive(struct mlxsw_core *mlxsw_core, struct sk_buff *skb,
 {
        struct mlxsw_rx_listener_item *rxl_item;
        const struct mlxsw_rx_listener *rxl;
-       struct mlxsw_core_pcpu_stats *pcpu_stats;
        u8 local_port;
        bool found = false;
 
@@ -1661,7 +1546,7 @@ void mlxsw_core_skb_receive(struct mlxsw_core *mlxsw_core, struct sk_buff *skb,
                            __func__, local_port, rx_info->trap_id);
 
        if ((rx_info->trap_id >= MLXSW_TRAP_ID_MAX) ||
-           (local_port >= MLXSW_PORT_MAX_PORTS))
+           (local_port >= mlxsw_core->max_ports))
                goto drop;
 
        rcu_read_lock();
@@ -1678,26 +1563,10 @@ void mlxsw_core_skb_receive(struct mlxsw_core *mlxsw_core, struct sk_buff *skb,
        if (!found)
                goto drop;
 
-       pcpu_stats = this_cpu_ptr(mlxsw_core->pcpu_stats);
-       u64_stats_update_begin(&pcpu_stats->syncp);
-       pcpu_stats->port_rx_packets[local_port]++;
-       pcpu_stats->port_rx_bytes[local_port] += skb->len;
-       pcpu_stats->trap_rx_packets[rx_info->trap_id]++;
-       pcpu_stats->trap_rx_bytes[rx_info->trap_id] += skb->len;
-       u64_stats_update_end(&pcpu_stats->syncp);
-
        rxl->func(skb, local_port, rxl_item->priv);
        return;
 
 drop:
-       if (rx_info->trap_id >= MLXSW_TRAP_ID_MAX)
-               this_cpu_inc(mlxsw_core->pcpu_stats->trap_rx_invalid);
-       else
-               this_cpu_inc(mlxsw_core->pcpu_stats->trap_rx_dropped[rx_info->trap_id]);
-       if (local_port >= MLXSW_PORT_MAX_PORTS)
-               this_cpu_inc(mlxsw_core->pcpu_stats->port_rx_invalid);
-       else
-               this_cpu_inc(mlxsw_core->pcpu_stats->port_rx_dropped[local_port]);
        dev_kfree_skb(skb);
 }
 EXPORT_SYMBOL(mlxsw_core_skb_receive);
@@ -1926,15 +1795,8 @@ static int __init mlxsw_core_module_init(void)
                err = -ENOMEM;
                goto err_alloc_ordered_workqueue;
        }
-       mlxsw_core_dbg_root = debugfs_create_dir(mlxsw_core_driver_name, NULL);
-       if (!mlxsw_core_dbg_root) {
-               err = -ENOMEM;
-               goto err_debugfs_create_dir;
-       }
        return 0;
 
-err_debugfs_create_dir:
-       destroy_workqueue(mlxsw_owq);
 err_alloc_ordered_workqueue:
        destroy_workqueue(mlxsw_wq);
        return err;
@@ -1942,7 +1804,6 @@ err_alloc_ordered_workqueue:
 
 static void __exit mlxsw_core_module_exit(void)
 {
-       debugfs_remove_recursive(mlxsw_core_dbg_root);
        destroy_workqueue(mlxsw_owq);
        destroy_workqueue(mlxsw_wq);
 }