/*
 * Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved.
 * Copyright (c) 2007, 2008 Mellanox Technologies. All rights reserved.
 *
 * This software is available to you under a choice of one of two
 * licenses.  You may choose to be licensed under the terms of the GNU
 * General Public License (GPL) Version 2, available from the file
 * COPYING in the main directory of this source tree, or the
 * OpenIB.org BSD license below:
 *
 *     Redistribution and use in source and binary forms, with or
 *     without modification, are permitted provided that the following
 *     conditions are met:
 *
 *      - Redistributions of source code must retain the above
 *        copyright notice, this list of conditions and the following
 *        disclaimer.
 *
 *      - Redistributions in binary form must reproduce the above
 *        copyright notice, this list of conditions and the following
 *        disclaimer in the documentation and/or other materials
 *        provided with the distribution.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include <linux/slab.h>
#include <linux/export.h>
#include <linux/errno.h>

#include "mlx4.h"

struct mlx4_device_context {
	struct list_head	list;
	struct list_head	bond_list;
	struct mlx4_interface  *intf;
	void		       *context;
};

static LIST_HEAD(intf_list);
static LIST_HEAD(dev_list);
static DEFINE_MUTEX(intf_mutex);

static void mlx4_add_device(struct mlx4_interface *intf, struct mlx4_priv *priv)
{
	struct mlx4_device_context *dev_ctx;

	dev_ctx = kmalloc(sizeof *dev_ctx, GFP_KERNEL);
	if (!dev_ctx)
		return;

	dev_ctx->intf    = intf;
	dev_ctx->context = intf->add(&priv->dev);

	if (dev_ctx->context) {
		spin_lock_irq(&priv->ctx_lock);
		list_add_tail(&dev_ctx->list, &priv->ctx_list);
		spin_unlock_irq(&priv->ctx_lock);
	} else
		kfree(dev_ctx);
}

static void mlx4_remove_device(struct mlx4_interface *intf, struct mlx4_priv *priv)
{
	struct mlx4_device_context *dev_ctx;

	list_for_each_entry(dev_ctx, &priv->ctx_list, list)
		if (dev_ctx->intf == intf) {
			spin_lock_irq(&priv->ctx_lock);
			list_del(&dev_ctx->list);
			spin_unlock_irq(&priv->ctx_lock);

			intf->remove(&priv->dev, dev_ctx->context);
			kfree(dev_ctx);
			return;
		}
}

int mlx4_register_interface(struct mlx4_interface *intf)
{
	struct mlx4_priv *priv;

	if (!intf->add || !intf->remove)
		return -EINVAL;

	mutex_lock(&intf_mutex);

	list_add_tail(&intf->list, &intf_list);
	list_for_each_entry(priv, &dev_list, dev_list) {
		if (mlx4_is_mfunc(&priv->dev) && (intf->flags & MLX4_INTFF_BONDING)) {
			mlx4_dbg(&priv->dev,
				 "SRIOV, disabling HA mode for intf proto %d\n", intf->protocol);
			intf->flags &= ~MLX4_INTFF_BONDING;
		}
		mlx4_add_device(intf, priv);
	}

	mutex_unlock(&intf_mutex);

	return 0;
}
EXPORT_SYMBOL_GPL(mlx4_register_interface);

void mlx4_unregister_interface(struct mlx4_interface *intf)
{
	struct mlx4_priv *priv;

	mutex_lock(&intf_mutex);

	list_for_each_entry(priv, &dev_list, dev_list)
		mlx4_remove_device(intf, priv);

	list_del(&intf->list);

	mutex_unlock(&intf_mutex);
}
EXPORT_SYMBOL_GPL(mlx4_unregister_interface);

int mlx4_do_bond(struct mlx4_dev *dev, bool enable)
{
	struct mlx4_priv *priv = mlx4_priv(dev);
	struct mlx4_device_context *dev_ctx = NULL, *temp_dev_ctx;
	unsigned long flags;
	int ret;
	LIST_HEAD(bond_list);

	if (!(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_PORT_REMAP))
		return -ENOTSUPP;

	ret = mlx4_disable_rx_port_check(dev, enable);
	if (ret) {
		mlx4_err(dev, "Fail to %s rx port check\n",
			 enable ? "enable" : "disable");
		return ret;
	}
	if (enable) {
		dev->flags |= MLX4_FLAG_BONDED;
	} else {
		 ret = mlx4_virt2phy_port_map(dev, 1, 2);
		if (ret) {
			mlx4_err(dev, "Fail to reset port map\n");
			return ret;
		}
		dev->flags &= ~MLX4_FLAG_BONDED;
	}

	spin_lock_irqsave(&priv->ctx_lock, flags);
	list_for_each_entry_safe(dev_ctx, temp_dev_ctx, &priv->ctx_list, list) {
		if (dev_ctx->intf->flags & MLX4_INTFF_BONDING) {
			list_add_tail(&dev_ctx->bond_list, &bond_list);
			list_del(&dev_ctx->list);
		}
	}
	spin_unlock_irqrestore(&priv->ctx_lock, flags);

	list_for_each_entry(dev_ctx, &bond_list, bond_list) {
		dev_ctx->intf->remove(dev, dev_ctx->context);
		dev_ctx->context =  dev_ctx->intf->add(dev);

		spin_lock_irqsave(&priv->ctx_lock, flags);
		list_add_tail(&dev_ctx->list, &priv->ctx_list);
		spin_unlock_irqrestore(&priv->ctx_lock, flags);

		mlx4_dbg(dev, "Inrerface for protocol %d restarted with when bonded mode is %s\n",
			 dev_ctx->intf->protocol, enable ?
			 "enabled" : "disabled");
	}
	return 0;
}

void mlx4_dispatch_event(struct mlx4_dev *dev, enum mlx4_dev_event type,
			 unsigned long param)
{
	struct mlx4_priv *priv = mlx4_priv(dev);
	struct mlx4_device_context *dev_ctx;
	unsigned long flags;

	spin_lock_irqsave(&priv->ctx_lock, flags);

	list_for_each_entry(dev_ctx, &priv->ctx_list, list)
		if (dev_ctx->intf->event)
			dev_ctx->intf->event(dev, dev_ctx->context, type, param);

	spin_unlock_irqrestore(&priv->ctx_lock, flags);
}

int mlx4_register_device(struct mlx4_dev *dev)
{
	struct mlx4_priv *priv = mlx4_priv(dev);
	struct mlx4_interface *intf;

	mutex_lock(&intf_mutex);

	dev->persist->interface_state |= MLX4_INTERFACE_STATE_UP;
	list_add_tail(&priv->dev_list, &dev_list);
	list_for_each_entry(intf, &intf_list, list)
		mlx4_add_device(intf, priv);

	mutex_unlock(&intf_mutex);
	mlx4_start_catas_poll(dev);

	return 0;
}

void mlx4_unregister_device(struct mlx4_dev *dev)
{
	struct mlx4_priv *priv = mlx4_priv(dev);
	struct mlx4_interface *intf;

	mlx4_stop_catas_poll(dev);
	mutex_lock(&intf_mutex);

	list_for_each_entry(intf, &intf_list, list)
		mlx4_remove_device(intf, priv);

	list_del(&priv->dev_list);
	dev->persist->interface_state &= ~MLX4_INTERFACE_STATE_UP;

	mutex_unlock(&intf_mutex);
}

void *mlx4_get_protocol_dev(struct mlx4_dev *dev, enum mlx4_protocol proto, int port)
{
	struct mlx4_priv *priv = mlx4_priv(dev);
	struct mlx4_device_context *dev_ctx;
	unsigned long flags;
	void *result = NULL;

	spin_lock_irqsave(&priv->ctx_lock, flags);

	list_for_each_entry(dev_ctx, &priv->ctx_list, list)
		if (dev_ctx->intf->protocol == proto && dev_ctx->intf->get_dev) {
			result = dev_ctx->intf->get_dev(dev, dev_ctx->context, port);
			break;
		}

	spin_unlock_irqrestore(&priv->ctx_lock, flags);

	return result;
}
EXPORT_SYMBOL_GPL(mlx4_get_protocol_dev);
