/* * * hil_events_server.c * Description: * HIL events MRPC server driver * * * GPL LICENSE SUMMARY * * Copyright(c) 2016-2020 Intel Corporation. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * 2200 Mission College Blvd. * Santa Clara, CA 97052 */ #include #include #include #include #include #define MAX_NAME_SIZE 50 #define HILEVENTS_MRPC_ID MRPC_RESERVED_ID_HILEVENTS #define HILEVENTS_SERV_PROC(proc, func, arglen) \ MRPC_PROCINFO_ENTRY(proc, func, arglen, 0) #define HILEVENTS_SERV_PROC_INT(proc, func, arglen) \ MRPC_PROCINFO_ENTRY(proc, func, arglen, sizeof(int)) /*HIL events MRPC PROC id*/ enum { MRPC_HIL_INIT_PROC_ID = 0, MRPC_HIL_REMOTE_PROC_ID, MRPC_HIL_REMOTE_WITH_PARAMS_PROC_ID, MRPC_HIL_NUM_IDS }; typedef struct { AVALANCHE_PP_PID_t pp_pid; } hil_mrpc_pid_create_param_t; typedef struct { AVALANCHE_PP_PID_RANGE_t pid_range; } hil_mrpc_pid_range_param_t; typedef struct { Uint8 vpid_handle; PP_LIST_ID_e list_id; } hil_mrpc_flush_sessions_param_t; typedef struct { Uint32 time_gap_between_two_upstream_maps; } hil_mrpc_set_docsis_turbodox_timer_param_t; typedef struct { Uint32 event_id; union { hil_mrpc_pid_create_param_t pid_create; hil_mrpc_pid_range_param_t pid_range; hil_mrpc_flush_sessions_param_t flush_sessions; hil_mrpc_set_docsis_turbodox_timer_param_t set_docsis_turbodox_timer; HIL_QOS_CLASSIFIER_VOICE_PP_DEL_PARAM_t voice_session_delete; } args; } hil_remote_cmd_t; typedef struct { char name[MAX_NAME_SIZE]; struct mrpc_server * mrpc_serv; struct mrpc_procinfo hilevents_mrpc_procs[MRPC_HIL_NUM_IDS]; } hil_mrpc_info_t; static int mrpc_hil_init_proc(void *arg, ssize_t arglen, void *rep, ssize_t replen); static int mrpc_hil_remote_proc(void *arg, ssize_t arglen, void *rep, ssize_t replen); static int mrpc_hil_remote_with_params_proc(void *arg, ssize_t arglen, void *rep, ssize_t replen); static hil_mrpc_info_t mrpc = { .hilevents_mrpc_procs = { HILEVENTS_SERV_PROC(MRPC_HIL_INIT_PROC_ID, mrpc_hil_init_proc, 0), HILEVENTS_SERV_PROC(MRPC_HIL_REMOTE_PROC_ID, mrpc_hil_remote_proc, sizeof(unsigned int)), HILEVENTS_SERV_PROC_INT(MRPC_HIL_REMOTE_WITH_PARAMS_PROC_ID, mrpc_hil_remote_with_params_proc, sizeof(hil_remote_cmd_t)), } }; /**************************************************************************/ /*! \fn static int mrpc_hil_init_proc * (void *arg, ssize_t arglen, void *rep, ssize_t replen) ************************************************************************** * \brief prepare hil events server * \param[in] arg - Pointer to arguments buffer. * \param[in] arglen - Arguments length. * \param[out] rep - Pointer to reply buffer. * \param[out] replen - Reply length. * \return 0. **************************************************************************/ static int mrpc_hil_init_proc(void *arg, ssize_t arglen, void *rep, ssize_t replen) { printk ("HIL Core: %s invoked, remote profile on ARM activated \n", __func__); return 0; } /**************************************************************************/ /*! \fn static int mrpc_hil_remote_proc * (void *arg, ssize_t arglen, void *rep, ssize_t replen) ************************************************************************** * \brief serv remote hil events * \param[in] arg - Pointer to arguments buffer. * \param[in] arglen - Arguments length. * \param[out] rep - Pointer to reply buffer. * \param[out] replen - Reply length. * \return 0 for success, error code otherwise. **************************************************************************/ static int mrpc_hil_remote_proc(void *arg, ssize_t arglen, void *rep, ssize_t replen) { int ret = 0; unsigned int *p_arg = arg; Uint32 event = ntohl(*p_arg); /* printk ("HIL Core: %s invoked for event %d\n", __func__, event); */ ret = ti_hil_pp_event(event, NULL); if (ret) { pr_err("hil event handler failed for event %u, res=%d\n", event, ret); } return ret; } /**************************************************************************/ /*! \fn static int handle_pid_create_mrpc * (hil_mrpc_pid_create_param_t *mrpc_pid_param, int* hil_ret) ************************************************************************** * \brief sends the TI_PP_PID_CREATE event * \param[in] mrpc_pid_param - Pointer to mrpc arguments buffer. * \param[out] hil_ret - Pointer to reply buffer. * \return 0 for success, error code otherwise. **************************************************************************/ static int inline handle_pid_create_mrpc(hil_mrpc_pid_create_param_t *mrpc_pid_param, int* hil_ret) { int i, ret = 0; HIL_PID_CREATE_PARAM_t hil_param; hil_param.netdev = NULL; memcpy(&hil_param.pid, &mrpc_pid_param->pp_pid, sizeof(AVALANCHE_PP_PID_t)); hil_param.pid.dflt_host_q = ntohs(mrpc_pid_param->pp_pid.dflt_host_q); hil_param.pid.dflt_infra_q = ntohs(mrpc_pid_param->pp_pid.dflt_infra_q); hil_param.pid.dflt_dst_tag = ntohs(mrpc_pid_param->pp_pid.dflt_dst_tag); for (i = 0; i < ARRAY_SIZE(hil_param.pid.tx_pri_q_map); i++) hil_param.pid.tx_pri_q_map[i] = ntohs(mrpc_pid_param->pp_pid.tx_pri_q_map[i]); ret = ti_hil_pp_event(TI_PP_PID_CREATE, (void*) &hil_param); if (ret) { pr_err("hil event handler failed for TI_PP_PID_CREATE, res=%d\n", ret); } if (hil_ret) *hil_ret = htonl(hil_param.ret); return ret; } /**************************************************************************/ /*! \fn static int handle_pid_config_range_mrpc * (hil_mrpc_pid_range_param_t *mrpc_pid_range, int* hil_ret) ************************************************************************** * \brief sends the TI_PP_PID_CONFIG_RANGE event * \param[in] mrpc_pid_param - Pointer to mrpc arguments buffer. * \param[out] hil_ret - Pointer to reply buffer. * \return 0 for success, error code otherwise. **************************************************************************/ static int inline handle_pid_config_range_mrpc(hil_mrpc_pid_range_param_t *mrpc_pid_range, int* hil_ret) { int ret = 0; HIL_PID_RANGE_PARAM_t hil_param; memcpy(&hil_param.pid_range, &mrpc_pid_range->pid_range, sizeof(AVALANCHE_PP_PID_RANGE_t)); ret = ti_hil_pp_event(TI_PP_PID_CONFIG_RANGE, (void*) &hil_param); if (ret) { pr_err("hil event handler failed for TI_PP_PID_CONFIG_RANGE, res=%d\n", ret); } if (hil_ret) *hil_ret = htonl(hil_param.ret); return ret; } /*! \fn static int handle_flush_sessions_mrpc * (hil_mrpc_pid_range_param_t *mrpc_pid_range, int* hil_ret) ************************************************************************** * \brief sends the TI_PP_FLUSH_SESSIONS event * \param[in] mrpc_pid_param - Pointer to mrpc arguments buffer. * \param[out] hil_ret - Pointer to reply buffer. * \return 0 for success, error code otherwise. **************************************************************************/ static int inline handle_flush_sessions_mrpc(hil_mrpc_flush_sessions_param_t *mrpc_flush_sessions, int* hil_ret) { int ret = 0; HIL_FLUSH_SESSIONS_PARAM_t hil_param; hil_param.list_id = ntohl(mrpc_flush_sessions->list_id); hil_param.vpid_handle = mrpc_flush_sessions->vpid_handle; ret = ti_hil_pp_event(TI_PP_FLUSH_SESSIONS, (void*) &hil_param); if (ret) { pr_err("hil event handler failed for TI_PP_PID_CONFIG_RANGE, res=%d\n", ret); } if (hil_ret) *hil_ret = htonl(hil_param.ret); return ret; } static int inline handle_docsis_set_turbodox_timer_mrpc(hil_mrpc_set_docsis_turbodox_timer_param_t *mrpc_set_docsis_turbodox_timer, int* hil_ret) { int ret = 0; HIL_SET_DOCSIS_TURBODOX_TIMER_PARAM_t hil_param; hil_param.time_gap_between_two_upstream_maps = ntohl(mrpc_set_docsis_turbodox_timer->time_gap_between_two_upstream_maps); ret = ti_hil_pp_event(TI_DOCSIS_SET_TURBODOX_TIMER, (void*) &hil_param); if (ret) { pr_err("hil event handler failed for TI_DOCSIS_SET_TURBODOX_TIMER, res=%d\n", ret); } if (hil_ret) *hil_ret = htonl(hil_param.ret); return ret; } /*! \fn static int inline handle_docsis_voice_sessions_del_mrpc * (HIL_QOS_CLASSIFIER_VOICE_PP_DEL_PARAM_t *mrpc_voice_sessions_del, int* hil_ret) ************************************************************************** * \brief sends the TI_DOCSIS_VOICE_SESSIONS_DEL event after convertion of MRPC structure into hil structure * \param[in] hil_mrpc_QosClassifierVoicePpDel_t - Pointer to mrpc arguments buffer. * \param[out] hil_ret - Pointer to reply buffer. * \return 0 for success, error code otherwise. **************************************************************************/ static int inline handle_docsis_voice_sessions_del_mrpc(HIL_QOS_CLASSIFIER_VOICE_PP_DEL_PARAM_t *mrpc_voice_sessions_del, int* hil_ret) { int ret = 0, ip_idx; HIL_QOS_CLASSIFIER_VOICE_PP_DEL_PARAM_t hil_param; hil_param.voice_session_delete.ip_version = ntohs(mrpc_voice_sessions_del->voice_session_delete.ip_version); if ((hil_param.voice_session_delete.ip_version >= PP_LOOKUP_FIELD_L3_TYPE_IPv4) && (hil_param.voice_session_delete.ip_version <= PP_LOOKUP_FIELD_L3_TYPE_FFFF)) { /* deleting specific sessions according the classifier created/changed*/ hil_param.voice_session_delete.srcPortStart = ntohs(mrpc_voice_sessions_del->voice_session_delete.srcPortStart); hil_param.voice_session_delete.srcPortEnd = ntohs(mrpc_voice_sessions_del->voice_session_delete.srcPortEnd); hil_param.voice_session_delete.dstPortStart = ntohs(mrpc_voice_sessions_del->voice_session_delete.dstPortStart); hil_param.voice_session_delete.dstPortEnd = ntohs(mrpc_voice_sessions_del->voice_session_delete.dstPortEnd); /* no need to handle IPv4 since TI_HIL_IP_PARAM_t is Union structure and IPv4 is presented by the first word of IPv6*/ for (ip_idx = 0; ip_idx < TI_HIL_IPV6_ADDRESS_SIZE; ip_idx++) { hil_param.voice_session_delete.source_ip.v6[ip_idx] = mrpc_voice_sessions_del->voice_session_delete.source_ip.v6[ip_idx]; hil_param.voice_session_delete.destination_ip.v6[ip_idx] = mrpc_voice_sessions_del->voice_session_delete.destination_ip.v6[ip_idx]; } ret = ti_hil_pp_event(TI_DOCSIS_VOICE_SESSIONS_DEL, (void *)&hil_param); } else { /* deleting entire voice call sessions */ ret = ti_hil_pp_event(TI_DOCSIS_VOICE_SESSIONS_DEL, NULL); hil_param.ret = PP_RC_SUCCESS; } if (ret) { pr_err("hil event handler failed for TI_DOCSIS_VOICE_SESSIONS_DEL, res=%d\n", ret); } if (hil_ret) *hil_ret = htonl(hil_param.ret); return ret; } /**************************************************************************/ /*! \fn static int mrpc_hil_remote_with_params_proc * (void *arg, ssize_t arglen, void *rep, ssize_t replen) ************************************************************************** * \brief serv remote hil events * \param[in] arg - Pointer to arguments buffer. * \param[in] arglen - Arguments length. * \param[out] rep - Pointer to reply buffer. * \param[out] replen - Reply length. * \return 0 for success, error code otherwise. **************************************************************************/ static int mrpc_hil_remote_with_params_proc(void *arg, ssize_t arglen, void *rep, ssize_t replen) { int ret = -1; hil_remote_cmd_t *hil_remote_cmd = arg; Uint32 event_id = ntohl(hil_remote_cmd->event_id); printk ("HIL Core: %s invoked for event %d\n", __func__, event_id); if (rep && (replen != sizeof(int))) { pr_err("%s:%d Error: Expected reply len %u but received %u\n", __FUNCTION__, __LINE__, sizeof(int), replen); return ret; } switch(event_id) { case TI_PP_PID_CREATE: ret = handle_pid_create_mrpc(&hil_remote_cmd->args.pid_create, (int*)rep); break; case TI_PP_PID_CONFIG_RANGE: ret = handle_pid_config_range_mrpc(&hil_remote_cmd->args.pid_range, (int*)rep); break; case TI_PP_FLUSH_SESSIONS: ret = handle_flush_sessions_mrpc(&hil_remote_cmd->args.flush_sessions, (int*)rep); break; case TI_DOCSIS_SET_TURBODOX_TIMER: ret = handle_docsis_set_turbodox_timer_mrpc(&hil_remote_cmd->args.set_docsis_turbodox_timer, (int*)rep); break; case TI_DOCSIS_VOICE_SESSIONS_DEL: ret = handle_docsis_voice_sessions_del_mrpc(&hil_remote_cmd->args.voice_session_delete, (int *)rep); break; default: pr_err("%s:%d Error: Cannot handle hil mrpc %u\n", __FUNCTION__, __LINE__, event_id); break; } return ret; } /**************************************************************************/ /*! \fn static int hilevents_server_probe(struct platform_device*) ************************************************************************** * \brief Probe function. * \param[in] pdev - Pointer to struct platform device * \param[out] None * \0 for success, error code otherwise. **************************************************************************/ static int hilevents_server_probe(struct platform_device *pdev) { int ret = 0; snprintf(mrpc.name, MAX_NAME_SIZE, "HIL events MRPC"); mrpc.mrpc_serv = mrpc_server_register( HILEVENTS_MRPC_ID, mrpc.name, mrpc.hilevents_mrpc_procs, ARRAY_SIZE(mrpc.hilevents_mrpc_procs) ); if (!mrpc.mrpc_serv) { pr_err("failed to register %s server\n", mrpc.name); ret = -ENODEV; } return ret; } /**************************************************************************/ /*! \fn static int hilevents_server_remove(struct platform_device*) ************************************************************************** * \brief Probe function. * \param[in] pdev - Pointer to struct platform device * \param[out] None * \0 for success, error code otherwise. **************************************************************************/ static int hilevents_server_remove(struct platform_device *pdev) { int ret; ret = mrpc_server_unregister(mrpc.mrpc_serv); return ret; } static struct platform_driver hilevents_server_driver = { .driver = { .name = "hilevents_server", }, .probe = hilevents_server_probe, .remove = hilevents_server_remove, }; static struct platform_device *hilevents_server_device; /**************************************************************************/ /*! \fn static int __init hilevents_server_init(void) ************************************************************************** * \brief Init function. * \param[in] None * \param[out] None * \0 for success, error code otherwise. **************************************************************************/ static int __init hilevents_server_init(void) { int ret; ret = platform_driver_register(&hilevents_server_driver); if (ret < 0) { pr_err("Failed to register hilevents platform driver: %d\n", ret); return ret; } pr_debug("hil events server platform driver is registered"); hilevents_server_device = platform_device_register_simple("hilevents_server", -1, NULL, 0); if (IS_ERR(hilevents_server_device)) { pr_err("Failed to register hilevents platform device\n"); platform_driver_unregister(&hilevents_server_driver); return PTR_ERR(hilevents_server_device); } dev_info(&hilevents_server_device->dev, "platform device is registered\n"); return 0; } /**************************************************************************/ /*! \fn static void __exit hilevents_server_exit(void) ************************************************************************** * \brief Exit function. * \param[in] None * \param[out] None **************************************************************************/ static void __exit hilevents_server_exit(void) { platform_device_unregister(hilevents_server_device); platform_driver_unregister(&hilevents_server_driver); } module_init(hilevents_server_init); module_exit(hilevents_server_exit); MODULE_AUTHOR("Intel Corporation"); MODULE_DESCRIPTION("HIL events mrpc server"); MODULE_LICENSE("GPL"); MODULE_VERSION("1.0");