| /* |
| <:copyright-BRCM:2016:DUAL/GPL:standard |
| |
| Broadcom Proprietary and Confidential.(c) 2016 Broadcom |
| All Rights Reserved |
| |
| Unless you and Broadcom execute a separate written software license |
| agreement governing use of this software, this software is licensed |
| to you under the terms of the GNU General Public License version 2 |
| (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php, |
| with the following added to such license: |
| |
| As a special exception, the copyright holders of this software give |
| you permission to link this software with independent modules, and |
| to copy and distribute the resulting executable under terms of your |
| choice, provided that you also meet, for each linked independent |
| module, the terms and conditions of the license of that module. |
| An independent module is a module which is not derived from this |
| software. The special exception does not apply to any modifications |
| of the software. |
| |
| Not withstanding the above, under no circumstances may you combine |
| this software in any way with any other Broadcom software provided |
| under a license other than the GPL, without Broadcom's express prior |
| written consent. |
| |
| :> |
| */ |
| |
| #ifndef _BCMOLT_MH_UTILS_H_ |
| #define _BCMOLT_MH_UTILS_H_ |
| |
| #define MH_EXIT_IF(cond, error) \ |
| do \ |
| { \ |
| if (cond) \ |
| { \ |
| if ((error) != BCM_ERR_OK && (error) != BCM_ERR_NO_MORE) \ |
| { \ |
| BCMOS_TRACE_INFO(#cond); \ |
| } \ |
| err = (error); \ |
| goto cleanup; \ |
| } \ |
| } while (BCMOS_FALSE) |
| |
| /* Macro for declaring cfg_get_multi handlers, since the format is perfectly regular */ |
| #define MH_DECLARE_CFG_GET_MULTI(obj) \ |
| static bcmos_errno mh_##obj##_cfg_get_multi( \ |
| const bcmolt_##obj##_cfg *filter, \ |
| bcmolt_filter_flags flags, \ |
| bcmolt_msg_set *msg_set) \ |
| { \ |
| bcmolt_##obj##_cfg cfg; \ |
| uint8_t *filter_packed = NULL; \ |
| uint8_t *msg_packed = NULL; \ |
| bcmos_errno err; \ |
| bcmos_bool success; \ |
| uint32_t len; \ |
| bcmolt_buf buf; \ |
| bcmos_bool is_match; \ |
| bcmolt_msg dummy_hdr; \ |
| bcmolt_##obj##_key_id dummy_prop_id; \ |
| \ |
| /* assume we didn't finish all objects unless told otherwise */ \ |
| msg_set->more = BCMOS_TRUE; \ |
| \ |
| /* start with the key included in the filter */ \ |
| *((bcmolt_##obj##_key *)msg_set->next_key) = filter->key; \ |
| \ |
| /* if the filter's key contains any wildcards, get the first real key */ \ |
| err = mh_##obj##_key_resolve_wildcards(msg_set->next_key); \ |
| MH_EXIT_IF(err != BCM_ERR_OK, err); \ |
| \ |
| /* if the initial key is invalid, exit early */ \ |
| MH_EXIT_IF( \ |
| !bcmolt_##obj##_key_bounds_check(msg_set->next_key, BCMOLT_PRESENCE_MASK_ALL, &dummy_prop_id), \ |
| BCM_ERR_KEY_RANGE); \ |
| err = mh_##obj##_key_validate(&dummy_hdr, msg_set->next_key); \ |
| MH_EXIT_IF(err != BCM_ERR_OK, err); \ |
| \ |
| /* pack filter data (including presence mask) for comparisons */ \ |
| len = bcmolt_##obj##_cfg_data_get_packed_length(&filter->data, filter->hdr.hdr.presence_mask); \ |
| filter_packed = bcmos_calloc(len); \ |
| MH_EXIT_IF(len > 0 && filter_packed == NULL, BCM_ERR_NOMEM); \ |
| bcmolt_buf_init(&buf, len, filter_packed, BCMOLT_BUF_ENDIAN_FIXED); \ |
| success = bcmolt_##obj##_cfg_data_pack(&filter->data, &buf, filter->hdr.hdr.presence_mask); \ |
| \ |
| while (msg_set->num_instances < msg_set->max_instances) \ |
| { \ |
| /* initialize the cfg structure with the key and pass it to the MH cfg_get handler */ \ |
| BCMOLT_CFG_INIT(&cfg, obj, *((bcmolt_##obj##_key *)msg_set->next_key)); \ |
| /* (get all properties that were requested or are being filtered on) */ \ |
| cfg.hdr.hdr.presence_mask = msg_set->presence_mask | filter->hdr.hdr.presence_mask; \ |
| cfg.hdr.hdr.type = BCMOLT_MSG_TYPE_GET; \ |
| cfg.hdr.hdr.dir = BCMOLT_MSG_DIR_RESPONSE; \ |
| cfg.hdr.hdr.err = mh_##obj##_cfg_get(&cfg.hdr.hdr, &cfg.key, &cfg.data); \ |
| MH_EXIT_IF(cfg.hdr.hdr.err != BCM_ERR_OK, cfg.hdr.hdr.err); \ |
| \ |
| /* pack the resulting message data */ \ |
| len = bcmolt_##obj##_cfg_data_get_packed_length(&cfg.data, filter->hdr.hdr.presence_mask); \ |
| msg_packed = bcmos_calloc(len); \ |
| MH_EXIT_IF(len > 0 && msg_packed == NULL, BCM_ERR_NOMEM); \ |
| bcmolt_buf_init(&buf, len, msg_packed, BCMOLT_BUF_ENDIAN_FIXED); \ |
| success = bcmolt_##obj##_cfg_data_pack(&cfg.data, &buf, filter->hdr.hdr.presence_mask); \ |
| MH_EXIT_IF(!success, BCM_ERR_INTERNAL); \ |
| \ |
| /* check the packed message against the filter */ \ |
| is_match = (memcmp(filter_packed, msg_packed, len) == 0); \ |
| if ((flags & BCMOLT_FILTER_FLAGS_INVERT_SELECTION) != 0) \ |
| { \ |
| is_match = !is_match; \ |
| } \ |
| bcmos_free(msg_packed); \ |
| msg_packed = NULL; \ |
| \ |
| if (is_match) \ |
| { \ |
| /* if there is a match, include this message in the message set */ \ |
| msg_set->msg[msg_set->num_instances] = NULL; \ |
| err = bcmolt_msg_clone(&msg_set->msg[msg_set->num_instances], &cfg.hdr.hdr); \ |
| MH_EXIT_IF(err != BCM_ERR_OK, err); \ |
| msg_set->num_instances++; \ |
| } \ |
| \ |
| /* get next key, break if no more keys are found */ \ |
| err = mh_##obj##_key_iterate(msg_set->next_key); \ |
| MH_EXIT_IF(err != BCM_ERR_OK, err); \ |
| } \ |
| \ |
| cleanup: \ |
| if (filter_packed != NULL) \ |
| { \ |
| bcmos_free(filter_packed); \ |
| } \ |
| if (msg_packed != NULL) \ |
| { \ |
| bcmos_free(msg_packed); \ |
| } \ |
| if (err == BCM_ERR_NO_MORE) \ |
| { \ |
| err = BCM_ERR_OK; \ |
| msg_set->more = BCMOS_FALSE; \ |
| } \ |
| return err; \ |
| } |
| |
| #endif /* _BCMOLT_MH_UTILS_H_ */ |
| |