/**************************************************************************** * * The MIT License (MIT) * * Copyright (c) 2020 VeriSilicon Holdings Co., Ltd. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * ***************************************************************************** * * The GPL License (GPL) * * Copyright (c) 2020 VeriSilicon Holdings Co., Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * 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; * ***************************************************************************** * * Note: This software is released under dual MIT and GPL licenses. A * recipient may use this file under the terms of either the MIT license or * GPL License. If you wish to use only one license not the other, you can * indicate your decision by deleting one of the above license notices in your * version of this file. * *****************************************************************************/ #ifdef __KERNEL__ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #else #include #include #include #endif #include "isp_irq_queue.h" #include "isp_ioctl.h" //enqueue int isp_irq_enqueue(isp_mis_t *new,isp_mis_t* head) { #ifdef __KERNEL__ isp_mis_t* new_node = (isp_mis_t*)kmalloc(sizeof(isp_mis_t), GFP_KERNEL); //create new node if (new == NULL || head == NULL) { //isp_info("%s: input wrong parameter\n", __func__); return -1; } new_node->val = new->val; new_node->irq_src = new->irq_src; /*isp_info("%s: new_node %px irq_src %d", __func__, new_node, new->irq_src);*/ INIT_LIST_HEAD(&new_node->list); list_add_tail(&new_node->list, &head->list); //append to tail #endif return 0; } //dequeue && release memory int isp_irq_dequeue(isp_mis_t* data, isp_mis_t* head) { #ifdef __KERNEL__ isp_mis_t* entry; if (data == NULL || head == NULL) { //isp_info("%s: input wrong parameter\n", __func__); return -1; } if (list_empty(&head->list)) { //isp_info("%s: There is no node\n", __func__); return -1; } entry = list_first_entry(&head->list, isp_mis_t, list); /*isp_info("%s: entry %px irq_src %d", __func__, entry, entry->irq_src);*/ data->val = entry->val; data->irq_src = entry->irq_src; list_del_init(&entry->list); kfree(entry); #endif return 0; } bool isp_irq_is_queue_empty( isp_mis_t* head) { #ifdef __KERNEL__ return list_empty(&head->list); #endif return 0; } int isp_irq_create_circle_queue(isp_mis_list_t* pCList, int number) { #ifdef __KERNEL__ int i; isp_mis_t* pMisNode; if (pCList == NULL || number <= 0) { isp_info("%s: create circle queue failed\n", __func__); return -1; } if (pCList->pHead == NULL) { pCList->pHead = (isp_mis_t*)kmalloc(sizeof(isp_mis_t), GFP_KERNEL); INIT_LIST_HEAD(&pCList->pHead->list); pCList->pRead = pCList->pHead; pCList->pWrite = pCList->pHead; } isp_info("%s:pHead %px\n", __func__, pCList->pHead); for (i = 0; i < number - 1; i++) { pMisNode = (isp_mis_t*)kmalloc(sizeof(isp_mis_t), GFP_KERNEL); INIT_LIST_HEAD(&pMisNode->list); list_add_tail(&pMisNode->list, &pCList->pHead->list); isp_info("%s:pMisNode %px\n", __func__, pMisNode); } #endif return 0; } int isp_irq_destroy_circle_queue(isp_mis_list_t* pCList) { #ifdef __KERNEL__ isp_mis_t* pMisNode; if ((pCList == NULL) || (pCList->pHead == NULL) ) { isp_info("%s: destroy circle queue failed. pClist %px\n", __func__, pCList); return -1; } while(!list_empty(&pCList->pHead->list)) { pMisNode = list_first_entry(&pCList->pHead->list, isp_mis_t, list); isp_info("%s:pMisNode %px\n", __func__, pMisNode); list_del(&pMisNode->list); kfree(pMisNode); pMisNode = NULL; } isp_info("%s:pHead %px\n", __func__, pCList->pHead); kfree(pCList->pHead); pCList->pHead = NULL; pCList->pRead = NULL; pCList->pWrite = NULL; #endif return 0; } int isp_irq_read_circle_queue(isp_mis_t* data, isp_mis_list_t* pCList) { #ifdef __KERNEL__ //isp_mis_t* pReadEntry; if (pCList == NULL) { isp_info("%s: can not read circle queue\n", __func__); return -1; } if (pCList->pRead == pCList->pWrite) { /*isp_info("%s: There is no irq mis data\n", __func__);*/ return -1; } data->val = pCList->pRead->val; data->irq_src = pCList->pRead->irq_src; /*isp_info("%s: entry %px irq_src %d, msi %08x\n", __func__, pCList->pRead, data->irq_src, data->val);*/ /*Get the next entry that link with read entry list*/ /*Update read pointer to next entry*/ pCList->pRead = list_first_entry(&pCList->pRead->list, isp_mis_t, list); //pCList->pRead = pReadEntry; #endif return 0; } int isp_irq_write_circle_queue(isp_mis_t* data, isp_mis_list_t* pCList) { #ifdef __KERNEL__ isp_mis_t* pWriteEntry; if (pCList == NULL) { isp_info("%s: can not read circle queue\n", __func__); return -1; } pCList->pWrite->val = data->val; pCList->pWrite->irq_src = data->irq_src; /*isp_info("%s: entry %px irq_src %d, msi %08x\n", __func__, pCList->pWrite, data->irq_src, data->val);*/ /*get the next write entry pointer that link with the write entry list*/ pWriteEntry = list_first_entry(&pCList->pWrite->list, isp_mis_t, list); /*Update write pointer to point next entry*/ pCList->pWrite = pWriteEntry; #endif return 0; } int isp_irq_reset_circle_queue(isp_mis_list_t* pCList) { #ifdef __KERNEL__ if (pCList == NULL) { isp_err("%s: can not reset circle queue\n", __func__); return -1; } pCList->pRead = pCList->pHead; pCList->pWrite = pCList->pHead; #endif return 0; }