| /* |
| <: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. |
| |
| :> |
| */ |
| |
| #include <bcmolt_host_api.h> |
| #include "bcmolt_user_appl_onu_tuning.h" |
| |
| #define ONU_TUNING_TASK_MSG_Q_SIZE 256 |
| |
| typedef struct |
| { |
| bcmos_msg os_msg; |
| bcmolt_auto *ind; |
| bcmolt_devid device_id; |
| } ot_task_msg; |
| |
| static bcmolt_onu_tuning_context ot_context[BCMTR_MAX_OLTS]; |
| |
| |
| static bcmos_errno onu_tuning_init_task(bcmolt_devid device_id) |
| { |
| bcmos_errno rc; |
| bcmos_task_parm task_params = {}; |
| snprintf(ot_context[device_id].task.name, sizeof(ot_context[device_id].task.name), "user_appl_onu_tuning%u", device_id); |
| task_params.name = ot_context[device_id].task.name; |
| task_params.priority = TASK_PRIORITY_USER_APPL_ONU_TUNING; |
| task_params.core = BCMOS_CPU_CORE_ANY; /* No CPU affinity */ |
| task_params.init_handler = NULL; |
| task_params.data = (long)device_id; |
| rc = bcmos_task_create(&ot_context[device_id].task, &task_params); |
| BCMOS_TRACE_CHECK_RETURN(rc, rc, "bcmos_task_create()\n"); |
| |
| return rc; |
| } |
| |
| static bcmos_errno onu_tuning_init_module(bcmolt_devid device_id) |
| { |
| /* This value is used inside bcmolt_onu_tuning_module_init for timer owner */ |
| ot_context[device_id].device = device_id; |
| bcmos_module_parm module_params = |
| { |
| .qparm = { .name = "user_appl_onu_tuning", |
| .size = ONU_TUNING_TASK_MSG_Q_SIZE }, |
| }; |
| |
| return bcmos_module_create(BCMOS_MODULE_ID_USER_APPL_ONU_TUNING_DEV0 + device_id, &ot_context[device_id].task, &module_params); |
| } |
| |
| void bcmolt_onu_tuning_appl_init(bcmolt_devid device_id) |
| { |
| bcmos_errno err; |
| |
| #ifdef ENABLE_LOG |
| char log_name[MAX_DEV_LOG_ID_NAME] = {}; |
| snprintf(log_name, sizeof(log_name) - 1, "user_appl_onu_tuning%u", device_id); |
| ot_context[device_id].log_id = bcm_dev_log_id_register(log_name, DEV_LOG_LEVEL_DEBUG, DEV_LOG_ID_TYPE_BOTH); |
| #endif |
| |
| err = bcmos_mutex_create(&ot_context[device_id].mutex, 0, NULL); |
| BUG_ON(err != BCM_ERR_OK); |
| |
| err = onu_tuning_init_task(device_id); |
| BUG_ON(err != BCM_ERR_OK); |
| |
| err = onu_tuning_init_module(device_id); |
| BUG_ON(err != BCM_ERR_OK); |
| |
| } |
| |
| bcmos_errno bcmolt_onu_tuning_appl_start(bcmolt_devid device_id) |
| { |
| bcmos_errno ret = BCM_ERR_OK; |
| |
| bcmos_mutex_lock(&ot_context[device_id].mutex); |
| |
| if (ot_context[device_id].is_running) |
| { |
| BCM_LOG(ERROR, ot_context[device_id].log_id, "ONU tuning application already running on device=%u\n", device_id); |
| ret = BCM_ERR_STATE; |
| goto exit; |
| } |
| |
| ot_context[device_id].is_running = BCMOS_TRUE; |
| ot_context[device_id].device = device_id; |
| |
| BCM_LOG(INFO, ot_context[device_id].log_id, "ONU tuning application started on device=%u\n", device_id); |
| ret = BCM_ERR_OK; |
| |
| exit: |
| bcmos_mutex_unlock(&ot_context[device_id].mutex); |
| return ret; |
| } |
| |
| bcmos_errno bcmolt_onu_tuning_appl_stop(bcmolt_devid device_id) |
| { |
| bcmos_errno ret; |
| |
| bcmos_mutex_lock(&ot_context[device_id].mutex); |
| |
| if (!ot_context[device_id].is_running) |
| { |
| ret = BCM_ERR_STATE; |
| goto exit; |
| } |
| |
| ot_context[device_id].is_running = BCMOS_FALSE; |
| bcmos_timer_stop(&ot_context[device_id].timer); |
| BCM_LOG(INFO, ot_context[device_id].log_id, "ONU tuning application stopped on device=%u\n", device_id); |
| ret = BCM_ERR_OK; |
| |
| exit: |
| bcmos_mutex_unlock(&ot_context[device_id].mutex); |
| return ret; |
| } |
| |
| bcmos_bool bcmolt_onu_tuning_appl_is_running(bcmolt_devid device_id) |
| { |
| bcmos_bool ret; |
| |
| bcmos_mutex_lock(&ot_context[device_id].mutex); |
| ret = ot_context[device_id].is_running; |
| bcmos_mutex_unlock(&ot_context[device_id].mutex); |
| |
| return ret; |
| } |
| |
| static bcmos_bool bcmolt_onu_tuning_is_interested(bcmolt_auto *ind) |
| { |
| switch (ind->hdr.obj_type) |
| { |
| case BCMOLT_OBJ_ID_XGPON_ONU: |
| switch (ind->hdr.subgroup) |
| { |
| case BCMOLT_XGPON_ONU_AUTO_ID_TUNING_RESPONSE: |
| return BCMOS_TRUE; |
| case BCMOLT_XGPON_ONU_AUTO_ID_ONU_TUNING_IN_COMPLETED: |
| return BCMOS_TRUE; |
| default: |
| break; |
| } |
| break; |
| default: |
| break; |
| } |
| |
| return BCMOS_FALSE; |
| } |
| |
| static void bcmolt_onu_tuning_ind_cb(bcmos_module_id module_id, bcmos_msg *os_msg) |
| { |
| ot_task_msg *msg = (ot_task_msg *)os_msg; |
| bcmolt_pon_ni pon_ni; |
| bcmolt_pon_onu_id onu_id; |
| bcmolt_auto *ind = msg->ind; |
| bcmos_errno rc; |
| |
| switch (msg->ind->hdr.obj_type) |
| { |
| case BCMOLT_OBJ_ID_XGPON_ONU: |
| switch (msg->ind->hdr.subgroup) |
| { |
| case BCMOLT_XGPON_ONU_AUTO_ID_TUNING_RESPONSE: |
| { |
| bcmolt_xgpon_onu_tuning_response *onu_tuning_response = (bcmolt_xgpon_onu_tuning_response *)ind; |
| onu_id = onu_tuning_response->key.onu_id; |
| pon_ni = onu_tuning_response->key.pon_ni; |
| |
| if (onu_tuning_response->data.ack == BCMOS_TRUE && onu_tuning_response->data.result == BCMOLT_RESULT_SUCCESS) |
| { |
| BCM_LOG(INFO, ot_context[msg->device_id].log_id, "Indication BCMOLT_XGPON_ONU_AUTO_ID_TUNING_RESPONSE handled: PON:%u ONU:%u target_pon_ni=%u\n", pon_ni, onu_id, ot_context[msg->device_id].onu_db[onu_id].target_pon_ni); |
| |
| /* start tuning in onu on target pon id */ |
| bcmolt_xgpon_onu_key key = { .pon_ni = ot_context[msg->device_id].onu_db[onu_id].target_pon_ni, .onu_id = onu_id }; |
| bcmolt_xgpon_onu_onu_tuning_in onu_tuning_in; |
| |
| BCMOLT_OPER_INIT(&onu_tuning_in, xgpon_onu, onu_tuning_in, key); |
| rc = bcmolt_oper_submit(msg->device_id, &onu_tuning_in.hdr); |
| if (rc != BCM_ERR_OK) |
| BCM_LOG(ERROR, ot_context[msg->device_id].log_id, "ONU=%u tuning in to PON=%u failed\n", onu_id, ot_context[msg->device_id].onu_db[onu_id].target_pon_ni); |
| } |
| |
| break; |
| } |
| case BCMOLT_XGPON_ONU_AUTO_ID_ONU_TUNING_IN_COMPLETED: |
| { |
| bcmolt_xgpon_onu_onu_tuning_in_completed *onu_tuning_in_completed = (bcmolt_xgpon_onu_onu_tuning_in_completed *)ind; |
| onu_id = onu_tuning_in_completed->key.onu_id; |
| pon_ni = onu_tuning_in_completed->key.pon_ni; |
| if (onu_tuning_in_completed->data.result == BCMOLT_RESULT_SUCCESS) |
| { |
| BCM_LOG(INFO, ot_context[msg->device_id].log_id, "Indication BCMOLT_XGPON_ONU_AUTO_ID_ONU_TUNING_IN_COMPLETED handled: PON:%u ONU:%u\n", pon_ni, onu_id); |
| |
| /* start tuning out onu on source pon id */ |
| bcmolt_xgpon_onu_key key = { .pon_ni = ot_context[msg->device_id].onu_db[onu_id].source_pon_ni, .onu_id = onu_id }; |
| bcmolt_xgpon_onu_onu_tuning_out onu_tuning_out; |
| |
| BCMOLT_OPER_INIT(&onu_tuning_out, xgpon_onu, onu_tuning_out, key); |
| BCMOLT_OPER_PROP_SET(&onu_tuning_out, xgpon_onu, onu_tuning_out, target_ds_pon_id, ot_context[msg->device_id].onu_db[onu_id].target_pon_id); |
| BCMOLT_OPER_PROP_SET(&onu_tuning_out, xgpon_onu, onu_tuning_out, target_us_pon_id, ot_context[msg->device_id].onu_db[onu_id].target_pon_id); |
| BCMOLT_OPER_PROP_SET(&onu_tuning_out, xgpon_onu, onu_tuning_out, time_to_switch, 1000); |
| BCMOLT_OPER_PROP_SET(&onu_tuning_out, xgpon_onu, onu_tuning_out, rollback, BCMOS_FALSE); |
| BCMOLT_OPER_PROP_SET(&onu_tuning_out, xgpon_onu, onu_tuning_out, status, BCMOLT_STATUS_OFF); |
| rc = bcmolt_oper_submit(msg->device_id, &onu_tuning_out.hdr); |
| if (rc != BCM_ERR_OK) |
| BCM_LOG(ERROR, ot_context[msg->device_id].log_id, "ONU=%u tuning out from PON=%u failed\n", onu_id, ot_context[msg->device_id].onu_db[onu_id].source_pon_ni); |
| } |
| break; |
| } |
| default: |
| break; |
| } |
| break; |
| default: |
| break; |
| } |
| |
| /* free the cloned indication since we're done processing it */ |
| bcmolt_msg_free(&msg->ind->hdr); |
| /* free the internal OS message handle */ |
| bcmos_free(os_msg); |
| } |
| |
| bcmos_errno bcmolt_onu_tuning_process_ind(bcmolt_devid device_id, bcmolt_auto *ind) |
| { |
| bcmos_errno err; |
| bcmolt_msg *ind_clone = NULL; |
| |
| /* if the application isn't running, don't listen to any indications */ |
| if (!bcmolt_onu_tuning_appl_is_running(device_id)) |
| return BCM_ERR_OK; |
| |
| /* check to see if we have a handler for this type of indication */ |
| if (!bcmolt_onu_tuning_is_interested(ind)) |
| return BCM_ERR_OK; |
| |
| /* clone the indication into newly-allocated memory so we can handle it after the original message has been freed */ |
| err = bcmolt_msg_clone(&ind_clone, &ind->hdr); |
| if (err != BCM_ERR_OK) |
| { |
| BCM_LOG(ERROR, ot_context[device_id].log_id, "Indication clone failed: %s\n", bcmos_strerror(err)); |
| return err; |
| } |
| |
| /* send the clone to the internal task's message queue */ |
| ot_task_msg *msg = bcmos_calloc(sizeof(*msg)); |
| if (msg == NULL) |
| { |
| BCM_LOG(ERROR, ot_context[device_id].log_id, "Message calloc failed: %s\n", bcmos_strerror(err)); |
| bcmolt_msg_free(ind_clone); |
| return BCM_ERR_NOMEM; |
| } |
| msg->os_msg.handler = bcmolt_onu_tuning_ind_cb; |
| msg->os_msg.release = bcmolt_os_msg_release_cb; |
| msg->device_id = device_id; |
| msg->ind = (bcmolt_auto *)ind_clone; |
| |
| err = bcmos_msg_send_to_module(TASK_PRIORITY_USER_APPL_ONU_TUNING + device_id, &msg->os_msg, 0); |
| if (err != BCM_ERR_OK) |
| { |
| BCM_LOG(ERROR, ot_context[device_id].log_id, "Message send failed: %s\n", bcmos_strerror(err)); |
| bcmolt_msg_free(ind_clone); |
| return err; |
| } |
| |
| return BCM_ERR_OK; |
| } |
| |
| bcmos_errno onu_tuning_update_onu_db (bcmolt_devid device_id, bcmolt_xgpon_onu_id onu_id, bcmolt_pon_ni source_pon_ni, bcmolt_pon_ni target_pon_ni, bcmolt_pon_id target_pon_id, bcmos_bool rollback) |
| { |
| bcmos_errno ret; |
| bcmos_mutex_lock(&ot_context[device_id].mutex); |
| |
| if (!ot_context[device_id].is_running) |
| { |
| ret = BCM_ERR_STATE; |
| goto exit; |
| } |
| ot_context[device_id].onu_db[onu_id].target_pon_ni = target_pon_ni; |
| ot_context[device_id].onu_db[onu_id].source_pon_ni = source_pon_ni; |
| ot_context[device_id].onu_db[onu_id].target_pon_id = target_pon_id; |
| ot_context[device_id].onu_db[onu_id].rollback = rollback; |
| ret = BCM_ERR_OK; |
| |
| exit: |
| bcmos_mutex_unlock(&ot_context[device_id].mutex); |
| return ret; |
| } |