OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [net/] [mlx4/] [catas.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
3
 *
4
 * This software is available to you under a choice of one of two
5
 * licenses.  You may choose to be licensed under the terms of the GNU
6
 * General Public License (GPL) Version 2, available from the file
7
 * COPYING in the main directory of this source tree, or the
8
 * OpenIB.org BSD license below:
9
 *
10
 *     Redistribution and use in source and binary forms, with or
11
 *     without modification, are permitted provided that the following
12
 *     conditions are met:
13
 *
14
 *      - Redistributions of source code must retain the above
15
 *        copyright notice, this list of conditions and the following
16
 *        disclaimer.
17
 *
18
 *      - Redistributions in binary form must reproduce the above
19
 *        copyright notice, this list of conditions and the following
20
 *        disclaimer in the documentation and/or other materials
21
 *        provided with the distribution.
22
 *
23
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30
 * SOFTWARE.
31
 */
32
 
33
#include <linux/workqueue.h>
34
 
35
#include "mlx4.h"
36
 
37
enum {
38
        MLX4_CATAS_POLL_INTERVAL        = 5 * HZ,
39
};
40
 
41
static DEFINE_SPINLOCK(catas_lock);
42
 
43
static LIST_HEAD(catas_list);
44
static struct workqueue_struct *catas_wq;
45
static struct work_struct catas_work;
46
 
47
static int internal_err_reset = 1;
48
module_param(internal_err_reset, int, 0644);
49
MODULE_PARM_DESC(internal_err_reset,
50
                 "Reset device on internal errors if non-zero (default 1)");
51
 
52
static void dump_err_buf(struct mlx4_dev *dev)
53
{
54
        struct mlx4_priv *priv = mlx4_priv(dev);
55
 
56
        int i;
57
 
58
        mlx4_err(dev, "Internal error detected:\n");
59
        for (i = 0; i < priv->fw.catas_size; ++i)
60
                mlx4_err(dev, "  buf[%02x]: %08x\n",
61
                         i, swab32(readl(priv->catas_err.map + i)));
62
}
63
 
64
static void poll_catas(unsigned long dev_ptr)
65
{
66
        struct mlx4_dev *dev = (struct mlx4_dev *) dev_ptr;
67
        struct mlx4_priv *priv = mlx4_priv(dev);
68
 
69
        if (readl(priv->catas_err.map)) {
70
                dump_err_buf(dev);
71
 
72
                mlx4_dispatch_event(dev, MLX4_EVENT_TYPE_LOCAL_CATAS_ERROR, 0, 0);
73
 
74
                if (internal_err_reset) {
75
                        spin_lock(&catas_lock);
76
                        list_add(&priv->catas_err.list, &catas_list);
77
                        spin_unlock(&catas_lock);
78
 
79
                        queue_work(catas_wq, &catas_work);
80
                }
81
        } else
82
                mod_timer(&priv->catas_err.timer,
83
                          round_jiffies(jiffies + MLX4_CATAS_POLL_INTERVAL));
84
}
85
 
86
static void catas_reset(struct work_struct *work)
87
{
88
        struct mlx4_priv *priv, *tmppriv;
89
        struct mlx4_dev *dev;
90
 
91
        LIST_HEAD(tlist);
92
        int ret;
93
 
94
        spin_lock_irq(&catas_lock);
95
        list_splice_init(&catas_list, &tlist);
96
        spin_unlock_irq(&catas_lock);
97
 
98
        list_for_each_entry_safe(priv, tmppriv, &tlist, catas_err.list) {
99
                ret = mlx4_restart_one(priv->dev.pdev);
100
                dev = &priv->dev;
101
                if (ret)
102
                        mlx4_err(dev, "Reset failed (%d)\n", ret);
103
                else
104
                        mlx4_dbg(dev, "Reset succeeded\n");
105
        }
106
}
107
 
108
void mlx4_start_catas_poll(struct mlx4_dev *dev)
109
{
110
        struct mlx4_priv *priv = mlx4_priv(dev);
111
        unsigned long addr;
112
 
113
        INIT_LIST_HEAD(&priv->catas_err.list);
114
        init_timer(&priv->catas_err.timer);
115
        priv->catas_err.map = NULL;
116
 
117
        addr = pci_resource_start(dev->pdev, priv->fw.catas_bar) +
118
                priv->fw.catas_offset;
119
 
120
        priv->catas_err.map = ioremap(addr, priv->fw.catas_size * 4);
121
        if (!priv->catas_err.map) {
122
                mlx4_warn(dev, "Failed to map internal error buffer at 0x%lx\n",
123
                          addr);
124
                return;
125
        }
126
 
127
        priv->catas_err.timer.data     = (unsigned long) dev;
128
        priv->catas_err.timer.function = poll_catas;
129
        priv->catas_err.timer.expires  =
130
                round_jiffies(jiffies + MLX4_CATAS_POLL_INTERVAL);
131
        add_timer(&priv->catas_err.timer);
132
}
133
 
134
void mlx4_stop_catas_poll(struct mlx4_dev *dev)
135
{
136
        struct mlx4_priv *priv = mlx4_priv(dev);
137
 
138
        del_timer_sync(&priv->catas_err.timer);
139
 
140
        if (priv->catas_err.map)
141
                iounmap(priv->catas_err.map);
142
 
143
        spin_lock_irq(&catas_lock);
144
        list_del(&priv->catas_err.list);
145
        spin_unlock_irq(&catas_lock);
146
}
147
 
148
int __init mlx4_catas_init(void)
149
{
150
        INIT_WORK(&catas_work, catas_reset);
151
 
152
        catas_wq = create_singlethread_workqueue("mlx4_err");
153
        if (!catas_wq)
154
                return -ENOMEM;
155
 
156
        return 0;
157
}
158
 
159
void mlx4_catas_cleanup(void)
160
{
161
        destroy_workqueue(catas_wq);
162
}

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.