summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/mellanox/mlxsw/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/mellanox/mlxsw/core.c')
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/core.c223
1 files changed, 42 insertions, 181 deletions
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c
index a4c07841aaf6..affe84eb4bff 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core.c
@@ -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);
}