~ubuntu-branches/ubuntu/karmic/openipmi/karmic

« back to all changes in this revision

Viewing changes to lib/pet.c

  • Committer: Bazaar Package Importer
  • Author(s): Noèl Köthe
  • Date: 2005-07-04 21:29:17 UTC
  • Revision ID: james.westby@ubuntu.com-20050704212917-igddk5jawjmhrlay
Tags: upstream-2.0.1
Import upstream version 2.0.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * pet.c
 
3
 *
 
4
 * MontaVista IPMI code handling for setting up and receiving platform
 
5
 * event traps.
 
6
 *
 
7
 * Author: MontaVista Software, Inc.
 
8
 *         Corey Minyard <minyard@mvista.com>
 
9
 *         source@mvista.com
 
10
 *
 
11
 * Copyright 2004 MontaVista Software Inc.
 
12
 *
 
13
 *  This program is free software; you can redistribute it and/or
 
14
 *  modify it under the terms of the GNU Lesser General Public License
 
15
 *  as published by the Free Software Foundation; either version 2 of
 
16
 *  the License, or (at your option) any later version.
 
17
 *
 
18
 *
 
19
 *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
 
20
 *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 
21
 *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 
22
 *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 
23
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 
24
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 
25
 *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 
26
 *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
 
27
 *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 
28
 *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
29
 *
 
30
 *  You should have received a copy of the GNU Lesser General Public
 
31
 *  License along with this program; if not, write to the Free
 
32
 *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
33
 */
 
34
 
 
35
/* NOTE: This code requires scan_sysaddr to be set for the BMC
 
36
   connections. */
 
37
 
 
38
#include <sys/types.h>
 
39
#include <sys/socket.h>
 
40
#include <netinet/in.h>
 
41
#include <errno.h>
 
42
#include <unistd.h>
 
43
#include <string.h>
 
44
#include <stdio.h>
 
45
 
 
46
#include <OpenIPMI/os_handler.h>
 
47
#include <OpenIPMI/ipmi_err.h>
 
48
#include <OpenIPMI/ipmi_pet.h>
 
49
#include <OpenIPMI/ipmi_pef.h>
 
50
#include <OpenIPMI/ipmi_lanparm.h>
 
51
#include <OpenIPMI/ipmi_msgbits.h>
 
52
 
 
53
#include <OpenIPMI/internal/ipmi_int.h>
 
54
#include <OpenIPMI/internal/locked_list.h>
 
55
#include <OpenIPMI/internal/ipmi_domain.h>
 
56
#include <OpenIPMI/internal/ipmi_mc.h>
 
57
 
 
58
/* Recheck the PET config every 10 minutes. */
 
59
#define PET_TIMEOUT_SEC 600
 
60
 
 
61
/* Time between alert retries (in seconds). */
 
62
#define IPMI_LANPARM_DEFAULT_ALERT_RETRY_TIMEOUT 1
 
63
 
 
64
/* Alerts get retried this many times. */
 
65
#define IPMI_LANPARM_DEFAULT_ALERT_RETRIES 3
 
66
 
 
67
#define IPMI_PET_ATTR_NAME "ipmi_pet"
 
68
 
 
69
 
 
70
/* This data structure defines a data/mask setting for a parameter,
 
71
   either from the LAN or PEF parms. */
 
72
typedef struct parm_check_s
 
73
{
 
74
    unsigned char conf_num; /* The number we are interested in. */
 
75
    unsigned char set;      /* The specific selector. */
 
76
    unsigned char data_len; /* The length of the data we are using. */
 
77
    unsigned char data[22]; /* The actual data. */
 
78
    unsigned char mask[22]; /* The mask bits used to mask what we compare. */
 
79
} parm_check_t;
 
80
 
 
81
/* Information for running the timer.  Note that there is no lock in
 
82
   the timer, since the timer is only deleted when the pet_lock is
 
83
   held write, we read-lock the pet timer to avoid locking problem. */
 
84
typedef struct pet_timer_s {
 
85
    int          cancelled;
 
86
    int          running;
 
87
    os_handler_t *os_hnd;
 
88
    ipmi_lock_t  *lock; /* Lock is here because we need it in the timer. */
 
89
    ipmi_pet_t   *pet;
 
90
    int          err;
 
91
} pet_timer_t;
 
92
 
 
93
#define NUM_PEF_SETTINGS 4
 
94
#define NUM_LANPARM_SETTINGS 2
 
95
 
 
96
struct ipmi_pet_s
 
97
{
 
98
    int destroyed;
 
99
    int in_list;
 
100
 
 
101
    unsigned int refcount;
 
102
 
 
103
    char name[IPMI_PET_NAME_LEN];
 
104
 
 
105
    /* Configuration parameters */
 
106
    ipmi_mcid_t      mc;
 
107
    ipmi_domain_id_t domain;
 
108
    struct in_addr   ip_addr;
 
109
    char             mac_addr[6];
 
110
    unsigned int     policy_num;
 
111
    unsigned int     eft_sel;
 
112
    unsigned int     apt_sel;
 
113
    unsigned int     lan_dest_sel;
 
114
 
 
115
    unsigned int channel;
 
116
    ipmi_pet_t   *pet;
 
117
    int          pef_err;
 
118
    int          pef_lock_broken;
 
119
    int          lanparm_err;
 
120
    int          lanparm_lock_broken;
 
121
    int          changed_lanparm;
 
122
    int          changed_pef;
 
123
 
 
124
    int            lanparm_check_pos;
 
125
    ipmi_lanparm_t *lanparm;
 
126
 
 
127
    int          pef_check_pos;
 
128
    ipmi_pef_t   *pef;
 
129
 
 
130
    /* The domain's OS handler */
 
131
    os_handler_t     *os_hnd;
 
132
 
 
133
    ipmi_pet_done_cb done;
 
134
    void             *cb_data;
 
135
 
 
136
    ipmi_pet_done_cb destroy_done;
 
137
    void             *destroy_cb_data;
 
138
 
 
139
    int              in_progress;
 
140
 
 
141
    /* The LAN configuration parameters to check. */
 
142
    parm_check_t     lanparm_check[NUM_LANPARM_SETTINGS];
 
143
 
 
144
    /* The PEF configuration parameters to check */
 
145
    parm_check_t     pef_check[NUM_PEF_SETTINGS];
 
146
 
 
147
    /* Timer to check the configuration periodically. */
 
148
    pet_timer_t       *timer_info;
 
149
    os_hnd_timer_id_t *timer;
 
150
};
 
151
 
 
152
static void rescan_pet(void *cb_data, os_hnd_timer_id_t *id);
 
153
 
 
154
static void
 
155
pet_lock(ipmi_pet_t *pet)
 
156
{
 
157
    ipmi_lock(pet->timer_info->lock);
 
158
}
 
159
 
 
160
static void
 
161
pet_unlock(ipmi_pet_t *pet)
 
162
{
 
163
    ipmi_unlock(pet->timer_info->lock);
 
164
}
 
165
 
 
166
static void
 
167
internal_pet_destroy(ipmi_pet_t *pet)
 
168
{
 
169
    os_handler_t *os_hnd = pet->timer_info->os_hnd;
 
170
 
 
171
    if (pet->in_list) {
 
172
        ipmi_domain_attr_t *attr;
 
173
        locked_list_t      *pets;
 
174
        int                rv;
 
175
        rv = ipmi_domain_id_find_attribute(pet->domain,
 
176
                                           IPMI_PET_ATTR_NAME, &attr);
 
177
        if (!rv) {
 
178
            pet->refcount++;
 
179
            pet->in_list = 0;
 
180
            pet_unlock(pet);
 
181
        
 
182
            pets = ipmi_domain_attr_get_data(attr);
 
183
 
 
184
            locked_list_remove(pets, pet, NULL);
 
185
            ipmi_domain_attr_put(attr);
 
186
            pet_lock(pet);
 
187
            /* While we were unlocked, someone may have come in and
 
188
               grabbed the PET by iterating the list of PETs.  That's
 
189
               ok, we just let them handle the destruction since this
 
190
               code will not be entered again. */
 
191
            if (pet->refcount != 1) {
 
192
                pet->refcount--;
 
193
                pet_unlock(pet);
 
194
                return;
 
195
            }
 
196
        }
 
197
    }
 
198
    pet_unlock(pet);
 
199
 
 
200
    if (os_hnd->stop_timer(os_hnd, pet->timer) == 0) {
 
201
        ipmi_destroy_lock(pet->timer_info->lock);
 
202
        os_hnd->free_timer(os_hnd, pet->timer);
 
203
        ipmi_mem_free(pet->timer_info);
 
204
    } else {
 
205
        pet->timer_info->cancelled = 1;
 
206
    }
 
207
 
 
208
    if (pet->destroy_done) {
 
209
        pet->destroy_done(pet, 0, pet->destroy_cb_data);
 
210
    }
 
211
 
 
212
    ipmi_mem_free(pet);
 
213
}
 
214
 
 
215
static void
 
216
pet_get(ipmi_pet_t *pet)
 
217
{
 
218
    pet_lock(pet);
 
219
    pet->refcount++;
 
220
    pet_unlock(pet);
 
221
}
 
222
 
 
223
static void
 
224
pet_put(ipmi_pet_t *pet)
 
225
{
 
226
    pet_lock(pet);
 
227
    pet->refcount--;
 
228
    if (pet->refcount == 0) {
 
229
        internal_pet_destroy(pet);
 
230
        return;
 
231
    }
 
232
    pet_unlock(pet);
 
233
}
 
234
 
 
235
void
 
236
ipmi_pet_ref(ipmi_pet_t *pet)
 
237
{
 
238
    pet_get(pet);
 
239
}
 
240
 
 
241
void
 
242
ipmi_pet_deref(ipmi_pet_t *pet)
 
243
{
 
244
    pet_put(pet);
 
245
}
 
246
 
 
247
static int
 
248
pet_attr_init(ipmi_domain_t *domain, void *cb_data, void **data)
 
249
{
 
250
    locked_list_t *pets;
 
251
    
 
252
    pets = locked_list_alloc(ipmi_domain_get_os_hnd(domain));
 
253
    if (!pets)
 
254
        return ENOMEM;
 
255
 
 
256
    *data = pets;
 
257
    return 0;
 
258
}
 
259
 
 
260
static int
 
261
destroy_pet(void *cb_data, void *item1, void *item2)
 
262
{
 
263
    ipmi_pet_t *pet = item1;
 
264
 
 
265
    pet_lock(pet);
 
266
    pet->in_list = 0;
 
267
    pet_unlock(pet);
 
268
    return LOCKED_LIST_ITER_CONTINUE;
 
269
}
 
270
 
 
271
static void
 
272
pet_attr_destroy(void *cb_data, void *data)
 
273
{
 
274
    locked_list_t *pets = data;
 
275
 
 
276
    locked_list_iterate(pets, destroy_pet, NULL);
 
277
    locked_list_destroy(pets);
 
278
}
 
279
 
 
280
/* Must be called locked, this will unlock the PET. */
 
281
static void
 
282
pet_op_done(ipmi_pet_t *pet)
 
283
{
 
284
    struct timeval timeout;
 
285
    os_handler_t   *os_hnd = pet->os_hnd;
 
286
 
 
287
    pet->in_progress--;
 
288
 
 
289
    if (pet->in_progress == 0) {
 
290
        if (pet->lanparm) {
 
291
            ipmi_lanparm_destroy(pet->lanparm, NULL, NULL);
 
292
            pet->lanparm = NULL;
 
293
        }
 
294
 
 
295
        if (pet->done) {
 
296
            ipmi_pet_done_cb done = pet->done;
 
297
            void             *cb_data = pet->cb_data;
 
298
            pet->done = NULL;
 
299
            pet_unlock(pet);
 
300
            done(pet, 0, cb_data);
 
301
            pet_lock(pet);
 
302
        }
 
303
 
 
304
        if (pet->destroyed) {
 
305
            internal_pet_destroy(pet);
 
306
            return;
 
307
        }
 
308
 
 
309
        /* Restart the timer */
 
310
        timeout.tv_sec = PET_TIMEOUT_SEC;
 
311
        timeout.tv_usec = 0;
 
312
        os_hnd->start_timer(os_hnd, pet->timer, &timeout, rescan_pet,
 
313
                            pet->timer_info);
 
314
        pet->timer_info->running = 1;
 
315
 
 
316
    }
 
317
 
 
318
    pet_unlock(pet);
 
319
}
 
320
 
 
321
static void
 
322
lanparm_unlocked(ipmi_lanparm_t *lanparm,
 
323
                 int            err,
 
324
                 void           *cb_data)
 
325
{
 
326
    ipmi_pet_t *pet = cb_data;
 
327
 
 
328
    pet_lock(pet);
 
329
    ipmi_lanparm_destroy(pet->lanparm, NULL, NULL);
 
330
    pet->lanparm = NULL;
 
331
    pet_op_done(pet);
 
332
}
 
333
 
 
334
static void
 
335
lanparm_commited(ipmi_lanparm_t *lanparm,
 
336
                 int            err,
 
337
                 void           *cb_data)
 
338
{
 
339
    ipmi_pet_t    *pet = cb_data;
 
340
    int           rv;
 
341
    unsigned char data[1];
 
342
 
 
343
    pet_lock(pet);
 
344
    if (pet->destroyed) {
 
345
        pet_op_done(pet);
 
346
        goto out;
 
347
    }
 
348
 
 
349
    /* Ignore the error, committing is optional. */
 
350
 
 
351
    data[0] = 0; /* clear lock */
 
352
    rv = ipmi_lanparm_set_parm(pet->lanparm, 0, data, 1,
 
353
                           lanparm_unlocked, pet);
 
354
    if (rv) {
 
355
        ipmi_log(IPMI_LOG_WARNING,
 
356
                 "pet.c(lanparm_commited): error clearing lock: 0x%x", rv);
 
357
        ipmi_lanparm_destroy(pet->lanparm, NULL, NULL);
 
358
        pet->lanparm = NULL;
 
359
        pet_op_done(pet);
 
360
        goto out;
 
361
    }
 
362
    pet_unlock(pet);
 
363
 out:
 
364
    return;
 
365
}
 
366
 
 
367
/* Must be called locked, this will unlock the PET. */
 
368
static void
 
369
lanparm_op_done(ipmi_pet_t *pet, int err)
 
370
{
 
371
    int           rv;
 
372
 
 
373
    /* Cheap hack, -1 means stop. */
 
374
    if (err == -1)
 
375
        err = 0;
 
376
 
 
377
    pet->lanparm_err = err;
 
378
    if (pet->lanparm_lock_broken) {
 
379
        /* Locking is not supported. */
 
380
        pet_op_done(pet);
 
381
        goto out;
 
382
    } else {
 
383
        unsigned char data[1];
 
384
 
 
385
        if (!pet->lanparm_err && pet->changed_lanparm) {
 
386
            /* Don't commit if an error occurred. */
 
387
            data[0] = 2; /* commit */
 
388
            rv = ipmi_lanparm_set_parm(pet->lanparm, 0, data, 1,
 
389
                                       lanparm_commited, pet);
 
390
        } else {
 
391
            data[0] = 0; /* clear lock */
 
392
            rv = ipmi_lanparm_set_parm(pet->lanparm, 0, data, 1,
 
393
                                       lanparm_unlocked, pet);
 
394
        }
 
395
        if (rv) {
 
396
            ipmi_log(IPMI_LOG_WARNING,
 
397
                     "pet.c(lanparm_op_done): error clearing lock: 0x%x", rv);
 
398
            ipmi_lanparm_destroy(pet->lanparm, NULL, NULL);
 
399
            pet->lanparm = NULL;
 
400
            pet_op_done(pet);
 
401
            goto out;
 
402
        }
 
403
    }
 
404
    pet_unlock(pet);
 
405
 out:
 
406
    return;
 
407
}
 
408
 
 
409
static void lanparm_got_config(ipmi_lanparm_t *lanparm,
 
410
                               int            err,
 
411
                               unsigned char  *data,
 
412
                               unsigned int   data_len,
 
413
                               void           *cb_data);
 
414
 
 
415
static int
 
416
lanparm_next_config(ipmi_pet_t *pet)
 
417
{
 
418
    parm_check_t  *check;
 
419
    int           rv;
 
420
 
 
421
    pet->lanparm_check_pos++;
 
422
    if (pet->lanparm_check_pos >= NUM_LANPARM_SETTINGS) {
 
423
        /* Return non-zero, to end the operation. */
 
424
        return -1;
 
425
    }
 
426
 
 
427
    check = &(pet->lanparm_check[pet->lanparm_check_pos]);
 
428
 
 
429
    rv = ipmi_lanparm_get_parm(pet->lanparm,
 
430
                               check->conf_num, check->set,
 
431
                               0, lanparm_got_config, pet);
 
432
    if (rv) {
 
433
        ipmi_log(IPMI_LOG_WARNING,
 
434
                 "pet.c(lanparm_next_config): get err for %d: 0x%x",
 
435
                 pet->lanparm_check_pos, rv);
 
436
    }
 
437
 
 
438
    return rv;
 
439
}
 
440
 
 
441
static void
 
442
lanparm_set_config(ipmi_lanparm_t *lanparm,
 
443
                   int            err,
 
444
                   void           *cb_data)
 
445
{
 
446
    ipmi_pet_t    *pet = cb_data;
 
447
    int           rv;
 
448
 
 
449
    pet_lock(pet);
 
450
    if (pet->destroyed) {
 
451
        lanparm_op_done(pet, ECANCELED);
 
452
        goto out;
 
453
    }
 
454
 
 
455
    if (err) {
 
456
        ipmi_log(IPMI_LOG_WARNING,
 
457
                 "pet.c(lanparm_set_config): set failed for %d: 0x%x",
 
458
                 pet->lanparm_check_pos, err);
 
459
        lanparm_op_done(pet, err);
 
460
        goto out;
 
461
    }
 
462
 
 
463
    rv = lanparm_next_config(pet);
 
464
    if (rv) {
 
465
        lanparm_op_done(pet, rv);
 
466
        goto out;
 
467
    }
 
468
    pet_unlock(pet);
 
469
 out:
 
470
    return;
 
471
}
 
472
 
 
473
static void
 
474
lanparm_got_config(ipmi_lanparm_t *lanparm,
 
475
                   int            err,
 
476
                   unsigned char  *data,
 
477
                   unsigned int   data_len,
 
478
                   void           *cb_data)
 
479
{
 
480
    ipmi_pet_t    *pet = cb_data;
 
481
    unsigned char val[22];
 
482
    int           rv;
 
483
    int           pos;
 
484
    parm_check_t  *check;
 
485
    int           check_failed = 0;
 
486
    int           i;
 
487
 
 
488
    pet_lock(pet);
 
489
    if (pet->destroyed) {
 
490
        lanparm_op_done(pet, ECANCELED);
 
491
        goto out;
 
492
    }
 
493
 
 
494
    if (err) {
 
495
        ipmi_log(IPMI_LOG_WARNING,
 
496
                 "pet.c(lanparm_got_config): get failed for %d: 0x%x",
 
497
                 pet->lanparm_check_pos, err);
 
498
        lanparm_op_done(pet, err);
 
499
        goto out;
 
500
    }
 
501
 
 
502
    pos = pet->lanparm_check_pos;
 
503
    check = &(pet->lanparm_check[pos]);
 
504
 
 
505
    /* Don't forget to skip the revision number in the length. */
 
506
    if (data_len < (check->data_len+1)) {
 
507
        ipmi_log(IPMI_LOG_WARNING,
 
508
                 "pet.c(lanparm_got_config): data length too short for"
 
509
                 " config %d, was %d, expected %d", check->conf_num,
 
510
                 data_len, check->data_len);
 
511
        lanparm_op_done(pet, EINVAL);
 
512
        goto out;
 
513
    }
 
514
 
 
515
    data++; /* Skip the revision number */
 
516
 
 
517
    /* Check the config item we got and make sure it matches.  If it
 
518
       does not match, send the proper data for it. */
 
519
    for (i=0; i<check->data_len; i++) {
 
520
        unsigned char checkdata;
 
521
 
 
522
        checkdata = check->data[i];
 
523
        if ((data[i] & check->mask[i]) != checkdata) {
 
524
            check_failed = 1;
 
525
            break;
 
526
        }
 
527
    }
 
528
 
 
529
    if (check_failed) {
 
530
        for (i=0; i<check->data_len; i++) {
 
531
            unsigned char checkdata;
 
532
 
 
533
            checkdata = check->data[i];
 
534
            val[i] = (data[i] & ~check->mask[i]) | checkdata;
 
535
        }
 
536
        rv = ipmi_lanparm_set_parm(pet->lanparm,
 
537
                                   check->conf_num, val, check->data_len,
 
538
                                   lanparm_set_config, pet);
 
539
        if (rv) {
 
540
            ipmi_log(IPMI_LOG_WARNING,
 
541
                     "pet.c(lanparm_got_config): sending set: 0x%x",
 
542
                     rv);
 
543
            lanparm_op_done(pet, rv);
 
544
            goto out;
 
545
        }
 
546
        pet->changed_lanparm = 1;
 
547
    } else {
 
548
        rv = lanparm_next_config(pet);
 
549
        if (rv) {
 
550
            lanparm_op_done(pet, rv);
 
551
            goto out;
 
552
        }
 
553
    }
 
554
 
 
555
    pet_unlock(pet);
 
556
 out:
 
557
    return;
 
558
}
 
559
 
 
560
static void
 
561
pef_unlocked(ipmi_pef_t    *pef,
 
562
             int           err,
 
563
             void          *cb_data)
 
564
{
 
565
    ipmi_pet_t *pet = cb_data;
 
566
 
 
567
    pet_lock(pet);
 
568
    ipmi_pef_destroy(pet->pef, NULL, NULL);
 
569
    pet->pef = NULL;
 
570
    pet_op_done(pet);
 
571
}
 
572
 
 
573
static void
 
574
pef_commited(ipmi_pef_t    *pef,
 
575
             int           err,
 
576
             void          *cb_data)
 
577
{
 
578
    ipmi_pet_t    *pet = cb_data;
 
579
    int           rv;
 
580
    unsigned char data[1];
 
581
 
 
582
    pet_lock(pet);
 
583
    if (pet->destroyed) {
 
584
        ipmi_pef_destroy(pet->pef, NULL, NULL);
 
585
        pet->pef = NULL;
 
586
        pet_op_done(pet);
 
587
        goto out;
 
588
    }
 
589
 
 
590
    /* Ignore the error, committing is optional. */
 
591
 
 
592
    data[0] = 0; /* clear lock */
 
593
    rv = ipmi_pef_set_parm(pet->pef, 0, data, 1,
 
594
                           pef_unlocked, pet);
 
595
    if (rv) {
 
596
        ipmi_log(IPMI_LOG_WARNING,
 
597
                 "pet.c(pef_commited): error clearing lock: 0x%x", rv);
 
598
        ipmi_pef_destroy(pet->pef, NULL, NULL);
 
599
        pet->pef = NULL;
 
600
        pet_op_done(pet);
 
601
        goto out;
 
602
    }
 
603
    pet_unlock(pet);
 
604
 out:
 
605
    return;
 
606
}
 
607
 
 
608
/* Must be called locked, this will unlock the PET. */
 
609
static void
 
610
pef_op_done(ipmi_pet_t *pet, int err)
 
611
{
 
612
    int           rv;
 
613
 
 
614
    /* Cheap hack, -1 means stop. */
 
615
    if (err == -1)
 
616
        err = 0;
 
617
 
 
618
    pet->pef_err = err;
 
619
    if (pet->pef_lock_broken) {
 
620
        /* Locking is not supported. */
 
621
        ipmi_pef_destroy(pet->pef, NULL, NULL);
 
622
        pet->pef = NULL;
 
623
        pet_op_done(pet);
 
624
        goto out;
 
625
    } else {
 
626
        unsigned char data[1];
 
627
 
 
628
        if (!pet->pef_err && pet->changed_pef) {
 
629
            /* Don't commit if an error occurred. */
 
630
            data[0] = 2; /* commit */
 
631
            rv = ipmi_pef_set_parm(pet->pef, 0, data, 1, pef_commited, pet);
 
632
        } else {
 
633
            data[0] = 0; /* clear lock */
 
634
            rv = ipmi_pef_set_parm(pet->pef, 0, data, 1, pef_unlocked, pet);
 
635
        }
 
636
        if (rv) {
 
637
            ipmi_log(IPMI_LOG_WARNING,
 
638
                     "pet.c(pef_op_done): error clearing lock: 0x%x", rv);
 
639
            pet_op_done(pet);
 
640
            ipmi_pef_destroy(pet->pef, NULL, NULL);
 
641
            pet->pef = NULL;
 
642
            goto out;
 
643
        }
 
644
    }
 
645
    pet_unlock(pet);
 
646
 out:
 
647
    return;
 
648
}
 
649
 
 
650
static void pef_got_config(ipmi_pef_t    *pef,
 
651
                           int           err,
 
652
                           unsigned char *data,
 
653
                           unsigned int  data_len,
 
654
                           void          *cb_data);
 
655
 
 
656
static int
 
657
pef_next_config(ipmi_pet_t *pet)
 
658
{
 
659
    parm_check_t  *check;
 
660
    int           rv;
 
661
 
 
662
    pet->pef_check_pos++;
 
663
    if (pet->pef_check_pos >= NUM_PEF_SETTINGS) {
 
664
        /* Return non-zero, to end the operation. */
 
665
        return -1;
 
666
    }
 
667
 
 
668
    check = &(pet->pef_check[pet->pef_check_pos]);
 
669
 
 
670
    rv = ipmi_pef_get_parm(pet->pef, check->conf_num, check->set,
 
671
                           0, pef_got_config, pet);
 
672
    if (rv) {
 
673
        ipmi_log(IPMI_LOG_WARNING,
 
674
                 "pet.c(pef_next_config): PEF get err: 0x%x", rv);
 
675
    }
 
676
 
 
677
    return rv;
 
678
}
 
679
 
 
680
static void
 
681
pef_set_config(ipmi_pef_t    *pef,
 
682
               int           err,
 
683
               void          *cb_data)
 
684
{
 
685
    ipmi_pet_t    *pet = cb_data;
 
686
    int           rv;
 
687
 
 
688
    pet_lock(pet);
 
689
    if (pet->destroyed) {
 
690
        pef_op_done(pet, ECANCELED);
 
691
        goto out;
 
692
    }
 
693
 
 
694
    if (err) {
 
695
        ipmi_log(IPMI_LOG_WARNING,
 
696
                 "pet.c(pef_set_config): PEF set failed for %d: 0x%x",
 
697
                 pet->pef_check_pos, err);
 
698
        pef_op_done(pet, err);
 
699
        goto out;
 
700
    }
 
701
 
 
702
    rv = pef_next_config(pet);
 
703
    if (rv) {
 
704
        pef_op_done(pet, rv);
 
705
        goto out;
 
706
    }
 
707
    pet_unlock(pet);
 
708
 out:
 
709
    return;
 
710
}
 
711
 
 
712
static void
 
713
pef_got_config(ipmi_pef_t    *pef,
 
714
               int           err,
 
715
               unsigned char *data,
 
716
               unsigned int  data_len,
 
717
               void          *cb_data)
 
718
{
 
719
    ipmi_pet_t    *pet = cb_data;
 
720
    unsigned char val[22];
 
721
    int           rv;
 
722
    int           pos;
 
723
    parm_check_t  *check;
 
724
    int           check_failed = 0;
 
725
    int           i;
 
726
 
 
727
    pet_lock(pet);
 
728
    if (pet->destroyed) {
 
729
        pef_op_done(pet, ECANCELED);
 
730
        goto out;
 
731
    }
 
732
 
 
733
    if (err) {
 
734
        ipmi_log(IPMI_LOG_WARNING,
 
735
                 "pet.c(pef_got_control): PEF alloc failed: 0x%x", err);
 
736
        pef_op_done(pet, err);
 
737
        goto out;
 
738
    }
 
739
 
 
740
    pos = pet->pef_check_pos;
 
741
    check = &(pet->pef_check[pos]);
 
742
 
 
743
    /* Don't forget to skip the revision number in the length. */
 
744
    if (data_len < check->data_len) {
 
745
        ipmi_log(IPMI_LOG_WARNING,
 
746
                 "pet.c(pef_got_cofnfig): PEF data length too short for"
 
747
                 " config %d, was %d, expected %d", check->conf_num,
 
748
                 data_len, check->data_len);
 
749
        pef_op_done(pet, EINVAL);
 
750
        goto out;
 
751
    }
 
752
 
 
753
    data++; /* Skip the revision number */
 
754
 
 
755
    /* Check the config item we got and make sure it matches.  If it
 
756
       does not match, send the proper data for it. */
 
757
    for (i=0; i<check->data_len; i++) {
 
758
        if ((data[i] & check->mask[i]) != check->data[i]) {
 
759
            check_failed = 1;
 
760
            break;
 
761
        }
 
762
    }
 
763
 
 
764
    if (check_failed) {
 
765
        for (i=0; i<check->data_len; i++)
 
766
            val[i] = (data[i] & ~check->mask[i]) | check->data[i];
 
767
        rv = ipmi_pef_set_parm(pef, check->conf_num, val, check->data_len,
 
768
                               pef_set_config, pet);
 
769
        if (rv) {
 
770
            ipmi_log(IPMI_LOG_WARNING,
 
771
                     "pet.c(pef_got_config): PEF error sending set: 0x%x",
 
772
                     rv);
 
773
            pef_op_done(pet, rv);
 
774
            goto out;
 
775
        }
 
776
        pet->changed_pef = 1;
 
777
    } else {
 
778
        rv = pef_next_config(pet);
 
779
        if (rv) {
 
780
            pef_op_done(pet, rv);
 
781
            goto out;
 
782
        }
 
783
    }
 
784
 
 
785
    pet_unlock(pet);
 
786
 out:
 
787
    return;
 
788
}
 
789
 
 
790
static void
 
791
pef_locked(ipmi_pef_t *pef,
 
792
           int        err,
 
793
           void       *cb_data)
 
794
{
 
795
    ipmi_pet_t    *pet = cb_data;
 
796
    int           rv;
 
797
 
 
798
    pet_lock(pet);
 
799
    if (pet->destroyed) {
 
800
        pef_op_done(pet, ECANCELED);
 
801
        goto out;
 
802
    }
 
803
 
 
804
    if (err == 0x80) {
 
805
        /* No support for locking, just set it so and continue. */
 
806
        pet->pef_lock_broken = 1;
 
807
    } else if (err) {
 
808
        ipmi_log(IPMI_LOG_WARNING,
 
809
                 "pet.c(pef_locked): PEF lock failed: 0x%x", err);
 
810
        pef_op_done(pet, err);
 
811
        goto out;
 
812
    }
 
813
 
 
814
    /* Start the configuration process. */
 
815
    rv = ipmi_pef_get_parm(pet->pef, pet->pef_check[0].conf_num,
 
816
                           pet->pef_check[0].set, 0,
 
817
                           pef_got_config, pet);
 
818
    if (rv) {
 
819
        ipmi_log(IPMI_LOG_WARNING,
 
820
                 "pet.c(pef_locked): PEF control get err: 0x%x", rv);
 
821
        pef_op_done(pet, rv);
 
822
        goto out;
 
823
    }
 
824
 
 
825
    pet_unlock(pet);
 
826
 out:
 
827
    return;
 
828
}
 
829
 
 
830
static void
 
831
pef_alloced(ipmi_pef_t *pef, int err, void *cb_data)
 
832
{
 
833
    ipmi_pet_t    *pet = cb_data;
 
834
    unsigned char data[1];
 
835
    int           rv;
 
836
 
 
837
    pet_lock(pet);
 
838
    if (pet->destroyed) {
 
839
        pef_op_done(pet, ECANCELED);
 
840
        goto out;
 
841
    }
 
842
 
 
843
    if (err) {
 
844
        ipmi_log(IPMI_LOG_WARNING,
 
845
                 "pet.c(pef_alloced): PEF alloc failed: 0x%x", err);
 
846
        pef_op_done(pet, err);
 
847
        goto out;
 
848
    }
 
849
 
 
850
    /* Start the configuration process. */
 
851
    data[0] = 1; /* Attempt to lock */
 
852
    rv = ipmi_pef_set_parm(pet->pef, 0, data, 1,
 
853
                           pef_locked, pet);
 
854
    if (rv) {
 
855
        ipmi_log(IPMI_LOG_WARNING,
 
856
                 "pet.c(pef_alloced): PEF control get err: 0x%x", rv);
 
857
        pef_op_done(pet, rv);
 
858
        goto out;
 
859
    }
 
860
 
 
861
    pet_unlock(pet);
 
862
 out:
 
863
    return;
 
864
}
 
865
 
 
866
static int
 
867
start_pet_setup(ipmi_mc_t  *mc,
 
868
                ipmi_pet_t *pet)
 
869
{
 
870
    int  rv = 0;
 
871
 
 
872
    pet_lock(pet);
 
873
 
 
874
    if (pet->in_progress) {
 
875
        pet_unlock(pet);
 
876
        return EAGAIN;
 
877
    }
 
878
 
 
879
    pet->pet = pet;
 
880
    pet->pef_lock_broken = 0;
 
881
    pet->pef_err = 0;
 
882
    pet->changed_pef = 0;
 
883
    pet->lanparm_lock_broken = 0;
 
884
    pet->lanparm_err = 0;
 
885
    pet->changed_lanparm = 0;
 
886
 
 
887
    pet->pef_check_pos = 0;
 
888
    pet->in_progress++;
 
889
    rv = ipmi_pef_alloc(mc, pef_alloced, pet, &pet->pef);
 
890
    if (rv) {
 
891
        pet->in_progress--;
 
892
        ipmi_log(IPMI_LOG_WARNING,
 
893
                 "start_pet_setup: Unable to allocate pef: 0x%x", rv);
 
894
        goto out;
 
895
    }
 
896
 
 
897
    /* Now that we have the channel, set up the lan parms. */
 
898
    pet->lanparm_check_pos = 0;
 
899
    rv = ipmi_lanparm_alloc(mc, pet->channel, &(pet->lanparm));
 
900
    if (rv) {
 
901
        ipmi_log(IPMI_LOG_WARNING,
 
902
                 "start_pet_setup: Unable to allocate lanparm: 0x%x",
 
903
                 rv);
 
904
    } else {
 
905
        pet->in_progress++;
 
906
        rv = ipmi_lanparm_get_parm(pet->lanparm,
 
907
                                   IPMI_LANPARM_DEST_TYPE,
 
908
                                   pet->lan_dest_sel,
 
909
                                   0,
 
910
                                   lanparm_got_config,
 
911
                                   pet);
 
912
        if (rv) {
 
913
            pet->in_progress--;
 
914
            ipmi_log(IPMI_LOG_WARNING,
 
915
                     "start_pet_setup: Unable to get dest type: 0x%x",
 
916
                     rv);
 
917
            ipmi_lanparm_destroy(pet->lanparm, NULL, NULL);
 
918
            pet->lanparm = NULL;
 
919
        }
 
920
    }
 
921
    rv = 0; /* We continue with the PEF run, even if the lanparm fails. */
 
922
 
 
923
 out:
 
924
    pet_unlock(pet);
 
925
    return rv;
 
926
}
 
927
 
 
928
int
 
929
ipmi_pet_create_mc(ipmi_mc_t        *mc,
 
930
                   unsigned int     channel,
 
931
                   struct in_addr   ip_addr,
 
932
                   unsigned char    mac_addr[6],
 
933
                   unsigned int     eft_sel,
 
934
                   unsigned int     policy_num,
 
935
                   unsigned int     apt_sel,
 
936
                   unsigned int     lan_dest_sel,
 
937
                   ipmi_pet_done_cb done,
 
938
                   void             *cb_data,
 
939
                   ipmi_pet_t       **ret_pet)
 
940
{
 
941
    ipmi_pet_t         *pet;
 
942
    int                rv;
 
943
    os_handler_t       *os_hnd;
 
944
    char               domain_name[IPMI_MC_NAME_LEN];
 
945
    ipmi_domain_t      *domain = ipmi_mc_get_domain(mc);
 
946
    ipmi_domain_attr_t *attr;
 
947
    locked_list_t      *pets;
 
948
 
 
949
    rv = ipmi_domain_register_attribute(domain, IPMI_PET_ATTR_NAME,
 
950
                                        pet_attr_init, pet_attr_destroy, NULL,
 
951
                                        &attr);
 
952
    if (rv)
 
953
        return rv;
 
954
    pets = ipmi_domain_attr_get_data(attr);
 
955
 
 
956
    pet = ipmi_mem_alloc(sizeof(*pet));
 
957
    if (!pet) {
 
958
        ipmi_domain_attr_put(attr);
 
959
        return ENOMEM;
 
960
    }
 
961
    memset(pet, 0, sizeof(*pet));
 
962
 
 
963
    ipmi_domain_get_name(domain, domain_name, sizeof(domain_name));
 
964
    snprintf(pet->name, sizeof(pet->name), "%s.%d", domain_name,
 
965
             ipmi_domain_get_unique_num(domain));
 
966
    pet->refcount = 1;
 
967
    pet->in_list = 1;
 
968
    pet->mc = ipmi_mc_convert_to_id(mc);
 
969
    pet->domain = ipmi_domain_convert_to_id(domain);
 
970
    pet->channel = channel;
 
971
    pet->ip_addr = ip_addr;
 
972
    pet->policy_num = policy_num;
 
973
    pet->eft_sel = eft_sel;
 
974
    pet->apt_sel = apt_sel;
 
975
    pet->lan_dest_sel = lan_dest_sel;
 
976
    pet->done = done;
 
977
    pet->cb_data = cb_data;
 
978
    memcpy(pet->mac_addr, mac_addr, sizeof(pet->mac_addr));
 
979
    pet->in_progress = 0;
 
980
 
 
981
    /* Set up all the data we want in the PEF and LANPARMs
 
982
       configuration. */
 
983
    pet->pef_check[0].conf_num = IPMI_PEFPARM_CONTROL;
 
984
    pet->pef_check[0].data_len = 1;
 
985
    pet->pef_check[0].data[0] = 1;
 
986
    pet->pef_check[0].mask[0] = 1;
 
987
    pet->pef_check[1].conf_num = IPMI_PEFPARM_ACTION_GLOBAL_CONTROL;
 
988
    pet->pef_check[1].data_len = 1;
 
989
    pet->pef_check[1].data[0] = 1;
 
990
    pet->pef_check[1].mask[0] = 1;
 
991
    pet->pef_check[2].conf_num = IPMI_PEFPARM_EVENT_FILTER_TABLE;
 
992
    pet->pef_check[2].set = eft_sel;
 
993
    pet->pef_check[2].data_len = 21;
 
994
    memset(pet->pef_check[2].data, 0xff, 10);
 
995
    memset(pet->pef_check[2].data+10, 0, 21-9);
 
996
    memset(pet->pef_check[2].mask, 0xff, 21);
 
997
    pet->pef_check[2].data[0] = eft_sel;
 
998
    pet->pef_check[2].mask[0] = 0x7f;
 
999
    pet->pef_check[2].data[1] = 0x80;
 
1000
    pet->pef_check[2].mask[1] = 0x80;
 
1001
    pet->pef_check[2].data[2] = 0x01;
 
1002
    pet->pef_check[2].mask[2] = 0x3f;
 
1003
    pet->pef_check[2].data[3] = policy_num;
 
1004
    pet->pef_check[2].mask[3] = 0x0f;
 
1005
    pet->pef_check[2].data[4] = 0;
 
1006
    pet->pef_check[2].data[10] = 0xff;
 
1007
    pet->pef_check[2].data[11] = 0xff;
 
1008
    pet->pef_check[3].conf_num = IPMI_PEFPARM_ALERT_POLICY_TABLE;
 
1009
    pet->pef_check[3].set = apt_sel;
 
1010
    pet->pef_check[3].data_len = 4;
 
1011
    pet->pef_check[3].data[0] = apt_sel;
 
1012
    pet->pef_check[3].mask[0] = 0x7f;
 
1013
    pet->pef_check[3].data[1] = 0x08 | (policy_num << 4);
 
1014
    pet->pef_check[3].mask[1] = 0xff;
 
1015
    pet->pef_check[3].data[2] = (channel << 4) | lan_dest_sel;
 
1016
    pet->pef_check[3].mask[2] = 0xff;
 
1017
    pet->pef_check[3].data[3] = 0;
 
1018
    pet->pef_check[3].mask[3] = 0xff;
 
1019
 
 
1020
    pet->lanparm_check[0].conf_num = IPMI_LANPARM_DEST_TYPE;
 
1021
    pet->lanparm_check[0].set = lan_dest_sel;
 
1022
    pet->lanparm_check[0].data_len = 4;
 
1023
    pet->lanparm_check[0].data[0] = lan_dest_sel;
 
1024
    pet->lanparm_check[0].mask[0] = 0x0f;
 
1025
    pet->lanparm_check[0].data[1] = 0x80;
 
1026
    pet->lanparm_check[0].mask[1] = 0x87;
 
1027
    pet->lanparm_check[0].data[2] = IPMI_LANPARM_DEFAULT_ALERT_RETRY_TIMEOUT;
 
1028
    pet->lanparm_check[0].mask[2] = 0xff;
 
1029
    pet->lanparm_check[0].data[3] = IPMI_LANPARM_DEFAULT_ALERT_RETRIES;
 
1030
    pet->lanparm_check[0].mask[3] = 0x07;
 
1031
    pet->lanparm_check[1].conf_num = IPMI_LANPARM_DEST_ADDR;
 
1032
    pet->lanparm_check[1].set = lan_dest_sel;
 
1033
    pet->lanparm_check[1].data_len = 13;
 
1034
    pet->lanparm_check[1].data[0] = lan_dest_sel;
 
1035
    pet->lanparm_check[1].mask[0] = 0x0f;
 
1036
    pet->lanparm_check[1].data[1] = 0x00;
 
1037
    pet->lanparm_check[1].mask[1] = 0xf0;
 
1038
    pet->lanparm_check[1].data[2] = 0x00;
 
1039
    pet->lanparm_check[1].mask[2] = 0x01;
 
1040
    memset(pet->lanparm_check[1].mask+3, 0xff, 10);
 
1041
    memcpy(pet->lanparm_check[1].data+3, &ip_addr, 4);
 
1042
    memcpy(pet->lanparm_check[1].data+7, mac_addr, 6);
 
1043
 
 
1044
    os_hnd = ipmi_domain_get_os_hnd(domain);
 
1045
    pet->os_hnd = os_hnd;
 
1046
 
 
1047
    /* Start a timer for this PET to periodically check it. */
 
1048
    pet->timer_info = ipmi_mem_alloc(sizeof(*(pet->timer_info)));
 
1049
    if (!pet->timer_info) {
 
1050
        rv = ENOMEM;
 
1051
        goto out_err;
 
1052
    }
 
1053
    pet->timer_info->cancelled = 0;
 
1054
    pet->timer_info->os_hnd = os_hnd;
 
1055
    pet->timer_info->pet = pet;
 
1056
    pet->timer_info->running = 0;
 
1057
    pet->timer_info->lock = NULL;
 
1058
    rv = os_hnd->alloc_timer(os_hnd, &pet->timer);
 
1059
    if (rv)
 
1060
        goto out_err;
 
1061
 
 
1062
    rv = ipmi_create_lock_os_hnd(os_hnd, &pet->timer_info->lock);
 
1063
    if (rv)
 
1064
        goto out_err;
 
1065
 
 
1066
    if (! locked_list_add(pets, pet, NULL)) {
 
1067
        rv = ENOMEM;
 
1068
        goto out_err;
 
1069
    }
 
1070
 
 
1071
    ipmi_domain_attr_put(attr);
 
1072
 
 
1073
    rv = start_pet_setup(mc, pet);
 
1074
    if (rv)
 
1075
        goto out_err;
 
1076
 
 
1077
    if (ret_pet)
 
1078
        *ret_pet = pet;
 
1079
 
 
1080
    return 0;
 
1081
 
 
1082
 out_err:
 
1083
    locked_list_remove(pets, pet, NULL);
 
1084
    ipmi_domain_attr_put(attr);
 
1085
    if (pet->timer_info) {
 
1086
        if (pet->timer) {
 
1087
            if (os_hnd->stop_timer(os_hnd, pet->timer) == 0) {
 
1088
                if (pet->timer_info->lock)
 
1089
                    ipmi_destroy_lock(pet->timer_info->lock);
 
1090
                os_hnd->free_timer(os_hnd, pet->timer);
 
1091
                ipmi_mem_free(pet->timer_info);
 
1092
            } else {
 
1093
                pet->timer_info->cancelled = 1;
 
1094
            }
 
1095
        } else
 
1096
            ipmi_mem_free(pet->timer_info);
 
1097
    }
 
1098
    ipmi_mem_free(pet);
 
1099
    return rv;
 
1100
}
 
1101
 
 
1102
int
 
1103
ipmi_pet_create(ipmi_domain_t    *domain,
 
1104
                unsigned int     connection,
 
1105
                unsigned int     channel,
 
1106
                struct in_addr   ip_addr,
 
1107
                unsigned char    mac_addr[6],
 
1108
                unsigned int     eft_sel,
 
1109
                unsigned int     policy_num,
 
1110
                unsigned int     apt_sel,
 
1111
                unsigned int     lan_dest_sel,
 
1112
                ipmi_pet_done_cb done,
 
1113
                void             *cb_data,
 
1114
                ipmi_pet_t       **ret_pet)
 
1115
{
 
1116
    ipmi_system_interface_addr_t si;
 
1117
    ipmi_mc_t                    *mc;
 
1118
    int                          rv;
 
1119
 
 
1120
    si.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
 
1121
    si.channel = connection;
 
1122
    si.lun = 0;
 
1123
 
 
1124
    mc = _ipmi_find_mc_by_addr(domain, (ipmi_addr_t *) &si, sizeof(si));
 
1125
    if ((!mc)  && (connection == 0)) {
 
1126
        /* If the specific connection doesn't exist and the connection
 
1127
           is 0, use the BMC channel. */
 
1128
        si.channel = IPMI_BMC_CHANNEL;
 
1129
        mc = _ipmi_find_mc_by_addr(domain, (ipmi_addr_t *) &si,
 
1130
                                   sizeof(si));
 
1131
    }
 
1132
 
 
1133
    if (!mc)
 
1134
        return EINVAL;
 
1135
 
 
1136
    rv = ipmi_pet_create_mc(mc,
 
1137
                            channel,
 
1138
                            ip_addr,
 
1139
                            mac_addr,
 
1140
                            eft_sel,
 
1141
                            policy_num,
 
1142
                            apt_sel,
 
1143
                            lan_dest_sel,
 
1144
                            done,
 
1145
                            cb_data,
 
1146
                            ret_pet);
 
1147
    _ipmi_mc_put(mc);
 
1148
 
 
1149
    return rv;
 
1150
}
 
1151
 
 
1152
static void
 
1153
rescan_pet_mc(ipmi_mc_t *mc, void *cb_data)
 
1154
{
 
1155
    pet_timer_t *timer_info = cb_data;
 
1156
    ipmi_pet_t  *pet = timer_info->pet;
 
1157
 
 
1158
    timer_info->err = start_pet_setup(mc, pet);
 
1159
}
 
1160
 
 
1161
static void
 
1162
rescan_pet(void *cb_data, os_hnd_timer_id_t *id)
 
1163
{
 
1164
    pet_timer_t    *timer_info = cb_data;
 
1165
    ipmi_pet_t     *pet;
 
1166
    int            rv;
 
1167
    struct timeval timeout;
 
1168
 
 
1169
    ipmi_lock(timer_info->lock);
 
1170
    if (timer_info->cancelled) {
 
1171
        ipmi_unlock(timer_info->lock);
 
1172
        timer_info->os_hnd->free_timer(timer_info->os_hnd, id);
 
1173
        ipmi_destroy_lock(timer_info->lock);
 
1174
        ipmi_mem_free(timer_info);
 
1175
        return;
 
1176
    }
 
1177
    pet = timer_info->pet;
 
1178
    pet->timer_info->running = 0;
 
1179
    pet_get(pet);
 
1180
 
 
1181
    timer_info->err = 0;
 
1182
    rv = ipmi_mc_pointer_cb(pet->mc, rescan_pet_mc, timer_info);
 
1183
    if (!rv)
 
1184
        rv = timer_info->err;
 
1185
 
 
1186
    if (rv) {
 
1187
        os_handler_t *os_hnd = timer_info->os_hnd;
 
1188
        /* Got an error, just restart the timer */
 
1189
        timeout.tv_sec = PET_TIMEOUT_SEC;
 
1190
        timeout.tv_usec = 0;
 
1191
        os_hnd->start_timer(os_hnd, pet->timer, &timeout, rescan_pet,
 
1192
                            pet->timer_info);
 
1193
        pet->timer_info->running = 1;
 
1194
    }
 
1195
 
 
1196
    ipmi_unlock(timer_info->lock);
 
1197
}
 
1198
 
 
1199
int
 
1200
ipmi_pet_destroy(ipmi_pet_t       *pet,
 
1201
                 ipmi_pet_done_cb done,
 
1202
                 void             *cb_data)
 
1203
 
 
1204
{
 
1205
    pet_lock(pet);
 
1206
    if (pet->in_list) {
 
1207
        ipmi_domain_attr_t *attr;
 
1208
        locked_list_t      *pets;
 
1209
        int                rv;
 
1210
 
 
1211
        pet->in_list = 0;
 
1212
        rv = ipmi_domain_id_find_attribute(pet->domain,
 
1213
                                           IPMI_PET_ATTR_NAME, &attr);
 
1214
        if (!rv) {
 
1215
            pet_unlock(pet);
 
1216
        
 
1217
            pets = ipmi_domain_attr_get_data(attr);
 
1218
 
 
1219
            locked_list_remove(pets, pet, NULL);
 
1220
            ipmi_domain_attr_put(attr);
 
1221
            pet_lock(pet);
 
1222
        }
 
1223
    }
 
1224
 
 
1225
    pet->destroyed = 1;
 
1226
    pet->destroy_done = done;
 
1227
    pet->destroy_cb_data = cb_data;
 
1228
    pet_unlock(pet);
 
1229
 
 
1230
    pet_put(pet);
 
1231
    return 0;
 
1232
}
 
1233
 
 
1234
int
 
1235
ipmi_pet_get_name(ipmi_pet_t *pet, char *name, int length)
 
1236
{
 
1237
    int  slen;
 
1238
 
 
1239
    if (length <= 0)
 
1240
        return 0;
 
1241
 
 
1242
    /* Never changes, no lock needed. */
 
1243
    slen = strlen(pet->name);
 
1244
    if (slen == 0) {
 
1245
        if (name)
 
1246
            *name = '\0';
 
1247
        goto out;
 
1248
    }
 
1249
 
 
1250
    if (name) {
 
1251
        memcpy(name, pet->name, slen);
 
1252
        name[slen] = '\0';
 
1253
    }
 
1254
 out:
 
1255
    return slen;
 
1256
}
 
1257
 
 
1258
typedef struct iterate_pets_info_s
 
1259
{
 
1260
    ipmi_pet_ptr_cb handler;
 
1261
    void            *cb_data;
 
1262
} iterate_pets_info_t;
 
1263
 
 
1264
static int
 
1265
pets_handler(void *cb_data, void *item1, void *item2)
 
1266
{
 
1267
    iterate_pets_info_t *info = cb_data;
 
1268
    info->handler(item1, info->cb_data);
 
1269
    pet_put(item1);
 
1270
    return LOCKED_LIST_ITER_CONTINUE;
 
1271
}
 
1272
 
 
1273
static int
 
1274
pets_prefunc(void *cb_data, void *item1, void *item2)
 
1275
{
 
1276
    pet_get(item1);
 
1277
    return LOCKED_LIST_ITER_CONTINUE;
 
1278
}
 
1279
 
 
1280
void
 
1281
ipmi_pet_iterate_pets(ipmi_domain_t   *domain,
 
1282
                      ipmi_pet_ptr_cb handler,
 
1283
                      void            *cb_data)
 
1284
{
 
1285
    iterate_pets_info_t info;
 
1286
    ipmi_domain_attr_t  *attr;
 
1287
    locked_list_t       *pets;
 
1288
    int                 rv;
 
1289
 
 
1290
    rv = ipmi_domain_find_attribute(domain, IPMI_PET_ATTR_NAME,
 
1291
                                    &attr);
 
1292
    if (rv)
 
1293
        return;
 
1294
    pets = ipmi_domain_attr_get_data(attr);
 
1295
 
 
1296
    info.handler = handler;
 
1297
    info.cb_data = cb_data;
 
1298
    locked_list_iterate_prefunc(pets, pets_prefunc, pets_handler, &info);
 
1299
    ipmi_domain_attr_put(attr);
 
1300
}
 
1301
 
 
1302
ipmi_mcid_t
 
1303
ipmi_pet_get_mc_id(ipmi_pet_t *pet)
 
1304
{
 
1305
    return pet->mc;
 
1306
}
 
1307
 
 
1308
unsigned int
 
1309
ipmi_pet_get_channel(ipmi_pet_t *pet)
 
1310
{
 
1311
    return pet->channel;
 
1312
}
 
1313
 
 
1314
struct in_addr *
 
1315
ipmi_pet_get_ip_addr(ipmi_pet_t *pet, struct in_addr *ip_addr)
 
1316
{
 
1317
    memcpy(ip_addr, &pet->ip_addr, sizeof(*ip_addr));
 
1318
    return ip_addr;
 
1319
}
 
1320
 
 
1321
unsigned char *
 
1322
ipmi_pet_get_mac_addr(ipmi_pet_t *pet, unsigned char mac_addr[6])
 
1323
{
 
1324
    memcpy(mac_addr, pet->mac_addr, sizeof(mac_addr));
 
1325
    return mac_addr;
 
1326
}
 
1327
 
 
1328
unsigned int
 
1329
ipmi_pet_get_eft_sel(ipmi_pet_t *pet)
 
1330
{
 
1331
    return pet->eft_sel;
 
1332
}
 
1333
 
 
1334
unsigned int
 
1335
ipmi_pet_get_policy_num(ipmi_pet_t *pet)
 
1336
{
 
1337
    return pet->policy_num;
 
1338
}
 
1339
 
 
1340
unsigned int
 
1341
ipmi_pet_get_apt_sel(ipmi_pet_t *pet)
 
1342
{
 
1343
    return pet->apt_sel;
 
1344
}
 
1345
 
 
1346
unsigned int
 
1347
ipmi_pet_get_lan_dest_sel(ipmi_pet_t *pet)
 
1348
{
 
1349
    return pet->lan_dest_sel;
 
1350
}