Shad Ansari | 2f7f9be | 2017-06-07 13:34:53 -0700 | [diff] [blame] | 1 | /* |
| 2 | <:copyright-BRCM:2016:DUAL/GPL:standard |
| 3 | |
| 4 | Broadcom Proprietary and Confidential.(c) 2016 Broadcom |
| 5 | All Rights Reserved |
| 6 | |
| 7 | Unless you and Broadcom execute a separate written software license |
| 8 | agreement governing use of this software, this software is licensed |
| 9 | to you under the terms of the GNU General Public License version 2 |
| 10 | (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php, |
| 11 | with the following added to such license: |
| 12 | |
| 13 | As a special exception, the copyright holders of this software give |
| 14 | you permission to link this software with independent modules, and |
| 15 | to copy and distribute the resulting executable under terms of your |
| 16 | choice, provided that you also meet, for each linked independent |
| 17 | module, the terms and conditions of the license of that module. |
| 18 | An independent module is a module which is not derived from this |
| 19 | software. The special exception does not apply to any modifications |
| 20 | of the software. |
| 21 | |
| 22 | Not withstanding the above, under no circumstances may you combine |
| 23 | this software in any way with any other Broadcom software provided |
| 24 | under a license other than the GPL, without Broadcom's express prior |
| 25 | written consent. |
| 26 | |
| 27 | :> |
| 28 | */ |
| 29 | |
| 30 | #include <bcmolt_host_api.h> |
| 31 | #include "bcmolt_user_appl_onu_tuning.h" |
| 32 | |
| 33 | #define ONU_TUNING_TASK_MSG_Q_SIZE 256 |
| 34 | |
| 35 | typedef struct |
| 36 | { |
| 37 | bcmos_msg os_msg; |
| 38 | bcmolt_auto *ind; |
| 39 | bcmolt_devid device_id; |
| 40 | } ot_task_msg; |
| 41 | |
| 42 | static bcmolt_onu_tuning_context ot_context[BCMTR_MAX_OLTS]; |
| 43 | |
| 44 | |
| 45 | static bcmos_errno onu_tuning_init_task(bcmolt_devid device_id) |
| 46 | { |
| 47 | bcmos_errno rc; |
| 48 | bcmos_task_parm task_params = {}; |
| 49 | snprintf(ot_context[device_id].task.name, sizeof(ot_context[device_id].task.name), "user_appl_onu_tuning%u", device_id); |
| 50 | task_params.name = ot_context[device_id].task.name; |
| 51 | task_params.priority = TASK_PRIORITY_USER_APPL_ONU_TUNING; |
| 52 | task_params.core = BCMOS_CPU_CORE_ANY; /* No CPU affinity */ |
| 53 | task_params.init_handler = NULL; |
| 54 | task_params.data = (long)device_id; |
| 55 | rc = bcmos_task_create(&ot_context[device_id].task, &task_params); |
| 56 | BCMOS_TRACE_CHECK_RETURN(rc, rc, "bcmos_task_create()\n"); |
| 57 | |
| 58 | return rc; |
| 59 | } |
| 60 | |
| 61 | static bcmos_errno onu_tuning_init_module(bcmolt_devid device_id) |
| 62 | { |
| 63 | /* This value is used inside bcmolt_onu_tuning_module_init for timer owner */ |
| 64 | ot_context[device_id].device = device_id; |
| 65 | bcmos_module_parm module_params = |
| 66 | { |
| 67 | .qparm = { .name = "user_appl_onu_tuning", |
| 68 | .size = ONU_TUNING_TASK_MSG_Q_SIZE }, |
| 69 | }; |
| 70 | |
| 71 | return bcmos_module_create(BCMOS_MODULE_ID_USER_APPL_ONU_TUNING_DEV0 + device_id, &ot_context[device_id].task, &module_params); |
| 72 | } |
| 73 | |
| 74 | void bcmolt_onu_tuning_appl_init(bcmolt_devid device_id) |
| 75 | { |
| 76 | bcmos_errno err; |
| 77 | |
| 78 | #ifdef ENABLE_LOG |
| 79 | char log_name[MAX_DEV_LOG_ID_NAME] = {}; |
| 80 | snprintf(log_name, sizeof(log_name) - 1, "user_appl_onu_tuning%u", device_id); |
| 81 | ot_context[device_id].log_id = bcm_dev_log_id_register(log_name, DEV_LOG_LEVEL_DEBUG, DEV_LOG_ID_TYPE_BOTH); |
| 82 | #endif |
| 83 | |
| 84 | err = bcmos_mutex_create(&ot_context[device_id].mutex, 0, NULL); |
| 85 | BUG_ON(err != BCM_ERR_OK); |
| 86 | |
| 87 | err = onu_tuning_init_task(device_id); |
| 88 | BUG_ON(err != BCM_ERR_OK); |
| 89 | |
| 90 | err = onu_tuning_init_module(device_id); |
| 91 | BUG_ON(err != BCM_ERR_OK); |
| 92 | |
| 93 | } |
| 94 | |
| 95 | bcmos_errno bcmolt_onu_tuning_appl_start(bcmolt_devid device_id) |
| 96 | { |
| 97 | bcmos_errno ret = BCM_ERR_OK; |
| 98 | |
| 99 | bcmos_mutex_lock(&ot_context[device_id].mutex); |
| 100 | |
| 101 | if (ot_context[device_id].is_running) |
| 102 | { |
| 103 | BCM_LOG(ERROR, ot_context[device_id].log_id, "ONU tuning application already running on device=%u\n", device_id); |
| 104 | ret = BCM_ERR_STATE; |
| 105 | goto exit; |
| 106 | } |
| 107 | |
| 108 | ot_context[device_id].is_running = BCMOS_TRUE; |
| 109 | ot_context[device_id].device = device_id; |
| 110 | |
| 111 | BCM_LOG(INFO, ot_context[device_id].log_id, "ONU tuning application started on device=%u\n", device_id); |
| 112 | ret = BCM_ERR_OK; |
| 113 | |
| 114 | exit: |
| 115 | bcmos_mutex_unlock(&ot_context[device_id].mutex); |
| 116 | return ret; |
| 117 | } |
| 118 | |
| 119 | bcmos_errno bcmolt_onu_tuning_appl_stop(bcmolt_devid device_id) |
| 120 | { |
| 121 | bcmos_errno ret; |
| 122 | |
| 123 | bcmos_mutex_lock(&ot_context[device_id].mutex); |
| 124 | |
| 125 | if (!ot_context[device_id].is_running) |
| 126 | { |
| 127 | ret = BCM_ERR_STATE; |
| 128 | goto exit; |
| 129 | } |
| 130 | |
| 131 | ot_context[device_id].is_running = BCMOS_FALSE; |
| 132 | bcmos_timer_stop(&ot_context[device_id].timer); |
| 133 | BCM_LOG(INFO, ot_context[device_id].log_id, "ONU tuning application stopped on device=%u\n", device_id); |
| 134 | ret = BCM_ERR_OK; |
| 135 | |
| 136 | exit: |
| 137 | bcmos_mutex_unlock(&ot_context[device_id].mutex); |
| 138 | return ret; |
| 139 | } |
| 140 | |
| 141 | bcmos_bool bcmolt_onu_tuning_appl_is_running(bcmolt_devid device_id) |
| 142 | { |
| 143 | bcmos_bool ret; |
| 144 | |
| 145 | bcmos_mutex_lock(&ot_context[device_id].mutex); |
| 146 | ret = ot_context[device_id].is_running; |
| 147 | bcmos_mutex_unlock(&ot_context[device_id].mutex); |
| 148 | |
| 149 | return ret; |
| 150 | } |
| 151 | |
| 152 | static bcmos_bool bcmolt_onu_tuning_is_interested(bcmolt_auto *ind) |
| 153 | { |
| 154 | switch (ind->hdr.obj_type) |
| 155 | { |
| 156 | case BCMOLT_OBJ_ID_XGPON_ONU: |
| 157 | switch (ind->hdr.subgroup) |
| 158 | { |
| 159 | case BCMOLT_XGPON_ONU_AUTO_ID_TUNING_RESPONSE: |
| 160 | return BCMOS_TRUE; |
| 161 | case BCMOLT_XGPON_ONU_AUTO_ID_ONU_TUNING_IN_COMPLETED: |
| 162 | return BCMOS_TRUE; |
| 163 | default: |
| 164 | break; |
| 165 | } |
| 166 | break; |
| 167 | default: |
| 168 | break; |
| 169 | } |
| 170 | |
| 171 | return BCMOS_FALSE; |
| 172 | } |
| 173 | |
| 174 | static void bcmolt_onu_tuning_ind_cb(bcmos_module_id module_id, bcmos_msg *os_msg) |
| 175 | { |
| 176 | ot_task_msg *msg = (ot_task_msg *)os_msg; |
| 177 | bcmolt_pon_ni pon_ni; |
| 178 | bcmolt_pon_onu_id onu_id; |
| 179 | bcmolt_auto *ind = msg->ind; |
| 180 | bcmos_errno rc; |
| 181 | |
| 182 | switch (msg->ind->hdr.obj_type) |
| 183 | { |
| 184 | case BCMOLT_OBJ_ID_XGPON_ONU: |
| 185 | switch (msg->ind->hdr.subgroup) |
| 186 | { |
| 187 | case BCMOLT_XGPON_ONU_AUTO_ID_TUNING_RESPONSE: |
| 188 | { |
| 189 | bcmolt_xgpon_onu_tuning_response *onu_tuning_response = (bcmolt_xgpon_onu_tuning_response *)ind; |
| 190 | onu_id = onu_tuning_response->key.onu_id; |
| 191 | pon_ni = onu_tuning_response->key.pon_ni; |
| 192 | |
| 193 | if (onu_tuning_response->data.ack == BCMOS_TRUE && onu_tuning_response->data.result == BCMOLT_RESULT_SUCCESS) |
| 194 | { |
| 195 | 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); |
| 196 | |
| 197 | /* start tuning in onu on target pon id */ |
| 198 | bcmolt_xgpon_onu_key key = { .pon_ni = ot_context[msg->device_id].onu_db[onu_id].target_pon_ni, .onu_id = onu_id }; |
| 199 | bcmolt_xgpon_onu_onu_tuning_in onu_tuning_in; |
| 200 | |
| 201 | BCMOLT_OPER_INIT(&onu_tuning_in, xgpon_onu, onu_tuning_in, key); |
| 202 | rc = bcmolt_oper_submit(msg->device_id, &onu_tuning_in.hdr); |
| 203 | if (rc != BCM_ERR_OK) |
| 204 | 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); |
| 205 | } |
| 206 | |
| 207 | break; |
| 208 | } |
| 209 | case BCMOLT_XGPON_ONU_AUTO_ID_ONU_TUNING_IN_COMPLETED: |
| 210 | { |
| 211 | bcmolt_xgpon_onu_onu_tuning_in_completed *onu_tuning_in_completed = (bcmolt_xgpon_onu_onu_tuning_in_completed *)ind; |
| 212 | onu_id = onu_tuning_in_completed->key.onu_id; |
| 213 | pon_ni = onu_tuning_in_completed->key.pon_ni; |
| 214 | if (onu_tuning_in_completed->data.result == BCMOLT_RESULT_SUCCESS) |
| 215 | { |
| 216 | 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); |
| 217 | |
| 218 | /* start tuning out onu on source pon id */ |
| 219 | bcmolt_xgpon_onu_key key = { .pon_ni = ot_context[msg->device_id].onu_db[onu_id].source_pon_ni, .onu_id = onu_id }; |
| 220 | bcmolt_xgpon_onu_onu_tuning_out onu_tuning_out; |
| 221 | |
| 222 | BCMOLT_OPER_INIT(&onu_tuning_out, xgpon_onu, onu_tuning_out, key); |
| 223 | 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); |
| 224 | 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); |
| 225 | BCMOLT_OPER_PROP_SET(&onu_tuning_out, xgpon_onu, onu_tuning_out, time_to_switch, 1000); |
| 226 | BCMOLT_OPER_PROP_SET(&onu_tuning_out, xgpon_onu, onu_tuning_out, rollback, BCMOS_FALSE); |
| 227 | BCMOLT_OPER_PROP_SET(&onu_tuning_out, xgpon_onu, onu_tuning_out, status, BCMOLT_STATUS_OFF); |
| 228 | rc = bcmolt_oper_submit(msg->device_id, &onu_tuning_out.hdr); |
| 229 | if (rc != BCM_ERR_OK) |
| 230 | 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); |
| 231 | } |
| 232 | break; |
| 233 | } |
| 234 | default: |
| 235 | break; |
| 236 | } |
| 237 | break; |
| 238 | default: |
| 239 | break; |
| 240 | } |
| 241 | |
| 242 | /* free the cloned indication since we're done processing it */ |
| 243 | bcmolt_msg_free(&msg->ind->hdr); |
| 244 | /* free the internal OS message handle */ |
| 245 | bcmos_free(os_msg); |
| 246 | } |
| 247 | |
| 248 | bcmos_errno bcmolt_onu_tuning_process_ind(bcmolt_devid device_id, bcmolt_auto *ind) |
| 249 | { |
| 250 | bcmos_errno err; |
| 251 | bcmolt_msg *ind_clone = NULL; |
| 252 | |
| 253 | /* if the application isn't running, don't listen to any indications */ |
| 254 | if (!bcmolt_onu_tuning_appl_is_running(device_id)) |
| 255 | return BCM_ERR_OK; |
| 256 | |
| 257 | /* check to see if we have a handler for this type of indication */ |
| 258 | if (!bcmolt_onu_tuning_is_interested(ind)) |
| 259 | return BCM_ERR_OK; |
| 260 | |
| 261 | /* clone the indication into newly-allocated memory so we can handle it after the original message has been freed */ |
| 262 | err = bcmolt_msg_clone(&ind_clone, &ind->hdr); |
| 263 | if (err != BCM_ERR_OK) |
| 264 | { |
| 265 | BCM_LOG(ERROR, ot_context[device_id].log_id, "Indication clone failed: %s\n", bcmos_strerror(err)); |
| 266 | return err; |
| 267 | } |
| 268 | |
| 269 | /* send the clone to the internal task's message queue */ |
| 270 | ot_task_msg *msg = bcmos_calloc(sizeof(*msg)); |
| 271 | if (msg == NULL) |
| 272 | { |
| 273 | BCM_LOG(ERROR, ot_context[device_id].log_id, "Message calloc failed: %s\n", bcmos_strerror(err)); |
| 274 | bcmolt_msg_free(ind_clone); |
| 275 | return BCM_ERR_NOMEM; |
| 276 | } |
| 277 | msg->os_msg.handler = bcmolt_onu_tuning_ind_cb; |
| 278 | msg->os_msg.release = bcmolt_os_msg_release_cb; |
| 279 | msg->device_id = device_id; |
| 280 | msg->ind = (bcmolt_auto *)ind_clone; |
| 281 | |
| 282 | err = bcmos_msg_send_to_module(TASK_PRIORITY_USER_APPL_ONU_TUNING + device_id, &msg->os_msg, 0); |
| 283 | if (err != BCM_ERR_OK) |
| 284 | { |
| 285 | BCM_LOG(ERROR, ot_context[device_id].log_id, "Message send failed: %s\n", bcmos_strerror(err)); |
| 286 | bcmolt_msg_free(ind_clone); |
| 287 | return err; |
| 288 | } |
| 289 | |
| 290 | return BCM_ERR_OK; |
| 291 | } |
| 292 | |
| 293 | 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) |
| 294 | { |
| 295 | bcmos_errno ret; |
| 296 | bcmos_mutex_lock(&ot_context[device_id].mutex); |
| 297 | |
| 298 | if (!ot_context[device_id].is_running) |
| 299 | { |
| 300 | ret = BCM_ERR_STATE; |
| 301 | goto exit; |
| 302 | } |
| 303 | ot_context[device_id].onu_db[onu_id].target_pon_ni = target_pon_ni; |
| 304 | ot_context[device_id].onu_db[onu_id].source_pon_ni = source_pon_ni; |
| 305 | ot_context[device_id].onu_db[onu_id].target_pon_id = target_pon_id; |
| 306 | ot_context[device_id].onu_db[onu_id].rollback = rollback; |
| 307 | ret = BCM_ERR_OK; |
| 308 | |
| 309 | exit: |
| 310 | bcmos_mutex_unlock(&ot_context[device_id].mutex); |
| 311 | return ret; |
| 312 | } |