1 /*
2  * sensor.c
3  *
4  * MontaVista IPMI code for handling sensors
5  *
6  * Author: MontaVista Software, Inc.
7  *         Corey Minyard <minyard@mvista.com>
8  *         source@mvista.com
9  *
10  * Copyright 2002,2003 MontaVista Software Inc.
11  *
12  *  This program is free software; you can redistribute it and/or
13  *  modify it under the terms of the GNU Lesser General Public License
14  *  as published by the Free Software Foundation; either version 2 of
15  *  the License, or (at your option) any later version.
16  *
17  *
18  *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
19  *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
24  *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25  *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
26  *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
27  *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  *
29  *  You should have received a copy of the GNU Lesser General Public
30  *  License along with this program; if not, write to the Free
31  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
32  */
33 
34 #include <string.h>
35 #include <stdio.h>
36 #include <math.h>
37 
38 #include <OpenIPMI/ipmiif.h>
39 #include <OpenIPMI/ipmi_sdr.h>
40 #include <OpenIPMI/ipmi_msgbits.h>
41 #include <OpenIPMI/ipmi_err.h>
42 
43 #include <OpenIPMI/internal/locked_list.h>
44 #include <OpenIPMI/internal/opq.h>
45 #include <OpenIPMI/internal/ipmi_int.h>
46 #include <OpenIPMI/internal/ipmi_sensor.h>
47 #include <OpenIPMI/internal/ipmi_entity.h>
48 #include <OpenIPMI/internal/ipmi_domain.h>
49 #include <OpenIPMI/internal/ipmi_mc.h>
50 #include <OpenIPMI/internal/ipmi_event.h>
51 
52 struct ipmi_sensor_info_s
53 {
54     int                      destroyed;
55 
56     /* Indexed by LUN and sensor # */
57     ipmi_sensor_t            **(sensors_by_idx[5]);
58     /* Size of above sensor array, per LUN.  This will be 0 if the
59        LUN has no sensors. */
60     unsigned int             idx_size[5];
61     /* In the above two, the 5th index is for non-standard sensors. */
62 
63     ipmi_lock_t              *idx_lock;
64 
65     /* Total number of sensors we have in this. */
66     unsigned int             sensor_count;
67 };
68 
69 #define SENSOR_ID_LEN 32 /* 16 bytes are allowed for a sensor. */
70 struct ipmi_sensor_s
71 {
72     unsigned int  usecount;
73 
74     ipmi_domain_t *domain; /* Domain I am in. */
75 
76     ipmi_mc_t     *mc; /* My owner, NOT the SMI mc (unless that
77                           happens to be my direct owner). */
78 
79     ipmi_mc_t     *source_mc; /* If the sensor came from the main SDR,
80 				 this will be NULL.  Otherwise, it
81 				 will be the MC that owned the device
82 				 SDR this came from. */
83     int           source_idx; /* The index into the source array where
84 				 this is stored.  This will be -1 if
85 				 it does not have a source index (ie
86 				 it's a non-standard sensor) */
87     int           source_recid; /* The SDR record ID the sensor came from. */
88     ipmi_sensor_t **source_array; /* This is the source array where
89                                      the sensor is stored. */
90 
91     int           destroyed;
92 
93     /* After the sensor is added, it will not be reported immediately.
94        Instead, it will wait until the usecount goes to zero before
95        being reported.  This marks that the add report is pending */
96     int add_pending;
97 
98     unsigned char owner;
99     unsigned char channel;
100     unsigned char lun;
101     unsigned char num;
102 
103     /* For OEM sensors, the sending LUN might be different that the
104        LUN we use for storage. */
105     unsigned char send_lun;
106 
107     ipmi_entity_t *entity;
108 
109     unsigned char entity_id;
110     unsigned char entity_instance;
111 
112     /* Can the sensor be read?  Event-only sensors cannot be read.  */
113     unsigned int  readable : 1;
114 
115     unsigned int  entity_instance_logical : 1;
116     unsigned int  sensor_init_scanning : 1;
117     unsigned int  sensor_init_events : 1;
118     unsigned int  sensor_init_thresholds : 1;
119     unsigned int  sensor_init_hysteresis : 1;
120     unsigned int  sensor_init_type : 1;
121     unsigned int  sensor_init_pu_events : 1;
122     unsigned int  sensor_init_pu_scanning : 1;
123     unsigned int  ignore_if_no_entity : 1;
124     unsigned int  supports_auto_rearm : 1;
125     unsigned int  hysteresis_support : 2;
126     unsigned int  threshold_access : 2;
127     unsigned int  event_support : 2;
128 
129     unsigned int sensor_direction : 2;
130 
131     unsigned int  ignore_for_presence : 1;
132 
133     int          hot_swap_requester;
134     int          hot_swap_requester_val;
135 
136     unsigned char sensor_type;
137 
138     unsigned char event_reading_type;
139 
140 #define IPMI_SENSOR_GET_MASK_BIT(mask, bit) (((mask) >> (bit)) & 1)
141 #define IPMI_SENSOR_SET_MASK_BIT(mask, bit, v) \
142 	(mask) = v ? (mask) | (1 << (bit)) : (mask) & ~(1 << (bit))
143     uint16_t mask1;
144     uint16_t mask2;
145     uint16_t mask3;
146 
147     unsigned int  analog_data_format : 2;
148 
149     unsigned int  rate_unit : 3;
150 
151     unsigned int  modifier_unit_use : 2;
152 
153     unsigned int  percentage : 1;
154 
155     unsigned char base_unit;
156     unsigned char modifier_unit;
157 
158     unsigned char linearization;
159 
160     struct {
161 	int m : 10;
162 	unsigned int tolerance : 6;
163 	int b : 10;
164 	int r_exp : 4;
165 	unsigned int accuracy_exp : 2;
166 	int accuracy : 10;
167 	int b_exp : 4;
168     } conv[256];
169 
170     unsigned int  normal_min_specified : 1;
171     unsigned int  normal_max_specified : 1;
172     unsigned int  nominal_reading_specified : 1;
173 
174     unsigned char nominal_reading;
175     unsigned char normal_max;
176     unsigned char normal_min;
177     unsigned char sensor_max;
178     unsigned char sensor_min;
179     unsigned char default_thresholds[6];
180     unsigned char positive_going_threshold_hysteresis;
181     unsigned char negative_going_threshold_hysteresis;
182 
183 
184     unsigned char oem1;
185 
186     /* Note that the ID is *not* nil terminated. */
187     enum ipmi_str_type_e id_type;
188     unsigned int id_len;
189     char id[SENSOR_ID_LEN]; /* The ID from the device SDR. */
190 
191     const char *sensor_type_string;
192     const char *event_reading_type_string;
193     const char *rate_unit_string;
194     const char *base_unit_string;
195     const char *modifier_unit_string;
196 
197     /* A list of handlers to call when an event for the sensor comes
198        in. */
199     locked_list_t *handler_list, *handler_list_cl;
200 
201     opq_t *waitq;
202     ipmi_event_state_t event_state;
203 
204     /* Polymorphic functions. */
205     ipmi_sensor_cbs_t cbs;
206 
207     /* OEM info */
208     void                            *oem_info;
209     ipmi_sensor_cleanup_oem_info_cb oem_info_cleanup_handler;
210 
211     ipmi_sensor_destroy_cb destroy_handler;
212     void                   *destroy_handler_cb_data;
213 
214     /* Name we use for reporting.  We add a ' ' onto the end, thus
215        the +1. */
216     char name[IPMI_SENSOR_NAME_LEN+1];
217 
218     /* Used for temporary linking. */
219     ipmi_sensor_t *tlink;
220 
221     /* Cruft. */
222     ipmi_sensor_threshold_event_handler_nd_cb threshold_event_handler;
223     ipmi_sensor_discrete_event_handler_nd_cb  discrete_event_handler;
224     void                         *cb_data;
225 };
226 
227 static void sensor_final_destroy(ipmi_sensor_t *sensor);
228 
229 /***********************************************************************
230  *
231  * Sensor ID handling.
232  *
233  **********************************************************************/
234 
235 /* Must be called with the domain entity lock held. */
236 int
i_ipmi_sensor_get(ipmi_sensor_t * sensor)237 i_ipmi_sensor_get(ipmi_sensor_t *sensor)
238 {
239     if (sensor->destroyed)
240 	return EINVAL;
241     sensor->usecount++;
242     return 0;
243 }
244 
245 void
i_ipmi_sensor_put(ipmi_sensor_t * sensor)246 i_ipmi_sensor_put(ipmi_sensor_t *sensor)
247 {
248     ipmi_domain_t *domain = sensor->domain;
249     i_ipmi_domain_entity_lock(domain);
250     if (sensor->usecount == 1) {
251 	if (sensor->add_pending) {
252 	    sensor->add_pending = 0;
253 	    i_ipmi_domain_entity_unlock(sensor->domain);
254 	    i_ipmi_entity_call_sensor_handlers(sensor->entity,
255 					      sensor, IPMI_ADDED);
256 	    i_ipmi_domain_entity_lock(sensor->domain);
257 	}
258 	if (sensor->destroyed
259 	    && (!sensor->waitq
260 		|| (!opq_stuff_in_progress(sensor->waitq))))
261 	{
262 	    i_ipmi_domain_entity_unlock(domain);
263 	    sensor_final_destroy(sensor);
264 	    return;
265 	}
266     }
267     sensor->usecount--;
268     i_ipmi_domain_entity_unlock(domain);
269 }
270 
271 ipmi_sensor_id_t
ipmi_sensor_convert_to_id(ipmi_sensor_t * sensor)272 ipmi_sensor_convert_to_id(ipmi_sensor_t *sensor)
273 {
274     ipmi_sensor_id_t val;
275 
276     CHECK_SENSOR_LOCK(sensor);
277 
278     val.mcid = ipmi_mc_convert_to_id(sensor->mc);
279     val.lun = sensor->lun;
280     val.sensor_num = sensor->num;
281 
282     return val;
283 }
284 
285 int
ipmi_cmp_sensor_id(ipmi_sensor_id_t id1,ipmi_sensor_id_t id2)286 ipmi_cmp_sensor_id(ipmi_sensor_id_t id1, ipmi_sensor_id_t id2)
287 {
288     int rv;
289 
290     rv = ipmi_cmp_mc_id(id1.mcid, id2.mcid);
291     if (rv)
292 	return rv;
293     if (id1.lun > id2.lun)
294 	return 1;
295     if (id1.lun < id2.lun)
296 	return -1;
297     if (id1.sensor_num > id2.sensor_num)
298 	return 1;
299     if (id1.sensor_num < id2.sensor_num)
300 	return -1;
301     return 0;
302 }
303 
304 void
ipmi_sensor_id_set_invalid(ipmi_sensor_id_t * id)305 ipmi_sensor_id_set_invalid(ipmi_sensor_id_t *id)
306 {
307     memset(id, 0, sizeof(*id));
308 }
309 
310 int
ipmi_sensor_id_is_invalid(const ipmi_sensor_id_t * id)311 ipmi_sensor_id_is_invalid(const ipmi_sensor_id_t *id)
312 {
313     return (id->mcid.domain_id.domain == NULL);
314 }
315 
316 typedef struct mc_cb_info_s
317 {
318     ipmi_sensor_ptr_cb handler;
319     void               *cb_data;
320     ipmi_sensor_id_t   id;
321     int                err;
322 } mc_cb_info_t;
323 
324 static void
mc_cb(ipmi_mc_t * mc,void * cb_data)325 mc_cb(ipmi_mc_t *mc, void *cb_data)
326 {
327     mc_cb_info_t       *info = cb_data;
328     ipmi_sensor_info_t *sensors;
329     ipmi_domain_t      *domain = ipmi_mc_get_domain(mc);
330     ipmi_sensor_t      *sensor;
331     ipmi_entity_t      *entity = NULL;
332 
333     sensors = i_ipmi_mc_get_sensors(mc);
334     i_ipmi_domain_entity_lock(domain);
335     if (info->id.lun > 4) {
336 	info->err = EINVAL;
337 	goto out_unlock;
338     }
339 
340     if (info->id.sensor_num >= sensors->idx_size[info->id.lun]) {
341 	info->err = EINVAL;
342 	goto out_unlock;
343     }
344 
345     sensor = sensors->sensors_by_idx[info->id.lun][info->id.sensor_num];
346     if (!sensor) {
347 	info->err = EINVAL;
348 	goto out_unlock;
349     }
350 
351     info->err = i_ipmi_entity_get(sensor->entity);
352     if (info->err)
353 	goto out_unlock;
354     entity = sensor->entity;
355 
356     info->err = i_ipmi_sensor_get(sensor);
357     if (info->err)
358 	goto out_unlock;
359 
360     i_ipmi_domain_entity_unlock(domain);
361 
362     info->handler(sensor, info->cb_data);
363 
364     i_ipmi_sensor_put(sensor);
365     i_ipmi_entity_put(entity);
366     return;
367 
368  out_unlock:
369     i_ipmi_domain_entity_unlock(domain);
370     if (entity)
371 	i_ipmi_entity_put(entity);
372 }
373 
374 int
ipmi_sensor_pointer_cb(ipmi_sensor_id_t id,ipmi_sensor_ptr_cb handler,void * cb_data)375 ipmi_sensor_pointer_cb(ipmi_sensor_id_t   id,
376 		       ipmi_sensor_ptr_cb handler,
377 		       void               *cb_data)
378 {
379     int          rv;
380     mc_cb_info_t info;
381 
382     if (id.lun >= 5)
383 	return EINVAL;
384 
385     info.handler = handler;
386     info.cb_data = cb_data;
387     info.id = id;
388     info.err = 0;
389 
390     rv = ipmi_mc_pointer_cb(id.mcid, mc_cb, &info);
391     if (!rv)
392 	rv = info.err;
393 
394     return rv;
395 }
396 
397 int
ipmi_sensor_pointer_noseq_cb(ipmi_sensor_id_t id,ipmi_sensor_ptr_cb handler,void * cb_data)398 ipmi_sensor_pointer_noseq_cb(ipmi_sensor_id_t   id,
399 			     ipmi_sensor_ptr_cb handler,
400 			     void               *cb_data)
401 {
402     int          rv;
403     mc_cb_info_t info;
404 
405     if (id.lun >= 5)
406 	return EINVAL;
407 
408     info.handler = handler;
409     info.cb_data = cb_data;
410     info.id = id;
411     info.err = 0;
412 
413     rv = ipmi_mc_pointer_noseq_cb(id.mcid, mc_cb, &info);
414     if (!rv)
415 	rv = info.err;
416 
417     return rv;
418 }
419 
420 typedef struct sensor_find_info_s
421 {
422     ipmi_sensor_id_t id;
423     char             *id_name;
424     int              rv;
425 } sensor_find_info_t;
426 
427 static void
sensor_search_cmp(ipmi_entity_t * entity,ipmi_sensor_t * sensor,void * cb_data)428 sensor_search_cmp(ipmi_entity_t *entity, ipmi_sensor_t *sensor, void *cb_data)
429 {
430     sensor_find_info_t *info = cb_data;
431     char               id[33];
432     int                rv;
433 
434     rv = ipmi_sensor_get_id(sensor, id, 33);
435     if (rv)
436 	return;
437     if (strcmp(info->id_name, id) == 0) {
438 	info->id = ipmi_sensor_convert_to_id(sensor);
439 	info->rv = 0;
440     }
441 }
442 
443 static void
sensor_search(ipmi_entity_t * entity,void * cb_data)444 sensor_search(ipmi_entity_t *entity, void *cb_data)
445 {
446     sensor_find_info_t *info = cb_data;
447 
448     ipmi_entity_iterate_sensors(entity, sensor_search_cmp, info);
449 }
450 
451 int
ipmi_sensor_find_id(ipmi_domain_id_t domain_id,int entity_id,int entity_instance,int channel,int slave_address,char * id_name,ipmi_sensor_id_t * id)452 ipmi_sensor_find_id(ipmi_domain_id_t domain_id,
453 		    int entity_id, int entity_instance,
454 		    int channel, int slave_address,
455 		    char *id_name,
456 		    ipmi_sensor_id_t *id)
457 {
458     int                rv;
459     ipmi_entity_id_t   entity;
460     sensor_find_info_t info;
461 
462     rv = ipmi_entity_find_id(domain_id, entity_id, entity_instance,
463 			     channel, slave_address, &entity);
464     if (rv)
465 	return rv;
466 
467     info.id_name = id_name;
468     info.rv = EINVAL;
469 
470     rv = ipmi_entity_pointer_cb(entity, sensor_search, &info);
471     if (!rv)
472 	rv = info.rv;
473     if (!rv)
474 	*id = info.id;
475 
476     return rv;
477 }
478 
479 /***********************************************************************
480  *
481  * Various sensor allocation/deallocation/opq/etc.
482  *
483  **********************************************************************/
484 
485 static int
sensor_ok_to_use(ipmi_sensor_t * sensor)486 sensor_ok_to_use(ipmi_sensor_t *sensor)
487 {
488     return (   !sensor->destroyed
489 	    && !i_ipmi_domain_in_shutdown(sensor->domain));
490 }
491 
492 static void sensor_set_name(ipmi_sensor_t *sensor);
493 
494 static void
sensor_opq_ready2(ipmi_sensor_t * sensor,void * cb_data)495 sensor_opq_ready2(ipmi_sensor_t *sensor, void *cb_data)
496 {
497     ipmi_sensor_op_info_t *info = cb_data;
498     if (info->__handler)
499 	info->__handler(sensor, 0, info->__cb_data);
500 }
501 
502 static int
sensor_opq_ready(void * cb_data,int shutdown)503 sensor_opq_ready(void *cb_data, int shutdown)
504 {
505     ipmi_sensor_op_info_t *info = cb_data;
506     int                   rv;
507 
508     if (shutdown) {
509 	if (info->__handler)
510 	    info->__handler(info->__sensor, ECANCELED, info->__cb_data);
511 	return OPQ_HANDLER_STARTED;
512     }
513 
514     rv = ipmi_sensor_pointer_cb(info->__sensor_id, sensor_opq_ready2, info);
515     if (rv)
516 	if (info->__handler)
517 	    info->__handler(info->__sensor, rv, info->__cb_data);
518     return OPQ_HANDLER_STARTED;
519 }
520 
521 int
ipmi_sensor_add_opq(ipmi_sensor_t * sensor,ipmi_sensor_op_cb handler,ipmi_sensor_op_info_t * info,void * cb_data)522 ipmi_sensor_add_opq(ipmi_sensor_t         *sensor,
523 		    ipmi_sensor_op_cb     handler,
524 		    ipmi_sensor_op_info_t *info,
525 		    void                  *cb_data)
526 {
527     if (sensor->destroyed)
528 	return EINVAL;
529 
530     info->__sensor = sensor;
531     info->__sensor_id = ipmi_sensor_convert_to_id(sensor);
532     info->__cb_data = cb_data;
533     info->__handler = handler;
534     if (!opq_new_op(sensor->waitq, sensor_opq_ready, info, 0))
535 	return ENOMEM;
536     return 0;
537 }
538 
539 static void
sensor_id_add_opq_cb(ipmi_sensor_t * sensor,void * cb_data)540 sensor_id_add_opq_cb(ipmi_sensor_t *sensor, void *cb_data)
541 {
542     ipmi_sensor_op_info_t *info = cb_data;
543 
544     info->__sensor = sensor;
545     if (!opq_new_op(sensor->waitq, sensor_opq_ready, info, 0))
546 	info->__err = ENOMEM;
547 }
548 
549 int
ipmi_sensor_id_add_opq(ipmi_sensor_id_t sensor_id,ipmi_sensor_op_cb handler,ipmi_sensor_op_info_t * info,void * cb_data)550 ipmi_sensor_id_add_opq(ipmi_sensor_id_t      sensor_id,
551 		       ipmi_sensor_op_cb     handler,
552 		       ipmi_sensor_op_info_t *info,
553 		       void                  *cb_data)
554 {
555     int rv;
556 
557     info->__sensor_id = sensor_id;
558     info->__cb_data = cb_data;
559     info->__handler = handler;
560     info->__err = 0;
561     rv = ipmi_sensor_pointer_cb(sensor_id, sensor_id_add_opq_cb, info);
562     if (!rv)
563 	rv = info->__err;
564     return rv;
565 }
566 
567 void
ipmi_sensor_opq_done(ipmi_sensor_t * sensor)568 ipmi_sensor_opq_done(ipmi_sensor_t *sensor)
569 {
570     /* Protect myself from NULL sensors.  This way, it doesn't have to
571        be done in each call. */
572     if (!sensor)
573 	return;
574 
575     /* This gets called on ECANCELLED error cases, if the sensor is
576        already destroyed we need to clear out the opq. */
577     if (sensor->destroyed) {
578 	if (sensor->waitq) {
579 	    opq_destroy(sensor->waitq);
580 	    sensor->waitq = NULL;
581 	}
582 	return;
583     }
584 
585     /* No check for the sensor lock.  It will sometimes fail at
586        destruction time. */
587 
588     opq_op_done(sensor->waitq);
589 }
590 
591 static void
sensor_rsp_handler2(ipmi_sensor_t * sensor,void * cb_data)592 sensor_rsp_handler2(ipmi_sensor_t *sensor, void *cb_data)
593 {
594     ipmi_sensor_op_info_t *info = cb_data;
595 
596     if (info->__rsp_handler)
597 	info->__rsp_handler(sensor, 0, info->__rsp, info->__cb_data);
598 }
599 
600 static void
sensor_rsp_handler(ipmi_mc_t * mc,ipmi_msg_t * rsp,void * rsp_data)601 sensor_rsp_handler(ipmi_mc_t  *mc,
602 		   ipmi_msg_t *rsp,
603 		   void       *rsp_data)
604 {
605     ipmi_sensor_op_info_t *info = rsp_data;
606     int                   rv;
607     ipmi_sensor_t         *sensor = info->__sensor;
608     ipmi_entity_t         *entity = NULL;
609 
610     if (sensor->destroyed) {
611 	i_ipmi_domain_entity_lock(sensor->domain);
612 	sensor->usecount++;
613 	rv = i_ipmi_entity_get(sensor->entity);
614 	if (! rv)
615 	    entity = sensor->entity;
616 	i_ipmi_domain_entity_unlock(sensor->domain);
617 
618 	if (info->__rsp_handler)
619 	    info->__rsp_handler(sensor, ECANCELED, NULL, info->__cb_data);
620 
621 	i_ipmi_sensor_put(sensor);
622 	if (entity)
623 	    i_ipmi_entity_put(entity);
624 	return;
625     }
626 
627     if (!mc) {
628 	i_ipmi_domain_entity_lock(sensor->domain);
629 	sensor->usecount++;
630 	rv = i_ipmi_entity_get(sensor->entity);
631 	if (! rv)
632 	    entity = sensor->entity;
633 	i_ipmi_domain_entity_unlock(sensor->domain);
634 
635 	if (info->__rsp_handler)
636 	    info->__rsp_handler(sensor, ECANCELED, rsp, info->__cb_data);
637 
638 	i_ipmi_sensor_put(sensor);
639 	if (entity)
640 	    i_ipmi_entity_put(entity);
641 	return;
642     }
643 
644     /* Call the next stage with the lock held. */
645     info->__rsp = rsp;
646     rv = ipmi_sensor_pointer_cb(info->__sensor_id,
647 				sensor_rsp_handler2,
648 				info);
649     if (rv) {
650 	int nrv;
651 
652 	ipmi_log(IPMI_LOG_ERR_INFO,
653 		 "%ssensor.c(sensor_rsp_handler):"
654 		 " Could not convert sensor id to a pointer",
655 		 MC_NAME(mc));
656 
657 	i_ipmi_domain_entity_lock(sensor->domain);
658 	sensor->usecount++;
659 	nrv = i_ipmi_entity_get(sensor->entity);
660 	if (! nrv)
661 	    entity = sensor->entity;
662 	i_ipmi_domain_entity_unlock(sensor->domain);
663 
664 	if (info->__rsp_handler)
665 	    info->__rsp_handler(sensor, rv, NULL, info->__cb_data);
666 
667 	i_ipmi_sensor_put(sensor);
668 	if (entity)
669 	    i_ipmi_entity_put(entity);
670     }
671 }
672 
673 int
ipmi_sensor_send_command(ipmi_sensor_t * sensor,ipmi_mc_t * mc,unsigned int lun,ipmi_msg_t * msg,ipmi_sensor_rsp_cb handler,ipmi_sensor_op_info_t * info,void * cb_data)674 ipmi_sensor_send_command(ipmi_sensor_t         *sensor,
675 			 ipmi_mc_t             *mc,
676 			 unsigned int          lun,
677 			 ipmi_msg_t            *msg,
678 			 ipmi_sensor_rsp_cb    handler,
679 			 ipmi_sensor_op_info_t *info,
680 			 void                  *cb_data)
681 {
682     int rv;
683 
684     CHECK_MC_LOCK(mc);
685     CHECK_SENSOR_LOCK(sensor);
686 
687     if (sensor->destroyed)
688 	return EINVAL;
689 
690     info->__sensor = sensor;
691     info->__sensor_id = ipmi_sensor_convert_to_id(sensor);
692     info->__cb_data = cb_data;
693     info->__rsp_handler = handler;
694     rv = ipmi_mc_send_command(mc, lun, msg, sensor_rsp_handler, info);
695     return rv;
696 }
697 
698 static int
sensor_addr_response_handler(ipmi_domain_t * domain,ipmi_msgi_t * rspi)699 sensor_addr_response_handler(ipmi_domain_t *domain, ipmi_msgi_t *rspi)
700 {
701     ipmi_msg_t            *msg = &rspi->msg;
702     ipmi_sensor_op_info_t *info = rspi->data1;
703     int                   rv;
704     ipmi_sensor_t         *sensor = info->__sensor;
705 
706     if (sensor->destroyed) {
707 	if (info->__rsp_handler) {
708 	    i_ipmi_domain_mc_lock(sensor->domain);
709 	    i_ipmi_mc_get(sensor->mc);
710 	    i_ipmi_domain_mc_unlock(sensor->domain);
711 	    i_ipmi_domain_entity_lock(sensor->domain);
712 	    i_ipmi_entity_get(sensor->entity);
713 	    sensor->usecount++;
714 	    i_ipmi_domain_entity_unlock(sensor->domain);
715 	    info->__rsp_handler(NULL, ECANCELED, NULL, info->__cb_data);
716 	    i_ipmi_sensor_put(sensor);
717 	    i_ipmi_mc_put(sensor->mc);
718 	    i_ipmi_entity_put(sensor->entity);
719 	}
720 	return IPMI_MSG_ITEM_NOT_USED;
721     }
722 
723     /* Call the next stage with the lock held. */
724     info->__rsp = msg;
725     rv = ipmi_sensor_pointer_cb(info->__sensor_id,
726 				sensor_rsp_handler2,
727 				info);
728     if (rv) {
729 	ipmi_log(IPMI_LOG_ERR_INFO,
730 		 "%ssensor.c(sensor_addr_rsp_handler):"
731 		 " Could not convert sensor id to a pointer",
732 		 DOMAIN_NAME(domain));
733 	if (info->__rsp_handler) {
734 	    i_ipmi_domain_mc_lock(sensor->domain);
735 	    i_ipmi_mc_get(sensor->mc);
736 	    i_ipmi_domain_mc_unlock(sensor->domain);
737 	    i_ipmi_domain_entity_lock(sensor->domain);
738 	    i_ipmi_entity_get(sensor->entity);
739 	    sensor->usecount++;
740 	    i_ipmi_domain_entity_unlock(sensor->domain);
741 	    info->__rsp_handler(sensor, rv, NULL, info->__cb_data);
742 	    i_ipmi_sensor_put(sensor);
743 	    i_ipmi_mc_put(sensor->mc);
744 	    i_ipmi_entity_put(sensor->entity);
745 	}
746     }
747     return IPMI_MSG_ITEM_NOT_USED;
748 }
749 
750 int
ipmi_sensor_send_command_addr(ipmi_domain_t * domain,ipmi_sensor_t * sensor,ipmi_addr_t * addr,unsigned int addr_len,ipmi_msg_t * msg,ipmi_sensor_rsp_cb handler,ipmi_sensor_op_info_t * info,void * cb_data)751 ipmi_sensor_send_command_addr(ipmi_domain_t         *domain,
752 			      ipmi_sensor_t         *sensor,
753 			      ipmi_addr_t           *addr,
754 			      unsigned int          addr_len,
755 			      ipmi_msg_t            *msg,
756 			      ipmi_sensor_rsp_cb    handler,
757 			      ipmi_sensor_op_info_t *info,
758 			      void                  *cb_data)
759 {
760     int rv;
761 
762     CHECK_SENSOR_LOCK(sensor);
763     CHECK_MC_LOCK(sensor->mc);
764 
765     info->__sensor = sensor;
766     info->__sensor_id = ipmi_sensor_convert_to_id(sensor);
767     info->__cb_data = cb_data;
768     info->__rsp_handler = handler;
769     rv = ipmi_send_command_addr(domain, addr, addr_len,
770 				msg, sensor_addr_response_handler, info, NULL);
771     return rv;
772 }
773 
774 int
ipmi_sensors_alloc(ipmi_mc_t * mc,ipmi_sensor_info_t ** new_sensors)775 ipmi_sensors_alloc(ipmi_mc_t *mc, ipmi_sensor_info_t **new_sensors)
776 {
777     ipmi_sensor_info_t *sensors;
778     ipmi_domain_t      *domain;
779     os_handler_t       *os_hnd;
780     int                i;
781     int                rv;
782 
783     CHECK_MC_LOCK(mc);
784 
785     domain = ipmi_mc_get_domain(mc);
786     os_hnd = ipmi_domain_get_os_hnd(domain);
787 
788     sensors = ipmi_mem_alloc(sizeof(*sensors));
789     if (!sensors)
790 	return ENOMEM;
791 
792     rv = ipmi_create_lock_os_hnd(os_hnd, &sensors->idx_lock);
793     if (rv) {
794 	ipmi_mem_free(sensors);
795 	return rv;
796     }
797 
798     sensors->destroyed = 0;
799     sensors->sensor_count = 0;
800     for (i=0; i<5; i++) {
801 	sensors->sensors_by_idx[i] = NULL;
802 	sensors->idx_size[i] = 0;
803     }
804 
805     *new_sensors = sensors;
806     return 0;
807 }
808 
809 unsigned int
ipmi_sensors_get_count(ipmi_sensor_info_t * sensors)810 ipmi_sensors_get_count(ipmi_sensor_info_t *sensors)
811 {
812     return sensors->sensor_count;
813 }
814 
815 int
ipmi_sensor_alloc_nonstandard(ipmi_sensor_t ** new_sensor)816 ipmi_sensor_alloc_nonstandard(ipmi_sensor_t **new_sensor)
817 {
818     ipmi_sensor_t *sensor;
819 
820     sensor = ipmi_mem_alloc(sizeof(*sensor));
821     if (!sensor)
822 	return ENOMEM;
823 
824     memset(sensor, 0, sizeof(*sensor));
825 
826     sensor->hot_swap_requester = -1;
827     sensor->usecount = 1;
828     sensor->readable = 1;
829 
830     *new_sensor = sensor;
831     return 0;
832 }
833 
834 int
ipmi_sensor_add_nonstandard(ipmi_mc_t * mc,ipmi_mc_t * source_mc,ipmi_sensor_t * sensor,unsigned int num,unsigned int send_lun,ipmi_entity_t * ent,ipmi_sensor_destroy_cb destroy_handler,void * destroy_handler_cb_data)835 ipmi_sensor_add_nonstandard(ipmi_mc_t              *mc,
836 			    ipmi_mc_t              *source_mc,
837 			    ipmi_sensor_t          *sensor,
838 			    unsigned int           num,
839 			    unsigned int           send_lun,
840 			    ipmi_entity_t          *ent,
841 			    ipmi_sensor_destroy_cb destroy_handler,
842 			    void                   *destroy_handler_cb_data)
843 {
844     ipmi_sensor_info_t *sensors = i_ipmi_mc_get_sensors(mc);
845     ipmi_domain_t      *domain;
846     os_handler_t       *os_hnd;
847     void               *link;
848     int                err;
849     unsigned int       i;
850 
851     CHECK_MC_LOCK(mc);
852     CHECK_ENTITY_LOCK(ent);
853 
854     domain = ipmi_mc_get_domain(mc);
855     os_hnd = ipmi_domain_get_os_hnd(domain);
856 
857     if ((num >= 256) && (num != UINT_MAX))
858 	return EINVAL;
859 
860     i_ipmi_domain_entity_lock(domain);
861     ipmi_lock(sensors->idx_lock);
862 
863     if (num == UINT_MAX){
864 	for (i=0; i<sensors->idx_size[4]; i++) {
865 	    if (! sensors->sensors_by_idx[4][i])
866 		break;
867 	}
868 	num = i;
869 	if (num >= 256) {
870 	    err = EAGAIN;
871 	    goto out_err;
872 	}
873     }
874 
875     if (num >= sensors->idx_size[4]) {
876 	ipmi_sensor_t **new_array;
877 	unsigned int  new_size;
878 	unsigned int  i;
879 
880 	/* Allocate the array in multiples of 16 (to avoid thrashing malloc
881 	   too much). */
882 	new_size = ((num / 16) * 16) + 16;
883 	new_array = ipmi_mem_alloc(sizeof(*new_array) * new_size);
884 	if (!new_array) {
885 	    err = ENOMEM;
886 	    goto out_err;
887 	}
888 	if (sensors->sensors_by_idx[4]) {
889 	    memcpy(new_array, sensors->sensors_by_idx[4],
890 		   sizeof(*new_array) * (sensors->idx_size[4]));
891 	    ipmi_mem_free(sensors->sensors_by_idx[4]);
892 	}
893 	for (i=sensors->idx_size[4]; i<new_size; i++)
894 	    new_array[i] = NULL;
895 	sensors->sensors_by_idx[4] = new_array;
896 	sensors->idx_size[4] = new_size;
897     }
898 
899     sensor->waitq = opq_alloc(os_hnd);
900     if (! sensor->waitq) {
901 	err = ENOMEM;
902 	goto out_err;
903     }
904 
905     sensor->handler_list = locked_list_alloc(os_hnd);
906     if (! sensor->handler_list) {
907 	opq_destroy(sensor->waitq);
908 	err = ENOMEM;
909 	goto out_err;
910     }
911 
912     sensor->handler_list_cl = locked_list_alloc(os_hnd);
913     if (! sensor->handler_list_cl) {
914 	locked_list_destroy(sensor->handler_list);
915 	opq_destroy(sensor->waitq);
916 	err = ENOMEM;
917 	goto out_err;
918     }
919 
920     link = locked_list_alloc_entry();
921     if (!link) {
922 	opq_destroy(sensor->waitq);
923 	sensor->waitq = NULL;
924 	locked_list_destroy(sensor->handler_list);
925 	locked_list_destroy(sensor->handler_list_cl);
926 	sensor->handler_list = NULL;
927 	err = ENOMEM;
928 	goto out_err;
929     }
930 
931     sensor->domain = domain;
932     sensor->mc = mc;
933     sensor->source_mc = source_mc;
934     sensor->lun = 4;
935     sensor->send_lun = send_lun;
936     sensor->num = num;
937     sensor->source_idx = -1;
938     sensor->source_array = NULL;
939     if (!sensors->sensors_by_idx[4][num])
940 	sensors->sensor_count++;
941     sensors->sensors_by_idx[4][num] = sensor;
942     sensor->entity = ent;
943     sensor->entity_id = ipmi_entity_get_entity_id(ent);
944     sensor->entity_instance = ipmi_entity_get_entity_instance(ent);
945     sensor->destroy_handler = destroy_handler;
946     sensor->destroy_handler_cb_data = destroy_handler_cb_data;
947     sensor_set_name(sensor);
948 
949     ipmi_unlock(sensors->idx_lock);
950 
951     i_ipmi_domain_entity_unlock(domain);
952 
953     ipmi_entity_add_sensor(ent, sensor, link);
954 
955     sensor->add_pending = 1;
956 
957     return 0;
958 
959  out_err:
960     ipmi_unlock(sensors->idx_lock);
961     i_ipmi_domain_entity_unlock(domain);
962     return err;
963 }
964 
965 typedef struct threshold_handler_cl_info_s
966 {
967     ipmi_sensor_threshold_event_cb handler;
968     void                           *handler_data;
969 } threshold_handler_cl_info_t;
970 
971 static int
iterate_threshold_handler_cl(void * cb_data,void * item1,void * item2)972 iterate_threshold_handler_cl(void *cb_data, void *item1, void *item2)
973 {
974     threshold_handler_cl_info_t       *info = cb_data;
975     ipmi_sensor_threshold_event_cl_cb handler = item1;
976 
977     handler(info->handler, info->handler_data, item2);
978     return LOCKED_LIST_ITER_CONTINUE;
979 }
980 
981 typedef struct discrete_handler_cl_info_s
982 {
983     ipmi_sensor_discrete_event_cb handler;
984     void                          *handler_data;
985 } discrete_handler_cl_info_t;
986 
987 static int
iterate_discrete_handler_cl(void * cb_data,void * item1,void * item2)988 iterate_discrete_handler_cl(void *cb_data, void *item1, void *item2)
989 {
990     discrete_handler_cl_info_t       *info = cb_data;
991     ipmi_sensor_discrete_event_cl_cb handler = item1;
992 
993     handler(info->handler, info->handler_data, item2);
994     return LOCKED_LIST_ITER_CONTINUE;
995 }
996 
997 static int
handler_list_cleanup(void * cb_data,void * item1,void * item2)998 handler_list_cleanup(void *cb_data, void *item1, void *item2)
999 {
1000     ipmi_sensor_t *sensor = cb_data;
1001 
1002     if (sensor->event_reading_type == IPMI_EVENT_READING_TYPE_THRESHOLD) {
1003 	threshold_handler_cl_info_t info;
1004 	info.handler = item1;
1005 	info.handler_data = item2;
1006 	locked_list_iterate(sensor->handler_list_cl,
1007 			    iterate_threshold_handler_cl,
1008 			    &info);
1009     } else {
1010 	discrete_handler_cl_info_t info;
1011 	info.handler = item1;
1012 	info.handler_data = item2;
1013 	locked_list_iterate(sensor->handler_list_cl,
1014 			    iterate_discrete_handler_cl,
1015 			    &info);
1016     }
1017     return LOCKED_LIST_ITER_CONTINUE;
1018 }
1019 
1020 static void
sensor_final_destroy(ipmi_sensor_t * sensor)1021 sensor_final_destroy(ipmi_sensor_t *sensor)
1022 {
1023     i_ipmi_entity_get(sensor->entity);
1024     i_ipmi_entity_call_sensor_handlers(sensor->entity, sensor, IPMI_DELETED);
1025 
1026     sensor->mc = NULL;
1027 
1028     if (sensor->destroy_handler)
1029 	sensor->destroy_handler(sensor, sensor->destroy_handler_cb_data);
1030 
1031     if (sensor->waitq)
1032 	opq_destroy(sensor->waitq);
1033 
1034     if (sensor->handler_list) {
1035 	locked_list_iterate(sensor->handler_list, handler_list_cleanup,
1036 			    sensor);
1037 	locked_list_destroy(sensor->handler_list);
1038     }
1039 
1040     if (sensor->handler_list_cl)
1041 	locked_list_destroy(sensor->handler_list_cl);
1042 
1043     ipmi_entity_remove_sensor(sensor->entity, sensor);
1044 
1045     if (sensor->oem_info_cleanup_handler)
1046 	sensor->oem_info_cleanup_handler(sensor, sensor->oem_info);
1047 
1048     i_ipmi_entity_put(sensor->entity);
1049     ipmi_mem_free(sensor);
1050 }
1051 
1052 int
ipmi_sensor_destroy(ipmi_sensor_t * sensor)1053 ipmi_sensor_destroy(ipmi_sensor_t *sensor)
1054 {
1055     ipmi_sensor_info_t *sensors;
1056     ipmi_mc_t          *mc = sensor->mc;
1057 
1058     i_ipmi_domain_mc_lock(sensor->domain);
1059     i_ipmi_mc_get(mc);
1060     i_ipmi_domain_mc_unlock(sensor->domain);
1061     sensors = i_ipmi_mc_get_sensors(sensor->mc);
1062 
1063     ipmi_lock(sensors->idx_lock);
1064     if (sensor == sensors->sensors_by_idx[sensor->lun][sensor->num]) {
1065 	sensors->sensor_count--;
1066 	sensors->sensors_by_idx[sensor->lun][sensor->num] = NULL;
1067     }
1068 
1069     i_ipmi_sensor_get(sensor);
1070 
1071     if (sensor->source_array)
1072 	sensor->source_array[sensor->source_idx] = NULL;
1073 
1074     ipmi_unlock(sensors->idx_lock);
1075 
1076     sensor->destroyed = 1;
1077     i_ipmi_sensor_put(sensor);
1078     i_ipmi_mc_put(mc);
1079     return 0;
1080 }
1081 
1082 int
ipmi_sensors_destroy(ipmi_sensor_info_t * sensors)1083 ipmi_sensors_destroy(ipmi_sensor_info_t *sensors)
1084 {
1085     unsigned int i, j;
1086 
1087     if (sensors->destroyed)
1088 	return EINVAL;
1089 
1090     sensors->destroyed = 1;
1091     for (i=0; i<=4; i++) {
1092 	for (j=0; j<sensors->idx_size[i]; j++) {
1093 	    if (sensors->sensors_by_idx[i][j]) {
1094 		ipmi_sensor_destroy(sensors->sensors_by_idx[i][j]);
1095 	    }
1096 	}
1097 	if (sensors->sensors_by_idx[i])
1098 	    ipmi_mem_free(sensors->sensors_by_idx[i]);
1099     }
1100     if (sensors->idx_lock)
1101 	ipmi_destroy_lock(sensors->idx_lock);
1102     ipmi_mem_free(sensors);
1103     return 0;
1104 }
1105 
1106 static void
sensor_set_name(ipmi_sensor_t * sensor)1107 sensor_set_name(ipmi_sensor_t *sensor)
1108 {
1109     int length;
1110 
1111     length = ipmi_entity_get_name(sensor->entity, sensor->name,
1112 				  sizeof(sensor->name)-2);
1113     sensor->name[length] = '.';
1114     length++;
1115     length += snprintf(sensor->name+length, IPMI_SENSOR_NAME_LEN-length-2,
1116 		       "%s", sensor->id);
1117     sensor->name[length] = ' ';
1118     length++;
1119     sensor->name[length] = '\0';
1120     length++;
1121 }
1122 
1123 const char *
i_ipmi_sensor_name(const ipmi_sensor_t * sensor)1124 i_ipmi_sensor_name(const ipmi_sensor_t *sensor)
1125 {
1126     return sensor->name;
1127 }
1128 
1129 int
ipmi_sensor_get_name(ipmi_sensor_t * sensor,char * name,int length)1130 ipmi_sensor_get_name(ipmi_sensor_t *sensor, char *name, int length)
1131 {
1132     int  slen;
1133 
1134     if (length <= 0)
1135 	return 0;
1136 
1137     /* Never changes, no lock needed. */
1138     slen = strlen(sensor->name);
1139     if (slen == 0) {
1140 	if (name)
1141 	    *name = '\0';
1142 	goto out;
1143     }
1144 
1145     slen -= 1; /* Remove the trailing ' ' */
1146     if (slen >= length)
1147 	slen = length - 1;
1148 
1149     if (name) {
1150 	memcpy(name, sensor->name, slen);
1151 	name[slen] = '\0';
1152     }
1153  out:
1154     return slen;
1155 }
1156 
1157 /***********************************************************************
1158  *
1159  * Sensor SDR handling
1160  *
1161  **********************************************************************/
1162 
1163 static int
get_sensors_from_sdrs(ipmi_domain_t * domain,ipmi_mc_t * source_mc,ipmi_sdr_info_t * sdrs,ipmi_sensor_t *** sensors,unsigned int * sensor_count)1164 get_sensors_from_sdrs(ipmi_domain_t      *domain,
1165 		      ipmi_mc_t          *source_mc,
1166 		      ipmi_sdr_info_t    *sdrs,
1167 		      ipmi_sensor_t      ***sensors,
1168 		      unsigned int       *sensor_count)
1169 {
1170     ipmi_sdr_t    sdr;
1171     unsigned int  count;
1172     ipmi_sensor_t **s = NULL;
1173     unsigned int  p, s_size = 0;
1174     int           val;
1175     int           rv;
1176     unsigned int  i;
1177     int           j;
1178     int           share_count;
1179     int           id_string_mod_type;
1180     int           entity_instance_incr;
1181     int           id_string_modifier_offset;
1182     unsigned char *str;
1183     unsigned int  str_len;
1184 
1185 
1186     rv = ipmi_get_sdr_count(sdrs, &count);
1187     if (rv) {
1188 	ipmi_log(IPMI_LOG_WARNING,
1189 		 "%ssensor.c(get_sensors_from_sdrs):"
1190 		 " Could not fetch SDR count fron the SDR record.",
1191 		 MC_NAME(source_mc));
1192 	goto out_err;
1193     }
1194 
1195     /* Get a real count on the number of sensors, since a single SDR can
1196        contain multiple sensors. */
1197     p = 0;
1198     for (i=0; i<count; i++) {
1199 	int incr;
1200 
1201 	rv = ipmi_get_sdr_by_index(sdrs, i, &sdr);
1202 	if (rv) {
1203 	    ipmi_log(IPMI_LOG_WARNING,
1204 		     "%ssensor.c(get_sensors_from_sdrs):"
1205 		     " SDR record %d could not be fetched from the SDR"
1206 		     " record: %d",
1207 		     MC_NAME(source_mc), i, rv);
1208 	    goto out_err;
1209 	}
1210 
1211 	if (sdr.type == 1) {
1212 	    incr = 1;
1213 	} else if (sdr.type == 2) {
1214 	    if (sdr.data[18] & 0x0f)
1215 		incr = sdr.data[18] & 0x0f;
1216 	    else
1217 		incr = 1;
1218 	} else if (sdr.type == 3) {
1219 	    if (sdr.data[7] & 0x0f)
1220 		incr = sdr.data[7] & 0x0f;
1221 	    else
1222 		incr = 1;
1223 	} else
1224 	    continue;
1225 
1226 	p += incr;
1227     }
1228     if (!p)
1229 	return 0;
1230 
1231     /* Setup memory to hold the sensors. */
1232     s = ipmi_mem_alloc(sizeof(*s) * p);
1233     if (!s)
1234 	goto out_err_enomem;
1235     s_size = p;
1236     memset(s, 0, sizeof(*s) * p);
1237 
1238     p = 0;
1239     for (i=0; i<count; i++) {
1240 	rv = ipmi_get_sdr_by_index(sdrs, i, &sdr);
1241 	if (rv) {
1242 	    ipmi_log(IPMI_LOG_WARNING,
1243 		     "%ssensor.c(get_sensors_from_sdrs):"
1244 		     " SDR record %d could not be fetched from the SDR"
1245 		     " record index: %d (2)",
1246 		     MC_NAME(source_mc), i, rv);
1247 	    goto out_err;
1248 	}
1249 
1250 	if ((sdr.type != 1) && (sdr.type != 2) && (sdr.type != 3))
1251 	    continue;
1252 
1253 	s[p] = ipmi_mem_alloc(sizeof(*s[p]));
1254 	if (!s[p])
1255 	    goto out_err_enomem;
1256 	memset(s[p], 0, sizeof(*s[p]));
1257 
1258 	s[p]->source_recid = sdr.record_id;
1259 	s[p]->hot_swap_requester = -1;
1260 
1261 	s[p]->waitq = opq_alloc(ipmi_domain_get_os_hnd(domain));
1262 	if (!s[p]->waitq)
1263 	    goto out_err_enomem;
1264 
1265 	s[p]->handler_list_cl
1266 	    = locked_list_alloc(ipmi_domain_get_os_hnd(domain));
1267 	if (! s[p]->handler_list_cl) {
1268 	    opq_destroy(s[p]->waitq);
1269 	    goto out_err_enomem;
1270 	}
1271 
1272 	s[p]->handler_list = locked_list_alloc(ipmi_domain_get_os_hnd(domain));
1273 	if (! s[p]->handler_list) {
1274 	    locked_list_destroy(s[i]->handler_list_cl);
1275 	    opq_destroy(s[p]->waitq);
1276 	    goto out_err_enomem;
1277 	}
1278 
1279 	s[p]->destroyed = 0;
1280 	s[p]->destroy_handler = NULL;
1281 
1282 	rv = i_ipmi_find_or_create_mc_by_slave_addr(domain,
1283 						    sdr.data[1] >> 4,
1284 						    sdr.data[0],
1285 						    &(s[p]->mc));
1286 	if (rv) {
1287 	    ipmi_log(IPMI_LOG_WARNING,
1288 		     "%ssensor.c(get_sensors_from_sdrs):"
1289 		     " Could not create MC for SDR record %d, channel %d"
1290 		     " owner 0x%x: %d",
1291 		     MC_NAME(source_mc), i, sdr.data[1] >> 4, sdr.data[0], rv);
1292 	    goto out_err;
1293 	}
1294 
1295 	share_count = 0;
1296 	id_string_mod_type = 0;
1297 	entity_instance_incr = 0;
1298 	id_string_modifier_offset = 0;
1299 
1300 	s[p]->usecount = 1;
1301 	s[p]->domain = domain;
1302 	s[p]->source_mc = source_mc;
1303 	s[p]->source_idx = p;
1304 	s[p]->source_array = s;
1305 	s[p]->owner = sdr.data[0];
1306 	s[p]->channel = sdr.data[1] >> 4;
1307 	s[p]->lun = sdr.data[1] & 0x03;
1308 	s[p]->send_lun = s[p]->lun;
1309 	s[p]->num = sdr.data[2];
1310 	s[p]->entity_id = sdr.data[3];
1311 	s[p]->entity_instance_logical = sdr.data[4] >> 7;
1312 	s[p]->entity_instance = sdr.data[4] & 0x7f;
1313 	if ((sdr.type == 1) || (sdr.type == 2)) {
1314 	    s[p]->readable = 1;
1315 
1316 	    s[p]->sensor_init_scanning = (sdr.data[5] >> 6) & 1;
1317 	    s[p]->sensor_init_events = (sdr.data[5] >> 5) & 1;
1318 	    s[p]->sensor_init_thresholds = (sdr.data[5] >> 4) & 1;
1319 	    s[p]->sensor_init_hysteresis = (sdr.data[5] >> 3) & 1;
1320 	    s[p]->sensor_init_type = (sdr.data[5] >> 2) & 1;
1321 	    s[p]->sensor_init_pu_events = (sdr.data[5] >> 1) & 1;
1322 	    s[p]->sensor_init_pu_scanning = (sdr.data[5] >> 0) & 1;
1323 	    s[p]->ignore_if_no_entity = (sdr.data[6] >> 7) & 1;
1324 	    s[p]->supports_auto_rearm = (sdr.data[6] >> 6) & 1 ;
1325 	    s[p]->hysteresis_support = (sdr.data[6] >> 4) & 3;
1326 	    s[p]->threshold_access = (sdr.data[6] >> 2) & 3;
1327 	    s[p]->event_support = sdr.data[6] & 3;
1328 	    s[p]->sensor_type = sdr.data[7];
1329 	    s[p]->event_reading_type = sdr.data[8];
1330 
1331 	    s[p]->mask1 = ipmi_get_uint16(sdr.data+9);
1332 	    s[p]->mask2 = ipmi_get_uint16(sdr.data+11);
1333 	    s[p]->mask3 = ipmi_get_uint16(sdr.data+13);
1334 
1335 	    s[p]->analog_data_format = (sdr.data[15] >> 6) & 3;
1336 	    s[p]->rate_unit = (sdr.data[15] >> 3) & 7;
1337 	    s[p]->modifier_unit_use = (sdr.data[15] >> 1) & 3;
1338 	    s[p]->percentage = sdr.data[15] & 1;
1339 	    s[p]->base_unit = sdr.data[16];
1340 	    s[p]->modifier_unit = sdr.data[17];
1341 	}
1342 
1343 	if (sdr.type == 1) {
1344 	    /* A full sensor record. */
1345 	    s[p]->linearization = sdr.data[18] & 0x7f;
1346 
1347 	    if (s[p]->linearization <= 11) {
1348 		for (j=0; j<256; j++) {
1349 		    s[p]->conv[j].m = sdr.data[19] | ((sdr.data[20] & 0xc0) << 2);
1350 		    s[p]->conv[j].tolerance = sdr.data[20] & 0x3f;
1351 		    s[p]->conv[j].b = sdr.data[21] | ((sdr.data[22] & 0xc0) << 2);
1352 		    s[p]->conv[j].accuracy = ((sdr.data[22] & 0x3f)
1353 					     | ((sdr.data[23] & 0xf0) << 2));
1354 		    s[p]->conv[j].accuracy_exp = (sdr.data[23] >> 2) & 0x3;
1355 		    s[p]->conv[j].r_exp = (sdr.data[24] >> 4) & 0xf;
1356 		    s[p]->conv[j].b_exp = sdr.data[24] & 0xf;
1357 		}
1358 	    }
1359 
1360 	    s[p]->sensor_direction = sdr.data[23] & 0x3;
1361 	    s[p]->normal_min_specified = (sdr.data[25] >> 2) & 1;
1362 	    s[p]->normal_max_specified = (sdr.data[25] >> 1) & 1;
1363 	    s[p]->nominal_reading_specified = sdr.data[25] & 1;
1364 	    s[p]->nominal_reading = sdr.data[26];
1365 	    s[p]->normal_max = sdr.data[27];
1366 	    s[p]->normal_min = sdr.data[28];
1367 	    s[p]->sensor_max = sdr.data[29];
1368 	    s[p]->sensor_min = sdr.data[30];
1369 	    s[p]->default_thresholds[IPMI_UPPER_NON_RECOVERABLE]= sdr.data[31];
1370 	    s[p]->default_thresholds[IPMI_UPPER_CRITICAL] = sdr.data[32];
1371 	    s[p]->default_thresholds[IPMI_UPPER_NON_CRITICAL] = sdr.data[33];
1372 	    s[p]->default_thresholds[IPMI_LOWER_NON_RECOVERABLE] = sdr.data[34];
1373 	    s[p]->default_thresholds[IPMI_LOWER_CRITICAL] = sdr.data[35];
1374 	    s[p]->default_thresholds[IPMI_LOWER_NON_CRITICAL] = sdr.data[36];
1375 	    s[p]->positive_going_threshold_hysteresis = sdr.data[37];
1376 	    s[p]->negative_going_threshold_hysteresis = sdr.data[38];
1377 	    s[p]->oem1 = sdr.data[41];
1378 
1379 	    str = sdr.data + 42;
1380 	    str_len = sdr.length - 42;
1381 
1382 	    if (s[p]->entity)
1383 		sensor_set_name(s[p]);
1384 	} else if (sdr.type == 2) {
1385 	    /* FIXME - make sure this is not a threshold sensor.  The
1386                question is, what do I do if it is? */
1387 	    /* A short sensor record. */
1388 
1389 	    s[p]->sensor_direction = (sdr.data[18] >> 6) & 0x3;
1390 
1391 	    s[p]->positive_going_threshold_hysteresis = sdr.data[20];
1392 	    s[p]->negative_going_threshold_hysteresis = sdr.data[21];
1393 	    s[p]->oem1 = sdr.data[25];
1394 
1395 	    str = sdr.data + 26;
1396 	    str_len = sdr.length - 26;
1397 
1398 	    share_count = sdr.data[18] & 0x0f;
1399 	    if (share_count == 0)
1400 		share_count = 1;
1401 	    id_string_mod_type = (sdr.data[18] >> 4) & 0x3;
1402 	    entity_instance_incr = (sdr.data[19] >> 7) & 0x01;
1403 	    id_string_modifier_offset = sdr.data[19] & 0x7f;
1404 	} else {
1405 	    /* Event-only sensor.  It is not readable. */
1406 
1407 	    s[p]->sensor_type = sdr.data[5];
1408 	    s[p]->event_reading_type = sdr.data[6];
1409 	    s[p]->oem1 = sdr.data[9];
1410 
1411 	    str = sdr.data + 10;
1412 	    str_len = sdr.length - 10;
1413 
1414 	    share_count = sdr.data[7] & 0x0f;
1415 	    if (share_count == 0)
1416 		share_count = 1;
1417 	    id_string_mod_type = (sdr.data[7] >> 4) & 0x3;
1418 	    entity_instance_incr = (sdr.data[8] >> 7) & 0x01;
1419 	    id_string_modifier_offset = sdr.data[8] & 0x7f;
1420 	}
1421 
1422 	rv = ipmi_get_device_string(&str, str_len,
1423 				    s[p]->id, IPMI_STR_SDR_SEMANTICS, 0,
1424 				    &s[p]->id_type, SENSOR_ID_LEN,
1425 				    &s[p]->id_len);
1426 	if (rv) {
1427 	    ipmi_log(IPMI_LOG_WARNING,
1428 		     "%ssensor.c(get_sensors_from_sdrs):"
1429 		     " Error getting device ID string from SDR record %d: %d,"
1430 		     " this sensor will be named **INVALID**",
1431 		     MC_NAME(source_mc), sdr.record_id, rv);
1432 	    strncpy(s[p]->id, "**INVALID**", sizeof(s[p]->id));
1433 	    s[p]->id_len = strlen(s[p]->id);
1434 	    s[p]->id_type = IPMI_ASCII_STR;
1435 	}
1436 
1437 	if (share_count > 1) {
1438 	    /* Duplicate the sensor records for each instance.  Go
1439 	       backwards to avoid destroying the first one until we
1440 	       finish the others. */
1441 	    for (j=share_count-1; j>=0; j--) {
1442 		int len;
1443 
1444 		if (j != 0) {
1445 		    /* The first one is already allocated, we are
1446                        using it to copy to the other ones, so this is
1447                        not necessary.  We still have to iterate the
1448                        first one to set its string name, though. */
1449 		    s[p+j] = ipmi_mem_alloc(sizeof(ipmi_sensor_t));
1450 		    if (!s[p+j])
1451 			goto out_err_enomem;
1452 		    memcpy(s[p+j], s[p], sizeof(ipmi_sensor_t));
1453 
1454 		    /* In case of error */
1455 		    s[p+j]->handler_list = NULL;
1456 
1457 		    /* For every sensor except the first, increment the usage
1458 		       count for the MC so that it will decrement properly.
1459 		       This cannot fail because we have already gotten it
1460 		       before. */
1461 		    i_ipmi_find_or_create_mc_by_slave_addr(domain,
1462 							   s[p+j]->channel,
1463 							   s[p+j]->owner,
1464 							   &(s[p+j]->mc));
1465 
1466 		    s[p+j]->waitq = opq_alloc(ipmi_domain_get_os_hnd(domain));
1467 		    if (!s[p+j]->waitq)
1468 			goto out_err_enomem;
1469 
1470 		    s[p+j]->handler_list_cl
1471 			= locked_list_alloc(ipmi_domain_get_os_hnd(domain));
1472 		    if (! s[p+j]->handler_list_cl)
1473 			goto out_err_enomem;
1474 
1475 		    s[p+j]->handler_list
1476 			= locked_list_alloc(ipmi_domain_get_os_hnd(domain));
1477 		    if (! s[p+j]->handler_list)
1478 			goto out_err_enomem;
1479 
1480 		    s[p+j]->num += j;
1481 
1482 		    if (entity_instance_incr & 0x80) {
1483 			s[p+j]->entity_instance += j;
1484 		    }
1485 
1486 		    s[p+j]->source_idx += j;
1487 		}
1488 
1489 		val = id_string_modifier_offset + j;
1490 		len = s[p+j]->id_len;
1491 		switch (id_string_mod_type) {
1492 		    case 0: /* Numeric */
1493 			if ((val / 10) > 0) {
1494 			    if (len < SENSOR_ID_LEN) {
1495 				s[p+j]->id[len] = (val/10) + '0';
1496 				len++;
1497 			    }
1498 			}
1499 			if (len < SENSOR_ID_LEN) {
1500 			    s[p+j]->id[len] = (val%10) + '0';
1501 			    len++;
1502 			}
1503 			break;
1504 		    case 1: /* Alpha */
1505 			if ((val / 26) > 0) {
1506 			    if (len < SENSOR_ID_LEN) {
1507 				s[p+j]->id[len] = (val/26) + 'A';
1508 				len++;
1509 			    }
1510 			}
1511 			if (len < SENSOR_ID_LEN) {
1512 			    s[p+j]->id[len] = (val%26) + 'A';
1513 			    len++;
1514 			}
1515 			break;
1516 		    /* FIXME - unicode handling? */
1517 		}
1518 		s[p+j]->id_len = len;
1519 		if (s[p+j]->entity)
1520 		    sensor_set_name(s[p+j]);
1521 	    }
1522 
1523 	    p += share_count;
1524 	} else
1525 	    p++;
1526     }
1527 
1528     *sensors = s;
1529     *sensor_count = s_size;
1530     return 0;
1531 
1532  out_err_enomem:
1533     rv = ENOMEM;
1534     ipmi_log(IPMI_LOG_WARNING,
1535 	     "%ssensor.c(get_sensors_from_sdrs):"
1536 	     " Out of memory while processing the SDRS.",
1537 	     MC_NAME(source_mc));
1538  out_err:
1539     if (s) {
1540 	for (i=0; i<s_size; i++)
1541 	    if (s[i]) {
1542 		if (s[i]->mc)
1543 		    i_ipmi_mc_put(s[i]->mc);
1544 		if (s[i]->waitq)
1545 		    opq_destroy(s[i]->waitq);
1546 		if (s[i]->handler_list)
1547 		    locked_list_destroy(s[i]->handler_list);
1548 		if (s[i]->handler_list_cl)
1549 		    locked_list_destroy(s[i]->handler_list_cl);
1550 		ipmi_mem_free(s[i]);
1551 	    }
1552 	ipmi_mem_free(s);
1553     }
1554     return rv;
1555 }
1556 
1557 static void
handle_new_sensor(ipmi_domain_t * domain,ipmi_sensor_t * sensor,void * link)1558 handle_new_sensor(ipmi_domain_t *domain,
1559 		  ipmi_sensor_t *sensor,
1560 		  void          *link)
1561 {
1562     /* Call this before the OEM call so the OEM call can replace it. */
1563     sensor->cbs = ipmi_standard_sensor_cb;
1564     sensor->sensor_type_string
1565 	= ipmi_get_sensor_type_string(sensor->sensor_type);
1566     sensor->event_reading_type_string
1567 	= ipmi_get_event_reading_type_string(sensor->event_reading_type);
1568     sensor->rate_unit_string
1569 	= ipmi_get_rate_unit_string(sensor->rate_unit);
1570     sensor->base_unit_string
1571 	= ipmi_get_unit_type_string(sensor->base_unit);
1572     sensor->modifier_unit_string
1573 	= ipmi_get_unit_type_string(sensor->modifier_unit);
1574 
1575     sensor_set_name(sensor);
1576 
1577     if ((sensor->source_mc)
1578 	&& (i_ipmi_mc_new_sensor(sensor->source_mc, sensor->entity,
1579 				 sensor, link)))
1580     {
1581         /* Nothing to do, OEM code handled the sensor. */
1582     } else {
1583 	ipmi_entity_add_sensor(sensor->entity, sensor, link);
1584     }
1585 
1586     i_call_new_sensor_handlers(domain, sensor);
1587 }
1588 
cmp_sensor(ipmi_sensor_t * s1,ipmi_sensor_t * s2)1589 static int cmp_sensor(ipmi_sensor_t *s1,
1590 		      ipmi_sensor_t *s2)
1591 {
1592     int i;
1593 
1594     if (s1->entity_instance_logical != s2->entity_instance_logical) return 0;
1595     if (s1->sensor_init_scanning != s2->sensor_init_scanning) return 0;
1596     if (s1->sensor_init_events != s2->sensor_init_events) return 0;
1597     if (s1->sensor_init_thresholds != s2->sensor_init_thresholds) return 0;
1598     if (s1->sensor_init_hysteresis != s2->sensor_init_hysteresis) return 0;
1599     if (s1->sensor_init_type != s2->sensor_init_type) return 0;
1600     if (s1->sensor_init_pu_events != s2->sensor_init_pu_events) return 0;
1601     if (s1->sensor_init_pu_scanning != s2->sensor_init_pu_scanning) return 0;
1602     if (s1->ignore_if_no_entity != s2->ignore_if_no_entity) return 0;
1603     if (s1->supports_auto_rearm != s2->supports_auto_rearm) return 0;
1604     if (s1->hysteresis_support != s2->hysteresis_support) return 0;
1605     if (s1->threshold_access != s2->threshold_access) return 0;
1606     if (s1->event_support != s2->event_support) return 0;
1607     if (s1->sensor_type != s2->sensor_type) return 0;
1608     if (s1->event_reading_type != s2->event_reading_type) return 0;
1609 
1610     if (s1->mask1 != s2->mask1) return 0;
1611     if (s1->mask2 != s2->mask2) return 0;
1612     if (s1->mask3 != s2->mask3) return 0;
1613 
1614     if (s1->analog_data_format != s2->analog_data_format) return 0;
1615     if (s1->rate_unit != s2->rate_unit) return 0;
1616     if (s1->modifier_unit_use != s2->modifier_unit_use) return 0;
1617     if (s1->percentage != s2->percentage) return 0;
1618     if (s1->base_unit != s2->base_unit) return 0;
1619     if (s1->modifier_unit != s2->modifier_unit) return 0;
1620     if (s1->linearization != s2->linearization) return 0;
1621     if (s1->linearization <= 11) {
1622 	if (s1->conv[0].m != s2->conv[0].m) return 0;
1623 	if (s1->conv[0].tolerance != s2->conv[0].tolerance) return 0;
1624 	if (s1->conv[0].b != s2->conv[0].b) return 0;
1625 	if (s1->conv[0].accuracy != s2->conv[0].accuracy) return 0;
1626 	if (s1->conv[0].accuracy_exp != s2->conv[0].accuracy_exp) return 0;
1627 	if (s1->conv[0].r_exp != s2->conv[0].r_exp) return 0;
1628 	if (s1->conv[0].b_exp != s2->conv[0].b_exp) return 0;
1629     }
1630     if (s1->normal_min_specified != s2->normal_min_specified) return 0;
1631     if (s1->normal_max_specified != s2->normal_max_specified) return 0;
1632     if (s1->nominal_reading_specified != s2->nominal_reading_specified) return 0;
1633     if (s1->nominal_reading != s2->nominal_reading) return 0;
1634     if (s1->normal_max != s2->normal_max) return 0;
1635     if (s1->normal_min != s2->normal_min) return 0;
1636     if (s1->sensor_max != s2->sensor_max) return 0;
1637     if (s1->sensor_min != s2->sensor_min) return 0;
1638     for (i=0; i<6; i++) {
1639 	if (s1->default_thresholds[i] != s2->default_thresholds[i])
1640 	    return 0;
1641     }
1642     if (s1->positive_going_threshold_hysteresis
1643 	!= s2->positive_going_threshold_hysteresis)
1644 	return 0;
1645     if (s1->negative_going_threshold_hysteresis
1646 	!= s2->negative_going_threshold_hysteresis)
1647 	return 0;
1648     if (s1->oem1 != s2->oem1) return 0;
1649 
1650     if (s1->id_type != s2->id_type) return 0;
1651     if (s1->id_len != s2->id_len) return 0;
1652     if (memcmp(s1->id, s2->id, s1->id_len) != 0) return 0;
1653 
1654     return 1;
1655 }
1656 
1657 enum entity_list_op { ENT_LIST_OLD, ENT_LIST_NEW, ENT_LIST_DUP };
1658 typedef struct entity_list_s
1659 {
1660     ipmi_entity_t        *ent;
1661     ipmi_sensor_t        *sensor;
1662     ipmi_sensor_t        *osensor;
1663     ipmi_mc_t            *mc;
1664     enum entity_list_op  op;
1665     struct entity_list_s *next;
1666 } entity_list_t;
1667 
1668 /* Assume it has enough space for one pointer. */
1669 struct locked_list_entry_s
1670 {
1671     locked_list_entry_t *next;
1672 };
1673 
1674 int
ipmi_sensor_handle_sdrs(ipmi_domain_t * domain,ipmi_mc_t * source_mc,ipmi_sdr_info_t * sdrs)1675 ipmi_sensor_handle_sdrs(ipmi_domain_t   *domain,
1676 			ipmi_mc_t       *source_mc,
1677 			ipmi_sdr_info_t *sdrs)
1678 {
1679     int                 rv;
1680     unsigned int        i, j;
1681     ipmi_sensor_t       **sdr_sensors = NULL;
1682     ipmi_sensor_t       **old_sdr_sensors;
1683     unsigned int        old_count;
1684     unsigned int        count = 0;
1685     ipmi_entity_info_t  *ents;
1686     ipmi_entity_t       *ent;
1687     entity_list_t       *new_sensors = NULL;
1688     entity_list_t       *del_sensors = NULL;
1689     entity_list_t       *ent_item;
1690     entity_list_t       *new_ent_item;
1691     locked_list_entry_t *link, *links = NULL;
1692     ipmi_sensor_t       **sens_tmp;
1693 
1694 
1695     CHECK_DOMAIN_LOCK(domain);
1696     if (source_mc)
1697 	CHECK_MC_LOCK(source_mc);
1698 
1699     rv = get_sensors_from_sdrs(domain, source_mc, sdrs, &sdr_sensors, &count);
1700     if (rv)
1701 	goto out_err;
1702 
1703     ents = ipmi_domain_get_entities(domain);
1704 
1705     /* Pre-allocate all the links we will need for registering sensors
1706        with the entities, and we make sure all the entities exist. */
1707     for (i=0; i<count; i++) {
1708 	ipmi_sensor_t      *nsensor = sdr_sensors[i];
1709 
1710 	ent = NULL;
1711 
1712 	if (nsensor != NULL) {
1713 	    ipmi_sensor_info_t *sensors;
1714 
1715 	    /* Make sure the entity exists for ALL sensors in the
1716 	       new list.  This way, if a sensor has changed
1717 	       entities, the new entity will exist. */
1718 	    rv = ipmi_entity_add(ents,
1719 				 domain,
1720 				 ipmi_mc_get_channel(nsensor->mc),
1721 				 ipmi_mc_get_address(nsensor->mc),
1722 				 i,
1723 				 nsensor->entity_id,
1724 				 nsensor->entity_instance,
1725 				 "",
1726 				 IPMI_ASCII_STR,
1727 				 0,
1728 				 NULL,
1729 				 NULL,
1730 				 &ent);
1731 	    if (rv)
1732 		goto out_err_free;
1733 
1734 	    nsensor->entity = ent;
1735 
1736 	    sensors = i_ipmi_mc_get_sensors(nsensor->mc);
1737 
1738 	    ipmi_lock(sensors->idx_lock);
1739 	    if (nsensor->num >= sensors->idx_size[nsensor->lun]) {
1740 		/* There's not enough room in the sensor repository
1741 		   for the new item, so expand the array. */
1742 		ipmi_sensor_t **new_by_idx;
1743 		unsigned int  new_size = nsensor->num+10;
1744 		new_by_idx = ipmi_mem_alloc(sizeof(ipmi_sensor_t *) * new_size);
1745 		if (!new_by_idx) {
1746 		    ipmi_unlock(sensors->idx_lock);
1747 		    rv = ENOMEM;
1748 		    i_ipmi_entity_put(ent);
1749 		    goto out_err_free;
1750 		}
1751 		if (sensors->sensors_by_idx[nsensor->lun]) {
1752 		    memcpy(new_by_idx,
1753 			   sensors->sensors_by_idx[nsensor->lun],
1754 			   (sensors->idx_size[nsensor->lun]
1755 			    * sizeof(ipmi_sensor_t *)));
1756 		    ipmi_mem_free(sensors->sensors_by_idx[nsensor->lun]);
1757 		}
1758 		for (j=sensors->idx_size[nsensor->lun]; j<new_size; j++)
1759 		    new_by_idx[j] = NULL;
1760 		sensors->sensors_by_idx[nsensor->lun] = new_by_idx;
1761 		sensors->idx_size[nsensor->lun] = new_size;
1762 	    }
1763 	    ipmi_unlock(sensors->idx_lock);
1764 
1765 	    /* Keep track of each entity/sensor pair. */
1766 	    new_ent_item = ipmi_mem_alloc(sizeof(*new_ent_item));
1767 	    if (!new_ent_item) {
1768 		i_ipmi_entity_put(ent);
1769 		goto out_err_free;
1770 	    }
1771 	    new_ent_item->ent = ent;
1772 	    new_ent_item->sensor = nsensor;
1773 	    new_ent_item->osensor = NULL;
1774 	    new_ent_item->mc = nsensor->mc;
1775 	    new_ent_item->op = ENT_LIST_OLD;
1776 	    new_ent_item->next = new_sensors;
1777 	    new_sensors = new_ent_item;
1778 
1779 	    /* Pre-allocate link entries for putting the sensor into
1780 	       the entity. */
1781 	    link = locked_list_alloc_entry();
1782 	    if (!link)
1783 		goto out_err_free;
1784 	    link->next = links;
1785 	    links = link;
1786 	}
1787     }
1788 
1789     /* Check for duplicate sensor numbers in the new sensor set. */
1790     sens_tmp = ipmi_mem_alloc(256 * sizeof(ipmi_sensor_t **));
1791     if (!sens_tmp) {
1792 	rv = ENOMEM;
1793 	goto out_err_free;
1794     }
1795     memset(sens_tmp, 0, 256 * sizeof(ipmi_sensor_t **));
1796     ent_item = new_sensors;
1797     while (ent_item) {
1798 	ipmi_sensor_t *nsensor = ent_item->sensor;
1799 	ipmi_sensor_t *csensor;
1800 
1801 	if ((!ent_item->ent) || (!nsensor)) {
1802 	    ent_item = ent_item->next;
1803 	    continue;
1804 	}
1805 
1806 	csensor = sens_tmp[nsensor->num];
1807 	while (csensor) {
1808 	    if ((csensor->lun == nsensor->lun)
1809 		&& (csensor->num == nsensor->num)
1810 		&& (csensor->mc == nsensor->mc))
1811 	    {
1812 		break;
1813 	    }
1814 	    csensor = csensor->tlink;
1815 	}
1816 	if (csensor) {
1817 	    ipmi_log(IPMI_LOG_WARNING,
1818 		     "%ssensor.c(ipmi_sensor_handle_sdrs):"
1819 		     " SDR record %d has the same sensor number as record"
1820 		     " %d in the repository.  Ignoring second sensor."
1821 		     " Fix your SDRs!",
1822 		     SENSOR_NAME(nsensor),
1823 		     csensor->source_recid,
1824 		     nsensor->source_recid);
1825 	    ent_item->op = ENT_LIST_DUP;
1826 	    ent_item->osensor = NULL;
1827 	} else {
1828 	    nsensor->tlink = sens_tmp[nsensor->num];
1829 	    sens_tmp[nsensor->num] = nsensor;
1830 	}
1831 	ent_item = ent_item->next;
1832     }
1833     ipmi_mem_free(sens_tmp);
1834 
1835     i_ipmi_domain_entity_lock(domain);
1836 
1837     i_ipmi_get_sdr_sensors(domain, source_mc,
1838 			   &old_sdr_sensors, &old_count);
1839 
1840     ent_item = new_sensors;
1841     while (ent_item) {
1842 	ipmi_sensor_t      *nsensor = ent_item->sensor;
1843 	ipmi_sensor_info_t *sensors;
1844 
1845 	if ((!ent_item->ent) || (!nsensor) || (ent_item->op == ENT_LIST_DUP)) {
1846 	    ent_item = ent_item->next;
1847 	    continue;
1848 	}
1849 
1850 	sensors = i_ipmi_mc_get_sensors(nsensor->mc);
1851 	ipmi_lock(sensors->idx_lock);
1852 	if (sensors->sensors_by_idx[nsensor->lun]
1853 	    && (nsensor->num < sensors->idx_size[nsensor->lun])
1854 	    && sensors->sensors_by_idx[nsensor->lun][nsensor->num])
1855 	{
1856 	    /* A sensor is already there. */
1857 	    ipmi_sensor_t *osensor
1858 		= sensors->sensors_by_idx[nsensor->lun][nsensor->num];
1859 
1860 	    if (cmp_sensor(nsensor, osensor)) {
1861 		/* Since the data is the same, there is no need to get
1862 		   the old sensor entity or mc, since they are already
1863 		   gotten by the new sensor. */
1864 		ent_item->op = ENT_LIST_DUP;
1865 		ent_item->osensor = osensor;
1866 	    } else {
1867 		/* We have to delete the old sensor. */
1868 		new_ent_item = ipmi_mem_alloc(sizeof(*new_ent_item));
1869 		if (!new_ent_item) {
1870 		    ipmi_unlock(sensors->idx_lock);
1871 		    rv = ENOMEM;
1872 		    goto out_err_free_unlock;
1873 		}
1874 		/* It's possible this can fail, but that means that
1875 		   the MC is currently being destroyed.  No big deal,
1876 		   just ignore it. */
1877 		new_ent_item->mc = NULL;
1878 		i_ipmi_find_or_create_mc_by_slave_addr(domain,
1879 						       osensor->channel,
1880 						       osensor->owner,
1881 						       &new_ent_item->mc);
1882 		i_ipmi_entity_get(osensor->entity);
1883 		i_ipmi_sensor_get(osensor);
1884 		new_ent_item->ent = osensor->entity;
1885 		new_ent_item->sensor = osensor;
1886 		new_ent_item->next = del_sensors;
1887 		del_sensors = new_ent_item;
1888 		ent_item->op = ENT_LIST_NEW;
1889 	    }
1890 	} else {
1891 	    ent_item->op = ENT_LIST_NEW;
1892 	}
1893 	ipmi_unlock(sensors->idx_lock);
1894 
1895 	ent_item = ent_item->next;
1896     }
1897 
1898     i_ipmi_domain_entity_unlock(domain);
1899 
1900     /* After this point, the operation cannot fail.  Nothing above
1901        this actually changes anything, it just gets it ready.  Now we
1902        put into place all the changes. */
1903 
1904     /* First delete the sensors that we are replacing. */
1905     ent_item = del_sensors;
1906     while (ent_item) {
1907 	ipmi_sensor_t *osensor = ent_item->sensor;
1908 
1909 	if (osensor->source_array) {
1910 	    osensor->source_array[osensor->source_idx] = NULL;
1911 	    osensor->source_array = NULL;
1912 	}
1913 	/* Note that the actual destroy is deferred until we put the
1914 	   sensor. */
1915 	ipmi_sensor_destroy(osensor);
1916 
1917 	ent_item = ent_item->next;
1918     }
1919 
1920     ent_item = new_sensors;
1921     while (ent_item) {
1922 	ipmi_sensor_t      *nsensor = ent_item->sensor;
1923 	ipmi_sensor_t      *osensor = ent_item->osensor;
1924 	ipmi_sensor_info_t *sensors;
1925 
1926 	if ((!ent_item->ent) || (!nsensor)) {
1927 	    ent_item = ent_item->next;
1928 	    continue;
1929 	}
1930 
1931 	sensors = i_ipmi_mc_get_sensors(nsensor->mc);
1932 	ipmi_lock(sensors->idx_lock);
1933 	switch (ent_item->op) {
1934 	case ENT_LIST_NEW:
1935 	    sensors->sensors_by_idx[nsensor->lun][nsensor->num] = nsensor;
1936 	    sensors->sensor_count++;
1937 	    link = links;
1938 	    links = link->next;
1939 	    handle_new_sensor(domain, nsensor, link);
1940 	    break;
1941 
1942 	case ENT_LIST_OLD:
1943 	    break;
1944 
1945 	case ENT_LIST_DUP:
1946 	    /* They compare, prefer to keep the old data. */
1947 	    i = nsensor->source_idx;
1948 	    opq_destroy(nsensor->waitq);
1949 	    locked_list_destroy(nsensor->handler_list);
1950 	    locked_list_destroy(nsensor->handler_list_cl);
1951 	    ipmi_mem_free(nsensor);
1952 	    ent_item->sensor = NULL;
1953 	    sdr_sensors[i] = osensor;
1954 	    if (osensor) {
1955 		if (osensor->source_array)
1956 		    osensor->source_array[osensor->source_idx] = NULL;
1957 		osensor->source_idx = i;
1958 		osensor->source_array = sdr_sensors;
1959 	    }
1960 	    break;
1961 	}
1962 	ipmi_unlock(sensors->idx_lock);
1963 	ent_item = ent_item->next;
1964     }
1965 
1966     i_ipmi_set_sdr_sensors(domain, source_mc, sdr_sensors, count);
1967 
1968     if (old_sdr_sensors) {
1969 	for (i=0; i<old_count; i++) {
1970 	    ipmi_sensor_t *osensor = old_sdr_sensors[i];
1971 	    if (osensor != NULL) {
1972 		/* This sensor was not in the new repository, so it must
1973 		   have been deleted. */
1974 		i_ipmi_domain_entity_lock(domain);
1975 		i_ipmi_sensor_get(osensor);
1976 		i_ipmi_domain_entity_unlock(domain);
1977 		ipmi_sensor_destroy(osensor);
1978 	    }
1979 	}
1980     }
1981 
1982     if (old_sdr_sensors) {
1983 	for (i=0; i<old_count; i++) {
1984 	    ipmi_sensor_t *osensor = old_sdr_sensors[i];
1985 	    if (osensor != NULL) {
1986 		i_ipmi_sensor_put(osensor);
1987 	    }
1988 	}
1989 	ipmi_mem_free(old_sdr_sensors);
1990     }
1991 
1992     /* Free up all the deleted sensors. */
1993     while (del_sensors) {
1994 	ent_item = del_sensors;
1995 	del_sensors = del_sensors->next;
1996 	if (ent_item->sensor)
1997 	    i_ipmi_sensor_put(ent_item->sensor);
1998 	if (ent_item->ent)
1999 	    i_ipmi_entity_put(ent_item->ent);
2000 	if (ent_item->mc)
2001 	    i_ipmi_mc_put(ent_item->mc);
2002 	ipmi_mem_free(ent_item);
2003     }
2004 
2005     /* Report then free up all the new sensors. */
2006     while (new_sensors) {
2007 	ent_item = new_sensors;
2008 	new_sensors = new_sensors->next;
2009 
2010 	if (ent_item->ent && ent_item->sensor)
2011 	    ent_item->sensor->add_pending = 1;
2012 	if (ent_item->sensor)
2013 	    i_ipmi_sensor_put(ent_item->sensor);
2014 	if (ent_item->ent)
2015 	    i_ipmi_entity_put(ent_item->ent);
2016 	if (ent_item->mc)
2017 	    i_ipmi_mc_put(ent_item->mc);
2018 	ipmi_mem_free(ent_item);
2019     }
2020 
2021  out:
2022     /* Cleanup unused links. */
2023     while (links) {
2024 	link = links;
2025 	links = link->next;
2026 	locked_list_free_entry(link);
2027     }
2028 
2029     return rv;
2030 
2031  out_err:
2032     /* Release all the entities, sensors, etc. */
2033     while (del_sensors) {
2034 	ent_item = del_sensors;
2035 	del_sensors = del_sensors->next;
2036 	if (ent_item->sensor)
2037 	    i_ipmi_sensor_put(ent_item->sensor);
2038 	if (ent_item->ent)
2039 	    i_ipmi_entity_put(ent_item->ent);
2040 	if (ent_item->mc)
2041 	    i_ipmi_mc_put(ent_item->mc);
2042 	ipmi_mem_free(ent_item);
2043     }
2044     while (new_sensors) {
2045 	ent_item = new_sensors;
2046 	new_sensors = new_sensors->next;
2047 	if (ent_item->sensor)
2048 	    i_ipmi_sensor_put(ent_item->sensor);
2049 	if (ent_item->ent)
2050 	    i_ipmi_entity_put(ent_item->ent);
2051 	if (ent_item->mc)
2052 	    i_ipmi_mc_put(ent_item->mc);
2053 	ipmi_mem_free(ent_item);
2054     }
2055     goto out;
2056 
2057  out_err_free_unlock:
2058     i_ipmi_domain_entity_unlock(domain);
2059  out_err_free:
2060     /* Free up the usecounts on all the MCs we got. */
2061     for (i=0; i<count; i++) {
2062 	ipmi_sensor_t *nsensor = sdr_sensors[i];
2063 
2064 	if ((nsensor) && (nsensor->mc))
2065 	    i_ipmi_mc_put(nsensor->mc);
2066     }
2067     goto out_err;
2068 }
2069 
2070 /***********************************************************************
2071  *
2072  * Get/set various local information about a sensor.
2073  *
2074  **********************************************************************/
2075 
2076 int
ipmi_sensor_get_nominal_reading(ipmi_sensor_t * sensor,double * nominal_reading)2077 ipmi_sensor_get_nominal_reading(ipmi_sensor_t *sensor,
2078 				double *nominal_reading)
2079 {
2080     CHECK_SENSOR_LOCK(sensor);
2081 
2082     if (!sensor->nominal_reading_specified)
2083 	return ENOSYS;
2084 
2085     return (ipmi_sensor_convert_from_raw(sensor,
2086 					 sensor->nominal_reading,
2087 					 nominal_reading));
2088 }
2089 
2090 int
ipmi_sensor_get_normal_max(ipmi_sensor_t * sensor,double * normal_max)2091 ipmi_sensor_get_normal_max(ipmi_sensor_t *sensor, double *normal_max)
2092 {
2093     CHECK_SENSOR_LOCK(sensor);
2094 
2095     if (!sensor->normal_max_specified)
2096 	return ENOSYS;
2097 
2098     return (ipmi_sensor_convert_from_raw(sensor,
2099 					 sensor->normal_max,
2100 					 normal_max));
2101 }
2102 
2103 int
ipmi_sensor_get_normal_min(ipmi_sensor_t * sensor,double * normal_min)2104 ipmi_sensor_get_normal_min(ipmi_sensor_t *sensor, double *normal_min)
2105 {
2106     CHECK_SENSOR_LOCK(sensor);
2107 
2108     if (!sensor->normal_min_specified)
2109 	return ENOSYS;
2110 
2111     return (ipmi_sensor_convert_from_raw(sensor,
2112 					 sensor->normal_min,
2113 					 normal_min));
2114 }
2115 
2116 int
ipmi_sensor_get_sensor_max(ipmi_sensor_t * sensor,double * sensor_max)2117 ipmi_sensor_get_sensor_max(ipmi_sensor_t *sensor, double *sensor_max)
2118 {
2119     CHECK_SENSOR_LOCK(sensor);
2120 
2121     return (ipmi_sensor_convert_from_raw(sensor,
2122 					 sensor->sensor_max,
2123 					 sensor_max));
2124 }
2125 
2126 int
ipmi_sensor_get_sensor_min(ipmi_sensor_t * sensor,double * sensor_min)2127 ipmi_sensor_get_sensor_min(ipmi_sensor_t *sensor, double *sensor_min)
2128 {
2129     CHECK_SENSOR_LOCK(sensor);
2130 
2131     return (ipmi_sensor_convert_from_raw(sensor,
2132 					 sensor->sensor_min,
2133 					 sensor_min));
2134 }
2135 
ipmi_sensor_set_raw_default_threshold(ipmi_sensor_t * sensor,int threshold,int val)2136 int ipmi_sensor_set_raw_default_threshold(ipmi_sensor_t *sensor,
2137 					  int           threshold,
2138 					  int           val)
2139 {
2140     if ((threshold < 0) || (threshold > 5))
2141 	return EINVAL;
2142 
2143     sensor->default_thresholds[threshold] = val;
2144     return 0;
2145 }
2146 
ipmi_sensor_get_default_threshold_raw(ipmi_sensor_t * sensor,int threshold,int * raw)2147 int ipmi_sensor_get_default_threshold_raw(ipmi_sensor_t *sensor,
2148 					  int           threshold,
2149 					  int           *raw)
2150 {
2151     int rv;
2152     int val;
2153 
2154     CHECK_SENSOR_LOCK(sensor);
2155 
2156     if ((threshold < 0) || (threshold > 5))
2157 	return EINVAL;
2158 
2159     rv = ipmi_sensor_threshold_settable(sensor, threshold, &val);
2160     if (rv)
2161 	return rv;
2162 
2163     if (!val)
2164 	return ENOSYS;
2165 
2166     if (!ipmi_sensor_get_sensor_init_thresholds(sensor))
2167 	return ENOSYS;
2168 
2169     *raw = sensor->default_thresholds[threshold];
2170     return 0;
2171 }
2172 
ipmi_sensor_get_default_threshold_cooked(ipmi_sensor_t * sensor,int threshold,double * cooked)2173 int ipmi_sensor_get_default_threshold_cooked(ipmi_sensor_t *sensor,
2174 					     int           threshold,
2175 					     double        *cooked)
2176 {
2177     int rv;
2178     int val;
2179 
2180     CHECK_SENSOR_LOCK(sensor);
2181 
2182     if ((threshold < 0) || (threshold > 5))
2183 	return EINVAL;
2184 
2185     rv = ipmi_sensor_threshold_settable(sensor, threshold, &val);
2186     if (rv)
2187 	return rv;
2188 
2189     if (!val)
2190 	return ENOSYS;
2191 
2192     if (!ipmi_sensor_get_sensor_init_thresholds(sensor))
2193 	return ENOSYS;
2194 
2195     return (ipmi_sensor_convert_from_raw(sensor,
2196 					 sensor->default_thresholds[threshold],
2197 					 cooked));
2198 }
2199 
2200 ipmi_mc_t *
ipmi_sensor_get_mc(ipmi_sensor_t * sensor)2201 ipmi_sensor_get_mc(ipmi_sensor_t *sensor)
2202 {
2203     return sensor->mc;
2204 }
2205 
2206 ipmi_mc_t *
ipmi_sensor_get_source_mc(ipmi_sensor_t * sensor)2207 ipmi_sensor_get_source_mc(ipmi_sensor_t *sensor)
2208 {
2209     CHECK_SENSOR_LOCK(sensor);
2210 
2211     return sensor->source_mc;
2212 }
2213 
2214 int
ipmi_sensor_get_num(ipmi_sensor_t * sensor,int * lun,int * num)2215 ipmi_sensor_get_num(ipmi_sensor_t *sensor,
2216 		    int           *lun,
2217 		    int           *num)
2218 {
2219     CHECK_SENSOR_LOCK(sensor);
2220 
2221     if (lun)
2222 	*lun = sensor->lun;
2223     if (num)
2224 	*num = sensor->num;
2225     return 0;
2226 }
2227 
2228 static void
ipmi_sensor_get_event_masks(ipmi_sensor_t * sensor,uint16_t * mask1,uint16_t * mask2)2229 ipmi_sensor_get_event_masks(ipmi_sensor_t *sensor,
2230 			    uint16_t      *mask1,
2231 			    uint16_t      *mask2)
2232 {
2233     if (sensor->event_reading_type == IPMI_EVENT_READING_TYPE_THRESHOLD) {
2234 	/* Remove the reading mask, as that is not part of the event
2235 	   values allowed. */
2236 	*mask1 = sensor->mask1 & 0x0fff;
2237 	*mask2 = sensor->mask2 & 0x0fff;
2238     } else {
2239 	/* Cannot set bit 15 */
2240 	*mask1 = sensor->mask1 & 0x7fff;
2241 	*mask2 = sensor->mask2 & 0x7fff;
2242     }
2243 }
2244 
2245 int
ipmi_sensor_threshold_event_supported(ipmi_sensor_t * sensor,enum ipmi_thresh_e event,enum ipmi_event_value_dir_e value_dir,enum ipmi_event_dir_e dir,int * val)2246 ipmi_sensor_threshold_event_supported(ipmi_sensor_t               *sensor,
2247 				      enum ipmi_thresh_e          event,
2248 				      enum ipmi_event_value_dir_e value_dir,
2249 				      enum ipmi_event_dir_e       dir,
2250 				      int                         *val)
2251 {
2252     int      idx;
2253     uint16_t mask;
2254 
2255     CHECK_SENSOR_LOCK(sensor);
2256 
2257     if (sensor->event_reading_type != IPMI_EVENT_READING_TYPE_THRESHOLD)
2258 	/* Not a threshold sensor, it doesn't have readings. */
2259 	return ENOSYS;
2260     if (sensor->threshold_access == IPMI_THRESHOLD_ACCESS_SUPPORT_NONE) {
2261 	/* No thresholds supported. */
2262 	*val = 0;
2263 	return 0;
2264     }
2265 
2266     if (dir == IPMI_ASSERTION)
2267 	mask = sensor->mask1;
2268     else if (dir == IPMI_DEASSERTION)
2269 	mask = sensor->mask2;
2270     else
2271 	return EINVAL;
2272 
2273     idx = (event * 2) + value_dir;
2274     if (idx > 11)
2275 	return EINVAL;
2276 
2277     *val = IPMI_SENSOR_GET_MASK_BIT(mask, idx);
2278     return 0;
2279 }
2280 
2281 void
ipmi_sensor_set_threshold_assertion_event_supported(ipmi_sensor_t * sensor,enum ipmi_thresh_e event,enum ipmi_event_value_dir_e dir,int val)2282 ipmi_sensor_set_threshold_assertion_event_supported(
2283     ipmi_sensor_t               *sensor,
2284     enum ipmi_thresh_e          event,
2285     enum ipmi_event_value_dir_e dir,
2286     int                         val)
2287 {
2288     int idx;
2289 
2290     idx = (event * 2) + dir;
2291     if (idx > 11)
2292 	return;
2293 
2294     IPMI_SENSOR_SET_MASK_BIT(sensor->mask1, idx, val);
2295 }
2296 
2297 void
ipmi_sensor_set_threshold_deassertion_event_supported(ipmi_sensor_t * sensor,enum ipmi_thresh_e event,enum ipmi_event_value_dir_e dir,int val)2298 ipmi_sensor_set_threshold_deassertion_event_supported(
2299     ipmi_sensor_t               *sensor,
2300     enum ipmi_thresh_e          event,
2301     enum ipmi_event_value_dir_e dir,
2302     int                         val)
2303 {
2304     int idx;
2305 
2306     idx = (event * 2) + dir;
2307     if (idx > 11)
2308 	return;
2309 
2310     IPMI_SENSOR_SET_MASK_BIT(sensor->mask2, idx, val);
2311 }
2312 
2313 int
ipmi_sensor_threshold_reading_supported(ipmi_sensor_t * sensor,enum ipmi_thresh_e thresh,int * val)2314 ipmi_sensor_threshold_reading_supported(ipmi_sensor_t      *sensor,
2315 					enum ipmi_thresh_e thresh,
2316 					int                *val)
2317 {
2318     CHECK_SENSOR_LOCK(sensor);
2319 
2320     if (sensor->event_reading_type != IPMI_EVENT_READING_TYPE_THRESHOLD)
2321 	/* Not a threshold sensor, it doesn't have readings. */
2322 	return ENOSYS;
2323 
2324     switch(thresh) {
2325     case IPMI_LOWER_NON_CRITICAL:
2326 	*val = IPMI_SENSOR_GET_MASK_BIT(sensor->mask1, 12);
2327 	break;
2328     case IPMI_LOWER_CRITICAL:
2329 	*val = IPMI_SENSOR_GET_MASK_BIT(sensor->mask1, 13);
2330 	break;
2331     case IPMI_LOWER_NON_RECOVERABLE:
2332 	*val = IPMI_SENSOR_GET_MASK_BIT(sensor->mask1, 14);
2333 	break;
2334     case IPMI_UPPER_NON_CRITICAL:
2335 	*val = IPMI_SENSOR_GET_MASK_BIT(sensor->mask2, 12);
2336 	break;
2337     case IPMI_UPPER_CRITICAL:
2338 	*val = IPMI_SENSOR_GET_MASK_BIT(sensor->mask2, 13);
2339 	break;
2340     case IPMI_UPPER_NON_RECOVERABLE:
2341 	*val = IPMI_SENSOR_GET_MASK_BIT(sensor->mask2, 14);
2342 	break;
2343     default:
2344 	return EINVAL;
2345     }
2346     return 0;
2347 }
2348 
2349 int
ipmi_sensor_threshold_settable(ipmi_sensor_t * sensor,enum ipmi_thresh_e event,int * val)2350 ipmi_sensor_threshold_settable(ipmi_sensor_t      *sensor,
2351 			       enum ipmi_thresh_e event,
2352 			       int                *val)
2353 {
2354     CHECK_SENSOR_LOCK(sensor);
2355 
2356     if (sensor->event_reading_type != IPMI_EVENT_READING_TYPE_THRESHOLD)
2357 	/* Not a threshold sensor, it doesn't have readings. */
2358 	return ENOSYS;
2359     if (sensor->threshold_access != IPMI_THRESHOLD_ACCESS_SUPPORT_SETTABLE) {
2360 	/* Threshold setting not supported for any thresholds. */
2361 	*val = 0;
2362 	return 0;
2363     }
2364 
2365     if (event > IPMI_UPPER_NON_RECOVERABLE)
2366 	return EINVAL;
2367 
2368     *val = IPMI_SENSOR_GET_MASK_BIT(sensor->mask3, event + 8);
2369     return 0;
2370 }
2371 
2372 void
ipmi_sensor_threshold_set_settable(ipmi_sensor_t * sensor,enum ipmi_thresh_e event,int val)2373 ipmi_sensor_threshold_set_settable(ipmi_sensor_t      *sensor,
2374 				   enum ipmi_thresh_e event,
2375 				   int                val)
2376 {
2377     if (sensor->event_reading_type != IPMI_EVENT_READING_TYPE_THRESHOLD)
2378 	/* Not a threshold sensor, it doesn't have readings. */
2379 	return;
2380 
2381     if (event > IPMI_UPPER_NON_RECOVERABLE)
2382 	return;
2383 
2384     IPMI_SENSOR_SET_MASK_BIT(sensor->mask3, event + 8, val);
2385 }
2386 
2387 int
ipmi_sensor_threshold_readable(ipmi_sensor_t * sensor,enum ipmi_thresh_e event,int * val)2388 ipmi_sensor_threshold_readable(ipmi_sensor_t      *sensor,
2389 			       enum ipmi_thresh_e event,
2390 			       int                *val)
2391 {
2392     CHECK_SENSOR_LOCK(sensor);
2393 
2394     if (sensor->event_reading_type != IPMI_EVENT_READING_TYPE_THRESHOLD)
2395 	/* Not a threshold sensor, it doesn't have readings. */
2396 	return ENOSYS;
2397     if ((sensor->threshold_access == IPMI_THRESHOLD_ACCESS_SUPPORT_NONE)
2398 	|| (sensor->threshold_access == IPMI_THRESHOLD_ACCESS_SUPPORT_FIXED))
2399     {
2400 	/* Threshold reading not supported for any thresholds. */
2401 	*val = 0;
2402 	return 0;
2403     }
2404 
2405     if (event > IPMI_UPPER_NON_RECOVERABLE)
2406 	return EINVAL;
2407 
2408     *val = IPMI_SENSOR_GET_MASK_BIT(sensor->mask3, event);
2409     return 0;
2410 }
2411 
2412 void
ipmi_sensor_threshold_set_readable(ipmi_sensor_t * sensor,enum ipmi_thresh_e event,int val)2413 ipmi_sensor_threshold_set_readable(ipmi_sensor_t      *sensor,
2414 				   enum ipmi_thresh_e event,
2415 				   int                val)
2416 {
2417     if (sensor->event_reading_type != IPMI_EVENT_READING_TYPE_THRESHOLD)
2418 	/* Not a threshold sensor, it doesn't have readings. */
2419 	return;
2420 
2421     if (event > IPMI_UPPER_NON_RECOVERABLE)
2422 	return;
2423 
2424     IPMI_SENSOR_SET_MASK_BIT(sensor->mask3, event, val);
2425 }
2426 
2427 int
ipmi_sensor_discrete_event_supported(ipmi_sensor_t * sensor,int event,enum ipmi_event_dir_e dir,int * val)2428 ipmi_sensor_discrete_event_supported(ipmi_sensor_t         *sensor,
2429 				     int                   event,
2430 				     enum ipmi_event_dir_e dir,
2431 				     int                   *val)
2432 {
2433     uint16_t mask;
2434 
2435     CHECK_SENSOR_LOCK(sensor);
2436 
2437     if (sensor->event_reading_type == IPMI_EVENT_READING_TYPE_THRESHOLD)
2438 	/* A threshold sensor, it doesn't have events. */
2439 	return ENOSYS;
2440 
2441     if (dir == IPMI_ASSERTION)
2442 	mask = sensor->mask1;
2443     else if (dir == IPMI_DEASSERTION)
2444 	mask = sensor->mask2;
2445     else
2446 	return EINVAL;
2447 
2448     if (event > 14)
2449 	return EINVAL;
2450 
2451     *val = IPMI_SENSOR_GET_MASK_BIT(mask, event);
2452     return 0;
2453 }
2454 
2455 void
ipmi_sensor_set_discrete_assertion_event_supported(ipmi_sensor_t * sensor,int event,int val)2456 ipmi_sensor_set_discrete_assertion_event_supported(ipmi_sensor_t *sensor,
2457 						   int           event,
2458 						   int           val)
2459 {
2460     if (event > 14)
2461 	return;
2462 
2463     IPMI_SENSOR_SET_MASK_BIT(sensor->mask1, event, val);
2464 }
2465 
2466 void
ipmi_sensor_set_discrete_deassertion_event_supported(ipmi_sensor_t * sensor,int event,int val)2467 ipmi_sensor_set_discrete_deassertion_event_supported(ipmi_sensor_t *sensor,
2468 						     int           event,
2469 						     int           val)
2470 {
2471     if (event > 14)
2472 	return;
2473 
2474     IPMI_SENSOR_SET_MASK_BIT(sensor->mask2, event, val);
2475 }
2476 
2477 int
ipmi_sensor_discrete_event_readable(ipmi_sensor_t * sensor,int event,int * val)2478 ipmi_sensor_discrete_event_readable(ipmi_sensor_t *sensor,
2479 				    int           event,
2480 				    int           *val)
2481 {
2482     CHECK_SENSOR_LOCK(sensor);
2483 
2484     if (sensor->event_reading_type == IPMI_EVENT_READING_TYPE_THRESHOLD)
2485 	/* A threshold sensor, it doesn't have events. */
2486 	return ENOSYS;
2487 
2488     if (event > 14)
2489 	return EINVAL;
2490 
2491     *val = IPMI_SENSOR_GET_MASK_BIT(sensor->mask3, event);
2492     return 0;
2493 }
2494 
2495 void
ipmi_sensor_discrete_set_event_readable(ipmi_sensor_t * sensor,int event,int val)2496 ipmi_sensor_discrete_set_event_readable(ipmi_sensor_t *sensor,
2497 					int           event,
2498 					int           val)
2499 {
2500     if (sensor->event_reading_type == IPMI_EVENT_READING_TYPE_THRESHOLD)
2501 	/* A threshold sensor, it doesn't have events. */
2502 	return;
2503 
2504     if (event > 14)
2505 	return;
2506 
2507     IPMI_SENSOR_SET_MASK_BIT(sensor->mask3, event, val);
2508 }
2509 
2510 int
ipmi_sensor_get_owner(ipmi_sensor_t * sensor)2511 ipmi_sensor_get_owner(ipmi_sensor_t *sensor)
2512 {
2513     CHECK_SENSOR_LOCK(sensor);
2514 
2515     return sensor->owner;
2516 }
2517 
2518 int
ipmi_sensor_get_channel(ipmi_sensor_t * sensor)2519 ipmi_sensor_get_channel(ipmi_sensor_t *sensor)
2520 {
2521     CHECK_SENSOR_LOCK(sensor);
2522 
2523     return sensor->channel;
2524 }
2525 
2526 int
ipmi_sensor_get_entity_id(ipmi_sensor_t * sensor)2527 ipmi_sensor_get_entity_id(ipmi_sensor_t *sensor)
2528 {
2529     CHECK_SENSOR_LOCK(sensor);
2530 
2531     return sensor->entity_id;
2532 }
2533 
2534 int
ipmi_sensor_get_entity_instance(ipmi_sensor_t * sensor)2535 ipmi_sensor_get_entity_instance(ipmi_sensor_t *sensor)
2536 {
2537     CHECK_SENSOR_LOCK(sensor);
2538 
2539     return sensor->entity_instance;
2540 }
2541 
2542 int
ipmi_sensor_get_entity_instance_logical(ipmi_sensor_t * sensor)2543 ipmi_sensor_get_entity_instance_logical(ipmi_sensor_t *sensor)
2544 {
2545     CHECK_SENSOR_LOCK(sensor);
2546 
2547     return sensor->entity_instance_logical;
2548 }
2549 
2550 int
ipmi_sensor_get_sensor_init_scanning(ipmi_sensor_t * sensor)2551 ipmi_sensor_get_sensor_init_scanning(ipmi_sensor_t *sensor)
2552 {
2553     CHECK_SENSOR_LOCK(sensor);
2554 
2555     return sensor->sensor_init_scanning;
2556 }
2557 
2558 int
ipmi_sensor_get_sensor_init_events(ipmi_sensor_t * sensor)2559 ipmi_sensor_get_sensor_init_events(ipmi_sensor_t *sensor)
2560 {
2561     CHECK_SENSOR_LOCK(sensor);
2562 
2563     return sensor->sensor_init_events;
2564 }
2565 
2566 int
ipmi_sensor_get_sensor_init_thresholds(ipmi_sensor_t * sensor)2567 ipmi_sensor_get_sensor_init_thresholds(ipmi_sensor_t *sensor)
2568 {
2569     CHECK_SENSOR_LOCK(sensor);
2570 
2571     return sensor->sensor_init_thresholds;
2572 }
2573 
2574 int
ipmi_sensor_get_sensor_init_hysteresis(ipmi_sensor_t * sensor)2575 ipmi_sensor_get_sensor_init_hysteresis(ipmi_sensor_t *sensor)
2576 {
2577     CHECK_SENSOR_LOCK(sensor);
2578 
2579     return sensor->sensor_init_hysteresis;
2580 }
2581 
2582 int
ipmi_sensor_get_sensor_init_type(ipmi_sensor_t * sensor)2583 ipmi_sensor_get_sensor_init_type(ipmi_sensor_t *sensor)
2584 {
2585     CHECK_SENSOR_LOCK(sensor);
2586 
2587     return sensor->sensor_init_type;
2588 }
2589 
2590 int
ipmi_sensor_get_sensor_init_pu_events(ipmi_sensor_t * sensor)2591 ipmi_sensor_get_sensor_init_pu_events(ipmi_sensor_t *sensor)
2592 {
2593     CHECK_SENSOR_LOCK(sensor);
2594 
2595     return sensor->sensor_init_pu_events;
2596 }
2597 
2598 int
ipmi_sensor_get_sensor_init_pu_scanning(ipmi_sensor_t * sensor)2599 ipmi_sensor_get_sensor_init_pu_scanning(ipmi_sensor_t *sensor)
2600 {
2601     CHECK_SENSOR_LOCK(sensor);
2602 
2603     return sensor->sensor_init_pu_scanning;
2604 }
2605 
2606 int
ipmi_sensor_get_ignore_if_no_entity(ipmi_sensor_t * sensor)2607 ipmi_sensor_get_ignore_if_no_entity(ipmi_sensor_t *sensor)
2608 {
2609     CHECK_SENSOR_LOCK(sensor);
2610 
2611     return sensor->ignore_if_no_entity;
2612 }
2613 
2614 int
ipmi_sensor_get_ignore_for_presence(ipmi_sensor_t * sensor)2615 ipmi_sensor_get_ignore_for_presence(ipmi_sensor_t *sensor)
2616 {
2617     CHECK_SENSOR_LOCK(sensor);
2618 
2619     return sensor->ignore_for_presence;
2620 }
2621 
2622 int
ipmi_sensor_get_supports_auto_rearm(ipmi_sensor_t * sensor)2623 ipmi_sensor_get_supports_auto_rearm(ipmi_sensor_t *sensor)
2624 {
2625     CHECK_SENSOR_LOCK(sensor);
2626 
2627     return sensor->supports_auto_rearm;
2628 }
2629 
2630 int
ipmi_sensor_get_hysteresis_support(ipmi_sensor_t * sensor)2631 ipmi_sensor_get_hysteresis_support(ipmi_sensor_t *sensor)
2632 {
2633     CHECK_SENSOR_LOCK(sensor);
2634 
2635     return sensor->hysteresis_support;
2636 }
2637 
2638 int
ipmi_sensor_get_threshold_access(ipmi_sensor_t * sensor)2639 ipmi_sensor_get_threshold_access(ipmi_sensor_t *sensor)
2640 {
2641     CHECK_SENSOR_LOCK(sensor);
2642 
2643     return sensor->threshold_access;
2644 }
2645 
2646 int
ipmi_sensor_get_event_support(ipmi_sensor_t * sensor)2647 ipmi_sensor_get_event_support(ipmi_sensor_t *sensor)
2648 {
2649     CHECK_SENSOR_LOCK(sensor);
2650 
2651     return sensor->event_support;
2652 }
2653 
2654 int
ipmi_sensor_get_sensor_type(ipmi_sensor_t * sensor)2655 ipmi_sensor_get_sensor_type(ipmi_sensor_t *sensor)
2656 {
2657     CHECK_SENSOR_LOCK(sensor);
2658 
2659     return sensor->sensor_type;
2660 }
2661 
2662 int
ipmi_sensor_get_event_reading_type(ipmi_sensor_t * sensor)2663 ipmi_sensor_get_event_reading_type(ipmi_sensor_t *sensor)
2664 {
2665     CHECK_SENSOR_LOCK(sensor);
2666 
2667     return sensor->event_reading_type;
2668 }
2669 
2670 int
ipmi_sensor_get_sensor_direction(ipmi_sensor_t * sensor)2671 ipmi_sensor_get_sensor_direction(ipmi_sensor_t *sensor)
2672 {
2673     CHECK_SENSOR_LOCK(sensor);
2674 
2675     return sensor->sensor_direction;
2676 }
2677 
2678 int
ipmi_sensor_get_is_readable(ipmi_sensor_t * sensor)2679 ipmi_sensor_get_is_readable(ipmi_sensor_t *sensor)
2680 {
2681     CHECK_SENSOR_LOCK(sensor);
2682 
2683     return sensor->readable;
2684 }
2685 
2686 int
ipmi_sensor_get_analog_data_format(ipmi_sensor_t * sensor)2687 ipmi_sensor_get_analog_data_format(ipmi_sensor_t *sensor)
2688 {
2689     CHECK_SENSOR_LOCK(sensor);
2690 
2691     return sensor->analog_data_format;
2692 }
2693 
2694 enum ipmi_rate_unit_e
ipmi_sensor_get_rate_unit(ipmi_sensor_t * sensor)2695 ipmi_sensor_get_rate_unit(ipmi_sensor_t *sensor)
2696 {
2697     CHECK_SENSOR_LOCK(sensor);
2698 
2699     return sensor->rate_unit;
2700 }
2701 
2702 enum ipmi_modifier_unit_use_e
ipmi_sensor_get_modifier_unit_use(ipmi_sensor_t * sensor)2703 ipmi_sensor_get_modifier_unit_use(ipmi_sensor_t *sensor)
2704 {
2705     CHECK_SENSOR_LOCK(sensor);
2706 
2707     return sensor->modifier_unit_use;
2708 }
2709 
2710 int
ipmi_sensor_get_percentage(ipmi_sensor_t * sensor)2711 ipmi_sensor_get_percentage(ipmi_sensor_t *sensor)
2712 {
2713     CHECK_SENSOR_LOCK(sensor);
2714 
2715     return sensor->percentage;
2716 }
2717 
2718 enum ipmi_unit_type_e
ipmi_sensor_get_base_unit(ipmi_sensor_t * sensor)2719 ipmi_sensor_get_base_unit(ipmi_sensor_t *sensor)
2720 {
2721     CHECK_SENSOR_LOCK(sensor);
2722 
2723     return sensor->base_unit;
2724 }
2725 
2726 enum ipmi_unit_type_e
ipmi_sensor_get_modifier_unit(ipmi_sensor_t * sensor)2727 ipmi_sensor_get_modifier_unit(ipmi_sensor_t *sensor)
2728 {
2729     CHECK_SENSOR_LOCK(sensor);
2730 
2731     return sensor->modifier_unit;
2732 }
2733 
2734 int
ipmi_sensor_get_linearization(ipmi_sensor_t * sensor)2735 ipmi_sensor_get_linearization(ipmi_sensor_t *sensor)
2736 {
2737     CHECK_SENSOR_LOCK(sensor);
2738 
2739     return sensor->linearization;
2740 }
2741 
2742 int
ipmi_sensor_get_raw_m(ipmi_sensor_t * sensor,int val)2743 ipmi_sensor_get_raw_m(ipmi_sensor_t *sensor, int val)
2744 {
2745     CHECK_SENSOR_LOCK(sensor);
2746 
2747     return sensor->conv[val].m;
2748 }
2749 
2750 int
ipmi_sensor_get_raw_tolerance(ipmi_sensor_t * sensor,int val)2751 ipmi_sensor_get_raw_tolerance(ipmi_sensor_t *sensor, int val)
2752 {
2753     CHECK_SENSOR_LOCK(sensor);
2754 
2755     return sensor->conv[val].tolerance;
2756 }
2757 
2758 int
ipmi_sensor_get_raw_b(ipmi_sensor_t * sensor,int val)2759 ipmi_sensor_get_raw_b(ipmi_sensor_t *sensor, int val)
2760 {
2761     CHECK_SENSOR_LOCK(sensor);
2762 
2763     return sensor->conv[val].b;
2764 }
2765 
2766 int
ipmi_sensor_get_raw_accuracy(ipmi_sensor_t * sensor,int val)2767 ipmi_sensor_get_raw_accuracy(ipmi_sensor_t *sensor, int val)
2768 {
2769     CHECK_SENSOR_LOCK(sensor);
2770 
2771     return sensor->conv[val].accuracy;
2772 }
2773 
2774 int
ipmi_sensor_get_raw_accuracy_exp(ipmi_sensor_t * sensor,int val)2775 ipmi_sensor_get_raw_accuracy_exp(ipmi_sensor_t *sensor, int val)
2776 {
2777     CHECK_SENSOR_LOCK(sensor);
2778 
2779     return sensor->conv[val].accuracy_exp;
2780 }
2781 
2782 int
ipmi_sensor_get_raw_r_exp(ipmi_sensor_t * sensor,int val)2783 ipmi_sensor_get_raw_r_exp(ipmi_sensor_t *sensor, int val)
2784 {
2785     CHECK_SENSOR_LOCK(sensor);
2786 
2787     return sensor->conv[val].r_exp;
2788 }
2789 
2790 int
ipmi_sensor_get_raw_b_exp(ipmi_sensor_t * sensor,int val)2791 ipmi_sensor_get_raw_b_exp(ipmi_sensor_t *sensor, int val)
2792 {
2793     CHECK_SENSOR_LOCK(sensor);
2794 
2795     return sensor->conv[val].b_exp;
2796 }
2797 
2798 int
ipmi_sensor_get_normal_min_specified(ipmi_sensor_t * sensor)2799 ipmi_sensor_get_normal_min_specified(ipmi_sensor_t *sensor)
2800 {
2801     CHECK_SENSOR_LOCK(sensor);
2802 
2803     return sensor->normal_min_specified;
2804 }
2805 
2806 int
ipmi_sensor_get_normal_max_specified(ipmi_sensor_t * sensor)2807 ipmi_sensor_get_normal_max_specified(ipmi_sensor_t *sensor)
2808 {
2809     CHECK_SENSOR_LOCK(sensor);
2810 
2811     return sensor->normal_max_specified;
2812 }
2813 
2814 int
ipmi_sensor_get_nominal_reading_specified(ipmi_sensor_t * sensor)2815 ipmi_sensor_get_nominal_reading_specified(ipmi_sensor_t *sensor)
2816 {
2817     CHECK_SENSOR_LOCK(sensor);
2818 
2819     return sensor->nominal_reading_specified;
2820 }
2821 
2822 int
ipmi_sensor_get_raw_nominal_reading(ipmi_sensor_t * sensor)2823 ipmi_sensor_get_raw_nominal_reading(ipmi_sensor_t *sensor)
2824 {
2825     CHECK_SENSOR_LOCK(sensor);
2826 
2827     return sensor->nominal_reading;
2828 }
2829 
2830 int
ipmi_sensor_get_raw_normal_max(ipmi_sensor_t * sensor)2831 ipmi_sensor_get_raw_normal_max(ipmi_sensor_t *sensor)
2832 {
2833     CHECK_SENSOR_LOCK(sensor);
2834 
2835     return sensor->normal_max;
2836 }
2837 
2838 int
ipmi_sensor_get_raw_normal_min(ipmi_sensor_t * sensor)2839 ipmi_sensor_get_raw_normal_min(ipmi_sensor_t *sensor)
2840 {
2841     CHECK_SENSOR_LOCK(sensor);
2842 
2843     return sensor->normal_min;
2844 }
2845 
2846 int
ipmi_sensor_get_raw_sensor_max(ipmi_sensor_t * sensor)2847 ipmi_sensor_get_raw_sensor_max(ipmi_sensor_t *sensor)
2848 {
2849     CHECK_SENSOR_LOCK(sensor);
2850 
2851     return sensor->sensor_max;
2852 }
2853 
2854 int
ipmi_sensor_get_raw_sensor_min(ipmi_sensor_t * sensor)2855 ipmi_sensor_get_raw_sensor_min(ipmi_sensor_t *sensor)
2856 {
2857     CHECK_SENSOR_LOCK(sensor);
2858 
2859     return sensor->sensor_min;
2860 }
2861 
2862 int
ipmi_sensor_get_positive_going_threshold_hysteresis(ipmi_sensor_t * sensor)2863 ipmi_sensor_get_positive_going_threshold_hysteresis(ipmi_sensor_t *sensor)
2864 {
2865     CHECK_SENSOR_LOCK(sensor);
2866 
2867     return sensor->positive_going_threshold_hysteresis;
2868 }
2869 
2870 int
ipmi_sensor_get_negative_going_threshold_hysteresis(ipmi_sensor_t * sensor)2871 ipmi_sensor_get_negative_going_threshold_hysteresis(ipmi_sensor_t *sensor)
2872 {
2873     CHECK_SENSOR_LOCK(sensor);
2874 
2875     return sensor->negative_going_threshold_hysteresis;
2876 }
2877 
2878 int
ipmi_sensor_get_oem1(ipmi_sensor_t * sensor)2879 ipmi_sensor_get_oem1(ipmi_sensor_t *sensor)
2880 {
2881     CHECK_SENSOR_LOCK(sensor);
2882 
2883     return sensor->oem1;
2884 }
2885 
2886 int
ipmi_sensor_get_id_length(ipmi_sensor_t * sensor)2887 ipmi_sensor_get_id_length(ipmi_sensor_t *sensor)
2888 {
2889     CHECK_SENSOR_LOCK(sensor);
2890 
2891     if (sensor->id_type == IPMI_ASCII_STR)
2892 	return sensor->id_len+1;
2893     else
2894 	return sensor->id_len;
2895 }
2896 
2897 enum ipmi_str_type_e
ipmi_sensor_get_id_type(ipmi_sensor_t * sensor)2898 ipmi_sensor_get_id_type(ipmi_sensor_t *sensor)
2899 {
2900     CHECK_SENSOR_LOCK(sensor);
2901 
2902     return sensor->id_type;
2903 }
2904 
2905 int
ipmi_sensor_get_id(ipmi_sensor_t * sensor,char * id,int length)2906 ipmi_sensor_get_id(ipmi_sensor_t *sensor, char *id, int length)
2907 {
2908     int clen;
2909 
2910     CHECK_SENSOR_LOCK(sensor);
2911 
2912     if ((int) sensor->id_len > length)
2913 	clen = length;
2914     else
2915 	clen = sensor->id_len;
2916     memcpy(id, sensor->id, clen);
2917 
2918     if (sensor->id_type == IPMI_ASCII_STR) {
2919 	/* NIL terminate the ASCII string. */
2920 	if (clen == length)
2921 	    clen--;
2922 
2923 	id[clen] = '\0';
2924     }
2925 
2926     return clen;
2927 }
2928 
2929 void
ipmi_sensor_set_owner(ipmi_sensor_t * sensor,int owner)2930 ipmi_sensor_set_owner(ipmi_sensor_t *sensor, int owner)
2931 {
2932     sensor->owner = owner;
2933 }
2934 
2935 void
ipmi_sensor_set_channel(ipmi_sensor_t * sensor,int channel)2936 ipmi_sensor_set_channel(ipmi_sensor_t *sensor, int channel)
2937 {
2938     sensor->channel = channel;
2939 }
2940 
2941 void
ipmi_sensor_set_entity_id(ipmi_sensor_t * sensor,int entity_id)2942 ipmi_sensor_set_entity_id(ipmi_sensor_t *sensor, int entity_id)
2943 {
2944     sensor->entity_id = entity_id;
2945 }
2946 
2947 void
ipmi_sensor_set_entity_instance(ipmi_sensor_t * sensor,int entity_instance)2948 ipmi_sensor_set_entity_instance(ipmi_sensor_t *sensor, int entity_instance)
2949 {
2950     sensor->entity_instance = entity_instance;
2951 }
2952 
2953 void
ipmi_sensor_set_entity_instance_logical(ipmi_sensor_t * sensor,int entity_instance_logical)2954 ipmi_sensor_set_entity_instance_logical(ipmi_sensor_t *sensor,
2955 					int           entity_instance_logical)
2956 {
2957     sensor->entity_instance_logical = entity_instance_logical;
2958 }
2959 
2960 void
ipmi_sensor_set_sensor_init_scanning(ipmi_sensor_t * sensor,int sensor_init_scanning)2961 ipmi_sensor_set_sensor_init_scanning(ipmi_sensor_t *sensor,
2962 				     int           sensor_init_scanning)
2963 {
2964     sensor->sensor_init_scanning = sensor_init_scanning;
2965 }
2966 
2967 void
ipmi_sensor_set_sensor_init_events(ipmi_sensor_t * sensor,int sensor_init_events)2968 ipmi_sensor_set_sensor_init_events(ipmi_sensor_t *sensor,
2969 				   int           sensor_init_events)
2970 {
2971     sensor->sensor_init_events = sensor_init_events;
2972 }
2973 
2974 void
ipmi_sensor_set_sensor_init_thresholds(ipmi_sensor_t * sensor,int sensor_init_thresholds)2975 ipmi_sensor_set_sensor_init_thresholds(ipmi_sensor_t *sensor,
2976 				       int           sensor_init_thresholds)
2977 {
2978     sensor->sensor_init_thresholds = sensor_init_thresholds;
2979 }
2980 
2981 void
ipmi_sensor_set_sensor_init_hysteresis(ipmi_sensor_t * sensor,int sensor_init_hysteresis)2982 ipmi_sensor_set_sensor_init_hysteresis(ipmi_sensor_t *sensor,
2983 				       int           sensor_init_hysteresis)
2984 {
2985     sensor->sensor_init_hysteresis = sensor_init_hysteresis;
2986 }
2987 
2988 void
ipmi_sensor_set_sensor_init_type(ipmi_sensor_t * sensor,int sensor_init_type)2989 ipmi_sensor_set_sensor_init_type(ipmi_sensor_t *sensor, int sensor_init_type)
2990 {
2991     sensor->sensor_init_type = sensor_init_type;
2992 }
2993 
2994 void
ipmi_sensor_set_sensor_init_pu_events(ipmi_sensor_t * sensor,int sensor_init_pu_events)2995 ipmi_sensor_set_sensor_init_pu_events(ipmi_sensor_t *sensor,
2996 				      int           sensor_init_pu_events)
2997 {
2998     sensor->sensor_init_pu_events = sensor_init_pu_events;
2999 }
3000 
3001 void
ipmi_sensor_set_sensor_init_pu_scanning(ipmi_sensor_t * sensor,int sensor_init_pu_scanning)3002 ipmi_sensor_set_sensor_init_pu_scanning(ipmi_sensor_t *sensor,
3003 					int           sensor_init_pu_scanning)
3004 {
3005     sensor->sensor_init_pu_scanning = sensor_init_pu_scanning;
3006 }
3007 
3008 void
ipmi_sensor_set_ignore_if_no_entity(ipmi_sensor_t * sensor,int ignore_if_no_entity)3009 ipmi_sensor_set_ignore_if_no_entity(ipmi_sensor_t *sensor,
3010 				    int           ignore_if_no_entity)
3011 {
3012     sensor->ignore_if_no_entity = ignore_if_no_entity;
3013 }
3014 
3015 void
ipmi_sensor_set_ignore_for_presence(ipmi_sensor_t * sensor,int ignore)3016 ipmi_sensor_set_ignore_for_presence(ipmi_sensor_t *sensor, int ignore)
3017 {
3018     sensor->ignore_for_presence = ignore;
3019 }
3020 
3021 void
ipmi_sensor_set_supports_auto_rearm(ipmi_sensor_t * sensor,int val)3022 ipmi_sensor_set_supports_auto_rearm(ipmi_sensor_t *sensor, int val)
3023 {
3024     sensor->supports_auto_rearm = val;
3025 }
3026 
3027 void
ipmi_sensor_set_hysteresis_support(ipmi_sensor_t * sensor,int hysteresis_support)3028 ipmi_sensor_set_hysteresis_support(ipmi_sensor_t *sensor,
3029 				   int           hysteresis_support)
3030 {
3031     sensor->hysteresis_support = hysteresis_support;
3032 }
3033 
3034 void
ipmi_sensor_set_threshold_access(ipmi_sensor_t * sensor,int threshold_access)3035 ipmi_sensor_set_threshold_access(ipmi_sensor_t *sensor, int threshold_access)
3036 {
3037     sensor->threshold_access = threshold_access;
3038 }
3039 
3040 void
ipmi_sensor_set_event_support(ipmi_sensor_t * sensor,int event_support)3041 ipmi_sensor_set_event_support(ipmi_sensor_t *sensor, int event_support)
3042 {
3043     sensor->event_support = event_support;
3044 }
3045 
3046 void
ipmi_sensor_set_sensor_type(ipmi_sensor_t * sensor,int sensor_type)3047 ipmi_sensor_set_sensor_type(ipmi_sensor_t *sensor, int sensor_type)
3048 {
3049     sensor->sensor_type = sensor_type;
3050 }
3051 
3052 void
ipmi_sensor_set_event_reading_type(ipmi_sensor_t * sensor,int event_reading_type)3053 ipmi_sensor_set_event_reading_type(ipmi_sensor_t *sensor,
3054 				   int           event_reading_type)
3055 {
3056     sensor->event_reading_type = event_reading_type;
3057 }
3058 
3059 void
ipmi_sensor_set_direction(ipmi_sensor_t * sensor,int direction)3060 ipmi_sensor_set_direction(ipmi_sensor_t *sensor,
3061 			  int           direction)
3062 {
3063     sensor->sensor_direction = direction;
3064 }
3065 
3066 void
ipmi_sensor_set_is_readable(ipmi_sensor_t * sensor,int readable)3067 ipmi_sensor_set_is_readable(ipmi_sensor_t *sensor,
3068 			    int           readable)
3069 {
3070     sensor->readable = readable != 0;
3071 }
3072 
3073 void
ipmi_sensor_set_analog_data_format(ipmi_sensor_t * sensor,int analog_data_format)3074 ipmi_sensor_set_analog_data_format(ipmi_sensor_t *sensor,
3075 				   int           analog_data_format)
3076 {
3077     sensor->analog_data_format = analog_data_format;
3078 }
3079 
3080 void
ipmi_sensor_set_rate_unit(ipmi_sensor_t * sensor,int rate_unit)3081 ipmi_sensor_set_rate_unit(ipmi_sensor_t *sensor, int rate_unit)
3082 {
3083     sensor->rate_unit = rate_unit;
3084 }
3085 
3086 void
ipmi_sensor_set_modifier_unit_use(ipmi_sensor_t * sensor,int modifier_unit_use)3087 ipmi_sensor_set_modifier_unit_use(ipmi_sensor_t *sensor, int modifier_unit_use)
3088 {
3089     sensor->modifier_unit_use = modifier_unit_use;
3090 }
3091 
3092 void
ipmi_sensor_set_percentage(ipmi_sensor_t * sensor,int percentage)3093 ipmi_sensor_set_percentage(ipmi_sensor_t *sensor, int percentage)
3094 {
3095     sensor->percentage = percentage;
3096 }
3097 
3098 void
ipmi_sensor_set_base_unit(ipmi_sensor_t * sensor,int base_unit)3099 ipmi_sensor_set_base_unit(ipmi_sensor_t *sensor, int base_unit)
3100 {
3101     sensor->base_unit = base_unit;
3102 }
3103 
3104 void
ipmi_sensor_set_modifier_unit(ipmi_sensor_t * sensor,int modifier_unit)3105 ipmi_sensor_set_modifier_unit(ipmi_sensor_t *sensor, int modifier_unit)
3106 {
3107     sensor->modifier_unit = modifier_unit;
3108 }
3109 
3110 void
ipmi_sensor_set_linearization(ipmi_sensor_t * sensor,int linearization)3111 ipmi_sensor_set_linearization(ipmi_sensor_t *sensor, int linearization)
3112 {
3113     sensor->linearization = linearization;
3114 }
3115 
3116 void
ipmi_sensor_set_raw_m(ipmi_sensor_t * sensor,int idx,int val)3117 ipmi_sensor_set_raw_m(ipmi_sensor_t *sensor, int idx, int val)
3118 {
3119     sensor->conv[idx].m = val;
3120 }
3121 
3122 void
ipmi_sensor_set_raw_tolerance(ipmi_sensor_t * sensor,int idx,int val)3123 ipmi_sensor_set_raw_tolerance(ipmi_sensor_t *sensor, int idx, int val)
3124 {
3125     sensor->conv[idx].tolerance = val;
3126 }
3127 
3128 void
ipmi_sensor_set_raw_b(ipmi_sensor_t * sensor,int idx,int val)3129 ipmi_sensor_set_raw_b(ipmi_sensor_t *sensor, int idx, int val)
3130 {
3131     sensor->conv[idx].b = val;
3132 }
3133 
3134 void
ipmi_sensor_set_raw_accuracy(ipmi_sensor_t * sensor,int idx,int val)3135 ipmi_sensor_set_raw_accuracy(ipmi_sensor_t *sensor, int idx, int val)
3136 {
3137     sensor->conv[idx].accuracy = val;
3138 }
3139 
3140 void
ipmi_sensor_set_raw_accuracy_exp(ipmi_sensor_t * sensor,int idx,int val)3141 ipmi_sensor_set_raw_accuracy_exp(ipmi_sensor_t *sensor, int idx, int val)
3142 {
3143     sensor->conv[idx].accuracy_exp = val;
3144 }
3145 
3146 void
ipmi_sensor_set_raw_r_exp(ipmi_sensor_t * sensor,int idx,int val)3147 ipmi_sensor_set_raw_r_exp(ipmi_sensor_t *sensor, int idx, int val)
3148 {
3149     sensor->conv[idx].r_exp = val;
3150 }
3151 
3152 void
ipmi_sensor_set_raw_b_exp(ipmi_sensor_t * sensor,int idx,int val)3153 ipmi_sensor_set_raw_b_exp(ipmi_sensor_t *sensor, int idx, int val)
3154 {
3155     sensor->conv[idx].b_exp = val;
3156 }
3157 
3158 void
ipmi_sensor_set_normal_min_specified(ipmi_sensor_t * sensor,int normal_min_specified)3159 ipmi_sensor_set_normal_min_specified(ipmi_sensor_t *sensor,
3160 				     int           normal_min_specified)
3161 {
3162     sensor->normal_min_specified = normal_min_specified;
3163 }
3164 
3165 void
ipmi_sensor_set_normal_max_specified(ipmi_sensor_t * sensor,int normal_max_specified)3166 ipmi_sensor_set_normal_max_specified(ipmi_sensor_t *sensor,
3167 				     int           normal_max_specified)
3168 {
3169     sensor->normal_max_specified = normal_max_specified;
3170 }
3171 
3172 void
ipmi_sensor_set_nominal_reading_specified(ipmi_sensor_t * sensor,int nominal_reading_specified)3173 ipmi_sensor_set_nominal_reading_specified(
3174     ipmi_sensor_t *sensor,
3175     int            nominal_reading_specified)
3176 {
3177     sensor->nominal_reading_specified = nominal_reading_specified;
3178 }
3179 
3180 void
ipmi_sensor_set_raw_nominal_reading(ipmi_sensor_t * sensor,int raw_nominal_reading)3181 ipmi_sensor_set_raw_nominal_reading(ipmi_sensor_t *sensor,
3182 				    int           raw_nominal_reading)
3183 {
3184     sensor->nominal_reading = raw_nominal_reading;
3185 }
3186 
3187 void
ipmi_sensor_set_raw_normal_max(ipmi_sensor_t * sensor,int raw_normal_max)3188 ipmi_sensor_set_raw_normal_max(ipmi_sensor_t *sensor, int raw_normal_max)
3189 {
3190     sensor->normal_max = raw_normal_max;
3191 }
3192 
3193 void
ipmi_sensor_set_raw_normal_min(ipmi_sensor_t * sensor,int raw_normal_min)3194 ipmi_sensor_set_raw_normal_min(ipmi_sensor_t *sensor, int raw_normal_min)
3195 {
3196     sensor->normal_min = raw_normal_min;
3197 }
3198 
3199 void
ipmi_sensor_set_raw_sensor_max(ipmi_sensor_t * sensor,int raw_sensor_max)3200 ipmi_sensor_set_raw_sensor_max(ipmi_sensor_t *sensor, int raw_sensor_max)
3201 {
3202     sensor->sensor_max = raw_sensor_max;
3203 }
3204 
3205 void
ipmi_sensor_set_raw_sensor_min(ipmi_sensor_t * sensor,int raw_sensor_min)3206 ipmi_sensor_set_raw_sensor_min(ipmi_sensor_t *sensor, int raw_sensor_min)
3207 {
3208     sensor->sensor_min = raw_sensor_min;
3209 }
3210 
3211 void
ipmi_sensor_set_positive_going_threshold_hysteresis(ipmi_sensor_t * sensor,int positive_going_threshold_hysteresis)3212 ipmi_sensor_set_positive_going_threshold_hysteresis(
3213     ipmi_sensor_t *sensor,
3214     int           positive_going_threshold_hysteresis)
3215 {
3216     sensor->positive_going_threshold_hysteresis
3217 	= positive_going_threshold_hysteresis;
3218 }
3219 
3220 void
ipmi_sensor_set_negative_going_threshold_hysteresis(ipmi_sensor_t * sensor,int negative_going_threshold_hysteresis)3221 ipmi_sensor_set_negative_going_threshold_hysteresis(
3222     ipmi_sensor_t *sensor,
3223     int           negative_going_threshold_hysteresis)
3224 {
3225     sensor->negative_going_threshold_hysteresis
3226 	= negative_going_threshold_hysteresis;
3227 }
3228 
3229 void
ipmi_sensor_set_oem1(ipmi_sensor_t * sensor,int oem1)3230 ipmi_sensor_set_oem1(ipmi_sensor_t *sensor, int oem1)
3231 {
3232     sensor->oem1 = oem1;
3233 }
3234 
3235 void
ipmi_sensor_set_id(ipmi_sensor_t * sensor,char * id,enum ipmi_str_type_e type,int length)3236 ipmi_sensor_set_id(ipmi_sensor_t *sensor, char *id,
3237 		   enum ipmi_str_type_e type, int length)
3238 {
3239     if (length > SENSOR_ID_LEN)
3240 	length = SENSOR_ID_LEN;
3241 
3242     memcpy(sensor->id, id, length);
3243     sensor->id_type = type;
3244     sensor->id_len = length;
3245     if (sensor->entity)
3246 	sensor_set_name(sensor);
3247 }
3248 
3249 void
ipmi_sensor_set_oem_info(ipmi_sensor_t * sensor,void * oem_info,ipmi_sensor_cleanup_oem_info_cb cleanup_handler)3250 ipmi_sensor_set_oem_info(ipmi_sensor_t *sensor, void *oem_info,
3251 			 ipmi_sensor_cleanup_oem_info_cb cleanup_handler)
3252 {
3253     sensor->oem_info = oem_info;
3254     sensor->oem_info_cleanup_handler = cleanup_handler;
3255 }
3256 
3257 void *
ipmi_sensor_get_oem_info(ipmi_sensor_t * sensor)3258 ipmi_sensor_get_oem_info(ipmi_sensor_t *sensor)
3259 {
3260     CHECK_SENSOR_LOCK(sensor);
3261 
3262     return sensor->oem_info;
3263 }
3264 
3265 const char *
ipmi_sensor_get_sensor_type_string(ipmi_sensor_t * sensor)3266 ipmi_sensor_get_sensor_type_string(ipmi_sensor_t *sensor)
3267 {
3268     CHECK_SENSOR_LOCK(sensor);
3269 
3270     return sensor->sensor_type_string;
3271 }
3272 
3273 void
ipmi_sensor_set_sensor_type_string(ipmi_sensor_t * sensor,const char * str)3274 ipmi_sensor_set_sensor_type_string(ipmi_sensor_t *sensor, const char *str)
3275 {
3276     sensor->sensor_type_string = str;
3277 }
3278 
3279 const char *
ipmi_sensor_get_event_reading_type_string(ipmi_sensor_t * sensor)3280 ipmi_sensor_get_event_reading_type_string(ipmi_sensor_t *sensor)
3281 {
3282     CHECK_SENSOR_LOCK(sensor);
3283 
3284     return sensor->event_reading_type_string;
3285 }
3286 
3287 void
ipmi_sensor_set_event_reading_type_string(ipmi_sensor_t * sensor,const char * str)3288 ipmi_sensor_set_event_reading_type_string(ipmi_sensor_t *sensor,
3289 					  const char    *str)
3290 {
3291     sensor->event_reading_type_string = str;
3292 }
3293 
3294 const char *
ipmi_sensor_get_rate_unit_string(ipmi_sensor_t * sensor)3295 ipmi_sensor_get_rate_unit_string(ipmi_sensor_t *sensor)
3296 {
3297     CHECK_SENSOR_LOCK(sensor);
3298 
3299     return sensor->rate_unit_string;
3300 }
3301 
3302 void
ipmi_sensor_set_rate_unit_string(ipmi_sensor_t * sensor,const char * str)3303 ipmi_sensor_set_rate_unit_string(ipmi_sensor_t *sensor,
3304 				 const char    *str)
3305 {
3306     sensor->rate_unit_string = str;
3307 }
3308 
3309 const char *
ipmi_sensor_get_base_unit_string(ipmi_sensor_t * sensor)3310 ipmi_sensor_get_base_unit_string(ipmi_sensor_t *sensor)
3311 {
3312     CHECK_SENSOR_LOCK(sensor);
3313 
3314     return sensor->base_unit_string;
3315 }
3316 
3317 void
ipmi_sensor_set_base_unit_string(ipmi_sensor_t * sensor,const char * str)3318 ipmi_sensor_set_base_unit_string(ipmi_sensor_t *sensor, const char *str)
3319 {
3320     sensor->base_unit_string = str;
3321 }
3322 
3323 const char *
ipmi_sensor_get_modifier_unit_string(ipmi_sensor_t * sensor)3324 ipmi_sensor_get_modifier_unit_string(ipmi_sensor_t *sensor)
3325 {
3326     CHECK_SENSOR_LOCK(sensor);
3327 
3328     return sensor->modifier_unit_string;
3329 }
3330 
3331 void
ipmi_sensor_set_modifier_unit_string(ipmi_sensor_t * sensor,const char * str)3332 ipmi_sensor_set_modifier_unit_string(ipmi_sensor_t *sensor, const char *str)
3333 {
3334     sensor->modifier_unit_string = str;
3335 }
3336 
3337 void
ipmi_sensor_set_hot_swap_requester(ipmi_sensor_t * sensor,int offset,int val_when_requesting)3338 ipmi_sensor_set_hot_swap_requester(ipmi_sensor_t *sensor,
3339 				   int           offset,
3340 				   int           val_when_requesting)
3341 {
3342     sensor->hot_swap_requester = offset;
3343     sensor->hot_swap_requester_val = val_when_requesting;
3344 }
3345 
3346 int
ipmi_sensor_is_hot_swap_requester(ipmi_sensor_t * sensor,int * offset,int * val_when_requesting)3347 ipmi_sensor_is_hot_swap_requester(ipmi_sensor_t *sensor,
3348 				  int           *offset,
3349 				  int           *val_when_requesting)
3350 {
3351     CHECK_SENSOR_LOCK(sensor);
3352 
3353     if (sensor->hot_swap_requester != -1) {
3354 	if (offset)
3355 	    *offset = sensor->hot_swap_requester;
3356 	if (val_when_requesting)
3357 	    *val_when_requesting = sensor->hot_swap_requester_val;
3358 	return 1;
3359     }
3360     return 0;
3361 }
3362 
3363 ipmi_domain_t *
ipmi_sensor_get_domain(ipmi_sensor_t * sensor)3364 ipmi_sensor_get_domain(ipmi_sensor_t *sensor)
3365 {
3366     return sensor->domain;
3367 }
3368 
3369 ipmi_entity_t *
ipmi_sensor_get_entity(ipmi_sensor_t * sensor)3370 ipmi_sensor_get_entity(ipmi_sensor_t *sensor)
3371 {
3372     return sensor->entity;
3373 }
3374 
3375 
3376 /***********************************************************************
3377  *
3378  * Incoming event handling for sensors.
3379  *
3380  **********************************************************************/
3381 
3382 int
ipmi_sensor_threshold_set_event_handler(ipmi_sensor_t * sensor,ipmi_sensor_threshold_event_handler_nd_cb handler,void * cb_data)3383 ipmi_sensor_threshold_set_event_handler(
3384     ipmi_sensor_t                             *sensor,
3385     ipmi_sensor_threshold_event_handler_nd_cb handler,
3386     void                                      *cb_data)
3387 {
3388     CHECK_SENSOR_LOCK(sensor);
3389 
3390     sensor->threshold_event_handler = handler;
3391     sensor->cb_data = cb_data;
3392     return 0;
3393 }
3394 
3395 int
ipmi_sensor_add_threshold_event_handler(ipmi_sensor_t * sensor,ipmi_sensor_threshold_event_cb handler,void * cb_data)3396 ipmi_sensor_add_threshold_event_handler(
3397     ipmi_sensor_t                  *sensor,
3398     ipmi_sensor_threshold_event_cb handler,
3399     void                           *cb_data)
3400 {
3401     CHECK_SENSOR_LOCK(sensor);
3402 
3403     if (! locked_list_add(sensor->handler_list, handler, cb_data))
3404 	return ENOMEM;
3405 
3406     return 0;
3407 }
3408 
3409 int
ipmi_sensor_remove_threshold_event_handler(ipmi_sensor_t * sensor,ipmi_sensor_threshold_event_cb handler,void * cb_data)3410 ipmi_sensor_remove_threshold_event_handler(
3411     ipmi_sensor_t                  *sensor,
3412     ipmi_sensor_threshold_event_cb handler,
3413     void                           *cb_data)
3414 {
3415     CHECK_SENSOR_LOCK(sensor);
3416 
3417     if (! locked_list_remove(sensor->handler_list, handler, cb_data))
3418 	return ENOENT;
3419 
3420     return 0;
3421 }
3422 
3423 int
ipmi_sensor_add_threshold_event_handler_cl(ipmi_sensor_t * sensor,ipmi_sensor_threshold_event_cl_cb handler,void * cb_data)3424 ipmi_sensor_add_threshold_event_handler_cl(
3425     ipmi_sensor_t                     *sensor,
3426     ipmi_sensor_threshold_event_cl_cb handler,
3427     void                              *cb_data)
3428 {
3429     CHECK_SENSOR_LOCK(sensor);
3430 
3431     if (! locked_list_add(sensor->handler_list_cl, handler, cb_data))
3432 	return ENOMEM;
3433 
3434     return 0;
3435 }
3436 
3437 int
ipmi_sensor_remove_threshold_event_handler_cl(ipmi_sensor_t * sensor,ipmi_sensor_threshold_event_cl_cb handler,void * cb_data)3438 ipmi_sensor_remove_threshold_event_handler_cl(
3439     ipmi_sensor_t                     *sensor,
3440     ipmi_sensor_threshold_event_cl_cb handler,
3441     void                              *cb_data)
3442 {
3443     CHECK_SENSOR_LOCK(sensor);
3444 
3445     if (! locked_list_remove(sensor->handler_list_cl, handler, cb_data))
3446 	return ENOENT;
3447 
3448     return 0;
3449 }
3450 
3451 
3452 int
ipmi_sensor_discrete_set_event_handler(ipmi_sensor_t * sensor,ipmi_sensor_discrete_event_handler_nd_cb handler,void * cb_data)3453 ipmi_sensor_discrete_set_event_handler(
3454     ipmi_sensor_t                            *sensor,
3455     ipmi_sensor_discrete_event_handler_nd_cb handler,
3456     void                                     *cb_data)
3457 {
3458     CHECK_SENSOR_LOCK(sensor);
3459 
3460     sensor->discrete_event_handler = handler;
3461     sensor->cb_data = cb_data;
3462     return 0;
3463 }
3464 
3465 int
ipmi_sensor_add_discrete_event_handler(ipmi_sensor_t * sensor,ipmi_sensor_discrete_event_cb handler,void * cb_data)3466 ipmi_sensor_add_discrete_event_handler(
3467     ipmi_sensor_t                 *sensor,
3468     ipmi_sensor_discrete_event_cb handler,
3469     void                          *cb_data)
3470 {
3471     CHECK_SENSOR_LOCK(sensor);
3472 
3473     if (! locked_list_add(sensor->handler_list, handler, cb_data))
3474 	return ENOMEM;
3475 
3476     return 0;
3477 }
3478 
3479 int
ipmi_sensor_remove_discrete_event_handler(ipmi_sensor_t * sensor,ipmi_sensor_discrete_event_cb handler,void * cb_data)3480 ipmi_sensor_remove_discrete_event_handler(
3481     ipmi_sensor_t                 *sensor,
3482     ipmi_sensor_discrete_event_cb handler,
3483     void                          *cb_data)
3484 {
3485     CHECK_SENSOR_LOCK(sensor);
3486 
3487     if (! locked_list_remove(sensor->handler_list, handler, cb_data))
3488 	return ENOENT;
3489 
3490     return 0;
3491 }
3492 
3493 int
ipmi_sensor_add_discrete_event_handler_cl(ipmi_sensor_t * sensor,ipmi_sensor_discrete_event_cl_cb handler,void * cb_data)3494 ipmi_sensor_add_discrete_event_handler_cl(
3495     ipmi_sensor_t                    *sensor,
3496     ipmi_sensor_discrete_event_cl_cb handler,
3497     void                             *cb_data)
3498 {
3499     CHECK_SENSOR_LOCK(sensor);
3500 
3501     if (! locked_list_add(sensor->handler_list_cl, handler, cb_data))
3502 	return ENOMEM;
3503 
3504     return 0;
3505 }
3506 
3507 int
ipmi_sensor_remove_discrete_event_handler_cl(ipmi_sensor_t * sensor,ipmi_sensor_discrete_event_cl_cb handler,void * cb_data)3508 ipmi_sensor_remove_discrete_event_handler_cl(
3509     ipmi_sensor_t                    *sensor,
3510     ipmi_sensor_discrete_event_cl_cb handler,
3511     void                             *cb_data)
3512 {
3513     CHECK_SENSOR_LOCK(sensor);
3514 
3515     if (! locked_list_remove(sensor->handler_list_cl, handler, cb_data))
3516 	return ENOENT;
3517 
3518     return 0;
3519 }
3520 
3521 typedef struct sensor_event_info_s
3522 {
3523     ipmi_sensor_t               *sensor;
3524     int                         handled;
3525 
3526     enum ipmi_event_dir_e       dir;
3527     enum ipmi_thresh_e          threshold;
3528     enum ipmi_event_value_dir_e high_low;
3529     enum ipmi_value_present_e   value_present;
3530     unsigned int                raw_value;
3531     double                      value;
3532 
3533     int                         offset;
3534     int                         severity;
3535     int                         prev_severity;
3536 
3537     ipmi_event_t                *event;
3538 } sensor_event_info_t;
3539 
3540 static int
threshold_sensor_event_call_handler(void * cb_data,void * item1,void * item2)3541 threshold_sensor_event_call_handler(void *cb_data, void *item1, void *item2)
3542 {
3543     ipmi_sensor_threshold_event_cb handler = item1;
3544     sensor_event_info_t            *info = cb_data;
3545     int                            handled;
3546 
3547     handled = handler(info->sensor, info->dir,
3548 		      info->threshold,
3549 		      info->high_low,
3550 		      info->value_present,
3551 		      info->raw_value, info->value,
3552 		      item2, info->event);
3553     if (handled != IPMI_EVENT_NOT_HANDLED) {
3554 	if (info->handled != IPMI_EVENT_HANDLED)
3555 	    /* Allow handled to override handled_pass, but not the
3556 	       other way. */
3557 	    info->handled = handled;
3558 	if (handled == IPMI_EVENT_HANDLED)
3559 	    info->event = NULL;
3560     }
3561     return LOCKED_LIST_ITER_CONTINUE;
3562 }
3563 
3564 void
ipmi_sensor_call_threshold_event_handlers(ipmi_sensor_t * sensor,enum ipmi_event_dir_e dir,enum ipmi_thresh_e threshold,enum ipmi_event_value_dir_e high_low,enum ipmi_value_present_e value_present,unsigned int raw_value,double value,ipmi_event_t ** event,int * handled)3565 ipmi_sensor_call_threshold_event_handlers
3566 (ipmi_sensor_t               *sensor,
3567  enum ipmi_event_dir_e       dir,
3568  enum ipmi_thresh_e          threshold,
3569  enum ipmi_event_value_dir_e high_low,
3570  enum ipmi_value_present_e   value_present,
3571  unsigned int                raw_value,
3572  double                      value,
3573  ipmi_event_t                **event,
3574  int                         *handled)
3575 {
3576     sensor_event_info_t info;
3577 
3578     info.sensor = sensor;
3579     info.dir = dir;
3580     info.threshold = threshold;
3581     info.high_low = high_low;
3582     info.value_present = value_present;
3583     info.raw_value = raw_value;
3584     info.value = value;
3585     info.event = *event;
3586     if (handled)
3587 	info.handled = *handled;
3588     else
3589 	info.handled = IPMI_EVENT_NOT_HANDLED;
3590 
3591     if (sensor->threshold_event_handler) {
3592 	sensor->threshold_event_handler(sensor, info.dir,
3593 					info.threshold,
3594 					info.high_low,
3595 					info.value_present,
3596 					info.raw_value, info.value,
3597 					sensor->cb_data, info.event);
3598 	if (info.event)
3599 	    info.handled = IPMI_EVENT_HANDLED;
3600 	info.event = NULL;
3601     }
3602     locked_list_iterate(sensor->handler_list,
3603 			threshold_sensor_event_call_handler, &info);
3604 
3605     if (handled)
3606 	*handled = info.handled;
3607     *event = info.event;
3608 }
3609 
3610 static int
discrete_sensor_event_call_handler(void * cb_data,void * item1,void * item2)3611 discrete_sensor_event_call_handler(void *cb_data, void *item1, void *item2)
3612 {
3613     ipmi_sensor_discrete_event_cb handler = item1;
3614     sensor_event_info_t           *info = cb_data;
3615     int                           handled;
3616 
3617     handled = handler(info->sensor, info->dir, info->offset,
3618 		      info->severity,
3619 		      info->prev_severity,
3620 		      item2, info->event);
3621     if (handled != IPMI_EVENT_NOT_HANDLED) {
3622 	if (info->handled != IPMI_EVENT_HANDLED)
3623 	    /* Allow handled to override handled_pass, but not the
3624 	       other way. */
3625 	    info->handled = handled;
3626 	if (handled == IPMI_EVENT_HANDLED)
3627 	    info->event = NULL;
3628     }
3629     return LOCKED_LIST_ITER_CONTINUE;
3630 }
3631 
3632 void
ipmi_sensor_call_discrete_event_handlers(ipmi_sensor_t * sensor,enum ipmi_event_dir_e dir,int offset,int severity,int prev_severity,ipmi_event_t ** event,int * handled)3633 ipmi_sensor_call_discrete_event_handlers(ipmi_sensor_t         *sensor,
3634 					 enum ipmi_event_dir_e dir,
3635 					 int                   offset,
3636 					 int                   severity,
3637 					 int                   prev_severity,
3638 					 ipmi_event_t          **event,
3639 					 int                   *handled)
3640 {
3641     sensor_event_info_t info;
3642 
3643     info.sensor = sensor;
3644     info.dir = dir;
3645     info.offset = offset;
3646     info.severity = severity;
3647     info.prev_severity = prev_severity;
3648     info.event = *event;
3649     if (handled)
3650 	info.handled = *handled;
3651     else
3652 	info.handled = IPMI_EVENT_NOT_HANDLED;
3653 
3654     if (sensor->discrete_event_handler) {
3655 	sensor->discrete_event_handler(sensor, info.dir, info.offset,
3656 				       info.severity,
3657 				       info.prev_severity,
3658 				       sensor->cb_data, info.event);
3659 	if (info.event)
3660 	    info.handled = IPMI_EVENT_HANDLED;
3661 	info.event = NULL;
3662     }
3663     locked_list_iterate(sensor->handler_list,
3664 			discrete_sensor_event_call_handler, &info);
3665 
3666     if (handled)
3667 	*handled = info.handled;
3668     *event = info.event;
3669 }
3670 
3671 int
ipmi_sensor_event(ipmi_sensor_t * sensor,ipmi_event_t * event)3672 ipmi_sensor_event(ipmi_sensor_t *sensor, ipmi_event_t *event)
3673 {
3674     int rv;
3675     int handled;
3676 
3677     CHECK_SENSOR_LOCK(sensor);
3678 
3679     handled = IPMI_EVENT_NOT_HANDLED;
3680 
3681     if (sensor->event_reading_type == IPMI_EVENT_READING_TYPE_THRESHOLD) {
3682 	enum ipmi_event_dir_e       dir;
3683 	enum ipmi_thresh_e          threshold;
3684 	enum ipmi_event_value_dir_e high_low;
3685 	enum ipmi_value_present_e   value_present;
3686 	unsigned int                raw_value;
3687 	double                      value;
3688 	const unsigned char         *data;
3689 
3690 	data = ipmi_event_get_data_ptr(event);
3691 	dir = data[9] >> 7;
3692 	threshold = (data[10] >> 1) & 0x07;
3693 	high_low = data[10] & 1;
3694 	raw_value = data[11];
3695 	value = 0.0;
3696 
3697 	if ((data[10] >> 6) == 1) {
3698 	    rv = ipmi_sensor_convert_from_raw(sensor, raw_value, &value);
3699 	    if (rv)
3700 		value_present = IPMI_RAW_VALUE_PRESENT;
3701 	    else
3702 		value_present = IPMI_BOTH_VALUES_PRESENT;
3703 	} else {
3704 	    value_present = IPMI_NO_VALUES_PRESENT;
3705 	}
3706 	ipmi_sensor_call_threshold_event_handlers(sensor, dir,
3707 						  threshold,
3708 						  high_low,
3709 						  value_present,
3710 						  raw_value, value,
3711 						  &event,
3712 						  &handled);
3713     } else {
3714 	enum ipmi_event_dir_e dir;
3715 	int                   offset;
3716 	int                   severity = 0;
3717 	int                   prev_severity = 0;
3718 	const unsigned char   *data;
3719 
3720 	data = ipmi_event_get_data_ptr(event);
3721 	dir = data[9] >> 7;
3722 	offset = data[10] & 0x0f;
3723 	if ((data[10] >> 6) == 2) {
3724 	    severity = data[11] >> 4;
3725 	    prev_severity = data[11] & 0xf;
3726 	    if (severity == 0xf)
3727 		severity = -1;
3728 	    if (prev_severity == 0xf)
3729 		prev_severity = -1;
3730 	}
3731 
3732 	ipmi_sensor_call_discrete_event_handlers(sensor, dir, offset,
3733 						 severity,
3734 						 prev_severity,
3735 						 &event,
3736 						 &handled);
3737     }
3738 
3739     /* Make sure the caller knows if we didn't deliver the event. */
3740     if (handled == IPMI_EVENT_NOT_HANDLED)
3741 	return EINVAL;
3742     return 0;
3743 }
3744 
3745 /***********************************************************************
3746  *
3747  * Standard sensor messaging.
3748  *
3749  **********************************************************************/
3750 
3751 typedef void (*sensor_done_handler_cb)(ipmi_sensor_t *sensor,
3752 				       int           err,
3753 				       void          *sinfo);
3754 
3755 static int
sensor_done_check_rsp(ipmi_sensor_t * sensor,int err,ipmi_msg_t * rsp,unsigned int min_length,char * name,sensor_done_handler_cb done,void * sinfo)3756 sensor_done_check_rsp(ipmi_sensor_t          *sensor,
3757 		      int                    err,
3758 		      ipmi_msg_t             *rsp,
3759 		      unsigned int           min_length,
3760 		      char                   *name,
3761 		      sensor_done_handler_cb done,
3762 		      void                   *sinfo)
3763 {
3764     if (err) {
3765 	ipmi_log(IPMI_LOG_ERR_INFO,
3766 		 "%ssensor.c(%s): Got error: %x",
3767 		 SENSOR_NAME(sensor), name, err);
3768 	done(sensor, err, sinfo);
3769 	return err;
3770     }
3771 
3772     if (!sensor) {
3773 	/* This *should* never happen, but we check it to shake out
3774 	   bugs. */
3775 	ipmi_log(IPMI_LOG_ERR_INFO,
3776 		 "%ssensor.c(%s): Sensor when away during operation",
3777 		 SENSOR_NAME(sensor), name);
3778 	done(sensor, ECANCELED, sinfo);
3779 	return ECANCELED;
3780     }
3781 
3782     if (rsp && rsp->data[0]) {
3783 #if 0
3784 	/* This is sometimes expected. */
3785 	ipmi_log(IPMI_LOG_ERR_INFO,
3786 		 "%ssensor.c(%s): Got IPMI error in response: %x",
3787 		 SENSOR_NAME(sensor), name, rsp->data[0]);
3788 #endif
3789 	done(sensor, IPMI_IPMI_ERR_VAL(rsp->data[0]), sinfo);
3790 	return IPMI_IPMI_ERR_VAL(rsp->data[0]);
3791     }
3792 
3793     if (rsp && (rsp->data_len < min_length)) {
3794 	ipmi_log(IPMI_LOG_ERR_INFO,
3795 		 "%ssensor.c(%s): Response was too short, got %d, expected %d",
3796 		 SENSOR_NAME(sensor), name, rsp->data_len, min_length);
3797 	done(sensor, EINVAL, sinfo);
3798 	return EINVAL;
3799     }
3800 
3801     return 0;
3802 }
3803 
3804 typedef struct event_enable_info_s
3805 {
3806     ipmi_sensor_op_info_t sdata;
3807     ipmi_event_state_t    state;
3808     ipmi_sensor_done_cb   done;
3809     void                  *cb_data;
3810     int                   do_enable;
3811     int                   do_disable;
3812 } event_enable_info_t;
3813 
enables_done_handler(ipmi_sensor_t * sensor,int err,void * sinfo)3814 static void enables_done_handler(ipmi_sensor_t *sensor,
3815 				 int           err,
3816 				 void          *sinfo)
3817 {
3818     event_enable_info_t *info = sinfo;
3819 
3820     if (info->done)
3821 	info->done(sensor, err, info->cb_data);
3822     ipmi_sensor_opq_done(sensor);
3823     ipmi_mem_free(info);
3824 }
3825 
3826 static void
disables_set(ipmi_sensor_t * sensor,int err,ipmi_msg_t * rsp,void * cb_data)3827 disables_set(ipmi_sensor_t *sensor,
3828 	     int           err,
3829 	     ipmi_msg_t    *rsp,
3830 	     void          *cb_data)
3831 {
3832     event_enable_info_t *info = cb_data;
3833 
3834     if (sensor_done_check_rsp(sensor, err, rsp, 1, "disables_set",
3835 			      enables_done_handler, info))
3836 	return;
3837 
3838     enables_done_handler(sensor, 0, info);
3839 }
3840 
3841 static void
enables_set(ipmi_sensor_t * sensor,int err,ipmi_msg_t * rsp,void * cb_data)3842 enables_set(ipmi_sensor_t *sensor,
3843 	    int           err,
3844 	    ipmi_msg_t    *rsp,
3845 	    void          *cb_data)
3846 {
3847     event_enable_info_t *info = cb_data;
3848     unsigned char       cmd_data[MAX_IPMI_DATA_SIZE];
3849     ipmi_msg_t          cmd_msg;
3850     int                 rv;
3851 
3852     if (sensor_done_check_rsp(sensor, err, rsp, 1, "enables_set",
3853 			      enables_done_handler, info))
3854 	return;
3855 
3856     if (info->do_disable) {
3857 	/* Enables were set, now disable all the other ones.  Make
3858 	   sure we only set event bits that we support. */
3859 	uint16_t val1, val2;
3860 
3861 	cmd_msg.netfn = IPMI_SENSOR_EVENT_NETFN;
3862 	cmd_msg.cmd = IPMI_SET_SENSOR_EVENT_ENABLE_CMD;
3863 	cmd_msg.data_len = 6;
3864 	cmd_msg.data = cmd_data;
3865 	cmd_data[0] = sensor->num;
3866 	cmd_data[1] = (info->state.status & 0xc0) | (0x02 << 4);
3867 	ipmi_sensor_get_event_masks(sensor, &val1, &val2);
3868 	val1 &= ~info->state.__assertion_events;
3869 	val2 &= ~info->state.__deassertion_events;
3870 	ipmi_set_uint16(cmd_data+2, val1);
3871 	ipmi_set_uint16(cmd_data+4, val2);
3872 	rv = ipmi_sensor_send_command(sensor, sensor->mc, sensor->send_lun,
3873 				      &cmd_msg, disables_set,
3874 				      &(info->sdata), info);
3875 	if (rv) {
3876 	    ipmi_log(IPMI_LOG_ERR_INFO,
3877 		     "%ssensors.c(enables_set):"
3878 		     " Error sending event enable command to clear events: %x",
3879 		     SENSOR_NAME(sensor), rv);
3880 	    enables_done_handler(sensor, rv, info);
3881 	}
3882     } else {
3883 	/* Just doing enables, we are done. */
3884 	enables_done_handler(sensor, 0, info);
3885     }
3886 }
3887 
3888 static void
event_enable_set_start(ipmi_sensor_t * sensor,int err,void * cb_data)3889 event_enable_set_start(ipmi_sensor_t *sensor, int err, void *cb_data)
3890 {
3891     event_enable_info_t *info = cb_data;
3892     unsigned char       cmd_data[MAX_IPMI_DATA_SIZE];
3893     ipmi_msg_t          cmd_msg;
3894     int                 event_support;
3895     int                 rv;
3896 
3897     if (sensor_done_check_rsp(sensor, err, NULL, 0, "event_enable_set_start",
3898 			      enables_done_handler, info))
3899 	return;
3900 
3901     event_support = ipmi_sensor_get_event_support(sensor);
3902 
3903     cmd_msg.data = cmd_data;
3904     cmd_msg.netfn = IPMI_SENSOR_EVENT_NETFN;
3905     cmd_msg.cmd = IPMI_SET_SENSOR_EVENT_ENABLE_CMD;
3906     cmd_msg.data = cmd_data;
3907     cmd_data[0] = sensor->num;
3908     if (event_support == IPMI_EVENT_SUPPORT_ENTIRE_SENSOR) {
3909 	/* We can only turn on/off the entire sensor, just pass the
3910            status to the sensor. */
3911 	cmd_data[1] = info->state.status & 0xc0;
3912 	cmd_msg.data_len = 2;
3913 	rv = ipmi_sensor_send_command(sensor, sensor->mc, sensor->send_lun,
3914 				      &cmd_msg, disables_set, &(info->sdata),
3915 				      info);
3916     } else if (info->do_enable) {
3917 	/* Start by first setting the enables, then set the disables
3918            in a second operation.  We do this because enables and
3919            disables cannot both be set at the same time, and it's
3920            safer to first enable the new events then to disable the
3921            events we want disabled.  It would be *really* nice if IPMI
3922            had a way to do this in one operation, such as using 11b in
3923            the request byte 2 bits 5:4 to say "set the events to
3924            exactly this state". */
3925 	cmd_data[1] = (info->state.status & 0xc0) | (0x01 << 4);
3926 	cmd_data[2] = info->state.__assertion_events & 0xff;
3927 	cmd_data[3] = info->state.__assertion_events >> 8;
3928 	cmd_data[4] = info->state.__deassertion_events & 0xff;
3929 	cmd_data[5] = info->state.__deassertion_events >> 8;
3930 	cmd_msg.data_len = 6;
3931 	rv = ipmi_sensor_send_command(sensor, sensor->mc, sensor->send_lun,
3932 				      &cmd_msg, enables_set, &(info->sdata),
3933 				      info);
3934     } else {
3935 	/* We are only doing disables. */
3936 	cmd_data[1] = (info->state.status & 0xc0) | (0x02 << 4);
3937 	cmd_data[2] = info->state.__assertion_events & 0xff;
3938 	cmd_data[3] = info->state.__assertion_events >> 8;
3939 	cmd_data[4] = info->state.__deassertion_events & 0xff;
3940 	cmd_data[5] = info->state.__deassertion_events >> 8;
3941 	cmd_msg.data_len = 6;
3942 	rv = ipmi_sensor_send_command(sensor, sensor->mc, sensor->send_lun,
3943 				      &cmd_msg, disables_set,
3944 				      &(info->sdata), info);
3945     }
3946     if (rv) {
3947 	ipmi_log(IPMI_LOG_ERR_INFO,
3948 		 "%ssensor.c(event_enable_set_start):"
3949 		 " Error sending event enable command: %x",
3950 		 SENSOR_NAME(sensor), rv);
3951 	enables_done_handler(sensor, rv, info);
3952     }
3953 }
3954 
3955 static int
check_events_capability(ipmi_sensor_t * sensor,ipmi_event_state_t * states)3956 check_events_capability(ipmi_sensor_t      *sensor,
3957 			ipmi_event_state_t *states)
3958 {
3959     int event_support;
3960 
3961     event_support = ipmi_sensor_get_event_support(sensor);
3962     if ((event_support == IPMI_EVENT_SUPPORT_NONE)
3963 	|| (event_support == IPMI_EVENT_SUPPORT_GLOBAL_ENABLE))
3964     {
3965 	/* We don't support setting events for this sensor. */
3966 	return EINVAL;
3967     }
3968 
3969     if ((event_support == IPMI_EVENT_SUPPORT_ENTIRE_SENSOR)
3970 	&& ((states->__assertion_events != 0)
3971 	    || (states->__deassertion_events != 0)))
3972     {
3973 	/* This sensor does not support individual event states, but
3974            the user is trying to set them. */
3975 	return EINVAL;
3976     }
3977 
3978     if (event_support == IPMI_EVENT_SUPPORT_PER_STATE) {
3979 	uint16_t mask1, mask2;
3980 
3981 	ipmi_sensor_get_event_masks(sensor, &mask1, &mask2);
3982 	if (((~mask1) & states->__assertion_events)
3983 	    || ((~mask2) & states->__deassertion_events))
3984 	{
3985 	    /* The user is attempting to set a state that the
3986 	       sensor does not support. */
3987 	    return EINVAL;
3988 	}
3989     }
3990 
3991     return 0;
3992 }
3993 
3994 static int
stand_ipmi_sensor_set_event_enables(ipmi_sensor_t * sensor,ipmi_event_state_t * states,ipmi_sensor_done_cb done,void * cb_data)3995 stand_ipmi_sensor_set_event_enables(ipmi_sensor_t         *sensor,
3996 				    ipmi_event_state_t    *states,
3997 				    ipmi_sensor_done_cb   done,
3998 				    void                  *cb_data)
3999 {
4000     event_enable_info_t *info;
4001     int                 rv;
4002 
4003     rv = check_events_capability(sensor, states);
4004     if (rv)
4005 	return rv;
4006 
4007     info = ipmi_mem_alloc(sizeof(*info));
4008     if (!info)
4009 	return ENOMEM;
4010     info->state = *states;
4011     info->done = done;
4012     info->cb_data = cb_data;
4013     info->do_enable = 1;
4014     info->do_disable = 1;
4015     rv = ipmi_sensor_add_opq(sensor, event_enable_set_start,
4016 			     &(info->sdata), info);
4017     if (rv)
4018 	ipmi_mem_free(info);
4019     return rv;
4020 }
4021 
4022 static int
stand_ipmi_sensor_enable_events(ipmi_sensor_t * sensor,ipmi_event_state_t * states,ipmi_sensor_done_cb done,void * cb_data)4023 stand_ipmi_sensor_enable_events(ipmi_sensor_t         *sensor,
4024 				ipmi_event_state_t    *states,
4025 				ipmi_sensor_done_cb   done,
4026 				void                  *cb_data)
4027 {
4028     event_enable_info_t *info;
4029     int                 rv;
4030 
4031     rv = check_events_capability(sensor, states);
4032     if (rv)
4033 	return rv;
4034 
4035     info = ipmi_mem_alloc(sizeof(*info));
4036     if (!info)
4037 	return ENOMEM;
4038     info->state = *states;
4039     info->done = done;
4040     info->cb_data = cb_data;
4041     info->do_enable = 1;
4042     info->do_disable = 0;
4043     rv = ipmi_sensor_add_opq(sensor, event_enable_set_start,
4044 			     &(info->sdata), info);
4045     if (rv)
4046 	ipmi_mem_free(info);
4047     return rv;
4048 }
4049 
4050 static int
stand_ipmi_sensor_disable_events(ipmi_sensor_t * sensor,ipmi_event_state_t * states,ipmi_sensor_done_cb done,void * cb_data)4051 stand_ipmi_sensor_disable_events(ipmi_sensor_t         *sensor,
4052 				 ipmi_event_state_t    *states,
4053 				 ipmi_sensor_done_cb   done,
4054 				 void                  *cb_data)
4055 {
4056     event_enable_info_t *info;
4057     int                 rv;
4058 
4059     rv = check_events_capability(sensor, states);
4060     if (rv)
4061 	return rv;
4062 
4063     info = ipmi_mem_alloc(sizeof(*info));
4064     if (!info)
4065 	return ENOMEM;
4066     info->state = *states;
4067     info->done = done;
4068     info->cb_data = cb_data;
4069     info->do_enable = 0;
4070     info->do_disable = 1;
4071     rv = ipmi_sensor_add_opq(sensor, event_enable_set_start,
4072 			     &(info->sdata), info);
4073     if (rv)
4074 	ipmi_mem_free(info);
4075     return rv;
4076 }
4077 
4078 typedef struct event_enable_get_info_s
4079 {
4080     ipmi_sensor_op_info_t        sdata;
4081     ipmi_event_state_t           state;
4082     ipmi_sensor_event_enables_cb done;
4083     void                         *cb_data;
4084 } event_enable_get_info_t;
4085 
enables_get_done_handler(ipmi_sensor_t * sensor,int err,void * sinfo)4086 static void enables_get_done_handler(ipmi_sensor_t *sensor,
4087 				     int           err,
4088 				     void          *sinfo)
4089 {
4090     event_enable_get_info_t *info = sinfo;
4091 
4092     if (info->done)
4093 	info->done(sensor, err, &info->state, info->cb_data);
4094     ipmi_sensor_opq_done(sensor);
4095     ipmi_mem_free(info);
4096 }
4097 
4098 static void
enables_get(ipmi_sensor_t * sensor,int err,ipmi_msg_t * rsp,void * cb_data)4099 enables_get(ipmi_sensor_t *sensor,
4100 	    int           err,
4101 	    ipmi_msg_t    *rsp,
4102 	    void          *cb_data)
4103 {
4104     event_enable_get_info_t *info = cb_data;
4105 
4106     if (sensor_done_check_rsp(sensor, err, rsp, 2, "enables_get",
4107 			      enables_get_done_handler, info))
4108 	return;
4109 
4110     info->state.status = rsp->data[1] & 0xc0;
4111     if (rsp->data_len >= 3)
4112 	info->state.__assertion_events = rsp->data[2];
4113     if (rsp->data_len >= 4)
4114         info->state.__assertion_events |= rsp->data[3] << 8;
4115     if (rsp->data_len >= 5)
4116         info->state.__deassertion_events = rsp->data[4];
4117     if (rsp->data_len >= 6)
4118         info->state.__deassertion_events |= rsp->data[5] << 8;
4119 
4120     /* Mask off reserved bits */
4121     if (sensor->event_reading_type == IPMI_EVENT_READING_TYPE_THRESHOLD) {
4122 	info->state.__assertion_events &= 0x0fff;
4123         info->state.__deassertion_events &= 0x0fff;
4124     } else {
4125 	info->state.__assertion_events &= 0x7fff;
4126         info->state.__deassertion_events &= 0x7fff;
4127     }
4128 
4129     /* It is possible that there are events set here that are not in
4130        sensor->mask1 (assertion events) or sensor->mask2 (deassertion
4131        events).  That's a bug in the sensor; it shouldn't be setting
4132        those bits.  If it ever comes to the point where we need to
4133        handle that here, a simple mask operation would do it. */
4134 
4135     enables_get_done_handler(sensor, 0, info);
4136 }
4137 
4138 static void
event_enable_get_start(ipmi_sensor_t * sensor,int err,void * cb_data)4139 event_enable_get_start(ipmi_sensor_t *sensor, int err, void *cb_data)
4140 {
4141     event_enable_get_info_t *info = cb_data;
4142     unsigned char           cmd_data[MAX_IPMI_DATA_SIZE];
4143     ipmi_msg_t              cmd_msg;
4144     int                     rv;
4145 
4146     if (sensor_done_check_rsp(sensor, err, NULL, 0, "event_enable_get_start",
4147 			      enables_get_done_handler, info))
4148 	return;
4149 
4150     cmd_msg.data = cmd_data;
4151     cmd_msg.netfn = IPMI_SENSOR_EVENT_NETFN;
4152     cmd_msg.cmd = IPMI_GET_SENSOR_EVENT_ENABLE_CMD;
4153     cmd_msg.data_len = 1;
4154     cmd_msg.data = cmd_data;
4155     cmd_data[0] = sensor->num;
4156     rv = ipmi_sensor_send_command(sensor, sensor->mc, sensor->send_lun,
4157 				  &cmd_msg, enables_get, &(info->sdata), info);
4158     if (rv) {
4159 	ipmi_log(IPMI_LOG_ERR_INFO,
4160 		 "%ssensor.c(event_enable_get_start):"
4161 		 " Error sending get event enables command: %x",
4162 		 SENSOR_NAME(sensor), rv);
4163 	enables_get_done_handler(sensor, rv, info);
4164     }
4165 }
4166 
4167 static int
stand_ipmi_sensor_get_event_enables(ipmi_sensor_t * sensor,ipmi_sensor_event_enables_cb done,void * cb_data)4168 stand_ipmi_sensor_get_event_enables(ipmi_sensor_t                *sensor,
4169 				    ipmi_sensor_event_enables_cb done,
4170 				    void                         *cb_data)
4171 {
4172     event_enable_get_info_t *info;
4173     int                     rv;
4174 
4175     info = ipmi_mem_alloc(sizeof(*info));
4176     if (!info)
4177 	return ENOMEM;
4178     memset(info, 0, sizeof(*info));
4179     info->done = done;
4180     info->cb_data = cb_data;
4181     rv = ipmi_sensor_add_opq(sensor, event_enable_get_start,
4182 			     &(info->sdata), info);
4183     if (rv)
4184 	ipmi_mem_free(info);
4185     return rv;
4186 }
4187 
4188 typedef struct sensor_rearm_info_s
4189 {
4190     ipmi_sensor_op_info_t sdata;
4191     ipmi_event_state_t    state;
4192     int                   global_enable;
4193     ipmi_sensor_done_cb   done;
4194     void                  *cb_data;
4195 } sensor_rearm_info_t;
4196 
sensor_rearm_done_handler(ipmi_sensor_t * sensor,int err,void * sinfo)4197 static void sensor_rearm_done_handler(ipmi_sensor_t *sensor,
4198 				      int           err,
4199 				      void          *sinfo)
4200 {
4201     sensor_rearm_info_t *info = sinfo;
4202 
4203     if (info->done)
4204 	info->done(sensor, err, info->cb_data);
4205     ipmi_sensor_opq_done(sensor);
4206     ipmi_mem_free(info);
4207 }
4208 
4209 static void
sensor_rearm(ipmi_sensor_t * sensor,int err,ipmi_msg_t * rsp,void * cb_data)4210 sensor_rearm(ipmi_sensor_t *sensor,
4211 	     int           err,
4212 	     ipmi_msg_t    *rsp,
4213 	     void          *cb_data)
4214 {
4215     sensor_rearm_info_t *info = cb_data;
4216 
4217     if (sensor_done_check_rsp(sensor, err, rsp, 1, "sensor_rearm",
4218 			      sensor_rearm_done_handler, info))
4219 	return;
4220 
4221     sensor_rearm_done_handler(sensor, 0, info);
4222 }
4223 
4224 static void
sensor_rearm_start(ipmi_sensor_t * sensor,int err,void * cb_data)4225 sensor_rearm_start(ipmi_sensor_t *sensor, int err, void *cb_data)
4226 {
4227     sensor_rearm_info_t *info = cb_data;
4228     unsigned char   cmd_data[MAX_IPMI_DATA_SIZE];
4229     ipmi_msg_t      cmd_msg;
4230     int             rv;
4231 
4232     if (sensor_done_check_rsp(sensor, err, NULL, 0, "sensor_rearm_start",
4233 			      sensor_rearm_done_handler, info))
4234 	return;
4235 
4236     cmd_msg.data = cmd_data;
4237     cmd_msg.netfn = IPMI_SENSOR_EVENT_NETFN;
4238     cmd_msg.cmd = IPMI_REARM_SENSOR_EVENTS_CMD;
4239     if (info->global_enable) {
4240 	cmd_msg.data_len = 2;
4241 	cmd_msg.data = cmd_data;
4242 	cmd_data[0] = sensor->num;
4243 	cmd_data[1] = 0; /* Rearm all events. */
4244     } else {
4245 	cmd_msg.data_len = 6;
4246 	cmd_msg.data = cmd_data;
4247 	cmd_data[0] = sensor->num;
4248 	cmd_data[1] = 0x80; /* Rearm only specific sensors. */
4249 	cmd_data[2] = info->state.__assertion_events & 0xff;
4250 	cmd_data[3] = info->state.__assertion_events >> 8;
4251 	cmd_data[4] = info->state.__deassertion_events & 0xff;
4252 	cmd_data[5] = info->state.__deassertion_events >> 8;
4253     }
4254     rv = ipmi_sensor_send_command(sensor, sensor->mc, sensor->send_lun,
4255 				  &cmd_msg, sensor_rearm,
4256 				  &(info->sdata), info);
4257     if (rv) {
4258 	ipmi_log(IPMI_LOG_ERR_INFO,
4259 		 "%ssensor.c(sensor_rearm_start):"
4260 		 " Error sending rearm command: %x",
4261 		 SENSOR_NAME(sensor), rv);
4262 	sensor_rearm_done_handler(sensor, rv, info);
4263     }
4264 }
4265 
4266 static int
stand_ipmi_sensor_rearm(ipmi_sensor_t * sensor,int global_enable,ipmi_event_state_t * state,ipmi_sensor_done_cb done,void * cb_data)4267 stand_ipmi_sensor_rearm(ipmi_sensor_t       *sensor,
4268 			int                 global_enable,
4269 			ipmi_event_state_t  *state,
4270 			ipmi_sensor_done_cb done,
4271 			void                *cb_data)
4272 {
4273     sensor_rearm_info_t *info;
4274     int                 rv;
4275 
4276     if (!global_enable && !state)
4277 	return EINVAL;
4278 
4279     info = ipmi_mem_alloc(sizeof(*info));
4280     if (!info)
4281 	return ENOMEM;
4282     info->done = done;
4283     info->cb_data = cb_data;
4284     info->global_enable = global_enable;
4285     if (state)
4286 	memcpy(&info->state, state, sizeof(info->state));
4287     rv = ipmi_sensor_add_opq(sensor, sensor_rearm_start, &(info->sdata), info);
4288     if (rv)
4289 	ipmi_mem_free(info);
4290     return rv;
4291 }
4292 
4293 typedef struct hyst_get_info_s
4294 {
4295     ipmi_sensor_op_info_t     sdata;
4296     ipmi_sensor_hysteresis_cb done;
4297     void                      *cb_data;
4298     unsigned int              positive;
4299     unsigned int              negative;
4300 } hyst_get_info_t;
4301 
hyst_get_done_handler(ipmi_sensor_t * sensor,int err,void * sinfo)4302 static void hyst_get_done_handler(ipmi_sensor_t *sensor,
4303 				  int           err,
4304 				  void          *sinfo)
4305 {
4306     hyst_get_info_t *info = sinfo;
4307 
4308     if (info->done)
4309 	info->done(sensor, err, info->positive, info->negative, info->cb_data);
4310     ipmi_sensor_opq_done(sensor);
4311     ipmi_mem_free(info);
4312 }
4313 
4314 static void
hyst_get(ipmi_sensor_t * sensor,int err,ipmi_msg_t * rsp,void * cb_data)4315 hyst_get(ipmi_sensor_t *sensor,
4316 	 int           err,
4317 	 ipmi_msg_t    *rsp,
4318 	 void          *cb_data)
4319 {
4320     hyst_get_info_t *info = cb_data;
4321 
4322     if (sensor_done_check_rsp(sensor, err, rsp, 3, "hyst_get",
4323 			      hyst_get_done_handler, info))
4324 	return;
4325 
4326     info->positive = rsp->data[1];
4327     info->negative = rsp->data[2];
4328     hyst_get_done_handler(sensor, 0, info);
4329 }
4330 
4331 static void
hyst_get_start(ipmi_sensor_t * sensor,int err,void * cb_data)4332 hyst_get_start(ipmi_sensor_t *sensor, int err, void *cb_data)
4333 {
4334     hyst_get_info_t *info = cb_data;
4335     unsigned char       cmd_data[MAX_IPMI_DATA_SIZE];
4336     ipmi_msg_t          cmd_msg;
4337     int                 rv;
4338 
4339     if (sensor_done_check_rsp(sensor, err, NULL, 0, "hyst_get_start",
4340 			      hyst_get_done_handler, info))
4341 	return;
4342 
4343     cmd_msg.data = cmd_data;
4344     cmd_msg.netfn = IPMI_SENSOR_EVENT_NETFN;
4345     cmd_msg.cmd = IPMI_GET_SENSOR_HYSTERESIS_CMD;
4346     cmd_msg.data_len = 2;
4347     cmd_msg.data = cmd_data;
4348     cmd_data[0] = sensor->num;
4349     cmd_data[1] = 0xff;
4350     rv = ipmi_sensor_send_command(sensor, sensor->mc, sensor->send_lun,
4351 				  &cmd_msg, hyst_get, &(info->sdata), info);
4352     if (rv) {
4353 	ipmi_log(IPMI_LOG_ERR_INFO,
4354 		 "%ssensor.c(hyst_get_start):"
4355 		 " Error sending hysteresis get command: %x",
4356 		 SENSOR_NAME(sensor), rv);
4357 	hyst_get_done_handler(sensor, rv, info);
4358     }
4359 }
4360 
4361 static int
stand_ipmi_sensor_get_hysteresis(ipmi_sensor_t * sensor,ipmi_sensor_hysteresis_cb done,void * cb_data)4362 stand_ipmi_sensor_get_hysteresis(ipmi_sensor_t             *sensor,
4363 				 ipmi_sensor_hysteresis_cb done,
4364 				 void                      *cb_data)
4365 {
4366     hyst_get_info_t *info;
4367     int             rv;
4368 
4369     if (sensor->event_reading_type != IPMI_EVENT_READING_TYPE_THRESHOLD)
4370 	/* Not a threshold sensor, it doesn't have readings. */
4371 	return ENOSYS;
4372 
4373     if ((sensor->hysteresis_support != IPMI_HYSTERESIS_SUPPORT_READABLE)
4374         && (sensor->hysteresis_support != IPMI_HYSTERESIS_SUPPORT_SETTABLE))
4375 	return ENOSYS;
4376 
4377     info = ipmi_mem_alloc(sizeof(*info));
4378     if (!info)
4379 	return ENOMEM;
4380     memset(info, 0, sizeof(*info));
4381     info->done = done;
4382     info->cb_data = cb_data;
4383     rv = ipmi_sensor_add_opq(sensor, hyst_get_start, &(info->sdata), info);
4384     if (rv)
4385 	ipmi_mem_free(info);
4386     return rv;
4387 }
4388 
4389 typedef struct hyst_set_info_s
4390 {
4391     ipmi_sensor_op_info_t sdata;
4392     unsigned int          positive, negative;
4393     ipmi_sensor_done_cb   done;
4394     void                  *cb_data;
4395 } hyst_set_info_t;
4396 
hyst_set_done_handler(ipmi_sensor_t * sensor,int err,void * sinfo)4397 static void hyst_set_done_handler(ipmi_sensor_t *sensor,
4398 				  int           err,
4399 				  void          *sinfo)
4400 {
4401     hyst_set_info_t *info = sinfo;
4402 
4403     if (info->done)
4404 	info->done(sensor, err, info->cb_data);
4405     ipmi_sensor_opq_done(sensor);
4406     ipmi_mem_free(info);
4407 }
4408 
4409 static void
hyst_set(ipmi_sensor_t * sensor,int err,ipmi_msg_t * rsp,void * cb_data)4410 hyst_set(ipmi_sensor_t *sensor,
4411 	 int           err,
4412 	 ipmi_msg_t    *rsp,
4413 	 void          *cb_data)
4414 {
4415     hyst_set_info_t *info = cb_data;
4416 
4417     if (sensor_done_check_rsp(sensor, err, rsp, 1, "hyst_set",
4418 			      hyst_set_done_handler, info))
4419 	return;
4420 
4421     hyst_set_done_handler(sensor, 0, info);
4422 }
4423 
4424 static void
hyst_set_start(ipmi_sensor_t * sensor,int err,void * cb_data)4425 hyst_set_start(ipmi_sensor_t *sensor, int err, void *cb_data)
4426 {
4427     hyst_set_info_t *info = cb_data;
4428     unsigned char   cmd_data[MAX_IPMI_DATA_SIZE];
4429     ipmi_msg_t      cmd_msg;
4430     int             rv;
4431 
4432     if (sensor_done_check_rsp(sensor, err, NULL, 0, "hyst_set_start",
4433 			      hyst_set_done_handler, info))
4434 	return;
4435 
4436     cmd_msg.data = cmd_data;
4437     cmd_msg.netfn = IPMI_SENSOR_EVENT_NETFN;
4438     cmd_msg.cmd = IPMI_SET_SENSOR_HYSTERESIS_CMD;
4439     cmd_msg.data_len = 4;
4440     cmd_msg.data = cmd_data;
4441     cmd_data[0] = sensor->num;
4442     cmd_data[1] = 0xff;
4443     cmd_data[2] = info->positive;
4444     cmd_data[3] = info->negative;
4445     rv = ipmi_sensor_send_command(sensor, sensor->mc, sensor->send_lun,
4446 				  &cmd_msg, hyst_set, &(info->sdata), info);
4447     if (rv) {
4448 	ipmi_log(IPMI_LOG_ERR_INFO,
4449 		 "%ssensor.c(hyst_set_start):"
4450 		 " Error sending hysteresis set command: %x",
4451 		 SENSOR_NAME(sensor), rv);
4452 	hyst_set_done_handler(sensor, rv, info);
4453     }
4454 }
4455 
4456 static int
stand_ipmi_sensor_set_hysteresis(ipmi_sensor_t * sensor,unsigned int positive_hysteresis,unsigned int negative_hysteresis,ipmi_sensor_done_cb done,void * cb_data)4457 stand_ipmi_sensor_set_hysteresis(ipmi_sensor_t       *sensor,
4458 				 unsigned int        positive_hysteresis,
4459 				 unsigned int        negative_hysteresis,
4460 				 ipmi_sensor_done_cb done,
4461 				 void                *cb_data)
4462 {
4463     hyst_set_info_t *info;
4464     int             rv;
4465 
4466     if (sensor->event_reading_type != IPMI_EVENT_READING_TYPE_THRESHOLD)
4467 	/* Not a threshold sensor, it doesn't have readings. */
4468 	return ENOSYS;
4469 
4470     if (sensor->hysteresis_support != IPMI_HYSTERESIS_SUPPORT_SETTABLE)
4471 	return ENOSYS;
4472 
4473     info = ipmi_mem_alloc(sizeof(*info));
4474     if (!info)
4475 	return ENOMEM;
4476     info->positive = positive_hysteresis;
4477     info->negative = negative_hysteresis;
4478     info->done = done;
4479     info->cb_data = cb_data;
4480     rv = ipmi_sensor_add_opq(sensor, hyst_set_start, &(info->sdata), info);
4481     if (rv)
4482 	ipmi_mem_free(info);
4483     return rv;
4484 }
4485 
4486 typedef struct thresh_get_info_s
4487 {
4488     ipmi_sensor_op_info_t     sdata;
4489     ipmi_thresholds_t         th;
4490     ipmi_sensor_thresholds_cb done;
4491     void                      *cb_data;
4492 } thresh_get_info_t;
4493 
thresh_get_done_handler(ipmi_sensor_t * sensor,int err,void * sinfo)4494 static void thresh_get_done_handler(ipmi_sensor_t *sensor,
4495 				    int           err,
4496 				    void          *sinfo)
4497 {
4498     thresh_get_info_t *info = sinfo;
4499 
4500     if (info->done)
4501 	info->done(sensor, err, &info->th, info->cb_data);
4502     ipmi_sensor_opq_done(sensor);
4503     ipmi_mem_free(info);
4504 }
4505 
4506 static void
thresh_get(ipmi_sensor_t * sensor,int err,ipmi_msg_t * rsp,void * cb_data)4507 thresh_get(ipmi_sensor_t *sensor,
4508 	   int           err,
4509 	   ipmi_msg_t    *rsp,
4510 	   void          *cb_data)
4511 {
4512     thresh_get_info_t  *info = cb_data;
4513     enum ipmi_thresh_e th;
4514 
4515     if (sensor_done_check_rsp(sensor, err, rsp, 8, "thresh_get",
4516 			      thresh_get_done_handler, info))
4517 	return;
4518 
4519     for (th=IPMI_LOWER_NON_CRITICAL; th<=IPMI_UPPER_NON_RECOVERABLE; th++) {
4520 	int rv;
4521 	if (rsp->data[1] & (1 << th)) {
4522 	    info->th.vals[th].status = 1;
4523 	    rv = ipmi_sensor_convert_from_raw(sensor,
4524 					      rsp->data[th+2],
4525 					      &(info->th.vals[th].val));
4526 	    if (rv) {
4527 		ipmi_log(IPMI_LOG_ERR_INFO,
4528 			 "%ssensor.c(thresh_get):"
4529 			 " Could not convert raw threshold value: %x",
4530 			 SENSOR_NAME(sensor), rv);
4531 		thresh_get_done_handler(sensor, rv, info);
4532 		return;
4533 	    }
4534 	} else {
4535 	    info->th.vals[th].status = 0;
4536 	}
4537     }
4538 
4539     thresh_get_done_handler(sensor, 0, info);
4540 }
4541 
4542 int
ipmi_get_default_sensor_thresholds(ipmi_sensor_t * sensor,ipmi_thresholds_t * th)4543 ipmi_get_default_sensor_thresholds(ipmi_sensor_t     *sensor,
4544 				   ipmi_thresholds_t *th)
4545 {
4546     enum ipmi_thresh_e thnum;
4547     int                rv = 0;
4548 
4549     CHECK_SENSOR_LOCK(sensor);
4550 
4551     for (thnum = IPMI_LOWER_NON_CRITICAL;
4552 	 thnum <= IPMI_UPPER_NON_RECOVERABLE;
4553 	 thnum++)
4554     {
4555 	th->vals[thnum].status = 1;
4556 	rv = ipmi_sensor_convert_from_raw(sensor,
4557 					  sensor->default_thresholds[thnum],
4558 					  &(th->vals[thnum].val));
4559 	if (rv)
4560 	    goto out;
4561     }
4562  out:
4563     return rv;
4564 }
4565 
4566 static void
thresh_get_start(ipmi_sensor_t * sensor,int err,void * cb_data)4567 thresh_get_start(ipmi_sensor_t *sensor, int err, void *cb_data)
4568 {
4569     thresh_get_info_t *info = cb_data;
4570     unsigned char     cmd_data[MAX_IPMI_DATA_SIZE];
4571     ipmi_msg_t        cmd_msg;
4572     int               rv;
4573 
4574     if (sensor_done_check_rsp(sensor, err, NULL, 0, "thresh_get_start",
4575 			      thresh_get_done_handler, info))
4576 	return;
4577 
4578     if (sensor->threshold_access == IPMI_THRESHOLD_ACCESS_SUPPORT_FIXED) {
4579 	int thnum;
4580 	/* Thresholds are fixed, they cannot be read. */
4581 	for (thnum = IPMI_LOWER_NON_CRITICAL;
4582 	     thnum <= IPMI_UPPER_NON_RECOVERABLE;
4583 	     thnum++)
4584 	{
4585 	    info->th.vals[thnum].status = 0;
4586 	}
4587 	thresh_get_done_handler(sensor, 0, info);
4588 	return;
4589     }
4590 
4591     cmd_msg.data = cmd_data;
4592     cmd_msg.netfn = IPMI_SENSOR_EVENT_NETFN;
4593     cmd_msg.cmd = IPMI_GET_SENSOR_THRESHOLD_CMD;
4594     cmd_msg.data_len = 1;
4595     cmd_msg.data = cmd_data;
4596     cmd_data[0] = sensor->num;
4597     rv = ipmi_sensor_send_command(sensor, sensor->mc, sensor->send_lun,
4598 				  &cmd_msg, thresh_get, &(info->sdata), info);
4599     if (rv) {
4600 	ipmi_log(IPMI_LOG_ERR_INFO,
4601 		 "%ssensor.c(thresh_get_start):"
4602 		 " Error sending threshold get command: %x",
4603 		 SENSOR_NAME(sensor), rv);
4604 	thresh_get_done_handler(sensor, rv, info);
4605     }
4606 }
4607 
4608 static int
stand_ipmi_sensor_get_thresholds(ipmi_sensor_t * sensor,ipmi_sensor_thresholds_cb done,void * cb_data)4609 stand_ipmi_sensor_get_thresholds(ipmi_sensor_t             *sensor,
4610 				 ipmi_sensor_thresholds_cb done,
4611 				 void                      *cb_data)
4612 {
4613     thresh_get_info_t *info;
4614     int               rv;
4615 
4616     if (sensor->event_reading_type != IPMI_EVENT_READING_TYPE_THRESHOLD)
4617 	/* Not a threshold sensor, it doesn't have readings. */
4618 	return ENOSYS;
4619 
4620     if (sensor->threshold_access == IPMI_THRESHOLD_ACCESS_SUPPORT_NONE)
4621 	return ENOSYS;
4622 
4623     info = ipmi_mem_alloc(sizeof(*info));
4624     if (!info)
4625 	return ENOMEM;
4626     info->done = done;
4627     info->cb_data = cb_data;
4628     rv = ipmi_sensor_add_opq(sensor, thresh_get_start, &(info->sdata), info);
4629     if (rv)
4630 	ipmi_mem_free(info);
4631     return rv;
4632 }
4633 
4634 typedef struct thresh_set_info_s
4635 {
4636     ipmi_sensor_op_info_t sdata;
4637     ipmi_thresholds_t     th;
4638     ipmi_sensor_done_cb   done;
4639     void                  *cb_data;
4640 } thresh_set_info_t;
4641 
thresh_set_done_handler(ipmi_sensor_t * sensor,int err,void * sinfo)4642 static void thresh_set_done_handler(ipmi_sensor_t *sensor,
4643 				    int           err,
4644 				    void          *sinfo)
4645 {
4646     thresh_set_info_t *info = sinfo;
4647 
4648     if (info->done)
4649 	info->done(sensor, err, info->cb_data);
4650     ipmi_sensor_opq_done(sensor);
4651     ipmi_mem_free(info);
4652 }
4653 
4654 static void
thresh_set(ipmi_sensor_t * sensor,int err,ipmi_msg_t * rsp,void * cb_data)4655 thresh_set(ipmi_sensor_t *sensor,
4656 	   int           err,
4657 	   ipmi_msg_t    *rsp,
4658 	   void          *cb_data)
4659 {
4660     thresh_set_info_t *info = cb_data;
4661 
4662     if (sensor_done_check_rsp(sensor, err, rsp, 1, "thresh_set",
4663 			      thresh_set_done_handler, info))
4664 	return;
4665 
4666     thresh_set_done_handler(sensor, 0, info);
4667 }
4668 
4669 static void
thresh_set_start(ipmi_sensor_t * sensor,int err,void * cb_data)4670 thresh_set_start(ipmi_sensor_t *sensor, int err, void *cb_data)
4671 {
4672     thresh_set_info_t  *info = cb_data;
4673     unsigned char      cmd_data[MAX_IPMI_DATA_SIZE];
4674     ipmi_msg_t         cmd_msg;
4675     int                rv;
4676     enum ipmi_thresh_e th;
4677 
4678     if (sensor_done_check_rsp(sensor, err, NULL, 0, "thresh_set_start",
4679 			      thresh_set_done_handler, info))
4680 	return;
4681 
4682     cmd_msg.data = cmd_data;
4683     cmd_msg.netfn = IPMI_SENSOR_EVENT_NETFN;
4684     cmd_msg.cmd = IPMI_SET_SENSOR_THRESHOLD_CMD;
4685     cmd_msg.data_len = 8;
4686     cmd_msg.data = cmd_data;
4687     cmd_data[0] = sensor->num;
4688     cmd_data[1] = 0;
4689     for (th=IPMI_LOWER_NON_CRITICAL; th<=IPMI_UPPER_NON_RECOVERABLE; th++) {
4690 	int val;
4691 	if (info->th.vals[th].status) {
4692 	    cmd_data[1] |= (1 << th);
4693 	    rv = ipmi_sensor_convert_to_raw(sensor,
4694 					    ROUND_NORMAL,
4695 					    info->th.vals[th].val,
4696 					    &val);
4697 	    if (rv) {
4698 		ipmi_log(IPMI_LOG_ERR_INFO,
4699 			 "%ssensor.c(thresh_set_start):"
4700 			 "Error converting threshold to raw: %x",
4701 			 SENSOR_NAME(sensor), rv);
4702 		thresh_set_done_handler(sensor, rv, info);
4703 		return;
4704 	    }
4705 	} else {
4706 	    val = 0;
4707 	}
4708 	cmd_data[th+2] = val;
4709     }
4710 
4711     rv = ipmi_sensor_send_command(sensor, sensor->mc, sensor->send_lun,
4712 				  &cmd_msg, thresh_set, &(info->sdata), info);
4713     if (rv) {
4714 	ipmi_log(IPMI_LOG_ERR_INFO,
4715 		 "%ssensor.c(thresh_set_start):"
4716 		 "Error sending thresholds set command: %x",
4717 		 SENSOR_NAME(sensor), rv);
4718 	thresh_set_done_handler(sensor, rv, info);
4719     }
4720 }
4721 
4722 static int
stand_ipmi_sensor_set_thresholds(ipmi_sensor_t * sensor,ipmi_thresholds_t * thresholds,ipmi_sensor_done_cb done,void * cb_data)4723 stand_ipmi_sensor_set_thresholds(ipmi_sensor_t       *sensor,
4724 				 ipmi_thresholds_t   *thresholds,
4725 				 ipmi_sensor_done_cb done,
4726 				 void                *cb_data)
4727 {
4728     thresh_set_info_t *info;
4729     int               rv;
4730 
4731     if (sensor->event_reading_type != IPMI_EVENT_READING_TYPE_THRESHOLD)
4732 	/* Not a threshold sensor, it doesn't have readings. */
4733 	return ENOSYS;
4734 
4735     if (sensor->threshold_access != IPMI_THRESHOLD_ACCESS_SUPPORT_SETTABLE)
4736 	return ENOSYS;
4737 
4738     info = ipmi_mem_alloc(sizeof(*info));
4739     if (!info)
4740 	return ENOMEM;
4741     info->th = *thresholds;
4742     info->done = done;
4743     info->cb_data = cb_data;
4744     rv = ipmi_sensor_add_opq(sensor, thresh_set_start, &(info->sdata), info);
4745     if (rv)
4746 	ipmi_mem_free(info);
4747     return rv;
4748 }
4749 
4750 typedef struct reading_get_info_s
4751 {
4752     ipmi_sensor_op_info_t      sdata;
4753     ipmi_sensor_reading_cb     done;
4754     void                       *cb_data;
4755     ipmi_states_t              states;
4756     enum ipmi_value_present_e  value_present;
4757     unsigned int               raw_val;
4758     double                     cooked_val;
4759 } reading_get_info_t;
4760 
reading_get_done_handler(ipmi_sensor_t * sensor,int err,void * sinfo)4761 static void reading_get_done_handler(ipmi_sensor_t *sensor,
4762 				     int           err,
4763 				     void          *sinfo)
4764 {
4765     reading_get_info_t *info = sinfo;
4766 
4767     if (info->done)
4768 	info->done(sensor, err, info->value_present,
4769 		   info->raw_val, info->cooked_val, &info->states,
4770 		   info->cb_data);
4771     ipmi_sensor_opq_done(sensor);
4772     ipmi_mem_free(info);
4773 }
4774 
4775 static void
reading_get(ipmi_sensor_t * sensor,int err,ipmi_msg_t * rsp,void * rsp_data)4776 reading_get(ipmi_sensor_t *sensor,
4777 	    int           err,
4778 	    ipmi_msg_t    *rsp,
4779 	    void          *rsp_data)
4780 {
4781     reading_get_info_t        *info = rsp_data;
4782     int                       rv;
4783 
4784     if (sensor_done_check_rsp(sensor, err, rsp, 3, "reading_get",
4785 			      reading_get_done_handler, info))
4786 	return;
4787 
4788     info->raw_val = rsp->data[1];
4789     if (sensor->analog_data_format != IPMI_ANALOG_DATA_FORMAT_NOT_ANALOG) {
4790 	rv = ipmi_sensor_convert_from_raw(sensor,
4791 					  info->raw_val,
4792 					  &info->cooked_val);
4793 	if (rv)
4794 	    info->value_present = IPMI_RAW_VALUE_PRESENT;
4795 	else
4796 	    info->value_present = IPMI_BOTH_VALUES_PRESENT;
4797     } else {
4798 	info->value_present = IPMI_NO_VALUES_PRESENT;
4799     }
4800 
4801     info->states.__event_messages_enabled = (rsp->data[2] >> 7) & 1;
4802     info->states.__sensor_scanning_enabled = (rsp->data[2] >> 6) & 1;
4803     info->states.__initial_update_in_progress = (rsp->data[2] >> 5) & 1;
4804     if (rsp->data_len >= 4)
4805 	info->states.__states = rsp->data[3];
4806 
4807     reading_get_done_handler(sensor, 0, info);
4808 }
4809 
4810 static void
reading_get_start(ipmi_sensor_t * sensor,int err,void * cb_data)4811 reading_get_start(ipmi_sensor_t *sensor, int err, void *cb_data)
4812 {
4813     reading_get_info_t *info = cb_data;
4814     unsigned char      cmd_data[MAX_IPMI_DATA_SIZE];
4815     ipmi_msg_t         cmd_msg;
4816     int                rv;
4817 
4818     if (sensor_done_check_rsp(sensor, err, NULL, 0, "reading_get_start",
4819 			      reading_get_done_handler, info))
4820 	return;
4821 
4822     cmd_msg.data = cmd_data;
4823     cmd_msg.netfn = IPMI_SENSOR_EVENT_NETFN;
4824     cmd_msg.cmd = IPMI_GET_SENSOR_READING_CMD;
4825     cmd_msg.data_len = 1;
4826     cmd_msg.data = cmd_data;
4827     cmd_data[0] = sensor->num;
4828     rv = ipmi_sensor_send_command(sensor, sensor->mc, sensor->send_lun,
4829 				  &cmd_msg, reading_get,
4830 				  &(info->sdata), info);
4831     if (rv) {
4832 	ipmi_log(IPMI_LOG_ERR_INFO,
4833 		 "%ssensor.c(reading_get_start):"
4834 		 "Error sending reading get command: %x",
4835 		 SENSOR_NAME(sensor), rv);
4836 	reading_get_done_handler(sensor, rv, info);
4837     }
4838 }
4839 
4840 static int
stand_ipmi_sensor_get_reading(ipmi_sensor_t * sensor,ipmi_sensor_reading_cb done,void * cb_data)4841 stand_ipmi_sensor_get_reading(ipmi_sensor_t          *sensor,
4842 			      ipmi_sensor_reading_cb done,
4843 			      void                   *cb_data)
4844 {
4845     reading_get_info_t *info;
4846     int                rv;
4847 
4848     if (sensor->event_reading_type != IPMI_EVENT_READING_TYPE_THRESHOLD)
4849 	/* Not a threshold sensor, it doesn't have readings. */
4850 	return ENOSYS;
4851     if (!sensor->readable)
4852 	return ENOSYS;
4853 
4854     info = ipmi_mem_alloc(sizeof(*info));
4855     if (!info)
4856 	return ENOMEM;
4857     info->done = done;
4858     info->cb_data = cb_data;
4859     info->value_present = IPMI_NO_VALUES_PRESENT;
4860     info->raw_val = 0;
4861     info->cooked_val = 0.0;
4862     ipmi_init_states(&info->states);
4863     rv = ipmi_sensor_add_opq(sensor, reading_get_start, &(info->sdata), info);
4864     if (rv)
4865 	ipmi_mem_free(info);
4866     return rv;
4867 }
4868 
4869 
4870 typedef struct states_get_info_s
4871 {
4872     ipmi_sensor_op_info_t sdata;
4873     ipmi_sensor_states_cb done;
4874     void                  *cb_data;
4875     ipmi_states_t         states;
4876 } states_get_info_t;
4877 
states_get_done_handler(ipmi_sensor_t * sensor,int err,void * sinfo)4878 static void states_get_done_handler(ipmi_sensor_t *sensor,
4879 				    int           err,
4880 				    void          *sinfo)
4881 {
4882     states_get_info_t *info = sinfo;
4883 
4884     if (info->done)
4885 	info->done(sensor, err, &info->states, info->cb_data);
4886     ipmi_sensor_opq_done(sensor);
4887     ipmi_mem_free(info);
4888 }
4889 
4890 static void
states_get(ipmi_sensor_t * sensor,int err,ipmi_msg_t * rsp,void * cb_data)4891 states_get(ipmi_sensor_t *sensor,
4892 	   int           err,
4893 	   ipmi_msg_t    *rsp,
4894 	   void          *cb_data)
4895 {
4896     states_get_info_t *info = cb_data;
4897 
4898     if (sensor_done_check_rsp(sensor, err, rsp, 3, "states_get",
4899 			      states_get_done_handler, info))
4900 	return;
4901 
4902     info->states.__event_messages_enabled = (rsp->data[2] >> 7) & 1;
4903     info->states.__sensor_scanning_enabled = (rsp->data[2] >> 6) & 1;
4904     info->states.__initial_update_in_progress = (rsp->data[2] >> 5) & 1;
4905 
4906     if (rsp->data_len >= 4)
4907 	info->states.__states |= rsp->data[3];
4908     if (rsp->data_len >= 5)
4909 	info->states.__states |= rsp->data[4] << 8;
4910 
4911     states_get_done_handler(sensor, 0, info);
4912 }
4913 
4914 static void
states_get_start(ipmi_sensor_t * sensor,int err,void * cb_data)4915 states_get_start(ipmi_sensor_t *sensor, int err, void *cb_data)
4916 {
4917     states_get_info_t *info = cb_data;
4918     unsigned char     cmd_data[MAX_IPMI_DATA_SIZE];
4919     ipmi_msg_t        cmd_msg;
4920     int               rv;
4921 
4922     if (sensor_done_check_rsp(sensor, err, NULL, 0, "states_get_start",
4923 			      states_get_done_handler, info))
4924 	return;
4925 
4926     cmd_msg.data = cmd_data;
4927     cmd_msg.netfn = IPMI_SENSOR_EVENT_NETFN;
4928     cmd_msg.cmd = IPMI_GET_SENSOR_READING_CMD;
4929     cmd_msg.data_len = 1;
4930     cmd_msg.data = cmd_data;
4931     cmd_data[0] = sensor->num;
4932     rv = ipmi_sensor_send_command(sensor, sensor->mc, sensor->send_lun,
4933 				  &cmd_msg, states_get,
4934 				  &(info->sdata), info);
4935     if (rv) {
4936 	ipmi_log(IPMI_LOG_ERR_INFO,
4937 		 "%sstates.c(states_get_start):"
4938 		 " Error sending states get command: %x",
4939 		 SENSOR_NAME(sensor), rv);
4940 	states_get_done_handler(sensor, rv, info);
4941     }
4942 }
4943 
4944 static int
stand_ipmi_sensor_get_states(ipmi_sensor_t * sensor,ipmi_sensor_states_cb done,void * cb_data)4945 stand_ipmi_sensor_get_states(ipmi_sensor_t         *sensor,
4946 			     ipmi_sensor_states_cb done,
4947 			     void                  *cb_data)
4948 {
4949     states_get_info_t *info;
4950     int               rv;
4951 
4952     if (sensor->event_reading_type == IPMI_EVENT_READING_TYPE_THRESHOLD)
4953 	/* A threshold sensor, it doesn't have states. */
4954 	return ENOSYS;
4955     if (!sensor->readable)
4956 	return ENOSYS;
4957 
4958     info = ipmi_mem_alloc(sizeof(*info));
4959     if (!info)
4960 	return ENOMEM;
4961     info->done = done;
4962     info->cb_data = cb_data;
4963     ipmi_init_states(&info->states);
4964     rv = ipmi_sensor_add_opq(sensor, states_get_start, &(info->sdata), info);
4965     if (rv)
4966 	ipmi_mem_free(info);
4967     return rv;
4968 }
4969 
4970 /***********************************************************************
4971  *
4972  * Various data conversion stuff.
4973  *
4974  **********************************************************************/
4975 
c_linear(double val)4976 static double c_linear(double val)
4977 {
4978     return val;
4979 }
4980 
c_log2(double val)4981 static double c_log2(double val)
4982 {
4983     return log(val) / 0.69314718 /* log(2) */;
4984 }
4985 
c_exp10(double val)4986 static double c_exp10(double val)
4987 {
4988     return pow(10.0, val);
4989 }
4990 
c_exp2(double val)4991 static double c_exp2(double val)
4992 {
4993     return pow(2.0, val);
4994 }
4995 
c_1_over_x(double val)4996 static double c_1_over_x(double val)
4997 {
4998     return 1.0 / val;
4999 }
5000 
c_sqr(double val)5001 static double c_sqr(double val)
5002 {
5003     return pow(val, 2.0);
5004 }
5005 
c_cube(double val)5006 static double c_cube(double val)
5007 {
5008     return pow(val, 3.0);
5009 }
5010 
c_1_over_cube(double val)5011 static double c_1_over_cube(double val)
5012 {
5013     return 1.0 / pow(val, 3.0);
5014 }
5015 
5016 typedef double (*linearizer)(double val);
5017 static linearizer linearize[12] =
5018 {
5019     c_linear,
5020     log,
5021     log10,
5022     c_log2,
5023     exp,
5024     c_exp10,
5025     c_exp2,
5026     c_1_over_x,
5027     c_sqr,
5028     c_cube,
5029     sqrt,
5030     c_1_over_cube
5031 };
5032 
5033 static int
sign_extend(int m,int bits)5034 sign_extend(int m, int bits)
5035 {
5036     if (m & (1 << (bits-1)))
5037 	return m | (-1 << bits);
5038     else
5039 	return m & (~(-1 << bits));
5040 }
5041 
5042 static int
stand_ipmi_sensor_convert_from_raw(ipmi_sensor_t * sensor,int val,double * result)5043 stand_ipmi_sensor_convert_from_raw(ipmi_sensor_t *sensor,
5044 				   int           val,
5045 				   double        *result)
5046 {
5047     double m, b, b_exp, r_exp, fval;
5048     linearizer c_func;
5049 
5050     if (sensor->event_reading_type != IPMI_EVENT_READING_TYPE_THRESHOLD)
5051 	/* Not a threshold sensor, it doesn't have readings. */
5052 	return ENOSYS;
5053 
5054     if (sensor->linearization == IPMI_LINEARIZATION_NONLINEAR)
5055 	c_func = c_linear;
5056     else if (sensor->linearization <= 11)
5057 	c_func = linearize[sensor->linearization];
5058     else
5059 	return EINVAL;
5060 
5061     val &= 0xff;
5062 
5063     m = sensor->conv[val].m;
5064     b = sensor->conv[val].b;
5065     r_exp = sensor->conv[val].r_exp;
5066     b_exp = sensor->conv[val].b_exp;
5067 
5068     switch(sensor->analog_data_format) {
5069 	case IPMI_ANALOG_DATA_FORMAT_UNSIGNED:
5070 	    fval = val;
5071 	    break;
5072 	case IPMI_ANALOG_DATA_FORMAT_1_COMPL:
5073 	    val = sign_extend(val, 8);
5074 	    if (val < 0)
5075 		val += 1;
5076 	    fval = val;
5077 	    break;
5078 	case IPMI_ANALOG_DATA_FORMAT_2_COMPL:
5079 	    fval = sign_extend(val, 8);
5080 	    break;
5081 	default:
5082 	    return EINVAL;
5083     }
5084 
5085     *result = c_func(((m * fval) + (b * pow(10, b_exp))) * pow(10, r_exp));
5086     return 0;
5087 }
5088 
5089 static int
stand_ipmi_sensor_convert_to_raw(ipmi_sensor_t * sensor,enum ipmi_round_e rounding,double val,int * result)5090 stand_ipmi_sensor_convert_to_raw(ipmi_sensor_t     *sensor,
5091 				 enum ipmi_round_e rounding,
5092 				 double            val,
5093 				 int               *result)
5094 {
5095     double cval;
5096     int    lowraw, highraw, raw, maxraw, minraw, next_raw;
5097     int    rv;
5098 
5099     if (sensor->event_reading_type != IPMI_EVENT_READING_TYPE_THRESHOLD)
5100 	/* Not a threshold sensor, it doesn't have readings. */
5101 	return ENOSYS;
5102 
5103     switch(sensor->analog_data_format) {
5104 	case IPMI_ANALOG_DATA_FORMAT_UNSIGNED:
5105 	    lowraw = 0;
5106 	    highraw = 255;
5107 	    minraw = 0;
5108 	    maxraw = 255;
5109 	    next_raw = 128;
5110 	    break;
5111 	case IPMI_ANALOG_DATA_FORMAT_1_COMPL:
5112 	    lowraw = -127;
5113 	    highraw = 127;
5114 	    minraw = -127;
5115 	    maxraw = 127;
5116 	    next_raw = 0;
5117 	    break;
5118 	case IPMI_ANALOG_DATA_FORMAT_2_COMPL:
5119 	    lowraw = -128;
5120 	    highraw = 127;
5121 	    minraw = -128;
5122 	    maxraw = 127;
5123 	    next_raw = 0;
5124 	    break;
5125 	default:
5126 	    return EINVAL;
5127     }
5128 
5129     /* We do a binary search for the right value.  Yuck, but I don't
5130        have a better plan that will work with non-linear sensors. */
5131     do {
5132 	raw = next_raw;
5133 	rv = ipmi_sensor_convert_from_raw(sensor, raw, &cval);
5134 	if (rv)
5135 	    return rv;
5136 
5137 	if (cval < val) {
5138 	    next_raw = ((highraw - raw) / 2) + raw;
5139 	    lowraw = raw;
5140 	} else {
5141 	    next_raw = ((raw - lowraw) / 2) + lowraw;
5142 	    highraw = raw;
5143 	}
5144     } while (raw != next_raw);
5145 
5146     /* The above loop gets us to within 1 of what it should be, we
5147        have to look at rounding to make the final decision. */
5148     switch (rounding)
5149     {
5150 	case ROUND_NORMAL:
5151 	    if (val > cval) {
5152 		if (raw < maxraw) {
5153 		    double nval;
5154 		    rv = ipmi_sensor_convert_from_raw(sensor, raw+1, &nval);
5155 		    if (rv)
5156 			return rv;
5157 		    nval = cval + ((nval - cval) / 2.0);
5158 		    if (val >= nval)
5159 			raw++;
5160 		}
5161 	    } else {
5162 		if (raw > minraw) {
5163 		    double pval;
5164 		    rv = ipmi_sensor_convert_from_raw(sensor, raw-1, &pval);
5165 		    if (rv)
5166 			return rv;
5167 		    pval = pval + ((cval - pval) / 2.0);
5168 		    if (val < pval)
5169 			raw--;
5170 		}
5171 	    }
5172 	    break;
5173 	case ROUND_UP:
5174 	    if ((val > cval) && (raw < maxraw)) {
5175 		raw++;
5176 	    }
5177 	    break;
5178 	case ROUND_DOWN:
5179 	    if ((val < cval) && (raw > minraw)) {
5180 		raw--;
5181 	    }
5182 	    break;
5183     }
5184 
5185     if (sensor->analog_data_format == IPMI_ANALOG_DATA_FORMAT_1_COMPL) {
5186 	if (raw < 0)
5187 	    raw -= 1;
5188     }
5189 
5190     *result = raw & 0xff;
5191     return 0;
5192 }
5193 
5194 static int
stand_ipmi_sensor_get_tolerance(ipmi_sensor_t * sensor,int val,double * tolerance)5195 stand_ipmi_sensor_get_tolerance(ipmi_sensor_t *sensor,
5196 				int           val,
5197 				double        *tolerance)
5198 {
5199     double m, r_exp, fval;
5200     linearizer c_func;
5201 
5202     if (sensor->event_reading_type != IPMI_EVENT_READING_TYPE_THRESHOLD)
5203 	/* Not a threshold sensor, it doesn't have readings. */
5204 	return ENOSYS;
5205 
5206     if (sensor->linearization == IPMI_LINEARIZATION_NONLINEAR)
5207 	c_func = c_linear;
5208     else if (sensor->linearization <= 11)
5209 	c_func = linearize[sensor->linearization];
5210     else
5211 	return EINVAL;
5212 
5213     val &= 0xff;
5214 
5215     m = sensor->conv[val].m;
5216     r_exp = sensor->conv[val].r_exp;
5217 
5218     fval = sign_extend(val, 8);
5219 
5220     *tolerance = c_func(((m * fval) / 2.0) * pow(10, r_exp));
5221     return 0;
5222 }
5223 
5224 /* Returns accuracy as a percentage value. */
5225 static int
stand_ipmi_sensor_get_accuracy(ipmi_sensor_t * sensor,int val,double * accuracy)5226 stand_ipmi_sensor_get_accuracy(ipmi_sensor_t *sensor, int val, double *accuracy)
5227 {
5228     double a, a_exp;
5229 
5230     if (sensor->event_reading_type != IPMI_EVENT_READING_TYPE_THRESHOLD)
5231 	/* Not a threshold sensor, it doesn't have readings. */
5232 	return ENOSYS;
5233 
5234     val &= 0xff;
5235 
5236     a = sensor->conv[val].accuracy;
5237     a_exp = sensor->conv[val].r_exp;
5238 
5239     *accuracy = (a * pow(10, a_exp)) / 100.0;
5240     return 0;
5241 }
5242 
5243 static const char *
stand_ipmi_sensor_reading_name_string(ipmi_sensor_t * sensor,int offset)5244 stand_ipmi_sensor_reading_name_string(ipmi_sensor_t *sensor, int offset)
5245 {
5246     return ipmi_get_reading_name(sensor->event_reading_type,
5247 				 sensor->sensor_type,
5248 				 offset);
5249 }
5250 
5251 /***********************************************************************
5252  *
5253  * The standard callback structure
5254  *
5255  **********************************************************************/
5256 
5257 const ipmi_sensor_cbs_t ipmi_standard_sensor_cb =
5258 {
5259     .ipmi_sensor_set_event_enables = stand_ipmi_sensor_set_event_enables,
5260     .ipmi_sensor_get_event_enables = stand_ipmi_sensor_get_event_enables,
5261     .ipmi_sensor_enable_events     = stand_ipmi_sensor_enable_events,
5262     .ipmi_sensor_disable_events    = stand_ipmi_sensor_disable_events,
5263     .ipmi_sensor_rearm             = stand_ipmi_sensor_rearm,
5264 
5265     .ipmi_sensor_convert_from_raw  = stand_ipmi_sensor_convert_from_raw,
5266     .ipmi_sensor_convert_to_raw    = stand_ipmi_sensor_convert_to_raw,
5267     .ipmi_sensor_get_accuracy      = stand_ipmi_sensor_get_accuracy,
5268     .ipmi_sensor_get_tolerance     = stand_ipmi_sensor_get_tolerance,
5269     .ipmi_sensor_get_hysteresis    = stand_ipmi_sensor_get_hysteresis,
5270     .ipmi_sensor_set_hysteresis    = stand_ipmi_sensor_set_hysteresis,
5271     .ipmi_sensor_set_thresholds    = stand_ipmi_sensor_set_thresholds,
5272     .ipmi_sensor_get_thresholds    = stand_ipmi_sensor_get_thresholds,
5273     .ipmi_sensor_get_reading       = stand_ipmi_sensor_get_reading,
5274 
5275     .ipmi_sensor_get_states        = stand_ipmi_sensor_get_states,
5276     .ipmi_sensor_reading_name_string = stand_ipmi_sensor_reading_name_string,
5277 };
5278 
5279 void
ipmi_sensor_get_callbacks(ipmi_sensor_t * sensor,ipmi_sensor_cbs_t * cbs)5280 ipmi_sensor_get_callbacks(ipmi_sensor_t *sensor, ipmi_sensor_cbs_t *cbs)
5281 {
5282     *cbs = sensor->cbs;
5283 }
5284 
5285 void
ipmi_sensor_set_callbacks(ipmi_sensor_t * sensor,ipmi_sensor_cbs_t * cbs)5286 ipmi_sensor_set_callbacks(ipmi_sensor_t *sensor, ipmi_sensor_cbs_t *cbs)
5287 {
5288     sensor->cbs = *cbs;
5289 }
5290 
5291 /***********************************************************************
5292  *
5293  * Polymorphic calls to the callback handlers.
5294  *
5295  **********************************************************************/
5296 
5297 int
ipmi_sensor_set_event_enables(ipmi_sensor_t * sensor,ipmi_event_state_t * states,ipmi_sensor_done_cb done,void * cb_data)5298 ipmi_sensor_set_event_enables(ipmi_sensor_t         *sensor,
5299 			      ipmi_event_state_t    *states,
5300 			      ipmi_sensor_done_cb   done,
5301 			      void                  *cb_data)
5302 {
5303     if (!sensor_ok_to_use(sensor))
5304 	return ECANCELED;
5305 
5306     CHECK_SENSOR_LOCK(sensor);
5307 
5308     if (!sensor->cbs.ipmi_sensor_set_event_enables)
5309 	return ENOSYS;
5310     return sensor->cbs.ipmi_sensor_set_event_enables(sensor,
5311 						     states,
5312 						     done,
5313 						     cb_data);
5314 }
5315 
5316 int
ipmi_sensor_enable_events(ipmi_sensor_t * sensor,ipmi_event_state_t * states,ipmi_sensor_done_cb done,void * cb_data)5317 ipmi_sensor_enable_events(ipmi_sensor_t         *sensor,
5318 			  ipmi_event_state_t    *states,
5319 			  ipmi_sensor_done_cb   done,
5320 			  void                  *cb_data)
5321 {
5322     if (!sensor_ok_to_use(sensor))
5323 	return ECANCELED;
5324 
5325     CHECK_SENSOR_LOCK(sensor);
5326 
5327     if (!sensor->cbs.ipmi_sensor_enable_events)
5328 	return ENOSYS;
5329     return sensor->cbs.ipmi_sensor_enable_events(sensor,
5330 						 states,
5331 						 done,
5332 						 cb_data);
5333 }
5334 
5335 int
ipmi_sensor_disable_events(ipmi_sensor_t * sensor,ipmi_event_state_t * states,ipmi_sensor_done_cb done,void * cb_data)5336 ipmi_sensor_disable_events(ipmi_sensor_t         *sensor,
5337 			   ipmi_event_state_t    *states,
5338 			   ipmi_sensor_done_cb   done,
5339 			   void                  *cb_data)
5340 {
5341     if (!sensor_ok_to_use(sensor))
5342 	return ECANCELED;
5343 
5344     CHECK_SENSOR_LOCK(sensor);
5345 
5346     if (!sensor->cbs.ipmi_sensor_disable_events)
5347 	return ENOSYS;
5348     return sensor->cbs.ipmi_sensor_disable_events(sensor,
5349 						  states,
5350 						  done,
5351 						  cb_data);
5352 }
5353 
5354 int
ipmi_sensor_rearm(ipmi_sensor_t * sensor,int global_enable,ipmi_event_state_t * state,ipmi_sensor_done_cb done,void * cb_data)5355 ipmi_sensor_rearm(ipmi_sensor_t       *sensor,
5356 		  int                 global_enable,
5357 		  ipmi_event_state_t  *state,
5358 		  ipmi_sensor_done_cb done,
5359 		  void                *cb_data)
5360 {
5361     if (!sensor_ok_to_use(sensor))
5362 	return ECANCELED;
5363 
5364     CHECK_SENSOR_LOCK(sensor);
5365 
5366     if (!sensor->cbs.ipmi_sensor_rearm)
5367 	return ENOSYS;
5368     return sensor->cbs.ipmi_sensor_rearm(sensor,
5369 					 global_enable,
5370 					 state,
5371 					 done,
5372 					 cb_data);
5373 }
5374 
5375 int
ipmi_sensor_get_event_enables(ipmi_sensor_t * sensor,ipmi_sensor_event_enables_cb done,void * cb_data)5376 ipmi_sensor_get_event_enables(ipmi_sensor_t                *sensor,
5377 			      ipmi_sensor_event_enables_cb done,
5378 			      void                         *cb_data)
5379 {
5380     if (!sensor_ok_to_use(sensor))
5381 	return ECANCELED;
5382 
5383     CHECK_SENSOR_LOCK(sensor);
5384 
5385     if (!sensor->cbs.ipmi_sensor_get_event_enables)
5386 	return ENOSYS;
5387     return sensor->cbs.ipmi_sensor_get_event_enables(sensor,
5388 						     done,
5389 						     cb_data);
5390 }
5391 
5392 int
ipmi_sensor_get_hysteresis(ipmi_sensor_t * sensor,ipmi_sensor_hysteresis_cb done,void * cb_data)5393 ipmi_sensor_get_hysteresis(ipmi_sensor_t             *sensor,
5394 			   ipmi_sensor_hysteresis_cb done,
5395 			   void                      *cb_data)
5396 {
5397     if (!sensor_ok_to_use(sensor))
5398 	return ECANCELED;
5399 
5400     CHECK_SENSOR_LOCK(sensor);
5401 
5402     if (!sensor->cbs.ipmi_sensor_get_hysteresis)
5403 	return ENOSYS;
5404     return sensor->cbs.ipmi_sensor_get_hysteresis(sensor,
5405 						  done,
5406 						  cb_data);
5407 }
5408 
5409 int
ipmi_sensor_set_hysteresis(ipmi_sensor_t * sensor,unsigned int positive_hysteresis,unsigned int negative_hysteresis,ipmi_sensor_done_cb done,void * cb_data)5410 ipmi_sensor_set_hysteresis(ipmi_sensor_t       *sensor,
5411 			   unsigned int        positive_hysteresis,
5412 			   unsigned int        negative_hysteresis,
5413 			   ipmi_sensor_done_cb done,
5414 			   void                *cb_data)
5415 {
5416     if (!sensor_ok_to_use(sensor))
5417 	return ECANCELED;
5418 
5419     CHECK_SENSOR_LOCK(sensor);
5420 
5421     if (!sensor->cbs.ipmi_sensor_set_hysteresis)
5422 	return ENOSYS;
5423     return sensor->cbs.ipmi_sensor_set_hysteresis(sensor,
5424 						  positive_hysteresis,
5425 						  negative_hysteresis,
5426 						  done,
5427 						  cb_data);
5428 }
5429 
5430 int
ipmi_sensor_get_thresholds(ipmi_sensor_t * sensor,ipmi_sensor_thresholds_cb done,void * cb_data)5431 ipmi_sensor_get_thresholds(ipmi_sensor_t             *sensor,
5432 			   ipmi_sensor_thresholds_cb done,
5433 			   void                      *cb_data)
5434 {
5435     if (!sensor_ok_to_use(sensor))
5436 	return ECANCELED;
5437 
5438     CHECK_SENSOR_LOCK(sensor);
5439 
5440     if (!sensor->cbs.ipmi_sensor_get_thresholds)
5441 	return ENOSYS;
5442     return sensor->cbs.ipmi_sensor_get_thresholds(sensor, done, cb_data);
5443 }
5444 
5445 int
ipmi_sensor_set_thresholds(ipmi_sensor_t * sensor,ipmi_thresholds_t * thresholds,ipmi_sensor_done_cb done,void * cb_data)5446 ipmi_sensor_set_thresholds(ipmi_sensor_t       *sensor,
5447 			   ipmi_thresholds_t   *thresholds,
5448 			   ipmi_sensor_done_cb done,
5449 			   void                *cb_data)
5450 {
5451     if (!sensor_ok_to_use(sensor))
5452 	return ECANCELED;
5453 
5454     CHECK_SENSOR_LOCK(sensor);
5455 
5456     if (!sensor->cbs.ipmi_sensor_set_thresholds)
5457 	return ENOSYS;
5458     return sensor->cbs.ipmi_sensor_set_thresholds(sensor, thresholds,
5459 						  done, cb_data);
5460 }
5461 
5462 int
ipmi_sensor_get_reading(ipmi_sensor_t * sensor,ipmi_sensor_reading_cb done,void * cb_data)5463 ipmi_sensor_get_reading(ipmi_sensor_t          *sensor,
5464 			ipmi_sensor_reading_cb done,
5465 			void                   *cb_data)
5466 {
5467     if (!sensor_ok_to_use(sensor))
5468 	return ECANCELED;
5469 
5470     CHECK_SENSOR_LOCK(sensor);
5471 
5472     if (!sensor->cbs.ipmi_sensor_get_reading)
5473 	return ENOSYS;
5474     return sensor->cbs.ipmi_sensor_get_reading(sensor, done, cb_data);
5475 }
5476 
5477 int
ipmi_sensor_get_states(ipmi_sensor_t * sensor,ipmi_sensor_states_cb done,void * cb_data)5478 ipmi_sensor_get_states(ipmi_sensor_t         *sensor,
5479 		       ipmi_sensor_states_cb done,
5480 		       void                  *cb_data)
5481 {
5482     if (!sensor_ok_to_use(sensor))
5483 	return ECANCELED;
5484 
5485     CHECK_SENSOR_LOCK(sensor);
5486 
5487     if (!sensor->cbs.ipmi_sensor_get_states)
5488 	return ENOSYS;
5489     return sensor->cbs.ipmi_sensor_get_states(sensor, done, cb_data);
5490 }
5491 
5492 const char *
ipmi_sensor_reading_name_string(ipmi_sensor_t * sensor,int offset)5493 ipmi_sensor_reading_name_string(ipmi_sensor_t *sensor, int offset)
5494 {
5495     CHECK_SENSOR_LOCK(sensor);
5496 
5497     if (!sensor->cbs.ipmi_sensor_reading_name_string)
5498 	return NULL;
5499     return sensor->cbs.ipmi_sensor_reading_name_string(sensor, offset);
5500 }
5501 
5502 int
ipmi_sensor_convert_from_raw(ipmi_sensor_t * sensor,int val,double * result)5503 ipmi_sensor_convert_from_raw(ipmi_sensor_t *sensor,
5504 			     int           val,
5505 			     double        *result)
5506 {
5507     CHECK_SENSOR_LOCK(sensor);
5508 
5509     if (!sensor->cbs.ipmi_sensor_convert_from_raw)
5510 	return ENOSYS;
5511     return sensor->cbs.ipmi_sensor_convert_from_raw(sensor, val, result);
5512 }
5513 
5514 int
ipmi_sensor_convert_to_raw(ipmi_sensor_t * sensor,enum ipmi_round_e rounding,double val,int * result)5515 ipmi_sensor_convert_to_raw(ipmi_sensor_t     *sensor,
5516 			   enum ipmi_round_e rounding,
5517 			   double            val,
5518 			   int               *result)
5519 {
5520     CHECK_SENSOR_LOCK(sensor);
5521 
5522     if (!sensor->cbs.ipmi_sensor_convert_to_raw)
5523 	return ENOSYS;
5524     return sensor->cbs.ipmi_sensor_convert_to_raw(sensor,
5525 						  rounding,
5526 						  val,
5527 						  result);
5528 }
5529 
5530 int
ipmi_sensor_get_tolerance(ipmi_sensor_t * sensor,int val,double * tolerance)5531 ipmi_sensor_get_tolerance(ipmi_sensor_t *sensor, int val, double *tolerance)
5532 {
5533     CHECK_SENSOR_LOCK(sensor);
5534 
5535     if (!sensor->cbs.ipmi_sensor_get_tolerance)
5536 	return ENOSYS;
5537     return sensor->cbs.ipmi_sensor_get_tolerance(sensor, val, tolerance);
5538 }
5539 
5540 /* Returns accuracy as a percentage value. */
5541 int
ipmi_sensor_get_accuracy(ipmi_sensor_t * sensor,int val,double * accuracy)5542 ipmi_sensor_get_accuracy(ipmi_sensor_t *sensor, int val, double *accuracy)
5543 {
5544     CHECK_SENSOR_LOCK(sensor);
5545 
5546     if (!sensor->cbs.ipmi_sensor_get_accuracy)
5547 	return ENOSYS;
5548     return sensor->cbs.ipmi_sensor_get_accuracy(sensor, val, accuracy);
5549 }
5550 
5551 
5552 /***********************************************************************
5553  *
5554  * Convenience functions that take ids.
5555  *
5556  **********************************************************************/
5557 
5558 typedef struct sensor_id_events_enable_set_s
5559 {
5560     ipmi_event_state_t    *states;
5561     ipmi_sensor_done_cb   done;
5562     void                  *cb_data;
5563     int                   rv;
5564 } sensor_id_events_enable_set_t;
5565 
5566 static void
sensor_id_set_event_enables_cb(ipmi_sensor_t * sensor,void * cb_data)5567 sensor_id_set_event_enables_cb(ipmi_sensor_t *sensor, void *cb_data)
5568 {
5569     sensor_id_events_enable_set_t *info = cb_data;
5570 
5571     info->rv = ipmi_sensor_set_event_enables(sensor, info->states,
5572 					     info->done, info->cb_data);
5573 }
5574 
5575 int
ipmi_sensor_id_set_event_enables(ipmi_sensor_id_t sensor_id,ipmi_event_state_t * states,ipmi_sensor_done_cb done,void * cb_data)5576 ipmi_sensor_id_set_event_enables(ipmi_sensor_id_t      sensor_id,
5577 				 ipmi_event_state_t    *states,
5578 				 ipmi_sensor_done_cb   done,
5579 				 void                  *cb_data)
5580 {
5581     sensor_id_events_enable_set_t info;
5582     int                           rv;
5583 
5584     info.states = states;
5585     info.done = done;
5586     info.cb_data = cb_data;
5587     rv = ipmi_sensor_pointer_cb(sensor_id, sensor_id_set_event_enables_cb,
5588 				&info);
5589     if (!rv)
5590 	rv = info.rv;
5591     return rv;
5592 }
5593 
5594 typedef struct sensor_id_events_enable_s
5595 {
5596     ipmi_event_state_t    *states;
5597     ipmi_sensor_done_cb   done;
5598     void                  *cb_data;
5599     int                   rv;
5600 } sensor_id_events_enable_t;
5601 
5602 static void
sensor_id_enable_events_cb(ipmi_sensor_t * sensor,void * cb_data)5603 sensor_id_enable_events_cb(ipmi_sensor_t *sensor, void *cb_data)
5604 {
5605     sensor_id_events_enable_t *info = cb_data;
5606 
5607     info->rv = ipmi_sensor_enable_events(sensor,
5608 					 info->states,
5609 					 info->done,
5610 					 info->cb_data);
5611 }
5612 
5613 int
ipmi_sensor_id_enable_events(ipmi_sensor_id_t sensor_id,ipmi_event_state_t * states,ipmi_sensor_done_cb done,void * cb_data)5614 ipmi_sensor_id_enable_events(ipmi_sensor_id_t      sensor_id,
5615 			     ipmi_event_state_t    *states,
5616 			     ipmi_sensor_done_cb   done,
5617 			     void                  *cb_data)
5618 {
5619     sensor_id_events_enable_t info;
5620     int                       rv;
5621 
5622     info.states = states;
5623     info.done = done;
5624     info.cb_data = cb_data;
5625     rv = ipmi_sensor_pointer_cb(sensor_id, sensor_id_enable_events_cb, &info);
5626     if (!rv)
5627 	rv = info.rv;
5628     return rv;
5629 }
5630 
5631 typedef struct sensor_id_events_disable_s
5632 {
5633     ipmi_event_state_t    *states;
5634     ipmi_sensor_done_cb   done;
5635     void                  *cb_data;
5636     int                   rv;
5637 } sensor_id_events_disable_t;
5638 
5639 static void
sensor_id_disable_events_cb(ipmi_sensor_t * sensor,void * cb_data)5640 sensor_id_disable_events_cb(ipmi_sensor_t *sensor, void *cb_data)
5641 {
5642     sensor_id_events_disable_t *info = cb_data;
5643 
5644     info->rv = ipmi_sensor_disable_events(sensor,
5645 					  info->states,
5646 					  info->done,
5647 					  info->cb_data);
5648 }
5649 
5650 int
ipmi_sensor_id_disable_events(ipmi_sensor_id_t sensor_id,ipmi_event_state_t * states,ipmi_sensor_done_cb done,void * cb_data)5651 ipmi_sensor_id_disable_events(ipmi_sensor_id_t      sensor_id,
5652 			      ipmi_event_state_t    *states,
5653 			      ipmi_sensor_done_cb   done,
5654 			      void                  *cb_data)
5655 {
5656     sensor_id_events_enable_t info;
5657     int                       rv;
5658 
5659     info.states = states;
5660     info.done = done;
5661     info.cb_data = cb_data;
5662     rv = ipmi_sensor_pointer_cb(sensor_id, sensor_id_disable_events_cb, &info);
5663     if (!rv)
5664 	rv = info.rv;
5665     return rv;
5666 }
5667 
5668 typedef struct sensor_id_events_enable_get_s
5669 {
5670     ipmi_sensor_event_enables_cb done;
5671     void                         *cb_data;
5672     int                          rv;
5673 } sensor_id_events_enable_get_t;
5674 
5675 static void
sensor_id_get_event_enables_cb(ipmi_sensor_t * sensor,void * cb_data)5676 sensor_id_get_event_enables_cb(ipmi_sensor_t *sensor, void *cb_data)
5677 {
5678     sensor_id_events_enable_get_t *info = cb_data;
5679 
5680     info->rv = ipmi_sensor_get_event_enables(sensor,
5681 					     info->done,
5682 					     info->cb_data);
5683 }
5684 
5685 int
ipmi_sensor_id_get_event_enables(ipmi_sensor_id_t sensor_id,ipmi_sensor_event_enables_cb done,void * cb_data)5686 ipmi_sensor_id_get_event_enables(ipmi_sensor_id_t             sensor_id,
5687 				 ipmi_sensor_event_enables_cb done,
5688 				 void                         *cb_data)
5689 {
5690     sensor_id_events_enable_get_t info;
5691     int                           rv;
5692 
5693     info.done = done;
5694     info.cb_data = cb_data;
5695     rv = ipmi_sensor_pointer_cb(sensor_id, sensor_id_get_event_enables_cb,
5696 				&info);
5697     if (!rv)
5698 	rv = info.rv;
5699     return rv;
5700 }
5701 
5702 typedef struct sensor_id_rearm_s
5703 {
5704     int                 global_enable;
5705     ipmi_event_state_t  *state;
5706     ipmi_sensor_done_cb done;
5707     void                *cb_data;
5708     int                 rv;
5709 } sensor_id_rearm_t;
5710 
5711 static void
sensor_id_rearm_cb(ipmi_sensor_t * sensor,void * cb_data)5712 sensor_id_rearm_cb(ipmi_sensor_t *sensor, void *cb_data)
5713 {
5714     sensor_id_rearm_t *info = cb_data;
5715 
5716     info->rv = ipmi_sensor_rearm(sensor,
5717 				 info->global_enable,
5718 				 info->state,
5719 				 info->done,
5720 				 info->cb_data);
5721 }
5722 
5723 int
ipmi_sensor_id_rearm(ipmi_sensor_id_t sensor_id,int global_enable,ipmi_event_state_t * state,ipmi_sensor_done_cb done,void * cb_data)5724 ipmi_sensor_id_rearm(ipmi_sensor_id_t    sensor_id,
5725 		     int                 global_enable,
5726 		     ipmi_event_state_t  *state,
5727 		     ipmi_sensor_done_cb done,
5728 		     void                *cb_data)
5729 {
5730     sensor_id_rearm_t info;
5731     int               rv;
5732 
5733     info.global_enable = global_enable;
5734     info.state = state;
5735     info.done = done;
5736     info.cb_data = cb_data;
5737     rv = ipmi_sensor_pointer_cb(sensor_id, sensor_id_rearm_cb, &info);
5738     if (!rv)
5739 	rv = info.rv;
5740     return rv;
5741 }
5742 
5743 typedef struct sensor_id_get_hysteresis_s
5744 {
5745     ipmi_sensor_hysteresis_cb done;
5746     void                      *cb_data;
5747     int                       rv;
5748 } sensor_id_get_hysteresis_t;
5749 
5750 static void
sensor_id_get_hysteresis_cb(ipmi_sensor_t * sensor,void * cb_data)5751 sensor_id_get_hysteresis_cb(ipmi_sensor_t *sensor, void *cb_data)
5752 {
5753     sensor_id_get_hysteresis_t *info = cb_data;
5754 
5755     info->rv = ipmi_sensor_get_hysteresis(sensor,
5756 					  info->done,
5757 					  info->cb_data);
5758 }
5759 
5760 int
ipmi_sensor_id_get_hysteresis(ipmi_sensor_id_t sensor_id,ipmi_sensor_hysteresis_cb done,void * cb_data)5761 ipmi_sensor_id_get_hysteresis(ipmi_sensor_id_t          sensor_id,
5762 			      ipmi_sensor_hysteresis_cb done,
5763 			      void                      *cb_data)
5764 {
5765     sensor_id_get_hysteresis_t info;
5766     int                        rv;
5767 
5768     info.done = done;
5769     info.cb_data = cb_data;
5770     rv = ipmi_sensor_pointer_cb(sensor_id, sensor_id_get_hysteresis_cb, &info);
5771     if (!rv)
5772 	rv = info.rv;
5773     return rv;
5774 }
5775 
5776 typedef struct sensor_id_set_hysteresis_s
5777 {
5778     unsigned int        positive_hysteresis;
5779     unsigned int        negative_hysteresis;
5780     ipmi_sensor_done_cb done;
5781     void                *cb_data;
5782     int                 rv;
5783 } sensor_id_set_hysteresis_t;
5784 
5785 static void
sensor_id_set_hysteresis_cb(ipmi_sensor_t * sensor,void * cb_data)5786 sensor_id_set_hysteresis_cb(ipmi_sensor_t *sensor, void *cb_data)
5787 {
5788     sensor_id_set_hysteresis_t *info = cb_data;
5789 
5790     info->rv = ipmi_sensor_set_hysteresis(sensor,
5791 					  info->positive_hysteresis,
5792 					  info->negative_hysteresis,
5793 					  info->done,
5794 					  info->cb_data);
5795 }
5796 
5797 int
ipmi_sensor_id_set_hysteresis(ipmi_sensor_id_t sensor_id,unsigned int positive_hysteresis,unsigned int negative_hysteresis,ipmi_sensor_done_cb done,void * cb_data)5798 ipmi_sensor_id_set_hysteresis(ipmi_sensor_id_t    sensor_id,
5799 			      unsigned int        positive_hysteresis,
5800 			      unsigned int        negative_hysteresis,
5801 			      ipmi_sensor_done_cb done,
5802 			      void                *cb_data)
5803 {
5804     sensor_id_set_hysteresis_t info;
5805     int                        rv;
5806 
5807     info.positive_hysteresis = positive_hysteresis;
5808     info.negative_hysteresis = negative_hysteresis;
5809     info.done = done;
5810     info.cb_data = cb_data;
5811     rv = ipmi_sensor_pointer_cb(sensor_id, sensor_id_set_hysteresis_cb, &info);
5812     if (!rv)
5813 	rv = info.rv;
5814     return rv;
5815 }
5816 
5817 typedef struct sensor_id_thresholds_set_s
5818 {
5819     ipmi_thresholds_t   *thresholds;
5820     ipmi_sensor_done_cb done;
5821     void                *cb_data;
5822     int                 rv;
5823 } sensor_id_thresholds_set_t;
5824 
5825 static void
sensor_id_set_thresholds_cb(ipmi_sensor_t * sensor,void * cb_data)5826 sensor_id_set_thresholds_cb(ipmi_sensor_t *sensor, void *cb_data)
5827 {
5828     sensor_id_thresholds_set_t *info = cb_data;
5829 
5830     info->rv = ipmi_sensor_set_thresholds(sensor,
5831 					  info->thresholds,
5832 					  info->done,
5833 					  info->cb_data);
5834 }
5835 
5836 int
ipmi_sensor_id_set_thresholds(ipmi_sensor_id_t sensor_id,ipmi_thresholds_t * thresholds,ipmi_sensor_done_cb done,void * cb_data)5837 ipmi_sensor_id_set_thresholds(ipmi_sensor_id_t    sensor_id,
5838 			      ipmi_thresholds_t   *thresholds,
5839 			      ipmi_sensor_done_cb done,
5840 			      void                *cb_data)
5841 {
5842     sensor_id_thresholds_set_t info;
5843     int               rv;
5844 
5845     info.thresholds = thresholds;
5846     info.done = done;
5847     info.cb_data = cb_data;
5848     rv = ipmi_sensor_pointer_cb(sensor_id, sensor_id_set_thresholds_cb, &info);
5849     if (!rv)
5850 	rv = info.rv;
5851     return rv;
5852 }
5853 
5854 typedef struct sensor_id_thresholds_get_s
5855 {
5856     ipmi_sensor_thresholds_cb done;
5857     void                      *cb_data;
5858     int                       rv;
5859 } sensor_id_thresholds_get_t;
5860 
5861 static void
sensor_id_get_thresholds_cb(ipmi_sensor_t * sensor,void * cb_data)5862 sensor_id_get_thresholds_cb(ipmi_sensor_t *sensor, void *cb_data)
5863 {
5864     sensor_id_thresholds_get_t *info = cb_data;
5865 
5866     info->rv = ipmi_sensor_get_thresholds(sensor,
5867 					  info->done,
5868 					  info->cb_data);
5869 }
5870 
5871 int
ipmi_sensor_id_get_thresholds(ipmi_sensor_id_t sensor_id,ipmi_sensor_thresholds_cb done,void * cb_data)5872 ipmi_sensor_id_get_thresholds(ipmi_sensor_id_t          sensor_id,
5873 			      ipmi_sensor_thresholds_cb done,
5874 			      void                      *cb_data)
5875 {
5876     sensor_id_thresholds_get_t info;
5877     int                        rv;
5878 
5879     info.done = done;
5880     info.cb_data = cb_data;
5881     rv = ipmi_sensor_pointer_cb(sensor_id, sensor_id_get_thresholds_cb, &info);
5882     if (!rv)
5883 	rv = info.rv;
5884     return rv;
5885 }
5886 
5887 typedef struct sensor_id_reading_get_s
5888 {
5889     ipmi_sensor_reading_cb done;
5890     void                   *cb_data;
5891     int                    rv;
5892 } sensor_id_reading_get_t;
5893 
5894 static void
sensor_id_get_reading_cb(ipmi_sensor_t * sensor,void * cb_data)5895 sensor_id_get_reading_cb(ipmi_sensor_t *sensor, void *cb_data)
5896 {
5897     sensor_id_reading_get_t *info = cb_data;
5898 
5899     info->rv = ipmi_sensor_get_reading(sensor,
5900 				       info->done,
5901 				       info->cb_data);
5902 }
5903 
5904 int
ipmi_sensor_id_get_reading(ipmi_sensor_id_t sensor_id,ipmi_sensor_reading_cb done,void * cb_data)5905 ipmi_sensor_id_get_reading(ipmi_sensor_id_t       sensor_id,
5906 			   ipmi_sensor_reading_cb done,
5907 			   void                   *cb_data)
5908 {
5909     sensor_id_reading_get_t info;
5910     int                     rv;
5911 
5912     info.done = done;
5913     info.cb_data = cb_data;
5914     rv = ipmi_sensor_pointer_cb(sensor_id, sensor_id_get_reading_cb, &info);
5915     if (!rv)
5916 	rv = info.rv;
5917     return rv;
5918 }
5919 
5920 typedef struct sensor_id_states_get_s
5921 {
5922     ipmi_sensor_states_cb done;
5923     void                  *cb_data;
5924     int                   rv;
5925 } sensor_id_states_get_t;
5926 
5927 static void
sensor_id_get_states_cb(ipmi_sensor_t * sensor,void * cb_data)5928 sensor_id_get_states_cb(ipmi_sensor_t *sensor, void *cb_data)
5929 {
5930     sensor_id_states_get_t *info = cb_data;
5931 
5932     info->rv = ipmi_sensor_get_states(sensor,
5933 				      info->done,
5934 				      info->cb_data);
5935 }
5936 
5937 int
ipmi_sensor_id_get_states(ipmi_sensor_id_t sensor_id,ipmi_sensor_states_cb done,void * cb_data)5938 ipmi_sensor_id_get_states(ipmi_sensor_id_t      sensor_id,
5939 			  ipmi_sensor_states_cb done,
5940 			  void                  *cb_data)
5941 {
5942     sensor_id_states_get_t info;
5943     int                    rv;
5944 
5945     info.done = done;
5946     info.cb_data = cb_data;
5947     rv = ipmi_sensor_pointer_cb(sensor_id, sensor_id_get_states_cb, &info);
5948     if (!rv)
5949 	rv = info.rv;
5950     return rv;
5951 }
5952 
5953 
5954 #ifdef IPMI_CHECK_LOCKS
5955 void
i__ipmi_check_sensor_lock(const ipmi_sensor_t * sensor)5956 i__ipmi_check_sensor_lock(const ipmi_sensor_t *sensor)
5957 {
5958     if (!sensor)
5959 	return;
5960 
5961     if (!DEBUG_LOCKS)
5962 	return;
5963 
5964     CHECK_ENTITY_LOCK(sensor->entity);
5965     CHECK_MC_LOCK(sensor->mc);
5966 
5967     if (sensor->usecount == 0)
5968 	ipmi_report_lock_error(ipmi_domain_get_os_hnd(sensor->domain),
5969 			       "sensor not locked when it should have been");
5970 }
5971 #endif
5972 
5973 /***********************************************************************
5974  *
5975  * Cruft
5976  *
5977  **********************************************************************/
5978 
5979 int
ipmi_sensor_threshold_assertion_event_supported(ipmi_sensor_t * sensor,enum ipmi_thresh_e event,enum ipmi_event_value_dir_e dir,int * val)5980 ipmi_sensor_threshold_assertion_event_supported(
5981     ipmi_sensor_t               *sensor,
5982     enum ipmi_thresh_e          event,
5983     enum ipmi_event_value_dir_e dir,
5984     int                         *val)
5985 {
5986     int idx;
5987 
5988     CHECK_SENSOR_LOCK(sensor);
5989 
5990     if (sensor->event_reading_type != IPMI_EVENT_READING_TYPE_THRESHOLD)
5991 	/* Not a threshold sensor, it doesn't have readings. */
5992 	return ENOSYS;
5993 
5994     idx = (event * 2) + dir;
5995     if (idx > 11)
5996 	return EINVAL;
5997 
5998     *val = IPMI_SENSOR_GET_MASK_BIT(sensor->mask1, idx);
5999     return 0;
6000 }
6001 
6002 int
ipmi_sensor_threshold_deassertion_event_supported(ipmi_sensor_t * sensor,enum ipmi_thresh_e event,enum ipmi_event_value_dir_e dir,int * val)6003 ipmi_sensor_threshold_deassertion_event_supported(
6004     ipmi_sensor_t               *sensor,
6005     enum ipmi_thresh_e          event,
6006     enum ipmi_event_value_dir_e dir,
6007     int                         *val)
6008 {
6009     int idx;
6010 
6011     CHECK_SENSOR_LOCK(sensor);
6012 
6013     if (sensor->event_reading_type != IPMI_EVENT_READING_TYPE_THRESHOLD)
6014 	/* Not a threshold sensor, it doesn't have readings. */
6015 	return ENOSYS;
6016 
6017     idx = (event * 2) + dir;
6018     if (idx > 11)
6019 	return 0;
6020 
6021     *val = IPMI_SENSOR_GET_MASK_BIT(sensor->mask2, idx);
6022     return 0;
6023 }
6024 
6025 int
ipmi_sensor_discrete_assertion_event_supported(ipmi_sensor_t * sensor,int event,int * val)6026 ipmi_sensor_discrete_assertion_event_supported(ipmi_sensor_t *sensor,
6027 					       int           event,
6028 					       int           *val)
6029 {
6030     CHECK_SENSOR_LOCK(sensor);
6031 
6032     if (sensor->event_reading_type == IPMI_EVENT_READING_TYPE_THRESHOLD)
6033 	/* A threshold sensor, it doesn't have events. */
6034 	return ENOSYS;
6035 
6036     if (event > 14)
6037 	return EINVAL;
6038 
6039     *val = IPMI_SENSOR_GET_MASK_BIT(sensor->mask1, event);
6040     return 0;
6041 }
6042 
6043 int
ipmi_sensor_discrete_deassertion_event_supported(ipmi_sensor_t * sensor,int event,int * val)6044 ipmi_sensor_discrete_deassertion_event_supported(ipmi_sensor_t *sensor,
6045 						 int           event,
6046 						 int           *val)
6047 {
6048     CHECK_SENSOR_LOCK(sensor);
6049 
6050     if (sensor->event_reading_type == IPMI_EVENT_READING_TYPE_THRESHOLD)
6051 	/* A threshold sensor, it doesn't have events. */
6052 	return ENOSYS;
6053 
6054     if (event > 14)
6055 	return EINVAL;
6056 
6057     *val = IPMI_SENSOR_GET_MASK_BIT(sensor->mask2, event);
6058     return 0;
6059 }
6060 
6061 int
ipmi_sensor_events_enable_get(ipmi_sensor_t * sensor,ipmi_sensor_event_enables_cb done,void * cb_data)6062 ipmi_sensor_events_enable_get(ipmi_sensor_t                *sensor,
6063 			      ipmi_sensor_event_enables_cb done,
6064 			      void                         *cb_data)
6065 {
6066     return ipmi_sensor_get_event_enables(sensor, done, cb_data);
6067 }
6068 
6069 int
ipmi_sensor_events_disable(ipmi_sensor_t * sensor,ipmi_event_state_t * states,ipmi_sensor_done_cb done,void * cb_data)6070 ipmi_sensor_events_disable(ipmi_sensor_t         *sensor,
6071 			   ipmi_event_state_t    *states,
6072 			   ipmi_sensor_done_cb   done,
6073 			   void                  *cb_data)
6074 {
6075     return ipmi_sensor_disable_events(sensor, states, done, cb_data);
6076 }
6077 
6078 int
ipmi_sensor_events_enable(ipmi_sensor_t * sensor,ipmi_event_state_t * states,ipmi_sensor_done_cb done,void * cb_data)6079 ipmi_sensor_events_enable(ipmi_sensor_t         *sensor,
6080 			  ipmi_event_state_t    *states,
6081 			  ipmi_sensor_done_cb   done,
6082 			  void                  *cb_data)
6083 {
6084     return ipmi_sensor_enable_events(sensor, states, done, cb_data);
6085 }
6086 
ipmi_sensor_events_enable_set(ipmi_sensor_t * sensor,ipmi_event_state_t * states,ipmi_sensor_done_cb done,void * cb_data)6087 int ipmi_sensor_events_enable_set(ipmi_sensor_t         *sensor,
6088 				  ipmi_event_state_t    *states,
6089 				  ipmi_sensor_done_cb   done,
6090 				  void                  *cb_data)
6091 {
6092     return ipmi_sensor_set_event_enables(sensor, states, done, cb_data);
6093 }
6094 
6095 int
ipmi_sensor_id_events_enable_set(ipmi_sensor_id_t sensor_id,ipmi_event_state_t * states,ipmi_sensor_done_cb done,void * cb_data)6096 ipmi_sensor_id_events_enable_set(ipmi_sensor_id_t      sensor_id,
6097 				 ipmi_event_state_t    *states,
6098 				 ipmi_sensor_done_cb   done,
6099 				 void                  *cb_data)
6100 {
6101     return ipmi_sensor_id_set_event_enables(sensor_id, states, done, cb_data);
6102 }
6103 
6104 int
ipmi_sensor_id_events_enable(ipmi_sensor_id_t sensor_id,ipmi_event_state_t * states,ipmi_sensor_done_cb done,void * cb_data)6105 ipmi_sensor_id_events_enable(ipmi_sensor_id_t      sensor_id,
6106 			     ipmi_event_state_t    *states,
6107 			     ipmi_sensor_done_cb   done,
6108 			     void                  *cb_data)
6109 {
6110     return ipmi_sensor_id_enable_events(sensor_id, states, done, cb_data);
6111 }
6112 
6113 int
ipmi_sensor_id_events_disable(ipmi_sensor_id_t sensor_id,ipmi_event_state_t * states,ipmi_sensor_done_cb done,void * cb_data)6114 ipmi_sensor_id_events_disable(ipmi_sensor_id_t      sensor_id,
6115 			      ipmi_event_state_t    *states,
6116 			      ipmi_sensor_done_cb   done,
6117 			      void                  *cb_data)
6118 {
6119     return ipmi_sensor_id_disable_events(sensor_id, states, done, cb_data);
6120 }
6121 
6122 int
ipmi_sensor_id_events_enable_get(ipmi_sensor_id_t sensor_id,ipmi_sensor_event_enables_cb done,void * cb_data)6123 ipmi_sensor_id_events_enable_get(ipmi_sensor_id_t             sensor_id,
6124 				 ipmi_sensor_event_enables_cb done,
6125 				 void                         *cb_data)
6126 {
6127     return ipmi_sensor_id_get_event_enables(sensor_id, done, cb_data);
6128 }
6129 
6130 int
ipmi_states_get(ipmi_sensor_t * sensor,ipmi_sensor_states_cb done,void * cb_data)6131 ipmi_states_get(ipmi_sensor_t         *sensor,
6132 		ipmi_sensor_states_cb done,
6133 		void                  *cb_data)
6134 {
6135     return ipmi_sensor_get_states(sensor, done, cb_data);
6136 }
6137 
6138 int
ipmi_reading_get(ipmi_sensor_t * sensor,ipmi_sensor_reading_cb done,void * cb_data)6139 ipmi_reading_get(ipmi_sensor_t          *sensor,
6140 		 ipmi_sensor_reading_cb done,
6141 		 void                   *cb_data)
6142 {
6143     return ipmi_sensor_get_reading(sensor, done, cb_data);
6144 }
6145 
6146 int
ipmi_thresholds_set(ipmi_sensor_t * sensor,ipmi_thresholds_t * thresholds,ipmi_sensor_done_cb done,void * cb_data)6147 ipmi_thresholds_set(ipmi_sensor_t       *sensor,
6148 		    ipmi_thresholds_t   *thresholds,
6149 		    ipmi_sensor_done_cb done,
6150 		    void                *cb_data)
6151 {
6152     return ipmi_sensor_set_thresholds(sensor, thresholds, done, cb_data);
6153 }
6154 
6155 int
ipmi_thresholds_get(ipmi_sensor_t * sensor,ipmi_sensor_thresholds_cb done,void * cb_data)6156 ipmi_thresholds_get(ipmi_sensor_t             *sensor,
6157 		    ipmi_sensor_thresholds_cb done,
6158 		    void                      *cb_data)
6159 {
6160     return ipmi_sensor_get_thresholds(sensor, done, cb_data);
6161 }
6162 
6163 int
ipmi_sensor_id_thresholds_set(ipmi_sensor_id_t sensor_id,ipmi_thresholds_t * thresholds,ipmi_sensor_done_cb done,void * cb_data)6164 ipmi_sensor_id_thresholds_set(ipmi_sensor_id_t    sensor_id,
6165 			      ipmi_thresholds_t   *thresholds,
6166 			      ipmi_sensor_done_cb done,
6167 			      void                *cb_data)
6168 {
6169     return ipmi_sensor_id_set_thresholds(sensor_id, thresholds, done, cb_data);
6170 }
6171 
6172 int
ipmi_sensor_id_thresholds_get(ipmi_sensor_id_t sensor_id,ipmi_sensor_thresholds_cb done,void * cb_data)6173 ipmi_sensor_id_thresholds_get(ipmi_sensor_id_t          sensor_id,
6174 			      ipmi_sensor_thresholds_cb done,
6175 			      void                      *cb_data)
6176 {
6177     return ipmi_sensor_id_get_thresholds(sensor_id, done, cb_data);
6178 }
6179 
6180 int
ipmi_sensor_id_reading_get(ipmi_sensor_id_t sensor_id,ipmi_sensor_reading_cb done,void * cb_data)6181 ipmi_sensor_id_reading_get(ipmi_sensor_id_t       sensor_id,
6182 			   ipmi_sensor_reading_cb done,
6183 			   void                   *cb_data)
6184 {
6185     return ipmi_sensor_id_get_reading(sensor_id, done, cb_data);
6186 }
6187 
6188 int
ipmi_sensor_id_states_get(ipmi_sensor_id_t sensor_id,ipmi_sensor_states_cb done,void * cb_data)6189 ipmi_sensor_id_states_get(ipmi_sensor_id_t      sensor_id,
6190 			  ipmi_sensor_states_cb done,
6191 			  void                  *cb_data)
6192 {
6193     return ipmi_sensor_id_get_states(sensor_id, done, cb_data);
6194 }
6195 
6196 int
ipmi_discrete_event_readable(ipmi_sensor_t * sensor,int event,int * val)6197 ipmi_discrete_event_readable(ipmi_sensor_t *sensor,
6198 			     int           event,
6199 			     int           *val)
6200 {
6201     CHECK_SENSOR_LOCK(sensor);
6202 
6203     if (sensor->event_reading_type == IPMI_EVENT_READING_TYPE_THRESHOLD)
6204 	/* A threshold sensor, it doesn't have events. */
6205 	return ENOSYS;
6206 
6207     if (event > 14)
6208 	return EINVAL;
6209 
6210     *val = IPMI_SENSOR_GET_MASK_BIT(sensor->mask3, event);
6211     return 0;
6212 }
6213