/*--------------------------------------------------------------------------- * File Name: aep_host_ipc.c *---------------------------------------------------------------------------- */ /* This file is provided under a dual BSD/GPLv2 license. When using or redistributing this file, you may do so under either license. GPL LICENSE SUMMARY Copyright(c) 2007-2012 Intel Corporation. All rights reserved. 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: */ /** This file defines wrapper functions to interact with the IPC. * */ #include "aep_core.h" #include "aep_host_ipc.h" #include "aep_host_ipc_defs.h" #include "aep_types.h" /* This global variable stores the host IPC handle. */ host_ipc_handler _aep_host_ipc_handle; static void host_tasklet_finish(unsigned long param) { host_ipc_handler *host; host = (host_ipc_handler *) param; del_timer(&host->timer); host->error = AEP_IPC_RET_SUCCESS; complete(host->done_data); } static void aep_ipc_timeout_timer(unsigned long data) { host_ipc_handler *aep_host; aep_host = (host_ipc_handler *) data; if (aep_host->ipc_req) { printk(KERN_ERR "%x: Timeout waiting for hardware " "interrupt.\n", aep_host->ipc_req); aep_host->error = -ETIMEDOUT; tasklet_schedule(aep_host->schedule_tasklet); } } /** * Initialize IPC communication * * Function: aep_host_ipc_initialize * Description: * This is used for initialize IPC comunication parameter with AEP * Parameters: * */ aep_result_t aep_host_ipc_initialize(struct tasklet_struct *schedule_tasklet, void *base_addr) { uint32_t aep_enabled; aep_result_t result = AEP_SUCCESS; _aep_host_ipc_handle.dev_base = base_addr; /* Initialize synchronous message semaphore */ sema_init(&_aep_host_ipc_handle.sync_request_sema, 1); sema_init(&_aep_host_ipc_handle.sync_reponse_sema, 1); sema_init(&_aep_host_ipc_handle.sync_msg_sema, 1); aep_enabled = readl(_aep_host_ipc_handle.dev_base + AEP_PV_CONTROL_REG); if (!(aep_enabled & AEP_ENABLED)) { result = AEP_ERROR_NOT_ENABLED; goto exit; } tasklet_init(schedule_tasklet, host_tasklet_finish, (unsigned long) &_aep_host_ipc_handle); _aep_host_ipc_handle.schedule_tasklet = schedule_tasklet; setup_timer(&_aep_host_ipc_handle.timer, aep_ipc_timeout_timer, (unsigned long) &_aep_host_ipc_handle); exit: return result; } /* * * Function: aep_host_ipc_deinitialize * */ aep_result_t aep_host_ipc_deinitialize() { if (0 != _aep_host_ipc_handle.dev_base) _aep_host_ipc_handle.dev_base = 0; return AEP_SUCCESS; } /* Function: aep_host_send_ipc will send IPC cmd request to AEP and wait for task to be done by AEP */ aep_result_t aep_host_send_ipc(aep_fw_cmd_t ipc_cmd, aep_ipc_sizes_t io_sizes, ipl_t *ipl, opl_t *opl) { aep_result_t rc = AEP_IPC_RET_ERROR; if (AEP_IPC_RET_SUCCESS == hostIPC_SendCmd(&_aep_host_ipc_handle, ipc_cmd, io_sizes, ipl, opl)) rc = AEP_SUCCESS; return rc; } aep_result_t aep_host_send_ipc_wq(aep_fw_cmd_t fw_cmd_ipc, ipl_t *ipl, opl_t *opl) { aep_work_t *ipc_work; int ret; aep_result_t wq_ret_val = AEP_ERROR_OPERATION_FAILED; ipc_work = kmalloc(sizeof(aep_work_t), GFP_ATOMIC); if (ipc_work) { ipc_work->aep_io_addr = NULL; ipc_work->ipc_cmd = fw_cmd_ipc; ipc_work->ipl = ipl; ipc_work->hipc = &_aep_host_ipc_handle; INIT_WORK((struct work_struct *)ipc_work, aep_workq_func); ret = queue_work(aep_globals.aep_work_queue, (struct work_struct *)ipc_work); if (ret) wq_ret_val = AEP_SUCCESS; else printk("\nFailed while adding to queue\n"); } return wq_ret_val; } /* Function: aep_host_send_response will send IPC response to AEP for a request sent by AEP */ aep_result_t aep_host_send_response(aep_fw_cmd_t ipc_cmd, aep_ipc_sizes_t io_sizes, ipl_t *ipl) { aep_result_t rc = AEP_IPC_RET_ERROR; if (AEP_IPC_RET_SUCCESS == hostIPC_SendResponse(&_aep_host_ipc_handle, ipc_cmd, io_sizes, ipl)) rc = AEP_SUCCESS; return rc; } aep_result_t aep_host_read_ipc_msg(void *opl, uint32_t offset, uint32_t opl_size) { HostIPC_ReadSynchronousResponse(&_aep_host_ipc_handle, opl, offset, opl_size); return AEP_SUCCESS; } aep_result_t aep_host_send_suspend_to_fw() { aep_result_t rc = AEP_IPC_RET_ERROR; return rc; }