catas.c

来自「linux 内核源代码」· C语言 代码 · 共 163 行

C
163
字号
/* * Copyright (c) 2007 Cisco Systems, Inc. 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/workqueue.h>#include "mlx4.h"enum {	MLX4_CATAS_POLL_INTERVAL	= 5 * HZ,};static DEFINE_SPINLOCK(catas_lock);static LIST_HEAD(catas_list);static struct workqueue_struct *catas_wq;static struct work_struct catas_work;static int internal_err_reset = 1;module_param(internal_err_reset, int, 0644);MODULE_PARM_DESC(internal_err_reset,		 "Reset device on internal errors if non-zero (default 1)");static void dump_err_buf(struct mlx4_dev *dev){	struct mlx4_priv *priv = mlx4_priv(dev);	int i;	mlx4_err(dev, "Internal error detected:\n");	for (i = 0; i < priv->fw.catas_size; ++i)		mlx4_err(dev, "  buf[%02x]: %08x\n",			 i, swab32(readl(priv->catas_err.map + i)));}static void poll_catas(unsigned long dev_ptr){	struct mlx4_dev *dev = (struct mlx4_dev *) dev_ptr;	struct mlx4_priv *priv = mlx4_priv(dev);	if (readl(priv->catas_err.map)) {		dump_err_buf(dev);		mlx4_dispatch_event(dev, MLX4_EVENT_TYPE_LOCAL_CATAS_ERROR, 0, 0);		if (internal_err_reset) {			spin_lock(&catas_lock);			list_add(&priv->catas_err.list, &catas_list);			spin_unlock(&catas_lock);			queue_work(catas_wq, &catas_work);		}	} else		mod_timer(&priv->catas_err.timer,			  round_jiffies(jiffies + MLX4_CATAS_POLL_INTERVAL));}static void catas_reset(struct work_struct *work){	struct mlx4_priv *priv, *tmppriv;	struct mlx4_dev *dev;	LIST_HEAD(tlist);	int ret;	spin_lock_irq(&catas_lock);	list_splice_init(&catas_list, &tlist);	spin_unlock_irq(&catas_lock);	list_for_each_entry_safe(priv, tmppriv, &tlist, catas_err.list) {		ret = mlx4_restart_one(priv->dev.pdev);		dev = &priv->dev;		if (ret)			mlx4_err(dev, "Reset failed (%d)\n", ret);		else			mlx4_dbg(dev, "Reset succeeded\n");	}}void mlx4_start_catas_poll(struct mlx4_dev *dev){	struct mlx4_priv *priv = mlx4_priv(dev);	unsigned long addr;	INIT_LIST_HEAD(&priv->catas_err.list);	init_timer(&priv->catas_err.timer);	priv->catas_err.map = NULL;	addr = pci_resource_start(dev->pdev, priv->fw.catas_bar) +		priv->fw.catas_offset;	priv->catas_err.map = ioremap(addr, priv->fw.catas_size * 4);	if (!priv->catas_err.map) {		mlx4_warn(dev, "Failed to map internal error buffer at 0x%lx\n",			  addr);		return;	}	priv->catas_err.timer.data     = (unsigned long) dev;	priv->catas_err.timer.function = poll_catas;	priv->catas_err.timer.expires  =		round_jiffies(jiffies + MLX4_CATAS_POLL_INTERVAL);	add_timer(&priv->catas_err.timer);}void mlx4_stop_catas_poll(struct mlx4_dev *dev){	struct mlx4_priv *priv = mlx4_priv(dev);	del_timer_sync(&priv->catas_err.timer);	if (priv->catas_err.map)		iounmap(priv->catas_err.map);	spin_lock_irq(&catas_lock);	list_del(&priv->catas_err.list);	spin_unlock_irq(&catas_lock);}int __init mlx4_catas_init(void){	INIT_WORK(&catas_work, catas_reset);	catas_wq = create_singlethread_workqueue("mlx4_err");	if (!catas_wq)		return -ENOMEM;	return 0;}void mlx4_catas_cleanup(void){	destroy_workqueue(catas_wq);}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?