4
* MontaVista IPMI code handling for setting up and receiving platform
7
* Author: MontaVista Software, Inc.
8
* Corey Minyard <minyard@mvista.com>
11
* Copyright 2004 MontaVista Software Inc.
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.
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.
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.
35
/* NOTE: This code requires scan_sysaddr to be set for the BMC
38
#include <sys/types.h>
39
#include <sys/socket.h>
40
#include <netinet/in.h>
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>
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>
58
/* Recheck the PET config every 10 minutes. */
59
#define PET_TIMEOUT_SEC 600
61
/* Time between alert retries (in seconds). */
62
#define IPMI_LANPARM_DEFAULT_ALERT_RETRY_TIMEOUT 1
64
/* Alerts get retried this many times. */
65
#define IPMI_LANPARM_DEFAULT_ALERT_RETRIES 3
67
#define IPMI_PET_ATTR_NAME "ipmi_pet"
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
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. */
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 {
88
ipmi_lock_t *lock; /* Lock is here because we need it in the timer. */
93
#define NUM_PEF_SETTINGS 4
94
#define NUM_LANPARM_SETTINGS 2
101
unsigned int refcount;
103
char name[IPMI_PET_NAME_LEN];
105
/* Configuration parameters */
107
ipmi_domain_id_t domain;
108
struct in_addr ip_addr;
110
unsigned int policy_num;
111
unsigned int eft_sel;
112
unsigned int apt_sel;
113
unsigned int lan_dest_sel;
115
unsigned int channel;
120
int lanparm_lock_broken;
124
int lanparm_check_pos;
125
ipmi_lanparm_t *lanparm;
130
/* The domain's OS handler */
131
os_handler_t *os_hnd;
133
ipmi_pet_done_cb done;
136
ipmi_pet_done_cb destroy_done;
137
void *destroy_cb_data;
141
/* The LAN configuration parameters to check. */
142
parm_check_t lanparm_check[NUM_LANPARM_SETTINGS];
144
/* The PEF configuration parameters to check */
145
parm_check_t pef_check[NUM_PEF_SETTINGS];
147
/* Timer to check the configuration periodically. */
148
pet_timer_t *timer_info;
149
os_hnd_timer_id_t *timer;
152
static void rescan_pet(void *cb_data, os_hnd_timer_id_t *id);
155
pet_lock(ipmi_pet_t *pet)
157
ipmi_lock(pet->timer_info->lock);
161
pet_unlock(ipmi_pet_t *pet)
163
ipmi_unlock(pet->timer_info->lock);
167
internal_pet_destroy(ipmi_pet_t *pet)
169
os_handler_t *os_hnd = pet->timer_info->os_hnd;
172
ipmi_domain_attr_t *attr;
175
rv = ipmi_domain_id_find_attribute(pet->domain,
176
IPMI_PET_ATTR_NAME, &attr);
182
pets = ipmi_domain_attr_get_data(attr);
184
locked_list_remove(pets, pet, NULL);
185
ipmi_domain_attr_put(attr);
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) {
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);
205
pet->timer_info->cancelled = 1;
208
if (pet->destroy_done) {
209
pet->destroy_done(pet, 0, pet->destroy_cb_data);
216
pet_get(ipmi_pet_t *pet)
224
pet_put(ipmi_pet_t *pet)
228
if (pet->refcount == 0) {
229
internal_pet_destroy(pet);
236
ipmi_pet_ref(ipmi_pet_t *pet)
242
ipmi_pet_deref(ipmi_pet_t *pet)
248
pet_attr_init(ipmi_domain_t *domain, void *cb_data, void **data)
252
pets = locked_list_alloc(ipmi_domain_get_os_hnd(domain));
261
destroy_pet(void *cb_data, void *item1, void *item2)
263
ipmi_pet_t *pet = item1;
268
return LOCKED_LIST_ITER_CONTINUE;
272
pet_attr_destroy(void *cb_data, void *data)
274
locked_list_t *pets = data;
276
locked_list_iterate(pets, destroy_pet, NULL);
277
locked_list_destroy(pets);
280
/* Must be called locked, this will unlock the PET. */
282
pet_op_done(ipmi_pet_t *pet)
284
struct timeval timeout;
285
os_handler_t *os_hnd = pet->os_hnd;
289
if (pet->in_progress == 0) {
291
ipmi_lanparm_destroy(pet->lanparm, NULL, NULL);
296
ipmi_pet_done_cb done = pet->done;
297
void *cb_data = pet->cb_data;
300
done(pet, 0, cb_data);
304
if (pet->destroyed) {
305
internal_pet_destroy(pet);
309
/* Restart the timer */
310
timeout.tv_sec = PET_TIMEOUT_SEC;
312
os_hnd->start_timer(os_hnd, pet->timer, &timeout, rescan_pet,
314
pet->timer_info->running = 1;
322
lanparm_unlocked(ipmi_lanparm_t *lanparm,
326
ipmi_pet_t *pet = cb_data;
329
ipmi_lanparm_destroy(pet->lanparm, NULL, NULL);
335
lanparm_commited(ipmi_lanparm_t *lanparm,
339
ipmi_pet_t *pet = cb_data;
341
unsigned char data[1];
344
if (pet->destroyed) {
349
/* Ignore the error, committing is optional. */
351
data[0] = 0; /* clear lock */
352
rv = ipmi_lanparm_set_parm(pet->lanparm, 0, data, 1,
353
lanparm_unlocked, pet);
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);
367
/* Must be called locked, this will unlock the PET. */
369
lanparm_op_done(ipmi_pet_t *pet, int err)
373
/* Cheap hack, -1 means stop. */
377
pet->lanparm_err = err;
378
if (pet->lanparm_lock_broken) {
379
/* Locking is not supported. */
383
unsigned char data[1];
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);
391
data[0] = 0; /* clear lock */
392
rv = ipmi_lanparm_set_parm(pet->lanparm, 0, data, 1,
393
lanparm_unlocked, pet);
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);
409
static void lanparm_got_config(ipmi_lanparm_t *lanparm,
412
unsigned int data_len,
416
lanparm_next_config(ipmi_pet_t *pet)
421
pet->lanparm_check_pos++;
422
if (pet->lanparm_check_pos >= NUM_LANPARM_SETTINGS) {
423
/* Return non-zero, to end the operation. */
427
check = &(pet->lanparm_check[pet->lanparm_check_pos]);
429
rv = ipmi_lanparm_get_parm(pet->lanparm,
430
check->conf_num, check->set,
431
0, lanparm_got_config, pet);
433
ipmi_log(IPMI_LOG_WARNING,
434
"pet.c(lanparm_next_config): get err for %d: 0x%x",
435
pet->lanparm_check_pos, rv);
442
lanparm_set_config(ipmi_lanparm_t *lanparm,
446
ipmi_pet_t *pet = cb_data;
450
if (pet->destroyed) {
451
lanparm_op_done(pet, ECANCELED);
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);
463
rv = lanparm_next_config(pet);
465
lanparm_op_done(pet, rv);
474
lanparm_got_config(ipmi_lanparm_t *lanparm,
477
unsigned int data_len,
480
ipmi_pet_t *pet = cb_data;
481
unsigned char val[22];
485
int check_failed = 0;
489
if (pet->destroyed) {
490
lanparm_op_done(pet, ECANCELED);
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);
502
pos = pet->lanparm_check_pos;
503
check = &(pet->lanparm_check[pos]);
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);
515
data++; /* Skip the revision number */
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;
522
checkdata = check->data[i];
523
if ((data[i] & check->mask[i]) != checkdata) {
530
for (i=0; i<check->data_len; i++) {
531
unsigned char checkdata;
533
checkdata = check->data[i];
534
val[i] = (data[i] & ~check->mask[i]) | checkdata;
536
rv = ipmi_lanparm_set_parm(pet->lanparm,
537
check->conf_num, val, check->data_len,
538
lanparm_set_config, pet);
540
ipmi_log(IPMI_LOG_WARNING,
541
"pet.c(lanparm_got_config): sending set: 0x%x",
543
lanparm_op_done(pet, rv);
546
pet->changed_lanparm = 1;
548
rv = lanparm_next_config(pet);
550
lanparm_op_done(pet, rv);
561
pef_unlocked(ipmi_pef_t *pef,
565
ipmi_pet_t *pet = cb_data;
568
ipmi_pef_destroy(pet->pef, NULL, NULL);
574
pef_commited(ipmi_pef_t *pef,
578
ipmi_pet_t *pet = cb_data;
580
unsigned char data[1];
583
if (pet->destroyed) {
584
ipmi_pef_destroy(pet->pef, NULL, NULL);
590
/* Ignore the error, committing is optional. */
592
data[0] = 0; /* clear lock */
593
rv = ipmi_pef_set_parm(pet->pef, 0, data, 1,
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);
608
/* Must be called locked, this will unlock the PET. */
610
pef_op_done(ipmi_pet_t *pet, int err)
614
/* Cheap hack, -1 means stop. */
619
if (pet->pef_lock_broken) {
620
/* Locking is not supported. */
621
ipmi_pef_destroy(pet->pef, NULL, NULL);
626
unsigned char data[1];
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);
633
data[0] = 0; /* clear lock */
634
rv = ipmi_pef_set_parm(pet->pef, 0, data, 1, pef_unlocked, pet);
637
ipmi_log(IPMI_LOG_WARNING,
638
"pet.c(pef_op_done): error clearing lock: 0x%x", rv);
640
ipmi_pef_destroy(pet->pef, NULL, NULL);
650
static void pef_got_config(ipmi_pef_t *pef,
653
unsigned int data_len,
657
pef_next_config(ipmi_pet_t *pet)
662
pet->pef_check_pos++;
663
if (pet->pef_check_pos >= NUM_PEF_SETTINGS) {
664
/* Return non-zero, to end the operation. */
668
check = &(pet->pef_check[pet->pef_check_pos]);
670
rv = ipmi_pef_get_parm(pet->pef, check->conf_num, check->set,
671
0, pef_got_config, pet);
673
ipmi_log(IPMI_LOG_WARNING,
674
"pet.c(pef_next_config): PEF get err: 0x%x", rv);
681
pef_set_config(ipmi_pef_t *pef,
685
ipmi_pet_t *pet = cb_data;
689
if (pet->destroyed) {
690
pef_op_done(pet, ECANCELED);
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);
702
rv = pef_next_config(pet);
704
pef_op_done(pet, rv);
713
pef_got_config(ipmi_pef_t *pef,
716
unsigned int data_len,
719
ipmi_pet_t *pet = cb_data;
720
unsigned char val[22];
724
int check_failed = 0;
728
if (pet->destroyed) {
729
pef_op_done(pet, ECANCELED);
734
ipmi_log(IPMI_LOG_WARNING,
735
"pet.c(pef_got_control): PEF alloc failed: 0x%x", err);
736
pef_op_done(pet, err);
740
pos = pet->pef_check_pos;
741
check = &(pet->pef_check[pos]);
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);
753
data++; /* Skip the revision number */
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]) {
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);
770
ipmi_log(IPMI_LOG_WARNING,
771
"pet.c(pef_got_config): PEF error sending set: 0x%x",
773
pef_op_done(pet, rv);
776
pet->changed_pef = 1;
778
rv = pef_next_config(pet);
780
pef_op_done(pet, rv);
791
pef_locked(ipmi_pef_t *pef,
795
ipmi_pet_t *pet = cb_data;
799
if (pet->destroyed) {
800
pef_op_done(pet, ECANCELED);
805
/* No support for locking, just set it so and continue. */
806
pet->pef_lock_broken = 1;
808
ipmi_log(IPMI_LOG_WARNING,
809
"pet.c(pef_locked): PEF lock failed: 0x%x", err);
810
pef_op_done(pet, err);
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);
819
ipmi_log(IPMI_LOG_WARNING,
820
"pet.c(pef_locked): PEF control get err: 0x%x", rv);
821
pef_op_done(pet, rv);
831
pef_alloced(ipmi_pef_t *pef, int err, void *cb_data)
833
ipmi_pet_t *pet = cb_data;
834
unsigned char data[1];
838
if (pet->destroyed) {
839
pef_op_done(pet, ECANCELED);
844
ipmi_log(IPMI_LOG_WARNING,
845
"pet.c(pef_alloced): PEF alloc failed: 0x%x", err);
846
pef_op_done(pet, err);
850
/* Start the configuration process. */
851
data[0] = 1; /* Attempt to lock */
852
rv = ipmi_pef_set_parm(pet->pef, 0, data, 1,
855
ipmi_log(IPMI_LOG_WARNING,
856
"pet.c(pef_alloced): PEF control get err: 0x%x", rv);
857
pef_op_done(pet, rv);
867
start_pet_setup(ipmi_mc_t *mc,
874
if (pet->in_progress) {
880
pet->pef_lock_broken = 0;
882
pet->changed_pef = 0;
883
pet->lanparm_lock_broken = 0;
884
pet->lanparm_err = 0;
885
pet->changed_lanparm = 0;
887
pet->pef_check_pos = 0;
889
rv = ipmi_pef_alloc(mc, pef_alloced, pet, &pet->pef);
892
ipmi_log(IPMI_LOG_WARNING,
893
"start_pet_setup: Unable to allocate pef: 0x%x", rv);
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));
901
ipmi_log(IPMI_LOG_WARNING,
902
"start_pet_setup: Unable to allocate lanparm: 0x%x",
906
rv = ipmi_lanparm_get_parm(pet->lanparm,
907
IPMI_LANPARM_DEST_TYPE,
914
ipmi_log(IPMI_LOG_WARNING,
915
"start_pet_setup: Unable to get dest type: 0x%x",
917
ipmi_lanparm_destroy(pet->lanparm, NULL, NULL);
921
rv = 0; /* We continue with the PEF run, even if the lanparm fails. */
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,
939
ipmi_pet_t **ret_pet)
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;
949
rv = ipmi_domain_register_attribute(domain, IPMI_PET_ATTR_NAME,
950
pet_attr_init, pet_attr_destroy, NULL,
954
pets = ipmi_domain_attr_get_data(attr);
956
pet = ipmi_mem_alloc(sizeof(*pet));
958
ipmi_domain_attr_put(attr);
961
memset(pet, 0, sizeof(*pet));
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));
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;
977
pet->cb_data = cb_data;
978
memcpy(pet->mac_addr, mac_addr, sizeof(pet->mac_addr));
979
pet->in_progress = 0;
981
/* Set up all the data we want in the PEF and LANPARMs
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;
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);
1044
os_hnd = ipmi_domain_get_os_hnd(domain);
1045
pet->os_hnd = os_hnd;
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) {
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);
1062
rv = ipmi_create_lock_os_hnd(os_hnd, &pet->timer_info->lock);
1066
if (! locked_list_add(pets, pet, NULL)) {
1071
ipmi_domain_attr_put(attr);
1073
rv = start_pet_setup(mc, pet);
1083
locked_list_remove(pets, pet, NULL);
1084
ipmi_domain_attr_put(attr);
1085
if (pet->timer_info) {
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);
1093
pet->timer_info->cancelled = 1;
1096
ipmi_mem_free(pet->timer_info);
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,
1114
ipmi_pet_t **ret_pet)
1116
ipmi_system_interface_addr_t si;
1120
si.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
1121
si.channel = connection;
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,
1136
rv = ipmi_pet_create_mc(mc,
1153
rescan_pet_mc(ipmi_mc_t *mc, void *cb_data)
1155
pet_timer_t *timer_info = cb_data;
1156
ipmi_pet_t *pet = timer_info->pet;
1158
timer_info->err = start_pet_setup(mc, pet);
1162
rescan_pet(void *cb_data, os_hnd_timer_id_t *id)
1164
pet_timer_t *timer_info = cb_data;
1167
struct timeval timeout;
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);
1177
pet = timer_info->pet;
1178
pet->timer_info->running = 0;
1181
timer_info->err = 0;
1182
rv = ipmi_mc_pointer_cb(pet->mc, rescan_pet_mc, timer_info);
1184
rv = timer_info->err;
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,
1193
pet->timer_info->running = 1;
1196
ipmi_unlock(timer_info->lock);
1200
ipmi_pet_destroy(ipmi_pet_t *pet,
1201
ipmi_pet_done_cb done,
1207
ipmi_domain_attr_t *attr;
1208
locked_list_t *pets;
1212
rv = ipmi_domain_id_find_attribute(pet->domain,
1213
IPMI_PET_ATTR_NAME, &attr);
1217
pets = ipmi_domain_attr_get_data(attr);
1219
locked_list_remove(pets, pet, NULL);
1220
ipmi_domain_attr_put(attr);
1226
pet->destroy_done = done;
1227
pet->destroy_cb_data = cb_data;
1235
ipmi_pet_get_name(ipmi_pet_t *pet, char *name, int length)
1242
/* Never changes, no lock needed. */
1243
slen = strlen(pet->name);
1251
memcpy(name, pet->name, slen);
1258
typedef struct iterate_pets_info_s
1260
ipmi_pet_ptr_cb handler;
1262
} iterate_pets_info_t;
1265
pets_handler(void *cb_data, void *item1, void *item2)
1267
iterate_pets_info_t *info = cb_data;
1268
info->handler(item1, info->cb_data);
1270
return LOCKED_LIST_ITER_CONTINUE;
1274
pets_prefunc(void *cb_data, void *item1, void *item2)
1277
return LOCKED_LIST_ITER_CONTINUE;
1281
ipmi_pet_iterate_pets(ipmi_domain_t *domain,
1282
ipmi_pet_ptr_cb handler,
1285
iterate_pets_info_t info;
1286
ipmi_domain_attr_t *attr;
1287
locked_list_t *pets;
1290
rv = ipmi_domain_find_attribute(domain, IPMI_PET_ATTR_NAME,
1294
pets = ipmi_domain_attr_get_data(attr);
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);
1303
ipmi_pet_get_mc_id(ipmi_pet_t *pet)
1309
ipmi_pet_get_channel(ipmi_pet_t *pet)
1311
return pet->channel;
1315
ipmi_pet_get_ip_addr(ipmi_pet_t *pet, struct in_addr *ip_addr)
1317
memcpy(ip_addr, &pet->ip_addr, sizeof(*ip_addr));
1322
ipmi_pet_get_mac_addr(ipmi_pet_t *pet, unsigned char mac_addr[6])
1324
memcpy(mac_addr, pet->mac_addr, sizeof(mac_addr));
1329
ipmi_pet_get_eft_sel(ipmi_pet_t *pet)
1331
return pet->eft_sel;
1335
ipmi_pet_get_policy_num(ipmi_pet_t *pet)
1337
return pet->policy_num;
1341
ipmi_pet_get_apt_sel(ipmi_pet_t *pet)
1343
return pet->apt_sel;
1347
ipmi_pet_get_lan_dest_sel(ipmi_pet_t *pet)
1349
return pet->lan_dest_sel;