Showing error 1629

User: Jiri Slaby
Error type: Invalid Pointer Dereference
Error type description: A pointer which is invalid is being dereferenced
File location: drivers/isdn/mISDN/fsm.c
Line in file: 47
Project: Linux Kernel
Project version: 2.6.28
Tools: Smatch (1.59)
Entered: 2013-09-10 07:54:05 UTC


Source:

  1/*
  2 * finite state machine implementation
  3 *
  4 * Author       Karsten Keil <kkeil@novell.com>
  5 *
  6 * Thanks to    Jan den Ouden
  7 *              Fritz Elfert
  8 * Copyright 2008  by Karsten Keil <kkeil@novell.com>
  9 *
 10 * This program is free software; you can redistribute it and/or modify
 11 * it under the terms of the GNU General Public License version 2 as
 12 * published by the Free Software Foundation.
 13 *
 14 * This program is distributed in the hope that it will be useful,
 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 17 * GNU General Public License for more details.
 18 *
 19 */
 20
 21#include <linux/kernel.h>
 22#include <linux/slab.h>
 23#include <linux/module.h>
 24#include <linux/string.h>
 25#include "fsm.h"
 26
 27#define FSM_TIMER_DEBUG 0
 28
 29void
 30mISDN_FsmNew(struct Fsm *fsm,
 31       struct FsmNode *fnlist, int fncount)
 32{
 33        int i;
 34
 35        fsm->jumpmatrix = kzalloc(sizeof(FSMFNPTR) * fsm->state_count *
 36                fsm->event_count, GFP_KERNEL);
 37
 38        for (i = 0; i < fncount; i++)
 39                if ((fnlist[i].state >= fsm->state_count) ||
 40                    (fnlist[i].event >= fsm->event_count)) {
 41                        printk(KERN_ERR
 42                            "mISDN_FsmNew Error: %d st(%ld/%ld) ev(%ld/%ld)\n",
 43                            i, (long)fnlist[i].state, (long)fsm->state_count,
 44                            (long)fnlist[i].event, (long)fsm->event_count);
 45                } else
 46                        fsm->jumpmatrix[fsm->state_count * fnlist[i].event +
 47                            fnlist[i].state] = (FSMFNPTR) fnlist[i].routine;
 48}
 49EXPORT_SYMBOL(mISDN_FsmNew);
 50
 51void
 52mISDN_FsmFree(struct Fsm *fsm)
 53{
 54        kfree((void *) fsm->jumpmatrix);
 55}
 56EXPORT_SYMBOL(mISDN_FsmFree);
 57
 58int
 59mISDN_FsmEvent(struct FsmInst *fi, int event, void *arg)
 60{
 61        FSMFNPTR r;
 62
 63        if ((fi->state >= fi->fsm->state_count) ||
 64            (event >= fi->fsm->event_count)) {
 65                printk(KERN_ERR
 66                    "mISDN_FsmEvent Error st(%ld/%ld) ev(%d/%ld)\n",
 67                    (long)fi->state, (long)fi->fsm->state_count, event,
 68                    (long)fi->fsm->event_count);
 69                return 1;
 70        }
 71        r = fi->fsm->jumpmatrix[fi->fsm->state_count * event + fi->state];
 72        if (r) {
 73                if (fi->debug)
 74                        fi->printdebug(fi, "State %s Event %s",
 75                                fi->fsm->strState[fi->state],
 76                                fi->fsm->strEvent[event]);
 77                r(fi, event, arg);
 78                return 0;
 79        } else {
 80                if (fi->debug)
 81                        fi->printdebug(fi, "State %s Event %s no action",
 82                                fi->fsm->strState[fi->state],
 83                                fi->fsm->strEvent[event]);
 84                return 1;
 85        }
 86}
 87EXPORT_SYMBOL(mISDN_FsmEvent);
 88
 89void
 90mISDN_FsmChangeState(struct FsmInst *fi, int newstate)
 91{
 92        fi->state = newstate;
 93        if (fi->debug)
 94                fi->printdebug(fi, "ChangeState %s",
 95                        fi->fsm->strState[newstate]);
 96}
 97EXPORT_SYMBOL(mISDN_FsmChangeState);
 98
 99static void
100FsmExpireTimer(struct FsmTimer *ft)
101{
102#if FSM_TIMER_DEBUG
103        if (ft->fi->debug)
104                ft->fi->printdebug(ft->fi, "FsmExpireTimer %lx", (long) ft);
105#endif
106        mISDN_FsmEvent(ft->fi, ft->event, ft->arg);
107}
108
109void
110mISDN_FsmInitTimer(struct FsmInst *fi, struct FsmTimer *ft)
111{
112        ft->fi = fi;
113        ft->tl.function = (void *) FsmExpireTimer;
114        ft->tl.data = (long) ft;
115#if FSM_TIMER_DEBUG
116        if (ft->fi->debug)
117                ft->fi->printdebug(ft->fi, "mISDN_FsmInitTimer %lx", (long) ft);
118#endif
119        init_timer(&ft->tl);
120}
121EXPORT_SYMBOL(mISDN_FsmInitTimer);
122
123void
124mISDN_FsmDelTimer(struct FsmTimer *ft, int where)
125{
126#if FSM_TIMER_DEBUG
127        if (ft->fi->debug)
128                ft->fi->printdebug(ft->fi, "mISDN_FsmDelTimer %lx %d",
129                        (long) ft, where);
130#endif
131        del_timer(&ft->tl);
132}
133EXPORT_SYMBOL(mISDN_FsmDelTimer);
134
135int
136mISDN_FsmAddTimer(struct FsmTimer *ft,
137            int millisec, int event, void *arg, int where)
138{
139
140#if FSM_TIMER_DEBUG
141        if (ft->fi->debug)
142                ft->fi->printdebug(ft->fi, "mISDN_FsmAddTimer %lx %d %d",
143                        (long) ft, millisec, where);
144#endif
145
146        if (timer_pending(&ft->tl)) {
147                if (ft->fi->debug) {
148                        printk(KERN_WARNING
149                                "mISDN_FsmAddTimer: timer already active!\n");
150                        ft->fi->printdebug(ft->fi,
151                                "mISDN_FsmAddTimer already active!");
152                }
153                return -1;
154        }
155        init_timer(&ft->tl);
156        ft->event = event;
157        ft->arg = arg;
158        ft->tl.expires = jiffies + (millisec * HZ) / 1000;
159        add_timer(&ft->tl);
160        return 0;
161}
162EXPORT_SYMBOL(mISDN_FsmAddTimer);
163
164void
165mISDN_FsmRestartTimer(struct FsmTimer *ft,
166            int millisec, int event, void *arg, int where)
167{
168
169#if FSM_TIMER_DEBUG
170        if (ft->fi->debug)
171                ft->fi->printdebug(ft->fi, "mISDN_FsmRestartTimer %lx %d %d",
172                        (long) ft, millisec, where);
173#endif
174
175        if (timer_pending(&ft->tl))
176                del_timer(&ft->tl);
177        init_timer(&ft->tl);
178        ft->event = event;
179        ft->arg = arg;
180        ft->tl.expires = jiffies + (millisec * HZ) / 1000;
181        add_timer(&ft->tl);
182}
183EXPORT_SYMBOL(mISDN_FsmRestartTimer);