From ff3d9c3c90c6edcb975c390db3671713899c2842 Mon Sep 17 00:00:00 2001 From: Mark Allyn Date: Wed, 28 Dec 2011 17:37:59 +0000 Subject: staging: sep: SEP update This is basically a rewrite so there isn't a nice easy to present way of providing this as a patch series. This patch is a pull of Mark's new driver into the upstream staging area. On top of that are a series of patches by Andy Shevchenko to make it build on the current tree, fix a few things and even get it passed sparse. The new driver supports the kernel crypto layer, passes the coding style checks, passes human taste checks and has proper kernel-doc formatted comments. I've then folded back in some later fixes it was missing that got applied to to the kernel tree. This should be ready for more serious review with a view to migration from the staging tree shortly. Signed-off-by: Mark Allyn [Forward port and some bug fixing] Signed-off-by: Andy Shevchenko [Fold and tweaks for 3.2] Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/sep/Kconfig b/drivers/staging/sep/Kconfig index 92bf166..185b676 100644 --- a/drivers/staging/sep/Kconfig +++ b/drivers/staging/sep/Kconfig @@ -3,7 +3,8 @@ config DX_SEP depends on PCI help Discretix SEP driver; used for the security processor subsystem - on bard the Intel Mobile Internet Device. + on board the Intel Mobile Internet Device and adds SEP availability + to the kernel crypto infrastructure The driver's name is sep_driver. diff --git a/drivers/staging/sep/Makefile b/drivers/staging/sep/Makefile index 628d5f9..e48a795 100644 --- a/drivers/staging/sep/Makefile +++ b/drivers/staging/sep/Makefile @@ -1,2 +1,3 @@ -obj-$(CONFIG_DX_SEP) := sep_driver.o - +ccflags-y += -I$(srctree)/$(src) +obj-$(CONFIG_DX_SEP) += sep_driver.o +sep_driver-objs := sep_crypto.o sep_main.o diff --git a/drivers/staging/sep/TODO b/drivers/staging/sep/TODO index 8f3b878..3524d0c 100644 --- a/drivers/staging/sep/TODO +++ b/drivers/staging/sep/TODO @@ -1,4 +1,3 @@ Todo's so far (from Alan Cox) -- Check whether it can be plugged into any of the kernel crypto API - interfaces - Crypto API 'glue' is still not ready to submit -- Clean up un-needed debug prints - Started to work on this +- Clean up unused ioctls +- Clean up unused fields in ioctl structures diff --git a/drivers/staging/sep/sep_crypto.c b/drivers/staging/sep/sep_crypto.c new file mode 100644 index 0000000..a6b0f83 --- /dev/null +++ b/drivers/staging/sep/sep_crypto.c @@ -0,0 +1,3768 @@ +/* + * + * sep_crypto.c - Crypto interface structures + * + * Copyright(c) 2009-2011 Intel Corporation. All rights reserved. + * Contributions(c) 2009-2010 Discretix. All rights reserved. + * + * 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; version 2 of the License. + * + * 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., 59 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * CONTACTS: + * + * Mark Allyn mark.a.allyn@intel.com + * Jayant Mangalampalli jayant.mangalampalli@intel.com + * + * CHANGES: + * + * 2009.06.26 Initial publish + * 2010.09.14 Upgrade to Medfield + * 2011.02.22 Enable Kernel Crypto + * + */ + +/* #define DEBUG */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "sep_driver_hw_defs.h" +#include "sep_driver_config.h" +#include "sep_driver_api.h" +#include "sep_dev.h" +#include "sep_crypto.h" + +/* Globals for queuing */ +static spinlock_t queue_lock; +static struct crypto_queue sep_queue; + +/* Declare of dequeuer */ +static void sep_dequeuer(void *data); + +/* TESTING */ +/** + * crypto_sep_dump_message - dump the message that is pending + * @sep: SEP device + * This will only print dump if DEBUG is set; it does + * follow kernel debug print enabling + */ +static void crypto_sep_dump_message(struct sep_system_ctx *sctx) +{ +#if 0 + u32 *p; + u32 *i; + int count; + + p = sctx->sep_used->shared_addr; + i = (u32 *)sctx->msg; + for (count = 0; count < 40 * 4; count += 4) + dev_dbg(&sctx->sep_used->pdev->dev, + "[PID%d] Word %d of the message is %x (local)%x\n", + current->pid, count/4, *p++, *i++); +#endif +} + +/** + * sep_do_callback + * @work: pointer to work_struct + * This is what is called by the queue; it is generic so that it + * can be used by any type of operation as each different callback + * function can use the data parameter in its own way + */ +static void sep_do_callback(struct work_struct *work) +{ + struct sep_work_struct *sep_work = container_of(work, + struct sep_work_struct, work); + if (sep_work != NULL) { + (sep_work->callback)(sep_work->data); + kfree(sep_work); + } else { + pr_debug("sep crypto: do callback - NULL container\n"); + } +} + +/** + * sep_submit_work + * @work_queue: pointer to struct_workqueue + * @funct: pointer to function to execute + * @data: pointer to data; function will know + * how to use it + * This is a generic API to submit something to + * the queue. The callback function will depend + * on what operation is to be done + */ +static int sep_submit_work(struct workqueue_struct *work_queue, + void(*funct)(void *), + void *data) +{ + struct sep_work_struct *sep_work; + int result; + + sep_work = kmalloc(sizeof(struct sep_work_struct), GFP_ATOMIC); + + if (sep_work == NULL) { + pr_debug("sep crypto: cant allocate work structure\n"); + return -ENOMEM; + } + + sep_work->callback = funct; + sep_work->data = data; + INIT_WORK(&sep_work->work, sep_do_callback); + result = queue_work(work_queue, &sep_work->work); + if (!result) { + pr_debug("sep_crypto: queue_work failed\n"); + return -EINVAL; + } + return 0; +} + +/** + * sep_alloc_sg_buf - + * @sep: pointer to struct sep_device + * @size: total size of area + * @block_size: minimum size of chunks + * each page is minimum or modulo this size + * @returns: pointer to struct scatterlist for new + * buffer + **/ +static struct scatterlist *sep_alloc_sg_buf( + struct sep_device *sep, + size_t size, + size_t block_size) +{ + u32 nbr_pages; + u32 ct1; + void *buf; + size_t current_size; + size_t real_page_size; + + struct scatterlist *sg, *sg_temp; + + if (size == 0) + return NULL; + + dev_dbg(&sep->pdev->dev, "sep alloc sg buf\n"); + + current_size = 0; + nbr_pages = 0; + real_page_size = PAGE_SIZE - (PAGE_SIZE % block_size); + /** + * The size of each page must be modulo of the operation + * block size; increment by the modified page size until + * the total size is reached, then you have the number of + * pages + */ + while (current_size < size) { + current_size += real_page_size; + nbr_pages += 1; + } + + sg = kmalloc((sizeof(struct scatterlist) * nbr_pages), GFP_ATOMIC); + if (!sg) { + dev_warn(&sep->pdev->dev, "Cannot allocate page for new sg\n"); + return NULL; + } + + sg_init_table(sg, nbr_pages); + + current_size = 0; + sg_temp = sg; + for (ct1 = 0; ct1 < nbr_pages; ct1 += 1) { + buf = (void *)get_zeroed_page(GFP_ATOMIC); + if (!buf) { + dev_warn(&sep->pdev->dev, + "Cannot allocate page for new buffer\n"); + kfree(sg); + return NULL; + } + + sg_set_buf(sg_temp, buf, real_page_size); + if ((size - current_size) > real_page_size) { + sg_temp->length = real_page_size; + current_size += real_page_size; + } else { + sg_temp->length = (size - current_size); + current_size = size; + } + sg_temp = sg_next(sg); + } + return sg; +} + +/** + * sep_free_sg_buf - + * @sg: pointer to struct scatterlist; points to area to free + */ +static void sep_free_sg_buf(struct scatterlist *sg) +{ + struct scatterlist *sg_temp = sg; + while (sg_temp) { + free_page((unsigned long)sg_virt(sg_temp)); + sg_temp = sg_next(sg_temp); + } + kfree(sg); +} + +/** + * sep_copy_sg - + * @sep: pointer to struct sep_device + * @sg_src: pointer to struct scatterlist for source + * @sg_dst: pointer to struct scatterlist for destination + * @size: size (in bytes) of data to copy + * + * Copy data from one scatterlist to another; both must + * be the same size + */ +static void sep_copy_sg( + struct sep_device *sep, + struct scatterlist *sg_src, + struct scatterlist *sg_dst, + size_t size) +{ + u32 seg_size; + u32 in_offset, out_offset; + + u32 count = 0; + struct scatterlist *sg_src_tmp = sg_src; + struct scatterlist *sg_dst_tmp = sg_dst; + in_offset = 0; + out_offset = 0; + + dev_dbg(&sep->pdev->dev, "sep copy sg\n"); + + if ((sg_src == NULL) || (sg_dst == NULL) || (size == 0)) + return; + + dev_dbg(&sep->pdev->dev, "sep copy sg not null\n"); + + while (count < size) { + if ((sg_src_tmp->length - in_offset) > + (sg_dst_tmp->length - out_offset)) + seg_size = sg_dst_tmp->length - out_offset; + else + seg_size = sg_src_tmp->length - in_offset; + + if (seg_size > (size - count)) + seg_size = (size = count); + + memcpy(sg_virt(sg_dst_tmp) + out_offset, + sg_virt(sg_src_tmp) + in_offset, + seg_size); + + in_offset += seg_size; + out_offset += seg_size; + count += seg_size; + + if (in_offset >= sg_src_tmp->length) { + sg_src_tmp = sg_next(sg_src_tmp); + in_offset = 0; + } + + if (out_offset >= sg_dst_tmp->length) { + sg_dst_tmp = sg_next(sg_dst_tmp); + out_offset = 0; + } + } +} + +/** + * sep_oddball_pages - + * @sep: pointer to struct sep_device + * @sg: pointer to struct scatterlist - buffer to check + * @size: total data size + * @blocksize: minimum block size; must be multiples of this size + * @to_copy: 1 means do copy, 0 means do not copy + * @new_sg: pointer to location to put pointer to new sg area + * @returns: 1 if new scatterlist is needed; 0 if not needed; + * error value if operation failed + * + * The SEP device requires all pages to be multiples of the + * minimum block size appropriate for the operation + * This function check all pages; if any are oddball sizes + * (not multiple of block sizes), it creates a new scatterlist. + * If the to_copy parameter is set to 1, then a scatter list + * copy is performed. The pointer to the new scatterlist is + * put into the address supplied by the new_sg parameter; if + * no new scatterlist is needed, then a NULL is put into + * the location at new_sg. + * + */ +static int sep_oddball_pages( + struct sep_device *sep, + struct scatterlist *sg, + size_t data_size, + u32 block_size, + struct scatterlist **new_sg, + u32 do_copy) +{ + struct scatterlist *sg_temp; + u32 flag; + u32 nbr_pages, page_count; + + dev_dbg(&sep->pdev->dev, "sep oddball\n"); + if ((sg == NULL) || (data_size == 0) || (data_size < block_size)) + return 0; + + dev_dbg(&sep->pdev->dev, "sep oddball not null\n"); + flag = 0; + nbr_pages = 0; + page_count = 0; + sg_temp = sg; + + while (sg_temp) { + nbr_pages += 1; + sg_temp = sg_next(sg_temp); + } + + sg_temp = sg; + while ((sg_temp) && (flag == 0)) { + page_count += 1; + if (sg_temp->length % block_size) + flag = 1; + else + sg_temp = sg_next(sg_temp); + } + + /* Do not process if last (or only) page is oddball */ + if (nbr_pages == page_count) + flag = 0; + + if (flag) { + dev_dbg(&sep->pdev->dev, "sep oddball processing\n"); + *new_sg = sep_alloc_sg_buf(sep, data_size, block_size); + if (*new_sg == NULL) { + dev_warn(&sep->pdev->dev, "cannot allocate new sg\n"); + return -ENOMEM; + } + + if (do_copy) + sep_copy_sg(sep, sg, *new_sg, data_size); + + return 1; + } else { + return 0; + } +} + +/** + * sep_copy_offset_sg - + * @sep: pointer to struct sep_device; + * @sg: pointer to struct scatterlist + * @offset: offset into scatterlist memory + * @dst: place to put data + * @len: length of data + * @returns: number of bytes copies + * + * This copies data from scatterlist buffer + * offset from beginning - it is needed for + * handling tail data in hash + */ +static size_t sep_copy_offset_sg( + struct sep_device *sep, + struct scatterlist *sg, + u32 offset, + void *dst, + u32 len) +{ + size_t page_start; + size_t page_end; + size_t offset_within_page; + size_t length_within_page; + size_t length_remaining; + size_t current_offset; + + /* Find which page is beginning of segment */ + page_start = 0; + page_end = sg->length; + while ((sg) && (offset > page_end)) { + page_start += sg->length; + sg = sg_next(sg); + if (sg) + page_end += sg->length; + } + + if (sg == NULL) + return -ENOMEM; + + offset_within_page = offset - page_start; + if ((sg->length - offset_within_page) >= len) { + /* All within this page */ + memcpy(dst, sg_virt(sg) + offset_within_page, len); + return len; + } else { + /* Scattered multiple pages */ + current_offset = 0; + length_remaining = len; + while ((sg) && (current_offset < len)) { + length_within_page = sg->length - offset_within_page; + if (length_within_page >= length_remaining) { + memcpy(dst+current_offset, + sg_virt(sg) + offset_within_page, + length_remaining); + length_remaining = 0; + current_offset = len; + } else { + memcpy(dst+current_offset, + sg_virt(sg) + offset_within_page, + length_within_page); + length_remaining -= length_within_page; + current_offset += length_within_page; + offset_within_page = 0; + sg = sg_next(sg); + } + } + + if (sg == NULL) + return -ENOMEM; + } + return len; +} + +/** + * partial_overlap - + * @src_ptr: source pointer + * @dst_ptr: destination pointer + * @nbytes: number of bytes + * @returns: 0 for success; -1 for failure + * We cannot have any partial overlap. Total overlap + * where src is the same as dst is okay + */ +static int partial_overlap(void *src_ptr, void *dst_ptr, u32 nbytes) +{ + /* Check for partial overlap */ + if (src_ptr != dst_ptr) { + if (src_ptr < dst_ptr) { + if ((src_ptr + nbytes) > dst_ptr) + return -EINVAL; + } else { + if ((dst_ptr + nbytes) > src_ptr) + return -EINVAL; + } + } + + return 0; +} + +/* Debug - prints only if DEBUG is defined; follows kernel debug model */ +static void sep_dump(struct sep_device *sep, char *stg, void *start, int len) +{ +#if 0 + int ct1; + u8 *ptt; + + dev_dbg(&sep->pdev->dev, + "Dump of %s starting at %08lx for %08x bytes\n", + stg, (unsigned long)start, len); + for (ct1 = 0; ct1 < len; ct1 += 1) { + ptt = (u8 *)(start + ct1); + dev_dbg(&sep->pdev->dev, "%02x ", *ptt); + if (ct1 % 16 == 15) + dev_dbg(&sep->pdev->dev, "\n"); + } + dev_dbg(&sep->pdev->dev, "\n"); +#endif +} + +/* Debug - prints only if DEBUG is defined; follows kernel debug model */ +static void sep_dump_sg(struct sep_device *sep, char *stg, + struct scatterlist *sg) +{ +#if 0 + int ct1, ct2; + u8 *ptt; + + dev_dbg(&sep->pdev->dev, "Dump of scatterlist %s\n", stg); + + ct1 = 0; + while (sg) { + dev_dbg(&sep->pdev->dev, "page %x\n size %x", ct1, + sg->length); + dev_dbg(&sep->pdev->dev, "phys addr is %lx", + (unsigned long)sg_phys(sg)); + ptt = sg_virt(sg); + for (ct2 = 0; ct2 < sg->length; ct2 += 1) { + dev_dbg(&sep->pdev->dev, "byte %x is %02x\n", + ct2, (unsigned char)*(ptt + ct2)); + } + + ct1 += 1; + sg = sg_next(sg); + } + dev_dbg(&sep->pdev->dev, "\n"); +#endif +} + +/** + * RFC2451: Weak key check + * Returns: 1 (weak), 0 (not weak) + */ +static int sep_weak_key(const u8 *key, unsigned int keylen) +{ + static const u8 parity[] = { + 8, 1, 0, 8, 0, 8, 8, 0, 0, 8, 8, 0, 8, 0, 2, 8, + 0, 8, 8, 0, 8, 0, 0, 8, 8, + 0, 0, 8, 0, 8, 8, 3, + 0, 8, 8, 0, 8, 0, 0, 8, 8, 0, 0, 8, 0, 8, 8, 0, + 8, 0, 0, 8, 0, 8, 8, 0, 0, + 8, 8, 0, 8, 0, 0, 8, + 0, 8, 8, 0, 8, 0, 0, 8, 8, 0, 0, 8, 0, 8, 8, 0, + 8, 0, 0, 8, 0, 8, 8, 0, 0, + 8, 8, 0, 8, 0, 0, 8, + 8, 0, 0, 8, 0, 8, 8, 0, 0, 8, 8, 0, 8, 0, 0, 8, + 0, 8, 8, 0, 8, 0, 0, 8, 8, + 0, 0, 8, 0, 8, 8, 0, + 0, 8, 8, 0, 8, 0, 0, 8, 8, 0, 0, 8, 0, 8, 8, 0, + 8, 0, 0, 8, 0, 8, 8, 0, 0, + 8, 8, 0, 8, 0, 0, 8, + 8, 0, 0, 8, 0, 8, 8, 0, 0, 8, 8, 0, 8, 0, 0, 8, + 0, 8, 8, 0, 8, 0, 0, 8, 8, + 0, 0, 8, 0, 8, 8, 0, + 8, 0, 0, 8, 0, 8, 8, 0, 0, 8, 8, 0, 8, 0, 0, 8, + 0, 8, 8, 0, 8, 0, 0, 8, 8, + 0, 0, 8, 0, 8, 8, 0, + 4, 8, 8, 0, 8, 0, 0, 8, 8, 0, 0, 8, 0, 8, 8, 0, + 8, 5, 0, 8, 0, 8, 8, 0, 0, + 8, 8, 0, 8, 0, 6, 8, + }; + + u32 n, w; + + n = parity[key[0]]; n <<= 4; + n |= parity[key[1]]; n <<= 4; + n |= parity[key[2]]; n <<= 4; + n |= parity[key[3]]; n <<= 4; + n |= parity[key[4]]; n <<= 4; + n |= parity[key[5]]; n <<= 4; + n |= parity[key[6]]; n <<= 4; + n |= parity[key[7]]; + w = 0x88888888L; + + /* 1 in 10^10 keys passes this test */ + if (!((n - (w >> 3)) & w)) { + if (n < 0x41415151) { + if (n < 0x31312121) { + if (n < 0x14141515) { + /* 01 01 01 01 01 01 01 01 */ + if (n == 0x11111111) + goto weak; + /* 01 1F 01 1F 01 0E 01 0E */ + if (n == 0x13131212) + goto weak; + } else { + /* 01 E0 01 E0 01 F1 01 F1 */ + if (n == 0x14141515) + goto weak; + /* 01 FE 01 FE 01 FE 01 FE */ + if (n == 0x16161616) + goto weak; + } + } else { + if (n < 0x34342525) { + /* 1F 01 1F 01 0E 01 0E 01 */ + if (n == 0x31312121) + goto weak; + /* 1F 1F 1F 1F 0E 0E 0E 0E (?) */ + if (n == 0x33332222) + goto weak; + } else { + /* 1F E0 1F E0 0E F1 0E F1 */ + if (n == 0x34342525) + goto weak; + /* 1F FE 1F FE 0E FE 0E FE */ + if (n == 0x36362626) + goto weak; + } + } + } else { + if (n < 0x61616161) { + if (n < 0x44445555) { + /* E0 01 E0 01 F1 01 F1 01 */ + if (n == 0x41415151) + goto weak; + /* E0 1F E0 1F F1 0E F1 0E */ + if (n == 0x43435252) + goto weak; + } else { + /* E0 E0 E0 E0 F1 F1 F1 F1 (?) */ + if (n == 0x44445555) + goto weak; + /* E0 FE E0 FE F1 FE F1 FE */ + if (n == 0x46465656) + goto weak; + } + } else { + if (n < 0x64646565) { + /* FE 01 FE 01 FE 01 FE 01 */ + if (n == 0x61616161) + goto weak; + /* FE 1F FE 1F FE 0E FE 0E */ + if (n == 0x63636262) + goto weak; + } else { + /* FE E0 FE E0 FE F1 FE F1 */ + if (n == 0x64646565) + goto weak; + /* FE FE FE FE FE FE FE FE */ + if (n == 0x66666666) + goto weak; + } + } + } + } + return 0; +weak: + return 1; +} +/** + * sep_sg_nents + */ +static u32 sep_sg_nents(struct scatterlist *sg) +{ + u32 ct1 = 0; + while (sg) { + ct1 += 1; + sg = sg_next(sg); + } + + return ct1; +} + +/** + * sep_start_msg - + * @sctx: pointer to struct sep_system_ctx + * @returns: offset to place for the next word in the message + * Set up pointer in message pool for new message + */ +static u32 sep_start_msg(struct sep_system_ctx *sctx) +{ + u32 *word_ptr; + sctx->msg_len_words = 2; + sctx->msgptr = sctx->msg; + memset(sctx->msg, 0, SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES); + sctx->msgptr += sizeof(u32) * 2; + word_ptr = (u32 *)sctx->msgptr; + *word_ptr = SEP_START_MSG_TOKEN; + return sizeof(u32) * 2; +} + +/** + * sep_end_msg - + * @sctx: pointer to struct sep_system_ctx + * @messages_offset: current message offset + * Returns: 0 for success; <0 otherwise + * End message; set length and CRC; and + * send interrupt to the SEP + */ +static void sep_end_msg(struct sep_system_ctx *sctx, u32 msg_offset) +{ + u32 *word_ptr; + /* Msg size goes into msg after token */ + sctx->msg_len_words = msg_offset / sizeof(u32) + 1; + word_ptr = (u32 *)sctx->msgptr; + word_ptr += 1; + *word_ptr = sctx->msg_len_words; + + /* CRC (currently 0) goes at end of msg */ + word_ptr = (u32 *)(sctx->msgptr + msg_offset); + *word_ptr = 0; +} + +/** + * sep_start_inbound_msg - + * @sctx: pointer to struct sep_system_ctx + * @msg_offset: offset to place for the next word in the message + * @returns: 0 for success; error value for failure + * Set up pointer in message pool for inbound message + */ +static u32 sep_start_inbound_msg(struct sep_system_ctx *sctx, u32 *msg_offset) +{ + u32 *word_ptr; + u32 token; + u32 error = SEP_OK; + + *msg_offset = sizeof(u32) * 2; + word_ptr = (u32 *)sctx->msgptr; + token = *word_ptr; + sctx->msg_len_words = *(word_ptr + 1); + + if (token != SEP_START_MSG_TOKEN) { + error = SEP_INVALID_START; + goto end_function; + } + +end_function: + + return error; +} + +/** + * sep_write_msg - + * @sctx: pointer to struct sep_system_ctx + * @in_addr: pointer to start of parameter + * @size: size of parameter to copy (in bytes) + * @max_size: size to move up offset; SEP mesg is in word sizes + * @msg_offset: pointer to current offset (is updated) + * @byte_array: flag ti indicate wheter endian must be changed + * Copies data into the message area from caller + */ +static void sep_write_msg(struct sep_system_ctx *sctx, void *in_addr, + u32 size, u32 max_size, u32 *msg_offset, u32 byte_array) +{ + u32 *word_ptr; + void *void_ptr; + void_ptr = sctx->msgptr + *msg_offset; + word_ptr = (u32 *)void_ptr; + memcpy(void_ptr, in_addr, size); + *msg_offset += max_size; + + /* Do we need to manipulate endian? */ + if (byte_array) { + u32 i; + for (i = 0; i < ((size + 3) / 4); i += 1) + *(word_ptr + i) = CHG_ENDIAN(*(word_ptr + i)); + } +} + +/** + * sep_make_header + * @sctx: pointer to struct sep_system_ctx + * @msg_offset: pointer to current offset (is updated) + * @op_code: op code to put into message + * Puts op code into message and updates offset + */ +static void sep_make_header(struct sep_system_ctx *sctx, u32 *msg_offset, + u32 op_code) +{ + u32 *word_ptr; + + *msg_offset = sep_start_msg(sctx); + word_ptr = (u32 *)(sctx->msgptr + *msg_offset); + *word_ptr = op_code; + *msg_offset += sizeof(u32); +} + + + +/** + * sep_read_msg - + * @sctx: pointer to struct sep_system_ctx + * @in_addr: pointer to start of parameter + * @size: size of parameter to copy (in bytes) + * @max_size: size to move up offset; SEP mesg is in word sizes + * @msg_offset: pointer to current offset (is updated) + * @byte_array: flag ti indicate wheter endian must be changed + * Copies data out of the message area to caller + */ +static void sep_read_msg(struct sep_system_ctx *sctx, void *in_addr, + u32 size, u32 max_size, u32 *msg_offset, u32 byte_array) +{ + u32 *word_ptr; + void *void_ptr; + void_ptr = sctx->msgptr + *msg_offset; + word_ptr = (u32 *)void_ptr; + + /* Do we need to manipulate endian? */ + if (byte_array) { + u32 i; + for (i = 0; i < ((size + 3) / 4); i += 1) + *(word_ptr + i) = CHG_ENDIAN(*(word_ptr + i)); + } + + memcpy(in_addr, void_ptr, size); + *msg_offset += max_size; +} + +/** + * sep_verify_op - + * @sctx: pointer to struct sep_system_ctx + * @op_code: expected op_code + * @msg_offset: pointer to current offset (is updated) + * @returns: 0 for success; error for failure + */ +static u32 sep_verify_op(struct sep_system_ctx *sctx, u32 op_code, + u32 *msg_offset) +{ + u32 error; + u32 in_ary[2]; + + struct sep_device *sep = sctx->sep_used; + + dev_dbg(&sep->pdev->dev, "dumping return message\n"); + error = sep_start_inbound_msg(sctx, msg_offset); + if (error) { + dev_warn(&sep->pdev->dev, + "sep_start_inbound_msg error\n"); + return error; + } + + sep_read_msg(sctx, in_ary, sizeof(u32) * 2, sizeof(u32) * 2, + msg_offset, 0); + + if (in_ary[0] != op_code) { + dev_warn(&sep->pdev->dev, + "sep got back wrong opcode\n"); + dev_warn(&sep->pdev->dev, + "got back %x; expected %x\n", + in_ary[0], op_code); + return SEP_WRONG_OPCODE; + } + + if (in_ary[1] != SEP_OK) { + dev_warn(&sep->pdev->dev, + "sep execution error\n"); + dev_warn(&sep->pdev->dev, + "got back %x; expected %x\n", + in_ary[1], SEP_OK); + return in_ary[0]; + } + +return 0; +} + +/** + * sep_read_context - + * @sctx: pointer to struct sep_system_ctx + * @msg_offset: point to current place in SEP msg; is updated + * @dst: pointer to place to put the context + * @len: size of the context structure (differs for crypro/hash) + * This function reads the context from the msg area + * There is a special way the vendor needs to have the maximum + * length calculated so that the msg_offset is updated properly; + * it skips over some words in the msg area depending on the size + * of the context + */ +static void sep_read_context(struct sep_system_ctx *sctx, u32 *msg_offset, + void *dst, u32 len) +{ + u32 max_length = ((len + 3) / sizeof(u32)) * sizeof(u32); + sep_read_msg(sctx, dst, len, max_length, msg_offset, 0); +} + +/** + * sep_write_context - + * @sctx: pointer to struct sep_system_ctx + * @msg_offset: point to current place in SEP msg; is updated + * @src: pointer to the current context + * @len: size of the context structure (differs for crypro/hash) + * This function writes the context to the msg area + * There is a special way the vendor needs to have the maximum + * length calculated so that the msg_offset is updated properly; + * it skips over some words in the msg area depending on the size + * of the context + */ +static void sep_write_context(struct sep_system_ctx *sctx, u32 *msg_offset, + void *src, u32 len) +{ + u32 max_length = ((len + 3) / sizeof(u32)) * sizeof(u32); + sep_write_msg(sctx, src, len, max_length, msg_offset, 0); +} + +/** + * sep_clear_out - + * @sctx: pointer to struct sep_system_ctx + * Clear out crypto related values in sep device structure + * to enable device to be used by anyone; either kernel + * crypto or userspace app via middleware + */ +static void sep_clear_out(struct sep_system_ctx *sctx) +{ + if (sctx->src_sg_hold) { + sep_free_sg_buf(sctx->src_sg_hold); + sctx->src_sg_hold = NULL; + } + + if (sctx->dst_sg_hold) { + sep_free_sg_buf(sctx->dst_sg_hold); + sctx->dst_sg_hold = NULL; + } + + sctx->src_sg = NULL; + sctx->dst_sg = NULL; + + sep_free_dma_table_data_handler(sctx->sep_used, &sctx->dma_ctx); + + if (sctx->i_own_sep) { + /** + * The following unlocks the sep and makes it available + * to any other application + * First, null out crypto entries in sep before relesing it + */ + sctx->sep_used->current_hash_req = NULL; + sctx->sep_used->current_cypher_req = NULL; + sctx->sep_used->current_request = 0; + sctx->sep_used->current_hash_stage = 0; + sctx->sep_used->sctx = NULL; + sctx->sep_used->in_kernel = 0; + + sctx->call_status.status = 0; + + /* Remove anything confidentail */ + memset(sctx->sep_used->shared_addr, 0, + SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES); + + sep_queue_status_remove(sctx->sep_used, &sctx->queue_elem); + +#ifdef SEP_ENABLE_RUNTIME_PM + sctx->sep_used->in_use = 0; + pm_runtime_mark_last_busy(&sctx->sep_used->pdev->dev); + pm_runtime_put_autosuspend(&sctx->sep_used->pdev->dev); +#endif + + clear_bit(SEP_WORKING_LOCK_BIT, &sctx->sep_used->in_use_flags); + sctx->sep_used->pid_doing_transaction = 0; + + dev_dbg(&sctx->sep_used->pdev->dev, + "[PID%d] waking up next transaction\n", + current->pid); + + clear_bit(SEP_TRANSACTION_STARTED_LOCK_BIT, + &sctx->sep_used->in_use_flags); + wake_up(&sctx->sep_used->event_transactions); + + sctx->i_own_sep = 0; + } +} + +/** + * Release crypto infrastructure from EINPROGRESS and + * clear sep_dev so that SEP is available to anyone + */ +static void sep_crypto_release(struct sep_system_ctx *sctx, u32 error) +{ + struct ahash_request *hash_req = sctx->current_hash_req; + struct ablkcipher_request *cypher_req = + sctx->current_cypher_req; + struct sep_device *sep = sctx->sep_used; + + sep_clear_out(sctx); + + if (cypher_req != NULL) { + if (cypher_req->base.complete == NULL) { + dev_dbg(&sep->pdev->dev, + "release is null for cypher!"); + } else { + cypher_req->base.complete( + &cypher_req->base, error); + } + } + + if (hash_req != NULL) { + if (hash_req->base.complete == NULL) { + dev_dbg(&sep->pdev->dev, + "release is null for hash!"); + } else { + hash_req->base.complete( + &hash_req->base, error); + } + } +} + +/** + * This is where we grab the sep itself and tell it to do something. + * It will sleep if the sep is currently busy + * and it will return 0 if sep is now ours; error value if there + * were problems + */ +static int sep_crypto_take_sep(struct sep_system_ctx *sctx) +{ + struct sep_device *sep = sctx->sep_used; + int result; + struct sep_msgarea_hdr *my_msg_header; + + my_msg_header = (struct sep_msgarea_hdr *)sctx->msg; + + /* add to status queue */ + sctx->queue_elem = sep_queue_status_add(sep, my_msg_header->opcode, + sctx->nbytes, current->pid, + current->comm, sizeof(current->comm)); + + if (!sctx->queue_elem) { + dev_dbg(&sep->pdev->dev, "[PID%d] updating queue" + " status error\n", current->pid); + return -EINVAL; + } + + /* get the device; this can sleep */ + result = sep_wait_transaction(sep); + if (result) + return result; + + if (sep_dev->power_save_setup == 1) + pm_runtime_get_sync(&sep_dev->pdev->dev); + + /* Copy in the message */ + memcpy(sep->shared_addr, sctx->msg, + SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES); + + /* Copy in the dcb information if there is any */ + if (sctx->dcb_region) { + result = sep_activate_dcb_dmatables_context(sep, + &sctx->dcb_region, &sctx->dmatables_region, + sctx->dma_ctx); + if (result) + return result; + } + + /* Mark the device so we know how to finish the job in the tasklet */ + if (sctx->current_hash_req) + sep->current_hash_req = sctx->current_hash_req; + else + sep->current_cypher_req = sctx->current_cypher_req; + + sep->current_request = sctx->current_request; + sep->current_hash_stage = sctx->current_hash_stage; + sep->sctx = sctx; + sep->in_kernel = 1; + sctx->i_own_sep = 1; + + result = sep_send_command_handler(sep); + + dev_dbg(&sep->pdev->dev, "[PID%d]: sending command to the sep\n", + current->pid); + + if (!result) { + set_bit(SEP_LEGACY_SENDMSG_DONE_OFFSET, + &sctx->call_status.status); + dev_dbg(&sep->pdev->dev, "[PID%d]: command sent okay\n", + current->pid); + } + + return result; +} + +/* This needs to be run as a work queue as it can be put asleep */ +static void sep_crypto_block(void *data) +{ + int int_error; + u32 msg_offset; + static u32 msg[10]; + void *src_ptr; + void *dst_ptr; + + static char small_buf[100]; + ssize_t copy_result; + int result; + + u32 max_length; + struct scatterlist *new_sg; + struct ablkcipher_request *req; + struct sep_block_ctx *bctx; + struct crypto_ablkcipher *tfm; + struct sep_system_ctx *sctx; + + req = (struct ablkcipher_request *)data; + bctx = ablkcipher_request_ctx(req); + tfm = crypto_ablkcipher_reqtfm(req); + sctx = crypto_ablkcipher_ctx(tfm); + + /* start the walk on scatterlists */ + ablkcipher_walk_init(&bctx->walk, req->src, req->dst, req->nbytes); + dev_dbg(&sctx->sep_used->pdev->dev, "sep crypto block data size of %x\n", + req->nbytes); + + int_error = ablkcipher_walk_phys(req, &bctx->walk); + if (int_error) { + dev_warn(&sctx->sep_used->pdev->dev, "walk phys error %x\n", + int_error); + sep_crypto_release(sctx, -ENOMEM); + return; + } + + /* check iv */ + if (bctx->des_opmode == SEP_DES_CBC) { + if (!bctx->walk.iv) { + dev_warn(&sctx->sep_used->pdev->dev, "no iv found\n"); + sep_crypto_release(sctx, -EINVAL); + return; + } + + memcpy(bctx->iv, bctx->walk.iv, SEP_DES_IV_SIZE_BYTES); + sep_dump(sctx->sep_used, "iv", bctx->iv, SEP_DES_IV_SIZE_BYTES); + } + + if (bctx->aes_opmode == SEP_AES_CBC) { + if (!bctx->walk.iv) { + dev_warn(&sctx->sep_used->pdev->dev, "no iv found\n"); + sep_crypto_release(sctx, -EINVAL); + return; + } + + memcpy(bctx->iv, bctx->walk.iv, SEP_AES_IV_SIZE_BYTES); + sep_dump(sctx->sep_used, "iv", bctx->iv, SEP_AES_IV_SIZE_BYTES); + } + + dev_dbg(&sctx->sep_used->pdev->dev, + "crypto block: src is %lx dst is %lx\n", + (unsigned long)req->src, (unsigned long)req->dst); + + /* Make sure all pages are even block */ + int_error = sep_oddball_pages(sctx->sep_used, req->src, + req->nbytes, bctx->walk.blocksize, &new_sg, 1); + + if (int_error < 0) { + dev_warn(&sctx->sep_used->pdev->dev, "oddball page eerror\n"); + sep_crypto_release(sctx, -ENOMEM); + return; + } else if (int_error == 1) { + sctx->src_sg = new_sg; + sctx->src_sg_hold = new_sg; + } else { + sctx->src_sg = req->src; + sctx->src_sg_hold = NULL; + } + + int_error = sep_oddball_pages(sctx->sep_used, req->dst, + req->nbytes, bctx->walk.blocksize, &new_sg, 0); + + if (int_error < 0) { + dev_warn(&sctx->sep_used->pdev->dev, "walk phys error %x\n", + int_error); + sep_crypto_release(sctx, -ENOMEM); + return; + } else if (int_error == 1) { + sctx->dst_sg = new_sg; + sctx->dst_sg_hold = new_sg; + } else { + sctx->dst_sg = req->dst; + sctx->dst_sg_hold = NULL; + } + + /* Do we need to perform init; ie; send key to sep? */ + if (sctx->key_sent == 0) { + + dev_dbg(&sctx->sep_used->pdev->dev, "sending key\n"); + + /* put together message to SEP */ + /* Start with op code */ + sep_make_header(sctx, &msg_offset, bctx->init_opcode); + + /* now deal with IV */ + if (bctx->init_opcode == SEP_DES_INIT_OPCODE) { + if (bctx->des_opmode == SEP_DES_CBC) { + sep_write_msg(sctx, bctx->iv, + SEP_DES_IV_SIZE_BYTES, sizeof(u32) * 4, + &msg_offset, 1); + sep_dump(sctx->sep_used, "initial IV", + bctx->walk.iv, SEP_DES_IV_SIZE_BYTES); + } else { + /* Skip if ECB */ + msg_offset += 4 * sizeof(u32); + } + } else { + max_length = ((SEP_AES_IV_SIZE_BYTES + 3) / + sizeof(u32)) * sizeof(u32); + if (bctx->aes_opmode == SEP_AES_CBC) { + sep_write_msg(sctx, bctx->iv, + SEP_AES_IV_SIZE_BYTES, max_length, + &msg_offset, 1); + sep_dump(sctx->sep_used, "initial IV", + bctx->walk.iv, SEP_AES_IV_SIZE_BYTES); + } else { + /* Skip if ECB */ + msg_offset += max_length; + } + } + + /* load the key */ + if (bctx->init_opcode == SEP_DES_INIT_OPCODE) { + sep_write_msg(sctx, (void *)&sctx->key.des.key1, + sizeof(u32) * 8, sizeof(u32) * 8, + &msg_offset, 1); + + msg[0] = (u32)sctx->des_nbr_keys; + msg[1] = (u32)bctx->des_encmode; + msg[2] = (u32)bctx->des_opmode; + + sep_write_msg(sctx, (void *)msg, + sizeof(u32) * 3, sizeof(u32) * 3, + &msg_offset, 0); + } else { + sep_write_msg(sctx, (void *)&sctx->key.aes, + sctx->keylen, + SEP_AES_MAX_KEY_SIZE_BYTES, + &msg_offset, 1); + + msg[0] = (u32)sctx->aes_key_size; + msg[1] = (u32)bctx->aes_encmode; + msg[2] = (u32)bctx->aes_opmode; + msg[3] = (u32)0; /* Secret key is not used */ + sep_write_msg(sctx, (void *)msg, + sizeof(u32) * 4, sizeof(u32) * 4, + &msg_offset, 0); + } + + } else { + + /* set nbytes for queue status */ + sctx->nbytes = req->nbytes; + + /* Key already done; this is for data */ + dev_dbg(&sctx->sep_used->pdev->dev, "sending data\n"); + + sep_dump_sg(sctx->sep_used, + "block sg in", sctx->src_sg); + + /* check for valid data and proper spacing */ + src_ptr = sg_virt(sctx->src_sg); + dst_ptr = sg_virt(sctx->dst_sg); + + if (!src_ptr || !dst_ptr || + (sctx->current_cypher_req->nbytes % + crypto_ablkcipher_blocksize(tfm))) { + + dev_warn(&sctx->sep_used->pdev->dev, + "cipher block size odd\n"); + dev_warn(&sctx->sep_used->pdev->dev, + "cipher block size is %x\n", + crypto_ablkcipher_blocksize(tfm)); + dev_warn(&sctx->sep_used->pdev->dev, + "cipher data size is %x\n", + sctx->current_cypher_req->nbytes); + sep_crypto_release(sctx, -EINVAL); + return; + } + + if (partial_overlap(src_ptr, dst_ptr, + sctx->current_cypher_req->nbytes)) { + dev_warn(&sctx->sep_used->pdev->dev, + "block partial overlap\n"); + sep_crypto_release(sctx, -EINVAL); + return; + } + + /* Put together the message */ + sep_make_header(sctx, &msg_offset, bctx->block_opcode); + + /* If des, and size is 1 block, put directly in msg */ + if ((bctx->block_opcode == SEP_DES_BLOCK_OPCODE) && + (req->nbytes == crypto_ablkcipher_blocksize(tfm))) { + + dev_dbg(&sctx->sep_used->pdev->dev, + "writing out one block des\n"); + + copy_result = sg_copy_to_buffer( + sctx->src_sg, sep_sg_nents(sctx->src_sg), + small_buf, crypto_ablkcipher_blocksize(tfm)); + + if (copy_result != crypto_ablkcipher_blocksize(tfm)) { + dev_warn(&sctx->sep_used->pdev->dev, + "des block copy faild\n"); + sep_crypto_release(sctx, -ENOMEM); + return; + } + + /* Put data into message */ + sep_write_msg(sctx, small_buf, + crypto_ablkcipher_blocksize(tfm), + crypto_ablkcipher_blocksize(tfm) * 2, + &msg_offset, 1); + + /* Put size into message */ + sep_write_msg(sctx, &req->nbytes, + sizeof(u32), sizeof(u32), &msg_offset, 0); + } else { + /* Otherwise, fill out dma tables */ + sctx->dcb_input_data.app_in_address = src_ptr; + sctx->dcb_input_data.data_in_size = req->nbytes; + sctx->dcb_input_data.app_out_address = dst_ptr; + sctx->dcb_input_data.block_size = + crypto_ablkcipher_blocksize(tfm); + sctx->dcb_input_data.tail_block_size = 0; + sctx->dcb_input_data.is_applet = 0; + sctx->dcb_input_data.src_sg = sctx->src_sg; + sctx->dcb_input_data.dst_sg = sctx->dst_sg; + + result = sep_create_dcb_dmatables_context_kernel( + sctx->sep_used, + &sctx->dcb_region, + &sctx->dmatables_region, + &sctx->dma_ctx, + &sctx->dcb_input_data, + 1); + if (result) { + dev_warn(&sctx->sep_used->pdev->dev, + "crypto dma table create failed\n"); + sep_crypto_release(sctx, -EINVAL); + return; + } + + /* Portion of msg is nulled (no data) */ + msg[0] = (u32)0; + msg[1] = (u32)0; + msg[2] = (u32)0; + msg[3] = (u32)0; + msg[4] = (u32)0; + sep_write_msg(sctx, (void *)msg, + sizeof(u32) * 5, + sizeof(u32) * 5, + &msg_offset, 0); + } + + /* Write context into message */ + if (bctx->block_opcode == SEP_DES_BLOCK_OPCODE) { + sep_write_context(sctx, &msg_offset, + &bctx->des_private_ctx, + sizeof(struct sep_des_private_context)); + sep_dump(sctx->sep_used, "ctx to block des", + &bctx->des_private_ctx, 40); + } else { + sep_write_context(sctx, &msg_offset, + &bctx->aes_private_ctx, + sizeof(struct sep_aes_private_context)); + sep_dump(sctx->sep_used, "ctx to block aes", + &bctx->aes_private_ctx, 20); + } + } + + /* conclude message and then tell sep to do its thing */ + sctx->done_with_transaction = 0; + + sep_end_msg(sctx, msg_offset); + result = sep_crypto_take_sep(sctx); + if (result) { + dev_warn(&sctx->sep_used->pdev->dev, + "sep_crypto_take_sep failed\n"); + sep_crypto_release(sctx, -EINVAL); + return; + } + + /** + * Sep is now working. Lets wait up to 5 seconds + * for completion. If it does not complete, we will do + * a crypto release with -EINVAL to release the + * kernel crypto infrastructure and let the system + * continue to boot up + * We have to wait this long because some crypto + * operations can take a while + */ + + dev_dbg(&sctx->sep_used->pdev->dev, + "waiting for done with transaction\n"); + + sctx->end_time = jiffies + (SEP_TRANSACTION_WAIT_TIME * HZ); + while ((time_before(jiffies, sctx->end_time)) && + (!sctx->done_with_transaction)) + schedule(); + + dev_dbg(&sctx->sep_used->pdev->dev, + "done waiting for done with transaction\n"); + + /* are we done? */ + if (!sctx->done_with_transaction) { + /* Nope, lets release and tell crypto no */ + dev_warn(&sctx->sep_used->pdev->dev, + "[PID%d] sep_crypto_block never finished\n", + current->pid); + sep_crypto_release(sctx, -EINVAL); + } +} + +/** + * Post operation (after interrupt) for crypto block + */ +static u32 crypto_post_op(struct sep_device *sep) +{ + /* HERE */ + int int_error; + u32 u32_error; + u32 msg_offset; + + ssize_t copy_result; + static char small_buf[100]; + + struct ablkcipher_request *req; + struct sep_block_ctx *bctx; + struct sep_system_ctx *sctx; + struct crypto_ablkcipher *tfm; + + if (!sep->current_cypher_req) + return -EINVAL; + + /* hold req since we need to submit work after clearing sep */ + req = sep->current_cypher_req; + + bctx = ablkcipher_request_ctx(sep->current_cypher_req); + tfm = crypto_ablkcipher_reqtfm(sep->current_cypher_req); + sctx = crypto_ablkcipher_ctx(tfm); + + dev_dbg(&sctx->sep_used->pdev->dev, "crypto post_op\n"); + dev_dbg(&sctx->sep_used->pdev->dev, "crypto post_op message dump\n"); + crypto_sep_dump_message(sctx); + + sctx->done_with_transaction = 1; + + /* first bring msg from shared area to local area */ + memcpy(sctx->msg, sep->shared_addr, + SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES); + + /* Is this the result of performing init (key to SEP */ + if (sctx->key_sent == 0) { + + /* Did SEP do it okay */ + u32_error = sep_verify_op(sctx, bctx->init_opcode, + &msg_offset); + if (u32_error) { + dev_warn(&sctx->sep_used->pdev->dev, + "aes init error %x\n", u32_error); + sep_crypto_release(sctx, u32_error); + return u32_error; + } + + /* Read Context */ + if (bctx->init_opcode == SEP_DES_INIT_OPCODE) { + sep_read_context(sctx, &msg_offset, + &bctx->des_private_ctx, + sizeof(struct sep_des_private_context)); + + sep_dump(sctx->sep_used, "ctx init des", + &bctx->des_private_ctx, 40); + } else { + sep_read_context(sctx, &msg_offset, + &bctx->aes_private_ctx, + sizeof(struct sep_des_private_context)); + + sep_dump(sctx->sep_used, "ctx init aes", + &bctx->aes_private_ctx, 20); + } + + /* We are done with init. Now send out the data */ + /* first release the sep */ + sctx->key_sent = 1; + sep_crypto_release(sctx, -EINPROGRESS); + + spin_lock_irq(&queue_lock); + int_error = crypto_enqueue_request(&sep_queue, &req->base); + spin_unlock_irq(&queue_lock); + + if ((int_error != 0) && (int_error != -EINPROGRESS)) { + dev_warn(&sctx->sep_used->pdev->dev, + "spe cypher post op cant queue\n"); + sep_crypto_release(sctx, int_error); + return int_error; + } + + /* schedule the data send */ + int_error = sep_submit_work(sep->workqueue, sep_dequeuer, + (void *)&sep_queue); + + if (int_error) { + dev_warn(&sep->pdev->dev, + "cant submit work sep_crypto_block\n"); + sep_crypto_release(sctx, -EINVAL); + return -EINVAL; + } + + } else { + + /** + * This is the result of a block request + */ + dev_dbg(&sctx->sep_used->pdev->dev, + "crypto_post_op block response\n"); + + u32_error = sep_verify_op(sctx, bctx->block_opcode, + &msg_offset); + + if (u32_error) { + dev_warn(&sctx->sep_used->pdev->dev, + "sep block error %x\n", u32_error); + sep_crypto_release(sctx, u32_error); + return -EINVAL; + } + + if (bctx->block_opcode == SEP_DES_BLOCK_OPCODE) { + + dev_dbg(&sctx->sep_used->pdev->dev, + "post op for DES\n"); + + /* special case for 1 block des */ + if (sep->current_cypher_req->nbytes == + crypto_ablkcipher_blocksize(tfm)) { + + sep_read_msg(sctx, small_buf, + crypto_ablkcipher_blocksize(tfm), + crypto_ablkcipher_blocksize(tfm) * 2, + &msg_offset, 1); + + dev_dbg(&sctx->sep_used->pdev->dev, + "reading in block des\n"); + + copy_result = sg_copy_from_buffer( + sctx->dst_sg, + sep_sg_nents(sctx->dst_sg), + small_buf, + crypto_ablkcipher_blocksize(tfm)); + + if (copy_result != + crypto_ablkcipher_blocksize(tfm)) { + + dev_warn(&sctx->sep_used->pdev->dev, + "des block copy faild\n"); + sep_crypto_release(sctx, -ENOMEM); + return -ENOMEM; + } + } + + /* Read Context */ + sep_read_context(sctx, &msg_offset, + &bctx->des_private_ctx, + sizeof(struct sep_des_private_context)); + } else { + + dev_dbg(&sctx->sep_used->pdev->dev, + "post op for AES\n"); + + /* Skip the MAC Output */ + msg_offset += (sizeof(u32) * 4); + + /* Read Context */ + sep_read_context(sctx, &msg_offset, + &bctx->aes_private_ctx, + sizeof(struct sep_aes_private_context)); + } + + sep_dump_sg(sctx->sep_used, + "block sg out", sctx->dst_sg); + + /* Copy to correct sg if this block had oddball pages */ + if (sctx->dst_sg_hold) + sep_copy_sg(sctx->sep_used, + sctx->dst_sg, + sctx->current_cypher_req->dst, + sctx->current_cypher_req->nbytes); + + /* finished, release everything */ + sep_crypto_release(sctx, 0); + } + return 0; +} + +static u32 hash_init_post_op(struct sep_device *sep) +{ + u32 u32_error; + u32 msg_offset; + struct crypto_ahash *tfm = crypto_ahash_reqtfm(sep->current_hash_req); + struct sep_hash_ctx *ctx = ahash_request_ctx(sep->current_hash_req); + struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); + dev_dbg(&sctx->sep_used->pdev->dev, + "hash init post op\n"); + + sctx->done_with_transaction = 1; + + /* first bring msg from shared area to local area */ + memcpy(sctx->msg, sep->shared_addr, + SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES); + + u32_error = sep_verify_op(sctx, SEP_HASH_INIT_OPCODE, + &msg_offset); + + if (u32_error) { + dev_warn(&sctx->sep_used->pdev->dev, "hash init error %x\n", + u32_error); + sep_crypto_release(sctx, u32_error); + return u32_error; + } + + /* Read Context */ + sep_read_context(sctx, &msg_offset, + &ctx->hash_private_ctx, + sizeof(struct sep_hash_private_context)); + + /* Signal to crypto infrastructure and clear out */ + dev_dbg(&sctx->sep_used->pdev->dev, "hash init post op done\n"); + sep_crypto_release(sctx, 0); + return 0; +} + +static u32 hash_update_post_op(struct sep_device *sep) +{ + u32 u32_error; + u32 msg_offset; + struct crypto_ahash *tfm = crypto_ahash_reqtfm(sep->current_hash_req); + struct sep_hash_ctx *ctx = ahash_request_ctx(sep->current_hash_req); + struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); + dev_dbg(&sctx->sep_used->pdev->dev, + "hash update post op\n"); + + sctx->done_with_transaction = 1; + + /* first bring msg from shared area to local area */ + memcpy(sctx->msg, sep->shared_addr, + SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES); + + u32_error = sep_verify_op(sctx, SEP_HASH_UPDATE_OPCODE, + &msg_offset); + + if (u32_error) { + dev_warn(&sctx->sep_used->pdev->dev, "hash init error %x\n", + u32_error); + sep_crypto_release(sctx, u32_error); + return u32_error; + } + + /* Read Context */ + sep_read_context(sctx, &msg_offset, + &ctx->hash_private_ctx, + sizeof(struct sep_hash_private_context)); + + sep_crypto_release(sctx, 0); + return 0; +} + +static u32 hash_final_post_op(struct sep_device *sep) +{ + int max_length; + u32 u32_error; + u32 msg_offset; + struct crypto_ahash *tfm = crypto_ahash_reqtfm(sep->current_hash_req); + struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); + dev_dbg(&sctx->sep_used->pdev->dev, + "hash final post op\n"); + + sctx->done_with_transaction = 1; + + /* first bring msg from shared area to local area */ + memcpy(sctx->msg, sep->shared_addr, + SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES); + + u32_error = sep_verify_op(sctx, SEP_HASH_FINISH_OPCODE, + &msg_offset); + + if (u32_error) { + dev_warn(&sctx->sep_used->pdev->dev, "hash finish error %x\n", + u32_error); + sep_crypto_release(sctx, u32_error); + return u32_error; + } + + /* Grab the result */ + if (sctx->current_hash_req->result == NULL) { + /* Oops, null buffer; error out here */ + dev_warn(&sctx->sep_used->pdev->dev, + "hash finish null buffer\n"); + sep_crypto_release(sctx, (u32)-ENOMEM); + return -ENOMEM; + } + + max_length = (((SEP_HASH_RESULT_SIZE_WORDS * sizeof(u32)) + 3) / + sizeof(u32)) * sizeof(u32); + + sep_read_msg(sctx, + sctx->current_hash_req->result, + crypto_ahash_digestsize(tfm), max_length, + &msg_offset, 0); + + /* Signal to crypto infrastructure and clear out */ + dev_dbg(&sctx->sep_used->pdev->dev, "hash finish post op done\n"); + sep_crypto_release(sctx, 0); + return 0; +} + +static u32 hash_digest_post_op(struct sep_device *sep) +{ + int max_length; + u32 u32_error; + u32 msg_offset; + struct crypto_ahash *tfm = crypto_ahash_reqtfm(sep->current_hash_req); + struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); + dev_dbg(&sctx->sep_used->pdev->dev, + "hash digest post op\n"); + + sctx->done_with_transaction = 1; + + /* first bring msg from shared area to local area */ + memcpy(sctx->msg, sep->shared_addr, + SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES); + + u32_error = sep_verify_op(sctx, SEP_HASH_SINGLE_OPCODE, + &msg_offset); + + if (u32_error) { + dev_warn(&sctx->sep_used->pdev->dev, + "hash digest finish error %x\n", u32_error); + + sep_crypto_release(sctx, u32_error); + return u32_error; + } + + /* Grab the result */ + if (sctx->current_hash_req->result == NULL) { + /* Oops, null buffer; error out here */ + dev_warn(&sctx->sep_used->pdev->dev, + "hash digest finish null buffer\n"); + sep_crypto_release(sctx, (u32)-ENOMEM); + return -ENOMEM; + } + + max_length = (((SEP_HASH_RESULT_SIZE_WORDS * sizeof(u32)) + 3) / + sizeof(u32)) * sizeof(u32); + + sep_read_msg(sctx, + sctx->current_hash_req->result, + crypto_ahash_digestsize(tfm), max_length, + &msg_offset, 0); + + /* Signal to crypto infrastructure and clear out */ + dev_dbg(&sctx->sep_used->pdev->dev, + "hash digest finish post op done\n"); + + sep_crypto_release(sctx, 0); + return 0; +} + +/** + * The sep_finish function is the function that is schedule (via tasket) + * by the interrupt service routine when the SEP sends and interrupt + * This is only called by the interrupt handler as a tasklet. + */ +static void sep_finish(unsigned long data) +{ + unsigned long flags; + struct sep_device *sep_dev; + int res; + + res = 0; + + if (data == 0) { + pr_debug("sep_finish called with null data\n"); + return; + } + + sep_dev = (struct sep_device *)data; + if (sep_dev == NULL) { + pr_debug("sep_finish; sep_dev is NULL\n"); + return; + } + + spin_lock_irqsave(&sep_dev->busy_lock, flags); + if (sep_dev->in_kernel == (u32)0) { + spin_unlock_irqrestore(&sep_dev->busy_lock, flags); + dev_warn(&sep_dev->pdev->dev, + "sep_finish; not in kernel operation\n"); + return; + } + spin_unlock_irqrestore(&sep_dev->busy_lock, flags); + + /* Did we really do a sep command prior to this? */ + if (0 == test_bit(SEP_LEGACY_SENDMSG_DONE_OFFSET, + &sep_dev->sctx->call_status.status)) { + + dev_warn(&sep_dev->pdev->dev, "[PID%d] sendmsg not called\n", + current->pid); + return; + } + + if (sep_dev->send_ct != sep_dev->reply_ct) { + dev_warn(&sep_dev->pdev->dev, + "[PID%d] poll; no message came back\n", + current->pid); + return; + } + + /* Check for error (In case time ran out) */ + if ((res != 0x0) && (res != 0x8)) { + dev_warn(&sep_dev->pdev->dev, + "[PID%d] poll; poll error GPR3 is %x\n", + current->pid, res); + return; + } + + /* What kind of interrupt from sep was this? */ + res = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR2_REG_ADDR); + + dev_dbg(&sep_dev->pdev->dev, "[PID%d] GPR2 at crypto finish is %x\n", + current->pid, res); + + /* Print request? */ + if ((res >> 30) & 0x1) { + dev_dbg(&sep_dev->pdev->dev, "[PID%d] sep print req\n", + current->pid); + dev_dbg(&sep_dev->pdev->dev, "[PID%d] contents: %s\n", + current->pid, + (char *)(sep_dev->shared_addr + + SEP_DRIVER_PRINTF_OFFSET_IN_BYTES)); + return; + } + + /* Request for daemon (not currently in POR)? */ + if (res >> 31) { + dev_dbg(&sep_dev->pdev->dev, + "[PID%d] sep request; ignoring\n", + current->pid); + return; + } + + /* If we got here, then we have a replay to a sep command */ + + dev_dbg(&sep_dev->pdev->dev, + "[PID%d] sep reply to command; processing request: %x\n", + current->pid, sep_dev->current_request); + + switch (sep_dev->current_request) { + case AES_CBC: + case AES_ECB: + case DES_CBC: + case DES_ECB: + res = crypto_post_op(sep_dev); + break; + case SHA1: + case MD5: + case SHA224: + case SHA256: + switch (sep_dev->current_hash_stage) { + case HASH_INIT: + res = hash_init_post_op(sep_dev); + break; + case HASH_UPDATE: + res = hash_update_post_op(sep_dev); + break; + case HASH_FINISH: + res = hash_final_post_op(sep_dev); + break; + case HASH_DIGEST: + res = hash_digest_post_op(sep_dev); + break; + default: + dev_warn(&sep_dev->pdev->dev, + "invalid stage for hash finish\n"); + } + break; + default: + dev_warn(&sep_dev->pdev->dev, + "invalid request for finish\n"); + } + + if (res) { + dev_warn(&sep_dev->pdev->dev, + "finish returned error %x\n", res); + } +} + +static int sep_hash_cra_init(struct crypto_tfm *tfm) + { + struct sep_system_ctx *sctx = crypto_tfm_ctx(tfm); + const char *alg_name = crypto_tfm_alg_name(tfm); + + sctx->sep_used = sep_dev; + + dev_dbg(&sctx->sep_used->pdev->dev, + "sep_hash_cra_init name is %s\n", alg_name); + + crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), + sizeof(struct sep_hash_ctx)); + return 0; + } + +static void sep_hash_cra_exit(struct crypto_tfm *tfm) +{ + struct sep_system_ctx *sctx = crypto_tfm_ctx(tfm); + + dev_dbg(&sctx->sep_used->pdev->dev, + "sep_hash_cra_exit\n"); + sctx->sep_used = NULL; +} + +static void sep_hash_init(void *data) +{ + u32 msg_offset; + int result; + struct ahash_request *req; + struct crypto_ahash *tfm; + struct sep_hash_ctx *ctx; + struct sep_system_ctx *sctx; + + req = (struct ahash_request *)data; + tfm = crypto_ahash_reqtfm(req); + ctx = ahash_request_ctx(req); + sctx = crypto_ahash_ctx(tfm); + + dev_dbg(&sctx->sep_used->pdev->dev, + "sep_hash_init\n"); + sctx->current_hash_stage = HASH_INIT; + /* opcode and mode */ + sep_make_header(sctx, &msg_offset, SEP_HASH_INIT_OPCODE); + sep_write_msg(sctx, &ctx->hash_opmode, + sizeof(u32), sizeof(u32), &msg_offset, 0); + sep_end_msg(sctx, msg_offset); + + sctx->done_with_transaction = 0; + + result = sep_crypto_take_sep(sctx); + if (result) { + dev_warn(&sctx->sep_used->pdev->dev, + "sep_hash_init take sep failed\n"); + sep_crypto_release(sctx, -EINVAL); + } + + /** + * Sep is now working. Lets wait up to 5 seconds + * for completion. If it does not complete, we will do + * a crypto release with -EINVAL to release the + * kernel crypto infrastructure and let the system + * continue to boot up + * We have to wait this long because some crypto + * operations can take a while + */ + dev_dbg(&sctx->sep_used->pdev->dev, + "waiting for done with transaction\n"); + + sctx->end_time = jiffies + (SEP_TRANSACTION_WAIT_TIME * HZ); + while ((time_before(jiffies, sctx->end_time)) && + (!sctx->done_with_transaction)) + schedule(); + + dev_dbg(&sctx->sep_used->pdev->dev, + "done waiting for done with transaction\n"); + + /* are we done? */ + if (!sctx->done_with_transaction) { + /* Nope, lets release and tell crypto no */ + dev_warn(&sctx->sep_used->pdev->dev, + "[PID%d] sep_hash_init never finished\n", + current->pid); + sep_crypto_release(sctx, -EINVAL); + } +} + +static void sep_hash_update(void *data) +{ + int int_error; + u32 msg_offset; + u32 len; + struct sep_hash_internal_context *int_ctx; + u32 block_size; + u32 head_len; + u32 tail_len; + static u32 msg[10]; + static char small_buf[100]; + void *src_ptr; + struct scatterlist *new_sg; + ssize_t copy_result; + struct ahash_request *req; + struct crypto_ahash *tfm; + struct sep_hash_ctx *ctx; + struct sep_system_ctx *sctx; + + req = (struct ahash_request *)data; + tfm = crypto_ahash_reqtfm(req); + ctx = ahash_request_ctx(req); + sctx = crypto_ahash_ctx(tfm); + + /* length for queue status */ + sctx->nbytes = req->nbytes; + + dev_dbg(&sctx->sep_used->pdev->dev, + "sep_hash_update\n"); + sctx->current_hash_stage = HASH_UPDATE; + len = req->nbytes; + + block_size = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm)); + tail_len = req->nbytes % block_size; + dev_dbg(&sctx->sep_used->pdev->dev, "length is %x\n", len); + dev_dbg(&sctx->sep_used->pdev->dev, "block_size is %x\n", block_size); + dev_dbg(&sctx->sep_used->pdev->dev, "tail len is %x\n", tail_len); + + /* Compute header/tail sizes */ + int_ctx = (struct sep_hash_internal_context *)&ctx-> + hash_private_ctx.internal_context; + head_len = (block_size - int_ctx->prev_update_bytes) % block_size; + tail_len = (req->nbytes - head_len) % block_size; + + /* Make sure all pages are even block */ + int_error = sep_oddball_pages(sctx->sep_used, req->src, + req->nbytes, + block_size, &new_sg, 1); + + if (int_error < 0) { + dev_warn(&sctx->sep_used->pdev->dev, + "oddball pages error in crash update\n"); + sep_crypto_release(sctx, -ENOMEM); + return; + } else if (int_error == 1) { + sctx->src_sg = new_sg; + sctx->src_sg_hold = new_sg; + } else { + sctx->src_sg = req->src; + sctx->src_sg_hold = NULL; + } + + src_ptr = sg_virt(sctx->src_sg); + + if ((!req->nbytes) || (!ctx->sg)) { + /* null data */ + src_ptr = NULL; + } + + sep_dump_sg(sctx->sep_used, "hash block sg in", sctx->src_sg); + + sctx->dcb_input_data.app_in_address = src_ptr; + sctx->dcb_input_data.data_in_size = req->nbytes - (head_len + tail_len); + sctx->dcb_input_data.app_out_address = NULL; + sctx->dcb_input_data.block_size = block_size; + sctx->dcb_input_data.tail_block_size = 0; + sctx->dcb_input_data.is_applet = 0; + sctx->dcb_input_data.src_sg = sctx->src_sg; + sctx->dcb_input_data.dst_sg = NULL; + + int_error = sep_create_dcb_dmatables_context_kernel( + sctx->sep_used, + &sctx->dcb_region, + &sctx->dmatables_region, + &sctx->dma_ctx, + &sctx->dcb_input_data, + 1); + if (int_error) { + dev_warn(&sctx->sep_used->pdev->dev, + "hash update dma table create failed\n"); + sep_crypto_release(sctx, -EINVAL); + return; + } + + /* Construct message to SEP */ + sep_make_header(sctx, &msg_offset, SEP_HASH_UPDATE_OPCODE); + + msg[0] = (u32)0; + msg[1] = (u32)0; + msg[2] = (u32)0; + + sep_write_msg(sctx, msg, sizeof(u32) * 3, sizeof(u32) * 3, + &msg_offset, 0); + + /* Handle remainders */ + + /* Head */ + sep_write_msg(sctx, &head_len, sizeof(u32), + sizeof(u32), &msg_offset, 0); + + if (head_len) { + copy_result = sg_copy_to_buffer( + req->src, + sep_sg_nents(sctx->src_sg), + small_buf, head_len); + + if (copy_result != head_len) { + dev_warn(&sctx->sep_used->pdev->dev, + "sg head copy failure in hash block\n"); + sep_crypto_release(sctx, -ENOMEM); + return; + } + + sep_write_msg(sctx, small_buf, head_len, + sizeof(u32) * 32, &msg_offset, 1); + } else { + msg_offset += sizeof(u32) * 32; + } + + /* Tail */ + sep_write_msg(sctx, &tail_len, sizeof(u32), + sizeof(u32), &msg_offset, 0); + + if (tail_len) { + copy_result = sep_copy_offset_sg( + sctx->sep_used, + sctx->src_sg, + req->nbytes - tail_len, + small_buf, tail_len); + + if (copy_result != tail_len) { + dev_warn(&sctx->sep_used->pdev->dev, + "sg tail copy failure in hash block\n"); + sep_crypto_release(sctx, -ENOMEM); + return; + } + + sep_write_msg(sctx, small_buf, tail_len, + sizeof(u32) * 32, &msg_offset, 1); + } else { + msg_offset += sizeof(u32) * 32; + } + + /* Context */ + sep_write_context(sctx, &msg_offset, &ctx->hash_private_ctx, + sizeof(struct sep_hash_private_context)); + + sep_end_msg(sctx, msg_offset); + sctx->done_with_transaction = 0; + int_error = sep_crypto_take_sep(sctx); + if (int_error) { + dev_warn(&sctx->sep_used->pdev->dev, + "sep_hash_update take sep failed\n"); + sep_crypto_release(sctx, -EINVAL); + } + + /** + * Sep is now working. Lets wait up to 5 seconds + * for completion. If it does not complete, we will do + * a crypto release with -EINVAL to release the + * kernel crypto infrastructure and let the system + * continue to boot up + * We have to wait this long because some crypto + * operations can take a while + */ + dev_dbg(&sctx->sep_used->pdev->dev, + "waiting for done with transaction\n"); + + sctx->end_time = jiffies + (SEP_TRANSACTION_WAIT_TIME * HZ); + while ((time_before(jiffies, sctx->end_time)) && + (!sctx->done_with_transaction)) + schedule(); + + dev_dbg(&sctx->sep_used->pdev->dev, + "done waiting for done with transaction\n"); + + /* are we done? */ + if (!sctx->done_with_transaction) { + /* Nope, lets release and tell crypto no */ + dev_warn(&sctx->sep_used->pdev->dev, + "[PID%d] sep_hash_update never finished\n", + current->pid); + sep_crypto_release(sctx, -EINVAL); + } +} + +static void sep_hash_final(void *data) +{ + u32 msg_offset; + struct ahash_request *req; + struct crypto_ahash *tfm; + struct sep_hash_ctx *ctx; + struct sep_system_ctx *sctx; + int result; + + req = (struct ahash_request *)data; + tfm = crypto_ahash_reqtfm(req); + ctx = ahash_request_ctx(req); + sctx = crypto_ahash_ctx(tfm); + + dev_dbg(&sctx->sep_used->pdev->dev, + "sep_hash_final\n"); + sctx->current_hash_stage = HASH_FINISH; + + /* opcode and mode */ + sep_make_header(sctx, &msg_offset, SEP_HASH_FINISH_OPCODE); + + /* Context */ + sep_write_context(sctx, &msg_offset, &ctx->hash_private_ctx, + sizeof(struct sep_hash_private_context)); + + sep_end_msg(sctx, msg_offset); + sctx->done_with_transaction = 0; + result = sep_crypto_take_sep(sctx); + if (result) { + dev_warn(&sctx->sep_used->pdev->dev, + "sep_hash_final take sep failed\n"); + sep_crypto_release(sctx, -EINVAL); + } + + /** + * Sep is now working. Lets wait up to 5 seconds + * for completion. If it does not complete, we will do + * a crypto release with -EINVAL to release the + * kernel crypto infrastructure and let the system + * continue to boot up + * We have to wait this long because some crypto + * operations can take a while + */ + dev_dbg(&sctx->sep_used->pdev->dev, + "waiting for done with transaction\n"); + + sctx->end_time = jiffies + (SEP_TRANSACTION_WAIT_TIME * HZ); + while ((time_before(jiffies, sctx->end_time)) && + (!sctx->done_with_transaction)) + schedule(); + + dev_dbg(&sctx->sep_used->pdev->dev, + "done waiting for done with transaction\n"); + + /* are we done? */ + if (!sctx->done_with_transaction) { + /* Nope, lets release and tell crypto no */ + dev_warn(&sctx->sep_used->pdev->dev, + "[PID%d] sep_hash_final never finished\n", + current->pid); + sep_crypto_release(sctx, -EINVAL); + } +} + +static void sep_hash_digest(void *data) +{ + int int_error; + u32 msg_offset; + u32 block_size; + u32 msg[10]; + size_t copy_result; + int result; + u32 tail_len; + static char small_buf[100]; + struct scatterlist *new_sg; + void *src_ptr; + + struct ahash_request *req; + struct crypto_ahash *tfm; + struct sep_hash_ctx *ctx; + struct sep_system_ctx *sctx; + + req = (struct ahash_request *)data; + tfm = crypto_ahash_reqtfm(req); + ctx = ahash_request_ctx(req); + sctx = crypto_ahash_ctx(tfm); + + dev_dbg(&sctx->sep_used->pdev->dev, + "sep_hash_digest\n"); + sctx->current_hash_stage = HASH_DIGEST; + + /* length for queue status */ + sctx->nbytes = req->nbytes; + + block_size = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm)); + tail_len = req->nbytes % block_size; + dev_dbg(&sctx->sep_used->pdev->dev, "length is %x\n", req->nbytes); + dev_dbg(&sctx->sep_used->pdev->dev, "block_size is %x\n", block_size); + dev_dbg(&sctx->sep_used->pdev->dev, "tail len is %x\n", tail_len); + + /* Make sure all pages are even block */ + int_error = sep_oddball_pages(sctx->sep_used, req->src, + req->nbytes, + block_size, &new_sg, 1); + + if (int_error < 0) { + dev_warn(&sctx->sep_used->pdev->dev, + "oddball pages error in crash update\n"); + sep_crypto_release(sctx, -ENOMEM); + return; + } else if (int_error == 1) { + sctx->src_sg = new_sg; + sctx->src_sg_hold = new_sg; + } else { + sctx->src_sg = req->src; + sctx->src_sg_hold = NULL; + } + + src_ptr = sg_virt(sctx->src_sg); + + if ((!req->nbytes) || (!ctx->sg)) { + /* null data */ + src_ptr = NULL; + } + + sep_dump_sg(sctx->sep_used, "hash block sg in", sctx->src_sg); + + sctx->dcb_input_data.app_in_address = src_ptr; + sctx->dcb_input_data.data_in_size = req->nbytes - tail_len; + sctx->dcb_input_data.app_out_address = NULL; + sctx->dcb_input_data.block_size = block_size; + sctx->dcb_input_data.tail_block_size = 0; + sctx->dcb_input_data.is_applet = 0; + sctx->dcb_input_data.src_sg = sctx->src_sg; + sctx->dcb_input_data.dst_sg = NULL; + + int_error = sep_create_dcb_dmatables_context_kernel( + sctx->sep_used, + &sctx->dcb_region, + &sctx->dmatables_region, + &sctx->dma_ctx, + &sctx->dcb_input_data, + 1); + if (int_error) { + dev_warn(&sctx->sep_used->pdev->dev, + "hash update dma table create failed\n"); + sep_crypto_release(sctx, -EINVAL); + return; + } + + /* Construct message to SEP */ + sep_make_header(sctx, &msg_offset, SEP_HASH_SINGLE_OPCODE); + sep_write_msg(sctx, &ctx->hash_opmode, + sizeof(u32), sizeof(u32), &msg_offset, 0); + + msg[0] = (u32)0; + msg[1] = (u32)0; + msg[2] = (u32)0; + + sep_write_msg(sctx, msg, sizeof(u32) * 3, sizeof(u32) * 3, + &msg_offset, 0); + + /* Tail */ + sep_write_msg(sctx, &tail_len, sizeof(u32), + sizeof(u32), &msg_offset, 0); + + if (tail_len) { + copy_result = sep_copy_offset_sg( + sctx->sep_used, + sctx->src_sg, + req->nbytes - tail_len, + small_buf, tail_len); + + if (copy_result != tail_len) { + dev_warn(&sctx->sep_used->pdev->dev, + "sg tail copy failure in hash block\n"); + sep_crypto_release(sctx, -ENOMEM); + return; + } + + sep_write_msg(sctx, small_buf, tail_len, + sizeof(u32) * 32, &msg_offset, 1); + } else { + msg_offset += sizeof(u32) * 32; + } + + sep_end_msg(sctx, msg_offset); + + sctx->done_with_transaction = 0; + + result = sep_crypto_take_sep(sctx); + if (result) { + dev_warn(&sctx->sep_used->pdev->dev, + "sep_hash_digest take sep failed\n"); + sep_crypto_release(sctx, -EINVAL); + } + + /** + * Sep is now working. Lets wait up to 5 seconds + * for completion. If it does not complete, we will do + * a crypto release with -EINVAL to release the + * kernel crypto infrastructure and let the system + * continue to boot up + * We have to wait this long because some crypto + * operations can take a while + */ + dev_dbg(&sctx->sep_used->pdev->dev, + "waiting for done with transaction\n"); + + sctx->end_time = jiffies + (SEP_TRANSACTION_WAIT_TIME * HZ); + while ((time_before(jiffies, sctx->end_time)) && + (!sctx->done_with_transaction)) + schedule(); + + dev_dbg(&sctx->sep_used->pdev->dev, + "done waiting for done with transaction\n"); + + /* are we done? */ + if (!sctx->done_with_transaction) { + /* Nope, lets release and tell crypto no */ + dev_warn(&sctx->sep_used->pdev->dev, + "[PID%d] sep_hash_digest never finished\n", + current->pid); + sep_crypto_release(sctx, -EINVAL); + } +} + +/** + * This is what is called by each of the API's provided + * in the kernel crypto descriptors. It is run in a process + * context using the kernel workqueues. Therefore it can + * be put to sleep. + */ +static void sep_dequeuer(void *data) +{ + struct crypto_queue *this_queue; + struct crypto_async_request *async_req; + struct crypto_async_request *backlog; + struct ablkcipher_request *cypher_req; + struct ahash_request *hash_req; + struct sep_system_ctx *sctx; + struct crypto_ahash *hash_tfm; + + + this_queue = (struct crypto_queue *)data; + + spin_lock_irq(&queue_lock); + backlog = crypto_get_backlog(this_queue); + async_req = crypto_dequeue_request(this_queue); + spin_unlock_irq(&queue_lock); + + if (!async_req) { + pr_debug("sep crypto queue is empty\n"); + return; + } + + if (backlog) { + pr_debug("sep crypto backlog set\n"); + if (backlog->complete) + backlog->complete(backlog, -EINPROGRESS); + backlog = NULL; + } + + if (!async_req->tfm) { + pr_debug("sep crypto queue null tfm\n"); + return; + } + + if (!async_req->tfm->__crt_alg) { + pr_debug("sep crypto queue null __crt_alg\n"); + return; + } + + if (!async_req->tfm->__crt_alg->cra_type) { + pr_debug("sep crypto queue null cra_type\n"); + return; + } + + /* we have stuff in the queue */ + if (async_req->tfm->__crt_alg->cra_type != + &crypto_ahash_type) { + /* This is for a cypher */ + pr_debug("sep crypto queue doing cipher\n"); + cypher_req = container_of(async_req, + struct ablkcipher_request, + base); + if (!cypher_req) { + pr_debug("sep crypto queue null cypher_req\n"); + return; + } + + sep_crypto_block((void *)cypher_req); + return; + } else { + /* This is a hash */ + pr_debug("sep crypto queue doing hash\n"); + /** + * This is a bit more complex than cipher; we + * need to figure out what type of operation + */ + hash_req = ahash_request_cast(async_req); + if (!hash_req) { + pr_debug("sep crypto queue null hash_req\n"); + return; + } + + hash_tfm = crypto_ahash_reqtfm(hash_req); + if (!hash_tfm) { + pr_debug("sep crypto queue null hash_tfm\n"); + return; + } + + + sctx = crypto_ahash_ctx(hash_tfm); + if (!sctx) { + pr_debug("sep crypto queue null sctx\n"); + return; + } + + if (sctx->current_hash_stage == HASH_INIT) { + pr_debug("sep crypto queue hash init\n"); + sep_hash_init((void *)hash_req); + return; + } else if (sctx->current_hash_stage == HASH_UPDATE) { + pr_debug("sep crypto queue hash update\n"); + sep_hash_update((void *)hash_req); + return; + } else if (sctx->current_hash_stage == HASH_FINISH) { + pr_debug("sep crypto queue hash final\n"); + sep_hash_final((void *)hash_req); + return; + } else if (sctx->current_hash_stage == HASH_DIGEST) { + pr_debug("sep crypto queue hash digest\n"); + sep_hash_digest((void *)hash_req); + return; + } else { + pr_debug("sep crypto queue hash oops nothing\n"); + return; + } + } +} + +static int sep_sha1_init(struct ahash_request *req) +{ + int error; + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct sep_hash_ctx *ctx = ahash_request_ctx(req); + struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); + + dev_dbg(&sctx->sep_used->pdev->dev, "doing sha1 init\n"); + sctx->current_request = SHA1; + sctx->current_hash_req = req; + sctx->current_cypher_req = NULL; + ctx->hash_opmode = SEP_HASH_SHA1; + sctx->current_hash_stage = HASH_INIT; + + spin_lock_irq(&queue_lock); + error = crypto_enqueue_request(&sep_queue, &req->base); + spin_unlock_irq(&queue_lock); + + if ((error != 0) && (error != -EINPROGRESS)) { + dev_warn(&sctx->sep_used->pdev->dev, + "sep sha1 init cant enqueue\n"); + sep_crypto_release(sctx, error); + return error; + } + + error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, + (void *)&sep_queue); + if (error) { + dev_warn(&sctx->sep_used->pdev->dev, + "sha1 init cannot submit queue\n"); + sep_crypto_release(sctx, -EINVAL); + return -EINVAL; + } + return -EINPROGRESS; +} + +static int sep_sha1_update(struct ahash_request *req) +{ + int error; + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct sep_hash_ctx *ctx = ahash_request_ctx(req); + struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); + + dev_dbg(&sctx->sep_used->pdev->dev, "doing sha1 update\n"); + sctx->current_request = SHA1; + sctx->current_hash_req = req; + sctx->current_cypher_req = NULL; + ctx->hash_opmode = SEP_HASH_SHA1; + sctx->current_hash_stage = HASH_INIT; + + spin_lock_irq(&queue_lock); + error = crypto_enqueue_request(&sep_queue, &req->base); + spin_unlock_irq(&queue_lock); + + if ((error != 0) && (error != -EINPROGRESS)) { + dev_warn(&sctx->sep_used->pdev->dev, + "sep sha1 update cant enqueue\n"); + sep_crypto_release(sctx, error); + return error; + } + + error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, + (void *)&sep_queue); + if (error) { + dev_warn(&sctx->sep_used->pdev->dev, + "sha1 update cannot submit queue\n"); + sep_crypto_release(sctx, -EINVAL); + return -EINVAL; + } + return -EINPROGRESS; +} + +static int sep_sha1_final(struct ahash_request *req) +{ + int error; + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct sep_hash_ctx *ctx = ahash_request_ctx(req); + struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); + dev_dbg(&sctx->sep_used->pdev->dev, "doing sha1 final\n"); + + sctx->current_request = SHA1; + sctx->current_hash_req = req; + sctx->current_cypher_req = NULL; + ctx->hash_opmode = SEP_HASH_SHA1; + sctx->current_hash_stage = HASH_FINISH; + + spin_lock_irq(&queue_lock); + error = crypto_enqueue_request(&sep_queue, &req->base); + spin_unlock_irq(&queue_lock); + + if ((error != 0) && (error != -EINPROGRESS)) { + dev_warn(&sctx->sep_used->pdev->dev, + "sep sha1 final cant enqueue\n"); + sep_crypto_release(sctx, error); + return error; + } + + error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, + (void *)&sep_queue); + if (error) { + dev_warn(&sctx->sep_used->pdev->dev, + "sha1 final cannot submit queue\n"); + sep_crypto_release(sctx, -EINVAL); + return -EINVAL; + } + return -EINPROGRESS; + +} + +static int sep_sha1_digest(struct ahash_request *req) +{ + int error; + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct sep_hash_ctx *ctx = ahash_request_ctx(req); + struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); + dev_dbg(&sctx->sep_used->pdev->dev, "doing sha1 digest\n"); + + sctx->current_request = SHA1; + sctx->current_hash_req = req; + sctx->current_cypher_req = NULL; + ctx->hash_opmode = SEP_HASH_SHA1; + sctx->current_hash_stage = HASH_DIGEST; + + spin_lock_irq(&queue_lock); + error = crypto_enqueue_request(&sep_queue, &req->base); + spin_unlock_irq(&queue_lock); + + if ((error != 0) && (error != -EINPROGRESS)) { + dev_warn(&sctx->sep_used->pdev->dev, + "sep sha1 digest cant enqueue\n"); + sep_crypto_release(sctx, error); + return error; + } + + error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, + (void *)&sep_queue); + if (error) { + dev_warn(&sctx->sep_used->pdev->dev, + "sha1 digest cannot submit queue\n"); + sep_crypto_release(sctx, -EINVAL); + return -EINVAL; + } + return -EINPROGRESS; + +} + +static int sep_md5_init(struct ahash_request *req) +{ + int error; + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct sep_hash_ctx *ctx = ahash_request_ctx(req); + struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); + dev_dbg(&sctx->sep_used->pdev->dev, "doing md5 init\n"); + + sctx->current_request = MD5; + sctx->current_hash_req = req; + sctx->current_cypher_req = NULL; + ctx->hash_opmode = SEP_HASH_MD5; + sctx->current_hash_stage = HASH_INIT; + + spin_lock_irq(&queue_lock); + error = crypto_enqueue_request(&sep_queue, &req->base); + spin_unlock_irq(&queue_lock); + + if ((error != 0) && (error != -EINPROGRESS)) { + dev_warn(&sctx->sep_used->pdev->dev, + "sep md5 init cant enqueue\n"); + sep_crypto_release(sctx, error); + return error; + } + + error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, + (void *)&sep_queue); + if (error) { + dev_warn(&sctx->sep_used->pdev->dev, + "md5 init cannot submit queue\n"); + sep_crypto_release(sctx, -EINVAL); + return -EINVAL; + } + return -EINPROGRESS; + +} + +static int sep_md5_update(struct ahash_request *req) +{ + int error; + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct sep_hash_ctx *ctx = ahash_request_ctx(req); + struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); + dev_dbg(&sctx->sep_used->pdev->dev, "doing md5 update\n"); + + sctx->current_request = MD5; + sctx->current_hash_req = req; + sctx->current_cypher_req = NULL; + ctx->hash_opmode = SEP_HASH_MD5; + sctx->current_hash_stage = HASH_UPDATE; + + spin_lock_irq(&queue_lock); + error = crypto_enqueue_request(&sep_queue, &req->base); + spin_unlock_irq(&queue_lock); + + if ((error != 0) && (error != -EINPROGRESS)) { + dev_warn(&sctx->sep_used->pdev->dev, + "md5 update cant enqueue\n"); + sep_crypto_release(sctx, error); + return error; + } + + error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, + (void *)&sep_queue); + if (error) { + dev_warn(&sctx->sep_used->pdev->dev, + "md5 update cannot submit queue\n"); + sep_crypto_release(sctx, -EINVAL); + return -EINVAL; + } + return -EINPROGRESS; +} + +static int sep_md5_final(struct ahash_request *req) +{ + int error; + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct sep_hash_ctx *ctx = ahash_request_ctx(req); + struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); + dev_dbg(&sctx->sep_used->pdev->dev, "doing md5 final\n"); + + sctx->current_request = MD5; + sctx->current_hash_req = req; + sctx->current_cypher_req = NULL; + ctx->hash_opmode = SEP_HASH_MD5; + sctx->current_hash_stage = HASH_FINISH; + + spin_lock_irq(&queue_lock); + error = crypto_enqueue_request(&sep_queue, &req->base); + spin_unlock_irq(&queue_lock); + + if ((error != 0) && (error != -EINPROGRESS)) { + dev_warn(&sctx->sep_used->pdev->dev, + "sep md5 final cant enqueue\n"); + sep_crypto_release(sctx, error); + return error; + } + + error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, + (void *)&sep_queue); + if (error) { + dev_warn(&sctx->sep_used->pdev->dev, + "md5 final cannot submit queue\n"); + sep_crypto_release(sctx, -EINVAL); + return -EINVAL; + } + return -EINPROGRESS; + +} + +static int sep_md5_digest(struct ahash_request *req) +{ + int error; + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct sep_hash_ctx *ctx = ahash_request_ctx(req); + struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); + + dev_dbg(&sctx->sep_used->pdev->dev, "doing md5 digest\n"); + sctx->current_request = MD5; + sctx->current_hash_req = req; + sctx->current_cypher_req = NULL; + ctx->hash_opmode = SEP_HASH_MD5; + sctx->current_hash_stage = HASH_DIGEST; + + spin_lock_irq(&queue_lock); + error = crypto_enqueue_request(&sep_queue, &req->base); + spin_unlock_irq(&queue_lock); + + if ((error != 0) && (error != -EINPROGRESS)) { + dev_warn(&sctx->sep_used->pdev->dev, + "sep md5 digest cant enqueue\n"); + sep_crypto_release(sctx, error); + return error; + } + + error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, + (void *)&sep_queue); + if (error) { + dev_warn(&sctx->sep_used->pdev->dev, + "md5 digest cannot submit queue\n"); + sep_crypto_release(sctx, -EINVAL); + return -EINVAL; + } + return -EINPROGRESS; +} + +static int sep_sha224_init(struct ahash_request *req) +{ + int error; + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct sep_hash_ctx *ctx = ahash_request_ctx(req); + struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); + dev_dbg(&sctx->sep_used->pdev->dev, "doing sha224 init\n"); + + sctx->current_request = SHA224; + sctx->current_hash_req = req; + sctx->current_cypher_req = NULL; + ctx->hash_opmode = SEP_HASH_SHA224; + sctx->current_hash_stage = HASH_INIT; + + spin_lock_irq(&queue_lock); + error = crypto_enqueue_request(&sep_queue, &req->base); + spin_unlock_irq(&queue_lock); + + if ((error != 0) && (error != -EINPROGRESS)) { + dev_warn(&sctx->sep_used->pdev->dev, + "sep sha224 init cant enqueue\n"); + sep_crypto_release(sctx, error); + return error; + } + + error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, + (void *)&sep_queue); + if (error) { + dev_warn(&sctx->sep_used->pdev->dev, + "sha224 init cannot submit queue\n"); + sep_crypto_release(sctx, -EINVAL); + return -EINVAL; + } + return -EINPROGRESS; +} + +static int sep_sha224_update(struct ahash_request *req) +{ + int error; + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct sep_hash_ctx *ctx = ahash_request_ctx(req); + struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); + dev_dbg(&sctx->sep_used->pdev->dev, "doing sha224 update\n"); + + sctx->current_request = SHA224; + sctx->current_hash_req = req; + sctx->current_cypher_req = NULL; + ctx->hash_opmode = SEP_HASH_SHA224; + sctx->current_hash_stage = HASH_UPDATE; + + spin_lock_irq(&queue_lock); + error = crypto_enqueue_request(&sep_queue, &req->base); + spin_unlock_irq(&queue_lock); + + if ((error != 0) && (error != -EINPROGRESS)) { + dev_warn(&sctx->sep_used->pdev->dev, + "sep sha224 update cant enqueue\n"); + sep_crypto_release(sctx, error); + return error; + } + + error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, + (void *)&sep_queue); + if (error) { + dev_warn(&sctx->sep_used->pdev->dev, + "sha224 update cannot submit queue\n"); + sep_crypto_release(sctx, -EINVAL); + return -EINVAL; + } + return -EINPROGRESS; +} + +static int sep_sha224_final(struct ahash_request *req) +{ + int error; + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct sep_hash_ctx *ctx = ahash_request_ctx(req); + struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); + dev_dbg(&sctx->sep_used->pdev->dev, "doing sha224 final\n"); + + sctx->current_request = SHA224; + sctx->current_hash_req = req; + sctx->current_cypher_req = NULL; + ctx->hash_opmode = SEP_HASH_SHA224; + sctx->current_hash_stage = HASH_FINISH; + + spin_lock_irq(&queue_lock); + error = crypto_enqueue_request(&sep_queue, &req->base); + spin_unlock_irq(&queue_lock); + + if ((error != 0) && (error != -EINPROGRESS)) { + dev_warn(&sctx->sep_used->pdev->dev, + "sep sha224 final cant enqueue\n"); + sep_crypto_release(sctx, error); + return error; + } + + error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, + (void *)&sep_queue); + if (error) { + dev_warn(&sctx->sep_used->pdev->dev, + "sha224 final cannot submit queue\n"); + sep_crypto_release(sctx, -EINVAL); + return -EINVAL; + } + return -EINPROGRESS; +} + +static int sep_sha224_digest(struct ahash_request *req) +{ + int error; + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct sep_hash_ctx *ctx = ahash_request_ctx(req); + struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); + + dev_dbg(&sctx->sep_used->pdev->dev, "doing 224 digest\n"); + sctx->current_request = SHA224; + sctx->current_hash_req = req; + sctx->current_cypher_req = NULL; + ctx->hash_opmode = SEP_HASH_SHA224; + sctx->current_hash_stage = HASH_DIGEST; + + spin_lock_irq(&queue_lock); + error = crypto_enqueue_request(&sep_queue, &req->base); + spin_unlock_irq(&queue_lock); + + if ((error != 0) && (error != -EINPROGRESS)) { + dev_warn(&sctx->sep_used->pdev->dev, + "sep sha224 digest cant enqueue\n"); + sep_crypto_release(sctx, error); + return error; + } + + error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, + (void *)&sep_queue); + if (error) { + dev_warn(&sctx->sep_used->pdev->dev, + "sha256 digest cannot submit queue\n"); + sep_crypto_release(sctx, -EINVAL); + return -EINVAL; + } + return -EINPROGRESS; +} + +static int sep_sha256_init(struct ahash_request *req) +{ + int error; + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct sep_hash_ctx *ctx = ahash_request_ctx(req); + struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); + dev_dbg(&sctx->sep_used->pdev->dev, "doing sha256 init\n"); + + sctx->current_request = SHA256; + sctx->current_hash_req = req; + sctx->current_cypher_req = NULL; + ctx->hash_opmode = SEP_HASH_SHA256; + sctx->current_hash_stage = HASH_INIT; + + spin_lock_irq(&queue_lock); + error = crypto_enqueue_request(&sep_queue, &req->base); + spin_unlock_irq(&queue_lock); + + if ((error != 0) && (error != -EINPROGRESS)) { + dev_warn(&sctx->sep_used->pdev->dev, + "sep sha256 init cant enqueue\n"); + sep_crypto_release(sctx, error); + return error; + } + + error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, + (void *)&sep_queue); + if (error) { + dev_warn(&sctx->sep_used->pdev->dev, + "sha256 init cannot submit queue\n"); + sep_crypto_release(sctx, -EINVAL); + return -EINVAL; + } + return -EINPROGRESS; +} + +static int sep_sha256_update(struct ahash_request *req) +{ + int error; + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct sep_hash_ctx *ctx = ahash_request_ctx(req); + struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); + dev_dbg(&sctx->sep_used->pdev->dev, "doing sha256 update\n"); + + sctx->current_request = SHA256; + sctx->current_hash_req = req; + sctx->current_cypher_req = NULL; + ctx->hash_opmode = SEP_HASH_SHA256; + sctx->current_hash_stage = HASH_UPDATE; + + spin_lock_irq(&queue_lock); + error = crypto_enqueue_request(&sep_queue, &req->base); + spin_unlock_irq(&queue_lock); + + if ((error != 0) && (error != -EINPROGRESS)) { + dev_warn(&sctx->sep_used->pdev->dev, + "sep sha256 update cant enqueue\n"); + sep_crypto_release(sctx, error); + return error; + } + + error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, + (void *)&sep_queue); + if (error) { + dev_warn(&sctx->sep_used->pdev->dev, + "sha256 update cannot submit queue\n"); + sep_crypto_release(sctx, -EINVAL); + return -EINVAL; + } + return -EINPROGRESS; +} + +static int sep_sha256_final(struct ahash_request *req) +{ + int error; + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct sep_hash_ctx *ctx = ahash_request_ctx(req); + struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); + dev_dbg(&sctx->sep_used->pdev->dev, "doing sha256 final\n"); + + sctx->current_request = SHA256; + sctx->current_hash_req = req; + sctx->current_cypher_req = NULL; + ctx->hash_opmode = SEP_HASH_SHA256; + sctx->current_hash_stage = HASH_FINISH; + + spin_lock_irq(&queue_lock); + error = crypto_enqueue_request(&sep_queue, &req->base); + spin_unlock_irq(&queue_lock); + + if ((error != 0) && (error != -EINPROGRESS)) { + dev_warn(&sctx->sep_used->pdev->dev, + "sep sha256 final cant enqueue\n"); + sep_crypto_release(sctx, error); + return error; + } + + error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, + (void *)&sep_queue); + if (error) { + dev_warn(&sctx->sep_used->pdev->dev, + "sha256 final cannot submit queue\n"); + sep_crypto_release(sctx, -EINVAL); + return -EINVAL; + } + return -EINPROGRESS; +} + +static int sep_sha256_digest(struct ahash_request *req) +{ + int error; + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct sep_hash_ctx *ctx = ahash_request_ctx(req); + struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); + + dev_dbg(&sctx->sep_used->pdev->dev, "doing sha256 digest\n"); + sctx->current_request = SHA256; + sctx->current_hash_req = req; + sctx->current_cypher_req = NULL; + ctx->hash_opmode = SEP_HASH_SHA256; + sctx->current_hash_stage = HASH_DIGEST; + + spin_lock_irq(&queue_lock); + error = crypto_enqueue_request(&sep_queue, &req->base); + spin_unlock_irq(&queue_lock); + + if ((error != 0) && (error != -EINPROGRESS)) { + dev_warn(&sctx->sep_used->pdev->dev, + "sep sha256 digest cant enqueue\n"); + sep_crypto_release(sctx, error); + return error; + } + + error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, + (void *)&sep_queue); + if (error) { + dev_warn(&sctx->sep_used->pdev->dev, + "sha256 digest cannot submit queue\n"); + sep_crypto_release(sctx, -EINVAL); + return -EINVAL; + } + return -EINPROGRESS; +} + +static int sep_crypto_init(struct crypto_tfm *tfm) +{ + struct sep_system_ctx *sctx = crypto_tfm_ctx(tfm); + const char *alg_name = crypto_tfm_alg_name(tfm); + + sctx->sep_used = sep_dev; + + if (alg_name == NULL) + dev_dbg(&sctx->sep_used->pdev->dev, "alg is NULL\n"); + else + dev_dbg(&sctx->sep_used->pdev->dev, "alg is %s\n", alg_name); + + tfm->crt_ablkcipher.reqsize = sizeof(struct sep_block_ctx); + dev_dbg(&sctx->sep_used->pdev->dev, "sep_crypto_init\n"); + return 0; +} + +static void sep_crypto_exit(struct crypto_tfm *tfm) +{ + struct sep_system_ctx *sctx = crypto_tfm_ctx(tfm); + dev_dbg(&sctx->sep_used->pdev->dev, "sep_crypto_exit\n"); + sctx->sep_used = NULL; +} + +static int sep_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key, + unsigned int keylen) +{ + struct sep_system_ctx *sctx = crypto_ablkcipher_ctx(tfm); + + dev_dbg(&sctx->sep_used->pdev->dev, "sep aes setkey\n"); + + switch (keylen) { + case SEP_AES_KEY_128_SIZE: + sctx->aes_key_size = AES_128; + break; + case SEP_AES_KEY_192_SIZE: + sctx->aes_key_size = AES_192; + break; + case SEP_AES_KEY_256_SIZE: + sctx->aes_key_size = AES_256; + break; + case SEP_AES_KEY_512_SIZE: + sctx->aes_key_size = AES_512; + break; + default: + dev_warn(&sctx->sep_used->pdev->dev, "sep aes key size %x\n", + keylen); + return -EINVAL; + } + + memset(&sctx->key.aes, 0, sizeof(u32) * + SEP_AES_MAX_KEY_SIZE_WORDS); + memcpy(&sctx->key.aes, key, keylen); + sctx->keylen = keylen; + /* Indicate to encrypt/decrypt function to send key to SEP */ + sctx->key_sent = 0; + sctx->last_block = 0; + + return 0; +} + +static int sep_aes_ecb_encrypt(struct ablkcipher_request *req) +{ + int error; + struct sep_block_ctx *bctx = ablkcipher_request_ctx(req); + struct sep_system_ctx *sctx = crypto_ablkcipher_ctx( + crypto_ablkcipher_reqtfm(req)); + + dev_dbg(&sctx->sep_used->pdev->dev, "sep aes ecb encrypt\n"); + sctx->current_request = AES_ECB; + sctx->current_hash_req = NULL; + sctx->current_cypher_req = req; + bctx->aes_encmode = SEP_AES_ENCRYPT; + bctx->aes_opmode = SEP_AES_ECB; + bctx->init_opcode = SEP_AES_INIT_OPCODE; + bctx->block_opcode = SEP_AES_BLOCK_OPCODE; + + spin_lock_irq(&queue_lock); + error = crypto_enqueue_request(&sep_queue, &req->base); + spin_unlock_irq(&queue_lock); + + if ((error != 0) && (error != -EINPROGRESS)) { + dev_warn(&sctx->sep_used->pdev->dev, + "sep_aes_ecb_encrypt cant enqueue\n"); + sep_crypto_release(sctx, error); + return error; + } + + error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, + (void *)&sep_queue); + if (error) { + dev_warn(&sctx->sep_used->pdev->dev, + "sep_aes_ecb_encrypt cannot submit queue\n"); + sep_crypto_release(sctx, -EINVAL); + return -EINVAL; + } + return -EINPROGRESS; +} + +static int sep_aes_ecb_decrypt(struct ablkcipher_request *req) +{ + int error; + struct sep_block_ctx *bctx = ablkcipher_request_ctx(req); + struct sep_system_ctx *sctx = crypto_ablkcipher_ctx( + crypto_ablkcipher_reqtfm(req)); + + dev_dbg(&sctx->sep_used->pdev->dev, "sep aes ecb decrypt\n"); + sctx->current_request = AES_ECB; + sctx->current_hash_req = NULL; + sctx->current_cypher_req = req; + bctx->aes_encmode = SEP_AES_DECRYPT; + bctx->aes_opmode = SEP_AES_ECB; + bctx->init_opcode = SEP_AES_INIT_OPCODE; + bctx->block_opcode = SEP_AES_BLOCK_OPCODE; + + spin_lock_irq(&queue_lock); + error = crypto_enqueue_request(&sep_queue, &req->base); + spin_unlock_irq(&queue_lock); + + if ((error != 0) && (error != -EINPROGRESS)) { + dev_warn(&sctx->sep_used->pdev->dev, + "sep_aes_ecb_decrypt cant enqueue\n"); + sep_crypto_release(sctx, error); + return error; + } + + error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, + (void *)&sep_queue); + if (error) { + dev_warn(&sctx->sep_used->pdev->dev, + "sep_aes_ecb_decrypt cannot submit queue\n"); + sep_crypto_release(sctx, -EINVAL); + return -EINVAL; + } + return -EINPROGRESS; +} + +static int sep_aes_cbc_encrypt(struct ablkcipher_request *req) +{ + int error; + struct sep_block_ctx *bctx = ablkcipher_request_ctx(req); + struct sep_system_ctx *sctx = crypto_ablkcipher_ctx( + crypto_ablkcipher_reqtfm(req)); + + dev_dbg(&sctx->sep_used->pdev->dev, "sep aes cbc encrypt\n"); + sctx->current_request = AES_CBC; + sctx->current_hash_req = NULL; + sctx->current_cypher_req = req; + bctx->aes_encmode = SEP_AES_ENCRYPT; + bctx->aes_opmode = SEP_AES_CBC; + bctx->init_opcode = SEP_AES_INIT_OPCODE; + bctx->block_opcode = SEP_AES_BLOCK_OPCODE; + + spin_lock_irq(&queue_lock); + error = crypto_enqueue_request(&sep_queue, &req->base); + spin_unlock_irq(&queue_lock); + + if ((error != 0) && (error != -EINPROGRESS)) { + dev_warn(&sctx->sep_used->pdev->dev, + "sep_aes_cbc_encrypt cant enqueue\n"); + sep_crypto_release(sctx, error); + return error; + } + + error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, + (void *)&sep_queue); + if (error) { + dev_warn(&sctx->sep_used->pdev->dev, + "sep_aes_cbc_encrypt cannot submit queue\n"); + sep_crypto_release(sctx, -EINVAL); + return -EINVAL; + } + return -EINPROGRESS; +} + +static int sep_aes_cbc_decrypt(struct ablkcipher_request *req) +{ + int error; + struct sep_block_ctx *bctx = ablkcipher_request_ctx(req); + struct sep_system_ctx *sctx = crypto_ablkcipher_ctx( + crypto_ablkcipher_reqtfm(req)); + + dev_dbg(&sctx->sep_used->pdev->dev, "sep aes cbc decrypt\n"); + sctx->current_request = AES_CBC; + sctx->current_hash_req = NULL; + sctx->current_cypher_req = req; + bctx->aes_encmode = SEP_AES_DECRYPT; + bctx->aes_opmode = SEP_AES_CBC; + bctx->init_opcode = SEP_AES_INIT_OPCODE; + bctx->block_opcode = SEP_AES_BLOCK_OPCODE; + + spin_lock_irq(&queue_lock); + error = crypto_enqueue_request(&sep_queue, &req->base); + spin_unlock_irq(&queue_lock); + + if ((error != 0) && (error != -EINPROGRESS)) { + dev_warn(&sctx->sep_used->pdev->dev, + "sep_aes_cbc_decrypt cant enqueue\n"); + sep_crypto_release(sctx, error); + return error; + } + + error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, + (void *)&sep_queue); + if (error) { + dev_warn(&sctx->sep_used->pdev->dev, + "sep_aes_cbc_decrypt cannot submit queue\n"); + sep_crypto_release(sctx, -EINVAL); + return -EINVAL; + } + return -EINPROGRESS; +} + +static int sep_des_setkey(struct crypto_ablkcipher *tfm, const u8 *key, + unsigned int keylen) +{ + struct sep_system_ctx *sctx = crypto_ablkcipher_ctx(tfm); + struct crypto_tfm *ctfm = crypto_ablkcipher_tfm(tfm); + u32 *flags = &ctfm->crt_flags; + + dev_dbg(&sctx->sep_used->pdev->dev, "sep des setkey\n"); + + switch (keylen) { + case DES_KEY_SIZE: + sctx->des_nbr_keys = DES_KEY_1; + break; + case DES_KEY_SIZE * 2: + sctx->des_nbr_keys = DES_KEY_2; + break; + case DES_KEY_SIZE * 3: + sctx->des_nbr_keys = DES_KEY_3; + break; + default: + dev_dbg(&sctx->sep_used->pdev->dev, "invalid key size %x\n", + keylen); + return -EINVAL; + } + + if ((*flags & CRYPTO_TFM_REQ_WEAK_KEY) && + (sep_weak_key(key, keylen))) { + + *flags |= CRYPTO_TFM_RES_WEAK_KEY; + dev_warn(&sctx->sep_used->pdev->dev, "weak key\n"); + return -EINVAL; + } + + memset(&sctx->key.des, 0, sizeof(struct sep_des_key)); + memcpy(&sctx->key.des.key1, key, keylen); + sctx->keylen = keylen; + /* Indicate to encrypt/decrypt function to send key to SEP */ + sctx->key_sent = 0; + sctx->last_block = 0; + + return 0; +} + +static int sep_des_ebc_encrypt(struct ablkcipher_request *req) +{ + int error; + struct sep_block_ctx *bctx = ablkcipher_request_ctx(req); + struct sep_system_ctx *sctx = crypto_ablkcipher_ctx( + crypto_ablkcipher_reqtfm(req)); + + dev_dbg(&sctx->sep_used->pdev->dev, "sep des ecb encrypt\n"); + sctx->current_request = DES_ECB; + sctx->current_hash_req = NULL; + sctx->current_cypher_req = req; + bctx->des_encmode = SEP_DES_ENCRYPT; + bctx->des_opmode = SEP_DES_ECB; + bctx->init_opcode = SEP_DES_INIT_OPCODE; + bctx->block_opcode = SEP_DES_BLOCK_OPCODE; + + spin_lock_irq(&queue_lock); + error = crypto_enqueue_request(&sep_queue, &req->base); + spin_unlock_irq(&queue_lock); + + if ((error != 0) && (error != -EINPROGRESS)) { + dev_warn(&sctx->sep_used->pdev->dev, + "sep_des_ecb_encrypt cant enqueue\n"); + sep_crypto_release(sctx, error); + return error; + } + + error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, + (void *)&sep_queue); + if (error) { + dev_warn(&sctx->sep_used->pdev->dev, + "sep_des_ecb_encrypt cannot submit queue\n"); + sep_crypto_release(sctx, -EINVAL); + return -EINVAL; + } + return -EINPROGRESS; +} + +static int sep_des_ebc_decrypt(struct ablkcipher_request *req) +{ + int error; + struct sep_block_ctx *bctx = ablkcipher_request_ctx(req); + struct sep_system_ctx *sctx = crypto_ablkcipher_ctx( + crypto_ablkcipher_reqtfm(req)); + + dev_dbg(&sctx->sep_used->pdev->dev, "sep des ecb decrypt\n"); + sctx->current_request = DES_ECB; + sctx->current_hash_req = NULL; + sctx->current_cypher_req = req; + bctx->des_encmode = SEP_DES_DECRYPT; + bctx->des_opmode = SEP_DES_ECB; + bctx->init_opcode = SEP_DES_INIT_OPCODE; + bctx->block_opcode = SEP_DES_BLOCK_OPCODE; + + spin_lock_irq(&queue_lock); + error = crypto_enqueue_request(&sep_queue, &req->base); + spin_unlock_irq(&queue_lock); + + if ((error != 0) && (error != -EINPROGRESS)) { + dev_warn(&sctx->sep_used->pdev->dev, + "sep_des_ecb_decrypt cant enqueue\n"); + sep_crypto_release(sctx, error); + return error; + } + + error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, + (void *)&sep_queue); + if (error) { + dev_warn(&sctx->sep_used->pdev->dev, + "sep_des_ecb_decrypt cannot submit queue\n"); + sep_crypto_release(sctx, -EINVAL); + return -EINVAL; + } + return -EINPROGRESS; +} + +static int sep_des_cbc_encrypt(struct ablkcipher_request *req) +{ + int error; + struct sep_block_ctx *bctx = ablkcipher_request_ctx(req); + struct sep_system_ctx *sctx = crypto_ablkcipher_ctx( + crypto_ablkcipher_reqtfm(req)); + + dev_dbg(&sctx->sep_used->pdev->dev, "sep des cbc encrypt\n"); + sctx->current_request = DES_CBC; + sctx->current_hash_req = NULL; + sctx->current_cypher_req = req; + bctx->des_encmode = SEP_DES_ENCRYPT; + bctx->des_opmode = SEP_DES_CBC; + bctx->init_opcode = SEP_DES_INIT_OPCODE; + bctx->block_opcode = SEP_DES_BLOCK_OPCODE; + + spin_lock_irq(&queue_lock); + error = crypto_enqueue_request(&sep_queue, &req->base); + spin_unlock_irq(&queue_lock); + + if ((error != 0) && (error != -EINPROGRESS)) { + dev_warn(&sctx->sep_used->pdev->dev, + "sep_des_cbc_encrypt cant enqueue\n"); + sep_crypto_release(sctx, error); + return error; + } + + error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, + (void *)&sep_queue); + if (error) { + dev_warn(&sctx->sep_used->pdev->dev, + "sep_des_cbc_encrypt cannot submit queue\n"); + sep_crypto_release(sctx, -EINVAL); + return -EINVAL; + } + return -EINPROGRESS; +} + +static int sep_des_cbc_decrypt(struct ablkcipher_request *req) +{ + int error; + struct sep_block_ctx *bctx = ablkcipher_request_ctx(req); + struct sep_system_ctx *sctx = crypto_ablkcipher_ctx( + crypto_ablkcipher_reqtfm(req)); + + dev_dbg(&sctx->sep_used->pdev->dev, "sep des cbc decrypt\n"); + sctx->current_request = DES_CBC; + sctx->current_hash_req = NULL; + sctx->current_cypher_req = req; + bctx->des_encmode = SEP_DES_DECRYPT; + bctx->des_opmode = SEP_DES_CBC; + bctx->init_opcode = SEP_DES_INIT_OPCODE; + bctx->block_opcode = SEP_DES_BLOCK_OPCODE; + + spin_lock_irq(&queue_lock); + error = crypto_enqueue_request(&sep_queue, &req->base); + spin_unlock_irq(&queue_lock); + + if ((error != 0) && (error != -EINPROGRESS)) { + dev_warn(&sctx->sep_used->pdev->dev, + "sep_des_cbc_decrypt cant enqueue\n"); + sep_crypto_release(sctx, error); + return error; + } + + error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, + (void *)&sep_queue); + if (error) { + dev_warn(&sctx->sep_used->pdev->dev, + "sep_des_cbc_decrypt cannot submit queue\n"); + sep_crypto_release(sctx, -EINVAL); + return -EINVAL; + } + return -EINPROGRESS; +} + +static struct ahash_alg hash_algs[] = { +{ + .init = sep_sha1_init, + .update = sep_sha1_update, + .final = sep_sha1_final, + .digest = sep_sha1_digest, + .halg = { + .digestsize = SHA1_DIGEST_SIZE, + .base = { + .cra_name = "sha1", + .cra_driver_name = "sha1-sep", + .cra_priority = 100, + .cra_flags = CRYPTO_ALG_TYPE_AHASH | + CRYPTO_ALG_ASYNC, + .cra_blocksize = SHA1_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct sep_system_ctx), + .cra_alignmask = 0, + .cra_module = THIS_MODULE, + .cra_init = sep_hash_cra_init, + .cra_exit = sep_hash_cra_exit, + } + } +}, +{ + .init = sep_md5_init, + .update = sep_md5_update, + .final = sep_md5_final, + .digest = sep_md5_digest, + .halg = { + .digestsize = MD5_DIGEST_SIZE, + .base = { + .cra_name = "md5", + .cra_driver_name = "md5-sep", + .cra_priority = 100, + .cra_flags = CRYPTO_ALG_TYPE_AHASH | + CRYPTO_ALG_ASYNC, + .cra_blocksize = SHA1_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct sep_system_ctx), + .cra_alignmask = 0, + .cra_module = THIS_MODULE, + .cra_init = sep_hash_cra_init, + .cra_exit = sep_hash_cra_exit, + } + } +}, +{ + .init = sep_sha224_init, + .update = sep_sha224_update, + .final = sep_sha224_final, + .digest = sep_sha224_digest, + .halg = { + .digestsize = SHA224_DIGEST_SIZE, + .base = { + .cra_name = "sha224", + .cra_driver_name = "sha224-sep", + .cra_priority = 100, + .cra_flags = CRYPTO_ALG_TYPE_AHASH | + CRYPTO_ALG_ASYNC, + .cra_blocksize = SHA224_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct sep_system_ctx), + .cra_alignmask = 0, + .cra_module = THIS_MODULE, + .cra_init = sep_hash_cra_init, + .cra_exit = sep_hash_cra_exit, + } + } +}, +{ + .init = sep_sha256_init, + .update = sep_sha256_update, + .final = sep_sha256_final, + .digest = sep_sha256_digest, + .halg = { + .digestsize = SHA256_DIGEST_SIZE, + .base = { + .cra_name = "sha256", + .cra_driver_name = "sha256-sep", + .cra_priority = 100, + .cra_flags = CRYPTO_ALG_TYPE_AHASH | + CRYPTO_ALG_ASYNC, + .cra_blocksize = SHA256_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct sep_system_ctx), + .cra_alignmask = 0, + .cra_module = THIS_MODULE, + .cra_init = sep_hash_cra_init, + .cra_exit = sep_hash_cra_exit, + } + } +} +}; + +static struct crypto_alg crypto_algs[] = { +{ + .cra_name = "ecb(aes)", + .cra_driver_name = "ecb-aes-sep", + .cra_priority = 100, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = AES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct sep_system_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_init = sep_crypto_init, + .cra_exit = sep_crypto_exit, + .cra_u.ablkcipher = { + .min_keysize = AES_MIN_KEY_SIZE, + .max_keysize = AES_MAX_KEY_SIZE, + .setkey = sep_aes_setkey, + .encrypt = sep_aes_ecb_encrypt, + .decrypt = sep_aes_ecb_decrypt, + } +}, +{ + .cra_name = "cbc(aes)", + .cra_driver_name = "cbc-aes-sep", + .cra_priority = 100, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = AES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct sep_system_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_init = sep_crypto_init, + .cra_exit = sep_crypto_exit, + .cra_u.ablkcipher = { + .min_keysize = AES_MIN_KEY_SIZE, + .max_keysize = AES_MAX_KEY_SIZE, + .setkey = sep_aes_setkey, + .encrypt = sep_aes_cbc_encrypt, + .decrypt = sep_aes_cbc_decrypt, + } +}, +{ + .cra_name = "ebc(des)", + .cra_driver_name = "ebc-des-sep", + .cra_priority = 100, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = DES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct sep_system_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_init = sep_crypto_init, + .cra_exit = sep_crypto_exit, + .cra_u.ablkcipher = { + .min_keysize = DES_KEY_SIZE, + .max_keysize = DES_KEY_SIZE, + .setkey = sep_des_setkey, + .encrypt = sep_des_ebc_encrypt, + .decrypt = sep_des_ebc_decrypt, + } +}, +{ + .cra_name = "cbc(des)", + .cra_driver_name = "cbc-des-sep", + .cra_priority = 100, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = DES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct sep_system_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_init = sep_crypto_init, + .cra_exit = sep_crypto_exit, + .cra_u.ablkcipher = { + .min_keysize = DES_KEY_SIZE, + .max_keysize = DES_KEY_SIZE, + .setkey = sep_des_setkey, + .encrypt = sep_des_cbc_encrypt, + .decrypt = sep_des_cbc_decrypt, + } +}, +{ + .cra_name = "ebc(des3-ede)", + .cra_driver_name = "ebc-des3-ede-sep", + .cra_priority = 100, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = DES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct sep_system_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_init = sep_crypto_init, + .cra_exit = sep_crypto_exit, + .cra_u.ablkcipher = { + .min_keysize = DES3_EDE_KEY_SIZE, + .max_keysize = DES3_EDE_KEY_SIZE, + .setkey = sep_des_setkey, + .encrypt = sep_des_ebc_encrypt, + .decrypt = sep_des_ebc_decrypt, + } +}, +{ + .cra_name = "cbc(des3-ede)", + .cra_driver_name = "cbc-des3--ede-sep", + .cra_priority = 100, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = DES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct sep_system_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_init = sep_crypto_init, + .cra_exit = sep_crypto_exit, + .cra_u.ablkcipher = { + .min_keysize = DES3_EDE_KEY_SIZE, + .max_keysize = DES3_EDE_KEY_SIZE, + .setkey = sep_des_setkey, + .encrypt = sep_des_cbc_encrypt, + .decrypt = sep_des_cbc_decrypt, + } +} +}; + +int sep_crypto_setup(void) +{ + int err, i, j, k; + tasklet_init(&sep_dev->finish_tasklet, sep_finish, + (unsigned long)sep_dev); + + crypto_init_queue(&sep_queue, SEP_QUEUE_LENGTH); + + sep_dev->workqueue = create_workqueue("sep_crypto_workqueue"); + if (!sep_dev->workqueue) { + dev_warn(&sep_dev->pdev->dev, "cant create workqueue\n"); + return -ENOMEM; + } + + i = 0; + j = 0; + + spin_lock_init(&sep_dev->busy_lock); + spin_lock_init(&queue_lock); + + err = 0; + + for (i = 0; i < ARRAY_SIZE(hash_algs); i++) { + err = crypto_register_ahash(&hash_algs[i]); + if (err) + goto err_algs; + } + + err = 0; + for (j = 0; j < ARRAY_SIZE(crypto_algs); j++) { + err = crypto_register_alg(&crypto_algs[j]); + if (err) + goto err_crypto_algs; + } + + return err; + +err_algs: + for (k = 0; k < i; k++) + crypto_unregister_ahash(&hash_algs[k]); + return err; + +err_crypto_algs: + for (k = 0; k < j; k++) + crypto_unregister_alg(&crypto_algs[k]); + goto err_algs; +} + +void sep_crypto_takedown(void) +{ + + int i; + + for (i = 0; i < ARRAY_SIZE(hash_algs); i++) + crypto_unregister_ahash(&hash_algs[i]); + for (i = 0; i < ARRAY_SIZE(crypto_algs); i++) + crypto_unregister_alg(&crypto_algs[i]); + + tasklet_kill(&sep_dev->finish_tasklet); +} diff --git a/drivers/staging/sep/sep_crypto.h b/drivers/staging/sep/sep_crypto.h new file mode 100644 index 0000000..52c58c4 --- /dev/null +++ b/drivers/staging/sep/sep_crypto.h @@ -0,0 +1,348 @@ +/* + * + * sep_crypto.h - Crypto interface structures + * + * Copyright(c) 2009-2011 Intel Corporation. All rights reserved. + * Contributions(c) 2009-2010 Discretix. All rights reserved. + * + * 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; version 2 of the License. + * + * 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., 59 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * CONTACTS: + * + * Mark Allyn mark.a.allyn@intel.com + * Jayant Mangalampalli jayant.mangalampalli@intel.com + * + * CHANGES: + * + * 2009.06.26 Initial publish + * 2011.02.22 Enable Kernel Crypto + * + */ + +/* Constants for SEP (from vendor) */ +#define SEP_START_MSG_TOKEN 0x02558808 + +#define SEP_DES_IV_SIZE_WORDS 2 +#define SEP_DES_IV_SIZE_BYTES (SEP_DES_IV_SIZE_WORDS * \ + sizeof(u32)) +#define SEP_DES_KEY_SIZE_WORDS 2 +#define SEP_DES_KEY_SIZE_BYTES (SEP_DES_KEY_SIZE_WORDS * \ + sizeof(u32)) +#define SEP_DES_BLOCK_SIZE 8 +#define SEP_DES_DUMMY_SIZE 16 + +#define SEP_DES_INIT_OPCODE 0x10 +#define SEP_DES_BLOCK_OPCODE 0x11 + +#define SEP_AES_BLOCK_SIZE_WORDS 4 +#define SEP_AES_BLOCK_SIZE_BYTES \ + (SEP_AES_BLOCK_SIZE_WORDS * sizeof(u32)) + +#define SEP_AES_DUMMY_BLOCK_SIZE 16 +#define SEP_AES_IV_SIZE_WORDS SEP_AES_BLOCK_SIZE_WORDS +#define SEP_AES_IV_SIZE_BYTES \ + (SEP_AES_IV_SIZE_WORDS * sizeof(u32)) + +#define SEP_AES_KEY_128_SIZE 16 +#define SEP_AES_KEY_192_SIZE 24 +#define SEP_AES_KEY_256_SIZE 32 +#define SEP_AES_KEY_512_SIZE 64 +#define SEP_AES_MAX_KEY_SIZE_WORDS 16 +#define SEP_AES_MAX_KEY_SIZE_BYTES \ + (SEP_AES_MAX_KEY_SIZE_WORDS * sizeof(u32)) + +#define SEP_AES_WRAP_MIN_SIZE 8 +#define SEP_AES_WRAP_MAX_SIZE 0x10000000 + +#define SEP_AES_WRAP_BLOCK_SIZE_WORDS 2 +#define SEP_AES_WRAP_BLOCK_SIZE_BYTES \ + (SEP_AES_WRAP_BLOCK_SIZE_WORDS * sizeof(u32)) + +#define SEP_AES_SECRET_RKEK1 0x1 +#define SEP_AES_SECRET_RKEK2 0x2 + +#define SEP_AES_INIT_OPCODE 0x2 +#define SEP_AES_BLOCK_OPCODE 0x3 +#define SEP_AES_FINISH_OPCODE 0x4 +#define SEP_AES_WRAP_OPCODE 0x6 +#define SEP_AES_UNWRAP_OPCODE 0x7 +#define SEP_AES_XTS_FINISH_OPCODE 0x8 + +#define SEP_HASH_RESULT_SIZE_WORDS 16 +#define SEP_MD5_DIGEST_SIZE_WORDS 4 +#define SEP_MD5_DIGEST_SIZE_BYTES \ + (SEP_MD5_DIGEST_SIZE_WORDS * sizeof(u32)) +#define SEP_SHA1_DIGEST_SIZE_WORDS 5 +#define SEP_SHA1_DIGEST_SIZE_BYTES \ + (SEP_SHA1_DIGEST_SIZE_WORDS * sizeof(u32)) +#define SEP_SHA224_DIGEST_SIZE_WORDS 7 +#define SEP_SHA224_DIGEST_SIZE_BYTES \ + (SEP_SHA224_DIGEST_SIZE_WORDS * sizeof(u32)) +#define SEP_SHA256_DIGEST_SIZE_WORDS 8 +#define SEP_SHA256_DIGEST_SIZE_BYTES \ + (SEP_SHA256_DIGEST_SIZE_WORDS * sizeof(u32)) +#define SEP_SHA384_DIGEST_SIZE_WORDS 12 +#define SEP_SHA384_DIGEST_SIZE_BYTES \ + (SEP_SHA384_DIGEST_SIZE_WORDS * sizeof(u32)) +#define SEP_SHA512_DIGEST_SIZE_WORDS 16 +#define SEP_SHA512_DIGEST_SIZE_BYTES \ + (SEP_SHA512_DIGEST_SIZE_WORDS * sizeof(u32)) +#define SEP_HASH_BLOCK_SIZE_WORDS 16 +#define SEP_HASH_BLOCK_SIZE_BYTES \ + (SEP_HASH_BLOCK_SIZE_WORDS * sizeof(u32)) +#define SEP_SHA2_BLOCK_SIZE_WORDS 32 +#define SEP_SHA2_BLOCK_SIZE_BYTES \ + (SEP_SHA2_BLOCK_SIZE_WORDS * sizeof(u32)) + +#define SEP_HASH_INIT_OPCODE 0x20 +#define SEP_HASH_UPDATE_OPCODE 0x21 +#define SEP_HASH_FINISH_OPCODE 0x22 +#define SEP_HASH_SINGLE_OPCODE 0x23 + +#define SEP_HOST_ERROR 0x0b000000 +#define SEP_OK 0x0 +#define SEP_INVALID_START (SEP_HOST_ERROR + 0x3) +#define SEP_WRONG_OPCODE (SEP_HOST_ERROR + 0x1) + +#define SEP_TRANSACTION_WAIT_TIME 5 + +#define SEP_QUEUE_LENGTH 10 +/* Macros */ +#ifndef __LITTLE_ENDIAN +#define CHG_ENDIAN(val) \ + (((val) >> 24) | \ + (((val) & 0x00FF0000) >> 8) | \ + (((val) & 0x0000FF00) << 8) | \ + (((val) & 0x000000FF) << 24)) +#else +#define CHG_ENDIAN(val) val +#endif +/* Enums for SEP (from vendor) */ +enum des_numkey { + DES_KEY_1 = 1, + DES_KEY_2 = 2, + DES_KEY_3 = 3, + SEP_NUMKEY_OPTIONS, + SEP_NUMKEY_LAST = 0x7fffffff, +}; + +enum des_enc_mode { + SEP_DES_ENCRYPT = 0, + SEP_DES_DECRYPT = 1, + SEP_DES_ENC_OPTIONS, + SEP_DES_ENC_LAST = 0x7fffffff, +}; + +enum des_op_mode { + SEP_DES_ECB = 0, + SEP_DES_CBC = 1, + SEP_OP_OPTIONS, + SEP_OP_LAST = 0x7fffffff, +}; + +enum aes_keysize { + AES_128 = 0, + AES_192 = 1, + AES_256 = 2, + AES_512 = 3, + AES_SIZE_OPTIONS, + AEA_SIZE_LAST = 0x7FFFFFFF, +}; + +enum aes_enc_mode { + SEP_AES_ENCRYPT = 0, + SEP_AES_DECRYPT = 1, + SEP_AES_ENC_OPTIONS, + SEP_AES_ENC_LAST = 0x7FFFFFFF, +}; + +enum aes_op_mode { + SEP_AES_ECB = 0, + SEP_AES_CBC = 1, + SEP_AES_MAC = 2, + SEP_AES_CTR = 3, + SEP_AES_XCBC = 4, + SEP_AES_CMAC = 5, + SEP_AES_XTS = 6, + SEP_AES_OP_OPTIONS, + SEP_AES_OP_LAST = 0x7FFFFFFF, +}; + +enum hash_op_mode { + SEP_HASH_SHA1 = 0, + SEP_HASH_SHA224 = 1, + SEP_HASH_SHA256 = 2, + SEP_HASH_SHA384 = 3, + SEP_HASH_SHA512 = 4, + SEP_HASH_MD5 = 5, + SEP_HASH_OPTIONS, + SEP_HASH_LAST_MODE = 0x7FFFFFFF, +}; + +/* Structures for SEP (from vendor) */ +struct sep_des_internal_key { + u32 key1[SEP_DES_KEY_SIZE_WORDS]; + u32 key2[SEP_DES_KEY_SIZE_WORDS]; + u32 key3[SEP_DES_KEY_SIZE_WORDS]; +}; + +struct sep_des_internal_context { + u32 iv_context[SEP_DES_IV_SIZE_WORDS]; + struct sep_des_internal_key context_key; + enum des_numkey nbr_keys; + enum des_enc_mode encryption; + enum des_op_mode operation; + u8 dummy_block[SEP_DES_DUMMY_SIZE]; +}; + +struct sep_des_private_context { + u32 valid_tag; + u32 iv; + u8 ctx_buf[sizeof(struct sep_des_internal_context)]; +}; + +/* This is the structure passed to SEP via msg area */ +struct sep_des_key { + u32 key1[SEP_DES_KEY_SIZE_WORDS]; + u32 key2[SEP_DES_KEY_SIZE_WORDS]; + u32 key3[SEP_DES_KEY_SIZE_WORDS]; + u32 pad[SEP_DES_KEY_SIZE_WORDS]; +}; + +struct sep_aes_internal_context { + u32 aes_ctx_iv[SEP_AES_IV_SIZE_WORDS]; + u32 aes_ctx_key[SEP_AES_MAX_KEY_SIZE_WORDS / 2]; + enum aes_keysize keysize; + enum aes_enc_mode encmode; + enum aes_op_mode opmode; + u8 secret_key; + u32 no_add_blocks; + u32 last_block_size; + u32 last_block[SEP_AES_BLOCK_SIZE_WORDS]; + u32 prev_iv[SEP_AES_BLOCK_SIZE_WORDS]; + u32 remaining_size; + union { + struct { + u32 dkey1[SEP_AES_BLOCK_SIZE_WORDS]; + u32 dkey2[SEP_AES_BLOCK_SIZE_WORDS]; + u32 dkey3[SEP_AES_BLOCK_SIZE_WORDS]; + } cmac_data; + struct { + u32 xts_key[SEP_AES_MAX_KEY_SIZE_WORDS / 2]; + u32 temp1[SEP_AES_BLOCK_SIZE_WORDS]; + u32 temp2[SEP_AES_BLOCK_SIZE_WORDS]; + } xtx_data; + } s_data; + u8 dummy_block[SEP_AES_DUMMY_BLOCK_SIZE]; +}; + +struct sep_aes_private_context { + u32 valid_tag; + u32 aes_iv; + u32 op_mode; + u8 cbuff[sizeof(struct sep_aes_internal_context)]; +}; + +struct sep_hash_internal_context { + u32 hash_result[SEP_HASH_RESULT_SIZE_WORDS]; + enum hash_op_mode hash_opmode; + u32 previous_data[SEP_SHA2_BLOCK_SIZE_WORDS]; + u16 prev_update_bytes; + u32 total_proc_128bit[4]; + u16 op_mode_block_size; + u8 dummy_aes_block[SEP_AES_DUMMY_BLOCK_SIZE]; +}; + +struct sep_hash_private_context { + u32 valid_tag; + u32 iv; + u8 internal_context[sizeof(struct sep_hash_internal_context)]; +}; + +/* Context structures for crypto API */ +struct sep_block_ctx { + struct sep_device *sep; + u32 done; + unsigned char iv[100]; + enum des_enc_mode des_encmode; + enum des_op_mode des_opmode; + enum aes_enc_mode aes_encmode; + enum aes_op_mode aes_opmode; + u32 init_opcode; + u32 block_opcode; + size_t data_length; + size_t ivlen; + struct ablkcipher_walk walk; + struct sep_des_private_context des_private_ctx; + struct sep_aes_private_context aes_private_ctx; + }; + +struct sep_hash_ctx { + u32 done; + unsigned char *buf; + size_t buflen; + unsigned char *dgst; + int digest_size_words; + int digest_size_bytes; + int block_size_words; + int block_size_bytes; + struct scatterlist *sg; + enum hash_op_mode hash_opmode; + struct sep_hash_private_context hash_private_ctx; + }; + +struct sep_system_ctx { + struct sep_device *sep_used; + union key_t { + struct sep_des_key des; + u32 aes[SEP_AES_MAX_KEY_SIZE_WORDS]; + } key; + int i_own_sep; /* Do I have custody of the sep? */ + size_t keylen; + enum des_numkey des_nbr_keys; + enum aes_keysize aes_key_size; + u32 key_sent; /* Indicate if key is sent to sep */ + u32 last_block; /* Indicate that this is the final block */ + struct sep_call_status call_status; + struct build_dcb_struct_kernel dcb_input_data; + struct sep_dma_context *dma_ctx; + void *dmatables_region; + size_t nbytes; + struct sep_dcblock *dcb_region; + struct sep_queue_info *queue_elem; + int msg_len_words; + unsigned char msg[SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES]; + void *msgptr; + struct scatterlist *src_sg; + struct scatterlist *dst_sg; + struct scatterlist *src_sg_hold; + struct scatterlist *dst_sg_hold; + struct ahash_request *current_hash_req; + struct ablkcipher_request *current_cypher_req; + enum type_of_request current_request; + enum hash_stage current_hash_stage; + int done_with_transaction; + unsigned long end_time; + }; + +/* work queue structures */ +struct sep_work_struct { + struct work_struct work; + void (*callback)(void *); + void *data; + }; + +/* Functions */ +int sep_crypto_setup(void); +void sep_crypto_takedown(void); diff --git a/drivers/staging/sep/sep_dev.h b/drivers/staging/sep/sep_dev.h index 696ab0d..66d8e95 100644 --- a/drivers/staging/sep/sep_dev.h +++ b/drivers/staging/sep/sep_dev.h @@ -5,8 +5,8 @@ * * sep_dev.h - Security Processor Device Structures * - * Copyright(c) 2009,2010 Intel Corporation. All rights reserved. - * Contributions(c) 2009,2010 Discretix. All rights reserved. + * Copyright(c) 2009-2011 Intel Corporation. All rights reserved. + * Contributions(c) 2009-2011 Discretix. All rights reserved. * * 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 @@ -28,6 +28,7 @@ * * CHANGES * 2010.09.14 upgrade to Medfield + * 2011.02.22 enable kernel crypto */ struct sep_device { @@ -36,33 +37,21 @@ struct sep_device { /* character device file */ struct cdev sep_cdev; - struct cdev sep_daemon_cdev; - struct cdev sep_singleton_cdev; /* devices (using misc dev) */ struct miscdevice miscdev_sep; - struct miscdevice miscdev_singleton; - struct miscdevice miscdev_daemon; /* major / minor numbers of device */ dev_t sep_devno; - dev_t sep_daemon_devno; - dev_t sep_singleton_devno; - - struct mutex sep_mutex; - struct mutex ioctl_mutex; + /* guards command sent counter */ spinlock_t snd_rply_lck; + /* guards driver memory usage in fastcall if */ + struct semaphore sep_doublebuf; /* flags to indicate use and lock status of sep */ u32 pid_doing_transaction; unsigned long in_use_flags; - /* request daemon alread open */ - unsigned long request_daemon_open; - - /* 1 = Moorestown; 0 = Medfield */ - int mrst; - /* address of the shared memory allocated during init for SEP driver (coherent alloc) */ dma_addr_t shared_bus; @@ -74,36 +63,78 @@ struct sep_device { dma_addr_t reg_physical_end; void __iomem *reg_addr; - /* wait queue head (event) of the driver */ - wait_queue_head_t event; - wait_queue_head_t event_request_daemon; - wait_queue_head_t event_mmap; + /* wait queue heads of the driver */ + wait_queue_head_t event_interrupt; + wait_queue_head_t event_transactions; - struct sep_caller_id_entry - caller_id_table[SEP_CALLER_ID_TABLE_NUM_ENTRIES]; + struct list_head sep_queue_status; + u32 sep_queue_num; + spinlock_t sep_queue_lock; - /* access flag for singleton device */ - unsigned long singleton_access_flag; + /* Is this in use? */ + u32 in_use; + + /* indicates whether power save is set up */ + u32 power_save_setup; + + /* Power state */ + u32 power_state; /* transaction counter that coordinates the transactions between SEP and HOST */ unsigned long send_ct; /* counter for the messages from sep */ unsigned long reply_ct; - /* counter for the number of bytes allocated in the pool for the - current transaction */ - long data_pool_bytes_allocated; - u32 num_of_data_allocations; + /* The following are used for kernel crypto client requests */ + u32 in_kernel; /* Set for kernel client request */ + struct tasklet_struct finish_tasklet; + enum type_of_request current_request; + enum hash_stage current_hash_stage; + struct ahash_request *current_hash_req; + struct ablkcipher_request *current_cypher_req; + struct sep_system_ctx *sctx; + spinlock_t busy_lock; + struct workqueue_struct *workqueue; +}; - /* number of the lli tables created in the current transaction */ - u32 num_lli_tables_created; +extern struct sep_device *sep_dev; - /* number of data control blocks */ - u32 nr_dcb_creat; +/** + * SEP message header for a transaction + * @reserved: reserved memory (two words) + * @token: SEP message token + * @msg_len: message length + * @opcpde: message opcode + */ +struct sep_msgarea_hdr { + u32 reserved[2]; + u32 token; + u32 msg_len; + u32 opcode; +}; - struct sep_dma_resource dma_res_arr[SEP_MAX_NUM_SYNC_DMA_OPS]; +/** + * sep_queue_data - data to be maintained in status queue for a transaction + * @opcode : transaction opcode + * @size : message size + * @pid: owner process + * @name: owner process name + */ +struct sep_queue_data { + u32 opcode; + u32 size; + s32 pid; + u8 name[TASK_COMM_LEN]; +}; +/** sep_queue_info - maintains status info of all transactions + * @list: head of list + * @sep_queue_data : data for transaction + */ +struct sep_queue_info { + struct list_head list; + struct sep_queue_data data; }; static inline void sep_write_reg(struct sep_device *dev, int reg, u32 value) diff --git a/drivers/staging/sep/sep_driver.c b/drivers/staging/sep/sep_driver.c deleted file mode 100644 index 6b3d156..0000000 --- a/drivers/staging/sep/sep_driver.c +++ /dev/null @@ -1,2932 +0,0 @@ -/* - * - * sep_driver.c - Security Processor Driver main group of functions - * - * Copyright(c) 2009,2010 Intel Corporation. All rights reserved. - * Contributions(c) 2009,2010 Discretix. All rights reserved. - * - * 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; version 2 of the License. - * - * 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., 59 - * Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * CONTACTS: - * - * Mark Allyn mark.a.allyn@intel.com - * Jayant Mangalampalli jayant.mangalampalli@intel.com - * - * CHANGES: - * - * 2009.06.26 Initial publish - * 2010.09.14 Upgrade to Medfield - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "sep_driver_hw_defs.h" -#include "sep_driver_config.h" -#include "sep_driver_api.h" -#include "sep_dev.h" - -/*---------------------------------------- - DEFINES ------------------------------------------*/ - -#define SEP_RAR_IO_MEM_REGION_SIZE 0x40000 - -/*-------------------------------------------- - GLOBAL variables ---------------------------------------------*/ - -/* Keep this a single static object for now to keep the conversion easy */ - -static struct sep_device *sep_dev; - -/** - * sep_dump_message - dump the message that is pending - * @sep: SEP device - */ -static void sep_dump_message(struct sep_device *sep) -{ - int count; - u32 *p = sep->shared_addr; - for (count = 0; count < 12 * 4; count += 4) - dev_dbg(&sep->pdev->dev, "Word %d of the message is %x\n", - count, *p++); -} - -/** - * sep_map_and_alloc_shared_area - allocate shared block - * @sep: security processor - * @size: size of shared area - */ -static int sep_map_and_alloc_shared_area(struct sep_device *sep) -{ - sep->shared_addr = dma_alloc_coherent(&sep->pdev->dev, - sep->shared_size, - &sep->shared_bus, GFP_KERNEL); - - if (!sep->shared_addr) { - dev_warn(&sep->pdev->dev, - "shared memory dma_alloc_coherent failed\n"); - return -ENOMEM; - } - dev_dbg(&sep->pdev->dev, - "shared_addr %zx bytes @%p (bus %llx)\n", - sep->shared_size, sep->shared_addr, - (unsigned long long)sep->shared_bus); - return 0; -} - -/** - * sep_unmap_and_free_shared_area - free shared block - * @sep: security processor - */ -static void sep_unmap_and_free_shared_area(struct sep_device *sep) -{ - dma_free_coherent(&sep->pdev->dev, sep->shared_size, - sep->shared_addr, sep->shared_bus); -} - -/** - * sep_shared_bus_to_virt - convert bus/virt addresses - * @sep: pointer to struct sep_device - * @bus_address: address to convert - * - * Returns virtual address inside the shared area according - * to the bus address. - */ -static void *sep_shared_bus_to_virt(struct sep_device *sep, - dma_addr_t bus_address) -{ - return sep->shared_addr + (bus_address - sep->shared_bus); -} - -/** - * open function for the singleton driver - * @inode_ptr struct inode * - * @file_ptr struct file * - * - * Called when the user opens the singleton device interface - */ -static int sep_singleton_open(struct inode *inode_ptr, struct file *file_ptr) -{ - struct sep_device *sep; - - /* - * Get the SEP device structure and use it for the - * private_data field in filp for other methods - */ - sep = sep_dev; - - file_ptr->private_data = sep; - - if (test_and_set_bit(0, &sep->singleton_access_flag)) - return -EBUSY; - return 0; -} - -/** - * sep_open - device open method - * @inode: inode of SEP device - * @filp: file handle to SEP device - * - * Open method for the SEP device. Called when userspace opens - * the SEP device node. - * - * Returns zero on success otherwise an error code. - */ -static int sep_open(struct inode *inode, struct file *filp) -{ - struct sep_device *sep; - - /* - * Get the SEP device structure and use it for the - * private_data field in filp for other methods - */ - sep = sep_dev; - filp->private_data = sep; - - /* Anyone can open; locking takes place at transaction level */ - return 0; -} - -/** - * sep_singleton_release - close a SEP singleton device - * @inode: inode of SEP device - * @filp: file handle being closed - * - * Called on the final close of a SEP device. As the open protects against - * multiple simultaenous opens that means this method is called when the - * final reference to the open handle is dropped. - */ -static int sep_singleton_release(struct inode *inode, struct file *filp) -{ - struct sep_device *sep = filp->private_data; - - clear_bit(0, &sep->singleton_access_flag); - return 0; -} - -/** - * sep_request_daemon_open - request daemon open method - * @inode: inode of SEP device - * @filp: file handle to SEP device - * - * Open method for the SEP request daemon. Called when - * request daemon in userspace opens the SEP device node. - * - * Returns zero on success otherwise an error code. - */ -static int sep_request_daemon_open(struct inode *inode, struct file *filp) -{ - struct sep_device *sep = sep_dev; - int error = 0; - - filp->private_data = sep; - - /* There is supposed to be only one request daemon */ - if (test_and_set_bit(0, &sep->request_daemon_open)) - error = -EBUSY; - return error; -} - -/** - * sep_request_daemon_release - close a SEP daemon - * @inode: inode of SEP device - * @filp: file handle being closed - * - * Called on the final close of a SEP daemon. - */ -static int sep_request_daemon_release(struct inode *inode, struct file *filp) -{ - struct sep_device *sep = filp->private_data; - - dev_dbg(&sep->pdev->dev, "Request daemon release for pid %d\n", - current->pid); - - /* Clear the request_daemon_open flag */ - clear_bit(0, &sep->request_daemon_open); - return 0; -} - -/** - * sep_req_daemon_send_reply_command_handler - poke the SEP - * @sep: struct sep_device * - * - * This function raises interrupt to SEPm that signals that is has a - * new command from HOST - */ -static int sep_req_daemon_send_reply_command_handler(struct sep_device *sep) -{ - unsigned long lck_flags; - - sep_dump_message(sep); - - /* Counters are lockable region */ - spin_lock_irqsave(&sep->snd_rply_lck, lck_flags); - sep->send_ct++; - sep->reply_ct++; - - /* Send the interrupt to SEP */ - sep_write_reg(sep, HW_HOST_HOST_SEP_GPR2_REG_ADDR, sep->send_ct); - sep->send_ct++; - - spin_unlock_irqrestore(&sep->snd_rply_lck, lck_flags); - - dev_dbg(&sep->pdev->dev, - "sep_req_daemon_send_reply send_ct %lx reply_ct %lx\n", - sep->send_ct, sep->reply_ct); - - return 0; -} - - -/** - * sep_free_dma_table_data_handler - free DMA table - * @sep: pointere to struct sep_device - * - * Handles the request to free DMA table for synchronic actions - */ -static int sep_free_dma_table_data_handler(struct sep_device *sep) -{ - int count; - int dcb_counter; - /* Pointer to the current dma_resource struct */ - struct sep_dma_resource *dma; - - for (dcb_counter = 0; dcb_counter < sep->nr_dcb_creat; dcb_counter++) { - dma = &sep->dma_res_arr[dcb_counter]; - - /* Unmap and free input map array */ - if (dma->in_map_array) { - for (count = 0; count < dma->in_num_pages; count++) { - dma_unmap_page(&sep->pdev->dev, - dma->in_map_array[count].dma_addr, - dma->in_map_array[count].size, - DMA_TO_DEVICE); - } - kfree(dma->in_map_array); - } - - /* Unmap output map array, DON'T free it yet */ - if (dma->out_map_array) { - for (count = 0; count < dma->out_num_pages; count++) { - dma_unmap_page(&sep->pdev->dev, - dma->out_map_array[count].dma_addr, - dma->out_map_array[count].size, - DMA_FROM_DEVICE); - } - kfree(dma->out_map_array); - } - - /* Free page cache for output */ - if (dma->in_page_array) { - for (count = 0; count < dma->in_num_pages; count++) { - flush_dcache_page(dma->in_page_array[count]); - page_cache_release(dma->in_page_array[count]); - } - kfree(dma->in_page_array); - } - - if (dma->out_page_array) { - for (count = 0; count < dma->out_num_pages; count++) { - if (!PageReserved(dma->out_page_array[count])) - SetPageDirty(dma->out_page_array[count]); - flush_dcache_page(dma->out_page_array[count]); - page_cache_release(dma->out_page_array[count]); - } - kfree(dma->out_page_array); - } - - /* Reset all the values */ - dma->in_page_array = NULL; - dma->out_page_array = NULL; - dma->in_num_pages = 0; - dma->out_num_pages = 0; - dma->in_map_array = NULL; - dma->out_map_array = NULL; - dma->in_map_num_entries = 0; - dma->out_map_num_entries = 0; - } - - sep->nr_dcb_creat = 0; - sep->num_lli_tables_created = 0; - - return 0; -} - -/** - * sep_request_daemon_mmap - maps the shared area to user space - * @filp: pointer to struct file - * @vma: pointer to vm_area_struct - * - * Called by the kernel when the daemon attempts an mmap() syscall - * using our handle. - */ -static int sep_request_daemon_mmap(struct file *filp, - struct vm_area_struct *vma) -{ - struct sep_device *sep = filp->private_data; - dma_addr_t bus_address; - int error = 0; - - if ((vma->vm_end - vma->vm_start) > SEP_DRIVER_MMMAP_AREA_SIZE) { - error = -EINVAL; - goto end_function; - } - - /* Get physical address */ - bus_address = sep->shared_bus; - - if (remap_pfn_range(vma, vma->vm_start, bus_address >> PAGE_SHIFT, - vma->vm_end - vma->vm_start, vma->vm_page_prot)) { - - dev_warn(&sep->pdev->dev, "remap_page_range failed\n"); - error = -EAGAIN; - goto end_function; - } - -end_function: - return error; -} - -/** - * sep_request_daemon_poll - poll implementation - * @sep: struct sep_device * for current SEP device - * @filp: struct file * for open file - * @wait: poll_table * for poll - * - * Called when our device is part of a poll() or select() syscall - */ -static unsigned int sep_request_daemon_poll(struct file *filp, - poll_table *wait) -{ - u32 mask = 0; - /* GPR2 register */ - u32 retval2; - unsigned long lck_flags; - struct sep_device *sep = filp->private_data; - - poll_wait(filp, &sep->event_request_daemon, wait); - - dev_dbg(&sep->pdev->dev, "daemon poll: send_ct is %lx reply ct is %lx\n", - sep->send_ct, sep->reply_ct); - - spin_lock_irqsave(&sep->snd_rply_lck, lck_flags); - /* Check if the data is ready */ - if (sep->send_ct == sep->reply_ct) { - spin_unlock_irqrestore(&sep->snd_rply_lck, lck_flags); - - retval2 = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR2_REG_ADDR); - dev_dbg(&sep->pdev->dev, - "daemon poll: data check (GPR2) is %x\n", retval2); - - /* Check if PRINT request */ - if ((retval2 >> 30) & 0x1) { - dev_dbg(&sep->pdev->dev, "daemon poll: PRINTF request in\n"); - mask |= POLLIN; - goto end_function; - } - /* Check if NVS request */ - if (retval2 >> 31) { - dev_dbg(&sep->pdev->dev, "daemon poll: NVS request in\n"); - mask |= POLLPRI | POLLWRNORM; - } - } else { - spin_unlock_irqrestore(&sep->snd_rply_lck, lck_flags); - dev_dbg(&sep->pdev->dev, - "daemon poll: no reply received; returning 0\n"); - mask = 0; - } -end_function: - return mask; -} - -/** - * sep_release - close a SEP device - * @inode: inode of SEP device - * @filp: file handle being closed - * - * Called on the final close of a SEP device. - */ -static int sep_release(struct inode *inode, struct file *filp) -{ - struct sep_device *sep = filp->private_data; - - dev_dbg(&sep->pdev->dev, "Release for pid %d\n", current->pid); - - mutex_lock(&sep->sep_mutex); - /* Is this the process that has a transaction open? - * If so, lets reset pid_doing_transaction to 0 and - * clear the in use flags, and then wake up sep_event - * so that other processes can do transactions - */ - if (sep->pid_doing_transaction == current->pid) { - clear_bit(SEP_MMAP_LOCK_BIT, &sep->in_use_flags); - clear_bit(SEP_SEND_MSG_LOCK_BIT, &sep->in_use_flags); - sep_free_dma_table_data_handler(sep); - wake_up(&sep->event); - sep->pid_doing_transaction = 0; - } - - mutex_unlock(&sep->sep_mutex); - return 0; -} - -/** - * sep_mmap - maps the shared area to user space - * @filp: pointer to struct file - * @vma: pointer to vm_area_struct - * - * Called on an mmap of our space via the normal SEP device - */ -static int sep_mmap(struct file *filp, struct vm_area_struct *vma) -{ - dma_addr_t bus_addr; - struct sep_device *sep = filp->private_data; - unsigned long error = 0; - - /* Set the transaction busy (own the device) */ - wait_event_interruptible(sep->event, - test_and_set_bit(SEP_MMAP_LOCK_BIT, - &sep->in_use_flags) == 0); - - if (signal_pending(current)) { - error = -EINTR; - goto end_function_with_error; - } - /* - * The pid_doing_transaction indicates that this process - * now owns the facilities to performa a transaction with - * the SEP. While this process is performing a transaction, - * no other process who has the SEP device open can perform - * any transactions. This method allows more than one process - * to have the device open at any given time, which provides - * finer granularity for device utilization by multiple - * processes. - */ - mutex_lock(&sep->sep_mutex); - sep->pid_doing_transaction = current->pid; - mutex_unlock(&sep->sep_mutex); - - /* Zero the pools and the number of data pool alocation pointers */ - sep->data_pool_bytes_allocated = 0; - sep->num_of_data_allocations = 0; - - /* - * Check that the size of the mapped range is as the size of the message - * shared area - */ - if ((vma->vm_end - vma->vm_start) > SEP_DRIVER_MMMAP_AREA_SIZE) { - error = -EINVAL; - goto end_function_with_error; - } - - dev_dbg(&sep->pdev->dev, "shared_addr is %p\n", sep->shared_addr); - - /* Get bus address */ - bus_addr = sep->shared_bus; - - if (remap_pfn_range(vma, vma->vm_start, bus_addr >> PAGE_SHIFT, - vma->vm_end - vma->vm_start, vma->vm_page_prot)) { - dev_warn(&sep->pdev->dev, "remap_page_range failed\n"); - error = -EAGAIN; - goto end_function_with_error; - } - goto end_function; - -end_function_with_error: - /* Clear the bit */ - clear_bit(SEP_MMAP_LOCK_BIT, &sep->in_use_flags); - mutex_lock(&sep->sep_mutex); - sep->pid_doing_transaction = 0; - mutex_unlock(&sep->sep_mutex); - - /* Raise event for stuck contextes */ - - wake_up(&sep->event); - -end_function: - return error; -} - -/** - * sep_poll - poll handler - * @filp: pointer to struct file - * @wait: pointer to poll_table - * - * Called by the OS when the kernel is asked to do a poll on - * a SEP file handle. - */ -static unsigned int sep_poll(struct file *filp, poll_table *wait) -{ - u32 mask = 0; - u32 retval = 0; - u32 retval2 = 0; - unsigned long lck_flags; - - struct sep_device *sep = filp->private_data; - - /* Am I the process that owns the transaction? */ - mutex_lock(&sep->sep_mutex); - if (current->pid != sep->pid_doing_transaction) { - dev_dbg(&sep->pdev->dev, "poll; wrong pid\n"); - mask = POLLERR; - mutex_unlock(&sep->sep_mutex); - goto end_function; - } - mutex_unlock(&sep->sep_mutex); - - /* Check if send command or send_reply were activated previously */ - if (!test_bit(SEP_SEND_MSG_LOCK_BIT, &sep->in_use_flags)) { - mask = POLLERR; - goto end_function; - } - - /* Add the event to the polling wait table */ - dev_dbg(&sep->pdev->dev, "poll: calling wait sep_event\n"); - - poll_wait(filp, &sep->event, wait); - - dev_dbg(&sep->pdev->dev, "poll: send_ct is %lx reply ct is %lx\n", - sep->send_ct, sep->reply_ct); - - /* Check if error occurred during poll */ - retval2 = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR3_REG_ADDR); - if (retval2 != 0x0) { - dev_warn(&sep->pdev->dev, "poll; poll error %x\n", retval2); - mask |= POLLERR; - goto end_function; - } - - spin_lock_irqsave(&sep->snd_rply_lck, lck_flags); - - if (sep->send_ct == sep->reply_ct) { - spin_unlock_irqrestore(&sep->snd_rply_lck, lck_flags); - retval = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR2_REG_ADDR); - dev_dbg(&sep->pdev->dev, "poll: data ready check (GPR2) %x\n", - retval); - - /* Check if printf request */ - if ((retval >> 30) & 0x1) { - dev_dbg(&sep->pdev->dev, "poll: SEP printf request\n"); - wake_up(&sep->event_request_daemon); - goto end_function; - } - - /* Check if the this is SEP reply or request */ - if (retval >> 31) { - dev_dbg(&sep->pdev->dev, "poll: SEP request\n"); - wake_up(&sep->event_request_daemon); - } else { - dev_dbg(&sep->pdev->dev, "poll: normal return\n"); - /* In case it is again by send_reply_comand */ - clear_bit(SEP_SEND_MSG_LOCK_BIT, &sep->in_use_flags); - sep_dump_message(sep); - dev_dbg(&sep->pdev->dev, - "poll; SEP reply POLLIN | POLLRDNORM\n"); - mask |= POLLIN | POLLRDNORM; - } - } else { - spin_unlock_irqrestore(&sep->snd_rply_lck, lck_flags); - dev_dbg(&sep->pdev->dev, - "poll; no reply received; returning mask of 0\n"); - mask = 0; - } - -end_function: - return mask; -} - -/** - * sep_time_address - address in SEP memory of time - * @sep: SEP device we want the address from - * - * Return the address of the two dwords in memory used for time - * setting. - */ -static u32 *sep_time_address(struct sep_device *sep) -{ - return sep->shared_addr + SEP_DRIVER_SYSTEM_TIME_MEMORY_OFFSET_IN_BYTES; -} - -/** - * sep_set_time - set the SEP time - * @sep: the SEP we are setting the time for - * - * Calculates time and sets it at the predefined address. - * Called with the SEP mutex held. - */ -static unsigned long sep_set_time(struct sep_device *sep) -{ - struct timeval time; - u32 *time_addr; /* Address of time as seen by the kernel */ - - - do_gettimeofday(&time); - - /* Set value in the SYSTEM MEMORY offset */ - time_addr = sep_time_address(sep); - - time_addr[0] = SEP_TIME_VAL_TOKEN; - time_addr[1] = time.tv_sec; - - dev_dbg(&sep->pdev->dev, "time.tv_sec is %lu\n", time.tv_sec); - dev_dbg(&sep->pdev->dev, "time_addr is %p\n", time_addr); - dev_dbg(&sep->pdev->dev, "sep->shared_addr is %p\n", sep->shared_addr); - - return time.tv_sec; -} - -/** - * sep_set_caller_id_handler - insert caller id entry - * @sep: SEP device - * @arg: pointer to struct caller_id_struct - * - * Inserts the data into the caller id table. Note that this function - * falls under the ioctl lock - */ -static int sep_set_caller_id_handler(struct sep_device *sep, unsigned long arg) -{ - void __user *hash; - int error = 0; - int i; - struct caller_id_struct command_args; - - for (i = 0; i < SEP_CALLER_ID_TABLE_NUM_ENTRIES; i++) { - if (sep->caller_id_table[i].pid == 0) - break; - } - - if (i == SEP_CALLER_ID_TABLE_NUM_ENTRIES) { - dev_dbg(&sep->pdev->dev, "no more caller id entries left\n"); - dev_dbg(&sep->pdev->dev, "maximum number is %d\n", - SEP_CALLER_ID_TABLE_NUM_ENTRIES); - error = -EUSERS; - goto end_function; - } - - /* Copy the data */ - if (copy_from_user(&command_args, (void __user *)arg, - sizeof(command_args))) { - error = -EFAULT; - goto end_function; - } - - hash = (void __user *)(unsigned long)command_args.callerIdAddress; - - if (!command_args.pid || !command_args.callerIdSizeInBytes) { - error = -EINVAL; - goto end_function; - } - - dev_dbg(&sep->pdev->dev, "pid is %x\n", command_args.pid); - dev_dbg(&sep->pdev->dev, "callerIdSizeInBytes is %x\n", - command_args.callerIdSizeInBytes); - - if (command_args.callerIdSizeInBytes > - SEP_CALLER_ID_HASH_SIZE_IN_BYTES) { - error = -EMSGSIZE; - goto end_function; - } - - sep->caller_id_table[i].pid = command_args.pid; - - if (copy_from_user(sep->caller_id_table[i].callerIdHash, - hash, command_args.callerIdSizeInBytes)) - error = -EFAULT; -end_function: - return error; -} - -/** - * sep_set_current_caller_id - set the caller id - * @sep: pointer to struct_sep_device - * - * Set the caller ID (if it exists) to the SEP. Note that this - * function falls under the ioctl lock - */ -static int sep_set_current_caller_id(struct sep_device *sep) -{ - int i; - u32 *hash_buf_ptr; - - /* Zero the previous value */ - memset(sep->shared_addr + SEP_CALLER_ID_OFFSET_BYTES, - 0, SEP_CALLER_ID_HASH_SIZE_IN_BYTES); - - for (i = 0; i < SEP_CALLER_ID_TABLE_NUM_ENTRIES; i++) { - if (sep->caller_id_table[i].pid == current->pid) { - dev_dbg(&sep->pdev->dev, "Caller Id found\n"); - - memcpy(sep->shared_addr + SEP_CALLER_ID_OFFSET_BYTES, - (void *)(sep->caller_id_table[i].callerIdHash), - SEP_CALLER_ID_HASH_SIZE_IN_BYTES); - break; - } - } - /* Ensure data is in little endian */ - hash_buf_ptr = (u32 *)sep->shared_addr + - SEP_CALLER_ID_OFFSET_BYTES; - - for (i = 0; i < SEP_CALLER_ID_HASH_SIZE_IN_WORDS; i++) - hash_buf_ptr[i] = cpu_to_le32(hash_buf_ptr[i]); - - return 0; -} - -/** - * sep_send_command_handler - kick off a command - * @sep: SEP being signalled - * - * This function raises interrupt to SEP that signals that is has a new - * command from the host - * - * Note that this function does fall under the ioctl lock - */ -static int sep_send_command_handler(struct sep_device *sep) -{ - unsigned long lck_flags; - int error = 0; - - if (test_and_set_bit(SEP_SEND_MSG_LOCK_BIT, &sep->in_use_flags)) { - error = -EPROTO; - goto end_function; - } - sep_set_time(sep); - - sep_set_current_caller_id(sep); - - sep_dump_message(sep); - - /* Update counter */ - spin_lock_irqsave(&sep->snd_rply_lck, lck_flags); - sep->send_ct++; - spin_unlock_irqrestore(&sep->snd_rply_lck, lck_flags); - - dev_dbg(&sep->pdev->dev, - "sep_send_command_handler send_ct %lx reply_ct %lx\n", - sep->send_ct, sep->reply_ct); - - /* Send interrupt to SEP */ - sep_write_reg(sep, HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x2); - -end_function: - return error; -} - -/** - * sep_allocate_data_pool_memory_handler -allocate pool memory - * @sep: pointer to struct sep_device - * @arg: pointer to struct alloc_struct - * - * This function handles the allocate data pool memory request - * This function returns calculates the bus address of the - * allocated memory, and the offset of this area from the mapped address. - * Therefore, the FVOs in user space can calculate the exact virtual - * address of this allocated memory - */ -static int sep_allocate_data_pool_memory_handler(struct sep_device *sep, - unsigned long arg) -{ - int error = 0; - struct alloc_struct command_args; - - /* Holds the allocated buffer address in the system memory pool */ - u32 *token_addr; - - if (copy_from_user(&command_args, (void __user *)arg, - sizeof(struct alloc_struct))) { - error = -EFAULT; - goto end_function; - } - - /* Allocate memory */ - if ((sep->data_pool_bytes_allocated + command_args.num_bytes) > - SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES) { - error = -ENOMEM; - goto end_function; - } - - dev_dbg(&sep->pdev->dev, - "data pool bytes_allocated: %x\n", (int)sep->data_pool_bytes_allocated); - dev_dbg(&sep->pdev->dev, - "offset: %x\n", SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES); - /* Set the virtual and bus address */ - command_args.offset = SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES + - sep->data_pool_bytes_allocated; - - /* Place in the shared area that is known by the SEP */ - token_addr = (u32 *)(sep->shared_addr + - SEP_DRIVER_DATA_POOL_ALLOCATION_OFFSET_IN_BYTES + - (sep->num_of_data_allocations)*2*sizeof(u32)); - - token_addr[0] = SEP_DATA_POOL_POINTERS_VAL_TOKEN; - token_addr[1] = (u32)sep->shared_bus + - SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES + - sep->data_pool_bytes_allocated; - - /* Write the memory back to the user space */ - error = copy_to_user((void *)arg, (void *)&command_args, - sizeof(struct alloc_struct)); - if (error) { - error = -EFAULT; - goto end_function; - } - - /* Update the allocation */ - sep->data_pool_bytes_allocated += command_args.num_bytes; - sep->num_of_data_allocations += 1; - -end_function: - return error; -} - -/** - * sep_lock_kernel_pages - map kernel pages for DMA - * @sep: pointer to struct sep_device - * @kernel_virt_addr: address of data buffer in kernel - * @data_size: size of data - * @lli_array_ptr: lli array - * @in_out_flag: input into device or output from device - * - * This function locks all the physical pages of the kernel virtual buffer - * and construct a basic lli array, where each entry holds the physical - * page address and the size that application data holds in this page - * This function is used only during kernel crypto mod calls from within - * the kernel (when ioctl is not used) - */ -static int sep_lock_kernel_pages(struct sep_device *sep, - unsigned long kernel_virt_addr, - u32 data_size, - struct sep_lli_entry **lli_array_ptr, - int in_out_flag) - -{ - int error = 0; - /* Array of lli */ - struct sep_lli_entry *lli_array; - /* Map array */ - struct sep_dma_map *map_array; - - dev_dbg(&sep->pdev->dev, "lock kernel pages kernel_virt_addr is %08lx\n", - (unsigned long)kernel_virt_addr); - dev_dbg(&sep->pdev->dev, "data_size is %x\n", data_size); - - lli_array = kmalloc(sizeof(struct sep_lli_entry), GFP_ATOMIC); - if (!lli_array) { - error = -ENOMEM; - goto end_function; - } - map_array = kmalloc(sizeof(struct sep_dma_map), GFP_ATOMIC); - if (!map_array) { - error = -ENOMEM; - goto end_function_with_error; - } - - map_array[0].dma_addr = - dma_map_single(&sep->pdev->dev, (void *)kernel_virt_addr, - data_size, DMA_BIDIRECTIONAL); - map_array[0].size = data_size; - - - /* - * Set the start address of the first page - app data may start not at - * the beginning of the page - */ - lli_array[0].bus_address = (u32)map_array[0].dma_addr; - lli_array[0].block_size = map_array[0].size; - - dev_dbg(&sep->pdev->dev, - "lli_array[0].bus_address is %08lx, lli_array[0].block_size is %x\n", - (unsigned long)lli_array[0].bus_address, - lli_array[0].block_size); - - /* Set the output parameters */ - if (in_out_flag == SEP_DRIVER_IN_FLAG) { - *lli_array_ptr = lli_array; - sep->dma_res_arr[sep->nr_dcb_creat].in_num_pages = 1; - sep->dma_res_arr[sep->nr_dcb_creat].in_page_array = NULL; - sep->dma_res_arr[sep->nr_dcb_creat].in_map_array = map_array; - sep->dma_res_arr[sep->nr_dcb_creat].in_map_num_entries = 1; - } else { - *lli_array_ptr = lli_array; - sep->dma_res_arr[sep->nr_dcb_creat].out_num_pages = 1; - sep->dma_res_arr[sep->nr_dcb_creat].out_page_array = NULL; - sep->dma_res_arr[sep->nr_dcb_creat].out_map_array = map_array; - sep->dma_res_arr[sep->nr_dcb_creat].out_map_num_entries = 1; - } - goto end_function; - -end_function_with_error: - kfree(lli_array); - -end_function: - return error; -} - -/** - * sep_lock_user_pages - lock and map user pages for DMA - * @sep: pointer to struct sep_device - * @app_virt_addr: user memory data buffer - * @data_size: size of data buffer - * @lli_array_ptr: lli array - * @in_out_flag: input or output to device - * - * This function locks all the physical pages of the application - * virtual buffer and construct a basic lli array, where each entry - * holds the physical page address and the size that application - * data holds in this physical pages - */ -static int sep_lock_user_pages(struct sep_device *sep, - u32 app_virt_addr, - u32 data_size, - struct sep_lli_entry **lli_array_ptr, - int in_out_flag) - -{ - int error = 0; - u32 count; - int result; - /* The the page of the end address of the user space buffer */ - u32 end_page; - /* The page of the start address of the user space buffer */ - u32 start_page; - /* The range in pages */ - u32 num_pages; - /* Array of pointers to page */ - struct page **page_array; - /* Array of lli */ - struct sep_lli_entry *lli_array; - /* Map array */ - struct sep_dma_map *map_array; - /* Direction of the DMA mapping for locked pages */ - enum dma_data_direction dir; - - /* Set start and end pages and num pages */ - end_page = (app_virt_addr + data_size - 1) >> PAGE_SHIFT; - start_page = app_virt_addr >> PAGE_SHIFT; - num_pages = end_page - start_page + 1; - - dev_dbg(&sep->pdev->dev, "lock user pages app_virt_addr is %x\n", app_virt_addr); - dev_dbg(&sep->pdev->dev, "data_size is %x\n", data_size); - dev_dbg(&sep->pdev->dev, "start_page is %x\n", start_page); - dev_dbg(&sep->pdev->dev, "end_page is %x\n", end_page); - dev_dbg(&sep->pdev->dev, "num_pages is %x\n", num_pages); - - /* Allocate array of pages structure pointers */ - page_array = kmalloc(sizeof(struct page *) * num_pages, GFP_ATOMIC); - if (!page_array) { - error = -ENOMEM; - goto end_function; - } - map_array = kmalloc(sizeof(struct sep_dma_map) * num_pages, GFP_ATOMIC); - if (!map_array) { - dev_warn(&sep->pdev->dev, "kmalloc for map_array failed\n"); - error = -ENOMEM; - goto end_function_with_error1; - } - - lli_array = kmalloc(sizeof(struct sep_lli_entry) * num_pages, - GFP_ATOMIC); - - if (!lli_array) { - dev_warn(&sep->pdev->dev, "kmalloc for lli_array failed\n"); - error = -ENOMEM; - goto end_function_with_error2; - } - - /* Convert the application virtual address into a set of physical */ - down_read(¤t->mm->mmap_sem); - result = get_user_pages(current, current->mm, app_virt_addr, - num_pages, - ((in_out_flag == SEP_DRIVER_IN_FLAG) ? 0 : 1), - 0, page_array, NULL); - - up_read(¤t->mm->mmap_sem); - - /* Check the number of pages locked - if not all then exit with error */ - if (result != num_pages) { - dev_warn(&sep->pdev->dev, - "not all pages locked by get_user_pages\n"); - error = -ENOMEM; - goto end_function_with_error3; - } - - dev_dbg(&sep->pdev->dev, "get_user_pages succeeded\n"); - - /* Set direction */ - if (in_out_flag == SEP_DRIVER_IN_FLAG) - dir = DMA_TO_DEVICE; - else - dir = DMA_FROM_DEVICE; - - /* - * Fill the array using page array data and - * map the pages - this action will also flush the cache as needed - */ - for (count = 0; count < num_pages; count++) { - /* Fill the map array */ - map_array[count].dma_addr = - dma_map_page(&sep->pdev->dev, page_array[count], - 0, PAGE_SIZE, /*dir*/DMA_BIDIRECTIONAL); - - map_array[count].size = PAGE_SIZE; - - /* Fill the lli array entry */ - lli_array[count].bus_address = (u32)map_array[count].dma_addr; - lli_array[count].block_size = PAGE_SIZE; - - dev_warn(&sep->pdev->dev, "lli_array[%x].bus_address is %08lx, lli_array[%x].block_size is %x\n", - count, (unsigned long)lli_array[count].bus_address, - count, lli_array[count].block_size); - } - - /* Check the offset for the first page */ - lli_array[0].bus_address = - lli_array[0].bus_address + (app_virt_addr & (~PAGE_MASK)); - - /* Check that not all the data is in the first page only */ - if ((PAGE_SIZE - (app_virt_addr & (~PAGE_MASK))) >= data_size) - lli_array[0].block_size = data_size; - else - lli_array[0].block_size = - PAGE_SIZE - (app_virt_addr & (~PAGE_MASK)); - - dev_dbg(&sep->pdev->dev, - "lli_array[0].bus_address is %08lx, lli_array[0].block_size is %x\n", - (unsigned long)lli_array[count].bus_address, - lli_array[count].block_size); - - /* Check the size of the last page */ - if (num_pages > 1) { - lli_array[num_pages - 1].block_size = - (app_virt_addr + data_size) & (~PAGE_MASK); - if (lli_array[num_pages - 1].block_size == 0) - lli_array[num_pages - 1].block_size = PAGE_SIZE; - - dev_warn(&sep->pdev->dev, - "lli_array[%x].bus_address is " - "%08lx, lli_array[%x].block_size is %x\n", - num_pages - 1, - (unsigned long)lli_array[num_pages - 1].bus_address, - num_pages - 1, - lli_array[num_pages - 1].block_size); - } - - /* Set output params according to the in_out flag */ - if (in_out_flag == SEP_DRIVER_IN_FLAG) { - *lli_array_ptr = lli_array; - sep->dma_res_arr[sep->nr_dcb_creat].in_num_pages = num_pages; - sep->dma_res_arr[sep->nr_dcb_creat].in_page_array = page_array; - sep->dma_res_arr[sep->nr_dcb_creat].in_map_array = map_array; - sep->dma_res_arr[sep->nr_dcb_creat].in_map_num_entries = - num_pages; - } else { - *lli_array_ptr = lli_array; - sep->dma_res_arr[sep->nr_dcb_creat].out_num_pages = num_pages; - sep->dma_res_arr[sep->nr_dcb_creat].out_page_array = - page_array; - sep->dma_res_arr[sep->nr_dcb_creat].out_map_array = map_array; - sep->dma_res_arr[sep->nr_dcb_creat].out_map_num_entries = - num_pages; - } - goto end_function; - -end_function_with_error3: - /* Free lli array */ - kfree(lli_array); - -end_function_with_error2: - kfree(map_array); - -end_function_with_error1: - /* Free page array */ - kfree(page_array); - -end_function: - return error; -} - -/** - * u32 sep_calculate_lli_table_max_size - size the LLI table - * @sep: pointer to struct sep_device - * @lli_in_array_ptr - * @num_array_entries - * @last_table_flag - * - * This function calculates the size of data that can be inserted into - * the lli table from this array, such that either the table is full - * (all entries are entered), or there are no more entries in the - * lli array - */ -static u32 sep_calculate_lli_table_max_size(struct sep_device *sep, - struct sep_lli_entry *lli_in_array_ptr, - u32 num_array_entries, - u32 *last_table_flag) -{ - u32 counter; - /* Table data size */ - u32 table_data_size = 0; - /* Data size for the next table */ - u32 next_table_data_size; - - *last_table_flag = 0; - - /* - * Calculate the data in the out lli table till we fill the whole - * table or till the data has ended - */ - for (counter = 0; - (counter < (SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP - 1)) && - (counter < num_array_entries); counter++) - table_data_size += lli_in_array_ptr[counter].block_size; - - /* - * Check if we reached the last entry, - * meaning this ia the last table to build, - * and no need to check the block alignment - */ - if (counter == num_array_entries) { - /* Set the last table flag */ - *last_table_flag = 1; - goto end_function; - } - - /* - * Calculate the data size of the next table. - * Stop if no entries left or if data size is more the DMA restriction - */ - next_table_data_size = 0; - for (; counter < num_array_entries; counter++) { - next_table_data_size += lli_in_array_ptr[counter].block_size; - if (next_table_data_size >= SEP_DRIVER_MIN_DATA_SIZE_PER_TABLE) - break; - } - - /* - * Check if the next table data size is less then DMA rstriction. - * if it is - recalculate the current table size, so that the next - * table data size will be adaquete for DMA - */ - if (next_table_data_size && - next_table_data_size < SEP_DRIVER_MIN_DATA_SIZE_PER_TABLE) - - table_data_size -= (SEP_DRIVER_MIN_DATA_SIZE_PER_TABLE - - next_table_data_size); - -end_function: - return table_data_size; -} - -/** - * sep_build_lli_table - build an lli array for the given table - * @sep: pointer to struct sep_device - * @lli_array_ptr: pointer to lli array - * @lli_table_ptr: pointer to lli table - * @num_processed_entries_ptr: pointer to number of entries - * @num_table_entries_ptr: pointer to number of tables - * @table_data_size: total data size - * - * Builds ant lli table from the lli_array according to - * the given size of data - */ -static void sep_build_lli_table(struct sep_device *sep, - struct sep_lli_entry *lli_array_ptr, - struct sep_lli_entry *lli_table_ptr, - u32 *num_processed_entries_ptr, - u32 *num_table_entries_ptr, - u32 table_data_size) -{ - /* Current table data size */ - u32 curr_table_data_size; - /* Counter of lli array entry */ - u32 array_counter; - - /* Init current table data size and lli array entry counter */ - curr_table_data_size = 0; - array_counter = 0; - *num_table_entries_ptr = 1; - - dev_dbg(&sep->pdev->dev, "build lli table table_data_size is %x\n", table_data_size); - - /* Fill the table till table size reaches the needed amount */ - while (curr_table_data_size < table_data_size) { - /* Update the number of entries in table */ - (*num_table_entries_ptr)++; - - lli_table_ptr->bus_address = - cpu_to_le32(lli_array_ptr[array_counter].bus_address); - - lli_table_ptr->block_size = - cpu_to_le32(lli_array_ptr[array_counter].block_size); - - curr_table_data_size += lli_array_ptr[array_counter].block_size; - - dev_dbg(&sep->pdev->dev, "lli_table_ptr is %p\n", - lli_table_ptr); - dev_dbg(&sep->pdev->dev, "lli_table_ptr->bus_address is %08lx\n", - (unsigned long)lli_table_ptr->bus_address); - dev_dbg(&sep->pdev->dev, "lli_table_ptr->block_size is %x\n", - lli_table_ptr->block_size); - - /* Check for overflow of the table data */ - if (curr_table_data_size > table_data_size) { - dev_dbg(&sep->pdev->dev, - "curr_table_data_size too large\n"); - - /* Update the size of block in the table */ - lli_table_ptr->block_size -= - cpu_to_le32((curr_table_data_size - table_data_size)); - - /* Update the physical address in the lli array */ - lli_array_ptr[array_counter].bus_address += - cpu_to_le32(lli_table_ptr->block_size); - - /* Update the block size left in the lli array */ - lli_array_ptr[array_counter].block_size = - (curr_table_data_size - table_data_size); - } else - /* Advance to the next entry in the lli_array */ - array_counter++; - - dev_dbg(&sep->pdev->dev, - "lli_table_ptr->bus_address is %08lx\n", - (unsigned long)lli_table_ptr->bus_address); - dev_dbg(&sep->pdev->dev, - "lli_table_ptr->block_size is %x\n", - lli_table_ptr->block_size); - - /* Move to the next entry in table */ - lli_table_ptr++; - } - - /* Set the info entry to default */ - lli_table_ptr->bus_address = 0xffffffff; - lli_table_ptr->block_size = 0; - - /* Set the output parameter */ - *num_processed_entries_ptr += array_counter; - -} - -/** - * sep_shared_area_virt_to_bus - map shared area to bus address - * @sep: pointer to struct sep_device - * @virt_address: virtual address to convert - * - * This functions returns the physical address inside shared area according - * to the virtual address. It can be either on the externa RAM device - * (ioremapped), or on the system RAM - * This implementation is for the external RAM - */ -static dma_addr_t sep_shared_area_virt_to_bus(struct sep_device *sep, - void *virt_address) -{ - dev_dbg(&sep->pdev->dev, "sh virt to phys v %p\n", virt_address); - dev_dbg(&sep->pdev->dev, "sh virt to phys p %08lx\n", - (unsigned long) - sep->shared_bus + (virt_address - sep->shared_addr)); - - return sep->shared_bus + (size_t)(virt_address - sep->shared_addr); -} - -/** - * sep_shared_area_bus_to_virt - map shared area bus address to kernel - * @sep: pointer to struct sep_device - * @bus_address: bus address to convert - * - * This functions returns the virtual address inside shared area - * according to the physical address. It can be either on the - * externa RAM device (ioremapped), or on the system RAM - * This implementation is for the external RAM - */ -static void *sep_shared_area_bus_to_virt(struct sep_device *sep, - dma_addr_t bus_address) -{ - dev_dbg(&sep->pdev->dev, "shared bus to virt b=%lx v=%lx\n", - (unsigned long)bus_address, (unsigned long)(sep->shared_addr + - (size_t)(bus_address - sep->shared_bus))); - - return sep->shared_addr + (size_t)(bus_address - sep->shared_bus); -} - -/** - * sep_debug_print_lli_tables - dump LLI table - * @sep: pointer to struct sep_device - * @lli_table_ptr: pointer to sep_lli_entry - * @num_table_entries: number of entries - * @table_data_size: total data size - * - * Walk the the list of the print created tables and print all the data - */ -static void sep_debug_print_lli_tables(struct sep_device *sep, - struct sep_lli_entry *lli_table_ptr, - unsigned long num_table_entries, - unsigned long table_data_size) -{ - unsigned long table_count = 1; - unsigned long entries_count = 0; - - dev_dbg(&sep->pdev->dev, "sep_debug_print_lli_tables start\n"); - - while ((unsigned long) lli_table_ptr->bus_address != 0xffffffff) { - dev_dbg(&sep->pdev->dev, - "lli table %08lx, table_data_size is %lu\n", - table_count, table_data_size); - dev_dbg(&sep->pdev->dev, "num_table_entries is %lu\n", - num_table_entries); - - /* Print entries of the table (without info entry) */ - for (entries_count = 0; entries_count < num_table_entries; - entries_count++, lli_table_ptr++) { - - dev_dbg(&sep->pdev->dev, - "lli_table_ptr address is %08lx\n", - (unsigned long) lli_table_ptr); - - dev_dbg(&sep->pdev->dev, - "phys address is %08lx block size is %x\n", - (unsigned long)lli_table_ptr->bus_address, - lli_table_ptr->block_size); - } - /* Point to the info entry */ - lli_table_ptr--; - - dev_dbg(&sep->pdev->dev, - "phys lli_table_ptr->block_size is %x\n", - lli_table_ptr->block_size); - - dev_dbg(&sep->pdev->dev, - "phys lli_table_ptr->physical_address is %08lu\n", - (unsigned long)lli_table_ptr->bus_address); - - - table_data_size = lli_table_ptr->block_size & 0xffffff; - num_table_entries = (lli_table_ptr->block_size >> 24) & 0xff; - - dev_dbg(&sep->pdev->dev, - "phys table_data_size is %lu num_table_entries is" - " %lu bus_address is%lu\n", table_data_size, - num_table_entries, (unsigned long)lli_table_ptr->bus_address); - - if ((unsigned long)lli_table_ptr->bus_address != 0xffffffff) - lli_table_ptr = (struct sep_lli_entry *) - sep_shared_bus_to_virt(sep, - (unsigned long)lli_table_ptr->bus_address); - - table_count++; - } - dev_dbg(&sep->pdev->dev, "sep_debug_print_lli_tables end\n"); -} - - -/** - * sep_prepare_empty_lli_table - create a blank LLI table - * @sep: pointer to struct sep_device - * @lli_table_addr_ptr: pointer to lli table - * @num_entries_ptr: pointer to number of entries - * @table_data_size_ptr: point to table data size - * - * This function creates empty lli tables when there is no data - */ -static void sep_prepare_empty_lli_table(struct sep_device *sep, - dma_addr_t *lli_table_addr_ptr, - u32 *num_entries_ptr, - u32 *table_data_size_ptr) -{ - struct sep_lli_entry *lli_table_ptr; - - /* Find the area for new table */ - lli_table_ptr = - (struct sep_lli_entry *)(sep->shared_addr + - SYNCHRONIC_DMA_TABLES_AREA_OFFSET_BYTES + - sep->num_lli_tables_created * sizeof(struct sep_lli_entry) * - SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP); - - lli_table_ptr->bus_address = 0; - lli_table_ptr->block_size = 0; - - lli_table_ptr++; - lli_table_ptr->bus_address = 0xFFFFFFFF; - lli_table_ptr->block_size = 0; - - /* Set the output parameter value */ - *lli_table_addr_ptr = sep->shared_bus + - SYNCHRONIC_DMA_TABLES_AREA_OFFSET_BYTES + - sep->num_lli_tables_created * - sizeof(struct sep_lli_entry) * - SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP; - - /* Set the num of entries and table data size for empty table */ - *num_entries_ptr = 2; - *table_data_size_ptr = 0; - - /* Update the number of created tables */ - sep->num_lli_tables_created++; -} - -/** - * sep_prepare_input_dma_table - prepare input DMA mappings - * @sep: pointer to struct sep_device - * @data_size: - * @block_size: - * @lli_table_ptr: - * @num_entries_ptr: - * @table_data_size_ptr: - * @is_kva: set for kernel data (kernel cryptio call) - * - * This function prepares only input DMA table for synhronic symmetric - * operations (HASH) - * Note that all bus addresses that are passed to the SEP - * are in 32 bit format; the SEP is a 32 bit device - */ -static int sep_prepare_input_dma_table(struct sep_device *sep, - unsigned long app_virt_addr, - u32 data_size, - u32 block_size, - dma_addr_t *lli_table_ptr, - u32 *num_entries_ptr, - u32 *table_data_size_ptr, - bool is_kva) -{ - int error = 0; - /* Pointer to the info entry of the table - the last entry */ - struct sep_lli_entry *info_entry_ptr; - /* Array of pointers to page */ - struct sep_lli_entry *lli_array_ptr; - /* Points to the first entry to be processed in the lli_in_array */ - u32 current_entry = 0; - /* Num entries in the virtual buffer */ - u32 sep_lli_entries = 0; - /* Lli table pointer */ - struct sep_lli_entry *in_lli_table_ptr; - /* The total data in one table */ - u32 table_data_size = 0; - /* Flag for last table */ - u32 last_table_flag = 0; - /* Number of entries in lli table */ - u32 num_entries_in_table = 0; - /* Next table address */ - void *lli_table_alloc_addr = 0; - - dev_dbg(&sep->pdev->dev, "prepare intput dma table data_size is %x\n", data_size); - dev_dbg(&sep->pdev->dev, "block_size is %x\n", block_size); - - /* Initialize the pages pointers */ - sep->dma_res_arr[sep->nr_dcb_creat].in_page_array = NULL; - sep->dma_res_arr[sep->nr_dcb_creat].in_num_pages = 0; - - /* Set the kernel address for first table to be allocated */ - lli_table_alloc_addr = (void *)(sep->shared_addr + - SYNCHRONIC_DMA_TABLES_AREA_OFFSET_BYTES + - sep->num_lli_tables_created * sizeof(struct sep_lli_entry) * - SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP); - - if (data_size == 0) { - /* Special case - create meptu table - 2 entries, zero data */ - sep_prepare_empty_lli_table(sep, lli_table_ptr, - num_entries_ptr, table_data_size_ptr); - goto update_dcb_counter; - } - - /* Check if the pages are in Kernel Virtual Address layout */ - if (is_kva == true) - /* Lock the pages in the kernel */ - error = sep_lock_kernel_pages(sep, app_virt_addr, - data_size, &lli_array_ptr, SEP_DRIVER_IN_FLAG); - else - /* - * Lock the pages of the user buffer - * and translate them to pages - */ - error = sep_lock_user_pages(sep, app_virt_addr, - data_size, &lli_array_ptr, SEP_DRIVER_IN_FLAG); - - if (error) - goto end_function; - - dev_dbg(&sep->pdev->dev, "output sep_in_num_pages is %x\n", - sep->dma_res_arr[sep->nr_dcb_creat].in_num_pages); - - current_entry = 0; - info_entry_ptr = NULL; - - sep_lli_entries = sep->dma_res_arr[sep->nr_dcb_creat].in_num_pages; - - /* Loop till all the entries in in array are not processed */ - while (current_entry < sep_lli_entries) { - - /* Set the new input and output tables */ - in_lli_table_ptr = - (struct sep_lli_entry *)lli_table_alloc_addr; - - lli_table_alloc_addr += sizeof(struct sep_lli_entry) * - SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP; - - if (lli_table_alloc_addr > - ((void *)sep->shared_addr + - SYNCHRONIC_DMA_TABLES_AREA_OFFSET_BYTES + - SYNCHRONIC_DMA_TABLES_AREA_SIZE_BYTES)) { - - error = -ENOMEM; - goto end_function_error; - - } - - /* Update the number of created tables */ - sep->num_lli_tables_created++; - - /* Calculate the maximum size of data for input table */ - table_data_size = sep_calculate_lli_table_max_size(sep, - &lli_array_ptr[current_entry], - (sep_lli_entries - current_entry), - &last_table_flag); - - /* - * If this is not the last table - - * then align it to the block size - */ - if (!last_table_flag) - table_data_size = - (table_data_size / block_size) * block_size; - - dev_dbg(&sep->pdev->dev, "output table_data_size is %x\n", - table_data_size); - - /* Construct input lli table */ - sep_build_lli_table(sep, &lli_array_ptr[current_entry], - in_lli_table_ptr, - ¤t_entry, &num_entries_in_table, table_data_size); - - if (info_entry_ptr == NULL) { - - /* Set the output parameters to physical addresses */ - *lli_table_ptr = sep_shared_area_virt_to_bus(sep, - in_lli_table_ptr); - *num_entries_ptr = num_entries_in_table; - *table_data_size_ptr = table_data_size; - - dev_dbg(&sep->pdev->dev, - "output lli_table_in_ptr is %08lx\n", - (unsigned long)*lli_table_ptr); - - } else { - /* Update the info entry of the previous in table */ - info_entry_ptr->bus_address = - sep_shared_area_virt_to_bus(sep, - in_lli_table_ptr); - info_entry_ptr->block_size = - ((num_entries_in_table) << 24) | - (table_data_size); - } - /* Save the pointer to the info entry of the current tables */ - info_entry_ptr = in_lli_table_ptr + num_entries_in_table - 1; - } - /* Print input tables */ - sep_debug_print_lli_tables(sep, (struct sep_lli_entry *) - sep_shared_area_bus_to_virt(sep, *lli_table_ptr), - *num_entries_ptr, *table_data_size_ptr); - /* The array of the pages */ - kfree(lli_array_ptr); - -update_dcb_counter: - /* Update DCB counter */ - sep->nr_dcb_creat++; - goto end_function; - -end_function_error: - /* Free all the allocated resources */ - kfree(sep->dma_res_arr[sep->nr_dcb_creat].in_map_array); - kfree(lli_array_ptr); - kfree(sep->dma_res_arr[sep->nr_dcb_creat].in_page_array); - -end_function: - return error; - -} -/** - * sep_construct_dma_tables_from_lli - prepare AES/DES mappings - * @sep: pointer to struct sep_device - * @lli_in_array: - * @sep_in_lli_entries: - * @lli_out_array: - * @sep_out_lli_entries - * @block_size - * @lli_table_in_ptr - * @lli_table_out_ptr - * @in_num_entries_ptr - * @out_num_entries_ptr - * @table_data_size_ptr - * - * This function creates the input and output DMA tables for - * symmetric operations (AES/DES) according to the block - * size from LLI arays - * Note that all bus addresses that are passed to the SEP - * are in 32 bit format; the SEP is a 32 bit device - */ -static int sep_construct_dma_tables_from_lli( - struct sep_device *sep, - struct sep_lli_entry *lli_in_array, - u32 sep_in_lli_entries, - struct sep_lli_entry *lli_out_array, - u32 sep_out_lli_entries, - u32 block_size, - dma_addr_t *lli_table_in_ptr, - dma_addr_t *lli_table_out_ptr, - u32 *in_num_entries_ptr, - u32 *out_num_entries_ptr, - u32 *table_data_size_ptr) -{ - /* Points to the area where next lli table can be allocated */ - void *lli_table_alloc_addr = 0; - /* Input lli table */ - struct sep_lli_entry *in_lli_table_ptr = NULL; - /* Output lli table */ - struct sep_lli_entry *out_lli_table_ptr = NULL; - /* Pointer to the info entry of the table - the last entry */ - struct sep_lli_entry *info_in_entry_ptr = NULL; - /* Pointer to the info entry of the table - the last entry */ - struct sep_lli_entry *info_out_entry_ptr = NULL; - /* Points to the first entry to be processed in the lli_in_array */ - u32 current_in_entry = 0; - /* Points to the first entry to be processed in the lli_out_array */ - u32 current_out_entry = 0; - /* Max size of the input table */ - u32 in_table_data_size = 0; - /* Max size of the output table */ - u32 out_table_data_size = 0; - /* Flag te signifies if this is the last tables build */ - u32 last_table_flag = 0; - /* The data size that should be in table */ - u32 table_data_size = 0; - /* Number of etnries in the input table */ - u32 num_entries_in_table = 0; - /* Number of etnries in the output table */ - u32 num_entries_out_table = 0; - - /* Initiate to point after the message area */ - lli_table_alloc_addr = (void *)(sep->shared_addr + - SYNCHRONIC_DMA_TABLES_AREA_OFFSET_BYTES + - (sep->num_lli_tables_created * - (sizeof(struct sep_lli_entry) * - SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP))); - - /* Loop till all the entries in in array are not processed */ - while (current_in_entry < sep_in_lli_entries) { - /* Set the new input and output tables */ - in_lli_table_ptr = - (struct sep_lli_entry *)lli_table_alloc_addr; - - lli_table_alloc_addr += sizeof(struct sep_lli_entry) * - SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP; - - /* Set the first output tables */ - out_lli_table_ptr = - (struct sep_lli_entry *)lli_table_alloc_addr; - - /* Check if the DMA table area limit was overrun */ - if ((lli_table_alloc_addr + sizeof(struct sep_lli_entry) * - SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP) > - ((void *)sep->shared_addr + - SYNCHRONIC_DMA_TABLES_AREA_OFFSET_BYTES + - SYNCHRONIC_DMA_TABLES_AREA_SIZE_BYTES)) { - - dev_warn(&sep->pdev->dev, "dma table limit overrun\n"); - return -ENOMEM; - } - - /* Update the number of the lli tables created */ - sep->num_lli_tables_created += 2; - - lli_table_alloc_addr += sizeof(struct sep_lli_entry) * - SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP; - - /* Calculate the maximum size of data for input table */ - in_table_data_size = - sep_calculate_lli_table_max_size(sep, - &lli_in_array[current_in_entry], - (sep_in_lli_entries - current_in_entry), - &last_table_flag); - - /* Calculate the maximum size of data for output table */ - out_table_data_size = - sep_calculate_lli_table_max_size(sep, - &lli_out_array[current_out_entry], - (sep_out_lli_entries - current_out_entry), - &last_table_flag); - - dev_dbg(&sep->pdev->dev, - "construct tables from lli in_table_data_size is %x\n", - in_table_data_size); - - dev_dbg(&sep->pdev->dev, - "construct tables from lli out_table_data_size is %x\n", - out_table_data_size); - - table_data_size = in_table_data_size; - - if (!last_table_flag) { - /* - * If this is not the last table, - * then must check where the data is smallest - * and then align it to the block size - */ - if (table_data_size > out_table_data_size) - table_data_size = out_table_data_size; - - /* - * Now calculate the table size so that - * it will be module block size - */ - table_data_size = (table_data_size / block_size) * - block_size; - } - - /* Construct input lli table */ - sep_build_lli_table(sep, &lli_in_array[current_in_entry], - in_lli_table_ptr, - ¤t_in_entry, - &num_entries_in_table, - table_data_size); - - /* Construct output lli table */ - sep_build_lli_table(sep, &lli_out_array[current_out_entry], - out_lli_table_ptr, - ¤t_out_entry, - &num_entries_out_table, - table_data_size); - - /* If info entry is null - this is the first table built */ - if (info_in_entry_ptr == NULL) { - /* Set the output parameters to physical addresses */ - *lli_table_in_ptr = - sep_shared_area_virt_to_bus(sep, in_lli_table_ptr); - - *in_num_entries_ptr = num_entries_in_table; - - *lli_table_out_ptr = - sep_shared_area_virt_to_bus(sep, - out_lli_table_ptr); - - *out_num_entries_ptr = num_entries_out_table; - *table_data_size_ptr = table_data_size; - - dev_dbg(&sep->pdev->dev, - "output lli_table_in_ptr is %08lx\n", - (unsigned long)*lli_table_in_ptr); - dev_dbg(&sep->pdev->dev, - "output lli_table_out_ptr is %08lx\n", - (unsigned long)*lli_table_out_ptr); - } else { - /* Update the info entry of the previous in table */ - info_in_entry_ptr->bus_address = - sep_shared_area_virt_to_bus(sep, - in_lli_table_ptr); - - info_in_entry_ptr->block_size = - ((num_entries_in_table) << 24) | - (table_data_size); - - /* Update the info entry of the previous in table */ - info_out_entry_ptr->bus_address = - sep_shared_area_virt_to_bus(sep, - out_lli_table_ptr); - - info_out_entry_ptr->block_size = - ((num_entries_out_table) << 24) | - (table_data_size); - - dev_dbg(&sep->pdev->dev, - "output lli_table_in_ptr:%08lx %08x\n", - (unsigned long)info_in_entry_ptr->bus_address, - info_in_entry_ptr->block_size); - - dev_dbg(&sep->pdev->dev, - "output lli_table_out_ptr:%08lx %08x\n", - (unsigned long)info_out_entry_ptr->bus_address, - info_out_entry_ptr->block_size); - } - - /* Save the pointer to the info entry of the current tables */ - info_in_entry_ptr = in_lli_table_ptr + - num_entries_in_table - 1; - info_out_entry_ptr = out_lli_table_ptr + - num_entries_out_table - 1; - - dev_dbg(&sep->pdev->dev, - "output num_entries_out_table is %x\n", - (u32)num_entries_out_table); - dev_dbg(&sep->pdev->dev, - "output info_in_entry_ptr is %lx\n", - (unsigned long)info_in_entry_ptr); - dev_dbg(&sep->pdev->dev, - "output info_out_entry_ptr is %lx\n", - (unsigned long)info_out_entry_ptr); - } - - /* Print input tables */ - sep_debug_print_lli_tables(sep, - (struct sep_lli_entry *) - sep_shared_area_bus_to_virt(sep, *lli_table_in_ptr), - *in_num_entries_ptr, - *table_data_size_ptr); - - /* Print output tables */ - sep_debug_print_lli_tables(sep, - (struct sep_lli_entry *) - sep_shared_area_bus_to_virt(sep, *lli_table_out_ptr), - *out_num_entries_ptr, - *table_data_size_ptr); - - return 0; -} - -/** - * sep_prepare_input_output_dma_table - prepare DMA I/O table - * @app_virt_in_addr: - * @app_virt_out_addr: - * @data_size: - * @block_size: - * @lli_table_in_ptr: - * @lli_table_out_ptr: - * @in_num_entries_ptr: - * @out_num_entries_ptr: - * @table_data_size_ptr: - * @is_kva: set for kernel data; used only for kernel crypto module - * - * This function builds input and output DMA tables for synhronic - * symmetric operations (AES, DES, HASH). It also checks that each table - * is of the modular block size - * Note that all bus addresses that are passed to the SEP - * are in 32 bit format; the SEP is a 32 bit device - */ -static int sep_prepare_input_output_dma_table(struct sep_device *sep, - unsigned long app_virt_in_addr, - unsigned long app_virt_out_addr, - u32 data_size, - u32 block_size, - dma_addr_t *lli_table_in_ptr, - dma_addr_t *lli_table_out_ptr, - u32 *in_num_entries_ptr, - u32 *out_num_entries_ptr, - u32 *table_data_size_ptr, - bool is_kva) - -{ - int error = 0; - /* Array of pointers of page */ - struct sep_lli_entry *lli_in_array; - /* Array of pointers of page */ - struct sep_lli_entry *lli_out_array; - - if (data_size == 0) { - /* Prepare empty table for input and output */ - sep_prepare_empty_lli_table(sep, lli_table_in_ptr, - in_num_entries_ptr, table_data_size_ptr); - - sep_prepare_empty_lli_table(sep, lli_table_out_ptr, - out_num_entries_ptr, table_data_size_ptr); - - goto update_dcb_counter; - } - - /* Initialize the pages pointers */ - sep->dma_res_arr[sep->nr_dcb_creat].in_page_array = NULL; - sep->dma_res_arr[sep->nr_dcb_creat].out_page_array = NULL; - - /* Lock the pages of the buffer and translate them to pages */ - if (is_kva == true) { - error = sep_lock_kernel_pages(sep, app_virt_in_addr, - data_size, &lli_in_array, SEP_DRIVER_IN_FLAG); - - if (error) { - dev_warn(&sep->pdev->dev, - "lock kernel for in failed\n"); - goto end_function; - } - - error = sep_lock_kernel_pages(sep, app_virt_out_addr, - data_size, &lli_out_array, SEP_DRIVER_OUT_FLAG); - - if (error) { - dev_warn(&sep->pdev->dev, - "lock kernel for out failed\n"); - goto end_function; - } - } - - else { - error = sep_lock_user_pages(sep, app_virt_in_addr, - data_size, &lli_in_array, SEP_DRIVER_IN_FLAG); - if (error) { - dev_warn(&sep->pdev->dev, - "sep_lock_user_pages for input virtual buffer failed\n"); - goto end_function; - } - - error = sep_lock_user_pages(sep, app_virt_out_addr, - data_size, &lli_out_array, SEP_DRIVER_OUT_FLAG); - - if (error) { - dev_warn(&sep->pdev->dev, - "sep_lock_user_pages for output virtual buffer failed\n"); - goto end_function_free_lli_in; - } - } - - dev_dbg(&sep->pdev->dev, "prep input output dma table sep_in_num_pages is %x\n", - sep->dma_res_arr[sep->nr_dcb_creat].in_num_pages); - dev_dbg(&sep->pdev->dev, "sep_out_num_pages is %x\n", - sep->dma_res_arr[sep->nr_dcb_creat].out_num_pages); - dev_dbg(&sep->pdev->dev, "SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP is %x\n", - SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP); - - /* Call the function that creates table from the lli arrays */ - error = sep_construct_dma_tables_from_lli(sep, lli_in_array, - sep->dma_res_arr[sep->nr_dcb_creat].in_num_pages, - lli_out_array, - sep->dma_res_arr[sep->nr_dcb_creat].out_num_pages, - block_size, lli_table_in_ptr, lli_table_out_ptr, - in_num_entries_ptr, out_num_entries_ptr, table_data_size_ptr); - - if (error) { - dev_warn(&sep->pdev->dev, - "sep_construct_dma_tables_from_lli failed\n"); - goto end_function_with_error; - } - - kfree(lli_out_array); - kfree(lli_in_array); - -update_dcb_counter: - /* Update DCB counter */ - sep->nr_dcb_creat++; - - goto end_function; - -end_function_with_error: - kfree(sep->dma_res_arr[sep->nr_dcb_creat].out_map_array); - kfree(sep->dma_res_arr[sep->nr_dcb_creat].out_page_array); - kfree(lli_out_array); - - -end_function_free_lli_in: - kfree(sep->dma_res_arr[sep->nr_dcb_creat].in_map_array); - kfree(sep->dma_res_arr[sep->nr_dcb_creat].in_page_array); - kfree(lli_in_array); - -end_function: - - return error; - -} - -/** - * sep_prepare_input_output_dma_table_in_dcb - prepare control blocks - * @app_in_address: unsigned long; for data buffer in (user space) - * @app_out_address: unsigned long; for data buffer out (user space) - * @data_in_size: u32; for size of data - * @block_size: u32; for block size - * @tail_block_size: u32; for size of tail block - * @isapplet: bool; to indicate external app - * @is_kva: bool; kernel buffer; only used for kernel crypto module - * - * This function prepares the linked DMA tables and puts the - * address for the linked list of tables inta a DCB (data control - * block) the address of which is known by the SEP hardware - * Note that all bus addresses that are passed to the SEP - * are in 32 bit format; the SEP is a 32 bit device - */ -static int sep_prepare_input_output_dma_table_in_dcb(struct sep_device *sep, - unsigned long app_in_address, - unsigned long app_out_address, - u32 data_in_size, - u32 block_size, - u32 tail_block_size, - bool isapplet, - bool is_kva) -{ - int error = 0; - /* Size of tail */ - u32 tail_size = 0; - /* Address of the created DCB table */ - struct sep_dcblock *dcb_table_ptr = NULL; - /* The physical address of the first input DMA table */ - dma_addr_t in_first_mlli_address = 0; - /* Number of entries in the first input DMA table */ - u32 in_first_num_entries = 0; - /* The physical address of the first output DMA table */ - dma_addr_t out_first_mlli_address = 0; - /* Number of entries in the first output DMA table */ - u32 out_first_num_entries = 0; - /* Data in the first input/output table */ - u32 first_data_size = 0; - - if (sep->nr_dcb_creat == SEP_MAX_NUM_SYNC_DMA_OPS) { - /* No more DCBs to allocate */ - dev_warn(&sep->pdev->dev, "no more DCBs available\n"); - error = -ENOSPC; - goto end_function; - } - - /* Allocate new DCB */ - dcb_table_ptr = (struct sep_dcblock *)(sep->shared_addr + - SEP_DRIVER_SYSTEM_DCB_MEMORY_OFFSET_IN_BYTES + - (sep->nr_dcb_creat * sizeof(struct sep_dcblock))); - - /* Set the default values in the DCB */ - dcb_table_ptr->input_mlli_address = 0; - dcb_table_ptr->input_mlli_num_entries = 0; - dcb_table_ptr->input_mlli_data_size = 0; - dcb_table_ptr->output_mlli_address = 0; - dcb_table_ptr->output_mlli_num_entries = 0; - dcb_table_ptr->output_mlli_data_size = 0; - dcb_table_ptr->tail_data_size = 0; - dcb_table_ptr->out_vr_tail_pt = 0; - - if (isapplet == true) { - - /* Check if there is enough data for DMA operation */ - if (data_in_size < SEP_DRIVER_MIN_DATA_SIZE_PER_TABLE) { - if (is_kva == true) { - memcpy(dcb_table_ptr->tail_data, - (void *)app_in_address, data_in_size); - } else { - if (copy_from_user(dcb_table_ptr->tail_data, - (void __user *)app_in_address, - data_in_size)) { - error = -EFAULT; - goto end_function; - } - } - - dcb_table_ptr->tail_data_size = data_in_size; - - /* Set the output user-space address for mem2mem op */ - if (app_out_address) - dcb_table_ptr->out_vr_tail_pt = - (aligned_u64)app_out_address; - - /* - * Update both data length parameters in order to avoid - * second data copy and allow building of empty mlli - * tables - */ - tail_size = 0x0; - data_in_size = 0x0; - - } else { - if (!app_out_address) { - tail_size = data_in_size % block_size; - if (!tail_size) { - if (tail_block_size == block_size) - tail_size = block_size; - } - } else { - tail_size = 0; - } - } - if (tail_size) { - if (tail_size > sizeof(dcb_table_ptr->tail_data)) - return -EINVAL; - if (is_kva == true) { - memcpy(dcb_table_ptr->tail_data, - (void *)(app_in_address + data_in_size - - tail_size), tail_size); - } else { - /* We have tail data - copy it to DCB */ - if (copy_from_user(dcb_table_ptr->tail_data, - (void *)(app_in_address + - data_in_size - tail_size), tail_size)) { - error = -EFAULT; - goto end_function; - } - } - if (app_out_address) - /* - * Calculate the output address - * according to tail data size - */ - dcb_table_ptr->out_vr_tail_pt = - (aligned_u64)app_out_address + data_in_size - - tail_size; - - /* Save the real tail data size */ - dcb_table_ptr->tail_data_size = tail_size; - /* - * Update the data size without the tail - * data size AKA data for the dma - */ - data_in_size = (data_in_size - tail_size); - } - } - /* Check if we need to build only input table or input/output */ - if (app_out_address) { - /* Prepare input/output tables */ - error = sep_prepare_input_output_dma_table(sep, - app_in_address, - app_out_address, - data_in_size, - block_size, - &in_first_mlli_address, - &out_first_mlli_address, - &in_first_num_entries, - &out_first_num_entries, - &first_data_size, - is_kva); - } else { - /* Prepare input tables */ - error = sep_prepare_input_dma_table(sep, - app_in_address, - data_in_size, - block_size, - &in_first_mlli_address, - &in_first_num_entries, - &first_data_size, - is_kva); - } - - if (error) { - dev_warn(&sep->pdev->dev, "prepare DMA table call failed from prepare DCB call\n"); - goto end_function; - } - - /* Set the DCB values */ - dcb_table_ptr->input_mlli_address = in_first_mlli_address; - dcb_table_ptr->input_mlli_num_entries = in_first_num_entries; - dcb_table_ptr->input_mlli_data_size = first_data_size; - dcb_table_ptr->output_mlli_address = out_first_mlli_address; - dcb_table_ptr->output_mlli_num_entries = out_first_num_entries; - dcb_table_ptr->output_mlli_data_size = first_data_size; - -end_function: - return error; - -} - -/** - * sep_free_dma_tables_and_dcb - free DMA tables and DCBs - * @sep: pointer to struct sep_device - * @isapplet: indicates external application (used for kernel access) - * @is_kva: indicates kernel addresses (only used for kernel crypto) - * - * This function frees the DMA tables and DCB - */ -static int sep_free_dma_tables_and_dcb(struct sep_device *sep, bool isapplet, - bool is_kva) -{ - int i = 0; - int error = 0; - int error_temp = 0; - struct sep_dcblock *dcb_table_ptr; - unsigned long pt_hold; - void *tail_pt; - - if (isapplet == true) { - /* Set pointer to first DCB table */ - dcb_table_ptr = (struct sep_dcblock *) - (sep->shared_addr + - SEP_DRIVER_SYSTEM_DCB_MEMORY_OFFSET_IN_BYTES); - - /* Go over each DCB and see if tail pointer must be updated */ - for (i = 0; i < sep->nr_dcb_creat; i++, dcb_table_ptr++) { - if (dcb_table_ptr->out_vr_tail_pt) { - pt_hold = (unsigned long)dcb_table_ptr->out_vr_tail_pt; - tail_pt = (void *)pt_hold; - if (is_kva == true) { - memcpy(tail_pt, - dcb_table_ptr->tail_data, - dcb_table_ptr->tail_data_size); - } else { - error_temp = copy_to_user( - tail_pt, - dcb_table_ptr->tail_data, - dcb_table_ptr->tail_data_size); - } - if (error_temp) { - /* Release the DMA resource */ - error = -EFAULT; - break; - } - } - } - } - /* Free the output pages, if any */ - sep_free_dma_table_data_handler(sep); - - return error; -} - -/** - * sep_get_static_pool_addr_handler - get static pool address - * @sep: pointer to struct sep_device - * - * This function sets the bus and virtual addresses of the static pool - */ -static int sep_get_static_pool_addr_handler(struct sep_device *sep) -{ - u32 *static_pool_addr = NULL; - - static_pool_addr = (u32 *)(sep->shared_addr + - SEP_DRIVER_SYSTEM_RAR_MEMORY_OFFSET_IN_BYTES); - - static_pool_addr[0] = SEP_STATIC_POOL_VAL_TOKEN; - static_pool_addr[1] = (u32)sep->shared_bus + - SEP_DRIVER_STATIC_AREA_OFFSET_IN_BYTES; - - dev_dbg(&sep->pdev->dev, "static pool segment: physical %x\n", - (u32)static_pool_addr[1]); - - return 0; -} - -/** - * sep_end_transaction_handler - end transaction - * @sep: pointer to struct sep_device - * - * This API handles the end transaction request - */ -static int sep_end_transaction_handler(struct sep_device *sep) -{ - /* Clear the data pool pointers Token */ - memset((void *)(sep->shared_addr + - SEP_DRIVER_DATA_POOL_ALLOCATION_OFFSET_IN_BYTES), - 0, sep->num_of_data_allocations*2*sizeof(u32)); - - /* Check that all the DMA resources were freed */ - sep_free_dma_table_data_handler(sep); - - clear_bit(SEP_MMAP_LOCK_BIT, &sep->in_use_flags); - - /* - * We are now through with the transaction. Let's - * allow other processes who have the device open - * to perform transactions - */ - mutex_lock(&sep->sep_mutex); - sep->pid_doing_transaction = 0; - mutex_unlock(&sep->sep_mutex); - /* Raise event for stuck contextes */ - wake_up(&sep->event); - - return 0; -} - -/** - * sep_prepare_dcb_handler - prepare a control block - * @sep: pointer to struct sep_device - * @arg: pointer to user parameters - * - * This function will retrieve the RAR buffer physical addresses, type - * & size corresponding to the RAR handles provided in the buffers vector. - */ -static int sep_prepare_dcb_handler(struct sep_device *sep, unsigned long arg) -{ - int error; - /* Command arguments */ - struct build_dcb_struct command_args; - - /* Get the command arguments */ - if (copy_from_user(&command_args, (void __user *)arg, - sizeof(struct build_dcb_struct))) { - error = -EFAULT; - goto end_function; - } - - dev_dbg(&sep->pdev->dev, "prep dcb handler app_in_address is %08llx\n", - command_args.app_in_address); - dev_dbg(&sep->pdev->dev, "app_out_address is %08llx\n", - command_args.app_out_address); - dev_dbg(&sep->pdev->dev, "data_size is %x\n", - command_args.data_in_size); - dev_dbg(&sep->pdev->dev, "block_size is %x\n", - command_args.block_size); - dev_dbg(&sep->pdev->dev, "tail block_size is %x\n", - command_args.tail_block_size); - - error = sep_prepare_input_output_dma_table_in_dcb(sep, - (unsigned long)command_args.app_in_address, - (unsigned long)command_args.app_out_address, - command_args.data_in_size, command_args.block_size, - command_args.tail_block_size, true, false); - -end_function: - return error; - -} - -/** - * sep_free_dcb_handler - free control block resources - * @sep: pointer to struct sep_device - * - * This function frees the DCB resources and updates the needed - * user-space buffers. - */ -static int sep_free_dcb_handler(struct sep_device *sep) -{ - return sep_free_dma_tables_and_dcb(sep, false, false); -} - -/** - * sep_rar_prepare_output_msg_handler - prepare an output message - * @sep: pointer to struct sep_device - * @arg: pointer to user parameters - * - * This function will retrieve the RAR buffer physical addresses, type - * & size corresponding to the RAR handles provided in the buffers vector. - */ -static int sep_rar_prepare_output_msg_handler(struct sep_device *sep, - unsigned long arg) -{ - int error = 0; - /* Command args */ - struct rar_hndl_to_bus_struct command_args; - /* Bus address */ - dma_addr_t rar_bus = 0; - /* Holds the RAR address in the system memory offset */ - u32 *rar_addr; - - /* Copy the data */ - if (copy_from_user(&command_args, (void __user *)arg, - sizeof(command_args))) { - error = -EFAULT; - goto end_function; - } - - /* Call to translation function only if user handle is not NULL */ - if (command_args.rar_handle) - return -EOPNOTSUPP; - dev_dbg(&sep->pdev->dev, "rar msg; rar_addr_bus = %x\n", (u32)rar_bus); - - /* Set value in the SYSTEM MEMORY offset */ - rar_addr = (u32 *)(sep->shared_addr + - SEP_DRIVER_SYSTEM_RAR_MEMORY_OFFSET_IN_BYTES); - - /* Copy the physical address to the System Area for the SEP */ - rar_addr[0] = SEP_RAR_VAL_TOKEN; - rar_addr[1] = rar_bus; - -end_function: - return error; -} - -/** - * sep_ioctl - ioctl api - * @filp: pointer to struct file - * @cmd: command - * @arg: pointer to argument structure - * - * Implement the ioctl methods available on the SEP device. - */ -static long sep_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -{ - int error = 0; - struct sep_device *sep = filp->private_data; - - /* Make sure we own this device */ - mutex_lock(&sep->sep_mutex); - if ((current->pid != sep->pid_doing_transaction) && - (sep->pid_doing_transaction != 0)) { - dev_dbg(&sep->pdev->dev, "ioctl pid is not owner\n"); - error = -EACCES; - } - mutex_unlock(&sep->sep_mutex); - - if (error) - return error; - - if (_IOC_TYPE(cmd) != SEP_IOC_MAGIC_NUMBER) - return -ENOTTY; - - /* Lock to prevent the daemon to interfere with operation */ - mutex_lock(&sep->ioctl_mutex); - - switch (cmd) { - case SEP_IOCSENDSEPCOMMAND: - /* Send command to SEP */ - error = sep_send_command_handler(sep); - break; - case SEP_IOCALLOCDATAPOLL: - /* Allocate data pool */ - error = sep_allocate_data_pool_memory_handler(sep, arg); - break; - case SEP_IOCGETSTATICPOOLADDR: - /* Inform the SEP the bus address of the static pool */ - error = sep_get_static_pool_addr_handler(sep); - break; - case SEP_IOCENDTRANSACTION: - error = sep_end_transaction_handler(sep); - break; - case SEP_IOCRARPREPAREMESSAGE: - error = sep_rar_prepare_output_msg_handler(sep, arg); - break; - case SEP_IOCPREPAREDCB: - error = sep_prepare_dcb_handler(sep, arg); - break; - case SEP_IOCFREEDCB: - error = sep_free_dcb_handler(sep); - break; - default: - error = -ENOTTY; - break; - } - - mutex_unlock(&sep->ioctl_mutex); - return error; -} - -/** - * sep_singleton_ioctl - ioctl api for singleton interface - * @filp: pointer to struct file - * @cmd: command - * @arg: pointer to argument structure - * - * Implement the additional ioctls for the singleton device - */ -static long sep_singleton_ioctl(struct file *filp, u32 cmd, unsigned long arg) -{ - long error = 0; - struct sep_device *sep = filp->private_data; - - /* Check that the command is for the SEP device */ - if (_IOC_TYPE(cmd) != SEP_IOC_MAGIC_NUMBER) - return -ENOTTY; - - /* Make sure we own this device */ - mutex_lock(&sep->sep_mutex); - if ((current->pid != sep->pid_doing_transaction) && - (sep->pid_doing_transaction != 0)) { - dev_dbg(&sep->pdev->dev, "singleton ioctl pid is not owner\n"); - mutex_unlock(&sep->sep_mutex); - return -EACCES; - } - - mutex_unlock(&sep->sep_mutex); - - switch (cmd) { - case SEP_IOCTLSETCALLERID: - mutex_lock(&sep->ioctl_mutex); - error = sep_set_caller_id_handler(sep, arg); - mutex_unlock(&sep->ioctl_mutex); - break; - default: - error = sep_ioctl(filp, cmd, arg); - break; - } - return error; -} - -/** - * sep_request_daemon_ioctl - ioctl for daemon - * @filp: pointer to struct file - * @cmd: command - * @arg: pointer to argument structure - * - * Called by the request daemon to perform ioctls on the daemon device - */ -static long sep_request_daemon_ioctl(struct file *filp, u32 cmd, - unsigned long arg) -{ - - long error; - struct sep_device *sep = filp->private_data; - - /* Check that the command is for SEP device */ - if (_IOC_TYPE(cmd) != SEP_IOC_MAGIC_NUMBER) - return -ENOTTY; - - /* Only one process can access ioctl at any given time */ - mutex_lock(&sep->ioctl_mutex); - - switch (cmd) { - case SEP_IOCSENDSEPRPLYCOMMAND: - /* Send reply command to SEP */ - error = sep_req_daemon_send_reply_command_handler(sep); - break; - case SEP_IOCENDTRANSACTION: - /* - * End req daemon transaction, do nothing - * will be removed upon update in middleware - * API library - */ - error = 0; - break; - default: - error = -ENOTTY; - } - mutex_unlock(&sep->ioctl_mutex); - return error; -} - -/** - * sep_inthandler - interrupt handler - * @irq: interrupt - * @dev_id: device id - */ -static irqreturn_t sep_inthandler(int irq, void *dev_id) -{ - irqreturn_t int_error = IRQ_HANDLED; - unsigned long lck_flags; - u32 reg_val, reg_val2 = 0; - struct sep_device *sep = dev_id; - - /* Read the IRR register to check if this is SEP interrupt */ - reg_val = sep_read_reg(sep, HW_HOST_IRR_REG_ADDR); - - if (reg_val & (0x1 << 13)) { - /* Lock and update the counter of reply messages */ - spin_lock_irqsave(&sep->snd_rply_lck, lck_flags); - sep->reply_ct++; - spin_unlock_irqrestore(&sep->snd_rply_lck, lck_flags); - - dev_dbg(&sep->pdev->dev, "sep int: send_ct %lx reply_ct %lx\n", - sep->send_ct, sep->reply_ct); - - /* Is this printf or daemon request? */ - reg_val2 = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR2_REG_ADDR); - dev_dbg(&sep->pdev->dev, - "SEP Interrupt - reg2 is %08x\n", reg_val2); - - if ((reg_val2 >> 30) & 0x1) { - dev_dbg(&sep->pdev->dev, "int: printf request\n"); - wake_up(&sep->event_request_daemon); - } else if (reg_val2 >> 31) { - dev_dbg(&sep->pdev->dev, "int: daemon request\n"); - wake_up(&sep->event_request_daemon); - } else { - dev_dbg(&sep->pdev->dev, "int: SEP reply\n"); - wake_up(&sep->event); - } - } else { - dev_dbg(&sep->pdev->dev, "int: not SEP interrupt\n"); - int_error = IRQ_NONE; - } - if (int_error == IRQ_HANDLED) - sep_write_reg(sep, HW_HOST_ICR_REG_ADDR, reg_val); - - return int_error; -} - -/** - * sep_reconfig_shared_area - reconfigure shared area - * @sep: pointer to struct sep_device - * - * Reconfig the shared area between HOST and SEP - needed in case - * the DX_CC_Init function was called before OS loading. - */ -static int sep_reconfig_shared_area(struct sep_device *sep) -{ - int ret_val; - - /* use to limit waiting for SEP */ - unsigned long end_time; - - /* Send the new SHARED MESSAGE AREA to the SEP */ - dev_dbg(&sep->pdev->dev, "reconfig shared; sending %08llx to sep\n", - (unsigned long long)sep->shared_bus); - - sep_write_reg(sep, HW_HOST_HOST_SEP_GPR1_REG_ADDR, sep->shared_bus); - - /* Poll for SEP response */ - ret_val = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR1_REG_ADDR); - - end_time = jiffies + (WAIT_TIME * HZ); - - while ((time_before(jiffies, end_time)) && (ret_val != 0xffffffff) && - (ret_val != sep->shared_bus)) - ret_val = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR1_REG_ADDR); - - /* Check the return value (register) */ - if (ret_val != sep->shared_bus) { - dev_warn(&sep->pdev->dev, "could not reconfig shared area\n"); - dev_warn(&sep->pdev->dev, "result was %x\n", ret_val); - ret_val = -ENOMEM; - } else - ret_val = 0; - - dev_dbg(&sep->pdev->dev, "reconfig shared area end\n"); - return ret_val; -} - -/* File operation for singleton SEP operations */ -static const struct file_operations singleton_file_operations = { - .owner = THIS_MODULE, - .unlocked_ioctl = sep_singleton_ioctl, - .poll = sep_poll, - .open = sep_singleton_open, - .release = sep_singleton_release, - .mmap = sep_mmap, -}; - -/* File operation for daemon operations */ -static const struct file_operations daemon_file_operations = { - .owner = THIS_MODULE, - .unlocked_ioctl = sep_request_daemon_ioctl, - .poll = sep_request_daemon_poll, - .open = sep_request_daemon_open, - .release = sep_request_daemon_release, - .mmap = sep_request_daemon_mmap, -}; - -/* The files operations structure of the driver */ -static const struct file_operations sep_file_operations = { - .owner = THIS_MODULE, - .unlocked_ioctl = sep_ioctl, - .poll = sep_poll, - .open = sep_open, - .release = sep_release, - .mmap = sep_mmap, -}; - -/** - * sep_register_driver_with_fs - register misc devices - * @sep: pointer to struct sep_device - * - * This function registers the driver with the file system - */ -static int sep_register_driver_with_fs(struct sep_device *sep) -{ - int ret_val; - - sep->miscdev_sep.minor = MISC_DYNAMIC_MINOR; - sep->miscdev_sep.name = SEP_DEV_NAME; - sep->miscdev_sep.fops = &sep_file_operations; - - sep->miscdev_singleton.minor = MISC_DYNAMIC_MINOR; - sep->miscdev_singleton.name = SEP_DEV_SINGLETON; - sep->miscdev_singleton.fops = &singleton_file_operations; - - sep->miscdev_daemon.minor = MISC_DYNAMIC_MINOR; - sep->miscdev_daemon.name = SEP_DEV_DAEMON; - sep->miscdev_daemon.fops = &daemon_file_operations; - - ret_val = misc_register(&sep->miscdev_sep); - if (ret_val) { - dev_warn(&sep->pdev->dev, "misc reg fails for SEP %x\n", - ret_val); - return ret_val; - } - - ret_val = misc_register(&sep->miscdev_singleton); - if (ret_val) { - dev_warn(&sep->pdev->dev, "misc reg fails for sing %x\n", - ret_val); - misc_deregister(&sep->miscdev_sep); - return ret_val; - } - - ret_val = misc_register(&sep->miscdev_daemon); - if (ret_val) { - dev_warn(&sep->pdev->dev, "misc reg fails for dmn %x\n", - ret_val); - misc_deregister(&sep->miscdev_sep); - misc_deregister(&sep->miscdev_singleton); - - return ret_val; - } - return ret_val; -} - - -/** - * sep_probe - probe a matching PCI device - * @pdev: pci_device - * @end: pci_device_id - * - * Attempt to set up and configure a SEP device that has been - * discovered by the PCI layer. - */ -static int __devinit sep_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - int error = 0; - struct sep_device *sep; - - if (sep_dev != NULL) { - dev_warn(&pdev->dev, "only one SEP supported.\n"); - return -EBUSY; - } - - /* Enable the device */ - error = pci_enable_device(pdev); - if (error) { - dev_warn(&pdev->dev, "error enabling pci device\n"); - goto end_function; - } - - /* Allocate the sep_device structure for this device */ - sep_dev = kzalloc(sizeof(struct sep_device), GFP_ATOMIC); - if (sep_dev == NULL) { - dev_warn(&pdev->dev, - "can't kmalloc the sep_device structure\n"); - error = -ENOMEM; - goto end_function_disable_device; - } - - /* - * We're going to use another variable for actually - * working with the device; this way, if we have - * multiple devices in the future, it would be easier - * to make appropriate changes - */ - sep = sep_dev; - - sep->pdev = pci_dev_get(pdev); - - init_waitqueue_head(&sep->event); - init_waitqueue_head(&sep->event_request_daemon); - spin_lock_init(&sep->snd_rply_lck); - mutex_init(&sep->sep_mutex); - mutex_init(&sep->ioctl_mutex); - - dev_dbg(&sep->pdev->dev, "sep probe: PCI obtained, device being prepared\n"); - dev_dbg(&sep->pdev->dev, "revision is %d\n", sep->pdev->revision); - - /* Set up our register area */ - sep->reg_physical_addr = pci_resource_start(sep->pdev, 0); - if (!sep->reg_physical_addr) { - dev_warn(&sep->pdev->dev, "Error getting register start\n"); - error = -ENODEV; - goto end_function_free_sep_dev; - } - - sep->reg_physical_end = pci_resource_end(sep->pdev, 0); - if (!sep->reg_physical_end) { - dev_warn(&sep->pdev->dev, "Error getting register end\n"); - error = -ENODEV; - goto end_function_free_sep_dev; - } - - sep->reg_addr = ioremap_nocache(sep->reg_physical_addr, - (size_t)(sep->reg_physical_end - sep->reg_physical_addr + 1)); - if (!sep->reg_addr) { - dev_warn(&sep->pdev->dev, "Error getting register virtual\n"); - error = -ENODEV; - goto end_function_free_sep_dev; - } - - dev_dbg(&sep->pdev->dev, - "Register area start %llx end %llx virtual %p\n", - (unsigned long long)sep->reg_physical_addr, - (unsigned long long)sep->reg_physical_end, - sep->reg_addr); - - /* Allocate the shared area */ - sep->shared_size = SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES + - SYNCHRONIC_DMA_TABLES_AREA_SIZE_BYTES + - SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES + - SEP_DRIVER_STATIC_AREA_SIZE_IN_BYTES + - SEP_DRIVER_SYSTEM_DATA_MEMORY_SIZE_IN_BYTES; - - if (sep_map_and_alloc_shared_area(sep)) { - error = -ENOMEM; - /* Allocation failed */ - goto end_function_error; - } - - /* Clear ICR register */ - sep_write_reg(sep, HW_HOST_ICR_REG_ADDR, 0xFFFFFFFF); - - /* Set the IMR register - open only GPR 2 */ - sep_write_reg(sep, HW_HOST_IMR_REG_ADDR, (~(0x1 << 13))); - - /* Read send/receive counters from SEP */ - sep->reply_ct = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR2_REG_ADDR); - sep->reply_ct &= 0x3FFFFFFF; - sep->send_ct = sep->reply_ct; - - /* Get the interrupt line */ - error = request_irq(pdev->irq, sep_inthandler, IRQF_SHARED, - "sep_driver", sep); - - if (error) - goto end_function_deallocate_sep_shared_area; - - /* The new chip requires a shared area reconfigure */ - if (sep->pdev->revision == 4) { /* Only for new chip */ - error = sep_reconfig_shared_area(sep); - if (error) - goto end_function_free_irq; - } - /* Finally magic up the device nodes */ - /* Register driver with the fs */ - error = sep_register_driver_with_fs(sep); - if (error == 0) - /* Success */ - return 0; - -end_function_free_irq: - free_irq(pdev->irq, sep); - -end_function_deallocate_sep_shared_area: - /* De-allocate shared area */ - sep_unmap_and_free_shared_area(sep); - -end_function_error: - iounmap(sep->reg_addr); - -end_function_free_sep_dev: - pci_dev_put(sep_dev->pdev); - kfree(sep_dev); - sep_dev = NULL; - -end_function_disable_device: - pci_disable_device(pdev); - -end_function: - return error; -} - -static void sep_remove(struct pci_dev *pdev) -{ - struct sep_device *sep = sep_dev; - - /* Unregister from fs */ - misc_deregister(&sep->miscdev_sep); - misc_deregister(&sep->miscdev_singleton); - misc_deregister(&sep->miscdev_daemon); - - /* Free the irq */ - free_irq(sep->pdev->irq, sep); - - /* Free the shared area */ - sep_unmap_and_free_shared_area(sep_dev); - iounmap((void *) sep_dev->reg_addr); -} - -static DEFINE_PCI_DEVICE_TABLE(sep_pci_id_tbl) = { - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MFLD_PCI_DEVICE_ID)}, - {0} -}; - -MODULE_DEVICE_TABLE(pci, sep_pci_id_tbl); - -/* Field for registering driver to PCI device */ -static struct pci_driver sep_pci_driver = { - .name = "sep_sec_driver", - .id_table = sep_pci_id_tbl, - .probe = sep_probe, - .remove = sep_remove -}; - - -/** - * sep_init - init function - * - * Module load time. Register the PCI device driver. - */ -static int __init sep_init(void) -{ - return pci_register_driver(&sep_pci_driver); -} - - -/** - * sep_exit - called to unload driver - * - * Drop the misc devices then remove and unmap the various resources - * that are not released by the driver remove method. - */ -static void __exit sep_exit(void) -{ - pci_unregister_driver(&sep_pci_driver); -} - - -module_init(sep_init); -module_exit(sep_exit); - -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/sep/sep_driver_api.h b/drivers/staging/sep/sep_driver_api.h index c3aacfc..78a4b69 100644 --- a/drivers/staging/sep/sep_driver_api.h +++ b/drivers/staging/sep/sep_driver_api.h @@ -2,8 +2,8 @@ * * sep_driver_api.h - Security Processor Driver api definitions * - * Copyright(c) 2009,2010 Intel Corporation. All rights reserved. - * Contributions(c) 2009,2010 Discretix. All rights reserved. + * Copyright(c) 2009-2011 Intel Corporation. All rights reserved. + * Contributions(c) 2009-2011 Discretix. All rights reserved. * * 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 @@ -26,6 +26,7 @@ * CHANGES: * * 2010.09.14 Upgrade to Medfield + * 2011.02.22 Enable kernel crypto * */ @@ -37,26 +38,30 @@ #define SEP_DRIVER_SRC_REQ 2 #define SEP_DRIVER_SRC_PRINTF 3 - -/*------------------------------------------- - TYPEDEFS -----------------------------------------------*/ - -struct alloc_struct { - /* offset from start of shared pool area */ - u32 offset; - /* number of bytes to allocate */ - u32 num_bytes; -}; - -/* command struct for getting caller id value and address */ -struct caller_id_struct { - /* pid of the process */ - u32 pid; - /* virtual address of the caller id hash */ - aligned_u64 callerIdAddress; - /* caller id hash size in bytes */ - u32 callerIdSizeInBytes; +/* Power state */ +#define SEP_DRIVER_POWERON 1 +#define SEP_DRIVER_POWEROFF 2 + +/* Following enums are used only for kernel crypto api */ +enum type_of_request { + NO_REQUEST, + AES_CBC, + AES_ECB, + DES_CBC, + DES_ECB, + DES3_ECB, + DES3_CBC, + SHA1, + MD5, + SHA224, + SHA256 + }; + +enum hash_stage { + HASH_INIT, + HASH_UPDATE, + HASH_FINISH, + HASH_DIGEST }; /* @@ -83,11 +88,6 @@ struct sep_dcblock { u8 tail_data[68]; }; -struct sep_caller_id_entry { - int pid; - unsigned char callerIdHash[SEP_CALLER_ID_HASH_SIZE_IN_BYTES]; -}; - /* command structure for building dcb block (currently for ext app only */ @@ -104,6 +104,33 @@ struct build_dcb_struct { /* the size of the block of the operation - if needed, every table will be modulo this parameter */ u32 tail_block_size; + + /* which application calls the driver DX or applet */ + u32 is_applet; +}; + +/* + command structure for building dcb block for kernel crypto +*/ +struct build_dcb_struct_kernel { + /* address value of the data in */ + void *app_in_address; + /* size of data in */ + ssize_t data_in_size; + /* address of the data out */ + void *app_out_address; + /* the size of the block of the operation - if needed, + every table will be modulo this parameter */ + u32 block_size; + /* the size of the block of the operation - if needed, + every table will be modulo this parameter */ + u32 tail_block_size; + + /* which application calls the driver DX or applet */ + u32 is_applet; + + struct scatterlist *src_sg; + struct scatterlist *dst_sg; }; /** @@ -147,6 +174,10 @@ struct sep_dma_resource { /* number of entries of the output mapp array */ u32 out_map_num_entries; + + /* Scatter list for kernel operations */ + struct scatterlist *src_sg; + struct scatterlist *dst_sg; }; @@ -169,47 +200,190 @@ struct sep_lli_entry { u32 block_size; }; -/*---------------------------------------------------------------- - IOCTL command defines - -----------------------------------------------------------------*/ +/* + * header format for each fastcall write operation + */ +struct sep_fastcall_hdr { + u32 magic; + u32 msg_len; + u32 num_dcbs; +}; -/* magic number 1 of the sep IOCTL command */ -#define SEP_IOC_MAGIC_NUMBER 's' +/* + * structure used in file pointer's private data field + * to track the status of the calls to the various + * driver interface + */ +struct sep_call_status { + unsigned long status; +}; -/* sends interrupt to sep that message is ready */ -#define SEP_IOCSENDSEPCOMMAND \ - _IO(SEP_IOC_MAGIC_NUMBER, 0) +/* + * format of dma context buffer used to store all DMA-related + * context information of a particular transaction + */ +struct sep_dma_context { + /* number of data control blocks */ + u32 nr_dcb_creat; + /* number of the lli tables created in the current transaction */ + u32 num_lli_tables_created; + /* size of currently allocated dma tables region */ + u32 dmatables_len; + /* size of input data */ + u32 input_data_len; + struct sep_dma_resource dma_res_arr[SEP_MAX_NUM_SYNC_DMA_OPS]; + /* Scatter gather for kernel crypto */ + struct scatterlist *src_sg; + struct scatterlist *dst_sg; +}; -/* sends interrupt to sep that message is ready */ -#define SEP_IOCSENDSEPRPLYCOMMAND \ - _IO(SEP_IOC_MAGIC_NUMBER, 1) +/* + * format for file pointer's private_data field + */ +struct sep_private_data { + struct sep_queue_info *my_queue_elem; + struct sep_device *device; + struct sep_call_status call_status; + struct sep_dma_context *dma_ctx; +}; + + +/* Functions used by sep_crypto */ + +/** + * sep_queue_status_remove - Removes transaction from status queue + * @sep: SEP device + * @sep_queue_info: pointer to status queue + * + * This function will removes information about transaction from the queue. + */ +void sep_queue_status_remove(struct sep_device *sep, + struct sep_queue_info **queue_elem); +/** + * sep_queue_status_add - Adds transaction to status queue + * @sep: SEP device + * @opcode: transaction opcode + * @size: input data size + * @pid: pid of current process + * @name: current process name + * @name_len: length of name (current process) + * + * This function adds information about about transaction started to the status + * queue. + */ +struct sep_queue_info *sep_queue_status_add( + struct sep_device *sep, + u32 opcode, + u32 size, + u32 pid, + u8 *name, size_t name_len); -/* allocate memory in data pool */ -#define SEP_IOCALLOCDATAPOLL \ - _IOW(SEP_IOC_MAGIC_NUMBER, 2, struct alloc_struct) +/** + * sep_create_dcb_dmatables_context_kernel - Creates DCB & MLLI/DMA table context + * for kernel crypto + * @sep: SEP device + * @dcb_region: DCB region buf to create for current transaction + * @dmatables_region: MLLI/DMA tables buf to create for current transaction + * @dma_ctx: DMA context buf to create for current transaction + * @user_dcb_args: User arguments for DCB/MLLI creation + * @num_dcbs: Number of DCBs to create + */ +int sep_create_dcb_dmatables_context_kernel(struct sep_device *sep, + struct sep_dcblock **dcb_region, + void **dmatables_region, + struct sep_dma_context **dma_ctx, + const struct build_dcb_struct_kernel *dcb_data, + const u32 num_dcbs); -/* free dynamic data aalocated during table creation */ -#define SEP_IOCFREEDMATABLEDATA \ - _IO(SEP_IOC_MAGIC_NUMBER, 7) +/** + * sep_activate_dcb_dmatables_context - Takes DCB & DMA tables + * contexts into use + * @sep: SEP device + * @dcb_region: DCB region copy + * @dmatables_region: MLLI/DMA tables copy + * @dma_ctx: DMA context for current transaction + */ +ssize_t sep_activate_dcb_dmatables_context(struct sep_device *sep, + struct sep_dcblock **dcb_region, + void **dmatables_region, + struct sep_dma_context *dma_ctx); -/* get the static pool area addersses (physical and virtual) */ -#define SEP_IOCGETSTATICPOOLADDR \ - _IO(SEP_IOC_MAGIC_NUMBER, 8) +/** + * sep_prepare_input_output_dma_table_in_dcb - prepare control blocks + * @app_in_address: unsigned long; for data buffer in (user space) + * @app_out_address: unsigned long; for data buffer out (user space) + * @data_in_size: u32; for size of data + * @block_size: u32; for block size + * @tail_block_size: u32; for size of tail block + * @isapplet: bool; to indicate external app + * @is_kva: bool; kernel buffer; only used for kernel crypto module + * + * This function prepares the linked DMA tables and puts the + * address for the linked list of tables inta a DCB (data control + * block) the address of which is known by the SEP hardware + * Note that all bus addresses that are passed to the SEP + * are in 32 bit format; the SEP is a 32 bit device + */ +int sep_prepare_input_output_dma_table_in_dcb(struct sep_device *sep, + unsigned long app_in_address, + unsigned long app_out_address, + u32 data_in_size, + u32 block_size, + u32 tail_block_size, + bool isapplet, + bool is_kva, + struct sep_dcblock *dcb_region, + void **dmatables_region, + struct sep_dma_context **dma_ctx, + struct scatterlist *src_sg, + struct scatterlist *dst_sg); + +/** + * sep_free_dma_table_data_handler - free DMA table + * @sep: pointere to struct sep_device + * @dma_ctx: dma context + * + * Handles the request to free DMA table for synchronic actions + */ +int sep_free_dma_table_data_handler(struct sep_device *sep, + struct sep_dma_context **dma_ctx); +/** + * sep_send_command_handler - kick off a command + * @sep: SEP being signalled + * + * This function raises interrupt to SEP that signals that is has a new + * command from the host + * + * Note that this function does fall under the ioctl lock + */ +int sep_send_command_handler(struct sep_device *sep); + +/** + * sep_wait_transaction - Used for synchronizing transactions + * @sep: SEP device + */ +int sep_wait_transaction(struct sep_device *sep); + +/** + * IOCTL command defines + */ +/* magic number 1 of the sep IOCTL command */ +#define SEP_IOC_MAGIC_NUMBER 's' + +/* sends interrupt to sep that message is ready */ +#define SEP_IOCSENDSEPCOMMAND \ + _IO(SEP_IOC_MAGIC_NUMBER, 0) /* end transaction command */ #define SEP_IOCENDTRANSACTION \ _IO(SEP_IOC_MAGIC_NUMBER, 15) -#define SEP_IOCRARPREPAREMESSAGE \ - _IOW(SEP_IOC_MAGIC_NUMBER, 20, struct rar_hndl_to_bus_struct) - -#define SEP_IOCTLSETCALLERID \ - _IOW(SEP_IOC_MAGIC_NUMBER, 34, struct caller_id_struct) - #define SEP_IOCPREPAREDCB \ _IOW(SEP_IOC_MAGIC_NUMBER, 35, struct build_dcb_struct) #define SEP_IOCFREEDCB \ _IO(SEP_IOC_MAGIC_NUMBER, 36) +struct sep_device; + #endif diff --git a/drivers/staging/sep/sep_driver_config.h b/drivers/staging/sep/sep_driver_config.h index d6bfd24..fa7c0d0 100644 --- a/drivers/staging/sep/sep_driver_config.h +++ b/drivers/staging/sep/sep_driver_config.h @@ -2,8 +2,8 @@ * * sep_driver_config.h - Security Processor Driver configuration * - * Copyright(c) 2009,2010 Intel Corporation. All rights reserved. - * Contributions(c) 2009,2010 Discretix. All rights reserved. + * Copyright(c) 2009-2011 Intel Corporation. All rights reserved. + * Contributions(c) 2009-2011 Discretix. All rights reserved. * * 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 @@ -26,6 +26,7 @@ * CHANGES: * * 2010.06.26 Upgrade to Medfield + * 2011.02.22 Enable kernel crypto * */ @@ -48,6 +49,8 @@ /* the mode for running on the ARM1172 Evaluation platform (flag is 1) */ #define SEP_DRIVER_ARM_DEBUG_MODE 0 +/* Critical message area contents for sanity checking */ +#define SEP_START_MSG_TOKEN 0x02558808 /*------------------------------------------- INTERNAL DATA CONFIGURATION -------------------------------------------*/ @@ -65,21 +68,17 @@ #define SEP_DRIVER_MIN_DATA_SIZE_PER_TABLE 16 /* flag that signifies tah the lock is -currently held by the process (struct file) */ +currently held by the proccess (struct file) */ #define SEP_DRIVER_OWN_LOCK_FLAG 1 /* flag that signifies tah the lock is currently NOT -held by the process (struct file) */ +held by the proccess (struct file) */ #define SEP_DRIVER_DISOWN_LOCK_FLAG 0 /* indicates whether driver has mapped/unmapped shared area */ #define SEP_REQUEST_DAEMON_MAPPED 1 #define SEP_REQUEST_DAEMON_UNMAPPED 0 -#define SEP_DEV_NAME "sep_sec_driver" -#define SEP_DEV_SINGLETON "sep_sec_singleton_driver" -#define SEP_DEV_DAEMON "sep_req_daemon_driver" - /*-------------------------------------------------------- SHARED AREA memory total size is 36K it is divided is following: @@ -90,7 +89,7 @@ held by the process (struct file) */ } DATA_POOL_AREA 12K } - SYNCHRONIC_DMA_TABLES_AREA 5K + SYNCHRONIC_DMA_TABLES_AREA 29K placeholder until drver changes FLOW_DMA_TABLES_AREA 4K @@ -109,6 +108,12 @@ held by the process (struct file) */ /* + the minimum length of the message - includes 2 reserved fields + at the start, then token, message size and opcode fields. all dwords +*/ +#define SEP_DRIVER_MIN_MESSAGE_SIZE_IN_BYTES (5*sizeof(u32)) + +/* the maximum length of the message - the rest of the message shared area will be dedicated to the dma lli tables */ @@ -124,7 +129,7 @@ held by the process (struct file) */ #define SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES (16 * 1024) /* the size of the message shared area in pages */ -#define SYNCHRONIC_DMA_TABLES_AREA_SIZE_BYTES (1024 * 5) +#define SYNCHRONIC_DMA_TABLES_AREA_SIZE_BYTES (1024 * 29) /* Placeholder until driver changes */ #define SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES (1024 * 4) @@ -132,6 +137,9 @@ held by the process (struct file) */ /* system data (time, caller id etc') pool */ #define SEP_DRIVER_SYSTEM_DATA_MEMORY_SIZE_IN_BYTES (1024 * 3) +/* Offset of the sep printf buffer in the message area */ +#define SEP_DRIVER_PRINTF_OFFSET_IN_BYTES (5888) + /* the size in bytes of the time memory */ #define SEP_DRIVER_TIME_MEMORY_SIZE_IN_BYTES 8 @@ -223,10 +231,10 @@ held by the process (struct file) */ #define SEP_ALREADY_INITIALIZED_ERR 12 /* bit that locks access to the shared area */ -#define SEP_MMAP_LOCK_BIT 0 +#define SEP_TRANSACTION_STARTED_LOCK_BIT 0 /* bit that lock access to the poll - after send_command */ -#define SEP_SEND_MSG_LOCK_BIT 1 +#define SEP_WORKING_LOCK_BIT 1 /* the token that defines the static pool address address */ #define SEP_STATIC_POOL_VAL_TOKEN 0xABBAABBA @@ -240,4 +248,51 @@ held by the process (struct file) */ /* Time limit for SEP to finish */ #define WAIT_TIME 10 +/* Delay for pm runtime suspend (reduces pm thrashing with bursty traffic */ +#define SUSPEND_DELAY 10 + +/* Number of delays to wait until scu boots after runtime resume */ +#define SCU_DELAY_MAX 50 + +/* Delay for each iteration (usec) wait for scu boots after runtime resume */ +#define SCU_DELAY_ITERATION 10 + + +/* + * Bits used in struct sep_call_status to check that + * driver's APIs are called in valid order + */ + +/* Bit offset which indicates status of sep_write() */ +#define SEP_FASTCALL_WRITE_DONE_OFFSET 0 + +/* Bit offset which indicates status of sep_mmap() */ +#define SEP_LEGACY_MMAP_DONE_OFFSET 1 + +/* Bit offset which indicates status of the SEP_IOCSENDSEPCOMMAND ioctl */ +#define SEP_LEGACY_SENDMSG_DONE_OFFSET 2 + +/* Bit offset which indicates status of sep_poll() */ +#define SEP_LEGACY_POLL_DONE_OFFSET 3 + +/* Bit offset which indicates status of the SEP_IOCENDTRANSACTION ioctl */ +#define SEP_LEGACY_ENDTRANSACTION_DONE_OFFSET 4 + +/* + * Used to limit number of concurrent processes + * allowed to allocte dynamic buffers in fastcall + * interface. + */ +#define SEP_DOUBLEBUF_USERS_LIMIT 3 + +/* Identifier for valid fastcall header */ +#define SEP_FC_MAGIC 0xFFAACCAA + +/* + * Used for enabling driver runtime power management. + * Useful for enabling/disabling it during performance + * testing + */ +#define SEP_ENABLE_RUNTIME_PM + #endif /* SEP DRIVER CONFIG */ diff --git a/drivers/staging/sep/sep_driver_hw_defs.h b/drivers/staging/sep/sep_driver_hw_defs.h index 300f909..c48e49a 100644 --- a/drivers/staging/sep/sep_driver_hw_defs.h +++ b/drivers/staging/sep/sep_driver_hw_defs.h @@ -2,8 +2,8 @@ * * sep_driver_hw_defs.h - Security Processor Driver hardware definitions * - * Copyright(c) 2009,2010 Intel Corporation. All rights reserved. - * Contributions(c) 2009,2010 Discretix. All rights reserved. + * Copyright(c) 2009-2011 Intel Corporation. All rights reserved. + * Contributions(c) 2009-2011 Discretix. All rights reserved. * * 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 @@ -26,6 +26,7 @@ * CHANGES: * * 2010.09.20 Upgrade to Medfield + * 2011.02.22 Enable kernel crypto * */ @@ -42,181 +43,9 @@ /* cf registers */ -#define HW_R0B_ADDR_0_REG_ADDR 0x0000UL -#define HW_R0B_ADDR_1_REG_ADDR 0x0004UL -#define HW_R0B_ADDR_2_REG_ADDR 0x0008UL -#define HW_R0B_ADDR_3_REG_ADDR 0x000cUL -#define HW_R0B_ADDR_4_REG_ADDR 0x0010UL -#define HW_R0B_ADDR_5_REG_ADDR 0x0014UL -#define HW_R0B_ADDR_6_REG_ADDR 0x0018UL -#define HW_R0B_ADDR_7_REG_ADDR 0x001cUL -#define HW_R0B_ADDR_8_REG_ADDR 0x0020UL -#define HW_R2B_ADDR_0_REG_ADDR 0x0080UL -#define HW_R2B_ADDR_1_REG_ADDR 0x0084UL -#define HW_R2B_ADDR_2_REG_ADDR 0x0088UL -#define HW_R2B_ADDR_3_REG_ADDR 0x008cUL -#define HW_R2B_ADDR_4_REG_ADDR 0x0090UL -#define HW_R2B_ADDR_5_REG_ADDR 0x0094UL -#define HW_R2B_ADDR_6_REG_ADDR 0x0098UL -#define HW_R2B_ADDR_7_REG_ADDR 0x009cUL -#define HW_R2B_ADDR_8_REG_ADDR 0x00a0UL -#define HW_R3B_REG_ADDR 0x00C0UL -#define HW_R4B_REG_ADDR 0x0100UL -#define HW_CSA_ADDR_0_REG_ADDR 0x0140UL -#define HW_CSA_ADDR_1_REG_ADDR 0x0144UL -#define HW_CSA_ADDR_2_REG_ADDR 0x0148UL -#define HW_CSA_ADDR_3_REG_ADDR 0x014cUL -#define HW_CSA_ADDR_4_REG_ADDR 0x0150UL -#define HW_CSA_ADDR_5_REG_ADDR 0x0154UL -#define HW_CSA_ADDR_6_REG_ADDR 0x0158UL -#define HW_CSA_ADDR_7_REG_ADDR 0x015cUL -#define HW_CSA_ADDR_8_REG_ADDR 0x0160UL -#define HW_CSA_REG_ADDR 0x0140UL -#define HW_SINB_REG_ADDR 0x0180UL -#define HW_SOUTB_REG_ADDR 0x0184UL -#define HW_PKI_CONTROL_REG_ADDR 0x01C0UL -#define HW_PKI_STATUS_REG_ADDR 0x01C4UL -#define HW_PKI_BUSY_REG_ADDR 0x01C8UL -#define HW_PKI_A_1025_REG_ADDR 0x01CCUL -#define HW_PKI_SDMA_CTL_REG_ADDR 0x01D0UL -#define HW_PKI_SDMA_OFFSET_REG_ADDR 0x01D4UL -#define HW_PKI_SDMA_POINTERS_REG_ADDR 0x01D8UL -#define HW_PKI_SDMA_DLENG_REG_ADDR 0x01DCUL -#define HW_PKI_SDMA_EXP_POINTERS_REG_ADDR 0x01E0UL -#define HW_PKI_SDMA_RES_POINTERS_REG_ADDR 0x01E4UL -#define HW_PKI_CLR_REG_ADDR 0x01E8UL -#define HW_PKI_SDMA_BUSY_REG_ADDR 0x01E8UL -#define HW_PKI_SDMA_FIRST_EXP_N_REG_ADDR 0x01ECUL -#define HW_PKI_SDMA_MUL_BY1_REG_ADDR 0x01F0UL -#define HW_PKI_SDMA_RMUL_SEL_REG_ADDR 0x01F4UL -#define HW_DES_KEY_0_REG_ADDR 0x0208UL -#define HW_DES_KEY_1_REG_ADDR 0x020CUL -#define HW_DES_KEY_2_REG_ADDR 0x0210UL -#define HW_DES_KEY_3_REG_ADDR 0x0214UL -#define HW_DES_KEY_4_REG_ADDR 0x0218UL -#define HW_DES_KEY_5_REG_ADDR 0x021CUL -#define HW_DES_CONTROL_0_REG_ADDR 0x0220UL -#define HW_DES_CONTROL_1_REG_ADDR 0x0224UL -#define HW_DES_IV_0_REG_ADDR 0x0228UL -#define HW_DES_IV_1_REG_ADDR 0x022CUL -#define HW_AES_KEY_0_ADDR_0_REG_ADDR 0x0400UL -#define HW_AES_KEY_0_ADDR_1_REG_ADDR 0x0404UL -#define HW_AES_KEY_0_ADDR_2_REG_ADDR 0x0408UL -#define HW_AES_KEY_0_ADDR_3_REG_ADDR 0x040cUL -#define HW_AES_KEY_0_ADDR_4_REG_ADDR 0x0410UL -#define HW_AES_KEY_0_ADDR_5_REG_ADDR 0x0414UL -#define HW_AES_KEY_0_ADDR_6_REG_ADDR 0x0418UL -#define HW_AES_KEY_0_ADDR_7_REG_ADDR 0x041cUL -#define HW_AES_KEY_0_REG_ADDR 0x0400UL -#define HW_AES_IV_0_ADDR_0_REG_ADDR 0x0440UL -#define HW_AES_IV_0_ADDR_1_REG_ADDR 0x0444UL -#define HW_AES_IV_0_ADDR_2_REG_ADDR 0x0448UL -#define HW_AES_IV_0_ADDR_3_REG_ADDR 0x044cUL -#define HW_AES_IV_0_REG_ADDR 0x0440UL -#define HW_AES_CTR1_ADDR_0_REG_ADDR 0x0460UL -#define HW_AES_CTR1_ADDR_1_REG_ADDR 0x0464UL -#define HW_AES_CTR1_ADDR_2_REG_ADDR 0x0468UL -#define HW_AES_CTR1_ADDR_3_REG_ADDR 0x046cUL -#define HW_AES_CTR1_REG_ADDR 0x0460UL -#define HW_AES_SK_REG_ADDR 0x0478UL -#define HW_AES_MAC_OK_REG_ADDR 0x0480UL -#define HW_AES_PREV_IV_0_ADDR_0_REG_ADDR 0x0490UL -#define HW_AES_PREV_IV_0_ADDR_1_REG_ADDR 0x0494UL -#define HW_AES_PREV_IV_0_ADDR_2_REG_ADDR 0x0498UL -#define HW_AES_PREV_IV_0_ADDR_3_REG_ADDR 0x049cUL -#define HW_AES_PREV_IV_0_REG_ADDR 0x0490UL -#define HW_AES_CONTROL_REG_ADDR 0x04C0UL -#define HW_HASH_H0_REG_ADDR 0x0640UL -#define HW_HASH_H1_REG_ADDR 0x0644UL -#define HW_HASH_H2_REG_ADDR 0x0648UL -#define HW_HASH_H3_REG_ADDR 0x064CUL -#define HW_HASH_H4_REG_ADDR 0x0650UL -#define HW_HASH_H5_REG_ADDR 0x0654UL -#define HW_HASH_H6_REG_ADDR 0x0658UL -#define HW_HASH_H7_REG_ADDR 0x065CUL -#define HW_HASH_H8_REG_ADDR 0x0660UL -#define HW_HASH_H9_REG_ADDR 0x0664UL -#define HW_HASH_H10_REG_ADDR 0x0668UL -#define HW_HASH_H11_REG_ADDR 0x066CUL -#define HW_HASH_H12_REG_ADDR 0x0670UL -#define HW_HASH_H13_REG_ADDR 0x0674UL -#define HW_HASH_H14_REG_ADDR 0x0678UL -#define HW_HASH_H15_REG_ADDR 0x067CUL -#define HW_HASH_CONTROL_REG_ADDR 0x07C0UL -#define HW_HASH_PAD_EN_REG_ADDR 0x07C4UL -#define HW_HASH_PAD_CFG_REG_ADDR 0x07C8UL -#define HW_HASH_CUR_LEN_0_REG_ADDR 0x07CCUL -#define HW_HASH_CUR_LEN_1_REG_ADDR 0x07D0UL -#define HW_HASH_CUR_LEN_2_REG_ADDR 0x07D4UL -#define HW_HASH_CUR_LEN_3_REG_ADDR 0x07D8UL -#define HW_HASH_PARAM_REG_ADDR 0x07DCUL -#define HW_HASH_INT_BUSY_REG_ADDR 0x07E0UL -#define HW_HASH_SW_RESET_REG_ADDR 0x07E4UL -#define HW_HASH_ENDIANESS_REG_ADDR 0x07E8UL -#define HW_HASH_DATA_REG_ADDR 0x07ECUL -#define HW_DRNG_CONTROL_REG_ADDR 0x0800UL -#define HW_DRNG_VALID_REG_ADDR 0x0804UL -#define HW_DRNG_DATA_REG_ADDR 0x0808UL -#define HW_RND_SRC_EN_REG_ADDR 0x080CUL -#define HW_AES_CLK_ENABLE_REG_ADDR 0x0810UL -#define HW_DES_CLK_ENABLE_REG_ADDR 0x0814UL -#define HW_HASH_CLK_ENABLE_REG_ADDR 0x0818UL -#define HW_PKI_CLK_ENABLE_REG_ADDR 0x081CUL -#define HW_CLK_STATUS_REG_ADDR 0x0824UL -#define HW_CLK_ENABLE_REG_ADDR 0x0828UL -#define HW_DRNG_SAMPLE_REG_ADDR 0x0850UL -#define HW_RND_SRC_CTL_REG_ADDR 0x0858UL -#define HW_CRYPTO_CTL_REG_ADDR 0x0900UL -#define HW_CRYPTO_STATUS_REG_ADDR 0x090CUL -#define HW_CRYPTO_BUSY_REG_ADDR 0x0910UL -#define HW_AES_BUSY_REG_ADDR 0x0914UL -#define HW_DES_BUSY_REG_ADDR 0x0918UL -#define HW_HASH_BUSY_REG_ADDR 0x091CUL -#define HW_CONTENT_REG_ADDR 0x0924UL -#define HW_VERSION_REG_ADDR 0x0928UL -#define HW_CONTEXT_ID_REG_ADDR 0x0930UL -#define HW_DIN_BUFFER_REG_ADDR 0x0C00UL -#define HW_DIN_MEM_DMA_BUSY_REG_ADDR 0x0c20UL -#define HW_SRC_LLI_MEM_ADDR_REG_ADDR 0x0c24UL -#define HW_SRC_LLI_WORD0_REG_ADDR 0x0C28UL -#define HW_SRC_LLI_WORD1_REG_ADDR 0x0C2CUL -#define HW_SRAM_SRC_ADDR_REG_ADDR 0x0c30UL -#define HW_DIN_SRAM_BYTES_LEN_REG_ADDR 0x0c34UL -#define HW_DIN_SRAM_DMA_BUSY_REG_ADDR 0x0C38UL -#define HW_WRITE_ALIGN_REG_ADDR 0x0C3CUL -#define HW_OLD_DATA_REG_ADDR 0x0C48UL -#define HW_WRITE_ALIGN_LAST_REG_ADDR 0x0C4CUL -#define HW_DOUT_BUFFER_REG_ADDR 0x0C00UL -#define HW_DST_LLI_WORD0_REG_ADDR 0x0D28UL -#define HW_DST_LLI_WORD1_REG_ADDR 0x0D2CUL -#define HW_DST_LLI_MEM_ADDR_REG_ADDR 0x0D24UL -#define HW_DOUT_MEM_DMA_BUSY_REG_ADDR 0x0D20UL -#define HW_SRAM_DEST_ADDR_REG_ADDR 0x0D30UL -#define HW_DOUT_SRAM_BYTES_LEN_REG_ADDR 0x0D34UL -#define HW_DOUT_SRAM_DMA_BUSY_REG_ADDR 0x0D38UL -#define HW_READ_ALIGN_REG_ADDR 0x0D3CUL -#define HW_READ_LAST_DATA_REG_ADDR 0x0D44UL -#define HW_RC4_THRU_CPU_REG_ADDR 0x0D4CUL -#define HW_AHB_SINGLE_REG_ADDR 0x0E00UL -#define HW_SRAM_DATA_REG_ADDR 0x0F00UL -#define HW_SRAM_ADDR_REG_ADDR 0x0F04UL -#define HW_SRAM_DATA_READY_REG_ADDR 0x0F08UL #define HW_HOST_IRR_REG_ADDR 0x0A00UL #define HW_HOST_IMR_REG_ADDR 0x0A04UL #define HW_HOST_ICR_REG_ADDR 0x0A08UL -#define HW_HOST_SEP_SRAM_THRESHOLD_REG_ADDR 0x0A10UL -#define HW_HOST_SEP_BUSY_REG_ADDR 0x0A14UL -#define HW_HOST_SEP_LCS_REG_ADDR 0x0A18UL -#define HW_HOST_CC_SW_RST_REG_ADDR 0x0A40UL -#define HW_HOST_SEP_SW_RST_REG_ADDR 0x0A44UL -#define HW_HOST_FLOW_DMA_SW_INT0_REG_ADDR 0x0A80UL -#define HW_HOST_FLOW_DMA_SW_INT1_REG_ADDR 0x0A84UL -#define HW_HOST_FLOW_DMA_SW_INT2_REG_ADDR 0x0A88UL -#define HW_HOST_FLOW_DMA_SW_INT3_REG_ADDR 0x0A8cUL -#define HW_HOST_FLOW_DMA_SW_INT4_REG_ADDR 0x0A90UL -#define HW_HOST_FLOW_DMA_SW_INT5_REG_ADDR 0x0A94UL -#define HW_HOST_FLOW_DMA_SW_INT6_REG_ADDR 0x0A98UL -#define HW_HOST_FLOW_DMA_SW_INT7_REG_ADDR 0x0A9cUL #define HW_HOST_SEP_HOST_GPR0_REG_ADDR 0x0B00UL #define HW_HOST_SEP_HOST_GPR1_REG_ADDR 0x0B04UL #define HW_HOST_SEP_HOST_GPR2_REG_ADDR 0x0B08UL @@ -225,9 +54,6 @@ #define HW_HOST_HOST_SEP_GPR1_REG_ADDR 0x0B84UL #define HW_HOST_HOST_SEP_GPR2_REG_ADDR 0x0B88UL #define HW_HOST_HOST_SEP_GPR3_REG_ADDR 0x0B8CUL -#define HW_HOST_HOST_ENDIAN_REG_ADDR 0x0B90UL -#define HW_HOST_HOST_COMM_CLK_EN_REG_ADDR 0x0B94UL -#define HW_CLR_SRAM_BUSY_REG_REG_ADDR 0x0F0CUL -#define HW_CC_SRAM_BASE_ADDRESS 0x5800UL +#define HW_SRAM_DATA_READY_REG_ADDR 0x0F08UL #endif /* ifndef HW_DEFS */ diff --git a/drivers/staging/sep/sep_main.c b/drivers/staging/sep/sep_main.c new file mode 100644 index 0000000..0defb0a --- /dev/null +++ b/drivers/staging/sep/sep_main.c @@ -0,0 +1,4286 @@ +/* + * + * sep_main.c - Security Processor Driver main group of functions + * + * Copyright(c) 2009-2011 Intel Corporation. All rights reserved. + * Contributions(c) 2009-2011 Discretix. All rights reserved. + * + * 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; version 2 of the License. + * + * 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., 59 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * CONTACTS: + * + * Mark Allyn mark.a.allyn@intel.com + * Jayant Mangalampalli jayant.mangalampalli@intel.com + * + * CHANGES: + * + * 2009.06.26 Initial publish + * 2010.09.14 Upgrade to Medfield + * 2011.01.21 Move to sep_main.c to allow for sep_crypto.c + * 2011.02.22 Enable kernel crypto operation + * + * Please note that this driver is based on information in the Discretix + * CryptoCell 5.2 Driver Implementation Guide; the Discretix CryptoCell 5.2 + * Integration Intel Medfield appendix; the Discretix CryptoCell 5.2 + * Linux Driver Integration Guide; and the Discretix CryptoCell 5.2 System + * Overview and Integration Guide. + */ +/* #define DEBUG */ +/* #define SEP_PERF_DEBUG */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sep_driver_hw_defs.h" +#include "sep_driver_config.h" +#include "sep_driver_api.h" +#include "sep_dev.h" +#include "sep_crypto.h" + +#define CREATE_TRACE_POINTS +#include "sep_trace_events.h" + +/* + * Let's not spend cycles iterating over message + * area contents if debugging not enabled + */ +#ifdef DEBUG +#define sep_dump_message(sep) _sep_dump_message(sep) +#else +#define sep_dump_message(sep) +#endif + +/** + * Currenlty, there is only one SEP device per platform; + * In event platforms in the future have more than one SEP + * device, this will be a linked list + */ + +struct sep_device *sep_dev; + +/** + * sep_queue_status_remove - Removes transaction from status queue + * @sep: SEP device + * @sep_queue_info: pointer to status queue + * + * This function will removes information about transaction from the queue. + */ +void sep_queue_status_remove(struct sep_device *sep, + struct sep_queue_info **queue_elem) +{ + unsigned long lck_flags; + + dev_dbg(&sep->pdev->dev, "[PID%d] sep_queue_status_remove\n", + current->pid); + + if (!queue_elem || !(*queue_elem)) { + dev_dbg(&sep->pdev->dev, "PID%d %s null\n", + current->pid, __func__); + return; + } + + spin_lock_irqsave(&sep->sep_queue_lock, lck_flags); + list_del(&(*queue_elem)->list); + sep->sep_queue_num--; + spin_unlock_irqrestore(&sep->sep_queue_lock, lck_flags); + + kfree(*queue_elem); + *queue_elem = NULL; + + dev_dbg(&sep->pdev->dev, "[PID%d] sep_queue_status_remove return\n", + current->pid); + return; +} + +/** + * sep_queue_status_add - Adds transaction to status queue + * @sep: SEP device + * @opcode: transaction opcode + * @size: input data size + * @pid: pid of current process + * @name: current process name + * @name_len: length of name (current process) + * + * This function adds information about about transaction started to the status + * queue. + */ +struct sep_queue_info *sep_queue_status_add( + struct sep_device *sep, + u32 opcode, + u32 size, + u32 pid, + u8 *name, size_t name_len) +{ + unsigned long lck_flags; + struct sep_queue_info *my_elem = NULL; + + my_elem = kzalloc(sizeof(struct sep_queue_info), GFP_KERNEL); + + if (!my_elem) + return NULL; + + dev_dbg(&sep->pdev->dev, "[PID%d] kzalloc ok\n", current->pid); + + my_elem->data.opcode = opcode; + my_elem->data.size = size; + my_elem->data.pid = pid; + + if (name_len > TASK_COMM_LEN) + name_len = TASK_COMM_LEN; + + memcpy(&my_elem->data.name, name, name_len); + + spin_lock_irqsave(&sep->sep_queue_lock, lck_flags); + + list_add_tail(&my_elem->list, &sep->sep_queue_status); + sep->sep_queue_num++; + + spin_unlock_irqrestore(&sep->sep_queue_lock, lck_flags); + + return my_elem; +} + +/** + * sep_allocate_dmatables_region - Allocates buf for the MLLI/DMA tables + * @sep: SEP device + * @dmatables_region: Destination pointer for the buffer + * @dma_ctx: DMA context for the transaction + * @table_count: Number of MLLI/DMA tables to create + * The buffer created will not work as-is for DMA operations, + * it needs to be copied over to the appropriate place in the + * shared area. + */ +static int sep_allocate_dmatables_region(struct sep_device *sep, + void **dmatables_region, + struct sep_dma_context *dma_ctx, + const u32 table_count) +{ + const size_t new_len = table_count * + sizeof(struct sep_lli_entry) * + SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP; + void *tmp_region = NULL; + + dev_dbg(&sep->pdev->dev, "[PID%d] dma_ctx = 0x%p\n", + current->pid, dma_ctx); + dev_dbg(&sep->pdev->dev, "[PID%d] dmatables_region = 0x%p\n", + current->pid, dmatables_region); + + if (!dma_ctx || !dmatables_region) { + dev_warn(&sep->pdev->dev, + "[PID%d] dma context/region uninitialized\n", + current->pid); + return -EINVAL; + } + + dev_dbg(&sep->pdev->dev, "[PID%d] newlen = 0x%08X\n", + current->pid, new_len); + dev_dbg(&sep->pdev->dev, "[PID%d] oldlen = 0x%08X\n", current->pid, + dma_ctx->dmatables_len); + tmp_region = kzalloc(new_len + dma_ctx->dmatables_len, GFP_KERNEL); + if (!tmp_region) { + dev_warn(&sep->pdev->dev, + "[PID%d] no mem for dma tables region\n", + current->pid); + return -ENOMEM; + } + + /* Were there any previous tables that need to be preserved ? */ + if (*dmatables_region) { + memcpy(tmp_region, *dmatables_region, dma_ctx->dmatables_len); + kfree(*dmatables_region); + } + + *dmatables_region = tmp_region; + + dma_ctx->dmatables_len += new_len; + + return 0; +} + +/** + * sep_wait_transaction - Used for synchronizing transactions + * @sep: SEP device + */ +int sep_wait_transaction(struct sep_device *sep) +{ + int error = 0; + DEFINE_WAIT(wait); + + if (0 == test_and_set_bit(SEP_TRANSACTION_STARTED_LOCK_BIT, + &sep->in_use_flags)) { + dev_dbg(&sep->pdev->dev, + "[PID%d] no transactions, returning\n", + current->pid); + goto end_function_setpid; + } + + /* + * Looping needed even for exclusive waitq entries + * due to process wakeup latencies, previous process + * might have already created another transaction. + */ + for (;;) { + /* + * Exclusive waitq entry, so that only one process is + * woken up from the queue at a time. + */ + prepare_to_wait_exclusive(&sep->event_transactions, + &wait, + TASK_INTERRUPTIBLE); + if (0 == test_and_set_bit(SEP_TRANSACTION_STARTED_LOCK_BIT, + &sep->in_use_flags)) { + dev_dbg(&sep->pdev->dev, + "[PID%d] no transactions, breaking\n", + current->pid); + break; + } + dev_dbg(&sep->pdev->dev, + "[PID%d] transactions ongoing, sleeping\n", + current->pid); + schedule(); + dev_dbg(&sep->pdev->dev, "[PID%d] woken up\n", current->pid); + + if (signal_pending(current)) { + dev_dbg(&sep->pdev->dev, "[PID%d] received signal\n", + current->pid); + error = -EINTR; + goto end_function; + } + } +end_function_setpid: + /* + * The pid_doing_transaction indicates that this process + * now owns the facilities to performa a transaction with + * the SEP. While this process is performing a transaction, + * no other process who has the SEP device open can perform + * any transactions. This method allows more than one process + * to have the device open at any given time, which provides + * finer granularity for device utilization by multiple + * processes. + */ + /* Only one process is able to progress here at a time */ + sep->pid_doing_transaction = current->pid; + +end_function: + finish_wait(&sep->event_transactions, &wait); + + return error; +} + +/** + * sep_check_transaction_owner - Checks if current process owns transaction + * @sep: SEP device + */ +static inline int sep_check_transaction_owner(struct sep_device *sep) +{ + dev_dbg(&sep->pdev->dev, "[PID%d] transaction pid = %d\n", + current->pid, + sep->pid_doing_transaction); + + if ((sep->pid_doing_transaction == 0) || + (current->pid != sep->pid_doing_transaction)) { + return -EACCES; + } + + /* We own the transaction */ + return 0; +} + +#ifdef DEBUG + +/** + * sep_dump_message - dump the message that is pending + * @sep: SEP device + * This will only print dump if DEBUG is set; it does + * follow kernel debug print enabling + */ +static void _sep_dump_message(struct sep_device *sep) +{ + int count; + + u32 *p = sep->shared_addr; + + for (count = 0; count < 40 * 4; count += 4) + dev_dbg(&sep->pdev->dev, + "[PID%d] Word %d of the message is %x\n", + current->pid, count/4, *p++); +} +#endif + +/** + * sep_map_and_alloc_shared_area -allocate shared block + * @sep: security processor + * @size: size of shared area + */ +static int sep_map_and_alloc_shared_area(struct sep_device *sep) +{ + sep->shared_addr = dma_alloc_coherent(&sep->pdev->dev, + sep->shared_size, + &sep->shared_bus, GFP_KERNEL); + + if (!sep->shared_addr) { + dev_dbg(&sep->pdev->dev, + "[PID%d] shared memory dma_alloc_coherent failed\n", + current->pid); + return -ENOMEM; + } + dev_dbg(&sep->pdev->dev, + "[PID%d] shared_addr %zx bytes @%p (bus %llx)\n", + current->pid, + sep->shared_size, sep->shared_addr, + (unsigned long long)sep->shared_bus); + return 0; +} + +/** + * sep_unmap_and_free_shared_area - free shared block + * @sep: security processor + */ +static void sep_unmap_and_free_shared_area(struct sep_device *sep) +{ + dma_free_coherent(&sep->pdev->dev, sep->shared_size, + sep->shared_addr, sep->shared_bus); +} + +/** + * sep_shared_bus_to_virt - convert bus/virt addresses + * @sep: pointer to struct sep_device + * @bus_address: address to convert + * + * Returns virtual address inside the shared area according + * to the bus address. + */ +static void *sep_shared_bus_to_virt(struct sep_device *sep, + dma_addr_t bus_address) +{ + return sep->shared_addr + (bus_address - sep->shared_bus); +} + +/** + * sep_open - device open method + * @inode: inode of SEP device + * @filp: file handle to SEP device + * + * Open method for the SEP device. Called when userspace opens + * the SEP device node. + * + * Returns zero on success otherwise an error code. + */ +static int sep_open(struct inode *inode, struct file *filp) +{ + struct sep_device *sep; + struct sep_private_data *priv; + + dev_dbg(&sep_dev->pdev->dev, "[PID%d] open\n", current->pid); + + if (filp->f_flags & O_NONBLOCK) + return -ENOTSUPP; + + /* + * Get the SEP device structure and use it for the + * private_data field in filp for other methods + */ + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + sep = sep_dev; + priv->device = sep; + filp->private_data = priv; + + dev_dbg(&sep_dev->pdev->dev, "[PID%d] priv is 0x%p\n", + current->pid, priv); + + /* Anyone can open; locking takes place at transaction level */ + return 0; +} + +/** + * sep_free_dma_table_data_handler - free DMA table + * @sep: pointere to struct sep_device + * @dma_ctx: dma context + * + * Handles the request to free DMA table for synchronic actions + */ +int sep_free_dma_table_data_handler(struct sep_device *sep, + struct sep_dma_context **dma_ctx) +{ + int count; + int dcb_counter; + /* Pointer to the current dma_resource struct */ + struct sep_dma_resource *dma; + + dev_dbg(&sep->pdev->dev, + "[PID%d] sep_free_dma_table_data_handler\n", + current->pid); + + if (!dma_ctx || !(*dma_ctx)) { + /* No context or context already freed */ + dev_dbg(&sep->pdev->dev, + "[PID%d] no DMA context or context already freed\n", + current->pid); + + return 0; + } + + dev_dbg(&sep->pdev->dev, "[PID%d] (*dma_ctx)->nr_dcb_creat 0x%x\n", + current->pid, + (*dma_ctx)->nr_dcb_creat); + + for (dcb_counter = 0; + dcb_counter < (*dma_ctx)->nr_dcb_creat; dcb_counter++) { + dma = &(*dma_ctx)->dma_res_arr[dcb_counter]; + + /* Unmap and free input map array */ + if (dma->in_map_array) { + for (count = 0; count < dma->in_num_pages; count++) { + dma_unmap_page(&sep->pdev->dev, + dma->in_map_array[count].dma_addr, + dma->in_map_array[count].size, + DMA_TO_DEVICE); + } + kfree(dma->in_map_array); + } + + /* Unmap output map array, DON'T free it yet */ + if (dma->out_map_array) { + for (count = 0; count < dma->out_num_pages; count++) { + dma_unmap_page(&sep->pdev->dev, + dma->out_map_array[count].dma_addr, + dma->out_map_array[count].size, + DMA_FROM_DEVICE); + } + kfree(dma->out_map_array); + } + + /* Free page cache for output */ + if (dma->in_page_array) { + for (count = 0; count < dma->in_num_pages; count++) { + flush_dcache_page(dma->in_page_array[count]); + page_cache_release(dma->in_page_array[count]); + } + kfree(dma->in_page_array); + } + + if (dma->out_page_array) { + for (count = 0; count < dma->out_num_pages; count++) { + if (!PageReserved(dma->out_page_array[count])) + + SetPageDirty(dma-> + out_page_array[count]); + + flush_dcache_page(dma->out_page_array[count]); + page_cache_release(dma->out_page_array[count]); + } + kfree(dma->out_page_array); + } + + /** + * Note that here we use in_map_num_entries because we + * don't have a page array; the page array is generated + * only in the lock_user_pages, which is not called + * for kernel crypto, which is what the sg (scatter gather + * is used for exclusively + */ + if (dma->src_sg) { + dma_unmap_sg(&sep->pdev->dev, dma->src_sg, + dma->in_map_num_entries, DMA_TO_DEVICE); + dma->src_sg = NULL; + } + + if (dma->dst_sg) { + dma_unmap_sg(&sep->pdev->dev, dma->dst_sg, + dma->in_map_num_entries, DMA_FROM_DEVICE); + dma->dst_sg = NULL; + } + + /* Reset all the values */ + dma->in_page_array = NULL; + dma->out_page_array = NULL; + dma->in_num_pages = 0; + dma->out_num_pages = 0; + dma->in_map_array = NULL; + dma->out_map_array = NULL; + dma->in_map_num_entries = 0; + dma->out_map_num_entries = 0; + } + + (*dma_ctx)->nr_dcb_creat = 0; + (*dma_ctx)->num_lli_tables_created = 0; + + kfree(*dma_ctx); + *dma_ctx = NULL; + + dev_dbg(&sep->pdev->dev, + "[PID%d] sep_free_dma_table_data_handler end\n", + current->pid); + + return 0; +} + +/** + * sep_end_transaction_handler - end transaction + * @sep: pointer to struct sep_device + * @dma_ctx: DMA context + * @call_status: Call status + * + * This API handles the end transaction request. + */ +static int sep_end_transaction_handler(struct sep_device *sep, + struct sep_dma_context **dma_ctx, + struct sep_call_status *call_status, + struct sep_queue_info **my_queue_elem) +{ + dev_dbg(&sep->pdev->dev, "[PID%d] ending transaction\n", current->pid); + + /* + * Extraneous transaction clearing would mess up PM + * device usage counters and SEP would get suspended + * just before we send a command to SEP in the next + * transaction + * */ + if (sep_check_transaction_owner(sep)) { + dev_dbg(&sep->pdev->dev, "[PID%d] not transaction owner\n", + current->pid); + return 0; + } + + /* Update queue status */ + sep_queue_status_remove(sep, my_queue_elem); + + /* Check that all the DMA resources were freed */ + if (dma_ctx) + sep_free_dma_table_data_handler(sep, dma_ctx); + + /* Reset call status for next transaction */ + if (call_status) + call_status->status = 0; + + /* Clear the message area to avoid next transaction reading + * sensitive results from previous transaction */ + memset(sep->shared_addr, 0, + SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES); + + /* start suspend delay */ +#ifdef SEP_ENABLE_RUNTIME_PM + if (sep->in_use) { + sep->in_use = 0; + pm_runtime_mark_last_busy(&sep->pdev->dev); + pm_runtime_put_autosuspend(&sep->pdev->dev); + } +#endif + + clear_bit(SEP_WORKING_LOCK_BIT, &sep->in_use_flags); + sep->pid_doing_transaction = 0; + + /* Now it's safe for next process to proceed */ + dev_dbg(&sep->pdev->dev, "[PID%d] waking up next transaction\n", + current->pid); + clear_bit(SEP_TRANSACTION_STARTED_LOCK_BIT, &sep->in_use_flags); + wake_up(&sep->event_transactions); + + return 0; +} + + +/** + * sep_release - close a SEP device + * @inode: inode of SEP device + * @filp: file handle being closed + * + * Called on the final close of a SEP device. + */ +static int sep_release(struct inode *inode, struct file *filp) +{ + struct sep_private_data * const private_data = filp->private_data; + struct sep_call_status *call_status = &private_data->call_status; + struct sep_device *sep = private_data->device; + struct sep_dma_context **dma_ctx = &private_data->dma_ctx; + struct sep_queue_info **my_queue_elem = &private_data->my_queue_elem; + + dev_dbg(&sep->pdev->dev, "[PID%d] release\n", current->pid); + + sep_end_transaction_handler(sep, dma_ctx, call_status, + my_queue_elem); + + kfree(filp->private_data); + + return 0; +} + +/** + * sep_mmap - maps the shared area to user space + * @filp: pointer to struct file + * @vma: pointer to vm_area_struct + * + * Called on an mmap of our space via the normal SEP device + */ +static int sep_mmap(struct file *filp, struct vm_area_struct *vma) +{ + struct sep_private_data * const private_data = filp->private_data; + struct sep_call_status *call_status = &private_data->call_status; + struct sep_device *sep = private_data->device; + struct sep_queue_info **my_queue_elem = &private_data->my_queue_elem; + dma_addr_t bus_addr; + unsigned long error = 0; + + dev_dbg(&sep->pdev->dev, "[PID%d] sep_mmap\n", current->pid); + + /* Set the transaction busy (own the device) */ + /* + * Problem for multithreaded applications is that here we're + * possibly going to sleep while holding a write lock on + * current->mm->mmap_sem, which will cause deadlock for ongoing + * transaction trying to create DMA tables + */ + error = sep_wait_transaction(sep); + if (error) + /* Interrupted by signal, don't clear transaction */ + goto end_function; + + /* Clear the message area to avoid next transaction reading + * sensitive results from previous transaction */ + memset(sep->shared_addr, 0, + SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES); + + /* + * Check that the size of the mapped range is as the size of the message + * shared area + */ + if ((vma->vm_end - vma->vm_start) > SEP_DRIVER_MMMAP_AREA_SIZE) { + error = -EINVAL; + goto end_function_with_error; + } + + dev_dbg(&sep->pdev->dev, "[PID%d] shared_addr is %p\n", + current->pid, sep->shared_addr); + + /* Get bus address */ + bus_addr = sep->shared_bus; + + if (remap_pfn_range(vma, vma->vm_start, bus_addr >> PAGE_SHIFT, + vma->vm_end - vma->vm_start, vma->vm_page_prot)) { + dev_dbg(&sep->pdev->dev, "[PID%d] remap_page_range failed\n", + current->pid); + error = -EAGAIN; + goto end_function_with_error; + } + + /* Update call status */ + set_bit(SEP_LEGACY_MMAP_DONE_OFFSET, &call_status->status); + + goto end_function; + +end_function_with_error: + /* Clear our transaction */ + sep_end_transaction_handler(sep, NULL, call_status, + my_queue_elem); + +end_function: + return error; +} + +/** + * sep_poll - poll handler + * @filp: pointer to struct file + * @wait: pointer to poll_table + * + * Called by the OS when the kernel is asked to do a poll on + * a SEP file handle. + */ +static unsigned int sep_poll(struct file *filp, poll_table *wait) +{ + struct sep_private_data * const private_data = filp->private_data; + struct sep_call_status *call_status = &private_data->call_status; + struct sep_device *sep = private_data->device; + u32 mask = 0; + u32 retval = 0; + u32 retval2 = 0; + unsigned long lock_irq_flag; + + /* Am I the process that owns the transaction? */ + if (sep_check_transaction_owner(sep)) { + dev_dbg(&sep->pdev->dev, "[PID%d] poll pid not owner\n", + current->pid); + mask = POLLERR; + goto end_function; + } + + /* Check if send command or send_reply were activated previously */ + if (0 == test_bit(SEP_LEGACY_SENDMSG_DONE_OFFSET, + &call_status->status)) { + dev_warn(&sep->pdev->dev, "[PID%d] sendmsg not called\n", + current->pid); + mask = POLLERR; + goto end_function; + } + + + /* Add the event to the polling wait table */ + dev_dbg(&sep->pdev->dev, "[PID%d] poll: calling wait sep_event\n", + current->pid); + + poll_wait(filp, &sep->event_interrupt, wait); + + dev_dbg(&sep->pdev->dev, + "[PID%d] poll: send_ct is %lx reply ct is %lx\n", + current->pid, sep->send_ct, sep->reply_ct); + + /* Check if error occured during poll */ + retval2 = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR3_REG_ADDR); + if ((retval2 != 0x0) && (retval2 != 0x8)) { + dev_dbg(&sep->pdev->dev, "[PID%d] poll; poll error %x\n", + current->pid, retval2); + mask |= POLLERR; + goto end_function; + } + + spin_lock_irqsave(&sep->snd_rply_lck, lock_irq_flag); + + if (sep->send_ct == sep->reply_ct) { + spin_unlock_irqrestore(&sep->snd_rply_lck, lock_irq_flag); + retval = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR2_REG_ADDR); + dev_dbg(&sep->pdev->dev, + "[PID%d] poll: data ready check (GPR2) %x\n", + current->pid, retval); + + /* Check if printf request */ + if ((retval >> 30) & 0x1) { + dev_dbg(&sep->pdev->dev, + "[PID%d] poll: SEP printf request\n", + current->pid); + goto end_function; + } + + /* Check if the this is SEP reply or request */ + if (retval >> 31) { + dev_dbg(&sep->pdev->dev, + "[PID%d] poll: SEP request\n", + current->pid); + } else { + dev_dbg(&sep->pdev->dev, + "[PID%d] poll: normal return\n", + current->pid); + sep_dump_message(sep); + dev_dbg(&sep->pdev->dev, + "[PID%d] poll; SEP reply POLLIN|POLLRDNORM\n", + current->pid); + mask |= POLLIN | POLLRDNORM; + } + set_bit(SEP_LEGACY_POLL_DONE_OFFSET, &call_status->status); + } else { + spin_unlock_irqrestore(&sep->snd_rply_lck, lock_irq_flag); + dev_dbg(&sep->pdev->dev, + "[PID%d] poll; no reply; returning mask of 0\n", + current->pid); + mask = 0; + } + +end_function: + return mask; +} + +/** + * sep_time_address - address in SEP memory of time + * @sep: SEP device we want the address from + * + * Return the address of the two dwords in memory used for time + * setting. + */ +static u32 *sep_time_address(struct sep_device *sep) +{ + return sep->shared_addr + + SEP_DRIVER_SYSTEM_TIME_MEMORY_OFFSET_IN_BYTES; +} + +/** + * sep_set_time - set the SEP time + * @sep: the SEP we are setting the time for + * + * Calculates time and sets it at the predefined address. + * Called with the SEP mutex held. + */ +static unsigned long sep_set_time(struct sep_device *sep) +{ + struct timeval time; + u32 *time_addr; /* Address of time as seen by the kernel */ + + + do_gettimeofday(&time); + + /* Set value in the SYSTEM MEMORY offset */ + time_addr = sep_time_address(sep); + + time_addr[0] = SEP_TIME_VAL_TOKEN; + time_addr[1] = time.tv_sec; + + dev_dbg(&sep->pdev->dev, "[PID%d] time.tv_sec is %lu\n", + current->pid, time.tv_sec); + dev_dbg(&sep->pdev->dev, "[PID%d] time_addr is %p\n", + current->pid, time_addr); + dev_dbg(&sep->pdev->dev, "[PID%d] sep->shared_addr is %p\n", + current->pid, sep->shared_addr); + + return time.tv_sec; +} + +/** + * sep_send_command_handler - kick off a command + * @sep: SEP being signalled + * + * This function raises interrupt to SEP that signals that is has a new + * command from the host + * + * Note that this function does fall under the ioctl lock + */ +int sep_send_command_handler(struct sep_device *sep) +{ + unsigned long lock_irq_flag; + u32 *msg_pool; + int error = 0; + + /* Basic sanity check; set msg pool to start of shared area */ + msg_pool = (u32 *)sep->shared_addr; + msg_pool += 2; + + /* Look for start msg token */ + if (*msg_pool != SEP_START_MSG_TOKEN) { + dev_warn(&sep->pdev->dev, "start message token not present\n"); + error = -EPROTO; + goto end_function; + } + + /* Do we have a reasonable size? */ + msg_pool += 1; + if ((*msg_pool < 2) || + (*msg_pool > SEP_DRIVER_MAX_MESSAGE_SIZE_IN_BYTES)) { + + dev_warn(&sep->pdev->dev, "invalid message size\n"); + error = -EPROTO; + goto end_function; + } + + /* Does the command look reasonable? */ + msg_pool += 1; + if (*msg_pool < 2) { + dev_warn(&sep->pdev->dev, "invalid message opcode\n"); + error = -EPROTO; + goto end_function; + } + +#if defined(CONFIG_PM_RUNTIME) && defined(SEP_ENABLE_RUNTIME_PM) + dev_dbg(&sep->pdev->dev, "[PID%d] before pm sync status 0x%X\n", + current->pid, + sep->pdev->dev.power.runtime_status); + sep->in_use = 1; /* device is about to be used */ + pm_runtime_get_sync(&sep->pdev->dev); +#endif + + if (test_and_set_bit(SEP_WORKING_LOCK_BIT, &sep->in_use_flags)) { + error = -EPROTO; + goto end_function; + } + sep->in_use = 1; /* device is about to be used */ + sep_set_time(sep); + + sep_dump_message(sep); + + /* Update counter */ + spin_lock_irqsave(&sep->snd_rply_lck, lock_irq_flag); + sep->send_ct++; + spin_unlock_irqrestore(&sep->snd_rply_lck, lock_irq_flag); + + dev_dbg(&sep->pdev->dev, + "[PID%d] sep_send_command_handler send_ct %lx reply_ct %lx\n", + current->pid, sep->send_ct, sep->reply_ct); + + /* Send interrupt to SEP */ + sep_write_reg(sep, HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x2); + +end_function: + return error; +} + +/** + * sep_crypto_dma - + * @sep: pointer to struct sep_device + * @sg: pointer to struct scatterlist + * @direction: + * @dma_maps: pointer to place a pointer to array of dma maps + * This is filled in; anything previous there will be lost + * The structure for dma maps is sep_dma_map + * @returns number of dma maps on success; negative on error + * + * This creates the dma table from the scatterlist + * It is used only for kernel crypto as it works with scatterlists + * representation of data buffers + * + */ +static int sep_crypto_dma( + struct sep_device *sep, + struct scatterlist *sg, + struct sep_dma_map **dma_maps, + enum dma_data_direction direction) +{ + struct scatterlist *temp_sg; + + u32 count_segment; + u32 count_mapped; + struct sep_dma_map *sep_dma; + int ct1; + + if (sg->length == 0) + return 0; + + /* Count the segments */ + temp_sg = sg; + count_segment = 0; + while (temp_sg) { + count_segment += 1; + temp_sg = scatterwalk_sg_next(temp_sg); + } + dev_dbg(&sep->pdev->dev, + "There are (hex) %x segments in sg\n", count_segment); + + /* DMA map segments */ + count_mapped = dma_map_sg(&sep->pdev->dev, sg, + count_segment, direction); + + dev_dbg(&sep->pdev->dev, + "There are (hex) %x maps in sg\n", count_mapped); + + if (count_mapped == 0) { + dev_dbg(&sep->pdev->dev, "Cannot dma_map_sg\n"); + return -ENOMEM; + } + + sep_dma = kmalloc(sizeof(struct sep_dma_map) * + count_mapped, GFP_ATOMIC); + + if (sep_dma == NULL) { + dev_dbg(&sep->pdev->dev, "Cannot allocate dma_maps\n"); + return -ENOMEM; + } + + for_each_sg(sg, temp_sg, count_mapped, ct1) { + sep_dma[ct1].dma_addr = sg_dma_address(temp_sg); + sep_dma[ct1].size = sg_dma_len(temp_sg); + dev_dbg(&sep->pdev->dev, "(all hex) map %x dma %lx len %lx\n", + ct1, (unsigned long)sep_dma[ct1].dma_addr, + (unsigned long)sep_dma[ct1].size); + } + + *dma_maps = sep_dma; + return count_mapped; + +} + +/** + * sep_crypto_lli - + * @sep: pointer to struct sep_device + * @sg: pointer to struct scatterlist + * @data_size: total data size + * @direction: + * @dma_maps: pointer to place a pointer to array of dma maps + * This is filled in; anything previous there will be lost + * The structure for dma maps is sep_dma_map + * @lli_maps: pointer to place a pointer to array of lli maps + * This is filled in; anything previous there will be lost + * The structure for dma maps is sep_dma_map + * @returns number of dma maps on success; negative on error + * + * This creates the LLI table from the scatterlist + * It is only used for kernel crypto as it works exclusively + * with scatterlists (struct scatterlist) representation of + * data buffers + */ +static int sep_crypto_lli( + struct sep_device *sep, + struct scatterlist *sg, + struct sep_dma_map **maps, + struct sep_lli_entry **llis, + u32 data_size, + enum dma_data_direction direction) +{ + + int ct1; + struct sep_lli_entry *sep_lli; + struct sep_dma_map *sep_map; + + int nbr_ents; + + nbr_ents = sep_crypto_dma(sep, sg, maps, direction); + if (nbr_ents <= 0) { + dev_dbg(&sep->pdev->dev, "crypto_dma failed %x\n", + nbr_ents); + return nbr_ents; + } + + sep_map = *maps; + + sep_lli = kmalloc(sizeof(struct sep_lli_entry) * nbr_ents, GFP_ATOMIC); + + if (sep_lli == NULL) { + dev_dbg(&sep->pdev->dev, "Cannot allocate lli_maps\n"); + + kfree(*maps); + *maps = NULL; + return -ENOMEM; + } + + for (ct1 = 0; ct1 < nbr_ents; ct1 += 1) { + sep_lli[ct1].bus_address = (u32)sep_map[ct1].dma_addr; + + /* Maximum for page is total data size */ + if (sep_map[ct1].size > data_size) + sep_map[ct1].size = data_size; + + sep_lli[ct1].block_size = (u32)sep_map[ct1].size; + } + + *llis = sep_lli; + return nbr_ents; +} + +/** + * sep_lock_kernel_pages - map kernel pages for DMA + * @sep: pointer to struct sep_device + * @kernel_virt_addr: address of data buffer in kernel + * @data_size: size of data + * @lli_array_ptr: lli array + * @in_out_flag: input into device or output from device + * + * This function locks all the physical pages of the kernel virtual buffer + * and construct a basic lli array, where each entry holds the physical + * page address and the size that application data holds in this page + * This function is used only during kernel crypto mod calls from within + * the kernel (when ioctl is not used) + * + * This is used only for kernel crypto. Kernel pages + * are handled differently as they are done via + * scatter gather lists (struct scatterlist) + */ +static int sep_lock_kernel_pages(struct sep_device *sep, + unsigned long kernel_virt_addr, + u32 data_size, + struct sep_lli_entry **lli_array_ptr, + int in_out_flag, + struct sep_dma_context *dma_ctx) + +{ + u32 num_pages; + struct scatterlist *sg; + + /* Array of lli */ + struct sep_lli_entry *lli_array; + /* Map array */ + struct sep_dma_map *map_array; + + enum dma_data_direction direction; + + lli_array = NULL; + map_array = NULL; + + if (in_out_flag == SEP_DRIVER_IN_FLAG) { + direction = DMA_TO_DEVICE; + sg = dma_ctx->src_sg; + } else { + direction = DMA_FROM_DEVICE; + sg = dma_ctx->dst_sg; + } + + num_pages = sep_crypto_lli(sep, sg, &map_array, &lli_array, + data_size, direction); + + if (num_pages <= 0) { + dev_dbg(&sep->pdev->dev, "sep_crypto_lli returned error %x\n", + num_pages); + return -ENOMEM; + } + + /* Put mapped kernel sg into kernel resource array */ + + /* Set output params acording to the in_out flag */ + if (in_out_flag == SEP_DRIVER_IN_FLAG) { + *lli_array_ptr = lli_array; + dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_num_pages = + num_pages; + dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_page_array = + NULL; + dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_map_array = + map_array; + dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_map_num_entries = + num_pages; + dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].src_sg = + dma_ctx->src_sg; + } else { + *lli_array_ptr = lli_array; + dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].out_num_pages = + num_pages; + dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].out_page_array = + NULL; + dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].out_map_array = + map_array; + dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat]. + out_map_num_entries = num_pages; + dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].dst_sg = + dma_ctx->dst_sg; + } + + return 0; +} + +/** + * sep_lock_user_pages - lock and map user pages for DMA + * @sep: pointer to struct sep_device + * @app_virt_addr: user memory data buffer + * @data_size: size of data buffer + * @lli_array_ptr: lli array + * @in_out_flag: input or output to device + * + * This function locks all the physical pages of the application + * virtual buffer and construct a basic lli array, where each entry + * holds the physical page address and the size that application + * data holds in this physical pages + */ +static int sep_lock_user_pages(struct sep_device *sep, + u32 app_virt_addr, + u32 data_size, + struct sep_lli_entry **lli_array_ptr, + int in_out_flag, + struct sep_dma_context *dma_ctx) + +{ + int error = 0; + u32 count; + int result; + /* The the page of the end address of the user space buffer */ + u32 end_page; + /* The page of the start address of the user space buffer */ + u32 start_page; + /* The range in pages */ + u32 num_pages; + /* Array of pointers to page */ + struct page **page_array; + /* Array of lli */ + struct sep_lli_entry *lli_array; + /* Map array */ + struct sep_dma_map *map_array; + + /* Set start and end pages and num pages */ + end_page = (app_virt_addr + data_size - 1) >> PAGE_SHIFT; + start_page = app_virt_addr >> PAGE_SHIFT; + num_pages = end_page - start_page + 1; + + dev_dbg(&sep->pdev->dev, + "[PID%d] lock user pages app_virt_addr is %x\n", + current->pid, app_virt_addr); + + dev_dbg(&sep->pdev->dev, "[PID%d] data_size is (hex) %x\n", + current->pid, data_size); + dev_dbg(&sep->pdev->dev, "[PID%d] start_page is (hex) %x\n", + current->pid, start_page); + dev_dbg(&sep->pdev->dev, "[PID%d] end_page is (hex) %x\n", + current->pid, end_page); + dev_dbg(&sep->pdev->dev, "[PID%d] num_pages is (hex) %x\n", + current->pid, num_pages); + + /* Allocate array of pages structure pointers */ + page_array = kmalloc(sizeof(struct page *) * num_pages, GFP_ATOMIC); + if (!page_array) { + error = -ENOMEM; + goto end_function; + } + map_array = kmalloc(sizeof(struct sep_dma_map) * num_pages, GFP_ATOMIC); + if (!map_array) { + dev_warn(&sep->pdev->dev, + "[PID%d] kmalloc for map_array failed\n", + current->pid); + error = -ENOMEM; + goto end_function_with_error1; + } + + lli_array = kmalloc(sizeof(struct sep_lli_entry) * num_pages, + GFP_ATOMIC); + + if (!lli_array) { + dev_warn(&sep->pdev->dev, + "[PID%d] kmalloc for lli_array failed\n", + current->pid); + error = -ENOMEM; + goto end_function_with_error2; + } + + /* Convert the application virtual address into a set of physical */ + down_read(¤t->mm->mmap_sem); + result = get_user_pages(current, current->mm, app_virt_addr, + num_pages, + ((in_out_flag == SEP_DRIVER_IN_FLAG) ? 0 : 1), + 0, page_array, NULL); + + up_read(¤t->mm->mmap_sem); + + /* Check the number of pages locked - if not all then exit with error */ + if (result != num_pages) { + dev_warn(&sep->pdev->dev, + "[PID%d] not all pages locked by get_user_pages, " + "result 0x%X, num_pages 0x%X\n", + current->pid, result, num_pages); + error = -ENOMEM; + goto end_function_with_error3; + } + + dev_dbg(&sep->pdev->dev, "[PID%d] get_user_pages succeeded\n", + current->pid); + + /* + * Fill the array using page array data and + * map the pages - this action will also flush the cache as needed + */ + for (count = 0; count < num_pages; count++) { + /* Fill the map array */ + map_array[count].dma_addr = + dma_map_page(&sep->pdev->dev, page_array[count], + 0, PAGE_SIZE, DMA_BIDIRECTIONAL); + + map_array[count].size = PAGE_SIZE; + + /* Fill the lli array entry */ + lli_array[count].bus_address = (u32)map_array[count].dma_addr; + lli_array[count].block_size = PAGE_SIZE; + + dev_dbg(&sep->pdev->dev, + "[PID%d] lli_array[%x].bus_address is %08lx, " + "lli_array[%x].block_size is (hex) %x\n", current->pid, + count, (unsigned long)lli_array[count].bus_address, + count, lli_array[count].block_size); + } + + /* Check the offset for the first page */ + lli_array[0].bus_address = + lli_array[0].bus_address + (app_virt_addr & (~PAGE_MASK)); + + /* Check that not all the data is in the first page only */ + if ((PAGE_SIZE - (app_virt_addr & (~PAGE_MASK))) >= data_size) + lli_array[0].block_size = data_size; + else + lli_array[0].block_size = + PAGE_SIZE - (app_virt_addr & (~PAGE_MASK)); + + dev_dbg(&sep->pdev->dev, + "[PID%d] After check if page 0 has all data\n", + current->pid); + dev_dbg(&sep->pdev->dev, + "[PID%d] lli_array[0].bus_address is (hex) %08lx, " + "lli_array[0].block_size is (hex) %x\n", + current->pid, + (unsigned long)lli_array[0].bus_address, + lli_array[0].block_size); + + + /* Check the size of the last page */ + if (num_pages > 1) { + lli_array[num_pages - 1].block_size = + (app_virt_addr + data_size) & (~PAGE_MASK); + if (lli_array[num_pages - 1].block_size == 0) + lli_array[num_pages - 1].block_size = PAGE_SIZE; + + dev_dbg(&sep->pdev->dev, + "[PID%d] After last page size adjustment\n", + current->pid); + dev_dbg(&sep->pdev->dev, + "[PID%d] lli_array[%x].bus_address is (hex) %08lx, " + "lli_array[%x].block_size is (hex) %x\n", + current->pid, + num_pages - 1, + (unsigned long)lli_array[num_pages - 1].bus_address, + num_pages - 1, + lli_array[num_pages - 1].block_size); + } + + /* Set output params acording to the in_out flag */ + if (in_out_flag == SEP_DRIVER_IN_FLAG) { + *lli_array_ptr = lli_array; + dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_num_pages = + num_pages; + dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_page_array = + page_array; + dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_map_array = + map_array; + dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_map_num_entries = + num_pages; + dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].src_sg = NULL; + } else { + *lli_array_ptr = lli_array; + dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].out_num_pages = + num_pages; + dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].out_page_array = + page_array; + dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].out_map_array = + map_array; + dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat]. + out_map_num_entries = num_pages; + dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].dst_sg = NULL; + } + goto end_function; + +end_function_with_error3: + /* Free lli array */ + kfree(lli_array); + +end_function_with_error2: + kfree(map_array); + +end_function_with_error1: + /* Free page array */ + kfree(page_array); + +end_function: + return error; +} + +/** + * sep_calculate_lli_table_max_size - size the LLI table + * @sep: pointer to struct sep_device + * @lli_in_array_ptr + * @num_array_entries + * @last_table_flag + * + * This function calculates the size of data that can be inserted into + * the lli table from this array, such that either the table is full + * (all entries are entered), or there are no more entries in the + * lli array + */ +static u32 sep_calculate_lli_table_max_size(struct sep_device *sep, + struct sep_lli_entry *lli_in_array_ptr, + u32 num_array_entries, + u32 *last_table_flag) +{ + u32 counter; + /* Table data size */ + u32 table_data_size = 0; + /* Data size for the next table */ + u32 next_table_data_size; + + *last_table_flag = 0; + + /* + * Calculate the data in the out lli table till we fill the whole + * table or till the data has ended + */ + for (counter = 0; + (counter < (SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP - 1)) && + (counter < num_array_entries); counter++) + table_data_size += lli_in_array_ptr[counter].block_size; + + /* + * Check if we reached the last entry, + * meaning this ia the last table to build, + * and no need to check the block alignment + */ + if (counter == num_array_entries) { + /* Set the last table flag */ + *last_table_flag = 1; + goto end_function; + } + + /* + * Calculate the data size of the next table. + * Stop if no entries left or if data size is more the DMA restriction + */ + next_table_data_size = 0; + for (; counter < num_array_entries; counter++) { + next_table_data_size += lli_in_array_ptr[counter].block_size; + if (next_table_data_size >= SEP_DRIVER_MIN_DATA_SIZE_PER_TABLE) + break; + } + + /* + * Check if the next table data size is less then DMA rstriction. + * if it is - recalculate the current table size, so that the next + * table data size will be adaquete for DMA + */ + if (next_table_data_size && + next_table_data_size < SEP_DRIVER_MIN_DATA_SIZE_PER_TABLE) + + table_data_size -= (SEP_DRIVER_MIN_DATA_SIZE_PER_TABLE - + next_table_data_size); + +end_function: + return table_data_size; +} + +/** + * sep_build_lli_table - build an lli array for the given table + * @sep: pointer to struct sep_device + * @lli_array_ptr: pointer to lli array + * @lli_table_ptr: pointer to lli table + * @num_processed_entries_ptr: pointer to number of entries + * @num_table_entries_ptr: pointer to number of tables + * @table_data_size: total data size + * + * Builds ant lli table from the lli_array according to + * the given size of data + */ +static void sep_build_lli_table(struct sep_device *sep, + struct sep_lli_entry *lli_array_ptr, + struct sep_lli_entry *lli_table_ptr, + u32 *num_processed_entries_ptr, + u32 *num_table_entries_ptr, + u32 table_data_size) +{ + /* Current table data size */ + u32 curr_table_data_size; + /* Counter of lli array entry */ + u32 array_counter; + + /* Init current table data size and lli array entry counter */ + curr_table_data_size = 0; + array_counter = 0; + *num_table_entries_ptr = 1; + + dev_dbg(&sep->pdev->dev, + "[PID%d] build lli table table_data_size: (hex) %x\n", + current->pid, table_data_size); + + /* Fill the table till table size reaches the needed amount */ + while (curr_table_data_size < table_data_size) { + /* Update the number of entries in table */ + (*num_table_entries_ptr)++; + + lli_table_ptr->bus_address = + cpu_to_le32(lli_array_ptr[array_counter].bus_address); + + lli_table_ptr->block_size = + cpu_to_le32(lli_array_ptr[array_counter].block_size); + + curr_table_data_size += lli_array_ptr[array_counter].block_size; + + dev_dbg(&sep->pdev->dev, + "[PID%d] lli_table_ptr is %p\n", + current->pid, lli_table_ptr); + dev_dbg(&sep->pdev->dev, + "[PID%d] lli_table_ptr->bus_address: %08lx\n", + current->pid, + (unsigned long)lli_table_ptr->bus_address); + + dev_dbg(&sep->pdev->dev, + "[PID%d] lli_table_ptr->block_size is (hex) %x\n", + current->pid, lli_table_ptr->block_size); + + /* Check for overflow of the table data */ + if (curr_table_data_size > table_data_size) { + dev_dbg(&sep->pdev->dev, + "[PID%d] curr_table_data_size too large\n", + current->pid); + + /* Update the size of block in the table */ + lli_table_ptr->block_size = + cpu_to_le32(lli_table_ptr->block_size) - + (curr_table_data_size - table_data_size); + + /* Update the physical address in the lli array */ + lli_array_ptr[array_counter].bus_address += + cpu_to_le32(lli_table_ptr->block_size); + + /* Update the block size left in the lli array */ + lli_array_ptr[array_counter].block_size = + (curr_table_data_size - table_data_size); + } else + /* Advance to the next entry in the lli_array */ + array_counter++; + + dev_dbg(&sep->pdev->dev, + "[PID%d] lli_table_ptr->bus_address is %08lx\n", + current->pid, + (unsigned long)lli_table_ptr->bus_address); + dev_dbg(&sep->pdev->dev, + "[PID%d] lli_table_ptr->block_size is (hex) %x\n", + current->pid, + lli_table_ptr->block_size); + + /* Move to the next entry in table */ + lli_table_ptr++; + } + + /* Set the info entry to default */ + lli_table_ptr->bus_address = 0xffffffff; + lli_table_ptr->block_size = 0; + + /* Set the output parameter */ + *num_processed_entries_ptr += array_counter; + +} + +/** + * sep_shared_area_virt_to_bus - map shared area to bus address + * @sep: pointer to struct sep_device + * @virt_address: virtual address to convert + * + * This functions returns the physical address inside shared area according + * to the virtual address. It can be either on the externa RAM device + * (ioremapped), or on the system RAM + * This implementation is for the external RAM + */ +static dma_addr_t sep_shared_area_virt_to_bus(struct sep_device *sep, + void *virt_address) +{ + dev_dbg(&sep->pdev->dev, "[PID%d] sh virt to phys v %p\n", + current->pid, virt_address); + dev_dbg(&sep->pdev->dev, "[PID%d] sh virt to phys p %08lx\n", + current->pid, + (unsigned long) + sep->shared_bus + (virt_address - sep->shared_addr)); + + return sep->shared_bus + (size_t)(virt_address - sep->shared_addr); +} + +/** + * sep_shared_area_bus_to_virt - map shared area bus address to kernel + * @sep: pointer to struct sep_device + * @bus_address: bus address to convert + * + * This functions returns the virtual address inside shared area + * according to the physical address. It can be either on the + * externa RAM device (ioremapped), or on the system RAM + * This implementation is for the external RAM + */ +static void *sep_shared_area_bus_to_virt(struct sep_device *sep, + dma_addr_t bus_address) +{ + dev_dbg(&sep->pdev->dev, "[PID%d] shared bus to virt b=%lx v=%lx\n", + current->pid, + (unsigned long)bus_address, (unsigned long)(sep->shared_addr + + (size_t)(bus_address - sep->shared_bus))); + + return sep->shared_addr + (size_t)(bus_address - sep->shared_bus); +} + +/** + * sep_debug_print_lli_tables - dump LLI table + * @sep: pointer to struct sep_device + * @lli_table_ptr: pointer to sep_lli_entry + * @num_table_entries: number of entries + * @table_data_size: total data size + * + * Walk the the list of the print created tables and print all the data + */ +static void sep_debug_print_lli_tables(struct sep_device *sep, + struct sep_lli_entry *lli_table_ptr, + unsigned long num_table_entries, + unsigned long table_data_size) +{ + unsigned long table_count = 1; + unsigned long entries_count = 0; + + dev_dbg(&sep->pdev->dev, "[PID%d] sep_debug_print_lli_tables start\n", + current->pid); + if (num_table_entries == 0) { + dev_dbg(&sep->pdev->dev, "[PID%d] no table to print\n", + current->pid); + return; + } + + while ((unsigned long) lli_table_ptr->bus_address != 0xffffffff) { + dev_dbg(&sep->pdev->dev, + "[PID%d] lli table %08lx, " + "table_data_size is (hex) %lx\n", + current->pid, table_count, table_data_size); + dev_dbg(&sep->pdev->dev, + "[PID%d] num_table_entries is (hex) %lx\n", + current->pid, num_table_entries); + + /* Print entries of the table (without info entry) */ + for (entries_count = 0; entries_count < num_table_entries; + entries_count++, lli_table_ptr++) { + + dev_dbg(&sep->pdev->dev, + "[PID%d] lli_table_ptr address is %08lx\n", + current->pid, + (unsigned long) lli_table_ptr); + + dev_dbg(&sep->pdev->dev, + "[PID%d] phys address is %08lx " + "block size is (hex) %x\n", current->pid, + (unsigned long)lli_table_ptr->bus_address, + lli_table_ptr->block_size); + } + + /* Point to the info entry */ + lli_table_ptr--; + + dev_dbg(&sep->pdev->dev, + "[PID%d] phys lli_table_ptr->block_size " + "is (hex) %x\n", + current->pid, + lli_table_ptr->block_size); + + dev_dbg(&sep->pdev->dev, + "[PID%d] phys lli_table_ptr->physical_address " + "is %08lx\n", + current->pid, + (unsigned long)lli_table_ptr->bus_address); + + + table_data_size = lli_table_ptr->block_size & 0xffffff; + num_table_entries = (lli_table_ptr->block_size >> 24) & 0xff; + + dev_dbg(&sep->pdev->dev, + "[PID%d] phys table_data_size is " + "(hex) %lx num_table_entries is" + " %lx bus_address is%lx\n", + current->pid, + table_data_size, + num_table_entries, + (unsigned long)lli_table_ptr->bus_address); + + if ((unsigned long)lli_table_ptr->bus_address != 0xffffffff) + lli_table_ptr = (struct sep_lli_entry *) + sep_shared_bus_to_virt(sep, + (unsigned long)lli_table_ptr->bus_address); + + table_count++; + } + dev_dbg(&sep->pdev->dev, "[PID%d] sep_debug_print_lli_tables end\n", + current->pid); +} + + +/** + * sep_prepare_empty_lli_table - create a blank LLI table + * @sep: pointer to struct sep_device + * @lli_table_addr_ptr: pointer to lli table + * @num_entries_ptr: pointer to number of entries + * @table_data_size_ptr: point to table data size + * @dmatables_region: Optional buffer for DMA tables + * @dma_ctx: DMA context + * + * This function creates empty lli tables when there is no data + */ +static void sep_prepare_empty_lli_table(struct sep_device *sep, + dma_addr_t *lli_table_addr_ptr, + u32 *num_entries_ptr, + u32 *table_data_size_ptr, + void **dmatables_region, + struct sep_dma_context *dma_ctx) +{ + struct sep_lli_entry *lli_table_ptr; + + /* Find the area for new table */ + lli_table_ptr = + (struct sep_lli_entry *)(sep->shared_addr + + SYNCHRONIC_DMA_TABLES_AREA_OFFSET_BYTES + + dma_ctx->num_lli_tables_created * sizeof(struct sep_lli_entry) * + SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP); + + if (dmatables_region && *dmatables_region) + lli_table_ptr = *dmatables_region; + + lli_table_ptr->bus_address = 0; + lli_table_ptr->block_size = 0; + + lli_table_ptr++; + lli_table_ptr->bus_address = 0xFFFFFFFF; + lli_table_ptr->block_size = 0; + + /* Set the output parameter value */ + *lli_table_addr_ptr = sep->shared_bus + + SYNCHRONIC_DMA_TABLES_AREA_OFFSET_BYTES + + dma_ctx->num_lli_tables_created * + sizeof(struct sep_lli_entry) * + SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP; + + /* Set the num of entries and table data size for empty table */ + *num_entries_ptr = 2; + *table_data_size_ptr = 0; + + /* Update the number of created tables */ + dma_ctx->num_lli_tables_created++; +} + +/** + * sep_prepare_input_dma_table - prepare input DMA mappings + * @sep: pointer to struct sep_device + * @data_size: + * @block_size: + * @lli_table_ptr: + * @num_entries_ptr: + * @table_data_size_ptr: + * @is_kva: set for kernel data (kernel cryptio call) + * + * This function prepares only input DMA table for synhronic symmetric + * operations (HASH) + * Note that all bus addresses that are passed to the SEP + * are in 32 bit format; the SEP is a 32 bit device + */ +static int sep_prepare_input_dma_table(struct sep_device *sep, + unsigned long app_virt_addr, + u32 data_size, + u32 block_size, + dma_addr_t *lli_table_ptr, + u32 *num_entries_ptr, + u32 *table_data_size_ptr, + bool is_kva, + void **dmatables_region, + struct sep_dma_context *dma_ctx +) +{ + int error = 0; + /* Pointer to the info entry of the table - the last entry */ + struct sep_lli_entry *info_entry_ptr; + /* Array of pointers to page */ + struct sep_lli_entry *lli_array_ptr; + /* Points to the first entry to be processed in the lli_in_array */ + u32 current_entry = 0; + /* Num entries in the virtual buffer */ + u32 sep_lli_entries = 0; + /* Lli table pointer */ + struct sep_lli_entry *in_lli_table_ptr; + /* The total data in one table */ + u32 table_data_size = 0; + /* Flag for last table */ + u32 last_table_flag = 0; + /* Number of entries in lli table */ + u32 num_entries_in_table = 0; + /* Next table address */ + void *lli_table_alloc_addr = NULL; + void *dma_lli_table_alloc_addr = NULL; + void *dma_in_lli_table_ptr = NULL; + + dev_dbg(&sep->pdev->dev, "[PID%d] prepare intput dma " + "tbl data size: (hex) %x\n", + current->pid, data_size); + + dev_dbg(&sep->pdev->dev, "[PID%d] block_size is (hex) %x\n", + current->pid, block_size); + + /* Initialize the pages pointers */ + dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_page_array = NULL; + dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_num_pages = 0; + + /* Set the kernel address for first table to be allocated */ + lli_table_alloc_addr = (void *)(sep->shared_addr + + SYNCHRONIC_DMA_TABLES_AREA_OFFSET_BYTES + + dma_ctx->num_lli_tables_created * sizeof(struct sep_lli_entry) * + SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP); + + if (data_size == 0) { + if (dmatables_region) { + error = sep_allocate_dmatables_region(sep, + dmatables_region, + dma_ctx, + 1); + if (error) + return error; + } + /* Special case - create meptu table - 2 entries, zero data */ + sep_prepare_empty_lli_table(sep, lli_table_ptr, + num_entries_ptr, table_data_size_ptr, + dmatables_region, dma_ctx); + goto update_dcb_counter; + } + + /* Check if the pages are in Kernel Virtual Address layout */ + if (is_kva == true) + error = sep_lock_kernel_pages(sep, app_virt_addr, + data_size, &lli_array_ptr, SEP_DRIVER_IN_FLAG, + dma_ctx); + else + /* + * Lock the pages of the user buffer + * and translate them to pages + */ + error = sep_lock_user_pages(sep, app_virt_addr, + data_size, &lli_array_ptr, SEP_DRIVER_IN_FLAG, + dma_ctx); + + if (error) + goto end_function; + + dev_dbg(&sep->pdev->dev, + "[PID%d] output sep_in_num_pages is (hex) %x\n", + current->pid, + dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_num_pages); + + current_entry = 0; + info_entry_ptr = NULL; + + sep_lli_entries = + dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_num_pages; + + dma_lli_table_alloc_addr = lli_table_alloc_addr; + if (dmatables_region) { + error = sep_allocate_dmatables_region(sep, + dmatables_region, + dma_ctx, + sep_lli_entries); + if (error) + return error; + lli_table_alloc_addr = *dmatables_region; + } + + /* Loop till all the entries in in array are processed */ + while (current_entry < sep_lli_entries) { + + /* Set the new input and output tables */ + in_lli_table_ptr = + (struct sep_lli_entry *)lli_table_alloc_addr; + dma_in_lli_table_ptr = + (struct sep_lli_entry *)dma_lli_table_alloc_addr; + + lli_table_alloc_addr += sizeof(struct sep_lli_entry) * + SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP; + dma_lli_table_alloc_addr += sizeof(struct sep_lli_entry) * + SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP; + + if (dma_lli_table_alloc_addr > + ((void *)sep->shared_addr + + SYNCHRONIC_DMA_TABLES_AREA_OFFSET_BYTES + + SYNCHRONIC_DMA_TABLES_AREA_SIZE_BYTES)) { + + error = -ENOMEM; + goto end_function_error; + + } + + /* Update the number of created tables */ + dma_ctx->num_lli_tables_created++; + + /* Calculate the maximum size of data for input table */ + table_data_size = sep_calculate_lli_table_max_size(sep, + &lli_array_ptr[current_entry], + (sep_lli_entries - current_entry), + &last_table_flag); + + /* + * If this is not the last table - + * then allign it to the block size + */ + if (!last_table_flag) + table_data_size = + (table_data_size / block_size) * block_size; + + dev_dbg(&sep->pdev->dev, + "[PID%d] output table_data_size is (hex) %x\n", + current->pid, + table_data_size); + + /* Construct input lli table */ + sep_build_lli_table(sep, &lli_array_ptr[current_entry], + in_lli_table_ptr, + ¤t_entry, &num_entries_in_table, table_data_size); + + if (info_entry_ptr == NULL) { + + /* Set the output parameters to physical addresses */ + *lli_table_ptr = sep_shared_area_virt_to_bus(sep, + dma_in_lli_table_ptr); + *num_entries_ptr = num_entries_in_table; + *table_data_size_ptr = table_data_size; + + dev_dbg(&sep->pdev->dev, + "[PID%d] output lli_table_in_ptr is %08lx\n", + current->pid, + (unsigned long)*lli_table_ptr); + + } else { + /* Update the info entry of the previous in table */ + info_entry_ptr->bus_address = + sep_shared_area_virt_to_bus(sep, + dma_in_lli_table_ptr); + info_entry_ptr->block_size = + ((num_entries_in_table) << 24) | + (table_data_size); + } + /* Save the pointer to the info entry of the current tables */ + info_entry_ptr = in_lli_table_ptr + num_entries_in_table - 1; + } + /* Print input tables */ + if (!dmatables_region) { + sep_debug_print_lli_tables(sep, (struct sep_lli_entry *) + sep_shared_area_bus_to_virt(sep, *lli_table_ptr), + *num_entries_ptr, *table_data_size_ptr); + } + + /* The array of the pages */ + kfree(lli_array_ptr); + +update_dcb_counter: + /* Update DCB counter */ + dma_ctx->nr_dcb_creat++; + goto end_function; + +end_function_error: + /* Free all the allocated resources */ + kfree(dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_map_array); + kfree(lli_array_ptr); + kfree(dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_page_array); + +end_function: + return error; + +} + +/** + * sep_construct_dma_tables_from_lli - prepare AES/DES mappings + * @sep: pointer to struct sep_device + * @lli_in_array: + * @sep_in_lli_entries: + * @lli_out_array: + * @sep_out_lli_entries + * @block_size + * @lli_table_in_ptr + * @lli_table_out_ptr + * @in_num_entries_ptr + * @out_num_entries_ptr + * @table_data_size_ptr + * + * This function creates the input and output DMA tables for + * symmetric operations (AES/DES) according to the block + * size from LLI arays + * Note that all bus addresses that are passed to the SEP + * are in 32 bit format; the SEP is a 32 bit device + */ +static int sep_construct_dma_tables_from_lli( + struct sep_device *sep, + struct sep_lli_entry *lli_in_array, + u32 sep_in_lli_entries, + struct sep_lli_entry *lli_out_array, + u32 sep_out_lli_entries, + u32 block_size, + dma_addr_t *lli_table_in_ptr, + dma_addr_t *lli_table_out_ptr, + u32 *in_num_entries_ptr, + u32 *out_num_entries_ptr, + u32 *table_data_size_ptr, + void **dmatables_region, + struct sep_dma_context *dma_ctx) +{ + /* Points to the area where next lli table can be allocated */ + void *lli_table_alloc_addr = NULL; + /* + * Points to the area in shared region where next lli table + * can be allocated + */ + void *dma_lli_table_alloc_addr = NULL; + /* Input lli table in dmatables_region or shared region */ + struct sep_lli_entry *in_lli_table_ptr = NULL; + /* Input lli table location in the shared region */ + struct sep_lli_entry *dma_in_lli_table_ptr = NULL; + /* Output lli table in dmatables_region or shared region */ + struct sep_lli_entry *out_lli_table_ptr = NULL; + /* Output lli table location in the shared region */ + struct sep_lli_entry *dma_out_lli_table_ptr = NULL; + /* Pointer to the info entry of the table - the last entry */ + struct sep_lli_entry *info_in_entry_ptr = NULL; + /* Pointer to the info entry of the table - the last entry */ + struct sep_lli_entry *info_out_entry_ptr = NULL; + /* Points to the first entry to be processed in the lli_in_array */ + u32 current_in_entry = 0; + /* Points to the first entry to be processed in the lli_out_array */ + u32 current_out_entry = 0; + /* Max size of the input table */ + u32 in_table_data_size = 0; + /* Max size of the output table */ + u32 out_table_data_size = 0; + /* Flag te signifies if this is the last tables build */ + u32 last_table_flag = 0; + /* The data size that should be in table */ + u32 table_data_size = 0; + /* Number of etnries in the input table */ + u32 num_entries_in_table = 0; + /* Number of etnries in the output table */ + u32 num_entries_out_table = 0; + + if (!dma_ctx) { + dev_warn(&sep->pdev->dev, "DMA context uninitialized\n"); + return -EINVAL; + } + + /* Initiate to point after the message area */ + lli_table_alloc_addr = (void *)(sep->shared_addr + + SYNCHRONIC_DMA_TABLES_AREA_OFFSET_BYTES + + (dma_ctx->num_lli_tables_created * + (sizeof(struct sep_lli_entry) * + SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP))); + dma_lli_table_alloc_addr = lli_table_alloc_addr; + + if (dmatables_region) { + /* 2 for both in+out table */ + if (sep_allocate_dmatables_region(sep, + dmatables_region, + dma_ctx, + 2*sep_in_lli_entries)) + return -ENOMEM; + lli_table_alloc_addr = *dmatables_region; + } + + /* Loop till all the entries in in array are not processed */ + while (current_in_entry < sep_in_lli_entries) { + /* Set the new input and output tables */ + in_lli_table_ptr = + (struct sep_lli_entry *)lli_table_alloc_addr; + dma_in_lli_table_ptr = + (struct sep_lli_entry *)dma_lli_table_alloc_addr; + + lli_table_alloc_addr += sizeof(struct sep_lli_entry) * + SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP; + dma_lli_table_alloc_addr += sizeof(struct sep_lli_entry) * + SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP; + + /* Set the first output tables */ + out_lli_table_ptr = + (struct sep_lli_entry *)lli_table_alloc_addr; + dma_out_lli_table_ptr = + (struct sep_lli_entry *)dma_lli_table_alloc_addr; + + /* Check if the DMA table area limit was overrun */ + if ((dma_lli_table_alloc_addr + sizeof(struct sep_lli_entry) * + SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP) > + ((void *)sep->shared_addr + + SYNCHRONIC_DMA_TABLES_AREA_OFFSET_BYTES + + SYNCHRONIC_DMA_TABLES_AREA_SIZE_BYTES)) { + + dev_warn(&sep->pdev->dev, "dma table limit overrun\n"); + return -ENOMEM; + } + + /* Update the number of the lli tables created */ + dma_ctx->num_lli_tables_created += 2; + + lli_table_alloc_addr += sizeof(struct sep_lli_entry) * + SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP; + dma_lli_table_alloc_addr += sizeof(struct sep_lli_entry) * + SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP; + + /* Calculate the maximum size of data for input table */ + in_table_data_size = + sep_calculate_lli_table_max_size(sep, + &lli_in_array[current_in_entry], + (sep_in_lli_entries - current_in_entry), + &last_table_flag); + + /* Calculate the maximum size of data for output table */ + out_table_data_size = + sep_calculate_lli_table_max_size(sep, + &lli_out_array[current_out_entry], + (sep_out_lli_entries - current_out_entry), + &last_table_flag); + + if (!last_table_flag) { + in_table_data_size = (in_table_data_size / + block_size) * block_size; + out_table_data_size = (out_table_data_size / + block_size) * block_size; + } + + table_data_size = in_table_data_size; + if (table_data_size > out_table_data_size) + table_data_size = out_table_data_size; + + dev_dbg(&sep->pdev->dev, + "[PID%d] construct tables from lli" + " in_table_data_size is (hex) %x\n", current->pid, + in_table_data_size); + + dev_dbg(&sep->pdev->dev, + "[PID%d] construct tables from lli" + "out_table_data_size is (hex) %x\n", current->pid, + out_table_data_size); + + /* Construct input lli table */ + sep_build_lli_table(sep, &lli_in_array[current_in_entry], + in_lli_table_ptr, + ¤t_in_entry, + &num_entries_in_table, + table_data_size); + + /* Construct output lli table */ + sep_build_lli_table(sep, &lli_out_array[current_out_entry], + out_lli_table_ptr, + ¤t_out_entry, + &num_entries_out_table, + table_data_size); + + /* If info entry is null - this is the first table built */ + if (info_in_entry_ptr == NULL) { + /* Set the output parameters to physical addresses */ + *lli_table_in_ptr = + sep_shared_area_virt_to_bus(sep, dma_in_lli_table_ptr); + + *in_num_entries_ptr = num_entries_in_table; + + *lli_table_out_ptr = + sep_shared_area_virt_to_bus(sep, + dma_out_lli_table_ptr); + + *out_num_entries_ptr = num_entries_out_table; + *table_data_size_ptr = table_data_size; + + dev_dbg(&sep->pdev->dev, + "[PID%d] output lli_table_in_ptr is %08lx\n", + current->pid, + (unsigned long)*lli_table_in_ptr); + dev_dbg(&sep->pdev->dev, + "[PID%d] output lli_table_out_ptr is %08lx\n", + current->pid, + (unsigned long)*lli_table_out_ptr); + } else { + /* Update the info entry of the previous in table */ + info_in_entry_ptr->bus_address = + sep_shared_area_virt_to_bus(sep, + dma_in_lli_table_ptr); + + info_in_entry_ptr->block_size = + ((num_entries_in_table) << 24) | + (table_data_size); + + /* Update the info entry of the previous in table */ + info_out_entry_ptr->bus_address = + sep_shared_area_virt_to_bus(sep, + dma_out_lli_table_ptr); + + info_out_entry_ptr->block_size = + ((num_entries_out_table) << 24) | + (table_data_size); + + dev_dbg(&sep->pdev->dev, + "[PID%d] output lli_table_in_ptr:%08lx %08x\n", + current->pid, + (unsigned long)info_in_entry_ptr->bus_address, + info_in_entry_ptr->block_size); + + dev_dbg(&sep->pdev->dev, + "[PID%d] output lli_table_out_ptr:" + "%08lx %08x\n", + current->pid, + (unsigned long)info_out_entry_ptr->bus_address, + info_out_entry_ptr->block_size); + } + + /* Save the pointer to the info entry of the current tables */ + info_in_entry_ptr = in_lli_table_ptr + + num_entries_in_table - 1; + info_out_entry_ptr = out_lli_table_ptr + + num_entries_out_table - 1; + + dev_dbg(&sep->pdev->dev, + "[PID%d] output num_entries_out_table is %x\n", + current->pid, + (u32)num_entries_out_table); + dev_dbg(&sep->pdev->dev, + "[PID%d] output info_in_entry_ptr is %lx\n", + current->pid, + (unsigned long)info_in_entry_ptr); + dev_dbg(&sep->pdev->dev, + "[PID%d] output info_out_entry_ptr is %lx\n", + current->pid, + (unsigned long)info_out_entry_ptr); + } + + /* Print input tables */ + if (!dmatables_region) { + sep_debug_print_lli_tables( + sep, + (struct sep_lli_entry *) + sep_shared_area_bus_to_virt(sep, *lli_table_in_ptr), + *in_num_entries_ptr, + *table_data_size_ptr); + } + + /* Print output tables */ + if (!dmatables_region) { + sep_debug_print_lli_tables( + sep, + (struct sep_lli_entry *) + sep_shared_area_bus_to_virt(sep, *lli_table_out_ptr), + *out_num_entries_ptr, + *table_data_size_ptr); + } + + return 0; +} + +/** + * sep_prepare_input_output_dma_table - prepare DMA I/O table + * @app_virt_in_addr: + * @app_virt_out_addr: + * @data_size: + * @block_size: + * @lli_table_in_ptr: + * @lli_table_out_ptr: + * @in_num_entries_ptr: + * @out_num_entries_ptr: + * @table_data_size_ptr: + * @is_kva: set for kernel data; used only for kernel crypto module + * + * This function builds input and output DMA tables for synhronic + * symmetric operations (AES, DES, HASH). It also checks that each table + * is of the modular block size + * Note that all bus addresses that are passed to the SEP + * are in 32 bit format; the SEP is a 32 bit device + */ +static int sep_prepare_input_output_dma_table(struct sep_device *sep, + unsigned long app_virt_in_addr, + unsigned long app_virt_out_addr, + u32 data_size, + u32 block_size, + dma_addr_t *lli_table_in_ptr, + dma_addr_t *lli_table_out_ptr, + u32 *in_num_entries_ptr, + u32 *out_num_entries_ptr, + u32 *table_data_size_ptr, + bool is_kva, + void **dmatables_region, + struct sep_dma_context *dma_ctx) + +{ + int error = 0; + /* Array of pointers of page */ + struct sep_lli_entry *lli_in_array; + /* Array of pointers of page */ + struct sep_lli_entry *lli_out_array; + + if (!dma_ctx) { + error = -EINVAL; + goto end_function; + } + + if (data_size == 0) { + /* Prepare empty table for input and output */ + if (dmatables_region) { + error = sep_allocate_dmatables_region( + sep, + dmatables_region, + dma_ctx, + 2); + if (error) + goto end_function; + } + sep_prepare_empty_lli_table(sep, lli_table_in_ptr, + in_num_entries_ptr, table_data_size_ptr, + dmatables_region, dma_ctx); + + sep_prepare_empty_lli_table(sep, lli_table_out_ptr, + out_num_entries_ptr, table_data_size_ptr, + dmatables_region, dma_ctx); + + goto update_dcb_counter; + } + + /* Initialize the pages pointers */ + dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_page_array = NULL; + dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].out_page_array = NULL; + + /* Lock the pages of the buffer and translate them to pages */ + if (is_kva == true) { + dev_dbg(&sep->pdev->dev, "[PID%d] Locking kernel input pages\n", + current->pid); + error = sep_lock_kernel_pages(sep, app_virt_in_addr, + data_size, &lli_in_array, SEP_DRIVER_IN_FLAG, + dma_ctx); + if (error) { + dev_warn(&sep->pdev->dev, + "[PID%d] sep_lock_kernel_pages for input " + "virtual buffer failed\n", current->pid); + + goto end_function; + } + + dev_dbg(&sep->pdev->dev, "[PID%d] Locking kernel output pages\n", + current->pid); + error = sep_lock_kernel_pages(sep, app_virt_out_addr, + data_size, &lli_out_array, SEP_DRIVER_OUT_FLAG, + dma_ctx); + + if (error) { + dev_warn(&sep->pdev->dev, + "[PID%d] sep_lock_kernel_pages for output " + "virtual buffer failed\n", current->pid); + + goto end_function_free_lli_in; + } + + } + + else { + dev_dbg(&sep->pdev->dev, "[PID%d] Locking user input pages\n", + current->pid); + error = sep_lock_user_pages(sep, app_virt_in_addr, + data_size, &lli_in_array, SEP_DRIVER_IN_FLAG, + dma_ctx); + if (error) { + dev_warn(&sep->pdev->dev, + "[PID%d] sep_lock_user_pages for input " + "virtual buffer failed\n", current->pid); + + goto end_function; + } + + dev_dbg(&sep->pdev->dev, "[PID%d] Locking user output pages\n", + current->pid); + + error = sep_lock_user_pages(sep, app_virt_out_addr, + data_size, &lli_out_array, SEP_DRIVER_OUT_FLAG, + dma_ctx); + + if (error) { + dev_warn(&sep->pdev->dev, + "[PID%d] sep_lock_user_pages" + " for output virtual buffer failed\n", + current->pid); + + goto end_function_free_lli_in; + } + } + + dev_dbg(&sep->pdev->dev, "[PID%d] After lock; prep input output dma " + "table sep_in_num_pages is (hex) %x\n", current->pid, + dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_num_pages); + + dev_dbg(&sep->pdev->dev, "[PID%d] sep_out_num_pages is (hex) %x\n", + current->pid, + dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].out_num_pages); + + dev_dbg(&sep->pdev->dev, "[PID%d] SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP" + " is (hex) %x\n", current->pid, + SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP); + + /* Call the fucntion that creates table from the lli arrays */ + dev_dbg(&sep->pdev->dev, "[PID%d] calling create table from lli\n", + current->pid); + error = sep_construct_dma_tables_from_lli( + sep, lli_in_array, + dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat]. + in_num_pages, + lli_out_array, + dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat]. + out_num_pages, + block_size, lli_table_in_ptr, lli_table_out_ptr, + in_num_entries_ptr, out_num_entries_ptr, + table_data_size_ptr, dmatables_region, dma_ctx); + + if (error) { + dev_warn(&sep->pdev->dev, + "[PID%d] sep_construct_dma_tables_from_lli failed\n", + current->pid); + goto end_function_with_error; + } + + kfree(lli_out_array); + kfree(lli_in_array); + +update_dcb_counter: + /* Update DCB counter */ + dma_ctx->nr_dcb_creat++; + + goto end_function; + +end_function_with_error: + kfree(dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].out_map_array); + kfree(dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].out_page_array); + kfree(lli_out_array); + + +end_function_free_lli_in: + kfree(dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_map_array); + kfree(dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_page_array); + kfree(lli_in_array); + +end_function: + + return error; + +} + +/** + * sep_prepare_input_output_dma_table_in_dcb - prepare control blocks + * @app_in_address: unsigned long; for data buffer in (user space) + * @app_out_address: unsigned long; for data buffer out (user space) + * @data_in_size: u32; for size of data + * @block_size: u32; for block size + * @tail_block_size: u32; for size of tail block + * @isapplet: bool; to indicate external app + * @is_kva: bool; kernel buffer; only used for kernel crypto module + * + * This function prepares the linked DMA tables and puts the + * address for the linked list of tables inta a DCB (data control + * block) the address of which is known by the SEP hardware + * Note that all bus addresses that are passed to the SEP + * are in 32 bit format; the SEP is a 32 bit device + */ +int sep_prepare_input_output_dma_table_in_dcb(struct sep_device *sep, + unsigned long app_in_address, + unsigned long app_out_address, + u32 data_in_size, + u32 block_size, + u32 tail_block_size, + bool isapplet, + bool is_kva, + struct sep_dcblock *dcb_region, + void **dmatables_region, + struct sep_dma_context **dma_ctx, + struct scatterlist *src_sg, + struct scatterlist *dst_sg) +{ + int error = 0; + /* Size of tail */ + u32 tail_size = 0; + /* Address of the created DCB table */ + struct sep_dcblock *dcb_table_ptr = NULL; + /* The physical address of the first input DMA table */ + dma_addr_t in_first_mlli_address = 0; + /* Number of entries in the first input DMA table */ + u32 in_first_num_entries = 0; + /* The physical address of the first output DMA table */ + dma_addr_t out_first_mlli_address = 0; + /* Number of entries in the first output DMA table */ + u32 out_first_num_entries = 0; + /* Data in the first input/output table */ + u32 first_data_size = 0; + + dev_dbg(&sep->pdev->dev, "[PID%d] app_in_address %lx\n", + current->pid, app_in_address); + + dev_dbg(&sep->pdev->dev, "[PID%d] app_out_address %lx\n", + current->pid, app_out_address); + + dev_dbg(&sep->pdev->dev, "[PID%d] data_in_size %x\n", + current->pid, data_in_size); + + dev_dbg(&sep->pdev->dev, "[PID%d] block_size %x\n", + current->pid, block_size); + + dev_dbg(&sep->pdev->dev, "[PID%d] tail_block_size %x\n", + current->pid, tail_block_size); + + dev_dbg(&sep->pdev->dev, "[PID%d] isapplet %x\n", + current->pid, isapplet); + + dev_dbg(&sep->pdev->dev, "[PID%d] is_kva %x\n", + current->pid, is_kva); + + dev_dbg(&sep->pdev->dev, "[PID%d] src_sg %p\n", + current->pid, src_sg); + + dev_dbg(&sep->pdev->dev, "[PID%d] dst_sg %p\n", + current->pid, dst_sg); + + if (!dma_ctx) { + dev_warn(&sep->pdev->dev, "[PID%d] no DMA context pointer\n", + current->pid); + error = -EINVAL; + goto end_function; + } + + if (*dma_ctx) { + /* In case there are multiple DCBs for this transaction */ + dev_dbg(&sep->pdev->dev, "[PID%d] DMA context already set\n", + current->pid); + } else { + *dma_ctx = kzalloc(sizeof(**dma_ctx), GFP_KERNEL); + if (!(*dma_ctx)) { + dev_dbg(&sep->pdev->dev, + "[PID%d] Not enough memory for DMA context\n", + current->pid); + error = -ENOMEM; + goto end_function; + } + dev_dbg(&sep->pdev->dev, + "[PID%d] Created DMA context addr at 0x%p\n", + current->pid, *dma_ctx); + } + + /* these are for kernel crypto only */ + (*dma_ctx)->src_sg = src_sg; + (*dma_ctx)->dst_sg = dst_sg; + + if ((*dma_ctx)->nr_dcb_creat == SEP_MAX_NUM_SYNC_DMA_OPS) { + /* No more DCBs to allocate */ + dev_dbg(&sep->pdev->dev, "[PID%d] no more DCBs available\n", + current->pid); + error = -ENOSPC; + goto end_function_error; + } + + /* Allocate new DCB */ + if (dcb_region) { + dcb_table_ptr = dcb_region; + } else { + dcb_table_ptr = (struct sep_dcblock *)(sep->shared_addr + + SEP_DRIVER_SYSTEM_DCB_MEMORY_OFFSET_IN_BYTES + + ((*dma_ctx)->nr_dcb_creat * + sizeof(struct sep_dcblock))); + } + + /* Set the default values in the DCB */ + dcb_table_ptr->input_mlli_address = 0; + dcb_table_ptr->input_mlli_num_entries = 0; + dcb_table_ptr->input_mlli_data_size = 0; + dcb_table_ptr->output_mlli_address = 0; + dcb_table_ptr->output_mlli_num_entries = 0; + dcb_table_ptr->output_mlli_data_size = 0; + dcb_table_ptr->tail_data_size = 0; + dcb_table_ptr->out_vr_tail_pt = 0; + + if (isapplet == true) { + + /* Check if there is enough data for DMA operation */ + if (data_in_size < SEP_DRIVER_MIN_DATA_SIZE_PER_TABLE) { + if (is_kva == true) { + error = -ENODEV; + goto end_function_error; + } else { + if (copy_from_user(dcb_table_ptr->tail_data, + (void __user *)app_in_address, + data_in_size)) { + error = -EFAULT; + goto end_function_error; + } + } + + dcb_table_ptr->tail_data_size = data_in_size; + + /* Set the output user-space address for mem2mem op */ + if (app_out_address) + dcb_table_ptr->out_vr_tail_pt = + (aligned_u64)app_out_address; + + /* + * Update both data length parameters in order to avoid + * second data copy and allow building of empty mlli + * tables + */ + tail_size = 0x0; + data_in_size = 0x0; + + } else { + if (!app_out_address) { + tail_size = data_in_size % block_size; + if (!tail_size) { + if (tail_block_size == block_size) + tail_size = block_size; + } + } else { + tail_size = 0; + } + } + if (tail_size) { + if (tail_size > sizeof(dcb_table_ptr->tail_data)) + return -EINVAL; + if (is_kva == true) { + error = -ENODEV; + goto end_function_error; + } else { + /* We have tail data - copy it to DCB */ + if (copy_from_user(dcb_table_ptr->tail_data, + (void __user *)(app_in_address + + data_in_size - tail_size), tail_size)) { + error = -EFAULT; + goto end_function_error; + } + } + if (app_out_address) + /* + * Calculate the output address + * according to tail data size + */ + dcb_table_ptr->out_vr_tail_pt = + (aligned_u64)app_out_address + + data_in_size - tail_size; + + /* Save the real tail data size */ + dcb_table_ptr->tail_data_size = tail_size; + /* + * Update the data size without the tail + * data size AKA data for the dma + */ + data_in_size = (data_in_size - tail_size); + } + } + /* Check if we need to build only input table or input/output */ + if (app_out_address) { + /* Prepare input/output tables */ + error = sep_prepare_input_output_dma_table(sep, + app_in_address, + app_out_address, + data_in_size, + block_size, + &in_first_mlli_address, + &out_first_mlli_address, + &in_first_num_entries, + &out_first_num_entries, + &first_data_size, + is_kva, + dmatables_region, + *dma_ctx); + } else { + /* Prepare input tables */ + error = sep_prepare_input_dma_table(sep, + app_in_address, + data_in_size, + block_size, + &in_first_mlli_address, + &in_first_num_entries, + &first_data_size, + is_kva, + dmatables_region, + *dma_ctx); + } + + if (error) { + dev_warn(&sep->pdev->dev, + "prepare DMA table call failed " + "from prepare DCB call\n"); + goto end_function_error; + } + + /* Set the DCB values */ + dcb_table_ptr->input_mlli_address = in_first_mlli_address; + dcb_table_ptr->input_mlli_num_entries = in_first_num_entries; + dcb_table_ptr->input_mlli_data_size = first_data_size; + dcb_table_ptr->output_mlli_address = out_first_mlli_address; + dcb_table_ptr->output_mlli_num_entries = out_first_num_entries; + dcb_table_ptr->output_mlli_data_size = first_data_size; + + goto end_function; + +end_function_error: + kfree(*dma_ctx); + +end_function: + return error; + +} + + +/** + * sep_free_dma_tables_and_dcb - free DMA tables and DCBs + * @sep: pointer to struct sep_device + * @isapplet: indicates external application (used for kernel access) + * @is_kva: indicates kernel addresses (only used for kernel crypto) + * + * This function frees the DMA tables and DCB + */ +static int sep_free_dma_tables_and_dcb(struct sep_device *sep, bool isapplet, + bool is_kva, struct sep_dma_context **dma_ctx) +{ + struct sep_dcblock *dcb_table_ptr; + unsigned long pt_hold; + void *tail_pt; + + int i = 0; + int error = 0; + int error_temp = 0; + + dev_dbg(&sep->pdev->dev, "[PID%d] sep_free_dma_tables_and_dcb\n", + current->pid); + + if (isapplet == true) { + /* Set pointer to first DCB table */ + dcb_table_ptr = (struct sep_dcblock *) + (sep->shared_addr + + SEP_DRIVER_SYSTEM_DCB_MEMORY_OFFSET_IN_BYTES); + + /* Go over each DCB and see if tail pointer must be updated */ + for (i = 0; + i < (*dma_ctx)->nr_dcb_creat; i++, dcb_table_ptr++) { + if (dcb_table_ptr->out_vr_tail_pt) { + pt_hold = (unsigned long)dcb_table_ptr-> + out_vr_tail_pt; + tail_pt = (void *)pt_hold; + if (is_kva == true) { + error = -ENODEV; + break; + } else { + error_temp = copy_to_user( + (void __user *)tail_pt, + dcb_table_ptr->tail_data, + dcb_table_ptr->tail_data_size); + } + if (error_temp) { + /* Release the DMA resource */ + error = -EFAULT; + break; + } + } + } + } + /* Free the output pages, if any */ + sep_free_dma_table_data_handler(sep, dma_ctx); + + dev_dbg(&sep->pdev->dev, "[PID%d] sep_free_dma_tables_and_dcb end\n", + current->pid); + + return error; +} + +/** + * sep_prepare_dcb_handler - prepare a control block + * @sep: pointer to struct sep_device + * @arg: pointer to user parameters + * + * This function will retrieve the RAR buffer physical addresses, type + * & size corresponding to the RAR handles provided in the buffers vector. + */ +static int sep_prepare_dcb_handler(struct sep_device *sep, unsigned long arg, + struct sep_dma_context **dma_ctx) +{ + int error; + /* Command arguments */ + static struct build_dcb_struct command_args; + + /* Get the command arguments */ + if (copy_from_user(&command_args, (void __user *)arg, + sizeof(struct build_dcb_struct))) { + error = -EFAULT; + goto end_function; + } + + dev_dbg(&sep->pdev->dev, + "[PID%d] prep dcb handler app_in_address is %08llx\n", + current->pid, command_args.app_in_address); + dev_dbg(&sep->pdev->dev, + "[PID%d] app_out_address is %08llx\n", + current->pid, command_args.app_out_address); + dev_dbg(&sep->pdev->dev, + "[PID%d] data_size is %x\n", + current->pid, command_args.data_in_size); + dev_dbg(&sep->pdev->dev, + "[PID%d] block_size is %x\n", + current->pid, command_args.block_size); + dev_dbg(&sep->pdev->dev, + "[PID%d] tail block_size is %x\n", + current->pid, command_args.tail_block_size); + dev_dbg(&sep->pdev->dev, + "[PID%d] is_applet is %x\n", + current->pid, command_args.is_applet); + + if (!command_args.app_in_address) { + dev_warn(&sep->pdev->dev, + "[PID%d] null app_in_address\n", current->pid); + error = -EINVAL; + goto end_function; + } + + error = sep_prepare_input_output_dma_table_in_dcb(sep, + (unsigned long)command_args.app_in_address, + (unsigned long)command_args.app_out_address, + command_args.data_in_size, command_args.block_size, + command_args.tail_block_size, + command_args.is_applet, false, + NULL, NULL, dma_ctx, NULL, NULL); + +end_function: + return error; + +} + +/** + * sep_free_dcb_handler - free control block resources + * @sep: pointer to struct sep_device + * + * This function frees the DCB resources and updates the needed + * user-space buffers. + */ +static int sep_free_dcb_handler(struct sep_device *sep, + struct sep_dma_context **dma_ctx) +{ + int error = 0; + + if (!dma_ctx || !(*dma_ctx)) { + dev_dbg(&sep->pdev->dev, "[PID%d] no dma context defined, nothing to free\n", + current->pid); + return error; + } + + dev_dbg(&sep->pdev->dev, "[PID%d] free dcbs num of DCBs %x\n", + current->pid, + (*dma_ctx)->nr_dcb_creat); + + error = sep_free_dma_tables_and_dcb(sep, false, false, dma_ctx); + + return error; +} + +/** + * sep_ioctl - ioctl handler for sep device + * @filp: pointer to struct file + * @cmd: command + * @arg: pointer to argument structure + * + * Implement the ioctl methods availble on the SEP device. + */ +static long sep_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + struct sep_private_data * const private_data = filp->private_data; + struct sep_call_status *call_status = &private_data->call_status; + struct sep_device *sep = private_data->device; + struct sep_dma_context **dma_ctx = &private_data->dma_ctx; + struct sep_queue_info **my_queue_elem = &private_data->my_queue_elem; + int error = 0; + + dev_dbg(&sep->pdev->dev, "[PID%d] ioctl cmd 0x%x\n", + current->pid, cmd); + dev_dbg(&sep->pdev->dev, "[PID%d] dma context addr 0x%p\n", + current->pid, *dma_ctx); + + /* Make sure we own this device */ + error = sep_check_transaction_owner(sep); + if (error) { + dev_dbg(&sep->pdev->dev, "[PID%d] ioctl pid is not owner\n", + current->pid); + goto end_function; + } + + /* Check that sep_mmap has been called before */ + if (0 == test_bit(SEP_LEGACY_MMAP_DONE_OFFSET, + &call_status->status)) { + dev_dbg(&sep->pdev->dev, + "[PID%d] mmap not called\n", current->pid); + error = -EPROTO; + goto end_function; + } + + /* Check that the command is for SEP device */ + if (_IOC_TYPE(cmd) != SEP_IOC_MAGIC_NUMBER) { + error = -ENOTTY; + goto end_function; + } + + switch (cmd) { + case SEP_IOCSENDSEPCOMMAND: + if (1 == test_bit(SEP_LEGACY_SENDMSG_DONE_OFFSET, + &call_status->status)) { + dev_dbg(&sep->pdev->dev, "[PID%d] send msg already done\n", + current->pid); + error = -EPROTO; + goto end_function; + } + /* Send command to SEP */ + error = sep_send_command_handler(sep); + if (!error) + set_bit(SEP_LEGACY_SENDMSG_DONE_OFFSET, + &call_status->status); + dev_dbg(&sep->pdev->dev, "[PID%d] SEP_IOCSENDSEPCOMMAND end\n", + current->pid); + break; + case SEP_IOCENDTRANSACTION: + error = sep_end_transaction_handler(sep, dma_ctx, call_status, + my_queue_elem); + dev_dbg(&sep->pdev->dev, "[PID%d] SEP_IOCENDTRANSACTION end\n", + current->pid); + break; + case SEP_IOCPREPAREDCB: + if (1 == test_bit(SEP_LEGACY_SENDMSG_DONE_OFFSET, + &call_status->status)) { + dev_dbg(&sep->pdev->dev, + "[PID%d] dcb preparation needed before send msg\n", + current->pid); + error = -EPROTO; + goto end_function; + } + + if (!arg) { + dev_dbg(&sep->pdev->dev, + "[PID%d] dcb prep null arg\n", current->pid); + error = -EINVAL; + goto end_function; + } + + error = sep_prepare_dcb_handler(sep, arg, dma_ctx); + dev_dbg(&sep->pdev->dev, "[PID%d] SEP_IOCPREPAREDCB end\n", + current->pid); + break; + case SEP_IOCFREEDCB: + error = sep_free_dcb_handler(sep, dma_ctx); + dev_dbg(&sep->pdev->dev, "[PID%d] SEP_IOCFREEDCB end\n", + current->pid); + break; + default: + error = -ENOTTY; + dev_dbg(&sep->pdev->dev, "[PID%d] default end\n", + current->pid); + break; + } + +end_function: + dev_dbg(&sep->pdev->dev, "[PID%d] ioctl end\n", current->pid); + + return error; +} + +/** + * sep_inthandler - interrupt handler for sep device + * @irq: interrupt + * @dev_id: device id + */ +static irqreturn_t sep_inthandler(int irq, void *dev_id) +{ + unsigned long lock_irq_flag; + u32 reg_val, reg_val2 = 0; + struct sep_device *sep = dev_id; + irqreturn_t int_error = IRQ_HANDLED; + + /* Are we in power save? */ +#if defined(CONFIG_PM_RUNTIME) && defined(SEP_ENABLE_RUNTIME_PM) + if (sep->pdev->dev.power.runtime_status != RPM_ACTIVE) { + dev_dbg(&sep->pdev->dev, "interrupt during pwr save\n"); + return IRQ_NONE; + } +#endif + + if (test_bit(SEP_WORKING_LOCK_BIT, &sep->in_use_flags) == 0) { + dev_dbg(&sep->pdev->dev, "interrupt while nobody using sep\n"); + return IRQ_NONE; + } + + /* Read the IRR register to check if this is SEP interrupt */ + reg_val = sep_read_reg(sep, HW_HOST_IRR_REG_ADDR); + + dev_dbg(&sep->pdev->dev, "sep int: IRR REG val: %x\n", reg_val); + + if (reg_val & (0x1 << 13)) { + + /* Lock and update the counter of reply messages */ + spin_lock_irqsave(&sep->snd_rply_lck, lock_irq_flag); + sep->reply_ct++; + spin_unlock_irqrestore(&sep->snd_rply_lck, lock_irq_flag); + + dev_dbg(&sep->pdev->dev, "sep int: send_ct %lx reply_ct %lx\n", + sep->send_ct, sep->reply_ct); + + /* Is this a kernel client request */ + if (sep->in_kernel) { + tasklet_schedule(&sep->finish_tasklet); + goto finished_interrupt; + } + + /* Is this printf or daemon request? */ + reg_val2 = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR2_REG_ADDR); + dev_dbg(&sep->pdev->dev, + "SEP Interrupt - GPR2 is %08x\n", reg_val2); + + clear_bit(SEP_WORKING_LOCK_BIT, &sep->in_use_flags); + + if ((reg_val2 >> 30) & 0x1) { + dev_dbg(&sep->pdev->dev, "int: printf request\n"); + } else if (reg_val2 >> 31) { + dev_dbg(&sep->pdev->dev, "int: daemon request\n"); + } else { + dev_dbg(&sep->pdev->dev, "int: SEP reply\n"); + wake_up(&sep->event_interrupt); + } + } else { + dev_dbg(&sep->pdev->dev, "int: not SEP interrupt\n"); + int_error = IRQ_NONE; + } + +finished_interrupt: + + if (int_error == IRQ_HANDLED) + sep_write_reg(sep, HW_HOST_ICR_REG_ADDR, reg_val); + + return int_error; +} + +/** + * sep_reconfig_shared_area - reconfigure shared area + * @sep: pointer to struct sep_device + * + * Reconfig the shared area between HOST and SEP - needed in case + * the DX_CC_Init function was called before OS loading. + */ +static int sep_reconfig_shared_area(struct sep_device *sep) +{ + int ret_val; + + /* use to limit waiting for SEP */ + unsigned long end_time; + + /* Send the new SHARED MESSAGE AREA to the SEP */ + dev_dbg(&sep->pdev->dev, "reconfig shared; sending %08llx to sep\n", + (unsigned long long)sep->shared_bus); + + sep_write_reg(sep, HW_HOST_HOST_SEP_GPR1_REG_ADDR, sep->shared_bus); + + /* Poll for SEP response */ + ret_val = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR1_REG_ADDR); + + end_time = jiffies + (WAIT_TIME * HZ); + + while ((time_before(jiffies, end_time)) && (ret_val != 0xffffffff) && + (ret_val != sep->shared_bus)) + ret_val = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR1_REG_ADDR); + + /* Check the return value (register) */ + if (ret_val != sep->shared_bus) { + dev_warn(&sep->pdev->dev, "could not reconfig shared area\n"); + dev_warn(&sep->pdev->dev, "result was %x\n", ret_val); + ret_val = -ENOMEM; + } else + ret_val = 0; + + dev_dbg(&sep->pdev->dev, "reconfig shared area end\n"); + + return ret_val; +} + +/** + * sep_activate_dcb_dmatables_context - Takes DCB & DMA tables + * contexts into use + * @sep: SEP device + * @dcb_region: DCB region copy + * @dmatables_region: MLLI/DMA tables copy + * @dma_ctx: DMA context for current transaction + */ +ssize_t sep_activate_dcb_dmatables_context(struct sep_device *sep, + struct sep_dcblock **dcb_region, + void **dmatables_region, + struct sep_dma_context *dma_ctx) +{ + void *dmaregion_free_start = NULL; + void *dmaregion_free_end = NULL; + void *dcbregion_free_start = NULL; + void *dcbregion_free_end = NULL; + ssize_t error = 0; + + dev_dbg(&sep->pdev->dev, "[PID%d] activating dcb/dma region\n", + current->pid); + + if (1 > dma_ctx->nr_dcb_creat) { + dev_warn(&sep->pdev->dev, + "[PID%d] invalid number of dcbs to activate 0x%08X\n", + current->pid, dma_ctx->nr_dcb_creat); + error = -EINVAL; + goto end_function; + } + + dmaregion_free_start = sep->shared_addr + + SYNCHRONIC_DMA_TABLES_AREA_OFFSET_BYTES; + dmaregion_free_end = dmaregion_free_start + + SYNCHRONIC_DMA_TABLES_AREA_SIZE_BYTES - 1; + + if (dmaregion_free_start + + dma_ctx->dmatables_len > dmaregion_free_end) { + error = -ENOMEM; + goto end_function; + } + memcpy(dmaregion_free_start, + *dmatables_region, + dma_ctx->dmatables_len); + /* Free MLLI table copy */ + kfree(*dmatables_region); + *dmatables_region = NULL; + + /* Copy thread's DCB table copy to DCB table region */ + dcbregion_free_start = sep->shared_addr + + SEP_DRIVER_SYSTEM_DCB_MEMORY_OFFSET_IN_BYTES; + dcbregion_free_end = dcbregion_free_start + + (SEP_MAX_NUM_SYNC_DMA_OPS * + sizeof(struct sep_dcblock)) - 1; + + if (dcbregion_free_start + + (dma_ctx->nr_dcb_creat * sizeof(struct sep_dcblock)) + > dcbregion_free_end) { + error = -ENOMEM; + goto end_function; + } + + memcpy(dcbregion_free_start, + *dcb_region, + dma_ctx->nr_dcb_creat * sizeof(struct sep_dcblock)); + + /* Print the tables */ + dev_dbg(&sep->pdev->dev, "activate: input table\n"); + sep_debug_print_lli_tables(sep, + (struct sep_lli_entry *)sep_shared_area_bus_to_virt(sep, + (*dcb_region)->input_mlli_address), + (*dcb_region)->input_mlli_num_entries, + (*dcb_region)->input_mlli_data_size); + + dev_dbg(&sep->pdev->dev, "activate: output table\n"); + sep_debug_print_lli_tables(sep, + (struct sep_lli_entry *)sep_shared_area_bus_to_virt(sep, + (*dcb_region)->output_mlli_address), + (*dcb_region)->output_mlli_num_entries, + (*dcb_region)->output_mlli_data_size); + + dev_dbg(&sep->pdev->dev, + "[PID%d] printing activated tables\n", current->pid); + +end_function: + kfree(*dmatables_region); + *dmatables_region = NULL; + + kfree(*dcb_region); + *dcb_region = NULL; + + return error; +} + +/** + * sep_create_dcb_dmatables_context - Creates DCB & MLLI/DMA table context + * @sep: SEP device + * @dcb_region: DCB region buf to create for current transaction + * @dmatables_region: MLLI/DMA tables buf to create for current transaction + * @dma_ctx: DMA context buf to create for current transaction + * @user_dcb_args: User arguments for DCB/MLLI creation + * @num_dcbs: Number of DCBs to create + */ +static ssize_t sep_create_dcb_dmatables_context(struct sep_device *sep, + struct sep_dcblock **dcb_region, + void **dmatables_region, + struct sep_dma_context **dma_ctx, + const struct build_dcb_struct __user *user_dcb_args, + const u32 num_dcbs) +{ + int error = 0; + int i = 0; + struct build_dcb_struct *dcb_args = NULL; + + dev_dbg(&sep->pdev->dev, "[PID%d] creating dcb/dma region\n", + current->pid); + + if (!dcb_region || !dma_ctx || !dmatables_region || !user_dcb_args) { + error = -EINVAL; + goto end_function; + } + + if (SEP_MAX_NUM_SYNC_DMA_OPS < num_dcbs) { + dev_warn(&sep->pdev->dev, + "[PID%d] invalid number of dcbs 0x%08X\n", + current->pid, num_dcbs); + error = -EINVAL; + goto end_function; + } + + dcb_args = kzalloc(num_dcbs * sizeof(struct build_dcb_struct), + GFP_KERNEL); + if (!dcb_args) { + dev_warn(&sep->pdev->dev, "[PID%d] no memory for dcb args\n", + current->pid); + error = -ENOMEM; + goto end_function; + } + + if (copy_from_user(dcb_args, + user_dcb_args, + num_dcbs * sizeof(struct build_dcb_struct))) { + error = -EINVAL; + goto end_function; + } + + /* Allocate thread-specific memory for DCB */ + *dcb_region = kzalloc(num_dcbs * sizeof(struct sep_dcblock), + GFP_KERNEL); + if (!(*dcb_region)) { + error = -ENOMEM; + goto end_function; + } + + /* Prepare DCB and MLLI table into the allocated regions */ + for (i = 0; i < num_dcbs; i++) { + error = sep_prepare_input_output_dma_table_in_dcb(sep, + (unsigned long)dcb_args[i].app_in_address, + (unsigned long)dcb_args[i].app_out_address, + dcb_args[i].data_in_size, + dcb_args[i].block_size, + dcb_args[i].tail_block_size, + dcb_args[i].is_applet, + false, + *dcb_region, dmatables_region, + dma_ctx, + NULL, + NULL); + if (error) { + dev_warn(&sep->pdev->dev, + "[PID%d] dma table creation failed\n", + current->pid); + goto end_function; + } + } + +end_function: + kfree(dcb_args); + return error; + +} + +/** + * sep_create_dcb_dmatables_context_kernel - Creates DCB & MLLI/DMA table context + * for kernel crypto + * @sep: SEP device + * @dcb_region: DCB region buf to create for current transaction + * @dmatables_region: MLLI/DMA tables buf to create for current transaction + * @dma_ctx: DMA context buf to create for current transaction + * @user_dcb_args: User arguments for DCB/MLLI creation + * @num_dcbs: Number of DCBs to create + * This does that same thing as sep_create_dcb_dmatables_context + * except that it is used only for the kernel crypto operation. It is + * separate because there is no user data involved; the dcb data structure + * is specific for kernel crypto (build_dcb_struct_kernel) + */ +int sep_create_dcb_dmatables_context_kernel(struct sep_device *sep, + struct sep_dcblock **dcb_region, + void **dmatables_region, + struct sep_dma_context **dma_ctx, + const struct build_dcb_struct_kernel *dcb_data, + const u32 num_dcbs) +{ + int error = 0; + int i = 0; + + dev_dbg(&sep->pdev->dev, "[PID%d] creating dcb/dma region\n", + current->pid); + + if (!dcb_region || !dma_ctx || !dmatables_region || !dcb_data) { + error = -EINVAL; + goto end_function; + } + + if (SEP_MAX_NUM_SYNC_DMA_OPS < num_dcbs) { + dev_warn(&sep->pdev->dev, + "[PID%d] invalid number of dcbs 0x%08X\n", + current->pid, num_dcbs); + error = -EINVAL; + goto end_function; + } + + dev_dbg(&sep->pdev->dev, "[PID%d] num_dcbs is %d\n", + current->pid, num_dcbs); + + /* Allocate thread-specific memory for DCB */ + *dcb_region = kzalloc(num_dcbs * sizeof(struct sep_dcblock), + GFP_KERNEL); + if (!(*dcb_region)) { + error = -ENOMEM; + goto end_function; + } + + /* Prepare DCB and MLLI table into the allocated regions */ + for (i = 0; i < num_dcbs; i++) { + error = sep_prepare_input_output_dma_table_in_dcb(sep, + (unsigned long)dcb_data->app_in_address, + (unsigned long)dcb_data->app_out_address, + dcb_data->data_in_size, + dcb_data->block_size, + dcb_data->tail_block_size, + dcb_data->is_applet, + true, + *dcb_region, dmatables_region, + dma_ctx, + dcb_data->src_sg, + dcb_data->dst_sg); + if (error) { + dev_warn(&sep->pdev->dev, + "[PID%d] dma table creation failed\n", + current->pid); + goto end_function; + } + } + +end_function: + return error; + +} + +/** + * sep_activate_msgarea_context - Takes the message area context into use + * @sep: SEP device + * @msg_region: Message area context buf + * @msg_len: Message area context buffer size + */ +static ssize_t sep_activate_msgarea_context(struct sep_device *sep, + void **msg_region, + const size_t msg_len) +{ + dev_dbg(&sep->pdev->dev, "[PID%d] activating msg region\n", + current->pid); + + if (!msg_region || !(*msg_region) || + SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES < msg_len) { + dev_warn(&sep->pdev->dev, + "[PID%d] invalid act msgarea len 0x%08X\n", + current->pid, msg_len); + return -EINVAL; + } + + memcpy(sep->shared_addr, *msg_region, msg_len); + + return 0; +} + +/** + * sep_create_msgarea_context - Creates message area context + * @sep: SEP device + * @msg_region: Msg area region buf to create for current transaction + * @msg_user: Content for msg area region from user + * @msg_len: Message area size + */ +static ssize_t sep_create_msgarea_context(struct sep_device *sep, + void **msg_region, + const void __user *msg_user, + const size_t msg_len) +{ + int error = 0; + + dev_dbg(&sep->pdev->dev, "[PID%d] creating msg region\n", + current->pid); + + if (!msg_region || + !msg_user || + SEP_DRIVER_MAX_MESSAGE_SIZE_IN_BYTES < msg_len || + SEP_DRIVER_MIN_MESSAGE_SIZE_IN_BYTES > msg_len) { + dev_warn(&sep->pdev->dev, + "[PID%d] invalid creat msgarea len 0x%08X\n", + current->pid, msg_len); + error = -EINVAL; + goto end_function; + } + + /* Allocate thread-specific memory for message buffer */ + *msg_region = kzalloc(msg_len, GFP_KERNEL); + if (!(*msg_region)) { + dev_warn(&sep->pdev->dev, + "[PID%d] no mem for msgarea context\n", + current->pid); + error = -ENOMEM; + goto end_function; + } + + /* Copy input data to write() to allocated message buffer */ + if (copy_from_user(*msg_region, msg_user, msg_len)) { + error = -EINVAL; + goto end_function; + } + +end_function: + if (error && msg_region) { + kfree(*msg_region); + *msg_region = NULL; + } + + return error; +} + + +/** + * sep_read - Returns results of an operation for fastcall interface + * @filp: File pointer + * @buf_user: User buffer for storing results + * @count_user: User buffer size + * @offset: File offset, not supported + * + * The implementation does not support reading in chunks, all data must be + * consumed during a single read system call. + */ +static ssize_t sep_read(struct file *filp, + char __user *buf_user, size_t count_user, + loff_t *offset) +{ + struct sep_private_data * const private_data = filp->private_data; + struct sep_call_status *call_status = &private_data->call_status; + struct sep_device *sep = private_data->device; + struct sep_dma_context **dma_ctx = &private_data->dma_ctx; + struct sep_queue_info **my_queue_elem = &private_data->my_queue_elem; + ssize_t error = 0, error_tmp = 0; + + /* Am I the process that owns the transaction? */ + error = sep_check_transaction_owner(sep); + if (error) { + dev_dbg(&sep->pdev->dev, "[PID%d] read pid is not owner\n", + current->pid); + goto end_function; + } + + /* Checks that user has called necessarry apis */ + if (0 == test_bit(SEP_FASTCALL_WRITE_DONE_OFFSET, + &call_status->status)) { + dev_warn(&sep->pdev->dev, + "[PID%d] fastcall write not called\n", + current->pid); + error = -EPROTO; + goto end_function_error; + } + + if (!buf_user) { + dev_warn(&sep->pdev->dev, + "[PID%d] null user buffer\n", + current->pid); + error = -EINVAL; + goto end_function_error; + } + + + /* Wait for SEP to finish */ + wait_event(sep->event_interrupt, + test_bit(SEP_WORKING_LOCK_BIT, + &sep->in_use_flags) == 0); + + sep_dump_message(sep); + + dev_dbg(&sep->pdev->dev, "[PID%d] count_user = 0x%08X\n", + current->pid, count_user); + + /* In case user has allocated bigger buffer */ + if (count_user > SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES) + count_user = SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES; + + if (copy_to_user(buf_user, sep->shared_addr, count_user)) { + error = -EFAULT; + goto end_function_error; + } + + dev_dbg(&sep->pdev->dev, "[PID%d] read succeeded\n", current->pid); + error = count_user; + +end_function_error: + /* Copy possible tail data to user and free DCB and MLLIs */ + error_tmp = sep_free_dcb_handler(sep, dma_ctx); + if (error_tmp) + dev_warn(&sep->pdev->dev, "[PID%d] dcb free failed\n", + current->pid); + + /* End the transaction, wakeup pending ones */ + error_tmp = sep_end_transaction_handler(sep, dma_ctx, call_status, + my_queue_elem); + if (error_tmp) + dev_warn(&sep->pdev->dev, + "[PID%d] ending transaction failed\n", + current->pid); + +end_function: + return error; +} + +/** + * sep_fastcall_args_get - Gets fastcall params from user + * sep: SEP device + * @args: Parameters buffer + * @buf_user: User buffer for operation parameters + * @count_user: User buffer size + */ +static inline ssize_t sep_fastcall_args_get(struct sep_device *sep, + struct sep_fastcall_hdr *args, + const char __user *buf_user, + const size_t count_user) +{ + ssize_t error = 0; + size_t actual_count = 0; + + if (!buf_user) { + dev_warn(&sep->pdev->dev, + "[PID%d] null user buffer\n", + current->pid); + error = -EINVAL; + goto end_function; + } + + if (count_user < sizeof(struct sep_fastcall_hdr)) { + dev_warn(&sep->pdev->dev, + "[PID%d] too small message size 0x%08X\n", + current->pid, count_user); + error = -EINVAL; + goto end_function; + } + + + if (copy_from_user(args, buf_user, sizeof(struct sep_fastcall_hdr))) { + error = -EFAULT; + goto end_function; + } + + if (SEP_FC_MAGIC != args->magic) { + dev_warn(&sep->pdev->dev, + "[PID%d] invalid fastcall magic 0x%08X\n", + current->pid, args->magic); + error = -EINVAL; + goto end_function; + } + + dev_dbg(&sep->pdev->dev, "[PID%d] fastcall hdr num of DCBs 0x%08X\n", + current->pid, args->num_dcbs); + dev_dbg(&sep->pdev->dev, "[PID%d] fastcall hdr msg len 0x%08X\n", + current->pid, args->msg_len); + + if (SEP_DRIVER_MAX_MESSAGE_SIZE_IN_BYTES < args->msg_len || + SEP_DRIVER_MIN_MESSAGE_SIZE_IN_BYTES > args->msg_len) { + dev_warn(&sep->pdev->dev, + "[PID%d] invalid message length\n", + current->pid); + error = -EINVAL; + goto end_function; + } + + actual_count = sizeof(struct sep_fastcall_hdr) + + args->msg_len + + (args->num_dcbs * sizeof(struct build_dcb_struct)); + + if (actual_count != count_user) { + dev_warn(&sep->pdev->dev, + "[PID%d] inconsistent message " + "sizes 0x%08X vs 0x%08X\n", + current->pid, actual_count, count_user); + error = -EMSGSIZE; + goto end_function; + } + +end_function: + return error; +} + +/** + * sep_write - Starts an operation for fastcall interface + * @filp: File pointer + * @buf_user: User buffer for operation parameters + * @count_user: User buffer size + * @offset: File offset, not supported + * + * The implementation does not support writing in chunks, + * all data must be given during a single write system call. + */ +static ssize_t sep_write(struct file *filp, + const char __user *buf_user, size_t count_user, + loff_t *offset) +{ + struct sep_private_data * const private_data = filp->private_data; + struct sep_call_status *call_status = &private_data->call_status; + struct sep_device *sep = private_data->device; + struct sep_dma_context *dma_ctx = NULL; + struct sep_fastcall_hdr call_hdr = {0}; + void *msg_region = NULL; + void *dmatables_region = NULL; + struct sep_dcblock *dcb_region = NULL; + ssize_t error = 0; + struct sep_queue_info *my_queue_elem = NULL; + + dev_dbg(&sep->pdev->dev, "[PID%d] sep dev is 0x%p\n", + current->pid, sep); + dev_dbg(&sep->pdev->dev, "[PID%d] private_data is 0x%p\n", + current->pid, private_data); + + error = sep_fastcall_args_get(sep, &call_hdr, buf_user, count_user); + if (error) + goto end_function; + + buf_user += sizeof(struct sep_fastcall_hdr); + + /* + * Controlling driver memory usage by limiting amount of + * buffers created. Only SEP_DOUBLEBUF_USERS_LIMIT number + * of threads can progress further at a time + */ + dev_dbg(&sep->pdev->dev, "[PID%d] waiting for double buffering " + "region access\n", current->pid); + error = down_interruptible(&sep->sep_doublebuf); + dev_dbg(&sep->pdev->dev, "[PID%d] double buffering region start\n", + current->pid); + if (error) { + /* Signal received */ + goto end_function_error; + } + + + /* + * Prepare contents of the shared area regions for + * the operation into temporary buffers + */ + if (0 < call_hdr.num_dcbs) { + error = sep_create_dcb_dmatables_context(sep, + &dcb_region, + &dmatables_region, + &dma_ctx, + (const struct build_dcb_struct __user *) + buf_user, + call_hdr.num_dcbs); + if (error) + goto end_function_error_doublebuf; + + buf_user += call_hdr.num_dcbs * sizeof(struct build_dcb_struct); + } + + error = sep_create_msgarea_context(sep, + &msg_region, + buf_user, + call_hdr.msg_len); + if (error) + goto end_function_error_doublebuf; + + dev_dbg(&sep->pdev->dev, "[PID%d] updating queue status\n", + current->pid); + my_queue_elem = sep_queue_status_add(sep, + ((struct sep_msgarea_hdr *)msg_region)->opcode, + (dma_ctx) ? dma_ctx->input_data_len : 0, + current->pid, + current->comm, sizeof(current->comm)); + + if (!my_queue_elem) { + dev_dbg(&sep->pdev->dev, "[PID%d] updating queue" + "status error\n", current->pid); + error = -ENOMEM; + goto end_function_error_doublebuf; + } + + /* Wait until current process gets the transaction */ + error = sep_wait_transaction(sep); + + if (error) { + /* Interrupted by signal, don't clear transaction */ + dev_dbg(&sep->pdev->dev, "[PID%d] interrupted by signal\n", + current->pid); + sep_queue_status_remove(sep, &my_queue_elem); + goto end_function_error_doublebuf; + } + + dev_dbg(&sep->pdev->dev, "[PID%d] saving queue element\n", + current->pid); + private_data->my_queue_elem = my_queue_elem; + + /* Activate shared area regions for the transaction */ + error = sep_activate_msgarea_context(sep, &msg_region, + call_hdr.msg_len); + if (error) + goto end_function_error_clear_transact; + + sep_dump_message(sep); + + if (0 < call_hdr.num_dcbs) { + error = sep_activate_dcb_dmatables_context(sep, + &dcb_region, + &dmatables_region, + dma_ctx); + if (error) + goto end_function_error_clear_transact; + } + + /* Send command to SEP */ + error = sep_send_command_handler(sep); + if (error) + goto end_function_error_clear_transact; + + /* Store DMA context for the transaction */ + private_data->dma_ctx = dma_ctx; + /* Update call status */ + set_bit(SEP_FASTCALL_WRITE_DONE_OFFSET, &call_status->status); + error = count_user; + + up(&sep->sep_doublebuf); + dev_dbg(&sep->pdev->dev, "[PID%d] double buffering region end\n", + current->pid); + + goto end_function; + +end_function_error_clear_transact: + sep_end_transaction_handler(sep, &dma_ctx, call_status, + &private_data->my_queue_elem); + +end_function_error_doublebuf: + up(&sep->sep_doublebuf); + dev_dbg(&sep->pdev->dev, "[PID%d] double buffering region end\n", + current->pid); + +end_function_error: + if (dma_ctx) + sep_free_dma_table_data_handler(sep, &dma_ctx); + +end_function: + kfree(dcb_region); + kfree(dmatables_region); + kfree(msg_region); + + return error; +} +/** + * sep_seek - Handler for seek system call + * @filp: File pointer + * @offset: File offset + * @origin: Options for offset + * + * Fastcall interface does not support seeking, all reads + * and writes are from/to offset zero + */ +static loff_t sep_seek(struct file *filp, loff_t offset, int origin) +{ + return -ENOSYS; +} + + + +/** + * sep_file_operations - file operation on sep device + * @sep_ioctl: ioctl handler from user space call + * @sep_poll: poll handler + * @sep_open: handles sep device open request + * @sep_release:handles sep device release request + * @sep_mmap: handles memory mapping requests + * @sep_read: handles read request on sep device + * @sep_write: handles write request on sep device + * @sep_seek: handles seek request on sep device + */ +static const struct file_operations sep_file_operations = { + .owner = THIS_MODULE, + .unlocked_ioctl = sep_ioctl, + .poll = sep_poll, + .open = sep_open, + .release = sep_release, + .mmap = sep_mmap, + .read = sep_read, + .write = sep_write, + .llseek = sep_seek, +}; + +/** + * sep_sysfs_read - read sysfs entry per gives arguments + * @filp: file pointer + * @kobj: kobject pointer + * @attr: binary file attributes + * @buf: read to this buffer + * @pos: offset to read + * @count: amount of data to read + * + * This function is to read sysfs entries for sep driver per given arguments. + */ +static ssize_t +sep_sysfs_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t pos, size_t count) +{ + unsigned long lck_flags; + size_t nleft = count; + struct sep_device *sep = sep_dev; + struct sep_queue_info *queue_elem = NULL; + u32 queue_num = 0; + u32 i = 1; + + spin_lock_irqsave(&sep->sep_queue_lock, lck_flags); + + queue_num = sep->sep_queue_num; + if (queue_num > SEP_DOUBLEBUF_USERS_LIMIT) + queue_num = SEP_DOUBLEBUF_USERS_LIMIT; + + + if (count < sizeof(queue_num) + + (queue_num * sizeof(struct sep_queue_data))) { + spin_unlock_irqrestore(&sep->sep_queue_lock, lck_flags); + return -EINVAL; + } + + memcpy(buf, &queue_num, sizeof(queue_num)); + buf += sizeof(queue_num); + nleft -= sizeof(queue_num); + + list_for_each_entry(queue_elem, &sep->sep_queue_status, list) { + if (i++ > queue_num) + break; + + memcpy(buf, &queue_elem->data, sizeof(queue_elem->data)); + nleft -= sizeof(queue_elem->data); + buf += sizeof(queue_elem->data); + } + spin_unlock_irqrestore(&sep->sep_queue_lock, lck_flags); + + return count - nleft; +} + +/** + * bin_attributes - defines attributes for queue_status + * @attr: attributes (name & permissions) + * @read: function pointer to read this file + * @size: maxinum size of binary attribute + */ +static const struct bin_attribute queue_status = { + .attr = {.name = "queue_status", .mode = 0444}, + .read = sep_sysfs_read, + .size = sizeof(u32) + + (SEP_DOUBLEBUF_USERS_LIMIT * sizeof(struct sep_queue_data)), +}; + +/** + * sep_register_driver_with_fs - register misc devices + * @sep: pointer to struct sep_device + * + * This function registers the driver with the file system + */ +static int sep_register_driver_with_fs(struct sep_device *sep) +{ + int ret_val; + + sep->miscdev_sep.minor = MISC_DYNAMIC_MINOR; + sep->miscdev_sep.name = SEP_DEV_NAME; + sep->miscdev_sep.fops = &sep_file_operations; + + ret_val = misc_register(&sep->miscdev_sep); + if (ret_val) { + dev_warn(&sep->pdev->dev, "misc reg fails for SEP %x\n", + ret_val); + return ret_val; + } + + ret_val = device_create_bin_file(sep->miscdev_sep.this_device, + &queue_status); + if (ret_val) { + dev_warn(&sep->pdev->dev, "sysfs attribute1 fails for SEP %x\n", + ret_val); + return ret_val; + } + + return ret_val; +} + + +/** + *sep_probe - probe a matching PCI device + *@pdev: pci_device + *@ent: pci_device_id + * + *Attempt to set up and configure a SEP device that has been + *discovered by the PCI layer. Allocates all required resources. + */ +static int __devinit sep_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + int error = 0; + struct sep_device *sep = NULL; + + if (sep_dev != NULL) { + dev_dbg(&pdev->dev, "only one SEP supported.\n"); + return -EBUSY; + } + + /* Enable the device */ + error = pci_enable_device(pdev); + if (error) { + dev_warn(&pdev->dev, "error enabling pci device\n"); + goto end_function; + } + + /* Allocate the sep_device structure for this device */ + sep_dev = kzalloc(sizeof(struct sep_device), GFP_ATOMIC); + if (sep_dev == NULL) { + dev_warn(&pdev->dev, + "can't kmalloc the sep_device structure\n"); + error = -ENOMEM; + goto end_function_disable_device; + } + + /* + * We're going to use another variable for actually + * working with the device; this way, if we have + * multiple devices in the future, it would be easier + * to make appropriate changes + */ + sep = sep_dev; + + sep->pdev = pci_dev_get(pdev); + + init_waitqueue_head(&sep->event_transactions); + init_waitqueue_head(&sep->event_interrupt); + spin_lock_init(&sep->snd_rply_lck); + spin_lock_init(&sep->sep_queue_lock); + sema_init(&sep->sep_doublebuf, SEP_DOUBLEBUF_USERS_LIMIT); + + INIT_LIST_HEAD(&sep->sep_queue_status); + + dev_dbg(&sep->pdev->dev, "sep probe: PCI obtained, " + "device being prepared\n"); + dev_dbg(&sep->pdev->dev, "revision is %d\n", sep->pdev->revision); + + /* Set up our register area */ + sep->reg_physical_addr = pci_resource_start(sep->pdev, 0); + if (!sep->reg_physical_addr) { + dev_warn(&sep->pdev->dev, "Error getting register start\n"); + error = -ENODEV; + goto end_function_free_sep_dev; + } + + sep->reg_physical_end = pci_resource_end(sep->pdev, 0); + if (!sep->reg_physical_end) { + dev_warn(&sep->pdev->dev, "Error getting register end\n"); + error = -ENODEV; + goto end_function_free_sep_dev; + } + + sep->reg_addr = ioremap_nocache(sep->reg_physical_addr, + (size_t)(sep->reg_physical_end - sep->reg_physical_addr + 1)); + if (!sep->reg_addr) { + dev_warn(&sep->pdev->dev, "Error getting register virtual\n"); + error = -ENODEV; + goto end_function_free_sep_dev; + } + + dev_dbg(&sep->pdev->dev, + "Register area start %llx end %llx virtual %p\n", + (unsigned long long)sep->reg_physical_addr, + (unsigned long long)sep->reg_physical_end, + sep->reg_addr); + + /* Allocate the shared area */ + sep->shared_size = SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES + + SYNCHRONIC_DMA_TABLES_AREA_SIZE_BYTES + + SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES + + SEP_DRIVER_STATIC_AREA_SIZE_IN_BYTES + + SEP_DRIVER_SYSTEM_DATA_MEMORY_SIZE_IN_BYTES; + + if (sep_map_and_alloc_shared_area(sep)) { + error = -ENOMEM; + /* Allocation failed */ + goto end_function_error; + } + + /* Clear ICR register */ + sep_write_reg(sep, HW_HOST_ICR_REG_ADDR, 0xFFFFFFFF); + + /* Set the IMR register - open only GPR 2 */ + sep_write_reg(sep, HW_HOST_IMR_REG_ADDR, (~(0x1 << 13))); + + /* Read send/receive counters from SEP */ + sep->reply_ct = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR2_REG_ADDR); + sep->reply_ct &= 0x3FFFFFFF; + sep->send_ct = sep->reply_ct; + + /* Get the interrupt line */ + error = request_irq(pdev->irq, sep_inthandler, IRQF_SHARED, + "sep_driver", sep); + + if (error) + goto end_function_deallocate_sep_shared_area; + + /* The new chip requires a shared area reconfigure */ + if (sep->pdev->revision != 0) { /* Only for new chip */ + error = sep_reconfig_shared_area(sep); + if (error) + goto end_function_free_irq; + } + + sep->in_use = 1; + + /* Finally magic up the device nodes */ + /* Register driver with the fs */ + error = sep_register_driver_with_fs(sep); + if (error) + goto end_function_free_irq; + +#ifdef SEP_ENABLE_RUNTIME_PM + pm_runtime_put_noidle(&sep->pdev->dev); + pm_runtime_allow(&sep->pdev->dev); + pm_runtime_set_autosuspend_delay(&sep->pdev->dev, + SUSPEND_DELAY); + pm_runtime_use_autosuspend(&sep->pdev->dev); + sep->power_save_setup = 1; +#endif + + sep->in_use = 0; + + /* register kernel crypto driver */ + error = sep_crypto_setup(); + if (error) { + dev_dbg(&sep->pdev->dev, "crypto setup fail\n"); + goto end_function_free_irq; + } + + goto end_function; + +end_function_free_irq: + free_irq(pdev->irq, sep); + +end_function_deallocate_sep_shared_area: + /* De-allocate shared area */ + sep_unmap_and_free_shared_area(sep); + +end_function_error: + iounmap(sep->reg_addr); + +end_function_free_sep_dev: + pci_dev_put(sep_dev->pdev); + kfree(sep_dev); + sep_dev = NULL; + +end_function_disable_device: + pci_disable_device(pdev); + +end_function: + return error; +} + +/** + * sep_remove - handles removing device from pci subsystem + * @pdev: pointer to pci device + * + * This function will handle removing our sep device from pci subsystem on exit + * or unloading this module. It should free up all used resources, and unmap if + * any memory regions mapped. + */ +static void sep_remove(struct pci_dev *pdev) +{ + struct sep_device *sep = sep_dev; + + /* Unregister from fs */ + misc_deregister(&sep->miscdev_sep); + + /* Unregister from kernel crypto */ + sep_crypto_takedown(); + + /* Free the irq */ + free_irq(sep->pdev->irq, sep); + + /* Free the shared area */ + sep_unmap_and_free_shared_area(sep_dev); + iounmap((void __iomem *)sep_dev->reg_addr); + +#ifdef SEP_ENABLE_RUNTIME_PM + if (sep->in_use) { + sep->in_use = 0; + pm_runtime_forbid(&sep->pdev->dev); + pm_runtime_get_noresume(&sep->pdev->dev); + } +#endif + pci_dev_put(sep_dev->pdev); + kfree(sep_dev); + sep_dev = NULL; +} + +/* Initialize struct pci_device_id for our driver */ +static DEFINE_PCI_DEVICE_TABLE(sep_pci_id_tbl) = { + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MFLD_PCI_DEVICE_ID)}, + {0} +}; + +/* Export our pci_device_id structure to user space */ +MODULE_DEVICE_TABLE(pci, sep_pci_id_tbl); + +#ifdef SEP_ENABLE_RUNTIME_PM + +/** + * sep_pm_resume - rsume routine while waking up from S3 state + * @dev: pointer to sep device + * + * This function is to be used to wake up sep driver while system awakes from S3 + * state i.e. suspend to ram. The RAM in intact. + * Notes - revisit with more understanding of pm, ICR/IMR & counters. + */ +static int sep_pci_resume(struct device *dev) +{ + struct sep_device *sep = sep_dev; + + dev_dbg(&sep->pdev->dev, "pci resume called\n"); + + if (sep->power_state == SEP_DRIVER_POWERON) + return 0; + + /* Clear ICR register */ + sep_write_reg(sep, HW_HOST_ICR_REG_ADDR, 0xFFFFFFFF); + + /* Set the IMR register - open only GPR 2 */ + sep_write_reg(sep, HW_HOST_IMR_REG_ADDR, (~(0x1 << 13))); + + /* Read send/receive counters from SEP */ + sep->reply_ct = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR2_REG_ADDR); + sep->reply_ct &= 0x3FFFFFFF; + sep->send_ct = sep->reply_ct; + + sep->power_state = SEP_DRIVER_POWERON; + + return 0; +} + +/** + * sep_pm_suspend - suspend routine while going to S3 state + * @dev: pointer to sep device + * + * This function is to be used to suspend sep driver while system goes to S3 + * state i.e. suspend to ram. The RAM in intact and ON during this suspend. + * Notes - revisit with more understanding of pm, ICR/IMR + */ +static int sep_pci_suspend(struct device *dev) +{ + struct sep_device *sep = sep_dev; + + dev_dbg(&sep->pdev->dev, "pci suspend called\n"); + if (sep->in_use == 1) + return -EAGAIN; + + sep->power_state = SEP_DRIVER_POWEROFF; + + /* Clear ICR register */ + sep_write_reg(sep, HW_HOST_ICR_REG_ADDR, 0xFFFFFFFF); + + /* Set the IMR to block all */ + sep_write_reg(sep, HW_HOST_IMR_REG_ADDR, 0xFFFFFFFF); + + return 0; +} + +/** + * sep_pm_runtime_resume - runtime resume routine + * @dev: pointer to sep device + * + * Notes - revisit with more understanding of pm, ICR/IMR & counters + */ +static int sep_pm_runtime_resume(struct device *dev) +{ + + u32 retval2; + u32 delay_count; + struct sep_device *sep = sep_dev; + + dev_dbg(&sep->pdev->dev, "pm runtime resume called\n"); + + /** + * Wait until the SCU boot is ready + * This is done by iterating SCU_DELAY_ITERATION (10 + * microseconds each) up to SCU_DELAY_MAX (50) times. + * This bit can be set in a random time that is less + * than 500 microseconds after each power resume + */ + retval2 = 0; + delay_count = 0; + while ((!retval2) && (delay_count < SCU_DELAY_MAX)) { + retval2 = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR3_REG_ADDR); + retval2 &= 0x00000008; + if (!retval2) { + udelay(SCU_DELAY_ITERATION); + delay_count += 1; + } + } + + if (!retval2) { + dev_warn(&sep->pdev->dev, "scu boot bit not set at resume\n"); + return -EINVAL; + } + + /* Clear ICR register */ + sep_write_reg(sep, HW_HOST_ICR_REG_ADDR, 0xFFFFFFFF); + + /* Set the IMR register - open only GPR 2 */ + sep_write_reg(sep, HW_HOST_IMR_REG_ADDR, (~(0x1 << 13))); + + /* Read send/receive counters from SEP */ + sep->reply_ct = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR2_REG_ADDR); + sep->reply_ct &= 0x3FFFFFFF; + sep->send_ct = sep->reply_ct; + + return 0; +} + +/** + * sep_pm_runtime_suspend - runtime suspend routine + * @dev: pointer to sep device + * + * Notes - revisit with more understanding of pm + */ +static int sep_pm_runtime_suspend(struct device *dev) +{ + struct sep_device *sep = sep_dev; + + dev_dbg(&sep->pdev->dev, "pm runtime suspend called\n"); + + /* Clear ICR register */ + sep_write_reg(sep, HW_HOST_ICR_REG_ADDR, 0xFFFFFFFF); + return 0; +} + +/** + * sep_pm - power management for sep driver + * @sep_pm_runtime_resume: resume- no communication with cpu & main memory + * @sep_pm_runtime_suspend: suspend- no communication with cpu & main memory + * @sep_pci_suspend: suspend - main memory is still ON + * @sep_pci_resume: resume - main meory is still ON + */ +static const struct dev_pm_ops sep_pm = { + .runtime_resume = sep_pm_runtime_resume, + .runtime_suspend = sep_pm_runtime_suspend, + .resume = sep_pci_resume, + .suspend = sep_pci_suspend, +}; +#endif /* SEP_ENABLE_RUNTIME_PM */ + +/** + * sep_pci_driver - registers this device with pci subsystem + * @name: name identifier for this driver + * @sep_pci_id_tbl: pointer to struct pci_device_id table + * @sep_probe: pointer to probe function in PCI driver + * @sep_remove: pointer to remove function in PCI driver + */ +static struct pci_driver sep_pci_driver = { +#ifdef SEP_ENABLE_RUNTIME_PM + .driver = { + .pm = &sep_pm, + }, +#endif + .name = "sep_sec_driver", + .id_table = sep_pci_id_tbl, + .probe = sep_probe, + .remove = sep_remove +}; + +/** + * sep_init - init function + * + * Module load time. Register the PCI device driver. + */ + +static int __init sep_init(void) +{ + return pci_register_driver(&sep_pci_driver); +} + + +/** + * sep_exit - called to unload driver + * + * Unregister the driver The device will perform all the cleanup required. + */ +static void __exit sep_exit(void) +{ + pci_unregister_driver(&sep_pci_driver); +} + + +module_init(sep_init); +module_exit(sep_exit); + +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/sep/sep_trace_events.h b/drivers/staging/sep/sep_trace_events.h new file mode 100644 index 0000000..2b053a9 --- /dev/null +++ b/drivers/staging/sep/sep_trace_events.h @@ -0,0 +1,188 @@ +/* + * If TRACE_SYSTEM is defined, that will be the directory created + * in the ftrace directory under /sys/kernel/debug/tracing/events/ + * + * The define_trace.h below will also look for a file name of + * TRACE_SYSTEM.h where TRACE_SYSTEM is what is defined here. + * In this case, it would look for sample.h + * + * If the header name will be different than the system name + * (as in this case), then you can override the header name that + * define_trace.h will look up by defining TRACE_INCLUDE_FILE + * + * This file is called trace-events-sample.h but we want the system + * to be called "sample". Therefore we must define the name of this + * file: + * + * #define TRACE_INCLUDE_FILE trace-events-sample + * + * As we do an the bottom of this file. + * + * Notice that TRACE_SYSTEM should be defined outside of #if + * protection, just like TRACE_INCLUDE_FILE. + */ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM sep + +/* + * Notice that this file is not protected like a normal header. + * We also must allow for rereading of this file. The + * + * || defined(TRACE_HEADER_MULTI_READ) + * + * serves this purpose. + */ +#if !defined(_TRACE_SEP_EVENTS_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_SEP_EVENTS_H + +#ifdef SEP_PERF_DEBUG +#define SEP_TRACE_FUNC_IN() trace_sep_func_start(__func__, 0) +#define SEP_TRACE_FUNC_OUT(branch) trace_sep_func_end(__func__, branch) +#define SEP_TRACE_EVENT(branch) trace_sep_misc_event(__func__, branch) +#else +#define SEP_TRACE_FUNC_IN() +#define SEP_TRACE_FUNC_OUT(branch) +#define SEP_TRACE_EVENT(branch) +#endif + + +/* + * All trace headers should include tracepoint.h, until we finally + * make it into a standard header. + */ +#include + +/* + * The TRACE_EVENT macro is broken up into 5 parts. + * + * name: name of the trace point. This is also how to enable the tracepoint. + * A function called trace_foo_bar() will be created. + * + * proto: the prototype of the function trace_foo_bar() + * Here it is trace_foo_bar(char *foo, int bar). + * + * args: must match the arguments in the prototype. + * Here it is simply "foo, bar". + * + * struct: This defines the way the data will be stored in the ring buffer. + * There are currently two types of elements. __field and __array. + * a __field is broken up into (type, name). Where type can be any + * type but an array. + * For an array. there are three fields. (type, name, size). The + * type of elements in the array, the name of the field and the size + * of the array. + * + * __array( char, foo, 10) is the same as saying char foo[10]. + * + * fast_assign: This is a C like function that is used to store the items + * into the ring buffer. + * + * printk: This is a way to print out the data in pretty print. This is + * useful if the system crashes and you are logging via a serial line, + * the data can be printed to the console using this "printk" method. + * + * Note, that for both the assign and the printk, __entry is the handler + * to the data structure in the ring buffer, and is defined by the + * TP_STRUCT__entry. + */ +TRACE_EVENT(sep_func_start, + + TP_PROTO(const char *name, int branch), + + TP_ARGS(name, branch), + + TP_STRUCT__entry( + __array(char, name, 20) + __field(int, branch) + ), + + TP_fast_assign( + strncpy(__entry->name, name, 20); + __entry->branch = branch; + ), + + TP_printk("func_start %s %d", __entry->name, __entry->branch) +); + +TRACE_EVENT(sep_func_end, + + TP_PROTO(const char *name, int branch), + + TP_ARGS(name, branch), + + TP_STRUCT__entry( + __array(char, name, 20) + __field(int, branch) + ), + + TP_fast_assign( + strncpy(__entry->name, name, 20); + __entry->branch = branch; + ), + + TP_printk("func_end %s %d", __entry->name, __entry->branch) +); + +TRACE_EVENT(sep_misc_event, + + TP_PROTO(const char *name, int branch), + + TP_ARGS(name, branch), + + TP_STRUCT__entry( + __array(char, name, 20) + __field(int, branch) + ), + + TP_fast_assign( + strncpy(__entry->name, name, 20); + __entry->branch = branch; + ), + + TP_printk("misc_event %s %d", __entry->name, __entry->branch) +); + + +#endif + +/***** NOTICE! The #if protection ends here. *****/ + + +/* + * There are several ways I could have done this. If I left out the + * TRACE_INCLUDE_PATH, then it would default to the kernel source + * include/trace/events directory. + * + * I could specify a path from the define_trace.h file back to this + * file. + * + * #define TRACE_INCLUDE_PATH ../../samples/trace_events + * + * But the safest and easiest way to simply make it use the directory + * that the file is in is to add in the Makefile: + * + * CFLAGS_trace-events-sample.o := -I$(src) + * + * This will make sure the current path is part of the include + * structure for our file so that define_trace.h can find it. + * + * I could have made only the top level directory the include: + * + * CFLAGS_trace-events-sample.o := -I$(PWD) + * + * And then let the path to this directory be the TRACE_INCLUDE_PATH: + * + * #define TRACE_INCLUDE_PATH samples/trace_events + * + * But then if something defines "samples" or "trace_events" as a macro + * then we could risk that being converted too, and give us an unexpected + * result. + */ +#undef TRACE_INCLUDE_PATH +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_PATH . +/* + * TRACE_INCLUDE_FILE is not needed if the filename and TRACE_SYSTEM are equal + */ +#define TRACE_INCLUDE_FILE sep_trace_events +#include -- cgit v0.10.2 From 5f356a67ae14033d734f73b79b926f8949300e83 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 31 Jan 2012 16:56:48 +0000 Subject: staging: sep: Fix warnings caused by sizeof() types Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/sep/sep_main.c b/drivers/staging/sep/sep_main.c index 0defb0a..7f8362c 100644 --- a/drivers/staging/sep/sep_main.c +++ b/drivers/staging/sep/sep_main.c @@ -214,7 +214,7 @@ static int sep_allocate_dmatables_region(struct sep_device *sep, return -EINVAL; } - dev_dbg(&sep->pdev->dev, "[PID%d] newlen = 0x%08X\n", + dev_dbg(&sep->pdev->dev, "[PID%d] newlen = 0x%08zX\n", current->pid, new_len); dev_dbg(&sep->pdev->dev, "[PID%d] oldlen = 0x%08X\n", current->pid, dma_ctx->dmatables_len); @@ -3344,7 +3344,7 @@ static ssize_t sep_activate_msgarea_context(struct sep_device *sep, if (!msg_region || !(*msg_region) || SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES < msg_len) { dev_warn(&sep->pdev->dev, - "[PID%d] invalid act msgarea len 0x%08X\n", + "[PID%d] invalid act msgarea len 0x%08zX\n", current->pid, msg_len); return -EINVAL; } @@ -3376,7 +3376,7 @@ static ssize_t sep_create_msgarea_context(struct sep_device *sep, SEP_DRIVER_MAX_MESSAGE_SIZE_IN_BYTES < msg_len || SEP_DRIVER_MIN_MESSAGE_SIZE_IN_BYTES > msg_len) { dev_warn(&sep->pdev->dev, - "[PID%d] invalid creat msgarea len 0x%08X\n", + "[PID%d] invalid creat msgarea len 0x%08zX\n", current->pid, msg_len); error = -EINVAL; goto end_function; @@ -3463,7 +3463,7 @@ static ssize_t sep_read(struct file *filp, sep_dump_message(sep); - dev_dbg(&sep->pdev->dev, "[PID%d] count_user = 0x%08X\n", + dev_dbg(&sep->pdev->dev, "[PID%d] count_user = 0x%08zX\n", current->pid, count_user); /* In case user has allocated bigger buffer */ @@ -3522,7 +3522,7 @@ static inline ssize_t sep_fastcall_args_get(struct sep_device *sep, if (count_user < sizeof(struct sep_fastcall_hdr)) { dev_warn(&sep->pdev->dev, - "[PID%d] too small message size 0x%08X\n", + "[PID%d] too small message size 0x%08zX\n", current->pid, count_user); error = -EINVAL; goto end_function; @@ -3563,7 +3563,7 @@ static inline ssize_t sep_fastcall_args_get(struct sep_device *sep, if (actual_count != count_user) { dev_warn(&sep->pdev->dev, "[PID%d] inconsistent message " - "sizes 0x%08X vs 0x%08X\n", + "sizes 0x%08zX vs 0x%08zX\n", current->pid, actual_count, count_user); error = -EMSGSIZE; goto end_function; -- cgit v0.10.2 From d1b5342c1f5946c2219e4e5bd770b1c1fc186272 Mon Sep 17 00:00:00 2001 From: Marc Dietrich Date: Mon, 26 Dec 2011 17:57:32 +0100 Subject: staging: nvec: ps2: add suspend/resume functions This adds suspend and resume functions to the nvec_ps2 mouse driver. During suspend the nvec sends a "Cancel all mouse events" command. If this is missed, there will be still some bytes in the received buffer after resume which make the mouse go out of sync. Signed-off-by: Marc Dietrich Signed-off-by: Julian Andres Klode Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/nvec/nvec_ps2.c b/drivers/staging/nvec/nvec_ps2.c index 742f5cc..4410dfb 100644 --- a/drivers/staging/nvec/nvec_ps2.c +++ b/drivers/staging/nvec/nvec_ps2.c @@ -111,8 +111,27 @@ static int __devinit nvec_mouse_probe(struct platform_device *pdev) return 0; } +static int nvec_mouse_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct nvec_chip *nvec = dev_get_drvdata(pdev->dev.parent); + + /* send cancel autoreceive */ + nvec_write_async(nvec, "\x06\x04", 2); + + return 0; +} + +static int nvec_mouse_resume(struct platform_device *pdev) +{ + ps2_startstreaming(ps2_dev.ser_dev); + + return 0; +} + static struct platform_driver nvec_mouse_driver = { .probe = nvec_mouse_probe, + .suspend = nvec_mouse_suspend, + .resume = nvec_mouse_resume, .driver = { .name = "nvec-mouse", .owner = THIS_MODULE, -- cgit v0.10.2 From 34ba143b9d1daf2eb7ea06b05c24b71faff82512 Mon Sep 17 00:00:00 2001 From: Marc Dietrich Date: Mon, 26 Dec 2011 17:57:33 +0100 Subject: staging: nvec: ps2: let the start/stop streaming commands be called by the start/stop functions of serio Instead of executing these commands during open/close, the start/stop event of the serio device seem to be more appropiete. Signed-off-by: Marc Dietrich Signed-off-by: Julian Andres Klode Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/nvec/nvec_ps2.c b/drivers/staging/nvec/nvec_ps2.c index 4410dfb..f152834 100644 --- a/drivers/staging/nvec/nvec_ps2.c +++ b/drivers/staging/nvec/nvec_ps2.c @@ -92,8 +92,8 @@ static int __devinit nvec_mouse_probe(struct platform_device *pdev) ser_dev->id.type = SERIO_8042; ser_dev->write = ps2_sendcommand; - ser_dev->open = ps2_startstreaming; - ser_dev->close = ps2_stopstreaming; + ser_dev->start = ps2_startstreaming; + ser_dev->stop = ps2_stopstreaming; strlcpy(ser_dev->name, "nvec mouse", sizeof(ser_dev->name)); strlcpy(ser_dev->phys, "nvec", sizeof(ser_dev->phys)); -- cgit v0.10.2 From 4b625c3abe91fca5b5a7f05681c10105af957e4f Mon Sep 17 00:00:00 2001 From: Marc Dietrich Date: Mon, 26 Dec 2011 17:57:34 +0100 Subject: staging: nvec: ps2: tell nvec to send 6 byte long messages This packet size used on most modern touchpads. Ideally, this should be configurable or autodetected. Signed-off-by: Marc Dietrich Signed-off-by: Julian Andres Klode Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/nvec/nvec_ps2.c b/drivers/staging/nvec/nvec_ps2.c index f152834..8bfaccd 100644 --- a/drivers/staging/nvec/nvec_ps2.c +++ b/drivers/staging/nvec/nvec_ps2.c @@ -21,7 +21,7 @@ #include "nvec.h" -#define START_STREAMING {'\x06', '\x03', '\x04'} +#define START_STREAMING {'\x06', '\x03', '\x06'} #define STOP_STREAMING {'\x06', '\x04'} #define SEND_COMMAND {'\x06', '\x01', '\xf4', '\x01'} -- cgit v0.10.2 From 0eedab704ed93d03b1ac392fd329f7ed20ab2279 Mon Sep 17 00:00:00 2001 From: Marc Dietrich Date: Mon, 26 Dec 2011 17:57:35 +0100 Subject: staging: nvec: ps2: add some more debug functions This can print the mouse traffic which goes over the i2c bus. Make mouse debugging messages configurable and disable them by default. Signed-off-by: Marc Dietrich Signed-off-by: Julian Andres Klode Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/nvec/nvec_ps2.c b/drivers/staging/nvec/nvec_ps2.c index 8bfaccd..7f470ba 100644 --- a/drivers/staging/nvec/nvec_ps2.c +++ b/drivers/staging/nvec/nvec_ps2.c @@ -25,6 +25,14 @@ #define STOP_STREAMING {'\x06', '\x04'} #define SEND_COMMAND {'\x06', '\x01', '\xf4', '\x01'} +#ifdef NVEC_PS2_DEBUG +#define NVEC_PHD(str, buf, len) \ + print_hex_dump(KERN_DEBUG, str, DUMP_PREFIX_NONE, \ + 16, 1, buf, len, false) +#else +#define NVEC_PHD(str, buf, len) +#endif + static const unsigned char MOUSE_RESET[] = {'\x06', '\x01', '\xff', '\x03'}; struct nvec_ps2 { @@ -67,18 +75,18 @@ static int nvec_ps2_notifier(struct notifier_block *nb, case NVEC_PS2_EVT: for (i = 0; i < msg[1]; i++) serio_interrupt(ps2_dev.ser_dev, msg[2 + i], 0); + NVEC_PHD("ps/2 mouse event: ", &msg[2], msg[1]); return NOTIFY_STOP; case NVEC_PS2: - if (msg[2] == 1) + if (msg[2] == 1) { for (i = 0; i < (msg[1] - 2); i++) serio_interrupt(ps2_dev.ser_dev, msg[i + 4], 0); - else if (msg[1] != 2) { /* !ack */ - print_hex_dump(KERN_WARNING, "unhandled mouse event: ", - DUMP_PREFIX_NONE, 16, 1, - msg, msg[1] + 2, true); + NVEC_PHD("ps/2 mouse reply: ", &msg[4], msg[1] - 2); } + else if (msg[1] != 2) /* !ack */ + NVEC_PHD("unhandled mouse event: ", msg, msg[1] + 2); return NOTIFY_STOP; } -- cgit v0.10.2 From a573298b81ffd05856ddaa222826471eabf3953b Mon Sep 17 00:00:00 2001 From: Marc Dietrich Date: Mon, 26 Dec 2011 17:57:36 +0100 Subject: staging: nvec: ps2: disable/enable mouse on suspend/resume This change makes the touchpad buttons work after suspend/resume. Signed-off-by: Marc Dietrich Signed-off-by: Julian Andres Klode Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/nvec/nvec_ps2.c b/drivers/staging/nvec/nvec_ps2.c index 7f470ba..4be3d22 100644 --- a/drivers/staging/nvec/nvec_ps2.c +++ b/drivers/staging/nvec/nvec_ps2.c @@ -123,6 +123,9 @@ static int nvec_mouse_suspend(struct platform_device *pdev, pm_message_t state) { struct nvec_chip *nvec = dev_get_drvdata(pdev->dev.parent); + /* disable mouse */ + nvec_write_async(nvec, "\x06\xf4", 2); + /* send cancel autoreceive */ nvec_write_async(nvec, "\x06\x04", 2); @@ -131,8 +134,13 @@ static int nvec_mouse_suspend(struct platform_device *pdev, pm_message_t state) static int nvec_mouse_resume(struct platform_device *pdev) { + struct nvec_chip *nvec = dev_get_drvdata(pdev->dev.parent); + ps2_startstreaming(ps2_dev.ser_dev); + /* enable mouse */ + nvec_write_async(nvec, "\x06\xf5", 2); + return 0; } -- cgit v0.10.2 From 36b30d6138f4677514aca35ab76c20c1604baaad Mon Sep 17 00:00:00 2001 From: Marc Dietrich Date: Mon, 26 Dec 2011 17:57:37 +0100 Subject: staging: nvec: ps2: change serio type to passthrough This changes the serio type of the nvec_ps2 mouse port to passthrough. The old 8042 type seems appropiete for keyboards only. Signed-off-by: Marc Dietrich Signed-off-by: Julian Andres Klode Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/nvec/nvec_ps2.c b/drivers/staging/nvec/nvec_ps2.c index 4be3d22..14a6f68 100644 --- a/drivers/staging/nvec/nvec_ps2.c +++ b/drivers/staging/nvec/nvec_ps2.c @@ -98,7 +98,7 @@ static int __devinit nvec_mouse_probe(struct platform_device *pdev) struct nvec_chip *nvec = dev_get_drvdata(pdev->dev.parent); struct serio *ser_dev = kzalloc(sizeof(struct serio), GFP_KERNEL); - ser_dev->id.type = SERIO_8042; + ser_dev->id.type = SERIO_PS_PSTHRU; ser_dev->write = ps2_sendcommand; ser_dev->start = ps2_startstreaming; ser_dev->stop = ps2_stopstreaming; -- cgit v0.10.2 From d3f862aec400dd831a4bdbea107fd85419bddab1 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Mon, 26 Dec 2011 17:57:38 +0100 Subject: staging: nvec: Fix typo s/I2C_SL_NEWL/I2C_SL_NEWSL/ The constant I2C_SL_NEWL meant "new slave", but the S was missing. Signed-off-by: Julian Andres Klode Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/nvec/nvec.c b/drivers/staging/nvec/nvec.c index fafdfa2..b6108af 100644 --- a/drivers/staging/nvec/nvec.c +++ b/drivers/staging/nvec/nvec.c @@ -49,7 +49,7 @@ #define I2C_CNFG_DEBOUNCE_CNT_SHIFT 12 #define I2C_SL_CNFG 0x20 -#define I2C_SL_NEWL (1<<2) +#define I2C_SL_NEWSL (1<<2) #define I2C_SL_NACK (1<<1) #define I2C_SL_RESP (1<<0) #define I2C_SL_IRQ (1<<3) @@ -687,7 +687,7 @@ static void tegra_init_i2c_slave(struct nvec_chip *nvec) clk_set_rate(nvec->i2c_clk, 8 * 80000); - writel(I2C_SL_NEWL, nvec->base + I2C_SL_CNFG); + writel(I2C_SL_NEWSL, nvec->base + I2C_SL_CNFG); writel(0x1E, nvec->base + I2C_SL_DELAY_COUNT); writel(nvec->i2c_addr>>1, nvec->base + I2C_SL_ADDR1); @@ -701,7 +701,7 @@ static void tegra_init_i2c_slave(struct nvec_chip *nvec) static void nvec_disable_i2c_slave(struct nvec_chip *nvec) { disable_irq(nvec->irq); - writel(I2C_SL_NEWL | I2C_SL_NACK, nvec->base + I2C_SL_CNFG); + writel(I2C_SL_NEWSL | I2C_SL_NACK, nvec->base + I2C_SL_CNFG); clk_disable(nvec->i2c_clk); } -- cgit v0.10.2 From aed92bbcf4ce760c4d7848013a0db3bdd4ae9492 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Mon, 26 Dec 2011 17:57:39 +0100 Subject: staging: nvec: Use gpio_request_one() instead of gpio_request() This saves us some calls and thus makes the code shorter and nicer. Signed-off-by: Julian Andres Klode Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/nvec/nvec.c b/drivers/staging/nvec/nvec.c index b6108af..3c60088 100644 --- a/drivers/staging/nvec/nvec.c +++ b/drivers/staging/nvec/nvec.c @@ -784,11 +784,6 @@ static int __devinit tegra_nvec_probe(struct platform_device *pdev) nvec->i2c_clk = i2c_clk; nvec->rx = &nvec->msg_pool[0]; - /* Set the gpio to low when we've got something to say */ - err = gpio_request(nvec->gpio, "nvec gpio"); - if (err < 0) - dev_err(nvec->dev, "couldn't request gpio\n"); - ATOMIC_INIT_NOTIFIER_HEAD(&nvec->notifier_list); init_completion(&nvec->sync_write); @@ -802,6 +797,12 @@ static int __devinit tegra_nvec_probe(struct platform_device *pdev) INIT_WORK(&nvec->tx_work, nvec_request_master); nvec->wq = alloc_workqueue("nvec", WQ_NON_REENTRANT, 2); + err = gpio_request_one(nvec->gpio, GPIOF_OUT_INIT_HIGH, "nvec gpio"); + if (err < 0) { + dev_err(nvec->dev, "couldn't request gpio\n"); + goto failed; + } + err = request_irq(nvec->irq, nvec_interrupt, 0, "nvec", nvec); if (err) { dev_err(nvec->dev, "couldn't request irq\n"); @@ -813,8 +814,6 @@ static int __devinit tegra_nvec_probe(struct platform_device *pdev) clk_enable(i2c_clk); - gpio_direction_output(nvec->gpio, 1); - gpio_set_value(nvec->gpio, 1); /* enable event reporting */ nvec_write_async(nvec, EC_ENABLE_EVENT_REPORTING, -- cgit v0.10.2 From e96045a7c837200e65c9fa8f8a94020bc2107931 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Mon, 26 Dec 2011 17:57:40 +0100 Subject: staging: nvec: Fix Kconfig dependencies nvec modules do not require other stuff to be build in, nor does nvec_ps2 require mouse support, only generic serio support. Signed-off-by: Julian Andres Klode Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/nvec/Kconfig b/drivers/staging/nvec/Kconfig index 86a8b8c..731301f 100644 --- a/drivers/staging/nvec/Kconfig +++ b/drivers/staging/nvec/Kconfig @@ -7,21 +7,21 @@ config MFD_NVEC config KEYBOARD_NVEC bool "Keyboard on nVidia compliant EC" - depends on MFD_NVEC && INPUT=y + depends on MFD_NVEC && INPUT help Say Y here to enable support for a keyboard connected to a nVidia compliant embedded controller. config SERIO_NVEC_PS2 bool "PS2 on nVidia EC" - depends on MFD_NVEC && MOUSE_PS2 + depends on MFD_NVEC && SERIO help Say Y here to enable support for a Touchpad / Mouse connected to a nVidia compliant embedded controller. config NVEC_POWER bool "NVEC charger and battery" - depends on MFD_NVEC && POWER_SUPPLY=y + depends on MFD_NVEC && POWER_SUPPLY help Say Y to enable support for battery and charger interface for nVidia compliant embedded controllers. -- cgit v0.10.2 From 28aa41fb8d555b120edefd7fdf879b156a1c9f3a Mon Sep 17 00:00:00 2001 From: Greg Dietsche Date: Sun, 15 Jan 2012 14:44:34 -0600 Subject: staging: android: ram_console use kmemdup instead of kmalloc Replace kmalloc + memcpy will kmemdup in ram_console_late_init Signed-off-by: Greg Dietsche Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/android/ram_console.c b/drivers/staging/android/ram_console.c index 6d4d679..0cb3f3c 100644 --- a/drivers/staging/android/ram_console.c +++ b/drivers/staging/android/ram_console.c @@ -411,15 +411,14 @@ static int __init ram_console_late_init(void) if (ram_console_old_log == NULL) return 0; #ifdef CONFIG_ANDROID_RAM_CONSOLE_EARLY_INIT - ram_console_old_log = kmalloc(ram_console_old_log_size, GFP_KERNEL); + ram_console_old_log = kmemdup(ram_console_old_log_init_buffer, + ram_console_old_log_size, GFP_KERNEL); if (ram_console_old_log == NULL) { printk(KERN_ERR "ram_console: failed to allocate buffer for old log\n"); ram_console_old_log_size = 0; return 0; } - memcpy(ram_console_old_log, - ram_console_old_log_init_buffer, ram_console_old_log_size); #endif entry = create_proc_entry("last_kmsg", S_IFREG | S_IRUGO, NULL); if (!entry) { -- cgit v0.10.2 From 217218f002a669905701cc0baa18a8d6ba1d5e21 Mon Sep 17 00:00:00 2001 From: "Justin P. Mattock" Date: Thu, 12 Jan 2012 06:51:31 -0800 Subject: drivers:staging:android Typos: fix some comments that have typos in them. Below is a patch that fixes some typos in some comments. Signed-off-by: Justin P. Mattock Cc: Randy Dunlap Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/android/TODO b/drivers/staging/android/TODO index e59c5be..b15fb0d 100644 --- a/drivers/staging/android/TODO +++ b/drivers/staging/android/TODO @@ -3,7 +3,7 @@ TODO: - sparse fixes - rename files to be not so "generic" - make sure things build as modules properly - - add proper arch dependancies as needed + - add proper arch dependencies as needed - audit userspace interfaces to make sure they are sane Please send patches to Greg Kroah-Hartman and Cc: diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index 7491801..e748756 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -257,7 +257,7 @@ struct binder_ref { }; struct binder_buffer { - struct list_head entry; /* free and allocated entries by addesss */ + struct list_head entry; /* free and allocated entries by address */ struct rb_node rb_node; /* free entry by size or allocated entry */ /* by address */ unsigned free:1; -- cgit v0.10.2 From 8d438bef6556315a23781fd673f13f7bfb94047d Mon Sep 17 00:00:00 2001 From: Thomas Meyer Date: Sun, 22 Jan 2012 18:34:58 +0100 Subject: Staging: android: ram_console: Use resource_size function The semantic patch that makes this change is available in scripts/coccinelle/api/resource_size.cocci. More information about semantic patching is available at http://coccinelle.lip6.fr/ Signed-off-by: Thomas Meyer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/android/ram_console.c b/drivers/staging/android/ram_console.c index 0cb3f3c..fabd398 100644 --- a/drivers/staging/android/ram_console.c +++ b/drivers/staging/android/ram_console.c @@ -351,7 +351,7 @@ static int ram_console_driver_probe(struct platform_device *pdev) "%lx\n", res, pdev->num_resources, res ? res->flags : 0); return -ENXIO; } - buffer_size = res->end - res->start + 1; + buffer_size = resource_size(res); start = res->start; printk(KERN_INFO "ram_console: got buffer at %zx, size %zx\n", start, buffer_size); -- cgit v0.10.2 From aa5af974127d317071d6225a0f3678c5f520e7ce Mon Sep 17 00:00:00 2001 From: Tracey Dent Date: Sun, 22 Jan 2012 21:28:44 -0500 Subject: drivers/staging/android/ashmem.c: Cleanups Minor cleanups that consist of removal of a whitespace and make file_operations const. Signed-off-by: Tracey Dent Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/android/ashmem.c b/drivers/staging/android/ashmem.c index 99052bf..9f1f27e 100644 --- a/drivers/staging/android/ashmem.c +++ b/drivers/staging/android/ashmem.c @@ -315,7 +315,7 @@ static int ashmem_mmap(struct file *file, struct vm_area_struct *vma) get_file(asma->file); /* - * XXX - Reworked to use shmem_zero_setup() instead of + * XXX - Reworked to use shmem_zero_setup() instead of * shmem_set_file while we're in staging. -jstultz */ if (vma->vm_flags & VM_SHARED) { @@ -680,7 +680,7 @@ static long ashmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return ret; } -static struct file_operations ashmem_fops = { +static const struct file_operations ashmem_fops = { .owner = THIS_MODULE, .open = ashmem_open, .release = ashmem_release, -- cgit v0.10.2 From e3251e0d7921fbedfe61cb237c6ce6c273bd93a7 Mon Sep 17 00:00:00 2001 From: Tracey Dent Date: Sun, 22 Jan 2012 21:28:46 -0500 Subject: drivers/staging/android/timed_gpio.c: Stlye fixes Just made it more neat and not bother scripts/checkpatch.pl Signed-off-by: Tracey Dent Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/android/timed_gpio.c b/drivers/staging/android/timed_gpio.c index a64481c..bc723ef 100644 --- a/drivers/staging/android/timed_gpio.c +++ b/drivers/staging/android/timed_gpio.c @@ -29,9 +29,9 @@ struct timed_gpio_data { struct timed_output_dev dev; struct hrtimer timer; spinlock_t lock; - unsigned gpio; - int max_timeout; - u8 active_low; + unsigned gpio; + int max_timeout; + u8 active_low; }; static enum hrtimer_restart gpio_timer_func(struct hrtimer *timer) -- cgit v0.10.2 From c626224de9370ae783e8b0cb6aaca2ba3d81fe62 Mon Sep 17 00:00:00 2001 From: Tim Bird Date: Tue, 7 Feb 2012 18:26:38 -0800 Subject: staging: android: logger: Change logger_offset() from macro to function Convert to function and add log as a parameter, rather than relying on log in the context of the macro. Signed-off-by: Tim Bird Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/android/logger.c b/drivers/staging/android/logger.c index ffc2d04..29ee137 100644 --- a/drivers/staging/android/logger.c +++ b/drivers/staging/android/logger.c @@ -60,7 +60,11 @@ struct logger_reader { }; /* logger_offset - returns index 'n' into the log via (optimized) modulus */ -#define logger_offset(n) ((n) & (log->size - 1)) +size_t logger_offset(struct logger_log *log, size_t n) +{ + return n & (log->size-1); +} + /* * file_get_log - Given a file structure, return the associated log @@ -137,7 +141,7 @@ static ssize_t do_read_log_to_user(struct logger_log *log, if (copy_to_user(buf + len, log->buffer, count - len)) return -EFAULT; - reader->r_off = logger_offset(reader->r_off + count); + reader->r_off = logger_offset(log, reader->r_off + count); return count; } @@ -225,7 +229,7 @@ static size_t get_next_entry(struct logger_log *log, size_t off, size_t len) do { size_t nr = get_entry_len(log, off); - off = logger_offset(off + nr); + off = logger_offset(log, off + nr); count += nr; } while (count < len); @@ -260,7 +264,7 @@ static inline int clock_interval(size_t a, size_t b, size_t c) static void fix_up_readers(struct logger_log *log, size_t len) { size_t old = log->w_off; - size_t new = logger_offset(old + len); + size_t new = logger_offset(log, old + len); struct logger_reader *reader; if (clock_interval(old, new, log->head)) @@ -286,7 +290,7 @@ static void do_write_log(struct logger_log *log, const void *buf, size_t count) if (count != len) memcpy(log->buffer, buf + len, count - len); - log->w_off = logger_offset(log->w_off + count); + log->w_off = logger_offset(log, log->w_off + count); } @@ -311,7 +315,7 @@ static ssize_t do_write_log_from_user(struct logger_log *log, if (copy_from_user(log->buffer, buf + len, count - len)) return -EFAULT; - log->w_off = logger_offset(log->w_off + count); + log->w_off = logger_offset(log, log->w_off + count); return count; } -- cgit v0.10.2 From 3bcfa431334d99fa8bff96c4e7c2108f0b26242e Mon Sep 17 00:00:00 2001 From: Tim Bird Date: Wed, 8 Feb 2012 10:37:57 -0800 Subject: staging: android: logger: simplify and optimize get_entry_len Make this code slightly easier to read, and eliminate calls to sub-routines. Some of these were previously optimized away by the compiler, but one memcpy was not. In my testing, this makes the code about 20% smaller, and has no sub-routine calls and no branches (on ARM). v2 of this patch is, IMHO, easier to read than v1. Compared to that patch it uses __u8 instead of unsigned char, for consistency with the __u16 val data type, simplifies the conditional expression, adds a another comment, and moves a common statement out of the if. Signed-off-by: Tim Bird Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/android/logger.c b/drivers/staging/android/logger.c index 29ee137..1e9e638 100644 --- a/drivers/staging/android/logger.c +++ b/drivers/staging/android/logger.c @@ -93,20 +93,24 @@ static inline struct logger_log *file_get_log(struct file *file) * get_entry_len - Grabs the length of the payload of the next entry starting * from 'off'. * + * An entry length is 2 bytes (16 bits) in host endian order. + * In the log, the length does not include the size of the log entry structure. + * This function returns the size including the log entry structure. + * * Caller needs to hold log->mutex. */ static __u32 get_entry_len(struct logger_log *log, size_t off) { __u16 val; - switch (log->size - off) { - case 1: - memcpy(&val, log->buffer + off, 1); - memcpy(((char *) &val) + 1, log->buffer, 1); - break; - default: - memcpy(&val, log->buffer + off, 2); - } + /* copy 2 bytes from buffer, in memcpy order, */ + /* handling possible wrap at end of buffer */ + + ((__u8 *)&val)[0] = log->buffer[off]; + if (likely(off+1 < log->size)) + ((__u8 *)&val)[1] = log->buffer[off+1]; + else + ((__u8 *)&val)[1] = log->buffer[0]; return sizeof(struct logger_entry) + val; } -- cgit v0.10.2 From c76c7ca31f16c9556cad527bfa3504b0aafb3045 Mon Sep 17 00:00:00 2001 From: Tim Bird Date: Tue, 7 Feb 2012 18:30:09 -0800 Subject: staging: android: logger: reorder prepare_to_wait and mutex_lock If mutex_lock waits, it will return in state TASK_RUNNING, rubbing out the effect of prepare_to_wait(). Signed-off-by: Tim Bird Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/android/logger.c b/drivers/staging/android/logger.c index 1e9e638..6dd6f04 100644 --- a/drivers/staging/android/logger.c +++ b/drivers/staging/android/logger.c @@ -172,9 +172,10 @@ static ssize_t logger_read(struct file *file, char __user *buf, start: while (1) { + mutex_lock(&log->mutex); + prepare_to_wait(&log->wq, &wait, TASK_INTERRUPTIBLE); - mutex_lock(&log->mutex); ret = (log->w_off == reader->r_off); mutex_unlock(&log->mutex); if (!ret) -- cgit v0.10.2 From 169c843afffcb328390ef39ff95227596d6f63c4 Mon Sep 17 00:00:00 2001 From: Tim Bird Date: Tue, 7 Feb 2012 18:32:02 -0800 Subject: staging: android: logger: clarify code in clock_interval Add commentary, rename the function and make the code easier to read. Signed-off-by: Tim Bird Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/android/logger.c b/drivers/staging/android/logger.c index 6dd6f04..6d92b7e 100644 --- a/drivers/staging/android/logger.c +++ b/drivers/staging/android/logger.c @@ -242,16 +242,28 @@ static size_t get_next_entry(struct logger_log *log, size_t off, size_t len) } /* - * clock_interval - is a < c < b in mod-space? Put another way, does the line - * from a to b cross c? + * is_between - is a < c < b, accounting for wrapping of a, b, and c + * positions in the buffer + * + * That is, if ab, check for c outside (not between) a and b + * + * |------- a xxxxxxxx b --------| + * c^ + * + * |xxxxx b --------- a xxxxxxxxx| + * c^ + * or c^ */ -static inline int clock_interval(size_t a, size_t b, size_t c) +static inline int is_between(size_t a, size_t b, size_t c) { - if (b < a) { - if (a < c || b >= c) + if (a < b) { + /* is c between a and b? */ + if (a < c && c <= b) return 1; } else { - if (a < c && b >= c) + /* is c outside of b through a? */ + if (c <= b || a < c) return 1; } @@ -272,11 +284,11 @@ static void fix_up_readers(struct logger_log *log, size_t len) size_t new = logger_offset(log, old + len); struct logger_reader *reader; - if (clock_interval(old, new, log->head)) + if (is_between(old, new, log->head)) log->head = get_next_entry(log, log->head, len); list_for_each_entry(reader, &log->readers, list) - if (clock_interval(old, new, reader->r_off)) + if (is_between(old, new, reader->r_off)) reader->r_off = get_next_entry(log, reader->r_off, len); } -- cgit v0.10.2 From 350a1955957d73352c043d0f948e3f28bb118c57 Mon Sep 17 00:00:00 2001 From: Tim Bird Date: Tue, 7 Feb 2012 18:34:28 -0800 Subject: staging: android: logger: clarify non-update of w_off in do_write_log_from_user Add comment to explain when w_off is not updated in case of failed second fragment copy to buffer. Signed-off-by: Tim Bird Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/android/logger.c b/drivers/staging/android/logger.c index 6d92b7e..0d2367f 100644 --- a/drivers/staging/android/logger.c +++ b/drivers/staging/android/logger.c @@ -330,6 +330,12 @@ static ssize_t do_write_log_from_user(struct logger_log *log, if (count != len) if (copy_from_user(log->buffer, buf + len, count - len)) + /* + * Note that by not updating w_off, this abandons the + * portion of the new entry that *was* successfully + * copied, just above. This is intentional to avoid + * message corruption from missing fragments. + */ return -EFAULT; log->w_off = logger_offset(log, log->w_off + count); -- cgit v0.10.2 From 294b27119f2e20643e71a0c1a1b511320a11e4c3 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Mon, 6 Feb 2012 20:29:41 +0400 Subject: staging: android/lowmemorykiller: Don't grab tasklist_lock Grabbing tasklist_lock has its disadvantages, i.e. it blocks process creation and destruction. If there are lots of processes, blocking doesn't sound as a great idea. For LMK, it is sufficient to surround tasks list traverse with rcu_read_{,un}lock(). >From now on using force_sig() is not safe, as it can race with an already exiting task, so we use send_sig() now. As a downside, it won't kill PID namespace init processes, but that's not what we want anyway. Suggested-by: Oleg Nesterov Signed-off-by: Anton Vorontsov Reviewed-by: Oleg Nesterov Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c index 2d8d2b7..63da844 100644 --- a/drivers/staging/android/lowmemorykiller.c +++ b/drivers/staging/android/lowmemorykiller.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -132,7 +133,7 @@ static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc) } selected_oom_adj = min_adj; - read_lock(&tasklist_lock); + rcu_read_lock(); for_each_process(p) { struct mm_struct *mm; struct signal_struct *sig; @@ -180,12 +181,12 @@ static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc) lowmem_deathpending = selected; task_handoff_register(&task_nb); #endif - force_sig(SIGKILL, selected); + send_sig(SIGKILL, selected, 0); rem -= selected_tasksize; } lowmem_print(4, "lowmem_shrink %lu, %x, return %d\n", sc->nr_to_scan, sc->gfp_mask, rem); - read_unlock(&tasklist_lock); + rcu_read_unlock(); return rem; } -- cgit v0.10.2 From 95670001188911f9d466875cd68e3681f39df38a Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Mon, 6 Feb 2012 20:29:47 +0400 Subject: staging: android/lowmemorykiller: Better mm handling LMK should not directly check for task->mm. The reason is that the process' threads may exit or detach its mm via use_mm(), but other threads may still have a valid mm. To catch this we use find_lock_task_mm(), which walks up all threads and returns an appropriate task (with lock held). Suggested-by: Oleg Nesterov Reviewed-by: Oleg Nesterov Signed-off-by: Anton Vorontsov Acked-by: KOSAKI Motohiro Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c index 63da844..0755e2f 100644 --- a/drivers/staging/android/lowmemorykiller.c +++ b/drivers/staging/android/lowmemorykiller.c @@ -82,7 +82,7 @@ task_notify_func(struct notifier_block *self, unsigned long val, void *data) static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc) { - struct task_struct *p; + struct task_struct *tsk; struct task_struct *selected = NULL; int rem = 0; int tasksize; @@ -134,15 +134,17 @@ static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc) selected_oom_adj = min_adj; rcu_read_lock(); - for_each_process(p) { - struct mm_struct *mm; + for_each_process(tsk) { + struct task_struct *p; struct signal_struct *sig; int oom_adj; - task_lock(p); - mm = p->mm; + p = find_lock_task_mm(tsk); + if (!p) + continue; + sig = p->signal; - if (!mm || !sig) { + if (!sig) { task_unlock(p); continue; } @@ -151,7 +153,7 @@ static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc) task_unlock(p); continue; } - tasksize = get_mm_rss(mm); + tasksize = get_mm_rss(p->mm); task_unlock(p); if (tasksize <= 0) continue; -- cgit v0.10.2 From 353416099128914a684e8bb81e7475d8c2961cc3 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Mon, 6 Feb 2012 20:29:54 +0400 Subject: staging: android/lowmemorykiller: No need for task->signal check task->signal == NULL is not possible, so no need for these checks. Suggested-by: Oleg Nesterov Reviewed-by: Oleg Nesterov Signed-off-by: Anton Vorontsov Acked-by: KOSAKI Motohiro Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c index 0755e2f..6e800d3 100644 --- a/drivers/staging/android/lowmemorykiller.c +++ b/drivers/staging/android/lowmemorykiller.c @@ -136,19 +136,13 @@ static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc) rcu_read_lock(); for_each_process(tsk) { struct task_struct *p; - struct signal_struct *sig; int oom_adj; p = find_lock_task_mm(tsk); if (!p) continue; - sig = p->signal; - if (!sig) { - task_unlock(p); - continue; - } - oom_adj = sig->oom_adj; + oom_adj = p->signal->oom_adj; if (oom_adj < min_adj) { task_unlock(p); continue; -- cgit v0.10.2 From 9823ec9ded836ee7ca4fe5ab7964b9cdc8af010c Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Mon, 6 Feb 2012 20:30:01 +0400 Subject: staging: android/lowmemorykiller: Do not kill kernel threads LMK should not try killing kernel threads. Suggested-by: Oleg Nesterov Reviewed-by: Oleg Nesterov Signed-off-by: Anton Vorontsov Acked-by: KOSAKI Motohiro Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c index 6e800d3..ae38c39 100644 --- a/drivers/staging/android/lowmemorykiller.c +++ b/drivers/staging/android/lowmemorykiller.c @@ -138,6 +138,9 @@ static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc) struct task_struct *p; int oom_adj; + if (tsk->flags & PF_KTHREAD) + continue; + p = find_lock_task_mm(tsk); if (!p) continue; -- cgit v0.10.2 From 6222d7a17745f6e48fddda7245e4bb0d58bfeaf0 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 30 Jan 2012 14:54:48 -0800 Subject: telephony: Move to staging This stuff is really old and in quite poor shape. Does anyone still use it? If not, I think it's appropriate to let it simmer in staging for a few releases. Signed-off-by: Joe Perches Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/Kconfig b/drivers/Kconfig index 5afe5d1..decf8e4 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -40,8 +40,6 @@ source "drivers/net/Kconfig" source "drivers/isdn/Kconfig" -source "drivers/telephony/Kconfig" - # input before char - char/joystick depends on it. As does USB. source "drivers/input/Kconfig" diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 21e2f4b..aaba36c 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -132,4 +132,6 @@ source "drivers/staging/omapdrm/Kconfig" source "drivers/staging/android/Kconfig" +source "drivers/staging/telephony/Kconfig" + endif # STAGING diff --git a/drivers/staging/telephony/Kconfig b/drivers/staging/telephony/Kconfig new file mode 100644 index 0000000..b5f78b6 --- /dev/null +++ b/drivers/staging/telephony/Kconfig @@ -0,0 +1,47 @@ +# +# Telephony device configuration +# + +menuconfig PHONE + tristate "Telephony support" + depends on HAS_IOMEM + ---help--- + Say Y here if you have a telephony card, which for example allows + you to use a regular phone for voice-over-IP applications. + + Note: this has nothing to do with modems. You do not need to say Y + here in order to be able to use a modem under Linux. + + To compile this driver as a module, choose M here: the + module will be called phonedev. + +if PHONE + +config PHONE_IXJ + tristate "QuickNet Internet LineJack/PhoneJack support" + depends on ISA || PCI + ---help--- + Say M if you have a telephony card manufactured by Quicknet + Technologies, Inc. These include the Internet PhoneJACK and + Internet LineJACK Telephony Cards. You will get a module called + ixj. + + For the ISA versions of these products, you can configure the + cards using the isapnp tools (pnpdump/isapnp) or you can use the + isapnp support. Please read . + + For more information on these cards, see Quicknet's web site at: + . + + If you do not have any Quicknet telephony cards, you can safely + say N here. + +config PHONE_IXJ_PCMCIA + tristate "QuickNet Internet LineJack/PhoneJack PCMCIA support" + depends on PHONE_IXJ && PCMCIA + help + Say Y here to configure in PCMCIA service support for the Quicknet + cards manufactured by Quicknet Technologies, Inc. This changes the + card initialization code to work with the card manager daemon. + +endif # PHONE diff --git a/drivers/staging/telephony/Makefile b/drivers/staging/telephony/Makefile new file mode 100644 index 0000000..1206615 --- /dev/null +++ b/drivers/staging/telephony/Makefile @@ -0,0 +1,7 @@ +# +# Makefile for drivers/telephony +# + +obj-$(CONFIG_PHONE) += phonedev.o +obj-$(CONFIG_PHONE_IXJ) += ixj.o +obj-$(CONFIG_PHONE_IXJ_PCMCIA) += ixj_pcmcia.o diff --git a/drivers/staging/telephony/TODO b/drivers/staging/telephony/TODO new file mode 100644 index 0000000..d47dec3 --- /dev/null +++ b/drivers/staging/telephony/TODO @@ -0,0 +1,10 @@ +TODO +. Determine if the boards are still in use + and move this module back to drivers/telephony if necessary +. Coding style cleanups + +Please send patches to Greg Kroah-Hartman and +cc Joe Perches if the module should be reactivated. + +If no module activity occurs before version 3.6 is released, this +module should be removed. diff --git a/drivers/staging/telephony/ixj-ver.h b/drivers/staging/telephony/ixj-ver.h new file mode 100644 index 0000000..2031ac6c --- /dev/null +++ b/drivers/staging/telephony/ixj-ver.h @@ -0,0 +1,4 @@ +/* configuration management identifiers */ +#define IXJ_VER_MAJOR 1 +#define IXJ_VER_MINOR 0 +#define IXJ_BLD_VER 1 diff --git a/drivers/staging/telephony/ixj.c b/drivers/staging/telephony/ixj.c new file mode 100644 index 0000000..d5f923b --- /dev/null +++ b/drivers/staging/telephony/ixj.c @@ -0,0 +1,10552 @@ +/**************************************************************************** + * ixj.c + * + * Device Driver for Quicknet Technologies, Inc.'s Telephony cards + * including the Internet PhoneJACK, Internet PhoneJACK Lite, + * Internet PhoneJACK PCI, Internet LineJACK, Internet PhoneCARD and + * SmartCABLE + * + * (c) Copyright 1999-2001 Quicknet Technologies, Inc. + * + * 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. + * + * Author: Ed Okerson, + * + * Contributors: Greg Herlein, + * David W. Erhart, + * John Sellers, + * Mike Preston, + * + * Fixes: David Huggins-Daines, + * Fabio Ferrari, + * Artis Kugevics, + * Daniele Bellucci, + * + * More information about the hardware related to this driver can be found + * at our website: http://www.quicknet.net + * + * IN NO EVENT SHALL QUICKNET TECHNOLOGIES, INC. BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF QUICKNET + * TECHNOLOGIES, INC. HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * QUICKNET TECHNOLOGIES, INC. SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND QUICKNET TECHNOLOGIES, INC. HAS NO OBLIGATION + * TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + ***************************************************************************/ + +/* + * Revision 4.8 2003/07/09 19:39:00 Daniele Bellucci + * Audit some copy_*_user and minor cleanup. + * + * Revision 4.7 2001/08/13 06:19:33 craigs + * Added additional changes from Alan Cox and John Anderson for + * 2.2 to 2.4 cleanup and bounds checking + * + * Revision 4.6 2001/08/13 01:05:05 craigs + * Really fixed PHONE_QUERY_CODEC problem this time + * + * Revision 4.5 2001/08/13 00:11:03 craigs + * Fixed problem in handling of PHONE_QUERY_CODEC, thanks to Shane Anderson + * + * Revision 4.4 2001/08/07 07:58:12 craigs + * Changed back to three digit version numbers + * Added tagbuild target to allow automatic and easy tagging of versions + * + * Revision 4.3 2001/08/07 07:24:47 craigs + * Added ixj-ver.h to allow easy configuration management of driver + * Added display of version number in /prox/ixj + * + * Revision 4.2 2001/08/06 07:07:19 craigs + * Reverted IXJCTL_DSP_TYPE and IXJCTL_DSP_VERSION files to original + * behaviour of returning int rather than short * + * + * Revision 4.1 2001/08/05 00:17:37 craigs + * More changes for correct PCMCIA installation + * Start of changes for backward Linux compatibility + * + * Revision 4.0 2001/08/04 12:33:12 craigs + * New version using GNU autoconf + * + * Revision 3.105 2001/07/20 23:14:32 eokerson + * More work on CallerID generation when using ring cadences. + * + * Revision 3.104 2001/07/06 01:33:55 eokerson + * Some bugfixes from Robert Vojta and a few mods to the Makefile. + * + * Revision 3.103 2001/07/05 19:20:16 eokerson + * Updated HOWTO + * Changed mic gain to 30dB on Internet LineJACK mic/speaker port. + * + * Revision 3.102 2001/07/03 23:51:21 eokerson + * Un-mute mic on Internet LineJACK when in speakerphone mode. + * + * Revision 3.101 2001/07/02 19:26:56 eokerson + * Removed initialiazation of ixjdebug and ixj_convert_loaded so they will go in the .bss instead of the .data + * + * Revision 3.100 2001/07/02 19:18:27 eokerson + * Changed driver to make dynamic allocation possible. We now pass IXJ * between functions instead of array indexes. + * Fixed the way the POTS and PSTN ports interact during a PSTN call to allow local answering. + * Fixed speaker mode on Internet LineJACK. + * + * Revision 3.99 2001/05/09 14:11:16 eokerson + * Fixed kmalloc error in ixj_build_filter_cadence. Thanks David Chan . + * + * Revision 3.98 2001/05/08 19:55:33 eokerson + * Fixed POTS hookstate detection while it is connected to PSTN port. + * + * Revision 3.97 2001/05/08 00:01:04 eokerson + * Fixed kernel oops when sending caller ID data. + * + * Revision 3.96 2001/05/04 23:09:30 eokerson + * Now uses one kernel timer for each card, instead of one for the entire driver. + * + * Revision 3.95 2001/04/25 22:06:47 eokerson + * Fixed squawking at beginning of some G.723.1 calls. + * + * Revision 3.94 2001/04/03 23:42:00 eokerson + * Added linear volume ioctls + * Added raw filter load ioctl + * + * Revision 3.93 2001/02/27 01:00:06 eokerson + * Fixed blocking in CallerID. + * Reduced size of ixj structure for smaller driver footprint. + * + * Revision 3.92 2001/02/20 22:02:59 eokerson + * Fixed isapnp and pcmcia module compatibility for 2.4.x kernels. + * Improved PSTN ring detection. + * Fixed wink generation on POTS ports. + * + * Revision 3.91 2001/02/13 00:55:44 eokerson + * Turn AEC back on after changing frame sizes. + * + * Revision 3.90 2001/02/12 16:42:00 eokerson + * Added ALAW codec, thanks to Fabio Ferrari for the table based converters to make ALAW from ULAW. + * + * Revision 3.89 2001/02/12 15:41:16 eokerson + * Fix from Artis Kugevics - Tone gains were not being set correctly. + * + * Revision 3.88 2001/02/05 23:25:42 eokerson + * Fixed lockup bugs with deregister. + * + * Revision 3.87 2001/01/29 21:00:39 eokerson + * Fix from Fabio Ferrari to properly handle EAGAIN and EINTR during non-blocking write. + * Updated copyright date. + * + * Revision 3.86 2001/01/23 23:53:46 eokerson + * Fixes to G.729 compatibility. + * + * Revision 3.85 2001/01/23 21:30:36 eokerson + * Added verbage about cards supported. + * Removed commands that put the card in low power mode at some times that it should not be in low power mode. + * + * Revision 3.84 2001/01/22 23:32:10 eokerson + * Some bugfixes from David Huggins-Daines, and other cleanups. + * + * Revision 3.83 2001/01/19 14:51:41 eokerson + * Fixed ixj_WriteDSPCommand to decrement usage counter when command fails. + * + * Revision 3.82 2001/01/19 00:34:49 eokerson + * Added verbosity to write overlap errors. + * + * Revision 3.81 2001/01/18 23:56:54 eokerson + * Fixed PSTN line test functions. + * + * Revision 3.80 2001/01/18 22:29:27 eokerson + * Updated AEC/AGC values for different cards. + * + * Revision 3.79 2001/01/17 02:58:54 eokerson + * Fixed AEC reset after Caller ID. + * Fixed Codec lockup after Caller ID on Call Waiting when not using 30ms frames. + * + * Revision 3.78 2001/01/16 19:43:09 eokerson + * Added support for Linux 2.4.x kernels. + * + * Revision 3.77 2001/01/09 04:00:52 eokerson + * Linetest will now test the line, even if it has previously succeeded. + * + * Revision 3.76 2001/01/08 19:27:00 eokerson + * Fixed problem with standard cable on Internet PhoneCARD. + * + * Revision 3.75 2000/12/22 16:52:14 eokerson + * Modified to allow hookstate detection on the POTS port when the PSTN port is selected. + * + * Revision 3.74 2000/12/08 22:41:50 eokerson + * Added capability for G729B. + * + * Revision 3.73 2000/12/07 23:35:16 eokerson + * Added capability to have different ring pattern before CallerID data. + * Added hookstate checks in CallerID routines to stop FSK. + * + * Revision 3.72 2000/12/06 19:31:31 eokerson + * Modified signal behavior to only send one signal per event. + * + * Revision 3.71 2000/12/06 03:23:08 eokerson + * Fixed CallerID on Call Waiting. + * + * Revision 3.70 2000/12/04 21:29:37 eokerson + * Added checking to Smart Cable gain functions. + * + * Revision 3.69 2000/12/04 21:05:20 eokerson + * Changed ixjdebug levels. + * Added ioctls to change gains in Internet Phone CARD Smart Cable. + * + * Revision 3.68 2000/12/04 00:17:21 craigs + * Changed mixer voice gain to +6dB rather than 0dB + * + * Revision 3.67 2000/11/30 21:25:51 eokerson + * Fixed write signal errors. + * + * Revision 3.66 2000/11/29 22:42:44 eokerson + * Fixed PSTN ring detect problems. + * + * Revision 3.65 2000/11/29 07:31:55 craigs + * Added new 425Hz filter co-efficients + * Added card-specific DTMF prescaler initialisation + * + * Revision 3.64 2000/11/28 14:03:32 craigs + * Changed certain mixer initialisations to be 0dB rather than 12dB + * Added additional information to /proc/ixj + * + * Revision 3.63 2000/11/28 11:38:41 craigs + * Added display of AEC modes in AUTO and AGC mode + * + * Revision 3.62 2000/11/28 04:05:44 eokerson + * Improved PSTN ring detection routine. + * + * Revision 3.61 2000/11/27 21:53:12 eokerson + * Fixed flash detection. + * + * Revision 3.60 2000/11/27 15:57:29 eokerson + * More work on G.729 load routines. + * + * Revision 3.59 2000/11/25 21:55:12 eokerson + * Fixed errors in G.729 load routine. + * + * Revision 3.58 2000/11/25 04:08:29 eokerson + * Added board locks around G.729 and TS85 load routines. + * + * Revision 3.57 2000/11/24 05:35:17 craigs + * Added ability to retrieve mixer values on LineJACK + * Added complete initialisation of all mixer values at startup + * Fixed spelling mistake + * + * Revision 3.56 2000/11/23 02:52:11 robertj + * Added cvs change log keyword. + * Fixed bug in capabilities list when using G.729 module. + * + */ + +#include "ixj-ver.h" + +#define PERFMON_STATS +#define IXJDEBUG 0 +#define MAXRINGS 5 + +#include + +#include +#include +#include /* printk() */ +#include /* everything... */ +#include /* error codes */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "ixj.h" + +#define TYPE(inode) (iminor(inode) >> 4) +#define NUM(inode) (iminor(inode) & 0xf) + +static DEFINE_MUTEX(ixj_mutex); +static int ixjdebug; +static int hertz = HZ; +static int samplerate = 100; + +module_param(ixjdebug, int, 0); + +static DEFINE_PCI_DEVICE_TABLE(ixj_pci_tbl) = { + { PCI_VENDOR_ID_QUICKNET, PCI_DEVICE_ID_QUICKNET_XJ, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { } +}; +MODULE_DEVICE_TABLE(pci, ixj_pci_tbl); + +/************************************************************************ +* +* ixjdebug meanings are now bit mapped instead of level based +* Values can be or'ed together to turn on multiple messages +* +* bit 0 (0x0001) = any failure +* bit 1 (0x0002) = general messages +* bit 2 (0x0004) = POTS ringing related +* bit 3 (0x0008) = PSTN events +* bit 4 (0x0010) = PSTN Cadence state details +* bit 5 (0x0020) = Tone detection triggers +* bit 6 (0x0040) = Tone detection cadence details +* bit 7 (0x0080) = ioctl tracking +* bit 8 (0x0100) = signal tracking +* bit 9 (0x0200) = CallerID generation details +* +************************************************************************/ + +#ifdef IXJ_DYN_ALLOC + +static IXJ *ixj[IXJMAX]; +#define get_ixj(b) ixj[(b)] + +/* + * Allocate a free IXJ device + */ + +static IXJ *ixj_alloc() +{ + for(cnt=0; cntDSPbase) + { + j = kmalloc(sizeof(IXJ), GFP_KERNEL); + if (j == NULL) + return NULL; + ixj[cnt] = j; + return j; + } + } + return NULL; +} + +static void ixj_fsk_free(IXJ *j) +{ + kfree(j->fskdata); + j->fskdata = NULL; +} + +static void ixj_fsk_alloc(IXJ *j) +{ + if(!j->fskdata) { + j->fskdata = kmalloc(8000, GFP_KERNEL); + if (!j->fskdata) { + if(ixjdebug & 0x0200) { + printk("IXJ phone%d - allocate failed\n", j->board); + } + return; + } else { + j->fsksize = 8000; + if(ixjdebug & 0x0200) { + printk("IXJ phone%d - allocate succeeded\n", j->board); + } + } + } +} + +#else + +static IXJ ixj[IXJMAX]; +#define get_ixj(b) (&ixj[(b)]) + +/* + * Allocate a free IXJ device + */ + +static IXJ *ixj_alloc(void) +{ + int cnt; + for(cnt=0; cntfsksize = 8000; +} + +#endif + +#ifdef PERFMON_STATS +#define ixj_perfmon(x) ((x)++) +#else +#define ixj_perfmon(x) do { } while(0) +#endif + +static int ixj_convert_loaded; + +static int ixj_WriteDSPCommand(unsigned short, IXJ *j); + +/************************************************************************ +* +* These are function definitions to allow external modules to register +* enhanced functionality call backs. +* +************************************************************************/ + +static int Stub(IXJ * J, unsigned long arg) +{ + return 0; +} + +static IXJ_REGFUNC ixj_PreRead = &Stub; +static IXJ_REGFUNC ixj_PostRead = &Stub; +static IXJ_REGFUNC ixj_PreWrite = &Stub; +static IXJ_REGFUNC ixj_PostWrite = &Stub; + +static void ixj_read_frame(IXJ *j); +static void ixj_write_frame(IXJ *j); +static void ixj_init_timer(IXJ *j); +static void ixj_add_timer(IXJ * j); +static void ixj_timeout(unsigned long ptr); +static int read_filters(IXJ *j); +static int LineMonitor(IXJ *j); +static int ixj_fasync(int fd, struct file *, int mode); +static int ixj_set_port(IXJ *j, int arg); +static int ixj_set_pots(IXJ *j, int arg); +static int ixj_hookstate(IXJ *j); +static int ixj_record_start(IXJ *j); +static void ixj_record_stop(IXJ *j); +static void set_rec_volume(IXJ *j, int volume); +static int get_rec_volume(IXJ *j); +static int set_rec_codec(IXJ *j, int rate); +static void ixj_vad(IXJ *j, int arg); +static int ixj_play_start(IXJ *j); +static void ixj_play_stop(IXJ *j); +static int ixj_set_tone_on(unsigned short arg, IXJ *j); +static int ixj_set_tone_off(unsigned short, IXJ *j); +static int ixj_play_tone(IXJ *j, char tone); +static void ixj_aec_start(IXJ *j, int level); +static int idle(IXJ *j); +static void ixj_ring_on(IXJ *j); +static void ixj_ring_off(IXJ *j); +static void aec_stop(IXJ *j); +static void ixj_ringback(IXJ *j); +static void ixj_busytone(IXJ *j); +static void ixj_dialtone(IXJ *j); +static void ixj_cpt_stop(IXJ *j); +static char daa_int_read(IXJ *j); +static char daa_CR_read(IXJ *j, int cr); +static int daa_set_mode(IXJ *j, int mode); +static int ixj_linetest(IXJ *j); +static int ixj_daa_write(IXJ *j); +static int ixj_daa_cid_read(IXJ *j); +static void DAA_Coeff_US(IXJ *j); +static void DAA_Coeff_UK(IXJ *j); +static void DAA_Coeff_France(IXJ *j); +static void DAA_Coeff_Germany(IXJ *j); +static void DAA_Coeff_Australia(IXJ *j); +static void DAA_Coeff_Japan(IXJ *j); +static int ixj_init_filter(IXJ *j, IXJ_FILTER * jf); +static int ixj_init_filter_raw(IXJ *j, IXJ_FILTER_RAW * jfr); +static int ixj_init_tone(IXJ *j, IXJ_TONE * ti); +static int ixj_build_cadence(IXJ *j, IXJ_CADENCE __user * cp); +static int ixj_build_filter_cadence(IXJ *j, IXJ_FILTER_CADENCE __user * cp); +/* Serial Control Interface funtions */ +static int SCI_Control(IXJ *j, int control); +static int SCI_Prepare(IXJ *j); +static int SCI_WaitHighSCI(IXJ *j); +static int SCI_WaitLowSCI(IXJ *j); +static DWORD PCIEE_GetSerialNumber(WORD wAddress); +static int ixj_PCcontrol_wait(IXJ *j); +static void ixj_pre_cid(IXJ *j); +static void ixj_write_cid(IXJ *j); +static void ixj_write_cid_bit(IXJ *j, int bit); +static int set_base_frame(IXJ *j, int size); +static int set_play_codec(IXJ *j, int rate); +static void set_rec_depth(IXJ *j, int depth); +static int ixj_mixer(long val, IXJ *j); + +/************************************************************************ +CT8020/CT8021 Host Programmers Model +Host address Function Access +DSPbase + +0-1 Aux Software Status Register (reserved) Read Only +2-3 Software Status Register Read Only +4-5 Aux Software Control Register (reserved) Read Write +6-7 Software Control Register Read Write +8-9 Hardware Status Register Read Only +A-B Hardware Control Register Read Write +C-D Host Transmit (Write) Data Buffer Access Port (buffer input)Write Only +E-F Host Receive (Read) Data Buffer Access Port (buffer input) Read Only +************************************************************************/ + +static inline void ixj_read_HSR(IXJ *j) +{ + j->hsr.bytes.low = inb_p(j->DSPbase + 8); + j->hsr.bytes.high = inb_p(j->DSPbase + 9); +} + +static inline int IsControlReady(IXJ *j) +{ + ixj_read_HSR(j); + return j->hsr.bits.controlrdy ? 1 : 0; +} + +static inline int IsPCControlReady(IXJ *j) +{ + j->pccr1.byte = inb_p(j->XILINXbase + 3); + return j->pccr1.bits.crr ? 1 : 0; +} + +static inline int IsStatusReady(IXJ *j) +{ + ixj_read_HSR(j); + return j->hsr.bits.statusrdy ? 1 : 0; +} + +static inline int IsRxReady(IXJ *j) +{ + ixj_read_HSR(j); + ixj_perfmon(j->rxreadycheck); + return j->hsr.bits.rxrdy ? 1 : 0; +} + +static inline int IsTxReady(IXJ *j) +{ + ixj_read_HSR(j); + ixj_perfmon(j->txreadycheck); + return j->hsr.bits.txrdy ? 1 : 0; +} + +static inline void set_play_volume(IXJ *j, int volume) +{ + if (ixjdebug & 0x0002) + printk(KERN_INFO "IXJ: /dev/phone%d Setting Play Volume to 0x%4.4x\n", j->board, volume); + ixj_WriteDSPCommand(0xCF02, j); + ixj_WriteDSPCommand(volume, j); +} + +static int set_play_volume_linear(IXJ *j, int volume) +{ + int newvolume, dspplaymax; + + if (ixjdebug & 0x0002) + printk(KERN_INFO "IXJ: /dev/phone %d Setting Linear Play Volume to 0x%4.4x\n", j->board, volume); + if(volume > 100 || volume < 0) { + return -1; + } + + /* This should normalize the perceived volumes between the different cards caused by differences in the hardware */ + switch (j->cardtype) { + case QTI_PHONEJACK: + dspplaymax = 0x380; + break; + case QTI_LINEJACK: + if(j->port == PORT_PSTN) { + dspplaymax = 0x48; + } else { + dspplaymax = 0x100; + } + break; + case QTI_PHONEJACK_LITE: + dspplaymax = 0x380; + break; + case QTI_PHONEJACK_PCI: + dspplaymax = 0x6C; + break; + case QTI_PHONECARD: + dspplaymax = 0x50; + break; + default: + return -1; + } + newvolume = (dspplaymax * volume) / 100; + set_play_volume(j, newvolume); + return 0; +} + +static inline void set_play_depth(IXJ *j, int depth) +{ + if (depth > 60) + depth = 60; + if (depth < 0) + depth = 0; + ixj_WriteDSPCommand(0x5280 + depth, j); +} + +static inline int get_play_volume(IXJ *j) +{ + ixj_WriteDSPCommand(0xCF00, j); + return j->ssr.high << 8 | j->ssr.low; +} + +static int get_play_volume_linear(IXJ *j) +{ + int volume, newvolume, dspplaymax; + + /* This should normalize the perceived volumes between the different cards caused by differences in the hardware */ + switch (j->cardtype) { + case QTI_PHONEJACK: + dspplaymax = 0x380; + break; + case QTI_LINEJACK: + if(j->port == PORT_PSTN) { + dspplaymax = 0x48; + } else { + dspplaymax = 0x100; + } + break; + case QTI_PHONEJACK_LITE: + dspplaymax = 0x380; + break; + case QTI_PHONEJACK_PCI: + dspplaymax = 0x6C; + break; + case QTI_PHONECARD: + dspplaymax = 100; + break; + default: + return -1; + } + volume = get_play_volume(j); + newvolume = (volume * 100) / dspplaymax; + if(newvolume > 100) + newvolume = 100; + return newvolume; +} + +static inline BYTE SLIC_GetState(IXJ *j) +{ + if (j->cardtype == QTI_PHONECARD) { + j->pccr1.byte = 0; + j->psccr.bits.dev = 3; + j->psccr.bits.rw = 1; + outw_p(j->psccr.byte << 8, j->XILINXbase + 0x00); + ixj_PCcontrol_wait(j); + j->pslic.byte = inw_p(j->XILINXbase + 0x00) & 0xFF; + ixj_PCcontrol_wait(j); + if (j->pslic.bits.powerdown) + return PLD_SLIC_STATE_OC; + else if (!j->pslic.bits.ring0 && !j->pslic.bits.ring1) + return PLD_SLIC_STATE_ACTIVE; + else + return PLD_SLIC_STATE_RINGING; + } else { + j->pld_slicr.byte = inb_p(j->XILINXbase + 0x01); + } + return j->pld_slicr.bits.state; +} + +static bool SLIC_SetState(BYTE byState, IXJ *j) +{ + bool fRetVal = false; + + if (j->cardtype == QTI_PHONECARD) { + if (j->flags.pcmciasct) { + switch (byState) { + case PLD_SLIC_STATE_TIPOPEN: + case PLD_SLIC_STATE_OC: + j->pslic.bits.powerdown = 1; + j->pslic.bits.ring0 = j->pslic.bits.ring1 = 0; + fRetVal = true; + break; + case PLD_SLIC_STATE_RINGING: + if (j->readers || j->writers) { + j->pslic.bits.powerdown = 0; + j->pslic.bits.ring0 = 1; + j->pslic.bits.ring1 = 0; + fRetVal = true; + } + break; + case PLD_SLIC_STATE_OHT: /* On-hook transmit */ + + case PLD_SLIC_STATE_STANDBY: + case PLD_SLIC_STATE_ACTIVE: + if (j->readers || j->writers) { + j->pslic.bits.powerdown = 0; + } else { + j->pslic.bits.powerdown = 1; + } + j->pslic.bits.ring0 = j->pslic.bits.ring1 = 0; + fRetVal = true; + break; + case PLD_SLIC_STATE_APR: /* Active polarity reversal */ + + case PLD_SLIC_STATE_OHTPR: /* OHT polarity reversal */ + + default: + fRetVal = false; + break; + } + j->psccr.bits.dev = 3; + j->psccr.bits.rw = 0; + outw_p(j->psccr.byte << 8 | j->pslic.byte, j->XILINXbase + 0x00); + ixj_PCcontrol_wait(j); + } + } else { + /* Set the C1, C2, C3 & B2EN signals. */ + switch (byState) { + case PLD_SLIC_STATE_OC: + j->pld_slicw.bits.c1 = 0; + j->pld_slicw.bits.c2 = 0; + j->pld_slicw.bits.c3 = 0; + j->pld_slicw.bits.b2en = 0; + outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); + fRetVal = true; + break; + case PLD_SLIC_STATE_RINGING: + j->pld_slicw.bits.c1 = 1; + j->pld_slicw.bits.c2 = 0; + j->pld_slicw.bits.c3 = 0; + j->pld_slicw.bits.b2en = 1; + outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); + fRetVal = true; + break; + case PLD_SLIC_STATE_ACTIVE: + j->pld_slicw.bits.c1 = 0; + j->pld_slicw.bits.c2 = 1; + j->pld_slicw.bits.c3 = 0; + j->pld_slicw.bits.b2en = 0; + outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); + fRetVal = true; + break; + case PLD_SLIC_STATE_OHT: /* On-hook transmit */ + + j->pld_slicw.bits.c1 = 1; + j->pld_slicw.bits.c2 = 1; + j->pld_slicw.bits.c3 = 0; + j->pld_slicw.bits.b2en = 0; + outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); + fRetVal = true; + break; + case PLD_SLIC_STATE_TIPOPEN: + j->pld_slicw.bits.c1 = 0; + j->pld_slicw.bits.c2 = 0; + j->pld_slicw.bits.c3 = 1; + j->pld_slicw.bits.b2en = 0; + outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); + fRetVal = true; + break; + case PLD_SLIC_STATE_STANDBY: + j->pld_slicw.bits.c1 = 1; + j->pld_slicw.bits.c2 = 0; + j->pld_slicw.bits.c3 = 1; + j->pld_slicw.bits.b2en = 1; + outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); + fRetVal = true; + break; + case PLD_SLIC_STATE_APR: /* Active polarity reversal */ + + j->pld_slicw.bits.c1 = 0; + j->pld_slicw.bits.c2 = 1; + j->pld_slicw.bits.c3 = 1; + j->pld_slicw.bits.b2en = 0; + outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); + fRetVal = true; + break; + case PLD_SLIC_STATE_OHTPR: /* OHT polarity reversal */ + + j->pld_slicw.bits.c1 = 1; + j->pld_slicw.bits.c2 = 1; + j->pld_slicw.bits.c3 = 1; + j->pld_slicw.bits.b2en = 0; + outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); + fRetVal = true; + break; + default: + fRetVal = false; + break; + } + } + + return fRetVal; +} + +static int ixj_wink(IXJ *j) +{ + BYTE slicnow; + + slicnow = SLIC_GetState(j); + + j->pots_winkstart = jiffies; + SLIC_SetState(PLD_SLIC_STATE_OC, j); + + msleep(jiffies_to_msecs(j->winktime)); + + SLIC_SetState(slicnow, j); + return 0; +} + +static void ixj_init_timer(IXJ *j) +{ + init_timer(&j->timer); + j->timer.function = ixj_timeout; + j->timer.data = (unsigned long)j; +} + +static void ixj_add_timer(IXJ *j) +{ + j->timer.expires = jiffies + (hertz / samplerate); + add_timer(&j->timer); +} + +static void ixj_tone_timeout(IXJ *j) +{ + IXJ_TONE ti; + + j->tone_state++; + if (j->tone_state == 3) { + j->tone_state = 0; + if (j->cadence_t) { + j->tone_cadence_state++; + if (j->tone_cadence_state >= j->cadence_t->elements_used) { + switch (j->cadence_t->termination) { + case PLAY_ONCE: + ixj_cpt_stop(j); + break; + case REPEAT_LAST_ELEMENT: + j->tone_cadence_state--; + ixj_play_tone(j, j->cadence_t->ce[j->tone_cadence_state].index); + break; + case REPEAT_ALL: + j->tone_cadence_state = 0; + if (j->cadence_t->ce[j->tone_cadence_state].freq0) { + ti.tone_index = j->cadence_t->ce[j->tone_cadence_state].index; + ti.freq0 = j->cadence_t->ce[j->tone_cadence_state].freq0; + ti.gain0 = j->cadence_t->ce[j->tone_cadence_state].gain0; + ti.freq1 = j->cadence_t->ce[j->tone_cadence_state].freq1; + ti.gain1 = j->cadence_t->ce[j->tone_cadence_state].gain1; + ixj_init_tone(j, &ti); + } + ixj_set_tone_on(j->cadence_t->ce[0].tone_on_time, j); + ixj_set_tone_off(j->cadence_t->ce[0].tone_off_time, j); + ixj_play_tone(j, j->cadence_t->ce[0].index); + break; + } + } else { + if (j->cadence_t->ce[j->tone_cadence_state].gain0) { + ti.tone_index = j->cadence_t->ce[j->tone_cadence_state].index; + ti.freq0 = j->cadence_t->ce[j->tone_cadence_state].freq0; + ti.gain0 = j->cadence_t->ce[j->tone_cadence_state].gain0; + ti.freq1 = j->cadence_t->ce[j->tone_cadence_state].freq1; + ti.gain1 = j->cadence_t->ce[j->tone_cadence_state].gain1; + ixj_init_tone(j, &ti); + } + ixj_set_tone_on(j->cadence_t->ce[j->tone_cadence_state].tone_on_time, j); + ixj_set_tone_off(j->cadence_t->ce[j->tone_cadence_state].tone_off_time, j); + ixj_play_tone(j, j->cadence_t->ce[j->tone_cadence_state].index); + } + } + } +} + +static inline void ixj_kill_fasync(IXJ *j, IXJ_SIGEVENT event, int dir) +{ + if(j->ixj_signals[event]) { + if(ixjdebug & 0x0100) + printk("Sending signal for event %d\n", event); + /* Send apps notice of change */ + /* see config.h for macro definition */ + kill_fasync(&(j->async_queue), j->ixj_signals[event], dir); + } +} + +static void ixj_pstn_state(IXJ *j) +{ + int var; + union XOPXR0 XR0, daaint; + + var = 10; + + XR0.reg = j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.reg; + daaint.reg = 0; + XR0.bitreg.RMR = j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.bitreg.RMR; + + j->pld_scrr.byte = inb_p(j->XILINXbase); + if (j->pld_scrr.bits.daaflag) { + daa_int_read(j); + if(j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.RING) { + if(time_after(jiffies, j->pstn_sleeptil) && !(j->flags.pots_pstn && j->hookstate)) { + daaint.bitreg.RING = 1; + if(ixjdebug & 0x0008) { + printk(KERN_INFO "IXJ DAA Ring Interrupt /dev/phone%d at %ld\n", j->board, jiffies); + } + } else { + daa_set_mode(j, SOP_PU_RESET); + } + } + if(j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.Caller_ID) { + daaint.bitreg.Caller_ID = 1; + j->pstn_cid_intr = 1; + j->pstn_cid_received = jiffies; + if(ixjdebug & 0x0008) { + printk(KERN_INFO "IXJ DAA Caller_ID Interrupt /dev/phone%d at %ld\n", j->board, jiffies); + } + } + if(j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.Cadence) { + daaint.bitreg.Cadence = 1; + if(ixjdebug & 0x0008) { + printk(KERN_INFO "IXJ DAA Cadence Interrupt /dev/phone%d at %ld\n", j->board, jiffies); + } + } + if(j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.VDD_OK != XR0.bitreg.VDD_OK) { + daaint.bitreg.VDD_OK = 1; + daaint.bitreg.SI_0 = j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.VDD_OK; + } + } + daa_CR_read(j, 1); + if(j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.bitreg.RMR != XR0.bitreg.RMR && time_after(jiffies, j->pstn_sleeptil) && !(j->flags.pots_pstn && j->hookstate)) { + daaint.bitreg.RMR = 1; + daaint.bitreg.SI_1 = j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.bitreg.RMR; + if(ixjdebug & 0x0008) { + printk(KERN_INFO "IXJ DAA RMR /dev/phone%d was %s for %ld\n", j->board, XR0.bitreg.RMR?"on":"off", jiffies - j->pstn_last_rmr); + } + j->pstn_prev_rmr = j->pstn_last_rmr; + j->pstn_last_rmr = jiffies; + } + switch(j->daa_mode) { + case SOP_PU_SLEEP: + if (daaint.bitreg.RING) { + if (!j->flags.pstn_ringing) { + if (j->daa_mode != SOP_PU_RINGING) { + j->pstn_ring_int = jiffies; + daa_set_mode(j, SOP_PU_RINGING); + } + } + } + break; + case SOP_PU_RINGING: + if (daaint.bitreg.RMR) { + if (ixjdebug & 0x0008) { + printk(KERN_INFO "IXJ Ring Cadence a state = %d /dev/phone%d at %ld\n", j->cadence_f[4].state, j->board, jiffies); + } + if (daaint.bitreg.SI_1) { /* Rising edge of RMR */ + j->flags.pstn_rmr = 1; + j->pstn_ring_start = jiffies; + j->pstn_ring_stop = 0; + j->ex.bits.pstn_ring = 0; + if (j->cadence_f[4].state == 0) { + j->cadence_f[4].state = 1; + j->cadence_f[4].on1min = jiffies + (long)((j->cadence_f[4].on1 * hertz * (100 - var)) / 10000); + j->cadence_f[4].on1dot = jiffies + (long)((j->cadence_f[4].on1 * hertz * (100)) / 10000); + j->cadence_f[4].on1max = jiffies + (long)((j->cadence_f[4].on1 * hertz * (100 + var)) / 10000); + } else if (j->cadence_f[4].state == 2) { + if((time_after(jiffies, j->cadence_f[4].off1min) && + time_before(jiffies, j->cadence_f[4].off1max))) { + if (j->cadence_f[4].on2) { + j->cadence_f[4].state = 3; + j->cadence_f[4].on2min = jiffies + (long)((j->cadence_f[4].on2 * (hertz * (100 - var)) / 10000)); + j->cadence_f[4].on2dot = jiffies + (long)((j->cadence_f[4].on2 * (hertz * (100)) / 10000)); + j->cadence_f[4].on2max = jiffies + (long)((j->cadence_f[4].on2 * (hertz * (100 + var)) / 10000)); + } else { + j->cadence_f[4].state = 7; + } + } else { + if (ixjdebug & 0x0008) { + printk(KERN_INFO "IXJ Ring Cadence fail state = %d /dev/phone%d at %ld should be %d\n", + j->cadence_f[4].state, j->board, jiffies - j->pstn_prev_rmr, + j->cadence_f[4].off1); + } + j->cadence_f[4].state = 0; + } + } else if (j->cadence_f[4].state == 4) { + if((time_after(jiffies, j->cadence_f[4].off2min) && + time_before(jiffies, j->cadence_f[4].off2max))) { + if (j->cadence_f[4].on3) { + j->cadence_f[4].state = 5; + j->cadence_f[4].on3min = jiffies + (long)((j->cadence_f[4].on3 * (hertz * (100 - var)) / 10000)); + j->cadence_f[4].on3dot = jiffies + (long)((j->cadence_f[4].on3 * (hertz * (100)) / 10000)); + j->cadence_f[4].on3max = jiffies + (long)((j->cadence_f[4].on3 * (hertz * (100 + var)) / 10000)); + } else { + j->cadence_f[4].state = 7; + } + } else { + if (ixjdebug & 0x0008) { + printk(KERN_INFO "IXJ Ring Cadence fail state = %d /dev/phone%d at %ld should be %d\n", + j->cadence_f[4].state, j->board, jiffies - j->pstn_prev_rmr, + j->cadence_f[4].off2); + } + j->cadence_f[4].state = 0; + } + } else if (j->cadence_f[4].state == 6) { + if((time_after(jiffies, j->cadence_f[4].off3min) && + time_before(jiffies, j->cadence_f[4].off3max))) { + j->cadence_f[4].state = 7; + } else { + if (ixjdebug & 0x0008) { + printk(KERN_INFO "IXJ Ring Cadence fail state = %d /dev/phone%d at %ld should be %d\n", + j->cadence_f[4].state, j->board, jiffies - j->pstn_prev_rmr, + j->cadence_f[4].off3); + } + j->cadence_f[4].state = 0; + } + } else { + j->cadence_f[4].state = 0; + } + } else { /* Falling edge of RMR */ + j->pstn_ring_start = 0; + j->pstn_ring_stop = jiffies; + if (j->cadence_f[4].state == 1) { + if(!j->cadence_f[4].on1) { + j->cadence_f[4].state = 7; + } else if((time_after(jiffies, j->cadence_f[4].on1min) && + time_before(jiffies, j->cadence_f[4].on1max))) { + if (j->cadence_f[4].off1) { + j->cadence_f[4].state = 2; + j->cadence_f[4].off1min = jiffies + (long)((j->cadence_f[4].off1 * (hertz * (100 - var)) / 10000)); + j->cadence_f[4].off1dot = jiffies + (long)((j->cadence_f[4].off1 * (hertz * (100)) / 10000)); + j->cadence_f[4].off1max = jiffies + (long)((j->cadence_f[4].off1 * (hertz * (100 + var)) / 10000)); + } else { + j->cadence_f[4].state = 7; + } + } else { + if (ixjdebug & 0x0008) { + printk(KERN_INFO "IXJ Ring Cadence fail state = %d /dev/phone%d at %ld should be %d\n", + j->cadence_f[4].state, j->board, jiffies - j->pstn_prev_rmr, + j->cadence_f[4].on1); + } + j->cadence_f[4].state = 0; + } + } else if (j->cadence_f[4].state == 3) { + if((time_after(jiffies, j->cadence_f[4].on2min) && + time_before(jiffies, j->cadence_f[4].on2max))) { + if (j->cadence_f[4].off2) { + j->cadence_f[4].state = 4; + j->cadence_f[4].off2min = jiffies + (long)((j->cadence_f[4].off2 * (hertz * (100 - var)) / 10000)); + j->cadence_f[4].off2dot = jiffies + (long)((j->cadence_f[4].off2 * (hertz * (100)) / 10000)); + j->cadence_f[4].off2max = jiffies + (long)((j->cadence_f[4].off2 * (hertz * (100 + var)) / 10000)); + } else { + j->cadence_f[4].state = 7; + } + } else { + if (ixjdebug & 0x0008) { + printk(KERN_INFO "IXJ Ring Cadence fail state = %d /dev/phone%d at %ld should be %d\n", + j->cadence_f[4].state, j->board, jiffies - j->pstn_prev_rmr, + j->cadence_f[4].on2); + } + j->cadence_f[4].state = 0; + } + } else if (j->cadence_f[4].state == 5) { + if((time_after(jiffies, j->cadence_f[4].on3min) && + time_before(jiffies, j->cadence_f[4].on3max))) { + if (j->cadence_f[4].off3) { + j->cadence_f[4].state = 6; + j->cadence_f[4].off3min = jiffies + (long)((j->cadence_f[4].off3 * (hertz * (100 - var)) / 10000)); + j->cadence_f[4].off3dot = jiffies + (long)((j->cadence_f[4].off3 * (hertz * (100)) / 10000)); + j->cadence_f[4].off3max = jiffies + (long)((j->cadence_f[4].off3 * (hertz * (100 + var)) / 10000)); + } else { + j->cadence_f[4].state = 7; + } + } else { + j->cadence_f[4].state = 0; + } + } else { + if (ixjdebug & 0x0008) { + printk(KERN_INFO "IXJ Ring Cadence fail state = %d /dev/phone%d at %ld should be %d\n", + j->cadence_f[4].state, j->board, jiffies - j->pstn_prev_rmr, + j->cadence_f[4].on3); + } + j->cadence_f[4].state = 0; + } + } + if (ixjdebug & 0x0010) { + printk(KERN_INFO "IXJ Ring Cadence b state = %d /dev/phone%d at %ld\n", j->cadence_f[4].state, j->board, jiffies); + } + if (ixjdebug & 0x0010) { + switch(j->cadence_f[4].state) { + case 1: + printk(KERN_INFO "IXJ /dev/phone%d Next Ring Cadence state at %u min %ld - %ld - max %ld\n", j->board, + j->cadence_f[4].on1, j->cadence_f[4].on1min, j->cadence_f[4].on1dot, j->cadence_f[4].on1max); + break; + case 2: + printk(KERN_INFO "IXJ /dev/phone%d Next Ring Cadence state at %u min %ld - %ld - max %ld\n", j->board, + j->cadence_f[4].off1, j->cadence_f[4].off1min, j->cadence_f[4].off1dot, j->cadence_f[4].off1max); + break; + case 3: + printk(KERN_INFO "IXJ /dev/phone%d Next Ring Cadence state at %u min %ld - %ld - max %ld\n", j->board, + j->cadence_f[4].on2, j->cadence_f[4].on2min, j->cadence_f[4].on2dot, j->cadence_f[4].on2max); + break; + case 4: + printk(KERN_INFO "IXJ /dev/phone%d Next Ring Cadence state at %u min %ld - %ld - max %ld\n", j->board, + j->cadence_f[4].off2, j->cadence_f[4].off2min, j->cadence_f[4].off2dot, j->cadence_f[4].off2max); + break; + case 5: + printk(KERN_INFO "IXJ /dev/phone%d Next Ring Cadence state at %u min %ld - %ld - max %ld\n", j->board, + j->cadence_f[4].on3, j->cadence_f[4].on3min, j->cadence_f[4].on3dot, j->cadence_f[4].on3max); + break; + case 6: + printk(KERN_INFO "IXJ /dev/phone%d Next Ring Cadence state at %u min %ld - %ld - max %ld\n", j->board, + j->cadence_f[4].off3, j->cadence_f[4].off3min, j->cadence_f[4].off3dot, j->cadence_f[4].off3max); + break; + } + } + } + if (j->cadence_f[4].state == 7) { + j->cadence_f[4].state = 0; + j->pstn_ring_stop = jiffies; + j->ex.bits.pstn_ring = 1; + ixj_kill_fasync(j, SIG_PSTN_RING, POLL_IN); + if(ixjdebug & 0x0008) { + printk(KERN_INFO "IXJ Ring int set /dev/phone%d at %ld\n", j->board, jiffies); + } + } + if((j->pstn_ring_int != 0 && time_after(jiffies, j->pstn_ring_int + (hertz * 5)) && !j->flags.pstn_rmr) || + (j->pstn_ring_stop != 0 && time_after(jiffies, j->pstn_ring_stop + (hertz * 5)))) { + if(ixjdebug & 0x0008) { + printk("IXJ DAA no ring in 5 seconds /dev/phone%d at %ld\n", j->board, jiffies); + printk("IXJ DAA pstn ring int /dev/phone%d at %ld\n", j->board, j->pstn_ring_int); + printk("IXJ DAA pstn ring stop /dev/phone%d at %ld\n", j->board, j->pstn_ring_stop); + } + j->pstn_ring_stop = j->pstn_ring_int = 0; + daa_set_mode(j, SOP_PU_SLEEP); + } + outb_p(j->pld_scrw.byte, j->XILINXbase); + if (j->pstn_cid_intr && time_after(jiffies, j->pstn_cid_received + hertz)) { + ixj_daa_cid_read(j); + j->ex.bits.caller_id = 1; + ixj_kill_fasync(j, SIG_CALLER_ID, POLL_IN); + j->pstn_cid_intr = 0; + } + if (daaint.bitreg.Cadence) { + if(ixjdebug & 0x0008) { + printk("IXJ DAA Cadence interrupt going to sleep /dev/phone%d\n", j->board); + } + daa_set_mode(j, SOP_PU_SLEEP); + j->ex.bits.pstn_ring = 0; + } + break; + case SOP_PU_CONVERSATION: + if (daaint.bitreg.VDD_OK) { + if(!daaint.bitreg.SI_0) { + if (!j->pstn_winkstart) { + if(ixjdebug & 0x0008) { + printk("IXJ DAA possible wink /dev/phone%d %ld\n", j->board, jiffies); + } + j->pstn_winkstart = jiffies; + } + } else { + if (j->pstn_winkstart) { + if(ixjdebug & 0x0008) { + printk("IXJ DAA possible wink end /dev/phone%d %ld\n", j->board, jiffies); + } + j->pstn_winkstart = 0; + } + } + } + if (j->pstn_winkstart && time_after(jiffies, j->pstn_winkstart + ((hertz * j->winktime) / 1000))) { + if(ixjdebug & 0x0008) { + printk("IXJ DAA wink detected going to sleep /dev/phone%d %ld\n", j->board, jiffies); + } + daa_set_mode(j, SOP_PU_SLEEP); + j->pstn_winkstart = 0; + j->ex.bits.pstn_wink = 1; + ixj_kill_fasync(j, SIG_PSTN_WINK, POLL_IN); + } + break; + } +} + +static void ixj_timeout(unsigned long ptr) +{ + int board; + unsigned long jifon; + IXJ *j = (IXJ *)ptr; + board = j->board; + + if (j->DSPbase && atomic_read(&j->DSPWrite) == 0 && test_and_set_bit(board, (void *)&j->busyflags) == 0) { + ixj_perfmon(j->timerchecks); + j->hookstate = ixj_hookstate(j); + if (j->tone_state) { + if (!(j->hookstate)) { + ixj_cpt_stop(j); + if (j->m_hook) { + j->m_hook = 0; + j->ex.bits.hookstate = 1; + ixj_kill_fasync(j, SIG_HOOKSTATE, POLL_IN); + } + clear_bit(board, &j->busyflags); + ixj_add_timer(j); + return; + } + if (j->tone_state == 1) + jifon = ((hertz * j->tone_on_time) * 25 / 100000); + else + jifon = ((hertz * j->tone_on_time) * 25 / 100000) + ((hertz * j->tone_off_time) * 25 / 100000); + if (time_before(jiffies, j->tone_start_jif + jifon)) { + if (j->tone_state == 1) { + ixj_play_tone(j, j->tone_index); + if (j->dsp.low == 0x20) { + clear_bit(board, &j->busyflags); + ixj_add_timer(j); + return; + } + } else { + ixj_play_tone(j, 0); + if (j->dsp.low == 0x20) { + clear_bit(board, &j->busyflags); + ixj_add_timer(j); + return; + } + } + } else { + ixj_tone_timeout(j); + if (j->flags.dialtone) { + ixj_dialtone(j); + } + if (j->flags.busytone) { + ixj_busytone(j); + if (j->dsp.low == 0x20) { + clear_bit(board, &j->busyflags); + ixj_add_timer(j); + return; + } + } + if (j->flags.ringback) { + ixj_ringback(j); + if (j->dsp.low == 0x20) { + clear_bit(board, &j->busyflags); + ixj_add_timer(j); + return; + } + } + if (!j->tone_state) { + ixj_cpt_stop(j); + } + } + } + if (!(j->tone_state && j->dsp.low == 0x20)) { + if (IsRxReady(j)) { + ixj_read_frame(j); + } + if (IsTxReady(j)) { + ixj_write_frame(j); + } + } + if (j->flags.cringing) { + if (j->hookstate & 1) { + j->flags.cringing = 0; + ixj_ring_off(j); + } else if(j->cadence_f[5].enable && ((!j->cadence_f[5].en_filter) || (j->cadence_f[5].en_filter && j->flags.firstring))) { + switch(j->cadence_f[5].state) { + case 0: + j->cadence_f[5].on1dot = jiffies + (long)((j->cadence_f[5].on1 * (hertz * 100) / 10000)); + if (time_before(jiffies, j->cadence_f[5].on1dot)) { + if(ixjdebug & 0x0004) { + printk("Ringing cadence state = %d - %ld\n", j->cadence_f[5].state, jiffies); + } + ixj_ring_on(j); + } + j->cadence_f[5].state = 1; + break; + case 1: + if (time_after(jiffies, j->cadence_f[5].on1dot)) { + j->cadence_f[5].off1dot = jiffies + (long)((j->cadence_f[5].off1 * (hertz * 100) / 10000)); + if(ixjdebug & 0x0004) { + printk("Ringing cadence state = %d - %ld\n", j->cadence_f[5].state, jiffies); + } + ixj_ring_off(j); + j->cadence_f[5].state = 2; + } + break; + case 2: + if (time_after(jiffies, j->cadence_f[5].off1dot)) { + if(ixjdebug & 0x0004) { + printk("Ringing cadence state = %d - %ld\n", j->cadence_f[5].state, jiffies); + } + ixj_ring_on(j); + if (j->cadence_f[5].on2) { + j->cadence_f[5].on2dot = jiffies + (long)((j->cadence_f[5].on2 * (hertz * 100) / 10000)); + j->cadence_f[5].state = 3; + } else { + j->cadence_f[5].state = 7; + } + } + break; + case 3: + if (time_after(jiffies, j->cadence_f[5].on2dot)) { + if(ixjdebug & 0x0004) { + printk("Ringing cadence state = %d - %ld\n", j->cadence_f[5].state, jiffies); + } + ixj_ring_off(j); + if (j->cadence_f[5].off2) { + j->cadence_f[5].off2dot = jiffies + (long)((j->cadence_f[5].off2 * (hertz * 100) / 10000)); + j->cadence_f[5].state = 4; + } else { + j->cadence_f[5].state = 7; + } + } + break; + case 4: + if (time_after(jiffies, j->cadence_f[5].off2dot)) { + if(ixjdebug & 0x0004) { + printk("Ringing cadence state = %d - %ld\n", j->cadence_f[5].state, jiffies); + } + ixj_ring_on(j); + if (j->cadence_f[5].on3) { + j->cadence_f[5].on3dot = jiffies + (long)((j->cadence_f[5].on3 * (hertz * 100) / 10000)); + j->cadence_f[5].state = 5; + } else { + j->cadence_f[5].state = 7; + } + } + break; + case 5: + if (time_after(jiffies, j->cadence_f[5].on3dot)) { + if(ixjdebug & 0x0004) { + printk("Ringing cadence state = %d - %ld\n", j->cadence_f[5].state, jiffies); + } + ixj_ring_off(j); + if (j->cadence_f[5].off3) { + j->cadence_f[5].off3dot = jiffies + (long)((j->cadence_f[5].off3 * (hertz * 100) / 10000)); + j->cadence_f[5].state = 6; + } else { + j->cadence_f[5].state = 7; + } + } + break; + case 6: + if (time_after(jiffies, j->cadence_f[5].off3dot)) { + if(ixjdebug & 0x0004) { + printk("Ringing cadence state = %d - %ld\n", j->cadence_f[5].state, jiffies); + } + j->cadence_f[5].state = 7; + } + break; + case 7: + if(ixjdebug & 0x0004) { + printk("Ringing cadence state = %d - %ld\n", j->cadence_f[5].state, jiffies); + } + j->flags.cidring = 1; + j->cadence_f[5].state = 0; + break; + } + if (j->flags.cidring && !j->flags.cidsent) { + j->flags.cidsent = 1; + if(j->fskdcnt) { + SLIC_SetState(PLD_SLIC_STATE_OHT, j); + ixj_pre_cid(j); + } + j->flags.cidring = 0; + } + clear_bit(board, &j->busyflags); + ixj_add_timer(j); + return; + } else { + if (time_after(jiffies, j->ring_cadence_jif + (hertz / 2))) { + if (j->flags.cidring && !j->flags.cidsent) { + j->flags.cidsent = 1; + if(j->fskdcnt) { + SLIC_SetState(PLD_SLIC_STATE_OHT, j); + ixj_pre_cid(j); + } + j->flags.cidring = 0; + } + j->ring_cadence_t--; + if (j->ring_cadence_t == -1) + j->ring_cadence_t = 15; + j->ring_cadence_jif = jiffies; + + if (j->ring_cadence & 1 << j->ring_cadence_t) { + if(j->flags.cidsent && j->cadence_f[5].en_filter) + j->flags.firstring = 1; + else + ixj_ring_on(j); + } else { + ixj_ring_off(j); + if(!j->flags.cidsent) + j->flags.cidring = 1; + } + } + clear_bit(board, &j->busyflags); + ixj_add_timer(j); + return; + } + } + if (!j->flags.ringing) { + if (j->hookstate) { /* & 1) { */ + if (j->dsp.low != 0x20 && + SLIC_GetState(j) != PLD_SLIC_STATE_ACTIVE) { + SLIC_SetState(PLD_SLIC_STATE_ACTIVE, j); + } + LineMonitor(j); + read_filters(j); + ixj_WriteDSPCommand(0x511B, j); + j->proc_load = j->ssr.high << 8 | j->ssr.low; + if (!j->m_hook && (j->hookstate & 1)) { + j->m_hook = j->ex.bits.hookstate = 1; + ixj_kill_fasync(j, SIG_HOOKSTATE, POLL_IN); + } + } else { + if (j->ex.bits.dtmf_ready) { + j->dtmf_wp = j->dtmf_rp = j->ex.bits.dtmf_ready = 0; + } + if (j->m_hook) { + j->m_hook = 0; + j->ex.bits.hookstate = 1; + ixj_kill_fasync(j, SIG_HOOKSTATE, POLL_IN); + } + } + } + if (j->cardtype == QTI_LINEJACK && !j->flags.pstncheck && j->flags.pstn_present) { + ixj_pstn_state(j); + } + if (j->ex.bytes) { + wake_up_interruptible(&j->poll_q); /* Wake any blocked selects */ + } + clear_bit(board, &j->busyflags); + } + ixj_add_timer(j); +} + +static int ixj_status_wait(IXJ *j) +{ + unsigned long jif; + + jif = jiffies + ((60 * hertz) / 100); + while (!IsStatusReady(j)) { + ixj_perfmon(j->statuswait); + if (time_after(jiffies, jif)) { + ixj_perfmon(j->statuswaitfail); + return -1; + } + } + return 0; +} + +static int ixj_PCcontrol_wait(IXJ *j) +{ + unsigned long jif; + + jif = jiffies + ((60 * hertz) / 100); + while (!IsPCControlReady(j)) { + ixj_perfmon(j->pcontrolwait); + if (time_after(jiffies, jif)) { + ixj_perfmon(j->pcontrolwaitfail); + return -1; + } + } + return 0; +} + +static int ixj_WriteDSPCommand(unsigned short cmd, IXJ *j) +{ + BYTES bytes; + unsigned long jif; + + atomic_inc(&j->DSPWrite); + if(atomic_read(&j->DSPWrite) > 1) { + printk("IXJ %d DSP write overlap attempting command 0x%4.4x\n", j->board, cmd); + return -1; + } + bytes.high = (cmd & 0xFF00) >> 8; + bytes.low = cmd & 0x00FF; + jif = jiffies + ((60 * hertz) / 100); + while (!IsControlReady(j)) { + ixj_perfmon(j->iscontrolready); + if (time_after(jiffies, jif)) { + ixj_perfmon(j->iscontrolreadyfail); + atomic_dec(&j->DSPWrite); + if(atomic_read(&j->DSPWrite) > 0) { + printk("IXJ %d DSP overlaped command 0x%4.4x during control ready failure.\n", j->board, cmd); + while(atomic_read(&j->DSPWrite) > 0) { + atomic_dec(&j->DSPWrite); + } + } + return -1; + } + } + outb(bytes.low, j->DSPbase + 6); + outb(bytes.high, j->DSPbase + 7); + + if (ixj_status_wait(j)) { + j->ssr.low = 0xFF; + j->ssr.high = 0xFF; + atomic_dec(&j->DSPWrite); + if(atomic_read(&j->DSPWrite) > 0) { + printk("IXJ %d DSP overlaped command 0x%4.4x during status wait failure.\n", j->board, cmd); + while(atomic_read(&j->DSPWrite) > 0) { + atomic_dec(&j->DSPWrite); + } + } + return -1; + } +/* Read Software Status Register */ + j->ssr.low = inb_p(j->DSPbase + 2); + j->ssr.high = inb_p(j->DSPbase + 3); + atomic_dec(&j->DSPWrite); + if(atomic_read(&j->DSPWrite) > 0) { + printk("IXJ %d DSP overlaped command 0x%4.4x\n", j->board, cmd); + while(atomic_read(&j->DSPWrite) > 0) { + atomic_dec(&j->DSPWrite); + } + } + return 0; +} + +/*************************************************************************** +* +* General Purpose IO Register read routine +* +***************************************************************************/ +static inline int ixj_gpio_read(IXJ *j) +{ + if (ixj_WriteDSPCommand(0x5143, j)) + return -1; + + j->gpio.bytes.low = j->ssr.low; + j->gpio.bytes.high = j->ssr.high; + + return 0; +} + +static inline void LED_SetState(int state, IXJ *j) +{ + if (j->cardtype == QTI_LINEJACK) { + j->pld_scrw.bits.led1 = state & 0x1 ? 1 : 0; + j->pld_scrw.bits.led2 = state & 0x2 ? 1 : 0; + j->pld_scrw.bits.led3 = state & 0x4 ? 1 : 0; + j->pld_scrw.bits.led4 = state & 0x8 ? 1 : 0; + + outb(j->pld_scrw.byte, j->XILINXbase); + } +} + +/********************************************************************* +* GPIO Pins are configured as follows on the Quicknet Internet +* PhoneJACK Telephony Cards +* +* POTS Select GPIO_6=0 GPIO_7=0 +* Mic/Speaker Select GPIO_6=0 GPIO_7=1 +* Handset Select GPIO_6=1 GPIO_7=0 +* +* SLIC Active GPIO_1=0 GPIO_2=1 GPIO_5=0 +* SLIC Ringing GPIO_1=1 GPIO_2=1 GPIO_5=0 +* SLIC Open Circuit GPIO_1=0 GPIO_2=0 GPIO_5=0 +* +* Hook Switch changes reported on GPIO_3 +*********************************************************************/ +static int ixj_set_port(IXJ *j, int arg) +{ + if (j->cardtype == QTI_PHONEJACK_LITE) { + if (arg != PORT_POTS) + return 10; + else + return 0; + } + switch (arg) { + case PORT_POTS: + j->port = PORT_POTS; + switch (j->cardtype) { + case QTI_PHONECARD: + if (j->flags.pcmciasct == 1) + SLIC_SetState(PLD_SLIC_STATE_ACTIVE, j); + else + return 11; + break; + case QTI_PHONEJACK_PCI: + j->pld_slicw.pcib.mic = 0; + j->pld_slicw.pcib.spk = 0; + outb(j->pld_slicw.byte, j->XILINXbase + 0x01); + break; + case QTI_LINEJACK: + ixj_set_pots(j, 0); /* Disconnect POTS/PSTN relay */ + if (ixj_WriteDSPCommand(0xC528, j)) /* Write CODEC config to + Software Control Register */ + return 2; + j->pld_scrw.bits.daafsyncen = 0; /* Turn off DAA Frame Sync */ + + outb(j->pld_scrw.byte, j->XILINXbase); + j->pld_clock.byte = 0; + outb(j->pld_clock.byte, j->XILINXbase + 0x04); + j->pld_slicw.bits.rly1 = 1; + j->pld_slicw.bits.spken = 0; + outb(j->pld_slicw.byte, j->XILINXbase + 0x01); + ixj_mixer(0x1200, j); /* Turn Off MIC switch on mixer left */ + ixj_mixer(0x1401, j); /* Turn On Mono1 switch on mixer left */ + ixj_mixer(0x1300, j); /* Turn Off MIC switch on mixer right */ + ixj_mixer(0x1501, j); /* Turn On Mono1 switch on mixer right */ + ixj_mixer(0x0E80, j); /*Mic mute */ + ixj_mixer(0x0F00, j); /* Set mono out (SLIC) to 0dB */ + ixj_mixer(0x0080, j); /* Mute Master Left volume */ + ixj_mixer(0x0180, j); /* Mute Master Right volume */ + SLIC_SetState(PLD_SLIC_STATE_STANDBY, j); +/* SLIC_SetState(PLD_SLIC_STATE_ACTIVE, j); */ + break; + case QTI_PHONEJACK: + j->gpio.bytes.high = 0x0B; + j->gpio.bits.gpio6 = 0; + j->gpio.bits.gpio7 = 0; + ixj_WriteDSPCommand(j->gpio.word, j); + break; + } + break; + case PORT_PSTN: + if (j->cardtype == QTI_LINEJACK) { + ixj_WriteDSPCommand(0xC534, j); /* Write CODEC config to Software Control Register */ + + j->pld_slicw.bits.rly3 = 0; + j->pld_slicw.bits.rly1 = 1; + j->pld_slicw.bits.spken = 0; + outb(j->pld_slicw.byte, j->XILINXbase + 0x01); + j->port = PORT_PSTN; + } else { + return 4; + } + break; + case PORT_SPEAKER: + j->port = PORT_SPEAKER; + switch (j->cardtype) { + case QTI_PHONECARD: + if (j->flags.pcmciasct) { + SLIC_SetState(PLD_SLIC_STATE_OC, j); + } + break; + case QTI_PHONEJACK_PCI: + j->pld_slicw.pcib.mic = 1; + j->pld_slicw.pcib.spk = 1; + outb(j->pld_slicw.byte, j->XILINXbase + 0x01); + break; + case QTI_LINEJACK: + ixj_set_pots(j, 0); /* Disconnect POTS/PSTN relay */ + if (ixj_WriteDSPCommand(0xC528, j)) /* Write CODEC config to + Software Control Register */ + return 2; + j->pld_scrw.bits.daafsyncen = 0; /* Turn off DAA Frame Sync */ + + outb(j->pld_scrw.byte, j->XILINXbase); + j->pld_clock.byte = 0; + outb(j->pld_clock.byte, j->XILINXbase + 0x04); + j->pld_slicw.bits.rly1 = 1; + j->pld_slicw.bits.spken = 1; + outb(j->pld_slicw.byte, j->XILINXbase + 0x01); + ixj_mixer(0x1201, j); /* Turn On MIC switch on mixer left */ + ixj_mixer(0x1400, j); /* Turn Off Mono1 switch on mixer left */ + ixj_mixer(0x1301, j); /* Turn On MIC switch on mixer right */ + ixj_mixer(0x1500, j); /* Turn Off Mono1 switch on mixer right */ + ixj_mixer(0x0E06, j); /*Mic un-mute 0dB */ + ixj_mixer(0x0F80, j); /* Mute mono out (SLIC) */ + ixj_mixer(0x0000, j); /* Set Master Left volume to 0dB */ + ixj_mixer(0x0100, j); /* Set Master Right volume to 0dB */ + break; + case QTI_PHONEJACK: + j->gpio.bytes.high = 0x0B; + j->gpio.bits.gpio6 = 0; + j->gpio.bits.gpio7 = 1; + ixj_WriteDSPCommand(j->gpio.word, j); + break; + } + break; + case PORT_HANDSET: + if (j->cardtype != QTI_PHONEJACK) { + return 5; + } else { + j->gpio.bytes.high = 0x0B; + j->gpio.bits.gpio6 = 1; + j->gpio.bits.gpio7 = 0; + ixj_WriteDSPCommand(j->gpio.word, j); + j->port = PORT_HANDSET; + } + break; + default: + return 6; + break; + } + return 0; +} + +static int ixj_set_pots(IXJ *j, int arg) +{ + if (j->cardtype == QTI_LINEJACK) { + if (arg) { + if (j->port == PORT_PSTN) { + j->pld_slicw.bits.rly1 = 0; + outb(j->pld_slicw.byte, j->XILINXbase + 0x01); + j->flags.pots_pstn = 1; + return 1; + } else { + j->flags.pots_pstn = 0; + return 0; + } + } else { + j->pld_slicw.bits.rly1 = 1; + outb(j->pld_slicw.byte, j->XILINXbase + 0x01); + j->flags.pots_pstn = 0; + return 1; + } + } else { + return 0; + } +} + +static void ixj_ring_on(IXJ *j) +{ + if (j->dsp.low == 0x20) /* Internet PhoneJACK */ + { + if (ixjdebug & 0x0004) + printk(KERN_INFO "IXJ Ring On /dev/phone%d\n", j->board); + + j->gpio.bytes.high = 0x0B; + j->gpio.bytes.low = 0x00; + j->gpio.bits.gpio1 = 1; + j->gpio.bits.gpio2 = 1; + j->gpio.bits.gpio5 = 0; + ixj_WriteDSPCommand(j->gpio.word, j); /* send the ring signal */ + } else /* Internet LineJACK, Internet PhoneJACK Lite or Internet PhoneJACK PCI */ + { + if (ixjdebug & 0x0004) + printk(KERN_INFO "IXJ Ring On /dev/phone%d\n", j->board); + + SLIC_SetState(PLD_SLIC_STATE_RINGING, j); + } +} + +static int ixj_siadc(IXJ *j, int val) +{ + if(j->cardtype == QTI_PHONECARD){ + if(j->flags.pcmciascp){ + if(val == -1) + return j->siadc.bits.rxg; + + if(val < 0 || val > 0x1F) + return -1; + + j->siadc.bits.hom = 0; /* Handset Out Mute */ + j->siadc.bits.lom = 0; /* Line Out Mute */ + j->siadc.bits.rxg = val; /*(0xC000 - 0x41C8) / 0x4EF; RX PGA Gain */ + j->psccr.bits.addr = 6; /* R/W Smart Cable Register Address */ + j->psccr.bits.rw = 0; /* Read / Write flag */ + j->psccr.bits.dev = 0; + outb(j->siadc.byte, j->XILINXbase + 0x00); + outb(j->psccr.byte, j->XILINXbase + 0x01); + ixj_PCcontrol_wait(j); + return j->siadc.bits.rxg; + } + } + return -1; +} + +static int ixj_sidac(IXJ *j, int val) +{ + if(j->cardtype == QTI_PHONECARD){ + if(j->flags.pcmciascp){ + if(val == -1) + return j->sidac.bits.txg; + + if(val < 0 || val > 0x1F) + return -1; + + j->sidac.bits.srm = 1; /* Speaker Right Mute */ + j->sidac.bits.slm = 1; /* Speaker Left Mute */ + j->sidac.bits.txg = val; /* (0xC000 - 0x45E4) / 0x5D3; TX PGA Gain */ + j->psccr.bits.addr = 7; /* R/W Smart Cable Register Address */ + j->psccr.bits.rw = 0; /* Read / Write flag */ + j->psccr.bits.dev = 0; + outb(j->sidac.byte, j->XILINXbase + 0x00); + outb(j->psccr.byte, j->XILINXbase + 0x01); + ixj_PCcontrol_wait(j); + return j->sidac.bits.txg; + } + } + return -1; +} + +static int ixj_pcmcia_cable_check(IXJ *j) +{ + j->pccr1.byte = inb_p(j->XILINXbase + 0x03); + if (!j->flags.pcmciastate) { + j->pccr2.byte = inb_p(j->XILINXbase + 0x02); + if (j->pccr1.bits.drf || j->pccr2.bits.rstc) { + j->flags.pcmciastate = 4; + return 0; + } + if (j->pccr1.bits.ed) { + j->pccr1.bits.ed = 0; + j->psccr.bits.dev = 3; + j->psccr.bits.rw = 1; + outw_p(j->psccr.byte << 8, j->XILINXbase + 0x00); + ixj_PCcontrol_wait(j); + j->pslic.byte = inw_p(j->XILINXbase + 0x00) & 0xFF; + j->pslic.bits.led2 = j->pslic.bits.det ? 1 : 0; + j->psccr.bits.dev = 3; + j->psccr.bits.rw = 0; + outw_p(j->psccr.byte << 8 | j->pslic.byte, j->XILINXbase + 0x00); + ixj_PCcontrol_wait(j); + return j->pslic.bits.led2 ? 1 : 0; + } else if (j->flags.pcmciasct) { + return j->r_hook; + } else { + return 1; + } + } else if (j->flags.pcmciastate == 4) { + if (!j->pccr1.bits.drf) { + j->flags.pcmciastate = 3; + } + return 0; + } else if (j->flags.pcmciastate == 3) { + j->pccr2.bits.pwr = 0; + j->pccr2.bits.rstc = 1; + outb(j->pccr2.byte, j->XILINXbase + 0x02); + j->checkwait = jiffies + (hertz * 2); + j->flags.incheck = 1; + j->flags.pcmciastate = 2; + return 0; + } else if (j->flags.pcmciastate == 2) { + if (j->flags.incheck) { + if (time_before(jiffies, j->checkwait)) { + return 0; + } else { + j->flags.incheck = 0; + } + } + j->pccr2.bits.pwr = 0; + j->pccr2.bits.rstc = 0; + outb_p(j->pccr2.byte, j->XILINXbase + 0x02); + j->flags.pcmciastate = 1; + return 0; + } else if (j->flags.pcmciastate == 1) { + j->flags.pcmciastate = 0; + if (!j->pccr1.bits.drf) { + j->psccr.bits.dev = 3; + j->psccr.bits.rw = 1; + outb_p(j->psccr.byte, j->XILINXbase + 0x01); + ixj_PCcontrol_wait(j); + j->flags.pcmciascp = 1; /* Set Cable Present Flag */ + + j->flags.pcmciasct = (inw_p(j->XILINXbase + 0x00) >> 8) & 0x03; /* Get Cable Type */ + + if (j->flags.pcmciasct == 3) { + j->flags.pcmciastate = 4; + return 0; + } else if (j->flags.pcmciasct == 0) { + j->pccr2.bits.pwr = 1; + j->pccr2.bits.rstc = 0; + outb_p(j->pccr2.byte, j->XILINXbase + 0x02); + j->port = PORT_SPEAKER; + } else { + j->port = PORT_POTS; + } + j->sic1.bits.cpd = 0; /* Chip Power Down */ + j->sic1.bits.mpd = 0; /* MIC Bias Power Down */ + j->sic1.bits.hpd = 0; /* Handset Bias Power Down */ + j->sic1.bits.lpd = 0; /* Line Bias Power Down */ + j->sic1.bits.spd = 1; /* Speaker Drive Power Down */ + j->psccr.bits.addr = 1; /* R/W Smart Cable Register Address */ + j->psccr.bits.rw = 0; /* Read / Write flag */ + j->psccr.bits.dev = 0; + outb(j->sic1.byte, j->XILINXbase + 0x00); + outb(j->psccr.byte, j->XILINXbase + 0x01); + ixj_PCcontrol_wait(j); + + j->sic2.bits.al = 0; /* Analog Loopback DAC analog -> ADC analog */ + j->sic2.bits.dl2 = 0; /* Digital Loopback DAC -> ADC one bit */ + j->sic2.bits.dl1 = 0; /* Digital Loopback ADC -> DAC one bit */ + j->sic2.bits.pll = 0; /* 1 = div 10, 0 = div 5 */ + j->sic2.bits.hpd = 0; /* HPF disable */ + j->psccr.bits.addr = 2; /* R/W Smart Cable Register Address */ + j->psccr.bits.rw = 0; /* Read / Write flag */ + j->psccr.bits.dev = 0; + outb(j->sic2.byte, j->XILINXbase + 0x00); + outb(j->psccr.byte, j->XILINXbase + 0x01); + ixj_PCcontrol_wait(j); + + j->psccr.bits.addr = 3; /* R/W Smart Cable Register Address */ + j->psccr.bits.rw = 0; /* Read / Write flag */ + j->psccr.bits.dev = 0; + outb(0x00, j->XILINXbase + 0x00); /* PLL Divide N1 */ + outb(j->psccr.byte, j->XILINXbase + 0x01); + ixj_PCcontrol_wait(j); + + j->psccr.bits.addr = 4; /* R/W Smart Cable Register Address */ + j->psccr.bits.rw = 0; /* Read / Write flag */ + j->psccr.bits.dev = 0; + outb(0x09, j->XILINXbase + 0x00); /* PLL Multiply M1 */ + outb(j->psccr.byte, j->XILINXbase + 0x01); + ixj_PCcontrol_wait(j); + + j->sirxg.bits.lig = 1; /* Line In Gain */ + j->sirxg.bits.lim = 1; /* Line In Mute */ + j->sirxg.bits.mcg = 0; /* MIC In Gain was 3 */ + j->sirxg.bits.mcm = 0; /* MIC In Mute */ + j->sirxg.bits.him = 0; /* Handset In Mute */ + j->sirxg.bits.iir = 1; /* IIR */ + j->psccr.bits.addr = 5; /* R/W Smart Cable Register Address */ + j->psccr.bits.rw = 0; /* Read / Write flag */ + j->psccr.bits.dev = 0; + outb(j->sirxg.byte, j->XILINXbase + 0x00); + outb(j->psccr.byte, j->XILINXbase + 0x01); + ixj_PCcontrol_wait(j); + + ixj_siadc(j, 0x17); + ixj_sidac(j, 0x1D); + + j->siaatt.bits.sot = 0; + j->psccr.bits.addr = 9; /* R/W Smart Cable Register Address */ + j->psccr.bits.rw = 0; /* Read / Write flag */ + j->psccr.bits.dev = 0; + outb(j->siaatt.byte, j->XILINXbase + 0x00); + outb(j->psccr.byte, j->XILINXbase + 0x01); + ixj_PCcontrol_wait(j); + + if (j->flags.pcmciasct == 1 && !j->readers && !j->writers) { + j->psccr.byte = j->pslic.byte = 0; + j->pslic.bits.powerdown = 1; + j->psccr.bits.dev = 3; + j->psccr.bits.rw = 0; + outw_p(j->psccr.byte << 8 | j->pslic.byte, j->XILINXbase + 0x00); + ixj_PCcontrol_wait(j); + } + } + return 0; + } else { + j->flags.pcmciascp = 0; + return 0; + } + return 0; +} + +static int ixj_hookstate(IXJ *j) +{ + int fOffHook = 0; + + switch (j->cardtype) { + case QTI_PHONEJACK: + ixj_gpio_read(j); + fOffHook = j->gpio.bits.gpio3read ? 1 : 0; + break; + case QTI_LINEJACK: + case QTI_PHONEJACK_LITE: + case QTI_PHONEJACK_PCI: + SLIC_GetState(j); + if(j->cardtype == QTI_LINEJACK && j->flags.pots_pstn == 1 && (j->readers || j->writers)) { + fOffHook = j->pld_slicr.bits.potspstn ? 1 : 0; + if(fOffHook != j->p_hook) { + if(!j->checkwait) { + j->checkwait = jiffies; + } + if(time_before(jiffies, j->checkwait + 2)) { + fOffHook ^= 1; + } else { + j->checkwait = 0; + } + j->p_hook = fOffHook; + printk("IXJ : /dev/phone%d pots-pstn hookstate check %d at %ld\n", j->board, fOffHook, jiffies); + } + } else { + if (j->pld_slicr.bits.state == PLD_SLIC_STATE_ACTIVE || + j->pld_slicr.bits.state == PLD_SLIC_STATE_STANDBY) { + if (j->flags.ringing || j->flags.cringing) { + if (!in_interrupt()) { + msleep(20); + } + SLIC_GetState(j); + if (j->pld_slicr.bits.state == PLD_SLIC_STATE_RINGING) { + ixj_ring_on(j); + } + } + if (j->cardtype == QTI_PHONEJACK_PCI) { + j->pld_scrr.byte = inb_p(j->XILINXbase); + fOffHook = j->pld_scrr.pcib.det ? 1 : 0; + } else + fOffHook = j->pld_slicr.bits.det ? 1 : 0; + } + } + break; + case QTI_PHONECARD: + fOffHook = ixj_pcmcia_cable_check(j); + break; + } + if (j->r_hook != fOffHook) { + j->r_hook = fOffHook; + if (j->port == PORT_SPEAKER || j->port == PORT_HANDSET) { // || (j->port == PORT_PSTN && j->flags.pots_pstn == 0)) { + j->ex.bits.hookstate = 1; + ixj_kill_fasync(j, SIG_HOOKSTATE, POLL_IN); + } else if (!fOffHook) { + j->flash_end = jiffies + ((60 * hertz) / 100); + } + } + if (fOffHook) { + if(time_before(jiffies, j->flash_end)) { + j->ex.bits.flash = 1; + j->flash_end = 0; + ixj_kill_fasync(j, SIG_FLASH, POLL_IN); + } + } else { + if(time_before(jiffies, j->flash_end)) { + fOffHook = 1; + } + } + + if (j->port == PORT_PSTN && j->daa_mode == SOP_PU_CONVERSATION) + fOffHook |= 2; + + if (j->port == PORT_SPEAKER) { + if(j->cardtype == QTI_PHONECARD) { + if(j->flags.pcmciascp && j->flags.pcmciasct) { + fOffHook |= 2; + } + } else { + fOffHook |= 2; + } + } + + if (j->port == PORT_HANDSET) + fOffHook |= 2; + + return fOffHook; +} + +static void ixj_ring_off(IXJ *j) +{ + if (j->dsp.low == 0x20) /* Internet PhoneJACK */ + { + if (ixjdebug & 0x0004) + printk(KERN_INFO "IXJ Ring Off\n"); + j->gpio.bytes.high = 0x0B; + j->gpio.bytes.low = 0x00; + j->gpio.bits.gpio1 = 0; + j->gpio.bits.gpio2 = 1; + j->gpio.bits.gpio5 = 0; + ixj_WriteDSPCommand(j->gpio.word, j); + } else /* Internet LineJACK */ + { + if (ixjdebug & 0x0004) + printk(KERN_INFO "IXJ Ring Off\n"); + + if(!j->flags.cidplay) + SLIC_SetState(PLD_SLIC_STATE_STANDBY, j); + + SLIC_GetState(j); + } +} + +static void ixj_ring_start(IXJ *j) +{ + j->flags.cringing = 1; + if (ixjdebug & 0x0004) + printk(KERN_INFO "IXJ Cadence Ringing Start /dev/phone%d\n", j->board); + if (ixj_hookstate(j) & 1) { + if (j->port == PORT_POTS) + ixj_ring_off(j); + j->flags.cringing = 0; + if (ixjdebug & 0x0004) + printk(KERN_INFO "IXJ Cadence Ringing Stopped /dev/phone%d off hook\n", j->board); + } else if(j->cadence_f[5].enable && (!j->cadence_f[5].en_filter)) { + j->ring_cadence_jif = jiffies; + j->flags.cidsent = j->flags.cidring = 0; + j->cadence_f[5].state = 0; + if(j->cadence_f[5].on1) + ixj_ring_on(j); + } else { + j->ring_cadence_jif = jiffies; + j->ring_cadence_t = 15; + if (j->ring_cadence & 1 << j->ring_cadence_t) { + ixj_ring_on(j); + } else { + ixj_ring_off(j); + } + j->flags.cidsent = j->flags.cidring = j->flags.firstring = 0; + } +} + +static int ixj_ring(IXJ *j) +{ + char cntr; + unsigned long jif; + + j->flags.ringing = 1; + if (ixj_hookstate(j) & 1) { + ixj_ring_off(j); + j->flags.ringing = 0; + return 1; + } + for (cntr = 0; cntr < j->maxrings; cntr++) { + jif = jiffies + (1 * hertz); + ixj_ring_on(j); + while (time_before(jiffies, jif)) { + if (ixj_hookstate(j) & 1) { + ixj_ring_off(j); + j->flags.ringing = 0; + return 1; + } + schedule_timeout_interruptible(1); + if (signal_pending(current)) + break; + } + jif = jiffies + (3 * hertz); + ixj_ring_off(j); + while (time_before(jiffies, jif)) { + if (ixj_hookstate(j) & 1) { + msleep(10); + if (ixj_hookstate(j) & 1) { + j->flags.ringing = 0; + return 1; + } + } + schedule_timeout_interruptible(1); + if (signal_pending(current)) + break; + } + } + ixj_ring_off(j); + j->flags.ringing = 0; + return 0; +} + +static int ixj_open(struct phone_device *p, struct file *file_p) +{ + IXJ *j = get_ixj(p->board); + file_p->private_data = j; + + if (!j->DSPbase) + return -ENODEV; + + if (file_p->f_mode & FMODE_READ) { + if(!j->readers) { + j->readers++; + } else { + return -EBUSY; + } + } + + if (file_p->f_mode & FMODE_WRITE) { + if(!j->writers) { + j->writers++; + } else { + if (file_p->f_mode & FMODE_READ){ + j->readers--; + } + return -EBUSY; + } + } + + if (j->cardtype == QTI_PHONECARD) { + j->pslic.bits.powerdown = 0; + j->psccr.bits.dev = 3; + j->psccr.bits.rw = 0; + outw_p(j->psccr.byte << 8 | j->pslic.byte, j->XILINXbase + 0x00); + ixj_PCcontrol_wait(j); + } + + j->flags.cidplay = 0; + j->flags.cidcw_ack = 0; + + if (ixjdebug & 0x0002) + printk(KERN_INFO "Opening board %d\n", p->board); + + j->framesread = j->frameswritten = 0; + return 0; +} + +static int ixj_release(struct inode *inode, struct file *file_p) +{ + IXJ_TONE ti; + int cnt; + IXJ *j = file_p->private_data; + int board = j->p.board; + + /* + * Set up locks to ensure that only one process is talking to the DSP at a time. + * This is necessary to keep the DSP from locking up. + */ + while(test_and_set_bit(board, (void *)&j->busyflags) != 0) + schedule_timeout_interruptible(1); + if (ixjdebug & 0x0002) + printk(KERN_INFO "Closing board %d\n", NUM(inode)); + + if (j->cardtype == QTI_PHONECARD) + ixj_set_port(j, PORT_SPEAKER); + else + ixj_set_port(j, PORT_POTS); + + aec_stop(j); + ixj_play_stop(j); + ixj_record_stop(j); + set_play_volume(j, 0x100); + set_rec_volume(j, 0x100); + ixj_ring_off(j); + + /* Restore the tone table to default settings. */ + ti.tone_index = 10; + ti.gain0 = 1; + ti.freq0 = hz941; + ti.gain1 = 0; + ti.freq1 = hz1209; + ixj_init_tone(j, &ti); + ti.tone_index = 11; + ti.gain0 = 1; + ti.freq0 = hz941; + ti.gain1 = 0; + ti.freq1 = hz1336; + ixj_init_tone(j, &ti); + ti.tone_index = 12; + ti.gain0 = 1; + ti.freq0 = hz941; + ti.gain1 = 0; + ti.freq1 = hz1477; + ixj_init_tone(j, &ti); + ti.tone_index = 13; + ti.gain0 = 1; + ti.freq0 = hz800; + ti.gain1 = 0; + ti.freq1 = 0; + ixj_init_tone(j, &ti); + ti.tone_index = 14; + ti.gain0 = 1; + ti.freq0 = hz1000; + ti.gain1 = 0; + ti.freq1 = 0; + ixj_init_tone(j, &ti); + ti.tone_index = 15; + ti.gain0 = 1; + ti.freq0 = hz1250; + ti.gain1 = 0; + ti.freq1 = 0; + ixj_init_tone(j, &ti); + ti.tone_index = 16; + ti.gain0 = 1; + ti.freq0 = hz950; + ti.gain1 = 0; + ti.freq1 = 0; + ixj_init_tone(j, &ti); + ti.tone_index = 17; + ti.gain0 = 1; + ti.freq0 = hz1100; + ti.gain1 = 0; + ti.freq1 = 0; + ixj_init_tone(j, &ti); + ti.tone_index = 18; + ti.gain0 = 1; + ti.freq0 = hz1400; + ti.gain1 = 0; + ti.freq1 = 0; + ixj_init_tone(j, &ti); + ti.tone_index = 19; + ti.gain0 = 1; + ti.freq0 = hz1500; + ti.gain1 = 0; + ti.freq1 = 0; + ixj_init_tone(j, &ti); + ti.tone_index = 20; + ti.gain0 = 1; + ti.freq0 = hz1600; + ti.gain1 = 0; + ti.freq1 = 0; + ixj_init_tone(j, &ti); + ti.tone_index = 21; + ti.gain0 = 1; + ti.freq0 = hz1800; + ti.gain1 = 0; + ti.freq1 = 0; + ixj_init_tone(j, &ti); + ti.tone_index = 22; + ti.gain0 = 1; + ti.freq0 = hz2100; + ti.gain1 = 0; + ti.freq1 = 0; + ixj_init_tone(j, &ti); + ti.tone_index = 23; + ti.gain0 = 1; + ti.freq0 = hz1300; + ti.gain1 = 0; + ti.freq1 = 0; + ixj_init_tone(j, &ti); + ti.tone_index = 24; + ti.gain0 = 1; + ti.freq0 = hz2450; + ti.gain1 = 0; + ti.freq1 = 0; + ixj_init_tone(j, &ti); + ti.tone_index = 25; + ti.gain0 = 1; + ti.freq0 = hz350; + ti.gain1 = 0; + ti.freq1 = hz440; + ixj_init_tone(j, &ti); + ti.tone_index = 26; + ti.gain0 = 1; + ti.freq0 = hz440; + ti.gain1 = 0; + ti.freq1 = hz480; + ixj_init_tone(j, &ti); + ti.tone_index = 27; + ti.gain0 = 1; + ti.freq0 = hz480; + ti.gain1 = 0; + ti.freq1 = hz620; + ixj_init_tone(j, &ti); + + set_rec_depth(j, 2); /* Set Record Channel Limit to 2 frames */ + + set_play_depth(j, 2); /* Set Playback Channel Limit to 2 frames */ + + j->ex.bits.dtmf_ready = 0; + j->dtmf_state = 0; + j->dtmf_wp = j->dtmf_rp = 0; + j->rec_mode = j->play_mode = -1; + j->flags.ringing = 0; + j->maxrings = MAXRINGS; + j->ring_cadence = USA_RING_CADENCE; + if(j->cadence_f[5].enable) { + j->cadence_f[5].enable = j->cadence_f[5].en_filter = j->cadence_f[5].state = 0; + } + j->drybuffer = 0; + j->winktime = 320; + j->flags.dtmf_oob = 0; + for (cnt = 0; cnt < 4; cnt++) + j->cadence_f[cnt].enable = 0; + + idle(j); + + if(j->cardtype == QTI_PHONECARD) { + SLIC_SetState(PLD_SLIC_STATE_OC, j); + } + + if (file_p->f_mode & FMODE_READ) + j->readers--; + if (file_p->f_mode & FMODE_WRITE) + j->writers--; + + if (j->read_buffer && !j->readers) { + kfree(j->read_buffer); + j->read_buffer = NULL; + j->read_buffer_size = 0; + } + if (j->write_buffer && !j->writers) { + kfree(j->write_buffer); + j->write_buffer = NULL; + j->write_buffer_size = 0; + } + j->rec_codec = j->play_codec = 0; + j->rec_frame_size = j->play_frame_size = 0; + j->flags.cidsent = j->flags.cidring = 0; + + if(j->cardtype == QTI_LINEJACK && !j->readers && !j->writers) { + ixj_set_port(j, PORT_PSTN); + daa_set_mode(j, SOP_PU_SLEEP); + ixj_set_pots(j, 1); + } + ixj_WriteDSPCommand(0x0FE3, j); /* Put the DSP in 1/5 power mode. */ + + /* Set up the default signals for events */ + for (cnt = 0; cnt < 35; cnt++) + j->ixj_signals[cnt] = SIGIO; + + /* Set the excetion signal enable flags */ + j->ex_sig.bits.dtmf_ready = j->ex_sig.bits.hookstate = j->ex_sig.bits.flash = j->ex_sig.bits.pstn_ring = + j->ex_sig.bits.caller_id = j->ex_sig.bits.pstn_wink = j->ex_sig.bits.f0 = j->ex_sig.bits.f1 = j->ex_sig.bits.f2 = + j->ex_sig.bits.f3 = j->ex_sig.bits.fc0 = j->ex_sig.bits.fc1 = j->ex_sig.bits.fc2 = j->ex_sig.bits.fc3 = 1; + + file_p->private_data = NULL; + clear_bit(board, &j->busyflags); + return 0; +} + +static int read_filters(IXJ *j) +{ + unsigned short fc, cnt, trg; + int var; + + trg = 0; + if (ixj_WriteDSPCommand(0x5144, j)) { + if(ixjdebug & 0x0001) { + printk(KERN_INFO "Read Frame Counter failed!\n"); + } + return -1; + } + fc = j->ssr.high << 8 | j->ssr.low; + if (fc == j->frame_count) + return 1; + + j->frame_count = fc; + + if (j->dtmf_proc) + return 1; + + var = 10; + + for (cnt = 0; cnt < 4; cnt++) { + if (ixj_WriteDSPCommand(0x5154 + cnt, j)) { + if(ixjdebug & 0x0001) { + printk(KERN_INFO "Select Filter %d failed!\n", cnt); + } + return -1; + } + if (ixj_WriteDSPCommand(0x515C, j)) { + if(ixjdebug & 0x0001) { + printk(KERN_INFO "Read Filter History %d failed!\n", cnt); + } + return -1; + } + j->filter_hist[cnt] = j->ssr.high << 8 | j->ssr.low; + + if (j->cadence_f[cnt].enable) { + if (j->filter_hist[cnt] & 3 && !(j->filter_hist[cnt] & 12)) { + if (j->cadence_f[cnt].state == 0) { + j->cadence_f[cnt].state = 1; + j->cadence_f[cnt].on1min = jiffies + (long)((j->cadence_f[cnt].on1 * (hertz * (100 - var)) / 10000)); + j->cadence_f[cnt].on1dot = jiffies + (long)((j->cadence_f[cnt].on1 * (hertz * (100)) / 10000)); + j->cadence_f[cnt].on1max = jiffies + (long)((j->cadence_f[cnt].on1 * (hertz * (100 + var)) / 10000)); + } else if (j->cadence_f[cnt].state == 2 && + (time_after(jiffies, j->cadence_f[cnt].off1min) && + time_before(jiffies, j->cadence_f[cnt].off1max))) { + if (j->cadence_f[cnt].on2) { + j->cadence_f[cnt].state = 3; + j->cadence_f[cnt].on2min = jiffies + (long)((j->cadence_f[cnt].on2 * (hertz * (100 - var)) / 10000)); + j->cadence_f[cnt].on2dot = jiffies + (long)((j->cadence_f[cnt].on2 * (hertz * (100)) / 10000)); + j->cadence_f[cnt].on2max = jiffies + (long)((j->cadence_f[cnt].on2 * (hertz * (100 + var)) / 10000)); + } else { + j->cadence_f[cnt].state = 7; + } + } else if (j->cadence_f[cnt].state == 4 && + (time_after(jiffies, j->cadence_f[cnt].off2min) && + time_before(jiffies, j->cadence_f[cnt].off2max))) { + if (j->cadence_f[cnt].on3) { + j->cadence_f[cnt].state = 5; + j->cadence_f[cnt].on3min = jiffies + (long)((j->cadence_f[cnt].on3 * (hertz * (100 - var)) / 10000)); + j->cadence_f[cnt].on3dot = jiffies + (long)((j->cadence_f[cnt].on3 * (hertz * (100)) / 10000)); + j->cadence_f[cnt].on3max = jiffies + (long)((j->cadence_f[cnt].on3 * (hertz * (100 + var)) / 10000)); + } else { + j->cadence_f[cnt].state = 7; + } + } else { + j->cadence_f[cnt].state = 0; + } + } else if (j->filter_hist[cnt] & 12 && !(j->filter_hist[cnt] & 3)) { + if (j->cadence_f[cnt].state == 1) { + if(!j->cadence_f[cnt].on1) { + j->cadence_f[cnt].state = 7; + } else if((time_after(jiffies, j->cadence_f[cnt].on1min) && + time_before(jiffies, j->cadence_f[cnt].on1max))) { + if(j->cadence_f[cnt].off1) { + j->cadence_f[cnt].state = 2; + j->cadence_f[cnt].off1min = jiffies + (long)((j->cadence_f[cnt].off1 * (hertz * (100 - var)) / 10000)); + j->cadence_f[cnt].off1dot = jiffies + (long)((j->cadence_f[cnt].off1 * (hertz * (100)) / 10000)); + j->cadence_f[cnt].off1max = jiffies + (long)((j->cadence_f[cnt].off1 * (hertz * (100 + var)) / 10000)); + } else { + j->cadence_f[cnt].state = 7; + } + } else { + j->cadence_f[cnt].state = 0; + } + } else if (j->cadence_f[cnt].state == 3) { + if((time_after(jiffies, j->cadence_f[cnt].on2min) && + time_before(jiffies, j->cadence_f[cnt].on2max))) { + if(j->cadence_f[cnt].off2) { + j->cadence_f[cnt].state = 4; + j->cadence_f[cnt].off2min = jiffies + (long)((j->cadence_f[cnt].off2 * (hertz * (100 - var)) / 10000)); + j->cadence_f[cnt].off2dot = jiffies + (long)((j->cadence_f[cnt].off2 * (hertz * (100)) / 10000)); + j->cadence_f[cnt].off2max = jiffies + (long)((j->cadence_f[cnt].off2 * (hertz * (100 + var)) / 10000)); + } else { + j->cadence_f[cnt].state = 7; + } + } else { + j->cadence_f[cnt].state = 0; + } + } else if (j->cadence_f[cnt].state == 5) { + if ((time_after(jiffies, j->cadence_f[cnt].on3min) && + time_before(jiffies, j->cadence_f[cnt].on3max))) { + if(j->cadence_f[cnt].off3) { + j->cadence_f[cnt].state = 6; + j->cadence_f[cnt].off3min = jiffies + (long)((j->cadence_f[cnt].off3 * (hertz * (100 - var)) / 10000)); + j->cadence_f[cnt].off3dot = jiffies + (long)((j->cadence_f[cnt].off3 * (hertz * (100)) / 10000)); + j->cadence_f[cnt].off3max = jiffies + (long)((j->cadence_f[cnt].off3 * (hertz * (100 + var)) / 10000)); + } else { + j->cadence_f[cnt].state = 7; + } + } else { + j->cadence_f[cnt].state = 0; + } + } else { + j->cadence_f[cnt].state = 0; + } + } else { + switch(j->cadence_f[cnt].state) { + case 1: + if(time_after(jiffies, j->cadence_f[cnt].on1dot) && + !j->cadence_f[cnt].off1 && + !j->cadence_f[cnt].on2 && !j->cadence_f[cnt].off2 && + !j->cadence_f[cnt].on3 && !j->cadence_f[cnt].off3) { + j->cadence_f[cnt].state = 7; + } + break; + case 3: + if(time_after(jiffies, j->cadence_f[cnt].on2dot) && + !j->cadence_f[cnt].off2 && + !j->cadence_f[cnt].on3 && !j->cadence_f[cnt].off3) { + j->cadence_f[cnt].state = 7; + } + break; + case 5: + if(time_after(jiffies, j->cadence_f[cnt].on3dot) && + !j->cadence_f[cnt].off3) { + j->cadence_f[cnt].state = 7; + } + break; + } + } + + if (ixjdebug & 0x0040) { + printk(KERN_INFO "IXJ Tone Cadence state = %d /dev/phone%d at %ld\n", j->cadence_f[cnt].state, j->board, jiffies); + switch(j->cadence_f[cnt].state) { + case 0: + printk(KERN_INFO "IXJ /dev/phone%d No Tone detected\n", j->board); + break; + case 1: + printk(KERN_INFO "IXJ /dev/phone%d Next Tone Cadence state at %u %ld - %ld - %ld\n", j->board, + j->cadence_f[cnt].on1, j->cadence_f[cnt].on1min, j->cadence_f[cnt].on1dot, j->cadence_f[cnt].on1max); + break; + case 2: + printk(KERN_INFO "IXJ /dev/phone%d Next Tone Cadence state at %ld - %ld\n", j->board, j->cadence_f[cnt].off1min, + j->cadence_f[cnt].off1max); + break; + case 3: + printk(KERN_INFO "IXJ /dev/phone%d Next Tone Cadence state at %ld - %ld\n", j->board, j->cadence_f[cnt].on2min, + j->cadence_f[cnt].on2max); + break; + case 4: + printk(KERN_INFO "IXJ /dev/phone%d Next Tone Cadence state at %ld - %ld\n", j->board, j->cadence_f[cnt].off2min, + j->cadence_f[cnt].off2max); + break; + case 5: + printk(KERN_INFO "IXJ /dev/phone%d Next Tone Cadence state at %ld - %ld\n", j->board, j->cadence_f[cnt].on3min, + j->cadence_f[cnt].on3max); + break; + case 6: + printk(KERN_INFO "IXJ /dev/phone%d Next Tone Cadence state at %ld - %ld\n", j->board, j->cadence_f[cnt].off3min, + j->cadence_f[cnt].off3max); + break; + } + } + } + if (j->cadence_f[cnt].state == 7) { + j->cadence_f[cnt].state = 0; + if (j->cadence_f[cnt].enable == 1) + j->cadence_f[cnt].enable = 0; + switch (cnt) { + case 0: + if(ixjdebug & 0x0020) { + printk(KERN_INFO "Filter Cadence 0 triggered %ld\n", jiffies); + } + j->ex.bits.fc0 = 1; + ixj_kill_fasync(j, SIG_FC0, POLL_IN); + break; + case 1: + if(ixjdebug & 0x0020) { + printk(KERN_INFO "Filter Cadence 1 triggered %ld\n", jiffies); + } + j->ex.bits.fc1 = 1; + ixj_kill_fasync(j, SIG_FC1, POLL_IN); + break; + case 2: + if(ixjdebug & 0x0020) { + printk(KERN_INFO "Filter Cadence 2 triggered %ld\n", jiffies); + } + j->ex.bits.fc2 = 1; + ixj_kill_fasync(j, SIG_FC2, POLL_IN); + break; + case 3: + if(ixjdebug & 0x0020) { + printk(KERN_INFO "Filter Cadence 3 triggered %ld\n", jiffies); + } + j->ex.bits.fc3 = 1; + ixj_kill_fasync(j, SIG_FC3, POLL_IN); + break; + } + } + if (j->filter_en[cnt] && ((j->filter_hist[cnt] & 3 && !(j->filter_hist[cnt] & 12)) || + (j->filter_hist[cnt] & 12 && !(j->filter_hist[cnt] & 3)))) { + if((j->filter_hist[cnt] & 3 && !(j->filter_hist[cnt] & 12))) { + trg = 1; + } else if((j->filter_hist[cnt] & 12 && !(j->filter_hist[cnt] & 3))) { + trg = 0; + } + switch (cnt) { + case 0: + if(ixjdebug & 0x0020) { + printk(KERN_INFO "Filter 0 triggered %d at %ld\n", trg, jiffies); + } + j->ex.bits.f0 = 1; + ixj_kill_fasync(j, SIG_F0, POLL_IN); + break; + case 1: + if(ixjdebug & 0x0020) { + printk(KERN_INFO "Filter 1 triggered %d at %ld\n", trg, jiffies); + } + j->ex.bits.f1 = 1; + ixj_kill_fasync(j, SIG_F1, POLL_IN); + break; + case 2: + if(ixjdebug & 0x0020) { + printk(KERN_INFO "Filter 2 triggered %d at %ld\n", trg, jiffies); + } + j->ex.bits.f2 = 1; + ixj_kill_fasync(j, SIG_F2, POLL_IN); + break; + case 3: + if(ixjdebug & 0x0020) { + printk(KERN_INFO "Filter 3 triggered %d at %ld\n", trg, jiffies); + } + j->ex.bits.f3 = 1; + ixj_kill_fasync(j, SIG_F3, POLL_IN); + break; + } + } + } + return 0; +} + +static int LineMonitor(IXJ *j) +{ + if (j->dtmf_proc) { + return -1; + } + j->dtmf_proc = 1; + + if (ixj_WriteDSPCommand(0x7000, j)) /* Line Monitor */ + return -1; + + j->dtmf.bytes.high = j->ssr.high; + j->dtmf.bytes.low = j->ssr.low; + if (!j->dtmf_state && j->dtmf.bits.dtmf_valid) { + j->dtmf_state = 1; + j->dtmf_current = j->dtmf.bits.digit; + } + if (j->dtmf_state && !j->dtmf.bits.dtmf_valid) /* && j->dtmf_wp != j->dtmf_rp) */ + { + if(!j->cidcw_wait) { + j->dtmfbuffer[j->dtmf_wp] = j->dtmf_current; + j->dtmf_wp++; + if (j->dtmf_wp == 79) + j->dtmf_wp = 0; + j->ex.bits.dtmf_ready = 1; + if(j->ex_sig.bits.dtmf_ready) { + ixj_kill_fasync(j, SIG_DTMF_READY, POLL_IN); + } + } + else if(j->dtmf_current == 0x00 || j->dtmf_current == 0x0D) { + if(ixjdebug & 0x0020) { + printk("IXJ phone%d saw CIDCW Ack DTMF %d from display at %ld\n", j->board, j->dtmf_current, jiffies); + } + j->flags.cidcw_ack = 1; + } + j->dtmf_state = 0; + } + j->dtmf_proc = 0; + + return 0; +} + +/************************************************************************ +* +* Functions to allow alaw <-> ulaw conversions. +* +************************************************************************/ + +static void ulaw2alaw(unsigned char *buff, unsigned long len) +{ + static unsigned char table_ulaw2alaw[] = + { + 0x2A, 0x2B, 0x28, 0x29, 0x2E, 0x2F, 0x2C, 0x2D, + 0x22, 0x23, 0x20, 0x21, 0x26, 0x27, 0x24, 0x25, + 0x3A, 0x3B, 0x38, 0x39, 0x3E, 0x3F, 0x3C, 0x3D, + 0x32, 0x33, 0x30, 0x31, 0x36, 0x37, 0x34, 0x35, + 0x0B, 0x08, 0x09, 0x0E, 0x0F, 0x0C, 0x0D, 0x02, + 0x03, 0x00, 0x01, 0x06, 0x07, 0x04, 0x05, 0x1A, + 0x1B, 0x18, 0x19, 0x1E, 0x1F, 0x1C, 0x1D, 0x12, + 0x13, 0x10, 0x11, 0x16, 0x17, 0x14, 0x15, 0x6B, + 0x68, 0x69, 0x6E, 0x6F, 0x6C, 0x6D, 0x62, 0x63, + 0x60, 0x61, 0x66, 0x67, 0x64, 0x65, 0x7B, 0x79, + 0x7E, 0x7F, 0x7C, 0x7D, 0x72, 0x73, 0x70, 0x71, + 0x76, 0x77, 0x74, 0x75, 0x4B, 0x49, 0x4F, 0x4D, + 0x42, 0x43, 0x40, 0x41, 0x46, 0x47, 0x44, 0x45, + 0x5A, 0x5B, 0x58, 0x59, 0x5E, 0x5F, 0x5C, 0x5D, + 0x52, 0x52, 0x53, 0x53, 0x50, 0x50, 0x51, 0x51, + 0x56, 0x56, 0x57, 0x57, 0x54, 0x54, 0x55, 0xD5, + 0xAA, 0xAB, 0xA8, 0xA9, 0xAE, 0xAF, 0xAC, 0xAD, + 0xA2, 0xA3, 0xA0, 0xA1, 0xA6, 0xA7, 0xA4, 0xA5, + 0xBA, 0xBB, 0xB8, 0xB9, 0xBE, 0xBF, 0xBC, 0xBD, + 0xB2, 0xB3, 0xB0, 0xB1, 0xB6, 0xB7, 0xB4, 0xB5, + 0x8B, 0x88, 0x89, 0x8E, 0x8F, 0x8C, 0x8D, 0x82, + 0x83, 0x80, 0x81, 0x86, 0x87, 0x84, 0x85, 0x9A, + 0x9B, 0x98, 0x99, 0x9E, 0x9F, 0x9C, 0x9D, 0x92, + 0x93, 0x90, 0x91, 0x96, 0x97, 0x94, 0x95, 0xEB, + 0xE8, 0xE9, 0xEE, 0xEF, 0xEC, 0xED, 0xE2, 0xE3, + 0xE0, 0xE1, 0xE6, 0xE7, 0xE4, 0xE5, 0xFB, 0xF9, + 0xFE, 0xFF, 0xFC, 0xFD, 0xF2, 0xF3, 0xF0, 0xF1, + 0xF6, 0xF7, 0xF4, 0xF5, 0xCB, 0xC9, 0xCF, 0xCD, + 0xC2, 0xC3, 0xC0, 0xC1, 0xC6, 0xC7, 0xC4, 0xC5, + 0xDA, 0xDB, 0xD8, 0xD9, 0xDE, 0xDF, 0xDC, 0xDD, + 0xD2, 0xD2, 0xD3, 0xD3, 0xD0, 0xD0, 0xD1, 0xD1, + 0xD6, 0xD6, 0xD7, 0xD7, 0xD4, 0xD4, 0xD5, 0xD5 + }; + + while (len--) + { + *buff = table_ulaw2alaw[*(unsigned char *)buff]; + buff++; + } +} + +static void alaw2ulaw(unsigned char *buff, unsigned long len) +{ + static unsigned char table_alaw2ulaw[] = + { + 0x29, 0x2A, 0x27, 0x28, 0x2D, 0x2E, 0x2B, 0x2C, + 0x21, 0x22, 0x1F, 0x20, 0x25, 0x26, 0x23, 0x24, + 0x39, 0x3A, 0x37, 0x38, 0x3D, 0x3E, 0x3B, 0x3C, + 0x31, 0x32, 0x2F, 0x30, 0x35, 0x36, 0x33, 0x34, + 0x0A, 0x0B, 0x08, 0x09, 0x0E, 0x0F, 0x0C, 0x0D, + 0x02, 0x03, 0x00, 0x01, 0x06, 0x07, 0x04, 0x05, + 0x1A, 0x1B, 0x18, 0x19, 0x1E, 0x1F, 0x1C, 0x1D, + 0x12, 0x13, 0x10, 0x11, 0x16, 0x17, 0x14, 0x15, + 0x62, 0x63, 0x60, 0x61, 0x66, 0x67, 0x64, 0x65, + 0x5D, 0x5D, 0x5C, 0x5C, 0x5F, 0x5F, 0x5E, 0x5E, + 0x74, 0x76, 0x70, 0x72, 0x7C, 0x7E, 0x78, 0x7A, + 0x6A, 0x6B, 0x68, 0x69, 0x6E, 0x6F, 0x6C, 0x6D, + 0x48, 0x49, 0x46, 0x47, 0x4C, 0x4D, 0x4A, 0x4B, + 0x40, 0x41, 0x3F, 0x3F, 0x44, 0x45, 0x42, 0x43, + 0x56, 0x57, 0x54, 0x55, 0x5A, 0x5B, 0x58, 0x59, + 0x4F, 0x4F, 0x4E, 0x4E, 0x52, 0x53, 0x50, 0x51, + 0xA9, 0xAA, 0xA7, 0xA8, 0xAD, 0xAE, 0xAB, 0xAC, + 0xA1, 0xA2, 0x9F, 0xA0, 0xA5, 0xA6, 0xA3, 0xA4, + 0xB9, 0xBA, 0xB7, 0xB8, 0xBD, 0xBE, 0xBB, 0xBC, + 0xB1, 0xB2, 0xAF, 0xB0, 0xB5, 0xB6, 0xB3, 0xB4, + 0x8A, 0x8B, 0x88, 0x89, 0x8E, 0x8F, 0x8C, 0x8D, + 0x82, 0x83, 0x80, 0x81, 0x86, 0x87, 0x84, 0x85, + 0x9A, 0x9B, 0x98, 0x99, 0x9E, 0x9F, 0x9C, 0x9D, + 0x92, 0x93, 0x90, 0x91, 0x96, 0x97, 0x94, 0x95, + 0xE2, 0xE3, 0xE0, 0xE1, 0xE6, 0xE7, 0xE4, 0xE5, + 0xDD, 0xDD, 0xDC, 0xDC, 0xDF, 0xDF, 0xDE, 0xDE, + 0xF4, 0xF6, 0xF0, 0xF2, 0xFC, 0xFE, 0xF8, 0xFA, + 0xEA, 0xEB, 0xE8, 0xE9, 0xEE, 0xEF, 0xEC, 0xED, + 0xC8, 0xC9, 0xC6, 0xC7, 0xCC, 0xCD, 0xCA, 0xCB, + 0xC0, 0xC1, 0xBF, 0xBF, 0xC4, 0xC5, 0xC2, 0xC3, + 0xD6, 0xD7, 0xD4, 0xD5, 0xDA, 0xDB, 0xD8, 0xD9, + 0xCF, 0xCF, 0xCE, 0xCE, 0xD2, 0xD3, 0xD0, 0xD1 + }; + + while (len--) + { + *buff = table_alaw2ulaw[*(unsigned char *)buff]; + buff++; + } +} + +static ssize_t ixj_read(struct file * file_p, char __user *buf, size_t length, loff_t * ppos) +{ + unsigned long i = *ppos; + IXJ * j = get_ixj(NUM(file_p->f_path.dentry->d_inode)); + + DECLARE_WAITQUEUE(wait, current); + + if (j->flags.inread) + return -EALREADY; + + j->flags.inread = 1; + + add_wait_queue(&j->read_q, &wait); + set_current_state(TASK_INTERRUPTIBLE); + mb(); + + while (!j->read_buffer_ready || (j->dtmf_state && j->flags.dtmf_oob)) { + ++j->read_wait; + if (file_p->f_flags & O_NONBLOCK) { + set_current_state(TASK_RUNNING); + remove_wait_queue(&j->read_q, &wait); + j->flags.inread = 0; + return -EAGAIN; + } + if (!ixj_hookstate(j)) { + set_current_state(TASK_RUNNING); + remove_wait_queue(&j->read_q, &wait); + j->flags.inread = 0; + return 0; + } + interruptible_sleep_on(&j->read_q); + if (signal_pending(current)) { + set_current_state(TASK_RUNNING); + remove_wait_queue(&j->read_q, &wait); + j->flags.inread = 0; + return -EINTR; + } + } + + remove_wait_queue(&j->read_q, &wait); + set_current_state(TASK_RUNNING); + /* Don't ever copy more than the user asks */ + if(j->rec_codec == ALAW) + ulaw2alaw(j->read_buffer, min(length, j->read_buffer_size)); + i = copy_to_user(buf, j->read_buffer, min(length, j->read_buffer_size)); + j->read_buffer_ready = 0; + if (i) { + j->flags.inread = 0; + return -EFAULT; + } else { + j->flags.inread = 0; + return min(length, j->read_buffer_size); + } +} + +static ssize_t ixj_enhanced_read(struct file * file_p, char __user *buf, size_t length, + loff_t * ppos) +{ + int pre_retval; + ssize_t read_retval = 0; + IXJ *j = get_ixj(NUM(file_p->f_path.dentry->d_inode)); + + pre_retval = ixj_PreRead(j, 0L); + switch (pre_retval) { + case NORMAL: + read_retval = ixj_read(file_p, buf, length, ppos); + ixj_PostRead(j, 0L); + break; + case NOPOST: + read_retval = ixj_read(file_p, buf, length, ppos); + break; + case POSTONLY: + ixj_PostRead(j, 0L); + break; + default: + read_retval = pre_retval; + } + return read_retval; +} + +static ssize_t ixj_write(struct file *file_p, const char __user *buf, size_t count, loff_t * ppos) +{ + unsigned long i = *ppos; + IXJ *j = file_p->private_data; + + DECLARE_WAITQUEUE(wait, current); + + if (j->flags.inwrite) + return -EALREADY; + + j->flags.inwrite = 1; + + add_wait_queue(&j->write_q, &wait); + set_current_state(TASK_INTERRUPTIBLE); + mb(); + + + while (!j->write_buffers_empty) { + ++j->write_wait; + if (file_p->f_flags & O_NONBLOCK) { + set_current_state(TASK_RUNNING); + remove_wait_queue(&j->write_q, &wait); + j->flags.inwrite = 0; + return -EAGAIN; + } + if (!ixj_hookstate(j)) { + set_current_state(TASK_RUNNING); + remove_wait_queue(&j->write_q, &wait); + j->flags.inwrite = 0; + return 0; + } + interruptible_sleep_on(&j->write_q); + if (signal_pending(current)) { + set_current_state(TASK_RUNNING); + remove_wait_queue(&j->write_q, &wait); + j->flags.inwrite = 0; + return -EINTR; + } + } + set_current_state(TASK_RUNNING); + remove_wait_queue(&j->write_q, &wait); + if (j->write_buffer_wp + count >= j->write_buffer_end) + j->write_buffer_wp = j->write_buffer; + i = copy_from_user(j->write_buffer_wp, buf, min(count, j->write_buffer_size)); + if (i) { + j->flags.inwrite = 0; + return -EFAULT; + } + if(j->play_codec == ALAW) + alaw2ulaw(j->write_buffer_wp, min(count, j->write_buffer_size)); + j->flags.inwrite = 0; + return min(count, j->write_buffer_size); +} + +static ssize_t ixj_enhanced_write(struct file * file_p, const char __user *buf, size_t count, loff_t * ppos) +{ + int pre_retval; + ssize_t write_retval = 0; + + IXJ *j = get_ixj(NUM(file_p->f_path.dentry->d_inode)); + + pre_retval = ixj_PreWrite(j, 0L); + switch (pre_retval) { + case NORMAL: + write_retval = ixj_write(file_p, buf, count, ppos); + if (write_retval > 0) { + ixj_PostWrite(j, 0L); + j->write_buffer_wp += write_retval; + j->write_buffers_empty--; + } + break; + case NOPOST: + write_retval = ixj_write(file_p, buf, count, ppos); + if (write_retval > 0) { + j->write_buffer_wp += write_retval; + j->write_buffers_empty--; + } + break; + case POSTONLY: + ixj_PostWrite(j, 0L); + break; + default: + write_retval = pre_retval; + } + return write_retval; +} + +static void ixj_read_frame(IXJ *j) +{ + int cnt, dly; + + if (j->read_buffer) { + for (cnt = 0; cnt < j->rec_frame_size * 2; cnt += 2) { + if (!(cnt % 16) && !IsRxReady(j)) { + dly = 0; + while (!IsRxReady(j)) { + if (dly++ > 5) { + dly = 0; + break; + } + udelay(10); + } + } + /* Throw away word 0 of the 8021 compressed format to get standard G.729. */ + if (j->rec_codec == G729 && (cnt == 0 || cnt == 10 || cnt == 20)) { + inb_p(j->DSPbase + 0x0E); + inb_p(j->DSPbase + 0x0F); + } + *(j->read_buffer + cnt) = inb_p(j->DSPbase + 0x0E); + *(j->read_buffer + cnt + 1) = inb_p(j->DSPbase + 0x0F); + } + ++j->framesread; + if (j->intercom != -1) { + if (IsTxReady(get_ixj(j->intercom))) { + for (cnt = 0; cnt < j->rec_frame_size * 2; cnt += 2) { + if (!(cnt % 16) && !IsTxReady(j)) { + dly = 0; + while (!IsTxReady(j)) { + if (dly++ > 5) { + dly = 0; + break; + } + udelay(10); + } + } + outb_p(*(j->read_buffer + cnt), get_ixj(j->intercom)->DSPbase + 0x0C); + outb_p(*(j->read_buffer + cnt + 1), get_ixj(j->intercom)->DSPbase + 0x0D); + } + get_ixj(j->intercom)->frameswritten++; + } + } else { + j->read_buffer_ready = 1; + wake_up_interruptible(&j->read_q); /* Wake any blocked readers */ + + wake_up_interruptible(&j->poll_q); /* Wake any blocked selects */ + + if(j->ixj_signals[SIG_READ_READY]) + ixj_kill_fasync(j, SIG_READ_READY, POLL_OUT); + } + } +} + +static short fsk[][6][20] = +{ + { + { + 0, 17846, 29934, 32364, 24351, 8481, -10126, -25465, -32587, -29196, + -16384, 1715, 19260, 30591, 32051, 23170, 6813, -11743, -26509, -32722 + }, + { + -28377, -14876, 3425, 20621, 31163, 31650, 21925, 5126, -13328, -27481, + -32767, -27481, -13328, 5126, 21925, 31650, 31163, 20621, 3425, -14876 + }, + { + -28377, -32722, -26509, -11743, 6813, 23170, 32051, 30591, 19260, 1715, + -16384, -29196, -32587, -25465, -10126, 8481, 24351, 32364, 29934, 17846 + }, + { + 0, -17846, -29934, -32364, -24351, -8481, 10126, 25465, 32587, 29196, + 16384, -1715, -19260, -30591, -32051, -23170, -6813, 11743, 26509, 32722 + }, + { + 28377, 14876, -3425, -20621, -31163, -31650, -21925, -5126, 13328, 27481, + 32767, 27481, 13328, -5126, -21925, -31650, -31163, -20621, -3425, 14876 + }, + { + 28377, 32722, 26509, 11743, -6813, -23170, -32051, -30591, -19260, -1715, + 16384, 29196, 32587, 25465, 10126, -8481, -24351, -32364, -29934, -17846 + } + }, + { + { + 0, 10126, 19260, 26509, 31163, 32767, 31163, 26509, 19260, 10126, + 0, -10126, -19260, -26509, -31163, -32767, -31163, -26509, -19260, -10126 + }, + { + -28377, -21925, -13328, -3425, 6813, 16384, 24351, 29934, 32587, 32051, + 28377, 21925, 13328, 3425, -6813, -16384, -24351, -29934, -32587, -32051 + }, + { + -28377, -32051, -32587, -29934, -24351, -16384, -6813, 3425, 13328, 21925, + 28377, 32051, 32587, 29934, 24351, 16384, 6813, -3425, -13328, -21925 + }, + { + 0, -10126, -19260, -26509, -31163, -32767, -31163, -26509, -19260, -10126, + 0, 10126, 19260, 26509, 31163, 32767, 31163, 26509, 19260, 10126 + }, + { + 28377, 21925, 13328, 3425, -6813, -16383, -24351, -29934, -32587, -32051, + -28377, -21925, -13328, -3425, 6813, 16383, 24351, 29934, 32587, 32051 + }, + { + 28377, 32051, 32587, 29934, 24351, 16384, 6813, -3425, -13328, -21925, + -28377, -32051, -32587, -29934, -24351, -16384, -6813, 3425, 13328, 21925 + } + } +}; + + +static void ixj_write_cid_bit(IXJ *j, int bit) +{ + while (j->fskcnt < 20) { + if(j->fskdcnt < (j->fsksize - 1)) + j->fskdata[j->fskdcnt++] = fsk[bit][j->fskz][j->fskcnt]; + + j->fskcnt += 3; + } + j->fskcnt %= 20; + + if (!bit) + j->fskz++; + if (j->fskz >= 6) + j->fskz = 0; + +} + +static void ixj_write_cid_byte(IXJ *j, char byte) +{ + IXJ_CBYTE cb; + + cb.cbyte = byte; + ixj_write_cid_bit(j, 0); + ixj_write_cid_bit(j, cb.cbits.b0 ? 1 : 0); + ixj_write_cid_bit(j, cb.cbits.b1 ? 1 : 0); + ixj_write_cid_bit(j, cb.cbits.b2 ? 1 : 0); + ixj_write_cid_bit(j, cb.cbits.b3 ? 1 : 0); + ixj_write_cid_bit(j, cb.cbits.b4 ? 1 : 0); + ixj_write_cid_bit(j, cb.cbits.b5 ? 1 : 0); + ixj_write_cid_bit(j, cb.cbits.b6 ? 1 : 0); + ixj_write_cid_bit(j, cb.cbits.b7 ? 1 : 0); + ixj_write_cid_bit(j, 1); +} + +static void ixj_write_cid_seize(IXJ *j) +{ + int cnt; + + for (cnt = 0; cnt < 150; cnt++) { + ixj_write_cid_bit(j, 0); + ixj_write_cid_bit(j, 1); + } + for (cnt = 0; cnt < 180; cnt++) { + ixj_write_cid_bit(j, 1); + } +} + +static void ixj_write_cidcw_seize(IXJ *j) +{ + int cnt; + + for (cnt = 0; cnt < 80; cnt++) { + ixj_write_cid_bit(j, 1); + } +} + +static int ixj_write_cid_string(IXJ *j, char *s, int checksum) +{ + int cnt; + + for (cnt = 0; cnt < strlen(s); cnt++) { + ixj_write_cid_byte(j, s[cnt]); + checksum = (checksum + s[cnt]); + } + return checksum; +} + +static void ixj_pad_fsk(IXJ *j, int pad) +{ + int cnt; + + for (cnt = 0; cnt < pad; cnt++) { + if(j->fskdcnt < (j->fsksize - 1)) + j->fskdata[j->fskdcnt++] = 0x0000; + } + for (cnt = 0; cnt < 720; cnt++) { + if(j->fskdcnt < (j->fsksize - 1)) + j->fskdata[j->fskdcnt++] = 0x0000; + } +} + +static void ixj_pre_cid(IXJ *j) +{ + j->cid_play_codec = j->play_codec; + j->cid_play_frame_size = j->play_frame_size; + j->cid_play_volume = get_play_volume(j); + j->cid_play_flag = j->flags.playing; + + j->cid_rec_codec = j->rec_codec; + j->cid_rec_volume = get_rec_volume(j); + j->cid_rec_flag = j->flags.recording; + + j->cid_play_aec_level = j->aec_level; + + switch(j->baseframe.low) { + case 0xA0: + j->cid_base_frame_size = 20; + break; + case 0x50: + j->cid_base_frame_size = 10; + break; + case 0xF0: + j->cid_base_frame_size = 30; + break; + } + + ixj_play_stop(j); + ixj_cpt_stop(j); + + j->flags.cidplay = 1; + + set_base_frame(j, 30); + set_play_codec(j, LINEAR16); + set_play_volume(j, 0x1B); + ixj_play_start(j); +} + +static void ixj_post_cid(IXJ *j) +{ + ixj_play_stop(j); + + if(j->cidsize > 5000) { + SLIC_SetState(PLD_SLIC_STATE_STANDBY, j); + } + j->flags.cidplay = 0; + if(ixjdebug & 0x0200) { + printk("IXJ phone%d Finished Playing CallerID data %ld\n", j->board, jiffies); + } + + ixj_fsk_free(j); + + j->fskdcnt = 0; + set_base_frame(j, j->cid_base_frame_size); + set_play_codec(j, j->cid_play_codec); + ixj_aec_start(j, j->cid_play_aec_level); + set_play_volume(j, j->cid_play_volume); + + set_rec_codec(j, j->cid_rec_codec); + set_rec_volume(j, j->cid_rec_volume); + + if(j->cid_rec_flag) + ixj_record_start(j); + + if(j->cid_play_flag) + ixj_play_start(j); + + if(j->cid_play_flag) { + wake_up_interruptible(&j->write_q); /* Wake any blocked writers */ + } +} + +static void ixj_write_cid(IXJ *j) +{ + char sdmf1[50]; + char sdmf2[50]; + char sdmf3[80]; + char mdmflen, len1, len2, len3; + int pad; + + int checksum = 0; + + if (j->dsp.low == 0x20 || j->flags.cidplay) + return; + + j->fskz = j->fskphase = j->fskcnt = j->fskdcnt = 0; + j->cidsize = j->cidcnt = 0; + + ixj_fsk_alloc(j); + + strcpy(sdmf1, j->cid_send.month); + strcat(sdmf1, j->cid_send.day); + strcat(sdmf1, j->cid_send.hour); + strcat(sdmf1, j->cid_send.min); + strcpy(sdmf2, j->cid_send.number); + strcpy(sdmf3, j->cid_send.name); + + len1 = strlen(sdmf1); + len2 = strlen(sdmf2); + len3 = strlen(sdmf3); + mdmflen = len1 + len2 + len3 + 6; + + while(1){ + ixj_write_cid_seize(j); + + ixj_write_cid_byte(j, 0x80); + checksum = 0x80; + ixj_write_cid_byte(j, mdmflen); + checksum = checksum + mdmflen; + + ixj_write_cid_byte(j, 0x01); + checksum = checksum + 0x01; + ixj_write_cid_byte(j, len1); + checksum = checksum + len1; + checksum = ixj_write_cid_string(j, sdmf1, checksum); + if(ixj_hookstate(j) & 1) + break; + + ixj_write_cid_byte(j, 0x02); + checksum = checksum + 0x02; + ixj_write_cid_byte(j, len2); + checksum = checksum + len2; + checksum = ixj_write_cid_string(j, sdmf2, checksum); + if(ixj_hookstate(j) & 1) + break; + + ixj_write_cid_byte(j, 0x07); + checksum = checksum + 0x07; + ixj_write_cid_byte(j, len3); + checksum = checksum + len3; + checksum = ixj_write_cid_string(j, sdmf3, checksum); + if(ixj_hookstate(j) & 1) + break; + + checksum %= 256; + checksum ^= 0xFF; + checksum += 1; + + ixj_write_cid_byte(j, (char) checksum); + + pad = j->fskdcnt % 240; + if (pad) { + pad = 240 - pad; + } + ixj_pad_fsk(j, pad); + break; + } + + ixj_write_frame(j); +} + +static void ixj_write_cidcw(IXJ *j) +{ + IXJ_TONE ti; + + char sdmf1[50]; + char sdmf2[50]; + char sdmf3[80]; + char mdmflen, len1, len2, len3; + int pad; + + int checksum = 0; + + if (j->dsp.low == 0x20 || j->flags.cidplay) + return; + + j->fskz = j->fskphase = j->fskcnt = j->fskdcnt = 0; + j->cidsize = j->cidcnt = 0; + + ixj_fsk_alloc(j); + + j->flags.cidcw_ack = 0; + + ti.tone_index = 23; + ti.gain0 = 1; + ti.freq0 = hz440; + ti.gain1 = 0; + ti.freq1 = 0; + ixj_init_tone(j, &ti); + + ixj_set_tone_on(1500, j); + ixj_set_tone_off(32, j); + if(ixjdebug & 0x0200) { + printk("IXJ cidcw phone%d first tone start at %ld\n", j->board, jiffies); + } + ixj_play_tone(j, 23); + + clear_bit(j->board, &j->busyflags); + while(j->tone_state) + schedule_timeout_interruptible(1); + while(test_and_set_bit(j->board, (void *)&j->busyflags) != 0) + schedule_timeout_interruptible(1); + if(ixjdebug & 0x0200) { + printk("IXJ cidcw phone%d first tone end at %ld\n", j->board, jiffies); + } + + ti.tone_index = 24; + ti.gain0 = 1; + ti.freq0 = hz2130; + ti.gain1 = 0; + ti.freq1 = hz2750; + ixj_init_tone(j, &ti); + + ixj_set_tone_off(10, j); + ixj_set_tone_on(600, j); + if(ixjdebug & 0x0200) { + printk("IXJ cidcw phone%d second tone start at %ld\n", j->board, jiffies); + } + ixj_play_tone(j, 24); + + clear_bit(j->board, &j->busyflags); + while(j->tone_state) + schedule_timeout_interruptible(1); + while(test_and_set_bit(j->board, (void *)&j->busyflags) != 0) + schedule_timeout_interruptible(1); + if(ixjdebug & 0x0200) { + printk("IXJ cidcw phone%d sent second tone at %ld\n", j->board, jiffies); + } + + j->cidcw_wait = jiffies + ((50 * hertz) / 100); + + clear_bit(j->board, &j->busyflags); + while(!j->flags.cidcw_ack && time_before(jiffies, j->cidcw_wait)) + schedule_timeout_interruptible(1); + while(test_and_set_bit(j->board, (void *)&j->busyflags) != 0) + schedule_timeout_interruptible(1); + j->cidcw_wait = 0; + if(!j->flags.cidcw_ack) { + if(ixjdebug & 0x0200) { + printk("IXJ cidcw phone%d did not receive ACK from display %ld\n", j->board, jiffies); + } + ixj_post_cid(j); + if(j->cid_play_flag) { + wake_up_interruptible(&j->write_q); /* Wake any blocked readers */ + } + return; + } else { + ixj_pre_cid(j); + } + j->flags.cidcw_ack = 0; + strcpy(sdmf1, j->cid_send.month); + strcat(sdmf1, j->cid_send.day); + strcat(sdmf1, j->cid_send.hour); + strcat(sdmf1, j->cid_send.min); + strcpy(sdmf2, j->cid_send.number); + strcpy(sdmf3, j->cid_send.name); + + len1 = strlen(sdmf1); + len2 = strlen(sdmf2); + len3 = strlen(sdmf3); + mdmflen = len1 + len2 + len3 + 6; + + ixj_write_cidcw_seize(j); + + ixj_write_cid_byte(j, 0x80); + checksum = 0x80; + ixj_write_cid_byte(j, mdmflen); + checksum = checksum + mdmflen; + + ixj_write_cid_byte(j, 0x01); + checksum = checksum + 0x01; + ixj_write_cid_byte(j, len1); + checksum = checksum + len1; + checksum = ixj_write_cid_string(j, sdmf1, checksum); + + ixj_write_cid_byte(j, 0x02); + checksum = checksum + 0x02; + ixj_write_cid_byte(j, len2); + checksum = checksum + len2; + checksum = ixj_write_cid_string(j, sdmf2, checksum); + + ixj_write_cid_byte(j, 0x07); + checksum = checksum + 0x07; + ixj_write_cid_byte(j, len3); + checksum = checksum + len3; + checksum = ixj_write_cid_string(j, sdmf3, checksum); + + checksum %= 256; + checksum ^= 0xFF; + checksum += 1; + + ixj_write_cid_byte(j, (char) checksum); + + pad = j->fskdcnt % 240; + if (pad) { + pad = 240 - pad; + } + ixj_pad_fsk(j, pad); + if(ixjdebug & 0x0200) { + printk("IXJ cidcw phone%d sent FSK data at %ld\n", j->board, jiffies); + } +} + +static void ixj_write_vmwi(IXJ *j, int msg) +{ + char mdmflen; + int pad; + + int checksum = 0; + + if (j->dsp.low == 0x20 || j->flags.cidplay) + return; + + j->fskz = j->fskphase = j->fskcnt = j->fskdcnt = 0; + j->cidsize = j->cidcnt = 0; + + ixj_fsk_alloc(j); + + mdmflen = 3; + + if (j->port == PORT_POTS) + SLIC_SetState(PLD_SLIC_STATE_OHT, j); + + ixj_write_cid_seize(j); + + ixj_write_cid_byte(j, 0x82); + checksum = 0x82; + ixj_write_cid_byte(j, mdmflen); + checksum = checksum + mdmflen; + + ixj_write_cid_byte(j, 0x0B); + checksum = checksum + 0x0B; + ixj_write_cid_byte(j, 1); + checksum = checksum + 1; + + if(msg) { + ixj_write_cid_byte(j, 0xFF); + checksum = checksum + 0xFF; + } + else { + ixj_write_cid_byte(j, 0x00); + checksum = checksum + 0x00; + } + + checksum %= 256; + checksum ^= 0xFF; + checksum += 1; + + ixj_write_cid_byte(j, (char) checksum); + + pad = j->fskdcnt % 240; + if (pad) { + pad = 240 - pad; + } + ixj_pad_fsk(j, pad); +} + +static void ixj_write_frame(IXJ *j) +{ + int cnt, frame_count, dly; + IXJ_WORD dat; + + frame_count = 0; + if(j->flags.cidplay) { + for(cnt = 0; cnt < 480; cnt++) { + if (!(cnt % 16) && !IsTxReady(j)) { + dly = 0; + while (!IsTxReady(j)) { + if (dly++ > 5) { + dly = 0; + break; + } + udelay(10); + } + } + dat.word = j->fskdata[j->cidcnt++]; + outb_p(dat.bytes.low, j->DSPbase + 0x0C); + outb_p(dat.bytes.high, j->DSPbase + 0x0D); + cnt++; + } + if(j->cidcnt >= j->fskdcnt) { + ixj_post_cid(j); + } + /* This may seem rude, but if we just played one frame of FSK data for CallerID + and there is real audio data in the buffer, we need to throw it away because + we just used it's time slot */ + if (j->write_buffer_rp > j->write_buffer_wp) { + j->write_buffer_rp += j->cid_play_frame_size * 2; + if (j->write_buffer_rp >= j->write_buffer_end) { + j->write_buffer_rp = j->write_buffer; + } + j->write_buffers_empty++; + wake_up_interruptible(&j->write_q); /* Wake any blocked writers */ + + wake_up_interruptible(&j->poll_q); /* Wake any blocked selects */ + } + } else if (j->write_buffer && j->write_buffers_empty < 1) { + if (j->write_buffer_wp > j->write_buffer_rp) { + frame_count = + (j->write_buffer_wp - j->write_buffer_rp) / (j->play_frame_size * 2); + } + if (j->write_buffer_rp > j->write_buffer_wp) { + frame_count = + (j->write_buffer_wp - j->write_buffer) / (j->play_frame_size * 2) + + (j->write_buffer_end - j->write_buffer_rp) / (j->play_frame_size * 2); + } + if (frame_count >= 1) { + if (j->ver.low == 0x12 && j->play_mode && j->flags.play_first_frame) { + BYTES blankword; + + switch (j->play_mode) { + case PLAYBACK_MODE_ULAW: + case PLAYBACK_MODE_ALAW: + blankword.low = blankword.high = 0xFF; + break; + case PLAYBACK_MODE_8LINEAR: + case PLAYBACK_MODE_16LINEAR: + default: + blankword.low = blankword.high = 0x00; + break; + case PLAYBACK_MODE_8LINEAR_WSS: + blankword.low = blankword.high = 0x80; + break; + } + for (cnt = 0; cnt < 16; cnt++) { + if (!(cnt % 16) && !IsTxReady(j)) { + dly = 0; + while (!IsTxReady(j)) { + if (dly++ > 5) { + dly = 0; + break; + } + udelay(10); + } + } + outb_p((blankword.low), j->DSPbase + 0x0C); + outb_p((blankword.high), j->DSPbase + 0x0D); + } + j->flags.play_first_frame = 0; + } else if (j->play_codec == G723_63 && j->flags.play_first_frame) { + for (cnt = 0; cnt < 24; cnt++) { + BYTES blankword; + + if(cnt == 12) { + blankword.low = 0x02; + blankword.high = 0x00; + } + else { + blankword.low = blankword.high = 0x00; + } + if (!(cnt % 16) && !IsTxReady(j)) { + dly = 0; + while (!IsTxReady(j)) { + if (dly++ > 5) { + dly = 0; + break; + } + udelay(10); + } + } + outb_p((blankword.low), j->DSPbase + 0x0C); + outb_p((blankword.high), j->DSPbase + 0x0D); + } + j->flags.play_first_frame = 0; + } + for (cnt = 0; cnt < j->play_frame_size * 2; cnt += 2) { + if (!(cnt % 16) && !IsTxReady(j)) { + dly = 0; + while (!IsTxReady(j)) { + if (dly++ > 5) { + dly = 0; + break; + } + udelay(10); + } + } + /* Add word 0 to G.729 frames for the 8021. Right now we don't do VAD/CNG */ + if (j->play_codec == G729 && (cnt == 0 || cnt == 10 || cnt == 20)) { + if (j->write_buffer_rp[cnt] == 0 && + j->write_buffer_rp[cnt + 1] == 0 && + j->write_buffer_rp[cnt + 2] == 0 && + j->write_buffer_rp[cnt + 3] == 0 && + j->write_buffer_rp[cnt + 4] == 0 && + j->write_buffer_rp[cnt + 5] == 0 && + j->write_buffer_rp[cnt + 6] == 0 && + j->write_buffer_rp[cnt + 7] == 0 && + j->write_buffer_rp[cnt + 8] == 0 && + j->write_buffer_rp[cnt + 9] == 0) { + /* someone is trying to write silence lets make this a type 0 frame. */ + outb_p(0x00, j->DSPbase + 0x0C); + outb_p(0x00, j->DSPbase + 0x0D); + } else { + /* so all other frames are type 1. */ + outb_p(0x01, j->DSPbase + 0x0C); + outb_p(0x00, j->DSPbase + 0x0D); + } + } + outb_p(*(j->write_buffer_rp + cnt), j->DSPbase + 0x0C); + outb_p(*(j->write_buffer_rp + cnt + 1), j->DSPbase + 0x0D); + *(j->write_buffer_rp + cnt) = 0; + *(j->write_buffer_rp + cnt + 1) = 0; + } + j->write_buffer_rp += j->play_frame_size * 2; + if (j->write_buffer_rp >= j->write_buffer_end) { + j->write_buffer_rp = j->write_buffer; + } + j->write_buffers_empty++; + wake_up_interruptible(&j->write_q); /* Wake any blocked writers */ + + wake_up_interruptible(&j->poll_q); /* Wake any blocked selects */ + + ++j->frameswritten; + } + } else { + j->drybuffer++; + } + if(j->ixj_signals[SIG_WRITE_READY]) { + ixj_kill_fasync(j, SIG_WRITE_READY, POLL_OUT); + } +} + +static int idle(IXJ *j) +{ + if (ixj_WriteDSPCommand(0x0000, j)) /* DSP Idle */ + + return 0; + + if (j->ssr.high || j->ssr.low) { + return 0; + } else { + j->play_mode = -1; + j->flags.playing = 0; + j->rec_mode = -1; + j->flags.recording = 0; + return 1; + } +} + +static int set_base_frame(IXJ *j, int size) +{ + unsigned short cmd; + int cnt; + + idle(j); + j->cid_play_aec_level = j->aec_level; + aec_stop(j); + for (cnt = 0; cnt < 10; cnt++) { + if (idle(j)) + break; + } + if (j->ssr.high || j->ssr.low) + return -1; + if (j->dsp.low != 0x20) { + switch (size) { + case 30: + cmd = 0x07F0; + /* Set Base Frame Size to 240 pg9-10 8021 */ + break; + case 20: + cmd = 0x07A0; + /* Set Base Frame Size to 160 pg9-10 8021 */ + break; + case 10: + cmd = 0x0750; + /* Set Base Frame Size to 80 pg9-10 8021 */ + break; + default: + return -1; + } + } else { + if (size == 30) + return size; + else + return -1; + } + if (ixj_WriteDSPCommand(cmd, j)) { + j->baseframe.high = j->baseframe.low = 0xFF; + return -1; + } else { + j->baseframe.high = j->ssr.high; + j->baseframe.low = j->ssr.low; + /* If the status returned is 0x0000 (pg9-9 8021) the call failed */ + if(j->baseframe.high == 0x00 && j->baseframe.low == 0x00) { + return -1; + } + } + ixj_aec_start(j, j->cid_play_aec_level); + return size; +} + +static int set_rec_codec(IXJ *j, int rate) +{ + int retval = 0; + + j->rec_codec = rate; + + switch (rate) { + case G723_63: + if (j->ver.low != 0x12 || ixj_convert_loaded) { + j->rec_frame_size = 12; + j->rec_mode = 0; + } else { + retval = 1; + } + break; + case G723_53: + if (j->ver.low != 0x12 || ixj_convert_loaded) { + j->rec_frame_size = 10; + j->rec_mode = 0; + } else { + retval = 1; + } + break; + case TS85: + if (j->dsp.low == 0x20 || j->flags.ts85_loaded) { + j->rec_frame_size = 16; + j->rec_mode = 0; + } else { + retval = 1; + } + break; + case TS48: + if (j->ver.low != 0x12 || ixj_convert_loaded) { + j->rec_frame_size = 9; + j->rec_mode = 0; + } else { + retval = 1; + } + break; + case TS41: + if (j->ver.low != 0x12 || ixj_convert_loaded) { + j->rec_frame_size = 8; + j->rec_mode = 0; + } else { + retval = 1; + } + break; + case G728: + if (j->dsp.low != 0x20) { + j->rec_frame_size = 48; + j->rec_mode = 0; + } else { + retval = 1; + } + break; + case G729: + if (j->dsp.low != 0x20) { + if (!j->flags.g729_loaded) { + retval = 1; + break; + } + switch (j->baseframe.low) { + case 0xA0: + j->rec_frame_size = 10; + break; + case 0x50: + j->rec_frame_size = 5; + break; + default: + j->rec_frame_size = 15; + break; + } + j->rec_mode = 0; + } else { + retval = 1; + } + break; + case G729B: + if (j->dsp.low != 0x20) { + if (!j->flags.g729_loaded) { + retval = 1; + break; + } + switch (j->baseframe.low) { + case 0xA0: + j->rec_frame_size = 12; + break; + case 0x50: + j->rec_frame_size = 6; + break; + default: + j->rec_frame_size = 18; + break; + } + j->rec_mode = 0; + } else { + retval = 1; + } + break; + case ULAW: + switch (j->baseframe.low) { + case 0xA0: + j->rec_frame_size = 80; + break; + case 0x50: + j->rec_frame_size = 40; + break; + default: + j->rec_frame_size = 120; + break; + } + j->rec_mode = 4; + break; + case ALAW: + switch (j->baseframe.low) { + case 0xA0: + j->rec_frame_size = 80; + break; + case 0x50: + j->rec_frame_size = 40; + break; + default: + j->rec_frame_size = 120; + break; + } + j->rec_mode = 4; + break; + case LINEAR16: + switch (j->baseframe.low) { + case 0xA0: + j->rec_frame_size = 160; + break; + case 0x50: + j->rec_frame_size = 80; + break; + default: + j->rec_frame_size = 240; + break; + } + j->rec_mode = 5; + break; + case LINEAR8: + switch (j->baseframe.low) { + case 0xA0: + j->rec_frame_size = 80; + break; + case 0x50: + j->rec_frame_size = 40; + break; + default: + j->rec_frame_size = 120; + break; + } + j->rec_mode = 6; + break; + case WSS: + switch (j->baseframe.low) { + case 0xA0: + j->rec_frame_size = 80; + break; + case 0x50: + j->rec_frame_size = 40; + break; + default: + j->rec_frame_size = 120; + break; + } + j->rec_mode = 7; + break; + default: + kfree(j->read_buffer); + j->rec_frame_size = 0; + j->rec_mode = -1; + j->read_buffer = NULL; + j->read_buffer_size = 0; + retval = 1; + break; + } + return retval; +} + +static int ixj_record_start(IXJ *j) +{ + unsigned short cmd = 0x0000; + + if (j->read_buffer) { + ixj_record_stop(j); + } + j->flags.recording = 1; + ixj_WriteDSPCommand(0x0FE0, j); /* Put the DSP in full power mode. */ + + if(ixjdebug & 0x0002) + printk("IXJ %d Starting Record Codec %d at %ld\n", j->board, j->rec_codec, jiffies); + + if (!j->rec_mode) { + switch (j->rec_codec) { + case G723_63: + cmd = 0x5131; + break; + case G723_53: + cmd = 0x5132; + break; + case TS85: + cmd = 0x5130; /* TrueSpeech 8.5 */ + + break; + case TS48: + cmd = 0x5133; /* TrueSpeech 4.8 */ + + break; + case TS41: + cmd = 0x5134; /* TrueSpeech 4.1 */ + + break; + case G728: + cmd = 0x5135; + break; + case G729: + case G729B: + cmd = 0x5136; + break; + default: + return 1; + } + if (ixj_WriteDSPCommand(cmd, j)) + return -1; + } + if (!j->read_buffer) { + if (!j->read_buffer) + j->read_buffer = kmalloc(j->rec_frame_size * 2, GFP_ATOMIC); + if (!j->read_buffer) { + printk("Read buffer allocation for ixj board %d failed!\n", j->board); + return -ENOMEM; + } + } + j->read_buffer_size = j->rec_frame_size * 2; + + if (ixj_WriteDSPCommand(0x5102, j)) /* Set Poll sync mode */ + + return -1; + + switch (j->rec_mode) { + case 0: + cmd = 0x1C03; /* Record C1 */ + + break; + case 4: + if (j->ver.low == 0x12) { + cmd = 0x1E03; /* Record C1 */ + + } else { + cmd = 0x1E01; /* Record C1 */ + + } + break; + case 5: + if (j->ver.low == 0x12) { + cmd = 0x1E83; /* Record C1 */ + + } else { + cmd = 0x1E81; /* Record C1 */ + + } + break; + case 6: + if (j->ver.low == 0x12) { + cmd = 0x1F03; /* Record C1 */ + + } else { + cmd = 0x1F01; /* Record C1 */ + + } + break; + case 7: + if (j->ver.low == 0x12) { + cmd = 0x1F83; /* Record C1 */ + } else { + cmd = 0x1F81; /* Record C1 */ + } + break; + } + if (ixj_WriteDSPCommand(cmd, j)) + return -1; + + if (j->flags.playing) { + ixj_aec_start(j, j->aec_level); + } + return 0; +} + +static void ixj_record_stop(IXJ *j) +{ + if (ixjdebug & 0x0002) + printk("IXJ %d Stopping Record Codec %d at %ld\n", j->board, j->rec_codec, jiffies); + + kfree(j->read_buffer); + j->read_buffer = NULL; + j->read_buffer_size = 0; + if (j->rec_mode > -1) { + ixj_WriteDSPCommand(0x5120, j); + j->rec_mode = -1; + } + j->flags.recording = 0; +} +static void ixj_vad(IXJ *j, int arg) +{ + if (arg) + ixj_WriteDSPCommand(0x513F, j); + else + ixj_WriteDSPCommand(0x513E, j); +} + +static void set_rec_depth(IXJ *j, int depth) +{ + if (depth > 60) + depth = 60; + if (depth < 0) + depth = 0; + ixj_WriteDSPCommand(0x5180 + depth, j); +} + +static void set_dtmf_prescale(IXJ *j, int volume) +{ + ixj_WriteDSPCommand(0xCF07, j); + ixj_WriteDSPCommand(volume, j); +} + +static int get_dtmf_prescale(IXJ *j) +{ + ixj_WriteDSPCommand(0xCF05, j); + return j->ssr.high << 8 | j->ssr.low; +} + +static void set_rec_volume(IXJ *j, int volume) +{ + if(j->aec_level == AEC_AGC) { + if (ixjdebug & 0x0002) + printk(KERN_INFO "IXJ: /dev/phone%d Setting AGC Threshold to 0x%4.4x\n", j->board, volume); + ixj_WriteDSPCommand(0xCF96, j); + ixj_WriteDSPCommand(volume, j); + } else { + if (ixjdebug & 0x0002) + printk(KERN_INFO "IXJ: /dev/phone %d Setting Record Volume to 0x%4.4x\n", j->board, volume); + ixj_WriteDSPCommand(0xCF03, j); + ixj_WriteDSPCommand(volume, j); + } +} + +static int set_rec_volume_linear(IXJ *j, int volume) +{ + int newvolume, dsprecmax; + + if (ixjdebug & 0x0002) + printk(KERN_INFO "IXJ: /dev/phone %d Setting Linear Record Volume to 0x%4.4x\n", j->board, volume); + if(volume > 100 || volume < 0) { + return -1; + } + + /* This should normalize the perceived volumes between the different cards caused by differences in the hardware */ + switch (j->cardtype) { + case QTI_PHONEJACK: + dsprecmax = 0x440; + break; + case QTI_LINEJACK: + dsprecmax = 0x180; + ixj_mixer(0x0203, j); /*Voice Left Volume unmute 6db */ + ixj_mixer(0x0303, j); /*Voice Right Volume unmute 6db */ + ixj_mixer(0x0C00, j); /*Mono1 unmute 12db */ + break; + case QTI_PHONEJACK_LITE: + dsprecmax = 0x4C0; + break; + case QTI_PHONEJACK_PCI: + dsprecmax = 0x100; + break; + case QTI_PHONECARD: + dsprecmax = 0x400; + break; + default: + return -1; + } + newvolume = (dsprecmax * volume) / 100; + set_rec_volume(j, newvolume); + return 0; +} + +static int get_rec_volume(IXJ *j) +{ + if(j->aec_level == AEC_AGC) { + if (ixjdebug & 0x0002) + printk(KERN_INFO "Getting AGC Threshold\n"); + ixj_WriteDSPCommand(0xCF86, j); + if (ixjdebug & 0x0002) + printk(KERN_INFO "AGC Threshold is 0x%2.2x%2.2x\n", j->ssr.high, j->ssr.low); + return j->ssr.high << 8 | j->ssr.low; + } else { + if (ixjdebug & 0x0002) + printk(KERN_INFO "Getting Record Volume\n"); + ixj_WriteDSPCommand(0xCF01, j); + return j->ssr.high << 8 | j->ssr.low; + } +} + +static int get_rec_volume_linear(IXJ *j) +{ + int volume, newvolume, dsprecmax; + + switch (j->cardtype) { + case QTI_PHONEJACK: + dsprecmax = 0x440; + break; + case QTI_LINEJACK: + dsprecmax = 0x180; + break; + case QTI_PHONEJACK_LITE: + dsprecmax = 0x4C0; + break; + case QTI_PHONEJACK_PCI: + dsprecmax = 0x100; + break; + case QTI_PHONECARD: + dsprecmax = 0x400; + break; + default: + return -1; + } + volume = get_rec_volume(j); + newvolume = (volume * 100) / dsprecmax; + if(newvolume > 100) + newvolume = 100; + return newvolume; +} + +static int get_rec_level(IXJ *j) +{ + int retval; + + ixj_WriteDSPCommand(0xCF88, j); + + retval = j->ssr.high << 8 | j->ssr.low; + retval = (retval * 256) / 240; + return retval; +} + +static void ixj_aec_start(IXJ *j, int level) +{ + j->aec_level = level; + if (ixjdebug & 0x0002) + printk(KERN_INFO "AGC set = 0x%2.2x\n", j->aec_level); + if (!level) { + aec_stop(j); + } else { + if (j->rec_codec == G729 || j->play_codec == G729 || j->rec_codec == G729B || j->play_codec == G729B) { + ixj_WriteDSPCommand(0xE022, j); /* Move AEC filter buffer */ + + ixj_WriteDSPCommand(0x0300, j); + } + ixj_WriteDSPCommand(0xB001, j); /* AEC On */ + + ixj_WriteDSPCommand(0xE013, j); /* Advanced AEC C1 */ + + switch (level) { + case AEC_LOW: + ixj_WriteDSPCommand(0x0000, j); /* Advanced AEC C2 = off */ + + ixj_WriteDSPCommand(0xE011, j); + ixj_WriteDSPCommand(0xFFFF, j); + + ixj_WriteDSPCommand(0xCF97, j); /* Set AGC Enable */ + ixj_WriteDSPCommand(0x0000, j); /* to off */ + + break; + + case AEC_MED: + ixj_WriteDSPCommand(0x0600, j); /* Advanced AEC C2 = on medium */ + + ixj_WriteDSPCommand(0xE011, j); + ixj_WriteDSPCommand(0x0080, j); + + ixj_WriteDSPCommand(0xCF97, j); /* Set AGC Enable */ + ixj_WriteDSPCommand(0x0000, j); /* to off */ + + break; + + case AEC_HIGH: + ixj_WriteDSPCommand(0x0C00, j); /* Advanced AEC C2 = on high */ + + ixj_WriteDSPCommand(0xE011, j); + ixj_WriteDSPCommand(0x0080, j); + + ixj_WriteDSPCommand(0xCF97, j); /* Set AGC Enable */ + ixj_WriteDSPCommand(0x0000, j); /* to off */ + + break; + + case AEC_AGC: + /* First we have to put the AEC into advance auto mode so that AGC will not conflict with it */ + ixj_WriteDSPCommand(0x0002, j); /* Attenuation scaling factor of 2 */ + + ixj_WriteDSPCommand(0xE011, j); + ixj_WriteDSPCommand(0x0100, j); /* Higher Threshold Floor */ + + ixj_WriteDSPCommand(0xE012, j); /* Set Train and Lock */ + + if(j->cardtype == QTI_LINEJACK || j->cardtype == QTI_PHONECARD) + ixj_WriteDSPCommand(0x0224, j); + else + ixj_WriteDSPCommand(0x1224, j); + + ixj_WriteDSPCommand(0xE014, j); + ixj_WriteDSPCommand(0x0003, j); /* Lock threshold at 3dB */ + + ixj_WriteDSPCommand(0xE338, j); /* Set Echo Suppresser Attenuation to 0dB */ + + /* Now we can set the AGC initial parameters and turn it on */ + ixj_WriteDSPCommand(0xCF90, j); /* Set AGC Minimum gain */ + ixj_WriteDSPCommand(0x0020, j); /* to 0.125 (-18dB) */ + + ixj_WriteDSPCommand(0xCF91, j); /* Set AGC Maximum gain */ + ixj_WriteDSPCommand(0x1000, j); /* to 16 (24dB) */ + + ixj_WriteDSPCommand(0xCF92, j); /* Set AGC start gain */ + ixj_WriteDSPCommand(0x0800, j); /* to 8 (+18dB) */ + + ixj_WriteDSPCommand(0xCF93, j); /* Set AGC hold time */ + ixj_WriteDSPCommand(0x1F40, j); /* to 2 seconds (units are 250us) */ + + ixj_WriteDSPCommand(0xCF94, j); /* Set AGC Attack Time Constant */ + ixj_WriteDSPCommand(0x0005, j); /* to 8ms */ + + ixj_WriteDSPCommand(0xCF95, j); /* Set AGC Decay Time Constant */ + ixj_WriteDSPCommand(0x000D, j); /* to 4096ms */ + + ixj_WriteDSPCommand(0xCF96, j); /* Set AGC Attack Threshold */ + ixj_WriteDSPCommand(0x1200, j); /* to 25% */ + + ixj_WriteDSPCommand(0xCF97, j); /* Set AGC Enable */ + ixj_WriteDSPCommand(0x0001, j); /* to on */ + + break; + + case AEC_AUTO: + ixj_WriteDSPCommand(0x0002, j); /* Attenuation scaling factor of 2 */ + + ixj_WriteDSPCommand(0xE011, j); + ixj_WriteDSPCommand(0x0100, j); /* Higher Threshold Floor */ + + ixj_WriteDSPCommand(0xE012, j); /* Set Train and Lock */ + + if(j->cardtype == QTI_LINEJACK || j->cardtype == QTI_PHONECARD) + ixj_WriteDSPCommand(0x0224, j); + else + ixj_WriteDSPCommand(0x1224, j); + + ixj_WriteDSPCommand(0xE014, j); + ixj_WriteDSPCommand(0x0003, j); /* Lock threshold at 3dB */ + + ixj_WriteDSPCommand(0xE338, j); /* Set Echo Suppresser Attenuation to 0dB */ + + break; + } + } +} + +static void aec_stop(IXJ *j) +{ + j->aec_level = AEC_OFF; + if (j->rec_codec == G729 || j->play_codec == G729 || j->rec_codec == G729B || j->play_codec == G729B) { + ixj_WriteDSPCommand(0xE022, j); /* Move AEC filter buffer back */ + + ixj_WriteDSPCommand(0x0700, j); + } + if (j->play_mode != -1 && j->rec_mode != -1) + { + ixj_WriteDSPCommand(0xB002, j); /* AEC Stop */ + } +} + +static int set_play_codec(IXJ *j, int rate) +{ + int retval = 0; + + j->play_codec = rate; + + switch (rate) { + case G723_63: + if (j->ver.low != 0x12 || ixj_convert_loaded) { + j->play_frame_size = 12; + j->play_mode = 0; + } else { + retval = 1; + } + break; + case G723_53: + if (j->ver.low != 0x12 || ixj_convert_loaded) { + j->play_frame_size = 10; + j->play_mode = 0; + } else { + retval = 1; + } + break; + case TS85: + if (j->dsp.low == 0x20 || j->flags.ts85_loaded) { + j->play_frame_size = 16; + j->play_mode = 0; + } else { + retval = 1; + } + break; + case TS48: + if (j->ver.low != 0x12 || ixj_convert_loaded) { + j->play_frame_size = 9; + j->play_mode = 0; + } else { + retval = 1; + } + break; + case TS41: + if (j->ver.low != 0x12 || ixj_convert_loaded) { + j->play_frame_size = 8; + j->play_mode = 0; + } else { + retval = 1; + } + break; + case G728: + if (j->dsp.low != 0x20) { + j->play_frame_size = 48; + j->play_mode = 0; + } else { + retval = 1; + } + break; + case G729: + if (j->dsp.low != 0x20) { + if (!j->flags.g729_loaded) { + retval = 1; + break; + } + switch (j->baseframe.low) { + case 0xA0: + j->play_frame_size = 10; + break; + case 0x50: + j->play_frame_size = 5; + break; + default: + j->play_frame_size = 15; + break; + } + j->play_mode = 0; + } else { + retval = 1; + } + break; + case G729B: + if (j->dsp.low != 0x20) { + if (!j->flags.g729_loaded) { + retval = 1; + break; + } + switch (j->baseframe.low) { + case 0xA0: + j->play_frame_size = 12; + break; + case 0x50: + j->play_frame_size = 6; + break; + default: + j->play_frame_size = 18; + break; + } + j->play_mode = 0; + } else { + retval = 1; + } + break; + case ULAW: + switch (j->baseframe.low) { + case 0xA0: + j->play_frame_size = 80; + break; + case 0x50: + j->play_frame_size = 40; + break; + default: + j->play_frame_size = 120; + break; + } + j->play_mode = 2; + break; + case ALAW: + switch (j->baseframe.low) { + case 0xA0: + j->play_frame_size = 80; + break; + case 0x50: + j->play_frame_size = 40; + break; + default: + j->play_frame_size = 120; + break; + } + j->play_mode = 2; + break; + case LINEAR16: + switch (j->baseframe.low) { + case 0xA0: + j->play_frame_size = 160; + break; + case 0x50: + j->play_frame_size = 80; + break; + default: + j->play_frame_size = 240; + break; + } + j->play_mode = 6; + break; + case LINEAR8: + switch (j->baseframe.low) { + case 0xA0: + j->play_frame_size = 80; + break; + case 0x50: + j->play_frame_size = 40; + break; + default: + j->play_frame_size = 120; + break; + } + j->play_mode = 4; + break; + case WSS: + switch (j->baseframe.low) { + case 0xA0: + j->play_frame_size = 80; + break; + case 0x50: + j->play_frame_size = 40; + break; + default: + j->play_frame_size = 120; + break; + } + j->play_mode = 5; + break; + default: + kfree(j->write_buffer); + j->play_frame_size = 0; + j->play_mode = -1; + j->write_buffer = NULL; + j->write_buffer_size = 0; + retval = 1; + break; + } + return retval; +} + +static int ixj_play_start(IXJ *j) +{ + unsigned short cmd = 0x0000; + + if (j->write_buffer) { + ixj_play_stop(j); + } + + if(ixjdebug & 0x0002) + printk("IXJ %d Starting Play Codec %d at %ld\n", j->board, j->play_codec, jiffies); + + j->flags.playing = 1; + ixj_WriteDSPCommand(0x0FE0, j); /* Put the DSP in full power mode. */ + + j->flags.play_first_frame = 1; + j->drybuffer = 0; + + if (!j->play_mode) { + switch (j->play_codec) { + case G723_63: + cmd = 0x5231; + break; + case G723_53: + cmd = 0x5232; + break; + case TS85: + cmd = 0x5230; /* TrueSpeech 8.5 */ + + break; + case TS48: + cmd = 0x5233; /* TrueSpeech 4.8 */ + + break; + case TS41: + cmd = 0x5234; /* TrueSpeech 4.1 */ + + break; + case G728: + cmd = 0x5235; + break; + case G729: + case G729B: + cmd = 0x5236; + break; + default: + return 1; + } + if (ixj_WriteDSPCommand(cmd, j)) + return -1; + } + j->write_buffer = kmalloc(j->play_frame_size * 2, GFP_ATOMIC); + if (!j->write_buffer) { + printk("Write buffer allocation for ixj board %d failed!\n", j->board); + return -ENOMEM; + } +/* j->write_buffers_empty = 2; */ + j->write_buffers_empty = 1; + j->write_buffer_size = j->play_frame_size * 2; + j->write_buffer_end = j->write_buffer + j->play_frame_size * 2; + j->write_buffer_rp = j->write_buffer_wp = j->write_buffer; + + if (ixj_WriteDSPCommand(0x5202, j)) /* Set Poll sync mode */ + + return -1; + + switch (j->play_mode) { + case 0: + cmd = 0x2C03; + break; + case 2: + if (j->ver.low == 0x12) { + cmd = 0x2C23; + } else { + cmd = 0x2C21; + } + break; + case 4: + if (j->ver.low == 0x12) { + cmd = 0x2C43; + } else { + cmd = 0x2C41; + } + break; + case 5: + if (j->ver.low == 0x12) { + cmd = 0x2C53; + } else { + cmd = 0x2C51; + } + break; + case 6: + if (j->ver.low == 0x12) { + cmd = 0x2C63; + } else { + cmd = 0x2C61; + } + break; + } + if (ixj_WriteDSPCommand(cmd, j)) + return -1; + + if (ixj_WriteDSPCommand(0x2000, j)) /* Playback C2 */ + return -1; + + if (ixj_WriteDSPCommand(0x2000 + j->play_frame_size, j)) /* Playback C3 */ + return -1; + + if (j->flags.recording) { + ixj_aec_start(j, j->aec_level); + } + + return 0; +} + +static void ixj_play_stop(IXJ *j) +{ + if (ixjdebug & 0x0002) + printk("IXJ %d Stopping Play Codec %d at %ld\n", j->board, j->play_codec, jiffies); + + kfree(j->write_buffer); + j->write_buffer = NULL; + j->write_buffer_size = 0; + if (j->play_mode > -1) { + ixj_WriteDSPCommand(0x5221, j); /* Stop playback and flush buffers. 8022 reference page 9-40 */ + + j->play_mode = -1; + } + j->flags.playing = 0; +} + +static inline int get_play_level(IXJ *j) +{ + int retval; + + ixj_WriteDSPCommand(0xCF8F, j); /* 8022 Reference page 9-38 */ + return j->ssr.high << 8 | j->ssr.low; + retval = j->ssr.high << 8 | j->ssr.low; + retval = (retval * 256) / 240; + return retval; +} + +static unsigned int ixj_poll(struct file *file_p, poll_table * wait) +{ + unsigned int mask = 0; + + IXJ *j = get_ixj(NUM(file_p->f_path.dentry->d_inode)); + + poll_wait(file_p, &(j->poll_q), wait); + if (j->read_buffer_ready > 0) + mask |= POLLIN | POLLRDNORM; /* readable */ + if (j->write_buffers_empty > 0) + mask |= POLLOUT | POLLWRNORM; /* writable */ + if (j->ex.bytes) + mask |= POLLPRI; + return mask; +} + +static int ixj_play_tone(IXJ *j, char tone) +{ + if (!j->tone_state) { + if(ixjdebug & 0x0002) { + printk("IXJ %d starting tone %d at %ld\n", j->board, tone, jiffies); + } + if (j->dsp.low == 0x20) { + idle(j); + } + j->tone_start_jif = jiffies; + + j->tone_state = 1; + } + + j->tone_index = tone; + if (ixj_WriteDSPCommand(0x6000 + j->tone_index, j)) + return -1; + + return 0; +} + +static int ixj_set_tone_on(unsigned short arg, IXJ *j) +{ + j->tone_on_time = arg; + + if (ixj_WriteDSPCommand(0x6E04, j)) /* Set Tone On Period */ + + return -1; + + if (ixj_WriteDSPCommand(arg, j)) + return -1; + + return 0; +} + +static int SCI_WaitHighSCI(IXJ *j) +{ + int cnt; + + j->pld_scrr.byte = inb_p(j->XILINXbase); + if (!j->pld_scrr.bits.sci) { + for (cnt = 0; cnt < 10; cnt++) { + udelay(32); + j->pld_scrr.byte = inb_p(j->XILINXbase); + + if ((j->pld_scrr.bits.sci)) + return 1; + } + if (ixjdebug & 0x0001) + printk(KERN_INFO "SCI Wait High failed %x\n", j->pld_scrr.byte); + return 0; + } else + return 1; +} + +static int SCI_WaitLowSCI(IXJ *j) +{ + int cnt; + + j->pld_scrr.byte = inb_p(j->XILINXbase); + if (j->pld_scrr.bits.sci) { + for (cnt = 0; cnt < 10; cnt++) { + udelay(32); + j->pld_scrr.byte = inb_p(j->XILINXbase); + + if (!(j->pld_scrr.bits.sci)) + return 1; + } + if (ixjdebug & 0x0001) + printk(KERN_INFO "SCI Wait Low failed %x\n", j->pld_scrr.byte); + return 0; + } else + return 1; +} + +static int SCI_Control(IXJ *j, int control) +{ + switch (control) { + case SCI_End: + j->pld_scrw.bits.c0 = 0; /* Set PLD Serial control interface */ + + j->pld_scrw.bits.c1 = 0; /* to no selection */ + + break; + case SCI_Enable_DAA: + j->pld_scrw.bits.c0 = 1; /* Set PLD Serial control interface */ + + j->pld_scrw.bits.c1 = 0; /* to write to DAA */ + + break; + case SCI_Enable_Mixer: + j->pld_scrw.bits.c0 = 0; /* Set PLD Serial control interface */ + + j->pld_scrw.bits.c1 = 1; /* to write to mixer */ + + break; + case SCI_Enable_EEPROM: + j->pld_scrw.bits.c0 = 1; /* Set PLD Serial control interface */ + + j->pld_scrw.bits.c1 = 1; /* to write to EEPROM */ + + break; + default: + return 0; + break; + } + outb_p(j->pld_scrw.byte, j->XILINXbase); + + switch (control) { + case SCI_End: + return 1; + break; + case SCI_Enable_DAA: + case SCI_Enable_Mixer: + case SCI_Enable_EEPROM: + if (!SCI_WaitHighSCI(j)) + return 0; + break; + default: + return 0; + break; + } + return 1; +} + +static int SCI_Prepare(IXJ *j) +{ + if (!SCI_Control(j, SCI_End)) + return 0; + + if (!SCI_WaitLowSCI(j)) + return 0; + + return 1; +} + +static int ixj_get_mixer(long val, IXJ *j) +{ + int reg = (val & 0x1F00) >> 8; + return j->mix.vol[reg]; +} + +static int ixj_mixer(long val, IXJ *j) +{ + BYTES bytes; + + bytes.high = (val & 0x1F00) >> 8; + bytes.low = val & 0x00FF; + + /* save mixer value so we can get back later on */ + j->mix.vol[bytes.high] = bytes.low; + + outb_p(bytes.high & 0x1F, j->XILINXbase + 0x03); /* Load Mixer Address */ + + outb_p(bytes.low, j->XILINXbase + 0x02); /* Load Mixer Data */ + + SCI_Control(j, SCI_Enable_Mixer); + + SCI_Control(j, SCI_End); + + return 0; +} + +static int daa_load(BYTES * p_bytes, IXJ *j) +{ + outb_p(p_bytes->high, j->XILINXbase + 0x03); + outb_p(p_bytes->low, j->XILINXbase + 0x02); + if (!SCI_Control(j, SCI_Enable_DAA)) + return 0; + else + return 1; +} + +static int ixj_daa_cr4(IXJ *j, char reg) +{ + BYTES bytes; + + switch (j->daa_mode) { + case SOP_PU_SLEEP: + bytes.high = 0x14; + break; + case SOP_PU_RINGING: + bytes.high = 0x54; + break; + case SOP_PU_CONVERSATION: + bytes.high = 0x94; + break; + case SOP_PU_PULSEDIALING: + bytes.high = 0xD4; + break; + } + + j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = reg; + + switch (j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.bitreg.AGX) { + case 0: + j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.bitreg.AGR_Z = 0; + break; + case 1: + j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.bitreg.AGR_Z = 2; + break; + case 2: + j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.bitreg.AGR_Z = 1; + break; + case 3: + j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.bitreg.AGR_Z = 3; + break; + } + + bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg; + + if (!daa_load(&bytes, j)) + return 0; + + if (!SCI_Prepare(j)) + return 0; + + return 1; +} + +static char daa_int_read(IXJ *j) +{ + BYTES bytes; + + if (!SCI_Prepare(j)) + return 0; + + bytes.high = 0x38; + bytes.low = 0x00; + outb_p(bytes.high, j->XILINXbase + 0x03); + outb_p(bytes.low, j->XILINXbase + 0x02); + + if (!SCI_Control(j, SCI_Enable_DAA)) + return 0; + + bytes.high = inb_p(j->XILINXbase + 0x03); + bytes.low = inb_p(j->XILINXbase + 0x02); + if (bytes.low != ALISDAA_ID_BYTE) { + if (ixjdebug & 0x0001) + printk("Cannot read DAA ID Byte high = %d low = %d\n", bytes.high, bytes.low); + return 0; + } + if (!SCI_Control(j, SCI_Enable_DAA)) + return 0; + if (!SCI_Control(j, SCI_End)) + return 0; + + bytes.high = inb_p(j->XILINXbase + 0x03); + bytes.low = inb_p(j->XILINXbase + 0x02); + + j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.reg = bytes.high; + + return 1; +} + +static char daa_CR_read(IXJ *j, int cr) +{ + IXJ_WORD wdata; + BYTES bytes; + + if (!SCI_Prepare(j)) + return 0; + + switch (j->daa_mode) { + case SOP_PU_SLEEP: + bytes.high = 0x30 + cr; + break; + case SOP_PU_RINGING: + bytes.high = 0x70 + cr; + break; + case SOP_PU_CONVERSATION: + bytes.high = 0xB0 + cr; + break; + case SOP_PU_PULSEDIALING: + default: + bytes.high = 0xF0 + cr; + break; + } + + bytes.low = 0x00; + + outb_p(bytes.high, j->XILINXbase + 0x03); + outb_p(bytes.low, j->XILINXbase + 0x02); + + if (!SCI_Control(j, SCI_Enable_DAA)) + return 0; + + bytes.high = inb_p(j->XILINXbase + 0x03); + bytes.low = inb_p(j->XILINXbase + 0x02); + if (bytes.low != ALISDAA_ID_BYTE) { + if (ixjdebug & 0x0001) + printk("Cannot read DAA ID Byte high = %d low = %d\n", bytes.high, bytes.low); + return 0; + } + if (!SCI_Control(j, SCI_Enable_DAA)) + return 0; + if (!SCI_Control(j, SCI_End)) + return 0; + + wdata.word = inw_p(j->XILINXbase + 0x02); + + switch(cr){ + case 5: + j->m_DAAShadowRegs.SOP_REGS.SOP.cr5.reg = wdata.bytes.high; + break; + case 4: + j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = wdata.bytes.high; + break; + case 3: + j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg = wdata.bytes.high; + break; + case 2: + j->m_DAAShadowRegs.SOP_REGS.SOP.cr2.reg = wdata.bytes.high; + break; + case 1: + j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.reg = wdata.bytes.high; + break; + case 0: + j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = wdata.bytes.high; + break; + default: + return 0; + } + return 1; +} + +static int ixj_daa_cid_reset(IXJ *j) +{ + int i; + BYTES bytes; + + if (ixjdebug & 0x0002) + printk("DAA Clearing CID ram\n"); + + if (!SCI_Prepare(j)) + return 0; + + bytes.high = 0x58; + bytes.low = 0x00; + outb_p(bytes.high, j->XILINXbase + 0x03); + outb_p(bytes.low, j->XILINXbase + 0x02); + + if (!SCI_Control(j, SCI_Enable_DAA)) + return 0; + + if (!SCI_WaitHighSCI(j)) + return 0; + + for (i = 0; i < ALISDAA_CALLERID_SIZE - 1; i += 2) { + bytes.high = bytes.low = 0x00; + outb_p(bytes.high, j->XILINXbase + 0x03); + + if (i < ALISDAA_CALLERID_SIZE - 1) + outb_p(bytes.low, j->XILINXbase + 0x02); + + if (!SCI_Control(j, SCI_Enable_DAA)) + return 0; + + if (!SCI_WaitHighSCI(j)) + return 0; + + } + + if (!SCI_Control(j, SCI_End)) + return 0; + + if (ixjdebug & 0x0002) + printk("DAA CID ram cleared\n"); + + return 1; +} + +static int ixj_daa_cid_read(IXJ *j) +{ + int i; + BYTES bytes; + char CID[ALISDAA_CALLERID_SIZE]; + bool mContinue; + char *pIn, *pOut; + + if (!SCI_Prepare(j)) + return 0; + + bytes.high = 0x78; + bytes.low = 0x00; + outb_p(bytes.high, j->XILINXbase + 0x03); + outb_p(bytes.low, j->XILINXbase + 0x02); + + if (!SCI_Control(j, SCI_Enable_DAA)) + return 0; + + if (!SCI_WaitHighSCI(j)) + return 0; + + bytes.high = inb_p(j->XILINXbase + 0x03); + bytes.low = inb_p(j->XILINXbase + 0x02); + if (bytes.low != ALISDAA_ID_BYTE) { + if (ixjdebug & 0x0001) + printk("DAA Get Version Cannot read DAA ID Byte high = %d low = %d\n", bytes.high, bytes.low); + return 0; + } + for (i = 0; i < ALISDAA_CALLERID_SIZE; i += 2) { + bytes.high = bytes.low = 0x00; + outb_p(bytes.high, j->XILINXbase + 0x03); + outb_p(bytes.low, j->XILINXbase + 0x02); + + if (!SCI_Control(j, SCI_Enable_DAA)) + return 0; + + if (!SCI_WaitHighSCI(j)) + return 0; + + CID[i + 0] = inb_p(j->XILINXbase + 0x03); + CID[i + 1] = inb_p(j->XILINXbase + 0x02); + } + + if (!SCI_Control(j, SCI_End)) + return 0; + + pIn = CID; + pOut = j->m_DAAShadowRegs.CAO_REGS.CAO.CallerID; + mContinue = true; + while (mContinue) { + if ((pIn[1] & 0x03) == 0x01) { + pOut[0] = pIn[0]; + } + if ((pIn[2] & 0x0c) == 0x04) { + pOut[1] = ((pIn[2] & 0x03) << 6) | ((pIn[1] & 0xfc) >> 2); + } + if ((pIn[3] & 0x30) == 0x10) { + pOut[2] = ((pIn[3] & 0x0f) << 4) | ((pIn[2] & 0xf0) >> 4); + } + if ((pIn[4] & 0xc0) == 0x40) { + pOut[3] = ((pIn[4] & 0x3f) << 2) | ((pIn[3] & 0xc0) >> 6); + } else { + mContinue = false; + } + pIn += 5, pOut += 4; + } + memset(&j->cid, 0, sizeof(PHONE_CID)); + pOut = j->m_DAAShadowRegs.CAO_REGS.CAO.CallerID; + pOut += 4; + strncpy(j->cid.month, pOut, 2); + pOut += 2; + strncpy(j->cid.day, pOut, 2); + pOut += 2; + strncpy(j->cid.hour, pOut, 2); + pOut += 2; + strncpy(j->cid.min, pOut, 2); + pOut += 3; + j->cid.numlen = *pOut; + pOut += 1; + strncpy(j->cid.number, pOut, j->cid.numlen); + pOut += j->cid.numlen + 1; + j->cid.namelen = *pOut; + pOut += 1; + strncpy(j->cid.name, pOut, j->cid.namelen); + + ixj_daa_cid_reset(j); + return 1; +} + +static char daa_get_version(IXJ *j) +{ + BYTES bytes; + + if (!SCI_Prepare(j)) + return 0; + + bytes.high = 0x35; + bytes.low = 0x00; + outb_p(bytes.high, j->XILINXbase + 0x03); + outb_p(bytes.low, j->XILINXbase + 0x02); + + if (!SCI_Control(j, SCI_Enable_DAA)) + return 0; + + bytes.high = inb_p(j->XILINXbase + 0x03); + bytes.low = inb_p(j->XILINXbase + 0x02); + if (bytes.low != ALISDAA_ID_BYTE) { + if (ixjdebug & 0x0001) + printk("DAA Get Version Cannot read DAA ID Byte high = %d low = %d\n", bytes.high, bytes.low); + return 0; + } + if (!SCI_Control(j, SCI_Enable_DAA)) + return 0; + + if (!SCI_Control(j, SCI_End)) + return 0; + + bytes.high = inb_p(j->XILINXbase + 0x03); + bytes.low = inb_p(j->XILINXbase + 0x02); + if (ixjdebug & 0x0002) + printk("DAA CR5 Byte high = 0x%x low = 0x%x\n", bytes.high, bytes.low); + j->m_DAAShadowRegs.SOP_REGS.SOP.cr5.reg = bytes.high; + return bytes.high; +} + +static int daa_set_mode(IXJ *j, int mode) +{ + /* NOTE: + The DAA *MUST* be in the conversation mode if the + PSTN line is to be seized (PSTN line off-hook). + Taking the PSTN line off-hook while the DAA is in + a mode other than conversation mode will cause a + hardware failure of the ALIS-A part. + + NOTE: + The DAA can only go to SLEEP, RINGING or PULSEDIALING modes + if the PSTN line is on-hook. Failure to have the PSTN line + in the on-hook state WILL CAUSE A HARDWARE FAILURE OF THE + ALIS-A part. + */ + + BYTES bytes; + + j->flags.pstn_rmr = 0; + + if (!SCI_Prepare(j)) + return 0; + + switch (mode) { + case SOP_PU_RESET: + j->pld_scrw.bits.daafsyncen = 0; /* Turn off DAA Frame Sync */ + + outb_p(j->pld_scrw.byte, j->XILINXbase); + j->pld_slicw.bits.rly2 = 0; + outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); + bytes.high = 0x10; + bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg; + daa_load(&bytes, j); + if (!SCI_Prepare(j)) + return 0; + + j->daa_mode = SOP_PU_SLEEP; + break; + case SOP_PU_SLEEP: + if(j->daa_mode == SOP_PU_SLEEP) + { + break; + } + if (ixjdebug & 0x0008) + printk(KERN_INFO "phone DAA: SOP_PU_SLEEP at %ld\n", jiffies); +/* if(j->daa_mode == SOP_PU_CONVERSATION) */ + { + j->pld_scrw.bits.daafsyncen = 0; /* Turn off DAA Frame Sync */ + + outb_p(j->pld_scrw.byte, j->XILINXbase); + j->pld_slicw.bits.rly2 = 0; + outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); + bytes.high = 0x10; + bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg; + daa_load(&bytes, j); + if (!SCI_Prepare(j)) + return 0; + } + j->pld_scrw.bits.daafsyncen = 0; /* Turn off DAA Frame Sync */ + + outb_p(j->pld_scrw.byte, j->XILINXbase); + j->pld_slicw.bits.rly2 = 0; + outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); + bytes.high = 0x10; + bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg; + daa_load(&bytes, j); + if (!SCI_Prepare(j)) + return 0; + + j->daa_mode = SOP_PU_SLEEP; + j->flags.pstn_ringing = 0; + j->ex.bits.pstn_ring = 0; + j->pstn_sleeptil = jiffies + (hertz / 4); + wake_up_interruptible(&j->read_q); /* Wake any blocked readers */ + wake_up_interruptible(&j->write_q); /* Wake any blocked writers */ + wake_up_interruptible(&j->poll_q); /* Wake any blocked selects */ + break; + case SOP_PU_RINGING: + if (ixjdebug & 0x0008) + printk(KERN_INFO "phone DAA: SOP_PU_RINGING at %ld\n", jiffies); + j->pld_scrw.bits.daafsyncen = 0; /* Turn off DAA Frame Sync */ + + outb_p(j->pld_scrw.byte, j->XILINXbase); + j->pld_slicw.bits.rly2 = 0; + outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); + bytes.high = 0x50; + bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg; + daa_load(&bytes, j); + if (!SCI_Prepare(j)) + return 0; + j->daa_mode = SOP_PU_RINGING; + break; + case SOP_PU_CONVERSATION: + if (ixjdebug & 0x0008) + printk(KERN_INFO "phone DAA: SOP_PU_CONVERSATION at %ld\n", jiffies); + bytes.high = 0x90; + bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg; + daa_load(&bytes, j); + if (!SCI_Prepare(j)) + return 0; + j->pld_slicw.bits.rly2 = 1; + outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); + j->pld_scrw.bits.daafsyncen = 1; /* Turn on DAA Frame Sync */ + + outb_p(j->pld_scrw.byte, j->XILINXbase); + j->daa_mode = SOP_PU_CONVERSATION; + j->flags.pstn_ringing = 0; + j->ex.bits.pstn_ring = 0; + j->pstn_sleeptil = jiffies; + j->pstn_ring_start = j->pstn_ring_stop = j->pstn_ring_int = 0; + break; + case SOP_PU_PULSEDIALING: + if (ixjdebug & 0x0008) + printk(KERN_INFO "phone DAA: SOP_PU_PULSEDIALING at %ld\n", jiffies); + j->pld_scrw.bits.daafsyncen = 0; /* Turn off DAA Frame Sync */ + + outb_p(j->pld_scrw.byte, j->XILINXbase); + j->pld_slicw.bits.rly2 = 0; + outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); + bytes.high = 0xD0; + bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg; + daa_load(&bytes, j); + if (!SCI_Prepare(j)) + return 0; + j->daa_mode = SOP_PU_PULSEDIALING; + break; + default: + break; + } + return 1; +} + +static int ixj_daa_write(IXJ *j) +{ + BYTES bytes; + + j->flags.pstncheck = 1; + + daa_set_mode(j, SOP_PU_SLEEP); + + if (!SCI_Prepare(j)) + return 0; + + outb_p(j->pld_scrw.byte, j->XILINXbase); + + bytes.high = 0x14; + bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg; + bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr2.reg; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.reg; + bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg; + if (!daa_load(&bytes, j)) + return 0; + + if (!SCI_Prepare(j)) + return 0; + + bytes.high = 0x1F; + bytes.low = j->m_DAAShadowRegs.XOP_REGS.XOP.xr7.reg; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.XOP_xr6_W.reg; + bytes.low = j->m_DAAShadowRegs.XOP_REGS.XOP.xr5.reg; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.XOP_REGS.XOP.xr4.reg; + bytes.low = j->m_DAAShadowRegs.XOP_REGS.XOP.xr3.reg; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.XOP_REGS.XOP.xr2.reg; + bytes.low = j->m_DAAShadowRegs.XOP_REGS.XOP.xr1.reg; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.XOP_xr0_W.reg; + bytes.low = 0x00; + if (!daa_load(&bytes, j)) + return 0; + + if (!SCI_Prepare(j)) + return 0; + + bytes.high = 0x00; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[7]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[6]; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[5]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[4]; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[3]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[2]; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[1]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[0]; + bytes.low = 0x00; + if (!daa_load(&bytes, j)) + return 0; + + if (!SCI_Control(j, SCI_End)) + return 0; + if (!SCI_WaitLowSCI(j)) + return 0; + + bytes.high = 0x01; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[7]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[6]; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[5]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[4]; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[3]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[2]; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[1]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[0]; + bytes.low = 0x00; + if (!daa_load(&bytes, j)) + return 0; + + if (!SCI_Control(j, SCI_End)) + return 0; + if (!SCI_WaitLowSCI(j)) + return 0; + + bytes.high = 0x02; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[7]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[6]; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[5]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[4]; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[3]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[2]; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[1]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[0]; + bytes.low = 0x00; + if (!daa_load(&bytes, j)) + return 0; + + if (!SCI_Control(j, SCI_End)) + return 0; + if (!SCI_WaitLowSCI(j)) + return 0; + + bytes.high = 0x03; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[7]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[6]; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[5]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[4]; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[3]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[2]; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[1]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[0]; + bytes.low = 0x00; + if (!daa_load(&bytes, j)) + return 0; + + if (!SCI_Control(j, SCI_End)) + return 0; + if (!SCI_WaitLowSCI(j)) + return 0; + + bytes.high = 0x04; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[6]; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[5]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[4]; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[3]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[2]; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[1]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[0]; + bytes.low = 0x00; + if (!daa_load(&bytes, j)) + return 0; + + if (!SCI_Control(j, SCI_End)) + return 0; + if (!SCI_WaitLowSCI(j)) + return 0; + + bytes.high = 0x05; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[7]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[6]; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[5]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[4]; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[3]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[2]; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[1]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[0]; + bytes.low = 0x00; + if (!daa_load(&bytes, j)) + return 0; + + if (!SCI_Control(j, SCI_End)) + return 0; + if (!SCI_WaitLowSCI(j)) + return 0; + + bytes.high = 0x06; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[7]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[6]; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[5]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[4]; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[3]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[2]; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[1]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[0]; + bytes.low = 0x00; + if (!daa_load(&bytes, j)) + return 0; + + if (!SCI_Control(j, SCI_End)) + return 0; + if (!SCI_WaitLowSCI(j)) + return 0; + + bytes.high = 0x07; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[7]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[6]; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[5]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[4]; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[3]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[2]; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[1]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[0]; + bytes.low = 0x00; + if (!daa_load(&bytes, j)) + return 0; + + if (!SCI_Control(j, SCI_End)) + return 0; + if (!SCI_WaitLowSCI(j)) + return 0; + + bytes.high = 0x08; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[7]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[6]; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[5]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[4]; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[3]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[2]; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[1]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[0]; + bytes.low = 0x00; + if (!daa_load(&bytes, j)) + return 0; + + if (!SCI_Control(j, SCI_End)) + return 0; + if (!SCI_WaitLowSCI(j)) + return 0; + + bytes.high = 0x09; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[3]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[2]; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[1]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[0]; + bytes.low = 0x00; + if (!daa_load(&bytes, j)) + return 0; + + if (!SCI_Control(j, SCI_End)) + return 0; + if (!SCI_WaitLowSCI(j)) + return 0; + + bytes.high = 0x0A; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[3]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[2]; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[1]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[0]; + bytes.low = 0x00; + if (!daa_load(&bytes, j)) + return 0; + + if (!SCI_Control(j, SCI_End)) + return 0; + if (!SCI_WaitLowSCI(j)) + return 0; + + bytes.high = 0x0B; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[3]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[2]; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[1]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[0]; + bytes.low = 0x00; + if (!daa_load(&bytes, j)) + return 0; + + if (!SCI_Control(j, SCI_End)) + return 0; + if (!SCI_WaitLowSCI(j)) + return 0; + + bytes.high = 0x0C; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[3]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[2]; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[1]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[0]; + bytes.low = 0x00; + if (!daa_load(&bytes, j)) + return 0; + + if (!SCI_Control(j, SCI_End)) + return 0; + if (!SCI_WaitLowSCI(j)) + return 0; + + bytes.high = 0x0D; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[3]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[2]; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[1]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[0]; + bytes.low = 0x00; + if (!daa_load(&bytes, j)) + return 0; + + if (!SCI_Control(j, SCI_End)) + return 0; + if (!SCI_WaitLowSCI(j)) + return 0; + + bytes.high = 0x0E; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[7]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[6]; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[5]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[4]; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[3]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[2]; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[1]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[0]; + bytes.low = 0x00; + if (!daa_load(&bytes, j)) + return 0; + + if (!SCI_Control(j, SCI_End)) + return 0; + if (!SCI_WaitLowSCI(j)) + return 0; + + bytes.high = 0x0F; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[7]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[6]; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[5]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[4]; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[3]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[2]; + bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[1]; + if (!daa_load(&bytes, j)) + return 0; + + bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[0]; + bytes.low = 0x00; + if (!daa_load(&bytes, j)) + return 0; + + udelay(32); + j->pld_scrr.byte = inb_p(j->XILINXbase); + if (!SCI_Control(j, SCI_End)) + return 0; + + outb_p(j->pld_scrw.byte, j->XILINXbase); + + if (ixjdebug & 0x0002) + printk("DAA Coefficients Loaded\n"); + + j->flags.pstncheck = 0; + return 1; +} + +static int ixj_set_tone_off(unsigned short arg, IXJ *j) +{ + j->tone_off_time = arg; + if (ixj_WriteDSPCommand(0x6E05, j)) /* Set Tone Off Period */ + + return -1; + if (ixj_WriteDSPCommand(arg, j)) + return -1; + return 0; +} + +static int ixj_get_tone_on(IXJ *j) +{ + if (ixj_WriteDSPCommand(0x6E06, j)) /* Get Tone On Period */ + + return -1; + return 0; +} + +static int ixj_get_tone_off(IXJ *j) +{ + if (ixj_WriteDSPCommand(0x6E07, j)) /* Get Tone Off Period */ + + return -1; + return 0; +} + +static void ixj_busytone(IXJ *j) +{ + j->flags.ringback = 0; + j->flags.dialtone = 0; + j->flags.busytone = 1; + ixj_set_tone_on(0x07D0, j); + ixj_set_tone_off(0x07D0, j); + ixj_play_tone(j, 27); +} + +static void ixj_dialtone(IXJ *j) +{ + j->flags.ringback = 0; + j->flags.dialtone = 1; + j->flags.busytone = 0; + if (j->dsp.low == 0x20) { + return; + } else { + ixj_set_tone_on(0xFFFF, j); + ixj_set_tone_off(0x0000, j); + ixj_play_tone(j, 25); + } +} + +static void ixj_cpt_stop(IXJ *j) +{ + if(j->tone_state || j->tone_cadence_state) + { + j->flags.dialtone = 0; + j->flags.busytone = 0; + j->flags.ringback = 0; + ixj_set_tone_on(0x0001, j); + ixj_set_tone_off(0x0000, j); + ixj_play_tone(j, 0); + j->tone_state = j->tone_cadence_state = 0; + if (j->cadence_t) { + kfree(j->cadence_t->ce); + kfree(j->cadence_t); + j->cadence_t = NULL; + } + } + if (j->play_mode == -1 && j->rec_mode == -1) + idle(j); + if (j->play_mode != -1 && j->dsp.low == 0x20) + ixj_play_start(j); + if (j->rec_mode != -1 && j->dsp.low == 0x20) + ixj_record_start(j); +} + +static void ixj_ringback(IXJ *j) +{ + j->flags.busytone = 0; + j->flags.dialtone = 0; + j->flags.ringback = 1; + ixj_set_tone_on(0x0FA0, j); + ixj_set_tone_off(0x2EE0, j); + ixj_play_tone(j, 26); +} + +static void ixj_testram(IXJ *j) +{ + ixj_WriteDSPCommand(0x3001, j); /* Test External SRAM */ +} + +static int ixj_build_cadence(IXJ *j, IXJ_CADENCE __user * cp) +{ + ixj_cadence *lcp; + IXJ_CADENCE_ELEMENT __user *cep; + IXJ_CADENCE_ELEMENT *lcep; + IXJ_TONE ti; + int err; + + lcp = kmalloc(sizeof(ixj_cadence), GFP_KERNEL); + if (lcp == NULL) + return -ENOMEM; + + err = -EFAULT; + if (copy_from_user(&lcp->elements_used, + &cp->elements_used, sizeof(int))) + goto out; + if (copy_from_user(&lcp->termination, + &cp->termination, sizeof(IXJ_CADENCE_TERM))) + goto out; + if (get_user(cep, &cp->ce)) + goto out; + + err = -EINVAL; + if ((unsigned)lcp->elements_used >= ~0U/sizeof(IXJ_CADENCE_ELEMENT)) + goto out; + + err = -ENOMEM; + lcep = kmalloc(sizeof(IXJ_CADENCE_ELEMENT) * lcp->elements_used, GFP_KERNEL); + if (!lcep) + goto out; + + err = -EFAULT; + if (copy_from_user(lcep, cep, sizeof(IXJ_CADENCE_ELEMENT) * lcp->elements_used)) + goto out1; + + if (j->cadence_t) { + kfree(j->cadence_t->ce); + kfree(j->cadence_t); + } + lcp->ce = (void *) lcep; + j->cadence_t = lcp; + j->tone_cadence_state = 0; + ixj_set_tone_on(lcp->ce[0].tone_on_time, j); + ixj_set_tone_off(lcp->ce[0].tone_off_time, j); + if (j->cadence_t->ce[j->tone_cadence_state].freq0) { + ti.tone_index = j->cadence_t->ce[j->tone_cadence_state].index; + ti.freq0 = j->cadence_t->ce[j->tone_cadence_state].freq0; + ti.gain0 = j->cadence_t->ce[j->tone_cadence_state].gain0; + ti.freq1 = j->cadence_t->ce[j->tone_cadence_state].freq1; + ti.gain1 = j->cadence_t->ce[j->tone_cadence_state].gain1; + ixj_init_tone(j, &ti); + } + ixj_play_tone(j, lcp->ce[0].index); + return 1; +out1: + kfree(lcep); +out: + kfree(lcp); + return err; +} + +static int ixj_build_filter_cadence(IXJ *j, IXJ_FILTER_CADENCE __user * cp) +{ + IXJ_FILTER_CADENCE *lcp; + lcp = memdup_user(cp, sizeof(IXJ_FILTER_CADENCE)); + if (IS_ERR(lcp)) { + if(ixjdebug & 0x0001) { + printk(KERN_INFO "Could not allocate memory for cadence or could not copy cadence to kernel\n"); + } + return PTR_ERR(lcp); + } + if (lcp->filter > 5) { + if(ixjdebug & 0x0001) { + printk(KERN_INFO "Cadence out of range\n"); + } + kfree(lcp); + return -1; + } + j->cadence_f[lcp->filter].state = 0; + j->cadence_f[lcp->filter].enable = lcp->enable; + j->filter_en[lcp->filter] = j->cadence_f[lcp->filter].en_filter = lcp->en_filter; + j->cadence_f[lcp->filter].on1 = lcp->on1; + j->cadence_f[lcp->filter].on1min = 0; + j->cadence_f[lcp->filter].on1max = 0; + j->cadence_f[lcp->filter].off1 = lcp->off1; + j->cadence_f[lcp->filter].off1min = 0; + j->cadence_f[lcp->filter].off1max = 0; + j->cadence_f[lcp->filter].on2 = lcp->on2; + j->cadence_f[lcp->filter].on2min = 0; + j->cadence_f[lcp->filter].on2max = 0; + j->cadence_f[lcp->filter].off2 = lcp->off2; + j->cadence_f[lcp->filter].off2min = 0; + j->cadence_f[lcp->filter].off2max = 0; + j->cadence_f[lcp->filter].on3 = lcp->on3; + j->cadence_f[lcp->filter].on3min = 0; + j->cadence_f[lcp->filter].on3max = 0; + j->cadence_f[lcp->filter].off3 = lcp->off3; + j->cadence_f[lcp->filter].off3min = 0; + j->cadence_f[lcp->filter].off3max = 0; + if(ixjdebug & 0x0002) { + printk(KERN_INFO "Cadence %d loaded\n", lcp->filter); + } + kfree(lcp); + return 0; +} + +static void add_caps(IXJ *j) +{ + j->caps = 0; + j->caplist[j->caps].cap = PHONE_VENDOR_QUICKNET; + strcpy(j->caplist[j->caps].desc, "Quicknet Technologies, Inc. (www.quicknet.net)"); + j->caplist[j->caps].captype = vendor; + j->caplist[j->caps].handle = j->caps++; + j->caplist[j->caps].captype = device; + switch (j->cardtype) { + case QTI_PHONEJACK: + strcpy(j->caplist[j->caps].desc, "Quicknet Internet PhoneJACK"); + break; + case QTI_LINEJACK: + strcpy(j->caplist[j->caps].desc, "Quicknet Internet LineJACK"); + break; + case QTI_PHONEJACK_LITE: + strcpy(j->caplist[j->caps].desc, "Quicknet Internet PhoneJACK Lite"); + break; + case QTI_PHONEJACK_PCI: + strcpy(j->caplist[j->caps].desc, "Quicknet Internet PhoneJACK PCI"); + break; + case QTI_PHONECARD: + strcpy(j->caplist[j->caps].desc, "Quicknet Internet PhoneCARD"); + break; + } + j->caplist[j->caps].cap = j->cardtype; + j->caplist[j->caps].handle = j->caps++; + strcpy(j->caplist[j->caps].desc, "POTS"); + j->caplist[j->caps].captype = port; + j->caplist[j->caps].cap = pots; + j->caplist[j->caps].handle = j->caps++; + + /* add devices that can do speaker/mic */ + switch (j->cardtype) { + case QTI_PHONEJACK: + case QTI_LINEJACK: + case QTI_PHONEJACK_PCI: + case QTI_PHONECARD: + strcpy(j->caplist[j->caps].desc, "SPEAKER"); + j->caplist[j->caps].captype = port; + j->caplist[j->caps].cap = speaker; + j->caplist[j->caps].handle = j->caps++; + default: + break; + } + + /* add devices that can do handset */ + switch (j->cardtype) { + case QTI_PHONEJACK: + strcpy(j->caplist[j->caps].desc, "HANDSET"); + j->caplist[j->caps].captype = port; + j->caplist[j->caps].cap = handset; + j->caplist[j->caps].handle = j->caps++; + break; + default: + break; + } + + /* add devices that can do PSTN */ + switch (j->cardtype) { + case QTI_LINEJACK: + strcpy(j->caplist[j->caps].desc, "PSTN"); + j->caplist[j->caps].captype = port; + j->caplist[j->caps].cap = pstn; + j->caplist[j->caps].handle = j->caps++; + break; + default: + break; + } + + /* add codecs - all cards can do uLaw, linear 8/16, and Windows sound system */ + strcpy(j->caplist[j->caps].desc, "ULAW"); + j->caplist[j->caps].captype = codec; + j->caplist[j->caps].cap = ULAW; + j->caplist[j->caps].handle = j->caps++; + + strcpy(j->caplist[j->caps].desc, "LINEAR 16 bit"); + j->caplist[j->caps].captype = codec; + j->caplist[j->caps].cap = LINEAR16; + j->caplist[j->caps].handle = j->caps++; + + strcpy(j->caplist[j->caps].desc, "LINEAR 8 bit"); + j->caplist[j->caps].captype = codec; + j->caplist[j->caps].cap = LINEAR8; + j->caplist[j->caps].handle = j->caps++; + + strcpy(j->caplist[j->caps].desc, "Windows Sound System"); + j->caplist[j->caps].captype = codec; + j->caplist[j->caps].cap = WSS; + j->caplist[j->caps].handle = j->caps++; + + /* software ALAW codec, made from ULAW */ + strcpy(j->caplist[j->caps].desc, "ALAW"); + j->caplist[j->caps].captype = codec; + j->caplist[j->caps].cap = ALAW; + j->caplist[j->caps].handle = j->caps++; + + /* version 12 of the 8020 does the following codecs in a broken way */ + if (j->dsp.low != 0x20 || j->ver.low != 0x12) { + strcpy(j->caplist[j->caps].desc, "G.723.1 6.3kbps"); + j->caplist[j->caps].captype = codec; + j->caplist[j->caps].cap = G723_63; + j->caplist[j->caps].handle = j->caps++; + + strcpy(j->caplist[j->caps].desc, "G.723.1 5.3kbps"); + j->caplist[j->caps].captype = codec; + j->caplist[j->caps].cap = G723_53; + j->caplist[j->caps].handle = j->caps++; + + strcpy(j->caplist[j->caps].desc, "TrueSpeech 4.8kbps"); + j->caplist[j->caps].captype = codec; + j->caplist[j->caps].cap = TS48; + j->caplist[j->caps].handle = j->caps++; + + strcpy(j->caplist[j->caps].desc, "TrueSpeech 4.1kbps"); + j->caplist[j->caps].captype = codec; + j->caplist[j->caps].cap = TS41; + j->caplist[j->caps].handle = j->caps++; + } + + /* 8020 chips can do TS8.5 native, and 8021/8022 can load it */ + if (j->dsp.low == 0x20 || j->flags.ts85_loaded) { + strcpy(j->caplist[j->caps].desc, "TrueSpeech 8.5kbps"); + j->caplist[j->caps].captype = codec; + j->caplist[j->caps].cap = TS85; + j->caplist[j->caps].handle = j->caps++; + } + + /* 8021 chips can do G728 */ + if (j->dsp.low == 0x21) { + strcpy(j->caplist[j->caps].desc, "G.728 16kbps"); + j->caplist[j->caps].captype = codec; + j->caplist[j->caps].cap = G728; + j->caplist[j->caps].handle = j->caps++; + } + + /* 8021/8022 chips can do G729 if loaded */ + if (j->dsp.low != 0x20 && j->flags.g729_loaded) { + strcpy(j->caplist[j->caps].desc, "G.729A 8kbps"); + j->caplist[j->caps].captype = codec; + j->caplist[j->caps].cap = G729; + j->caplist[j->caps].handle = j->caps++; + } + if (j->dsp.low != 0x20 && j->flags.g729_loaded) { + strcpy(j->caplist[j->caps].desc, "G.729B 8kbps"); + j->caplist[j->caps].captype = codec; + j->caplist[j->caps].cap = G729B; + j->caplist[j->caps].handle = j->caps++; + } +} + +static int capabilities_check(IXJ *j, struct phone_capability *pcreq) +{ + int cnt; + int retval = 0; + for (cnt = 0; cnt < j->caps; cnt++) { + if (pcreq->captype == j->caplist[cnt].captype + && pcreq->cap == j->caplist[cnt].cap) { + retval = 1; + break; + } + } + return retval; +} + +static long do_ixj_ioctl(struct file *file_p, unsigned int cmd, unsigned long arg) +{ + IXJ_TONE ti; + IXJ_FILTER jf; + IXJ_FILTER_RAW jfr; + void __user *argp = (void __user *)arg; + struct inode *inode = file_p->f_path.dentry->d_inode; + unsigned int minor = iminor(inode); + unsigned int raise, mant; + int board = NUM(inode); + + IXJ *j = get_ixj(NUM(inode)); + + int retval = 0; + + /* + * Set up locks to ensure that only one process is talking to the DSP at a time. + * This is necessary to keep the DSP from locking up. + */ + while(test_and_set_bit(board, (void *)&j->busyflags) != 0) + schedule_timeout_interruptible(1); + if (ixjdebug & 0x0040) + printk("phone%d ioctl, cmd: 0x%x, arg: 0x%lx\n", minor, cmd, arg); + if (minor >= IXJMAX) { + clear_bit(board, &j->busyflags); + return -ENODEV; + } + /* + * Check ioctls only root can use. + */ + if (!capable(CAP_SYS_ADMIN)) { + switch (cmd) { + case IXJCTL_TESTRAM: + case IXJCTL_HZ: + retval = -EPERM; + } + } + switch (cmd) { + case IXJCTL_TESTRAM: + ixj_testram(j); + retval = (j->ssr.high << 8) + j->ssr.low; + break; + case IXJCTL_CARDTYPE: + retval = j->cardtype; + break; + case IXJCTL_SERIAL: + retval = j->serial; + break; + case IXJCTL_VERSION: + { + char arg_str[100]; + snprintf(arg_str, sizeof(arg_str), + "\nDriver version %i.%i.%i", IXJ_VER_MAJOR, + IXJ_VER_MINOR, IXJ_BLD_VER); + if (copy_to_user(argp, arg_str, strlen(arg_str))) + retval = -EFAULT; + } + break; + case PHONE_RING_CADENCE: + j->ring_cadence = arg; + break; + case IXJCTL_CIDCW: + if(arg) { + if (copy_from_user(&j->cid_send, argp, sizeof(PHONE_CID))) { + retval = -EFAULT; + break; + } + } else { + memset(&j->cid_send, 0, sizeof(PHONE_CID)); + } + ixj_write_cidcw(j); + break; + /* Binary compatbility */ + case OLD_PHONE_RING_START: + arg = 0; + /* Fall through */ + case PHONE_RING_START: + if(arg) { + if (copy_from_user(&j->cid_send, argp, sizeof(PHONE_CID))) { + retval = -EFAULT; + break; + } + ixj_write_cid(j); + } else { + memset(&j->cid_send, 0, sizeof(PHONE_CID)); + } + ixj_ring_start(j); + break; + case PHONE_RING_STOP: + j->flags.cringing = 0; + if(j->cadence_f[5].enable) { + j->cadence_f[5].state = 0; + } + ixj_ring_off(j); + break; + case PHONE_RING: + retval = ixj_ring(j); + break; + case PHONE_EXCEPTION: + retval = j->ex.bytes; + if(j->ex.bits.flash) { + j->flash_end = 0; + j->ex.bits.flash = 0; + } + j->ex.bits.pstn_ring = 0; + j->ex.bits.caller_id = 0; + j->ex.bits.pstn_wink = 0; + j->ex.bits.f0 = 0; + j->ex.bits.f1 = 0; + j->ex.bits.f2 = 0; + j->ex.bits.f3 = 0; + j->ex.bits.fc0 = 0; + j->ex.bits.fc1 = 0; + j->ex.bits.fc2 = 0; + j->ex.bits.fc3 = 0; + j->ex.bits.reserved = 0; + break; + case PHONE_HOOKSTATE: + j->ex.bits.hookstate = 0; + retval = j->hookstate; //j->r_hook; + break; + case IXJCTL_SET_LED: + LED_SetState(arg, j); + break; + case PHONE_FRAME: + retval = set_base_frame(j, arg); + break; + case PHONE_REC_CODEC: + retval = set_rec_codec(j, arg); + break; + case PHONE_VAD: + ixj_vad(j, arg); + break; + case PHONE_REC_START: + ixj_record_start(j); + break; + case PHONE_REC_STOP: + ixj_record_stop(j); + break; + case PHONE_REC_DEPTH: + set_rec_depth(j, arg); + break; + case PHONE_REC_VOLUME: + if(arg == -1) { + retval = get_rec_volume(j); + } + else { + set_rec_volume(j, arg); + retval = arg; + } + break; + case PHONE_REC_VOLUME_LINEAR: + if(arg == -1) { + retval = get_rec_volume_linear(j); + } + else { + set_rec_volume_linear(j, arg); + retval = arg; + } + break; + case IXJCTL_DTMF_PRESCALE: + if(arg == -1) { + retval = get_dtmf_prescale(j); + } + else { + set_dtmf_prescale(j, arg); + retval = arg; + } + break; + case PHONE_REC_LEVEL: + retval = get_rec_level(j); + break; + case IXJCTL_SC_RXG: + retval = ixj_siadc(j, arg); + break; + case IXJCTL_SC_TXG: + retval = ixj_sidac(j, arg); + break; + case IXJCTL_AEC_START: + ixj_aec_start(j, arg); + break; + case IXJCTL_AEC_STOP: + aec_stop(j); + break; + case IXJCTL_AEC_GET_LEVEL: + retval = j->aec_level; + break; + case PHONE_PLAY_CODEC: + retval = set_play_codec(j, arg); + break; + case PHONE_PLAY_START: + retval = ixj_play_start(j); + break; + case PHONE_PLAY_STOP: + ixj_play_stop(j); + break; + case PHONE_PLAY_DEPTH: + set_play_depth(j, arg); + break; + case PHONE_PLAY_VOLUME: + if(arg == -1) { + retval = get_play_volume(j); + } + else { + set_play_volume(j, arg); + retval = arg; + } + break; + case PHONE_PLAY_VOLUME_LINEAR: + if(arg == -1) { + retval = get_play_volume_linear(j); + } + else { + set_play_volume_linear(j, arg); + retval = arg; + } + break; + case PHONE_PLAY_LEVEL: + retval = get_play_level(j); + break; + case IXJCTL_DSP_TYPE: + retval = (j->dsp.high << 8) + j->dsp.low; + break; + case IXJCTL_DSP_VERSION: + retval = (j->ver.high << 8) + j->ver.low; + break; + case IXJCTL_HZ: + hertz = arg; + break; + case IXJCTL_RATE: + if (arg > hertz) + retval = -1; + else + samplerate = arg; + break; + case IXJCTL_DRYBUFFER_READ: + put_user(j->drybuffer, (unsigned long __user *) argp); + break; + case IXJCTL_DRYBUFFER_CLEAR: + j->drybuffer = 0; + break; + case IXJCTL_FRAMES_READ: + put_user(j->framesread, (unsigned long __user *) argp); + break; + case IXJCTL_FRAMES_WRITTEN: + put_user(j->frameswritten, (unsigned long __user *) argp); + break; + case IXJCTL_READ_WAIT: + put_user(j->read_wait, (unsigned long __user *) argp); + break; + case IXJCTL_WRITE_WAIT: + put_user(j->write_wait, (unsigned long __user *) argp); + break; + case PHONE_MAXRINGS: + j->maxrings = arg; + break; + case PHONE_SET_TONE_ON_TIME: + ixj_set_tone_on(arg, j); + break; + case PHONE_SET_TONE_OFF_TIME: + ixj_set_tone_off(arg, j); + break; + case PHONE_GET_TONE_ON_TIME: + if (ixj_get_tone_on(j)) { + retval = -1; + } else { + retval = (j->ssr.high << 8) + j->ssr.low; + } + break; + case PHONE_GET_TONE_OFF_TIME: + if (ixj_get_tone_off(j)) { + retval = -1; + } else { + retval = (j->ssr.high << 8) + j->ssr.low; + } + break; + case PHONE_PLAY_TONE: + if (!j->tone_state) + retval = ixj_play_tone(j, arg); + else + retval = -1; + break; + case PHONE_GET_TONE_STATE: + retval = j->tone_state; + break; + case PHONE_DTMF_READY: + retval = j->ex.bits.dtmf_ready; + break; + case PHONE_GET_DTMF: + if (ixj_hookstate(j)) { + if (j->dtmf_rp != j->dtmf_wp) { + retval = j->dtmfbuffer[j->dtmf_rp]; + j->dtmf_rp++; + if (j->dtmf_rp == 79) + j->dtmf_rp = 0; + if (j->dtmf_rp == j->dtmf_wp) { + j->ex.bits.dtmf_ready = j->dtmf_rp = j->dtmf_wp = 0; + } + } + } + break; + case PHONE_GET_DTMF_ASCII: + if (ixj_hookstate(j)) { + if (j->dtmf_rp != j->dtmf_wp) { + switch (j->dtmfbuffer[j->dtmf_rp]) { + case 10: + retval = 42; /* '*'; */ + + break; + case 11: + retval = 48; /*'0'; */ + + break; + case 12: + retval = 35; /*'#'; */ + + break; + case 28: + retval = 65; /*'A'; */ + + break; + case 29: + retval = 66; /*'B'; */ + + break; + case 30: + retval = 67; /*'C'; */ + + break; + case 31: + retval = 68; /*'D'; */ + + break; + default: + retval = 48 + j->dtmfbuffer[j->dtmf_rp]; + break; + } + j->dtmf_rp++; + if (j->dtmf_rp == 79) + j->dtmf_rp = 0; + if(j->dtmf_rp == j->dtmf_wp) + { + j->ex.bits.dtmf_ready = j->dtmf_rp = j->dtmf_wp = 0; + } + } + } + break; + case PHONE_DTMF_OOB: + j->flags.dtmf_oob = arg; + break; + case PHONE_DIALTONE: + ixj_dialtone(j); + break; + case PHONE_BUSY: + ixj_busytone(j); + break; + case PHONE_RINGBACK: + ixj_ringback(j); + break; + case PHONE_WINK: + if(j->cardtype == QTI_PHONEJACK) + retval = -1; + else + retval = ixj_wink(j); + break; + case PHONE_CPT_STOP: + ixj_cpt_stop(j); + break; + case PHONE_QUERY_CODEC: + { + struct phone_codec_data pd; + int val; + int proto_size[] = { + -1, + 12, 10, 16, 9, 8, 48, 5, + 40, 40, 80, 40, 40, 6 + }; + if(copy_from_user(&pd, argp, sizeof(pd))) { + retval = -EFAULT; + break; + } + if(pd.type<1 || pd.type>13) { + retval = -EPROTONOSUPPORT; + break; + } + if(pd.typebaseframe.low) + { + case 0xA0:val=2*proto_size[pd.type];break; + case 0x50:val=proto_size[pd.type];break; + default:val=proto_size[pd.type]*3;break; + } + pd.buf_min=pd.buf_max=pd.buf_opt=val; + if(copy_to_user(argp, &pd, sizeof(pd))) + retval = -EFAULT; + break; + } + case IXJCTL_DSP_IDLE: + idle(j); + break; + case IXJCTL_MIXER: + if ((arg & 0xff) == 0xff) + retval = ixj_get_mixer(arg, j); + else + ixj_mixer(arg, j); + break; + case IXJCTL_DAA_COEFF_SET: + switch (arg) { + case DAA_US: + DAA_Coeff_US(j); + retval = ixj_daa_write(j); + break; + case DAA_UK: + DAA_Coeff_UK(j); + retval = ixj_daa_write(j); + break; + case DAA_FRANCE: + DAA_Coeff_France(j); + retval = ixj_daa_write(j); + break; + case DAA_GERMANY: + DAA_Coeff_Germany(j); + retval = ixj_daa_write(j); + break; + case DAA_AUSTRALIA: + DAA_Coeff_Australia(j); + retval = ixj_daa_write(j); + break; + case DAA_JAPAN: + DAA_Coeff_Japan(j); + retval = ixj_daa_write(j); + break; + default: + retval = 1; + break; + } + break; + case IXJCTL_DAA_AGAIN: + ixj_daa_cr4(j, arg | 0x02); + break; + case IXJCTL_PSTN_LINETEST: + retval = ixj_linetest(j); + break; + case IXJCTL_VMWI: + ixj_write_vmwi(j, arg); + break; + case IXJCTL_CID: + if (copy_to_user(argp, &j->cid, sizeof(PHONE_CID))) + retval = -EFAULT; + j->ex.bits.caller_id = 0; + break; + case IXJCTL_WINK_DURATION: + j->winktime = arg; + break; + case IXJCTL_PORT: + if (arg) + retval = ixj_set_port(j, arg); + else + retval = j->port; + break; + case IXJCTL_POTS_PSTN: + retval = ixj_set_pots(j, arg); + break; + case PHONE_CAPABILITIES: + add_caps(j); + retval = j->caps; + break; + case PHONE_CAPABILITIES_LIST: + add_caps(j); + if (copy_to_user(argp, j->caplist, sizeof(struct phone_capability) * j->caps)) + retval = -EFAULT; + break; + case PHONE_CAPABILITIES_CHECK: + { + struct phone_capability cap; + if (copy_from_user(&cap, argp, sizeof(cap))) + retval = -EFAULT; + else { + add_caps(j); + retval = capabilities_check(j, &cap); + } + } + break; + case PHONE_PSTN_SET_STATE: + daa_set_mode(j, arg); + break; + case PHONE_PSTN_GET_STATE: + retval = j->daa_mode; + j->ex.bits.pstn_ring = 0; + break; + case IXJCTL_SET_FILTER: + if (copy_from_user(&jf, argp, sizeof(jf))) + retval = -EFAULT; + else + retval = ixj_init_filter(j, &jf); + break; + case IXJCTL_SET_FILTER_RAW: + if (copy_from_user(&jfr, argp, sizeof(jfr))) + retval = -EFAULT; + else + retval = ixj_init_filter_raw(j, &jfr); + break; + case IXJCTL_GET_FILTER_HIST: + if(arg<0||arg>3) + retval = -EINVAL; + else + retval = j->filter_hist[arg]; + break; + case IXJCTL_INIT_TONE: + if (copy_from_user(&ti, argp, sizeof(ti))) + retval = -EFAULT; + else + retval = ixj_init_tone(j, &ti); + break; + case IXJCTL_TONE_CADENCE: + retval = ixj_build_cadence(j, argp); + break; + case IXJCTL_FILTER_CADENCE: + retval = ixj_build_filter_cadence(j, argp); + break; + case IXJCTL_SIGCTL: + if (copy_from_user(&j->sigdef, argp, sizeof(IXJ_SIGDEF))) { + retval = -EFAULT; + break; + } + j->ixj_signals[j->sigdef.event] = j->sigdef.signal; + if(j->sigdef.event < 33) { + raise = 1; + for(mant = 0; mant < j->sigdef.event; mant++){ + raise *= 2; + } + if(j->sigdef.signal) + j->ex_sig.bytes |= raise; + else + j->ex_sig.bytes &= (raise^0xffff); + } + break; + case IXJCTL_INTERCOM_STOP: + if(arg < 0 || arg >= IXJMAX) + return -EINVAL; + j->intercom = -1; + ixj_record_stop(j); + ixj_play_stop(j); + idle(j); + get_ixj(arg)->intercom = -1; + ixj_record_stop(get_ixj(arg)); + ixj_play_stop(get_ixj(arg)); + idle(get_ixj(arg)); + break; + case IXJCTL_INTERCOM_START: + if(arg < 0 || arg >= IXJMAX) + return -EINVAL; + j->intercom = arg; + ixj_record_start(j); + ixj_play_start(j); + get_ixj(arg)->intercom = board; + ixj_play_start(get_ixj(arg)); + ixj_record_start(get_ixj(arg)); + break; + } + if (ixjdebug & 0x0040) + printk("phone%d ioctl end, cmd: 0x%x, arg: 0x%lx\n", minor, cmd, arg); + clear_bit(board, &j->busyflags); + return retval; +} + +static long ixj_ioctl(struct file *file_p, unsigned int cmd, unsigned long arg) +{ + long ret; + mutex_lock(&ixj_mutex); + ret = do_ixj_ioctl(file_p, cmd, arg); + mutex_unlock(&ixj_mutex); + return ret; +} + +static int ixj_fasync(int fd, struct file *file_p, int mode) +{ + IXJ *j = get_ixj(NUM(file_p->f_path.dentry->d_inode)); + + return fasync_helper(fd, file_p, mode, &j->async_queue); +} + +static const struct file_operations ixj_fops = +{ + .owner = THIS_MODULE, + .read = ixj_enhanced_read, + .write = ixj_enhanced_write, + .poll = ixj_poll, + .unlocked_ioctl = ixj_ioctl, + .release = ixj_release, + .fasync = ixj_fasync, + .llseek = default_llseek, +}; + +static int ixj_linetest(IXJ *j) +{ + j->flags.pstncheck = 1; /* Testing */ + j->flags.pstn_present = 0; /* Assume the line is not there */ + + daa_int_read(j); /*Clear DAA Interrupt flags */ + /* */ + /* Hold all relays in the normally de-energized position. */ + /* */ + + j->pld_slicw.bits.rly1 = 0; + j->pld_slicw.bits.rly2 = 0; + j->pld_slicw.bits.rly3 = 0; + outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); + j->pld_scrw.bits.daafsyncen = 0; /* Turn off DAA Frame Sync */ + + outb_p(j->pld_scrw.byte, j->XILINXbase); + j->pld_slicr.byte = inb_p(j->XILINXbase + 0x01); + if (j->pld_slicr.bits.potspstn) { + j->flags.pots_pstn = 1; + j->flags.pots_correct = 0; + LED_SetState(0x4, j); + } else { + j->flags.pots_pstn = 0; + j->pld_slicw.bits.rly1 = 0; + j->pld_slicw.bits.rly2 = 0; + j->pld_slicw.bits.rly3 = 1; + outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); + j->pld_scrw.bits.daafsyncen = 0; /* Turn off DAA Frame Sync */ + + outb_p(j->pld_scrw.byte, j->XILINXbase); + daa_set_mode(j, SOP_PU_CONVERSATION); + msleep(1000); + daa_int_read(j); + daa_set_mode(j, SOP_PU_RESET); + if (j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.VDD_OK) { + j->flags.pots_correct = 0; /* Should not be line voltage on POTS port. */ + LED_SetState(0x4, j); + j->pld_slicw.bits.rly3 = 0; + outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); + } else { + j->flags.pots_correct = 1; + LED_SetState(0x8, j); + j->pld_slicw.bits.rly1 = 1; + j->pld_slicw.bits.rly2 = 0; + j->pld_slicw.bits.rly3 = 0; + outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); + } + } + j->pld_slicw.bits.rly3 = 0; + outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); + daa_set_mode(j, SOP_PU_CONVERSATION); + msleep(1000); + daa_int_read(j); + daa_set_mode(j, SOP_PU_RESET); + if (j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.VDD_OK) { + j->pstn_sleeptil = jiffies + (hertz / 4); + j->flags.pstn_present = 1; + } else { + j->flags.pstn_present = 0; + } + if (j->flags.pstn_present) { + if (j->flags.pots_correct) { + LED_SetState(0xA, j); + } else { + LED_SetState(0x6, j); + } + } else { + if (j->flags.pots_correct) { + LED_SetState(0x9, j); + } else { + LED_SetState(0x5, j); + } + } + j->flags.pstncheck = 0; /* Testing */ + return j->flags.pstn_present; +} + +static int ixj_selfprobe(IXJ *j) +{ + unsigned short cmd; + int cnt; + BYTES bytes; + + init_waitqueue_head(&j->poll_q); + init_waitqueue_head(&j->read_q); + init_waitqueue_head(&j->write_q); + + while(atomic_read(&j->DSPWrite) > 0) + atomic_dec(&j->DSPWrite); + if (ixjdebug & 0x0002) + printk(KERN_INFO "Write IDLE to Software Control Register\n"); + ixj_WriteDSPCommand(0x0FE0, j); /* Put the DSP in full power mode. */ + + if (ixj_WriteDSPCommand(0x0000, j)) /* Write IDLE to Software Control Register */ + return -1; +/* The read values of the SSR should be 0x00 for the IDLE command */ + if (j->ssr.low || j->ssr.high) + return -1; + if (ixjdebug & 0x0002) + printk(KERN_INFO "Get Device ID Code\n"); + if (ixj_WriteDSPCommand(0x3400, j)) /* Get Device ID Code */ + return -1; + j->dsp.low = j->ssr.low; + j->dsp.high = j->ssr.high; + if (ixjdebug & 0x0002) + printk(KERN_INFO "Get Device Version Code\n"); + if (ixj_WriteDSPCommand(0x3800, j)) /* Get Device Version Code */ + return -1; + j->ver.low = j->ssr.low; + j->ver.high = j->ssr.high; + if (!j->cardtype) { + if (j->dsp.low == 0x21) { + bytes.high = bytes.low = inb_p(j->XILINXbase + 0x02); + outb_p(bytes.low ^ 0xFF, j->XILINXbase + 0x02); +/* Test for Internet LineJACK or Internet PhoneJACK Lite */ + bytes.low = inb_p(j->XILINXbase + 0x02); + if (bytes.low == bytes.high) /* Register is read only on */ + /* Internet PhoneJack Lite */ + { + j->cardtype = QTI_PHONEJACK_LITE; + if (!request_region(j->XILINXbase, 4, "ixj control")) { + printk(KERN_INFO "ixj: can't get I/O address 0x%x\n", j->XILINXbase); + return -1; + } + j->pld_slicw.pcib.e1 = 1; + outb_p(j->pld_slicw.byte, j->XILINXbase); + } else { + j->cardtype = QTI_LINEJACK; + + if (!request_region(j->XILINXbase, 8, "ixj control")) { + printk(KERN_INFO "ixj: can't get I/O address 0x%x\n", j->XILINXbase); + return -1; + } + } + } else if (j->dsp.low == 0x22) { + j->cardtype = QTI_PHONEJACK_PCI; + request_region(j->XILINXbase, 4, "ixj control"); + j->pld_slicw.pcib.e1 = 1; + outb_p(j->pld_slicw.byte, j->XILINXbase); + } else + j->cardtype = QTI_PHONEJACK; + } else { + switch (j->cardtype) { + case QTI_PHONEJACK: + if (!j->dsp.low != 0x20) { + j->dsp.high = 0x80; + j->dsp.low = 0x20; + ixj_WriteDSPCommand(0x3800, j); + j->ver.low = j->ssr.low; + j->ver.high = j->ssr.high; + } + break; + case QTI_LINEJACK: + if (!request_region(j->XILINXbase, 8, "ixj control")) { + printk(KERN_INFO "ixj: can't get I/O address 0x%x\n", j->XILINXbase); + return -1; + } + break; + case QTI_PHONEJACK_LITE: + case QTI_PHONEJACK_PCI: + if (!request_region(j->XILINXbase, 4, "ixj control")) { + printk(KERN_INFO "ixj: can't get I/O address 0x%x\n", j->XILINXbase); + return -1; + } + j->pld_slicw.pcib.e1 = 1; + outb_p(j->pld_slicw.byte, j->XILINXbase); + break; + case QTI_PHONECARD: + break; + } + } + if (j->dsp.low == 0x20 || j->cardtype == QTI_PHONEJACK_LITE || j->cardtype == QTI_PHONEJACK_PCI) { + if (ixjdebug & 0x0002) + printk(KERN_INFO "Write CODEC config to Software Control Register\n"); + if (ixj_WriteDSPCommand(0xC462, j)) /* Write CODEC config to Software Control Register */ + return -1; + if (ixjdebug & 0x0002) + printk(KERN_INFO "Write CODEC timing to Software Control Register\n"); + if (j->cardtype == QTI_PHONEJACK) { + cmd = 0x9FF2; + } else { + cmd = 0x9FF5; + } + if (ixj_WriteDSPCommand(cmd, j)) /* Write CODEC timing to Software Control Register */ + return -1; + } else { + if (set_base_frame(j, 30) != 30) + return -1; + if (ixjdebug & 0x0002) + printk(KERN_INFO "Write CODEC config to Software Control Register\n"); + if (j->cardtype == QTI_PHONECARD) { + if (ixj_WriteDSPCommand(0xC528, j)) /* Write CODEC config to Software Control Register */ + return -1; + } + if (j->cardtype == QTI_LINEJACK) { + if (ixj_WriteDSPCommand(0xC528, j)) /* Write CODEC config to Software Control Register */ + return -1; + if (ixjdebug & 0x0002) + printk(KERN_INFO "Turn on the PLD Clock at 8Khz\n"); + j->pld_clock.byte = 0; + outb_p(j->pld_clock.byte, j->XILINXbase + 0x04); + } + } + + if (j->dsp.low == 0x20) { + if (ixjdebug & 0x0002) + printk(KERN_INFO "Configure GPIO pins\n"); + j->gpio.bytes.high = 0x09; +/* bytes.low = 0xEF; 0xF7 */ + j->gpio.bits.gpio1 = 1; + j->gpio.bits.gpio2 = 1; + j->gpio.bits.gpio3 = 0; + j->gpio.bits.gpio4 = 1; + j->gpio.bits.gpio5 = 1; + j->gpio.bits.gpio6 = 1; + j->gpio.bits.gpio7 = 1; + ixj_WriteDSPCommand(j->gpio.word, j); /* Set GPIO pin directions */ + if (ixjdebug & 0x0002) + printk(KERN_INFO "Enable SLIC\n"); + j->gpio.bytes.high = 0x0B; + j->gpio.bytes.low = 0x00; + j->gpio.bits.gpio1 = 0; + j->gpio.bits.gpio2 = 1; + j->gpio.bits.gpio5 = 0; + ixj_WriteDSPCommand(j->gpio.word, j); /* send the ring stop signal */ + j->port = PORT_POTS; + } else { + if (j->cardtype == QTI_LINEJACK) { + LED_SetState(0x1, j); + msleep(100); + LED_SetState(0x2, j); + msleep(100); + LED_SetState(0x4, j); + msleep(100); + LED_SetState(0x8, j); + msleep(100); + LED_SetState(0x0, j); + daa_get_version(j); + if (ixjdebug & 0x0002) + printk("Loading DAA Coefficients\n"); + DAA_Coeff_US(j); + if (!ixj_daa_write(j)) { + printk("DAA write failed on board %d\n", j->board); + return -1; + } + if(!ixj_daa_cid_reset(j)) { + printk("DAA CID reset failed on board %d\n", j->board); + return -1; + } + j->flags.pots_correct = 0; + j->flags.pstn_present = 0; + ixj_linetest(j); + if (j->flags.pots_correct) { + j->pld_scrw.bits.daafsyncen = 0; /* Turn off DAA Frame Sync */ + + outb_p(j->pld_scrw.byte, j->XILINXbase); + j->pld_slicw.bits.rly1 = 1; + j->pld_slicw.bits.spken = 1; + outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); + SLIC_SetState(PLD_SLIC_STATE_STANDBY, j); +/* SLIC_SetState(PLD_SLIC_STATE_ACTIVE, j); */ + j->port = PORT_POTS; + } + ixj_set_port(j, PORT_PSTN); + ixj_set_pots(j, 1); + if (ixjdebug & 0x0002) + printk(KERN_INFO "Enable Mixer\n"); + ixj_mixer(0x0000, j); /*Master Volume Left unmute 0db */ + ixj_mixer(0x0100, j); /*Master Volume Right unmute 0db */ + + ixj_mixer(0x0203, j); /*Voice Left Volume unmute 6db */ + ixj_mixer(0x0303, j); /*Voice Right Volume unmute 6db */ + + ixj_mixer(0x0480, j); /*FM Left mute */ + ixj_mixer(0x0580, j); /*FM Right mute */ + + ixj_mixer(0x0680, j); /*CD Left mute */ + ixj_mixer(0x0780, j); /*CD Right mute */ + + ixj_mixer(0x0880, j); /*Line Left mute */ + ixj_mixer(0x0980, j); /*Line Right mute */ + + ixj_mixer(0x0A80, j); /*Aux left mute */ + ixj_mixer(0x0B80, j); /*Aux right mute */ + + ixj_mixer(0x0C00, j); /*Mono1 unmute 12db */ + ixj_mixer(0x0D80, j); /*Mono2 mute */ + + ixj_mixer(0x0E80, j); /*Mic mute */ + + ixj_mixer(0x0F00, j); /*Mono Out Volume unmute 0db */ + + ixj_mixer(0x1000, j); /*Voice Left and Right out only */ + ixj_mixer(0x110C, j); + + + ixj_mixer(0x1200, j); /*Mono1 switch on mixer left */ + ixj_mixer(0x1401, j); + + ixj_mixer(0x1300, j); /*Mono1 switch on mixer right */ + ixj_mixer(0x1501, j); + + ixj_mixer(0x1700, j); /*Clock select */ + + ixj_mixer(0x1800, j); /*ADC input from mixer */ + + ixj_mixer(0x1901, j); /*Mic gain 30db */ + + if (ixjdebug & 0x0002) + printk(KERN_INFO "Setting Default US Ring Cadence Detection\n"); + j->cadence_f[4].state = 0; + j->cadence_f[4].on1 = 0; /*Cadence Filter 4 is used for PSTN ring cadence */ + j->cadence_f[4].off1 = 0; + j->cadence_f[4].on2 = 0; + j->cadence_f[4].off2 = 0; + j->cadence_f[4].on3 = 0; + j->cadence_f[4].off3 = 0; /* These should represent standard US ring pulse. */ + j->pstn_last_rmr = jiffies; + + } else { + if (j->cardtype == QTI_PHONECARD) { + ixj_WriteDSPCommand(0xCF07, j); + ixj_WriteDSPCommand(0x00B0, j); + ixj_set_port(j, PORT_SPEAKER); + } else { + ixj_set_port(j, PORT_POTS); + SLIC_SetState(PLD_SLIC_STATE_STANDBY, j); +/* SLIC_SetState(PLD_SLIC_STATE_ACTIVE, j); */ + } + } + } + + j->intercom = -1; + j->framesread = j->frameswritten = 0; + j->read_wait = j->write_wait = 0; + j->rxreadycheck = j->txreadycheck = 0; + + /* initialise the DTMF prescale to a sensible value */ + if (j->cardtype == QTI_LINEJACK) { + set_dtmf_prescale(j, 0x10); + } else { + set_dtmf_prescale(j, 0x40); + } + set_play_volume(j, 0x100); + set_rec_volume(j, 0x100); + + if (ixj_WriteDSPCommand(0x0000, j)) /* Write IDLE to Software Control Register */ + return -1; +/* The read values of the SSR should be 0x00 for the IDLE command */ + if (j->ssr.low || j->ssr.high) + return -1; + + if (ixjdebug & 0x0002) + printk(KERN_INFO "Enable Line Monitor\n"); + + if (ixjdebug & 0x0002) + printk(KERN_INFO "Set Line Monitor to Asyncronous Mode\n"); + + if (ixj_WriteDSPCommand(0x7E01, j)) /* Asynchronous Line Monitor */ + return -1; + + if (ixjdebug & 0x002) + printk(KERN_INFO "Enable DTMF Detectors\n"); + + if (ixj_WriteDSPCommand(0x5151, j)) /* Enable DTMF detection */ + return -1; + + if (ixj_WriteDSPCommand(0x6E01, j)) /* Set Asyncronous Tone Generation */ + return -1; + + set_rec_depth(j, 2); /* Set Record Channel Limit to 2 frames */ + + set_play_depth(j, 2); /* Set Playback Channel Limit to 2 frames */ + + j->ex.bits.dtmf_ready = 0; + j->dtmf_state = 0; + j->dtmf_wp = j->dtmf_rp = 0; + j->rec_mode = j->play_mode = -1; + j->flags.ringing = 0; + j->maxrings = MAXRINGS; + j->ring_cadence = USA_RING_CADENCE; + j->drybuffer = 0; + j->winktime = 320; + j->flags.dtmf_oob = 0; + for (cnt = 0; cnt < 4; cnt++) + j->cadence_f[cnt].enable = 0; + /* must be a device on the specified address */ + ixj_WriteDSPCommand(0x0FE3, j); /* Put the DSP in 1/5 power mode. */ + + /* Set up the default signals for events */ + for (cnt = 0; cnt < 35; cnt++) + j->ixj_signals[cnt] = SIGIO; + + /* Set the excetion signal enable flags */ + j->ex_sig.bits.dtmf_ready = j->ex_sig.bits.hookstate = j->ex_sig.bits.flash = j->ex_sig.bits.pstn_ring = + j->ex_sig.bits.caller_id = j->ex_sig.bits.pstn_wink = j->ex_sig.bits.f0 = j->ex_sig.bits.f1 = j->ex_sig.bits.f2 = + j->ex_sig.bits.f3 = j->ex_sig.bits.fc0 = j->ex_sig.bits.fc1 = j->ex_sig.bits.fc2 = j->ex_sig.bits.fc3 = 1; +#ifdef IXJ_DYN_ALLOC + j->fskdata = NULL; +#endif + j->fskdcnt = 0; + j->cidcw_wait = 0; + + /* Register with the Telephony for Linux subsystem */ + j->p.f_op = &ixj_fops; + j->p.open = ixj_open; + j->p.board = j->board; + phone_register_device(&j->p, PHONE_UNIT_ANY); + + ixj_init_timer(j); + ixj_add_timer(j); + return 0; +} + +/* + * Exported service for pcmcia card handling + */ + +IXJ *ixj_pcmcia_probe(unsigned long dsp, unsigned long xilinx) +{ + IXJ *j = ixj_alloc(); + + j->board = 0; + + j->DSPbase = dsp; + j->XILINXbase = xilinx; + j->cardtype = QTI_PHONECARD; + ixj_selfprobe(j); + return j; +} + +EXPORT_SYMBOL(ixj_pcmcia_probe); /* Fpr PCMCIA */ + +static int ixj_get_status_proc(char *buf) +{ + int len; + int cnt; + IXJ *j; + len = 0; + len += sprintf(buf + len, "\nDriver version %i.%i.%i", IXJ_VER_MAJOR, IXJ_VER_MINOR, IXJ_BLD_VER); + len += sprintf(buf + len, "\nsizeof IXJ struct %Zd bytes", sizeof(IXJ)); + len += sprintf(buf + len, "\nsizeof DAA struct %Zd bytes", sizeof(DAA_REGS)); + len += sprintf(buf + len, "\nUsing old telephony API"); + len += sprintf(buf + len, "\nDebug Level %d\n", ixjdebug); + + for (cnt = 0; cnt < IXJMAX; cnt++) { + j = get_ixj(cnt); + if(j==NULL) + continue; + if (j->DSPbase) { + len += sprintf(buf + len, "\nCard Num %d", cnt); + len += sprintf(buf + len, "\nDSP Base Address 0x%4.4x", j->DSPbase); + if (j->cardtype != QTI_PHONEJACK) + len += sprintf(buf + len, "\nXILINX Base Address 0x%4.4x", j->XILINXbase); + len += sprintf(buf + len, "\nDSP Type %2.2x%2.2x", j->dsp.high, j->dsp.low); + len += sprintf(buf + len, "\nDSP Version %2.2x.%2.2x", j->ver.high, j->ver.low); + len += sprintf(buf + len, "\nSerial Number %8.8x", j->serial); + switch (j->cardtype) { + case (QTI_PHONEJACK): + len += sprintf(buf + len, "\nCard Type = Internet PhoneJACK"); + break; + case (QTI_LINEJACK): + len += sprintf(buf + len, "\nCard Type = Internet LineJACK"); + if (j->flags.g729_loaded) + len += sprintf(buf + len, " w/G.729 A/B"); + len += sprintf(buf + len, " Country = %d", j->daa_country); + break; + case (QTI_PHONEJACK_LITE): + len += sprintf(buf + len, "\nCard Type = Internet PhoneJACK Lite"); + if (j->flags.g729_loaded) + len += sprintf(buf + len, " w/G.729 A/B"); + break; + case (QTI_PHONEJACK_PCI): + len += sprintf(buf + len, "\nCard Type = Internet PhoneJACK PCI"); + if (j->flags.g729_loaded) + len += sprintf(buf + len, " w/G.729 A/B"); + break; + case (QTI_PHONECARD): + len += sprintf(buf + len, "\nCard Type = Internet PhoneCARD"); + if (j->flags.g729_loaded) + len += sprintf(buf + len, " w/G.729 A/B"); + len += sprintf(buf + len, "\nSmart Cable %spresent", j->pccr1.bits.drf ? "not " : ""); + if (!j->pccr1.bits.drf) + len += sprintf(buf + len, "\nSmart Cable type %d", j->flags.pcmciasct); + len += sprintf(buf + len, "\nSmart Cable state %d", j->flags.pcmciastate); + break; + default: + len += sprintf(buf + len, "\nCard Type = %d", j->cardtype); + break; + } + len += sprintf(buf + len, "\nReaders %d", j->readers); + len += sprintf(buf + len, "\nWriters %d", j->writers); + add_caps(j); + len += sprintf(buf + len, "\nCapabilities %d", j->caps); + if (j->dsp.low != 0x20) + len += sprintf(buf + len, "\nDSP Processor load %d", j->proc_load); + if (j->flags.cidsent) + len += sprintf(buf + len, "\nCaller ID data sent"); + else + len += sprintf(buf + len, "\nCaller ID data not sent"); + + len += sprintf(buf + len, "\nPlay CODEC "); + switch (j->play_codec) { + case G723_63: + len += sprintf(buf + len, "G.723.1 6.3"); + break; + case G723_53: + len += sprintf(buf + len, "G.723.1 5.3"); + break; + case TS85: + len += sprintf(buf + len, "TrueSpeech 8.5"); + break; + case TS48: + len += sprintf(buf + len, "TrueSpeech 4.8"); + break; + case TS41: + len += sprintf(buf + len, "TrueSpeech 4.1"); + break; + case G728: + len += sprintf(buf + len, "G.728"); + break; + case G729: + len += sprintf(buf + len, "G.729"); + break; + case G729B: + len += sprintf(buf + len, "G.729B"); + break; + case ULAW: + len += sprintf(buf + len, "uLaw"); + break; + case ALAW: + len += sprintf(buf + len, "aLaw"); + break; + case LINEAR16: + len += sprintf(buf + len, "16 bit Linear"); + break; + case LINEAR8: + len += sprintf(buf + len, "8 bit Linear"); + break; + case WSS: + len += sprintf(buf + len, "Windows Sound System"); + break; + default: + len += sprintf(buf + len, "NO CODEC CHOSEN"); + break; + } + len += sprintf(buf + len, "\nRecord CODEC "); + switch (j->rec_codec) { + case G723_63: + len += sprintf(buf + len, "G.723.1 6.3"); + break; + case G723_53: + len += sprintf(buf + len, "G.723.1 5.3"); + break; + case TS85: + len += sprintf(buf + len, "TrueSpeech 8.5"); + break; + case TS48: + len += sprintf(buf + len, "TrueSpeech 4.8"); + break; + case TS41: + len += sprintf(buf + len, "TrueSpeech 4.1"); + break; + case G728: + len += sprintf(buf + len, "G.728"); + break; + case G729: + len += sprintf(buf + len, "G.729"); + break; + case G729B: + len += sprintf(buf + len, "G.729B"); + break; + case ULAW: + len += sprintf(buf + len, "uLaw"); + break; + case ALAW: + len += sprintf(buf + len, "aLaw"); + break; + case LINEAR16: + len += sprintf(buf + len, "16 bit Linear"); + break; + case LINEAR8: + len += sprintf(buf + len, "8 bit Linear"); + break; + case WSS: + len += sprintf(buf + len, "Windows Sound System"); + break; + default: + len += sprintf(buf + len, "NO CODEC CHOSEN"); + break; + } + len += sprintf(buf + len, "\nAEC "); + switch (j->aec_level) { + case AEC_OFF: + len += sprintf(buf + len, "Off"); + break; + case AEC_LOW: + len += sprintf(buf + len, "Low"); + break; + case AEC_MED: + len += sprintf(buf + len, "Med"); + break; + case AEC_HIGH: + len += sprintf(buf + len, "High"); + break; + case AEC_AUTO: + len += sprintf(buf + len, "Auto"); + break; + case AEC_AGC: + len += sprintf(buf + len, "AEC/AGC"); + break; + default: + len += sprintf(buf + len, "unknown(%i)", j->aec_level); + break; + } + + len += sprintf(buf + len, "\nRec volume 0x%x", get_rec_volume(j)); + len += sprintf(buf + len, "\nPlay volume 0x%x", get_play_volume(j)); + len += sprintf(buf + len, "\nDTMF prescale 0x%x", get_dtmf_prescale(j)); + + len += sprintf(buf + len, "\nHook state %d", j->hookstate); /* j->r_hook); */ + + if (j->cardtype == QTI_LINEJACK) { + len += sprintf(buf + len, "\nPOTS Correct %d", j->flags.pots_correct); + len += sprintf(buf + len, "\nPSTN Present %d", j->flags.pstn_present); + len += sprintf(buf + len, "\nPSTN Check %d", j->flags.pstncheck); + len += sprintf(buf + len, "\nPOTS to PSTN %d", j->flags.pots_pstn); + switch (j->daa_mode) { + case SOP_PU_SLEEP: + len += sprintf(buf + len, "\nDAA PSTN On Hook"); + break; + case SOP_PU_RINGING: + len += sprintf(buf + len, "\nDAA PSTN Ringing"); + len += sprintf(buf + len, "\nRinging state = %d", j->cadence_f[4].state); + break; + case SOP_PU_CONVERSATION: + len += sprintf(buf + len, "\nDAA PSTN Off Hook"); + break; + case SOP_PU_PULSEDIALING: + len += sprintf(buf + len, "\nDAA PSTN Pulse Dialing"); + break; + } + len += sprintf(buf + len, "\nDAA RMR = %d", j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.bitreg.RMR); + len += sprintf(buf + len, "\nDAA VDD OK = %d", j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.VDD_OK); + len += sprintf(buf + len, "\nDAA CR0 = 0x%02x", j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg); + len += sprintf(buf + len, "\nDAA CR1 = 0x%02x", j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.reg); + len += sprintf(buf + len, "\nDAA CR2 = 0x%02x", j->m_DAAShadowRegs.SOP_REGS.SOP.cr2.reg); + len += sprintf(buf + len, "\nDAA CR3 = 0x%02x", j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg); + len += sprintf(buf + len, "\nDAA CR4 = 0x%02x", j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg); + len += sprintf(buf + len, "\nDAA CR5 = 0x%02x", j->m_DAAShadowRegs.SOP_REGS.SOP.cr5.reg); + len += sprintf(buf + len, "\nDAA XR0 = 0x%02x", j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.reg); + len += sprintf(buf + len, "\nDAA ringstop %ld - jiffies %ld", j->pstn_ring_stop, jiffies); + } + switch (j->port) { + case PORT_POTS: + len += sprintf(buf + len, "\nPort POTS"); + break; + case PORT_PSTN: + len += sprintf(buf + len, "\nPort PSTN"); + break; + case PORT_SPEAKER: + len += sprintf(buf + len, "\nPort SPEAKER/MIC"); + break; + case PORT_HANDSET: + len += sprintf(buf + len, "\nPort HANDSET"); + break; + } + if (j->dsp.low == 0x21 || j->dsp.low == 0x22) { + len += sprintf(buf + len, "\nSLIC state "); + switch (SLIC_GetState(j)) { + case PLD_SLIC_STATE_OC: + len += sprintf(buf + len, "OC"); + break; + case PLD_SLIC_STATE_RINGING: + len += sprintf(buf + len, "RINGING"); + break; + case PLD_SLIC_STATE_ACTIVE: + len += sprintf(buf + len, "ACTIVE"); + break; + case PLD_SLIC_STATE_OHT: /* On-hook transmit */ + len += sprintf(buf + len, "OHT"); + break; + case PLD_SLIC_STATE_TIPOPEN: + len += sprintf(buf + len, "TIPOPEN"); + break; + case PLD_SLIC_STATE_STANDBY: + len += sprintf(buf + len, "STANDBY"); + break; + case PLD_SLIC_STATE_APR: /* Active polarity reversal */ + len += sprintf(buf + len, "APR"); + break; + case PLD_SLIC_STATE_OHTPR: /* OHT polarity reversal */ + len += sprintf(buf + len, "OHTPR"); + break; + default: + len += sprintf(buf + len, "%d", SLIC_GetState(j)); + break; + } + } + len += sprintf(buf + len, "\nBase Frame %2.2x.%2.2x", j->baseframe.high, j->baseframe.low); + len += sprintf(buf + len, "\nCID Base Frame %2d", j->cid_base_frame_size); +#ifdef PERFMON_STATS + len += sprintf(buf + len, "\nTimer Checks %ld", j->timerchecks); + len += sprintf(buf + len, "\nRX Ready Checks %ld", j->rxreadycheck); + len += sprintf(buf + len, "\nTX Ready Checks %ld", j->txreadycheck); + len += sprintf(buf + len, "\nFrames Read %ld", j->framesread); + len += sprintf(buf + len, "\nFrames Written %ld", j->frameswritten); + len += sprintf(buf + len, "\nDry Buffer %ld", j->drybuffer); + len += sprintf(buf + len, "\nRead Waits %ld", j->read_wait); + len += sprintf(buf + len, "\nWrite Waits %ld", j->write_wait); + len += sprintf(buf + len, "\nStatus Waits %ld", j->statuswait); + len += sprintf(buf + len, "\nStatus Wait Fails %ld", j->statuswaitfail); + len += sprintf(buf + len, "\nPControl Waits %ld", j->pcontrolwait); + len += sprintf(buf + len, "\nPControl Wait Fails %ld", j->pcontrolwaitfail); + len += sprintf(buf + len, "\nIs Control Ready Checks %ld", j->iscontrolready); + len += sprintf(buf + len, "\nIs Control Ready Check failures %ld", j->iscontrolreadyfail); + +#endif + len += sprintf(buf + len, "\n"); + } + } + return len; +} + +static int ixj_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int len = ixj_get_status_proc(page); + if (len <= off+count) *eof = 1; + *start = page + off; + len -= off; + if (len>count) len = count; + if (len<0) len = 0; + return len; +} + + +static void cleanup(void) +{ + int cnt; + IXJ *j; + + for (cnt = 0; cnt < IXJMAX; cnt++) { + j = get_ixj(cnt); + if(j != NULL && j->DSPbase) { + if (ixjdebug & 0x0002) + printk(KERN_INFO "IXJ: Deleting timer for /dev/phone%d\n", cnt); + del_timer(&j->timer); + if (j->cardtype == QTI_LINEJACK) { + j->pld_scrw.bits.daafsyncen = 0; /* Turn off DAA Frame Sync */ + + outb_p(j->pld_scrw.byte, j->XILINXbase); + j->pld_slicw.bits.rly1 = 0; + j->pld_slicw.bits.rly2 = 0; + j->pld_slicw.bits.rly3 = 0; + outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); + LED_SetState(0x0, j); + if (ixjdebug & 0x0002) + printk(KERN_INFO "IXJ: Releasing XILINX address for /dev/phone%d\n", cnt); + release_region(j->XILINXbase, 8); + } else if (j->cardtype == QTI_PHONEJACK_LITE || j->cardtype == QTI_PHONEJACK_PCI) { + if (ixjdebug & 0x0002) + printk(KERN_INFO "IXJ: Releasing XILINX address for /dev/phone%d\n", cnt); + release_region(j->XILINXbase, 4); + } + kfree(j->read_buffer); + kfree(j->write_buffer); + if (j->dev) + pnp_device_detach(j->dev); + if (ixjdebug & 0x0002) + printk(KERN_INFO "IXJ: Unregistering /dev/phone%d from LTAPI\n", cnt); + phone_unregister_device(&j->p); + if (ixjdebug & 0x0002) + printk(KERN_INFO "IXJ: Releasing DSP address for /dev/phone%d\n", cnt); + release_region(j->DSPbase, 16); +#ifdef IXJ_DYN_ALLOC + if (ixjdebug & 0x0002) + printk(KERN_INFO "IXJ: Freeing memory for /dev/phone%d\n", cnt); + kfree(j); + ixj[cnt] = NULL; +#endif + } + } + if (ixjdebug & 0x0002) + printk(KERN_INFO "IXJ: Removing /proc/ixj\n"); + remove_proc_entry ("ixj", NULL); +} + +/* Typedefs */ +typedef struct { + BYTE length; + DWORD bits; +} DATABLOCK; + +static void PCIEE_WriteBit(WORD wEEPROMAddress, BYTE lastLCC, BYTE byData) +{ + lastLCC = lastLCC & 0xfb; + lastLCC = lastLCC | (byData ? 4 : 0); + outb(lastLCC, wEEPROMAddress); /*set data out bit as appropriate */ + + mdelay(1); + lastLCC = lastLCC | 0x01; + outb(lastLCC, wEEPROMAddress); /*SK rising edge */ + + byData = byData << 1; + lastLCC = lastLCC & 0xfe; + mdelay(1); + outb(lastLCC, wEEPROMAddress); /*after delay, SK falling edge */ + +} + +static BYTE PCIEE_ReadBit(WORD wEEPROMAddress, BYTE lastLCC) +{ + mdelay(1); + lastLCC = lastLCC | 0x01; + outb(lastLCC, wEEPROMAddress); /*SK rising edge */ + + lastLCC = lastLCC & 0xfe; + mdelay(1); + outb(lastLCC, wEEPROMAddress); /*after delay, SK falling edge */ + + return ((inb(wEEPROMAddress) >> 3) & 1); +} + +static bool PCIEE_ReadWord(WORD wAddress, WORD wLoc, WORD * pwResult) +{ + BYTE lastLCC; + WORD wEEPROMAddress = wAddress + 3; + DWORD i; + BYTE byResult; + *pwResult = 0; + lastLCC = inb(wEEPROMAddress); + lastLCC = lastLCC | 0x02; + lastLCC = lastLCC & 0xfe; + outb(lastLCC, wEEPROMAddress); /* CS hi, SK lo */ + + mdelay(1); /* delay */ + + PCIEE_WriteBit(wEEPROMAddress, lastLCC, 1); + PCIEE_WriteBit(wEEPROMAddress, lastLCC, 1); + PCIEE_WriteBit(wEEPROMAddress, lastLCC, 0); + for (i = 0; i < 8; i++) { + PCIEE_WriteBit(wEEPROMAddress, lastLCC, wLoc & 0x80 ? 1 : 0); + wLoc <<= 1; + } + + for (i = 0; i < 16; i++) { + byResult = PCIEE_ReadBit(wEEPROMAddress, lastLCC); + *pwResult = (*pwResult << 1) | byResult; + } + + mdelay(1); /* another delay */ + + lastLCC = lastLCC & 0xfd; + outb(lastLCC, wEEPROMAddress); /* negate CS */ + + return 0; +} + +static DWORD PCIEE_GetSerialNumber(WORD wAddress) +{ + WORD wLo, wHi; + if (PCIEE_ReadWord(wAddress, 62, &wLo)) + return 0; + if (PCIEE_ReadWord(wAddress, 63, &wHi)) + return 0; + return (((DWORD) wHi << 16) | wLo); +} + +static int dspio[IXJMAX + 1] = +{ + 0, +}; +static int xio[IXJMAX + 1] = +{ + 0, +}; + +module_param_array(dspio, int, NULL, 0); +module_param_array(xio, int, NULL, 0); +MODULE_DESCRIPTION("Quicknet VoIP Telephony card module - www.quicknet.net"); +MODULE_AUTHOR("Ed Okerson "); +MODULE_LICENSE("GPL"); + +static void __exit ixj_exit(void) +{ + cleanup(); +} + +static IXJ *new_ixj(unsigned long port) +{ + IXJ *res; + if (!request_region(port, 16, "ixj DSP")) { + printk(KERN_INFO "ixj: can't get I/O address 0x%lx\n", port); + return NULL; + } + res = ixj_alloc(); + if (!res) { + release_region(port, 16); + printk(KERN_INFO "ixj: out of memory\n"); + return NULL; + } + res->DSPbase = port; + return res; +} + +static int __init ixj_probe_isapnp(int *cnt) +{ + int probe = 0; + int func = 0x110; + struct pnp_dev *dev = NULL, *old_dev = NULL; + + while (1) { + do { + IXJ *j; + int result; + + old_dev = dev; + dev = pnp_find_dev(NULL, ISAPNP_VENDOR('Q', 'T', 'I'), + ISAPNP_FUNCTION(func), old_dev); + if (!dev || !dev->card) + break; + result = pnp_device_attach(dev); + if (result < 0) { + printk("pnp attach failed %d \n", result); + break; + } + if (pnp_activate_dev(dev) < 0) { + printk("pnp activate failed (out of resources?)\n"); + pnp_device_detach(dev); + return -ENOMEM; + } + + if (!pnp_port_valid(dev, 0)) { + pnp_device_detach(dev); + return -ENODEV; + } + + j = new_ixj(pnp_port_start(dev, 0)); + if (!j) + break; + + if (func != 0x110) + j->XILINXbase = pnp_port_start(dev, 1); /* get real port */ + + switch (func) { + case (0x110): + j->cardtype = QTI_PHONEJACK; + break; + case (0x310): + j->cardtype = QTI_LINEJACK; + break; + case (0x410): + j->cardtype = QTI_PHONEJACK_LITE; + break; + } + j->board = *cnt; + probe = ixj_selfprobe(j); + if(!probe) { + j->serial = dev->card->serial; + j->dev = dev; + switch (func) { + case 0x110: + printk(KERN_INFO "ixj: found Internet PhoneJACK at 0x%x\n", j->DSPbase); + break; + case 0x310: + printk(KERN_INFO "ixj: found Internet LineJACK at 0x%x\n", j->DSPbase); + break; + case 0x410: + printk(KERN_INFO "ixj: found Internet PhoneJACK Lite at 0x%x\n", j->DSPbase); + break; + } + } + ++*cnt; + } while (dev); + if (func == 0x410) + break; + if (func == 0x310) + func = 0x410; + if (func == 0x110) + func = 0x310; + dev = NULL; + } + return probe; +} + +static int __init ixj_probe_isa(int *cnt) +{ + int i, probe; + + /* Use passed parameters for older kernels without PnP */ + for (i = 0; i < IXJMAX; i++) { + if (dspio[i]) { + IXJ *j = new_ixj(dspio[i]); + + if (!j) + break; + + j->XILINXbase = xio[i]; + j->cardtype = 0; + + j->board = *cnt; + probe = ixj_selfprobe(j); + j->dev = NULL; + ++*cnt; + } + } + return 0; +} + +static int __init ixj_probe_pci(int *cnt) +{ + struct pci_dev *pci = NULL; + int i, probe = 0; + IXJ *j = NULL; + + for (i = 0; i < IXJMAX - *cnt; i++) { + pci = pci_get_device(PCI_VENDOR_ID_QUICKNET, + PCI_DEVICE_ID_QUICKNET_XJ, pci); + if (!pci) + break; + + if (pci_enable_device(pci)) + break; + j = new_ixj(pci_resource_start(pci, 0)); + if (!j) + break; + + j->serial = (PCIEE_GetSerialNumber)pci_resource_start(pci, 2); + j->XILINXbase = j->DSPbase + 0x10; + j->cardtype = QTI_PHONEJACK_PCI; + j->board = *cnt; + probe = ixj_selfprobe(j); + if (!probe) + printk(KERN_INFO "ixj: found Internet PhoneJACK PCI at 0x%x\n", j->DSPbase); + ++*cnt; + } + pci_dev_put(pci); + return probe; +} + +static int __init ixj_init(void) +{ + int cnt = 0; + int probe = 0; + + cnt = 0; + + /* These might be no-ops, see above. */ + if ((probe = ixj_probe_isapnp(&cnt)) < 0) { + return probe; + } + if ((probe = ixj_probe_isa(&cnt)) < 0) { + return probe; + } + if ((probe = ixj_probe_pci(&cnt)) < 0) { + return probe; + } + printk(KERN_INFO "ixj driver initialized.\n"); + create_proc_read_entry ("ixj", 0, NULL, ixj_read_proc, NULL); + return probe; +} + +module_init(ixj_init); +module_exit(ixj_exit); + +static void DAA_Coeff_US(IXJ *j) +{ + int i; + + j->daa_country = DAA_US; + /*----------------------------------------------- */ + /* CAO */ + for (i = 0; i < ALISDAA_CALLERID_SIZE; i++) { + j->m_DAAShadowRegs.CAO_REGS.CAO.CallerID[i] = 0; + } + +/* Bytes for IM-filter part 1 (04): 0E,32,E2,2F,C2,5A,C0,00 */ + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7] = 0x03; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[6] = 0x4B; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[5] = 0x5D; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[4] = 0xCD; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[3] = 0x24; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[2] = 0xC5; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[1] = 0xA0; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[0] = 0x00; +/* Bytes for IM-filter part 2 (05): 72,85,00,0E,2B,3A,D0,08 */ + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[7] = 0x71; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[6] = 0x1A; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[5] = 0x00; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[4] = 0x0A; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[3] = 0xB5; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[2] = 0x33; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[1] = 0xE0; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[0] = 0x08; +/* Bytes for FRX-filter (08): 03,8F,48,F2,8F,48,70,08 */ + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[7] = 0x05; + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[6] = 0xA3; + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[5] = 0x72; + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[4] = 0x34; + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[3] = 0x3F; + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[2] = 0x3B; + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[1] = 0x30; + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[0] = 0x08; +/* Bytes for FRR-filter (07): 04,8F,38,7F,9B,EA,B0,08 */ + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[7] = 0x05; + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[6] = 0x87; + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[5] = 0xF9; + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[4] = 0x3E; + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[3] = 0x32; + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[2] = 0xDA; + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[1] = 0xB0; + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[0] = 0x08; +/* Bytes for AX-filter (0A): 16,55,DD,CA */ + j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[3] = 0x41; + j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[2] = 0xB5; + j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[1] = 0xDD; + j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[0] = 0xCA; +/* Bytes for AR-filter (09): 52,D3,11,42 */ + j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[3] = 0x25; + j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[2] = 0xC7; + j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[1] = 0x10; + j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[0] = 0xD6; +/* Bytes for TH-filter part 1 (00): 00,42,48,81,B3,80,00,98 */ + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[7] = 0x00; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[6] = 0x42; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[5] = 0x48; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[4] = 0x81; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[3] = 0xA5; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[2] = 0x80; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[1] = 0x00; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[0] = 0x98; +/* Bytes for TH-filter part 2 (01): 02,F2,33,A0,68,AB,8A,AD */ + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[7] = 0x02; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[6] = 0xA2; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[5] = 0x2B; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[4] = 0xB0; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[3] = 0xE8; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[2] = 0xAB; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[1] = 0x81; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[0] = 0xCC; +/* Bytes for TH-filter part 3 (02): 00,88,DA,54,A4,BA,2D,BB */ + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[7] = 0x00; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[6] = 0x88; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[5] = 0xD2; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[4] = 0x24; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[3] = 0xBA; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[2] = 0xA9; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[1] = 0x3B; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[0] = 0xA6; +/* ; (10K, 0.68uF) */ + /* */ + /* Bytes for Ringing part 1 (03):1B,3B,9B,BA,D4,1C,B3,23 */ + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[7] = 0x1B; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[6] = 0x3C; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[5] = 0x93; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[4] = 0x3A; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[3] = 0x22; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[2] = 0x12; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[1] = 0xA3; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[0] = 0x23; + /* Bytes for Ringing part 2 (06):13,42,A6,BA,D4,73,CA,D5 */ + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[7] = 0x12; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[6] = 0xA2; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[5] = 0xA6; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[4] = 0xBA; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[3] = 0x22; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[2] = 0x7A; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[1] = 0x0A; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[0] = 0xD5; + + /* Levelmetering Ringing (0D):B2,45,0F,8E */ + j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[3] = 0xAA; + j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[2] = 0x35; + j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[1] = 0x0F; + j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[0] = 0x8E; + + /* Bytes for Ringing part 1 (03):1B,3B,9B,BA,D4,1C,B3,23 */ +/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[7] = 0x1C; */ +/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[6] = 0xB3; */ +/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[5] = 0xAB; */ +/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[4] = 0xAB; */ +/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[3] = 0x54; */ +/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[2] = 0x2D; */ +/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[1] = 0x62; */ +/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[0] = 0x2D; */ + /* Bytes for Ringing part 2 (06):13,42,A6,BA,D4,73,CA,D5 */ +/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[7] = 0x2D; */ +/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[6] = 0x62; */ +/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[5] = 0xA6; */ +/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[4] = 0xBB; */ +/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[3] = 0x2A; */ +/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[2] = 0x7D; */ +/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[1] = 0x0A; */ +/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[0] = 0xD4; */ +/* */ + /* Levelmetering Ringing (0D):B2,45,0F,8E */ +/* j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[3] = 0xAA; */ +/* j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[2] = 0x05; */ +/* j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[1] = 0x0F; */ +/* j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[0] = 0x8E; */ + + /* Caller ID 1st Tone (0E):CA,0E,CA,09,99,99,99,99 */ + j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[7] = 0xCA; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[6] = 0x0E; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[5] = 0xCA; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[4] = 0x09; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[3] = 0x99; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[2] = 0x99; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[1] = 0x99; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[0] = 0x99; +/* Caller ID 2nd Tone (0F):FD,B5,BA,07,DA,00,00,00 */ + j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[7] = 0xFD; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[6] = 0xB5; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[5] = 0xBA; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[4] = 0x07; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[3] = 0xDA; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[2] = 0x00; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[1] = 0x00; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[0] = 0x00; +/* */ + /* ;CR Registers */ + /* Config. Reg. 0 (filters) (cr0):FE ; CLK gen. by crystal */ + j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFF; +/* Config. Reg. 1 (dialing) (cr1):05 */ + j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.reg = 0x05; +/* Config. Reg. 2 (caller ID) (cr2):04 */ + j->m_DAAShadowRegs.SOP_REGS.SOP.cr2.reg = 0x04; +/* Config. Reg. 3 (testloops) (cr3):03 ; SEL Bit==0, HP-disabled */ + j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg = 0x00; +/* Config. Reg. 4 (analog gain) (cr4):02 */ + j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = 0x02; + /* Config. Reg. 5 (Version) (cr5):02 */ + /* Config. Reg. 6 (Reserved) (cr6):00 */ + /* Config. Reg. 7 (Reserved) (cr7):00 */ + /* */ + /* ;xr Registers */ + /* Ext. Reg. 0 (Interrupt Reg.) (xr0):02 */ + + j->m_DAAShadowRegs.XOP_xr0_W.reg = 0x02; /* SO_1 set to '1' because it is inverted. */ + /* Ext. Reg. 1 (Interrupt enable) (xr1):3C Cadence, RING, Caller ID, VDD_OK */ + + j->m_DAAShadowRegs.XOP_REGS.XOP.xr1.reg = 0x3C; +/* Ext. Reg. 2 (Cadence Time Out) (xr2):7D */ + j->m_DAAShadowRegs.XOP_REGS.XOP.xr2.reg = 0x7D; +/* Ext. Reg. 3 (DC Char) (xr3):32 ; B-Filter Off == 1 */ + j->m_DAAShadowRegs.XOP_REGS.XOP.xr3.reg = 0x3B; /*0x32; */ + /* Ext. Reg. 4 (Cadence) (xr4):00 */ + + j->m_DAAShadowRegs.XOP_REGS.XOP.xr4.reg = 0x00; +/* Ext. Reg. 5 (Ring timer) (xr5):22 */ + j->m_DAAShadowRegs.XOP_REGS.XOP.xr5.reg = 0x22; +/* Ext. Reg. 6 (Power State) (xr6):00 */ + j->m_DAAShadowRegs.XOP_xr6_W.reg = 0x00; +/* Ext. Reg. 7 (Vdd) (xr7):40 */ + j->m_DAAShadowRegs.XOP_REGS.XOP.xr7.reg = 0x40; /* 0x40 ??? Should it be 0x00? */ + /* */ + /* DTMF Tone 1 (0B): 11,B3,5A,2C ; 697 Hz */ + /* 12,33,5A,C3 ; 770 Hz */ + /* 13,3C,5B,32 ; 852 Hz */ + /* 1D,1B,5C,CC ; 941 Hz */ + + j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[3] = 0x11; + j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[2] = 0xB3; + j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[1] = 0x5A; + j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[0] = 0x2C; +/* DTMF Tone 2 (0C): 32,32,52,B3 ; 1209 Hz */ + /* EC,1D,52,22 ; 1336 Hz */ + /* AA,AC,51,D2 ; 1477 Hz */ + /* 9B,3B,51,25 ; 1633 Hz */ + j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[3] = 0x32; + j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[2] = 0x32; + j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[1] = 0x52; + j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[0] = 0xB3; +} + +static void DAA_Coeff_UK(IXJ *j) +{ + int i; + + j->daa_country = DAA_UK; + /*----------------------------------------------- */ + /* CAO */ + for (i = 0; i < ALISDAA_CALLERID_SIZE; i++) { + j->m_DAAShadowRegs.CAO_REGS.CAO.CallerID[i] = 0; + } + +/* Bytes for IM-filter part 1 (04): 00,C2,BB,A8,CB,81,A0,00 */ + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7] = 0x00; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[6] = 0xC2; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[5] = 0xBB; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[4] = 0xA8; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[3] = 0xCB; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[2] = 0x81; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[1] = 0xA0; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[0] = 0x00; +/* Bytes for IM-filter part 2 (05): 40,00,00,0A,A4,33,E0,08 */ + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[7] = 0x40; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[6] = 0x00; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[5] = 0x00; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[4] = 0x0A; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[3] = 0xA4; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[2] = 0x33; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[1] = 0xE0; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[0] = 0x08; +/* Bytes for FRX-filter (08): 07,9B,ED,24,B2,A2,A0,08 */ + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[7] = 0x07; + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[6] = 0x9B; + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[5] = 0xED; + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[4] = 0x24; + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[3] = 0xB2; + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[2] = 0xA2; + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[1] = 0xA0; + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[0] = 0x08; +/* Bytes for FRR-filter (07): 0F,92,F2,B2,87,D2,30,08 */ + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[7] = 0x0F; + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[6] = 0x92; + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[5] = 0xF2; + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[4] = 0xB2; + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[3] = 0x87; + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[2] = 0xD2; + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[1] = 0x30; + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[0] = 0x08; +/* Bytes for AX-filter (0A): 1B,A5,DD,CA */ + j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[3] = 0x1B; + j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[2] = 0xA5; + j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[1] = 0xDD; + j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[0] = 0xCA; +/* Bytes for AR-filter (09): E2,27,10,D6 */ + j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[3] = 0xE2; + j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[2] = 0x27; + j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[1] = 0x10; + j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[0] = 0xD6; +/* Bytes for TH-filter part 1 (00): 80,2D,38,8B,D0,00,00,98 */ + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[7] = 0x80; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[6] = 0x2D; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[5] = 0x38; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[4] = 0x8B; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[3] = 0xD0; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[2] = 0x00; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[1] = 0x00; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[0] = 0x98; +/* Bytes for TH-filter part 2 (01): 02,5A,53,F0,0B,5F,84,D4 */ + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[7] = 0x02; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[6] = 0x5A; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[5] = 0x53; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[4] = 0xF0; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[3] = 0x0B; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[2] = 0x5F; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[1] = 0x84; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[0] = 0xD4; +/* Bytes for TH-filter part 3 (02): 00,88,6A,A4,8F,52,F5,32 */ + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[7] = 0x00; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[6] = 0x88; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[5] = 0x6A; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[4] = 0xA4; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[3] = 0x8F; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[2] = 0x52; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[1] = 0xF5; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[0] = 0x32; +/* ; idle */ + /* Bytes for Ringing part 1 (03):1B,3C,93,3A,22,12,A3,23 */ + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[7] = 0x1B; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[6] = 0x3C; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[5] = 0x93; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[4] = 0x3A; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[3] = 0x22; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[2] = 0x12; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[1] = 0xA3; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[0] = 0x23; +/* Bytes for Ringing part 2 (06):12,A2,A6,BA,22,7A,0A,D5 */ + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[7] = 0x12; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[6] = 0xA2; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[5] = 0xA6; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[4] = 0xBA; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[3] = 0x22; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[2] = 0x7A; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[1] = 0x0A; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[0] = 0xD5; +/* Levelmetering Ringing (0D):AA,35,0F,8E ; 25Hz 30V less possible? */ + j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[3] = 0xAA; + j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[2] = 0x35; + j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[1] = 0x0F; + j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[0] = 0x8E; +/* Caller ID 1st Tone (0E):CA,0E,CA,09,99,99,99,99 */ + j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[7] = 0xCA; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[6] = 0x0E; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[5] = 0xCA; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[4] = 0x09; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[3] = 0x99; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[2] = 0x99; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[1] = 0x99; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[0] = 0x99; +/* Caller ID 2nd Tone (0F):FD,B5,BA,07,DA,00,00,00 */ + j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[7] = 0xFD; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[6] = 0xB5; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[5] = 0xBA; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[4] = 0x07; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[3] = 0xDA; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[2] = 0x00; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[1] = 0x00; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[0] = 0x00; +/* ;CR Registers */ + /* Config. Reg. 0 (filters) (cr0):FF */ + j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFF; +/* Config. Reg. 1 (dialing) (cr1):05 */ + j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.reg = 0x05; +/* Config. Reg. 2 (caller ID) (cr2):04 */ + j->m_DAAShadowRegs.SOP_REGS.SOP.cr2.reg = 0x04; +/* Config. Reg. 3 (testloops) (cr3):00 ; */ + j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg = 0x00; +/* Config. Reg. 4 (analog gain) (cr4):02 */ + j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = 0x02; + /* Config. Reg. 5 (Version) (cr5):02 */ + /* Config. Reg. 6 (Reserved) (cr6):00 */ + /* Config. Reg. 7 (Reserved) (cr7):00 */ + /* ;xr Registers */ + /* Ext. Reg. 0 (Interrupt Reg.) (xr0):02 */ + + j->m_DAAShadowRegs.XOP_xr0_W.reg = 0x02; /* SO_1 set to '1' because it is inverted. */ + /* Ext. Reg. 1 (Interrupt enable) (xr1):1C */ + + j->m_DAAShadowRegs.XOP_REGS.XOP.xr1.reg = 0x1C; /* RING, Caller ID, VDD_OK */ + /* Ext. Reg. 2 (Cadence Time Out) (xr2):7D */ + + j->m_DAAShadowRegs.XOP_REGS.XOP.xr2.reg = 0x7D; +/* Ext. Reg. 3 (DC Char) (xr3):36 ; */ + j->m_DAAShadowRegs.XOP_REGS.XOP.xr3.reg = 0x36; +/* Ext. Reg. 4 (Cadence) (xr4):00 */ + j->m_DAAShadowRegs.XOP_REGS.XOP.xr4.reg = 0x00; +/* Ext. Reg. 5 (Ring timer) (xr5):22 */ + j->m_DAAShadowRegs.XOP_REGS.XOP.xr5.reg = 0x22; +/* Ext. Reg. 6 (Power State) (xr6):00 */ + j->m_DAAShadowRegs.XOP_xr6_W.reg = 0x00; +/* Ext. Reg. 7 (Vdd) (xr7):46 */ + j->m_DAAShadowRegs.XOP_REGS.XOP.xr7.reg = 0x46; /* 0x46 ??? Should it be 0x00? */ + /* DTMF Tone 1 (0B): 11,B3,5A,2C ; 697 Hz */ + /* 12,33,5A,C3 ; 770 Hz */ + /* 13,3C,5B,32 ; 852 Hz */ + /* 1D,1B,5C,CC ; 941 Hz */ + + j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[3] = 0x11; + j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[2] = 0xB3; + j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[1] = 0x5A; + j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[0] = 0x2C; +/* DTMF Tone 2 (0C): 32,32,52,B3 ; 1209 Hz */ + /* EC,1D,52,22 ; 1336 Hz */ + /* AA,AC,51,D2 ; 1477 Hz */ + /* 9B,3B,51,25 ; 1633 Hz */ + j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[3] = 0x32; + j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[2] = 0x32; + j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[1] = 0x52; + j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[0] = 0xB3; +} + + +static void DAA_Coeff_France(IXJ *j) +{ + int i; + + j->daa_country = DAA_FRANCE; + /*----------------------------------------------- */ + /* CAO */ + for (i = 0; i < ALISDAA_CALLERID_SIZE; i++) { + j->m_DAAShadowRegs.CAO_REGS.CAO.CallerID[i] = 0; + } + +/* Bytes for IM-filter part 1 (04): 02,A2,43,2C,22,AF,A0,00 */ + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7] = 0x02; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[6] = 0xA2; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[5] = 0x43; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[4] = 0x2C; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[3] = 0x22; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[2] = 0xAF; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[1] = 0xA0; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[0] = 0x00; +/* Bytes for IM-filter part 2 (05): 67,CE,00,0C,22,33,E0,08 */ + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[7] = 0x67; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[6] = 0xCE; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[5] = 0x00; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[4] = 0x2C; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[3] = 0x22; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[2] = 0x33; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[1] = 0xE0; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[0] = 0x08; +/* Bytes for FRX-filter (08): 07,9A,28,F6,23,4A,B0,08 */ + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[7] = 0x07; + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[6] = 0x9A; + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[5] = 0x28; + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[4] = 0xF6; + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[3] = 0x23; + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[2] = 0x4A; + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[1] = 0xB0; + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[0] = 0x08; +/* Bytes for FRR-filter (07): 03,8F,F9,2F,9E,FA,20,08 */ + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[7] = 0x03; + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[6] = 0x8F; + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[5] = 0xF9; + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[4] = 0x2F; + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[3] = 0x9E; + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[2] = 0xFA; + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[1] = 0x20; + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[0] = 0x08; +/* Bytes for AX-filter (0A): 16,B5,DD,CA */ + j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[3] = 0x16; + j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[2] = 0xB5; + j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[1] = 0xDD; + j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[0] = 0xCA; +/* Bytes for AR-filter (09): 52,C7,10,D6 */ + j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[3] = 0xE2; + j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[2] = 0xC7; + j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[1] = 0x10; + j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[0] = 0xD6; +/* Bytes for TH-filter part 1 (00): 00,42,48,81,A6,80,00,98 */ + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[7] = 0x00; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[6] = 0x42; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[5] = 0x48; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[4] = 0x81; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[3] = 0xA6; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[2] = 0x80; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[1] = 0x00; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[0] = 0x98; +/* Bytes for TH-filter part 2 (01): 02,AC,2A,30,78,AC,8A,2C */ + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[7] = 0x02; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[6] = 0xAC; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[5] = 0x2A; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[4] = 0x30; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[3] = 0x78; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[2] = 0xAC; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[1] = 0x8A; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[0] = 0x2C; +/* Bytes for TH-filter part 3 (02): 00,88,DA,A5,22,BA,2C,45 */ + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[7] = 0x00; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[6] = 0x88; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[5] = 0xDA; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[4] = 0xA5; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[3] = 0x22; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[2] = 0xBA; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[1] = 0x2C; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[0] = 0x45; +/* ; idle */ + /* Bytes for Ringing part 1 (03):1B,3C,93,3A,22,12,A3,23 */ + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[7] = 0x1B; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[6] = 0x3C; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[5] = 0x93; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[4] = 0x3A; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[3] = 0x22; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[2] = 0x12; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[1] = 0xA3; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[0] = 0x23; +/* Bytes for Ringing part 2 (06):12,A2,A6,BA,22,7A,0A,D5 */ + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[7] = 0x12; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[6] = 0xA2; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[5] = 0xA6; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[4] = 0xBA; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[3] = 0x22; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[2] = 0x7A; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[1] = 0x0A; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[0] = 0xD5; +/* Levelmetering Ringing (0D):32,45,B5,84 ; 50Hz 20V */ + j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[3] = 0x32; + j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[2] = 0x45; + j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[1] = 0xB5; + j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[0] = 0x84; +/* Caller ID 1st Tone (0E):CA,0E,CA,09,99,99,99,99 */ + j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[7] = 0xCA; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[6] = 0x0E; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[5] = 0xCA; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[4] = 0x09; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[3] = 0x99; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[2] = 0x99; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[1] = 0x99; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[0] = 0x99; +/* Caller ID 2nd Tone (0F):FD,B5,BA,07,DA,00,00,00 */ + j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[7] = 0xFD; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[6] = 0xB5; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[5] = 0xBA; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[4] = 0x07; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[3] = 0xDA; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[2] = 0x00; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[1] = 0x00; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[0] = 0x00; +/* ;CR Registers */ + /* Config. Reg. 0 (filters) (cr0):FF */ + j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFF; +/* Config. Reg. 1 (dialing) (cr1):05 */ + j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.reg = 0x05; +/* Config. Reg. 2 (caller ID) (cr2):04 */ + j->m_DAAShadowRegs.SOP_REGS.SOP.cr2.reg = 0x04; +/* Config. Reg. 3 (testloops) (cr3):00 ; */ + j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg = 0x00; +/* Config. Reg. 4 (analog gain) (cr4):02 */ + j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = 0x02; + /* Config. Reg. 5 (Version) (cr5):02 */ + /* Config. Reg. 6 (Reserved) (cr6):00 */ + /* Config. Reg. 7 (Reserved) (cr7):00 */ + /* ;xr Registers */ + /* Ext. Reg. 0 (Interrupt Reg.) (xr0):02 */ + + j->m_DAAShadowRegs.XOP_xr0_W.reg = 0x02; /* SO_1 set to '1' because it is inverted. */ + /* Ext. Reg. 1 (Interrupt enable) (xr1):1C */ + + j->m_DAAShadowRegs.XOP_REGS.XOP.xr1.reg = 0x1C; /* RING, Caller ID, VDD_OK */ + /* Ext. Reg. 2 (Cadence Time Out) (xr2):7D */ + + j->m_DAAShadowRegs.XOP_REGS.XOP.xr2.reg = 0x7D; +/* Ext. Reg. 3 (DC Char) (xr3):36 ; */ + j->m_DAAShadowRegs.XOP_REGS.XOP.xr3.reg = 0x36; +/* Ext. Reg. 4 (Cadence) (xr4):00 */ + j->m_DAAShadowRegs.XOP_REGS.XOP.xr4.reg = 0x00; +/* Ext. Reg. 5 (Ring timer) (xr5):22 */ + j->m_DAAShadowRegs.XOP_REGS.XOP.xr5.reg = 0x22; +/* Ext. Reg. 6 (Power State) (xr6):00 */ + j->m_DAAShadowRegs.XOP_xr6_W.reg = 0x00; +/* Ext. Reg. 7 (Vdd) (xr7):46 */ + j->m_DAAShadowRegs.XOP_REGS.XOP.xr7.reg = 0x46; /* 0x46 ??? Should it be 0x00? */ + /* DTMF Tone 1 (0B): 11,B3,5A,2C ; 697 Hz */ + /* 12,33,5A,C3 ; 770 Hz */ + /* 13,3C,5B,32 ; 852 Hz */ + /* 1D,1B,5C,CC ; 941 Hz */ + + j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[3] = 0x11; + j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[2] = 0xB3; + j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[1] = 0x5A; + j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[0] = 0x2C; +/* DTMF Tone 2 (0C): 32,32,52,B3 ; 1209 Hz */ + /* EC,1D,52,22 ; 1336 Hz */ + /* AA,AC,51,D2 ; 1477 Hz */ + /* 9B,3B,51,25 ; 1633 Hz */ + j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[3] = 0x32; + j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[2] = 0x32; + j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[1] = 0x52; + j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[0] = 0xB3; +} + + +static void DAA_Coeff_Germany(IXJ *j) +{ + int i; + + j->daa_country = DAA_GERMANY; + /*----------------------------------------------- */ + /* CAO */ + for (i = 0; i < ALISDAA_CALLERID_SIZE; i++) { + j->m_DAAShadowRegs.CAO_REGS.CAO.CallerID[i] = 0; + } + +/* Bytes for IM-filter part 1 (04): 00,CE,BB,B8,D2,81,B0,00 */ + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7] = 0x00; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[6] = 0xCE; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[5] = 0xBB; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[4] = 0xB8; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[3] = 0xD2; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[2] = 0x81; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[1] = 0xB0; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[0] = 0x00; +/* Bytes for IM-filter part 2 (05): 45,8F,00,0C,D2,3A,D0,08 */ + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[7] = 0x45; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[6] = 0x8F; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[5] = 0x00; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[4] = 0x0C; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[3] = 0xD2; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[2] = 0x3A; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[1] = 0xD0; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[0] = 0x08; +/* Bytes for FRX-filter (08): 07,AA,E2,34,24,89,20,08 */ + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[7] = 0x07; + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[6] = 0xAA; + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[5] = 0xE2; + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[4] = 0x34; + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[3] = 0x24; + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[2] = 0x89; + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[1] = 0x20; + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[0] = 0x08; +/* Bytes for FRR-filter (07): 02,87,FA,37,9A,CA,B0,08 */ + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[7] = 0x02; + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[6] = 0x87; + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[5] = 0xFA; + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[4] = 0x37; + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[3] = 0x9A; + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[2] = 0xCA; + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[1] = 0xB0; + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[0] = 0x08; +/* Bytes for AX-filter (0A): 72,D5,DD,CA */ + j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[3] = 0x72; + j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[2] = 0xD5; + j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[1] = 0xDD; + j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[0] = 0xCA; +/* Bytes for AR-filter (09): 72,42,13,4B */ + j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[3] = 0x72; + j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[2] = 0x42; + j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[1] = 0x13; + j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[0] = 0x4B; +/* Bytes for TH-filter part 1 (00): 80,52,48,81,AD,80,00,98 */ + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[7] = 0x80; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[6] = 0x52; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[5] = 0x48; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[4] = 0x81; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[3] = 0xAD; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[2] = 0x80; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[1] = 0x00; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[0] = 0x98; +/* Bytes for TH-filter part 2 (01): 02,42,5A,20,E8,1A,81,27 */ + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[7] = 0x02; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[6] = 0x42; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[5] = 0x5A; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[4] = 0x20; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[3] = 0xE8; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[2] = 0x1A; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[1] = 0x81; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[0] = 0x27; +/* Bytes for TH-filter part 3 (02): 00,88,63,26,BD,4B,A3,C2 */ + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[7] = 0x00; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[6] = 0x88; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[5] = 0x63; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[4] = 0x26; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[3] = 0xBD; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[2] = 0x4B; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[1] = 0xA3; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[0] = 0xC2; +/* ; (10K, 0.68uF) */ + /* Bytes for Ringing part 1 (03):1B,3B,9B,BA,D4,1C,B3,23 */ + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[7] = 0x1B; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[6] = 0x3B; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[5] = 0x9B; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[4] = 0xBA; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[3] = 0xD4; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[2] = 0x1C; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[1] = 0xB3; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[0] = 0x23; +/* Bytes for Ringing part 2 (06):13,42,A6,BA,D4,73,CA,D5 */ + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[7] = 0x13; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[6] = 0x42; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[5] = 0xA6; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[4] = 0xBA; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[3] = 0xD4; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[2] = 0x73; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[1] = 0xCA; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[0] = 0xD5; +/* Levelmetering Ringing (0D):B2,45,0F,8E */ + j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[3] = 0xB2; + j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[2] = 0x45; + j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[1] = 0x0F; + j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[0] = 0x8E; +/* Caller ID 1st Tone (0E):CA,0E,CA,09,99,99,99,99 */ + j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[7] = 0xCA; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[6] = 0x0E; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[5] = 0xCA; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[4] = 0x09; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[3] = 0x99; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[2] = 0x99; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[1] = 0x99; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[0] = 0x99; +/* Caller ID 2nd Tone (0F):FD,B5,BA,07,DA,00,00,00 */ + j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[7] = 0xFD; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[6] = 0xB5; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[5] = 0xBA; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[4] = 0x07; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[3] = 0xDA; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[2] = 0x00; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[1] = 0x00; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[0] = 0x00; +/* ;CR Registers */ + /* Config. Reg. 0 (filters) (cr0):FF ; all Filters enabled, CLK from ext. source */ + j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFF; +/* Config. Reg. 1 (dialing) (cr1):05 ; Manual Ring, Ring metering enabled */ + j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.reg = 0x05; +/* Config. Reg. 2 (caller ID) (cr2):04 ; Analog Gain 0dB, FSC internal */ + j->m_DAAShadowRegs.SOP_REGS.SOP.cr2.reg = 0x04; +/* Config. Reg. 3 (testloops) (cr3):00 ; SEL Bit==0, HP-enabled */ + j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg = 0x00; +/* Config. Reg. 4 (analog gain) (cr4):02 */ + j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = 0x02; + /* Config. Reg. 5 (Version) (cr5):02 */ + /* Config. Reg. 6 (Reserved) (cr6):00 */ + /* Config. Reg. 7 (Reserved) (cr7):00 */ + /* ;xr Registers */ + /* Ext. Reg. 0 (Interrupt Reg.) (xr0):02 */ + + j->m_DAAShadowRegs.XOP_xr0_W.reg = 0x02; /* SO_1 set to '1' because it is inverted. */ + /* Ext. Reg. 1 (Interrupt enable) (xr1):1C ; Ring, CID, VDDOK Interrupts enabled */ + + j->m_DAAShadowRegs.XOP_REGS.XOP.xr1.reg = 0x1C; /* RING, Caller ID, VDD_OK */ + /* Ext. Reg. 2 (Cadence Time Out) (xr2):7D */ + + j->m_DAAShadowRegs.XOP_REGS.XOP.xr2.reg = 0x7D; +/* Ext. Reg. 3 (DC Char) (xr3):32 ; B-Filter Off==1, U0=3.5V, R=200Ohm */ + j->m_DAAShadowRegs.XOP_REGS.XOP.xr3.reg = 0x32; +/* Ext. Reg. 4 (Cadence) (xr4):00 */ + j->m_DAAShadowRegs.XOP_REGS.XOP.xr4.reg = 0x00; +/* Ext. Reg. 5 (Ring timer) (xr5):22 */ + j->m_DAAShadowRegs.XOP_REGS.XOP.xr5.reg = 0x22; +/* Ext. Reg. 6 (Power State) (xr6):00 */ + j->m_DAAShadowRegs.XOP_xr6_W.reg = 0x00; +/* Ext. Reg. 7 (Vdd) (xr7):40 ; VDD=4.25 V */ + j->m_DAAShadowRegs.XOP_REGS.XOP.xr7.reg = 0x40; /* 0x40 ??? Should it be 0x00? */ + /* DTMF Tone 1 (0B): 11,B3,5A,2C ; 697 Hz */ + /* 12,33,5A,C3 ; 770 Hz */ + /* 13,3C,5B,32 ; 852 Hz */ + /* 1D,1B,5C,CC ; 941 Hz */ + + j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[3] = 0x11; + j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[2] = 0xB3; + j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[1] = 0x5A; + j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[0] = 0x2C; +/* DTMF Tone 2 (0C): 32,32,52,B3 ; 1209 Hz */ + /* EC,1D,52,22 ; 1336 Hz */ + /* AA,AC,51,D2 ; 1477 Hz */ + /* 9B,3B,51,25 ; 1633 Hz */ + j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[3] = 0x32; + j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[2] = 0x32; + j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[1] = 0x52; + j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[0] = 0xB3; +} + + +static void DAA_Coeff_Australia(IXJ *j) +{ + int i; + + j->daa_country = DAA_AUSTRALIA; + /*----------------------------------------------- */ + /* CAO */ + for (i = 0; i < ALISDAA_CALLERID_SIZE; i++) { + j->m_DAAShadowRegs.CAO_REGS.CAO.CallerID[i] = 0; + } + +/* Bytes for IM-filter part 1 (04): 00,A3,AA,28,B3,82,D0,00 */ + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7] = 0x00; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[6] = 0xA3; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[5] = 0xAA; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[4] = 0x28; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[3] = 0xB3; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[2] = 0x82; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[1] = 0xD0; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[0] = 0x00; +/* Bytes for IM-filter part 2 (05): 70,96,00,09,32,6B,C0,08 */ + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[7] = 0x70; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[6] = 0x96; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[5] = 0x00; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[4] = 0x09; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[3] = 0x32; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[2] = 0x6B; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[1] = 0xC0; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[0] = 0x08; +/* Bytes for FRX-filter (08): 07,96,E2,34,32,9B,30,08 */ + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[7] = 0x07; + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[6] = 0x96; + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[5] = 0xE2; + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[4] = 0x34; + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[3] = 0x32; + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[2] = 0x9B; + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[1] = 0x30; + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[0] = 0x08; +/* Bytes for FRR-filter (07): 0F,9A,E9,2F,22,CC,A0,08 */ + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[7] = 0x0F; + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[6] = 0x9A; + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[5] = 0xE9; + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[4] = 0x2F; + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[3] = 0x22; + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[2] = 0xCC; + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[1] = 0xA0; + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[0] = 0x08; +/* Bytes for AX-filter (0A): CB,45,DD,CA */ + j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[3] = 0xCB; + j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[2] = 0x45; + j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[1] = 0xDD; + j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[0] = 0xCA; +/* Bytes for AR-filter (09): 1B,67,10,D6 */ + j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[3] = 0x1B; + j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[2] = 0x67; + j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[1] = 0x10; + j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[0] = 0xD6; +/* Bytes for TH-filter part 1 (00): 80,52,48,81,AF,80,00,98 */ + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[7] = 0x80; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[6] = 0x52; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[5] = 0x48; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[4] = 0x81; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[3] = 0xAF; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[2] = 0x80; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[1] = 0x00; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[0] = 0x98; +/* Bytes for TH-filter part 2 (01): 02,DB,52,B0,38,01,82,AC */ + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[7] = 0x02; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[6] = 0xDB; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[5] = 0x52; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[4] = 0xB0; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[3] = 0x38; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[2] = 0x01; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[1] = 0x82; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[0] = 0xAC; +/* Bytes for TH-filter part 3 (02): 00,88,4A,3E,2C,3B,24,46 */ + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[7] = 0x00; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[6] = 0x88; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[5] = 0x4A; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[4] = 0x3E; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[3] = 0x2C; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[2] = 0x3B; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[1] = 0x24; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[0] = 0x46; +/* ; idle */ + /* Bytes for Ringing part 1 (03):1B,3C,93,3A,22,12,A3,23 */ + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[7] = 0x1B; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[6] = 0x3C; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[5] = 0x93; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[4] = 0x3A; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[3] = 0x22; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[2] = 0x12; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[1] = 0xA3; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[0] = 0x23; +/* Bytes for Ringing part 2 (06):12,A2,A6,BA,22,7A,0A,D5 */ + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[7] = 0x12; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[6] = 0xA2; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[5] = 0xA6; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[4] = 0xBA; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[3] = 0x22; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[2] = 0x7A; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[1] = 0x0A; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[0] = 0xD5; +/* Levelmetering Ringing (0D):32,45,B5,84 ; 50Hz 20V */ + j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[3] = 0x32; + j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[2] = 0x45; + j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[1] = 0xB5; + j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[0] = 0x84; +/* Caller ID 1st Tone (0E):CA,0E,CA,09,99,99,99,99 */ + j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[7] = 0xCA; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[6] = 0x0E; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[5] = 0xCA; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[4] = 0x09; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[3] = 0x99; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[2] = 0x99; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[1] = 0x99; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[0] = 0x99; +/* Caller ID 2nd Tone (0F):FD,B5,BA,07,DA,00,00,00 */ + j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[7] = 0xFD; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[6] = 0xB5; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[5] = 0xBA; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[4] = 0x07; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[3] = 0xDA; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[2] = 0x00; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[1] = 0x00; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[0] = 0x00; +/* ;CR Registers */ + /* Config. Reg. 0 (filters) (cr0):FF */ + j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFF; +/* Config. Reg. 1 (dialing) (cr1):05 */ + j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.reg = 0x05; +/* Config. Reg. 2 (caller ID) (cr2):04 */ + j->m_DAAShadowRegs.SOP_REGS.SOP.cr2.reg = 0x04; +/* Config. Reg. 3 (testloops) (cr3):00 ; */ + j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg = 0x00; +/* Config. Reg. 4 (analog gain) (cr4):02 */ + j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = 0x02; + /* Config. Reg. 5 (Version) (cr5):02 */ + /* Config. Reg. 6 (Reserved) (cr6):00 */ + /* Config. Reg. 7 (Reserved) (cr7):00 */ + /* ;xr Registers */ + /* Ext. Reg. 0 (Interrupt Reg.) (xr0):02 */ + + j->m_DAAShadowRegs.XOP_xr0_W.reg = 0x02; /* SO_1 set to '1' because it is inverted. */ + /* Ext. Reg. 1 (Interrupt enable) (xr1):1C */ + + j->m_DAAShadowRegs.XOP_REGS.XOP.xr1.reg = 0x1C; /* RING, Caller ID, VDD_OK */ + /* Ext. Reg. 2 (Cadence Time Out) (xr2):7D */ + + j->m_DAAShadowRegs.XOP_REGS.XOP.xr2.reg = 0x7D; +/* Ext. Reg. 3 (DC Char) (xr3):2B ; */ + j->m_DAAShadowRegs.XOP_REGS.XOP.xr3.reg = 0x2B; +/* Ext. Reg. 4 (Cadence) (xr4):00 */ + j->m_DAAShadowRegs.XOP_REGS.XOP.xr4.reg = 0x00; +/* Ext. Reg. 5 (Ring timer) (xr5):22 */ + j->m_DAAShadowRegs.XOP_REGS.XOP.xr5.reg = 0x22; +/* Ext. Reg. 6 (Power State) (xr6):00 */ + j->m_DAAShadowRegs.XOP_xr6_W.reg = 0x00; +/* Ext. Reg. 7 (Vdd) (xr7):40 */ + j->m_DAAShadowRegs.XOP_REGS.XOP.xr7.reg = 0x40; /* 0x40 ??? Should it be 0x00? */ + + /* DTMF Tone 1 (0B): 11,B3,5A,2C ; 697 Hz */ + /* 12,33,5A,C3 ; 770 Hz */ + /* 13,3C,5B,32 ; 852 Hz */ + /* 1D,1B,5C,CC ; 941 Hz */ + j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[3] = 0x11; + j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[2] = 0xB3; + j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[1] = 0x5A; + j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[0] = 0x2C; + + /* DTMF Tone 2 (0C): 32,32,52,B3 ; 1209 Hz */ + /* EC,1D,52,22 ; 1336 Hz */ + /* AA,AC,51,D2 ; 1477 Hz */ + /* 9B,3B,51,25 ; 1633 Hz */ + j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[3] = 0x32; + j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[2] = 0x32; + j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[1] = 0x52; + j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[0] = 0xB3; +} + +static void DAA_Coeff_Japan(IXJ *j) +{ + int i; + + j->daa_country = DAA_JAPAN; + /*----------------------------------------------- */ + /* CAO */ + for (i = 0; i < ALISDAA_CALLERID_SIZE; i++) { + j->m_DAAShadowRegs.CAO_REGS.CAO.CallerID[i] = 0; + } + +/* Bytes for IM-filter part 1 (04): 06,BD,E2,2D,BA,F9,A0,00 */ + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7] = 0x06; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[6] = 0xBD; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[5] = 0xE2; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[4] = 0x2D; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[3] = 0xBA; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[2] = 0xF9; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[1] = 0xA0; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[0] = 0x00; +/* Bytes for IM-filter part 2 (05): 6F,F7,00,0E,34,33,E0,08 */ + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[7] = 0x6F; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[6] = 0xF7; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[5] = 0x00; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[4] = 0x0E; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[3] = 0x34; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[2] = 0x33; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[1] = 0xE0; + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[0] = 0x08; +/* Bytes for FRX-filter (08): 02,8F,68,77,9C,58,F0,08 */ + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[7] = 0x02; + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[6] = 0x8F; + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[5] = 0x68; + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[4] = 0x77; + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[3] = 0x9C; + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[2] = 0x58; + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[1] = 0xF0; + j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[0] = 0x08; +/* Bytes for FRR-filter (07): 03,8F,38,73,87,EA,20,08 */ + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[7] = 0x03; + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[6] = 0x8F; + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[5] = 0x38; + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[4] = 0x73; + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[3] = 0x87; + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[2] = 0xEA; + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[1] = 0x20; + j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[0] = 0x08; +/* Bytes for AX-filter (0A): 51,C5,DD,CA */ + j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[3] = 0x51; + j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[2] = 0xC5; + j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[1] = 0xDD; + j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[0] = 0xCA; +/* Bytes for AR-filter (09): 25,A7,10,D6 */ + j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[3] = 0x25; + j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[2] = 0xA7; + j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[1] = 0x10; + j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[0] = 0xD6; +/* Bytes for TH-filter part 1 (00): 00,42,48,81,AE,80,00,98 */ + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[7] = 0x00; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[6] = 0x42; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[5] = 0x48; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[4] = 0x81; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[3] = 0xAE; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[2] = 0x80; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[1] = 0x00; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[0] = 0x98; +/* Bytes for TH-filter part 2 (01): 02,AB,2A,20,99,5B,89,28 */ + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[7] = 0x02; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[6] = 0xAB; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[5] = 0x2A; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[4] = 0x20; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[3] = 0x99; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[2] = 0x5B; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[1] = 0x89; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[0] = 0x28; +/* Bytes for TH-filter part 3 (02): 00,88,DA,25,34,C5,4C,BA */ + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[7] = 0x00; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[6] = 0x88; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[5] = 0xDA; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[4] = 0x25; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[3] = 0x34; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[2] = 0xC5; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[1] = 0x4C; + j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[0] = 0xBA; +/* ; idle */ + /* Bytes for Ringing part 1 (03):1B,3C,93,3A,22,12,A3,23 */ + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[7] = 0x1B; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[6] = 0x3C; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[5] = 0x93; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[4] = 0x3A; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[3] = 0x22; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[2] = 0x12; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[1] = 0xA3; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[0] = 0x23; +/* Bytes for Ringing part 2 (06):12,A2,A6,BA,22,7A,0A,D5 */ + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[7] = 0x12; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[6] = 0xA2; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[5] = 0xA6; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[4] = 0xBA; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[3] = 0x22; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[2] = 0x7A; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[1] = 0x0A; + j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[0] = 0xD5; +/* Levelmetering Ringing (0D):AA,35,0F,8E ; 25Hz 30V ????????? */ + j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[3] = 0xAA; + j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[2] = 0x35; + j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[1] = 0x0F; + j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[0] = 0x8E; +/* Caller ID 1st Tone (0E):CA,0E,CA,09,99,99,99,99 */ + j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[7] = 0xCA; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[6] = 0x0E; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[5] = 0xCA; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[4] = 0x09; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[3] = 0x99; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[2] = 0x99; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[1] = 0x99; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[0] = 0x99; +/* Caller ID 2nd Tone (0F):FD,B5,BA,07,DA,00,00,00 */ + j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[7] = 0xFD; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[6] = 0xB5; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[5] = 0xBA; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[4] = 0x07; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[3] = 0xDA; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[2] = 0x00; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[1] = 0x00; + j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[0] = 0x00; +/* ;CR Registers */ + /* Config. Reg. 0 (filters) (cr0):FF */ + j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFF; +/* Config. Reg. 1 (dialing) (cr1):05 */ + j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.reg = 0x05; +/* Config. Reg. 2 (caller ID) (cr2):04 */ + j->m_DAAShadowRegs.SOP_REGS.SOP.cr2.reg = 0x04; +/* Config. Reg. 3 (testloops) (cr3):00 ; */ + j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg = 0x00; +/* Config. Reg. 4 (analog gain) (cr4):02 */ + j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = 0x02; + /* Config. Reg. 5 (Version) (cr5):02 */ + /* Config. Reg. 6 (Reserved) (cr6):00 */ + /* Config. Reg. 7 (Reserved) (cr7):00 */ + /* ;xr Registers */ + /* Ext. Reg. 0 (Interrupt Reg.) (xr0):02 */ + + j->m_DAAShadowRegs.XOP_xr0_W.reg = 0x02; /* SO_1 set to '1' because it is inverted. */ + /* Ext. Reg. 1 (Interrupt enable) (xr1):1C */ + + j->m_DAAShadowRegs.XOP_REGS.XOP.xr1.reg = 0x1C; /* RING, Caller ID, VDD_OK */ + /* Ext. Reg. 2 (Cadence Time Out) (xr2):7D */ + + j->m_DAAShadowRegs.XOP_REGS.XOP.xr2.reg = 0x7D; +/* Ext. Reg. 3 (DC Char) (xr3):22 ; */ + j->m_DAAShadowRegs.XOP_REGS.XOP.xr3.reg = 0x22; +/* Ext. Reg. 4 (Cadence) (xr4):00 */ + j->m_DAAShadowRegs.XOP_REGS.XOP.xr4.reg = 0x00; +/* Ext. Reg. 5 (Ring timer) (xr5):22 */ + j->m_DAAShadowRegs.XOP_REGS.XOP.xr5.reg = 0x22; +/* Ext. Reg. 6 (Power State) (xr6):00 */ + j->m_DAAShadowRegs.XOP_xr6_W.reg = 0x00; +/* Ext. Reg. 7 (Vdd) (xr7):40 */ + j->m_DAAShadowRegs.XOP_REGS.XOP.xr7.reg = 0x40; /* 0x40 ??? Should it be 0x00? */ + /* DTMF Tone 1 (0B): 11,B3,5A,2C ; 697 Hz */ + /* 12,33,5A,C3 ; 770 Hz */ + /* 13,3C,5B,32 ; 852 Hz */ + /* 1D,1B,5C,CC ; 941 Hz */ + + j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[3] = 0x11; + j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[2] = 0xB3; + j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[1] = 0x5A; + j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[0] = 0x2C; +/* DTMF Tone 2 (0C): 32,32,52,B3 ; 1209 Hz */ + /* EC,1D,52,22 ; 1336 Hz */ + /* AA,AC,51,D2 ; 1477 Hz */ + /* 9B,3B,51,25 ; 1633 Hz */ + j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[3] = 0x32; + j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[2] = 0x32; + j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[1] = 0x52; + j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[0] = 0xB3; +} + +static s16 tone_table[][19] = +{ + { /* f20_50[] 11 */ + 32538, /* A1 = 1.985962 */ + -32325, /* A2 = -0.986511 */ + -343, /* B2 = -0.010493 */ + 0, /* B1 = 0 */ + 343, /* B0 = 0.010493 */ + 32619, /* A1 = 1.990906 */ + -32520, /* A2 = -0.992462 */ + 19179, /* B2 = 0.585327 */ + -19178, /* B1 = -1.170593 */ + 19179, /* B0 = 0.585327 */ + 32723, /* A1 = 1.997314 */ + -32686, /* A2 = -0.997528 */ + 9973, /* B2 = 0.304352 */ + -9955, /* B1 = -0.607605 */ + 9973, /* B0 = 0.304352 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f133_200[] 12 */ + 32072, /* A1 = 1.95752 */ + -31896, /* A2 = -0.973419 */ + -435, /* B2 = -0.013294 */ + 0, /* B1 = 0 */ + 435, /* B0 = 0.013294 */ + 32188, /* A1 = 1.9646 */ + -32400, /* A2 = -0.98877 */ + 15139, /* B2 = 0.462036 */ + -14882, /* B1 = -0.908356 */ + 15139, /* B0 = 0.462036 */ + 32473, /* A1 = 1.981995 */ + -32524, /* A2 = -0.992584 */ + 23200, /* B2 = 0.708008 */ + -23113, /* B1 = -1.410706 */ + 23200, /* B0 = 0.708008 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f300 13 */ + 31769, /* A1 = -1.939026 */ + -32584, /* A2 = 0.994385 */ + -475, /* B2 = -0.014522 */ + 0, /* B1 = 0.000000 */ + 475, /* B0 = 0.014522 */ + 31789, /* A1 = -1.940247 */ + -32679, /* A2 = 0.997284 */ + 17280, /* B2 = 0.527344 */ + -16865, /* B1 = -1.029358 */ + 17280, /* B0 = 0.527344 */ + 31841, /* A1 = -1.943481 */ + -32681, /* A2 = 0.997345 */ + 543, /* B2 = 0.016579 */ + -525, /* B1 = -0.032097 */ + 543, /* B0 = 0.016579 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f300_420[] 14 */ + 30750, /* A1 = 1.876892 */ + -31212, /* A2 = -0.952515 */ + -804, /* B2 = -0.024541 */ + 0, /* B1 = 0 */ + 804, /* B0 = 0.024541 */ + 30686, /* A1 = 1.872925 */ + -32145, /* A2 = -0.980988 */ + 14747, /* B2 = 0.450043 */ + -13703, /* B1 = -0.836395 */ + 14747, /* B0 = 0.450043 */ + 31651, /* A1 = 1.931824 */ + -32321, /* A2 = -0.986389 */ + 24425, /* B2 = 0.745422 */ + -23914, /* B1 = -1.459595 */ + 24427, /* B0 = 0.745483 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f330 15 */ + 31613, /* A1 = -1.929565 */ + -32646, /* A2 = 0.996277 */ + -185, /* B2 = -0.005657 */ + 0, /* B1 = 0.000000 */ + 185, /* B0 = 0.005657 */ + 31620, /* A1 = -1.929932 */ + -32713, /* A2 = 0.998352 */ + 19253, /* B2 = 0.587585 */ + -18566, /* B1 = -1.133179 */ + 19253, /* B0 = 0.587585 */ + 31674, /* A1 = -1.933228 */ + -32715, /* A2 = 0.998413 */ + 2575, /* B2 = 0.078590 */ + -2495, /* B1 = -0.152283 */ + 2575, /* B0 = 0.078590 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f300_425[] 16 */ + 30741, /* A1 = 1.876282 */ + -31475, /* A2 = -0.960541 */ + -703, /* B2 = -0.021484 */ + 0, /* B1 = 0 */ + 703, /* B0 = 0.021484 */ + 30688, /* A1 = 1.873047 */ + -32248, /* A2 = -0.984161 */ + 14542, /* B2 = 0.443787 */ + -13523, /* B1 = -0.825439 */ + 14542, /* B0 = 0.443817 */ + 31494, /* A1 = 1.922302 */ + -32366, /* A2 = -0.987762 */ + 21577, /* B2 = 0.658508 */ + -21013, /* B1 = -1.282532 */ + 21577, /* B0 = 0.658508 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f330_440[] 17 */ + 30627, /* A1 = 1.869324 */ + -31338, /* A2 = -0.95636 */ + -843, /* B2 = -0.025749 */ + 0, /* B1 = 0 */ + 843, /* B0 = 0.025749 */ + 30550, /* A1 = 1.864685 */ + -32221, /* A2 = -0.983337 */ + 13594, /* B2 = 0.414886 */ + -12589, /* B1 = -0.768402 */ + 13594, /* B0 = 0.414886 */ + 31488, /* A1 = 1.921936 */ + -32358, /* A2 = -0.987518 */ + 24684, /* B2 = 0.753296 */ + -24029, /* B1 = -1.466614 */ + 24684, /* B0 = 0.753296 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f340 18 */ + 31546, /* A1 = -1.925476 */ + -32646, /* A2 = 0.996277 */ + -445, /* B2 = -0.013588 */ + 0, /* B1 = 0.000000 */ + 445, /* B0 = 0.013588 */ + 31551, /* A1 = -1.925781 */ + -32713, /* A2 = 0.998352 */ + 23884, /* B2 = 0.728882 */ + -22979, /* B1 = -1.402527 */ + 23884, /* B0 = 0.728882 */ + 31606, /* A1 = -1.929138 */ + -32715, /* A2 = 0.998413 */ + 863, /* B2 = 0.026367 */ + -835, /* B1 = -0.050985 */ + 863, /* B0 = 0.026367 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f350_400[] 19 */ + 31006, /* A1 = 1.892517 */ + -32029, /* A2 = -0.977448 */ + -461, /* B2 = -0.014096 */ + 0, /* B1 = 0 */ + 461, /* B0 = 0.014096 */ + 30999, /* A1 = 1.892029 */ + -32487, /* A2 = -0.991455 */ + 11325, /* B2 = 0.345612 */ + -10682, /* B1 = -0.651978 */ + 11325, /* B0 = 0.345612 */ + 31441, /* A1 = 1.919067 */ + -32526, /* A2 = -0.992615 */ + 24324, /* B2 = 0.74231 */ + -23535, /* B1 = -1.436523 */ + 24324, /* B0 = 0.74231 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f350_440[] */ + 30634, /* A1 = 1.869751 */ + -31533, /* A2 = -0.962341 */ + -680, /* B2 = -0.020782 */ + 0, /* B1 = 0 */ + 680, /* B0 = 0.020782 */ + 30571, /* A1 = 1.865906 */ + -32277, /* A2 = -0.985016 */ + 12894, /* B2 = 0.393524 */ + -11945, /* B1 = -0.729065 */ + 12894, /* B0 = 0.393524 */ + 31367, /* A1 = 1.91449 */ + -32379, /* A2 = -0.988129 */ + 23820, /* B2 = 0.726929 */ + -23104, /* B1 = -1.410217 */ + 23820, /* B0 = 0.726929 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f350_450[] */ + 30552, /* A1 = 1.864807 */ + -31434, /* A2 = -0.95929 */ + -690, /* B2 = -0.021066 */ + 0, /* B1 = 0 */ + 690, /* B0 = 0.021066 */ + 30472, /* A1 = 1.859924 */ + -32248, /* A2 = -0.984161 */ + 13385, /* B2 = 0.408478 */ + -12357, /* B1 = -0.754242 */ + 13385, /* B0 = 0.408478 */ + 31358, /* A1 = 1.914001 */ + -32366, /* A2 = -0.987732 */ + 26488, /* B2 = 0.80835 */ + -25692, /* B1 = -1.568176 */ + 26490, /* B0 = 0.808411 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f360 */ + 31397, /* A1 = -1.916321 */ + -32623, /* A2 = 0.995605 */ + -117, /* B2 = -0.003598 */ + 0, /* B1 = 0.000000 */ + 117, /* B0 = 0.003598 */ + 31403, /* A1 = -1.916687 */ + -32700, /* A2 = 0.997925 */ + 3388, /* B2 = 0.103401 */ + -3240, /* B1 = -0.197784 */ + 3388, /* B0 = 0.103401 */ + 31463, /* A1 = -1.920410 */ + -32702, /* A2 = 0.997986 */ + 13346, /* B2 = 0.407288 */ + -12863, /* B1 = -0.785126 */ + 13346, /* B0 = 0.407288 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f380_420[] */ + 30831, /* A1 = 1.881775 */ + -32064, /* A2 = -0.978546 */ + -367, /* B2 = -0.01122 */ + 0, /* B1 = 0 */ + 367, /* B0 = 0.01122 */ + 30813, /* A1 = 1.880737 */ + -32456, /* A2 = -0.990509 */ + 11068, /* B2 = 0.337769 */ + -10338, /* B1 = -0.631042 */ + 11068, /* B0 = 0.337769 */ + 31214, /* A1 = 1.905212 */ + -32491, /* A2 = -0.991577 */ + 16374, /* B2 = 0.499695 */ + -15781, /* B1 = -0.963196 */ + 16374, /* B0 = 0.499695 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f392 */ + 31152, /* A1 = -1.901428 */ + -32613, /* A2 = 0.995300 */ + -314, /* B2 = -0.009605 */ + 0, /* B1 = 0.000000 */ + 314, /* B0 = 0.009605 */ + 31156, /* A1 = -1.901672 */ + -32694, /* A2 = 0.997742 */ + 28847, /* B2 = 0.880371 */ + -2734, /* B1 = -0.166901 */ + 28847, /* B0 = 0.880371 */ + 31225, /* A1 = -1.905823 */ + -32696, /* A2 = 0.997803 */ + 462, /* B2 = 0.014108 */ + -442, /* B1 = -0.027019 */ + 462, /* B0 = 0.014108 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f400_425[] */ + 30836, /* A1 = 1.882141 */ + -32296, /* A2 = -0.985596 */ + -324, /* B2 = -0.009903 */ + 0, /* B1 = 0 */ + 324, /* B0 = 0.009903 */ + 30825, /* A1 = 1.881409 */ + -32570, /* A2 = -0.993958 */ + 16847, /* B2 = 0.51416 */ + -15792, /* B1 = -0.963898 */ + 16847, /* B0 = 0.51416 */ + 31106, /* A1 = 1.89856 */ + -32584, /* A2 = -0.994415 */ + 9579, /* B2 = 0.292328 */ + -9164, /* B1 = -0.559357 */ + 9579, /* B0 = 0.292328 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f400_440[] */ + 30702, /* A1 = 1.873962 */ + -32134, /* A2 = -0.980682 */ + -517, /* B2 = -0.015793 */ + 0, /* B1 = 0 */ + 517, /* B0 = 0.015793 */ + 30676, /* A1 = 1.872375 */ + -32520, /* A2 = -0.992462 */ + 8144, /* B2 = 0.24855 */ + -7596, /* B1 = -0.463684 */ + 8144, /* B0 = 0.24855 */ + 31084, /* A1 = 1.897217 */ + -32547, /* A2 = -0.993256 */ + 22713, /* B2 = 0.693176 */ + -21734, /* B1 = -1.326599 */ + 22713, /* B0 = 0.693176 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f400_450[] */ + 30613, /* A1 = 1.86853 */ + -32031, /* A2 = -0.977509 */ + -618, /* B2 = -0.018866 */ + 0, /* B1 = 0 */ + 618, /* B0 = 0.018866 */ + 30577, /* A1 = 1.866272 */ + -32491, /* A2 = -0.991577 */ + 9612, /* B2 = 0.293335 */ + -8935, /* B1 = -0.54541 */ + 9612, /* B0 = 0.293335 */ + 31071, /* A1 = 1.896484 */ + -32524, /* A2 = -0.992584 */ + 21596, /* B2 = 0.659058 */ + -20667, /* B1 = -1.261414 */ + 21596, /* B0 = 0.659058 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f420 */ + 30914, /* A1 = -1.886841 */ + -32584, /* A2 = 0.994385 */ + -426, /* B2 = -0.013020 */ + 0, /* B1 = 0.000000 */ + 426, /* B0 = 0.013020 */ + 30914, /* A1 = -1.886841 */ + -32679, /* A2 = 0.997314 */ + 17520, /* B2 = 0.534668 */ + -16471, /* B1 = -1.005310 */ + 17520, /* B0 = 0.534668 */ + 31004, /* A1 = -1.892334 */ + -32683, /* A2 = 0.997406 */ + 819, /* B2 = 0.025023 */ + -780, /* B1 = -0.047619 */ + 819, /* B0 = 0.025023 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, +#if 0 + { /* f425 */ + 30881, /* A1 = -1.884827 */ + -32603, /* A2 = 0.994965 */ + -496, /* B2 = -0.015144 */ + 0, /* B1 = 0.000000 */ + 496, /* B0 = 0.015144 */ + 30880, /* A1 = -1.884766 */ + -32692, /* A2 = 0.997711 */ + 24767, /* B2 = 0.755859 */ + -23290, /* B1 = -1.421509 */ + 24767, /* B0 = 0.755859 */ + 30967, /* A1 = -1.890076 */ + -32694, /* A2 = 0.997772 */ + 728, /* B2 = 0.022232 */ + -691, /* B1 = -0.042194 */ + 728, /* B0 = 0.022232 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, +#else + { + 30850, + -32534, + -504, + 0, + 504, + 30831, + -32669, + 24303, + -22080, + 24303, + 30994, + -32673, + 1905, + -1811, + 1905, + 5, + 129, + 17, + 0xff5 + }, +#endif + { /* f425_450[] */ + 30646, /* A1 = 1.870544 */ + -32327, /* A2 = -0.986572 */ + -287, /* B2 = -0.008769 */ + 0, /* B1 = 0 */ + 287, /* B0 = 0.008769 */ + 30627, /* A1 = 1.869324 */ + -32607, /* A2 = -0.995087 */ + 13269, /* B2 = 0.404968 */ + -12376, /* B1 = -0.755432 */ + 13269, /* B0 = 0.404968 */ + 30924, /* A1 = 1.887512 */ + -32619, /* A2 = -0.995453 */ + 19950, /* B2 = 0.608826 */ + -18940, /* B1 = -1.156006 */ + 19950, /* B0 = 0.608826 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f425_475[] */ + 30396, /* A1 = 1.855225 */ + -32014, /* A2 = -0.97699 */ + -395, /* B2 = -0.012055 */ + 0, /* B1 = 0 */ + 395, /* B0 = 0.012055 */ + 30343, /* A1 = 1.85199 */ + -32482, /* A2 = -0.991302 */ + 17823, /* B2 = 0.543945 */ + -16431, /* B1 = -1.002869 */ + 17823, /* B0 = 0.543945 */ + 30872, /* A1 = 1.884338 */ + -32516, /* A2 = -0.99231 */ + 18124, /* B2 = 0.553101 */ + -17246, /* B1 = -1.052673 */ + 18124, /* B0 = 0.553101 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f435 */ + 30796, /* A1 = -1.879639 */ + -32603, /* A2 = 0.994965 */ + -254, /* B2 = -0.007762 */ + 0, /* B1 = 0.000000 */ + 254, /* B0 = 0.007762 */ + 30793, /* A1 = -1.879456 */ + -32692, /* A2 = 0.997711 */ + 18934, /* B2 = 0.577820 */ + -17751, /* B1 = -1.083496 */ + 18934, /* B0 = 0.577820 */ + 30882, /* A1 = -1.884888 */ + -32694, /* A2 = 0.997772 */ + 1858, /* B2 = 0.056713 */ + -1758, /* B1 = -0.107357 */ + 1858, /* B0 = 0.056713 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f440_450[] */ + 30641, /* A1 = 1.870239 */ + -32458, /* A2 = -0.99057 */ + -155, /* B2 = -0.004735 */ + 0, /* B1 = 0 */ + 155, /* B0 = 0.004735 */ + 30631, /* A1 = 1.869568 */ + -32630, /* A2 = -0.995789 */ + 11453, /* B2 = 0.349548 */ + -10666, /* B1 = -0.651001 */ + 11453, /* B0 = 0.349548 */ + 30810, /* A1 = 1.880554 */ + -32634, /* A2 = -0.995941 */ + 12237, /* B2 = 0.373474 */ + -11588, /* B1 = -0.707336 */ + 12237, /* B0 = 0.373474 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f440_480[] */ + 30367, /* A1 = 1.853455 */ + -32147, /* A2 = -0.981079 */ + -495, /* B2 = -0.015113 */ + 0, /* B1 = 0 */ + 495, /* B0 = 0.015113 */ + 30322, /* A1 = 1.850769 */ + -32543, /* A2 = -0.993134 */ + 10031, /* B2 = 0.306152 */ + -9252, /* B1 = -0.564728 */ + 10031, /* B0 = 0.306152 */ + 30770, /* A1 = 1.878052 */ + -32563, /* A2 = -0.993774 */ + 22674, /* B2 = 0.691956 */ + -21465, /* B1 = -1.31012 */ + 22674, /* B0 = 0.691956 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f445 */ + 30709, /* A1 = -1.874329 */ + -32603, /* A2 = 0.994965 */ + -83, /* B2 = -0.002545 */ + 0, /* B1 = 0.000000 */ + 83, /* B0 = 0.002545 */ + 30704, /* A1 = -1.874084 */ + -32692, /* A2 = 0.997711 */ + 10641, /* B2 = 0.324738 */ + -9947, /* B1 = -0.607147 */ + 10641, /* B0 = 0.324738 */ + 30796, /* A1 = -1.879639 */ + -32694, /* A2 = 0.997772 */ + 10079, /* B2 = 0.307587 */ + 9513, /* B1 = 0.580688 */ + 10079, /* B0 = 0.307587 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f450 */ + 30664, /* A1 = -1.871643 */ + -32603, /* A2 = 0.994965 */ + -164, /* B2 = -0.005029 */ + 0, /* B1 = 0.000000 */ + 164, /* B0 = 0.005029 */ + 30661, /* A1 = -1.871399 */ + -32692, /* A2 = 0.997711 */ + 15294, /* B2 = 0.466736 */ + -14275, /* B1 = -0.871307 */ + 15294, /* B0 = 0.466736 */ + 30751, /* A1 = -1.876953 */ + -32694, /* A2 = 0.997772 */ + 3548, /* B2 = 0.108284 */ + -3344, /* B1 = -0.204155 */ + 3548, /* B0 = 0.108284 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f452 */ + 30653, /* A1 = -1.870911 */ + -32615, /* A2 = 0.995361 */ + -209, /* B2 = -0.006382 */ + 0, /* B1 = 0.000000 */ + 209, /* B0 = 0.006382 */ + 30647, /* A1 = -1.870605 */ + -32702, /* A2 = 0.997986 */ + 18971, /* B2 = 0.578979 */ + -17716, /* B1 = -1.081299 */ + 18971, /* B0 = 0.578979 */ + 30738, /* A1 = -1.876099 */ + -32702, /* A2 = 0.998016 */ + 2967, /* B2 = 0.090561 */ + -2793, /* B1 = -0.170502 */ + 2967, /* B0 = 0.090561 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f475 */ + 30437, /* A1 = -1.857727 */ + -32603, /* A2 = 0.994965 */ + -264, /* B2 = -0.008062 */ + 0, /* B1 = 0.000000 */ + 264, /* B0 = 0.008062 */ + 30430, /* A1 = -1.857300 */ + -32692, /* A2 = 0.997711 */ + 21681, /* B2 = 0.661682 */ + -20082, /* B1 = -1.225708 */ + 21681, /* B0 = 0.661682 */ + 30526, /* A1 = -1.863220 */ + -32694, /* A2 = 0.997742 */ + 1559, /* B2 = 0.047600 */ + -1459, /* B1 = -0.089096 */ + 1559, /* B0 = 0.047600 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f480_620[] */ + 28975, /* A1 = 1.768494 */ + -30955, /* A2 = -0.944672 */ + -1026, /* B2 = -0.03133 */ + 0, /* B1 = 0 */ + 1026, /* B0 = 0.03133 */ + 28613, /* A1 = 1.746399 */ + -32089, /* A2 = -0.979309 */ + 14214, /* B2 = 0.433807 */ + -12202, /* B1 = -0.744812 */ + 14214, /* B0 = 0.433807 */ + 30243, /* A1 = 1.845947 */ + -32238, /* A2 = -0.983856 */ + 24825, /* B2 = 0.757629 */ + -23402, /* B1 = -1.428345 */ + 24825, /* B0 = 0.757629 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f494 */ + 30257, /* A1 = -1.846741 */ + -32605, /* A2 = 0.995056 */ + -249, /* B2 = -0.007625 */ + 0, /* B1 = 0.000000 */ + 249, /* B0 = 0.007625 */ + 30247, /* A1 = -1.846191 */ + -32694, /* A2 = 0.997772 */ + 18088, /* B2 = 0.552002 */ + -16652, /* B1 = -1.016418 */ + 18088, /* B0 = 0.552002 */ + 30348, /* A1 = -1.852295 */ + -32696, /* A2 = 0.997803 */ + 2099, /* B2 = 0.064064 */ + -1953, /* B1 = -0.119202 */ + 2099, /* B0 = 0.064064 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f500 */ + 30202, /* A1 = -1.843431 */ + -32624, /* A2 = 0.995622 */ + -413, /* B2 = -0.012622 */ + 0, /* B1 = 0.000000 */ + 413, /* B0 = 0.012622 */ + 30191, /* A1 = -1.842721 */ + -32714, /* A2 = 0.998364 */ + 25954, /* B2 = 0.792057 */ + -23890, /* B1 = -1.458131 */ + 25954, /* B0 = 0.792057 */ + 30296, /* A1 = -1.849172 */ + -32715, /* A2 = 0.998397 */ + 2007, /* B2 = 0.061264 */ + -1860, /* B1 = -0.113568 */ + 2007, /* B0 = 0.061264 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f520 */ + 30001, /* A1 = -1.831116 */ + -32613, /* A2 = 0.995270 */ + -155, /* B2 = -0.004750 */ + 0, /* B1 = 0.000000 */ + 155, /* B0 = 0.004750 */ + 29985, /* A1 = -1.830200 */ + -32710, /* A2 = 0.998260 */ + 6584, /* B2 = 0.200928 */ + -6018, /* B1 = -0.367355 */ + 6584, /* B0 = 0.200928 */ + 30105, /* A1 = -1.837524 */ + -32712, /* A2 = 0.998291 */ + 23812, /* B2 = 0.726685 */ + -21936, /* B1 = -1.338928 */ + 23812, /* B0 = 0.726685 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f523 */ + 29964, /* A1 = -1.828918 */ + -32601, /* A2 = 0.994904 */ + -101, /* B2 = -0.003110 */ + 0, /* B1 = 0.000000 */ + 101, /* B0 = 0.003110 */ + 29949, /* A1 = -1.827942 */ + -32700, /* A2 = 0.997925 */ + 11041, /* B2 = 0.336975 */ + -10075, /* B1 = -0.614960 */ + 11041, /* B0 = 0.336975 */ + 30070, /* A1 = -1.835388 */ + -32702, /* A2 = 0.997986 */ + 16762, /* B2 = 0.511536 */ + -15437, /* B1 = -0.942230 */ + 16762, /* B0 = 0.511536 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f525 */ + 29936, /* A1 = -1.827209 */ + -32584, /* A2 = 0.994415 */ + -91, /* B2 = -0.002806 */ + 0, /* B1 = 0.000000 */ + 91, /* B0 = 0.002806 */ + 29921, /* A1 = -1.826233 */ + -32688, /* A2 = 0.997559 */ + 11449, /* B2 = 0.349396 */ + -10426, /* B1 = -0.636383 */ + 11449, /* B0 = 0.349396 */ + 30045, /* A1 = -1.833862 */ + -32688, /* A2 = 0.997589 */ + 13055, /* B2 = 0.398407 */ + -12028, /* B1 = -0.734161 */ + 13055, /* B0 = 0.398407 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f540_660[] */ + 28499, /* A1 = 1.739441 */ + -31129, /* A2 = -0.949982 */ + -849, /* B2 = -0.025922 */ + 0, /* B1 = 0 */ + 849, /* B0 = 0.025922 */ + 28128, /* A1 = 1.716797 */ + -32130, /* A2 = -0.98056 */ + 14556, /* B2 = 0.444214 */ + -12251, /* B1 = -0.747772 */ + 14556, /* B0 = 0.444244 */ + 29667, /* A1 = 1.81073 */ + -32244, /* A2 = -0.984039 */ + 23038, /* B2 = 0.703064 */ + -21358, /* B1 = -1.303589 */ + 23040, /* B0 = 0.703125 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f587 */ + 29271, /* A1 = -1.786560 */ + -32599, /* A2 = 0.994873 */ + -490, /* B2 = -0.014957 */ + 0, /* B1 = 0.000000 */ + 490, /* B0 = 0.014957 */ + 29246, /* A1 = -1.785095 */ + -32700, /* A2 = 0.997925 */ + 28961, /* B2 = 0.883850 */ + -25796, /* B1 = -1.574463 */ + 28961, /* B0 = 0.883850 */ + 29383, /* A1 = -1.793396 */ + -32700, /* A2 = 0.997955 */ + 1299, /* B2 = 0.039650 */ + -1169, /* B1 = -0.071396 */ + 1299, /* B0 = 0.039650 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f590 */ + 29230, /* A1 = -1.784058 */ + -32584, /* A2 = 0.994415 */ + -418, /* B2 = -0.012757 */ + 0, /* B1 = 0.000000 */ + 418, /* B0 = 0.012757 */ + 29206, /* A1 = -1.782593 */ + -32688, /* A2 = 0.997559 */ + 36556, /* B2 = 1.115601 */ + -32478, /* B1 = -1.982300 */ + 36556, /* B0 = 1.115601 */ + 29345, /* A1 = -1.791077 */ + -32688, /* A2 = 0.997589 */ + 897, /* B2 = 0.027397 */ + -808, /* B1 = -0.049334 */ + 897, /* B0 = 0.027397 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f600 */ + 29116, /* A1 = -1.777100 */ + -32603, /* A2 = 0.994965 */ + -165, /* B2 = -0.005039 */ + 0, /* B1 = 0.000000 */ + 165, /* B0 = 0.005039 */ + 29089, /* A1 = -1.775452 */ + -32708, /* A2 = 0.998199 */ + 6963, /* B2 = 0.212494 */ + -6172, /* B1 = -0.376770 */ + 6963, /* B0 = 0.212494 */ + 29237, /* A1 = -1.784485 */ + -32710, /* A2 = 0.998230 */ + 24197, /* B2 = 0.738464 */ + -21657, /* B1 = -1.321899 */ + 24197, /* B0 = 0.738464 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f660 */ + 28376, /* A1 = -1.731934 */ + -32567, /* A2 = 0.993896 */ + -363, /* B2 = -0.011102 */ + 0, /* B1 = 0.000000 */ + 363, /* B0 = 0.011102 */ + 28337, /* A1 = -1.729614 */ + -32683, /* A2 = 0.997434 */ + 21766, /* B2 = 0.664246 */ + -18761, /* B1 = -1.145081 */ + 21766, /* B0 = 0.664246 */ + 28513, /* A1 = -1.740356 */ + -32686, /* A2 = 0.997498 */ + 2509, /* B2 = 0.076584 */ + -2196, /* B1 = -0.134041 */ + 2509, /* B0 = 0.076584 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f700 */ + 27844, /* A1 = -1.699463 */ + -32563, /* A2 = 0.993744 */ + -366, /* B2 = -0.011187 */ + 0, /* B1 = 0.000000 */ + 366, /* B0 = 0.011187 */ + 27797, /* A1 = -1.696655 */ + -32686, /* A2 = 0.997498 */ + 22748, /* B2 = 0.694214 */ + -19235, /* B1 = -1.174072 */ + 22748, /* B0 = 0.694214 */ + 27995, /* A1 = -1.708740 */ + -32688, /* A2 = 0.997559 */ + 2964, /* B2 = 0.090477 */ + -2546, /* B1 = -0.155449 */ + 2964, /* B0 = 0.090477 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f740 */ + 27297, /* A1 = -1.666077 */ + -32551, /* A2 = 0.993408 */ + -345, /* B2 = -0.010540 */ + 0, /* B1 = 0.000000 */ + 345, /* B0 = 0.010540 */ + 27240, /* A1 = -1.662598 */ + -32683, /* A2 = 0.997406 */ + 22560, /* B2 = 0.688477 */ + -18688, /* B1 = -1.140625 */ + 22560, /* B0 = 0.688477 */ + 27461, /* A1 = -1.676147 */ + -32684, /* A2 = 0.997467 */ + 3541, /* B2 = 0.108086 */ + -2985, /* B1 = -0.182220 */ + 3541, /* B0 = 0.108086 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f750 */ + 27155, /* A1 = -1.657410 */ + -32551, /* A2 = 0.993408 */ + -462, /* B2 = -0.014117 */ + 0, /* B1 = 0.000000 */ + 462, /* B0 = 0.014117 */ + 27097, /* A1 = -1.653870 */ + -32683, /* A2 = 0.997406 */ + 32495, /* B2 = 0.991699 */ + -26776, /* B1 = -1.634338 */ + 32495, /* B0 = 0.991699 */ + 27321, /* A1 = -1.667542 */ + -32684, /* A2 = 0.997467 */ + 1835, /* B2 = 0.056007 */ + -1539, /* B1 = -0.093948 */ + 1835, /* B0 = 0.056007 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f750_1450[] */ + 19298, /* A1 = 1.177917 */ + -24471, /* A2 = -0.746796 */ + -4152, /* B2 = -0.126709 */ + 0, /* B1 = 0 */ + 4152, /* B0 = 0.126709 */ + 12902, /* A1 = 0.787476 */ + -29091, /* A2 = -0.887817 */ + 12491, /* B2 = 0.38121 */ + -1794, /* B1 = -0.109528 */ + 12494, /* B0 = 0.381317 */ + 26291, /* A1 = 1.604736 */ + -30470, /* A2 = -0.929901 */ + 28859, /* B2 = 0.880737 */ + -26084, /* B1 = -1.592102 */ + 28861, /* B0 = 0.880798 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f770 */ + 26867, /* A1 = -1.639832 */ + -32551, /* A2 = 0.993408 */ + -123, /* B2 = -0.003755 */ + 0, /* B1 = 0.000000 */ + 123, /* B0 = 0.003755 */ + 26805, /* A1 = -1.636108 */ + -32683, /* A2 = 0.997406 */ + 17297, /* B2 = 0.527863 */ + -14096, /* B1 = -0.860382 */ + 17297, /* B0 = 0.527863 */ + 27034, /* A1 = -1.650085 */ + -32684, /* A2 = 0.997467 */ + 12958, /* B2 = 0.395477 */ + -10756, /* B1 = -0.656525 */ + 12958, /* B0 = 0.395477 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f800 */ + 26413, /* A1 = -1.612122 */ + -32547, /* A2 = 0.993286 */ + -223, /* B2 = -0.006825 */ + 0, /* B1 = 0.000000 */ + 223, /* B0 = 0.006825 */ + 26342, /* A1 = -1.607849 */ + -32686, /* A2 = 0.997498 */ + 6391, /* B2 = 0.195053 */ + -5120, /* B1 = -0.312531 */ + 6391, /* B0 = 0.195053 */ + 26593, /* A1 = -1.623108 */ + -32688, /* A2 = 0.997559 */ + 23681, /* B2 = 0.722717 */ + -19328, /* B1 = -1.179688 */ + 23681, /* B0 = 0.722717 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f816 */ + 26168, /* A1 = -1.597209 */ + -32528, /* A2 = 0.992706 */ + -235, /* B2 = -0.007182 */ + 0, /* B1 = 0.000000 */ + 235, /* B0 = 0.007182 */ + 26092, /* A1 = -1.592590 */ + -32675, /* A2 = 0.997192 */ + 20823, /* B2 = 0.635498 */ + -16510, /* B1 = -1.007751 */ + 20823, /* B0 = 0.635498 */ + 26363, /* A1 = -1.609070 */ + -32677, /* A2 = 0.997253 */ + 6739, /* B2 = 0.205688 */ + -5459, /* B1 = -0.333206 */ + 6739, /* B0 = 0.205688 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f850 */ + 25641, /* A1 = -1.565063 */ + -32536, /* A2 = 0.992950 */ + -121, /* B2 = -0.003707 */ + 0, /* B1 = 0.000000 */ + 121, /* B0 = 0.003707 */ + 25560, /* A1 = -1.560059 */ + -32684, /* A2 = 0.997437 */ + 18341, /* B2 = 0.559753 */ + -14252, /* B1 = -0.869904 */ + 18341, /* B0 = 0.559753 */ + 25837, /* A1 = -1.577026 */ + -32684, /* A2 = 0.997467 */ + 16679, /* B2 = 0.509003 */ + -13232, /* B1 = -0.807648 */ + 16679, /* B0 = 0.509003 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f857_1645[] */ + 16415, /* A1 = 1.001953 */ + -23669, /* A2 = -0.722321 */ + -4549, /* B2 = -0.138847 */ + 0, /* B1 = 0 */ + 4549, /* B0 = 0.138847 */ + 8456, /* A1 = 0.516174 */ + -28996, /* A2 = -0.884918 */ + 13753, /* B2 = 0.419724 */ + -12, /* B1 = -0.000763 */ + 13757, /* B0 = 0.419846 */ + 24632, /* A1 = 1.503418 */ + -30271, /* A2 = -0.923828 */ + 29070, /* B2 = 0.887146 */ + -25265, /* B1 = -1.542114 */ + 29073, /* B0 = 0.887268 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f900 */ + 24806, /* A1 = -1.514099 */ + -32501, /* A2 = 0.991852 */ + -326, /* B2 = -0.009969 */ + 0, /* B1 = 0.000000 */ + 326, /* B0 = 0.009969 */ + 24709, /* A1 = -1.508118 */ + -32659, /* A2 = 0.996674 */ + 20277, /* B2 = 0.618835 */ + -15182, /* B1 = -0.926636 */ + 20277, /* B0 = 0.618835 */ + 25022, /* A1 = -1.527222 */ + -32661, /* A2 = 0.996735 */ + 4320, /* B2 = 0.131836 */ + -3331, /* B1 = -0.203339 */ + 4320, /* B0 = 0.131836 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f900_1300[] */ + 19776, /* A1 = 1.207092 */ + -27437, /* A2 = -0.837341 */ + -2666, /* B2 = -0.081371 */ + 0, /* B1 = 0 */ + 2666, /* B0 = 0.081371 */ + 16302, /* A1 = 0.995026 */ + -30354, /* A2 = -0.926361 */ + 10389, /* B2 = 0.317062 */ + -3327, /* B1 = -0.203064 */ + 10389, /* B0 = 0.317062 */ + 24299, /* A1 = 1.483154 */ + -30930, /* A2 = -0.943909 */ + 25016, /* B2 = 0.763428 */ + -21171, /* B1 = -1.292236 */ + 25016, /* B0 = 0.763428 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f935_1215[] */ + 20554, /* A1 = 1.254517 */ + -28764, /* A2 = -0.877838 */ + -2048, /* B2 = -0.062515 */ + 0, /* B1 = 0 */ + 2048, /* B0 = 0.062515 */ + 18209, /* A1 = 1.11145 */ + -30951, /* A2 = -0.94458 */ + 9390, /* B2 = 0.286575 */ + -3955, /* B1 = -0.241455 */ + 9390, /* B0 = 0.286575 */ + 23902, /* A1 = 1.458923 */ + -31286, /* A2 = -0.954803 */ + 23252, /* B2 = 0.709595 */ + -19132, /* B1 = -1.167725 */ + 23252, /* B0 = 0.709595 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f941_1477[] */ + 17543, /* A1 = 1.07074 */ + -26220, /* A2 = -0.800201 */ + -3298, /* B2 = -0.100647 */ + 0, /* B1 = 0 */ + 3298, /* B0 = 0.100647 */ + 12423, /* A1 = 0.75827 */ + -30036, /* A2 = -0.916626 */ + 12651, /* B2 = 0.386078 */ + -2444, /* B1 = -0.14917 */ + 12653, /* B0 = 0.386154 */ + 23518, /* A1 = 1.435425 */ + -30745, /* A2 = -0.938293 */ + 27282, /* B2 = 0.832581 */ + -22529, /* B1 = -1.375122 */ + 27286, /* B0 = 0.832703 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f942 */ + 24104, /* A1 = -1.471252 */ + -32507, /* A2 = 0.992065 */ + -351, /* B2 = -0.010722 */ + 0, /* B1 = 0.000000 */ + 351, /* B0 = 0.010722 */ + 23996, /* A1 = -1.464600 */ + -32671, /* A2 = 0.997040 */ + 22848, /* B2 = 0.697266 */ + -16639, /* B1 = -1.015564 */ + 22848, /* B0 = 0.697266 */ + 24332, /* A1 = -1.485168 */ + -32673, /* A2 = 0.997101 */ + 4906, /* B2 = 0.149727 */ + -3672, /* B1 = -0.224174 */ + 4906, /* B0 = 0.149727 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f950 */ + 23967, /* A1 = -1.462830 */ + -32507, /* A2 = 0.992065 */ + -518, /* B2 = -0.015821 */ + 0, /* B1 = 0.000000 */ + 518, /* B0 = 0.015821 */ + 23856, /* A1 = -1.456055 */ + -32671, /* A2 = 0.997040 */ + 26287, /* B2 = 0.802246 */ + -19031, /* B1 = -1.161560 */ + 26287, /* B0 = 0.802246 */ + 24195, /* A1 = -1.476746 */ + -32673, /* A2 = 0.997101 */ + 2890, /* B2 = 0.088196 */ + -2151, /* B1 = -0.131317 */ + 2890, /* B0 = 0.088196 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f950_1400[] */ + 18294, /* A1 = 1.116638 */ + -26962, /* A2 = -0.822845 */ + -2914, /* B2 = -0.088936 */ + 0, /* B1 = 0 */ + 2914, /* B0 = 0.088936 */ + 14119, /* A1 = 0.861786 */ + -30227, /* A2 = -0.922455 */ + 11466, /* B2 = 0.349945 */ + -2833, /* B1 = -0.172943 */ + 11466, /* B0 = 0.349945 */ + 23431, /* A1 = 1.430115 */ + -30828, /* A2 = -0.940796 */ + 25331, /* B2 = 0.773071 */ + -20911, /* B1 = -1.276367 */ + 25331, /* B0 = 0.773071 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f975 */ + 23521, /* A1 = -1.435608 */ + -32489, /* A2 = 0.991516 */ + -193, /* B2 = -0.005915 */ + 0, /* B1 = 0.000000 */ + 193, /* B0 = 0.005915 */ + 23404, /* A1 = -1.428467 */ + -32655, /* A2 = 0.996582 */ + 17740, /* B2 = 0.541412 */ + -12567, /* B1 = -0.767029 */ + 17740, /* B0 = 0.541412 */ + 23753, /* A1 = -1.449829 */ + -32657, /* A2 = 0.996613 */ + 9090, /* B2 = 0.277405 */ + -6662, /* B1 = -0.406647 */ + 9090, /* B0 = 0.277405 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f1000 */ + 23071, /* A1 = -1.408203 */ + -32489, /* A2 = 0.991516 */ + -293, /* B2 = -0.008965 */ + 0, /* B1 = 0.000000 */ + 293, /* B0 = 0.008965 */ + 22951, /* A1 = -1.400818 */ + -32655, /* A2 = 0.996582 */ + 5689, /* B2 = 0.173645 */ + -3951, /* B1 = -0.241150 */ + 5689, /* B0 = 0.173645 */ + 23307, /* A1 = -1.422607 */ + -32657, /* A2 = 0.996613 */ + 18692, /* B2 = 0.570435 */ + -13447, /* B1 = -0.820770 */ + 18692, /* B0 = 0.570435 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f1020 */ + 22701, /* A1 = -1.385620 */ + -32474, /* A2 = 0.991058 */ + -292, /* B2 = -0.008933 */ + 0, /*163840 , B1 = 10.000000 */ + 292, /* B0 = 0.008933 */ + 22564, /* A1 = -1.377258 */ + -32655, /* A2 = 0.996552 */ + 20756, /* B2 = 0.633423 */ + -14176, /* B1 = -0.865295 */ + 20756, /* B0 = 0.633423 */ + 22960, /* A1 = -1.401428 */ + -32657, /* A2 = 0.996613 */ + 6520, /* B2 = 0.198990 */ + -4619, /* B1 = -0.281937 */ + 6520, /* B0 = 0.198990 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f1050 */ + 22142, /* A1 = -1.351501 */ + -32474, /* A2 = 0.991058 */ + -147, /* B2 = -0.004493 */ + 0, /* B1 = 0.000000 */ + 147, /* B0 = 0.004493 */ + 22000, /* A1 = -1.342834 */ + -32655, /* A2 = 0.996552 */ + 15379, /* B2 = 0.469360 */ + -10237, /* B1 = -0.624847 */ + 15379, /* B0 = 0.469360 */ + 22406, /* A1 = -1.367554 */ + -32657, /* A2 = 0.996613 */ + 17491, /* B2 = 0.533783 */ + -12096, /* B1 = -0.738312 */ + 17491, /* B0 = 0.533783 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f1100_1750[] */ + 12973, /* A1 = 0.79184 */ + -24916, /* A2 = -0.760376 */ + 6655, /* B2 = 0.203102 */ + 367, /* B1 = 0.0224 */ + 6657, /* B0 = 0.203171 */ + 5915, /* A1 = 0.361053 */ + -29560, /* A2 = -0.90213 */ + -7777, /* B2 = -0.23735 */ + 0, /* B1 = 0 */ + 7777, /* B0 = 0.23735 */ + 20510, /* A1 = 1.251892 */ + -30260, /* A2 = -0.923462 */ + 26662, /* B2 = 0.81366 */ + -20573, /* B1 = -1.255737 */ + 26668, /* B0 = 0.813843 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f1140 */ + 20392, /* A1 = -1.244629 */ + -32460, /* A2 = 0.990601 */ + -270, /* B2 = -0.008240 */ + 0, /* B1 = 0.000000 */ + 270, /* B0 = 0.008240 */ + 20218, /* A1 = -1.234009 */ + -32655, /* A2 = 0.996582 */ + 21337, /* B2 = 0.651154 */ + -13044, /* B1 = -0.796143 */ + 21337, /* B0 = 0.651154 */ + 20684, /* A1 = -1.262512 */ + -32657, /* A2 = 0.996643 */ + 8572, /* B2 = 0.261612 */ + -5476, /* B1 = -0.334244 */ + 8572, /* B0 = 0.261612 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f1200 */ + 19159, /* A1 = -1.169373 */ + -32456, /* A2 = 0.990509 */ + -335, /* B2 = -0.010252 */ + 0, /* B1 = 0.000000 */ + 335, /* B0 = 0.010252 */ + 18966, /* A1 = -1.157593 */ + -32661, /* A2 = 0.996735 */ + 6802, /* B2 = 0.207588 */ + -3900, /* B1 = -0.238098 */ + 6802, /* B0 = 0.207588 */ + 19467, /* A1 = -1.188232 */ + -32661, /* A2 = 0.996765 */ + 25035, /* B2 = 0.764008 */ + -15049, /* B1 = -0.918579 */ + 25035, /* B0 = 0.764008 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f1209 */ + 18976, /* A1 = -1.158264 */ + -32439, /* A2 = 0.989990 */ + -183, /* B2 = -0.005588 */ + 0, /* B1 = 0.000000 */ + 183, /* B0 = 0.005588 */ + 18774, /* A1 = -1.145874 */ + -32650, /* A2 = 0.996429 */ + 15468, /* B2 = 0.472076 */ + -8768, /* B1 = -0.535217 */ + 15468, /* B0 = 0.472076 */ + 19300, /* A1 = -1.177979 */ + -32652, /* A2 = 0.996490 */ + 19840, /* B2 = 0.605499 */ + -11842, /* B1 = -0.722809 */ + 19840, /* B0 = 0.605499 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f1330 */ + 16357, /* A1 = -0.998413 */ + -32368, /* A2 = 0.987793 */ + -217, /* B2 = -0.006652 */ + 0, /* B1 = 0.000000 */ + 217, /* B0 = 0.006652 */ + 16107, /* A1 = -0.983126 */ + -32601, /* A2 = 0.994904 */ + 11602, /* B2 = 0.354065 */ + -5555, /* B1 = -0.339111 */ + 11602, /* B0 = 0.354065 */ + 16722, /* A1 = -1.020630 */ + -32603, /* A2 = 0.994965 */ + 15574, /* B2 = 0.475311 */ + -8176, /* B1 = -0.499069 */ + 15574, /* B0 = 0.475311 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f1336 */ + 16234, /* A1 = -0.990875 */ + 32404, /* A2 = -0.988922 */ + -193, /* B2 = -0.005908 */ + 0, /* B1 = 0.000000 */ + 193, /* B0 = 0.005908 */ + 15986, /* A1 = -0.975769 */ + -32632, /* A2 = 0.995880 */ + 18051, /* B2 = 0.550903 */ + -8658, /* B1 = -0.528473 */ + 18051, /* B0 = 0.550903 */ + 16591, /* A1 = -1.012695 */ + -32634, /* A2 = 0.995941 */ + 15736, /* B2 = 0.480240 */ + -8125, /* B1 = -0.495926 */ + 15736, /* B0 = 0.480240 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f1366 */ + 15564, /* A1 = -0.949982 */ + -32404, /* A2 = 0.988922 */ + -269, /* B2 = -0.008216 */ + 0, /* B1 = 0.000000 */ + 269, /* B0 = 0.008216 */ + 15310, /* A1 = -0.934479 */ + -32632, /* A2 = 0.995880 */ + 10815, /* B2 = 0.330063 */ + -4962, /* B1 = -0.302887 */ + 10815, /* B0 = 0.330063 */ + 15924, /* A1 = -0.971924 */ + -32634, /* A2 = 0.995941 */ + 18880, /* B2 = 0.576172 */ + -9364, /* B1 = -0.571594 */ + 18880, /* B0 = 0.576172 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f1380 */ + 15247, /* A1 = -0.930603 */ + -32397, /* A2 = 0.988708 */ + -244, /* B2 = -0.007451 */ + 0, /* B1 = 0.000000 */ + 244, /* B0 = 0.007451 */ + 14989, /* A1 = -0.914886 */ + -32627, /* A2 = 0.995697 */ + 18961, /* B2 = 0.578644 */ + -8498, /* B1 = -0.518707 */ + 18961, /* B0 = 0.578644 */ + 15608, /* A1 = -0.952667 */ + -32628, /* A2 = 0.995758 */ + 11145, /* B2 = 0.340134 */ + -5430, /* B1 = -0.331467 */ + 11145, /* B0 = 0.340134 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f1400 */ + 14780, /* A1 = -0.902130 */ + -32393, /* A2 = 0.988586 */ + -396, /* B2 = -0.012086 */ + 0, /* B1 = 0.000000 */ + 396, /* B0 = 0.012086 */ + 14510, /* A1 = -0.885651 */ + -32630, /* A2 = 0.995819 */ + 6326, /* B2 = 0.193069 */ + -2747, /* B1 = -0.167671 */ + 6326, /* B0 = 0.193069 */ + 15154, /* A1 = -0.924957 */ + -32632, /* A2 = 0.995850 */ + 23235, /* B2 = 0.709076 */ + -10983, /* B1 = -0.670380 */ + 23235, /* B0 = 0.709076 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f1477 */ + 13005, /* A1 = -0.793793 */ + -32368, /* A2 = 0.987823 */ + -500, /* B2 = -0.015265 */ + 0, /* B1 = 0.000000 */ + 500, /* B0 = 0.015265 */ + 12708, /* A1 = -0.775665 */ + -32615, /* A2 = 0.995331 */ + 11420, /* B2 = 0.348526 */ + -4306, /* B1 = -0.262833 */ + 11420, /* B0 = 0.348526 */ + 13397, /* A1 = -0.817688 */ + -32615, /* A2 = 0.995361 */ + 9454, /* B2 = 0.288528 */ + -3981, /* B1 = -0.243027 */ + 9454, /* B0 = 0.288528 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f1600 */ + 10046, /* A1 = -0.613190 */ + -32331, /* A2 = 0.986694 */ + -455, /* B2 = -0.013915 */ + 0, /* B1 = 0.000000 */ + 455, /* B0 = 0.013915 */ + 9694, /* A1 = -0.591705 */ + -32601, /* A2 = 0.994934 */ + 6023, /* B2 = 0.183815 */ + -1708, /* B1 = -0.104279 */ + 6023, /* B0 = 0.183815 */ + 10478, /* A1 = -0.639587 */ + -32603, /* A2 = 0.994965 */ + 22031, /* B2 = 0.672333 */ + -7342, /* B1 = -0.448151 */ + 22031, /* B0 = 0.672333 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f1633_1638[] */ + 9181, /* A1 = 0.560394 */ + -32256, /* A2 = -0.984375 */ + -556, /* B2 = -0.016975 */ + 0, /* B1 = 0 */ + 556, /* B0 = 0.016975 */ + 8757, /* A1 = 0.534515 */ + -32574, /* A2 = -0.99408 */ + 8443, /* B2 = 0.25769 */ + -2135, /* B1 = -0.130341 */ + 8443, /* B0 = 0.25769 */ + 9691, /* A1 = 0.591522 */ + -32574, /* A2 = -0.99411 */ + 15446, /* B2 = 0.471375 */ + -4809, /* B1 = -0.293579 */ + 15446, /* B0 = 0.471375 */ + 7, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f1800 */ + 5076, /* A1 = -0.309875 */ + -32304, /* A2 = 0.985840 */ + -508, /* B2 = -0.015503 */ + 0, /* B1 = 0.000000 */ + 508, /* B0 = 0.015503 */ + 4646, /* A1 = -0.283600 */ + -32605, /* A2 = 0.995026 */ + 6742, /* B2 = 0.205780 */ + -878, /* B1 = -0.053635 */ + 6742, /* B0 = 0.205780 */ + 5552, /* A1 = -0.338928 */ + -32605, /* A2 = 0.995056 */ + 23667, /* B2 = 0.722260 */ + -4297, /* B1 = -0.262329 */ + 23667, /* B0 = 0.722260 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, + { /* f1860 */ + 3569, /* A1 = -0.217865 */ + -32292, /* A2 = 0.985504 */ + -239, /* B2 = -0.007322 */ + 0, /* B1 = 0.000000 */ + 239, /* B0 = 0.007322 */ + 3117, /* A1 = -0.190277 */ + -32603, /* A2 = 0.994965 */ + 18658, /* B2 = 0.569427 */ + -1557, /* B1 = -0.095032 */ + 18658, /* B0 = 0.569427 */ + 4054, /* A1 = -0.247437 */ + -32603, /* A2 = 0.994965 */ + 18886, /* B2 = 0.576385 */ + -2566, /* B1 = -0.156647 */ + 18886, /* B0 = 0.576385 */ + 5, /* Internal filter scaling */ + 159, /* Minimum in-band energy threshold */ + 21, /* 21/32 in-band to broad-band ratio */ + 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ + }, +}; +static int ixj_init_filter(IXJ *j, IXJ_FILTER * jf) +{ + unsigned short cmd; + int cnt, max; + + if (jf->filter > 3) { + return -1; + } + if (ixj_WriteDSPCommand(0x5154 + jf->filter, j)) /* Select Filter */ + + return -1; + if (!jf->enable) { + if (ixj_WriteDSPCommand(0x5152, j)) /* Disable Filter */ + + return -1; + else + return 0; + } else { + if (ixj_WriteDSPCommand(0x5153, j)) /* Enable Filter */ + + return -1; + /* Select the filter (f0 - f3) to use. */ + if (ixj_WriteDSPCommand(0x5154 + jf->filter, j)) + return -1; + } + if (jf->freq < 12 && jf->freq > 3) { + /* Select the frequency for the selected filter. */ + if (ixj_WriteDSPCommand(0x5170 + jf->freq, j)) + return -1; + } else if (jf->freq > 11) { + /* We need to load a programmable filter set for undefined */ + /* frequencies. So we will point the filter to a programmable set. */ + /* Since there are only 4 filters and 4 programmable sets, we will */ + /* just point the filter to the same number set and program it for the */ + /* frequency we want. */ + if (ixj_WriteDSPCommand(0x5170 + jf->filter, j)) + return -1; + if (j->ver.low != 0x12) { + cmd = 0x515B; + max = 19; + } else { + cmd = 0x515E; + max = 15; + } + if (ixj_WriteDSPCommand(cmd, j)) + return -1; + for (cnt = 0; cnt < max; cnt++) { + if (ixj_WriteDSPCommand(tone_table[jf->freq - 12][cnt], j)) + return -1; + } + } + j->filter_en[jf->filter] = jf->enable; + return 0; +} + +static int ixj_init_filter_raw(IXJ *j, IXJ_FILTER_RAW * jfr) +{ + unsigned short cmd; + int cnt, max; + if (jfr->filter > 3) { + return -1; + } + if (ixj_WriteDSPCommand(0x5154 + jfr->filter, j)) /* Select Filter */ + return -1; + + if (!jfr->enable) { + if (ixj_WriteDSPCommand(0x5152, j)) /* Disable Filter */ + return -1; + else + return 0; + } else { + if (ixj_WriteDSPCommand(0x5153, j)) /* Enable Filter */ + return -1; + /* Select the filter (f0 - f3) to use. */ + if (ixj_WriteDSPCommand(0x5154 + jfr->filter, j)) + return -1; + } + /* We need to load a programmable filter set for undefined */ + /* frequencies. So we will point the filter to a programmable set. */ + /* Since there are only 4 filters and 4 programmable sets, we will */ + /* just point the filter to the same number set and program it for the */ + /* frequency we want. */ + if (ixj_WriteDSPCommand(0x5170 + jfr->filter, j)) + return -1; + if (j->ver.low != 0x12) { + cmd = 0x515B; + max = 19; + } else { + cmd = 0x515E; + max = 15; + } + if (ixj_WriteDSPCommand(cmd, j)) + return -1; + for (cnt = 0; cnt < max; cnt++) { + if (ixj_WriteDSPCommand(jfr->coeff[cnt], j)) + return -1; + } + j->filter_en[jfr->filter] = jfr->enable; + return 0; +} + +static int ixj_init_tone(IXJ *j, IXJ_TONE * ti) +{ + int freq0, freq1; + unsigned short data; + if (ti->freq0) { + freq0 = ti->freq0; + } else { + freq0 = 0x7FFF; + } + + if (ti->freq1) { + freq1 = ti->freq1; + } else { + freq1 = 0x7FFF; + } + + if(ti->tone_index > 12 && ti->tone_index < 28) + { + if (ixj_WriteDSPCommand(0x6800 + ti->tone_index, j)) + return -1; + if (ixj_WriteDSPCommand(0x6000 + (ti->gain1 << 4) + ti->gain0, j)) + return -1; + data = freq0; + if (ixj_WriteDSPCommand(data, j)) + return -1; + data = freq1; + if (ixj_WriteDSPCommand(data, j)) + return -1; + } + return freq0; +} + diff --git a/drivers/staging/telephony/ixj.h b/drivers/staging/telephony/ixj.h new file mode 100644 index 0000000..2c84113 --- /dev/null +++ b/drivers/staging/telephony/ixj.h @@ -0,0 +1,1322 @@ +/****************************************************************************** + * ixj.h + * + * + * Device Driver for Quicknet Technologies, Inc.'s Telephony cards + * including the Internet PhoneJACK, Internet PhoneJACK Lite, + * Internet PhoneJACK PCI, Internet LineJACK, Internet PhoneCARD and + * SmartCABLE + * + * (c) Copyright 1999-2001 Quicknet Technologies, Inc. + * + * 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. + * + * Author: Ed Okerson, + * + * Contributors: Greg Herlein, + * David W. Erhart, + * John Sellers, + * Mike Preston, + * + * More information about the hardware related to this driver can be found + * at our website: http://www.quicknet.net + * + * Fixes: + * + * IN NO EVENT SHALL QUICKNET TECHNOLOGIES, INC. BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF QUICKNET + * TECHNOLOGIES, INC.HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * QUICKNET TECHNOLOGIES, INC. SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND QUICKNET TECHNOLOGIES, INC. HAS NO OBLIGATION + * TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + *****************************************************************************/ +#define IXJ_VERSION 3031 + +#include + +#include +#include + +typedef __u16 WORD; +typedef __u32 DWORD; +typedef __u8 BYTE; + +#ifndef IXJMAX +#define IXJMAX 16 +#endif + +/****************************************************************************** +* +* This structure when unioned with the structures below makes simple byte +* access to the registers easier. +* +******************************************************************************/ +typedef struct { + unsigned char low; + unsigned char high; +} BYTES; + +typedef union { + BYTES bytes; + short word; +} IXJ_WORD; + +typedef struct{ + unsigned int b0:1; + unsigned int b1:1; + unsigned int b2:1; + unsigned int b3:1; + unsigned int b4:1; + unsigned int b5:1; + unsigned int b6:1; + unsigned int b7:1; +} IXJ_CBITS; + +typedef union{ + IXJ_CBITS cbits; + char cbyte; +} IXJ_CBYTE; + +/****************************************************************************** +* +* This structure represents the Hardware Control Register of the CT8020/8021 +* The CT8020 is used in the Internet PhoneJACK, and the 8021 in the +* Internet LineJACK +* +******************************************************************************/ +typedef struct { + unsigned int rxrdy:1; + unsigned int txrdy:1; + unsigned int status:1; + unsigned int auxstatus:1; + unsigned int rxdma:1; + unsigned int txdma:1; + unsigned int rxburst:1; + unsigned int txburst:1; + unsigned int dmadir:1; + unsigned int cont:1; + unsigned int irqn:1; + unsigned int t:5; +} HCRBIT; + +typedef union { + HCRBIT bits; + BYTES bytes; +} HCR; + +/****************************************************************************** +* +* This structure represents the Hardware Status Register of the CT8020/8021 +* The CT8020 is used in the Internet PhoneJACK, and the 8021 in the +* Internet LineJACK +* +******************************************************************************/ +typedef struct { + unsigned int controlrdy:1; + unsigned int auxctlrdy:1; + unsigned int statusrdy:1; + unsigned int auxstatusrdy:1; + unsigned int rxrdy:1; + unsigned int txrdy:1; + unsigned int restart:1; + unsigned int irqn:1; + unsigned int rxdma:1; + unsigned int txdma:1; + unsigned int cohostshutdown:1; + unsigned int t:5; +} HSRBIT; + +typedef union { + HSRBIT bits; + BYTES bytes; +} HSR; + +/****************************************************************************** +* +* This structure represents the General Purpose IO Register of the CT8020/8021 +* The CT8020 is used in the Internet PhoneJACK, and the 8021 in the +* Internet LineJACK +* +******************************************************************************/ +typedef struct { + unsigned int x:1; + unsigned int gpio1:1; + unsigned int gpio2:1; + unsigned int gpio3:1; + unsigned int gpio4:1; + unsigned int gpio5:1; + unsigned int gpio6:1; + unsigned int gpio7:1; + unsigned int xread:1; + unsigned int gpio1read:1; + unsigned int gpio2read:1; + unsigned int gpio3read:1; + unsigned int gpio4read:1; + unsigned int gpio5read:1; + unsigned int gpio6read:1; + unsigned int gpio7read:1; +} GPIOBIT; + +typedef union { + GPIOBIT bits; + BYTES bytes; + unsigned short word; +} GPIO; + +/****************************************************************************** +* +* This structure represents the Line Monitor status response +* +******************************************************************************/ +typedef struct { + unsigned int digit:4; + unsigned int cpf_valid:1; + unsigned int dtmf_valid:1; + unsigned int peak:1; + unsigned int z:1; + unsigned int f0:1; + unsigned int f1:1; + unsigned int f2:1; + unsigned int f3:1; + unsigned int frame:4; +} LMON; + +typedef union { + LMON bits; + BYTES bytes; +} DTMF; + +typedef struct { + unsigned int z:7; + unsigned int dtmf_en:1; + unsigned int y:4; + unsigned int F3:1; + unsigned int F2:1; + unsigned int F1:1; + unsigned int F0:1; +} CP; + +typedef union { + CP bits; + BYTES bytes; +} CPTF; + +/****************************************************************************** +* +* This structure represents the Status Control Register on the Internet +* LineJACK +* +******************************************************************************/ +typedef struct { + unsigned int c0:1; + unsigned int c1:1; + unsigned int stereo:1; + unsigned int daafsyncen:1; + unsigned int led1:1; + unsigned int led2:1; + unsigned int led3:1; + unsigned int led4:1; +} PSCRWI; /* Internet LineJACK and Internet PhoneJACK Lite */ + +typedef struct { + unsigned int eidp:1; + unsigned int eisd:1; + unsigned int x:6; +} PSCRWP; /* Internet PhoneJACK PCI */ + +typedef union { + PSCRWI bits; + PSCRWP pcib; + char byte; +} PLD_SCRW; + +typedef struct { + unsigned int c0:1; + unsigned int c1:1; + unsigned int x:1; + unsigned int d0ee:1; + unsigned int mixerbusy:1; + unsigned int sci:1; + unsigned int dspflag:1; + unsigned int daaflag:1; +} PSCRRI; + +typedef struct { + unsigned int eidp:1; + unsigned int eisd:1; + unsigned int x:4; + unsigned int dspflag:1; + unsigned int det:1; +} PSCRRP; + +typedef union { + PSCRRI bits; + PSCRRP pcib; + char byte; +} PLD_SCRR; + +/****************************************************************************** +* +* These structures represents the SLIC Control Register on the +* Internet LineJACK +* +******************************************************************************/ +typedef struct { + unsigned int c1:1; + unsigned int c2:1; + unsigned int c3:1; + unsigned int b2en:1; + unsigned int spken:1; + unsigned int rly1:1; + unsigned int rly2:1; + unsigned int rly3:1; +} PSLICWRITE; + +typedef struct { + unsigned int state:3; + unsigned int b2en:1; + unsigned int spken:1; + unsigned int c3:1; + unsigned int potspstn:1; + unsigned int det:1; +} PSLICREAD; + +typedef struct { + unsigned int c1:1; + unsigned int c2:1; + unsigned int c3:1; + unsigned int b2en:1; + unsigned int e1:1; + unsigned int mic:1; + unsigned int spk:1; + unsigned int x:1; +} PSLICPCI; + +typedef union { + PSLICPCI pcib; + PSLICWRITE bits; + PSLICREAD slic; + char byte; +} PLD_SLICW; + +typedef union { + PSLICPCI pcib; + PSLICREAD bits; + char byte; +} PLD_SLICR; + +/****************************************************************************** +* +* These structures represents the Clock Control Register on the +* Internet LineJACK +* +******************************************************************************/ +typedef struct { + unsigned int clk0:1; + unsigned int clk1:1; + unsigned int clk2:1; + unsigned int x0:1; + unsigned int slic_e1:1; + unsigned int x1:1; + unsigned int x2:1; + unsigned int x3:1; +} PCLOCK; + +typedef union { + PCLOCK bits; + char byte; +} PLD_CLOCK; + +/****************************************************************************** +* +* These structures deal with the mixer on the Internet LineJACK +* +******************************************************************************/ + +typedef struct { + unsigned short vol[10]; + unsigned int recsrc; + unsigned int modcnt; + unsigned short micpreamp; +} MIX; + +/****************************************************************************** +* +* These structures deal with the control logic on the Internet PhoneCARD +* +******************************************************************************/ +typedef struct { + unsigned int x0:4; /* unused bits */ + + unsigned int ed:1; /* Event Detect */ + + unsigned int drf:1; /* SmartCABLE Removal Flag 1=no cable */ + + unsigned int dspf:1; /* DSP Flag 1=DSP Ready */ + + unsigned int crr:1; /* Control Register Ready */ + +} COMMAND_REG1; + +typedef union { + COMMAND_REG1 bits; + unsigned char byte; +} PCMCIA_CR1; + +typedef struct { + unsigned int x0:4; /* unused bits */ + + unsigned int rstc:1; /* SmartCABLE Reset */ + + unsigned int pwr:1; /* SmartCABLE Power */ + + unsigned int x1:2; /* unused bits */ + +} COMMAND_REG2; + +typedef union { + COMMAND_REG2 bits; + unsigned char byte; +} PCMCIA_CR2; + +typedef struct { + unsigned int addr:5; /* R/W SmartCABLE Register Address */ + + unsigned int rw:1; /* Read / Write flag */ + + unsigned int dev:2; /* 2 bit SmartCABLE Device Address */ + +} CONTROL_REG; + +typedef union { + CONTROL_REG bits; + unsigned char byte; +} PCMCIA_SCCR; + +typedef struct { + unsigned int hsw:1; + unsigned int det:1; + unsigned int led2:1; + unsigned int led1:1; + unsigned int ring1:1; + unsigned int ring0:1; + unsigned int x:1; + unsigned int powerdown:1; +} PCMCIA_SLIC_REG; + +typedef union { + PCMCIA_SLIC_REG bits; + unsigned char byte; +} PCMCIA_SLIC; + +typedef struct { + unsigned int cpd:1; /* Chip Power Down */ + + unsigned int mpd:1; /* MIC Bias Power Down */ + + unsigned int hpd:1; /* Handset Drive Power Down */ + + unsigned int lpd:1; /* Line Drive Power Down */ + + unsigned int spd:1; /* Speaker Drive Power Down */ + + unsigned int x:2; /* unused bits */ + + unsigned int sr:1; /* Software Reset */ + +} Si3CONTROL1; + +typedef union { + Si3CONTROL1 bits; + unsigned char byte; +} Si3C1; + +typedef struct { + unsigned int al:1; /* Analog Loopback DAC analog -> ADC analog */ + + unsigned int dl2:1; /* Digital Loopback DAC -> ADC one bit */ + + unsigned int dl1:1; /* Digital Loopback ADC -> DAC one bit */ + + unsigned int pll:1; /* 1 = div 10, 0 = div 5 */ + + unsigned int hpd:1; /* HPF disable */ + + unsigned int x:3; /* unused bits */ + +} Si3CONTROL2; + +typedef union { + Si3CONTROL2 bits; + unsigned char byte; +} Si3C2; + +typedef struct { + unsigned int iir:1; /* 1 enables IIR, 0 enables FIR */ + + unsigned int him:1; /* Handset Input Mute */ + + unsigned int mcm:1; /* MIC In Mute */ + + unsigned int mcg:2; /* MIC In Gain */ + + unsigned int lim:1; /* Line In Mute */ + + unsigned int lig:2; /* Line In Gain */ + +} Si3RXGAIN; + +typedef union { + Si3RXGAIN bits; + unsigned char byte; +} Si3RXG; + +typedef struct { + unsigned int hom:1; /* Handset Out Mute */ + + unsigned int lom:1; /* Line Out Mute */ + + unsigned int rxg:5; /* RX PGA Gain */ + + unsigned int x:1; /* unused bit */ + +} Si3ADCVOLUME; + +typedef union { + Si3ADCVOLUME bits; + unsigned char byte; +} Si3ADC; + +typedef struct { + unsigned int srm:1; /* Speaker Right Mute */ + + unsigned int slm:1; /* Speaker Left Mute */ + + unsigned int txg:5; /* TX PGA Gain */ + + unsigned int x:1; /* unused bit */ + +} Si3DACVOLUME; + +typedef union { + Si3DACVOLUME bits; + unsigned char byte; +} Si3DAC; + +typedef struct { + unsigned int x:5; /* unused bit */ + + unsigned int losc:1; /* Line Out Short Circuit */ + + unsigned int srsc:1; /* Speaker Right Short Circuit */ + + unsigned int slsc:1; /* Speaker Left Short Circuit */ + +} Si3STATUSREPORT; + +typedef union { + Si3STATUSREPORT bits; + unsigned char byte; +} Si3STAT; + +typedef struct { + unsigned int sot:2; /* Speaker Out Attenuation */ + + unsigned int lot:2; /* Line Out Attenuation */ + + unsigned int x:4; /* unused bits */ + +} Si3ANALOGATTN; + +typedef union { + Si3ANALOGATTN bits; + unsigned char byte; +} Si3AATT; + +/****************************************************************************** +* +* These structures deal with the DAA on the Internet LineJACK +* +******************************************************************************/ + +typedef struct _DAA_REGS { + /*----------------------------------------------- */ + /* SOP Registers */ + /* */ + BYTE bySOP; + + union _SOP_REGS { + struct _SOP { + union /* SOP - CR0 Register */ + { + BYTE reg; + struct _CR0_BITREGS { + BYTE CLK_EXT:1; /* cr0[0:0] */ + + BYTE RIP:1; /* cr0[1:1] */ + + BYTE AR:1; /* cr0[2:2] */ + + BYTE AX:1; /* cr0[3:3] */ + + BYTE FRR:1; /* cr0[4:4] */ + + BYTE FRX:1; /* cr0[5:5] */ + + BYTE IM:1; /* cr0[6:6] */ + + BYTE TH:1; /* cr0[7:7] */ + + } bitreg; + } cr0; + + union /* SOP - CR1 Register */ + { + BYTE reg; + struct _CR1_REGS { + BYTE RM:1; /* cr1[0:0] */ + + BYTE RMR:1; /* cr1[1:1] */ + + BYTE No_auto:1; /* cr1[2:2] */ + + BYTE Pulse:1; /* cr1[3:3] */ + + BYTE P_Tone1:1; /* cr1[4:4] */ + + BYTE P_Tone2:1; /* cr1[5:5] */ + + BYTE E_Tone1:1; /* cr1[6:6] */ + + BYTE E_Tone2:1; /* cr1[7:7] */ + + } bitreg; + } cr1; + + union /* SOP - CR2 Register */ + { + BYTE reg; + struct _CR2_REGS { + BYTE Call_II:1; /* CR2[0:0] */ + + BYTE Call_I:1; /* CR2[1:1] */ + + BYTE Call_en:1; /* CR2[2:2] */ + + BYTE Call_pon:1; /* CR2[3:3] */ + + BYTE IDR:1; /* CR2[4:4] */ + + BYTE COT_R:3; /* CR2[5:7] */ + + } bitreg; + } cr2; + + union /* SOP - CR3 Register */ + { + BYTE reg; + struct _CR3_REGS { + BYTE DHP_X:1; /* CR3[0:0] */ + + BYTE DHP_R:1; /* CR3[1:1] */ + + BYTE Cal_pctl:1; /* CR3[2:2] */ + + BYTE SEL:1; /* CR3[3:3] */ + + BYTE TestLoops:4; /* CR3[4:7] */ + + } bitreg; + } cr3; + + union /* SOP - CR4 Register */ + { + BYTE reg; + struct _CR4_REGS { + BYTE Fsc_en:1; /* CR4[0:0] */ + + BYTE Int_en:1; /* CR4[1:1] */ + + BYTE AGX:2; /* CR4[2:3] */ + + BYTE AGR_R:2; /* CR4[4:5] */ + + BYTE AGR_Z:2; /* CR4[6:7] */ + + } bitreg; + } cr4; + + union /* SOP - CR5 Register */ + { + BYTE reg; + struct _CR5_REGS { + BYTE V_0:1; /* CR5[0:0] */ + + BYTE V_1:1; /* CR5[1:1] */ + + BYTE V_2:1; /* CR5[2:2] */ + + BYTE V_3:1; /* CR5[3:3] */ + + BYTE V_4:1; /* CR5[4:4] */ + + BYTE V_5:1; /* CR5[5:5] */ + + BYTE V_6:1; /* CR5[6:6] */ + + BYTE V_7:1; /* CR5[7:7] */ + + } bitreg; + } cr5; + + union /* SOP - CR6 Register */ + { + BYTE reg; + struct _CR6_REGS { + BYTE reserved:8; /* CR6[0:7] */ + + } bitreg; + } cr6; + + union /* SOP - CR7 Register */ + { + BYTE reg; + struct _CR7_REGS { + BYTE reserved:8; /* CR7[0:7] */ + + } bitreg; + } cr7; + } SOP; + + BYTE ByteRegs[sizeof(struct _SOP)]; + + } SOP_REGS; + + /* DAA_REGS.SOP_REGS.SOP.CR5.reg */ + /* DAA_REGS.SOP_REGS.SOP.CR5.bitreg */ + /* DAA_REGS.SOP_REGS.SOP.CR5.bitreg.V_2 */ + /* DAA_REGS.SOP_REGS.ByteRegs[5] */ + + /*----------------------------------------------- */ + /* XOP Registers */ + /* */ + BYTE byXOP; + + union _XOP_REGS { + struct _XOP { + union XOPXR0/* XOP - XR0 Register - Read values */ + { + BYTE reg; + struct _XR0_BITREGS { + BYTE SI_0:1; /* XR0[0:0] - Read */ + + BYTE SI_1:1; /* XR0[1:1] - Read */ + + BYTE VDD_OK:1; /* XR0[2:2] - Read */ + + BYTE Caller_ID:1; /* XR0[3:3] - Read */ + + BYTE RING:1; /* XR0[4:4] - Read */ + + BYTE Cadence:1; /* XR0[5:5] - Read */ + + BYTE Wake_up:1; /* XR0[6:6] - Read */ + + BYTE RMR:1; /* XR0[7:7] - Read */ + + } bitreg; + } xr0; + + union /* XOP - XR1 Register */ + { + BYTE reg; + struct _XR1_BITREGS { + BYTE M_SI_0:1; /* XR1[0:0] */ + + BYTE M_SI_1:1; /* XR1[1:1] */ + + BYTE M_VDD_OK:1; /* XR1[2:2] */ + + BYTE M_Caller_ID:1; /* XR1[3:3] */ + + BYTE M_RING:1; /* XR1[4:4] */ + + BYTE M_Cadence:1; /* XR1[5:5] */ + + BYTE M_Wake_up:1; /* XR1[6:6] */ + + BYTE unused:1; /* XR1[7:7] */ + + } bitreg; + } xr1; + + union /* XOP - XR2 Register */ + { + BYTE reg; + struct _XR2_BITREGS { + BYTE CTO0:1; /* XR2[0:0] */ + + BYTE CTO1:1; /* XR2[1:1] */ + + BYTE CTO2:1; /* XR2[2:2] */ + + BYTE CTO3:1; /* XR2[3:3] */ + + BYTE CTO4:1; /* XR2[4:4] */ + + BYTE CTO5:1; /* XR2[5:5] */ + + BYTE CTO6:1; /* XR2[6:6] */ + + BYTE CTO7:1; /* XR2[7:7] */ + + } bitreg; + } xr2; + + union /* XOP - XR3 Register */ + { + BYTE reg; + struct _XR3_BITREGS { + BYTE DCR0:1; /* XR3[0:0] */ + + BYTE DCR1:1; /* XR3[1:1] */ + + BYTE DCI:1; /* XR3[2:2] */ + + BYTE DCU0:1; /* XR3[3:3] */ + + BYTE DCU1:1; /* XR3[4:4] */ + + BYTE B_off:1; /* XR3[5:5] */ + + BYTE AGB0:1; /* XR3[6:6] */ + + BYTE AGB1:1; /* XR3[7:7] */ + + } bitreg; + } xr3; + + union /* XOP - XR4 Register */ + { + BYTE reg; + struct _XR4_BITREGS { + BYTE C_0:1; /* XR4[0:0] */ + + BYTE C_1:1; /* XR4[1:1] */ + + BYTE C_2:1; /* XR4[2:2] */ + + BYTE C_3:1; /* XR4[3:3] */ + + BYTE C_4:1; /* XR4[4:4] */ + + BYTE C_5:1; /* XR4[5:5] */ + + BYTE C_6:1; /* XR4[6:6] */ + + BYTE C_7:1; /* XR4[7:7] */ + + } bitreg; + } xr4; + + union /* XOP - XR5 Register */ + { + BYTE reg; + struct _XR5_BITREGS { + BYTE T_0:1; /* XR5[0:0] */ + + BYTE T_1:1; /* XR5[1:1] */ + + BYTE T_2:1; /* XR5[2:2] */ + + BYTE T_3:1; /* XR5[3:3] */ + + BYTE T_4:1; /* XR5[4:4] */ + + BYTE T_5:1; /* XR5[5:5] */ + + BYTE T_6:1; /* XR5[6:6] */ + + BYTE T_7:1; /* XR5[7:7] */ + + } bitreg; + } xr5; + + union /* XOP - XR6 Register - Read Values */ + { + BYTE reg; + struct _XR6_BITREGS { + BYTE CPS0:1; /* XR6[0:0] */ + + BYTE CPS1:1; /* XR6[1:1] */ + + BYTE unused1:2; /* XR6[2:3] */ + + BYTE CLK_OFF:1; /* XR6[4:4] */ + + BYTE unused2:3; /* XR6[5:7] */ + + } bitreg; + } xr6; + + union /* XOP - XR7 Register */ + { + BYTE reg; + struct _XR7_BITREGS { + BYTE unused1:1; /* XR7[0:0] */ + + BYTE Vdd0:1; /* XR7[1:1] */ + + BYTE Vdd1:1; /* XR7[2:2] */ + + BYTE unused2:5; /* XR7[3:7] */ + + } bitreg; + } xr7; + } XOP; + + BYTE ByteRegs[sizeof(struct _XOP)]; + + } XOP_REGS; + + /* DAA_REGS.XOP_REGS.XOP.XR7.reg */ + /* DAA_REGS.XOP_REGS.XOP.XR7.bitreg */ + /* DAA_REGS.XOP_REGS.XOP.XR7.bitreg.Vdd0 */ + /* DAA_REGS.XOP_REGS.ByteRegs[7] */ + + /*----------------------------------------------- */ + /* COP Registers */ + /* */ + BYTE byCOP; + + union _COP_REGS { + struct _COP { + BYTE THFilterCoeff_1[8]; /* COP - TH Filter Coefficients, CODE=0, Part 1 */ + + BYTE THFilterCoeff_2[8]; /* COP - TH Filter Coefficients, CODE=1, Part 2 */ + + BYTE THFilterCoeff_3[8]; /* COP - TH Filter Coefficients, CODE=2, Part 3 */ + + BYTE RingerImpendance_1[8]; /* COP - Ringer Impendance Coefficients, CODE=3, Part 1 */ + + BYTE IMFilterCoeff_1[8]; /* COP - IM Filter Coefficients, CODE=4, Part 1 */ + + BYTE IMFilterCoeff_2[8]; /* COP - IM Filter Coefficients, CODE=5, Part 2 */ + + BYTE RingerImpendance_2[8]; /* COP - Ringer Impendance Coefficients, CODE=6, Part 2 */ + + BYTE FRRFilterCoeff[8]; /* COP - FRR Filter Coefficients, CODE=7 */ + + BYTE FRXFilterCoeff[8]; /* COP - FRX Filter Coefficients, CODE=8 */ + + BYTE ARFilterCoeff[4]; /* COP - AR Filter Coefficients, CODE=9 */ + + BYTE AXFilterCoeff[4]; /* COP - AX Filter Coefficients, CODE=10 */ + + BYTE Tone1Coeff[4]; /* COP - Tone1 Coefficients, CODE=11 */ + + BYTE Tone2Coeff[4]; /* COP - Tone2 Coefficients, CODE=12 */ + + BYTE LevelmeteringRinging[4]; /* COP - Levelmetering Ringing, CODE=13 */ + + BYTE CallerID1stTone[8]; /* COP - Caller ID 1st Tone, CODE=14 */ + + BYTE CallerID2ndTone[8]; /* COP - Caller ID 2nd Tone, CODE=15 */ + + } COP; + + BYTE ByteRegs[sizeof(struct _COP)]; + + } COP_REGS; + + /* DAA_REGS.COP_REGS.COP.XR7.Tone1Coeff[3] */ + /* DAA_REGS.COP_REGS.COP.XR7.bitreg */ + /* DAA_REGS.COP_REGS.COP.XR7.bitreg.Vdd0 */ + /* DAA_REGS.COP_REGS.ByteRegs[57] */ + + /*----------------------------------------------- */ + /* CAO Registers */ + /* */ + BYTE byCAO; + + union _CAO_REGS { + struct _CAO { + BYTE CallerID[512]; /* CAO - Caller ID Bytes */ + + } CAO; + + BYTE ByteRegs[sizeof(struct _CAO)]; + } CAO_REGS; + + union /* XOP - XR0 Register - Write values */ + { + BYTE reg; + struct _XR0_BITREGSW { + BYTE SO_0:1; /* XR1[0:0] - Write */ + + BYTE SO_1:1; /* XR1[1:1] - Write */ + + BYTE SO_2:1; /* XR1[2:2] - Write */ + + BYTE unused:5; /* XR1[3:7] - Write */ + + } bitreg; + } XOP_xr0_W; + + union /* XOP - XR6 Register - Write values */ + { + BYTE reg; + struct _XR6_BITREGSW { + BYTE unused1:4; /* XR6[0:3] */ + + BYTE CLK_OFF:1; /* XR6[4:4] */ + + BYTE unused2:3; /* XR6[5:7] */ + + } bitreg; + } XOP_xr6_W; + +} DAA_REGS; + +#define ALISDAA_ID_BYTE 0x81 +#define ALISDAA_CALLERID_SIZE 512 + +/*------------------------------ */ +/* */ +/* Misc definitions */ +/* */ + +/* Power Up Operation */ +#define SOP_PU_SLEEP 0 +#define SOP_PU_RINGING 1 +#define SOP_PU_CONVERSATION 2 +#define SOP_PU_PULSEDIALING 3 +#define SOP_PU_RESET 4 + +#define ALISDAA_CALLERID_SIZE 512 + +#define PLAYBACK_MODE_COMPRESSED 0 /* Selects: Compressed modes, TrueSpeech 8.5-4.1, G.723.1, G.722, G.728, G.729 */ +#define PLAYBACK_MODE_TRUESPEECH_V40 0 /* Selects: TrueSpeech 8.5, 6.3, 5.3, 4.8 or 4.1 Kbps */ +#define PLAYBACK_MODE_TRUESPEECH 8 /* Selects: TrueSpeech 8.5, 6.3, 5.3, 4.8 or 4.1 Kbps Version 5.1 */ +#define PLAYBACK_MODE_ULAW 2 /* Selects: 64 Kbit/sec MuA-law PCM */ +#define PLAYBACK_MODE_ALAW 10 /* Selects: 64 Kbit/sec A-law PCM */ +#define PLAYBACK_MODE_16LINEAR 6 /* Selects: 128 Kbit/sec 16-bit linear */ +#define PLAYBACK_MODE_8LINEAR 4 /* Selects: 64 Kbit/sec 8-bit signed linear */ +#define PLAYBACK_MODE_8LINEAR_WSS 5 /* Selects: 64 Kbit/sec WSS 8-bit unsigned linear */ + +#define RECORD_MODE_COMPRESSED 0 /* Selects: Compressed modes, TrueSpeech 8.5-4.1, G.723.1, G.722, G.728, G.729 */ +#define RECORD_MODE_TRUESPEECH 0 /* Selects: TrueSpeech 8.5, 6.3, 5.3, 4.8 or 4.1 Kbps */ +#define RECORD_MODE_ULAW 4 /* Selects: 64 Kbit/sec Mu-law PCM */ +#define RECORD_MODE_ALAW 12 /* Selects: 64 Kbit/sec A-law PCM */ +#define RECORD_MODE_16LINEAR 5 /* Selects: 128 Kbit/sec 16-bit linear */ +#define RECORD_MODE_8LINEAR 6 /* Selects: 64 Kbit/sec 8-bit signed linear */ +#define RECORD_MODE_8LINEAR_WSS 7 /* Selects: 64 Kbit/sec WSS 8-bit unsigned linear */ + +enum SLIC_STATES { + PLD_SLIC_STATE_OC = 0, + PLD_SLIC_STATE_RINGING, + PLD_SLIC_STATE_ACTIVE, + PLD_SLIC_STATE_OHT, + PLD_SLIC_STATE_TIPOPEN, + PLD_SLIC_STATE_STANDBY, + PLD_SLIC_STATE_APR, + PLD_SLIC_STATE_OHTPR +}; + +enum SCI_CONTROL { + SCI_End = 0, + SCI_Enable_DAA, + SCI_Enable_Mixer, + SCI_Enable_EEPROM +}; + +enum Mode { + T63, T53, T48, T40 +}; +enum Dir { + V3_TO_V4, V4_TO_V3, V4_TO_V5, V5_TO_V4 +}; + +typedef struct Proc_Info_Tag { + enum Mode convert_mode; + enum Dir convert_dir; + int Prev_Frame_Type; + int Current_Frame_Type; +} Proc_Info_Type; + +enum PREVAL { + NORMAL = 0, + NOPOST, + POSTONLY, + PREERROR +}; + +enum IXJ_EXTENSIONS { + G729LOADER = 0, + TS85LOADER, + PRE_READ, + POST_READ, + PRE_WRITE, + POST_WRITE, + PRE_IOCTL, + POST_IOCTL +}; + +typedef struct { + char enable; + char en_filter; + unsigned int filter; + unsigned int state; /* State 0 when cadence has not started. */ + + unsigned int on1; /* State 1 */ + + unsigned long on1min; /* State 1 - 10% + jiffies */ + unsigned long on1dot; /* State 1 + jiffies */ + + unsigned long on1max; /* State 1 + 10% + jiffies */ + + unsigned int off1; /* State 2 */ + + unsigned long off1min; + unsigned long off1dot; /* State 2 + jiffies */ + unsigned long off1max; + unsigned int on2; /* State 3 */ + + unsigned long on2min; + unsigned long on2dot; + unsigned long on2max; + unsigned int off2; /* State 4 */ + + unsigned long off2min; + unsigned long off2dot; /* State 4 + jiffies */ + unsigned long off2max; + unsigned int on3; /* State 5 */ + + unsigned long on3min; + unsigned long on3dot; + unsigned long on3max; + unsigned int off3; /* State 6 */ + + unsigned long off3min; + unsigned long off3dot; /* State 6 + jiffies */ + unsigned long off3max; +} IXJ_CADENCE_F; + +typedef struct { + unsigned int busytone:1; + unsigned int dialtone:1; + unsigned int ringback:1; + unsigned int ringing:1; + unsigned int playing:1; + unsigned int recording:1; + unsigned int cringing:1; + unsigned int play_first_frame:1; + unsigned int pstn_present:1; + unsigned int pstn_ringing:1; + unsigned int pots_correct:1; + unsigned int pots_pstn:1; + unsigned int g729_loaded:1; + unsigned int ts85_loaded:1; + unsigned int dtmf_oob:1; /* DTMF Out-Of-Band */ + + unsigned int pcmciascp:1; /* SmartCABLE Present */ + + unsigned int pcmciasct:2; /* SmartCABLE Type */ + + unsigned int pcmciastate:3; /* SmartCABLE Init State */ + + unsigned int inwrite:1; /* Currently writing */ + + unsigned int inread:1; /* Currently reading */ + + unsigned int incheck:1; /* Currently checking the SmartCABLE */ + + unsigned int cidplay:1; /* Currently playing Caller ID */ + + unsigned int cidring:1; /* This is the ring for Caller ID */ + + unsigned int cidsent:1; /* Caller ID has been sent */ + + unsigned int cidcw_ack:1; /* Caller ID CW ACK (from CPE) */ + unsigned int firstring:1; /* First ring cadence is complete */ + unsigned int pstncheck:1; /* Currently checking the PSTN Line */ + unsigned int pstn_rmr:1; + unsigned int x:3; /* unused bits */ + +} IXJ_FLAGS; + +/****************************************************************************** +* +* This structure holds the state of all of the Quicknet cards +* +******************************************************************************/ + +typedef struct { + int elements_used; + IXJ_CADENCE_TERM termination; + IXJ_CADENCE_ELEMENT *ce; +} ixj_cadence; + +typedef struct { + struct phone_device p; + struct timer_list timer; + unsigned int board; + unsigned int DSPbase; + unsigned int XILINXbase; + unsigned int serial; + atomic_t DSPWrite; + struct phone_capability caplist[30]; + unsigned int caps; + struct pnp_dev *dev; + unsigned int cardtype; + unsigned int rec_codec; + unsigned int cid_rec_codec; + unsigned int cid_rec_volume; + unsigned char cid_rec_flag; + signed char rec_mode; + unsigned int play_codec; + unsigned int cid_play_codec; + unsigned int cid_play_volume; + unsigned char cid_play_flag; + signed char play_mode; + IXJ_FLAGS flags; + unsigned long busyflags; + unsigned int rec_frame_size; + unsigned int play_frame_size; + unsigned int cid_play_frame_size; + unsigned int cid_base_frame_size; + unsigned long cidcw_wait; + int aec_level; + int cid_play_aec_level; + int readers, writers; + wait_queue_head_t poll_q; + wait_queue_head_t read_q; + char *read_buffer, *read_buffer_end; + char *read_convert_buffer; + size_t read_buffer_size; + unsigned int read_buffer_ready; + wait_queue_head_t write_q; + char *write_buffer, *write_buffer_end; + char *write_convert_buffer; + size_t write_buffer_size; + unsigned int write_buffers_empty; + unsigned long drybuffer; + char *write_buffer_rp, *write_buffer_wp; + char dtmfbuffer[80]; + char dtmf_current; + int dtmf_wp, dtmf_rp, dtmf_state, dtmf_proc; + int tone_off_time, tone_on_time; + struct fasync_struct *async_queue; + unsigned long tone_start_jif; + char tone_index; + char tone_state; + char maxrings; + ixj_cadence *cadence_t; + ixj_cadence *cadence_r; + int tone_cadence_state; + IXJ_CADENCE_F cadence_f[6]; + DTMF dtmf; + CPTF cptf; + BYTES dsp; + BYTES ver; + BYTES scr; + BYTES ssr; + BYTES baseframe; + HSR hsr; + GPIO gpio; + PLD_SCRR pld_scrr; + PLD_SCRW pld_scrw; + PLD_SLICW pld_slicw; + PLD_SLICR pld_slicr; + PLD_CLOCK pld_clock; + PCMCIA_CR1 pccr1; + PCMCIA_CR2 pccr2; + PCMCIA_SCCR psccr; + PCMCIA_SLIC pslic; + char pscdd; + Si3C1 sic1; + Si3C2 sic2; + Si3RXG sirxg; + Si3ADC siadc; + Si3DAC sidac; + Si3STAT sistat; + Si3AATT siaatt; + MIX mix; + unsigned short ring_cadence; + int ring_cadence_t; + unsigned long ring_cadence_jif; + unsigned long checkwait; + int intercom; + int m_hook; + int r_hook; + int p_hook; + char pstn_envelope; + char pstn_cid_intr; + unsigned char fskz; + unsigned char fskphase; + unsigned char fskcnt; + unsigned int cidsize; + unsigned int cidcnt; + unsigned long pstn_cid_received; + PHONE_CID cid; + PHONE_CID cid_send; + unsigned long pstn_ring_int; + unsigned long pstn_ring_start; + unsigned long pstn_ring_stop; + unsigned long pstn_winkstart; + unsigned long pstn_last_rmr; + unsigned long pstn_prev_rmr; + unsigned long pots_winkstart; + unsigned int winktime; + unsigned long flash_end; + char port; + char hookstate; + union telephony_exception ex; + union telephony_exception ex_sig; + int ixj_signals[35]; + IXJ_SIGDEF sigdef; + char daa_mode; + char daa_country; + unsigned long pstn_sleeptil; + DAA_REGS m_DAAShadowRegs; + Proc_Info_Type Info_read; + Proc_Info_Type Info_write; + unsigned short frame_count; + unsigned int filter_hist[4]; + unsigned char filter_en[6]; + unsigned short proc_load; + unsigned long framesread; + unsigned long frameswritten; + unsigned long read_wait; + unsigned long write_wait; + unsigned long timerchecks; + unsigned long txreadycheck; + unsigned long rxreadycheck; + unsigned long statuswait; + unsigned long statuswaitfail; + unsigned long pcontrolwait; + unsigned long pcontrolwaitfail; + unsigned long iscontrolready; + unsigned long iscontrolreadyfail; + unsigned long pstnstatecheck; +#ifdef IXJ_DYN_ALLOC + short *fskdata; +#else + short fskdata[8000]; +#endif + int fsksize; + int fskdcnt; +} IXJ; + +typedef int (*IXJ_REGFUNC) (IXJ * j, unsigned long arg); + +extern IXJ *ixj_pcmcia_probe(unsigned long, unsigned long); + diff --git a/drivers/staging/telephony/ixj_pcmcia.c b/drivers/staging/telephony/ixj_pcmcia.c new file mode 100644 index 0000000..05032e2 --- /dev/null +++ b/drivers/staging/telephony/ixj_pcmcia.c @@ -0,0 +1,187 @@ +#include "ixj-ver.h" + +#include + +#include +#include /* printk() */ +#include /* everything... */ +#include /* error codes */ +#include + +#include +#include + +#include "ixj.h" + +/* + * PCMCIA service support for Quicknet cards + */ + + +typedef struct ixj_info_t { + int ndev; + struct ixj *port; +} ixj_info_t; + +static void ixj_detach(struct pcmcia_device *p_dev); +static int ixj_config(struct pcmcia_device * link); +static void ixj_cs_release(struct pcmcia_device * link); + +static int ixj_probe(struct pcmcia_device *p_dev) +{ + dev_dbg(&p_dev->dev, "ixj_attach()\n"); + /* Create new ixj device */ + p_dev->priv = kzalloc(sizeof(struct ixj_info_t), GFP_KERNEL); + if (!p_dev->priv) { + return -ENOMEM; + } + + return ixj_config(p_dev); +} + +static void ixj_detach(struct pcmcia_device *link) +{ + dev_dbg(&link->dev, "ixj_detach\n"); + + ixj_cs_release(link); + + kfree(link->priv); +} + +static void ixj_get_serial(struct pcmcia_device * link, IXJ * j) +{ + char *str; + int i, place; + dev_dbg(&link->dev, "ixj_get_serial\n"); + + str = link->prod_id[0]; + if (!str) + goto failed; + printk("%s", str); + str = link->prod_id[1]; + if (!str) + goto failed; + printk(" %s", str); + str = link->prod_id[2]; + if (!str) + goto failed; + place = 1; + for (i = strlen(str) - 1; i >= 0; i--) { + switch (str[i]) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + j->serial += (str[i] - 48) * place; + break; + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + j->serial += (str[i] - 55) * place; + break; + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + j->serial += (str[i] - 87) * place; + break; + } + place = place * 0x10; + } + str = link->prod_id[3]; + if (!str) + goto failed; + printk(" version %s\n", str); +failed: + return; +} + +static int ixj_config_check(struct pcmcia_device *p_dev, void *priv_data) +{ + p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; + p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; + p_dev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH; + p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8; + p_dev->io_lines = 3; + + return pcmcia_request_io(p_dev); +} + +static int ixj_config(struct pcmcia_device * link) +{ + IXJ *j; + ixj_info_t *info; + + info = link->priv; + dev_dbg(&link->dev, "ixj_config\n"); + + link->config_flags = CONF_AUTO_SET_IO; + + if (pcmcia_loop_config(link, ixj_config_check, NULL)) + goto failed; + + if (pcmcia_enable_device(link)) + goto failed; + + /* + * Register the card with the core. + */ + j = ixj_pcmcia_probe(link->resource[0]->start, + link->resource[0]->start + 0x10); + + info->ndev = 1; + ixj_get_serial(link, j); + return 0; + +failed: + ixj_cs_release(link); + return -ENODEV; +} + +static void ixj_cs_release(struct pcmcia_device *link) +{ + ixj_info_t *info = link->priv; + dev_dbg(&link->dev, "ixj_cs_release\n"); + info->ndev = 0; + pcmcia_disable_device(link); +} + +static const struct pcmcia_device_id ixj_ids[] = { + PCMCIA_DEVICE_MANF_CARD(0x0257, 0x0600), + PCMCIA_DEVICE_NULL +}; +MODULE_DEVICE_TABLE(pcmcia, ixj_ids); + +static struct pcmcia_driver ixj_driver = { + .owner = THIS_MODULE, + .name = "ixj_cs", + .probe = ixj_probe, + .remove = ixj_detach, + .id_table = ixj_ids, +}; + +static int __init ixj_pcmcia_init(void) +{ + return pcmcia_register_driver(&ixj_driver); +} + +static void ixj_pcmcia_exit(void) +{ + pcmcia_unregister_driver(&ixj_driver); +} + +module_init(ixj_pcmcia_init); +module_exit(ixj_pcmcia_exit); + +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/telephony/phonedev.c b/drivers/staging/telephony/phonedev.c new file mode 100644 index 0000000..1915af2 --- /dev/null +++ b/drivers/staging/telephony/phonedev.c @@ -0,0 +1,167 @@ +/* + * Telephony registration for Linux + * + * (c) Copyright 1999 Red Hat Software Inc. + * + * 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. + * + * Author: Alan Cox, + * + * Fixes: Mar 01 2000 Thomas Sparr, + * phone_register_device now works with unit!=PHONE_UNIT_ANY + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define PHONE_NUM_DEVICES 256 + +/* + * Active devices + */ + +static struct phone_device *phone_device[PHONE_NUM_DEVICES]; +static DEFINE_MUTEX(phone_lock); + +/* + * Open a phone device. + */ + +static int phone_open(struct inode *inode, struct file *file) +{ + unsigned int minor = iminor(inode); + int err = 0; + struct phone_device *p; + const struct file_operations *old_fops, *new_fops = NULL; + + if (minor >= PHONE_NUM_DEVICES) + return -ENODEV; + + mutex_lock(&phone_lock); + p = phone_device[minor]; + if (p) + new_fops = fops_get(p->f_op); + if (!new_fops) { + mutex_unlock(&phone_lock); + request_module("char-major-%d-%d", PHONE_MAJOR, minor); + mutex_lock(&phone_lock); + p = phone_device[minor]; + if (p == NULL || (new_fops = fops_get(p->f_op)) == NULL) + { + err=-ENODEV; + goto end; + } + } + old_fops = file->f_op; + file->f_op = new_fops; + if (p->open) + err = p->open(p, file); /* Tell the device it is open */ + if (err) { + fops_put(file->f_op); + file->f_op = fops_get(old_fops); + } + fops_put(old_fops); +end: + mutex_unlock(&phone_lock); + return err; +} + +/* + * Telephony For Linux device drivers request registration here. + */ + +int phone_register_device(struct phone_device *p, int unit) +{ + int base; + int end; + int i; + + base = 0; + end = PHONE_NUM_DEVICES - 1; + + if (unit != PHONE_UNIT_ANY) { + base = unit; + end = unit + 1; /* enter the loop at least one time */ + } + + mutex_lock(&phone_lock); + for (i = base; i < end; i++) { + if (phone_device[i] == NULL) { + phone_device[i] = p; + p->minor = i; + mutex_unlock(&phone_lock); + return 0; + } + } + mutex_unlock(&phone_lock); + return -ENFILE; +} + +/* + * Unregister an unused Telephony for linux device + */ + +void phone_unregister_device(struct phone_device *pfd) +{ + mutex_lock(&phone_lock); + if (likely(phone_device[pfd->minor] == pfd)) + phone_device[pfd->minor] = NULL; + mutex_unlock(&phone_lock); +} + + +static const struct file_operations phone_fops = +{ + .owner = THIS_MODULE, + .open = phone_open, + .llseek = noop_llseek, +}; + +/* + * Board init functions + */ + + +/* + * Initialise Telephony for linux + */ + +static int __init telephony_init(void) +{ + printk(KERN_INFO "Linux telephony interface: v1.00\n"); + if (register_chrdev(PHONE_MAJOR, "telephony", &phone_fops)) { + printk("phonedev: unable to get major %d\n", PHONE_MAJOR); + return -EIO; + } + + return 0; +} + +static void __exit telephony_exit(void) +{ + unregister_chrdev(PHONE_MAJOR, "telephony"); +} + +module_init(telephony_init); +module_exit(telephony_exit); + +MODULE_LICENSE("GPL"); + +EXPORT_SYMBOL(phone_register_device); +EXPORT_SYMBOL(phone_unregister_device); diff --git a/drivers/telephony/Kconfig b/drivers/telephony/Kconfig deleted file mode 100644 index b5f78b6..0000000 --- a/drivers/telephony/Kconfig +++ /dev/null @@ -1,47 +0,0 @@ -# -# Telephony device configuration -# - -menuconfig PHONE - tristate "Telephony support" - depends on HAS_IOMEM - ---help--- - Say Y here if you have a telephony card, which for example allows - you to use a regular phone for voice-over-IP applications. - - Note: this has nothing to do with modems. You do not need to say Y - here in order to be able to use a modem under Linux. - - To compile this driver as a module, choose M here: the - module will be called phonedev. - -if PHONE - -config PHONE_IXJ - tristate "QuickNet Internet LineJack/PhoneJack support" - depends on ISA || PCI - ---help--- - Say M if you have a telephony card manufactured by Quicknet - Technologies, Inc. These include the Internet PhoneJACK and - Internet LineJACK Telephony Cards. You will get a module called - ixj. - - For the ISA versions of these products, you can configure the - cards using the isapnp tools (pnpdump/isapnp) or you can use the - isapnp support. Please read . - - For more information on these cards, see Quicknet's web site at: - . - - If you do not have any Quicknet telephony cards, you can safely - say N here. - -config PHONE_IXJ_PCMCIA - tristate "QuickNet Internet LineJack/PhoneJack PCMCIA support" - depends on PHONE_IXJ && PCMCIA - help - Say Y here to configure in PCMCIA service support for the Quicknet - cards manufactured by Quicknet Technologies, Inc. This changes the - card initialization code to work with the card manager daemon. - -endif # PHONE diff --git a/drivers/telephony/Makefile b/drivers/telephony/Makefile deleted file mode 100644 index 1206615..0000000 --- a/drivers/telephony/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# -# Makefile for drivers/telephony -# - -obj-$(CONFIG_PHONE) += phonedev.o -obj-$(CONFIG_PHONE_IXJ) += ixj.o -obj-$(CONFIG_PHONE_IXJ_PCMCIA) += ixj_pcmcia.o diff --git a/drivers/telephony/ixj-ver.h b/drivers/telephony/ixj-ver.h deleted file mode 100644 index 2031ac6c..0000000 --- a/drivers/telephony/ixj-ver.h +++ /dev/null @@ -1,4 +0,0 @@ -/* configuration management identifiers */ -#define IXJ_VER_MAJOR 1 -#define IXJ_VER_MINOR 0 -#define IXJ_BLD_VER 1 diff --git a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c deleted file mode 100644 index d5f923b..0000000 --- a/drivers/telephony/ixj.c +++ /dev/null @@ -1,10552 +0,0 @@ -/**************************************************************************** - * ixj.c - * - * Device Driver for Quicknet Technologies, Inc.'s Telephony cards - * including the Internet PhoneJACK, Internet PhoneJACK Lite, - * Internet PhoneJACK PCI, Internet LineJACK, Internet PhoneCARD and - * SmartCABLE - * - * (c) Copyright 1999-2001 Quicknet Technologies, Inc. - * - * 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. - * - * Author: Ed Okerson, - * - * Contributors: Greg Herlein, - * David W. Erhart, - * John Sellers, - * Mike Preston, - * - * Fixes: David Huggins-Daines, - * Fabio Ferrari, - * Artis Kugevics, - * Daniele Bellucci, - * - * More information about the hardware related to this driver can be found - * at our website: http://www.quicknet.net - * - * IN NO EVENT SHALL QUICKNET TECHNOLOGIES, INC. BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT - * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF QUICKNET - * TECHNOLOGIES, INC. HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * QUICKNET TECHNOLOGIES, INC. SPECIFICALLY DISCLAIMS ANY WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND QUICKNET TECHNOLOGIES, INC. HAS NO OBLIGATION - * TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - * - ***************************************************************************/ - -/* - * Revision 4.8 2003/07/09 19:39:00 Daniele Bellucci - * Audit some copy_*_user and minor cleanup. - * - * Revision 4.7 2001/08/13 06:19:33 craigs - * Added additional changes from Alan Cox and John Anderson for - * 2.2 to 2.4 cleanup and bounds checking - * - * Revision 4.6 2001/08/13 01:05:05 craigs - * Really fixed PHONE_QUERY_CODEC problem this time - * - * Revision 4.5 2001/08/13 00:11:03 craigs - * Fixed problem in handling of PHONE_QUERY_CODEC, thanks to Shane Anderson - * - * Revision 4.4 2001/08/07 07:58:12 craigs - * Changed back to three digit version numbers - * Added tagbuild target to allow automatic and easy tagging of versions - * - * Revision 4.3 2001/08/07 07:24:47 craigs - * Added ixj-ver.h to allow easy configuration management of driver - * Added display of version number in /prox/ixj - * - * Revision 4.2 2001/08/06 07:07:19 craigs - * Reverted IXJCTL_DSP_TYPE and IXJCTL_DSP_VERSION files to original - * behaviour of returning int rather than short * - * - * Revision 4.1 2001/08/05 00:17:37 craigs - * More changes for correct PCMCIA installation - * Start of changes for backward Linux compatibility - * - * Revision 4.0 2001/08/04 12:33:12 craigs - * New version using GNU autoconf - * - * Revision 3.105 2001/07/20 23:14:32 eokerson - * More work on CallerID generation when using ring cadences. - * - * Revision 3.104 2001/07/06 01:33:55 eokerson - * Some bugfixes from Robert Vojta and a few mods to the Makefile. - * - * Revision 3.103 2001/07/05 19:20:16 eokerson - * Updated HOWTO - * Changed mic gain to 30dB on Internet LineJACK mic/speaker port. - * - * Revision 3.102 2001/07/03 23:51:21 eokerson - * Un-mute mic on Internet LineJACK when in speakerphone mode. - * - * Revision 3.101 2001/07/02 19:26:56 eokerson - * Removed initialiazation of ixjdebug and ixj_convert_loaded so they will go in the .bss instead of the .data - * - * Revision 3.100 2001/07/02 19:18:27 eokerson - * Changed driver to make dynamic allocation possible. We now pass IXJ * between functions instead of array indexes. - * Fixed the way the POTS and PSTN ports interact during a PSTN call to allow local answering. - * Fixed speaker mode on Internet LineJACK. - * - * Revision 3.99 2001/05/09 14:11:16 eokerson - * Fixed kmalloc error in ixj_build_filter_cadence. Thanks David Chan . - * - * Revision 3.98 2001/05/08 19:55:33 eokerson - * Fixed POTS hookstate detection while it is connected to PSTN port. - * - * Revision 3.97 2001/05/08 00:01:04 eokerson - * Fixed kernel oops when sending caller ID data. - * - * Revision 3.96 2001/05/04 23:09:30 eokerson - * Now uses one kernel timer for each card, instead of one for the entire driver. - * - * Revision 3.95 2001/04/25 22:06:47 eokerson - * Fixed squawking at beginning of some G.723.1 calls. - * - * Revision 3.94 2001/04/03 23:42:00 eokerson - * Added linear volume ioctls - * Added raw filter load ioctl - * - * Revision 3.93 2001/02/27 01:00:06 eokerson - * Fixed blocking in CallerID. - * Reduced size of ixj structure for smaller driver footprint. - * - * Revision 3.92 2001/02/20 22:02:59 eokerson - * Fixed isapnp and pcmcia module compatibility for 2.4.x kernels. - * Improved PSTN ring detection. - * Fixed wink generation on POTS ports. - * - * Revision 3.91 2001/02/13 00:55:44 eokerson - * Turn AEC back on after changing frame sizes. - * - * Revision 3.90 2001/02/12 16:42:00 eokerson - * Added ALAW codec, thanks to Fabio Ferrari for the table based converters to make ALAW from ULAW. - * - * Revision 3.89 2001/02/12 15:41:16 eokerson - * Fix from Artis Kugevics - Tone gains were not being set correctly. - * - * Revision 3.88 2001/02/05 23:25:42 eokerson - * Fixed lockup bugs with deregister. - * - * Revision 3.87 2001/01/29 21:00:39 eokerson - * Fix from Fabio Ferrari to properly handle EAGAIN and EINTR during non-blocking write. - * Updated copyright date. - * - * Revision 3.86 2001/01/23 23:53:46 eokerson - * Fixes to G.729 compatibility. - * - * Revision 3.85 2001/01/23 21:30:36 eokerson - * Added verbage about cards supported. - * Removed commands that put the card in low power mode at some times that it should not be in low power mode. - * - * Revision 3.84 2001/01/22 23:32:10 eokerson - * Some bugfixes from David Huggins-Daines, and other cleanups. - * - * Revision 3.83 2001/01/19 14:51:41 eokerson - * Fixed ixj_WriteDSPCommand to decrement usage counter when command fails. - * - * Revision 3.82 2001/01/19 00:34:49 eokerson - * Added verbosity to write overlap errors. - * - * Revision 3.81 2001/01/18 23:56:54 eokerson - * Fixed PSTN line test functions. - * - * Revision 3.80 2001/01/18 22:29:27 eokerson - * Updated AEC/AGC values for different cards. - * - * Revision 3.79 2001/01/17 02:58:54 eokerson - * Fixed AEC reset after Caller ID. - * Fixed Codec lockup after Caller ID on Call Waiting when not using 30ms frames. - * - * Revision 3.78 2001/01/16 19:43:09 eokerson - * Added support for Linux 2.4.x kernels. - * - * Revision 3.77 2001/01/09 04:00:52 eokerson - * Linetest will now test the line, even if it has previously succeeded. - * - * Revision 3.76 2001/01/08 19:27:00 eokerson - * Fixed problem with standard cable on Internet PhoneCARD. - * - * Revision 3.75 2000/12/22 16:52:14 eokerson - * Modified to allow hookstate detection on the POTS port when the PSTN port is selected. - * - * Revision 3.74 2000/12/08 22:41:50 eokerson - * Added capability for G729B. - * - * Revision 3.73 2000/12/07 23:35:16 eokerson - * Added capability to have different ring pattern before CallerID data. - * Added hookstate checks in CallerID routines to stop FSK. - * - * Revision 3.72 2000/12/06 19:31:31 eokerson - * Modified signal behavior to only send one signal per event. - * - * Revision 3.71 2000/12/06 03:23:08 eokerson - * Fixed CallerID on Call Waiting. - * - * Revision 3.70 2000/12/04 21:29:37 eokerson - * Added checking to Smart Cable gain functions. - * - * Revision 3.69 2000/12/04 21:05:20 eokerson - * Changed ixjdebug levels. - * Added ioctls to change gains in Internet Phone CARD Smart Cable. - * - * Revision 3.68 2000/12/04 00:17:21 craigs - * Changed mixer voice gain to +6dB rather than 0dB - * - * Revision 3.67 2000/11/30 21:25:51 eokerson - * Fixed write signal errors. - * - * Revision 3.66 2000/11/29 22:42:44 eokerson - * Fixed PSTN ring detect problems. - * - * Revision 3.65 2000/11/29 07:31:55 craigs - * Added new 425Hz filter co-efficients - * Added card-specific DTMF prescaler initialisation - * - * Revision 3.64 2000/11/28 14:03:32 craigs - * Changed certain mixer initialisations to be 0dB rather than 12dB - * Added additional information to /proc/ixj - * - * Revision 3.63 2000/11/28 11:38:41 craigs - * Added display of AEC modes in AUTO and AGC mode - * - * Revision 3.62 2000/11/28 04:05:44 eokerson - * Improved PSTN ring detection routine. - * - * Revision 3.61 2000/11/27 21:53:12 eokerson - * Fixed flash detection. - * - * Revision 3.60 2000/11/27 15:57:29 eokerson - * More work on G.729 load routines. - * - * Revision 3.59 2000/11/25 21:55:12 eokerson - * Fixed errors in G.729 load routine. - * - * Revision 3.58 2000/11/25 04:08:29 eokerson - * Added board locks around G.729 and TS85 load routines. - * - * Revision 3.57 2000/11/24 05:35:17 craigs - * Added ability to retrieve mixer values on LineJACK - * Added complete initialisation of all mixer values at startup - * Fixed spelling mistake - * - * Revision 3.56 2000/11/23 02:52:11 robertj - * Added cvs change log keyword. - * Fixed bug in capabilities list when using G.729 module. - * - */ - -#include "ixj-ver.h" - -#define PERFMON_STATS -#define IXJDEBUG 0 -#define MAXRINGS 5 - -#include - -#include -#include -#include /* printk() */ -#include /* everything... */ -#include /* error codes */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include "ixj.h" - -#define TYPE(inode) (iminor(inode) >> 4) -#define NUM(inode) (iminor(inode) & 0xf) - -static DEFINE_MUTEX(ixj_mutex); -static int ixjdebug; -static int hertz = HZ; -static int samplerate = 100; - -module_param(ixjdebug, int, 0); - -static DEFINE_PCI_DEVICE_TABLE(ixj_pci_tbl) = { - { PCI_VENDOR_ID_QUICKNET, PCI_DEVICE_ID_QUICKNET_XJ, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - { } -}; -MODULE_DEVICE_TABLE(pci, ixj_pci_tbl); - -/************************************************************************ -* -* ixjdebug meanings are now bit mapped instead of level based -* Values can be or'ed together to turn on multiple messages -* -* bit 0 (0x0001) = any failure -* bit 1 (0x0002) = general messages -* bit 2 (0x0004) = POTS ringing related -* bit 3 (0x0008) = PSTN events -* bit 4 (0x0010) = PSTN Cadence state details -* bit 5 (0x0020) = Tone detection triggers -* bit 6 (0x0040) = Tone detection cadence details -* bit 7 (0x0080) = ioctl tracking -* bit 8 (0x0100) = signal tracking -* bit 9 (0x0200) = CallerID generation details -* -************************************************************************/ - -#ifdef IXJ_DYN_ALLOC - -static IXJ *ixj[IXJMAX]; -#define get_ixj(b) ixj[(b)] - -/* - * Allocate a free IXJ device - */ - -static IXJ *ixj_alloc() -{ - for(cnt=0; cntDSPbase) - { - j = kmalloc(sizeof(IXJ), GFP_KERNEL); - if (j == NULL) - return NULL; - ixj[cnt] = j; - return j; - } - } - return NULL; -} - -static void ixj_fsk_free(IXJ *j) -{ - kfree(j->fskdata); - j->fskdata = NULL; -} - -static void ixj_fsk_alloc(IXJ *j) -{ - if(!j->fskdata) { - j->fskdata = kmalloc(8000, GFP_KERNEL); - if (!j->fskdata) { - if(ixjdebug & 0x0200) { - printk("IXJ phone%d - allocate failed\n", j->board); - } - return; - } else { - j->fsksize = 8000; - if(ixjdebug & 0x0200) { - printk("IXJ phone%d - allocate succeeded\n", j->board); - } - } - } -} - -#else - -static IXJ ixj[IXJMAX]; -#define get_ixj(b) (&ixj[(b)]) - -/* - * Allocate a free IXJ device - */ - -static IXJ *ixj_alloc(void) -{ - int cnt; - for(cnt=0; cntfsksize = 8000; -} - -#endif - -#ifdef PERFMON_STATS -#define ixj_perfmon(x) ((x)++) -#else -#define ixj_perfmon(x) do { } while(0) -#endif - -static int ixj_convert_loaded; - -static int ixj_WriteDSPCommand(unsigned short, IXJ *j); - -/************************************************************************ -* -* These are function definitions to allow external modules to register -* enhanced functionality call backs. -* -************************************************************************/ - -static int Stub(IXJ * J, unsigned long arg) -{ - return 0; -} - -static IXJ_REGFUNC ixj_PreRead = &Stub; -static IXJ_REGFUNC ixj_PostRead = &Stub; -static IXJ_REGFUNC ixj_PreWrite = &Stub; -static IXJ_REGFUNC ixj_PostWrite = &Stub; - -static void ixj_read_frame(IXJ *j); -static void ixj_write_frame(IXJ *j); -static void ixj_init_timer(IXJ *j); -static void ixj_add_timer(IXJ * j); -static void ixj_timeout(unsigned long ptr); -static int read_filters(IXJ *j); -static int LineMonitor(IXJ *j); -static int ixj_fasync(int fd, struct file *, int mode); -static int ixj_set_port(IXJ *j, int arg); -static int ixj_set_pots(IXJ *j, int arg); -static int ixj_hookstate(IXJ *j); -static int ixj_record_start(IXJ *j); -static void ixj_record_stop(IXJ *j); -static void set_rec_volume(IXJ *j, int volume); -static int get_rec_volume(IXJ *j); -static int set_rec_codec(IXJ *j, int rate); -static void ixj_vad(IXJ *j, int arg); -static int ixj_play_start(IXJ *j); -static void ixj_play_stop(IXJ *j); -static int ixj_set_tone_on(unsigned short arg, IXJ *j); -static int ixj_set_tone_off(unsigned short, IXJ *j); -static int ixj_play_tone(IXJ *j, char tone); -static void ixj_aec_start(IXJ *j, int level); -static int idle(IXJ *j); -static void ixj_ring_on(IXJ *j); -static void ixj_ring_off(IXJ *j); -static void aec_stop(IXJ *j); -static void ixj_ringback(IXJ *j); -static void ixj_busytone(IXJ *j); -static void ixj_dialtone(IXJ *j); -static void ixj_cpt_stop(IXJ *j); -static char daa_int_read(IXJ *j); -static char daa_CR_read(IXJ *j, int cr); -static int daa_set_mode(IXJ *j, int mode); -static int ixj_linetest(IXJ *j); -static int ixj_daa_write(IXJ *j); -static int ixj_daa_cid_read(IXJ *j); -static void DAA_Coeff_US(IXJ *j); -static void DAA_Coeff_UK(IXJ *j); -static void DAA_Coeff_France(IXJ *j); -static void DAA_Coeff_Germany(IXJ *j); -static void DAA_Coeff_Australia(IXJ *j); -static void DAA_Coeff_Japan(IXJ *j); -static int ixj_init_filter(IXJ *j, IXJ_FILTER * jf); -static int ixj_init_filter_raw(IXJ *j, IXJ_FILTER_RAW * jfr); -static int ixj_init_tone(IXJ *j, IXJ_TONE * ti); -static int ixj_build_cadence(IXJ *j, IXJ_CADENCE __user * cp); -static int ixj_build_filter_cadence(IXJ *j, IXJ_FILTER_CADENCE __user * cp); -/* Serial Control Interface funtions */ -static int SCI_Control(IXJ *j, int control); -static int SCI_Prepare(IXJ *j); -static int SCI_WaitHighSCI(IXJ *j); -static int SCI_WaitLowSCI(IXJ *j); -static DWORD PCIEE_GetSerialNumber(WORD wAddress); -static int ixj_PCcontrol_wait(IXJ *j); -static void ixj_pre_cid(IXJ *j); -static void ixj_write_cid(IXJ *j); -static void ixj_write_cid_bit(IXJ *j, int bit); -static int set_base_frame(IXJ *j, int size); -static int set_play_codec(IXJ *j, int rate); -static void set_rec_depth(IXJ *j, int depth); -static int ixj_mixer(long val, IXJ *j); - -/************************************************************************ -CT8020/CT8021 Host Programmers Model -Host address Function Access -DSPbase + -0-1 Aux Software Status Register (reserved) Read Only -2-3 Software Status Register Read Only -4-5 Aux Software Control Register (reserved) Read Write -6-7 Software Control Register Read Write -8-9 Hardware Status Register Read Only -A-B Hardware Control Register Read Write -C-D Host Transmit (Write) Data Buffer Access Port (buffer input)Write Only -E-F Host Receive (Read) Data Buffer Access Port (buffer input) Read Only -************************************************************************/ - -static inline void ixj_read_HSR(IXJ *j) -{ - j->hsr.bytes.low = inb_p(j->DSPbase + 8); - j->hsr.bytes.high = inb_p(j->DSPbase + 9); -} - -static inline int IsControlReady(IXJ *j) -{ - ixj_read_HSR(j); - return j->hsr.bits.controlrdy ? 1 : 0; -} - -static inline int IsPCControlReady(IXJ *j) -{ - j->pccr1.byte = inb_p(j->XILINXbase + 3); - return j->pccr1.bits.crr ? 1 : 0; -} - -static inline int IsStatusReady(IXJ *j) -{ - ixj_read_HSR(j); - return j->hsr.bits.statusrdy ? 1 : 0; -} - -static inline int IsRxReady(IXJ *j) -{ - ixj_read_HSR(j); - ixj_perfmon(j->rxreadycheck); - return j->hsr.bits.rxrdy ? 1 : 0; -} - -static inline int IsTxReady(IXJ *j) -{ - ixj_read_HSR(j); - ixj_perfmon(j->txreadycheck); - return j->hsr.bits.txrdy ? 1 : 0; -} - -static inline void set_play_volume(IXJ *j, int volume) -{ - if (ixjdebug & 0x0002) - printk(KERN_INFO "IXJ: /dev/phone%d Setting Play Volume to 0x%4.4x\n", j->board, volume); - ixj_WriteDSPCommand(0xCF02, j); - ixj_WriteDSPCommand(volume, j); -} - -static int set_play_volume_linear(IXJ *j, int volume) -{ - int newvolume, dspplaymax; - - if (ixjdebug & 0x0002) - printk(KERN_INFO "IXJ: /dev/phone %d Setting Linear Play Volume to 0x%4.4x\n", j->board, volume); - if(volume > 100 || volume < 0) { - return -1; - } - - /* This should normalize the perceived volumes between the different cards caused by differences in the hardware */ - switch (j->cardtype) { - case QTI_PHONEJACK: - dspplaymax = 0x380; - break; - case QTI_LINEJACK: - if(j->port == PORT_PSTN) { - dspplaymax = 0x48; - } else { - dspplaymax = 0x100; - } - break; - case QTI_PHONEJACK_LITE: - dspplaymax = 0x380; - break; - case QTI_PHONEJACK_PCI: - dspplaymax = 0x6C; - break; - case QTI_PHONECARD: - dspplaymax = 0x50; - break; - default: - return -1; - } - newvolume = (dspplaymax * volume) / 100; - set_play_volume(j, newvolume); - return 0; -} - -static inline void set_play_depth(IXJ *j, int depth) -{ - if (depth > 60) - depth = 60; - if (depth < 0) - depth = 0; - ixj_WriteDSPCommand(0x5280 + depth, j); -} - -static inline int get_play_volume(IXJ *j) -{ - ixj_WriteDSPCommand(0xCF00, j); - return j->ssr.high << 8 | j->ssr.low; -} - -static int get_play_volume_linear(IXJ *j) -{ - int volume, newvolume, dspplaymax; - - /* This should normalize the perceived volumes between the different cards caused by differences in the hardware */ - switch (j->cardtype) { - case QTI_PHONEJACK: - dspplaymax = 0x380; - break; - case QTI_LINEJACK: - if(j->port == PORT_PSTN) { - dspplaymax = 0x48; - } else { - dspplaymax = 0x100; - } - break; - case QTI_PHONEJACK_LITE: - dspplaymax = 0x380; - break; - case QTI_PHONEJACK_PCI: - dspplaymax = 0x6C; - break; - case QTI_PHONECARD: - dspplaymax = 100; - break; - default: - return -1; - } - volume = get_play_volume(j); - newvolume = (volume * 100) / dspplaymax; - if(newvolume > 100) - newvolume = 100; - return newvolume; -} - -static inline BYTE SLIC_GetState(IXJ *j) -{ - if (j->cardtype == QTI_PHONECARD) { - j->pccr1.byte = 0; - j->psccr.bits.dev = 3; - j->psccr.bits.rw = 1; - outw_p(j->psccr.byte << 8, j->XILINXbase + 0x00); - ixj_PCcontrol_wait(j); - j->pslic.byte = inw_p(j->XILINXbase + 0x00) & 0xFF; - ixj_PCcontrol_wait(j); - if (j->pslic.bits.powerdown) - return PLD_SLIC_STATE_OC; - else if (!j->pslic.bits.ring0 && !j->pslic.bits.ring1) - return PLD_SLIC_STATE_ACTIVE; - else - return PLD_SLIC_STATE_RINGING; - } else { - j->pld_slicr.byte = inb_p(j->XILINXbase + 0x01); - } - return j->pld_slicr.bits.state; -} - -static bool SLIC_SetState(BYTE byState, IXJ *j) -{ - bool fRetVal = false; - - if (j->cardtype == QTI_PHONECARD) { - if (j->flags.pcmciasct) { - switch (byState) { - case PLD_SLIC_STATE_TIPOPEN: - case PLD_SLIC_STATE_OC: - j->pslic.bits.powerdown = 1; - j->pslic.bits.ring0 = j->pslic.bits.ring1 = 0; - fRetVal = true; - break; - case PLD_SLIC_STATE_RINGING: - if (j->readers || j->writers) { - j->pslic.bits.powerdown = 0; - j->pslic.bits.ring0 = 1; - j->pslic.bits.ring1 = 0; - fRetVal = true; - } - break; - case PLD_SLIC_STATE_OHT: /* On-hook transmit */ - - case PLD_SLIC_STATE_STANDBY: - case PLD_SLIC_STATE_ACTIVE: - if (j->readers || j->writers) { - j->pslic.bits.powerdown = 0; - } else { - j->pslic.bits.powerdown = 1; - } - j->pslic.bits.ring0 = j->pslic.bits.ring1 = 0; - fRetVal = true; - break; - case PLD_SLIC_STATE_APR: /* Active polarity reversal */ - - case PLD_SLIC_STATE_OHTPR: /* OHT polarity reversal */ - - default: - fRetVal = false; - break; - } - j->psccr.bits.dev = 3; - j->psccr.bits.rw = 0; - outw_p(j->psccr.byte << 8 | j->pslic.byte, j->XILINXbase + 0x00); - ixj_PCcontrol_wait(j); - } - } else { - /* Set the C1, C2, C3 & B2EN signals. */ - switch (byState) { - case PLD_SLIC_STATE_OC: - j->pld_slicw.bits.c1 = 0; - j->pld_slicw.bits.c2 = 0; - j->pld_slicw.bits.c3 = 0; - j->pld_slicw.bits.b2en = 0; - outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); - fRetVal = true; - break; - case PLD_SLIC_STATE_RINGING: - j->pld_slicw.bits.c1 = 1; - j->pld_slicw.bits.c2 = 0; - j->pld_slicw.bits.c3 = 0; - j->pld_slicw.bits.b2en = 1; - outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); - fRetVal = true; - break; - case PLD_SLIC_STATE_ACTIVE: - j->pld_slicw.bits.c1 = 0; - j->pld_slicw.bits.c2 = 1; - j->pld_slicw.bits.c3 = 0; - j->pld_slicw.bits.b2en = 0; - outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); - fRetVal = true; - break; - case PLD_SLIC_STATE_OHT: /* On-hook transmit */ - - j->pld_slicw.bits.c1 = 1; - j->pld_slicw.bits.c2 = 1; - j->pld_slicw.bits.c3 = 0; - j->pld_slicw.bits.b2en = 0; - outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); - fRetVal = true; - break; - case PLD_SLIC_STATE_TIPOPEN: - j->pld_slicw.bits.c1 = 0; - j->pld_slicw.bits.c2 = 0; - j->pld_slicw.bits.c3 = 1; - j->pld_slicw.bits.b2en = 0; - outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); - fRetVal = true; - break; - case PLD_SLIC_STATE_STANDBY: - j->pld_slicw.bits.c1 = 1; - j->pld_slicw.bits.c2 = 0; - j->pld_slicw.bits.c3 = 1; - j->pld_slicw.bits.b2en = 1; - outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); - fRetVal = true; - break; - case PLD_SLIC_STATE_APR: /* Active polarity reversal */ - - j->pld_slicw.bits.c1 = 0; - j->pld_slicw.bits.c2 = 1; - j->pld_slicw.bits.c3 = 1; - j->pld_slicw.bits.b2en = 0; - outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); - fRetVal = true; - break; - case PLD_SLIC_STATE_OHTPR: /* OHT polarity reversal */ - - j->pld_slicw.bits.c1 = 1; - j->pld_slicw.bits.c2 = 1; - j->pld_slicw.bits.c3 = 1; - j->pld_slicw.bits.b2en = 0; - outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); - fRetVal = true; - break; - default: - fRetVal = false; - break; - } - } - - return fRetVal; -} - -static int ixj_wink(IXJ *j) -{ - BYTE slicnow; - - slicnow = SLIC_GetState(j); - - j->pots_winkstart = jiffies; - SLIC_SetState(PLD_SLIC_STATE_OC, j); - - msleep(jiffies_to_msecs(j->winktime)); - - SLIC_SetState(slicnow, j); - return 0; -} - -static void ixj_init_timer(IXJ *j) -{ - init_timer(&j->timer); - j->timer.function = ixj_timeout; - j->timer.data = (unsigned long)j; -} - -static void ixj_add_timer(IXJ *j) -{ - j->timer.expires = jiffies + (hertz / samplerate); - add_timer(&j->timer); -} - -static void ixj_tone_timeout(IXJ *j) -{ - IXJ_TONE ti; - - j->tone_state++; - if (j->tone_state == 3) { - j->tone_state = 0; - if (j->cadence_t) { - j->tone_cadence_state++; - if (j->tone_cadence_state >= j->cadence_t->elements_used) { - switch (j->cadence_t->termination) { - case PLAY_ONCE: - ixj_cpt_stop(j); - break; - case REPEAT_LAST_ELEMENT: - j->tone_cadence_state--; - ixj_play_tone(j, j->cadence_t->ce[j->tone_cadence_state].index); - break; - case REPEAT_ALL: - j->tone_cadence_state = 0; - if (j->cadence_t->ce[j->tone_cadence_state].freq0) { - ti.tone_index = j->cadence_t->ce[j->tone_cadence_state].index; - ti.freq0 = j->cadence_t->ce[j->tone_cadence_state].freq0; - ti.gain0 = j->cadence_t->ce[j->tone_cadence_state].gain0; - ti.freq1 = j->cadence_t->ce[j->tone_cadence_state].freq1; - ti.gain1 = j->cadence_t->ce[j->tone_cadence_state].gain1; - ixj_init_tone(j, &ti); - } - ixj_set_tone_on(j->cadence_t->ce[0].tone_on_time, j); - ixj_set_tone_off(j->cadence_t->ce[0].tone_off_time, j); - ixj_play_tone(j, j->cadence_t->ce[0].index); - break; - } - } else { - if (j->cadence_t->ce[j->tone_cadence_state].gain0) { - ti.tone_index = j->cadence_t->ce[j->tone_cadence_state].index; - ti.freq0 = j->cadence_t->ce[j->tone_cadence_state].freq0; - ti.gain0 = j->cadence_t->ce[j->tone_cadence_state].gain0; - ti.freq1 = j->cadence_t->ce[j->tone_cadence_state].freq1; - ti.gain1 = j->cadence_t->ce[j->tone_cadence_state].gain1; - ixj_init_tone(j, &ti); - } - ixj_set_tone_on(j->cadence_t->ce[j->tone_cadence_state].tone_on_time, j); - ixj_set_tone_off(j->cadence_t->ce[j->tone_cadence_state].tone_off_time, j); - ixj_play_tone(j, j->cadence_t->ce[j->tone_cadence_state].index); - } - } - } -} - -static inline void ixj_kill_fasync(IXJ *j, IXJ_SIGEVENT event, int dir) -{ - if(j->ixj_signals[event]) { - if(ixjdebug & 0x0100) - printk("Sending signal for event %d\n", event); - /* Send apps notice of change */ - /* see config.h for macro definition */ - kill_fasync(&(j->async_queue), j->ixj_signals[event], dir); - } -} - -static void ixj_pstn_state(IXJ *j) -{ - int var; - union XOPXR0 XR0, daaint; - - var = 10; - - XR0.reg = j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.reg; - daaint.reg = 0; - XR0.bitreg.RMR = j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.bitreg.RMR; - - j->pld_scrr.byte = inb_p(j->XILINXbase); - if (j->pld_scrr.bits.daaflag) { - daa_int_read(j); - if(j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.RING) { - if(time_after(jiffies, j->pstn_sleeptil) && !(j->flags.pots_pstn && j->hookstate)) { - daaint.bitreg.RING = 1; - if(ixjdebug & 0x0008) { - printk(KERN_INFO "IXJ DAA Ring Interrupt /dev/phone%d at %ld\n", j->board, jiffies); - } - } else { - daa_set_mode(j, SOP_PU_RESET); - } - } - if(j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.Caller_ID) { - daaint.bitreg.Caller_ID = 1; - j->pstn_cid_intr = 1; - j->pstn_cid_received = jiffies; - if(ixjdebug & 0x0008) { - printk(KERN_INFO "IXJ DAA Caller_ID Interrupt /dev/phone%d at %ld\n", j->board, jiffies); - } - } - if(j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.Cadence) { - daaint.bitreg.Cadence = 1; - if(ixjdebug & 0x0008) { - printk(KERN_INFO "IXJ DAA Cadence Interrupt /dev/phone%d at %ld\n", j->board, jiffies); - } - } - if(j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.VDD_OK != XR0.bitreg.VDD_OK) { - daaint.bitreg.VDD_OK = 1; - daaint.bitreg.SI_0 = j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.VDD_OK; - } - } - daa_CR_read(j, 1); - if(j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.bitreg.RMR != XR0.bitreg.RMR && time_after(jiffies, j->pstn_sleeptil) && !(j->flags.pots_pstn && j->hookstate)) { - daaint.bitreg.RMR = 1; - daaint.bitreg.SI_1 = j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.bitreg.RMR; - if(ixjdebug & 0x0008) { - printk(KERN_INFO "IXJ DAA RMR /dev/phone%d was %s for %ld\n", j->board, XR0.bitreg.RMR?"on":"off", jiffies - j->pstn_last_rmr); - } - j->pstn_prev_rmr = j->pstn_last_rmr; - j->pstn_last_rmr = jiffies; - } - switch(j->daa_mode) { - case SOP_PU_SLEEP: - if (daaint.bitreg.RING) { - if (!j->flags.pstn_ringing) { - if (j->daa_mode != SOP_PU_RINGING) { - j->pstn_ring_int = jiffies; - daa_set_mode(j, SOP_PU_RINGING); - } - } - } - break; - case SOP_PU_RINGING: - if (daaint.bitreg.RMR) { - if (ixjdebug & 0x0008) { - printk(KERN_INFO "IXJ Ring Cadence a state = %d /dev/phone%d at %ld\n", j->cadence_f[4].state, j->board, jiffies); - } - if (daaint.bitreg.SI_1) { /* Rising edge of RMR */ - j->flags.pstn_rmr = 1; - j->pstn_ring_start = jiffies; - j->pstn_ring_stop = 0; - j->ex.bits.pstn_ring = 0; - if (j->cadence_f[4].state == 0) { - j->cadence_f[4].state = 1; - j->cadence_f[4].on1min = jiffies + (long)((j->cadence_f[4].on1 * hertz * (100 - var)) / 10000); - j->cadence_f[4].on1dot = jiffies + (long)((j->cadence_f[4].on1 * hertz * (100)) / 10000); - j->cadence_f[4].on1max = jiffies + (long)((j->cadence_f[4].on1 * hertz * (100 + var)) / 10000); - } else if (j->cadence_f[4].state == 2) { - if((time_after(jiffies, j->cadence_f[4].off1min) && - time_before(jiffies, j->cadence_f[4].off1max))) { - if (j->cadence_f[4].on2) { - j->cadence_f[4].state = 3; - j->cadence_f[4].on2min = jiffies + (long)((j->cadence_f[4].on2 * (hertz * (100 - var)) / 10000)); - j->cadence_f[4].on2dot = jiffies + (long)((j->cadence_f[4].on2 * (hertz * (100)) / 10000)); - j->cadence_f[4].on2max = jiffies + (long)((j->cadence_f[4].on2 * (hertz * (100 + var)) / 10000)); - } else { - j->cadence_f[4].state = 7; - } - } else { - if (ixjdebug & 0x0008) { - printk(KERN_INFO "IXJ Ring Cadence fail state = %d /dev/phone%d at %ld should be %d\n", - j->cadence_f[4].state, j->board, jiffies - j->pstn_prev_rmr, - j->cadence_f[4].off1); - } - j->cadence_f[4].state = 0; - } - } else if (j->cadence_f[4].state == 4) { - if((time_after(jiffies, j->cadence_f[4].off2min) && - time_before(jiffies, j->cadence_f[4].off2max))) { - if (j->cadence_f[4].on3) { - j->cadence_f[4].state = 5; - j->cadence_f[4].on3min = jiffies + (long)((j->cadence_f[4].on3 * (hertz * (100 - var)) / 10000)); - j->cadence_f[4].on3dot = jiffies + (long)((j->cadence_f[4].on3 * (hertz * (100)) / 10000)); - j->cadence_f[4].on3max = jiffies + (long)((j->cadence_f[4].on3 * (hertz * (100 + var)) / 10000)); - } else { - j->cadence_f[4].state = 7; - } - } else { - if (ixjdebug & 0x0008) { - printk(KERN_INFO "IXJ Ring Cadence fail state = %d /dev/phone%d at %ld should be %d\n", - j->cadence_f[4].state, j->board, jiffies - j->pstn_prev_rmr, - j->cadence_f[4].off2); - } - j->cadence_f[4].state = 0; - } - } else if (j->cadence_f[4].state == 6) { - if((time_after(jiffies, j->cadence_f[4].off3min) && - time_before(jiffies, j->cadence_f[4].off3max))) { - j->cadence_f[4].state = 7; - } else { - if (ixjdebug & 0x0008) { - printk(KERN_INFO "IXJ Ring Cadence fail state = %d /dev/phone%d at %ld should be %d\n", - j->cadence_f[4].state, j->board, jiffies - j->pstn_prev_rmr, - j->cadence_f[4].off3); - } - j->cadence_f[4].state = 0; - } - } else { - j->cadence_f[4].state = 0; - } - } else { /* Falling edge of RMR */ - j->pstn_ring_start = 0; - j->pstn_ring_stop = jiffies; - if (j->cadence_f[4].state == 1) { - if(!j->cadence_f[4].on1) { - j->cadence_f[4].state = 7; - } else if((time_after(jiffies, j->cadence_f[4].on1min) && - time_before(jiffies, j->cadence_f[4].on1max))) { - if (j->cadence_f[4].off1) { - j->cadence_f[4].state = 2; - j->cadence_f[4].off1min = jiffies + (long)((j->cadence_f[4].off1 * (hertz * (100 - var)) / 10000)); - j->cadence_f[4].off1dot = jiffies + (long)((j->cadence_f[4].off1 * (hertz * (100)) / 10000)); - j->cadence_f[4].off1max = jiffies + (long)((j->cadence_f[4].off1 * (hertz * (100 + var)) / 10000)); - } else { - j->cadence_f[4].state = 7; - } - } else { - if (ixjdebug & 0x0008) { - printk(KERN_INFO "IXJ Ring Cadence fail state = %d /dev/phone%d at %ld should be %d\n", - j->cadence_f[4].state, j->board, jiffies - j->pstn_prev_rmr, - j->cadence_f[4].on1); - } - j->cadence_f[4].state = 0; - } - } else if (j->cadence_f[4].state == 3) { - if((time_after(jiffies, j->cadence_f[4].on2min) && - time_before(jiffies, j->cadence_f[4].on2max))) { - if (j->cadence_f[4].off2) { - j->cadence_f[4].state = 4; - j->cadence_f[4].off2min = jiffies + (long)((j->cadence_f[4].off2 * (hertz * (100 - var)) / 10000)); - j->cadence_f[4].off2dot = jiffies + (long)((j->cadence_f[4].off2 * (hertz * (100)) / 10000)); - j->cadence_f[4].off2max = jiffies + (long)((j->cadence_f[4].off2 * (hertz * (100 + var)) / 10000)); - } else { - j->cadence_f[4].state = 7; - } - } else { - if (ixjdebug & 0x0008) { - printk(KERN_INFO "IXJ Ring Cadence fail state = %d /dev/phone%d at %ld should be %d\n", - j->cadence_f[4].state, j->board, jiffies - j->pstn_prev_rmr, - j->cadence_f[4].on2); - } - j->cadence_f[4].state = 0; - } - } else if (j->cadence_f[4].state == 5) { - if((time_after(jiffies, j->cadence_f[4].on3min) && - time_before(jiffies, j->cadence_f[4].on3max))) { - if (j->cadence_f[4].off3) { - j->cadence_f[4].state = 6; - j->cadence_f[4].off3min = jiffies + (long)((j->cadence_f[4].off3 * (hertz * (100 - var)) / 10000)); - j->cadence_f[4].off3dot = jiffies + (long)((j->cadence_f[4].off3 * (hertz * (100)) / 10000)); - j->cadence_f[4].off3max = jiffies + (long)((j->cadence_f[4].off3 * (hertz * (100 + var)) / 10000)); - } else { - j->cadence_f[4].state = 7; - } - } else { - j->cadence_f[4].state = 0; - } - } else { - if (ixjdebug & 0x0008) { - printk(KERN_INFO "IXJ Ring Cadence fail state = %d /dev/phone%d at %ld should be %d\n", - j->cadence_f[4].state, j->board, jiffies - j->pstn_prev_rmr, - j->cadence_f[4].on3); - } - j->cadence_f[4].state = 0; - } - } - if (ixjdebug & 0x0010) { - printk(KERN_INFO "IXJ Ring Cadence b state = %d /dev/phone%d at %ld\n", j->cadence_f[4].state, j->board, jiffies); - } - if (ixjdebug & 0x0010) { - switch(j->cadence_f[4].state) { - case 1: - printk(KERN_INFO "IXJ /dev/phone%d Next Ring Cadence state at %u min %ld - %ld - max %ld\n", j->board, - j->cadence_f[4].on1, j->cadence_f[4].on1min, j->cadence_f[4].on1dot, j->cadence_f[4].on1max); - break; - case 2: - printk(KERN_INFO "IXJ /dev/phone%d Next Ring Cadence state at %u min %ld - %ld - max %ld\n", j->board, - j->cadence_f[4].off1, j->cadence_f[4].off1min, j->cadence_f[4].off1dot, j->cadence_f[4].off1max); - break; - case 3: - printk(KERN_INFO "IXJ /dev/phone%d Next Ring Cadence state at %u min %ld - %ld - max %ld\n", j->board, - j->cadence_f[4].on2, j->cadence_f[4].on2min, j->cadence_f[4].on2dot, j->cadence_f[4].on2max); - break; - case 4: - printk(KERN_INFO "IXJ /dev/phone%d Next Ring Cadence state at %u min %ld - %ld - max %ld\n", j->board, - j->cadence_f[4].off2, j->cadence_f[4].off2min, j->cadence_f[4].off2dot, j->cadence_f[4].off2max); - break; - case 5: - printk(KERN_INFO "IXJ /dev/phone%d Next Ring Cadence state at %u min %ld - %ld - max %ld\n", j->board, - j->cadence_f[4].on3, j->cadence_f[4].on3min, j->cadence_f[4].on3dot, j->cadence_f[4].on3max); - break; - case 6: - printk(KERN_INFO "IXJ /dev/phone%d Next Ring Cadence state at %u min %ld - %ld - max %ld\n", j->board, - j->cadence_f[4].off3, j->cadence_f[4].off3min, j->cadence_f[4].off3dot, j->cadence_f[4].off3max); - break; - } - } - } - if (j->cadence_f[4].state == 7) { - j->cadence_f[4].state = 0; - j->pstn_ring_stop = jiffies; - j->ex.bits.pstn_ring = 1; - ixj_kill_fasync(j, SIG_PSTN_RING, POLL_IN); - if(ixjdebug & 0x0008) { - printk(KERN_INFO "IXJ Ring int set /dev/phone%d at %ld\n", j->board, jiffies); - } - } - if((j->pstn_ring_int != 0 && time_after(jiffies, j->pstn_ring_int + (hertz * 5)) && !j->flags.pstn_rmr) || - (j->pstn_ring_stop != 0 && time_after(jiffies, j->pstn_ring_stop + (hertz * 5)))) { - if(ixjdebug & 0x0008) { - printk("IXJ DAA no ring in 5 seconds /dev/phone%d at %ld\n", j->board, jiffies); - printk("IXJ DAA pstn ring int /dev/phone%d at %ld\n", j->board, j->pstn_ring_int); - printk("IXJ DAA pstn ring stop /dev/phone%d at %ld\n", j->board, j->pstn_ring_stop); - } - j->pstn_ring_stop = j->pstn_ring_int = 0; - daa_set_mode(j, SOP_PU_SLEEP); - } - outb_p(j->pld_scrw.byte, j->XILINXbase); - if (j->pstn_cid_intr && time_after(jiffies, j->pstn_cid_received + hertz)) { - ixj_daa_cid_read(j); - j->ex.bits.caller_id = 1; - ixj_kill_fasync(j, SIG_CALLER_ID, POLL_IN); - j->pstn_cid_intr = 0; - } - if (daaint.bitreg.Cadence) { - if(ixjdebug & 0x0008) { - printk("IXJ DAA Cadence interrupt going to sleep /dev/phone%d\n", j->board); - } - daa_set_mode(j, SOP_PU_SLEEP); - j->ex.bits.pstn_ring = 0; - } - break; - case SOP_PU_CONVERSATION: - if (daaint.bitreg.VDD_OK) { - if(!daaint.bitreg.SI_0) { - if (!j->pstn_winkstart) { - if(ixjdebug & 0x0008) { - printk("IXJ DAA possible wink /dev/phone%d %ld\n", j->board, jiffies); - } - j->pstn_winkstart = jiffies; - } - } else { - if (j->pstn_winkstart) { - if(ixjdebug & 0x0008) { - printk("IXJ DAA possible wink end /dev/phone%d %ld\n", j->board, jiffies); - } - j->pstn_winkstart = 0; - } - } - } - if (j->pstn_winkstart && time_after(jiffies, j->pstn_winkstart + ((hertz * j->winktime) / 1000))) { - if(ixjdebug & 0x0008) { - printk("IXJ DAA wink detected going to sleep /dev/phone%d %ld\n", j->board, jiffies); - } - daa_set_mode(j, SOP_PU_SLEEP); - j->pstn_winkstart = 0; - j->ex.bits.pstn_wink = 1; - ixj_kill_fasync(j, SIG_PSTN_WINK, POLL_IN); - } - break; - } -} - -static void ixj_timeout(unsigned long ptr) -{ - int board; - unsigned long jifon; - IXJ *j = (IXJ *)ptr; - board = j->board; - - if (j->DSPbase && atomic_read(&j->DSPWrite) == 0 && test_and_set_bit(board, (void *)&j->busyflags) == 0) { - ixj_perfmon(j->timerchecks); - j->hookstate = ixj_hookstate(j); - if (j->tone_state) { - if (!(j->hookstate)) { - ixj_cpt_stop(j); - if (j->m_hook) { - j->m_hook = 0; - j->ex.bits.hookstate = 1; - ixj_kill_fasync(j, SIG_HOOKSTATE, POLL_IN); - } - clear_bit(board, &j->busyflags); - ixj_add_timer(j); - return; - } - if (j->tone_state == 1) - jifon = ((hertz * j->tone_on_time) * 25 / 100000); - else - jifon = ((hertz * j->tone_on_time) * 25 / 100000) + ((hertz * j->tone_off_time) * 25 / 100000); - if (time_before(jiffies, j->tone_start_jif + jifon)) { - if (j->tone_state == 1) { - ixj_play_tone(j, j->tone_index); - if (j->dsp.low == 0x20) { - clear_bit(board, &j->busyflags); - ixj_add_timer(j); - return; - } - } else { - ixj_play_tone(j, 0); - if (j->dsp.low == 0x20) { - clear_bit(board, &j->busyflags); - ixj_add_timer(j); - return; - } - } - } else { - ixj_tone_timeout(j); - if (j->flags.dialtone) { - ixj_dialtone(j); - } - if (j->flags.busytone) { - ixj_busytone(j); - if (j->dsp.low == 0x20) { - clear_bit(board, &j->busyflags); - ixj_add_timer(j); - return; - } - } - if (j->flags.ringback) { - ixj_ringback(j); - if (j->dsp.low == 0x20) { - clear_bit(board, &j->busyflags); - ixj_add_timer(j); - return; - } - } - if (!j->tone_state) { - ixj_cpt_stop(j); - } - } - } - if (!(j->tone_state && j->dsp.low == 0x20)) { - if (IsRxReady(j)) { - ixj_read_frame(j); - } - if (IsTxReady(j)) { - ixj_write_frame(j); - } - } - if (j->flags.cringing) { - if (j->hookstate & 1) { - j->flags.cringing = 0; - ixj_ring_off(j); - } else if(j->cadence_f[5].enable && ((!j->cadence_f[5].en_filter) || (j->cadence_f[5].en_filter && j->flags.firstring))) { - switch(j->cadence_f[5].state) { - case 0: - j->cadence_f[5].on1dot = jiffies + (long)((j->cadence_f[5].on1 * (hertz * 100) / 10000)); - if (time_before(jiffies, j->cadence_f[5].on1dot)) { - if(ixjdebug & 0x0004) { - printk("Ringing cadence state = %d - %ld\n", j->cadence_f[5].state, jiffies); - } - ixj_ring_on(j); - } - j->cadence_f[5].state = 1; - break; - case 1: - if (time_after(jiffies, j->cadence_f[5].on1dot)) { - j->cadence_f[5].off1dot = jiffies + (long)((j->cadence_f[5].off1 * (hertz * 100) / 10000)); - if(ixjdebug & 0x0004) { - printk("Ringing cadence state = %d - %ld\n", j->cadence_f[5].state, jiffies); - } - ixj_ring_off(j); - j->cadence_f[5].state = 2; - } - break; - case 2: - if (time_after(jiffies, j->cadence_f[5].off1dot)) { - if(ixjdebug & 0x0004) { - printk("Ringing cadence state = %d - %ld\n", j->cadence_f[5].state, jiffies); - } - ixj_ring_on(j); - if (j->cadence_f[5].on2) { - j->cadence_f[5].on2dot = jiffies + (long)((j->cadence_f[5].on2 * (hertz * 100) / 10000)); - j->cadence_f[5].state = 3; - } else { - j->cadence_f[5].state = 7; - } - } - break; - case 3: - if (time_after(jiffies, j->cadence_f[5].on2dot)) { - if(ixjdebug & 0x0004) { - printk("Ringing cadence state = %d - %ld\n", j->cadence_f[5].state, jiffies); - } - ixj_ring_off(j); - if (j->cadence_f[5].off2) { - j->cadence_f[5].off2dot = jiffies + (long)((j->cadence_f[5].off2 * (hertz * 100) / 10000)); - j->cadence_f[5].state = 4; - } else { - j->cadence_f[5].state = 7; - } - } - break; - case 4: - if (time_after(jiffies, j->cadence_f[5].off2dot)) { - if(ixjdebug & 0x0004) { - printk("Ringing cadence state = %d - %ld\n", j->cadence_f[5].state, jiffies); - } - ixj_ring_on(j); - if (j->cadence_f[5].on3) { - j->cadence_f[5].on3dot = jiffies + (long)((j->cadence_f[5].on3 * (hertz * 100) / 10000)); - j->cadence_f[5].state = 5; - } else { - j->cadence_f[5].state = 7; - } - } - break; - case 5: - if (time_after(jiffies, j->cadence_f[5].on3dot)) { - if(ixjdebug & 0x0004) { - printk("Ringing cadence state = %d - %ld\n", j->cadence_f[5].state, jiffies); - } - ixj_ring_off(j); - if (j->cadence_f[5].off3) { - j->cadence_f[5].off3dot = jiffies + (long)((j->cadence_f[5].off3 * (hertz * 100) / 10000)); - j->cadence_f[5].state = 6; - } else { - j->cadence_f[5].state = 7; - } - } - break; - case 6: - if (time_after(jiffies, j->cadence_f[5].off3dot)) { - if(ixjdebug & 0x0004) { - printk("Ringing cadence state = %d - %ld\n", j->cadence_f[5].state, jiffies); - } - j->cadence_f[5].state = 7; - } - break; - case 7: - if(ixjdebug & 0x0004) { - printk("Ringing cadence state = %d - %ld\n", j->cadence_f[5].state, jiffies); - } - j->flags.cidring = 1; - j->cadence_f[5].state = 0; - break; - } - if (j->flags.cidring && !j->flags.cidsent) { - j->flags.cidsent = 1; - if(j->fskdcnt) { - SLIC_SetState(PLD_SLIC_STATE_OHT, j); - ixj_pre_cid(j); - } - j->flags.cidring = 0; - } - clear_bit(board, &j->busyflags); - ixj_add_timer(j); - return; - } else { - if (time_after(jiffies, j->ring_cadence_jif + (hertz / 2))) { - if (j->flags.cidring && !j->flags.cidsent) { - j->flags.cidsent = 1; - if(j->fskdcnt) { - SLIC_SetState(PLD_SLIC_STATE_OHT, j); - ixj_pre_cid(j); - } - j->flags.cidring = 0; - } - j->ring_cadence_t--; - if (j->ring_cadence_t == -1) - j->ring_cadence_t = 15; - j->ring_cadence_jif = jiffies; - - if (j->ring_cadence & 1 << j->ring_cadence_t) { - if(j->flags.cidsent && j->cadence_f[5].en_filter) - j->flags.firstring = 1; - else - ixj_ring_on(j); - } else { - ixj_ring_off(j); - if(!j->flags.cidsent) - j->flags.cidring = 1; - } - } - clear_bit(board, &j->busyflags); - ixj_add_timer(j); - return; - } - } - if (!j->flags.ringing) { - if (j->hookstate) { /* & 1) { */ - if (j->dsp.low != 0x20 && - SLIC_GetState(j) != PLD_SLIC_STATE_ACTIVE) { - SLIC_SetState(PLD_SLIC_STATE_ACTIVE, j); - } - LineMonitor(j); - read_filters(j); - ixj_WriteDSPCommand(0x511B, j); - j->proc_load = j->ssr.high << 8 | j->ssr.low; - if (!j->m_hook && (j->hookstate & 1)) { - j->m_hook = j->ex.bits.hookstate = 1; - ixj_kill_fasync(j, SIG_HOOKSTATE, POLL_IN); - } - } else { - if (j->ex.bits.dtmf_ready) { - j->dtmf_wp = j->dtmf_rp = j->ex.bits.dtmf_ready = 0; - } - if (j->m_hook) { - j->m_hook = 0; - j->ex.bits.hookstate = 1; - ixj_kill_fasync(j, SIG_HOOKSTATE, POLL_IN); - } - } - } - if (j->cardtype == QTI_LINEJACK && !j->flags.pstncheck && j->flags.pstn_present) { - ixj_pstn_state(j); - } - if (j->ex.bytes) { - wake_up_interruptible(&j->poll_q); /* Wake any blocked selects */ - } - clear_bit(board, &j->busyflags); - } - ixj_add_timer(j); -} - -static int ixj_status_wait(IXJ *j) -{ - unsigned long jif; - - jif = jiffies + ((60 * hertz) / 100); - while (!IsStatusReady(j)) { - ixj_perfmon(j->statuswait); - if (time_after(jiffies, jif)) { - ixj_perfmon(j->statuswaitfail); - return -1; - } - } - return 0; -} - -static int ixj_PCcontrol_wait(IXJ *j) -{ - unsigned long jif; - - jif = jiffies + ((60 * hertz) / 100); - while (!IsPCControlReady(j)) { - ixj_perfmon(j->pcontrolwait); - if (time_after(jiffies, jif)) { - ixj_perfmon(j->pcontrolwaitfail); - return -1; - } - } - return 0; -} - -static int ixj_WriteDSPCommand(unsigned short cmd, IXJ *j) -{ - BYTES bytes; - unsigned long jif; - - atomic_inc(&j->DSPWrite); - if(atomic_read(&j->DSPWrite) > 1) { - printk("IXJ %d DSP write overlap attempting command 0x%4.4x\n", j->board, cmd); - return -1; - } - bytes.high = (cmd & 0xFF00) >> 8; - bytes.low = cmd & 0x00FF; - jif = jiffies + ((60 * hertz) / 100); - while (!IsControlReady(j)) { - ixj_perfmon(j->iscontrolready); - if (time_after(jiffies, jif)) { - ixj_perfmon(j->iscontrolreadyfail); - atomic_dec(&j->DSPWrite); - if(atomic_read(&j->DSPWrite) > 0) { - printk("IXJ %d DSP overlaped command 0x%4.4x during control ready failure.\n", j->board, cmd); - while(atomic_read(&j->DSPWrite) > 0) { - atomic_dec(&j->DSPWrite); - } - } - return -1; - } - } - outb(bytes.low, j->DSPbase + 6); - outb(bytes.high, j->DSPbase + 7); - - if (ixj_status_wait(j)) { - j->ssr.low = 0xFF; - j->ssr.high = 0xFF; - atomic_dec(&j->DSPWrite); - if(atomic_read(&j->DSPWrite) > 0) { - printk("IXJ %d DSP overlaped command 0x%4.4x during status wait failure.\n", j->board, cmd); - while(atomic_read(&j->DSPWrite) > 0) { - atomic_dec(&j->DSPWrite); - } - } - return -1; - } -/* Read Software Status Register */ - j->ssr.low = inb_p(j->DSPbase + 2); - j->ssr.high = inb_p(j->DSPbase + 3); - atomic_dec(&j->DSPWrite); - if(atomic_read(&j->DSPWrite) > 0) { - printk("IXJ %d DSP overlaped command 0x%4.4x\n", j->board, cmd); - while(atomic_read(&j->DSPWrite) > 0) { - atomic_dec(&j->DSPWrite); - } - } - return 0; -} - -/*************************************************************************** -* -* General Purpose IO Register read routine -* -***************************************************************************/ -static inline int ixj_gpio_read(IXJ *j) -{ - if (ixj_WriteDSPCommand(0x5143, j)) - return -1; - - j->gpio.bytes.low = j->ssr.low; - j->gpio.bytes.high = j->ssr.high; - - return 0; -} - -static inline void LED_SetState(int state, IXJ *j) -{ - if (j->cardtype == QTI_LINEJACK) { - j->pld_scrw.bits.led1 = state & 0x1 ? 1 : 0; - j->pld_scrw.bits.led2 = state & 0x2 ? 1 : 0; - j->pld_scrw.bits.led3 = state & 0x4 ? 1 : 0; - j->pld_scrw.bits.led4 = state & 0x8 ? 1 : 0; - - outb(j->pld_scrw.byte, j->XILINXbase); - } -} - -/********************************************************************* -* GPIO Pins are configured as follows on the Quicknet Internet -* PhoneJACK Telephony Cards -* -* POTS Select GPIO_6=0 GPIO_7=0 -* Mic/Speaker Select GPIO_6=0 GPIO_7=1 -* Handset Select GPIO_6=1 GPIO_7=0 -* -* SLIC Active GPIO_1=0 GPIO_2=1 GPIO_5=0 -* SLIC Ringing GPIO_1=1 GPIO_2=1 GPIO_5=0 -* SLIC Open Circuit GPIO_1=0 GPIO_2=0 GPIO_5=0 -* -* Hook Switch changes reported on GPIO_3 -*********************************************************************/ -static int ixj_set_port(IXJ *j, int arg) -{ - if (j->cardtype == QTI_PHONEJACK_LITE) { - if (arg != PORT_POTS) - return 10; - else - return 0; - } - switch (arg) { - case PORT_POTS: - j->port = PORT_POTS; - switch (j->cardtype) { - case QTI_PHONECARD: - if (j->flags.pcmciasct == 1) - SLIC_SetState(PLD_SLIC_STATE_ACTIVE, j); - else - return 11; - break; - case QTI_PHONEJACK_PCI: - j->pld_slicw.pcib.mic = 0; - j->pld_slicw.pcib.spk = 0; - outb(j->pld_slicw.byte, j->XILINXbase + 0x01); - break; - case QTI_LINEJACK: - ixj_set_pots(j, 0); /* Disconnect POTS/PSTN relay */ - if (ixj_WriteDSPCommand(0xC528, j)) /* Write CODEC config to - Software Control Register */ - return 2; - j->pld_scrw.bits.daafsyncen = 0; /* Turn off DAA Frame Sync */ - - outb(j->pld_scrw.byte, j->XILINXbase); - j->pld_clock.byte = 0; - outb(j->pld_clock.byte, j->XILINXbase + 0x04); - j->pld_slicw.bits.rly1 = 1; - j->pld_slicw.bits.spken = 0; - outb(j->pld_slicw.byte, j->XILINXbase + 0x01); - ixj_mixer(0x1200, j); /* Turn Off MIC switch on mixer left */ - ixj_mixer(0x1401, j); /* Turn On Mono1 switch on mixer left */ - ixj_mixer(0x1300, j); /* Turn Off MIC switch on mixer right */ - ixj_mixer(0x1501, j); /* Turn On Mono1 switch on mixer right */ - ixj_mixer(0x0E80, j); /*Mic mute */ - ixj_mixer(0x0F00, j); /* Set mono out (SLIC) to 0dB */ - ixj_mixer(0x0080, j); /* Mute Master Left volume */ - ixj_mixer(0x0180, j); /* Mute Master Right volume */ - SLIC_SetState(PLD_SLIC_STATE_STANDBY, j); -/* SLIC_SetState(PLD_SLIC_STATE_ACTIVE, j); */ - break; - case QTI_PHONEJACK: - j->gpio.bytes.high = 0x0B; - j->gpio.bits.gpio6 = 0; - j->gpio.bits.gpio7 = 0; - ixj_WriteDSPCommand(j->gpio.word, j); - break; - } - break; - case PORT_PSTN: - if (j->cardtype == QTI_LINEJACK) { - ixj_WriteDSPCommand(0xC534, j); /* Write CODEC config to Software Control Register */ - - j->pld_slicw.bits.rly3 = 0; - j->pld_slicw.bits.rly1 = 1; - j->pld_slicw.bits.spken = 0; - outb(j->pld_slicw.byte, j->XILINXbase + 0x01); - j->port = PORT_PSTN; - } else { - return 4; - } - break; - case PORT_SPEAKER: - j->port = PORT_SPEAKER; - switch (j->cardtype) { - case QTI_PHONECARD: - if (j->flags.pcmciasct) { - SLIC_SetState(PLD_SLIC_STATE_OC, j); - } - break; - case QTI_PHONEJACK_PCI: - j->pld_slicw.pcib.mic = 1; - j->pld_slicw.pcib.spk = 1; - outb(j->pld_slicw.byte, j->XILINXbase + 0x01); - break; - case QTI_LINEJACK: - ixj_set_pots(j, 0); /* Disconnect POTS/PSTN relay */ - if (ixj_WriteDSPCommand(0xC528, j)) /* Write CODEC config to - Software Control Register */ - return 2; - j->pld_scrw.bits.daafsyncen = 0; /* Turn off DAA Frame Sync */ - - outb(j->pld_scrw.byte, j->XILINXbase); - j->pld_clock.byte = 0; - outb(j->pld_clock.byte, j->XILINXbase + 0x04); - j->pld_slicw.bits.rly1 = 1; - j->pld_slicw.bits.spken = 1; - outb(j->pld_slicw.byte, j->XILINXbase + 0x01); - ixj_mixer(0x1201, j); /* Turn On MIC switch on mixer left */ - ixj_mixer(0x1400, j); /* Turn Off Mono1 switch on mixer left */ - ixj_mixer(0x1301, j); /* Turn On MIC switch on mixer right */ - ixj_mixer(0x1500, j); /* Turn Off Mono1 switch on mixer right */ - ixj_mixer(0x0E06, j); /*Mic un-mute 0dB */ - ixj_mixer(0x0F80, j); /* Mute mono out (SLIC) */ - ixj_mixer(0x0000, j); /* Set Master Left volume to 0dB */ - ixj_mixer(0x0100, j); /* Set Master Right volume to 0dB */ - break; - case QTI_PHONEJACK: - j->gpio.bytes.high = 0x0B; - j->gpio.bits.gpio6 = 0; - j->gpio.bits.gpio7 = 1; - ixj_WriteDSPCommand(j->gpio.word, j); - break; - } - break; - case PORT_HANDSET: - if (j->cardtype != QTI_PHONEJACK) { - return 5; - } else { - j->gpio.bytes.high = 0x0B; - j->gpio.bits.gpio6 = 1; - j->gpio.bits.gpio7 = 0; - ixj_WriteDSPCommand(j->gpio.word, j); - j->port = PORT_HANDSET; - } - break; - default: - return 6; - break; - } - return 0; -} - -static int ixj_set_pots(IXJ *j, int arg) -{ - if (j->cardtype == QTI_LINEJACK) { - if (arg) { - if (j->port == PORT_PSTN) { - j->pld_slicw.bits.rly1 = 0; - outb(j->pld_slicw.byte, j->XILINXbase + 0x01); - j->flags.pots_pstn = 1; - return 1; - } else { - j->flags.pots_pstn = 0; - return 0; - } - } else { - j->pld_slicw.bits.rly1 = 1; - outb(j->pld_slicw.byte, j->XILINXbase + 0x01); - j->flags.pots_pstn = 0; - return 1; - } - } else { - return 0; - } -} - -static void ixj_ring_on(IXJ *j) -{ - if (j->dsp.low == 0x20) /* Internet PhoneJACK */ - { - if (ixjdebug & 0x0004) - printk(KERN_INFO "IXJ Ring On /dev/phone%d\n", j->board); - - j->gpio.bytes.high = 0x0B; - j->gpio.bytes.low = 0x00; - j->gpio.bits.gpio1 = 1; - j->gpio.bits.gpio2 = 1; - j->gpio.bits.gpio5 = 0; - ixj_WriteDSPCommand(j->gpio.word, j); /* send the ring signal */ - } else /* Internet LineJACK, Internet PhoneJACK Lite or Internet PhoneJACK PCI */ - { - if (ixjdebug & 0x0004) - printk(KERN_INFO "IXJ Ring On /dev/phone%d\n", j->board); - - SLIC_SetState(PLD_SLIC_STATE_RINGING, j); - } -} - -static int ixj_siadc(IXJ *j, int val) -{ - if(j->cardtype == QTI_PHONECARD){ - if(j->flags.pcmciascp){ - if(val == -1) - return j->siadc.bits.rxg; - - if(val < 0 || val > 0x1F) - return -1; - - j->siadc.bits.hom = 0; /* Handset Out Mute */ - j->siadc.bits.lom = 0; /* Line Out Mute */ - j->siadc.bits.rxg = val; /*(0xC000 - 0x41C8) / 0x4EF; RX PGA Gain */ - j->psccr.bits.addr = 6; /* R/W Smart Cable Register Address */ - j->psccr.bits.rw = 0; /* Read / Write flag */ - j->psccr.bits.dev = 0; - outb(j->siadc.byte, j->XILINXbase + 0x00); - outb(j->psccr.byte, j->XILINXbase + 0x01); - ixj_PCcontrol_wait(j); - return j->siadc.bits.rxg; - } - } - return -1; -} - -static int ixj_sidac(IXJ *j, int val) -{ - if(j->cardtype == QTI_PHONECARD){ - if(j->flags.pcmciascp){ - if(val == -1) - return j->sidac.bits.txg; - - if(val < 0 || val > 0x1F) - return -1; - - j->sidac.bits.srm = 1; /* Speaker Right Mute */ - j->sidac.bits.slm = 1; /* Speaker Left Mute */ - j->sidac.bits.txg = val; /* (0xC000 - 0x45E4) / 0x5D3; TX PGA Gain */ - j->psccr.bits.addr = 7; /* R/W Smart Cable Register Address */ - j->psccr.bits.rw = 0; /* Read / Write flag */ - j->psccr.bits.dev = 0; - outb(j->sidac.byte, j->XILINXbase + 0x00); - outb(j->psccr.byte, j->XILINXbase + 0x01); - ixj_PCcontrol_wait(j); - return j->sidac.bits.txg; - } - } - return -1; -} - -static int ixj_pcmcia_cable_check(IXJ *j) -{ - j->pccr1.byte = inb_p(j->XILINXbase + 0x03); - if (!j->flags.pcmciastate) { - j->pccr2.byte = inb_p(j->XILINXbase + 0x02); - if (j->pccr1.bits.drf || j->pccr2.bits.rstc) { - j->flags.pcmciastate = 4; - return 0; - } - if (j->pccr1.bits.ed) { - j->pccr1.bits.ed = 0; - j->psccr.bits.dev = 3; - j->psccr.bits.rw = 1; - outw_p(j->psccr.byte << 8, j->XILINXbase + 0x00); - ixj_PCcontrol_wait(j); - j->pslic.byte = inw_p(j->XILINXbase + 0x00) & 0xFF; - j->pslic.bits.led2 = j->pslic.bits.det ? 1 : 0; - j->psccr.bits.dev = 3; - j->psccr.bits.rw = 0; - outw_p(j->psccr.byte << 8 | j->pslic.byte, j->XILINXbase + 0x00); - ixj_PCcontrol_wait(j); - return j->pslic.bits.led2 ? 1 : 0; - } else if (j->flags.pcmciasct) { - return j->r_hook; - } else { - return 1; - } - } else if (j->flags.pcmciastate == 4) { - if (!j->pccr1.bits.drf) { - j->flags.pcmciastate = 3; - } - return 0; - } else if (j->flags.pcmciastate == 3) { - j->pccr2.bits.pwr = 0; - j->pccr2.bits.rstc = 1; - outb(j->pccr2.byte, j->XILINXbase + 0x02); - j->checkwait = jiffies + (hertz * 2); - j->flags.incheck = 1; - j->flags.pcmciastate = 2; - return 0; - } else if (j->flags.pcmciastate == 2) { - if (j->flags.incheck) { - if (time_before(jiffies, j->checkwait)) { - return 0; - } else { - j->flags.incheck = 0; - } - } - j->pccr2.bits.pwr = 0; - j->pccr2.bits.rstc = 0; - outb_p(j->pccr2.byte, j->XILINXbase + 0x02); - j->flags.pcmciastate = 1; - return 0; - } else if (j->flags.pcmciastate == 1) { - j->flags.pcmciastate = 0; - if (!j->pccr1.bits.drf) { - j->psccr.bits.dev = 3; - j->psccr.bits.rw = 1; - outb_p(j->psccr.byte, j->XILINXbase + 0x01); - ixj_PCcontrol_wait(j); - j->flags.pcmciascp = 1; /* Set Cable Present Flag */ - - j->flags.pcmciasct = (inw_p(j->XILINXbase + 0x00) >> 8) & 0x03; /* Get Cable Type */ - - if (j->flags.pcmciasct == 3) { - j->flags.pcmciastate = 4; - return 0; - } else if (j->flags.pcmciasct == 0) { - j->pccr2.bits.pwr = 1; - j->pccr2.bits.rstc = 0; - outb_p(j->pccr2.byte, j->XILINXbase + 0x02); - j->port = PORT_SPEAKER; - } else { - j->port = PORT_POTS; - } - j->sic1.bits.cpd = 0; /* Chip Power Down */ - j->sic1.bits.mpd = 0; /* MIC Bias Power Down */ - j->sic1.bits.hpd = 0; /* Handset Bias Power Down */ - j->sic1.bits.lpd = 0; /* Line Bias Power Down */ - j->sic1.bits.spd = 1; /* Speaker Drive Power Down */ - j->psccr.bits.addr = 1; /* R/W Smart Cable Register Address */ - j->psccr.bits.rw = 0; /* Read / Write flag */ - j->psccr.bits.dev = 0; - outb(j->sic1.byte, j->XILINXbase + 0x00); - outb(j->psccr.byte, j->XILINXbase + 0x01); - ixj_PCcontrol_wait(j); - - j->sic2.bits.al = 0; /* Analog Loopback DAC analog -> ADC analog */ - j->sic2.bits.dl2 = 0; /* Digital Loopback DAC -> ADC one bit */ - j->sic2.bits.dl1 = 0; /* Digital Loopback ADC -> DAC one bit */ - j->sic2.bits.pll = 0; /* 1 = div 10, 0 = div 5 */ - j->sic2.bits.hpd = 0; /* HPF disable */ - j->psccr.bits.addr = 2; /* R/W Smart Cable Register Address */ - j->psccr.bits.rw = 0; /* Read / Write flag */ - j->psccr.bits.dev = 0; - outb(j->sic2.byte, j->XILINXbase + 0x00); - outb(j->psccr.byte, j->XILINXbase + 0x01); - ixj_PCcontrol_wait(j); - - j->psccr.bits.addr = 3; /* R/W Smart Cable Register Address */ - j->psccr.bits.rw = 0; /* Read / Write flag */ - j->psccr.bits.dev = 0; - outb(0x00, j->XILINXbase + 0x00); /* PLL Divide N1 */ - outb(j->psccr.byte, j->XILINXbase + 0x01); - ixj_PCcontrol_wait(j); - - j->psccr.bits.addr = 4; /* R/W Smart Cable Register Address */ - j->psccr.bits.rw = 0; /* Read / Write flag */ - j->psccr.bits.dev = 0; - outb(0x09, j->XILINXbase + 0x00); /* PLL Multiply M1 */ - outb(j->psccr.byte, j->XILINXbase + 0x01); - ixj_PCcontrol_wait(j); - - j->sirxg.bits.lig = 1; /* Line In Gain */ - j->sirxg.bits.lim = 1; /* Line In Mute */ - j->sirxg.bits.mcg = 0; /* MIC In Gain was 3 */ - j->sirxg.bits.mcm = 0; /* MIC In Mute */ - j->sirxg.bits.him = 0; /* Handset In Mute */ - j->sirxg.bits.iir = 1; /* IIR */ - j->psccr.bits.addr = 5; /* R/W Smart Cable Register Address */ - j->psccr.bits.rw = 0; /* Read / Write flag */ - j->psccr.bits.dev = 0; - outb(j->sirxg.byte, j->XILINXbase + 0x00); - outb(j->psccr.byte, j->XILINXbase + 0x01); - ixj_PCcontrol_wait(j); - - ixj_siadc(j, 0x17); - ixj_sidac(j, 0x1D); - - j->siaatt.bits.sot = 0; - j->psccr.bits.addr = 9; /* R/W Smart Cable Register Address */ - j->psccr.bits.rw = 0; /* Read / Write flag */ - j->psccr.bits.dev = 0; - outb(j->siaatt.byte, j->XILINXbase + 0x00); - outb(j->psccr.byte, j->XILINXbase + 0x01); - ixj_PCcontrol_wait(j); - - if (j->flags.pcmciasct == 1 && !j->readers && !j->writers) { - j->psccr.byte = j->pslic.byte = 0; - j->pslic.bits.powerdown = 1; - j->psccr.bits.dev = 3; - j->psccr.bits.rw = 0; - outw_p(j->psccr.byte << 8 | j->pslic.byte, j->XILINXbase + 0x00); - ixj_PCcontrol_wait(j); - } - } - return 0; - } else { - j->flags.pcmciascp = 0; - return 0; - } - return 0; -} - -static int ixj_hookstate(IXJ *j) -{ - int fOffHook = 0; - - switch (j->cardtype) { - case QTI_PHONEJACK: - ixj_gpio_read(j); - fOffHook = j->gpio.bits.gpio3read ? 1 : 0; - break; - case QTI_LINEJACK: - case QTI_PHONEJACK_LITE: - case QTI_PHONEJACK_PCI: - SLIC_GetState(j); - if(j->cardtype == QTI_LINEJACK && j->flags.pots_pstn == 1 && (j->readers || j->writers)) { - fOffHook = j->pld_slicr.bits.potspstn ? 1 : 0; - if(fOffHook != j->p_hook) { - if(!j->checkwait) { - j->checkwait = jiffies; - } - if(time_before(jiffies, j->checkwait + 2)) { - fOffHook ^= 1; - } else { - j->checkwait = 0; - } - j->p_hook = fOffHook; - printk("IXJ : /dev/phone%d pots-pstn hookstate check %d at %ld\n", j->board, fOffHook, jiffies); - } - } else { - if (j->pld_slicr.bits.state == PLD_SLIC_STATE_ACTIVE || - j->pld_slicr.bits.state == PLD_SLIC_STATE_STANDBY) { - if (j->flags.ringing || j->flags.cringing) { - if (!in_interrupt()) { - msleep(20); - } - SLIC_GetState(j); - if (j->pld_slicr.bits.state == PLD_SLIC_STATE_RINGING) { - ixj_ring_on(j); - } - } - if (j->cardtype == QTI_PHONEJACK_PCI) { - j->pld_scrr.byte = inb_p(j->XILINXbase); - fOffHook = j->pld_scrr.pcib.det ? 1 : 0; - } else - fOffHook = j->pld_slicr.bits.det ? 1 : 0; - } - } - break; - case QTI_PHONECARD: - fOffHook = ixj_pcmcia_cable_check(j); - break; - } - if (j->r_hook != fOffHook) { - j->r_hook = fOffHook; - if (j->port == PORT_SPEAKER || j->port == PORT_HANDSET) { // || (j->port == PORT_PSTN && j->flags.pots_pstn == 0)) { - j->ex.bits.hookstate = 1; - ixj_kill_fasync(j, SIG_HOOKSTATE, POLL_IN); - } else if (!fOffHook) { - j->flash_end = jiffies + ((60 * hertz) / 100); - } - } - if (fOffHook) { - if(time_before(jiffies, j->flash_end)) { - j->ex.bits.flash = 1; - j->flash_end = 0; - ixj_kill_fasync(j, SIG_FLASH, POLL_IN); - } - } else { - if(time_before(jiffies, j->flash_end)) { - fOffHook = 1; - } - } - - if (j->port == PORT_PSTN && j->daa_mode == SOP_PU_CONVERSATION) - fOffHook |= 2; - - if (j->port == PORT_SPEAKER) { - if(j->cardtype == QTI_PHONECARD) { - if(j->flags.pcmciascp && j->flags.pcmciasct) { - fOffHook |= 2; - } - } else { - fOffHook |= 2; - } - } - - if (j->port == PORT_HANDSET) - fOffHook |= 2; - - return fOffHook; -} - -static void ixj_ring_off(IXJ *j) -{ - if (j->dsp.low == 0x20) /* Internet PhoneJACK */ - { - if (ixjdebug & 0x0004) - printk(KERN_INFO "IXJ Ring Off\n"); - j->gpio.bytes.high = 0x0B; - j->gpio.bytes.low = 0x00; - j->gpio.bits.gpio1 = 0; - j->gpio.bits.gpio2 = 1; - j->gpio.bits.gpio5 = 0; - ixj_WriteDSPCommand(j->gpio.word, j); - } else /* Internet LineJACK */ - { - if (ixjdebug & 0x0004) - printk(KERN_INFO "IXJ Ring Off\n"); - - if(!j->flags.cidplay) - SLIC_SetState(PLD_SLIC_STATE_STANDBY, j); - - SLIC_GetState(j); - } -} - -static void ixj_ring_start(IXJ *j) -{ - j->flags.cringing = 1; - if (ixjdebug & 0x0004) - printk(KERN_INFO "IXJ Cadence Ringing Start /dev/phone%d\n", j->board); - if (ixj_hookstate(j) & 1) { - if (j->port == PORT_POTS) - ixj_ring_off(j); - j->flags.cringing = 0; - if (ixjdebug & 0x0004) - printk(KERN_INFO "IXJ Cadence Ringing Stopped /dev/phone%d off hook\n", j->board); - } else if(j->cadence_f[5].enable && (!j->cadence_f[5].en_filter)) { - j->ring_cadence_jif = jiffies; - j->flags.cidsent = j->flags.cidring = 0; - j->cadence_f[5].state = 0; - if(j->cadence_f[5].on1) - ixj_ring_on(j); - } else { - j->ring_cadence_jif = jiffies; - j->ring_cadence_t = 15; - if (j->ring_cadence & 1 << j->ring_cadence_t) { - ixj_ring_on(j); - } else { - ixj_ring_off(j); - } - j->flags.cidsent = j->flags.cidring = j->flags.firstring = 0; - } -} - -static int ixj_ring(IXJ *j) -{ - char cntr; - unsigned long jif; - - j->flags.ringing = 1; - if (ixj_hookstate(j) & 1) { - ixj_ring_off(j); - j->flags.ringing = 0; - return 1; - } - for (cntr = 0; cntr < j->maxrings; cntr++) { - jif = jiffies + (1 * hertz); - ixj_ring_on(j); - while (time_before(jiffies, jif)) { - if (ixj_hookstate(j) & 1) { - ixj_ring_off(j); - j->flags.ringing = 0; - return 1; - } - schedule_timeout_interruptible(1); - if (signal_pending(current)) - break; - } - jif = jiffies + (3 * hertz); - ixj_ring_off(j); - while (time_before(jiffies, jif)) { - if (ixj_hookstate(j) & 1) { - msleep(10); - if (ixj_hookstate(j) & 1) { - j->flags.ringing = 0; - return 1; - } - } - schedule_timeout_interruptible(1); - if (signal_pending(current)) - break; - } - } - ixj_ring_off(j); - j->flags.ringing = 0; - return 0; -} - -static int ixj_open(struct phone_device *p, struct file *file_p) -{ - IXJ *j = get_ixj(p->board); - file_p->private_data = j; - - if (!j->DSPbase) - return -ENODEV; - - if (file_p->f_mode & FMODE_READ) { - if(!j->readers) { - j->readers++; - } else { - return -EBUSY; - } - } - - if (file_p->f_mode & FMODE_WRITE) { - if(!j->writers) { - j->writers++; - } else { - if (file_p->f_mode & FMODE_READ){ - j->readers--; - } - return -EBUSY; - } - } - - if (j->cardtype == QTI_PHONECARD) { - j->pslic.bits.powerdown = 0; - j->psccr.bits.dev = 3; - j->psccr.bits.rw = 0; - outw_p(j->psccr.byte << 8 | j->pslic.byte, j->XILINXbase + 0x00); - ixj_PCcontrol_wait(j); - } - - j->flags.cidplay = 0; - j->flags.cidcw_ack = 0; - - if (ixjdebug & 0x0002) - printk(KERN_INFO "Opening board %d\n", p->board); - - j->framesread = j->frameswritten = 0; - return 0; -} - -static int ixj_release(struct inode *inode, struct file *file_p) -{ - IXJ_TONE ti; - int cnt; - IXJ *j = file_p->private_data; - int board = j->p.board; - - /* - * Set up locks to ensure that only one process is talking to the DSP at a time. - * This is necessary to keep the DSP from locking up. - */ - while(test_and_set_bit(board, (void *)&j->busyflags) != 0) - schedule_timeout_interruptible(1); - if (ixjdebug & 0x0002) - printk(KERN_INFO "Closing board %d\n", NUM(inode)); - - if (j->cardtype == QTI_PHONECARD) - ixj_set_port(j, PORT_SPEAKER); - else - ixj_set_port(j, PORT_POTS); - - aec_stop(j); - ixj_play_stop(j); - ixj_record_stop(j); - set_play_volume(j, 0x100); - set_rec_volume(j, 0x100); - ixj_ring_off(j); - - /* Restore the tone table to default settings. */ - ti.tone_index = 10; - ti.gain0 = 1; - ti.freq0 = hz941; - ti.gain1 = 0; - ti.freq1 = hz1209; - ixj_init_tone(j, &ti); - ti.tone_index = 11; - ti.gain0 = 1; - ti.freq0 = hz941; - ti.gain1 = 0; - ti.freq1 = hz1336; - ixj_init_tone(j, &ti); - ti.tone_index = 12; - ti.gain0 = 1; - ti.freq0 = hz941; - ti.gain1 = 0; - ti.freq1 = hz1477; - ixj_init_tone(j, &ti); - ti.tone_index = 13; - ti.gain0 = 1; - ti.freq0 = hz800; - ti.gain1 = 0; - ti.freq1 = 0; - ixj_init_tone(j, &ti); - ti.tone_index = 14; - ti.gain0 = 1; - ti.freq0 = hz1000; - ti.gain1 = 0; - ti.freq1 = 0; - ixj_init_tone(j, &ti); - ti.tone_index = 15; - ti.gain0 = 1; - ti.freq0 = hz1250; - ti.gain1 = 0; - ti.freq1 = 0; - ixj_init_tone(j, &ti); - ti.tone_index = 16; - ti.gain0 = 1; - ti.freq0 = hz950; - ti.gain1 = 0; - ti.freq1 = 0; - ixj_init_tone(j, &ti); - ti.tone_index = 17; - ti.gain0 = 1; - ti.freq0 = hz1100; - ti.gain1 = 0; - ti.freq1 = 0; - ixj_init_tone(j, &ti); - ti.tone_index = 18; - ti.gain0 = 1; - ti.freq0 = hz1400; - ti.gain1 = 0; - ti.freq1 = 0; - ixj_init_tone(j, &ti); - ti.tone_index = 19; - ti.gain0 = 1; - ti.freq0 = hz1500; - ti.gain1 = 0; - ti.freq1 = 0; - ixj_init_tone(j, &ti); - ti.tone_index = 20; - ti.gain0 = 1; - ti.freq0 = hz1600; - ti.gain1 = 0; - ti.freq1 = 0; - ixj_init_tone(j, &ti); - ti.tone_index = 21; - ti.gain0 = 1; - ti.freq0 = hz1800; - ti.gain1 = 0; - ti.freq1 = 0; - ixj_init_tone(j, &ti); - ti.tone_index = 22; - ti.gain0 = 1; - ti.freq0 = hz2100; - ti.gain1 = 0; - ti.freq1 = 0; - ixj_init_tone(j, &ti); - ti.tone_index = 23; - ti.gain0 = 1; - ti.freq0 = hz1300; - ti.gain1 = 0; - ti.freq1 = 0; - ixj_init_tone(j, &ti); - ti.tone_index = 24; - ti.gain0 = 1; - ti.freq0 = hz2450; - ti.gain1 = 0; - ti.freq1 = 0; - ixj_init_tone(j, &ti); - ti.tone_index = 25; - ti.gain0 = 1; - ti.freq0 = hz350; - ti.gain1 = 0; - ti.freq1 = hz440; - ixj_init_tone(j, &ti); - ti.tone_index = 26; - ti.gain0 = 1; - ti.freq0 = hz440; - ti.gain1 = 0; - ti.freq1 = hz480; - ixj_init_tone(j, &ti); - ti.tone_index = 27; - ti.gain0 = 1; - ti.freq0 = hz480; - ti.gain1 = 0; - ti.freq1 = hz620; - ixj_init_tone(j, &ti); - - set_rec_depth(j, 2); /* Set Record Channel Limit to 2 frames */ - - set_play_depth(j, 2); /* Set Playback Channel Limit to 2 frames */ - - j->ex.bits.dtmf_ready = 0; - j->dtmf_state = 0; - j->dtmf_wp = j->dtmf_rp = 0; - j->rec_mode = j->play_mode = -1; - j->flags.ringing = 0; - j->maxrings = MAXRINGS; - j->ring_cadence = USA_RING_CADENCE; - if(j->cadence_f[5].enable) { - j->cadence_f[5].enable = j->cadence_f[5].en_filter = j->cadence_f[5].state = 0; - } - j->drybuffer = 0; - j->winktime = 320; - j->flags.dtmf_oob = 0; - for (cnt = 0; cnt < 4; cnt++) - j->cadence_f[cnt].enable = 0; - - idle(j); - - if(j->cardtype == QTI_PHONECARD) { - SLIC_SetState(PLD_SLIC_STATE_OC, j); - } - - if (file_p->f_mode & FMODE_READ) - j->readers--; - if (file_p->f_mode & FMODE_WRITE) - j->writers--; - - if (j->read_buffer && !j->readers) { - kfree(j->read_buffer); - j->read_buffer = NULL; - j->read_buffer_size = 0; - } - if (j->write_buffer && !j->writers) { - kfree(j->write_buffer); - j->write_buffer = NULL; - j->write_buffer_size = 0; - } - j->rec_codec = j->play_codec = 0; - j->rec_frame_size = j->play_frame_size = 0; - j->flags.cidsent = j->flags.cidring = 0; - - if(j->cardtype == QTI_LINEJACK && !j->readers && !j->writers) { - ixj_set_port(j, PORT_PSTN); - daa_set_mode(j, SOP_PU_SLEEP); - ixj_set_pots(j, 1); - } - ixj_WriteDSPCommand(0x0FE3, j); /* Put the DSP in 1/5 power mode. */ - - /* Set up the default signals for events */ - for (cnt = 0; cnt < 35; cnt++) - j->ixj_signals[cnt] = SIGIO; - - /* Set the excetion signal enable flags */ - j->ex_sig.bits.dtmf_ready = j->ex_sig.bits.hookstate = j->ex_sig.bits.flash = j->ex_sig.bits.pstn_ring = - j->ex_sig.bits.caller_id = j->ex_sig.bits.pstn_wink = j->ex_sig.bits.f0 = j->ex_sig.bits.f1 = j->ex_sig.bits.f2 = - j->ex_sig.bits.f3 = j->ex_sig.bits.fc0 = j->ex_sig.bits.fc1 = j->ex_sig.bits.fc2 = j->ex_sig.bits.fc3 = 1; - - file_p->private_data = NULL; - clear_bit(board, &j->busyflags); - return 0; -} - -static int read_filters(IXJ *j) -{ - unsigned short fc, cnt, trg; - int var; - - trg = 0; - if (ixj_WriteDSPCommand(0x5144, j)) { - if(ixjdebug & 0x0001) { - printk(KERN_INFO "Read Frame Counter failed!\n"); - } - return -1; - } - fc = j->ssr.high << 8 | j->ssr.low; - if (fc == j->frame_count) - return 1; - - j->frame_count = fc; - - if (j->dtmf_proc) - return 1; - - var = 10; - - for (cnt = 0; cnt < 4; cnt++) { - if (ixj_WriteDSPCommand(0x5154 + cnt, j)) { - if(ixjdebug & 0x0001) { - printk(KERN_INFO "Select Filter %d failed!\n", cnt); - } - return -1; - } - if (ixj_WriteDSPCommand(0x515C, j)) { - if(ixjdebug & 0x0001) { - printk(KERN_INFO "Read Filter History %d failed!\n", cnt); - } - return -1; - } - j->filter_hist[cnt] = j->ssr.high << 8 | j->ssr.low; - - if (j->cadence_f[cnt].enable) { - if (j->filter_hist[cnt] & 3 && !(j->filter_hist[cnt] & 12)) { - if (j->cadence_f[cnt].state == 0) { - j->cadence_f[cnt].state = 1; - j->cadence_f[cnt].on1min = jiffies + (long)((j->cadence_f[cnt].on1 * (hertz * (100 - var)) / 10000)); - j->cadence_f[cnt].on1dot = jiffies + (long)((j->cadence_f[cnt].on1 * (hertz * (100)) / 10000)); - j->cadence_f[cnt].on1max = jiffies + (long)((j->cadence_f[cnt].on1 * (hertz * (100 + var)) / 10000)); - } else if (j->cadence_f[cnt].state == 2 && - (time_after(jiffies, j->cadence_f[cnt].off1min) && - time_before(jiffies, j->cadence_f[cnt].off1max))) { - if (j->cadence_f[cnt].on2) { - j->cadence_f[cnt].state = 3; - j->cadence_f[cnt].on2min = jiffies + (long)((j->cadence_f[cnt].on2 * (hertz * (100 - var)) / 10000)); - j->cadence_f[cnt].on2dot = jiffies + (long)((j->cadence_f[cnt].on2 * (hertz * (100)) / 10000)); - j->cadence_f[cnt].on2max = jiffies + (long)((j->cadence_f[cnt].on2 * (hertz * (100 + var)) / 10000)); - } else { - j->cadence_f[cnt].state = 7; - } - } else if (j->cadence_f[cnt].state == 4 && - (time_after(jiffies, j->cadence_f[cnt].off2min) && - time_before(jiffies, j->cadence_f[cnt].off2max))) { - if (j->cadence_f[cnt].on3) { - j->cadence_f[cnt].state = 5; - j->cadence_f[cnt].on3min = jiffies + (long)((j->cadence_f[cnt].on3 * (hertz * (100 - var)) / 10000)); - j->cadence_f[cnt].on3dot = jiffies + (long)((j->cadence_f[cnt].on3 * (hertz * (100)) / 10000)); - j->cadence_f[cnt].on3max = jiffies + (long)((j->cadence_f[cnt].on3 * (hertz * (100 + var)) / 10000)); - } else { - j->cadence_f[cnt].state = 7; - } - } else { - j->cadence_f[cnt].state = 0; - } - } else if (j->filter_hist[cnt] & 12 && !(j->filter_hist[cnt] & 3)) { - if (j->cadence_f[cnt].state == 1) { - if(!j->cadence_f[cnt].on1) { - j->cadence_f[cnt].state = 7; - } else if((time_after(jiffies, j->cadence_f[cnt].on1min) && - time_before(jiffies, j->cadence_f[cnt].on1max))) { - if(j->cadence_f[cnt].off1) { - j->cadence_f[cnt].state = 2; - j->cadence_f[cnt].off1min = jiffies + (long)((j->cadence_f[cnt].off1 * (hertz * (100 - var)) / 10000)); - j->cadence_f[cnt].off1dot = jiffies + (long)((j->cadence_f[cnt].off1 * (hertz * (100)) / 10000)); - j->cadence_f[cnt].off1max = jiffies + (long)((j->cadence_f[cnt].off1 * (hertz * (100 + var)) / 10000)); - } else { - j->cadence_f[cnt].state = 7; - } - } else { - j->cadence_f[cnt].state = 0; - } - } else if (j->cadence_f[cnt].state == 3) { - if((time_after(jiffies, j->cadence_f[cnt].on2min) && - time_before(jiffies, j->cadence_f[cnt].on2max))) { - if(j->cadence_f[cnt].off2) { - j->cadence_f[cnt].state = 4; - j->cadence_f[cnt].off2min = jiffies + (long)((j->cadence_f[cnt].off2 * (hertz * (100 - var)) / 10000)); - j->cadence_f[cnt].off2dot = jiffies + (long)((j->cadence_f[cnt].off2 * (hertz * (100)) / 10000)); - j->cadence_f[cnt].off2max = jiffies + (long)((j->cadence_f[cnt].off2 * (hertz * (100 + var)) / 10000)); - } else { - j->cadence_f[cnt].state = 7; - } - } else { - j->cadence_f[cnt].state = 0; - } - } else if (j->cadence_f[cnt].state == 5) { - if ((time_after(jiffies, j->cadence_f[cnt].on3min) && - time_before(jiffies, j->cadence_f[cnt].on3max))) { - if(j->cadence_f[cnt].off3) { - j->cadence_f[cnt].state = 6; - j->cadence_f[cnt].off3min = jiffies + (long)((j->cadence_f[cnt].off3 * (hertz * (100 - var)) / 10000)); - j->cadence_f[cnt].off3dot = jiffies + (long)((j->cadence_f[cnt].off3 * (hertz * (100)) / 10000)); - j->cadence_f[cnt].off3max = jiffies + (long)((j->cadence_f[cnt].off3 * (hertz * (100 + var)) / 10000)); - } else { - j->cadence_f[cnt].state = 7; - } - } else { - j->cadence_f[cnt].state = 0; - } - } else { - j->cadence_f[cnt].state = 0; - } - } else { - switch(j->cadence_f[cnt].state) { - case 1: - if(time_after(jiffies, j->cadence_f[cnt].on1dot) && - !j->cadence_f[cnt].off1 && - !j->cadence_f[cnt].on2 && !j->cadence_f[cnt].off2 && - !j->cadence_f[cnt].on3 && !j->cadence_f[cnt].off3) { - j->cadence_f[cnt].state = 7; - } - break; - case 3: - if(time_after(jiffies, j->cadence_f[cnt].on2dot) && - !j->cadence_f[cnt].off2 && - !j->cadence_f[cnt].on3 && !j->cadence_f[cnt].off3) { - j->cadence_f[cnt].state = 7; - } - break; - case 5: - if(time_after(jiffies, j->cadence_f[cnt].on3dot) && - !j->cadence_f[cnt].off3) { - j->cadence_f[cnt].state = 7; - } - break; - } - } - - if (ixjdebug & 0x0040) { - printk(KERN_INFO "IXJ Tone Cadence state = %d /dev/phone%d at %ld\n", j->cadence_f[cnt].state, j->board, jiffies); - switch(j->cadence_f[cnt].state) { - case 0: - printk(KERN_INFO "IXJ /dev/phone%d No Tone detected\n", j->board); - break; - case 1: - printk(KERN_INFO "IXJ /dev/phone%d Next Tone Cadence state at %u %ld - %ld - %ld\n", j->board, - j->cadence_f[cnt].on1, j->cadence_f[cnt].on1min, j->cadence_f[cnt].on1dot, j->cadence_f[cnt].on1max); - break; - case 2: - printk(KERN_INFO "IXJ /dev/phone%d Next Tone Cadence state at %ld - %ld\n", j->board, j->cadence_f[cnt].off1min, - j->cadence_f[cnt].off1max); - break; - case 3: - printk(KERN_INFO "IXJ /dev/phone%d Next Tone Cadence state at %ld - %ld\n", j->board, j->cadence_f[cnt].on2min, - j->cadence_f[cnt].on2max); - break; - case 4: - printk(KERN_INFO "IXJ /dev/phone%d Next Tone Cadence state at %ld - %ld\n", j->board, j->cadence_f[cnt].off2min, - j->cadence_f[cnt].off2max); - break; - case 5: - printk(KERN_INFO "IXJ /dev/phone%d Next Tone Cadence state at %ld - %ld\n", j->board, j->cadence_f[cnt].on3min, - j->cadence_f[cnt].on3max); - break; - case 6: - printk(KERN_INFO "IXJ /dev/phone%d Next Tone Cadence state at %ld - %ld\n", j->board, j->cadence_f[cnt].off3min, - j->cadence_f[cnt].off3max); - break; - } - } - } - if (j->cadence_f[cnt].state == 7) { - j->cadence_f[cnt].state = 0; - if (j->cadence_f[cnt].enable == 1) - j->cadence_f[cnt].enable = 0; - switch (cnt) { - case 0: - if(ixjdebug & 0x0020) { - printk(KERN_INFO "Filter Cadence 0 triggered %ld\n", jiffies); - } - j->ex.bits.fc0 = 1; - ixj_kill_fasync(j, SIG_FC0, POLL_IN); - break; - case 1: - if(ixjdebug & 0x0020) { - printk(KERN_INFO "Filter Cadence 1 triggered %ld\n", jiffies); - } - j->ex.bits.fc1 = 1; - ixj_kill_fasync(j, SIG_FC1, POLL_IN); - break; - case 2: - if(ixjdebug & 0x0020) { - printk(KERN_INFO "Filter Cadence 2 triggered %ld\n", jiffies); - } - j->ex.bits.fc2 = 1; - ixj_kill_fasync(j, SIG_FC2, POLL_IN); - break; - case 3: - if(ixjdebug & 0x0020) { - printk(KERN_INFO "Filter Cadence 3 triggered %ld\n", jiffies); - } - j->ex.bits.fc3 = 1; - ixj_kill_fasync(j, SIG_FC3, POLL_IN); - break; - } - } - if (j->filter_en[cnt] && ((j->filter_hist[cnt] & 3 && !(j->filter_hist[cnt] & 12)) || - (j->filter_hist[cnt] & 12 && !(j->filter_hist[cnt] & 3)))) { - if((j->filter_hist[cnt] & 3 && !(j->filter_hist[cnt] & 12))) { - trg = 1; - } else if((j->filter_hist[cnt] & 12 && !(j->filter_hist[cnt] & 3))) { - trg = 0; - } - switch (cnt) { - case 0: - if(ixjdebug & 0x0020) { - printk(KERN_INFO "Filter 0 triggered %d at %ld\n", trg, jiffies); - } - j->ex.bits.f0 = 1; - ixj_kill_fasync(j, SIG_F0, POLL_IN); - break; - case 1: - if(ixjdebug & 0x0020) { - printk(KERN_INFO "Filter 1 triggered %d at %ld\n", trg, jiffies); - } - j->ex.bits.f1 = 1; - ixj_kill_fasync(j, SIG_F1, POLL_IN); - break; - case 2: - if(ixjdebug & 0x0020) { - printk(KERN_INFO "Filter 2 triggered %d at %ld\n", trg, jiffies); - } - j->ex.bits.f2 = 1; - ixj_kill_fasync(j, SIG_F2, POLL_IN); - break; - case 3: - if(ixjdebug & 0x0020) { - printk(KERN_INFO "Filter 3 triggered %d at %ld\n", trg, jiffies); - } - j->ex.bits.f3 = 1; - ixj_kill_fasync(j, SIG_F3, POLL_IN); - break; - } - } - } - return 0; -} - -static int LineMonitor(IXJ *j) -{ - if (j->dtmf_proc) { - return -1; - } - j->dtmf_proc = 1; - - if (ixj_WriteDSPCommand(0x7000, j)) /* Line Monitor */ - return -1; - - j->dtmf.bytes.high = j->ssr.high; - j->dtmf.bytes.low = j->ssr.low; - if (!j->dtmf_state && j->dtmf.bits.dtmf_valid) { - j->dtmf_state = 1; - j->dtmf_current = j->dtmf.bits.digit; - } - if (j->dtmf_state && !j->dtmf.bits.dtmf_valid) /* && j->dtmf_wp != j->dtmf_rp) */ - { - if(!j->cidcw_wait) { - j->dtmfbuffer[j->dtmf_wp] = j->dtmf_current; - j->dtmf_wp++; - if (j->dtmf_wp == 79) - j->dtmf_wp = 0; - j->ex.bits.dtmf_ready = 1; - if(j->ex_sig.bits.dtmf_ready) { - ixj_kill_fasync(j, SIG_DTMF_READY, POLL_IN); - } - } - else if(j->dtmf_current == 0x00 || j->dtmf_current == 0x0D) { - if(ixjdebug & 0x0020) { - printk("IXJ phone%d saw CIDCW Ack DTMF %d from display at %ld\n", j->board, j->dtmf_current, jiffies); - } - j->flags.cidcw_ack = 1; - } - j->dtmf_state = 0; - } - j->dtmf_proc = 0; - - return 0; -} - -/************************************************************************ -* -* Functions to allow alaw <-> ulaw conversions. -* -************************************************************************/ - -static void ulaw2alaw(unsigned char *buff, unsigned long len) -{ - static unsigned char table_ulaw2alaw[] = - { - 0x2A, 0x2B, 0x28, 0x29, 0x2E, 0x2F, 0x2C, 0x2D, - 0x22, 0x23, 0x20, 0x21, 0x26, 0x27, 0x24, 0x25, - 0x3A, 0x3B, 0x38, 0x39, 0x3E, 0x3F, 0x3C, 0x3D, - 0x32, 0x33, 0x30, 0x31, 0x36, 0x37, 0x34, 0x35, - 0x0B, 0x08, 0x09, 0x0E, 0x0F, 0x0C, 0x0D, 0x02, - 0x03, 0x00, 0x01, 0x06, 0x07, 0x04, 0x05, 0x1A, - 0x1B, 0x18, 0x19, 0x1E, 0x1F, 0x1C, 0x1D, 0x12, - 0x13, 0x10, 0x11, 0x16, 0x17, 0x14, 0x15, 0x6B, - 0x68, 0x69, 0x6E, 0x6F, 0x6C, 0x6D, 0x62, 0x63, - 0x60, 0x61, 0x66, 0x67, 0x64, 0x65, 0x7B, 0x79, - 0x7E, 0x7F, 0x7C, 0x7D, 0x72, 0x73, 0x70, 0x71, - 0x76, 0x77, 0x74, 0x75, 0x4B, 0x49, 0x4F, 0x4D, - 0x42, 0x43, 0x40, 0x41, 0x46, 0x47, 0x44, 0x45, - 0x5A, 0x5B, 0x58, 0x59, 0x5E, 0x5F, 0x5C, 0x5D, - 0x52, 0x52, 0x53, 0x53, 0x50, 0x50, 0x51, 0x51, - 0x56, 0x56, 0x57, 0x57, 0x54, 0x54, 0x55, 0xD5, - 0xAA, 0xAB, 0xA8, 0xA9, 0xAE, 0xAF, 0xAC, 0xAD, - 0xA2, 0xA3, 0xA0, 0xA1, 0xA6, 0xA7, 0xA4, 0xA5, - 0xBA, 0xBB, 0xB8, 0xB9, 0xBE, 0xBF, 0xBC, 0xBD, - 0xB2, 0xB3, 0xB0, 0xB1, 0xB6, 0xB7, 0xB4, 0xB5, - 0x8B, 0x88, 0x89, 0x8E, 0x8F, 0x8C, 0x8D, 0x82, - 0x83, 0x80, 0x81, 0x86, 0x87, 0x84, 0x85, 0x9A, - 0x9B, 0x98, 0x99, 0x9E, 0x9F, 0x9C, 0x9D, 0x92, - 0x93, 0x90, 0x91, 0x96, 0x97, 0x94, 0x95, 0xEB, - 0xE8, 0xE9, 0xEE, 0xEF, 0xEC, 0xED, 0xE2, 0xE3, - 0xE0, 0xE1, 0xE6, 0xE7, 0xE4, 0xE5, 0xFB, 0xF9, - 0xFE, 0xFF, 0xFC, 0xFD, 0xF2, 0xF3, 0xF0, 0xF1, - 0xF6, 0xF7, 0xF4, 0xF5, 0xCB, 0xC9, 0xCF, 0xCD, - 0xC2, 0xC3, 0xC0, 0xC1, 0xC6, 0xC7, 0xC4, 0xC5, - 0xDA, 0xDB, 0xD8, 0xD9, 0xDE, 0xDF, 0xDC, 0xDD, - 0xD2, 0xD2, 0xD3, 0xD3, 0xD0, 0xD0, 0xD1, 0xD1, - 0xD6, 0xD6, 0xD7, 0xD7, 0xD4, 0xD4, 0xD5, 0xD5 - }; - - while (len--) - { - *buff = table_ulaw2alaw[*(unsigned char *)buff]; - buff++; - } -} - -static void alaw2ulaw(unsigned char *buff, unsigned long len) -{ - static unsigned char table_alaw2ulaw[] = - { - 0x29, 0x2A, 0x27, 0x28, 0x2D, 0x2E, 0x2B, 0x2C, - 0x21, 0x22, 0x1F, 0x20, 0x25, 0x26, 0x23, 0x24, - 0x39, 0x3A, 0x37, 0x38, 0x3D, 0x3E, 0x3B, 0x3C, - 0x31, 0x32, 0x2F, 0x30, 0x35, 0x36, 0x33, 0x34, - 0x0A, 0x0B, 0x08, 0x09, 0x0E, 0x0F, 0x0C, 0x0D, - 0x02, 0x03, 0x00, 0x01, 0x06, 0x07, 0x04, 0x05, - 0x1A, 0x1B, 0x18, 0x19, 0x1E, 0x1F, 0x1C, 0x1D, - 0x12, 0x13, 0x10, 0x11, 0x16, 0x17, 0x14, 0x15, - 0x62, 0x63, 0x60, 0x61, 0x66, 0x67, 0x64, 0x65, - 0x5D, 0x5D, 0x5C, 0x5C, 0x5F, 0x5F, 0x5E, 0x5E, - 0x74, 0x76, 0x70, 0x72, 0x7C, 0x7E, 0x78, 0x7A, - 0x6A, 0x6B, 0x68, 0x69, 0x6E, 0x6F, 0x6C, 0x6D, - 0x48, 0x49, 0x46, 0x47, 0x4C, 0x4D, 0x4A, 0x4B, - 0x40, 0x41, 0x3F, 0x3F, 0x44, 0x45, 0x42, 0x43, - 0x56, 0x57, 0x54, 0x55, 0x5A, 0x5B, 0x58, 0x59, - 0x4F, 0x4F, 0x4E, 0x4E, 0x52, 0x53, 0x50, 0x51, - 0xA9, 0xAA, 0xA7, 0xA8, 0xAD, 0xAE, 0xAB, 0xAC, - 0xA1, 0xA2, 0x9F, 0xA0, 0xA5, 0xA6, 0xA3, 0xA4, - 0xB9, 0xBA, 0xB7, 0xB8, 0xBD, 0xBE, 0xBB, 0xBC, - 0xB1, 0xB2, 0xAF, 0xB0, 0xB5, 0xB6, 0xB3, 0xB4, - 0x8A, 0x8B, 0x88, 0x89, 0x8E, 0x8F, 0x8C, 0x8D, - 0x82, 0x83, 0x80, 0x81, 0x86, 0x87, 0x84, 0x85, - 0x9A, 0x9B, 0x98, 0x99, 0x9E, 0x9F, 0x9C, 0x9D, - 0x92, 0x93, 0x90, 0x91, 0x96, 0x97, 0x94, 0x95, - 0xE2, 0xE3, 0xE0, 0xE1, 0xE6, 0xE7, 0xE4, 0xE5, - 0xDD, 0xDD, 0xDC, 0xDC, 0xDF, 0xDF, 0xDE, 0xDE, - 0xF4, 0xF6, 0xF0, 0xF2, 0xFC, 0xFE, 0xF8, 0xFA, - 0xEA, 0xEB, 0xE8, 0xE9, 0xEE, 0xEF, 0xEC, 0xED, - 0xC8, 0xC9, 0xC6, 0xC7, 0xCC, 0xCD, 0xCA, 0xCB, - 0xC0, 0xC1, 0xBF, 0xBF, 0xC4, 0xC5, 0xC2, 0xC3, - 0xD6, 0xD7, 0xD4, 0xD5, 0xDA, 0xDB, 0xD8, 0xD9, - 0xCF, 0xCF, 0xCE, 0xCE, 0xD2, 0xD3, 0xD0, 0xD1 - }; - - while (len--) - { - *buff = table_alaw2ulaw[*(unsigned char *)buff]; - buff++; - } -} - -static ssize_t ixj_read(struct file * file_p, char __user *buf, size_t length, loff_t * ppos) -{ - unsigned long i = *ppos; - IXJ * j = get_ixj(NUM(file_p->f_path.dentry->d_inode)); - - DECLARE_WAITQUEUE(wait, current); - - if (j->flags.inread) - return -EALREADY; - - j->flags.inread = 1; - - add_wait_queue(&j->read_q, &wait); - set_current_state(TASK_INTERRUPTIBLE); - mb(); - - while (!j->read_buffer_ready || (j->dtmf_state && j->flags.dtmf_oob)) { - ++j->read_wait; - if (file_p->f_flags & O_NONBLOCK) { - set_current_state(TASK_RUNNING); - remove_wait_queue(&j->read_q, &wait); - j->flags.inread = 0; - return -EAGAIN; - } - if (!ixj_hookstate(j)) { - set_current_state(TASK_RUNNING); - remove_wait_queue(&j->read_q, &wait); - j->flags.inread = 0; - return 0; - } - interruptible_sleep_on(&j->read_q); - if (signal_pending(current)) { - set_current_state(TASK_RUNNING); - remove_wait_queue(&j->read_q, &wait); - j->flags.inread = 0; - return -EINTR; - } - } - - remove_wait_queue(&j->read_q, &wait); - set_current_state(TASK_RUNNING); - /* Don't ever copy more than the user asks */ - if(j->rec_codec == ALAW) - ulaw2alaw(j->read_buffer, min(length, j->read_buffer_size)); - i = copy_to_user(buf, j->read_buffer, min(length, j->read_buffer_size)); - j->read_buffer_ready = 0; - if (i) { - j->flags.inread = 0; - return -EFAULT; - } else { - j->flags.inread = 0; - return min(length, j->read_buffer_size); - } -} - -static ssize_t ixj_enhanced_read(struct file * file_p, char __user *buf, size_t length, - loff_t * ppos) -{ - int pre_retval; - ssize_t read_retval = 0; - IXJ *j = get_ixj(NUM(file_p->f_path.dentry->d_inode)); - - pre_retval = ixj_PreRead(j, 0L); - switch (pre_retval) { - case NORMAL: - read_retval = ixj_read(file_p, buf, length, ppos); - ixj_PostRead(j, 0L); - break; - case NOPOST: - read_retval = ixj_read(file_p, buf, length, ppos); - break; - case POSTONLY: - ixj_PostRead(j, 0L); - break; - default: - read_retval = pre_retval; - } - return read_retval; -} - -static ssize_t ixj_write(struct file *file_p, const char __user *buf, size_t count, loff_t * ppos) -{ - unsigned long i = *ppos; - IXJ *j = file_p->private_data; - - DECLARE_WAITQUEUE(wait, current); - - if (j->flags.inwrite) - return -EALREADY; - - j->flags.inwrite = 1; - - add_wait_queue(&j->write_q, &wait); - set_current_state(TASK_INTERRUPTIBLE); - mb(); - - - while (!j->write_buffers_empty) { - ++j->write_wait; - if (file_p->f_flags & O_NONBLOCK) { - set_current_state(TASK_RUNNING); - remove_wait_queue(&j->write_q, &wait); - j->flags.inwrite = 0; - return -EAGAIN; - } - if (!ixj_hookstate(j)) { - set_current_state(TASK_RUNNING); - remove_wait_queue(&j->write_q, &wait); - j->flags.inwrite = 0; - return 0; - } - interruptible_sleep_on(&j->write_q); - if (signal_pending(current)) { - set_current_state(TASK_RUNNING); - remove_wait_queue(&j->write_q, &wait); - j->flags.inwrite = 0; - return -EINTR; - } - } - set_current_state(TASK_RUNNING); - remove_wait_queue(&j->write_q, &wait); - if (j->write_buffer_wp + count >= j->write_buffer_end) - j->write_buffer_wp = j->write_buffer; - i = copy_from_user(j->write_buffer_wp, buf, min(count, j->write_buffer_size)); - if (i) { - j->flags.inwrite = 0; - return -EFAULT; - } - if(j->play_codec == ALAW) - alaw2ulaw(j->write_buffer_wp, min(count, j->write_buffer_size)); - j->flags.inwrite = 0; - return min(count, j->write_buffer_size); -} - -static ssize_t ixj_enhanced_write(struct file * file_p, const char __user *buf, size_t count, loff_t * ppos) -{ - int pre_retval; - ssize_t write_retval = 0; - - IXJ *j = get_ixj(NUM(file_p->f_path.dentry->d_inode)); - - pre_retval = ixj_PreWrite(j, 0L); - switch (pre_retval) { - case NORMAL: - write_retval = ixj_write(file_p, buf, count, ppos); - if (write_retval > 0) { - ixj_PostWrite(j, 0L); - j->write_buffer_wp += write_retval; - j->write_buffers_empty--; - } - break; - case NOPOST: - write_retval = ixj_write(file_p, buf, count, ppos); - if (write_retval > 0) { - j->write_buffer_wp += write_retval; - j->write_buffers_empty--; - } - break; - case POSTONLY: - ixj_PostWrite(j, 0L); - break; - default: - write_retval = pre_retval; - } - return write_retval; -} - -static void ixj_read_frame(IXJ *j) -{ - int cnt, dly; - - if (j->read_buffer) { - for (cnt = 0; cnt < j->rec_frame_size * 2; cnt += 2) { - if (!(cnt % 16) && !IsRxReady(j)) { - dly = 0; - while (!IsRxReady(j)) { - if (dly++ > 5) { - dly = 0; - break; - } - udelay(10); - } - } - /* Throw away word 0 of the 8021 compressed format to get standard G.729. */ - if (j->rec_codec == G729 && (cnt == 0 || cnt == 10 || cnt == 20)) { - inb_p(j->DSPbase + 0x0E); - inb_p(j->DSPbase + 0x0F); - } - *(j->read_buffer + cnt) = inb_p(j->DSPbase + 0x0E); - *(j->read_buffer + cnt + 1) = inb_p(j->DSPbase + 0x0F); - } - ++j->framesread; - if (j->intercom != -1) { - if (IsTxReady(get_ixj(j->intercom))) { - for (cnt = 0; cnt < j->rec_frame_size * 2; cnt += 2) { - if (!(cnt % 16) && !IsTxReady(j)) { - dly = 0; - while (!IsTxReady(j)) { - if (dly++ > 5) { - dly = 0; - break; - } - udelay(10); - } - } - outb_p(*(j->read_buffer + cnt), get_ixj(j->intercom)->DSPbase + 0x0C); - outb_p(*(j->read_buffer + cnt + 1), get_ixj(j->intercom)->DSPbase + 0x0D); - } - get_ixj(j->intercom)->frameswritten++; - } - } else { - j->read_buffer_ready = 1; - wake_up_interruptible(&j->read_q); /* Wake any blocked readers */ - - wake_up_interruptible(&j->poll_q); /* Wake any blocked selects */ - - if(j->ixj_signals[SIG_READ_READY]) - ixj_kill_fasync(j, SIG_READ_READY, POLL_OUT); - } - } -} - -static short fsk[][6][20] = -{ - { - { - 0, 17846, 29934, 32364, 24351, 8481, -10126, -25465, -32587, -29196, - -16384, 1715, 19260, 30591, 32051, 23170, 6813, -11743, -26509, -32722 - }, - { - -28377, -14876, 3425, 20621, 31163, 31650, 21925, 5126, -13328, -27481, - -32767, -27481, -13328, 5126, 21925, 31650, 31163, 20621, 3425, -14876 - }, - { - -28377, -32722, -26509, -11743, 6813, 23170, 32051, 30591, 19260, 1715, - -16384, -29196, -32587, -25465, -10126, 8481, 24351, 32364, 29934, 17846 - }, - { - 0, -17846, -29934, -32364, -24351, -8481, 10126, 25465, 32587, 29196, - 16384, -1715, -19260, -30591, -32051, -23170, -6813, 11743, 26509, 32722 - }, - { - 28377, 14876, -3425, -20621, -31163, -31650, -21925, -5126, 13328, 27481, - 32767, 27481, 13328, -5126, -21925, -31650, -31163, -20621, -3425, 14876 - }, - { - 28377, 32722, 26509, 11743, -6813, -23170, -32051, -30591, -19260, -1715, - 16384, 29196, 32587, 25465, 10126, -8481, -24351, -32364, -29934, -17846 - } - }, - { - { - 0, 10126, 19260, 26509, 31163, 32767, 31163, 26509, 19260, 10126, - 0, -10126, -19260, -26509, -31163, -32767, -31163, -26509, -19260, -10126 - }, - { - -28377, -21925, -13328, -3425, 6813, 16384, 24351, 29934, 32587, 32051, - 28377, 21925, 13328, 3425, -6813, -16384, -24351, -29934, -32587, -32051 - }, - { - -28377, -32051, -32587, -29934, -24351, -16384, -6813, 3425, 13328, 21925, - 28377, 32051, 32587, 29934, 24351, 16384, 6813, -3425, -13328, -21925 - }, - { - 0, -10126, -19260, -26509, -31163, -32767, -31163, -26509, -19260, -10126, - 0, 10126, 19260, 26509, 31163, 32767, 31163, 26509, 19260, 10126 - }, - { - 28377, 21925, 13328, 3425, -6813, -16383, -24351, -29934, -32587, -32051, - -28377, -21925, -13328, -3425, 6813, 16383, 24351, 29934, 32587, 32051 - }, - { - 28377, 32051, 32587, 29934, 24351, 16384, 6813, -3425, -13328, -21925, - -28377, -32051, -32587, -29934, -24351, -16384, -6813, 3425, 13328, 21925 - } - } -}; - - -static void ixj_write_cid_bit(IXJ *j, int bit) -{ - while (j->fskcnt < 20) { - if(j->fskdcnt < (j->fsksize - 1)) - j->fskdata[j->fskdcnt++] = fsk[bit][j->fskz][j->fskcnt]; - - j->fskcnt += 3; - } - j->fskcnt %= 20; - - if (!bit) - j->fskz++; - if (j->fskz >= 6) - j->fskz = 0; - -} - -static void ixj_write_cid_byte(IXJ *j, char byte) -{ - IXJ_CBYTE cb; - - cb.cbyte = byte; - ixj_write_cid_bit(j, 0); - ixj_write_cid_bit(j, cb.cbits.b0 ? 1 : 0); - ixj_write_cid_bit(j, cb.cbits.b1 ? 1 : 0); - ixj_write_cid_bit(j, cb.cbits.b2 ? 1 : 0); - ixj_write_cid_bit(j, cb.cbits.b3 ? 1 : 0); - ixj_write_cid_bit(j, cb.cbits.b4 ? 1 : 0); - ixj_write_cid_bit(j, cb.cbits.b5 ? 1 : 0); - ixj_write_cid_bit(j, cb.cbits.b6 ? 1 : 0); - ixj_write_cid_bit(j, cb.cbits.b7 ? 1 : 0); - ixj_write_cid_bit(j, 1); -} - -static void ixj_write_cid_seize(IXJ *j) -{ - int cnt; - - for (cnt = 0; cnt < 150; cnt++) { - ixj_write_cid_bit(j, 0); - ixj_write_cid_bit(j, 1); - } - for (cnt = 0; cnt < 180; cnt++) { - ixj_write_cid_bit(j, 1); - } -} - -static void ixj_write_cidcw_seize(IXJ *j) -{ - int cnt; - - for (cnt = 0; cnt < 80; cnt++) { - ixj_write_cid_bit(j, 1); - } -} - -static int ixj_write_cid_string(IXJ *j, char *s, int checksum) -{ - int cnt; - - for (cnt = 0; cnt < strlen(s); cnt++) { - ixj_write_cid_byte(j, s[cnt]); - checksum = (checksum + s[cnt]); - } - return checksum; -} - -static void ixj_pad_fsk(IXJ *j, int pad) -{ - int cnt; - - for (cnt = 0; cnt < pad; cnt++) { - if(j->fskdcnt < (j->fsksize - 1)) - j->fskdata[j->fskdcnt++] = 0x0000; - } - for (cnt = 0; cnt < 720; cnt++) { - if(j->fskdcnt < (j->fsksize - 1)) - j->fskdata[j->fskdcnt++] = 0x0000; - } -} - -static void ixj_pre_cid(IXJ *j) -{ - j->cid_play_codec = j->play_codec; - j->cid_play_frame_size = j->play_frame_size; - j->cid_play_volume = get_play_volume(j); - j->cid_play_flag = j->flags.playing; - - j->cid_rec_codec = j->rec_codec; - j->cid_rec_volume = get_rec_volume(j); - j->cid_rec_flag = j->flags.recording; - - j->cid_play_aec_level = j->aec_level; - - switch(j->baseframe.low) { - case 0xA0: - j->cid_base_frame_size = 20; - break; - case 0x50: - j->cid_base_frame_size = 10; - break; - case 0xF0: - j->cid_base_frame_size = 30; - break; - } - - ixj_play_stop(j); - ixj_cpt_stop(j); - - j->flags.cidplay = 1; - - set_base_frame(j, 30); - set_play_codec(j, LINEAR16); - set_play_volume(j, 0x1B); - ixj_play_start(j); -} - -static void ixj_post_cid(IXJ *j) -{ - ixj_play_stop(j); - - if(j->cidsize > 5000) { - SLIC_SetState(PLD_SLIC_STATE_STANDBY, j); - } - j->flags.cidplay = 0; - if(ixjdebug & 0x0200) { - printk("IXJ phone%d Finished Playing CallerID data %ld\n", j->board, jiffies); - } - - ixj_fsk_free(j); - - j->fskdcnt = 0; - set_base_frame(j, j->cid_base_frame_size); - set_play_codec(j, j->cid_play_codec); - ixj_aec_start(j, j->cid_play_aec_level); - set_play_volume(j, j->cid_play_volume); - - set_rec_codec(j, j->cid_rec_codec); - set_rec_volume(j, j->cid_rec_volume); - - if(j->cid_rec_flag) - ixj_record_start(j); - - if(j->cid_play_flag) - ixj_play_start(j); - - if(j->cid_play_flag) { - wake_up_interruptible(&j->write_q); /* Wake any blocked writers */ - } -} - -static void ixj_write_cid(IXJ *j) -{ - char sdmf1[50]; - char sdmf2[50]; - char sdmf3[80]; - char mdmflen, len1, len2, len3; - int pad; - - int checksum = 0; - - if (j->dsp.low == 0x20 || j->flags.cidplay) - return; - - j->fskz = j->fskphase = j->fskcnt = j->fskdcnt = 0; - j->cidsize = j->cidcnt = 0; - - ixj_fsk_alloc(j); - - strcpy(sdmf1, j->cid_send.month); - strcat(sdmf1, j->cid_send.day); - strcat(sdmf1, j->cid_send.hour); - strcat(sdmf1, j->cid_send.min); - strcpy(sdmf2, j->cid_send.number); - strcpy(sdmf3, j->cid_send.name); - - len1 = strlen(sdmf1); - len2 = strlen(sdmf2); - len3 = strlen(sdmf3); - mdmflen = len1 + len2 + len3 + 6; - - while(1){ - ixj_write_cid_seize(j); - - ixj_write_cid_byte(j, 0x80); - checksum = 0x80; - ixj_write_cid_byte(j, mdmflen); - checksum = checksum + mdmflen; - - ixj_write_cid_byte(j, 0x01); - checksum = checksum + 0x01; - ixj_write_cid_byte(j, len1); - checksum = checksum + len1; - checksum = ixj_write_cid_string(j, sdmf1, checksum); - if(ixj_hookstate(j) & 1) - break; - - ixj_write_cid_byte(j, 0x02); - checksum = checksum + 0x02; - ixj_write_cid_byte(j, len2); - checksum = checksum + len2; - checksum = ixj_write_cid_string(j, sdmf2, checksum); - if(ixj_hookstate(j) & 1) - break; - - ixj_write_cid_byte(j, 0x07); - checksum = checksum + 0x07; - ixj_write_cid_byte(j, len3); - checksum = checksum + len3; - checksum = ixj_write_cid_string(j, sdmf3, checksum); - if(ixj_hookstate(j) & 1) - break; - - checksum %= 256; - checksum ^= 0xFF; - checksum += 1; - - ixj_write_cid_byte(j, (char) checksum); - - pad = j->fskdcnt % 240; - if (pad) { - pad = 240 - pad; - } - ixj_pad_fsk(j, pad); - break; - } - - ixj_write_frame(j); -} - -static void ixj_write_cidcw(IXJ *j) -{ - IXJ_TONE ti; - - char sdmf1[50]; - char sdmf2[50]; - char sdmf3[80]; - char mdmflen, len1, len2, len3; - int pad; - - int checksum = 0; - - if (j->dsp.low == 0x20 || j->flags.cidplay) - return; - - j->fskz = j->fskphase = j->fskcnt = j->fskdcnt = 0; - j->cidsize = j->cidcnt = 0; - - ixj_fsk_alloc(j); - - j->flags.cidcw_ack = 0; - - ti.tone_index = 23; - ti.gain0 = 1; - ti.freq0 = hz440; - ti.gain1 = 0; - ti.freq1 = 0; - ixj_init_tone(j, &ti); - - ixj_set_tone_on(1500, j); - ixj_set_tone_off(32, j); - if(ixjdebug & 0x0200) { - printk("IXJ cidcw phone%d first tone start at %ld\n", j->board, jiffies); - } - ixj_play_tone(j, 23); - - clear_bit(j->board, &j->busyflags); - while(j->tone_state) - schedule_timeout_interruptible(1); - while(test_and_set_bit(j->board, (void *)&j->busyflags) != 0) - schedule_timeout_interruptible(1); - if(ixjdebug & 0x0200) { - printk("IXJ cidcw phone%d first tone end at %ld\n", j->board, jiffies); - } - - ti.tone_index = 24; - ti.gain0 = 1; - ti.freq0 = hz2130; - ti.gain1 = 0; - ti.freq1 = hz2750; - ixj_init_tone(j, &ti); - - ixj_set_tone_off(10, j); - ixj_set_tone_on(600, j); - if(ixjdebug & 0x0200) { - printk("IXJ cidcw phone%d second tone start at %ld\n", j->board, jiffies); - } - ixj_play_tone(j, 24); - - clear_bit(j->board, &j->busyflags); - while(j->tone_state) - schedule_timeout_interruptible(1); - while(test_and_set_bit(j->board, (void *)&j->busyflags) != 0) - schedule_timeout_interruptible(1); - if(ixjdebug & 0x0200) { - printk("IXJ cidcw phone%d sent second tone at %ld\n", j->board, jiffies); - } - - j->cidcw_wait = jiffies + ((50 * hertz) / 100); - - clear_bit(j->board, &j->busyflags); - while(!j->flags.cidcw_ack && time_before(jiffies, j->cidcw_wait)) - schedule_timeout_interruptible(1); - while(test_and_set_bit(j->board, (void *)&j->busyflags) != 0) - schedule_timeout_interruptible(1); - j->cidcw_wait = 0; - if(!j->flags.cidcw_ack) { - if(ixjdebug & 0x0200) { - printk("IXJ cidcw phone%d did not receive ACK from display %ld\n", j->board, jiffies); - } - ixj_post_cid(j); - if(j->cid_play_flag) { - wake_up_interruptible(&j->write_q); /* Wake any blocked readers */ - } - return; - } else { - ixj_pre_cid(j); - } - j->flags.cidcw_ack = 0; - strcpy(sdmf1, j->cid_send.month); - strcat(sdmf1, j->cid_send.day); - strcat(sdmf1, j->cid_send.hour); - strcat(sdmf1, j->cid_send.min); - strcpy(sdmf2, j->cid_send.number); - strcpy(sdmf3, j->cid_send.name); - - len1 = strlen(sdmf1); - len2 = strlen(sdmf2); - len3 = strlen(sdmf3); - mdmflen = len1 + len2 + len3 + 6; - - ixj_write_cidcw_seize(j); - - ixj_write_cid_byte(j, 0x80); - checksum = 0x80; - ixj_write_cid_byte(j, mdmflen); - checksum = checksum + mdmflen; - - ixj_write_cid_byte(j, 0x01); - checksum = checksum + 0x01; - ixj_write_cid_byte(j, len1); - checksum = checksum + len1; - checksum = ixj_write_cid_string(j, sdmf1, checksum); - - ixj_write_cid_byte(j, 0x02); - checksum = checksum + 0x02; - ixj_write_cid_byte(j, len2); - checksum = checksum + len2; - checksum = ixj_write_cid_string(j, sdmf2, checksum); - - ixj_write_cid_byte(j, 0x07); - checksum = checksum + 0x07; - ixj_write_cid_byte(j, len3); - checksum = checksum + len3; - checksum = ixj_write_cid_string(j, sdmf3, checksum); - - checksum %= 256; - checksum ^= 0xFF; - checksum += 1; - - ixj_write_cid_byte(j, (char) checksum); - - pad = j->fskdcnt % 240; - if (pad) { - pad = 240 - pad; - } - ixj_pad_fsk(j, pad); - if(ixjdebug & 0x0200) { - printk("IXJ cidcw phone%d sent FSK data at %ld\n", j->board, jiffies); - } -} - -static void ixj_write_vmwi(IXJ *j, int msg) -{ - char mdmflen; - int pad; - - int checksum = 0; - - if (j->dsp.low == 0x20 || j->flags.cidplay) - return; - - j->fskz = j->fskphase = j->fskcnt = j->fskdcnt = 0; - j->cidsize = j->cidcnt = 0; - - ixj_fsk_alloc(j); - - mdmflen = 3; - - if (j->port == PORT_POTS) - SLIC_SetState(PLD_SLIC_STATE_OHT, j); - - ixj_write_cid_seize(j); - - ixj_write_cid_byte(j, 0x82); - checksum = 0x82; - ixj_write_cid_byte(j, mdmflen); - checksum = checksum + mdmflen; - - ixj_write_cid_byte(j, 0x0B); - checksum = checksum + 0x0B; - ixj_write_cid_byte(j, 1); - checksum = checksum + 1; - - if(msg) { - ixj_write_cid_byte(j, 0xFF); - checksum = checksum + 0xFF; - } - else { - ixj_write_cid_byte(j, 0x00); - checksum = checksum + 0x00; - } - - checksum %= 256; - checksum ^= 0xFF; - checksum += 1; - - ixj_write_cid_byte(j, (char) checksum); - - pad = j->fskdcnt % 240; - if (pad) { - pad = 240 - pad; - } - ixj_pad_fsk(j, pad); -} - -static void ixj_write_frame(IXJ *j) -{ - int cnt, frame_count, dly; - IXJ_WORD dat; - - frame_count = 0; - if(j->flags.cidplay) { - for(cnt = 0; cnt < 480; cnt++) { - if (!(cnt % 16) && !IsTxReady(j)) { - dly = 0; - while (!IsTxReady(j)) { - if (dly++ > 5) { - dly = 0; - break; - } - udelay(10); - } - } - dat.word = j->fskdata[j->cidcnt++]; - outb_p(dat.bytes.low, j->DSPbase + 0x0C); - outb_p(dat.bytes.high, j->DSPbase + 0x0D); - cnt++; - } - if(j->cidcnt >= j->fskdcnt) { - ixj_post_cid(j); - } - /* This may seem rude, but if we just played one frame of FSK data for CallerID - and there is real audio data in the buffer, we need to throw it away because - we just used it's time slot */ - if (j->write_buffer_rp > j->write_buffer_wp) { - j->write_buffer_rp += j->cid_play_frame_size * 2; - if (j->write_buffer_rp >= j->write_buffer_end) { - j->write_buffer_rp = j->write_buffer; - } - j->write_buffers_empty++; - wake_up_interruptible(&j->write_q); /* Wake any blocked writers */ - - wake_up_interruptible(&j->poll_q); /* Wake any blocked selects */ - } - } else if (j->write_buffer && j->write_buffers_empty < 1) { - if (j->write_buffer_wp > j->write_buffer_rp) { - frame_count = - (j->write_buffer_wp - j->write_buffer_rp) / (j->play_frame_size * 2); - } - if (j->write_buffer_rp > j->write_buffer_wp) { - frame_count = - (j->write_buffer_wp - j->write_buffer) / (j->play_frame_size * 2) + - (j->write_buffer_end - j->write_buffer_rp) / (j->play_frame_size * 2); - } - if (frame_count >= 1) { - if (j->ver.low == 0x12 && j->play_mode && j->flags.play_first_frame) { - BYTES blankword; - - switch (j->play_mode) { - case PLAYBACK_MODE_ULAW: - case PLAYBACK_MODE_ALAW: - blankword.low = blankword.high = 0xFF; - break; - case PLAYBACK_MODE_8LINEAR: - case PLAYBACK_MODE_16LINEAR: - default: - blankword.low = blankword.high = 0x00; - break; - case PLAYBACK_MODE_8LINEAR_WSS: - blankword.low = blankword.high = 0x80; - break; - } - for (cnt = 0; cnt < 16; cnt++) { - if (!(cnt % 16) && !IsTxReady(j)) { - dly = 0; - while (!IsTxReady(j)) { - if (dly++ > 5) { - dly = 0; - break; - } - udelay(10); - } - } - outb_p((blankword.low), j->DSPbase + 0x0C); - outb_p((blankword.high), j->DSPbase + 0x0D); - } - j->flags.play_first_frame = 0; - } else if (j->play_codec == G723_63 && j->flags.play_first_frame) { - for (cnt = 0; cnt < 24; cnt++) { - BYTES blankword; - - if(cnt == 12) { - blankword.low = 0x02; - blankword.high = 0x00; - } - else { - blankword.low = blankword.high = 0x00; - } - if (!(cnt % 16) && !IsTxReady(j)) { - dly = 0; - while (!IsTxReady(j)) { - if (dly++ > 5) { - dly = 0; - break; - } - udelay(10); - } - } - outb_p((blankword.low), j->DSPbase + 0x0C); - outb_p((blankword.high), j->DSPbase + 0x0D); - } - j->flags.play_first_frame = 0; - } - for (cnt = 0; cnt < j->play_frame_size * 2; cnt += 2) { - if (!(cnt % 16) && !IsTxReady(j)) { - dly = 0; - while (!IsTxReady(j)) { - if (dly++ > 5) { - dly = 0; - break; - } - udelay(10); - } - } - /* Add word 0 to G.729 frames for the 8021. Right now we don't do VAD/CNG */ - if (j->play_codec == G729 && (cnt == 0 || cnt == 10 || cnt == 20)) { - if (j->write_buffer_rp[cnt] == 0 && - j->write_buffer_rp[cnt + 1] == 0 && - j->write_buffer_rp[cnt + 2] == 0 && - j->write_buffer_rp[cnt + 3] == 0 && - j->write_buffer_rp[cnt + 4] == 0 && - j->write_buffer_rp[cnt + 5] == 0 && - j->write_buffer_rp[cnt + 6] == 0 && - j->write_buffer_rp[cnt + 7] == 0 && - j->write_buffer_rp[cnt + 8] == 0 && - j->write_buffer_rp[cnt + 9] == 0) { - /* someone is trying to write silence lets make this a type 0 frame. */ - outb_p(0x00, j->DSPbase + 0x0C); - outb_p(0x00, j->DSPbase + 0x0D); - } else { - /* so all other frames are type 1. */ - outb_p(0x01, j->DSPbase + 0x0C); - outb_p(0x00, j->DSPbase + 0x0D); - } - } - outb_p(*(j->write_buffer_rp + cnt), j->DSPbase + 0x0C); - outb_p(*(j->write_buffer_rp + cnt + 1), j->DSPbase + 0x0D); - *(j->write_buffer_rp + cnt) = 0; - *(j->write_buffer_rp + cnt + 1) = 0; - } - j->write_buffer_rp += j->play_frame_size * 2; - if (j->write_buffer_rp >= j->write_buffer_end) { - j->write_buffer_rp = j->write_buffer; - } - j->write_buffers_empty++; - wake_up_interruptible(&j->write_q); /* Wake any blocked writers */ - - wake_up_interruptible(&j->poll_q); /* Wake any blocked selects */ - - ++j->frameswritten; - } - } else { - j->drybuffer++; - } - if(j->ixj_signals[SIG_WRITE_READY]) { - ixj_kill_fasync(j, SIG_WRITE_READY, POLL_OUT); - } -} - -static int idle(IXJ *j) -{ - if (ixj_WriteDSPCommand(0x0000, j)) /* DSP Idle */ - - return 0; - - if (j->ssr.high || j->ssr.low) { - return 0; - } else { - j->play_mode = -1; - j->flags.playing = 0; - j->rec_mode = -1; - j->flags.recording = 0; - return 1; - } -} - -static int set_base_frame(IXJ *j, int size) -{ - unsigned short cmd; - int cnt; - - idle(j); - j->cid_play_aec_level = j->aec_level; - aec_stop(j); - for (cnt = 0; cnt < 10; cnt++) { - if (idle(j)) - break; - } - if (j->ssr.high || j->ssr.low) - return -1; - if (j->dsp.low != 0x20) { - switch (size) { - case 30: - cmd = 0x07F0; - /* Set Base Frame Size to 240 pg9-10 8021 */ - break; - case 20: - cmd = 0x07A0; - /* Set Base Frame Size to 160 pg9-10 8021 */ - break; - case 10: - cmd = 0x0750; - /* Set Base Frame Size to 80 pg9-10 8021 */ - break; - default: - return -1; - } - } else { - if (size == 30) - return size; - else - return -1; - } - if (ixj_WriteDSPCommand(cmd, j)) { - j->baseframe.high = j->baseframe.low = 0xFF; - return -1; - } else { - j->baseframe.high = j->ssr.high; - j->baseframe.low = j->ssr.low; - /* If the status returned is 0x0000 (pg9-9 8021) the call failed */ - if(j->baseframe.high == 0x00 && j->baseframe.low == 0x00) { - return -1; - } - } - ixj_aec_start(j, j->cid_play_aec_level); - return size; -} - -static int set_rec_codec(IXJ *j, int rate) -{ - int retval = 0; - - j->rec_codec = rate; - - switch (rate) { - case G723_63: - if (j->ver.low != 0x12 || ixj_convert_loaded) { - j->rec_frame_size = 12; - j->rec_mode = 0; - } else { - retval = 1; - } - break; - case G723_53: - if (j->ver.low != 0x12 || ixj_convert_loaded) { - j->rec_frame_size = 10; - j->rec_mode = 0; - } else { - retval = 1; - } - break; - case TS85: - if (j->dsp.low == 0x20 || j->flags.ts85_loaded) { - j->rec_frame_size = 16; - j->rec_mode = 0; - } else { - retval = 1; - } - break; - case TS48: - if (j->ver.low != 0x12 || ixj_convert_loaded) { - j->rec_frame_size = 9; - j->rec_mode = 0; - } else { - retval = 1; - } - break; - case TS41: - if (j->ver.low != 0x12 || ixj_convert_loaded) { - j->rec_frame_size = 8; - j->rec_mode = 0; - } else { - retval = 1; - } - break; - case G728: - if (j->dsp.low != 0x20) { - j->rec_frame_size = 48; - j->rec_mode = 0; - } else { - retval = 1; - } - break; - case G729: - if (j->dsp.low != 0x20) { - if (!j->flags.g729_loaded) { - retval = 1; - break; - } - switch (j->baseframe.low) { - case 0xA0: - j->rec_frame_size = 10; - break; - case 0x50: - j->rec_frame_size = 5; - break; - default: - j->rec_frame_size = 15; - break; - } - j->rec_mode = 0; - } else { - retval = 1; - } - break; - case G729B: - if (j->dsp.low != 0x20) { - if (!j->flags.g729_loaded) { - retval = 1; - break; - } - switch (j->baseframe.low) { - case 0xA0: - j->rec_frame_size = 12; - break; - case 0x50: - j->rec_frame_size = 6; - break; - default: - j->rec_frame_size = 18; - break; - } - j->rec_mode = 0; - } else { - retval = 1; - } - break; - case ULAW: - switch (j->baseframe.low) { - case 0xA0: - j->rec_frame_size = 80; - break; - case 0x50: - j->rec_frame_size = 40; - break; - default: - j->rec_frame_size = 120; - break; - } - j->rec_mode = 4; - break; - case ALAW: - switch (j->baseframe.low) { - case 0xA0: - j->rec_frame_size = 80; - break; - case 0x50: - j->rec_frame_size = 40; - break; - default: - j->rec_frame_size = 120; - break; - } - j->rec_mode = 4; - break; - case LINEAR16: - switch (j->baseframe.low) { - case 0xA0: - j->rec_frame_size = 160; - break; - case 0x50: - j->rec_frame_size = 80; - break; - default: - j->rec_frame_size = 240; - break; - } - j->rec_mode = 5; - break; - case LINEAR8: - switch (j->baseframe.low) { - case 0xA0: - j->rec_frame_size = 80; - break; - case 0x50: - j->rec_frame_size = 40; - break; - default: - j->rec_frame_size = 120; - break; - } - j->rec_mode = 6; - break; - case WSS: - switch (j->baseframe.low) { - case 0xA0: - j->rec_frame_size = 80; - break; - case 0x50: - j->rec_frame_size = 40; - break; - default: - j->rec_frame_size = 120; - break; - } - j->rec_mode = 7; - break; - default: - kfree(j->read_buffer); - j->rec_frame_size = 0; - j->rec_mode = -1; - j->read_buffer = NULL; - j->read_buffer_size = 0; - retval = 1; - break; - } - return retval; -} - -static int ixj_record_start(IXJ *j) -{ - unsigned short cmd = 0x0000; - - if (j->read_buffer) { - ixj_record_stop(j); - } - j->flags.recording = 1; - ixj_WriteDSPCommand(0x0FE0, j); /* Put the DSP in full power mode. */ - - if(ixjdebug & 0x0002) - printk("IXJ %d Starting Record Codec %d at %ld\n", j->board, j->rec_codec, jiffies); - - if (!j->rec_mode) { - switch (j->rec_codec) { - case G723_63: - cmd = 0x5131; - break; - case G723_53: - cmd = 0x5132; - break; - case TS85: - cmd = 0x5130; /* TrueSpeech 8.5 */ - - break; - case TS48: - cmd = 0x5133; /* TrueSpeech 4.8 */ - - break; - case TS41: - cmd = 0x5134; /* TrueSpeech 4.1 */ - - break; - case G728: - cmd = 0x5135; - break; - case G729: - case G729B: - cmd = 0x5136; - break; - default: - return 1; - } - if (ixj_WriteDSPCommand(cmd, j)) - return -1; - } - if (!j->read_buffer) { - if (!j->read_buffer) - j->read_buffer = kmalloc(j->rec_frame_size * 2, GFP_ATOMIC); - if (!j->read_buffer) { - printk("Read buffer allocation for ixj board %d failed!\n", j->board); - return -ENOMEM; - } - } - j->read_buffer_size = j->rec_frame_size * 2; - - if (ixj_WriteDSPCommand(0x5102, j)) /* Set Poll sync mode */ - - return -1; - - switch (j->rec_mode) { - case 0: - cmd = 0x1C03; /* Record C1 */ - - break; - case 4: - if (j->ver.low == 0x12) { - cmd = 0x1E03; /* Record C1 */ - - } else { - cmd = 0x1E01; /* Record C1 */ - - } - break; - case 5: - if (j->ver.low == 0x12) { - cmd = 0x1E83; /* Record C1 */ - - } else { - cmd = 0x1E81; /* Record C1 */ - - } - break; - case 6: - if (j->ver.low == 0x12) { - cmd = 0x1F03; /* Record C1 */ - - } else { - cmd = 0x1F01; /* Record C1 */ - - } - break; - case 7: - if (j->ver.low == 0x12) { - cmd = 0x1F83; /* Record C1 */ - } else { - cmd = 0x1F81; /* Record C1 */ - } - break; - } - if (ixj_WriteDSPCommand(cmd, j)) - return -1; - - if (j->flags.playing) { - ixj_aec_start(j, j->aec_level); - } - return 0; -} - -static void ixj_record_stop(IXJ *j) -{ - if (ixjdebug & 0x0002) - printk("IXJ %d Stopping Record Codec %d at %ld\n", j->board, j->rec_codec, jiffies); - - kfree(j->read_buffer); - j->read_buffer = NULL; - j->read_buffer_size = 0; - if (j->rec_mode > -1) { - ixj_WriteDSPCommand(0x5120, j); - j->rec_mode = -1; - } - j->flags.recording = 0; -} -static void ixj_vad(IXJ *j, int arg) -{ - if (arg) - ixj_WriteDSPCommand(0x513F, j); - else - ixj_WriteDSPCommand(0x513E, j); -} - -static void set_rec_depth(IXJ *j, int depth) -{ - if (depth > 60) - depth = 60; - if (depth < 0) - depth = 0; - ixj_WriteDSPCommand(0x5180 + depth, j); -} - -static void set_dtmf_prescale(IXJ *j, int volume) -{ - ixj_WriteDSPCommand(0xCF07, j); - ixj_WriteDSPCommand(volume, j); -} - -static int get_dtmf_prescale(IXJ *j) -{ - ixj_WriteDSPCommand(0xCF05, j); - return j->ssr.high << 8 | j->ssr.low; -} - -static void set_rec_volume(IXJ *j, int volume) -{ - if(j->aec_level == AEC_AGC) { - if (ixjdebug & 0x0002) - printk(KERN_INFO "IXJ: /dev/phone%d Setting AGC Threshold to 0x%4.4x\n", j->board, volume); - ixj_WriteDSPCommand(0xCF96, j); - ixj_WriteDSPCommand(volume, j); - } else { - if (ixjdebug & 0x0002) - printk(KERN_INFO "IXJ: /dev/phone %d Setting Record Volume to 0x%4.4x\n", j->board, volume); - ixj_WriteDSPCommand(0xCF03, j); - ixj_WriteDSPCommand(volume, j); - } -} - -static int set_rec_volume_linear(IXJ *j, int volume) -{ - int newvolume, dsprecmax; - - if (ixjdebug & 0x0002) - printk(KERN_INFO "IXJ: /dev/phone %d Setting Linear Record Volume to 0x%4.4x\n", j->board, volume); - if(volume > 100 || volume < 0) { - return -1; - } - - /* This should normalize the perceived volumes between the different cards caused by differences in the hardware */ - switch (j->cardtype) { - case QTI_PHONEJACK: - dsprecmax = 0x440; - break; - case QTI_LINEJACK: - dsprecmax = 0x180; - ixj_mixer(0x0203, j); /*Voice Left Volume unmute 6db */ - ixj_mixer(0x0303, j); /*Voice Right Volume unmute 6db */ - ixj_mixer(0x0C00, j); /*Mono1 unmute 12db */ - break; - case QTI_PHONEJACK_LITE: - dsprecmax = 0x4C0; - break; - case QTI_PHONEJACK_PCI: - dsprecmax = 0x100; - break; - case QTI_PHONECARD: - dsprecmax = 0x400; - break; - default: - return -1; - } - newvolume = (dsprecmax * volume) / 100; - set_rec_volume(j, newvolume); - return 0; -} - -static int get_rec_volume(IXJ *j) -{ - if(j->aec_level == AEC_AGC) { - if (ixjdebug & 0x0002) - printk(KERN_INFO "Getting AGC Threshold\n"); - ixj_WriteDSPCommand(0xCF86, j); - if (ixjdebug & 0x0002) - printk(KERN_INFO "AGC Threshold is 0x%2.2x%2.2x\n", j->ssr.high, j->ssr.low); - return j->ssr.high << 8 | j->ssr.low; - } else { - if (ixjdebug & 0x0002) - printk(KERN_INFO "Getting Record Volume\n"); - ixj_WriteDSPCommand(0xCF01, j); - return j->ssr.high << 8 | j->ssr.low; - } -} - -static int get_rec_volume_linear(IXJ *j) -{ - int volume, newvolume, dsprecmax; - - switch (j->cardtype) { - case QTI_PHONEJACK: - dsprecmax = 0x440; - break; - case QTI_LINEJACK: - dsprecmax = 0x180; - break; - case QTI_PHONEJACK_LITE: - dsprecmax = 0x4C0; - break; - case QTI_PHONEJACK_PCI: - dsprecmax = 0x100; - break; - case QTI_PHONECARD: - dsprecmax = 0x400; - break; - default: - return -1; - } - volume = get_rec_volume(j); - newvolume = (volume * 100) / dsprecmax; - if(newvolume > 100) - newvolume = 100; - return newvolume; -} - -static int get_rec_level(IXJ *j) -{ - int retval; - - ixj_WriteDSPCommand(0xCF88, j); - - retval = j->ssr.high << 8 | j->ssr.low; - retval = (retval * 256) / 240; - return retval; -} - -static void ixj_aec_start(IXJ *j, int level) -{ - j->aec_level = level; - if (ixjdebug & 0x0002) - printk(KERN_INFO "AGC set = 0x%2.2x\n", j->aec_level); - if (!level) { - aec_stop(j); - } else { - if (j->rec_codec == G729 || j->play_codec == G729 || j->rec_codec == G729B || j->play_codec == G729B) { - ixj_WriteDSPCommand(0xE022, j); /* Move AEC filter buffer */ - - ixj_WriteDSPCommand(0x0300, j); - } - ixj_WriteDSPCommand(0xB001, j); /* AEC On */ - - ixj_WriteDSPCommand(0xE013, j); /* Advanced AEC C1 */ - - switch (level) { - case AEC_LOW: - ixj_WriteDSPCommand(0x0000, j); /* Advanced AEC C2 = off */ - - ixj_WriteDSPCommand(0xE011, j); - ixj_WriteDSPCommand(0xFFFF, j); - - ixj_WriteDSPCommand(0xCF97, j); /* Set AGC Enable */ - ixj_WriteDSPCommand(0x0000, j); /* to off */ - - break; - - case AEC_MED: - ixj_WriteDSPCommand(0x0600, j); /* Advanced AEC C2 = on medium */ - - ixj_WriteDSPCommand(0xE011, j); - ixj_WriteDSPCommand(0x0080, j); - - ixj_WriteDSPCommand(0xCF97, j); /* Set AGC Enable */ - ixj_WriteDSPCommand(0x0000, j); /* to off */ - - break; - - case AEC_HIGH: - ixj_WriteDSPCommand(0x0C00, j); /* Advanced AEC C2 = on high */ - - ixj_WriteDSPCommand(0xE011, j); - ixj_WriteDSPCommand(0x0080, j); - - ixj_WriteDSPCommand(0xCF97, j); /* Set AGC Enable */ - ixj_WriteDSPCommand(0x0000, j); /* to off */ - - break; - - case AEC_AGC: - /* First we have to put the AEC into advance auto mode so that AGC will not conflict with it */ - ixj_WriteDSPCommand(0x0002, j); /* Attenuation scaling factor of 2 */ - - ixj_WriteDSPCommand(0xE011, j); - ixj_WriteDSPCommand(0x0100, j); /* Higher Threshold Floor */ - - ixj_WriteDSPCommand(0xE012, j); /* Set Train and Lock */ - - if(j->cardtype == QTI_LINEJACK || j->cardtype == QTI_PHONECARD) - ixj_WriteDSPCommand(0x0224, j); - else - ixj_WriteDSPCommand(0x1224, j); - - ixj_WriteDSPCommand(0xE014, j); - ixj_WriteDSPCommand(0x0003, j); /* Lock threshold at 3dB */ - - ixj_WriteDSPCommand(0xE338, j); /* Set Echo Suppresser Attenuation to 0dB */ - - /* Now we can set the AGC initial parameters and turn it on */ - ixj_WriteDSPCommand(0xCF90, j); /* Set AGC Minimum gain */ - ixj_WriteDSPCommand(0x0020, j); /* to 0.125 (-18dB) */ - - ixj_WriteDSPCommand(0xCF91, j); /* Set AGC Maximum gain */ - ixj_WriteDSPCommand(0x1000, j); /* to 16 (24dB) */ - - ixj_WriteDSPCommand(0xCF92, j); /* Set AGC start gain */ - ixj_WriteDSPCommand(0x0800, j); /* to 8 (+18dB) */ - - ixj_WriteDSPCommand(0xCF93, j); /* Set AGC hold time */ - ixj_WriteDSPCommand(0x1F40, j); /* to 2 seconds (units are 250us) */ - - ixj_WriteDSPCommand(0xCF94, j); /* Set AGC Attack Time Constant */ - ixj_WriteDSPCommand(0x0005, j); /* to 8ms */ - - ixj_WriteDSPCommand(0xCF95, j); /* Set AGC Decay Time Constant */ - ixj_WriteDSPCommand(0x000D, j); /* to 4096ms */ - - ixj_WriteDSPCommand(0xCF96, j); /* Set AGC Attack Threshold */ - ixj_WriteDSPCommand(0x1200, j); /* to 25% */ - - ixj_WriteDSPCommand(0xCF97, j); /* Set AGC Enable */ - ixj_WriteDSPCommand(0x0001, j); /* to on */ - - break; - - case AEC_AUTO: - ixj_WriteDSPCommand(0x0002, j); /* Attenuation scaling factor of 2 */ - - ixj_WriteDSPCommand(0xE011, j); - ixj_WriteDSPCommand(0x0100, j); /* Higher Threshold Floor */ - - ixj_WriteDSPCommand(0xE012, j); /* Set Train and Lock */ - - if(j->cardtype == QTI_LINEJACK || j->cardtype == QTI_PHONECARD) - ixj_WriteDSPCommand(0x0224, j); - else - ixj_WriteDSPCommand(0x1224, j); - - ixj_WriteDSPCommand(0xE014, j); - ixj_WriteDSPCommand(0x0003, j); /* Lock threshold at 3dB */ - - ixj_WriteDSPCommand(0xE338, j); /* Set Echo Suppresser Attenuation to 0dB */ - - break; - } - } -} - -static void aec_stop(IXJ *j) -{ - j->aec_level = AEC_OFF; - if (j->rec_codec == G729 || j->play_codec == G729 || j->rec_codec == G729B || j->play_codec == G729B) { - ixj_WriteDSPCommand(0xE022, j); /* Move AEC filter buffer back */ - - ixj_WriteDSPCommand(0x0700, j); - } - if (j->play_mode != -1 && j->rec_mode != -1) - { - ixj_WriteDSPCommand(0xB002, j); /* AEC Stop */ - } -} - -static int set_play_codec(IXJ *j, int rate) -{ - int retval = 0; - - j->play_codec = rate; - - switch (rate) { - case G723_63: - if (j->ver.low != 0x12 || ixj_convert_loaded) { - j->play_frame_size = 12; - j->play_mode = 0; - } else { - retval = 1; - } - break; - case G723_53: - if (j->ver.low != 0x12 || ixj_convert_loaded) { - j->play_frame_size = 10; - j->play_mode = 0; - } else { - retval = 1; - } - break; - case TS85: - if (j->dsp.low == 0x20 || j->flags.ts85_loaded) { - j->play_frame_size = 16; - j->play_mode = 0; - } else { - retval = 1; - } - break; - case TS48: - if (j->ver.low != 0x12 || ixj_convert_loaded) { - j->play_frame_size = 9; - j->play_mode = 0; - } else { - retval = 1; - } - break; - case TS41: - if (j->ver.low != 0x12 || ixj_convert_loaded) { - j->play_frame_size = 8; - j->play_mode = 0; - } else { - retval = 1; - } - break; - case G728: - if (j->dsp.low != 0x20) { - j->play_frame_size = 48; - j->play_mode = 0; - } else { - retval = 1; - } - break; - case G729: - if (j->dsp.low != 0x20) { - if (!j->flags.g729_loaded) { - retval = 1; - break; - } - switch (j->baseframe.low) { - case 0xA0: - j->play_frame_size = 10; - break; - case 0x50: - j->play_frame_size = 5; - break; - default: - j->play_frame_size = 15; - break; - } - j->play_mode = 0; - } else { - retval = 1; - } - break; - case G729B: - if (j->dsp.low != 0x20) { - if (!j->flags.g729_loaded) { - retval = 1; - break; - } - switch (j->baseframe.low) { - case 0xA0: - j->play_frame_size = 12; - break; - case 0x50: - j->play_frame_size = 6; - break; - default: - j->play_frame_size = 18; - break; - } - j->play_mode = 0; - } else { - retval = 1; - } - break; - case ULAW: - switch (j->baseframe.low) { - case 0xA0: - j->play_frame_size = 80; - break; - case 0x50: - j->play_frame_size = 40; - break; - default: - j->play_frame_size = 120; - break; - } - j->play_mode = 2; - break; - case ALAW: - switch (j->baseframe.low) { - case 0xA0: - j->play_frame_size = 80; - break; - case 0x50: - j->play_frame_size = 40; - break; - default: - j->play_frame_size = 120; - break; - } - j->play_mode = 2; - break; - case LINEAR16: - switch (j->baseframe.low) { - case 0xA0: - j->play_frame_size = 160; - break; - case 0x50: - j->play_frame_size = 80; - break; - default: - j->play_frame_size = 240; - break; - } - j->play_mode = 6; - break; - case LINEAR8: - switch (j->baseframe.low) { - case 0xA0: - j->play_frame_size = 80; - break; - case 0x50: - j->play_frame_size = 40; - break; - default: - j->play_frame_size = 120; - break; - } - j->play_mode = 4; - break; - case WSS: - switch (j->baseframe.low) { - case 0xA0: - j->play_frame_size = 80; - break; - case 0x50: - j->play_frame_size = 40; - break; - default: - j->play_frame_size = 120; - break; - } - j->play_mode = 5; - break; - default: - kfree(j->write_buffer); - j->play_frame_size = 0; - j->play_mode = -1; - j->write_buffer = NULL; - j->write_buffer_size = 0; - retval = 1; - break; - } - return retval; -} - -static int ixj_play_start(IXJ *j) -{ - unsigned short cmd = 0x0000; - - if (j->write_buffer) { - ixj_play_stop(j); - } - - if(ixjdebug & 0x0002) - printk("IXJ %d Starting Play Codec %d at %ld\n", j->board, j->play_codec, jiffies); - - j->flags.playing = 1; - ixj_WriteDSPCommand(0x0FE0, j); /* Put the DSP in full power mode. */ - - j->flags.play_first_frame = 1; - j->drybuffer = 0; - - if (!j->play_mode) { - switch (j->play_codec) { - case G723_63: - cmd = 0x5231; - break; - case G723_53: - cmd = 0x5232; - break; - case TS85: - cmd = 0x5230; /* TrueSpeech 8.5 */ - - break; - case TS48: - cmd = 0x5233; /* TrueSpeech 4.8 */ - - break; - case TS41: - cmd = 0x5234; /* TrueSpeech 4.1 */ - - break; - case G728: - cmd = 0x5235; - break; - case G729: - case G729B: - cmd = 0x5236; - break; - default: - return 1; - } - if (ixj_WriteDSPCommand(cmd, j)) - return -1; - } - j->write_buffer = kmalloc(j->play_frame_size * 2, GFP_ATOMIC); - if (!j->write_buffer) { - printk("Write buffer allocation for ixj board %d failed!\n", j->board); - return -ENOMEM; - } -/* j->write_buffers_empty = 2; */ - j->write_buffers_empty = 1; - j->write_buffer_size = j->play_frame_size * 2; - j->write_buffer_end = j->write_buffer + j->play_frame_size * 2; - j->write_buffer_rp = j->write_buffer_wp = j->write_buffer; - - if (ixj_WriteDSPCommand(0x5202, j)) /* Set Poll sync mode */ - - return -1; - - switch (j->play_mode) { - case 0: - cmd = 0x2C03; - break; - case 2: - if (j->ver.low == 0x12) { - cmd = 0x2C23; - } else { - cmd = 0x2C21; - } - break; - case 4: - if (j->ver.low == 0x12) { - cmd = 0x2C43; - } else { - cmd = 0x2C41; - } - break; - case 5: - if (j->ver.low == 0x12) { - cmd = 0x2C53; - } else { - cmd = 0x2C51; - } - break; - case 6: - if (j->ver.low == 0x12) { - cmd = 0x2C63; - } else { - cmd = 0x2C61; - } - break; - } - if (ixj_WriteDSPCommand(cmd, j)) - return -1; - - if (ixj_WriteDSPCommand(0x2000, j)) /* Playback C2 */ - return -1; - - if (ixj_WriteDSPCommand(0x2000 + j->play_frame_size, j)) /* Playback C3 */ - return -1; - - if (j->flags.recording) { - ixj_aec_start(j, j->aec_level); - } - - return 0; -} - -static void ixj_play_stop(IXJ *j) -{ - if (ixjdebug & 0x0002) - printk("IXJ %d Stopping Play Codec %d at %ld\n", j->board, j->play_codec, jiffies); - - kfree(j->write_buffer); - j->write_buffer = NULL; - j->write_buffer_size = 0; - if (j->play_mode > -1) { - ixj_WriteDSPCommand(0x5221, j); /* Stop playback and flush buffers. 8022 reference page 9-40 */ - - j->play_mode = -1; - } - j->flags.playing = 0; -} - -static inline int get_play_level(IXJ *j) -{ - int retval; - - ixj_WriteDSPCommand(0xCF8F, j); /* 8022 Reference page 9-38 */ - return j->ssr.high << 8 | j->ssr.low; - retval = j->ssr.high << 8 | j->ssr.low; - retval = (retval * 256) / 240; - return retval; -} - -static unsigned int ixj_poll(struct file *file_p, poll_table * wait) -{ - unsigned int mask = 0; - - IXJ *j = get_ixj(NUM(file_p->f_path.dentry->d_inode)); - - poll_wait(file_p, &(j->poll_q), wait); - if (j->read_buffer_ready > 0) - mask |= POLLIN | POLLRDNORM; /* readable */ - if (j->write_buffers_empty > 0) - mask |= POLLOUT | POLLWRNORM; /* writable */ - if (j->ex.bytes) - mask |= POLLPRI; - return mask; -} - -static int ixj_play_tone(IXJ *j, char tone) -{ - if (!j->tone_state) { - if(ixjdebug & 0x0002) { - printk("IXJ %d starting tone %d at %ld\n", j->board, tone, jiffies); - } - if (j->dsp.low == 0x20) { - idle(j); - } - j->tone_start_jif = jiffies; - - j->tone_state = 1; - } - - j->tone_index = tone; - if (ixj_WriteDSPCommand(0x6000 + j->tone_index, j)) - return -1; - - return 0; -} - -static int ixj_set_tone_on(unsigned short arg, IXJ *j) -{ - j->tone_on_time = arg; - - if (ixj_WriteDSPCommand(0x6E04, j)) /* Set Tone On Period */ - - return -1; - - if (ixj_WriteDSPCommand(arg, j)) - return -1; - - return 0; -} - -static int SCI_WaitHighSCI(IXJ *j) -{ - int cnt; - - j->pld_scrr.byte = inb_p(j->XILINXbase); - if (!j->pld_scrr.bits.sci) { - for (cnt = 0; cnt < 10; cnt++) { - udelay(32); - j->pld_scrr.byte = inb_p(j->XILINXbase); - - if ((j->pld_scrr.bits.sci)) - return 1; - } - if (ixjdebug & 0x0001) - printk(KERN_INFO "SCI Wait High failed %x\n", j->pld_scrr.byte); - return 0; - } else - return 1; -} - -static int SCI_WaitLowSCI(IXJ *j) -{ - int cnt; - - j->pld_scrr.byte = inb_p(j->XILINXbase); - if (j->pld_scrr.bits.sci) { - for (cnt = 0; cnt < 10; cnt++) { - udelay(32); - j->pld_scrr.byte = inb_p(j->XILINXbase); - - if (!(j->pld_scrr.bits.sci)) - return 1; - } - if (ixjdebug & 0x0001) - printk(KERN_INFO "SCI Wait Low failed %x\n", j->pld_scrr.byte); - return 0; - } else - return 1; -} - -static int SCI_Control(IXJ *j, int control) -{ - switch (control) { - case SCI_End: - j->pld_scrw.bits.c0 = 0; /* Set PLD Serial control interface */ - - j->pld_scrw.bits.c1 = 0; /* to no selection */ - - break; - case SCI_Enable_DAA: - j->pld_scrw.bits.c0 = 1; /* Set PLD Serial control interface */ - - j->pld_scrw.bits.c1 = 0; /* to write to DAA */ - - break; - case SCI_Enable_Mixer: - j->pld_scrw.bits.c0 = 0; /* Set PLD Serial control interface */ - - j->pld_scrw.bits.c1 = 1; /* to write to mixer */ - - break; - case SCI_Enable_EEPROM: - j->pld_scrw.bits.c0 = 1; /* Set PLD Serial control interface */ - - j->pld_scrw.bits.c1 = 1; /* to write to EEPROM */ - - break; - default: - return 0; - break; - } - outb_p(j->pld_scrw.byte, j->XILINXbase); - - switch (control) { - case SCI_End: - return 1; - break; - case SCI_Enable_DAA: - case SCI_Enable_Mixer: - case SCI_Enable_EEPROM: - if (!SCI_WaitHighSCI(j)) - return 0; - break; - default: - return 0; - break; - } - return 1; -} - -static int SCI_Prepare(IXJ *j) -{ - if (!SCI_Control(j, SCI_End)) - return 0; - - if (!SCI_WaitLowSCI(j)) - return 0; - - return 1; -} - -static int ixj_get_mixer(long val, IXJ *j) -{ - int reg = (val & 0x1F00) >> 8; - return j->mix.vol[reg]; -} - -static int ixj_mixer(long val, IXJ *j) -{ - BYTES bytes; - - bytes.high = (val & 0x1F00) >> 8; - bytes.low = val & 0x00FF; - - /* save mixer value so we can get back later on */ - j->mix.vol[bytes.high] = bytes.low; - - outb_p(bytes.high & 0x1F, j->XILINXbase + 0x03); /* Load Mixer Address */ - - outb_p(bytes.low, j->XILINXbase + 0x02); /* Load Mixer Data */ - - SCI_Control(j, SCI_Enable_Mixer); - - SCI_Control(j, SCI_End); - - return 0; -} - -static int daa_load(BYTES * p_bytes, IXJ *j) -{ - outb_p(p_bytes->high, j->XILINXbase + 0x03); - outb_p(p_bytes->low, j->XILINXbase + 0x02); - if (!SCI_Control(j, SCI_Enable_DAA)) - return 0; - else - return 1; -} - -static int ixj_daa_cr4(IXJ *j, char reg) -{ - BYTES bytes; - - switch (j->daa_mode) { - case SOP_PU_SLEEP: - bytes.high = 0x14; - break; - case SOP_PU_RINGING: - bytes.high = 0x54; - break; - case SOP_PU_CONVERSATION: - bytes.high = 0x94; - break; - case SOP_PU_PULSEDIALING: - bytes.high = 0xD4; - break; - } - - j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = reg; - - switch (j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.bitreg.AGX) { - case 0: - j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.bitreg.AGR_Z = 0; - break; - case 1: - j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.bitreg.AGR_Z = 2; - break; - case 2: - j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.bitreg.AGR_Z = 1; - break; - case 3: - j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.bitreg.AGR_Z = 3; - break; - } - - bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg; - - if (!daa_load(&bytes, j)) - return 0; - - if (!SCI_Prepare(j)) - return 0; - - return 1; -} - -static char daa_int_read(IXJ *j) -{ - BYTES bytes; - - if (!SCI_Prepare(j)) - return 0; - - bytes.high = 0x38; - bytes.low = 0x00; - outb_p(bytes.high, j->XILINXbase + 0x03); - outb_p(bytes.low, j->XILINXbase + 0x02); - - if (!SCI_Control(j, SCI_Enable_DAA)) - return 0; - - bytes.high = inb_p(j->XILINXbase + 0x03); - bytes.low = inb_p(j->XILINXbase + 0x02); - if (bytes.low != ALISDAA_ID_BYTE) { - if (ixjdebug & 0x0001) - printk("Cannot read DAA ID Byte high = %d low = %d\n", bytes.high, bytes.low); - return 0; - } - if (!SCI_Control(j, SCI_Enable_DAA)) - return 0; - if (!SCI_Control(j, SCI_End)) - return 0; - - bytes.high = inb_p(j->XILINXbase + 0x03); - bytes.low = inb_p(j->XILINXbase + 0x02); - - j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.reg = bytes.high; - - return 1; -} - -static char daa_CR_read(IXJ *j, int cr) -{ - IXJ_WORD wdata; - BYTES bytes; - - if (!SCI_Prepare(j)) - return 0; - - switch (j->daa_mode) { - case SOP_PU_SLEEP: - bytes.high = 0x30 + cr; - break; - case SOP_PU_RINGING: - bytes.high = 0x70 + cr; - break; - case SOP_PU_CONVERSATION: - bytes.high = 0xB0 + cr; - break; - case SOP_PU_PULSEDIALING: - default: - bytes.high = 0xF0 + cr; - break; - } - - bytes.low = 0x00; - - outb_p(bytes.high, j->XILINXbase + 0x03); - outb_p(bytes.low, j->XILINXbase + 0x02); - - if (!SCI_Control(j, SCI_Enable_DAA)) - return 0; - - bytes.high = inb_p(j->XILINXbase + 0x03); - bytes.low = inb_p(j->XILINXbase + 0x02); - if (bytes.low != ALISDAA_ID_BYTE) { - if (ixjdebug & 0x0001) - printk("Cannot read DAA ID Byte high = %d low = %d\n", bytes.high, bytes.low); - return 0; - } - if (!SCI_Control(j, SCI_Enable_DAA)) - return 0; - if (!SCI_Control(j, SCI_End)) - return 0; - - wdata.word = inw_p(j->XILINXbase + 0x02); - - switch(cr){ - case 5: - j->m_DAAShadowRegs.SOP_REGS.SOP.cr5.reg = wdata.bytes.high; - break; - case 4: - j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = wdata.bytes.high; - break; - case 3: - j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg = wdata.bytes.high; - break; - case 2: - j->m_DAAShadowRegs.SOP_REGS.SOP.cr2.reg = wdata.bytes.high; - break; - case 1: - j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.reg = wdata.bytes.high; - break; - case 0: - j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = wdata.bytes.high; - break; - default: - return 0; - } - return 1; -} - -static int ixj_daa_cid_reset(IXJ *j) -{ - int i; - BYTES bytes; - - if (ixjdebug & 0x0002) - printk("DAA Clearing CID ram\n"); - - if (!SCI_Prepare(j)) - return 0; - - bytes.high = 0x58; - bytes.low = 0x00; - outb_p(bytes.high, j->XILINXbase + 0x03); - outb_p(bytes.low, j->XILINXbase + 0x02); - - if (!SCI_Control(j, SCI_Enable_DAA)) - return 0; - - if (!SCI_WaitHighSCI(j)) - return 0; - - for (i = 0; i < ALISDAA_CALLERID_SIZE - 1; i += 2) { - bytes.high = bytes.low = 0x00; - outb_p(bytes.high, j->XILINXbase + 0x03); - - if (i < ALISDAA_CALLERID_SIZE - 1) - outb_p(bytes.low, j->XILINXbase + 0x02); - - if (!SCI_Control(j, SCI_Enable_DAA)) - return 0; - - if (!SCI_WaitHighSCI(j)) - return 0; - - } - - if (!SCI_Control(j, SCI_End)) - return 0; - - if (ixjdebug & 0x0002) - printk("DAA CID ram cleared\n"); - - return 1; -} - -static int ixj_daa_cid_read(IXJ *j) -{ - int i; - BYTES bytes; - char CID[ALISDAA_CALLERID_SIZE]; - bool mContinue; - char *pIn, *pOut; - - if (!SCI_Prepare(j)) - return 0; - - bytes.high = 0x78; - bytes.low = 0x00; - outb_p(bytes.high, j->XILINXbase + 0x03); - outb_p(bytes.low, j->XILINXbase + 0x02); - - if (!SCI_Control(j, SCI_Enable_DAA)) - return 0; - - if (!SCI_WaitHighSCI(j)) - return 0; - - bytes.high = inb_p(j->XILINXbase + 0x03); - bytes.low = inb_p(j->XILINXbase + 0x02); - if (bytes.low != ALISDAA_ID_BYTE) { - if (ixjdebug & 0x0001) - printk("DAA Get Version Cannot read DAA ID Byte high = %d low = %d\n", bytes.high, bytes.low); - return 0; - } - for (i = 0; i < ALISDAA_CALLERID_SIZE; i += 2) { - bytes.high = bytes.low = 0x00; - outb_p(bytes.high, j->XILINXbase + 0x03); - outb_p(bytes.low, j->XILINXbase + 0x02); - - if (!SCI_Control(j, SCI_Enable_DAA)) - return 0; - - if (!SCI_WaitHighSCI(j)) - return 0; - - CID[i + 0] = inb_p(j->XILINXbase + 0x03); - CID[i + 1] = inb_p(j->XILINXbase + 0x02); - } - - if (!SCI_Control(j, SCI_End)) - return 0; - - pIn = CID; - pOut = j->m_DAAShadowRegs.CAO_REGS.CAO.CallerID; - mContinue = true; - while (mContinue) { - if ((pIn[1] & 0x03) == 0x01) { - pOut[0] = pIn[0]; - } - if ((pIn[2] & 0x0c) == 0x04) { - pOut[1] = ((pIn[2] & 0x03) << 6) | ((pIn[1] & 0xfc) >> 2); - } - if ((pIn[3] & 0x30) == 0x10) { - pOut[2] = ((pIn[3] & 0x0f) << 4) | ((pIn[2] & 0xf0) >> 4); - } - if ((pIn[4] & 0xc0) == 0x40) { - pOut[3] = ((pIn[4] & 0x3f) << 2) | ((pIn[3] & 0xc0) >> 6); - } else { - mContinue = false; - } - pIn += 5, pOut += 4; - } - memset(&j->cid, 0, sizeof(PHONE_CID)); - pOut = j->m_DAAShadowRegs.CAO_REGS.CAO.CallerID; - pOut += 4; - strncpy(j->cid.month, pOut, 2); - pOut += 2; - strncpy(j->cid.day, pOut, 2); - pOut += 2; - strncpy(j->cid.hour, pOut, 2); - pOut += 2; - strncpy(j->cid.min, pOut, 2); - pOut += 3; - j->cid.numlen = *pOut; - pOut += 1; - strncpy(j->cid.number, pOut, j->cid.numlen); - pOut += j->cid.numlen + 1; - j->cid.namelen = *pOut; - pOut += 1; - strncpy(j->cid.name, pOut, j->cid.namelen); - - ixj_daa_cid_reset(j); - return 1; -} - -static char daa_get_version(IXJ *j) -{ - BYTES bytes; - - if (!SCI_Prepare(j)) - return 0; - - bytes.high = 0x35; - bytes.low = 0x00; - outb_p(bytes.high, j->XILINXbase + 0x03); - outb_p(bytes.low, j->XILINXbase + 0x02); - - if (!SCI_Control(j, SCI_Enable_DAA)) - return 0; - - bytes.high = inb_p(j->XILINXbase + 0x03); - bytes.low = inb_p(j->XILINXbase + 0x02); - if (bytes.low != ALISDAA_ID_BYTE) { - if (ixjdebug & 0x0001) - printk("DAA Get Version Cannot read DAA ID Byte high = %d low = %d\n", bytes.high, bytes.low); - return 0; - } - if (!SCI_Control(j, SCI_Enable_DAA)) - return 0; - - if (!SCI_Control(j, SCI_End)) - return 0; - - bytes.high = inb_p(j->XILINXbase + 0x03); - bytes.low = inb_p(j->XILINXbase + 0x02); - if (ixjdebug & 0x0002) - printk("DAA CR5 Byte high = 0x%x low = 0x%x\n", bytes.high, bytes.low); - j->m_DAAShadowRegs.SOP_REGS.SOP.cr5.reg = bytes.high; - return bytes.high; -} - -static int daa_set_mode(IXJ *j, int mode) -{ - /* NOTE: - The DAA *MUST* be in the conversation mode if the - PSTN line is to be seized (PSTN line off-hook). - Taking the PSTN line off-hook while the DAA is in - a mode other than conversation mode will cause a - hardware failure of the ALIS-A part. - - NOTE: - The DAA can only go to SLEEP, RINGING or PULSEDIALING modes - if the PSTN line is on-hook. Failure to have the PSTN line - in the on-hook state WILL CAUSE A HARDWARE FAILURE OF THE - ALIS-A part. - */ - - BYTES bytes; - - j->flags.pstn_rmr = 0; - - if (!SCI_Prepare(j)) - return 0; - - switch (mode) { - case SOP_PU_RESET: - j->pld_scrw.bits.daafsyncen = 0; /* Turn off DAA Frame Sync */ - - outb_p(j->pld_scrw.byte, j->XILINXbase); - j->pld_slicw.bits.rly2 = 0; - outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); - bytes.high = 0x10; - bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg; - daa_load(&bytes, j); - if (!SCI_Prepare(j)) - return 0; - - j->daa_mode = SOP_PU_SLEEP; - break; - case SOP_PU_SLEEP: - if(j->daa_mode == SOP_PU_SLEEP) - { - break; - } - if (ixjdebug & 0x0008) - printk(KERN_INFO "phone DAA: SOP_PU_SLEEP at %ld\n", jiffies); -/* if(j->daa_mode == SOP_PU_CONVERSATION) */ - { - j->pld_scrw.bits.daafsyncen = 0; /* Turn off DAA Frame Sync */ - - outb_p(j->pld_scrw.byte, j->XILINXbase); - j->pld_slicw.bits.rly2 = 0; - outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); - bytes.high = 0x10; - bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg; - daa_load(&bytes, j); - if (!SCI_Prepare(j)) - return 0; - } - j->pld_scrw.bits.daafsyncen = 0; /* Turn off DAA Frame Sync */ - - outb_p(j->pld_scrw.byte, j->XILINXbase); - j->pld_slicw.bits.rly2 = 0; - outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); - bytes.high = 0x10; - bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg; - daa_load(&bytes, j); - if (!SCI_Prepare(j)) - return 0; - - j->daa_mode = SOP_PU_SLEEP; - j->flags.pstn_ringing = 0; - j->ex.bits.pstn_ring = 0; - j->pstn_sleeptil = jiffies + (hertz / 4); - wake_up_interruptible(&j->read_q); /* Wake any blocked readers */ - wake_up_interruptible(&j->write_q); /* Wake any blocked writers */ - wake_up_interruptible(&j->poll_q); /* Wake any blocked selects */ - break; - case SOP_PU_RINGING: - if (ixjdebug & 0x0008) - printk(KERN_INFO "phone DAA: SOP_PU_RINGING at %ld\n", jiffies); - j->pld_scrw.bits.daafsyncen = 0; /* Turn off DAA Frame Sync */ - - outb_p(j->pld_scrw.byte, j->XILINXbase); - j->pld_slicw.bits.rly2 = 0; - outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); - bytes.high = 0x50; - bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg; - daa_load(&bytes, j); - if (!SCI_Prepare(j)) - return 0; - j->daa_mode = SOP_PU_RINGING; - break; - case SOP_PU_CONVERSATION: - if (ixjdebug & 0x0008) - printk(KERN_INFO "phone DAA: SOP_PU_CONVERSATION at %ld\n", jiffies); - bytes.high = 0x90; - bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg; - daa_load(&bytes, j); - if (!SCI_Prepare(j)) - return 0; - j->pld_slicw.bits.rly2 = 1; - outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); - j->pld_scrw.bits.daafsyncen = 1; /* Turn on DAA Frame Sync */ - - outb_p(j->pld_scrw.byte, j->XILINXbase); - j->daa_mode = SOP_PU_CONVERSATION; - j->flags.pstn_ringing = 0; - j->ex.bits.pstn_ring = 0; - j->pstn_sleeptil = jiffies; - j->pstn_ring_start = j->pstn_ring_stop = j->pstn_ring_int = 0; - break; - case SOP_PU_PULSEDIALING: - if (ixjdebug & 0x0008) - printk(KERN_INFO "phone DAA: SOP_PU_PULSEDIALING at %ld\n", jiffies); - j->pld_scrw.bits.daafsyncen = 0; /* Turn off DAA Frame Sync */ - - outb_p(j->pld_scrw.byte, j->XILINXbase); - j->pld_slicw.bits.rly2 = 0; - outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); - bytes.high = 0xD0; - bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg; - daa_load(&bytes, j); - if (!SCI_Prepare(j)) - return 0; - j->daa_mode = SOP_PU_PULSEDIALING; - break; - default: - break; - } - return 1; -} - -static int ixj_daa_write(IXJ *j) -{ - BYTES bytes; - - j->flags.pstncheck = 1; - - daa_set_mode(j, SOP_PU_SLEEP); - - if (!SCI_Prepare(j)) - return 0; - - outb_p(j->pld_scrw.byte, j->XILINXbase); - - bytes.high = 0x14; - bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg; - bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr2.reg; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.reg; - bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg; - if (!daa_load(&bytes, j)) - return 0; - - if (!SCI_Prepare(j)) - return 0; - - bytes.high = 0x1F; - bytes.low = j->m_DAAShadowRegs.XOP_REGS.XOP.xr7.reg; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.XOP_xr6_W.reg; - bytes.low = j->m_DAAShadowRegs.XOP_REGS.XOP.xr5.reg; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.XOP_REGS.XOP.xr4.reg; - bytes.low = j->m_DAAShadowRegs.XOP_REGS.XOP.xr3.reg; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.XOP_REGS.XOP.xr2.reg; - bytes.low = j->m_DAAShadowRegs.XOP_REGS.XOP.xr1.reg; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.XOP_xr0_W.reg; - bytes.low = 0x00; - if (!daa_load(&bytes, j)) - return 0; - - if (!SCI_Prepare(j)) - return 0; - - bytes.high = 0x00; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[7]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[6]; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[5]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[4]; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[3]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[2]; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[1]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[0]; - bytes.low = 0x00; - if (!daa_load(&bytes, j)) - return 0; - - if (!SCI_Control(j, SCI_End)) - return 0; - if (!SCI_WaitLowSCI(j)) - return 0; - - bytes.high = 0x01; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[7]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[6]; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[5]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[4]; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[3]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[2]; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[1]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[0]; - bytes.low = 0x00; - if (!daa_load(&bytes, j)) - return 0; - - if (!SCI_Control(j, SCI_End)) - return 0; - if (!SCI_WaitLowSCI(j)) - return 0; - - bytes.high = 0x02; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[7]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[6]; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[5]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[4]; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[3]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[2]; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[1]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[0]; - bytes.low = 0x00; - if (!daa_load(&bytes, j)) - return 0; - - if (!SCI_Control(j, SCI_End)) - return 0; - if (!SCI_WaitLowSCI(j)) - return 0; - - bytes.high = 0x03; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[7]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[6]; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[5]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[4]; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[3]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[2]; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[1]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[0]; - bytes.low = 0x00; - if (!daa_load(&bytes, j)) - return 0; - - if (!SCI_Control(j, SCI_End)) - return 0; - if (!SCI_WaitLowSCI(j)) - return 0; - - bytes.high = 0x04; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[6]; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[5]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[4]; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[3]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[2]; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[1]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[0]; - bytes.low = 0x00; - if (!daa_load(&bytes, j)) - return 0; - - if (!SCI_Control(j, SCI_End)) - return 0; - if (!SCI_WaitLowSCI(j)) - return 0; - - bytes.high = 0x05; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[7]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[6]; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[5]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[4]; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[3]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[2]; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[1]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[0]; - bytes.low = 0x00; - if (!daa_load(&bytes, j)) - return 0; - - if (!SCI_Control(j, SCI_End)) - return 0; - if (!SCI_WaitLowSCI(j)) - return 0; - - bytes.high = 0x06; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[7]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[6]; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[5]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[4]; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[3]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[2]; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[1]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[0]; - bytes.low = 0x00; - if (!daa_load(&bytes, j)) - return 0; - - if (!SCI_Control(j, SCI_End)) - return 0; - if (!SCI_WaitLowSCI(j)) - return 0; - - bytes.high = 0x07; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[7]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[6]; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[5]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[4]; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[3]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[2]; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[1]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[0]; - bytes.low = 0x00; - if (!daa_load(&bytes, j)) - return 0; - - if (!SCI_Control(j, SCI_End)) - return 0; - if (!SCI_WaitLowSCI(j)) - return 0; - - bytes.high = 0x08; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[7]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[6]; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[5]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[4]; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[3]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[2]; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[1]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[0]; - bytes.low = 0x00; - if (!daa_load(&bytes, j)) - return 0; - - if (!SCI_Control(j, SCI_End)) - return 0; - if (!SCI_WaitLowSCI(j)) - return 0; - - bytes.high = 0x09; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[3]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[2]; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[1]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[0]; - bytes.low = 0x00; - if (!daa_load(&bytes, j)) - return 0; - - if (!SCI_Control(j, SCI_End)) - return 0; - if (!SCI_WaitLowSCI(j)) - return 0; - - bytes.high = 0x0A; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[3]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[2]; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[1]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[0]; - bytes.low = 0x00; - if (!daa_load(&bytes, j)) - return 0; - - if (!SCI_Control(j, SCI_End)) - return 0; - if (!SCI_WaitLowSCI(j)) - return 0; - - bytes.high = 0x0B; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[3]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[2]; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[1]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[0]; - bytes.low = 0x00; - if (!daa_load(&bytes, j)) - return 0; - - if (!SCI_Control(j, SCI_End)) - return 0; - if (!SCI_WaitLowSCI(j)) - return 0; - - bytes.high = 0x0C; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[3]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[2]; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[1]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[0]; - bytes.low = 0x00; - if (!daa_load(&bytes, j)) - return 0; - - if (!SCI_Control(j, SCI_End)) - return 0; - if (!SCI_WaitLowSCI(j)) - return 0; - - bytes.high = 0x0D; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[3]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[2]; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[1]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[0]; - bytes.low = 0x00; - if (!daa_load(&bytes, j)) - return 0; - - if (!SCI_Control(j, SCI_End)) - return 0; - if (!SCI_WaitLowSCI(j)) - return 0; - - bytes.high = 0x0E; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[7]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[6]; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[5]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[4]; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[3]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[2]; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[1]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[0]; - bytes.low = 0x00; - if (!daa_load(&bytes, j)) - return 0; - - if (!SCI_Control(j, SCI_End)) - return 0; - if (!SCI_WaitLowSCI(j)) - return 0; - - bytes.high = 0x0F; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[7]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[6]; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[5]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[4]; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[3]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[2]; - bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[1]; - if (!daa_load(&bytes, j)) - return 0; - - bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[0]; - bytes.low = 0x00; - if (!daa_load(&bytes, j)) - return 0; - - udelay(32); - j->pld_scrr.byte = inb_p(j->XILINXbase); - if (!SCI_Control(j, SCI_End)) - return 0; - - outb_p(j->pld_scrw.byte, j->XILINXbase); - - if (ixjdebug & 0x0002) - printk("DAA Coefficients Loaded\n"); - - j->flags.pstncheck = 0; - return 1; -} - -static int ixj_set_tone_off(unsigned short arg, IXJ *j) -{ - j->tone_off_time = arg; - if (ixj_WriteDSPCommand(0x6E05, j)) /* Set Tone Off Period */ - - return -1; - if (ixj_WriteDSPCommand(arg, j)) - return -1; - return 0; -} - -static int ixj_get_tone_on(IXJ *j) -{ - if (ixj_WriteDSPCommand(0x6E06, j)) /* Get Tone On Period */ - - return -1; - return 0; -} - -static int ixj_get_tone_off(IXJ *j) -{ - if (ixj_WriteDSPCommand(0x6E07, j)) /* Get Tone Off Period */ - - return -1; - return 0; -} - -static void ixj_busytone(IXJ *j) -{ - j->flags.ringback = 0; - j->flags.dialtone = 0; - j->flags.busytone = 1; - ixj_set_tone_on(0x07D0, j); - ixj_set_tone_off(0x07D0, j); - ixj_play_tone(j, 27); -} - -static void ixj_dialtone(IXJ *j) -{ - j->flags.ringback = 0; - j->flags.dialtone = 1; - j->flags.busytone = 0; - if (j->dsp.low == 0x20) { - return; - } else { - ixj_set_tone_on(0xFFFF, j); - ixj_set_tone_off(0x0000, j); - ixj_play_tone(j, 25); - } -} - -static void ixj_cpt_stop(IXJ *j) -{ - if(j->tone_state || j->tone_cadence_state) - { - j->flags.dialtone = 0; - j->flags.busytone = 0; - j->flags.ringback = 0; - ixj_set_tone_on(0x0001, j); - ixj_set_tone_off(0x0000, j); - ixj_play_tone(j, 0); - j->tone_state = j->tone_cadence_state = 0; - if (j->cadence_t) { - kfree(j->cadence_t->ce); - kfree(j->cadence_t); - j->cadence_t = NULL; - } - } - if (j->play_mode == -1 && j->rec_mode == -1) - idle(j); - if (j->play_mode != -1 && j->dsp.low == 0x20) - ixj_play_start(j); - if (j->rec_mode != -1 && j->dsp.low == 0x20) - ixj_record_start(j); -} - -static void ixj_ringback(IXJ *j) -{ - j->flags.busytone = 0; - j->flags.dialtone = 0; - j->flags.ringback = 1; - ixj_set_tone_on(0x0FA0, j); - ixj_set_tone_off(0x2EE0, j); - ixj_play_tone(j, 26); -} - -static void ixj_testram(IXJ *j) -{ - ixj_WriteDSPCommand(0x3001, j); /* Test External SRAM */ -} - -static int ixj_build_cadence(IXJ *j, IXJ_CADENCE __user * cp) -{ - ixj_cadence *lcp; - IXJ_CADENCE_ELEMENT __user *cep; - IXJ_CADENCE_ELEMENT *lcep; - IXJ_TONE ti; - int err; - - lcp = kmalloc(sizeof(ixj_cadence), GFP_KERNEL); - if (lcp == NULL) - return -ENOMEM; - - err = -EFAULT; - if (copy_from_user(&lcp->elements_used, - &cp->elements_used, sizeof(int))) - goto out; - if (copy_from_user(&lcp->termination, - &cp->termination, sizeof(IXJ_CADENCE_TERM))) - goto out; - if (get_user(cep, &cp->ce)) - goto out; - - err = -EINVAL; - if ((unsigned)lcp->elements_used >= ~0U/sizeof(IXJ_CADENCE_ELEMENT)) - goto out; - - err = -ENOMEM; - lcep = kmalloc(sizeof(IXJ_CADENCE_ELEMENT) * lcp->elements_used, GFP_KERNEL); - if (!lcep) - goto out; - - err = -EFAULT; - if (copy_from_user(lcep, cep, sizeof(IXJ_CADENCE_ELEMENT) * lcp->elements_used)) - goto out1; - - if (j->cadence_t) { - kfree(j->cadence_t->ce); - kfree(j->cadence_t); - } - lcp->ce = (void *) lcep; - j->cadence_t = lcp; - j->tone_cadence_state = 0; - ixj_set_tone_on(lcp->ce[0].tone_on_time, j); - ixj_set_tone_off(lcp->ce[0].tone_off_time, j); - if (j->cadence_t->ce[j->tone_cadence_state].freq0) { - ti.tone_index = j->cadence_t->ce[j->tone_cadence_state].index; - ti.freq0 = j->cadence_t->ce[j->tone_cadence_state].freq0; - ti.gain0 = j->cadence_t->ce[j->tone_cadence_state].gain0; - ti.freq1 = j->cadence_t->ce[j->tone_cadence_state].freq1; - ti.gain1 = j->cadence_t->ce[j->tone_cadence_state].gain1; - ixj_init_tone(j, &ti); - } - ixj_play_tone(j, lcp->ce[0].index); - return 1; -out1: - kfree(lcep); -out: - kfree(lcp); - return err; -} - -static int ixj_build_filter_cadence(IXJ *j, IXJ_FILTER_CADENCE __user * cp) -{ - IXJ_FILTER_CADENCE *lcp; - lcp = memdup_user(cp, sizeof(IXJ_FILTER_CADENCE)); - if (IS_ERR(lcp)) { - if(ixjdebug & 0x0001) { - printk(KERN_INFO "Could not allocate memory for cadence or could not copy cadence to kernel\n"); - } - return PTR_ERR(lcp); - } - if (lcp->filter > 5) { - if(ixjdebug & 0x0001) { - printk(KERN_INFO "Cadence out of range\n"); - } - kfree(lcp); - return -1; - } - j->cadence_f[lcp->filter].state = 0; - j->cadence_f[lcp->filter].enable = lcp->enable; - j->filter_en[lcp->filter] = j->cadence_f[lcp->filter].en_filter = lcp->en_filter; - j->cadence_f[lcp->filter].on1 = lcp->on1; - j->cadence_f[lcp->filter].on1min = 0; - j->cadence_f[lcp->filter].on1max = 0; - j->cadence_f[lcp->filter].off1 = lcp->off1; - j->cadence_f[lcp->filter].off1min = 0; - j->cadence_f[lcp->filter].off1max = 0; - j->cadence_f[lcp->filter].on2 = lcp->on2; - j->cadence_f[lcp->filter].on2min = 0; - j->cadence_f[lcp->filter].on2max = 0; - j->cadence_f[lcp->filter].off2 = lcp->off2; - j->cadence_f[lcp->filter].off2min = 0; - j->cadence_f[lcp->filter].off2max = 0; - j->cadence_f[lcp->filter].on3 = lcp->on3; - j->cadence_f[lcp->filter].on3min = 0; - j->cadence_f[lcp->filter].on3max = 0; - j->cadence_f[lcp->filter].off3 = lcp->off3; - j->cadence_f[lcp->filter].off3min = 0; - j->cadence_f[lcp->filter].off3max = 0; - if(ixjdebug & 0x0002) { - printk(KERN_INFO "Cadence %d loaded\n", lcp->filter); - } - kfree(lcp); - return 0; -} - -static void add_caps(IXJ *j) -{ - j->caps = 0; - j->caplist[j->caps].cap = PHONE_VENDOR_QUICKNET; - strcpy(j->caplist[j->caps].desc, "Quicknet Technologies, Inc. (www.quicknet.net)"); - j->caplist[j->caps].captype = vendor; - j->caplist[j->caps].handle = j->caps++; - j->caplist[j->caps].captype = device; - switch (j->cardtype) { - case QTI_PHONEJACK: - strcpy(j->caplist[j->caps].desc, "Quicknet Internet PhoneJACK"); - break; - case QTI_LINEJACK: - strcpy(j->caplist[j->caps].desc, "Quicknet Internet LineJACK"); - break; - case QTI_PHONEJACK_LITE: - strcpy(j->caplist[j->caps].desc, "Quicknet Internet PhoneJACK Lite"); - break; - case QTI_PHONEJACK_PCI: - strcpy(j->caplist[j->caps].desc, "Quicknet Internet PhoneJACK PCI"); - break; - case QTI_PHONECARD: - strcpy(j->caplist[j->caps].desc, "Quicknet Internet PhoneCARD"); - break; - } - j->caplist[j->caps].cap = j->cardtype; - j->caplist[j->caps].handle = j->caps++; - strcpy(j->caplist[j->caps].desc, "POTS"); - j->caplist[j->caps].captype = port; - j->caplist[j->caps].cap = pots; - j->caplist[j->caps].handle = j->caps++; - - /* add devices that can do speaker/mic */ - switch (j->cardtype) { - case QTI_PHONEJACK: - case QTI_LINEJACK: - case QTI_PHONEJACK_PCI: - case QTI_PHONECARD: - strcpy(j->caplist[j->caps].desc, "SPEAKER"); - j->caplist[j->caps].captype = port; - j->caplist[j->caps].cap = speaker; - j->caplist[j->caps].handle = j->caps++; - default: - break; - } - - /* add devices that can do handset */ - switch (j->cardtype) { - case QTI_PHONEJACK: - strcpy(j->caplist[j->caps].desc, "HANDSET"); - j->caplist[j->caps].captype = port; - j->caplist[j->caps].cap = handset; - j->caplist[j->caps].handle = j->caps++; - break; - default: - break; - } - - /* add devices that can do PSTN */ - switch (j->cardtype) { - case QTI_LINEJACK: - strcpy(j->caplist[j->caps].desc, "PSTN"); - j->caplist[j->caps].captype = port; - j->caplist[j->caps].cap = pstn; - j->caplist[j->caps].handle = j->caps++; - break; - default: - break; - } - - /* add codecs - all cards can do uLaw, linear 8/16, and Windows sound system */ - strcpy(j->caplist[j->caps].desc, "ULAW"); - j->caplist[j->caps].captype = codec; - j->caplist[j->caps].cap = ULAW; - j->caplist[j->caps].handle = j->caps++; - - strcpy(j->caplist[j->caps].desc, "LINEAR 16 bit"); - j->caplist[j->caps].captype = codec; - j->caplist[j->caps].cap = LINEAR16; - j->caplist[j->caps].handle = j->caps++; - - strcpy(j->caplist[j->caps].desc, "LINEAR 8 bit"); - j->caplist[j->caps].captype = codec; - j->caplist[j->caps].cap = LINEAR8; - j->caplist[j->caps].handle = j->caps++; - - strcpy(j->caplist[j->caps].desc, "Windows Sound System"); - j->caplist[j->caps].captype = codec; - j->caplist[j->caps].cap = WSS; - j->caplist[j->caps].handle = j->caps++; - - /* software ALAW codec, made from ULAW */ - strcpy(j->caplist[j->caps].desc, "ALAW"); - j->caplist[j->caps].captype = codec; - j->caplist[j->caps].cap = ALAW; - j->caplist[j->caps].handle = j->caps++; - - /* version 12 of the 8020 does the following codecs in a broken way */ - if (j->dsp.low != 0x20 || j->ver.low != 0x12) { - strcpy(j->caplist[j->caps].desc, "G.723.1 6.3kbps"); - j->caplist[j->caps].captype = codec; - j->caplist[j->caps].cap = G723_63; - j->caplist[j->caps].handle = j->caps++; - - strcpy(j->caplist[j->caps].desc, "G.723.1 5.3kbps"); - j->caplist[j->caps].captype = codec; - j->caplist[j->caps].cap = G723_53; - j->caplist[j->caps].handle = j->caps++; - - strcpy(j->caplist[j->caps].desc, "TrueSpeech 4.8kbps"); - j->caplist[j->caps].captype = codec; - j->caplist[j->caps].cap = TS48; - j->caplist[j->caps].handle = j->caps++; - - strcpy(j->caplist[j->caps].desc, "TrueSpeech 4.1kbps"); - j->caplist[j->caps].captype = codec; - j->caplist[j->caps].cap = TS41; - j->caplist[j->caps].handle = j->caps++; - } - - /* 8020 chips can do TS8.5 native, and 8021/8022 can load it */ - if (j->dsp.low == 0x20 || j->flags.ts85_loaded) { - strcpy(j->caplist[j->caps].desc, "TrueSpeech 8.5kbps"); - j->caplist[j->caps].captype = codec; - j->caplist[j->caps].cap = TS85; - j->caplist[j->caps].handle = j->caps++; - } - - /* 8021 chips can do G728 */ - if (j->dsp.low == 0x21) { - strcpy(j->caplist[j->caps].desc, "G.728 16kbps"); - j->caplist[j->caps].captype = codec; - j->caplist[j->caps].cap = G728; - j->caplist[j->caps].handle = j->caps++; - } - - /* 8021/8022 chips can do G729 if loaded */ - if (j->dsp.low != 0x20 && j->flags.g729_loaded) { - strcpy(j->caplist[j->caps].desc, "G.729A 8kbps"); - j->caplist[j->caps].captype = codec; - j->caplist[j->caps].cap = G729; - j->caplist[j->caps].handle = j->caps++; - } - if (j->dsp.low != 0x20 && j->flags.g729_loaded) { - strcpy(j->caplist[j->caps].desc, "G.729B 8kbps"); - j->caplist[j->caps].captype = codec; - j->caplist[j->caps].cap = G729B; - j->caplist[j->caps].handle = j->caps++; - } -} - -static int capabilities_check(IXJ *j, struct phone_capability *pcreq) -{ - int cnt; - int retval = 0; - for (cnt = 0; cnt < j->caps; cnt++) { - if (pcreq->captype == j->caplist[cnt].captype - && pcreq->cap == j->caplist[cnt].cap) { - retval = 1; - break; - } - } - return retval; -} - -static long do_ixj_ioctl(struct file *file_p, unsigned int cmd, unsigned long arg) -{ - IXJ_TONE ti; - IXJ_FILTER jf; - IXJ_FILTER_RAW jfr; - void __user *argp = (void __user *)arg; - struct inode *inode = file_p->f_path.dentry->d_inode; - unsigned int minor = iminor(inode); - unsigned int raise, mant; - int board = NUM(inode); - - IXJ *j = get_ixj(NUM(inode)); - - int retval = 0; - - /* - * Set up locks to ensure that only one process is talking to the DSP at a time. - * This is necessary to keep the DSP from locking up. - */ - while(test_and_set_bit(board, (void *)&j->busyflags) != 0) - schedule_timeout_interruptible(1); - if (ixjdebug & 0x0040) - printk("phone%d ioctl, cmd: 0x%x, arg: 0x%lx\n", minor, cmd, arg); - if (minor >= IXJMAX) { - clear_bit(board, &j->busyflags); - return -ENODEV; - } - /* - * Check ioctls only root can use. - */ - if (!capable(CAP_SYS_ADMIN)) { - switch (cmd) { - case IXJCTL_TESTRAM: - case IXJCTL_HZ: - retval = -EPERM; - } - } - switch (cmd) { - case IXJCTL_TESTRAM: - ixj_testram(j); - retval = (j->ssr.high << 8) + j->ssr.low; - break; - case IXJCTL_CARDTYPE: - retval = j->cardtype; - break; - case IXJCTL_SERIAL: - retval = j->serial; - break; - case IXJCTL_VERSION: - { - char arg_str[100]; - snprintf(arg_str, sizeof(arg_str), - "\nDriver version %i.%i.%i", IXJ_VER_MAJOR, - IXJ_VER_MINOR, IXJ_BLD_VER); - if (copy_to_user(argp, arg_str, strlen(arg_str))) - retval = -EFAULT; - } - break; - case PHONE_RING_CADENCE: - j->ring_cadence = arg; - break; - case IXJCTL_CIDCW: - if(arg) { - if (copy_from_user(&j->cid_send, argp, sizeof(PHONE_CID))) { - retval = -EFAULT; - break; - } - } else { - memset(&j->cid_send, 0, sizeof(PHONE_CID)); - } - ixj_write_cidcw(j); - break; - /* Binary compatbility */ - case OLD_PHONE_RING_START: - arg = 0; - /* Fall through */ - case PHONE_RING_START: - if(arg) { - if (copy_from_user(&j->cid_send, argp, sizeof(PHONE_CID))) { - retval = -EFAULT; - break; - } - ixj_write_cid(j); - } else { - memset(&j->cid_send, 0, sizeof(PHONE_CID)); - } - ixj_ring_start(j); - break; - case PHONE_RING_STOP: - j->flags.cringing = 0; - if(j->cadence_f[5].enable) { - j->cadence_f[5].state = 0; - } - ixj_ring_off(j); - break; - case PHONE_RING: - retval = ixj_ring(j); - break; - case PHONE_EXCEPTION: - retval = j->ex.bytes; - if(j->ex.bits.flash) { - j->flash_end = 0; - j->ex.bits.flash = 0; - } - j->ex.bits.pstn_ring = 0; - j->ex.bits.caller_id = 0; - j->ex.bits.pstn_wink = 0; - j->ex.bits.f0 = 0; - j->ex.bits.f1 = 0; - j->ex.bits.f2 = 0; - j->ex.bits.f3 = 0; - j->ex.bits.fc0 = 0; - j->ex.bits.fc1 = 0; - j->ex.bits.fc2 = 0; - j->ex.bits.fc3 = 0; - j->ex.bits.reserved = 0; - break; - case PHONE_HOOKSTATE: - j->ex.bits.hookstate = 0; - retval = j->hookstate; //j->r_hook; - break; - case IXJCTL_SET_LED: - LED_SetState(arg, j); - break; - case PHONE_FRAME: - retval = set_base_frame(j, arg); - break; - case PHONE_REC_CODEC: - retval = set_rec_codec(j, arg); - break; - case PHONE_VAD: - ixj_vad(j, arg); - break; - case PHONE_REC_START: - ixj_record_start(j); - break; - case PHONE_REC_STOP: - ixj_record_stop(j); - break; - case PHONE_REC_DEPTH: - set_rec_depth(j, arg); - break; - case PHONE_REC_VOLUME: - if(arg == -1) { - retval = get_rec_volume(j); - } - else { - set_rec_volume(j, arg); - retval = arg; - } - break; - case PHONE_REC_VOLUME_LINEAR: - if(arg == -1) { - retval = get_rec_volume_linear(j); - } - else { - set_rec_volume_linear(j, arg); - retval = arg; - } - break; - case IXJCTL_DTMF_PRESCALE: - if(arg == -1) { - retval = get_dtmf_prescale(j); - } - else { - set_dtmf_prescale(j, arg); - retval = arg; - } - break; - case PHONE_REC_LEVEL: - retval = get_rec_level(j); - break; - case IXJCTL_SC_RXG: - retval = ixj_siadc(j, arg); - break; - case IXJCTL_SC_TXG: - retval = ixj_sidac(j, arg); - break; - case IXJCTL_AEC_START: - ixj_aec_start(j, arg); - break; - case IXJCTL_AEC_STOP: - aec_stop(j); - break; - case IXJCTL_AEC_GET_LEVEL: - retval = j->aec_level; - break; - case PHONE_PLAY_CODEC: - retval = set_play_codec(j, arg); - break; - case PHONE_PLAY_START: - retval = ixj_play_start(j); - break; - case PHONE_PLAY_STOP: - ixj_play_stop(j); - break; - case PHONE_PLAY_DEPTH: - set_play_depth(j, arg); - break; - case PHONE_PLAY_VOLUME: - if(arg == -1) { - retval = get_play_volume(j); - } - else { - set_play_volume(j, arg); - retval = arg; - } - break; - case PHONE_PLAY_VOLUME_LINEAR: - if(arg == -1) { - retval = get_play_volume_linear(j); - } - else { - set_play_volume_linear(j, arg); - retval = arg; - } - break; - case PHONE_PLAY_LEVEL: - retval = get_play_level(j); - break; - case IXJCTL_DSP_TYPE: - retval = (j->dsp.high << 8) + j->dsp.low; - break; - case IXJCTL_DSP_VERSION: - retval = (j->ver.high << 8) + j->ver.low; - break; - case IXJCTL_HZ: - hertz = arg; - break; - case IXJCTL_RATE: - if (arg > hertz) - retval = -1; - else - samplerate = arg; - break; - case IXJCTL_DRYBUFFER_READ: - put_user(j->drybuffer, (unsigned long __user *) argp); - break; - case IXJCTL_DRYBUFFER_CLEAR: - j->drybuffer = 0; - break; - case IXJCTL_FRAMES_READ: - put_user(j->framesread, (unsigned long __user *) argp); - break; - case IXJCTL_FRAMES_WRITTEN: - put_user(j->frameswritten, (unsigned long __user *) argp); - break; - case IXJCTL_READ_WAIT: - put_user(j->read_wait, (unsigned long __user *) argp); - break; - case IXJCTL_WRITE_WAIT: - put_user(j->write_wait, (unsigned long __user *) argp); - break; - case PHONE_MAXRINGS: - j->maxrings = arg; - break; - case PHONE_SET_TONE_ON_TIME: - ixj_set_tone_on(arg, j); - break; - case PHONE_SET_TONE_OFF_TIME: - ixj_set_tone_off(arg, j); - break; - case PHONE_GET_TONE_ON_TIME: - if (ixj_get_tone_on(j)) { - retval = -1; - } else { - retval = (j->ssr.high << 8) + j->ssr.low; - } - break; - case PHONE_GET_TONE_OFF_TIME: - if (ixj_get_tone_off(j)) { - retval = -1; - } else { - retval = (j->ssr.high << 8) + j->ssr.low; - } - break; - case PHONE_PLAY_TONE: - if (!j->tone_state) - retval = ixj_play_tone(j, arg); - else - retval = -1; - break; - case PHONE_GET_TONE_STATE: - retval = j->tone_state; - break; - case PHONE_DTMF_READY: - retval = j->ex.bits.dtmf_ready; - break; - case PHONE_GET_DTMF: - if (ixj_hookstate(j)) { - if (j->dtmf_rp != j->dtmf_wp) { - retval = j->dtmfbuffer[j->dtmf_rp]; - j->dtmf_rp++; - if (j->dtmf_rp == 79) - j->dtmf_rp = 0; - if (j->dtmf_rp == j->dtmf_wp) { - j->ex.bits.dtmf_ready = j->dtmf_rp = j->dtmf_wp = 0; - } - } - } - break; - case PHONE_GET_DTMF_ASCII: - if (ixj_hookstate(j)) { - if (j->dtmf_rp != j->dtmf_wp) { - switch (j->dtmfbuffer[j->dtmf_rp]) { - case 10: - retval = 42; /* '*'; */ - - break; - case 11: - retval = 48; /*'0'; */ - - break; - case 12: - retval = 35; /*'#'; */ - - break; - case 28: - retval = 65; /*'A'; */ - - break; - case 29: - retval = 66; /*'B'; */ - - break; - case 30: - retval = 67; /*'C'; */ - - break; - case 31: - retval = 68; /*'D'; */ - - break; - default: - retval = 48 + j->dtmfbuffer[j->dtmf_rp]; - break; - } - j->dtmf_rp++; - if (j->dtmf_rp == 79) - j->dtmf_rp = 0; - if(j->dtmf_rp == j->dtmf_wp) - { - j->ex.bits.dtmf_ready = j->dtmf_rp = j->dtmf_wp = 0; - } - } - } - break; - case PHONE_DTMF_OOB: - j->flags.dtmf_oob = arg; - break; - case PHONE_DIALTONE: - ixj_dialtone(j); - break; - case PHONE_BUSY: - ixj_busytone(j); - break; - case PHONE_RINGBACK: - ixj_ringback(j); - break; - case PHONE_WINK: - if(j->cardtype == QTI_PHONEJACK) - retval = -1; - else - retval = ixj_wink(j); - break; - case PHONE_CPT_STOP: - ixj_cpt_stop(j); - break; - case PHONE_QUERY_CODEC: - { - struct phone_codec_data pd; - int val; - int proto_size[] = { - -1, - 12, 10, 16, 9, 8, 48, 5, - 40, 40, 80, 40, 40, 6 - }; - if(copy_from_user(&pd, argp, sizeof(pd))) { - retval = -EFAULT; - break; - } - if(pd.type<1 || pd.type>13) { - retval = -EPROTONOSUPPORT; - break; - } - if(pd.typebaseframe.low) - { - case 0xA0:val=2*proto_size[pd.type];break; - case 0x50:val=proto_size[pd.type];break; - default:val=proto_size[pd.type]*3;break; - } - pd.buf_min=pd.buf_max=pd.buf_opt=val; - if(copy_to_user(argp, &pd, sizeof(pd))) - retval = -EFAULT; - break; - } - case IXJCTL_DSP_IDLE: - idle(j); - break; - case IXJCTL_MIXER: - if ((arg & 0xff) == 0xff) - retval = ixj_get_mixer(arg, j); - else - ixj_mixer(arg, j); - break; - case IXJCTL_DAA_COEFF_SET: - switch (arg) { - case DAA_US: - DAA_Coeff_US(j); - retval = ixj_daa_write(j); - break; - case DAA_UK: - DAA_Coeff_UK(j); - retval = ixj_daa_write(j); - break; - case DAA_FRANCE: - DAA_Coeff_France(j); - retval = ixj_daa_write(j); - break; - case DAA_GERMANY: - DAA_Coeff_Germany(j); - retval = ixj_daa_write(j); - break; - case DAA_AUSTRALIA: - DAA_Coeff_Australia(j); - retval = ixj_daa_write(j); - break; - case DAA_JAPAN: - DAA_Coeff_Japan(j); - retval = ixj_daa_write(j); - break; - default: - retval = 1; - break; - } - break; - case IXJCTL_DAA_AGAIN: - ixj_daa_cr4(j, arg | 0x02); - break; - case IXJCTL_PSTN_LINETEST: - retval = ixj_linetest(j); - break; - case IXJCTL_VMWI: - ixj_write_vmwi(j, arg); - break; - case IXJCTL_CID: - if (copy_to_user(argp, &j->cid, sizeof(PHONE_CID))) - retval = -EFAULT; - j->ex.bits.caller_id = 0; - break; - case IXJCTL_WINK_DURATION: - j->winktime = arg; - break; - case IXJCTL_PORT: - if (arg) - retval = ixj_set_port(j, arg); - else - retval = j->port; - break; - case IXJCTL_POTS_PSTN: - retval = ixj_set_pots(j, arg); - break; - case PHONE_CAPABILITIES: - add_caps(j); - retval = j->caps; - break; - case PHONE_CAPABILITIES_LIST: - add_caps(j); - if (copy_to_user(argp, j->caplist, sizeof(struct phone_capability) * j->caps)) - retval = -EFAULT; - break; - case PHONE_CAPABILITIES_CHECK: - { - struct phone_capability cap; - if (copy_from_user(&cap, argp, sizeof(cap))) - retval = -EFAULT; - else { - add_caps(j); - retval = capabilities_check(j, &cap); - } - } - break; - case PHONE_PSTN_SET_STATE: - daa_set_mode(j, arg); - break; - case PHONE_PSTN_GET_STATE: - retval = j->daa_mode; - j->ex.bits.pstn_ring = 0; - break; - case IXJCTL_SET_FILTER: - if (copy_from_user(&jf, argp, sizeof(jf))) - retval = -EFAULT; - else - retval = ixj_init_filter(j, &jf); - break; - case IXJCTL_SET_FILTER_RAW: - if (copy_from_user(&jfr, argp, sizeof(jfr))) - retval = -EFAULT; - else - retval = ixj_init_filter_raw(j, &jfr); - break; - case IXJCTL_GET_FILTER_HIST: - if(arg<0||arg>3) - retval = -EINVAL; - else - retval = j->filter_hist[arg]; - break; - case IXJCTL_INIT_TONE: - if (copy_from_user(&ti, argp, sizeof(ti))) - retval = -EFAULT; - else - retval = ixj_init_tone(j, &ti); - break; - case IXJCTL_TONE_CADENCE: - retval = ixj_build_cadence(j, argp); - break; - case IXJCTL_FILTER_CADENCE: - retval = ixj_build_filter_cadence(j, argp); - break; - case IXJCTL_SIGCTL: - if (copy_from_user(&j->sigdef, argp, sizeof(IXJ_SIGDEF))) { - retval = -EFAULT; - break; - } - j->ixj_signals[j->sigdef.event] = j->sigdef.signal; - if(j->sigdef.event < 33) { - raise = 1; - for(mant = 0; mant < j->sigdef.event; mant++){ - raise *= 2; - } - if(j->sigdef.signal) - j->ex_sig.bytes |= raise; - else - j->ex_sig.bytes &= (raise^0xffff); - } - break; - case IXJCTL_INTERCOM_STOP: - if(arg < 0 || arg >= IXJMAX) - return -EINVAL; - j->intercom = -1; - ixj_record_stop(j); - ixj_play_stop(j); - idle(j); - get_ixj(arg)->intercom = -1; - ixj_record_stop(get_ixj(arg)); - ixj_play_stop(get_ixj(arg)); - idle(get_ixj(arg)); - break; - case IXJCTL_INTERCOM_START: - if(arg < 0 || arg >= IXJMAX) - return -EINVAL; - j->intercom = arg; - ixj_record_start(j); - ixj_play_start(j); - get_ixj(arg)->intercom = board; - ixj_play_start(get_ixj(arg)); - ixj_record_start(get_ixj(arg)); - break; - } - if (ixjdebug & 0x0040) - printk("phone%d ioctl end, cmd: 0x%x, arg: 0x%lx\n", minor, cmd, arg); - clear_bit(board, &j->busyflags); - return retval; -} - -static long ixj_ioctl(struct file *file_p, unsigned int cmd, unsigned long arg) -{ - long ret; - mutex_lock(&ixj_mutex); - ret = do_ixj_ioctl(file_p, cmd, arg); - mutex_unlock(&ixj_mutex); - return ret; -} - -static int ixj_fasync(int fd, struct file *file_p, int mode) -{ - IXJ *j = get_ixj(NUM(file_p->f_path.dentry->d_inode)); - - return fasync_helper(fd, file_p, mode, &j->async_queue); -} - -static const struct file_operations ixj_fops = -{ - .owner = THIS_MODULE, - .read = ixj_enhanced_read, - .write = ixj_enhanced_write, - .poll = ixj_poll, - .unlocked_ioctl = ixj_ioctl, - .release = ixj_release, - .fasync = ixj_fasync, - .llseek = default_llseek, -}; - -static int ixj_linetest(IXJ *j) -{ - j->flags.pstncheck = 1; /* Testing */ - j->flags.pstn_present = 0; /* Assume the line is not there */ - - daa_int_read(j); /*Clear DAA Interrupt flags */ - /* */ - /* Hold all relays in the normally de-energized position. */ - /* */ - - j->pld_slicw.bits.rly1 = 0; - j->pld_slicw.bits.rly2 = 0; - j->pld_slicw.bits.rly3 = 0; - outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); - j->pld_scrw.bits.daafsyncen = 0; /* Turn off DAA Frame Sync */ - - outb_p(j->pld_scrw.byte, j->XILINXbase); - j->pld_slicr.byte = inb_p(j->XILINXbase + 0x01); - if (j->pld_slicr.bits.potspstn) { - j->flags.pots_pstn = 1; - j->flags.pots_correct = 0; - LED_SetState(0x4, j); - } else { - j->flags.pots_pstn = 0; - j->pld_slicw.bits.rly1 = 0; - j->pld_slicw.bits.rly2 = 0; - j->pld_slicw.bits.rly3 = 1; - outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); - j->pld_scrw.bits.daafsyncen = 0; /* Turn off DAA Frame Sync */ - - outb_p(j->pld_scrw.byte, j->XILINXbase); - daa_set_mode(j, SOP_PU_CONVERSATION); - msleep(1000); - daa_int_read(j); - daa_set_mode(j, SOP_PU_RESET); - if (j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.VDD_OK) { - j->flags.pots_correct = 0; /* Should not be line voltage on POTS port. */ - LED_SetState(0x4, j); - j->pld_slicw.bits.rly3 = 0; - outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); - } else { - j->flags.pots_correct = 1; - LED_SetState(0x8, j); - j->pld_slicw.bits.rly1 = 1; - j->pld_slicw.bits.rly2 = 0; - j->pld_slicw.bits.rly3 = 0; - outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); - } - } - j->pld_slicw.bits.rly3 = 0; - outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); - daa_set_mode(j, SOP_PU_CONVERSATION); - msleep(1000); - daa_int_read(j); - daa_set_mode(j, SOP_PU_RESET); - if (j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.VDD_OK) { - j->pstn_sleeptil = jiffies + (hertz / 4); - j->flags.pstn_present = 1; - } else { - j->flags.pstn_present = 0; - } - if (j->flags.pstn_present) { - if (j->flags.pots_correct) { - LED_SetState(0xA, j); - } else { - LED_SetState(0x6, j); - } - } else { - if (j->flags.pots_correct) { - LED_SetState(0x9, j); - } else { - LED_SetState(0x5, j); - } - } - j->flags.pstncheck = 0; /* Testing */ - return j->flags.pstn_present; -} - -static int ixj_selfprobe(IXJ *j) -{ - unsigned short cmd; - int cnt; - BYTES bytes; - - init_waitqueue_head(&j->poll_q); - init_waitqueue_head(&j->read_q); - init_waitqueue_head(&j->write_q); - - while(atomic_read(&j->DSPWrite) > 0) - atomic_dec(&j->DSPWrite); - if (ixjdebug & 0x0002) - printk(KERN_INFO "Write IDLE to Software Control Register\n"); - ixj_WriteDSPCommand(0x0FE0, j); /* Put the DSP in full power mode. */ - - if (ixj_WriteDSPCommand(0x0000, j)) /* Write IDLE to Software Control Register */ - return -1; -/* The read values of the SSR should be 0x00 for the IDLE command */ - if (j->ssr.low || j->ssr.high) - return -1; - if (ixjdebug & 0x0002) - printk(KERN_INFO "Get Device ID Code\n"); - if (ixj_WriteDSPCommand(0x3400, j)) /* Get Device ID Code */ - return -1; - j->dsp.low = j->ssr.low; - j->dsp.high = j->ssr.high; - if (ixjdebug & 0x0002) - printk(KERN_INFO "Get Device Version Code\n"); - if (ixj_WriteDSPCommand(0x3800, j)) /* Get Device Version Code */ - return -1; - j->ver.low = j->ssr.low; - j->ver.high = j->ssr.high; - if (!j->cardtype) { - if (j->dsp.low == 0x21) { - bytes.high = bytes.low = inb_p(j->XILINXbase + 0x02); - outb_p(bytes.low ^ 0xFF, j->XILINXbase + 0x02); -/* Test for Internet LineJACK or Internet PhoneJACK Lite */ - bytes.low = inb_p(j->XILINXbase + 0x02); - if (bytes.low == bytes.high) /* Register is read only on */ - /* Internet PhoneJack Lite */ - { - j->cardtype = QTI_PHONEJACK_LITE; - if (!request_region(j->XILINXbase, 4, "ixj control")) { - printk(KERN_INFO "ixj: can't get I/O address 0x%x\n", j->XILINXbase); - return -1; - } - j->pld_slicw.pcib.e1 = 1; - outb_p(j->pld_slicw.byte, j->XILINXbase); - } else { - j->cardtype = QTI_LINEJACK; - - if (!request_region(j->XILINXbase, 8, "ixj control")) { - printk(KERN_INFO "ixj: can't get I/O address 0x%x\n", j->XILINXbase); - return -1; - } - } - } else if (j->dsp.low == 0x22) { - j->cardtype = QTI_PHONEJACK_PCI; - request_region(j->XILINXbase, 4, "ixj control"); - j->pld_slicw.pcib.e1 = 1; - outb_p(j->pld_slicw.byte, j->XILINXbase); - } else - j->cardtype = QTI_PHONEJACK; - } else { - switch (j->cardtype) { - case QTI_PHONEJACK: - if (!j->dsp.low != 0x20) { - j->dsp.high = 0x80; - j->dsp.low = 0x20; - ixj_WriteDSPCommand(0x3800, j); - j->ver.low = j->ssr.low; - j->ver.high = j->ssr.high; - } - break; - case QTI_LINEJACK: - if (!request_region(j->XILINXbase, 8, "ixj control")) { - printk(KERN_INFO "ixj: can't get I/O address 0x%x\n", j->XILINXbase); - return -1; - } - break; - case QTI_PHONEJACK_LITE: - case QTI_PHONEJACK_PCI: - if (!request_region(j->XILINXbase, 4, "ixj control")) { - printk(KERN_INFO "ixj: can't get I/O address 0x%x\n", j->XILINXbase); - return -1; - } - j->pld_slicw.pcib.e1 = 1; - outb_p(j->pld_slicw.byte, j->XILINXbase); - break; - case QTI_PHONECARD: - break; - } - } - if (j->dsp.low == 0x20 || j->cardtype == QTI_PHONEJACK_LITE || j->cardtype == QTI_PHONEJACK_PCI) { - if (ixjdebug & 0x0002) - printk(KERN_INFO "Write CODEC config to Software Control Register\n"); - if (ixj_WriteDSPCommand(0xC462, j)) /* Write CODEC config to Software Control Register */ - return -1; - if (ixjdebug & 0x0002) - printk(KERN_INFO "Write CODEC timing to Software Control Register\n"); - if (j->cardtype == QTI_PHONEJACK) { - cmd = 0x9FF2; - } else { - cmd = 0x9FF5; - } - if (ixj_WriteDSPCommand(cmd, j)) /* Write CODEC timing to Software Control Register */ - return -1; - } else { - if (set_base_frame(j, 30) != 30) - return -1; - if (ixjdebug & 0x0002) - printk(KERN_INFO "Write CODEC config to Software Control Register\n"); - if (j->cardtype == QTI_PHONECARD) { - if (ixj_WriteDSPCommand(0xC528, j)) /* Write CODEC config to Software Control Register */ - return -1; - } - if (j->cardtype == QTI_LINEJACK) { - if (ixj_WriteDSPCommand(0xC528, j)) /* Write CODEC config to Software Control Register */ - return -1; - if (ixjdebug & 0x0002) - printk(KERN_INFO "Turn on the PLD Clock at 8Khz\n"); - j->pld_clock.byte = 0; - outb_p(j->pld_clock.byte, j->XILINXbase + 0x04); - } - } - - if (j->dsp.low == 0x20) { - if (ixjdebug & 0x0002) - printk(KERN_INFO "Configure GPIO pins\n"); - j->gpio.bytes.high = 0x09; -/* bytes.low = 0xEF; 0xF7 */ - j->gpio.bits.gpio1 = 1; - j->gpio.bits.gpio2 = 1; - j->gpio.bits.gpio3 = 0; - j->gpio.bits.gpio4 = 1; - j->gpio.bits.gpio5 = 1; - j->gpio.bits.gpio6 = 1; - j->gpio.bits.gpio7 = 1; - ixj_WriteDSPCommand(j->gpio.word, j); /* Set GPIO pin directions */ - if (ixjdebug & 0x0002) - printk(KERN_INFO "Enable SLIC\n"); - j->gpio.bytes.high = 0x0B; - j->gpio.bytes.low = 0x00; - j->gpio.bits.gpio1 = 0; - j->gpio.bits.gpio2 = 1; - j->gpio.bits.gpio5 = 0; - ixj_WriteDSPCommand(j->gpio.word, j); /* send the ring stop signal */ - j->port = PORT_POTS; - } else { - if (j->cardtype == QTI_LINEJACK) { - LED_SetState(0x1, j); - msleep(100); - LED_SetState(0x2, j); - msleep(100); - LED_SetState(0x4, j); - msleep(100); - LED_SetState(0x8, j); - msleep(100); - LED_SetState(0x0, j); - daa_get_version(j); - if (ixjdebug & 0x0002) - printk("Loading DAA Coefficients\n"); - DAA_Coeff_US(j); - if (!ixj_daa_write(j)) { - printk("DAA write failed on board %d\n", j->board); - return -1; - } - if(!ixj_daa_cid_reset(j)) { - printk("DAA CID reset failed on board %d\n", j->board); - return -1; - } - j->flags.pots_correct = 0; - j->flags.pstn_present = 0; - ixj_linetest(j); - if (j->flags.pots_correct) { - j->pld_scrw.bits.daafsyncen = 0; /* Turn off DAA Frame Sync */ - - outb_p(j->pld_scrw.byte, j->XILINXbase); - j->pld_slicw.bits.rly1 = 1; - j->pld_slicw.bits.spken = 1; - outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); - SLIC_SetState(PLD_SLIC_STATE_STANDBY, j); -/* SLIC_SetState(PLD_SLIC_STATE_ACTIVE, j); */ - j->port = PORT_POTS; - } - ixj_set_port(j, PORT_PSTN); - ixj_set_pots(j, 1); - if (ixjdebug & 0x0002) - printk(KERN_INFO "Enable Mixer\n"); - ixj_mixer(0x0000, j); /*Master Volume Left unmute 0db */ - ixj_mixer(0x0100, j); /*Master Volume Right unmute 0db */ - - ixj_mixer(0x0203, j); /*Voice Left Volume unmute 6db */ - ixj_mixer(0x0303, j); /*Voice Right Volume unmute 6db */ - - ixj_mixer(0x0480, j); /*FM Left mute */ - ixj_mixer(0x0580, j); /*FM Right mute */ - - ixj_mixer(0x0680, j); /*CD Left mute */ - ixj_mixer(0x0780, j); /*CD Right mute */ - - ixj_mixer(0x0880, j); /*Line Left mute */ - ixj_mixer(0x0980, j); /*Line Right mute */ - - ixj_mixer(0x0A80, j); /*Aux left mute */ - ixj_mixer(0x0B80, j); /*Aux right mute */ - - ixj_mixer(0x0C00, j); /*Mono1 unmute 12db */ - ixj_mixer(0x0D80, j); /*Mono2 mute */ - - ixj_mixer(0x0E80, j); /*Mic mute */ - - ixj_mixer(0x0F00, j); /*Mono Out Volume unmute 0db */ - - ixj_mixer(0x1000, j); /*Voice Left and Right out only */ - ixj_mixer(0x110C, j); - - - ixj_mixer(0x1200, j); /*Mono1 switch on mixer left */ - ixj_mixer(0x1401, j); - - ixj_mixer(0x1300, j); /*Mono1 switch on mixer right */ - ixj_mixer(0x1501, j); - - ixj_mixer(0x1700, j); /*Clock select */ - - ixj_mixer(0x1800, j); /*ADC input from mixer */ - - ixj_mixer(0x1901, j); /*Mic gain 30db */ - - if (ixjdebug & 0x0002) - printk(KERN_INFO "Setting Default US Ring Cadence Detection\n"); - j->cadence_f[4].state = 0; - j->cadence_f[4].on1 = 0; /*Cadence Filter 4 is used for PSTN ring cadence */ - j->cadence_f[4].off1 = 0; - j->cadence_f[4].on2 = 0; - j->cadence_f[4].off2 = 0; - j->cadence_f[4].on3 = 0; - j->cadence_f[4].off3 = 0; /* These should represent standard US ring pulse. */ - j->pstn_last_rmr = jiffies; - - } else { - if (j->cardtype == QTI_PHONECARD) { - ixj_WriteDSPCommand(0xCF07, j); - ixj_WriteDSPCommand(0x00B0, j); - ixj_set_port(j, PORT_SPEAKER); - } else { - ixj_set_port(j, PORT_POTS); - SLIC_SetState(PLD_SLIC_STATE_STANDBY, j); -/* SLIC_SetState(PLD_SLIC_STATE_ACTIVE, j); */ - } - } - } - - j->intercom = -1; - j->framesread = j->frameswritten = 0; - j->read_wait = j->write_wait = 0; - j->rxreadycheck = j->txreadycheck = 0; - - /* initialise the DTMF prescale to a sensible value */ - if (j->cardtype == QTI_LINEJACK) { - set_dtmf_prescale(j, 0x10); - } else { - set_dtmf_prescale(j, 0x40); - } - set_play_volume(j, 0x100); - set_rec_volume(j, 0x100); - - if (ixj_WriteDSPCommand(0x0000, j)) /* Write IDLE to Software Control Register */ - return -1; -/* The read values of the SSR should be 0x00 for the IDLE command */ - if (j->ssr.low || j->ssr.high) - return -1; - - if (ixjdebug & 0x0002) - printk(KERN_INFO "Enable Line Monitor\n"); - - if (ixjdebug & 0x0002) - printk(KERN_INFO "Set Line Monitor to Asyncronous Mode\n"); - - if (ixj_WriteDSPCommand(0x7E01, j)) /* Asynchronous Line Monitor */ - return -1; - - if (ixjdebug & 0x002) - printk(KERN_INFO "Enable DTMF Detectors\n"); - - if (ixj_WriteDSPCommand(0x5151, j)) /* Enable DTMF detection */ - return -1; - - if (ixj_WriteDSPCommand(0x6E01, j)) /* Set Asyncronous Tone Generation */ - return -1; - - set_rec_depth(j, 2); /* Set Record Channel Limit to 2 frames */ - - set_play_depth(j, 2); /* Set Playback Channel Limit to 2 frames */ - - j->ex.bits.dtmf_ready = 0; - j->dtmf_state = 0; - j->dtmf_wp = j->dtmf_rp = 0; - j->rec_mode = j->play_mode = -1; - j->flags.ringing = 0; - j->maxrings = MAXRINGS; - j->ring_cadence = USA_RING_CADENCE; - j->drybuffer = 0; - j->winktime = 320; - j->flags.dtmf_oob = 0; - for (cnt = 0; cnt < 4; cnt++) - j->cadence_f[cnt].enable = 0; - /* must be a device on the specified address */ - ixj_WriteDSPCommand(0x0FE3, j); /* Put the DSP in 1/5 power mode. */ - - /* Set up the default signals for events */ - for (cnt = 0; cnt < 35; cnt++) - j->ixj_signals[cnt] = SIGIO; - - /* Set the excetion signal enable flags */ - j->ex_sig.bits.dtmf_ready = j->ex_sig.bits.hookstate = j->ex_sig.bits.flash = j->ex_sig.bits.pstn_ring = - j->ex_sig.bits.caller_id = j->ex_sig.bits.pstn_wink = j->ex_sig.bits.f0 = j->ex_sig.bits.f1 = j->ex_sig.bits.f2 = - j->ex_sig.bits.f3 = j->ex_sig.bits.fc0 = j->ex_sig.bits.fc1 = j->ex_sig.bits.fc2 = j->ex_sig.bits.fc3 = 1; -#ifdef IXJ_DYN_ALLOC - j->fskdata = NULL; -#endif - j->fskdcnt = 0; - j->cidcw_wait = 0; - - /* Register with the Telephony for Linux subsystem */ - j->p.f_op = &ixj_fops; - j->p.open = ixj_open; - j->p.board = j->board; - phone_register_device(&j->p, PHONE_UNIT_ANY); - - ixj_init_timer(j); - ixj_add_timer(j); - return 0; -} - -/* - * Exported service for pcmcia card handling - */ - -IXJ *ixj_pcmcia_probe(unsigned long dsp, unsigned long xilinx) -{ - IXJ *j = ixj_alloc(); - - j->board = 0; - - j->DSPbase = dsp; - j->XILINXbase = xilinx; - j->cardtype = QTI_PHONECARD; - ixj_selfprobe(j); - return j; -} - -EXPORT_SYMBOL(ixj_pcmcia_probe); /* Fpr PCMCIA */ - -static int ixj_get_status_proc(char *buf) -{ - int len; - int cnt; - IXJ *j; - len = 0; - len += sprintf(buf + len, "\nDriver version %i.%i.%i", IXJ_VER_MAJOR, IXJ_VER_MINOR, IXJ_BLD_VER); - len += sprintf(buf + len, "\nsizeof IXJ struct %Zd bytes", sizeof(IXJ)); - len += sprintf(buf + len, "\nsizeof DAA struct %Zd bytes", sizeof(DAA_REGS)); - len += sprintf(buf + len, "\nUsing old telephony API"); - len += sprintf(buf + len, "\nDebug Level %d\n", ixjdebug); - - for (cnt = 0; cnt < IXJMAX; cnt++) { - j = get_ixj(cnt); - if(j==NULL) - continue; - if (j->DSPbase) { - len += sprintf(buf + len, "\nCard Num %d", cnt); - len += sprintf(buf + len, "\nDSP Base Address 0x%4.4x", j->DSPbase); - if (j->cardtype != QTI_PHONEJACK) - len += sprintf(buf + len, "\nXILINX Base Address 0x%4.4x", j->XILINXbase); - len += sprintf(buf + len, "\nDSP Type %2.2x%2.2x", j->dsp.high, j->dsp.low); - len += sprintf(buf + len, "\nDSP Version %2.2x.%2.2x", j->ver.high, j->ver.low); - len += sprintf(buf + len, "\nSerial Number %8.8x", j->serial); - switch (j->cardtype) { - case (QTI_PHONEJACK): - len += sprintf(buf + len, "\nCard Type = Internet PhoneJACK"); - break; - case (QTI_LINEJACK): - len += sprintf(buf + len, "\nCard Type = Internet LineJACK"); - if (j->flags.g729_loaded) - len += sprintf(buf + len, " w/G.729 A/B"); - len += sprintf(buf + len, " Country = %d", j->daa_country); - break; - case (QTI_PHONEJACK_LITE): - len += sprintf(buf + len, "\nCard Type = Internet PhoneJACK Lite"); - if (j->flags.g729_loaded) - len += sprintf(buf + len, " w/G.729 A/B"); - break; - case (QTI_PHONEJACK_PCI): - len += sprintf(buf + len, "\nCard Type = Internet PhoneJACK PCI"); - if (j->flags.g729_loaded) - len += sprintf(buf + len, " w/G.729 A/B"); - break; - case (QTI_PHONECARD): - len += sprintf(buf + len, "\nCard Type = Internet PhoneCARD"); - if (j->flags.g729_loaded) - len += sprintf(buf + len, " w/G.729 A/B"); - len += sprintf(buf + len, "\nSmart Cable %spresent", j->pccr1.bits.drf ? "not " : ""); - if (!j->pccr1.bits.drf) - len += sprintf(buf + len, "\nSmart Cable type %d", j->flags.pcmciasct); - len += sprintf(buf + len, "\nSmart Cable state %d", j->flags.pcmciastate); - break; - default: - len += sprintf(buf + len, "\nCard Type = %d", j->cardtype); - break; - } - len += sprintf(buf + len, "\nReaders %d", j->readers); - len += sprintf(buf + len, "\nWriters %d", j->writers); - add_caps(j); - len += sprintf(buf + len, "\nCapabilities %d", j->caps); - if (j->dsp.low != 0x20) - len += sprintf(buf + len, "\nDSP Processor load %d", j->proc_load); - if (j->flags.cidsent) - len += sprintf(buf + len, "\nCaller ID data sent"); - else - len += sprintf(buf + len, "\nCaller ID data not sent"); - - len += sprintf(buf + len, "\nPlay CODEC "); - switch (j->play_codec) { - case G723_63: - len += sprintf(buf + len, "G.723.1 6.3"); - break; - case G723_53: - len += sprintf(buf + len, "G.723.1 5.3"); - break; - case TS85: - len += sprintf(buf + len, "TrueSpeech 8.5"); - break; - case TS48: - len += sprintf(buf + len, "TrueSpeech 4.8"); - break; - case TS41: - len += sprintf(buf + len, "TrueSpeech 4.1"); - break; - case G728: - len += sprintf(buf + len, "G.728"); - break; - case G729: - len += sprintf(buf + len, "G.729"); - break; - case G729B: - len += sprintf(buf + len, "G.729B"); - break; - case ULAW: - len += sprintf(buf + len, "uLaw"); - break; - case ALAW: - len += sprintf(buf + len, "aLaw"); - break; - case LINEAR16: - len += sprintf(buf + len, "16 bit Linear"); - break; - case LINEAR8: - len += sprintf(buf + len, "8 bit Linear"); - break; - case WSS: - len += sprintf(buf + len, "Windows Sound System"); - break; - default: - len += sprintf(buf + len, "NO CODEC CHOSEN"); - break; - } - len += sprintf(buf + len, "\nRecord CODEC "); - switch (j->rec_codec) { - case G723_63: - len += sprintf(buf + len, "G.723.1 6.3"); - break; - case G723_53: - len += sprintf(buf + len, "G.723.1 5.3"); - break; - case TS85: - len += sprintf(buf + len, "TrueSpeech 8.5"); - break; - case TS48: - len += sprintf(buf + len, "TrueSpeech 4.8"); - break; - case TS41: - len += sprintf(buf + len, "TrueSpeech 4.1"); - break; - case G728: - len += sprintf(buf + len, "G.728"); - break; - case G729: - len += sprintf(buf + len, "G.729"); - break; - case G729B: - len += sprintf(buf + len, "G.729B"); - break; - case ULAW: - len += sprintf(buf + len, "uLaw"); - break; - case ALAW: - len += sprintf(buf + len, "aLaw"); - break; - case LINEAR16: - len += sprintf(buf + len, "16 bit Linear"); - break; - case LINEAR8: - len += sprintf(buf + len, "8 bit Linear"); - break; - case WSS: - len += sprintf(buf + len, "Windows Sound System"); - break; - default: - len += sprintf(buf + len, "NO CODEC CHOSEN"); - break; - } - len += sprintf(buf + len, "\nAEC "); - switch (j->aec_level) { - case AEC_OFF: - len += sprintf(buf + len, "Off"); - break; - case AEC_LOW: - len += sprintf(buf + len, "Low"); - break; - case AEC_MED: - len += sprintf(buf + len, "Med"); - break; - case AEC_HIGH: - len += sprintf(buf + len, "High"); - break; - case AEC_AUTO: - len += sprintf(buf + len, "Auto"); - break; - case AEC_AGC: - len += sprintf(buf + len, "AEC/AGC"); - break; - default: - len += sprintf(buf + len, "unknown(%i)", j->aec_level); - break; - } - - len += sprintf(buf + len, "\nRec volume 0x%x", get_rec_volume(j)); - len += sprintf(buf + len, "\nPlay volume 0x%x", get_play_volume(j)); - len += sprintf(buf + len, "\nDTMF prescale 0x%x", get_dtmf_prescale(j)); - - len += sprintf(buf + len, "\nHook state %d", j->hookstate); /* j->r_hook); */ - - if (j->cardtype == QTI_LINEJACK) { - len += sprintf(buf + len, "\nPOTS Correct %d", j->flags.pots_correct); - len += sprintf(buf + len, "\nPSTN Present %d", j->flags.pstn_present); - len += sprintf(buf + len, "\nPSTN Check %d", j->flags.pstncheck); - len += sprintf(buf + len, "\nPOTS to PSTN %d", j->flags.pots_pstn); - switch (j->daa_mode) { - case SOP_PU_SLEEP: - len += sprintf(buf + len, "\nDAA PSTN On Hook"); - break; - case SOP_PU_RINGING: - len += sprintf(buf + len, "\nDAA PSTN Ringing"); - len += sprintf(buf + len, "\nRinging state = %d", j->cadence_f[4].state); - break; - case SOP_PU_CONVERSATION: - len += sprintf(buf + len, "\nDAA PSTN Off Hook"); - break; - case SOP_PU_PULSEDIALING: - len += sprintf(buf + len, "\nDAA PSTN Pulse Dialing"); - break; - } - len += sprintf(buf + len, "\nDAA RMR = %d", j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.bitreg.RMR); - len += sprintf(buf + len, "\nDAA VDD OK = %d", j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.VDD_OK); - len += sprintf(buf + len, "\nDAA CR0 = 0x%02x", j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg); - len += sprintf(buf + len, "\nDAA CR1 = 0x%02x", j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.reg); - len += sprintf(buf + len, "\nDAA CR2 = 0x%02x", j->m_DAAShadowRegs.SOP_REGS.SOP.cr2.reg); - len += sprintf(buf + len, "\nDAA CR3 = 0x%02x", j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg); - len += sprintf(buf + len, "\nDAA CR4 = 0x%02x", j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg); - len += sprintf(buf + len, "\nDAA CR5 = 0x%02x", j->m_DAAShadowRegs.SOP_REGS.SOP.cr5.reg); - len += sprintf(buf + len, "\nDAA XR0 = 0x%02x", j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.reg); - len += sprintf(buf + len, "\nDAA ringstop %ld - jiffies %ld", j->pstn_ring_stop, jiffies); - } - switch (j->port) { - case PORT_POTS: - len += sprintf(buf + len, "\nPort POTS"); - break; - case PORT_PSTN: - len += sprintf(buf + len, "\nPort PSTN"); - break; - case PORT_SPEAKER: - len += sprintf(buf + len, "\nPort SPEAKER/MIC"); - break; - case PORT_HANDSET: - len += sprintf(buf + len, "\nPort HANDSET"); - break; - } - if (j->dsp.low == 0x21 || j->dsp.low == 0x22) { - len += sprintf(buf + len, "\nSLIC state "); - switch (SLIC_GetState(j)) { - case PLD_SLIC_STATE_OC: - len += sprintf(buf + len, "OC"); - break; - case PLD_SLIC_STATE_RINGING: - len += sprintf(buf + len, "RINGING"); - break; - case PLD_SLIC_STATE_ACTIVE: - len += sprintf(buf + len, "ACTIVE"); - break; - case PLD_SLIC_STATE_OHT: /* On-hook transmit */ - len += sprintf(buf + len, "OHT"); - break; - case PLD_SLIC_STATE_TIPOPEN: - len += sprintf(buf + len, "TIPOPEN"); - break; - case PLD_SLIC_STATE_STANDBY: - len += sprintf(buf + len, "STANDBY"); - break; - case PLD_SLIC_STATE_APR: /* Active polarity reversal */ - len += sprintf(buf + len, "APR"); - break; - case PLD_SLIC_STATE_OHTPR: /* OHT polarity reversal */ - len += sprintf(buf + len, "OHTPR"); - break; - default: - len += sprintf(buf + len, "%d", SLIC_GetState(j)); - break; - } - } - len += sprintf(buf + len, "\nBase Frame %2.2x.%2.2x", j->baseframe.high, j->baseframe.low); - len += sprintf(buf + len, "\nCID Base Frame %2d", j->cid_base_frame_size); -#ifdef PERFMON_STATS - len += sprintf(buf + len, "\nTimer Checks %ld", j->timerchecks); - len += sprintf(buf + len, "\nRX Ready Checks %ld", j->rxreadycheck); - len += sprintf(buf + len, "\nTX Ready Checks %ld", j->txreadycheck); - len += sprintf(buf + len, "\nFrames Read %ld", j->framesread); - len += sprintf(buf + len, "\nFrames Written %ld", j->frameswritten); - len += sprintf(buf + len, "\nDry Buffer %ld", j->drybuffer); - len += sprintf(buf + len, "\nRead Waits %ld", j->read_wait); - len += sprintf(buf + len, "\nWrite Waits %ld", j->write_wait); - len += sprintf(buf + len, "\nStatus Waits %ld", j->statuswait); - len += sprintf(buf + len, "\nStatus Wait Fails %ld", j->statuswaitfail); - len += sprintf(buf + len, "\nPControl Waits %ld", j->pcontrolwait); - len += sprintf(buf + len, "\nPControl Wait Fails %ld", j->pcontrolwaitfail); - len += sprintf(buf + len, "\nIs Control Ready Checks %ld", j->iscontrolready); - len += sprintf(buf + len, "\nIs Control Ready Check failures %ld", j->iscontrolreadyfail); - -#endif - len += sprintf(buf + len, "\n"); - } - } - return len; -} - -static int ixj_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - int len = ixj_get_status_proc(page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - return len; -} - - -static void cleanup(void) -{ - int cnt; - IXJ *j; - - for (cnt = 0; cnt < IXJMAX; cnt++) { - j = get_ixj(cnt); - if(j != NULL && j->DSPbase) { - if (ixjdebug & 0x0002) - printk(KERN_INFO "IXJ: Deleting timer for /dev/phone%d\n", cnt); - del_timer(&j->timer); - if (j->cardtype == QTI_LINEJACK) { - j->pld_scrw.bits.daafsyncen = 0; /* Turn off DAA Frame Sync */ - - outb_p(j->pld_scrw.byte, j->XILINXbase); - j->pld_slicw.bits.rly1 = 0; - j->pld_slicw.bits.rly2 = 0; - j->pld_slicw.bits.rly3 = 0; - outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); - LED_SetState(0x0, j); - if (ixjdebug & 0x0002) - printk(KERN_INFO "IXJ: Releasing XILINX address for /dev/phone%d\n", cnt); - release_region(j->XILINXbase, 8); - } else if (j->cardtype == QTI_PHONEJACK_LITE || j->cardtype == QTI_PHONEJACK_PCI) { - if (ixjdebug & 0x0002) - printk(KERN_INFO "IXJ: Releasing XILINX address for /dev/phone%d\n", cnt); - release_region(j->XILINXbase, 4); - } - kfree(j->read_buffer); - kfree(j->write_buffer); - if (j->dev) - pnp_device_detach(j->dev); - if (ixjdebug & 0x0002) - printk(KERN_INFO "IXJ: Unregistering /dev/phone%d from LTAPI\n", cnt); - phone_unregister_device(&j->p); - if (ixjdebug & 0x0002) - printk(KERN_INFO "IXJ: Releasing DSP address for /dev/phone%d\n", cnt); - release_region(j->DSPbase, 16); -#ifdef IXJ_DYN_ALLOC - if (ixjdebug & 0x0002) - printk(KERN_INFO "IXJ: Freeing memory for /dev/phone%d\n", cnt); - kfree(j); - ixj[cnt] = NULL; -#endif - } - } - if (ixjdebug & 0x0002) - printk(KERN_INFO "IXJ: Removing /proc/ixj\n"); - remove_proc_entry ("ixj", NULL); -} - -/* Typedefs */ -typedef struct { - BYTE length; - DWORD bits; -} DATABLOCK; - -static void PCIEE_WriteBit(WORD wEEPROMAddress, BYTE lastLCC, BYTE byData) -{ - lastLCC = lastLCC & 0xfb; - lastLCC = lastLCC | (byData ? 4 : 0); - outb(lastLCC, wEEPROMAddress); /*set data out bit as appropriate */ - - mdelay(1); - lastLCC = lastLCC | 0x01; - outb(lastLCC, wEEPROMAddress); /*SK rising edge */ - - byData = byData << 1; - lastLCC = lastLCC & 0xfe; - mdelay(1); - outb(lastLCC, wEEPROMAddress); /*after delay, SK falling edge */ - -} - -static BYTE PCIEE_ReadBit(WORD wEEPROMAddress, BYTE lastLCC) -{ - mdelay(1); - lastLCC = lastLCC | 0x01; - outb(lastLCC, wEEPROMAddress); /*SK rising edge */ - - lastLCC = lastLCC & 0xfe; - mdelay(1); - outb(lastLCC, wEEPROMAddress); /*after delay, SK falling edge */ - - return ((inb(wEEPROMAddress) >> 3) & 1); -} - -static bool PCIEE_ReadWord(WORD wAddress, WORD wLoc, WORD * pwResult) -{ - BYTE lastLCC; - WORD wEEPROMAddress = wAddress + 3; - DWORD i; - BYTE byResult; - *pwResult = 0; - lastLCC = inb(wEEPROMAddress); - lastLCC = lastLCC | 0x02; - lastLCC = lastLCC & 0xfe; - outb(lastLCC, wEEPROMAddress); /* CS hi, SK lo */ - - mdelay(1); /* delay */ - - PCIEE_WriteBit(wEEPROMAddress, lastLCC, 1); - PCIEE_WriteBit(wEEPROMAddress, lastLCC, 1); - PCIEE_WriteBit(wEEPROMAddress, lastLCC, 0); - for (i = 0; i < 8; i++) { - PCIEE_WriteBit(wEEPROMAddress, lastLCC, wLoc & 0x80 ? 1 : 0); - wLoc <<= 1; - } - - for (i = 0; i < 16; i++) { - byResult = PCIEE_ReadBit(wEEPROMAddress, lastLCC); - *pwResult = (*pwResult << 1) | byResult; - } - - mdelay(1); /* another delay */ - - lastLCC = lastLCC & 0xfd; - outb(lastLCC, wEEPROMAddress); /* negate CS */ - - return 0; -} - -static DWORD PCIEE_GetSerialNumber(WORD wAddress) -{ - WORD wLo, wHi; - if (PCIEE_ReadWord(wAddress, 62, &wLo)) - return 0; - if (PCIEE_ReadWord(wAddress, 63, &wHi)) - return 0; - return (((DWORD) wHi << 16) | wLo); -} - -static int dspio[IXJMAX + 1] = -{ - 0, -}; -static int xio[IXJMAX + 1] = -{ - 0, -}; - -module_param_array(dspio, int, NULL, 0); -module_param_array(xio, int, NULL, 0); -MODULE_DESCRIPTION("Quicknet VoIP Telephony card module - www.quicknet.net"); -MODULE_AUTHOR("Ed Okerson "); -MODULE_LICENSE("GPL"); - -static void __exit ixj_exit(void) -{ - cleanup(); -} - -static IXJ *new_ixj(unsigned long port) -{ - IXJ *res; - if (!request_region(port, 16, "ixj DSP")) { - printk(KERN_INFO "ixj: can't get I/O address 0x%lx\n", port); - return NULL; - } - res = ixj_alloc(); - if (!res) { - release_region(port, 16); - printk(KERN_INFO "ixj: out of memory\n"); - return NULL; - } - res->DSPbase = port; - return res; -} - -static int __init ixj_probe_isapnp(int *cnt) -{ - int probe = 0; - int func = 0x110; - struct pnp_dev *dev = NULL, *old_dev = NULL; - - while (1) { - do { - IXJ *j; - int result; - - old_dev = dev; - dev = pnp_find_dev(NULL, ISAPNP_VENDOR('Q', 'T', 'I'), - ISAPNP_FUNCTION(func), old_dev); - if (!dev || !dev->card) - break; - result = pnp_device_attach(dev); - if (result < 0) { - printk("pnp attach failed %d \n", result); - break; - } - if (pnp_activate_dev(dev) < 0) { - printk("pnp activate failed (out of resources?)\n"); - pnp_device_detach(dev); - return -ENOMEM; - } - - if (!pnp_port_valid(dev, 0)) { - pnp_device_detach(dev); - return -ENODEV; - } - - j = new_ixj(pnp_port_start(dev, 0)); - if (!j) - break; - - if (func != 0x110) - j->XILINXbase = pnp_port_start(dev, 1); /* get real port */ - - switch (func) { - case (0x110): - j->cardtype = QTI_PHONEJACK; - break; - case (0x310): - j->cardtype = QTI_LINEJACK; - break; - case (0x410): - j->cardtype = QTI_PHONEJACK_LITE; - break; - } - j->board = *cnt; - probe = ixj_selfprobe(j); - if(!probe) { - j->serial = dev->card->serial; - j->dev = dev; - switch (func) { - case 0x110: - printk(KERN_INFO "ixj: found Internet PhoneJACK at 0x%x\n", j->DSPbase); - break; - case 0x310: - printk(KERN_INFO "ixj: found Internet LineJACK at 0x%x\n", j->DSPbase); - break; - case 0x410: - printk(KERN_INFO "ixj: found Internet PhoneJACK Lite at 0x%x\n", j->DSPbase); - break; - } - } - ++*cnt; - } while (dev); - if (func == 0x410) - break; - if (func == 0x310) - func = 0x410; - if (func == 0x110) - func = 0x310; - dev = NULL; - } - return probe; -} - -static int __init ixj_probe_isa(int *cnt) -{ - int i, probe; - - /* Use passed parameters for older kernels without PnP */ - for (i = 0; i < IXJMAX; i++) { - if (dspio[i]) { - IXJ *j = new_ixj(dspio[i]); - - if (!j) - break; - - j->XILINXbase = xio[i]; - j->cardtype = 0; - - j->board = *cnt; - probe = ixj_selfprobe(j); - j->dev = NULL; - ++*cnt; - } - } - return 0; -} - -static int __init ixj_probe_pci(int *cnt) -{ - struct pci_dev *pci = NULL; - int i, probe = 0; - IXJ *j = NULL; - - for (i = 0; i < IXJMAX - *cnt; i++) { - pci = pci_get_device(PCI_VENDOR_ID_QUICKNET, - PCI_DEVICE_ID_QUICKNET_XJ, pci); - if (!pci) - break; - - if (pci_enable_device(pci)) - break; - j = new_ixj(pci_resource_start(pci, 0)); - if (!j) - break; - - j->serial = (PCIEE_GetSerialNumber)pci_resource_start(pci, 2); - j->XILINXbase = j->DSPbase + 0x10; - j->cardtype = QTI_PHONEJACK_PCI; - j->board = *cnt; - probe = ixj_selfprobe(j); - if (!probe) - printk(KERN_INFO "ixj: found Internet PhoneJACK PCI at 0x%x\n", j->DSPbase); - ++*cnt; - } - pci_dev_put(pci); - return probe; -} - -static int __init ixj_init(void) -{ - int cnt = 0; - int probe = 0; - - cnt = 0; - - /* These might be no-ops, see above. */ - if ((probe = ixj_probe_isapnp(&cnt)) < 0) { - return probe; - } - if ((probe = ixj_probe_isa(&cnt)) < 0) { - return probe; - } - if ((probe = ixj_probe_pci(&cnt)) < 0) { - return probe; - } - printk(KERN_INFO "ixj driver initialized.\n"); - create_proc_read_entry ("ixj", 0, NULL, ixj_read_proc, NULL); - return probe; -} - -module_init(ixj_init); -module_exit(ixj_exit); - -static void DAA_Coeff_US(IXJ *j) -{ - int i; - - j->daa_country = DAA_US; - /*----------------------------------------------- */ - /* CAO */ - for (i = 0; i < ALISDAA_CALLERID_SIZE; i++) { - j->m_DAAShadowRegs.CAO_REGS.CAO.CallerID[i] = 0; - } - -/* Bytes for IM-filter part 1 (04): 0E,32,E2,2F,C2,5A,C0,00 */ - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7] = 0x03; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[6] = 0x4B; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[5] = 0x5D; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[4] = 0xCD; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[3] = 0x24; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[2] = 0xC5; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[1] = 0xA0; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[0] = 0x00; -/* Bytes for IM-filter part 2 (05): 72,85,00,0E,2B,3A,D0,08 */ - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[7] = 0x71; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[6] = 0x1A; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[5] = 0x00; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[4] = 0x0A; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[3] = 0xB5; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[2] = 0x33; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[1] = 0xE0; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[0] = 0x08; -/* Bytes for FRX-filter (08): 03,8F,48,F2,8F,48,70,08 */ - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[7] = 0x05; - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[6] = 0xA3; - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[5] = 0x72; - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[4] = 0x34; - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[3] = 0x3F; - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[2] = 0x3B; - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[1] = 0x30; - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[0] = 0x08; -/* Bytes for FRR-filter (07): 04,8F,38,7F,9B,EA,B0,08 */ - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[7] = 0x05; - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[6] = 0x87; - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[5] = 0xF9; - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[4] = 0x3E; - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[3] = 0x32; - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[2] = 0xDA; - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[1] = 0xB0; - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[0] = 0x08; -/* Bytes for AX-filter (0A): 16,55,DD,CA */ - j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[3] = 0x41; - j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[2] = 0xB5; - j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[1] = 0xDD; - j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[0] = 0xCA; -/* Bytes for AR-filter (09): 52,D3,11,42 */ - j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[3] = 0x25; - j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[2] = 0xC7; - j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[1] = 0x10; - j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[0] = 0xD6; -/* Bytes for TH-filter part 1 (00): 00,42,48,81,B3,80,00,98 */ - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[7] = 0x00; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[6] = 0x42; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[5] = 0x48; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[4] = 0x81; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[3] = 0xA5; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[2] = 0x80; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[1] = 0x00; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[0] = 0x98; -/* Bytes for TH-filter part 2 (01): 02,F2,33,A0,68,AB,8A,AD */ - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[7] = 0x02; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[6] = 0xA2; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[5] = 0x2B; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[4] = 0xB0; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[3] = 0xE8; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[2] = 0xAB; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[1] = 0x81; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[0] = 0xCC; -/* Bytes for TH-filter part 3 (02): 00,88,DA,54,A4,BA,2D,BB */ - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[7] = 0x00; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[6] = 0x88; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[5] = 0xD2; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[4] = 0x24; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[3] = 0xBA; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[2] = 0xA9; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[1] = 0x3B; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[0] = 0xA6; -/* ; (10K, 0.68uF) */ - /* */ - /* Bytes for Ringing part 1 (03):1B,3B,9B,BA,D4,1C,B3,23 */ - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[7] = 0x1B; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[6] = 0x3C; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[5] = 0x93; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[4] = 0x3A; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[3] = 0x22; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[2] = 0x12; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[1] = 0xA3; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[0] = 0x23; - /* Bytes for Ringing part 2 (06):13,42,A6,BA,D4,73,CA,D5 */ - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[7] = 0x12; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[6] = 0xA2; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[5] = 0xA6; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[4] = 0xBA; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[3] = 0x22; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[2] = 0x7A; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[1] = 0x0A; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[0] = 0xD5; - - /* Levelmetering Ringing (0D):B2,45,0F,8E */ - j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[3] = 0xAA; - j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[2] = 0x35; - j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[1] = 0x0F; - j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[0] = 0x8E; - - /* Bytes for Ringing part 1 (03):1B,3B,9B,BA,D4,1C,B3,23 */ -/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[7] = 0x1C; */ -/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[6] = 0xB3; */ -/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[5] = 0xAB; */ -/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[4] = 0xAB; */ -/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[3] = 0x54; */ -/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[2] = 0x2D; */ -/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[1] = 0x62; */ -/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[0] = 0x2D; */ - /* Bytes for Ringing part 2 (06):13,42,A6,BA,D4,73,CA,D5 */ -/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[7] = 0x2D; */ -/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[6] = 0x62; */ -/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[5] = 0xA6; */ -/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[4] = 0xBB; */ -/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[3] = 0x2A; */ -/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[2] = 0x7D; */ -/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[1] = 0x0A; */ -/* j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[0] = 0xD4; */ -/* */ - /* Levelmetering Ringing (0D):B2,45,0F,8E */ -/* j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[3] = 0xAA; */ -/* j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[2] = 0x05; */ -/* j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[1] = 0x0F; */ -/* j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[0] = 0x8E; */ - - /* Caller ID 1st Tone (0E):CA,0E,CA,09,99,99,99,99 */ - j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[7] = 0xCA; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[6] = 0x0E; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[5] = 0xCA; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[4] = 0x09; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[3] = 0x99; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[2] = 0x99; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[1] = 0x99; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[0] = 0x99; -/* Caller ID 2nd Tone (0F):FD,B5,BA,07,DA,00,00,00 */ - j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[7] = 0xFD; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[6] = 0xB5; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[5] = 0xBA; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[4] = 0x07; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[3] = 0xDA; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[2] = 0x00; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[1] = 0x00; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[0] = 0x00; -/* */ - /* ;CR Registers */ - /* Config. Reg. 0 (filters) (cr0):FE ; CLK gen. by crystal */ - j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFF; -/* Config. Reg. 1 (dialing) (cr1):05 */ - j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.reg = 0x05; -/* Config. Reg. 2 (caller ID) (cr2):04 */ - j->m_DAAShadowRegs.SOP_REGS.SOP.cr2.reg = 0x04; -/* Config. Reg. 3 (testloops) (cr3):03 ; SEL Bit==0, HP-disabled */ - j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg = 0x00; -/* Config. Reg. 4 (analog gain) (cr4):02 */ - j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = 0x02; - /* Config. Reg. 5 (Version) (cr5):02 */ - /* Config. Reg. 6 (Reserved) (cr6):00 */ - /* Config. Reg. 7 (Reserved) (cr7):00 */ - /* */ - /* ;xr Registers */ - /* Ext. Reg. 0 (Interrupt Reg.) (xr0):02 */ - - j->m_DAAShadowRegs.XOP_xr0_W.reg = 0x02; /* SO_1 set to '1' because it is inverted. */ - /* Ext. Reg. 1 (Interrupt enable) (xr1):3C Cadence, RING, Caller ID, VDD_OK */ - - j->m_DAAShadowRegs.XOP_REGS.XOP.xr1.reg = 0x3C; -/* Ext. Reg. 2 (Cadence Time Out) (xr2):7D */ - j->m_DAAShadowRegs.XOP_REGS.XOP.xr2.reg = 0x7D; -/* Ext. Reg. 3 (DC Char) (xr3):32 ; B-Filter Off == 1 */ - j->m_DAAShadowRegs.XOP_REGS.XOP.xr3.reg = 0x3B; /*0x32; */ - /* Ext. Reg. 4 (Cadence) (xr4):00 */ - - j->m_DAAShadowRegs.XOP_REGS.XOP.xr4.reg = 0x00; -/* Ext. Reg. 5 (Ring timer) (xr5):22 */ - j->m_DAAShadowRegs.XOP_REGS.XOP.xr5.reg = 0x22; -/* Ext. Reg. 6 (Power State) (xr6):00 */ - j->m_DAAShadowRegs.XOP_xr6_W.reg = 0x00; -/* Ext. Reg. 7 (Vdd) (xr7):40 */ - j->m_DAAShadowRegs.XOP_REGS.XOP.xr7.reg = 0x40; /* 0x40 ??? Should it be 0x00? */ - /* */ - /* DTMF Tone 1 (0B): 11,B3,5A,2C ; 697 Hz */ - /* 12,33,5A,C3 ; 770 Hz */ - /* 13,3C,5B,32 ; 852 Hz */ - /* 1D,1B,5C,CC ; 941 Hz */ - - j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[3] = 0x11; - j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[2] = 0xB3; - j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[1] = 0x5A; - j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[0] = 0x2C; -/* DTMF Tone 2 (0C): 32,32,52,B3 ; 1209 Hz */ - /* EC,1D,52,22 ; 1336 Hz */ - /* AA,AC,51,D2 ; 1477 Hz */ - /* 9B,3B,51,25 ; 1633 Hz */ - j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[3] = 0x32; - j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[2] = 0x32; - j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[1] = 0x52; - j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[0] = 0xB3; -} - -static void DAA_Coeff_UK(IXJ *j) -{ - int i; - - j->daa_country = DAA_UK; - /*----------------------------------------------- */ - /* CAO */ - for (i = 0; i < ALISDAA_CALLERID_SIZE; i++) { - j->m_DAAShadowRegs.CAO_REGS.CAO.CallerID[i] = 0; - } - -/* Bytes for IM-filter part 1 (04): 00,C2,BB,A8,CB,81,A0,00 */ - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7] = 0x00; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[6] = 0xC2; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[5] = 0xBB; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[4] = 0xA8; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[3] = 0xCB; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[2] = 0x81; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[1] = 0xA0; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[0] = 0x00; -/* Bytes for IM-filter part 2 (05): 40,00,00,0A,A4,33,E0,08 */ - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[7] = 0x40; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[6] = 0x00; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[5] = 0x00; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[4] = 0x0A; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[3] = 0xA4; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[2] = 0x33; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[1] = 0xE0; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[0] = 0x08; -/* Bytes for FRX-filter (08): 07,9B,ED,24,B2,A2,A0,08 */ - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[7] = 0x07; - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[6] = 0x9B; - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[5] = 0xED; - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[4] = 0x24; - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[3] = 0xB2; - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[2] = 0xA2; - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[1] = 0xA0; - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[0] = 0x08; -/* Bytes for FRR-filter (07): 0F,92,F2,B2,87,D2,30,08 */ - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[7] = 0x0F; - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[6] = 0x92; - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[5] = 0xF2; - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[4] = 0xB2; - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[3] = 0x87; - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[2] = 0xD2; - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[1] = 0x30; - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[0] = 0x08; -/* Bytes for AX-filter (0A): 1B,A5,DD,CA */ - j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[3] = 0x1B; - j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[2] = 0xA5; - j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[1] = 0xDD; - j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[0] = 0xCA; -/* Bytes for AR-filter (09): E2,27,10,D6 */ - j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[3] = 0xE2; - j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[2] = 0x27; - j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[1] = 0x10; - j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[0] = 0xD6; -/* Bytes for TH-filter part 1 (00): 80,2D,38,8B,D0,00,00,98 */ - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[7] = 0x80; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[6] = 0x2D; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[5] = 0x38; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[4] = 0x8B; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[3] = 0xD0; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[2] = 0x00; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[1] = 0x00; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[0] = 0x98; -/* Bytes for TH-filter part 2 (01): 02,5A,53,F0,0B,5F,84,D4 */ - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[7] = 0x02; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[6] = 0x5A; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[5] = 0x53; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[4] = 0xF0; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[3] = 0x0B; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[2] = 0x5F; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[1] = 0x84; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[0] = 0xD4; -/* Bytes for TH-filter part 3 (02): 00,88,6A,A4,8F,52,F5,32 */ - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[7] = 0x00; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[6] = 0x88; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[5] = 0x6A; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[4] = 0xA4; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[3] = 0x8F; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[2] = 0x52; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[1] = 0xF5; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[0] = 0x32; -/* ; idle */ - /* Bytes for Ringing part 1 (03):1B,3C,93,3A,22,12,A3,23 */ - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[7] = 0x1B; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[6] = 0x3C; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[5] = 0x93; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[4] = 0x3A; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[3] = 0x22; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[2] = 0x12; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[1] = 0xA3; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[0] = 0x23; -/* Bytes for Ringing part 2 (06):12,A2,A6,BA,22,7A,0A,D5 */ - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[7] = 0x12; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[6] = 0xA2; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[5] = 0xA6; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[4] = 0xBA; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[3] = 0x22; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[2] = 0x7A; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[1] = 0x0A; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[0] = 0xD5; -/* Levelmetering Ringing (0D):AA,35,0F,8E ; 25Hz 30V less possible? */ - j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[3] = 0xAA; - j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[2] = 0x35; - j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[1] = 0x0F; - j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[0] = 0x8E; -/* Caller ID 1st Tone (0E):CA,0E,CA,09,99,99,99,99 */ - j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[7] = 0xCA; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[6] = 0x0E; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[5] = 0xCA; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[4] = 0x09; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[3] = 0x99; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[2] = 0x99; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[1] = 0x99; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[0] = 0x99; -/* Caller ID 2nd Tone (0F):FD,B5,BA,07,DA,00,00,00 */ - j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[7] = 0xFD; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[6] = 0xB5; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[5] = 0xBA; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[4] = 0x07; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[3] = 0xDA; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[2] = 0x00; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[1] = 0x00; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[0] = 0x00; -/* ;CR Registers */ - /* Config. Reg. 0 (filters) (cr0):FF */ - j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFF; -/* Config. Reg. 1 (dialing) (cr1):05 */ - j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.reg = 0x05; -/* Config. Reg. 2 (caller ID) (cr2):04 */ - j->m_DAAShadowRegs.SOP_REGS.SOP.cr2.reg = 0x04; -/* Config. Reg. 3 (testloops) (cr3):00 ; */ - j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg = 0x00; -/* Config. Reg. 4 (analog gain) (cr4):02 */ - j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = 0x02; - /* Config. Reg. 5 (Version) (cr5):02 */ - /* Config. Reg. 6 (Reserved) (cr6):00 */ - /* Config. Reg. 7 (Reserved) (cr7):00 */ - /* ;xr Registers */ - /* Ext. Reg. 0 (Interrupt Reg.) (xr0):02 */ - - j->m_DAAShadowRegs.XOP_xr0_W.reg = 0x02; /* SO_1 set to '1' because it is inverted. */ - /* Ext. Reg. 1 (Interrupt enable) (xr1):1C */ - - j->m_DAAShadowRegs.XOP_REGS.XOP.xr1.reg = 0x1C; /* RING, Caller ID, VDD_OK */ - /* Ext. Reg. 2 (Cadence Time Out) (xr2):7D */ - - j->m_DAAShadowRegs.XOP_REGS.XOP.xr2.reg = 0x7D; -/* Ext. Reg. 3 (DC Char) (xr3):36 ; */ - j->m_DAAShadowRegs.XOP_REGS.XOP.xr3.reg = 0x36; -/* Ext. Reg. 4 (Cadence) (xr4):00 */ - j->m_DAAShadowRegs.XOP_REGS.XOP.xr4.reg = 0x00; -/* Ext. Reg. 5 (Ring timer) (xr5):22 */ - j->m_DAAShadowRegs.XOP_REGS.XOP.xr5.reg = 0x22; -/* Ext. Reg. 6 (Power State) (xr6):00 */ - j->m_DAAShadowRegs.XOP_xr6_W.reg = 0x00; -/* Ext. Reg. 7 (Vdd) (xr7):46 */ - j->m_DAAShadowRegs.XOP_REGS.XOP.xr7.reg = 0x46; /* 0x46 ??? Should it be 0x00? */ - /* DTMF Tone 1 (0B): 11,B3,5A,2C ; 697 Hz */ - /* 12,33,5A,C3 ; 770 Hz */ - /* 13,3C,5B,32 ; 852 Hz */ - /* 1D,1B,5C,CC ; 941 Hz */ - - j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[3] = 0x11; - j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[2] = 0xB3; - j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[1] = 0x5A; - j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[0] = 0x2C; -/* DTMF Tone 2 (0C): 32,32,52,B3 ; 1209 Hz */ - /* EC,1D,52,22 ; 1336 Hz */ - /* AA,AC,51,D2 ; 1477 Hz */ - /* 9B,3B,51,25 ; 1633 Hz */ - j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[3] = 0x32; - j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[2] = 0x32; - j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[1] = 0x52; - j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[0] = 0xB3; -} - - -static void DAA_Coeff_France(IXJ *j) -{ - int i; - - j->daa_country = DAA_FRANCE; - /*----------------------------------------------- */ - /* CAO */ - for (i = 0; i < ALISDAA_CALLERID_SIZE; i++) { - j->m_DAAShadowRegs.CAO_REGS.CAO.CallerID[i] = 0; - } - -/* Bytes for IM-filter part 1 (04): 02,A2,43,2C,22,AF,A0,00 */ - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7] = 0x02; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[6] = 0xA2; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[5] = 0x43; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[4] = 0x2C; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[3] = 0x22; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[2] = 0xAF; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[1] = 0xA0; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[0] = 0x00; -/* Bytes for IM-filter part 2 (05): 67,CE,00,0C,22,33,E0,08 */ - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[7] = 0x67; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[6] = 0xCE; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[5] = 0x00; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[4] = 0x2C; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[3] = 0x22; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[2] = 0x33; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[1] = 0xE0; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[0] = 0x08; -/* Bytes for FRX-filter (08): 07,9A,28,F6,23,4A,B0,08 */ - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[7] = 0x07; - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[6] = 0x9A; - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[5] = 0x28; - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[4] = 0xF6; - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[3] = 0x23; - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[2] = 0x4A; - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[1] = 0xB0; - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[0] = 0x08; -/* Bytes for FRR-filter (07): 03,8F,F9,2F,9E,FA,20,08 */ - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[7] = 0x03; - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[6] = 0x8F; - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[5] = 0xF9; - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[4] = 0x2F; - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[3] = 0x9E; - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[2] = 0xFA; - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[1] = 0x20; - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[0] = 0x08; -/* Bytes for AX-filter (0A): 16,B5,DD,CA */ - j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[3] = 0x16; - j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[2] = 0xB5; - j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[1] = 0xDD; - j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[0] = 0xCA; -/* Bytes for AR-filter (09): 52,C7,10,D6 */ - j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[3] = 0xE2; - j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[2] = 0xC7; - j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[1] = 0x10; - j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[0] = 0xD6; -/* Bytes for TH-filter part 1 (00): 00,42,48,81,A6,80,00,98 */ - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[7] = 0x00; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[6] = 0x42; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[5] = 0x48; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[4] = 0x81; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[3] = 0xA6; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[2] = 0x80; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[1] = 0x00; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[0] = 0x98; -/* Bytes for TH-filter part 2 (01): 02,AC,2A,30,78,AC,8A,2C */ - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[7] = 0x02; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[6] = 0xAC; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[5] = 0x2A; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[4] = 0x30; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[3] = 0x78; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[2] = 0xAC; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[1] = 0x8A; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[0] = 0x2C; -/* Bytes for TH-filter part 3 (02): 00,88,DA,A5,22,BA,2C,45 */ - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[7] = 0x00; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[6] = 0x88; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[5] = 0xDA; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[4] = 0xA5; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[3] = 0x22; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[2] = 0xBA; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[1] = 0x2C; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[0] = 0x45; -/* ; idle */ - /* Bytes for Ringing part 1 (03):1B,3C,93,3A,22,12,A3,23 */ - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[7] = 0x1B; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[6] = 0x3C; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[5] = 0x93; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[4] = 0x3A; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[3] = 0x22; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[2] = 0x12; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[1] = 0xA3; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[0] = 0x23; -/* Bytes for Ringing part 2 (06):12,A2,A6,BA,22,7A,0A,D5 */ - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[7] = 0x12; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[6] = 0xA2; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[5] = 0xA6; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[4] = 0xBA; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[3] = 0x22; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[2] = 0x7A; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[1] = 0x0A; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[0] = 0xD5; -/* Levelmetering Ringing (0D):32,45,B5,84 ; 50Hz 20V */ - j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[3] = 0x32; - j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[2] = 0x45; - j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[1] = 0xB5; - j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[0] = 0x84; -/* Caller ID 1st Tone (0E):CA,0E,CA,09,99,99,99,99 */ - j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[7] = 0xCA; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[6] = 0x0E; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[5] = 0xCA; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[4] = 0x09; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[3] = 0x99; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[2] = 0x99; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[1] = 0x99; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[0] = 0x99; -/* Caller ID 2nd Tone (0F):FD,B5,BA,07,DA,00,00,00 */ - j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[7] = 0xFD; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[6] = 0xB5; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[5] = 0xBA; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[4] = 0x07; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[3] = 0xDA; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[2] = 0x00; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[1] = 0x00; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[0] = 0x00; -/* ;CR Registers */ - /* Config. Reg. 0 (filters) (cr0):FF */ - j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFF; -/* Config. Reg. 1 (dialing) (cr1):05 */ - j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.reg = 0x05; -/* Config. Reg. 2 (caller ID) (cr2):04 */ - j->m_DAAShadowRegs.SOP_REGS.SOP.cr2.reg = 0x04; -/* Config. Reg. 3 (testloops) (cr3):00 ; */ - j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg = 0x00; -/* Config. Reg. 4 (analog gain) (cr4):02 */ - j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = 0x02; - /* Config. Reg. 5 (Version) (cr5):02 */ - /* Config. Reg. 6 (Reserved) (cr6):00 */ - /* Config. Reg. 7 (Reserved) (cr7):00 */ - /* ;xr Registers */ - /* Ext. Reg. 0 (Interrupt Reg.) (xr0):02 */ - - j->m_DAAShadowRegs.XOP_xr0_W.reg = 0x02; /* SO_1 set to '1' because it is inverted. */ - /* Ext. Reg. 1 (Interrupt enable) (xr1):1C */ - - j->m_DAAShadowRegs.XOP_REGS.XOP.xr1.reg = 0x1C; /* RING, Caller ID, VDD_OK */ - /* Ext. Reg. 2 (Cadence Time Out) (xr2):7D */ - - j->m_DAAShadowRegs.XOP_REGS.XOP.xr2.reg = 0x7D; -/* Ext. Reg. 3 (DC Char) (xr3):36 ; */ - j->m_DAAShadowRegs.XOP_REGS.XOP.xr3.reg = 0x36; -/* Ext. Reg. 4 (Cadence) (xr4):00 */ - j->m_DAAShadowRegs.XOP_REGS.XOP.xr4.reg = 0x00; -/* Ext. Reg. 5 (Ring timer) (xr5):22 */ - j->m_DAAShadowRegs.XOP_REGS.XOP.xr5.reg = 0x22; -/* Ext. Reg. 6 (Power State) (xr6):00 */ - j->m_DAAShadowRegs.XOP_xr6_W.reg = 0x00; -/* Ext. Reg. 7 (Vdd) (xr7):46 */ - j->m_DAAShadowRegs.XOP_REGS.XOP.xr7.reg = 0x46; /* 0x46 ??? Should it be 0x00? */ - /* DTMF Tone 1 (0B): 11,B3,5A,2C ; 697 Hz */ - /* 12,33,5A,C3 ; 770 Hz */ - /* 13,3C,5B,32 ; 852 Hz */ - /* 1D,1B,5C,CC ; 941 Hz */ - - j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[3] = 0x11; - j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[2] = 0xB3; - j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[1] = 0x5A; - j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[0] = 0x2C; -/* DTMF Tone 2 (0C): 32,32,52,B3 ; 1209 Hz */ - /* EC,1D,52,22 ; 1336 Hz */ - /* AA,AC,51,D2 ; 1477 Hz */ - /* 9B,3B,51,25 ; 1633 Hz */ - j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[3] = 0x32; - j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[2] = 0x32; - j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[1] = 0x52; - j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[0] = 0xB3; -} - - -static void DAA_Coeff_Germany(IXJ *j) -{ - int i; - - j->daa_country = DAA_GERMANY; - /*----------------------------------------------- */ - /* CAO */ - for (i = 0; i < ALISDAA_CALLERID_SIZE; i++) { - j->m_DAAShadowRegs.CAO_REGS.CAO.CallerID[i] = 0; - } - -/* Bytes for IM-filter part 1 (04): 00,CE,BB,B8,D2,81,B0,00 */ - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7] = 0x00; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[6] = 0xCE; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[5] = 0xBB; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[4] = 0xB8; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[3] = 0xD2; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[2] = 0x81; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[1] = 0xB0; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[0] = 0x00; -/* Bytes for IM-filter part 2 (05): 45,8F,00,0C,D2,3A,D0,08 */ - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[7] = 0x45; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[6] = 0x8F; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[5] = 0x00; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[4] = 0x0C; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[3] = 0xD2; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[2] = 0x3A; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[1] = 0xD0; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[0] = 0x08; -/* Bytes for FRX-filter (08): 07,AA,E2,34,24,89,20,08 */ - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[7] = 0x07; - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[6] = 0xAA; - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[5] = 0xE2; - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[4] = 0x34; - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[3] = 0x24; - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[2] = 0x89; - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[1] = 0x20; - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[0] = 0x08; -/* Bytes for FRR-filter (07): 02,87,FA,37,9A,CA,B0,08 */ - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[7] = 0x02; - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[6] = 0x87; - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[5] = 0xFA; - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[4] = 0x37; - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[3] = 0x9A; - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[2] = 0xCA; - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[1] = 0xB0; - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[0] = 0x08; -/* Bytes for AX-filter (0A): 72,D5,DD,CA */ - j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[3] = 0x72; - j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[2] = 0xD5; - j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[1] = 0xDD; - j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[0] = 0xCA; -/* Bytes for AR-filter (09): 72,42,13,4B */ - j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[3] = 0x72; - j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[2] = 0x42; - j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[1] = 0x13; - j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[0] = 0x4B; -/* Bytes for TH-filter part 1 (00): 80,52,48,81,AD,80,00,98 */ - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[7] = 0x80; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[6] = 0x52; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[5] = 0x48; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[4] = 0x81; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[3] = 0xAD; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[2] = 0x80; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[1] = 0x00; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[0] = 0x98; -/* Bytes for TH-filter part 2 (01): 02,42,5A,20,E8,1A,81,27 */ - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[7] = 0x02; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[6] = 0x42; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[5] = 0x5A; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[4] = 0x20; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[3] = 0xE8; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[2] = 0x1A; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[1] = 0x81; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[0] = 0x27; -/* Bytes for TH-filter part 3 (02): 00,88,63,26,BD,4B,A3,C2 */ - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[7] = 0x00; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[6] = 0x88; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[5] = 0x63; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[4] = 0x26; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[3] = 0xBD; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[2] = 0x4B; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[1] = 0xA3; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[0] = 0xC2; -/* ; (10K, 0.68uF) */ - /* Bytes for Ringing part 1 (03):1B,3B,9B,BA,D4,1C,B3,23 */ - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[7] = 0x1B; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[6] = 0x3B; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[5] = 0x9B; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[4] = 0xBA; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[3] = 0xD4; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[2] = 0x1C; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[1] = 0xB3; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[0] = 0x23; -/* Bytes for Ringing part 2 (06):13,42,A6,BA,D4,73,CA,D5 */ - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[7] = 0x13; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[6] = 0x42; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[5] = 0xA6; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[4] = 0xBA; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[3] = 0xD4; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[2] = 0x73; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[1] = 0xCA; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[0] = 0xD5; -/* Levelmetering Ringing (0D):B2,45,0F,8E */ - j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[3] = 0xB2; - j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[2] = 0x45; - j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[1] = 0x0F; - j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[0] = 0x8E; -/* Caller ID 1st Tone (0E):CA,0E,CA,09,99,99,99,99 */ - j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[7] = 0xCA; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[6] = 0x0E; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[5] = 0xCA; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[4] = 0x09; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[3] = 0x99; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[2] = 0x99; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[1] = 0x99; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[0] = 0x99; -/* Caller ID 2nd Tone (0F):FD,B5,BA,07,DA,00,00,00 */ - j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[7] = 0xFD; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[6] = 0xB5; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[5] = 0xBA; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[4] = 0x07; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[3] = 0xDA; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[2] = 0x00; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[1] = 0x00; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[0] = 0x00; -/* ;CR Registers */ - /* Config. Reg. 0 (filters) (cr0):FF ; all Filters enabled, CLK from ext. source */ - j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFF; -/* Config. Reg. 1 (dialing) (cr1):05 ; Manual Ring, Ring metering enabled */ - j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.reg = 0x05; -/* Config. Reg. 2 (caller ID) (cr2):04 ; Analog Gain 0dB, FSC internal */ - j->m_DAAShadowRegs.SOP_REGS.SOP.cr2.reg = 0x04; -/* Config. Reg. 3 (testloops) (cr3):00 ; SEL Bit==0, HP-enabled */ - j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg = 0x00; -/* Config. Reg. 4 (analog gain) (cr4):02 */ - j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = 0x02; - /* Config. Reg. 5 (Version) (cr5):02 */ - /* Config. Reg. 6 (Reserved) (cr6):00 */ - /* Config. Reg. 7 (Reserved) (cr7):00 */ - /* ;xr Registers */ - /* Ext. Reg. 0 (Interrupt Reg.) (xr0):02 */ - - j->m_DAAShadowRegs.XOP_xr0_W.reg = 0x02; /* SO_1 set to '1' because it is inverted. */ - /* Ext. Reg. 1 (Interrupt enable) (xr1):1C ; Ring, CID, VDDOK Interrupts enabled */ - - j->m_DAAShadowRegs.XOP_REGS.XOP.xr1.reg = 0x1C; /* RING, Caller ID, VDD_OK */ - /* Ext. Reg. 2 (Cadence Time Out) (xr2):7D */ - - j->m_DAAShadowRegs.XOP_REGS.XOP.xr2.reg = 0x7D; -/* Ext. Reg. 3 (DC Char) (xr3):32 ; B-Filter Off==1, U0=3.5V, R=200Ohm */ - j->m_DAAShadowRegs.XOP_REGS.XOP.xr3.reg = 0x32; -/* Ext. Reg. 4 (Cadence) (xr4):00 */ - j->m_DAAShadowRegs.XOP_REGS.XOP.xr4.reg = 0x00; -/* Ext. Reg. 5 (Ring timer) (xr5):22 */ - j->m_DAAShadowRegs.XOP_REGS.XOP.xr5.reg = 0x22; -/* Ext. Reg. 6 (Power State) (xr6):00 */ - j->m_DAAShadowRegs.XOP_xr6_W.reg = 0x00; -/* Ext. Reg. 7 (Vdd) (xr7):40 ; VDD=4.25 V */ - j->m_DAAShadowRegs.XOP_REGS.XOP.xr7.reg = 0x40; /* 0x40 ??? Should it be 0x00? */ - /* DTMF Tone 1 (0B): 11,B3,5A,2C ; 697 Hz */ - /* 12,33,5A,C3 ; 770 Hz */ - /* 13,3C,5B,32 ; 852 Hz */ - /* 1D,1B,5C,CC ; 941 Hz */ - - j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[3] = 0x11; - j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[2] = 0xB3; - j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[1] = 0x5A; - j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[0] = 0x2C; -/* DTMF Tone 2 (0C): 32,32,52,B3 ; 1209 Hz */ - /* EC,1D,52,22 ; 1336 Hz */ - /* AA,AC,51,D2 ; 1477 Hz */ - /* 9B,3B,51,25 ; 1633 Hz */ - j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[3] = 0x32; - j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[2] = 0x32; - j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[1] = 0x52; - j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[0] = 0xB3; -} - - -static void DAA_Coeff_Australia(IXJ *j) -{ - int i; - - j->daa_country = DAA_AUSTRALIA; - /*----------------------------------------------- */ - /* CAO */ - for (i = 0; i < ALISDAA_CALLERID_SIZE; i++) { - j->m_DAAShadowRegs.CAO_REGS.CAO.CallerID[i] = 0; - } - -/* Bytes for IM-filter part 1 (04): 00,A3,AA,28,B3,82,D0,00 */ - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7] = 0x00; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[6] = 0xA3; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[5] = 0xAA; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[4] = 0x28; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[3] = 0xB3; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[2] = 0x82; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[1] = 0xD0; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[0] = 0x00; -/* Bytes for IM-filter part 2 (05): 70,96,00,09,32,6B,C0,08 */ - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[7] = 0x70; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[6] = 0x96; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[5] = 0x00; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[4] = 0x09; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[3] = 0x32; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[2] = 0x6B; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[1] = 0xC0; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[0] = 0x08; -/* Bytes for FRX-filter (08): 07,96,E2,34,32,9B,30,08 */ - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[7] = 0x07; - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[6] = 0x96; - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[5] = 0xE2; - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[4] = 0x34; - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[3] = 0x32; - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[2] = 0x9B; - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[1] = 0x30; - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[0] = 0x08; -/* Bytes for FRR-filter (07): 0F,9A,E9,2F,22,CC,A0,08 */ - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[7] = 0x0F; - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[6] = 0x9A; - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[5] = 0xE9; - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[4] = 0x2F; - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[3] = 0x22; - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[2] = 0xCC; - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[1] = 0xA0; - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[0] = 0x08; -/* Bytes for AX-filter (0A): CB,45,DD,CA */ - j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[3] = 0xCB; - j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[2] = 0x45; - j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[1] = 0xDD; - j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[0] = 0xCA; -/* Bytes for AR-filter (09): 1B,67,10,D6 */ - j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[3] = 0x1B; - j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[2] = 0x67; - j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[1] = 0x10; - j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[0] = 0xD6; -/* Bytes for TH-filter part 1 (00): 80,52,48,81,AF,80,00,98 */ - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[7] = 0x80; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[6] = 0x52; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[5] = 0x48; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[4] = 0x81; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[3] = 0xAF; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[2] = 0x80; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[1] = 0x00; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[0] = 0x98; -/* Bytes for TH-filter part 2 (01): 02,DB,52,B0,38,01,82,AC */ - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[7] = 0x02; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[6] = 0xDB; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[5] = 0x52; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[4] = 0xB0; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[3] = 0x38; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[2] = 0x01; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[1] = 0x82; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[0] = 0xAC; -/* Bytes for TH-filter part 3 (02): 00,88,4A,3E,2C,3B,24,46 */ - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[7] = 0x00; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[6] = 0x88; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[5] = 0x4A; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[4] = 0x3E; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[3] = 0x2C; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[2] = 0x3B; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[1] = 0x24; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[0] = 0x46; -/* ; idle */ - /* Bytes for Ringing part 1 (03):1B,3C,93,3A,22,12,A3,23 */ - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[7] = 0x1B; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[6] = 0x3C; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[5] = 0x93; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[4] = 0x3A; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[3] = 0x22; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[2] = 0x12; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[1] = 0xA3; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[0] = 0x23; -/* Bytes for Ringing part 2 (06):12,A2,A6,BA,22,7A,0A,D5 */ - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[7] = 0x12; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[6] = 0xA2; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[5] = 0xA6; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[4] = 0xBA; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[3] = 0x22; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[2] = 0x7A; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[1] = 0x0A; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[0] = 0xD5; -/* Levelmetering Ringing (0D):32,45,B5,84 ; 50Hz 20V */ - j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[3] = 0x32; - j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[2] = 0x45; - j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[1] = 0xB5; - j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[0] = 0x84; -/* Caller ID 1st Tone (0E):CA,0E,CA,09,99,99,99,99 */ - j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[7] = 0xCA; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[6] = 0x0E; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[5] = 0xCA; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[4] = 0x09; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[3] = 0x99; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[2] = 0x99; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[1] = 0x99; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[0] = 0x99; -/* Caller ID 2nd Tone (0F):FD,B5,BA,07,DA,00,00,00 */ - j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[7] = 0xFD; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[6] = 0xB5; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[5] = 0xBA; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[4] = 0x07; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[3] = 0xDA; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[2] = 0x00; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[1] = 0x00; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[0] = 0x00; -/* ;CR Registers */ - /* Config. Reg. 0 (filters) (cr0):FF */ - j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFF; -/* Config. Reg. 1 (dialing) (cr1):05 */ - j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.reg = 0x05; -/* Config. Reg. 2 (caller ID) (cr2):04 */ - j->m_DAAShadowRegs.SOP_REGS.SOP.cr2.reg = 0x04; -/* Config. Reg. 3 (testloops) (cr3):00 ; */ - j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg = 0x00; -/* Config. Reg. 4 (analog gain) (cr4):02 */ - j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = 0x02; - /* Config. Reg. 5 (Version) (cr5):02 */ - /* Config. Reg. 6 (Reserved) (cr6):00 */ - /* Config. Reg. 7 (Reserved) (cr7):00 */ - /* ;xr Registers */ - /* Ext. Reg. 0 (Interrupt Reg.) (xr0):02 */ - - j->m_DAAShadowRegs.XOP_xr0_W.reg = 0x02; /* SO_1 set to '1' because it is inverted. */ - /* Ext. Reg. 1 (Interrupt enable) (xr1):1C */ - - j->m_DAAShadowRegs.XOP_REGS.XOP.xr1.reg = 0x1C; /* RING, Caller ID, VDD_OK */ - /* Ext. Reg. 2 (Cadence Time Out) (xr2):7D */ - - j->m_DAAShadowRegs.XOP_REGS.XOP.xr2.reg = 0x7D; -/* Ext. Reg. 3 (DC Char) (xr3):2B ; */ - j->m_DAAShadowRegs.XOP_REGS.XOP.xr3.reg = 0x2B; -/* Ext. Reg. 4 (Cadence) (xr4):00 */ - j->m_DAAShadowRegs.XOP_REGS.XOP.xr4.reg = 0x00; -/* Ext. Reg. 5 (Ring timer) (xr5):22 */ - j->m_DAAShadowRegs.XOP_REGS.XOP.xr5.reg = 0x22; -/* Ext. Reg. 6 (Power State) (xr6):00 */ - j->m_DAAShadowRegs.XOP_xr6_W.reg = 0x00; -/* Ext. Reg. 7 (Vdd) (xr7):40 */ - j->m_DAAShadowRegs.XOP_REGS.XOP.xr7.reg = 0x40; /* 0x40 ??? Should it be 0x00? */ - - /* DTMF Tone 1 (0B): 11,B3,5A,2C ; 697 Hz */ - /* 12,33,5A,C3 ; 770 Hz */ - /* 13,3C,5B,32 ; 852 Hz */ - /* 1D,1B,5C,CC ; 941 Hz */ - j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[3] = 0x11; - j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[2] = 0xB3; - j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[1] = 0x5A; - j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[0] = 0x2C; - - /* DTMF Tone 2 (0C): 32,32,52,B3 ; 1209 Hz */ - /* EC,1D,52,22 ; 1336 Hz */ - /* AA,AC,51,D2 ; 1477 Hz */ - /* 9B,3B,51,25 ; 1633 Hz */ - j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[3] = 0x32; - j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[2] = 0x32; - j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[1] = 0x52; - j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[0] = 0xB3; -} - -static void DAA_Coeff_Japan(IXJ *j) -{ - int i; - - j->daa_country = DAA_JAPAN; - /*----------------------------------------------- */ - /* CAO */ - for (i = 0; i < ALISDAA_CALLERID_SIZE; i++) { - j->m_DAAShadowRegs.CAO_REGS.CAO.CallerID[i] = 0; - } - -/* Bytes for IM-filter part 1 (04): 06,BD,E2,2D,BA,F9,A0,00 */ - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7] = 0x06; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[6] = 0xBD; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[5] = 0xE2; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[4] = 0x2D; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[3] = 0xBA; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[2] = 0xF9; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[1] = 0xA0; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[0] = 0x00; -/* Bytes for IM-filter part 2 (05): 6F,F7,00,0E,34,33,E0,08 */ - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[7] = 0x6F; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[6] = 0xF7; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[5] = 0x00; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[4] = 0x0E; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[3] = 0x34; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[2] = 0x33; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[1] = 0xE0; - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[0] = 0x08; -/* Bytes for FRX-filter (08): 02,8F,68,77,9C,58,F0,08 */ - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[7] = 0x02; - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[6] = 0x8F; - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[5] = 0x68; - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[4] = 0x77; - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[3] = 0x9C; - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[2] = 0x58; - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[1] = 0xF0; - j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[0] = 0x08; -/* Bytes for FRR-filter (07): 03,8F,38,73,87,EA,20,08 */ - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[7] = 0x03; - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[6] = 0x8F; - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[5] = 0x38; - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[4] = 0x73; - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[3] = 0x87; - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[2] = 0xEA; - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[1] = 0x20; - j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[0] = 0x08; -/* Bytes for AX-filter (0A): 51,C5,DD,CA */ - j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[3] = 0x51; - j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[2] = 0xC5; - j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[1] = 0xDD; - j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[0] = 0xCA; -/* Bytes for AR-filter (09): 25,A7,10,D6 */ - j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[3] = 0x25; - j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[2] = 0xA7; - j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[1] = 0x10; - j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[0] = 0xD6; -/* Bytes for TH-filter part 1 (00): 00,42,48,81,AE,80,00,98 */ - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[7] = 0x00; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[6] = 0x42; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[5] = 0x48; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[4] = 0x81; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[3] = 0xAE; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[2] = 0x80; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[1] = 0x00; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[0] = 0x98; -/* Bytes for TH-filter part 2 (01): 02,AB,2A,20,99,5B,89,28 */ - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[7] = 0x02; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[6] = 0xAB; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[5] = 0x2A; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[4] = 0x20; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[3] = 0x99; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[2] = 0x5B; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[1] = 0x89; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[0] = 0x28; -/* Bytes for TH-filter part 3 (02): 00,88,DA,25,34,C5,4C,BA */ - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[7] = 0x00; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[6] = 0x88; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[5] = 0xDA; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[4] = 0x25; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[3] = 0x34; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[2] = 0xC5; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[1] = 0x4C; - j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[0] = 0xBA; -/* ; idle */ - /* Bytes for Ringing part 1 (03):1B,3C,93,3A,22,12,A3,23 */ - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[7] = 0x1B; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[6] = 0x3C; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[5] = 0x93; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[4] = 0x3A; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[3] = 0x22; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[2] = 0x12; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[1] = 0xA3; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[0] = 0x23; -/* Bytes for Ringing part 2 (06):12,A2,A6,BA,22,7A,0A,D5 */ - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[7] = 0x12; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[6] = 0xA2; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[5] = 0xA6; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[4] = 0xBA; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[3] = 0x22; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[2] = 0x7A; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[1] = 0x0A; - j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[0] = 0xD5; -/* Levelmetering Ringing (0D):AA,35,0F,8E ; 25Hz 30V ????????? */ - j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[3] = 0xAA; - j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[2] = 0x35; - j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[1] = 0x0F; - j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[0] = 0x8E; -/* Caller ID 1st Tone (0E):CA,0E,CA,09,99,99,99,99 */ - j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[7] = 0xCA; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[6] = 0x0E; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[5] = 0xCA; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[4] = 0x09; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[3] = 0x99; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[2] = 0x99; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[1] = 0x99; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[0] = 0x99; -/* Caller ID 2nd Tone (0F):FD,B5,BA,07,DA,00,00,00 */ - j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[7] = 0xFD; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[6] = 0xB5; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[5] = 0xBA; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[4] = 0x07; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[3] = 0xDA; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[2] = 0x00; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[1] = 0x00; - j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[0] = 0x00; -/* ;CR Registers */ - /* Config. Reg. 0 (filters) (cr0):FF */ - j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFF; -/* Config. Reg. 1 (dialing) (cr1):05 */ - j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.reg = 0x05; -/* Config. Reg. 2 (caller ID) (cr2):04 */ - j->m_DAAShadowRegs.SOP_REGS.SOP.cr2.reg = 0x04; -/* Config. Reg. 3 (testloops) (cr3):00 ; */ - j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg = 0x00; -/* Config. Reg. 4 (analog gain) (cr4):02 */ - j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = 0x02; - /* Config. Reg. 5 (Version) (cr5):02 */ - /* Config. Reg. 6 (Reserved) (cr6):00 */ - /* Config. Reg. 7 (Reserved) (cr7):00 */ - /* ;xr Registers */ - /* Ext. Reg. 0 (Interrupt Reg.) (xr0):02 */ - - j->m_DAAShadowRegs.XOP_xr0_W.reg = 0x02; /* SO_1 set to '1' because it is inverted. */ - /* Ext. Reg. 1 (Interrupt enable) (xr1):1C */ - - j->m_DAAShadowRegs.XOP_REGS.XOP.xr1.reg = 0x1C; /* RING, Caller ID, VDD_OK */ - /* Ext. Reg. 2 (Cadence Time Out) (xr2):7D */ - - j->m_DAAShadowRegs.XOP_REGS.XOP.xr2.reg = 0x7D; -/* Ext. Reg. 3 (DC Char) (xr3):22 ; */ - j->m_DAAShadowRegs.XOP_REGS.XOP.xr3.reg = 0x22; -/* Ext. Reg. 4 (Cadence) (xr4):00 */ - j->m_DAAShadowRegs.XOP_REGS.XOP.xr4.reg = 0x00; -/* Ext. Reg. 5 (Ring timer) (xr5):22 */ - j->m_DAAShadowRegs.XOP_REGS.XOP.xr5.reg = 0x22; -/* Ext. Reg. 6 (Power State) (xr6):00 */ - j->m_DAAShadowRegs.XOP_xr6_W.reg = 0x00; -/* Ext. Reg. 7 (Vdd) (xr7):40 */ - j->m_DAAShadowRegs.XOP_REGS.XOP.xr7.reg = 0x40; /* 0x40 ??? Should it be 0x00? */ - /* DTMF Tone 1 (0B): 11,B3,5A,2C ; 697 Hz */ - /* 12,33,5A,C3 ; 770 Hz */ - /* 13,3C,5B,32 ; 852 Hz */ - /* 1D,1B,5C,CC ; 941 Hz */ - - j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[3] = 0x11; - j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[2] = 0xB3; - j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[1] = 0x5A; - j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[0] = 0x2C; -/* DTMF Tone 2 (0C): 32,32,52,B3 ; 1209 Hz */ - /* EC,1D,52,22 ; 1336 Hz */ - /* AA,AC,51,D2 ; 1477 Hz */ - /* 9B,3B,51,25 ; 1633 Hz */ - j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[3] = 0x32; - j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[2] = 0x32; - j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[1] = 0x52; - j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[0] = 0xB3; -} - -static s16 tone_table[][19] = -{ - { /* f20_50[] 11 */ - 32538, /* A1 = 1.985962 */ - -32325, /* A2 = -0.986511 */ - -343, /* B2 = -0.010493 */ - 0, /* B1 = 0 */ - 343, /* B0 = 0.010493 */ - 32619, /* A1 = 1.990906 */ - -32520, /* A2 = -0.992462 */ - 19179, /* B2 = 0.585327 */ - -19178, /* B1 = -1.170593 */ - 19179, /* B0 = 0.585327 */ - 32723, /* A1 = 1.997314 */ - -32686, /* A2 = -0.997528 */ - 9973, /* B2 = 0.304352 */ - -9955, /* B1 = -0.607605 */ - 9973, /* B0 = 0.304352 */ - 7, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f133_200[] 12 */ - 32072, /* A1 = 1.95752 */ - -31896, /* A2 = -0.973419 */ - -435, /* B2 = -0.013294 */ - 0, /* B1 = 0 */ - 435, /* B0 = 0.013294 */ - 32188, /* A1 = 1.9646 */ - -32400, /* A2 = -0.98877 */ - 15139, /* B2 = 0.462036 */ - -14882, /* B1 = -0.908356 */ - 15139, /* B0 = 0.462036 */ - 32473, /* A1 = 1.981995 */ - -32524, /* A2 = -0.992584 */ - 23200, /* B2 = 0.708008 */ - -23113, /* B1 = -1.410706 */ - 23200, /* B0 = 0.708008 */ - 7, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f300 13 */ - 31769, /* A1 = -1.939026 */ - -32584, /* A2 = 0.994385 */ - -475, /* B2 = -0.014522 */ - 0, /* B1 = 0.000000 */ - 475, /* B0 = 0.014522 */ - 31789, /* A1 = -1.940247 */ - -32679, /* A2 = 0.997284 */ - 17280, /* B2 = 0.527344 */ - -16865, /* B1 = -1.029358 */ - 17280, /* B0 = 0.527344 */ - 31841, /* A1 = -1.943481 */ - -32681, /* A2 = 0.997345 */ - 543, /* B2 = 0.016579 */ - -525, /* B1 = -0.032097 */ - 543, /* B0 = 0.016579 */ - 5, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f300_420[] 14 */ - 30750, /* A1 = 1.876892 */ - -31212, /* A2 = -0.952515 */ - -804, /* B2 = -0.024541 */ - 0, /* B1 = 0 */ - 804, /* B0 = 0.024541 */ - 30686, /* A1 = 1.872925 */ - -32145, /* A2 = -0.980988 */ - 14747, /* B2 = 0.450043 */ - -13703, /* B1 = -0.836395 */ - 14747, /* B0 = 0.450043 */ - 31651, /* A1 = 1.931824 */ - -32321, /* A2 = -0.986389 */ - 24425, /* B2 = 0.745422 */ - -23914, /* B1 = -1.459595 */ - 24427, /* B0 = 0.745483 */ - 7, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f330 15 */ - 31613, /* A1 = -1.929565 */ - -32646, /* A2 = 0.996277 */ - -185, /* B2 = -0.005657 */ - 0, /* B1 = 0.000000 */ - 185, /* B0 = 0.005657 */ - 31620, /* A1 = -1.929932 */ - -32713, /* A2 = 0.998352 */ - 19253, /* B2 = 0.587585 */ - -18566, /* B1 = -1.133179 */ - 19253, /* B0 = 0.587585 */ - 31674, /* A1 = -1.933228 */ - -32715, /* A2 = 0.998413 */ - 2575, /* B2 = 0.078590 */ - -2495, /* B1 = -0.152283 */ - 2575, /* B0 = 0.078590 */ - 5, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f300_425[] 16 */ - 30741, /* A1 = 1.876282 */ - -31475, /* A2 = -0.960541 */ - -703, /* B2 = -0.021484 */ - 0, /* B1 = 0 */ - 703, /* B0 = 0.021484 */ - 30688, /* A1 = 1.873047 */ - -32248, /* A2 = -0.984161 */ - 14542, /* B2 = 0.443787 */ - -13523, /* B1 = -0.825439 */ - 14542, /* B0 = 0.443817 */ - 31494, /* A1 = 1.922302 */ - -32366, /* A2 = -0.987762 */ - 21577, /* B2 = 0.658508 */ - -21013, /* B1 = -1.282532 */ - 21577, /* B0 = 0.658508 */ - 7, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f330_440[] 17 */ - 30627, /* A1 = 1.869324 */ - -31338, /* A2 = -0.95636 */ - -843, /* B2 = -0.025749 */ - 0, /* B1 = 0 */ - 843, /* B0 = 0.025749 */ - 30550, /* A1 = 1.864685 */ - -32221, /* A2 = -0.983337 */ - 13594, /* B2 = 0.414886 */ - -12589, /* B1 = -0.768402 */ - 13594, /* B0 = 0.414886 */ - 31488, /* A1 = 1.921936 */ - -32358, /* A2 = -0.987518 */ - 24684, /* B2 = 0.753296 */ - -24029, /* B1 = -1.466614 */ - 24684, /* B0 = 0.753296 */ - 7, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f340 18 */ - 31546, /* A1 = -1.925476 */ - -32646, /* A2 = 0.996277 */ - -445, /* B2 = -0.013588 */ - 0, /* B1 = 0.000000 */ - 445, /* B0 = 0.013588 */ - 31551, /* A1 = -1.925781 */ - -32713, /* A2 = 0.998352 */ - 23884, /* B2 = 0.728882 */ - -22979, /* B1 = -1.402527 */ - 23884, /* B0 = 0.728882 */ - 31606, /* A1 = -1.929138 */ - -32715, /* A2 = 0.998413 */ - 863, /* B2 = 0.026367 */ - -835, /* B1 = -0.050985 */ - 863, /* B0 = 0.026367 */ - 5, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f350_400[] 19 */ - 31006, /* A1 = 1.892517 */ - -32029, /* A2 = -0.977448 */ - -461, /* B2 = -0.014096 */ - 0, /* B1 = 0 */ - 461, /* B0 = 0.014096 */ - 30999, /* A1 = 1.892029 */ - -32487, /* A2 = -0.991455 */ - 11325, /* B2 = 0.345612 */ - -10682, /* B1 = -0.651978 */ - 11325, /* B0 = 0.345612 */ - 31441, /* A1 = 1.919067 */ - -32526, /* A2 = -0.992615 */ - 24324, /* B2 = 0.74231 */ - -23535, /* B1 = -1.436523 */ - 24324, /* B0 = 0.74231 */ - 7, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f350_440[] */ - 30634, /* A1 = 1.869751 */ - -31533, /* A2 = -0.962341 */ - -680, /* B2 = -0.020782 */ - 0, /* B1 = 0 */ - 680, /* B0 = 0.020782 */ - 30571, /* A1 = 1.865906 */ - -32277, /* A2 = -0.985016 */ - 12894, /* B2 = 0.393524 */ - -11945, /* B1 = -0.729065 */ - 12894, /* B0 = 0.393524 */ - 31367, /* A1 = 1.91449 */ - -32379, /* A2 = -0.988129 */ - 23820, /* B2 = 0.726929 */ - -23104, /* B1 = -1.410217 */ - 23820, /* B0 = 0.726929 */ - 7, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f350_450[] */ - 30552, /* A1 = 1.864807 */ - -31434, /* A2 = -0.95929 */ - -690, /* B2 = -0.021066 */ - 0, /* B1 = 0 */ - 690, /* B0 = 0.021066 */ - 30472, /* A1 = 1.859924 */ - -32248, /* A2 = -0.984161 */ - 13385, /* B2 = 0.408478 */ - -12357, /* B1 = -0.754242 */ - 13385, /* B0 = 0.408478 */ - 31358, /* A1 = 1.914001 */ - -32366, /* A2 = -0.987732 */ - 26488, /* B2 = 0.80835 */ - -25692, /* B1 = -1.568176 */ - 26490, /* B0 = 0.808411 */ - 7, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f360 */ - 31397, /* A1 = -1.916321 */ - -32623, /* A2 = 0.995605 */ - -117, /* B2 = -0.003598 */ - 0, /* B1 = 0.000000 */ - 117, /* B0 = 0.003598 */ - 31403, /* A1 = -1.916687 */ - -32700, /* A2 = 0.997925 */ - 3388, /* B2 = 0.103401 */ - -3240, /* B1 = -0.197784 */ - 3388, /* B0 = 0.103401 */ - 31463, /* A1 = -1.920410 */ - -32702, /* A2 = 0.997986 */ - 13346, /* B2 = 0.407288 */ - -12863, /* B1 = -0.785126 */ - 13346, /* B0 = 0.407288 */ - 5, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f380_420[] */ - 30831, /* A1 = 1.881775 */ - -32064, /* A2 = -0.978546 */ - -367, /* B2 = -0.01122 */ - 0, /* B1 = 0 */ - 367, /* B0 = 0.01122 */ - 30813, /* A1 = 1.880737 */ - -32456, /* A2 = -0.990509 */ - 11068, /* B2 = 0.337769 */ - -10338, /* B1 = -0.631042 */ - 11068, /* B0 = 0.337769 */ - 31214, /* A1 = 1.905212 */ - -32491, /* A2 = -0.991577 */ - 16374, /* B2 = 0.499695 */ - -15781, /* B1 = -0.963196 */ - 16374, /* B0 = 0.499695 */ - 7, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f392 */ - 31152, /* A1 = -1.901428 */ - -32613, /* A2 = 0.995300 */ - -314, /* B2 = -0.009605 */ - 0, /* B1 = 0.000000 */ - 314, /* B0 = 0.009605 */ - 31156, /* A1 = -1.901672 */ - -32694, /* A2 = 0.997742 */ - 28847, /* B2 = 0.880371 */ - -2734, /* B1 = -0.166901 */ - 28847, /* B0 = 0.880371 */ - 31225, /* A1 = -1.905823 */ - -32696, /* A2 = 0.997803 */ - 462, /* B2 = 0.014108 */ - -442, /* B1 = -0.027019 */ - 462, /* B0 = 0.014108 */ - 5, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f400_425[] */ - 30836, /* A1 = 1.882141 */ - -32296, /* A2 = -0.985596 */ - -324, /* B2 = -0.009903 */ - 0, /* B1 = 0 */ - 324, /* B0 = 0.009903 */ - 30825, /* A1 = 1.881409 */ - -32570, /* A2 = -0.993958 */ - 16847, /* B2 = 0.51416 */ - -15792, /* B1 = -0.963898 */ - 16847, /* B0 = 0.51416 */ - 31106, /* A1 = 1.89856 */ - -32584, /* A2 = -0.994415 */ - 9579, /* B2 = 0.292328 */ - -9164, /* B1 = -0.559357 */ - 9579, /* B0 = 0.292328 */ - 7, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f400_440[] */ - 30702, /* A1 = 1.873962 */ - -32134, /* A2 = -0.980682 */ - -517, /* B2 = -0.015793 */ - 0, /* B1 = 0 */ - 517, /* B0 = 0.015793 */ - 30676, /* A1 = 1.872375 */ - -32520, /* A2 = -0.992462 */ - 8144, /* B2 = 0.24855 */ - -7596, /* B1 = -0.463684 */ - 8144, /* B0 = 0.24855 */ - 31084, /* A1 = 1.897217 */ - -32547, /* A2 = -0.993256 */ - 22713, /* B2 = 0.693176 */ - -21734, /* B1 = -1.326599 */ - 22713, /* B0 = 0.693176 */ - 7, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f400_450[] */ - 30613, /* A1 = 1.86853 */ - -32031, /* A2 = -0.977509 */ - -618, /* B2 = -0.018866 */ - 0, /* B1 = 0 */ - 618, /* B0 = 0.018866 */ - 30577, /* A1 = 1.866272 */ - -32491, /* A2 = -0.991577 */ - 9612, /* B2 = 0.293335 */ - -8935, /* B1 = -0.54541 */ - 9612, /* B0 = 0.293335 */ - 31071, /* A1 = 1.896484 */ - -32524, /* A2 = -0.992584 */ - 21596, /* B2 = 0.659058 */ - -20667, /* B1 = -1.261414 */ - 21596, /* B0 = 0.659058 */ - 7, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f420 */ - 30914, /* A1 = -1.886841 */ - -32584, /* A2 = 0.994385 */ - -426, /* B2 = -0.013020 */ - 0, /* B1 = 0.000000 */ - 426, /* B0 = 0.013020 */ - 30914, /* A1 = -1.886841 */ - -32679, /* A2 = 0.997314 */ - 17520, /* B2 = 0.534668 */ - -16471, /* B1 = -1.005310 */ - 17520, /* B0 = 0.534668 */ - 31004, /* A1 = -1.892334 */ - -32683, /* A2 = 0.997406 */ - 819, /* B2 = 0.025023 */ - -780, /* B1 = -0.047619 */ - 819, /* B0 = 0.025023 */ - 5, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, -#if 0 - { /* f425 */ - 30881, /* A1 = -1.884827 */ - -32603, /* A2 = 0.994965 */ - -496, /* B2 = -0.015144 */ - 0, /* B1 = 0.000000 */ - 496, /* B0 = 0.015144 */ - 30880, /* A1 = -1.884766 */ - -32692, /* A2 = 0.997711 */ - 24767, /* B2 = 0.755859 */ - -23290, /* B1 = -1.421509 */ - 24767, /* B0 = 0.755859 */ - 30967, /* A1 = -1.890076 */ - -32694, /* A2 = 0.997772 */ - 728, /* B2 = 0.022232 */ - -691, /* B1 = -0.042194 */ - 728, /* B0 = 0.022232 */ - 5, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, -#else - { - 30850, - -32534, - -504, - 0, - 504, - 30831, - -32669, - 24303, - -22080, - 24303, - 30994, - -32673, - 1905, - -1811, - 1905, - 5, - 129, - 17, - 0xff5 - }, -#endif - { /* f425_450[] */ - 30646, /* A1 = 1.870544 */ - -32327, /* A2 = -0.986572 */ - -287, /* B2 = -0.008769 */ - 0, /* B1 = 0 */ - 287, /* B0 = 0.008769 */ - 30627, /* A1 = 1.869324 */ - -32607, /* A2 = -0.995087 */ - 13269, /* B2 = 0.404968 */ - -12376, /* B1 = -0.755432 */ - 13269, /* B0 = 0.404968 */ - 30924, /* A1 = 1.887512 */ - -32619, /* A2 = -0.995453 */ - 19950, /* B2 = 0.608826 */ - -18940, /* B1 = -1.156006 */ - 19950, /* B0 = 0.608826 */ - 7, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f425_475[] */ - 30396, /* A1 = 1.855225 */ - -32014, /* A2 = -0.97699 */ - -395, /* B2 = -0.012055 */ - 0, /* B1 = 0 */ - 395, /* B0 = 0.012055 */ - 30343, /* A1 = 1.85199 */ - -32482, /* A2 = -0.991302 */ - 17823, /* B2 = 0.543945 */ - -16431, /* B1 = -1.002869 */ - 17823, /* B0 = 0.543945 */ - 30872, /* A1 = 1.884338 */ - -32516, /* A2 = -0.99231 */ - 18124, /* B2 = 0.553101 */ - -17246, /* B1 = -1.052673 */ - 18124, /* B0 = 0.553101 */ - 7, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f435 */ - 30796, /* A1 = -1.879639 */ - -32603, /* A2 = 0.994965 */ - -254, /* B2 = -0.007762 */ - 0, /* B1 = 0.000000 */ - 254, /* B0 = 0.007762 */ - 30793, /* A1 = -1.879456 */ - -32692, /* A2 = 0.997711 */ - 18934, /* B2 = 0.577820 */ - -17751, /* B1 = -1.083496 */ - 18934, /* B0 = 0.577820 */ - 30882, /* A1 = -1.884888 */ - -32694, /* A2 = 0.997772 */ - 1858, /* B2 = 0.056713 */ - -1758, /* B1 = -0.107357 */ - 1858, /* B0 = 0.056713 */ - 5, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f440_450[] */ - 30641, /* A1 = 1.870239 */ - -32458, /* A2 = -0.99057 */ - -155, /* B2 = -0.004735 */ - 0, /* B1 = 0 */ - 155, /* B0 = 0.004735 */ - 30631, /* A1 = 1.869568 */ - -32630, /* A2 = -0.995789 */ - 11453, /* B2 = 0.349548 */ - -10666, /* B1 = -0.651001 */ - 11453, /* B0 = 0.349548 */ - 30810, /* A1 = 1.880554 */ - -32634, /* A2 = -0.995941 */ - 12237, /* B2 = 0.373474 */ - -11588, /* B1 = -0.707336 */ - 12237, /* B0 = 0.373474 */ - 7, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f440_480[] */ - 30367, /* A1 = 1.853455 */ - -32147, /* A2 = -0.981079 */ - -495, /* B2 = -0.015113 */ - 0, /* B1 = 0 */ - 495, /* B0 = 0.015113 */ - 30322, /* A1 = 1.850769 */ - -32543, /* A2 = -0.993134 */ - 10031, /* B2 = 0.306152 */ - -9252, /* B1 = -0.564728 */ - 10031, /* B0 = 0.306152 */ - 30770, /* A1 = 1.878052 */ - -32563, /* A2 = -0.993774 */ - 22674, /* B2 = 0.691956 */ - -21465, /* B1 = -1.31012 */ - 22674, /* B0 = 0.691956 */ - 7, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f445 */ - 30709, /* A1 = -1.874329 */ - -32603, /* A2 = 0.994965 */ - -83, /* B2 = -0.002545 */ - 0, /* B1 = 0.000000 */ - 83, /* B0 = 0.002545 */ - 30704, /* A1 = -1.874084 */ - -32692, /* A2 = 0.997711 */ - 10641, /* B2 = 0.324738 */ - -9947, /* B1 = -0.607147 */ - 10641, /* B0 = 0.324738 */ - 30796, /* A1 = -1.879639 */ - -32694, /* A2 = 0.997772 */ - 10079, /* B2 = 0.307587 */ - 9513, /* B1 = 0.580688 */ - 10079, /* B0 = 0.307587 */ - 5, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f450 */ - 30664, /* A1 = -1.871643 */ - -32603, /* A2 = 0.994965 */ - -164, /* B2 = -0.005029 */ - 0, /* B1 = 0.000000 */ - 164, /* B0 = 0.005029 */ - 30661, /* A1 = -1.871399 */ - -32692, /* A2 = 0.997711 */ - 15294, /* B2 = 0.466736 */ - -14275, /* B1 = -0.871307 */ - 15294, /* B0 = 0.466736 */ - 30751, /* A1 = -1.876953 */ - -32694, /* A2 = 0.997772 */ - 3548, /* B2 = 0.108284 */ - -3344, /* B1 = -0.204155 */ - 3548, /* B0 = 0.108284 */ - 5, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f452 */ - 30653, /* A1 = -1.870911 */ - -32615, /* A2 = 0.995361 */ - -209, /* B2 = -0.006382 */ - 0, /* B1 = 0.000000 */ - 209, /* B0 = 0.006382 */ - 30647, /* A1 = -1.870605 */ - -32702, /* A2 = 0.997986 */ - 18971, /* B2 = 0.578979 */ - -17716, /* B1 = -1.081299 */ - 18971, /* B0 = 0.578979 */ - 30738, /* A1 = -1.876099 */ - -32702, /* A2 = 0.998016 */ - 2967, /* B2 = 0.090561 */ - -2793, /* B1 = -0.170502 */ - 2967, /* B0 = 0.090561 */ - 5, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f475 */ - 30437, /* A1 = -1.857727 */ - -32603, /* A2 = 0.994965 */ - -264, /* B2 = -0.008062 */ - 0, /* B1 = 0.000000 */ - 264, /* B0 = 0.008062 */ - 30430, /* A1 = -1.857300 */ - -32692, /* A2 = 0.997711 */ - 21681, /* B2 = 0.661682 */ - -20082, /* B1 = -1.225708 */ - 21681, /* B0 = 0.661682 */ - 30526, /* A1 = -1.863220 */ - -32694, /* A2 = 0.997742 */ - 1559, /* B2 = 0.047600 */ - -1459, /* B1 = -0.089096 */ - 1559, /* B0 = 0.047600 */ - 5, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f480_620[] */ - 28975, /* A1 = 1.768494 */ - -30955, /* A2 = -0.944672 */ - -1026, /* B2 = -0.03133 */ - 0, /* B1 = 0 */ - 1026, /* B0 = 0.03133 */ - 28613, /* A1 = 1.746399 */ - -32089, /* A2 = -0.979309 */ - 14214, /* B2 = 0.433807 */ - -12202, /* B1 = -0.744812 */ - 14214, /* B0 = 0.433807 */ - 30243, /* A1 = 1.845947 */ - -32238, /* A2 = -0.983856 */ - 24825, /* B2 = 0.757629 */ - -23402, /* B1 = -1.428345 */ - 24825, /* B0 = 0.757629 */ - 7, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f494 */ - 30257, /* A1 = -1.846741 */ - -32605, /* A2 = 0.995056 */ - -249, /* B2 = -0.007625 */ - 0, /* B1 = 0.000000 */ - 249, /* B0 = 0.007625 */ - 30247, /* A1 = -1.846191 */ - -32694, /* A2 = 0.997772 */ - 18088, /* B2 = 0.552002 */ - -16652, /* B1 = -1.016418 */ - 18088, /* B0 = 0.552002 */ - 30348, /* A1 = -1.852295 */ - -32696, /* A2 = 0.997803 */ - 2099, /* B2 = 0.064064 */ - -1953, /* B1 = -0.119202 */ - 2099, /* B0 = 0.064064 */ - 5, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f500 */ - 30202, /* A1 = -1.843431 */ - -32624, /* A2 = 0.995622 */ - -413, /* B2 = -0.012622 */ - 0, /* B1 = 0.000000 */ - 413, /* B0 = 0.012622 */ - 30191, /* A1 = -1.842721 */ - -32714, /* A2 = 0.998364 */ - 25954, /* B2 = 0.792057 */ - -23890, /* B1 = -1.458131 */ - 25954, /* B0 = 0.792057 */ - 30296, /* A1 = -1.849172 */ - -32715, /* A2 = 0.998397 */ - 2007, /* B2 = 0.061264 */ - -1860, /* B1 = -0.113568 */ - 2007, /* B0 = 0.061264 */ - 5, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f520 */ - 30001, /* A1 = -1.831116 */ - -32613, /* A2 = 0.995270 */ - -155, /* B2 = -0.004750 */ - 0, /* B1 = 0.000000 */ - 155, /* B0 = 0.004750 */ - 29985, /* A1 = -1.830200 */ - -32710, /* A2 = 0.998260 */ - 6584, /* B2 = 0.200928 */ - -6018, /* B1 = -0.367355 */ - 6584, /* B0 = 0.200928 */ - 30105, /* A1 = -1.837524 */ - -32712, /* A2 = 0.998291 */ - 23812, /* B2 = 0.726685 */ - -21936, /* B1 = -1.338928 */ - 23812, /* B0 = 0.726685 */ - 5, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f523 */ - 29964, /* A1 = -1.828918 */ - -32601, /* A2 = 0.994904 */ - -101, /* B2 = -0.003110 */ - 0, /* B1 = 0.000000 */ - 101, /* B0 = 0.003110 */ - 29949, /* A1 = -1.827942 */ - -32700, /* A2 = 0.997925 */ - 11041, /* B2 = 0.336975 */ - -10075, /* B1 = -0.614960 */ - 11041, /* B0 = 0.336975 */ - 30070, /* A1 = -1.835388 */ - -32702, /* A2 = 0.997986 */ - 16762, /* B2 = 0.511536 */ - -15437, /* B1 = -0.942230 */ - 16762, /* B0 = 0.511536 */ - 5, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f525 */ - 29936, /* A1 = -1.827209 */ - -32584, /* A2 = 0.994415 */ - -91, /* B2 = -0.002806 */ - 0, /* B1 = 0.000000 */ - 91, /* B0 = 0.002806 */ - 29921, /* A1 = -1.826233 */ - -32688, /* A2 = 0.997559 */ - 11449, /* B2 = 0.349396 */ - -10426, /* B1 = -0.636383 */ - 11449, /* B0 = 0.349396 */ - 30045, /* A1 = -1.833862 */ - -32688, /* A2 = 0.997589 */ - 13055, /* B2 = 0.398407 */ - -12028, /* B1 = -0.734161 */ - 13055, /* B0 = 0.398407 */ - 5, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f540_660[] */ - 28499, /* A1 = 1.739441 */ - -31129, /* A2 = -0.949982 */ - -849, /* B2 = -0.025922 */ - 0, /* B1 = 0 */ - 849, /* B0 = 0.025922 */ - 28128, /* A1 = 1.716797 */ - -32130, /* A2 = -0.98056 */ - 14556, /* B2 = 0.444214 */ - -12251, /* B1 = -0.747772 */ - 14556, /* B0 = 0.444244 */ - 29667, /* A1 = 1.81073 */ - -32244, /* A2 = -0.984039 */ - 23038, /* B2 = 0.703064 */ - -21358, /* B1 = -1.303589 */ - 23040, /* B0 = 0.703125 */ - 7, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f587 */ - 29271, /* A1 = -1.786560 */ - -32599, /* A2 = 0.994873 */ - -490, /* B2 = -0.014957 */ - 0, /* B1 = 0.000000 */ - 490, /* B0 = 0.014957 */ - 29246, /* A1 = -1.785095 */ - -32700, /* A2 = 0.997925 */ - 28961, /* B2 = 0.883850 */ - -25796, /* B1 = -1.574463 */ - 28961, /* B0 = 0.883850 */ - 29383, /* A1 = -1.793396 */ - -32700, /* A2 = 0.997955 */ - 1299, /* B2 = 0.039650 */ - -1169, /* B1 = -0.071396 */ - 1299, /* B0 = 0.039650 */ - 5, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f590 */ - 29230, /* A1 = -1.784058 */ - -32584, /* A2 = 0.994415 */ - -418, /* B2 = -0.012757 */ - 0, /* B1 = 0.000000 */ - 418, /* B0 = 0.012757 */ - 29206, /* A1 = -1.782593 */ - -32688, /* A2 = 0.997559 */ - 36556, /* B2 = 1.115601 */ - -32478, /* B1 = -1.982300 */ - 36556, /* B0 = 1.115601 */ - 29345, /* A1 = -1.791077 */ - -32688, /* A2 = 0.997589 */ - 897, /* B2 = 0.027397 */ - -808, /* B1 = -0.049334 */ - 897, /* B0 = 0.027397 */ - 5, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f600 */ - 29116, /* A1 = -1.777100 */ - -32603, /* A2 = 0.994965 */ - -165, /* B2 = -0.005039 */ - 0, /* B1 = 0.000000 */ - 165, /* B0 = 0.005039 */ - 29089, /* A1 = -1.775452 */ - -32708, /* A2 = 0.998199 */ - 6963, /* B2 = 0.212494 */ - -6172, /* B1 = -0.376770 */ - 6963, /* B0 = 0.212494 */ - 29237, /* A1 = -1.784485 */ - -32710, /* A2 = 0.998230 */ - 24197, /* B2 = 0.738464 */ - -21657, /* B1 = -1.321899 */ - 24197, /* B0 = 0.738464 */ - 5, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f660 */ - 28376, /* A1 = -1.731934 */ - -32567, /* A2 = 0.993896 */ - -363, /* B2 = -0.011102 */ - 0, /* B1 = 0.000000 */ - 363, /* B0 = 0.011102 */ - 28337, /* A1 = -1.729614 */ - -32683, /* A2 = 0.997434 */ - 21766, /* B2 = 0.664246 */ - -18761, /* B1 = -1.145081 */ - 21766, /* B0 = 0.664246 */ - 28513, /* A1 = -1.740356 */ - -32686, /* A2 = 0.997498 */ - 2509, /* B2 = 0.076584 */ - -2196, /* B1 = -0.134041 */ - 2509, /* B0 = 0.076584 */ - 5, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f700 */ - 27844, /* A1 = -1.699463 */ - -32563, /* A2 = 0.993744 */ - -366, /* B2 = -0.011187 */ - 0, /* B1 = 0.000000 */ - 366, /* B0 = 0.011187 */ - 27797, /* A1 = -1.696655 */ - -32686, /* A2 = 0.997498 */ - 22748, /* B2 = 0.694214 */ - -19235, /* B1 = -1.174072 */ - 22748, /* B0 = 0.694214 */ - 27995, /* A1 = -1.708740 */ - -32688, /* A2 = 0.997559 */ - 2964, /* B2 = 0.090477 */ - -2546, /* B1 = -0.155449 */ - 2964, /* B0 = 0.090477 */ - 5, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f740 */ - 27297, /* A1 = -1.666077 */ - -32551, /* A2 = 0.993408 */ - -345, /* B2 = -0.010540 */ - 0, /* B1 = 0.000000 */ - 345, /* B0 = 0.010540 */ - 27240, /* A1 = -1.662598 */ - -32683, /* A2 = 0.997406 */ - 22560, /* B2 = 0.688477 */ - -18688, /* B1 = -1.140625 */ - 22560, /* B0 = 0.688477 */ - 27461, /* A1 = -1.676147 */ - -32684, /* A2 = 0.997467 */ - 3541, /* B2 = 0.108086 */ - -2985, /* B1 = -0.182220 */ - 3541, /* B0 = 0.108086 */ - 5, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f750 */ - 27155, /* A1 = -1.657410 */ - -32551, /* A2 = 0.993408 */ - -462, /* B2 = -0.014117 */ - 0, /* B1 = 0.000000 */ - 462, /* B0 = 0.014117 */ - 27097, /* A1 = -1.653870 */ - -32683, /* A2 = 0.997406 */ - 32495, /* B2 = 0.991699 */ - -26776, /* B1 = -1.634338 */ - 32495, /* B0 = 0.991699 */ - 27321, /* A1 = -1.667542 */ - -32684, /* A2 = 0.997467 */ - 1835, /* B2 = 0.056007 */ - -1539, /* B1 = -0.093948 */ - 1835, /* B0 = 0.056007 */ - 5, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f750_1450[] */ - 19298, /* A1 = 1.177917 */ - -24471, /* A2 = -0.746796 */ - -4152, /* B2 = -0.126709 */ - 0, /* B1 = 0 */ - 4152, /* B0 = 0.126709 */ - 12902, /* A1 = 0.787476 */ - -29091, /* A2 = -0.887817 */ - 12491, /* B2 = 0.38121 */ - -1794, /* B1 = -0.109528 */ - 12494, /* B0 = 0.381317 */ - 26291, /* A1 = 1.604736 */ - -30470, /* A2 = -0.929901 */ - 28859, /* B2 = 0.880737 */ - -26084, /* B1 = -1.592102 */ - 28861, /* B0 = 0.880798 */ - 7, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f770 */ - 26867, /* A1 = -1.639832 */ - -32551, /* A2 = 0.993408 */ - -123, /* B2 = -0.003755 */ - 0, /* B1 = 0.000000 */ - 123, /* B0 = 0.003755 */ - 26805, /* A1 = -1.636108 */ - -32683, /* A2 = 0.997406 */ - 17297, /* B2 = 0.527863 */ - -14096, /* B1 = -0.860382 */ - 17297, /* B0 = 0.527863 */ - 27034, /* A1 = -1.650085 */ - -32684, /* A2 = 0.997467 */ - 12958, /* B2 = 0.395477 */ - -10756, /* B1 = -0.656525 */ - 12958, /* B0 = 0.395477 */ - 5, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f800 */ - 26413, /* A1 = -1.612122 */ - -32547, /* A2 = 0.993286 */ - -223, /* B2 = -0.006825 */ - 0, /* B1 = 0.000000 */ - 223, /* B0 = 0.006825 */ - 26342, /* A1 = -1.607849 */ - -32686, /* A2 = 0.997498 */ - 6391, /* B2 = 0.195053 */ - -5120, /* B1 = -0.312531 */ - 6391, /* B0 = 0.195053 */ - 26593, /* A1 = -1.623108 */ - -32688, /* A2 = 0.997559 */ - 23681, /* B2 = 0.722717 */ - -19328, /* B1 = -1.179688 */ - 23681, /* B0 = 0.722717 */ - 5, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f816 */ - 26168, /* A1 = -1.597209 */ - -32528, /* A2 = 0.992706 */ - -235, /* B2 = -0.007182 */ - 0, /* B1 = 0.000000 */ - 235, /* B0 = 0.007182 */ - 26092, /* A1 = -1.592590 */ - -32675, /* A2 = 0.997192 */ - 20823, /* B2 = 0.635498 */ - -16510, /* B1 = -1.007751 */ - 20823, /* B0 = 0.635498 */ - 26363, /* A1 = -1.609070 */ - -32677, /* A2 = 0.997253 */ - 6739, /* B2 = 0.205688 */ - -5459, /* B1 = -0.333206 */ - 6739, /* B0 = 0.205688 */ - 5, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f850 */ - 25641, /* A1 = -1.565063 */ - -32536, /* A2 = 0.992950 */ - -121, /* B2 = -0.003707 */ - 0, /* B1 = 0.000000 */ - 121, /* B0 = 0.003707 */ - 25560, /* A1 = -1.560059 */ - -32684, /* A2 = 0.997437 */ - 18341, /* B2 = 0.559753 */ - -14252, /* B1 = -0.869904 */ - 18341, /* B0 = 0.559753 */ - 25837, /* A1 = -1.577026 */ - -32684, /* A2 = 0.997467 */ - 16679, /* B2 = 0.509003 */ - -13232, /* B1 = -0.807648 */ - 16679, /* B0 = 0.509003 */ - 5, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f857_1645[] */ - 16415, /* A1 = 1.001953 */ - -23669, /* A2 = -0.722321 */ - -4549, /* B2 = -0.138847 */ - 0, /* B1 = 0 */ - 4549, /* B0 = 0.138847 */ - 8456, /* A1 = 0.516174 */ - -28996, /* A2 = -0.884918 */ - 13753, /* B2 = 0.419724 */ - -12, /* B1 = -0.000763 */ - 13757, /* B0 = 0.419846 */ - 24632, /* A1 = 1.503418 */ - -30271, /* A2 = -0.923828 */ - 29070, /* B2 = 0.887146 */ - -25265, /* B1 = -1.542114 */ - 29073, /* B0 = 0.887268 */ - 7, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f900 */ - 24806, /* A1 = -1.514099 */ - -32501, /* A2 = 0.991852 */ - -326, /* B2 = -0.009969 */ - 0, /* B1 = 0.000000 */ - 326, /* B0 = 0.009969 */ - 24709, /* A1 = -1.508118 */ - -32659, /* A2 = 0.996674 */ - 20277, /* B2 = 0.618835 */ - -15182, /* B1 = -0.926636 */ - 20277, /* B0 = 0.618835 */ - 25022, /* A1 = -1.527222 */ - -32661, /* A2 = 0.996735 */ - 4320, /* B2 = 0.131836 */ - -3331, /* B1 = -0.203339 */ - 4320, /* B0 = 0.131836 */ - 5, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f900_1300[] */ - 19776, /* A1 = 1.207092 */ - -27437, /* A2 = -0.837341 */ - -2666, /* B2 = -0.081371 */ - 0, /* B1 = 0 */ - 2666, /* B0 = 0.081371 */ - 16302, /* A1 = 0.995026 */ - -30354, /* A2 = -0.926361 */ - 10389, /* B2 = 0.317062 */ - -3327, /* B1 = -0.203064 */ - 10389, /* B0 = 0.317062 */ - 24299, /* A1 = 1.483154 */ - -30930, /* A2 = -0.943909 */ - 25016, /* B2 = 0.763428 */ - -21171, /* B1 = -1.292236 */ - 25016, /* B0 = 0.763428 */ - 7, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f935_1215[] */ - 20554, /* A1 = 1.254517 */ - -28764, /* A2 = -0.877838 */ - -2048, /* B2 = -0.062515 */ - 0, /* B1 = 0 */ - 2048, /* B0 = 0.062515 */ - 18209, /* A1 = 1.11145 */ - -30951, /* A2 = -0.94458 */ - 9390, /* B2 = 0.286575 */ - -3955, /* B1 = -0.241455 */ - 9390, /* B0 = 0.286575 */ - 23902, /* A1 = 1.458923 */ - -31286, /* A2 = -0.954803 */ - 23252, /* B2 = 0.709595 */ - -19132, /* B1 = -1.167725 */ - 23252, /* B0 = 0.709595 */ - 7, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f941_1477[] */ - 17543, /* A1 = 1.07074 */ - -26220, /* A2 = -0.800201 */ - -3298, /* B2 = -0.100647 */ - 0, /* B1 = 0 */ - 3298, /* B0 = 0.100647 */ - 12423, /* A1 = 0.75827 */ - -30036, /* A2 = -0.916626 */ - 12651, /* B2 = 0.386078 */ - -2444, /* B1 = -0.14917 */ - 12653, /* B0 = 0.386154 */ - 23518, /* A1 = 1.435425 */ - -30745, /* A2 = -0.938293 */ - 27282, /* B2 = 0.832581 */ - -22529, /* B1 = -1.375122 */ - 27286, /* B0 = 0.832703 */ - 7, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f942 */ - 24104, /* A1 = -1.471252 */ - -32507, /* A2 = 0.992065 */ - -351, /* B2 = -0.010722 */ - 0, /* B1 = 0.000000 */ - 351, /* B0 = 0.010722 */ - 23996, /* A1 = -1.464600 */ - -32671, /* A2 = 0.997040 */ - 22848, /* B2 = 0.697266 */ - -16639, /* B1 = -1.015564 */ - 22848, /* B0 = 0.697266 */ - 24332, /* A1 = -1.485168 */ - -32673, /* A2 = 0.997101 */ - 4906, /* B2 = 0.149727 */ - -3672, /* B1 = -0.224174 */ - 4906, /* B0 = 0.149727 */ - 5, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f950 */ - 23967, /* A1 = -1.462830 */ - -32507, /* A2 = 0.992065 */ - -518, /* B2 = -0.015821 */ - 0, /* B1 = 0.000000 */ - 518, /* B0 = 0.015821 */ - 23856, /* A1 = -1.456055 */ - -32671, /* A2 = 0.997040 */ - 26287, /* B2 = 0.802246 */ - -19031, /* B1 = -1.161560 */ - 26287, /* B0 = 0.802246 */ - 24195, /* A1 = -1.476746 */ - -32673, /* A2 = 0.997101 */ - 2890, /* B2 = 0.088196 */ - -2151, /* B1 = -0.131317 */ - 2890, /* B0 = 0.088196 */ - 5, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f950_1400[] */ - 18294, /* A1 = 1.116638 */ - -26962, /* A2 = -0.822845 */ - -2914, /* B2 = -0.088936 */ - 0, /* B1 = 0 */ - 2914, /* B0 = 0.088936 */ - 14119, /* A1 = 0.861786 */ - -30227, /* A2 = -0.922455 */ - 11466, /* B2 = 0.349945 */ - -2833, /* B1 = -0.172943 */ - 11466, /* B0 = 0.349945 */ - 23431, /* A1 = 1.430115 */ - -30828, /* A2 = -0.940796 */ - 25331, /* B2 = 0.773071 */ - -20911, /* B1 = -1.276367 */ - 25331, /* B0 = 0.773071 */ - 7, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f975 */ - 23521, /* A1 = -1.435608 */ - -32489, /* A2 = 0.991516 */ - -193, /* B2 = -0.005915 */ - 0, /* B1 = 0.000000 */ - 193, /* B0 = 0.005915 */ - 23404, /* A1 = -1.428467 */ - -32655, /* A2 = 0.996582 */ - 17740, /* B2 = 0.541412 */ - -12567, /* B1 = -0.767029 */ - 17740, /* B0 = 0.541412 */ - 23753, /* A1 = -1.449829 */ - -32657, /* A2 = 0.996613 */ - 9090, /* B2 = 0.277405 */ - -6662, /* B1 = -0.406647 */ - 9090, /* B0 = 0.277405 */ - 5, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f1000 */ - 23071, /* A1 = -1.408203 */ - -32489, /* A2 = 0.991516 */ - -293, /* B2 = -0.008965 */ - 0, /* B1 = 0.000000 */ - 293, /* B0 = 0.008965 */ - 22951, /* A1 = -1.400818 */ - -32655, /* A2 = 0.996582 */ - 5689, /* B2 = 0.173645 */ - -3951, /* B1 = -0.241150 */ - 5689, /* B0 = 0.173645 */ - 23307, /* A1 = -1.422607 */ - -32657, /* A2 = 0.996613 */ - 18692, /* B2 = 0.570435 */ - -13447, /* B1 = -0.820770 */ - 18692, /* B0 = 0.570435 */ - 5, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f1020 */ - 22701, /* A1 = -1.385620 */ - -32474, /* A2 = 0.991058 */ - -292, /* B2 = -0.008933 */ - 0, /*163840 , B1 = 10.000000 */ - 292, /* B0 = 0.008933 */ - 22564, /* A1 = -1.377258 */ - -32655, /* A2 = 0.996552 */ - 20756, /* B2 = 0.633423 */ - -14176, /* B1 = -0.865295 */ - 20756, /* B0 = 0.633423 */ - 22960, /* A1 = -1.401428 */ - -32657, /* A2 = 0.996613 */ - 6520, /* B2 = 0.198990 */ - -4619, /* B1 = -0.281937 */ - 6520, /* B0 = 0.198990 */ - 5, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f1050 */ - 22142, /* A1 = -1.351501 */ - -32474, /* A2 = 0.991058 */ - -147, /* B2 = -0.004493 */ - 0, /* B1 = 0.000000 */ - 147, /* B0 = 0.004493 */ - 22000, /* A1 = -1.342834 */ - -32655, /* A2 = 0.996552 */ - 15379, /* B2 = 0.469360 */ - -10237, /* B1 = -0.624847 */ - 15379, /* B0 = 0.469360 */ - 22406, /* A1 = -1.367554 */ - -32657, /* A2 = 0.996613 */ - 17491, /* B2 = 0.533783 */ - -12096, /* B1 = -0.738312 */ - 17491, /* B0 = 0.533783 */ - 5, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f1100_1750[] */ - 12973, /* A1 = 0.79184 */ - -24916, /* A2 = -0.760376 */ - 6655, /* B2 = 0.203102 */ - 367, /* B1 = 0.0224 */ - 6657, /* B0 = 0.203171 */ - 5915, /* A1 = 0.361053 */ - -29560, /* A2 = -0.90213 */ - -7777, /* B2 = -0.23735 */ - 0, /* B1 = 0 */ - 7777, /* B0 = 0.23735 */ - 20510, /* A1 = 1.251892 */ - -30260, /* A2 = -0.923462 */ - 26662, /* B2 = 0.81366 */ - -20573, /* B1 = -1.255737 */ - 26668, /* B0 = 0.813843 */ - 7, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f1140 */ - 20392, /* A1 = -1.244629 */ - -32460, /* A2 = 0.990601 */ - -270, /* B2 = -0.008240 */ - 0, /* B1 = 0.000000 */ - 270, /* B0 = 0.008240 */ - 20218, /* A1 = -1.234009 */ - -32655, /* A2 = 0.996582 */ - 21337, /* B2 = 0.651154 */ - -13044, /* B1 = -0.796143 */ - 21337, /* B0 = 0.651154 */ - 20684, /* A1 = -1.262512 */ - -32657, /* A2 = 0.996643 */ - 8572, /* B2 = 0.261612 */ - -5476, /* B1 = -0.334244 */ - 8572, /* B0 = 0.261612 */ - 5, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f1200 */ - 19159, /* A1 = -1.169373 */ - -32456, /* A2 = 0.990509 */ - -335, /* B2 = -0.010252 */ - 0, /* B1 = 0.000000 */ - 335, /* B0 = 0.010252 */ - 18966, /* A1 = -1.157593 */ - -32661, /* A2 = 0.996735 */ - 6802, /* B2 = 0.207588 */ - -3900, /* B1 = -0.238098 */ - 6802, /* B0 = 0.207588 */ - 19467, /* A1 = -1.188232 */ - -32661, /* A2 = 0.996765 */ - 25035, /* B2 = 0.764008 */ - -15049, /* B1 = -0.918579 */ - 25035, /* B0 = 0.764008 */ - 5, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f1209 */ - 18976, /* A1 = -1.158264 */ - -32439, /* A2 = 0.989990 */ - -183, /* B2 = -0.005588 */ - 0, /* B1 = 0.000000 */ - 183, /* B0 = 0.005588 */ - 18774, /* A1 = -1.145874 */ - -32650, /* A2 = 0.996429 */ - 15468, /* B2 = 0.472076 */ - -8768, /* B1 = -0.535217 */ - 15468, /* B0 = 0.472076 */ - 19300, /* A1 = -1.177979 */ - -32652, /* A2 = 0.996490 */ - 19840, /* B2 = 0.605499 */ - -11842, /* B1 = -0.722809 */ - 19840, /* B0 = 0.605499 */ - 5, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f1330 */ - 16357, /* A1 = -0.998413 */ - -32368, /* A2 = 0.987793 */ - -217, /* B2 = -0.006652 */ - 0, /* B1 = 0.000000 */ - 217, /* B0 = 0.006652 */ - 16107, /* A1 = -0.983126 */ - -32601, /* A2 = 0.994904 */ - 11602, /* B2 = 0.354065 */ - -5555, /* B1 = -0.339111 */ - 11602, /* B0 = 0.354065 */ - 16722, /* A1 = -1.020630 */ - -32603, /* A2 = 0.994965 */ - 15574, /* B2 = 0.475311 */ - -8176, /* B1 = -0.499069 */ - 15574, /* B0 = 0.475311 */ - 5, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f1336 */ - 16234, /* A1 = -0.990875 */ - 32404, /* A2 = -0.988922 */ - -193, /* B2 = -0.005908 */ - 0, /* B1 = 0.000000 */ - 193, /* B0 = 0.005908 */ - 15986, /* A1 = -0.975769 */ - -32632, /* A2 = 0.995880 */ - 18051, /* B2 = 0.550903 */ - -8658, /* B1 = -0.528473 */ - 18051, /* B0 = 0.550903 */ - 16591, /* A1 = -1.012695 */ - -32634, /* A2 = 0.995941 */ - 15736, /* B2 = 0.480240 */ - -8125, /* B1 = -0.495926 */ - 15736, /* B0 = 0.480240 */ - 5, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f1366 */ - 15564, /* A1 = -0.949982 */ - -32404, /* A2 = 0.988922 */ - -269, /* B2 = -0.008216 */ - 0, /* B1 = 0.000000 */ - 269, /* B0 = 0.008216 */ - 15310, /* A1 = -0.934479 */ - -32632, /* A2 = 0.995880 */ - 10815, /* B2 = 0.330063 */ - -4962, /* B1 = -0.302887 */ - 10815, /* B0 = 0.330063 */ - 15924, /* A1 = -0.971924 */ - -32634, /* A2 = 0.995941 */ - 18880, /* B2 = 0.576172 */ - -9364, /* B1 = -0.571594 */ - 18880, /* B0 = 0.576172 */ - 5, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f1380 */ - 15247, /* A1 = -0.930603 */ - -32397, /* A2 = 0.988708 */ - -244, /* B2 = -0.007451 */ - 0, /* B1 = 0.000000 */ - 244, /* B0 = 0.007451 */ - 14989, /* A1 = -0.914886 */ - -32627, /* A2 = 0.995697 */ - 18961, /* B2 = 0.578644 */ - -8498, /* B1 = -0.518707 */ - 18961, /* B0 = 0.578644 */ - 15608, /* A1 = -0.952667 */ - -32628, /* A2 = 0.995758 */ - 11145, /* B2 = 0.340134 */ - -5430, /* B1 = -0.331467 */ - 11145, /* B0 = 0.340134 */ - 5, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f1400 */ - 14780, /* A1 = -0.902130 */ - -32393, /* A2 = 0.988586 */ - -396, /* B2 = -0.012086 */ - 0, /* B1 = 0.000000 */ - 396, /* B0 = 0.012086 */ - 14510, /* A1 = -0.885651 */ - -32630, /* A2 = 0.995819 */ - 6326, /* B2 = 0.193069 */ - -2747, /* B1 = -0.167671 */ - 6326, /* B0 = 0.193069 */ - 15154, /* A1 = -0.924957 */ - -32632, /* A2 = 0.995850 */ - 23235, /* B2 = 0.709076 */ - -10983, /* B1 = -0.670380 */ - 23235, /* B0 = 0.709076 */ - 5, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f1477 */ - 13005, /* A1 = -0.793793 */ - -32368, /* A2 = 0.987823 */ - -500, /* B2 = -0.015265 */ - 0, /* B1 = 0.000000 */ - 500, /* B0 = 0.015265 */ - 12708, /* A1 = -0.775665 */ - -32615, /* A2 = 0.995331 */ - 11420, /* B2 = 0.348526 */ - -4306, /* B1 = -0.262833 */ - 11420, /* B0 = 0.348526 */ - 13397, /* A1 = -0.817688 */ - -32615, /* A2 = 0.995361 */ - 9454, /* B2 = 0.288528 */ - -3981, /* B1 = -0.243027 */ - 9454, /* B0 = 0.288528 */ - 5, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f1600 */ - 10046, /* A1 = -0.613190 */ - -32331, /* A2 = 0.986694 */ - -455, /* B2 = -0.013915 */ - 0, /* B1 = 0.000000 */ - 455, /* B0 = 0.013915 */ - 9694, /* A1 = -0.591705 */ - -32601, /* A2 = 0.994934 */ - 6023, /* B2 = 0.183815 */ - -1708, /* B1 = -0.104279 */ - 6023, /* B0 = 0.183815 */ - 10478, /* A1 = -0.639587 */ - -32603, /* A2 = 0.994965 */ - 22031, /* B2 = 0.672333 */ - -7342, /* B1 = -0.448151 */ - 22031, /* B0 = 0.672333 */ - 5, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f1633_1638[] */ - 9181, /* A1 = 0.560394 */ - -32256, /* A2 = -0.984375 */ - -556, /* B2 = -0.016975 */ - 0, /* B1 = 0 */ - 556, /* B0 = 0.016975 */ - 8757, /* A1 = 0.534515 */ - -32574, /* A2 = -0.99408 */ - 8443, /* B2 = 0.25769 */ - -2135, /* B1 = -0.130341 */ - 8443, /* B0 = 0.25769 */ - 9691, /* A1 = 0.591522 */ - -32574, /* A2 = -0.99411 */ - 15446, /* B2 = 0.471375 */ - -4809, /* B1 = -0.293579 */ - 15446, /* B0 = 0.471375 */ - 7, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f1800 */ - 5076, /* A1 = -0.309875 */ - -32304, /* A2 = 0.985840 */ - -508, /* B2 = -0.015503 */ - 0, /* B1 = 0.000000 */ - 508, /* B0 = 0.015503 */ - 4646, /* A1 = -0.283600 */ - -32605, /* A2 = 0.995026 */ - 6742, /* B2 = 0.205780 */ - -878, /* B1 = -0.053635 */ - 6742, /* B0 = 0.205780 */ - 5552, /* A1 = -0.338928 */ - -32605, /* A2 = 0.995056 */ - 23667, /* B2 = 0.722260 */ - -4297, /* B1 = -0.262329 */ - 23667, /* B0 = 0.722260 */ - 5, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, - { /* f1860 */ - 3569, /* A1 = -0.217865 */ - -32292, /* A2 = 0.985504 */ - -239, /* B2 = -0.007322 */ - 0, /* B1 = 0.000000 */ - 239, /* B0 = 0.007322 */ - 3117, /* A1 = -0.190277 */ - -32603, /* A2 = 0.994965 */ - 18658, /* B2 = 0.569427 */ - -1557, /* B1 = -0.095032 */ - 18658, /* B0 = 0.569427 */ - 4054, /* A1 = -0.247437 */ - -32603, /* A2 = 0.994965 */ - 18886, /* B2 = 0.576385 */ - -2566, /* B1 = -0.156647 */ - 18886, /* B0 = 0.576385 */ - 5, /* Internal filter scaling */ - 159, /* Minimum in-band energy threshold */ - 21, /* 21/32 in-band to broad-band ratio */ - 0x0FF5 /* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */ - }, -}; -static int ixj_init_filter(IXJ *j, IXJ_FILTER * jf) -{ - unsigned short cmd; - int cnt, max; - - if (jf->filter > 3) { - return -1; - } - if (ixj_WriteDSPCommand(0x5154 + jf->filter, j)) /* Select Filter */ - - return -1; - if (!jf->enable) { - if (ixj_WriteDSPCommand(0x5152, j)) /* Disable Filter */ - - return -1; - else - return 0; - } else { - if (ixj_WriteDSPCommand(0x5153, j)) /* Enable Filter */ - - return -1; - /* Select the filter (f0 - f3) to use. */ - if (ixj_WriteDSPCommand(0x5154 + jf->filter, j)) - return -1; - } - if (jf->freq < 12 && jf->freq > 3) { - /* Select the frequency for the selected filter. */ - if (ixj_WriteDSPCommand(0x5170 + jf->freq, j)) - return -1; - } else if (jf->freq > 11) { - /* We need to load a programmable filter set for undefined */ - /* frequencies. So we will point the filter to a programmable set. */ - /* Since there are only 4 filters and 4 programmable sets, we will */ - /* just point the filter to the same number set and program it for the */ - /* frequency we want. */ - if (ixj_WriteDSPCommand(0x5170 + jf->filter, j)) - return -1; - if (j->ver.low != 0x12) { - cmd = 0x515B; - max = 19; - } else { - cmd = 0x515E; - max = 15; - } - if (ixj_WriteDSPCommand(cmd, j)) - return -1; - for (cnt = 0; cnt < max; cnt++) { - if (ixj_WriteDSPCommand(tone_table[jf->freq - 12][cnt], j)) - return -1; - } - } - j->filter_en[jf->filter] = jf->enable; - return 0; -} - -static int ixj_init_filter_raw(IXJ *j, IXJ_FILTER_RAW * jfr) -{ - unsigned short cmd; - int cnt, max; - if (jfr->filter > 3) { - return -1; - } - if (ixj_WriteDSPCommand(0x5154 + jfr->filter, j)) /* Select Filter */ - return -1; - - if (!jfr->enable) { - if (ixj_WriteDSPCommand(0x5152, j)) /* Disable Filter */ - return -1; - else - return 0; - } else { - if (ixj_WriteDSPCommand(0x5153, j)) /* Enable Filter */ - return -1; - /* Select the filter (f0 - f3) to use. */ - if (ixj_WriteDSPCommand(0x5154 + jfr->filter, j)) - return -1; - } - /* We need to load a programmable filter set for undefined */ - /* frequencies. So we will point the filter to a programmable set. */ - /* Since there are only 4 filters and 4 programmable sets, we will */ - /* just point the filter to the same number set and program it for the */ - /* frequency we want. */ - if (ixj_WriteDSPCommand(0x5170 + jfr->filter, j)) - return -1; - if (j->ver.low != 0x12) { - cmd = 0x515B; - max = 19; - } else { - cmd = 0x515E; - max = 15; - } - if (ixj_WriteDSPCommand(cmd, j)) - return -1; - for (cnt = 0; cnt < max; cnt++) { - if (ixj_WriteDSPCommand(jfr->coeff[cnt], j)) - return -1; - } - j->filter_en[jfr->filter] = jfr->enable; - return 0; -} - -static int ixj_init_tone(IXJ *j, IXJ_TONE * ti) -{ - int freq0, freq1; - unsigned short data; - if (ti->freq0) { - freq0 = ti->freq0; - } else { - freq0 = 0x7FFF; - } - - if (ti->freq1) { - freq1 = ti->freq1; - } else { - freq1 = 0x7FFF; - } - - if(ti->tone_index > 12 && ti->tone_index < 28) - { - if (ixj_WriteDSPCommand(0x6800 + ti->tone_index, j)) - return -1; - if (ixj_WriteDSPCommand(0x6000 + (ti->gain1 << 4) + ti->gain0, j)) - return -1; - data = freq0; - if (ixj_WriteDSPCommand(data, j)) - return -1; - data = freq1; - if (ixj_WriteDSPCommand(data, j)) - return -1; - } - return freq0; -} - diff --git a/drivers/telephony/ixj.h b/drivers/telephony/ixj.h deleted file mode 100644 index 2c84113..0000000 --- a/drivers/telephony/ixj.h +++ /dev/null @@ -1,1322 +0,0 @@ -/****************************************************************************** - * ixj.h - * - * - * Device Driver for Quicknet Technologies, Inc.'s Telephony cards - * including the Internet PhoneJACK, Internet PhoneJACK Lite, - * Internet PhoneJACK PCI, Internet LineJACK, Internet PhoneCARD and - * SmartCABLE - * - * (c) Copyright 1999-2001 Quicknet Technologies, Inc. - * - * 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. - * - * Author: Ed Okerson, - * - * Contributors: Greg Herlein, - * David W. Erhart, - * John Sellers, - * Mike Preston, - * - * More information about the hardware related to this driver can be found - * at our website: http://www.quicknet.net - * - * Fixes: - * - * IN NO EVENT SHALL QUICKNET TECHNOLOGIES, INC. BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT - * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF QUICKNET - * TECHNOLOGIES, INC.HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * QUICKNET TECHNOLOGIES, INC. SPECIFICALLY DISCLAIMS ANY WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND QUICKNET TECHNOLOGIES, INC. HAS NO OBLIGATION - * TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - * - *****************************************************************************/ -#define IXJ_VERSION 3031 - -#include - -#include -#include - -typedef __u16 WORD; -typedef __u32 DWORD; -typedef __u8 BYTE; - -#ifndef IXJMAX -#define IXJMAX 16 -#endif - -/****************************************************************************** -* -* This structure when unioned with the structures below makes simple byte -* access to the registers easier. -* -******************************************************************************/ -typedef struct { - unsigned char low; - unsigned char high; -} BYTES; - -typedef union { - BYTES bytes; - short word; -} IXJ_WORD; - -typedef struct{ - unsigned int b0:1; - unsigned int b1:1; - unsigned int b2:1; - unsigned int b3:1; - unsigned int b4:1; - unsigned int b5:1; - unsigned int b6:1; - unsigned int b7:1; -} IXJ_CBITS; - -typedef union{ - IXJ_CBITS cbits; - char cbyte; -} IXJ_CBYTE; - -/****************************************************************************** -* -* This structure represents the Hardware Control Register of the CT8020/8021 -* The CT8020 is used in the Internet PhoneJACK, and the 8021 in the -* Internet LineJACK -* -******************************************************************************/ -typedef struct { - unsigned int rxrdy:1; - unsigned int txrdy:1; - unsigned int status:1; - unsigned int auxstatus:1; - unsigned int rxdma:1; - unsigned int txdma:1; - unsigned int rxburst:1; - unsigned int txburst:1; - unsigned int dmadir:1; - unsigned int cont:1; - unsigned int irqn:1; - unsigned int t:5; -} HCRBIT; - -typedef union { - HCRBIT bits; - BYTES bytes; -} HCR; - -/****************************************************************************** -* -* This structure represents the Hardware Status Register of the CT8020/8021 -* The CT8020 is used in the Internet PhoneJACK, and the 8021 in the -* Internet LineJACK -* -******************************************************************************/ -typedef struct { - unsigned int controlrdy:1; - unsigned int auxctlrdy:1; - unsigned int statusrdy:1; - unsigned int auxstatusrdy:1; - unsigned int rxrdy:1; - unsigned int txrdy:1; - unsigned int restart:1; - unsigned int irqn:1; - unsigned int rxdma:1; - unsigned int txdma:1; - unsigned int cohostshutdown:1; - unsigned int t:5; -} HSRBIT; - -typedef union { - HSRBIT bits; - BYTES bytes; -} HSR; - -/****************************************************************************** -* -* This structure represents the General Purpose IO Register of the CT8020/8021 -* The CT8020 is used in the Internet PhoneJACK, and the 8021 in the -* Internet LineJACK -* -******************************************************************************/ -typedef struct { - unsigned int x:1; - unsigned int gpio1:1; - unsigned int gpio2:1; - unsigned int gpio3:1; - unsigned int gpio4:1; - unsigned int gpio5:1; - unsigned int gpio6:1; - unsigned int gpio7:1; - unsigned int xread:1; - unsigned int gpio1read:1; - unsigned int gpio2read:1; - unsigned int gpio3read:1; - unsigned int gpio4read:1; - unsigned int gpio5read:1; - unsigned int gpio6read:1; - unsigned int gpio7read:1; -} GPIOBIT; - -typedef union { - GPIOBIT bits; - BYTES bytes; - unsigned short word; -} GPIO; - -/****************************************************************************** -* -* This structure represents the Line Monitor status response -* -******************************************************************************/ -typedef struct { - unsigned int digit:4; - unsigned int cpf_valid:1; - unsigned int dtmf_valid:1; - unsigned int peak:1; - unsigned int z:1; - unsigned int f0:1; - unsigned int f1:1; - unsigned int f2:1; - unsigned int f3:1; - unsigned int frame:4; -} LMON; - -typedef union { - LMON bits; - BYTES bytes; -} DTMF; - -typedef struct { - unsigned int z:7; - unsigned int dtmf_en:1; - unsigned int y:4; - unsigned int F3:1; - unsigned int F2:1; - unsigned int F1:1; - unsigned int F0:1; -} CP; - -typedef union { - CP bits; - BYTES bytes; -} CPTF; - -/****************************************************************************** -* -* This structure represents the Status Control Register on the Internet -* LineJACK -* -******************************************************************************/ -typedef struct { - unsigned int c0:1; - unsigned int c1:1; - unsigned int stereo:1; - unsigned int daafsyncen:1; - unsigned int led1:1; - unsigned int led2:1; - unsigned int led3:1; - unsigned int led4:1; -} PSCRWI; /* Internet LineJACK and Internet PhoneJACK Lite */ - -typedef struct { - unsigned int eidp:1; - unsigned int eisd:1; - unsigned int x:6; -} PSCRWP; /* Internet PhoneJACK PCI */ - -typedef union { - PSCRWI bits; - PSCRWP pcib; - char byte; -} PLD_SCRW; - -typedef struct { - unsigned int c0:1; - unsigned int c1:1; - unsigned int x:1; - unsigned int d0ee:1; - unsigned int mixerbusy:1; - unsigned int sci:1; - unsigned int dspflag:1; - unsigned int daaflag:1; -} PSCRRI; - -typedef struct { - unsigned int eidp:1; - unsigned int eisd:1; - unsigned int x:4; - unsigned int dspflag:1; - unsigned int det:1; -} PSCRRP; - -typedef union { - PSCRRI bits; - PSCRRP pcib; - char byte; -} PLD_SCRR; - -/****************************************************************************** -* -* These structures represents the SLIC Control Register on the -* Internet LineJACK -* -******************************************************************************/ -typedef struct { - unsigned int c1:1; - unsigned int c2:1; - unsigned int c3:1; - unsigned int b2en:1; - unsigned int spken:1; - unsigned int rly1:1; - unsigned int rly2:1; - unsigned int rly3:1; -} PSLICWRITE; - -typedef struct { - unsigned int state:3; - unsigned int b2en:1; - unsigned int spken:1; - unsigned int c3:1; - unsigned int potspstn:1; - unsigned int det:1; -} PSLICREAD; - -typedef struct { - unsigned int c1:1; - unsigned int c2:1; - unsigned int c3:1; - unsigned int b2en:1; - unsigned int e1:1; - unsigned int mic:1; - unsigned int spk:1; - unsigned int x:1; -} PSLICPCI; - -typedef union { - PSLICPCI pcib; - PSLICWRITE bits; - PSLICREAD slic; - char byte; -} PLD_SLICW; - -typedef union { - PSLICPCI pcib; - PSLICREAD bits; - char byte; -} PLD_SLICR; - -/****************************************************************************** -* -* These structures represents the Clock Control Register on the -* Internet LineJACK -* -******************************************************************************/ -typedef struct { - unsigned int clk0:1; - unsigned int clk1:1; - unsigned int clk2:1; - unsigned int x0:1; - unsigned int slic_e1:1; - unsigned int x1:1; - unsigned int x2:1; - unsigned int x3:1; -} PCLOCK; - -typedef union { - PCLOCK bits; - char byte; -} PLD_CLOCK; - -/****************************************************************************** -* -* These structures deal with the mixer on the Internet LineJACK -* -******************************************************************************/ - -typedef struct { - unsigned short vol[10]; - unsigned int recsrc; - unsigned int modcnt; - unsigned short micpreamp; -} MIX; - -/****************************************************************************** -* -* These structures deal with the control logic on the Internet PhoneCARD -* -******************************************************************************/ -typedef struct { - unsigned int x0:4; /* unused bits */ - - unsigned int ed:1; /* Event Detect */ - - unsigned int drf:1; /* SmartCABLE Removal Flag 1=no cable */ - - unsigned int dspf:1; /* DSP Flag 1=DSP Ready */ - - unsigned int crr:1; /* Control Register Ready */ - -} COMMAND_REG1; - -typedef union { - COMMAND_REG1 bits; - unsigned char byte; -} PCMCIA_CR1; - -typedef struct { - unsigned int x0:4; /* unused bits */ - - unsigned int rstc:1; /* SmartCABLE Reset */ - - unsigned int pwr:1; /* SmartCABLE Power */ - - unsigned int x1:2; /* unused bits */ - -} COMMAND_REG2; - -typedef union { - COMMAND_REG2 bits; - unsigned char byte; -} PCMCIA_CR2; - -typedef struct { - unsigned int addr:5; /* R/W SmartCABLE Register Address */ - - unsigned int rw:1; /* Read / Write flag */ - - unsigned int dev:2; /* 2 bit SmartCABLE Device Address */ - -} CONTROL_REG; - -typedef union { - CONTROL_REG bits; - unsigned char byte; -} PCMCIA_SCCR; - -typedef struct { - unsigned int hsw:1; - unsigned int det:1; - unsigned int led2:1; - unsigned int led1:1; - unsigned int ring1:1; - unsigned int ring0:1; - unsigned int x:1; - unsigned int powerdown:1; -} PCMCIA_SLIC_REG; - -typedef union { - PCMCIA_SLIC_REG bits; - unsigned char byte; -} PCMCIA_SLIC; - -typedef struct { - unsigned int cpd:1; /* Chip Power Down */ - - unsigned int mpd:1; /* MIC Bias Power Down */ - - unsigned int hpd:1; /* Handset Drive Power Down */ - - unsigned int lpd:1; /* Line Drive Power Down */ - - unsigned int spd:1; /* Speaker Drive Power Down */ - - unsigned int x:2; /* unused bits */ - - unsigned int sr:1; /* Software Reset */ - -} Si3CONTROL1; - -typedef union { - Si3CONTROL1 bits; - unsigned char byte; -} Si3C1; - -typedef struct { - unsigned int al:1; /* Analog Loopback DAC analog -> ADC analog */ - - unsigned int dl2:1; /* Digital Loopback DAC -> ADC one bit */ - - unsigned int dl1:1; /* Digital Loopback ADC -> DAC one bit */ - - unsigned int pll:1; /* 1 = div 10, 0 = div 5 */ - - unsigned int hpd:1; /* HPF disable */ - - unsigned int x:3; /* unused bits */ - -} Si3CONTROL2; - -typedef union { - Si3CONTROL2 bits; - unsigned char byte; -} Si3C2; - -typedef struct { - unsigned int iir:1; /* 1 enables IIR, 0 enables FIR */ - - unsigned int him:1; /* Handset Input Mute */ - - unsigned int mcm:1; /* MIC In Mute */ - - unsigned int mcg:2; /* MIC In Gain */ - - unsigned int lim:1; /* Line In Mute */ - - unsigned int lig:2; /* Line In Gain */ - -} Si3RXGAIN; - -typedef union { - Si3RXGAIN bits; - unsigned char byte; -} Si3RXG; - -typedef struct { - unsigned int hom:1; /* Handset Out Mute */ - - unsigned int lom:1; /* Line Out Mute */ - - unsigned int rxg:5; /* RX PGA Gain */ - - unsigned int x:1; /* unused bit */ - -} Si3ADCVOLUME; - -typedef union { - Si3ADCVOLUME bits; - unsigned char byte; -} Si3ADC; - -typedef struct { - unsigned int srm:1; /* Speaker Right Mute */ - - unsigned int slm:1; /* Speaker Left Mute */ - - unsigned int txg:5; /* TX PGA Gain */ - - unsigned int x:1; /* unused bit */ - -} Si3DACVOLUME; - -typedef union { - Si3DACVOLUME bits; - unsigned char byte; -} Si3DAC; - -typedef struct { - unsigned int x:5; /* unused bit */ - - unsigned int losc:1; /* Line Out Short Circuit */ - - unsigned int srsc:1; /* Speaker Right Short Circuit */ - - unsigned int slsc:1; /* Speaker Left Short Circuit */ - -} Si3STATUSREPORT; - -typedef union { - Si3STATUSREPORT bits; - unsigned char byte; -} Si3STAT; - -typedef struct { - unsigned int sot:2; /* Speaker Out Attenuation */ - - unsigned int lot:2; /* Line Out Attenuation */ - - unsigned int x:4; /* unused bits */ - -} Si3ANALOGATTN; - -typedef union { - Si3ANALOGATTN bits; - unsigned char byte; -} Si3AATT; - -/****************************************************************************** -* -* These structures deal with the DAA on the Internet LineJACK -* -******************************************************************************/ - -typedef struct _DAA_REGS { - /*----------------------------------------------- */ - /* SOP Registers */ - /* */ - BYTE bySOP; - - union _SOP_REGS { - struct _SOP { - union /* SOP - CR0 Register */ - { - BYTE reg; - struct _CR0_BITREGS { - BYTE CLK_EXT:1; /* cr0[0:0] */ - - BYTE RIP:1; /* cr0[1:1] */ - - BYTE AR:1; /* cr0[2:2] */ - - BYTE AX:1; /* cr0[3:3] */ - - BYTE FRR:1; /* cr0[4:4] */ - - BYTE FRX:1; /* cr0[5:5] */ - - BYTE IM:1; /* cr0[6:6] */ - - BYTE TH:1; /* cr0[7:7] */ - - } bitreg; - } cr0; - - union /* SOP - CR1 Register */ - { - BYTE reg; - struct _CR1_REGS { - BYTE RM:1; /* cr1[0:0] */ - - BYTE RMR:1; /* cr1[1:1] */ - - BYTE No_auto:1; /* cr1[2:2] */ - - BYTE Pulse:1; /* cr1[3:3] */ - - BYTE P_Tone1:1; /* cr1[4:4] */ - - BYTE P_Tone2:1; /* cr1[5:5] */ - - BYTE E_Tone1:1; /* cr1[6:6] */ - - BYTE E_Tone2:1; /* cr1[7:7] */ - - } bitreg; - } cr1; - - union /* SOP - CR2 Register */ - { - BYTE reg; - struct _CR2_REGS { - BYTE Call_II:1; /* CR2[0:0] */ - - BYTE Call_I:1; /* CR2[1:1] */ - - BYTE Call_en:1; /* CR2[2:2] */ - - BYTE Call_pon:1; /* CR2[3:3] */ - - BYTE IDR:1; /* CR2[4:4] */ - - BYTE COT_R:3; /* CR2[5:7] */ - - } bitreg; - } cr2; - - union /* SOP - CR3 Register */ - { - BYTE reg; - struct _CR3_REGS { - BYTE DHP_X:1; /* CR3[0:0] */ - - BYTE DHP_R:1; /* CR3[1:1] */ - - BYTE Cal_pctl:1; /* CR3[2:2] */ - - BYTE SEL:1; /* CR3[3:3] */ - - BYTE TestLoops:4; /* CR3[4:7] */ - - } bitreg; - } cr3; - - union /* SOP - CR4 Register */ - { - BYTE reg; - struct _CR4_REGS { - BYTE Fsc_en:1; /* CR4[0:0] */ - - BYTE Int_en:1; /* CR4[1:1] */ - - BYTE AGX:2; /* CR4[2:3] */ - - BYTE AGR_R:2; /* CR4[4:5] */ - - BYTE AGR_Z:2; /* CR4[6:7] */ - - } bitreg; - } cr4; - - union /* SOP - CR5 Register */ - { - BYTE reg; - struct _CR5_REGS { - BYTE V_0:1; /* CR5[0:0] */ - - BYTE V_1:1; /* CR5[1:1] */ - - BYTE V_2:1; /* CR5[2:2] */ - - BYTE V_3:1; /* CR5[3:3] */ - - BYTE V_4:1; /* CR5[4:4] */ - - BYTE V_5:1; /* CR5[5:5] */ - - BYTE V_6:1; /* CR5[6:6] */ - - BYTE V_7:1; /* CR5[7:7] */ - - } bitreg; - } cr5; - - union /* SOP - CR6 Register */ - { - BYTE reg; - struct _CR6_REGS { - BYTE reserved:8; /* CR6[0:7] */ - - } bitreg; - } cr6; - - union /* SOP - CR7 Register */ - { - BYTE reg; - struct _CR7_REGS { - BYTE reserved:8; /* CR7[0:7] */ - - } bitreg; - } cr7; - } SOP; - - BYTE ByteRegs[sizeof(struct _SOP)]; - - } SOP_REGS; - - /* DAA_REGS.SOP_REGS.SOP.CR5.reg */ - /* DAA_REGS.SOP_REGS.SOP.CR5.bitreg */ - /* DAA_REGS.SOP_REGS.SOP.CR5.bitreg.V_2 */ - /* DAA_REGS.SOP_REGS.ByteRegs[5] */ - - /*----------------------------------------------- */ - /* XOP Registers */ - /* */ - BYTE byXOP; - - union _XOP_REGS { - struct _XOP { - union XOPXR0/* XOP - XR0 Register - Read values */ - { - BYTE reg; - struct _XR0_BITREGS { - BYTE SI_0:1; /* XR0[0:0] - Read */ - - BYTE SI_1:1; /* XR0[1:1] - Read */ - - BYTE VDD_OK:1; /* XR0[2:2] - Read */ - - BYTE Caller_ID:1; /* XR0[3:3] - Read */ - - BYTE RING:1; /* XR0[4:4] - Read */ - - BYTE Cadence:1; /* XR0[5:5] - Read */ - - BYTE Wake_up:1; /* XR0[6:6] - Read */ - - BYTE RMR:1; /* XR0[7:7] - Read */ - - } bitreg; - } xr0; - - union /* XOP - XR1 Register */ - { - BYTE reg; - struct _XR1_BITREGS { - BYTE M_SI_0:1; /* XR1[0:0] */ - - BYTE M_SI_1:1; /* XR1[1:1] */ - - BYTE M_VDD_OK:1; /* XR1[2:2] */ - - BYTE M_Caller_ID:1; /* XR1[3:3] */ - - BYTE M_RING:1; /* XR1[4:4] */ - - BYTE M_Cadence:1; /* XR1[5:5] */ - - BYTE M_Wake_up:1; /* XR1[6:6] */ - - BYTE unused:1; /* XR1[7:7] */ - - } bitreg; - } xr1; - - union /* XOP - XR2 Register */ - { - BYTE reg; - struct _XR2_BITREGS { - BYTE CTO0:1; /* XR2[0:0] */ - - BYTE CTO1:1; /* XR2[1:1] */ - - BYTE CTO2:1; /* XR2[2:2] */ - - BYTE CTO3:1; /* XR2[3:3] */ - - BYTE CTO4:1; /* XR2[4:4] */ - - BYTE CTO5:1; /* XR2[5:5] */ - - BYTE CTO6:1; /* XR2[6:6] */ - - BYTE CTO7:1; /* XR2[7:7] */ - - } bitreg; - } xr2; - - union /* XOP - XR3 Register */ - { - BYTE reg; - struct _XR3_BITREGS { - BYTE DCR0:1; /* XR3[0:0] */ - - BYTE DCR1:1; /* XR3[1:1] */ - - BYTE DCI:1; /* XR3[2:2] */ - - BYTE DCU0:1; /* XR3[3:3] */ - - BYTE DCU1:1; /* XR3[4:4] */ - - BYTE B_off:1; /* XR3[5:5] */ - - BYTE AGB0:1; /* XR3[6:6] */ - - BYTE AGB1:1; /* XR3[7:7] */ - - } bitreg; - } xr3; - - union /* XOP - XR4 Register */ - { - BYTE reg; - struct _XR4_BITREGS { - BYTE C_0:1; /* XR4[0:0] */ - - BYTE C_1:1; /* XR4[1:1] */ - - BYTE C_2:1; /* XR4[2:2] */ - - BYTE C_3:1; /* XR4[3:3] */ - - BYTE C_4:1; /* XR4[4:4] */ - - BYTE C_5:1; /* XR4[5:5] */ - - BYTE C_6:1; /* XR4[6:6] */ - - BYTE C_7:1; /* XR4[7:7] */ - - } bitreg; - } xr4; - - union /* XOP - XR5 Register */ - { - BYTE reg; - struct _XR5_BITREGS { - BYTE T_0:1; /* XR5[0:0] */ - - BYTE T_1:1; /* XR5[1:1] */ - - BYTE T_2:1; /* XR5[2:2] */ - - BYTE T_3:1; /* XR5[3:3] */ - - BYTE T_4:1; /* XR5[4:4] */ - - BYTE T_5:1; /* XR5[5:5] */ - - BYTE T_6:1; /* XR5[6:6] */ - - BYTE T_7:1; /* XR5[7:7] */ - - } bitreg; - } xr5; - - union /* XOP - XR6 Register - Read Values */ - { - BYTE reg; - struct _XR6_BITREGS { - BYTE CPS0:1; /* XR6[0:0] */ - - BYTE CPS1:1; /* XR6[1:1] */ - - BYTE unused1:2; /* XR6[2:3] */ - - BYTE CLK_OFF:1; /* XR6[4:4] */ - - BYTE unused2:3; /* XR6[5:7] */ - - } bitreg; - } xr6; - - union /* XOP - XR7 Register */ - { - BYTE reg; - struct _XR7_BITREGS { - BYTE unused1:1; /* XR7[0:0] */ - - BYTE Vdd0:1; /* XR7[1:1] */ - - BYTE Vdd1:1; /* XR7[2:2] */ - - BYTE unused2:5; /* XR7[3:7] */ - - } bitreg; - } xr7; - } XOP; - - BYTE ByteRegs[sizeof(struct _XOP)]; - - } XOP_REGS; - - /* DAA_REGS.XOP_REGS.XOP.XR7.reg */ - /* DAA_REGS.XOP_REGS.XOP.XR7.bitreg */ - /* DAA_REGS.XOP_REGS.XOP.XR7.bitreg.Vdd0 */ - /* DAA_REGS.XOP_REGS.ByteRegs[7] */ - - /*----------------------------------------------- */ - /* COP Registers */ - /* */ - BYTE byCOP; - - union _COP_REGS { - struct _COP { - BYTE THFilterCoeff_1[8]; /* COP - TH Filter Coefficients, CODE=0, Part 1 */ - - BYTE THFilterCoeff_2[8]; /* COP - TH Filter Coefficients, CODE=1, Part 2 */ - - BYTE THFilterCoeff_3[8]; /* COP - TH Filter Coefficients, CODE=2, Part 3 */ - - BYTE RingerImpendance_1[8]; /* COP - Ringer Impendance Coefficients, CODE=3, Part 1 */ - - BYTE IMFilterCoeff_1[8]; /* COP - IM Filter Coefficients, CODE=4, Part 1 */ - - BYTE IMFilterCoeff_2[8]; /* COP - IM Filter Coefficients, CODE=5, Part 2 */ - - BYTE RingerImpendance_2[8]; /* COP - Ringer Impendance Coefficients, CODE=6, Part 2 */ - - BYTE FRRFilterCoeff[8]; /* COP - FRR Filter Coefficients, CODE=7 */ - - BYTE FRXFilterCoeff[8]; /* COP - FRX Filter Coefficients, CODE=8 */ - - BYTE ARFilterCoeff[4]; /* COP - AR Filter Coefficients, CODE=9 */ - - BYTE AXFilterCoeff[4]; /* COP - AX Filter Coefficients, CODE=10 */ - - BYTE Tone1Coeff[4]; /* COP - Tone1 Coefficients, CODE=11 */ - - BYTE Tone2Coeff[4]; /* COP - Tone2 Coefficients, CODE=12 */ - - BYTE LevelmeteringRinging[4]; /* COP - Levelmetering Ringing, CODE=13 */ - - BYTE CallerID1stTone[8]; /* COP - Caller ID 1st Tone, CODE=14 */ - - BYTE CallerID2ndTone[8]; /* COP - Caller ID 2nd Tone, CODE=15 */ - - } COP; - - BYTE ByteRegs[sizeof(struct _COP)]; - - } COP_REGS; - - /* DAA_REGS.COP_REGS.COP.XR7.Tone1Coeff[3] */ - /* DAA_REGS.COP_REGS.COP.XR7.bitreg */ - /* DAA_REGS.COP_REGS.COP.XR7.bitreg.Vdd0 */ - /* DAA_REGS.COP_REGS.ByteRegs[57] */ - - /*----------------------------------------------- */ - /* CAO Registers */ - /* */ - BYTE byCAO; - - union _CAO_REGS { - struct _CAO { - BYTE CallerID[512]; /* CAO - Caller ID Bytes */ - - } CAO; - - BYTE ByteRegs[sizeof(struct _CAO)]; - } CAO_REGS; - - union /* XOP - XR0 Register - Write values */ - { - BYTE reg; - struct _XR0_BITREGSW { - BYTE SO_0:1; /* XR1[0:0] - Write */ - - BYTE SO_1:1; /* XR1[1:1] - Write */ - - BYTE SO_2:1; /* XR1[2:2] - Write */ - - BYTE unused:5; /* XR1[3:7] - Write */ - - } bitreg; - } XOP_xr0_W; - - union /* XOP - XR6 Register - Write values */ - { - BYTE reg; - struct _XR6_BITREGSW { - BYTE unused1:4; /* XR6[0:3] */ - - BYTE CLK_OFF:1; /* XR6[4:4] */ - - BYTE unused2:3; /* XR6[5:7] */ - - } bitreg; - } XOP_xr6_W; - -} DAA_REGS; - -#define ALISDAA_ID_BYTE 0x81 -#define ALISDAA_CALLERID_SIZE 512 - -/*------------------------------ */ -/* */ -/* Misc definitions */ -/* */ - -/* Power Up Operation */ -#define SOP_PU_SLEEP 0 -#define SOP_PU_RINGING 1 -#define SOP_PU_CONVERSATION 2 -#define SOP_PU_PULSEDIALING 3 -#define SOP_PU_RESET 4 - -#define ALISDAA_CALLERID_SIZE 512 - -#define PLAYBACK_MODE_COMPRESSED 0 /* Selects: Compressed modes, TrueSpeech 8.5-4.1, G.723.1, G.722, G.728, G.729 */ -#define PLAYBACK_MODE_TRUESPEECH_V40 0 /* Selects: TrueSpeech 8.5, 6.3, 5.3, 4.8 or 4.1 Kbps */ -#define PLAYBACK_MODE_TRUESPEECH 8 /* Selects: TrueSpeech 8.5, 6.3, 5.3, 4.8 or 4.1 Kbps Version 5.1 */ -#define PLAYBACK_MODE_ULAW 2 /* Selects: 64 Kbit/sec MuA-law PCM */ -#define PLAYBACK_MODE_ALAW 10 /* Selects: 64 Kbit/sec A-law PCM */ -#define PLAYBACK_MODE_16LINEAR 6 /* Selects: 128 Kbit/sec 16-bit linear */ -#define PLAYBACK_MODE_8LINEAR 4 /* Selects: 64 Kbit/sec 8-bit signed linear */ -#define PLAYBACK_MODE_8LINEAR_WSS 5 /* Selects: 64 Kbit/sec WSS 8-bit unsigned linear */ - -#define RECORD_MODE_COMPRESSED 0 /* Selects: Compressed modes, TrueSpeech 8.5-4.1, G.723.1, G.722, G.728, G.729 */ -#define RECORD_MODE_TRUESPEECH 0 /* Selects: TrueSpeech 8.5, 6.3, 5.3, 4.8 or 4.1 Kbps */ -#define RECORD_MODE_ULAW 4 /* Selects: 64 Kbit/sec Mu-law PCM */ -#define RECORD_MODE_ALAW 12 /* Selects: 64 Kbit/sec A-law PCM */ -#define RECORD_MODE_16LINEAR 5 /* Selects: 128 Kbit/sec 16-bit linear */ -#define RECORD_MODE_8LINEAR 6 /* Selects: 64 Kbit/sec 8-bit signed linear */ -#define RECORD_MODE_8LINEAR_WSS 7 /* Selects: 64 Kbit/sec WSS 8-bit unsigned linear */ - -enum SLIC_STATES { - PLD_SLIC_STATE_OC = 0, - PLD_SLIC_STATE_RINGING, - PLD_SLIC_STATE_ACTIVE, - PLD_SLIC_STATE_OHT, - PLD_SLIC_STATE_TIPOPEN, - PLD_SLIC_STATE_STANDBY, - PLD_SLIC_STATE_APR, - PLD_SLIC_STATE_OHTPR -}; - -enum SCI_CONTROL { - SCI_End = 0, - SCI_Enable_DAA, - SCI_Enable_Mixer, - SCI_Enable_EEPROM -}; - -enum Mode { - T63, T53, T48, T40 -}; -enum Dir { - V3_TO_V4, V4_TO_V3, V4_TO_V5, V5_TO_V4 -}; - -typedef struct Proc_Info_Tag { - enum Mode convert_mode; - enum Dir convert_dir; - int Prev_Frame_Type; - int Current_Frame_Type; -} Proc_Info_Type; - -enum PREVAL { - NORMAL = 0, - NOPOST, - POSTONLY, - PREERROR -}; - -enum IXJ_EXTENSIONS { - G729LOADER = 0, - TS85LOADER, - PRE_READ, - POST_READ, - PRE_WRITE, - POST_WRITE, - PRE_IOCTL, - POST_IOCTL -}; - -typedef struct { - char enable; - char en_filter; - unsigned int filter; - unsigned int state; /* State 0 when cadence has not started. */ - - unsigned int on1; /* State 1 */ - - unsigned long on1min; /* State 1 - 10% + jiffies */ - unsigned long on1dot; /* State 1 + jiffies */ - - unsigned long on1max; /* State 1 + 10% + jiffies */ - - unsigned int off1; /* State 2 */ - - unsigned long off1min; - unsigned long off1dot; /* State 2 + jiffies */ - unsigned long off1max; - unsigned int on2; /* State 3 */ - - unsigned long on2min; - unsigned long on2dot; - unsigned long on2max; - unsigned int off2; /* State 4 */ - - unsigned long off2min; - unsigned long off2dot; /* State 4 + jiffies */ - unsigned long off2max; - unsigned int on3; /* State 5 */ - - unsigned long on3min; - unsigned long on3dot; - unsigned long on3max; - unsigned int off3; /* State 6 */ - - unsigned long off3min; - unsigned long off3dot; /* State 6 + jiffies */ - unsigned long off3max; -} IXJ_CADENCE_F; - -typedef struct { - unsigned int busytone:1; - unsigned int dialtone:1; - unsigned int ringback:1; - unsigned int ringing:1; - unsigned int playing:1; - unsigned int recording:1; - unsigned int cringing:1; - unsigned int play_first_frame:1; - unsigned int pstn_present:1; - unsigned int pstn_ringing:1; - unsigned int pots_correct:1; - unsigned int pots_pstn:1; - unsigned int g729_loaded:1; - unsigned int ts85_loaded:1; - unsigned int dtmf_oob:1; /* DTMF Out-Of-Band */ - - unsigned int pcmciascp:1; /* SmartCABLE Present */ - - unsigned int pcmciasct:2; /* SmartCABLE Type */ - - unsigned int pcmciastate:3; /* SmartCABLE Init State */ - - unsigned int inwrite:1; /* Currently writing */ - - unsigned int inread:1; /* Currently reading */ - - unsigned int incheck:1; /* Currently checking the SmartCABLE */ - - unsigned int cidplay:1; /* Currently playing Caller ID */ - - unsigned int cidring:1; /* This is the ring for Caller ID */ - - unsigned int cidsent:1; /* Caller ID has been sent */ - - unsigned int cidcw_ack:1; /* Caller ID CW ACK (from CPE) */ - unsigned int firstring:1; /* First ring cadence is complete */ - unsigned int pstncheck:1; /* Currently checking the PSTN Line */ - unsigned int pstn_rmr:1; - unsigned int x:3; /* unused bits */ - -} IXJ_FLAGS; - -/****************************************************************************** -* -* This structure holds the state of all of the Quicknet cards -* -******************************************************************************/ - -typedef struct { - int elements_used; - IXJ_CADENCE_TERM termination; - IXJ_CADENCE_ELEMENT *ce; -} ixj_cadence; - -typedef struct { - struct phone_device p; - struct timer_list timer; - unsigned int board; - unsigned int DSPbase; - unsigned int XILINXbase; - unsigned int serial; - atomic_t DSPWrite; - struct phone_capability caplist[30]; - unsigned int caps; - struct pnp_dev *dev; - unsigned int cardtype; - unsigned int rec_codec; - unsigned int cid_rec_codec; - unsigned int cid_rec_volume; - unsigned char cid_rec_flag; - signed char rec_mode; - unsigned int play_codec; - unsigned int cid_play_codec; - unsigned int cid_play_volume; - unsigned char cid_play_flag; - signed char play_mode; - IXJ_FLAGS flags; - unsigned long busyflags; - unsigned int rec_frame_size; - unsigned int play_frame_size; - unsigned int cid_play_frame_size; - unsigned int cid_base_frame_size; - unsigned long cidcw_wait; - int aec_level; - int cid_play_aec_level; - int readers, writers; - wait_queue_head_t poll_q; - wait_queue_head_t read_q; - char *read_buffer, *read_buffer_end; - char *read_convert_buffer; - size_t read_buffer_size; - unsigned int read_buffer_ready; - wait_queue_head_t write_q; - char *write_buffer, *write_buffer_end; - char *write_convert_buffer; - size_t write_buffer_size; - unsigned int write_buffers_empty; - unsigned long drybuffer; - char *write_buffer_rp, *write_buffer_wp; - char dtmfbuffer[80]; - char dtmf_current; - int dtmf_wp, dtmf_rp, dtmf_state, dtmf_proc; - int tone_off_time, tone_on_time; - struct fasync_struct *async_queue; - unsigned long tone_start_jif; - char tone_index; - char tone_state; - char maxrings; - ixj_cadence *cadence_t; - ixj_cadence *cadence_r; - int tone_cadence_state; - IXJ_CADENCE_F cadence_f[6]; - DTMF dtmf; - CPTF cptf; - BYTES dsp; - BYTES ver; - BYTES scr; - BYTES ssr; - BYTES baseframe; - HSR hsr; - GPIO gpio; - PLD_SCRR pld_scrr; - PLD_SCRW pld_scrw; - PLD_SLICW pld_slicw; - PLD_SLICR pld_slicr; - PLD_CLOCK pld_clock; - PCMCIA_CR1 pccr1; - PCMCIA_CR2 pccr2; - PCMCIA_SCCR psccr; - PCMCIA_SLIC pslic; - char pscdd; - Si3C1 sic1; - Si3C2 sic2; - Si3RXG sirxg; - Si3ADC siadc; - Si3DAC sidac; - Si3STAT sistat; - Si3AATT siaatt; - MIX mix; - unsigned short ring_cadence; - int ring_cadence_t; - unsigned long ring_cadence_jif; - unsigned long checkwait; - int intercom; - int m_hook; - int r_hook; - int p_hook; - char pstn_envelope; - char pstn_cid_intr; - unsigned char fskz; - unsigned char fskphase; - unsigned char fskcnt; - unsigned int cidsize; - unsigned int cidcnt; - unsigned long pstn_cid_received; - PHONE_CID cid; - PHONE_CID cid_send; - unsigned long pstn_ring_int; - unsigned long pstn_ring_start; - unsigned long pstn_ring_stop; - unsigned long pstn_winkstart; - unsigned long pstn_last_rmr; - unsigned long pstn_prev_rmr; - unsigned long pots_winkstart; - unsigned int winktime; - unsigned long flash_end; - char port; - char hookstate; - union telephony_exception ex; - union telephony_exception ex_sig; - int ixj_signals[35]; - IXJ_SIGDEF sigdef; - char daa_mode; - char daa_country; - unsigned long pstn_sleeptil; - DAA_REGS m_DAAShadowRegs; - Proc_Info_Type Info_read; - Proc_Info_Type Info_write; - unsigned short frame_count; - unsigned int filter_hist[4]; - unsigned char filter_en[6]; - unsigned short proc_load; - unsigned long framesread; - unsigned long frameswritten; - unsigned long read_wait; - unsigned long write_wait; - unsigned long timerchecks; - unsigned long txreadycheck; - unsigned long rxreadycheck; - unsigned long statuswait; - unsigned long statuswaitfail; - unsigned long pcontrolwait; - unsigned long pcontrolwaitfail; - unsigned long iscontrolready; - unsigned long iscontrolreadyfail; - unsigned long pstnstatecheck; -#ifdef IXJ_DYN_ALLOC - short *fskdata; -#else - short fskdata[8000]; -#endif - int fsksize; - int fskdcnt; -} IXJ; - -typedef int (*IXJ_REGFUNC) (IXJ * j, unsigned long arg); - -extern IXJ *ixj_pcmcia_probe(unsigned long, unsigned long); - diff --git a/drivers/telephony/ixj_pcmcia.c b/drivers/telephony/ixj_pcmcia.c deleted file mode 100644 index 05032e2..0000000 --- a/drivers/telephony/ixj_pcmcia.c +++ /dev/null @@ -1,187 +0,0 @@ -#include "ixj-ver.h" - -#include - -#include -#include /* printk() */ -#include /* everything... */ -#include /* error codes */ -#include - -#include -#include - -#include "ixj.h" - -/* - * PCMCIA service support for Quicknet cards - */ - - -typedef struct ixj_info_t { - int ndev; - struct ixj *port; -} ixj_info_t; - -static void ixj_detach(struct pcmcia_device *p_dev); -static int ixj_config(struct pcmcia_device * link); -static void ixj_cs_release(struct pcmcia_device * link); - -static int ixj_probe(struct pcmcia_device *p_dev) -{ - dev_dbg(&p_dev->dev, "ixj_attach()\n"); - /* Create new ixj device */ - p_dev->priv = kzalloc(sizeof(struct ixj_info_t), GFP_KERNEL); - if (!p_dev->priv) { - return -ENOMEM; - } - - return ixj_config(p_dev); -} - -static void ixj_detach(struct pcmcia_device *link) -{ - dev_dbg(&link->dev, "ixj_detach\n"); - - ixj_cs_release(link); - - kfree(link->priv); -} - -static void ixj_get_serial(struct pcmcia_device * link, IXJ * j) -{ - char *str; - int i, place; - dev_dbg(&link->dev, "ixj_get_serial\n"); - - str = link->prod_id[0]; - if (!str) - goto failed; - printk("%s", str); - str = link->prod_id[1]; - if (!str) - goto failed; - printk(" %s", str); - str = link->prod_id[2]; - if (!str) - goto failed; - place = 1; - for (i = strlen(str) - 1; i >= 0; i--) { - switch (str[i]) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - j->serial += (str[i] - 48) * place; - break; - case 'A': - case 'B': - case 'C': - case 'D': - case 'E': - case 'F': - j->serial += (str[i] - 55) * place; - break; - case 'a': - case 'b': - case 'c': - case 'd': - case 'e': - case 'f': - j->serial += (str[i] - 87) * place; - break; - } - place = place * 0x10; - } - str = link->prod_id[3]; - if (!str) - goto failed; - printk(" version %s\n", str); -failed: - return; -} - -static int ixj_config_check(struct pcmcia_device *p_dev, void *priv_data) -{ - p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; - p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; - p_dev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH; - p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8; - p_dev->io_lines = 3; - - return pcmcia_request_io(p_dev); -} - -static int ixj_config(struct pcmcia_device * link) -{ - IXJ *j; - ixj_info_t *info; - - info = link->priv; - dev_dbg(&link->dev, "ixj_config\n"); - - link->config_flags = CONF_AUTO_SET_IO; - - if (pcmcia_loop_config(link, ixj_config_check, NULL)) - goto failed; - - if (pcmcia_enable_device(link)) - goto failed; - - /* - * Register the card with the core. - */ - j = ixj_pcmcia_probe(link->resource[0]->start, - link->resource[0]->start + 0x10); - - info->ndev = 1; - ixj_get_serial(link, j); - return 0; - -failed: - ixj_cs_release(link); - return -ENODEV; -} - -static void ixj_cs_release(struct pcmcia_device *link) -{ - ixj_info_t *info = link->priv; - dev_dbg(&link->dev, "ixj_cs_release\n"); - info->ndev = 0; - pcmcia_disable_device(link); -} - -static const struct pcmcia_device_id ixj_ids[] = { - PCMCIA_DEVICE_MANF_CARD(0x0257, 0x0600), - PCMCIA_DEVICE_NULL -}; -MODULE_DEVICE_TABLE(pcmcia, ixj_ids); - -static struct pcmcia_driver ixj_driver = { - .owner = THIS_MODULE, - .name = "ixj_cs", - .probe = ixj_probe, - .remove = ixj_detach, - .id_table = ixj_ids, -}; - -static int __init ixj_pcmcia_init(void) -{ - return pcmcia_register_driver(&ixj_driver); -} - -static void ixj_pcmcia_exit(void) -{ - pcmcia_unregister_driver(&ixj_driver); -} - -module_init(ixj_pcmcia_init); -module_exit(ixj_pcmcia_exit); - -MODULE_LICENSE("GPL"); diff --git a/drivers/telephony/phonedev.c b/drivers/telephony/phonedev.c deleted file mode 100644 index 1915af2..0000000 --- a/drivers/telephony/phonedev.c +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Telephony registration for Linux - * - * (c) Copyright 1999 Red Hat Software Inc. - * - * 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. - * - * Author: Alan Cox, - * - * Fixes: Mar 01 2000 Thomas Sparr, - * phone_register_device now works with unit!=PHONE_UNIT_ANY - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#define PHONE_NUM_DEVICES 256 - -/* - * Active devices - */ - -static struct phone_device *phone_device[PHONE_NUM_DEVICES]; -static DEFINE_MUTEX(phone_lock); - -/* - * Open a phone device. - */ - -static int phone_open(struct inode *inode, struct file *file) -{ - unsigned int minor = iminor(inode); - int err = 0; - struct phone_device *p; - const struct file_operations *old_fops, *new_fops = NULL; - - if (minor >= PHONE_NUM_DEVICES) - return -ENODEV; - - mutex_lock(&phone_lock); - p = phone_device[minor]; - if (p) - new_fops = fops_get(p->f_op); - if (!new_fops) { - mutex_unlock(&phone_lock); - request_module("char-major-%d-%d", PHONE_MAJOR, minor); - mutex_lock(&phone_lock); - p = phone_device[minor]; - if (p == NULL || (new_fops = fops_get(p->f_op)) == NULL) - { - err=-ENODEV; - goto end; - } - } - old_fops = file->f_op; - file->f_op = new_fops; - if (p->open) - err = p->open(p, file); /* Tell the device it is open */ - if (err) { - fops_put(file->f_op); - file->f_op = fops_get(old_fops); - } - fops_put(old_fops); -end: - mutex_unlock(&phone_lock); - return err; -} - -/* - * Telephony For Linux device drivers request registration here. - */ - -int phone_register_device(struct phone_device *p, int unit) -{ - int base; - int end; - int i; - - base = 0; - end = PHONE_NUM_DEVICES - 1; - - if (unit != PHONE_UNIT_ANY) { - base = unit; - end = unit + 1; /* enter the loop at least one time */ - } - - mutex_lock(&phone_lock); - for (i = base; i < end; i++) { - if (phone_device[i] == NULL) { - phone_device[i] = p; - p->minor = i; - mutex_unlock(&phone_lock); - return 0; - } - } - mutex_unlock(&phone_lock); - return -ENFILE; -} - -/* - * Unregister an unused Telephony for linux device - */ - -void phone_unregister_device(struct phone_device *pfd) -{ - mutex_lock(&phone_lock); - if (likely(phone_device[pfd->minor] == pfd)) - phone_device[pfd->minor] = NULL; - mutex_unlock(&phone_lock); -} - - -static const struct file_operations phone_fops = -{ - .owner = THIS_MODULE, - .open = phone_open, - .llseek = noop_llseek, -}; - -/* - * Board init functions - */ - - -/* - * Initialise Telephony for linux - */ - -static int __init telephony_init(void) -{ - printk(KERN_INFO "Linux telephony interface: v1.00\n"); - if (register_chrdev(PHONE_MAJOR, "telephony", &phone_fops)) { - printk("phonedev: unable to get major %d\n", PHONE_MAJOR); - return -EIO; - } - - return 0; -} - -static void __exit telephony_exit(void) -{ - unregister_chrdev(PHONE_MAJOR, "telephony"); -} - -module_init(telephony_init); -module_exit(telephony_exit); - -MODULE_LICENSE("GPL"); - -EXPORT_SYMBOL(phone_register_device); -EXPORT_SYMBOL(phone_unregister_device); -- cgit v0.10.2 From 32de21f75d0152571eb3710f170cddb5db3d0336 Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Wed, 25 Jan 2012 23:14:56 +0900 Subject: staging: Fix typo in mei/interrupt.c Correct spelling "reseting" to "resetting" in drivers/staging/mei/interrupt.c Signed-off-by: Masanari Iida Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/mei/interrupt.c b/drivers/staging/mei/interrupt.c index 3544fee..e85a85a 100644 --- a/drivers/staging/mei/interrupt.c +++ b/drivers/staging/mei/interrupt.c @@ -1423,7 +1423,7 @@ void mei_timer(struct work_struct *work) if (dev->iamthif_stall_timer) { if (--dev->iamthif_stall_timer == 0) { - dev_dbg(&dev->pdev->dev, "reseting because of hang to amthi.\n"); + dev_dbg(&dev->pdev->dev, "resetting because of hang to amthi.\n"); mei_reset(dev, 1); dev->iamthif_msg_buf_size = 0; dev->iamthif_msg_buf_index = 0; -- cgit v0.10.2 From 1135ca9c869fff55a32fdce2171b33f36e44ea0c Mon Sep 17 00:00:00 2001 From: Dan Magenheimer Date: Mon, 30 Jan 2012 14:39:18 -0800 Subject: staging: ramster: cluster/messaging foundation Copy cluster subdirectory from ocfs2. These files implement the basic cluster discovery, mapping, heartbeat / keepalive, and messaging ("o2net") that ramster requires for internode communication. Note: there are NO ramster-specific changes yet; this commit does NOT pass checkpatch since the copied source files do not. (Why copy? This particular part of ocfs2 has never been broken out for non-ocfs2 use before, some (small) changes are required for ramster to use that code, and ramster is currently incompatible with real ocfs2 anyway (requires !CONFIG_OCFS2_FS). Before ramster can be promoted out of staging, we will need to work with the ocfs2 maintainers to see if the code interdependencies can be merged, but for now, for staging, this seemed to be an expedient way to make use of the ocfs2 core cluster code while still incorporating necessary changes for ramster.) Signed-off-by: Dan Magenheimer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/ramster/cluster/Makefile b/drivers/staging/ramster/cluster/Makefile new file mode 100644 index 0000000..bc8c5e7 --- /dev/null +++ b/drivers/staging/ramster/cluster/Makefile @@ -0,0 +1,4 @@ +obj-$(CONFIG_OCFS2_FS) += ocfs2_nodemanager.o + +ocfs2_nodemanager-objs := heartbeat.o masklog.o sys.o nodemanager.o \ + quorum.o tcp.o netdebug.o ver.o diff --git a/drivers/staging/ramster/cluster/heartbeat.c b/drivers/staging/ramster/cluster/heartbeat.c new file mode 100644 index 0000000..a4e855e --- /dev/null +++ b/drivers/staging/ramster/cluster/heartbeat.c @@ -0,0 +1,2678 @@ +/* -*- mode: c; c-basic-offset: 8; -*- + * vim: noexpandtab sw=8 ts=8 sts=0: + * + * Copyright (C) 2004, 2005 Oracle. All rights reserved. + * + * 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; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 021110-1307, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "heartbeat.h" +#include "tcp.h" +#include "nodemanager.h" +#include "quorum.h" + +#include "masklog.h" + + +/* + * The first heartbeat pass had one global thread that would serialize all hb + * callback calls. This global serializing sem should only be removed once + * we've made sure that all callees can deal with being called concurrently + * from multiple hb region threads. + */ +static DECLARE_RWSEM(o2hb_callback_sem); + +/* + * multiple hb threads are watching multiple regions. A node is live + * whenever any of the threads sees activity from the node in its region. + */ +static DEFINE_SPINLOCK(o2hb_live_lock); +static struct list_head o2hb_live_slots[O2NM_MAX_NODES]; +static unsigned long o2hb_live_node_bitmap[BITS_TO_LONGS(O2NM_MAX_NODES)]; +static LIST_HEAD(o2hb_node_events); +static DECLARE_WAIT_QUEUE_HEAD(o2hb_steady_queue); + +/* + * In global heartbeat, we maintain a series of region bitmaps. + * - o2hb_region_bitmap allows us to limit the region number to max region. + * - o2hb_live_region_bitmap tracks live regions (seen steady iterations). + * - o2hb_quorum_region_bitmap tracks live regions that have seen all nodes + * heartbeat on it. + * - o2hb_failed_region_bitmap tracks the regions that have seen io timeouts. + */ +static unsigned long o2hb_region_bitmap[BITS_TO_LONGS(O2NM_MAX_REGIONS)]; +static unsigned long o2hb_live_region_bitmap[BITS_TO_LONGS(O2NM_MAX_REGIONS)]; +static unsigned long o2hb_quorum_region_bitmap[BITS_TO_LONGS(O2NM_MAX_REGIONS)]; +static unsigned long o2hb_failed_region_bitmap[BITS_TO_LONGS(O2NM_MAX_REGIONS)]; + +#define O2HB_DB_TYPE_LIVENODES 0 +#define O2HB_DB_TYPE_LIVEREGIONS 1 +#define O2HB_DB_TYPE_QUORUMREGIONS 2 +#define O2HB_DB_TYPE_FAILEDREGIONS 3 +#define O2HB_DB_TYPE_REGION_LIVENODES 4 +#define O2HB_DB_TYPE_REGION_NUMBER 5 +#define O2HB_DB_TYPE_REGION_ELAPSED_TIME 6 +#define O2HB_DB_TYPE_REGION_PINNED 7 +struct o2hb_debug_buf { + int db_type; + int db_size; + int db_len; + void *db_data; +}; + +static struct o2hb_debug_buf *o2hb_db_livenodes; +static struct o2hb_debug_buf *o2hb_db_liveregions; +static struct o2hb_debug_buf *o2hb_db_quorumregions; +static struct o2hb_debug_buf *o2hb_db_failedregions; + +#define O2HB_DEBUG_DIR "o2hb" +#define O2HB_DEBUG_LIVENODES "livenodes" +#define O2HB_DEBUG_LIVEREGIONS "live_regions" +#define O2HB_DEBUG_QUORUMREGIONS "quorum_regions" +#define O2HB_DEBUG_FAILEDREGIONS "failed_regions" +#define O2HB_DEBUG_REGION_NUMBER "num" +#define O2HB_DEBUG_REGION_ELAPSED_TIME "elapsed_time_in_ms" +#define O2HB_DEBUG_REGION_PINNED "pinned" + +static struct dentry *o2hb_debug_dir; +static struct dentry *o2hb_debug_livenodes; +static struct dentry *o2hb_debug_liveregions; +static struct dentry *o2hb_debug_quorumregions; +static struct dentry *o2hb_debug_failedregions; + +static LIST_HEAD(o2hb_all_regions); + +static struct o2hb_callback { + struct list_head list; +} o2hb_callbacks[O2HB_NUM_CB]; + +static struct o2hb_callback *hbcall_from_type(enum o2hb_callback_type type); + +#define O2HB_DEFAULT_BLOCK_BITS 9 + +enum o2hb_heartbeat_modes { + O2HB_HEARTBEAT_LOCAL = 0, + O2HB_HEARTBEAT_GLOBAL, + O2HB_HEARTBEAT_NUM_MODES, +}; + +char *o2hb_heartbeat_mode_desc[O2HB_HEARTBEAT_NUM_MODES] = { + "local", /* O2HB_HEARTBEAT_LOCAL */ + "global", /* O2HB_HEARTBEAT_GLOBAL */ +}; + +unsigned int o2hb_dead_threshold = O2HB_DEFAULT_DEAD_THRESHOLD; +unsigned int o2hb_heartbeat_mode = O2HB_HEARTBEAT_LOCAL; + +/* + * o2hb_dependent_users tracks the number of registered callbacks that depend + * on heartbeat. o2net and o2dlm are two entities that register this callback. + * However only o2dlm depends on the heartbeat. It does not want the heartbeat + * to stop while a dlm domain is still active. + */ +unsigned int o2hb_dependent_users; + +/* + * In global heartbeat mode, all regions are pinned if there are one or more + * dependent users and the quorum region count is <= O2HB_PIN_CUT_OFF. All + * regions are unpinned if the region count exceeds the cut off or the number + * of dependent users falls to zero. + */ +#define O2HB_PIN_CUT_OFF 3 + +/* + * In local heartbeat mode, we assume the dlm domain name to be the same as + * region uuid. This is true for domains created for the file system but not + * necessarily true for userdlm domains. This is a known limitation. + * + * In global heartbeat mode, we pin/unpin all o2hb regions. This solution + * works for both file system and userdlm domains. + */ +static int o2hb_region_pin(const char *region_uuid); +static void o2hb_region_unpin(const char *region_uuid); + +/* Only sets a new threshold if there are no active regions. + * + * No locking or otherwise interesting code is required for reading + * o2hb_dead_threshold as it can't change once regions are active and + * it's not interesting to anyone until then anyway. */ +static void o2hb_dead_threshold_set(unsigned int threshold) +{ + if (threshold > O2HB_MIN_DEAD_THRESHOLD) { + spin_lock(&o2hb_live_lock); + if (list_empty(&o2hb_all_regions)) + o2hb_dead_threshold = threshold; + spin_unlock(&o2hb_live_lock); + } +} + +static int o2hb_global_hearbeat_mode_set(unsigned int hb_mode) +{ + int ret = -1; + + if (hb_mode < O2HB_HEARTBEAT_NUM_MODES) { + spin_lock(&o2hb_live_lock); + if (list_empty(&o2hb_all_regions)) { + o2hb_heartbeat_mode = hb_mode; + ret = 0; + } + spin_unlock(&o2hb_live_lock); + } + + return ret; +} + +struct o2hb_node_event { + struct list_head hn_item; + enum o2hb_callback_type hn_event_type; + struct o2nm_node *hn_node; + int hn_node_num; +}; + +struct o2hb_disk_slot { + struct o2hb_disk_heartbeat_block *ds_raw_block; + u8 ds_node_num; + u64 ds_last_time; + u64 ds_last_generation; + u16 ds_equal_samples; + u16 ds_changed_samples; + struct list_head ds_live_item; +}; + +/* each thread owns a region.. when we're asked to tear down the region + * we ask the thread to stop, who cleans up the region */ +struct o2hb_region { + struct config_item hr_item; + + struct list_head hr_all_item; + unsigned hr_unclean_stop:1, + hr_aborted_start:1, + hr_item_pinned:1, + hr_item_dropped:1; + + /* protected by the hr_callback_sem */ + struct task_struct *hr_task; + + unsigned int hr_blocks; + unsigned long long hr_start_block; + + unsigned int hr_block_bits; + unsigned int hr_block_bytes; + + unsigned int hr_slots_per_page; + unsigned int hr_num_pages; + + struct page **hr_slot_data; + struct block_device *hr_bdev; + struct o2hb_disk_slot *hr_slots; + + /* live node map of this region */ + unsigned long hr_live_node_bitmap[BITS_TO_LONGS(O2NM_MAX_NODES)]; + unsigned int hr_region_num; + + struct dentry *hr_debug_dir; + struct dentry *hr_debug_livenodes; + struct dentry *hr_debug_regnum; + struct dentry *hr_debug_elapsed_time; + struct dentry *hr_debug_pinned; + struct o2hb_debug_buf *hr_db_livenodes; + struct o2hb_debug_buf *hr_db_regnum; + struct o2hb_debug_buf *hr_db_elapsed_time; + struct o2hb_debug_buf *hr_db_pinned; + + /* let the person setting up hb wait for it to return until it + * has reached a 'steady' state. This will be fixed when we have + * a more complete api that doesn't lead to this sort of fragility. */ + atomic_t hr_steady_iterations; + + /* terminate o2hb thread if it does not reach steady state + * (hr_steady_iterations == 0) within hr_unsteady_iterations */ + atomic_t hr_unsteady_iterations; + + char hr_dev_name[BDEVNAME_SIZE]; + + unsigned int hr_timeout_ms; + + /* randomized as the region goes up and down so that a node + * recognizes a node going up and down in one iteration */ + u64 hr_generation; + + struct delayed_work hr_write_timeout_work; + unsigned long hr_last_timeout_start; + + /* Used during o2hb_check_slot to hold a copy of the block + * being checked because we temporarily have to zero out the + * crc field. */ + struct o2hb_disk_heartbeat_block *hr_tmp_block; +}; + +struct o2hb_bio_wait_ctxt { + atomic_t wc_num_reqs; + struct completion wc_io_complete; + int wc_error; +}; + +static int o2hb_pop_count(void *map, int count) +{ + int i = -1, pop = 0; + + while ((i = find_next_bit(map, count, i + 1)) < count) + pop++; + return pop; +} + +static void o2hb_write_timeout(struct work_struct *work) +{ + int failed, quorum; + unsigned long flags; + struct o2hb_region *reg = + container_of(work, struct o2hb_region, + hr_write_timeout_work.work); + + mlog(ML_ERROR, "Heartbeat write timeout to device %s after %u " + "milliseconds\n", reg->hr_dev_name, + jiffies_to_msecs(jiffies - reg->hr_last_timeout_start)); + + if (o2hb_global_heartbeat_active()) { + spin_lock_irqsave(&o2hb_live_lock, flags); + if (test_bit(reg->hr_region_num, o2hb_quorum_region_bitmap)) + set_bit(reg->hr_region_num, o2hb_failed_region_bitmap); + failed = o2hb_pop_count(&o2hb_failed_region_bitmap, + O2NM_MAX_REGIONS); + quorum = o2hb_pop_count(&o2hb_quorum_region_bitmap, + O2NM_MAX_REGIONS); + spin_unlock_irqrestore(&o2hb_live_lock, flags); + + mlog(ML_HEARTBEAT, "Number of regions %d, failed regions %d\n", + quorum, failed); + + /* + * Fence if the number of failed regions >= half the number + * of quorum regions + */ + if ((failed << 1) < quorum) + return; + } + + o2quo_disk_timeout(); +} + +static void o2hb_arm_write_timeout(struct o2hb_region *reg) +{ + /* Arm writeout only after thread reaches steady state */ + if (atomic_read(®->hr_steady_iterations) != 0) + return; + + mlog(ML_HEARTBEAT, "Queue write timeout for %u ms\n", + O2HB_MAX_WRITE_TIMEOUT_MS); + + if (o2hb_global_heartbeat_active()) { + spin_lock(&o2hb_live_lock); + clear_bit(reg->hr_region_num, o2hb_failed_region_bitmap); + spin_unlock(&o2hb_live_lock); + } + cancel_delayed_work(®->hr_write_timeout_work); + reg->hr_last_timeout_start = jiffies; + schedule_delayed_work(®->hr_write_timeout_work, + msecs_to_jiffies(O2HB_MAX_WRITE_TIMEOUT_MS)); +} + +static void o2hb_disarm_write_timeout(struct o2hb_region *reg) +{ + cancel_delayed_work_sync(®->hr_write_timeout_work); +} + +static inline void o2hb_bio_wait_init(struct o2hb_bio_wait_ctxt *wc) +{ + atomic_set(&wc->wc_num_reqs, 1); + init_completion(&wc->wc_io_complete); + wc->wc_error = 0; +} + +/* Used in error paths too */ +static inline void o2hb_bio_wait_dec(struct o2hb_bio_wait_ctxt *wc, + unsigned int num) +{ + /* sadly atomic_sub_and_test() isn't available on all platforms. The + * good news is that the fast path only completes one at a time */ + while(num--) { + if (atomic_dec_and_test(&wc->wc_num_reqs)) { + BUG_ON(num > 0); + complete(&wc->wc_io_complete); + } + } +} + +static void o2hb_wait_on_io(struct o2hb_region *reg, + struct o2hb_bio_wait_ctxt *wc) +{ + o2hb_bio_wait_dec(wc, 1); + wait_for_completion(&wc->wc_io_complete); +} + +static void o2hb_bio_end_io(struct bio *bio, + int error) +{ + struct o2hb_bio_wait_ctxt *wc = bio->bi_private; + + if (error) { + mlog(ML_ERROR, "IO Error %d\n", error); + wc->wc_error = error; + } + + o2hb_bio_wait_dec(wc, 1); + bio_put(bio); +} + +/* Setup a Bio to cover I/O against num_slots slots starting at + * start_slot. */ +static struct bio *o2hb_setup_one_bio(struct o2hb_region *reg, + struct o2hb_bio_wait_ctxt *wc, + unsigned int *current_slot, + unsigned int max_slots) +{ + int len, current_page; + unsigned int vec_len, vec_start; + unsigned int bits = reg->hr_block_bits; + unsigned int spp = reg->hr_slots_per_page; + unsigned int cs = *current_slot; + struct bio *bio; + struct page *page; + + /* Testing has shown this allocation to take long enough under + * GFP_KERNEL that the local node can get fenced. It would be + * nicest if we could pre-allocate these bios and avoid this + * all together. */ + bio = bio_alloc(GFP_ATOMIC, 16); + if (!bio) { + mlog(ML_ERROR, "Could not alloc slots BIO!\n"); + bio = ERR_PTR(-ENOMEM); + goto bail; + } + + /* Must put everything in 512 byte sectors for the bio... */ + bio->bi_sector = (reg->hr_start_block + cs) << (bits - 9); + bio->bi_bdev = reg->hr_bdev; + bio->bi_private = wc; + bio->bi_end_io = o2hb_bio_end_io; + + vec_start = (cs << bits) % PAGE_CACHE_SIZE; + while(cs < max_slots) { + current_page = cs / spp; + page = reg->hr_slot_data[current_page]; + + vec_len = min(PAGE_CACHE_SIZE - vec_start, + (max_slots-cs) * (PAGE_CACHE_SIZE/spp) ); + + mlog(ML_HB_BIO, "page %d, vec_len = %u, vec_start = %u\n", + current_page, vec_len, vec_start); + + len = bio_add_page(bio, page, vec_len, vec_start); + if (len != vec_len) break; + + cs += vec_len / (PAGE_CACHE_SIZE/spp); + vec_start = 0; + } + +bail: + *current_slot = cs; + return bio; +} + +static int o2hb_read_slots(struct o2hb_region *reg, + unsigned int max_slots) +{ + unsigned int current_slot=0; + int status; + struct o2hb_bio_wait_ctxt wc; + struct bio *bio; + + o2hb_bio_wait_init(&wc); + + while(current_slot < max_slots) { + bio = o2hb_setup_one_bio(reg, &wc, ¤t_slot, max_slots); + if (IS_ERR(bio)) { + status = PTR_ERR(bio); + mlog_errno(status); + goto bail_and_wait; + } + + atomic_inc(&wc.wc_num_reqs); + submit_bio(READ, bio); + } + + status = 0; + +bail_and_wait: + o2hb_wait_on_io(reg, &wc); + if (wc.wc_error && !status) + status = wc.wc_error; + + return status; +} + +static int o2hb_issue_node_write(struct o2hb_region *reg, + struct o2hb_bio_wait_ctxt *write_wc) +{ + int status; + unsigned int slot; + struct bio *bio; + + o2hb_bio_wait_init(write_wc); + + slot = o2nm_this_node(); + + bio = o2hb_setup_one_bio(reg, write_wc, &slot, slot+1); + if (IS_ERR(bio)) { + status = PTR_ERR(bio); + mlog_errno(status); + goto bail; + } + + atomic_inc(&write_wc->wc_num_reqs); + submit_bio(WRITE, bio); + + status = 0; +bail: + return status; +} + +static u32 o2hb_compute_block_crc_le(struct o2hb_region *reg, + struct o2hb_disk_heartbeat_block *hb_block) +{ + __le32 old_cksum; + u32 ret; + + /* We want to compute the block crc with a 0 value in the + * hb_cksum field. Save it off here and replace after the + * crc. */ + old_cksum = hb_block->hb_cksum; + hb_block->hb_cksum = 0; + + ret = crc32_le(0, (unsigned char *) hb_block, reg->hr_block_bytes); + + hb_block->hb_cksum = old_cksum; + + return ret; +} + +static void o2hb_dump_slot(struct o2hb_disk_heartbeat_block *hb_block) +{ + mlog(ML_ERROR, "Dump slot information: seq = 0x%llx, node = %u, " + "cksum = 0x%x, generation 0x%llx\n", + (long long)le64_to_cpu(hb_block->hb_seq), + hb_block->hb_node, le32_to_cpu(hb_block->hb_cksum), + (long long)le64_to_cpu(hb_block->hb_generation)); +} + +static int o2hb_verify_crc(struct o2hb_region *reg, + struct o2hb_disk_heartbeat_block *hb_block) +{ + u32 read, computed; + + read = le32_to_cpu(hb_block->hb_cksum); + computed = o2hb_compute_block_crc_le(reg, hb_block); + + return read == computed; +} + +/* + * Compare the slot data with what we wrote in the last iteration. + * If the match fails, print an appropriate error message. This is to + * detect errors like... another node hearting on the same slot, + * flaky device that is losing writes, etc. + * Returns 1 if check succeeds, 0 otherwise. + */ +static int o2hb_check_own_slot(struct o2hb_region *reg) +{ + struct o2hb_disk_slot *slot; + struct o2hb_disk_heartbeat_block *hb_block; + char *errstr; + + slot = ®->hr_slots[o2nm_this_node()]; + /* Don't check on our 1st timestamp */ + if (!slot->ds_last_time) + return 0; + + hb_block = slot->ds_raw_block; + if (le64_to_cpu(hb_block->hb_seq) == slot->ds_last_time && + le64_to_cpu(hb_block->hb_generation) == slot->ds_last_generation && + hb_block->hb_node == slot->ds_node_num) + return 1; + +#define ERRSTR1 "Another node is heartbeating on device" +#define ERRSTR2 "Heartbeat generation mismatch on device" +#define ERRSTR3 "Heartbeat sequence mismatch on device" + + if (hb_block->hb_node != slot->ds_node_num) + errstr = ERRSTR1; + else if (le64_to_cpu(hb_block->hb_generation) != + slot->ds_last_generation) + errstr = ERRSTR2; + else + errstr = ERRSTR3; + + mlog(ML_ERROR, "%s (%s): expected(%u:0x%llx, 0x%llx), " + "ondisk(%u:0x%llx, 0x%llx)\n", errstr, reg->hr_dev_name, + slot->ds_node_num, (unsigned long long)slot->ds_last_generation, + (unsigned long long)slot->ds_last_time, hb_block->hb_node, + (unsigned long long)le64_to_cpu(hb_block->hb_generation), + (unsigned long long)le64_to_cpu(hb_block->hb_seq)); + + return 0; +} + +static inline void o2hb_prepare_block(struct o2hb_region *reg, + u64 generation) +{ + int node_num; + u64 cputime; + struct o2hb_disk_slot *slot; + struct o2hb_disk_heartbeat_block *hb_block; + + node_num = o2nm_this_node(); + slot = ®->hr_slots[node_num]; + + hb_block = (struct o2hb_disk_heartbeat_block *)slot->ds_raw_block; + memset(hb_block, 0, reg->hr_block_bytes); + /* TODO: time stuff */ + cputime = CURRENT_TIME.tv_sec; + if (!cputime) + cputime = 1; + + hb_block->hb_seq = cpu_to_le64(cputime); + hb_block->hb_node = node_num; + hb_block->hb_generation = cpu_to_le64(generation); + hb_block->hb_dead_ms = cpu_to_le32(o2hb_dead_threshold * O2HB_REGION_TIMEOUT_MS); + + /* This step must always happen last! */ + hb_block->hb_cksum = cpu_to_le32(o2hb_compute_block_crc_le(reg, + hb_block)); + + mlog(ML_HB_BIO, "our node generation = 0x%llx, cksum = 0x%x\n", + (long long)generation, + le32_to_cpu(hb_block->hb_cksum)); +} + +static void o2hb_fire_callbacks(struct o2hb_callback *hbcall, + struct o2nm_node *node, + int idx) +{ + struct list_head *iter; + struct o2hb_callback_func *f; + + list_for_each(iter, &hbcall->list) { + f = list_entry(iter, struct o2hb_callback_func, hc_item); + mlog(ML_HEARTBEAT, "calling funcs %p\n", f); + (f->hc_func)(node, idx, f->hc_data); + } +} + +/* Will run the list in order until we process the passed event */ +static void o2hb_run_event_list(struct o2hb_node_event *queued_event) +{ + int empty; + struct o2hb_callback *hbcall; + struct o2hb_node_event *event; + + spin_lock(&o2hb_live_lock); + empty = list_empty(&queued_event->hn_item); + spin_unlock(&o2hb_live_lock); + if (empty) + return; + + /* Holding callback sem assures we don't alter the callback + * lists when doing this, and serializes ourselves with other + * processes wanting callbacks. */ + down_write(&o2hb_callback_sem); + + spin_lock(&o2hb_live_lock); + while (!list_empty(&o2hb_node_events) + && !list_empty(&queued_event->hn_item)) { + event = list_entry(o2hb_node_events.next, + struct o2hb_node_event, + hn_item); + list_del_init(&event->hn_item); + spin_unlock(&o2hb_live_lock); + + mlog(ML_HEARTBEAT, "Node %s event for %d\n", + event->hn_event_type == O2HB_NODE_UP_CB ? "UP" : "DOWN", + event->hn_node_num); + + hbcall = hbcall_from_type(event->hn_event_type); + + /* We should *never* have gotten on to the list with a + * bad type... This isn't something that we should try + * to recover from. */ + BUG_ON(IS_ERR(hbcall)); + + o2hb_fire_callbacks(hbcall, event->hn_node, event->hn_node_num); + + spin_lock(&o2hb_live_lock); + } + spin_unlock(&o2hb_live_lock); + + up_write(&o2hb_callback_sem); +} + +static void o2hb_queue_node_event(struct o2hb_node_event *event, + enum o2hb_callback_type type, + struct o2nm_node *node, + int node_num) +{ + assert_spin_locked(&o2hb_live_lock); + + BUG_ON((!node) && (type != O2HB_NODE_DOWN_CB)); + + event->hn_event_type = type; + event->hn_node = node; + event->hn_node_num = node_num; + + mlog(ML_HEARTBEAT, "Queue node %s event for node %d\n", + type == O2HB_NODE_UP_CB ? "UP" : "DOWN", node_num); + + list_add_tail(&event->hn_item, &o2hb_node_events); +} + +static void o2hb_shutdown_slot(struct o2hb_disk_slot *slot) +{ + struct o2hb_node_event event = + { .hn_item = LIST_HEAD_INIT(event.hn_item), }; + struct o2nm_node *node; + + node = o2nm_get_node_by_num(slot->ds_node_num); + if (!node) + return; + + spin_lock(&o2hb_live_lock); + if (!list_empty(&slot->ds_live_item)) { + mlog(ML_HEARTBEAT, "Shutdown, node %d leaves region\n", + slot->ds_node_num); + + list_del_init(&slot->ds_live_item); + + if (list_empty(&o2hb_live_slots[slot->ds_node_num])) { + clear_bit(slot->ds_node_num, o2hb_live_node_bitmap); + + o2hb_queue_node_event(&event, O2HB_NODE_DOWN_CB, node, + slot->ds_node_num); + } + } + spin_unlock(&o2hb_live_lock); + + o2hb_run_event_list(&event); + + o2nm_node_put(node); +} + +static void o2hb_set_quorum_device(struct o2hb_region *reg) +{ + if (!o2hb_global_heartbeat_active()) + return; + + /* Prevent race with o2hb_heartbeat_group_drop_item() */ + if (kthread_should_stop()) + return; + + /* Tag region as quorum only after thread reaches steady state */ + if (atomic_read(®->hr_steady_iterations) != 0) + return; + + spin_lock(&o2hb_live_lock); + + if (test_bit(reg->hr_region_num, o2hb_quorum_region_bitmap)) + goto unlock; + + /* + * A region can be added to the quorum only when it sees all + * live nodes heartbeat on it. In other words, the region has been + * added to all nodes. + */ + if (memcmp(reg->hr_live_node_bitmap, o2hb_live_node_bitmap, + sizeof(o2hb_live_node_bitmap))) + goto unlock; + + printk(KERN_NOTICE "o2hb: Region %s (%s) is now a quorum device\n", + config_item_name(®->hr_item), reg->hr_dev_name); + + set_bit(reg->hr_region_num, o2hb_quorum_region_bitmap); + + /* + * If global heartbeat active, unpin all regions if the + * region count > CUT_OFF + */ + if (o2hb_pop_count(&o2hb_quorum_region_bitmap, + O2NM_MAX_REGIONS) > O2HB_PIN_CUT_OFF) + o2hb_region_unpin(NULL); +unlock: + spin_unlock(&o2hb_live_lock); +} + +static int o2hb_check_slot(struct o2hb_region *reg, + struct o2hb_disk_slot *slot) +{ + int changed = 0, gen_changed = 0; + struct o2hb_node_event event = + { .hn_item = LIST_HEAD_INIT(event.hn_item), }; + struct o2nm_node *node; + struct o2hb_disk_heartbeat_block *hb_block = reg->hr_tmp_block; + u64 cputime; + unsigned int dead_ms = o2hb_dead_threshold * O2HB_REGION_TIMEOUT_MS; + unsigned int slot_dead_ms; + int tmp; + + memcpy(hb_block, slot->ds_raw_block, reg->hr_block_bytes); + + /* + * If a node is no longer configured but is still in the livemap, we + * may need to clear that bit from the livemap. + */ + node = o2nm_get_node_by_num(slot->ds_node_num); + if (!node) { + spin_lock(&o2hb_live_lock); + tmp = test_bit(slot->ds_node_num, o2hb_live_node_bitmap); + spin_unlock(&o2hb_live_lock); + if (!tmp) + return 0; + } + + if (!o2hb_verify_crc(reg, hb_block)) { + /* all paths from here will drop o2hb_live_lock for + * us. */ + spin_lock(&o2hb_live_lock); + + /* Don't print an error on the console in this case - + * a freshly formatted heartbeat area will not have a + * crc set on it. */ + if (list_empty(&slot->ds_live_item)) + goto out; + + /* The node is live but pushed out a bad crc. We + * consider it a transient miss but don't populate any + * other values as they may be junk. */ + mlog(ML_ERROR, "Node %d has written a bad crc to %s\n", + slot->ds_node_num, reg->hr_dev_name); + o2hb_dump_slot(hb_block); + + slot->ds_equal_samples++; + goto fire_callbacks; + } + + /* we don't care if these wrap.. the state transitions below + * clear at the right places */ + cputime = le64_to_cpu(hb_block->hb_seq); + if (slot->ds_last_time != cputime) + slot->ds_changed_samples++; + else + slot->ds_equal_samples++; + slot->ds_last_time = cputime; + + /* The node changed heartbeat generations. We assume this to + * mean it dropped off but came back before we timed out. We + * want to consider it down for the time being but don't want + * to lose any changed_samples state we might build up to + * considering it live again. */ + if (slot->ds_last_generation != le64_to_cpu(hb_block->hb_generation)) { + gen_changed = 1; + slot->ds_equal_samples = 0; + mlog(ML_HEARTBEAT, "Node %d changed generation (0x%llx " + "to 0x%llx)\n", slot->ds_node_num, + (long long)slot->ds_last_generation, + (long long)le64_to_cpu(hb_block->hb_generation)); + } + + slot->ds_last_generation = le64_to_cpu(hb_block->hb_generation); + + mlog(ML_HEARTBEAT, "Slot %d gen 0x%llx cksum 0x%x " + "seq %llu last %llu changed %u equal %u\n", + slot->ds_node_num, (long long)slot->ds_last_generation, + le32_to_cpu(hb_block->hb_cksum), + (unsigned long long)le64_to_cpu(hb_block->hb_seq), + (unsigned long long)slot->ds_last_time, slot->ds_changed_samples, + slot->ds_equal_samples); + + spin_lock(&o2hb_live_lock); + +fire_callbacks: + /* dead nodes only come to life after some number of + * changes at any time during their dead time */ + if (list_empty(&slot->ds_live_item) && + slot->ds_changed_samples >= O2HB_LIVE_THRESHOLD) { + mlog(ML_HEARTBEAT, "Node %d (id 0x%llx) joined my region\n", + slot->ds_node_num, (long long)slot->ds_last_generation); + + set_bit(slot->ds_node_num, reg->hr_live_node_bitmap); + + /* first on the list generates a callback */ + if (list_empty(&o2hb_live_slots[slot->ds_node_num])) { + mlog(ML_HEARTBEAT, "o2hb: Add node %d to live nodes " + "bitmap\n", slot->ds_node_num); + set_bit(slot->ds_node_num, o2hb_live_node_bitmap); + + o2hb_queue_node_event(&event, O2HB_NODE_UP_CB, node, + slot->ds_node_num); + + changed = 1; + } + + list_add_tail(&slot->ds_live_item, + &o2hb_live_slots[slot->ds_node_num]); + + slot->ds_equal_samples = 0; + + /* We want to be sure that all nodes agree on the + * number of milliseconds before a node will be + * considered dead. The self-fencing timeout is + * computed from this value, and a discrepancy might + * result in heartbeat calling a node dead when it + * hasn't self-fenced yet. */ + slot_dead_ms = le32_to_cpu(hb_block->hb_dead_ms); + if (slot_dead_ms && slot_dead_ms != dead_ms) { + /* TODO: Perhaps we can fail the region here. */ + mlog(ML_ERROR, "Node %d on device %s has a dead count " + "of %u ms, but our count is %u ms.\n" + "Please double check your configuration values " + "for 'O2CB_HEARTBEAT_THRESHOLD'\n", + slot->ds_node_num, reg->hr_dev_name, slot_dead_ms, + dead_ms); + } + goto out; + } + + /* if the list is dead, we're done.. */ + if (list_empty(&slot->ds_live_item)) + goto out; + + /* live nodes only go dead after enough consequtive missed + * samples.. reset the missed counter whenever we see + * activity */ + if (slot->ds_equal_samples >= o2hb_dead_threshold || gen_changed) { + mlog(ML_HEARTBEAT, "Node %d left my region\n", + slot->ds_node_num); + + clear_bit(slot->ds_node_num, reg->hr_live_node_bitmap); + + /* last off the live_slot generates a callback */ + list_del_init(&slot->ds_live_item); + if (list_empty(&o2hb_live_slots[slot->ds_node_num])) { + mlog(ML_HEARTBEAT, "o2hb: Remove node %d from live " + "nodes bitmap\n", slot->ds_node_num); + clear_bit(slot->ds_node_num, o2hb_live_node_bitmap); + + /* node can be null */ + o2hb_queue_node_event(&event, O2HB_NODE_DOWN_CB, + node, slot->ds_node_num); + + changed = 1; + } + + /* We don't clear this because the node is still + * actually writing new blocks. */ + if (!gen_changed) + slot->ds_changed_samples = 0; + goto out; + } + if (slot->ds_changed_samples) { + slot->ds_changed_samples = 0; + slot->ds_equal_samples = 0; + } +out: + spin_unlock(&o2hb_live_lock); + + o2hb_run_event_list(&event); + + if (node) + o2nm_node_put(node); + return changed; +} + +/* This could be faster if we just implmented a find_last_bit, but I + * don't think the circumstances warrant it. */ +static int o2hb_highest_node(unsigned long *nodes, + int numbits) +{ + int highest, node; + + highest = numbits; + node = -1; + while ((node = find_next_bit(nodes, numbits, node + 1)) != -1) { + if (node >= numbits) + break; + + highest = node; + } + + return highest; +} + +static int o2hb_do_disk_heartbeat(struct o2hb_region *reg) +{ + int i, ret, highest_node; + int membership_change = 0, own_slot_ok = 0; + unsigned long configured_nodes[BITS_TO_LONGS(O2NM_MAX_NODES)]; + unsigned long live_node_bitmap[BITS_TO_LONGS(O2NM_MAX_NODES)]; + struct o2hb_bio_wait_ctxt write_wc; + + ret = o2nm_configured_node_map(configured_nodes, + sizeof(configured_nodes)); + if (ret) { + mlog_errno(ret); + goto bail; + } + + /* + * If a node is not configured but is in the livemap, we still need + * to read the slot so as to be able to remove it from the livemap. + */ + o2hb_fill_node_map(live_node_bitmap, sizeof(live_node_bitmap)); + i = -1; + while ((i = find_next_bit(live_node_bitmap, + O2NM_MAX_NODES, i + 1)) < O2NM_MAX_NODES) { + set_bit(i, configured_nodes); + } + + highest_node = o2hb_highest_node(configured_nodes, O2NM_MAX_NODES); + if (highest_node >= O2NM_MAX_NODES) { + mlog(ML_NOTICE, "o2hb: No configured nodes found!\n"); + ret = -EINVAL; + goto bail; + } + + /* No sense in reading the slots of nodes that don't exist + * yet. Of course, if the node definitions have holes in them + * then we're reading an empty slot anyway... Consider this + * best-effort. */ + ret = o2hb_read_slots(reg, highest_node + 1); + if (ret < 0) { + mlog_errno(ret); + goto bail; + } + + /* With an up to date view of the slots, we can check that no + * other node has been improperly configured to heartbeat in + * our slot. */ + own_slot_ok = o2hb_check_own_slot(reg); + + /* fill in the proper info for our next heartbeat */ + o2hb_prepare_block(reg, reg->hr_generation); + + ret = o2hb_issue_node_write(reg, &write_wc); + if (ret < 0) { + mlog_errno(ret); + goto bail; + } + + i = -1; + while((i = find_next_bit(configured_nodes, + O2NM_MAX_NODES, i + 1)) < O2NM_MAX_NODES) { + membership_change |= o2hb_check_slot(reg, ®->hr_slots[i]); + } + + /* + * We have to be sure we've advertised ourselves on disk + * before we can go to steady state. This ensures that + * people we find in our steady state have seen us. + */ + o2hb_wait_on_io(reg, &write_wc); + if (write_wc.wc_error) { + /* Do not re-arm the write timeout on I/O error - we + * can't be sure that the new block ever made it to + * disk */ + mlog(ML_ERROR, "Write error %d on device \"%s\"\n", + write_wc.wc_error, reg->hr_dev_name); + ret = write_wc.wc_error; + goto bail; + } + + /* Skip disarming the timeout if own slot has stale/bad data */ + if (own_slot_ok) { + o2hb_set_quorum_device(reg); + o2hb_arm_write_timeout(reg); + } + +bail: + /* let the person who launched us know when things are steady */ + if (atomic_read(®->hr_steady_iterations) != 0) { + if (!ret && own_slot_ok && !membership_change) { + if (atomic_dec_and_test(®->hr_steady_iterations)) + wake_up(&o2hb_steady_queue); + } + } + + if (atomic_read(®->hr_steady_iterations) != 0) { + if (atomic_dec_and_test(®->hr_unsteady_iterations)) { + printk(KERN_NOTICE "o2hb: Unable to stabilize " + "heartbeart on region %s (%s)\n", + config_item_name(®->hr_item), + reg->hr_dev_name); + atomic_set(®->hr_steady_iterations, 0); + reg->hr_aborted_start = 1; + wake_up(&o2hb_steady_queue); + ret = -EIO; + } + } + + return ret; +} + +/* Subtract b from a, storing the result in a. a *must* have a larger + * value than b. */ +static void o2hb_tv_subtract(struct timeval *a, + struct timeval *b) +{ + /* just return 0 when a is after b */ + if (a->tv_sec < b->tv_sec || + (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec)) { + a->tv_sec = 0; + a->tv_usec = 0; + return; + } + + a->tv_sec -= b->tv_sec; + a->tv_usec -= b->tv_usec; + while ( a->tv_usec < 0 ) { + a->tv_sec--; + a->tv_usec += 1000000; + } +} + +static unsigned int o2hb_elapsed_msecs(struct timeval *start, + struct timeval *end) +{ + struct timeval res = *end; + + o2hb_tv_subtract(&res, start); + + return res.tv_sec * 1000 + res.tv_usec / 1000; +} + +/* + * we ride the region ref that the region dir holds. before the region + * dir is removed and drops it ref it will wait to tear down this + * thread. + */ +static int o2hb_thread(void *data) +{ + int i, ret; + struct o2hb_region *reg = data; + struct o2hb_bio_wait_ctxt write_wc; + struct timeval before_hb, after_hb; + unsigned int elapsed_msec; + + mlog(ML_HEARTBEAT|ML_KTHREAD, "hb thread running\n"); + + set_user_nice(current, -20); + + /* Pin node */ + o2nm_depend_this_node(); + + while (!kthread_should_stop() && + !reg->hr_unclean_stop && !reg->hr_aborted_start) { + /* We track the time spent inside + * o2hb_do_disk_heartbeat so that we avoid more than + * hr_timeout_ms between disk writes. On busy systems + * this should result in a heartbeat which is less + * likely to time itself out. */ + do_gettimeofday(&before_hb); + + ret = o2hb_do_disk_heartbeat(reg); + + do_gettimeofday(&after_hb); + elapsed_msec = o2hb_elapsed_msecs(&before_hb, &after_hb); + + mlog(ML_HEARTBEAT, + "start = %lu.%lu, end = %lu.%lu, msec = %u\n", + before_hb.tv_sec, (unsigned long) before_hb.tv_usec, + after_hb.tv_sec, (unsigned long) after_hb.tv_usec, + elapsed_msec); + + if (!kthread_should_stop() && + elapsed_msec < reg->hr_timeout_ms) { + /* the kthread api has blocked signals for us so no + * need to record the return value. */ + msleep_interruptible(reg->hr_timeout_ms - elapsed_msec); + } + } + + o2hb_disarm_write_timeout(reg); + + /* unclean stop is only used in very bad situation */ + for(i = 0; !reg->hr_unclean_stop && i < reg->hr_blocks; i++) + o2hb_shutdown_slot(®->hr_slots[i]); + + /* Explicit down notification - avoid forcing the other nodes + * to timeout on this region when we could just as easily + * write a clear generation - thus indicating to them that + * this node has left this region. + */ + if (!reg->hr_unclean_stop && !reg->hr_aborted_start) { + o2hb_prepare_block(reg, 0); + ret = o2hb_issue_node_write(reg, &write_wc); + if (ret == 0) + o2hb_wait_on_io(reg, &write_wc); + else + mlog_errno(ret); + } + + /* Unpin node */ + o2nm_undepend_this_node(); + + mlog(ML_HEARTBEAT|ML_KTHREAD, "o2hb thread exiting\n"); + + return 0; +} + +#ifdef CONFIG_DEBUG_FS +static int o2hb_debug_open(struct inode *inode, struct file *file) +{ + struct o2hb_debug_buf *db = inode->i_private; + struct o2hb_region *reg; + unsigned long map[BITS_TO_LONGS(O2NM_MAX_NODES)]; + unsigned long lts; + char *buf = NULL; + int i = -1; + int out = 0; + + /* max_nodes should be the largest bitmap we pass here */ + BUG_ON(sizeof(map) < db->db_size); + + buf = kmalloc(PAGE_SIZE, GFP_KERNEL); + if (!buf) + goto bail; + + switch (db->db_type) { + case O2HB_DB_TYPE_LIVENODES: + case O2HB_DB_TYPE_LIVEREGIONS: + case O2HB_DB_TYPE_QUORUMREGIONS: + case O2HB_DB_TYPE_FAILEDREGIONS: + spin_lock(&o2hb_live_lock); + memcpy(map, db->db_data, db->db_size); + spin_unlock(&o2hb_live_lock); + break; + + case O2HB_DB_TYPE_REGION_LIVENODES: + spin_lock(&o2hb_live_lock); + reg = (struct o2hb_region *)db->db_data; + memcpy(map, reg->hr_live_node_bitmap, db->db_size); + spin_unlock(&o2hb_live_lock); + break; + + case O2HB_DB_TYPE_REGION_NUMBER: + reg = (struct o2hb_region *)db->db_data; + out += snprintf(buf + out, PAGE_SIZE - out, "%d\n", + reg->hr_region_num); + goto done; + + case O2HB_DB_TYPE_REGION_ELAPSED_TIME: + reg = (struct o2hb_region *)db->db_data; + lts = reg->hr_last_timeout_start; + /* If 0, it has never been set before */ + if (lts) + lts = jiffies_to_msecs(jiffies - lts); + out += snprintf(buf + out, PAGE_SIZE - out, "%lu\n", lts); + goto done; + + case O2HB_DB_TYPE_REGION_PINNED: + reg = (struct o2hb_region *)db->db_data; + out += snprintf(buf + out, PAGE_SIZE - out, "%u\n", + !!reg->hr_item_pinned); + goto done; + + default: + goto done; + } + + while ((i = find_next_bit(map, db->db_len, i + 1)) < db->db_len) + out += snprintf(buf + out, PAGE_SIZE - out, "%d ", i); + out += snprintf(buf + out, PAGE_SIZE - out, "\n"); + +done: + i_size_write(inode, out); + + file->private_data = buf; + + return 0; +bail: + return -ENOMEM; +} + +static int o2hb_debug_release(struct inode *inode, struct file *file) +{ + kfree(file->private_data); + return 0; +} + +static ssize_t o2hb_debug_read(struct file *file, char __user *buf, + size_t nbytes, loff_t *ppos) +{ + return simple_read_from_buffer(buf, nbytes, ppos, file->private_data, + i_size_read(file->f_mapping->host)); +} +#else +static int o2hb_debug_open(struct inode *inode, struct file *file) +{ + return 0; +} +static int o2hb_debug_release(struct inode *inode, struct file *file) +{ + return 0; +} +static ssize_t o2hb_debug_read(struct file *file, char __user *buf, + size_t nbytes, loff_t *ppos) +{ + return 0; +} +#endif /* CONFIG_DEBUG_FS */ + +static const struct file_operations o2hb_debug_fops = { + .open = o2hb_debug_open, + .release = o2hb_debug_release, + .read = o2hb_debug_read, + .llseek = generic_file_llseek, +}; + +void o2hb_exit(void) +{ + kfree(o2hb_db_livenodes); + kfree(o2hb_db_liveregions); + kfree(o2hb_db_quorumregions); + kfree(o2hb_db_failedregions); + debugfs_remove(o2hb_debug_failedregions); + debugfs_remove(o2hb_debug_quorumregions); + debugfs_remove(o2hb_debug_liveregions); + debugfs_remove(o2hb_debug_livenodes); + debugfs_remove(o2hb_debug_dir); +} + +static struct dentry *o2hb_debug_create(const char *name, struct dentry *dir, + struct o2hb_debug_buf **db, int db_len, + int type, int size, int len, void *data) +{ + *db = kmalloc(db_len, GFP_KERNEL); + if (!*db) + return NULL; + + (*db)->db_type = type; + (*db)->db_size = size; + (*db)->db_len = len; + (*db)->db_data = data; + + return debugfs_create_file(name, S_IFREG|S_IRUSR, dir, *db, + &o2hb_debug_fops); +} + +static int o2hb_debug_init(void) +{ + int ret = -ENOMEM; + + o2hb_debug_dir = debugfs_create_dir(O2HB_DEBUG_DIR, NULL); + if (!o2hb_debug_dir) { + mlog_errno(ret); + goto bail; + } + + o2hb_debug_livenodes = o2hb_debug_create(O2HB_DEBUG_LIVENODES, + o2hb_debug_dir, + &o2hb_db_livenodes, + sizeof(*o2hb_db_livenodes), + O2HB_DB_TYPE_LIVENODES, + sizeof(o2hb_live_node_bitmap), + O2NM_MAX_NODES, + o2hb_live_node_bitmap); + if (!o2hb_debug_livenodes) { + mlog_errno(ret); + goto bail; + } + + o2hb_debug_liveregions = o2hb_debug_create(O2HB_DEBUG_LIVEREGIONS, + o2hb_debug_dir, + &o2hb_db_liveregions, + sizeof(*o2hb_db_liveregions), + O2HB_DB_TYPE_LIVEREGIONS, + sizeof(o2hb_live_region_bitmap), + O2NM_MAX_REGIONS, + o2hb_live_region_bitmap); + if (!o2hb_debug_liveregions) { + mlog_errno(ret); + goto bail; + } + + o2hb_debug_quorumregions = + o2hb_debug_create(O2HB_DEBUG_QUORUMREGIONS, + o2hb_debug_dir, + &o2hb_db_quorumregions, + sizeof(*o2hb_db_quorumregions), + O2HB_DB_TYPE_QUORUMREGIONS, + sizeof(o2hb_quorum_region_bitmap), + O2NM_MAX_REGIONS, + o2hb_quorum_region_bitmap); + if (!o2hb_debug_quorumregions) { + mlog_errno(ret); + goto bail; + } + + o2hb_debug_failedregions = + o2hb_debug_create(O2HB_DEBUG_FAILEDREGIONS, + o2hb_debug_dir, + &o2hb_db_failedregions, + sizeof(*o2hb_db_failedregions), + O2HB_DB_TYPE_FAILEDREGIONS, + sizeof(o2hb_failed_region_bitmap), + O2NM_MAX_REGIONS, + o2hb_failed_region_bitmap); + if (!o2hb_debug_failedregions) { + mlog_errno(ret); + goto bail; + } + + ret = 0; +bail: + if (ret) + o2hb_exit(); + + return ret; +} + +int o2hb_init(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(o2hb_callbacks); i++) + INIT_LIST_HEAD(&o2hb_callbacks[i].list); + + for (i = 0; i < ARRAY_SIZE(o2hb_live_slots); i++) + INIT_LIST_HEAD(&o2hb_live_slots[i]); + + INIT_LIST_HEAD(&o2hb_node_events); + + memset(o2hb_live_node_bitmap, 0, sizeof(o2hb_live_node_bitmap)); + memset(o2hb_region_bitmap, 0, sizeof(o2hb_region_bitmap)); + memset(o2hb_live_region_bitmap, 0, sizeof(o2hb_live_region_bitmap)); + memset(o2hb_quorum_region_bitmap, 0, sizeof(o2hb_quorum_region_bitmap)); + memset(o2hb_failed_region_bitmap, 0, sizeof(o2hb_failed_region_bitmap)); + + o2hb_dependent_users = 0; + + return o2hb_debug_init(); +} + +/* if we're already in a callback then we're already serialized by the sem */ +static void o2hb_fill_node_map_from_callback(unsigned long *map, + unsigned bytes) +{ + BUG_ON(bytes < (BITS_TO_LONGS(O2NM_MAX_NODES) * sizeof(unsigned long))); + + memcpy(map, &o2hb_live_node_bitmap, bytes); +} + +/* + * get a map of all nodes that are heartbeating in any regions + */ +void o2hb_fill_node_map(unsigned long *map, unsigned bytes) +{ + /* callers want to serialize this map and callbacks so that they + * can trust that they don't miss nodes coming to the party */ + down_read(&o2hb_callback_sem); + spin_lock(&o2hb_live_lock); + o2hb_fill_node_map_from_callback(map, bytes); + spin_unlock(&o2hb_live_lock); + up_read(&o2hb_callback_sem); +} +EXPORT_SYMBOL_GPL(o2hb_fill_node_map); + +/* + * heartbeat configfs bits. The heartbeat set is a default set under + * the cluster set in nodemanager.c. + */ + +static struct o2hb_region *to_o2hb_region(struct config_item *item) +{ + return item ? container_of(item, struct o2hb_region, hr_item) : NULL; +} + +/* drop_item only drops its ref after killing the thread, nothing should + * be using the region anymore. this has to clean up any state that + * attributes might have built up. */ +static void o2hb_region_release(struct config_item *item) +{ + int i; + struct page *page; + struct o2hb_region *reg = to_o2hb_region(item); + + mlog(ML_HEARTBEAT, "hb region release (%s)\n", reg->hr_dev_name); + + if (reg->hr_tmp_block) + kfree(reg->hr_tmp_block); + + if (reg->hr_slot_data) { + for (i = 0; i < reg->hr_num_pages; i++) { + page = reg->hr_slot_data[i]; + if (page) + __free_page(page); + } + kfree(reg->hr_slot_data); + } + + if (reg->hr_bdev) + blkdev_put(reg->hr_bdev, FMODE_READ|FMODE_WRITE); + + if (reg->hr_slots) + kfree(reg->hr_slots); + + kfree(reg->hr_db_regnum); + kfree(reg->hr_db_livenodes); + debugfs_remove(reg->hr_debug_livenodes); + debugfs_remove(reg->hr_debug_regnum); + debugfs_remove(reg->hr_debug_elapsed_time); + debugfs_remove(reg->hr_debug_pinned); + debugfs_remove(reg->hr_debug_dir); + + spin_lock(&o2hb_live_lock); + list_del(®->hr_all_item); + spin_unlock(&o2hb_live_lock); + + kfree(reg); +} + +static int o2hb_read_block_input(struct o2hb_region *reg, + const char *page, + size_t count, + unsigned long *ret_bytes, + unsigned int *ret_bits) +{ + unsigned long bytes; + char *p = (char *)page; + + bytes = simple_strtoul(p, &p, 0); + if (!p || (*p && (*p != '\n'))) + return -EINVAL; + + /* Heartbeat and fs min / max block sizes are the same. */ + if (bytes > 4096 || bytes < 512) + return -ERANGE; + if (hweight16(bytes) != 1) + return -EINVAL; + + if (ret_bytes) + *ret_bytes = bytes; + if (ret_bits) + *ret_bits = ffs(bytes) - 1; + + return 0; +} + +static ssize_t o2hb_region_block_bytes_read(struct o2hb_region *reg, + char *page) +{ + return sprintf(page, "%u\n", reg->hr_block_bytes); +} + +static ssize_t o2hb_region_block_bytes_write(struct o2hb_region *reg, + const char *page, + size_t count) +{ + int status; + unsigned long block_bytes; + unsigned int block_bits; + + if (reg->hr_bdev) + return -EINVAL; + + status = o2hb_read_block_input(reg, page, count, + &block_bytes, &block_bits); + if (status) + return status; + + reg->hr_block_bytes = (unsigned int)block_bytes; + reg->hr_block_bits = block_bits; + + return count; +} + +static ssize_t o2hb_region_start_block_read(struct o2hb_region *reg, + char *page) +{ + return sprintf(page, "%llu\n", reg->hr_start_block); +} + +static ssize_t o2hb_region_start_block_write(struct o2hb_region *reg, + const char *page, + size_t count) +{ + unsigned long long tmp; + char *p = (char *)page; + + if (reg->hr_bdev) + return -EINVAL; + + tmp = simple_strtoull(p, &p, 0); + if (!p || (*p && (*p != '\n'))) + return -EINVAL; + + reg->hr_start_block = tmp; + + return count; +} + +static ssize_t o2hb_region_blocks_read(struct o2hb_region *reg, + char *page) +{ + return sprintf(page, "%d\n", reg->hr_blocks); +} + +static ssize_t o2hb_region_blocks_write(struct o2hb_region *reg, + const char *page, + size_t count) +{ + unsigned long tmp; + char *p = (char *)page; + + if (reg->hr_bdev) + return -EINVAL; + + tmp = simple_strtoul(p, &p, 0); + if (!p || (*p && (*p != '\n'))) + return -EINVAL; + + if (tmp > O2NM_MAX_NODES || tmp == 0) + return -ERANGE; + + reg->hr_blocks = (unsigned int)tmp; + + return count; +} + +static ssize_t o2hb_region_dev_read(struct o2hb_region *reg, + char *page) +{ + unsigned int ret = 0; + + if (reg->hr_bdev) + ret = sprintf(page, "%s\n", reg->hr_dev_name); + + return ret; +} + +static void o2hb_init_region_params(struct o2hb_region *reg) +{ + reg->hr_slots_per_page = PAGE_CACHE_SIZE >> reg->hr_block_bits; + reg->hr_timeout_ms = O2HB_REGION_TIMEOUT_MS; + + mlog(ML_HEARTBEAT, "hr_start_block = %llu, hr_blocks = %u\n", + reg->hr_start_block, reg->hr_blocks); + mlog(ML_HEARTBEAT, "hr_block_bytes = %u, hr_block_bits = %u\n", + reg->hr_block_bytes, reg->hr_block_bits); + mlog(ML_HEARTBEAT, "hr_timeout_ms = %u\n", reg->hr_timeout_ms); + mlog(ML_HEARTBEAT, "dead threshold = %u\n", o2hb_dead_threshold); +} + +static int o2hb_map_slot_data(struct o2hb_region *reg) +{ + int i, j; + unsigned int last_slot; + unsigned int spp = reg->hr_slots_per_page; + struct page *page; + char *raw; + struct o2hb_disk_slot *slot; + + reg->hr_tmp_block = kmalloc(reg->hr_block_bytes, GFP_KERNEL); + if (reg->hr_tmp_block == NULL) { + mlog_errno(-ENOMEM); + return -ENOMEM; + } + + reg->hr_slots = kcalloc(reg->hr_blocks, + sizeof(struct o2hb_disk_slot), GFP_KERNEL); + if (reg->hr_slots == NULL) { + mlog_errno(-ENOMEM); + return -ENOMEM; + } + + for(i = 0; i < reg->hr_blocks; i++) { + slot = ®->hr_slots[i]; + slot->ds_node_num = i; + INIT_LIST_HEAD(&slot->ds_live_item); + slot->ds_raw_block = NULL; + } + + reg->hr_num_pages = (reg->hr_blocks + spp - 1) / spp; + mlog(ML_HEARTBEAT, "Going to require %u pages to cover %u blocks " + "at %u blocks per page\n", + reg->hr_num_pages, reg->hr_blocks, spp); + + reg->hr_slot_data = kcalloc(reg->hr_num_pages, sizeof(struct page *), + GFP_KERNEL); + if (!reg->hr_slot_data) { + mlog_errno(-ENOMEM); + return -ENOMEM; + } + + for(i = 0; i < reg->hr_num_pages; i++) { + page = alloc_page(GFP_KERNEL); + if (!page) { + mlog_errno(-ENOMEM); + return -ENOMEM; + } + + reg->hr_slot_data[i] = page; + + last_slot = i * spp; + raw = page_address(page); + for (j = 0; + (j < spp) && ((j + last_slot) < reg->hr_blocks); + j++) { + BUG_ON((j + last_slot) >= reg->hr_blocks); + + slot = ®->hr_slots[j + last_slot]; + slot->ds_raw_block = + (struct o2hb_disk_heartbeat_block *) raw; + + raw += reg->hr_block_bytes; + } + } + + return 0; +} + +/* Read in all the slots available and populate the tracking + * structures so that we can start with a baseline idea of what's + * there. */ +static int o2hb_populate_slot_data(struct o2hb_region *reg) +{ + int ret, i; + struct o2hb_disk_slot *slot; + struct o2hb_disk_heartbeat_block *hb_block; + + ret = o2hb_read_slots(reg, reg->hr_blocks); + if (ret) { + mlog_errno(ret); + goto out; + } + + /* We only want to get an idea of the values initially in each + * slot, so we do no verification - o2hb_check_slot will + * actually determine if each configured slot is valid and + * whether any values have changed. */ + for(i = 0; i < reg->hr_blocks; i++) { + slot = ®->hr_slots[i]; + hb_block = (struct o2hb_disk_heartbeat_block *) slot->ds_raw_block; + + /* Only fill the values that o2hb_check_slot uses to + * determine changing slots */ + slot->ds_last_time = le64_to_cpu(hb_block->hb_seq); + slot->ds_last_generation = le64_to_cpu(hb_block->hb_generation); + } + +out: + return ret; +} + +/* this is acting as commit; we set up all of hr_bdev and hr_task or nothing */ +static ssize_t o2hb_region_dev_write(struct o2hb_region *reg, + const char *page, + size_t count) +{ + struct task_struct *hb_task; + long fd; + int sectsize; + char *p = (char *)page; + struct file *filp = NULL; + struct inode *inode = NULL; + ssize_t ret = -EINVAL; + int live_threshold; + + if (reg->hr_bdev) + goto out; + + /* We can't heartbeat without having had our node number + * configured yet. */ + if (o2nm_this_node() == O2NM_MAX_NODES) + goto out; + + fd = simple_strtol(p, &p, 0); + if (!p || (*p && (*p != '\n'))) + goto out; + + if (fd < 0 || fd >= INT_MAX) + goto out; + + filp = fget(fd); + if (filp == NULL) + goto out; + + if (reg->hr_blocks == 0 || reg->hr_start_block == 0 || + reg->hr_block_bytes == 0) + goto out; + + inode = igrab(filp->f_mapping->host); + if (inode == NULL) + goto out; + + if (!S_ISBLK(inode->i_mode)) + goto out; + + reg->hr_bdev = I_BDEV(filp->f_mapping->host); + ret = blkdev_get(reg->hr_bdev, FMODE_WRITE | FMODE_READ, NULL); + if (ret) { + reg->hr_bdev = NULL; + goto out; + } + inode = NULL; + + bdevname(reg->hr_bdev, reg->hr_dev_name); + + sectsize = bdev_logical_block_size(reg->hr_bdev); + if (sectsize != reg->hr_block_bytes) { + mlog(ML_ERROR, + "blocksize %u incorrect for device, expected %d", + reg->hr_block_bytes, sectsize); + ret = -EINVAL; + goto out; + } + + o2hb_init_region_params(reg); + + /* Generation of zero is invalid */ + do { + get_random_bytes(®->hr_generation, + sizeof(reg->hr_generation)); + } while (reg->hr_generation == 0); + + ret = o2hb_map_slot_data(reg); + if (ret) { + mlog_errno(ret); + goto out; + } + + ret = o2hb_populate_slot_data(reg); + if (ret) { + mlog_errno(ret); + goto out; + } + + INIT_DELAYED_WORK(®->hr_write_timeout_work, o2hb_write_timeout); + + /* + * A node is considered live after it has beat LIVE_THRESHOLD + * times. We're not steady until we've given them a chance + * _after_ our first read. + * The default threshold is bare minimum so as to limit the delay + * during mounts. For global heartbeat, the threshold doubled for the + * first region. + */ + live_threshold = O2HB_LIVE_THRESHOLD; + if (o2hb_global_heartbeat_active()) { + spin_lock(&o2hb_live_lock); + if (o2hb_pop_count(&o2hb_region_bitmap, O2NM_MAX_REGIONS) == 1) + live_threshold <<= 1; + spin_unlock(&o2hb_live_lock); + } + ++live_threshold; + atomic_set(®->hr_steady_iterations, live_threshold); + /* unsteady_iterations is double the steady_iterations */ + atomic_set(®->hr_unsteady_iterations, (live_threshold << 1)); + + hb_task = kthread_run(o2hb_thread, reg, "o2hb-%s", + reg->hr_item.ci_name); + if (IS_ERR(hb_task)) { + ret = PTR_ERR(hb_task); + mlog_errno(ret); + goto out; + } + + spin_lock(&o2hb_live_lock); + reg->hr_task = hb_task; + spin_unlock(&o2hb_live_lock); + + ret = wait_event_interruptible(o2hb_steady_queue, + atomic_read(®->hr_steady_iterations) == 0); + if (ret) { + atomic_set(®->hr_steady_iterations, 0); + reg->hr_aborted_start = 1; + } + + if (reg->hr_aborted_start) { + ret = -EIO; + goto out; + } + + /* Ok, we were woken. Make sure it wasn't by drop_item() */ + spin_lock(&o2hb_live_lock); + hb_task = reg->hr_task; + if (o2hb_global_heartbeat_active()) + set_bit(reg->hr_region_num, o2hb_live_region_bitmap); + spin_unlock(&o2hb_live_lock); + + if (hb_task) + ret = count; + else + ret = -EIO; + + if (hb_task && o2hb_global_heartbeat_active()) + printk(KERN_NOTICE "o2hb: Heartbeat started on region %s (%s)\n", + config_item_name(®->hr_item), reg->hr_dev_name); + +out: + if (filp) + fput(filp); + if (inode) + iput(inode); + if (ret < 0) { + if (reg->hr_bdev) { + blkdev_put(reg->hr_bdev, FMODE_READ|FMODE_WRITE); + reg->hr_bdev = NULL; + } + } + return ret; +} + +static ssize_t o2hb_region_pid_read(struct o2hb_region *reg, + char *page) +{ + pid_t pid = 0; + + spin_lock(&o2hb_live_lock); + if (reg->hr_task) + pid = task_pid_nr(reg->hr_task); + spin_unlock(&o2hb_live_lock); + + if (!pid) + return 0; + + return sprintf(page, "%u\n", pid); +} + +struct o2hb_region_attribute { + struct configfs_attribute attr; + ssize_t (*show)(struct o2hb_region *, char *); + ssize_t (*store)(struct o2hb_region *, const char *, size_t); +}; + +static struct o2hb_region_attribute o2hb_region_attr_block_bytes = { + .attr = { .ca_owner = THIS_MODULE, + .ca_name = "block_bytes", + .ca_mode = S_IRUGO | S_IWUSR }, + .show = o2hb_region_block_bytes_read, + .store = o2hb_region_block_bytes_write, +}; + +static struct o2hb_region_attribute o2hb_region_attr_start_block = { + .attr = { .ca_owner = THIS_MODULE, + .ca_name = "start_block", + .ca_mode = S_IRUGO | S_IWUSR }, + .show = o2hb_region_start_block_read, + .store = o2hb_region_start_block_write, +}; + +static struct o2hb_region_attribute o2hb_region_attr_blocks = { + .attr = { .ca_owner = THIS_MODULE, + .ca_name = "blocks", + .ca_mode = S_IRUGO | S_IWUSR }, + .show = o2hb_region_blocks_read, + .store = o2hb_region_blocks_write, +}; + +static struct o2hb_region_attribute o2hb_region_attr_dev = { + .attr = { .ca_owner = THIS_MODULE, + .ca_name = "dev", + .ca_mode = S_IRUGO | S_IWUSR }, + .show = o2hb_region_dev_read, + .store = o2hb_region_dev_write, +}; + +static struct o2hb_region_attribute o2hb_region_attr_pid = { + .attr = { .ca_owner = THIS_MODULE, + .ca_name = "pid", + .ca_mode = S_IRUGO | S_IRUSR }, + .show = o2hb_region_pid_read, +}; + +static struct configfs_attribute *o2hb_region_attrs[] = { + &o2hb_region_attr_block_bytes.attr, + &o2hb_region_attr_start_block.attr, + &o2hb_region_attr_blocks.attr, + &o2hb_region_attr_dev.attr, + &o2hb_region_attr_pid.attr, + NULL, +}; + +static ssize_t o2hb_region_show(struct config_item *item, + struct configfs_attribute *attr, + char *page) +{ + struct o2hb_region *reg = to_o2hb_region(item); + struct o2hb_region_attribute *o2hb_region_attr = + container_of(attr, struct o2hb_region_attribute, attr); + ssize_t ret = 0; + + if (o2hb_region_attr->show) + ret = o2hb_region_attr->show(reg, page); + return ret; +} + +static ssize_t o2hb_region_store(struct config_item *item, + struct configfs_attribute *attr, + const char *page, size_t count) +{ + struct o2hb_region *reg = to_o2hb_region(item); + struct o2hb_region_attribute *o2hb_region_attr = + container_of(attr, struct o2hb_region_attribute, attr); + ssize_t ret = -EINVAL; + + if (o2hb_region_attr->store) + ret = o2hb_region_attr->store(reg, page, count); + return ret; +} + +static struct configfs_item_operations o2hb_region_item_ops = { + .release = o2hb_region_release, + .show_attribute = o2hb_region_show, + .store_attribute = o2hb_region_store, +}; + +static struct config_item_type o2hb_region_type = { + .ct_item_ops = &o2hb_region_item_ops, + .ct_attrs = o2hb_region_attrs, + .ct_owner = THIS_MODULE, +}; + +/* heartbeat set */ + +struct o2hb_heartbeat_group { + struct config_group hs_group; + /* some stuff? */ +}; + +static struct o2hb_heartbeat_group *to_o2hb_heartbeat_group(struct config_group *group) +{ + return group ? + container_of(group, struct o2hb_heartbeat_group, hs_group) + : NULL; +} + +static int o2hb_debug_region_init(struct o2hb_region *reg, struct dentry *dir) +{ + int ret = -ENOMEM; + + reg->hr_debug_dir = + debugfs_create_dir(config_item_name(®->hr_item), dir); + if (!reg->hr_debug_dir) { + mlog_errno(ret); + goto bail; + } + + reg->hr_debug_livenodes = + o2hb_debug_create(O2HB_DEBUG_LIVENODES, + reg->hr_debug_dir, + &(reg->hr_db_livenodes), + sizeof(*(reg->hr_db_livenodes)), + O2HB_DB_TYPE_REGION_LIVENODES, + sizeof(reg->hr_live_node_bitmap), + O2NM_MAX_NODES, reg); + if (!reg->hr_debug_livenodes) { + mlog_errno(ret); + goto bail; + } + + reg->hr_debug_regnum = + o2hb_debug_create(O2HB_DEBUG_REGION_NUMBER, + reg->hr_debug_dir, + &(reg->hr_db_regnum), + sizeof(*(reg->hr_db_regnum)), + O2HB_DB_TYPE_REGION_NUMBER, + 0, O2NM_MAX_NODES, reg); + if (!reg->hr_debug_regnum) { + mlog_errno(ret); + goto bail; + } + + reg->hr_debug_elapsed_time = + o2hb_debug_create(O2HB_DEBUG_REGION_ELAPSED_TIME, + reg->hr_debug_dir, + &(reg->hr_db_elapsed_time), + sizeof(*(reg->hr_db_elapsed_time)), + O2HB_DB_TYPE_REGION_ELAPSED_TIME, + 0, 0, reg); + if (!reg->hr_debug_elapsed_time) { + mlog_errno(ret); + goto bail; + } + + reg->hr_debug_pinned = + o2hb_debug_create(O2HB_DEBUG_REGION_PINNED, + reg->hr_debug_dir, + &(reg->hr_db_pinned), + sizeof(*(reg->hr_db_pinned)), + O2HB_DB_TYPE_REGION_PINNED, + 0, 0, reg); + if (!reg->hr_debug_pinned) { + mlog_errno(ret); + goto bail; + } + + ret = 0; +bail: + return ret; +} + +static struct config_item *o2hb_heartbeat_group_make_item(struct config_group *group, + const char *name) +{ + struct o2hb_region *reg = NULL; + int ret; + + reg = kzalloc(sizeof(struct o2hb_region), GFP_KERNEL); + if (reg == NULL) + return ERR_PTR(-ENOMEM); + + if (strlen(name) > O2HB_MAX_REGION_NAME_LEN) { + ret = -ENAMETOOLONG; + goto free; + } + + spin_lock(&o2hb_live_lock); + reg->hr_region_num = 0; + if (o2hb_global_heartbeat_active()) { + reg->hr_region_num = find_first_zero_bit(o2hb_region_bitmap, + O2NM_MAX_REGIONS); + if (reg->hr_region_num >= O2NM_MAX_REGIONS) { + spin_unlock(&o2hb_live_lock); + ret = -EFBIG; + goto free; + } + set_bit(reg->hr_region_num, o2hb_region_bitmap); + } + list_add_tail(®->hr_all_item, &o2hb_all_regions); + spin_unlock(&o2hb_live_lock); + + config_item_init_type_name(®->hr_item, name, &o2hb_region_type); + + ret = o2hb_debug_region_init(reg, o2hb_debug_dir); + if (ret) { + config_item_put(®->hr_item); + goto free; + } + + return ®->hr_item; +free: + kfree(reg); + return ERR_PTR(ret); +} + +static void o2hb_heartbeat_group_drop_item(struct config_group *group, + struct config_item *item) +{ + struct task_struct *hb_task; + struct o2hb_region *reg = to_o2hb_region(item); + int quorum_region = 0; + + /* stop the thread when the user removes the region dir */ + spin_lock(&o2hb_live_lock); + hb_task = reg->hr_task; + reg->hr_task = NULL; + reg->hr_item_dropped = 1; + spin_unlock(&o2hb_live_lock); + + if (hb_task) + kthread_stop(hb_task); + + if (o2hb_global_heartbeat_active()) { + spin_lock(&o2hb_live_lock); + clear_bit(reg->hr_region_num, o2hb_region_bitmap); + clear_bit(reg->hr_region_num, o2hb_live_region_bitmap); + if (test_bit(reg->hr_region_num, o2hb_quorum_region_bitmap)) + quorum_region = 1; + clear_bit(reg->hr_region_num, o2hb_quorum_region_bitmap); + spin_unlock(&o2hb_live_lock); + printk(KERN_NOTICE "o2hb: Heartbeat %s on region %s (%s)\n", + ((atomic_read(®->hr_steady_iterations) == 0) ? + "stopped" : "start aborted"), config_item_name(item), + reg->hr_dev_name); + } + + /* + * If we're racing a dev_write(), we need to wake them. They will + * check reg->hr_task + */ + if (atomic_read(®->hr_steady_iterations) != 0) { + reg->hr_aborted_start = 1; + atomic_set(®->hr_steady_iterations, 0); + wake_up(&o2hb_steady_queue); + } + + config_item_put(item); + + if (!o2hb_global_heartbeat_active() || !quorum_region) + return; + + /* + * If global heartbeat active and there are dependent users, + * pin all regions if quorum region count <= CUT_OFF + */ + spin_lock(&o2hb_live_lock); + + if (!o2hb_dependent_users) + goto unlock; + + if (o2hb_pop_count(&o2hb_quorum_region_bitmap, + O2NM_MAX_REGIONS) <= O2HB_PIN_CUT_OFF) + o2hb_region_pin(NULL); + +unlock: + spin_unlock(&o2hb_live_lock); +} + +struct o2hb_heartbeat_group_attribute { + struct configfs_attribute attr; + ssize_t (*show)(struct o2hb_heartbeat_group *, char *); + ssize_t (*store)(struct o2hb_heartbeat_group *, const char *, size_t); +}; + +static ssize_t o2hb_heartbeat_group_show(struct config_item *item, + struct configfs_attribute *attr, + char *page) +{ + struct o2hb_heartbeat_group *reg = to_o2hb_heartbeat_group(to_config_group(item)); + struct o2hb_heartbeat_group_attribute *o2hb_heartbeat_group_attr = + container_of(attr, struct o2hb_heartbeat_group_attribute, attr); + ssize_t ret = 0; + + if (o2hb_heartbeat_group_attr->show) + ret = o2hb_heartbeat_group_attr->show(reg, page); + return ret; +} + +static ssize_t o2hb_heartbeat_group_store(struct config_item *item, + struct configfs_attribute *attr, + const char *page, size_t count) +{ + struct o2hb_heartbeat_group *reg = to_o2hb_heartbeat_group(to_config_group(item)); + struct o2hb_heartbeat_group_attribute *o2hb_heartbeat_group_attr = + container_of(attr, struct o2hb_heartbeat_group_attribute, attr); + ssize_t ret = -EINVAL; + + if (o2hb_heartbeat_group_attr->store) + ret = o2hb_heartbeat_group_attr->store(reg, page, count); + return ret; +} + +static ssize_t o2hb_heartbeat_group_threshold_show(struct o2hb_heartbeat_group *group, + char *page) +{ + return sprintf(page, "%u\n", o2hb_dead_threshold); +} + +static ssize_t o2hb_heartbeat_group_threshold_store(struct o2hb_heartbeat_group *group, + const char *page, + size_t count) +{ + unsigned long tmp; + char *p = (char *)page; + + tmp = simple_strtoul(p, &p, 10); + if (!p || (*p && (*p != '\n'))) + return -EINVAL; + + /* this will validate ranges for us. */ + o2hb_dead_threshold_set((unsigned int) tmp); + + return count; +} + +static +ssize_t o2hb_heartbeat_group_mode_show(struct o2hb_heartbeat_group *group, + char *page) +{ + return sprintf(page, "%s\n", + o2hb_heartbeat_mode_desc[o2hb_heartbeat_mode]); +} + +static +ssize_t o2hb_heartbeat_group_mode_store(struct o2hb_heartbeat_group *group, + const char *page, size_t count) +{ + unsigned int i; + int ret; + size_t len; + + len = (page[count - 1] == '\n') ? count - 1 : count; + if (!len) + return -EINVAL; + + for (i = 0; i < O2HB_HEARTBEAT_NUM_MODES; ++i) { + if (strnicmp(page, o2hb_heartbeat_mode_desc[i], len)) + continue; + + ret = o2hb_global_hearbeat_mode_set(i); + if (!ret) + printk(KERN_NOTICE "o2hb: Heartbeat mode set to %s\n", + o2hb_heartbeat_mode_desc[i]); + return count; + } + + return -EINVAL; + +} + +static struct o2hb_heartbeat_group_attribute o2hb_heartbeat_group_attr_threshold = { + .attr = { .ca_owner = THIS_MODULE, + .ca_name = "dead_threshold", + .ca_mode = S_IRUGO | S_IWUSR }, + .show = o2hb_heartbeat_group_threshold_show, + .store = o2hb_heartbeat_group_threshold_store, +}; + +static struct o2hb_heartbeat_group_attribute o2hb_heartbeat_group_attr_mode = { + .attr = { .ca_owner = THIS_MODULE, + .ca_name = "mode", + .ca_mode = S_IRUGO | S_IWUSR }, + .show = o2hb_heartbeat_group_mode_show, + .store = o2hb_heartbeat_group_mode_store, +}; + +static struct configfs_attribute *o2hb_heartbeat_group_attrs[] = { + &o2hb_heartbeat_group_attr_threshold.attr, + &o2hb_heartbeat_group_attr_mode.attr, + NULL, +}; + +static struct configfs_item_operations o2hb_hearbeat_group_item_ops = { + .show_attribute = o2hb_heartbeat_group_show, + .store_attribute = o2hb_heartbeat_group_store, +}; + +static struct configfs_group_operations o2hb_heartbeat_group_group_ops = { + .make_item = o2hb_heartbeat_group_make_item, + .drop_item = o2hb_heartbeat_group_drop_item, +}; + +static struct config_item_type o2hb_heartbeat_group_type = { + .ct_group_ops = &o2hb_heartbeat_group_group_ops, + .ct_item_ops = &o2hb_hearbeat_group_item_ops, + .ct_attrs = o2hb_heartbeat_group_attrs, + .ct_owner = THIS_MODULE, +}; + +/* this is just here to avoid touching group in heartbeat.h which the + * entire damn world #includes */ +struct config_group *o2hb_alloc_hb_set(void) +{ + struct o2hb_heartbeat_group *hs = NULL; + struct config_group *ret = NULL; + + hs = kzalloc(sizeof(struct o2hb_heartbeat_group), GFP_KERNEL); + if (hs == NULL) + goto out; + + config_group_init_type_name(&hs->hs_group, "heartbeat", + &o2hb_heartbeat_group_type); + + ret = &hs->hs_group; +out: + if (ret == NULL) + kfree(hs); + return ret; +} + +void o2hb_free_hb_set(struct config_group *group) +{ + struct o2hb_heartbeat_group *hs = to_o2hb_heartbeat_group(group); + kfree(hs); +} + +/* hb callback registration and issuing */ + +static struct o2hb_callback *hbcall_from_type(enum o2hb_callback_type type) +{ + if (type == O2HB_NUM_CB) + return ERR_PTR(-EINVAL); + + return &o2hb_callbacks[type]; +} + +void o2hb_setup_callback(struct o2hb_callback_func *hc, + enum o2hb_callback_type type, + o2hb_cb_func *func, + void *data, + int priority) +{ + INIT_LIST_HEAD(&hc->hc_item); + hc->hc_func = func; + hc->hc_data = data; + hc->hc_priority = priority; + hc->hc_type = type; + hc->hc_magic = O2HB_CB_MAGIC; +} +EXPORT_SYMBOL_GPL(o2hb_setup_callback); + +/* + * In local heartbeat mode, region_uuid passed matches the dlm domain name. + * In global heartbeat mode, region_uuid passed is NULL. + * + * In local, we only pin the matching region. In global we pin all the active + * regions. + */ +static int o2hb_region_pin(const char *region_uuid) +{ + int ret = 0, found = 0; + struct o2hb_region *reg; + char *uuid; + + assert_spin_locked(&o2hb_live_lock); + + list_for_each_entry(reg, &o2hb_all_regions, hr_all_item) { + uuid = config_item_name(®->hr_item); + + /* local heartbeat */ + if (region_uuid) { + if (strcmp(region_uuid, uuid)) + continue; + found = 1; + } + + if (reg->hr_item_pinned || reg->hr_item_dropped) + goto skip_pin; + + /* Ignore ENOENT only for local hb (userdlm domain) */ + ret = o2nm_depend_item(®->hr_item); + if (!ret) { + mlog(ML_CLUSTER, "Pin region %s\n", uuid); + reg->hr_item_pinned = 1; + } else { + if (ret == -ENOENT && found) + ret = 0; + else { + mlog(ML_ERROR, "Pin region %s fails with %d\n", + uuid, ret); + break; + } + } +skip_pin: + if (found) + break; + } + + return ret; +} + +/* + * In local heartbeat mode, region_uuid passed matches the dlm domain name. + * In global heartbeat mode, region_uuid passed is NULL. + * + * In local, we only unpin the matching region. In global we unpin all the + * active regions. + */ +static void o2hb_region_unpin(const char *region_uuid) +{ + struct o2hb_region *reg; + char *uuid; + int found = 0; + + assert_spin_locked(&o2hb_live_lock); + + list_for_each_entry(reg, &o2hb_all_regions, hr_all_item) { + uuid = config_item_name(®->hr_item); + if (region_uuid) { + if (strcmp(region_uuid, uuid)) + continue; + found = 1; + } + + if (reg->hr_item_pinned) { + mlog(ML_CLUSTER, "Unpin region %s\n", uuid); + o2nm_undepend_item(®->hr_item); + reg->hr_item_pinned = 0; + } + if (found) + break; + } +} + +static int o2hb_region_inc_user(const char *region_uuid) +{ + int ret = 0; + + spin_lock(&o2hb_live_lock); + + /* local heartbeat */ + if (!o2hb_global_heartbeat_active()) { + ret = o2hb_region_pin(region_uuid); + goto unlock; + } + + /* + * if global heartbeat active and this is the first dependent user, + * pin all regions if quorum region count <= CUT_OFF + */ + o2hb_dependent_users++; + if (o2hb_dependent_users > 1) + goto unlock; + + if (o2hb_pop_count(&o2hb_quorum_region_bitmap, + O2NM_MAX_REGIONS) <= O2HB_PIN_CUT_OFF) + ret = o2hb_region_pin(NULL); + +unlock: + spin_unlock(&o2hb_live_lock); + return ret; +} + +void o2hb_region_dec_user(const char *region_uuid) +{ + spin_lock(&o2hb_live_lock); + + /* local heartbeat */ + if (!o2hb_global_heartbeat_active()) { + o2hb_region_unpin(region_uuid); + goto unlock; + } + + /* + * if global heartbeat active and there are no dependent users, + * unpin all quorum regions + */ + o2hb_dependent_users--; + if (!o2hb_dependent_users) + o2hb_region_unpin(NULL); + +unlock: + spin_unlock(&o2hb_live_lock); +} + +int o2hb_register_callback(const char *region_uuid, + struct o2hb_callback_func *hc) +{ + struct o2hb_callback_func *tmp; + struct list_head *iter; + struct o2hb_callback *hbcall; + int ret; + + BUG_ON(hc->hc_magic != O2HB_CB_MAGIC); + BUG_ON(!list_empty(&hc->hc_item)); + + hbcall = hbcall_from_type(hc->hc_type); + if (IS_ERR(hbcall)) { + ret = PTR_ERR(hbcall); + goto out; + } + + if (region_uuid) { + ret = o2hb_region_inc_user(region_uuid); + if (ret) { + mlog_errno(ret); + goto out; + } + } + + down_write(&o2hb_callback_sem); + + list_for_each(iter, &hbcall->list) { + tmp = list_entry(iter, struct o2hb_callback_func, hc_item); + if (hc->hc_priority < tmp->hc_priority) { + list_add_tail(&hc->hc_item, iter); + break; + } + } + if (list_empty(&hc->hc_item)) + list_add_tail(&hc->hc_item, &hbcall->list); + + up_write(&o2hb_callback_sem); + ret = 0; +out: + mlog(ML_CLUSTER, "returning %d on behalf of %p for funcs %p\n", + ret, __builtin_return_address(0), hc); + return ret; +} +EXPORT_SYMBOL_GPL(o2hb_register_callback); + +void o2hb_unregister_callback(const char *region_uuid, + struct o2hb_callback_func *hc) +{ + BUG_ON(hc->hc_magic != O2HB_CB_MAGIC); + + mlog(ML_CLUSTER, "on behalf of %p for funcs %p\n", + __builtin_return_address(0), hc); + + /* XXX Can this happen _with_ a region reference? */ + if (list_empty(&hc->hc_item)) + return; + + if (region_uuid) + o2hb_region_dec_user(region_uuid); + + down_write(&o2hb_callback_sem); + + list_del_init(&hc->hc_item); + + up_write(&o2hb_callback_sem); +} +EXPORT_SYMBOL_GPL(o2hb_unregister_callback); + +int o2hb_check_node_heartbeating(u8 node_num) +{ + unsigned long testing_map[BITS_TO_LONGS(O2NM_MAX_NODES)]; + + o2hb_fill_node_map(testing_map, sizeof(testing_map)); + if (!test_bit(node_num, testing_map)) { + mlog(ML_HEARTBEAT, + "node (%u) does not have heartbeating enabled.\n", + node_num); + return 0; + } + + return 1; +} +EXPORT_SYMBOL_GPL(o2hb_check_node_heartbeating); + +int o2hb_check_node_heartbeating_from_callback(u8 node_num) +{ + unsigned long testing_map[BITS_TO_LONGS(O2NM_MAX_NODES)]; + + o2hb_fill_node_map_from_callback(testing_map, sizeof(testing_map)); + if (!test_bit(node_num, testing_map)) { + mlog(ML_HEARTBEAT, + "node (%u) does not have heartbeating enabled.\n", + node_num); + return 0; + } + + return 1; +} +EXPORT_SYMBOL_GPL(o2hb_check_node_heartbeating_from_callback); + +/* Makes sure our local node is configured with a node number, and is + * heartbeating. */ +int o2hb_check_local_node_heartbeating(void) +{ + u8 node_num; + + /* if this node was set then we have networking */ + node_num = o2nm_this_node(); + if (node_num == O2NM_MAX_NODES) { + mlog(ML_HEARTBEAT, "this node has not been configured.\n"); + return 0; + } + + return o2hb_check_node_heartbeating(node_num); +} +EXPORT_SYMBOL_GPL(o2hb_check_local_node_heartbeating); + +/* + * this is just a hack until we get the plumbing which flips file systems + * read only and drops the hb ref instead of killing the node dead. + */ +void o2hb_stop_all_regions(void) +{ + struct o2hb_region *reg; + + mlog(ML_ERROR, "stopping heartbeat on all active regions.\n"); + + spin_lock(&o2hb_live_lock); + + list_for_each_entry(reg, &o2hb_all_regions, hr_all_item) + reg->hr_unclean_stop = 1; + + spin_unlock(&o2hb_live_lock); +} +EXPORT_SYMBOL_GPL(o2hb_stop_all_regions); + +int o2hb_get_all_regions(char *region_uuids, u8 max_regions) +{ + struct o2hb_region *reg; + int numregs = 0; + char *p; + + spin_lock(&o2hb_live_lock); + + p = region_uuids; + list_for_each_entry(reg, &o2hb_all_regions, hr_all_item) { + mlog(0, "Region: %s\n", config_item_name(®->hr_item)); + if (numregs < max_regions) { + memcpy(p, config_item_name(®->hr_item), + O2HB_MAX_REGION_NAME_LEN); + p += O2HB_MAX_REGION_NAME_LEN; + } + numregs++; + } + + spin_unlock(&o2hb_live_lock); + + return numregs; +} +EXPORT_SYMBOL_GPL(o2hb_get_all_regions); + +int o2hb_global_heartbeat_active(void) +{ + return (o2hb_heartbeat_mode == O2HB_HEARTBEAT_GLOBAL); +} +EXPORT_SYMBOL(o2hb_global_heartbeat_active); diff --git a/drivers/staging/ramster/cluster/heartbeat.h b/drivers/staging/ramster/cluster/heartbeat.h new file mode 100644 index 0000000..00ad8e8 --- /dev/null +++ b/drivers/staging/ramster/cluster/heartbeat.h @@ -0,0 +1,89 @@ +/* -*- mode: c; c-basic-offset: 8; -*- + * vim: noexpandtab sw=8 ts=8 sts=0: + * + * heartbeat.h + * + * Function prototypes + * + * Copyright (C) 2004 Oracle. All rights reserved. + * + * 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; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 021110-1307, USA. + * + */ + +#ifndef O2CLUSTER_HEARTBEAT_H +#define O2CLUSTER_HEARTBEAT_H + +#include "ocfs2_heartbeat.h" + +#define O2HB_REGION_TIMEOUT_MS 2000 + +#define O2HB_MAX_REGION_NAME_LEN 32 + +/* number of changes to be seen as live */ +#define O2HB_LIVE_THRESHOLD 2 +/* number of equal samples to be seen as dead */ +extern unsigned int o2hb_dead_threshold; +#define O2HB_DEFAULT_DEAD_THRESHOLD 31 +/* Otherwise MAX_WRITE_TIMEOUT will be zero... */ +#define O2HB_MIN_DEAD_THRESHOLD 2 +#define O2HB_MAX_WRITE_TIMEOUT_MS (O2HB_REGION_TIMEOUT_MS * (o2hb_dead_threshold - 1)) + +#define O2HB_CB_MAGIC 0x51d1e4ec + +/* callback stuff */ +enum o2hb_callback_type { + O2HB_NODE_DOWN_CB = 0, + O2HB_NODE_UP_CB, + O2HB_NUM_CB +}; + +struct o2nm_node; +typedef void (o2hb_cb_func)(struct o2nm_node *, int, void *); + +struct o2hb_callback_func { + u32 hc_magic; + struct list_head hc_item; + o2hb_cb_func *hc_func; + void *hc_data; + int hc_priority; + enum o2hb_callback_type hc_type; +}; + +struct config_group *o2hb_alloc_hb_set(void); +void o2hb_free_hb_set(struct config_group *group); + +void o2hb_setup_callback(struct o2hb_callback_func *hc, + enum o2hb_callback_type type, + o2hb_cb_func *func, + void *data, + int priority); +int o2hb_register_callback(const char *region_uuid, + struct o2hb_callback_func *hc); +void o2hb_unregister_callback(const char *region_uuid, + struct o2hb_callback_func *hc); +void o2hb_fill_node_map(unsigned long *map, + unsigned bytes); +void o2hb_exit(void); +int o2hb_init(void); +int o2hb_check_node_heartbeating(u8 node_num); +int o2hb_check_node_heartbeating_from_callback(u8 node_num); +int o2hb_check_local_node_heartbeating(void); +void o2hb_stop_all_regions(void); +int o2hb_get_all_regions(char *region_uuids, u8 numregions); +int o2hb_global_heartbeat_active(void); + +#endif /* O2CLUSTER_HEARTBEAT_H */ diff --git a/drivers/staging/ramster/cluster/masklog.c b/drivers/staging/ramster/cluster/masklog.c new file mode 100644 index 0000000..07ac24f --- /dev/null +++ b/drivers/staging/ramster/cluster/masklog.c @@ -0,0 +1,155 @@ +/* -*- mode: c; c-basic-offset: 8; -*- + * vim: noexpandtab sw=8 ts=8 sts=0: + * + * Copyright (C) 2004, 2005 Oracle. All rights reserved. + * + * 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; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 021110-1307, USA. + */ + +#include +#include +#include +#include +#include +#include + +#include "masklog.h" + +struct mlog_bits mlog_and_bits = MLOG_BITS_RHS(MLOG_INITIAL_AND_MASK); +EXPORT_SYMBOL_GPL(mlog_and_bits); +struct mlog_bits mlog_not_bits = MLOG_BITS_RHS(0); +EXPORT_SYMBOL_GPL(mlog_not_bits); + +static ssize_t mlog_mask_show(u64 mask, char *buf) +{ + char *state; + + if (__mlog_test_u64(mask, mlog_and_bits)) + state = "allow"; + else if (__mlog_test_u64(mask, mlog_not_bits)) + state = "deny"; + else + state = "off"; + + return snprintf(buf, PAGE_SIZE, "%s\n", state); +} + +static ssize_t mlog_mask_store(u64 mask, const char *buf, size_t count) +{ + if (!strnicmp(buf, "allow", 5)) { + __mlog_set_u64(mask, mlog_and_bits); + __mlog_clear_u64(mask, mlog_not_bits); + } else if (!strnicmp(buf, "deny", 4)) { + __mlog_set_u64(mask, mlog_not_bits); + __mlog_clear_u64(mask, mlog_and_bits); + } else if (!strnicmp(buf, "off", 3)) { + __mlog_clear_u64(mask, mlog_not_bits); + __mlog_clear_u64(mask, mlog_and_bits); + } else + return -EINVAL; + + return count; +} + +struct mlog_attribute { + struct attribute attr; + u64 mask; +}; + +#define to_mlog_attr(_attr) container_of(_attr, struct mlog_attribute, attr) + +#define define_mask(_name) { \ + .attr = { \ + .name = #_name, \ + .mode = S_IRUGO | S_IWUSR, \ + }, \ + .mask = ML_##_name, \ +} + +static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = { + define_mask(TCP), + define_mask(MSG), + define_mask(SOCKET), + define_mask(HEARTBEAT), + define_mask(HB_BIO), + define_mask(DLMFS), + define_mask(DLM), + define_mask(DLM_DOMAIN), + define_mask(DLM_THREAD), + define_mask(DLM_MASTER), + define_mask(DLM_RECOVERY), + define_mask(DLM_GLUE), + define_mask(VOTE), + define_mask(CONN), + define_mask(QUORUM), + define_mask(BASTS), + define_mask(CLUSTER), + define_mask(ERROR), + define_mask(NOTICE), + define_mask(KTHREAD), +}; + +static struct attribute *mlog_attr_ptrs[MLOG_MAX_BITS] = {NULL, }; + +static ssize_t mlog_show(struct kobject *obj, struct attribute *attr, + char *buf) +{ + struct mlog_attribute *mlog_attr = to_mlog_attr(attr); + + return mlog_mask_show(mlog_attr->mask, buf); +} + +static ssize_t mlog_store(struct kobject *obj, struct attribute *attr, + const char *buf, size_t count) +{ + struct mlog_attribute *mlog_attr = to_mlog_attr(attr); + + return mlog_mask_store(mlog_attr->mask, buf, count); +} + +static const struct sysfs_ops mlog_attr_ops = { + .show = mlog_show, + .store = mlog_store, +}; + +static struct kobj_type mlog_ktype = { + .default_attrs = mlog_attr_ptrs, + .sysfs_ops = &mlog_attr_ops, +}; + +static struct kset mlog_kset = { + .kobj = {.ktype = &mlog_ktype}, +}; + +int mlog_sys_init(struct kset *o2cb_kset) +{ + int i = 0; + + while (mlog_attrs[i].attr.mode) { + mlog_attr_ptrs[i] = &mlog_attrs[i].attr; + i++; + } + mlog_attr_ptrs[i] = NULL; + + kobject_set_name(&mlog_kset.kobj, "logmask"); + mlog_kset.kobj.kset = o2cb_kset; + return kset_register(&mlog_kset); +} + +void mlog_sys_shutdown(void) +{ + kset_unregister(&mlog_kset); +} diff --git a/drivers/staging/ramster/cluster/masklog.h b/drivers/staging/ramster/cluster/masklog.h new file mode 100644 index 0000000..baa2b9e --- /dev/null +++ b/drivers/staging/ramster/cluster/masklog.h @@ -0,0 +1,219 @@ +/* -*- mode: c; c-basic-offset: 8; -*- + * vim: noexpandtab sw=8 ts=8 sts=0: + * + * Copyright (C) 2005 Oracle. All rights reserved. + * + * 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; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 021110-1307, USA. + */ + +#ifndef O2CLUSTER_MASKLOG_H +#define O2CLUSTER_MASKLOG_H + +/* + * For now this is a trivial wrapper around printk() that gives the critical + * ability to enable sets of debugging output at run-time. In the future this + * will almost certainly be redirected to relayfs so that it can pay a + * substantially lower heisenberg tax. + * + * Callers associate the message with a bitmask and a global bitmask is + * maintained with help from /proc. If any of the bits match the message is + * output. + * + * We must have efficient bit tests on i386 and it seems gcc still emits crazy + * code for the 64bit compare. It emits very good code for the dual unsigned + * long tests, though, completely avoiding tests that can never pass if the + * caller gives a constant bitmask that fills one of the longs with all 0s. So + * the desire is to have almost all of the calls decided on by comparing just + * one of the longs. This leads to having infrequently given bits that are + * frequently matched in the high bits. + * + * _ERROR and _NOTICE are used for messages that always go to the console and + * have appropriate KERN_ prefixes. We wrap these in our function instead of + * just calling printk() so that this can eventually make its way through + * relayfs along with the debugging messages. Everything else gets KERN_DEBUG. + * The inline tests and macro dance give GCC the opportunity to quite cleverly + * only emit the appropriage printk() when the caller passes in a constant + * mask, as is almost always the case. + * + * All this bitmask nonsense is managed from the files under + * /sys/fs/o2cb/logmask/. Reading the files gives a straightforward + * indication of which bits are allowed (allow) or denied (off/deny). + * ENTRY deny + * EXIT deny + * TCP off + * MSG off + * SOCKET off + * ERROR allow + * NOTICE allow + * + * Writing changes the state of a given bit and requires a strictly formatted + * single write() call: + * + * write(fd, "allow", 5); + * + * Echoing allow/deny/off string into the logmask files can flip the bits + * on or off as expected; here is the bash script for example: + * + * log_mask="/sys/fs/o2cb/log_mask" + * for node in ENTRY EXIT TCP MSG SOCKET ERROR NOTICE; do + * echo allow >"$log_mask"/"$node" + * done + * + * The debugfs.ocfs2 tool can also flip the bits with the -l option: + * + * debugfs.ocfs2 -l TCP allow + */ + +/* for task_struct */ +#include + +/* bits that are frequently given and infrequently matched in the low word */ +/* NOTE: If you add a flag, you need to also update masklog.c! */ +#define ML_TCP 0x0000000000000001ULL /* net cluster/tcp.c */ +#define ML_MSG 0x0000000000000002ULL /* net network messages */ +#define ML_SOCKET 0x0000000000000004ULL /* net socket lifetime */ +#define ML_HEARTBEAT 0x0000000000000008ULL /* hb all heartbeat tracking */ +#define ML_HB_BIO 0x0000000000000010ULL /* hb io tracing */ +#define ML_DLMFS 0x0000000000000020ULL /* dlm user dlmfs */ +#define ML_DLM 0x0000000000000040ULL /* dlm general debugging */ +#define ML_DLM_DOMAIN 0x0000000000000080ULL /* dlm domain debugging */ +#define ML_DLM_THREAD 0x0000000000000100ULL /* dlm domain thread */ +#define ML_DLM_MASTER 0x0000000000000200ULL /* dlm master functions */ +#define ML_DLM_RECOVERY 0x0000000000000400ULL /* dlm master functions */ +#define ML_DLM_GLUE 0x0000000000000800ULL /* ocfs2 dlm glue layer */ +#define ML_VOTE 0x0000000000001000ULL /* ocfs2 node messaging */ +#define ML_CONN 0x0000000000002000ULL /* net connection management */ +#define ML_QUORUM 0x0000000000004000ULL /* net connection quorum */ +#define ML_BASTS 0x0000000000008000ULL /* dlmglue asts and basts */ +#define ML_CLUSTER 0x0000000000010000ULL /* cluster stack */ + +/* bits that are infrequently given and frequently matched in the high word */ +#define ML_ERROR 0x1000000000000000ULL /* sent to KERN_ERR */ +#define ML_NOTICE 0x2000000000000000ULL /* setn to KERN_NOTICE */ +#define ML_KTHREAD 0x4000000000000000ULL /* kernel thread activity */ + +#define MLOG_INITIAL_AND_MASK (ML_ERROR|ML_NOTICE) +#ifndef MLOG_MASK_PREFIX +#define MLOG_MASK_PREFIX 0 +#endif + +/* + * When logging is disabled, force the bit test to 0 for anything other + * than errors and notices, allowing gcc to remove the code completely. + * When enabled, allow all masks. + */ +#if defined(CONFIG_OCFS2_DEBUG_MASKLOG) +#define ML_ALLOWED_BITS ~0 +#else +#define ML_ALLOWED_BITS (ML_ERROR|ML_NOTICE) +#endif + +#define MLOG_MAX_BITS 64 + +struct mlog_bits { + unsigned long words[MLOG_MAX_BITS / BITS_PER_LONG]; +}; + +extern struct mlog_bits mlog_and_bits, mlog_not_bits; + +#if BITS_PER_LONG == 32 + +#define __mlog_test_u64(mask, bits) \ + ( (u32)(mask & 0xffffffff) & bits.words[0] || \ + ((u64)(mask) >> 32) & bits.words[1] ) +#define __mlog_set_u64(mask, bits) do { \ + bits.words[0] |= (u32)(mask & 0xffffffff); \ + bits.words[1] |= (u64)(mask) >> 32; \ +} while (0) +#define __mlog_clear_u64(mask, bits) do { \ + bits.words[0] &= ~((u32)(mask & 0xffffffff)); \ + bits.words[1] &= ~((u64)(mask) >> 32); \ +} while (0) +#define MLOG_BITS_RHS(mask) { \ + { \ + [0] = (u32)(mask & 0xffffffff), \ + [1] = (u64)(mask) >> 32, \ + } \ +} + +#else /* 32bit long above, 64bit long below */ + +#define __mlog_test_u64(mask, bits) ((mask) & bits.words[0]) +#define __mlog_set_u64(mask, bits) do { \ + bits.words[0] |= (mask); \ +} while (0) +#define __mlog_clear_u64(mask, bits) do { \ + bits.words[0] &= ~(mask); \ +} while (0) +#define MLOG_BITS_RHS(mask) { { (mask) } } + +#endif + +/* + * smp_processor_id() "helpfully" screams when called outside preemptible + * regions in current kernels. sles doesn't have the variants that don't + * scream. just do this instead of trying to guess which we're building + * against.. *sigh*. + */ +#define __mlog_cpu_guess ({ \ + unsigned long _cpu = get_cpu(); \ + put_cpu(); \ + _cpu; \ +}) + +/* In the following two macros, the whitespace after the ',' just + * before ##args is intentional. Otherwise, gcc 2.95 will eat the + * previous token if args expands to nothing. + */ +#define __mlog_printk(level, fmt, args...) \ + printk(level "(%s,%u,%lu):%s:%d " fmt, current->comm, \ + task_pid_nr(current), __mlog_cpu_guess, \ + __PRETTY_FUNCTION__, __LINE__ , ##args) + +#define mlog(mask, fmt, args...) do { \ + u64 __m = MLOG_MASK_PREFIX | (mask); \ + if ((__m & ML_ALLOWED_BITS) && \ + __mlog_test_u64(__m, mlog_and_bits) && \ + !__mlog_test_u64(__m, mlog_not_bits)) { \ + if (__m & ML_ERROR) \ + __mlog_printk(KERN_ERR, "ERROR: "fmt , ##args); \ + else if (__m & ML_NOTICE) \ + __mlog_printk(KERN_NOTICE, fmt , ##args); \ + else __mlog_printk(KERN_INFO, fmt , ##args); \ + } \ +} while (0) + +#define mlog_errno(st) do { \ + int _st = (st); \ + if (_st != -ERESTARTSYS && _st != -EINTR && \ + _st != AOP_TRUNCATED_PAGE && _st != -ENOSPC) \ + mlog(ML_ERROR, "status = %lld\n", (long long)_st); \ +} while (0) + +#define mlog_bug_on_msg(cond, fmt, args...) do { \ + if (cond) { \ + mlog(ML_ERROR, "bug expression: " #cond "\n"); \ + mlog(ML_ERROR, fmt, ##args); \ + BUG(); \ + } \ +} while (0) + +#include +#include +int mlog_sys_init(struct kset *o2cb_subsys); +void mlog_sys_shutdown(void); + +#endif /* O2CLUSTER_MASKLOG_H */ diff --git a/drivers/staging/ramster/cluster/netdebug.c b/drivers/staging/ramster/cluster/netdebug.c new file mode 100644 index 0000000..dc45deb --- /dev/null +++ b/drivers/staging/ramster/cluster/netdebug.c @@ -0,0 +1,579 @@ +/* -*- mode: c; c-basic-offset: 8; -*- + * vim: noexpandtab sw=8 ts=8 sts=0: + * + * netdebug.c + * + * debug functionality for o2net + * + * Copyright (C) 2005, 2008 Oracle. All rights reserved. + * + * 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; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 021110-1307, USA. + * + */ + +#ifdef CONFIG_DEBUG_FS + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "tcp.h" +#include "nodemanager.h" +#define MLOG_MASK_PREFIX ML_TCP +#include "masklog.h" + +#include "tcp_internal.h" + +#define O2NET_DEBUG_DIR "o2net" +#define SC_DEBUG_NAME "sock_containers" +#define NST_DEBUG_NAME "send_tracking" +#define STATS_DEBUG_NAME "stats" +#define NODES_DEBUG_NAME "connected_nodes" + +#define SHOW_SOCK_CONTAINERS 0 +#define SHOW_SOCK_STATS 1 + +static struct dentry *o2net_dentry; +static struct dentry *sc_dentry; +static struct dentry *nst_dentry; +static struct dentry *stats_dentry; +static struct dentry *nodes_dentry; + +static DEFINE_SPINLOCK(o2net_debug_lock); + +static LIST_HEAD(sock_containers); +static LIST_HEAD(send_tracking); + +void o2net_debug_add_nst(struct o2net_send_tracking *nst) +{ + spin_lock(&o2net_debug_lock); + list_add(&nst->st_net_debug_item, &send_tracking); + spin_unlock(&o2net_debug_lock); +} + +void o2net_debug_del_nst(struct o2net_send_tracking *nst) +{ + spin_lock(&o2net_debug_lock); + if (!list_empty(&nst->st_net_debug_item)) + list_del_init(&nst->st_net_debug_item); + spin_unlock(&o2net_debug_lock); +} + +static struct o2net_send_tracking + *next_nst(struct o2net_send_tracking *nst_start) +{ + struct o2net_send_tracking *nst, *ret = NULL; + + assert_spin_locked(&o2net_debug_lock); + + list_for_each_entry(nst, &nst_start->st_net_debug_item, + st_net_debug_item) { + /* discover the head of the list */ + if (&nst->st_net_debug_item == &send_tracking) + break; + + /* use st_task to detect real nsts in the list */ + if (nst->st_task != NULL) { + ret = nst; + break; + } + } + + return ret; +} + +static void *nst_seq_start(struct seq_file *seq, loff_t *pos) +{ + struct o2net_send_tracking *nst, *dummy_nst = seq->private; + + spin_lock(&o2net_debug_lock); + nst = next_nst(dummy_nst); + spin_unlock(&o2net_debug_lock); + + return nst; +} + +static void *nst_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + struct o2net_send_tracking *nst, *dummy_nst = seq->private; + + spin_lock(&o2net_debug_lock); + nst = next_nst(dummy_nst); + list_del_init(&dummy_nst->st_net_debug_item); + if (nst) + list_add(&dummy_nst->st_net_debug_item, + &nst->st_net_debug_item); + spin_unlock(&o2net_debug_lock); + + return nst; /* unused, just needs to be null when done */ +} + +static int nst_seq_show(struct seq_file *seq, void *v) +{ + struct o2net_send_tracking *nst, *dummy_nst = seq->private; + ktime_t now; + s64 sock, send, status; + + spin_lock(&o2net_debug_lock); + nst = next_nst(dummy_nst); + if (!nst) + goto out; + + now = ktime_get(); + sock = ktime_to_us(ktime_sub(now, nst->st_sock_time)); + send = ktime_to_us(ktime_sub(now, nst->st_send_time)); + status = ktime_to_us(ktime_sub(now, nst->st_status_time)); + + /* get_task_comm isn't exported. oh well. */ + seq_printf(seq, "%p:\n" + " pid: %lu\n" + " tgid: %lu\n" + " process name: %s\n" + " node: %u\n" + " sc: %p\n" + " message id: %d\n" + " message type: %u\n" + " message key: 0x%08x\n" + " sock acquiry: %lld usecs ago\n" + " send start: %lld usecs ago\n" + " wait start: %lld usecs ago\n", + nst, (unsigned long)task_pid_nr(nst->st_task), + (unsigned long)nst->st_task->tgid, + nst->st_task->comm, nst->st_node, + nst->st_sc, nst->st_id, nst->st_msg_type, + nst->st_msg_key, + (long long)sock, + (long long)send, + (long long)status); + +out: + spin_unlock(&o2net_debug_lock); + + return 0; +} + +static void nst_seq_stop(struct seq_file *seq, void *v) +{ +} + +static const struct seq_operations nst_seq_ops = { + .start = nst_seq_start, + .next = nst_seq_next, + .stop = nst_seq_stop, + .show = nst_seq_show, +}; + +static int nst_fop_open(struct inode *inode, struct file *file) +{ + struct o2net_send_tracking *dummy_nst; + struct seq_file *seq; + int ret; + + dummy_nst = kmalloc(sizeof(struct o2net_send_tracking), GFP_KERNEL); + if (dummy_nst == NULL) { + ret = -ENOMEM; + goto out; + } + dummy_nst->st_task = NULL; + + ret = seq_open(file, &nst_seq_ops); + if (ret) + goto out; + + seq = file->private_data; + seq->private = dummy_nst; + o2net_debug_add_nst(dummy_nst); + + dummy_nst = NULL; + +out: + kfree(dummy_nst); + return ret; +} + +static int nst_fop_release(struct inode *inode, struct file *file) +{ + struct seq_file *seq = file->private_data; + struct o2net_send_tracking *dummy_nst = seq->private; + + o2net_debug_del_nst(dummy_nst); + return seq_release_private(inode, file); +} + +static const struct file_operations nst_seq_fops = { + .open = nst_fop_open, + .read = seq_read, + .llseek = seq_lseek, + .release = nst_fop_release, +}; + +void o2net_debug_add_sc(struct o2net_sock_container *sc) +{ + spin_lock(&o2net_debug_lock); + list_add(&sc->sc_net_debug_item, &sock_containers); + spin_unlock(&o2net_debug_lock); +} + +void o2net_debug_del_sc(struct o2net_sock_container *sc) +{ + spin_lock(&o2net_debug_lock); + list_del_init(&sc->sc_net_debug_item); + spin_unlock(&o2net_debug_lock); +} + +struct o2net_sock_debug { + int dbg_ctxt; + struct o2net_sock_container *dbg_sock; +}; + +static struct o2net_sock_container + *next_sc(struct o2net_sock_container *sc_start) +{ + struct o2net_sock_container *sc, *ret = NULL; + + assert_spin_locked(&o2net_debug_lock); + + list_for_each_entry(sc, &sc_start->sc_net_debug_item, + sc_net_debug_item) { + /* discover the head of the list miscast as a sc */ + if (&sc->sc_net_debug_item == &sock_containers) + break; + + /* use sc_page to detect real scs in the list */ + if (sc->sc_page != NULL) { + ret = sc; + break; + } + } + + return ret; +} + +static void *sc_seq_start(struct seq_file *seq, loff_t *pos) +{ + struct o2net_sock_debug *sd = seq->private; + struct o2net_sock_container *sc, *dummy_sc = sd->dbg_sock; + + spin_lock(&o2net_debug_lock); + sc = next_sc(dummy_sc); + spin_unlock(&o2net_debug_lock); + + return sc; +} + +static void *sc_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + struct o2net_sock_debug *sd = seq->private; + struct o2net_sock_container *sc, *dummy_sc = sd->dbg_sock; + + spin_lock(&o2net_debug_lock); + sc = next_sc(dummy_sc); + list_del_init(&dummy_sc->sc_net_debug_item); + if (sc) + list_add(&dummy_sc->sc_net_debug_item, &sc->sc_net_debug_item); + spin_unlock(&o2net_debug_lock); + + return sc; /* unused, just needs to be null when done */ +} + +#ifdef CONFIG_OCFS2_FS_STATS +# define sc_send_count(_s) ((_s)->sc_send_count) +# define sc_recv_count(_s) ((_s)->sc_recv_count) +# define sc_tv_acquiry_total_ns(_s) (ktime_to_ns((_s)->sc_tv_acquiry_total)) +# define sc_tv_send_total_ns(_s) (ktime_to_ns((_s)->sc_tv_send_total)) +# define sc_tv_status_total_ns(_s) (ktime_to_ns((_s)->sc_tv_status_total)) +# define sc_tv_process_total_ns(_s) (ktime_to_ns((_s)->sc_tv_process_total)) +#else +# define sc_send_count(_s) (0U) +# define sc_recv_count(_s) (0U) +# define sc_tv_acquiry_total_ns(_s) (0LL) +# define sc_tv_send_total_ns(_s) (0LL) +# define sc_tv_status_total_ns(_s) (0LL) +# define sc_tv_process_total_ns(_s) (0LL) +#endif + +/* So that debugfs.ocfs2 can determine which format is being used */ +#define O2NET_STATS_STR_VERSION 1 +static void sc_show_sock_stats(struct seq_file *seq, + struct o2net_sock_container *sc) +{ + if (!sc) + return; + + seq_printf(seq, "%d,%u,%lu,%lld,%lld,%lld,%lu,%lld\n", O2NET_STATS_STR_VERSION, + sc->sc_node->nd_num, (unsigned long)sc_send_count(sc), + (long long)sc_tv_acquiry_total_ns(sc), + (long long)sc_tv_send_total_ns(sc), + (long long)sc_tv_status_total_ns(sc), + (unsigned long)sc_recv_count(sc), + (long long)sc_tv_process_total_ns(sc)); +} + +static void sc_show_sock_container(struct seq_file *seq, + struct o2net_sock_container *sc) +{ + struct inet_sock *inet = NULL; + __be32 saddr = 0, daddr = 0; + __be16 sport = 0, dport = 0; + + if (!sc) + return; + + if (sc->sc_sock) { + inet = inet_sk(sc->sc_sock->sk); + /* the stack's structs aren't sparse endian clean */ + saddr = (__force __be32)inet->inet_saddr; + daddr = (__force __be32)inet->inet_daddr; + sport = (__force __be16)inet->inet_sport; + dport = (__force __be16)inet->inet_dport; + } + + /* XXX sigh, inet-> doesn't have sparse annotation so any + * use of it here generates a warning with -Wbitwise */ + seq_printf(seq, "%p:\n" + " krefs: %d\n" + " sock: %pI4:%u -> " + "%pI4:%u\n" + " remote node: %s\n" + " page off: %zu\n" + " handshake ok: %u\n" + " timer: %lld usecs\n" + " data ready: %lld usecs\n" + " advance start: %lld usecs\n" + " advance stop: %lld usecs\n" + " func start: %lld usecs\n" + " func stop: %lld usecs\n" + " func key: 0x%08x\n" + " func type: %u\n", + sc, + atomic_read(&sc->sc_kref.refcount), + &saddr, inet ? ntohs(sport) : 0, + &daddr, inet ? ntohs(dport) : 0, + sc->sc_node->nd_name, + sc->sc_page_off, + sc->sc_handshake_ok, + (long long)ktime_to_us(sc->sc_tv_timer), + (long long)ktime_to_us(sc->sc_tv_data_ready), + (long long)ktime_to_us(sc->sc_tv_advance_start), + (long long)ktime_to_us(sc->sc_tv_advance_stop), + (long long)ktime_to_us(sc->sc_tv_func_start), + (long long)ktime_to_us(sc->sc_tv_func_stop), + sc->sc_msg_key, + sc->sc_msg_type); +} + +static int sc_seq_show(struct seq_file *seq, void *v) +{ + struct o2net_sock_debug *sd = seq->private; + struct o2net_sock_container *sc, *dummy_sc = sd->dbg_sock; + + spin_lock(&o2net_debug_lock); + sc = next_sc(dummy_sc); + + if (sc) { + if (sd->dbg_ctxt == SHOW_SOCK_CONTAINERS) + sc_show_sock_container(seq, sc); + else + sc_show_sock_stats(seq, sc); + } + + spin_unlock(&o2net_debug_lock); + + return 0; +} + +static void sc_seq_stop(struct seq_file *seq, void *v) +{ +} + +static const struct seq_operations sc_seq_ops = { + .start = sc_seq_start, + .next = sc_seq_next, + .stop = sc_seq_stop, + .show = sc_seq_show, +}; + +static int sc_common_open(struct file *file, struct o2net_sock_debug *sd) +{ + struct o2net_sock_container *dummy_sc; + struct seq_file *seq; + int ret; + + dummy_sc = kmalloc(sizeof(struct o2net_sock_container), GFP_KERNEL); + if (dummy_sc == NULL) { + ret = -ENOMEM; + goto out; + } + dummy_sc->sc_page = NULL; + + ret = seq_open(file, &sc_seq_ops); + if (ret) + goto out; + + seq = file->private_data; + seq->private = sd; + sd->dbg_sock = dummy_sc; + o2net_debug_add_sc(dummy_sc); + + dummy_sc = NULL; + +out: + kfree(dummy_sc); + return ret; +} + +static int sc_fop_release(struct inode *inode, struct file *file) +{ + struct seq_file *seq = file->private_data; + struct o2net_sock_debug *sd = seq->private; + struct o2net_sock_container *dummy_sc = sd->dbg_sock; + + o2net_debug_del_sc(dummy_sc); + return seq_release_private(inode, file); +} + +static int stats_fop_open(struct inode *inode, struct file *file) +{ + struct o2net_sock_debug *sd; + + sd = kmalloc(sizeof(struct o2net_sock_debug), GFP_KERNEL); + if (sd == NULL) + return -ENOMEM; + + sd->dbg_ctxt = SHOW_SOCK_STATS; + sd->dbg_sock = NULL; + + return sc_common_open(file, sd); +} + +static const struct file_operations stats_seq_fops = { + .open = stats_fop_open, + .read = seq_read, + .llseek = seq_lseek, + .release = sc_fop_release, +}; + +static int sc_fop_open(struct inode *inode, struct file *file) +{ + struct o2net_sock_debug *sd; + + sd = kmalloc(sizeof(struct o2net_sock_debug), GFP_KERNEL); + if (sd == NULL) + return -ENOMEM; + + sd->dbg_ctxt = SHOW_SOCK_CONTAINERS; + sd->dbg_sock = NULL; + + return sc_common_open(file, sd); +} + +static const struct file_operations sc_seq_fops = { + .open = sc_fop_open, + .read = seq_read, + .llseek = seq_lseek, + .release = sc_fop_release, +}; + +static int o2net_fill_bitmap(char *buf, int len) +{ + unsigned long map[BITS_TO_LONGS(O2NM_MAX_NODES)]; + int i = -1, out = 0; + + o2net_fill_node_map(map, sizeof(map)); + + while ((i = find_next_bit(map, O2NM_MAX_NODES, i + 1)) < O2NM_MAX_NODES) + out += snprintf(buf + out, PAGE_SIZE - out, "%d ", i); + out += snprintf(buf + out, PAGE_SIZE - out, "\n"); + + return out; +} + +static int nodes_fop_open(struct inode *inode, struct file *file) +{ + char *buf; + + buf = kmalloc(PAGE_SIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + i_size_write(inode, o2net_fill_bitmap(buf, PAGE_SIZE)); + + file->private_data = buf; + + return 0; +} + +static int o2net_debug_release(struct inode *inode, struct file *file) +{ + kfree(file->private_data); + return 0; +} + +static ssize_t o2net_debug_read(struct file *file, char __user *buf, + size_t nbytes, loff_t *ppos) +{ + return simple_read_from_buffer(buf, nbytes, ppos, file->private_data, + i_size_read(file->f_mapping->host)); +} + +static const struct file_operations nodes_fops = { + .open = nodes_fop_open, + .release = o2net_debug_release, + .read = o2net_debug_read, + .llseek = generic_file_llseek, +}; + +void o2net_debugfs_exit(void) +{ + debugfs_remove(nodes_dentry); + debugfs_remove(stats_dentry); + debugfs_remove(sc_dentry); + debugfs_remove(nst_dentry); + debugfs_remove(o2net_dentry); +} + +int o2net_debugfs_init(void) +{ + mode_t mode = S_IFREG|S_IRUSR; + + o2net_dentry = debugfs_create_dir(O2NET_DEBUG_DIR, NULL); + if (o2net_dentry) + nst_dentry = debugfs_create_file(NST_DEBUG_NAME, mode, + o2net_dentry, NULL, &nst_seq_fops); + if (nst_dentry) + sc_dentry = debugfs_create_file(SC_DEBUG_NAME, mode, + o2net_dentry, NULL, &sc_seq_fops); + if (sc_dentry) + stats_dentry = debugfs_create_file(STATS_DEBUG_NAME, mode, + o2net_dentry, NULL, &stats_seq_fops); + if (stats_dentry) + nodes_dentry = debugfs_create_file(NODES_DEBUG_NAME, mode, + o2net_dentry, NULL, &nodes_fops); + if (nodes_dentry) + return 0; + + o2net_debugfs_exit(); + mlog_errno(-ENOMEM); + return -ENOMEM; +} + +#endif /* CONFIG_DEBUG_FS */ diff --git a/drivers/staging/ramster/cluster/nodemanager.c b/drivers/staging/ramster/cluster/nodemanager.c new file mode 100644 index 0000000..bb24064 --- /dev/null +++ b/drivers/staging/ramster/cluster/nodemanager.c @@ -0,0 +1,989 @@ +/* -*- mode: c; c-basic-offset: 8; -*- + * vim: noexpandtab sw=8 ts=8 sts=0: + * + * Copyright (C) 2004, 2005 Oracle. All rights reserved. + * + * 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; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 021110-1307, USA. + */ + +#include +#include +#include +#include + +#include "tcp.h" +#include "nodemanager.h" +#include "heartbeat.h" +#include "masklog.h" +#include "sys.h" +#include "ver.h" + +/* for now we operate under the assertion that there can be only one + * cluster active at a time. Changing this will require trickling + * cluster references throughout where nodes are looked up */ +struct o2nm_cluster *o2nm_single_cluster = NULL; + +char *o2nm_fence_method_desc[O2NM_FENCE_METHODS] = { + "reset", /* O2NM_FENCE_RESET */ + "panic", /* O2NM_FENCE_PANIC */ +}; + +struct o2nm_node *o2nm_get_node_by_num(u8 node_num) +{ + struct o2nm_node *node = NULL; + + if (node_num >= O2NM_MAX_NODES || o2nm_single_cluster == NULL) + goto out; + + read_lock(&o2nm_single_cluster->cl_nodes_lock); + node = o2nm_single_cluster->cl_nodes[node_num]; + if (node) + config_item_get(&node->nd_item); + read_unlock(&o2nm_single_cluster->cl_nodes_lock); +out: + return node; +} +EXPORT_SYMBOL_GPL(o2nm_get_node_by_num); + +int o2nm_configured_node_map(unsigned long *map, unsigned bytes) +{ + struct o2nm_cluster *cluster = o2nm_single_cluster; + + BUG_ON(bytes < (sizeof(cluster->cl_nodes_bitmap))); + + if (cluster == NULL) + return -EINVAL; + + read_lock(&cluster->cl_nodes_lock); + memcpy(map, cluster->cl_nodes_bitmap, sizeof(cluster->cl_nodes_bitmap)); + read_unlock(&cluster->cl_nodes_lock); + + return 0; +} +EXPORT_SYMBOL_GPL(o2nm_configured_node_map); + +static struct o2nm_node *o2nm_node_ip_tree_lookup(struct o2nm_cluster *cluster, + __be32 ip_needle, + struct rb_node ***ret_p, + struct rb_node **ret_parent) +{ + struct rb_node **p = &cluster->cl_node_ip_tree.rb_node; + struct rb_node *parent = NULL; + struct o2nm_node *node, *ret = NULL; + + while (*p) { + int cmp; + + parent = *p; + node = rb_entry(parent, struct o2nm_node, nd_ip_node); + + cmp = memcmp(&ip_needle, &node->nd_ipv4_address, + sizeof(ip_needle)); + if (cmp < 0) + p = &(*p)->rb_left; + else if (cmp > 0) + p = &(*p)->rb_right; + else { + ret = node; + break; + } + } + + if (ret_p != NULL) + *ret_p = p; + if (ret_parent != NULL) + *ret_parent = parent; + + return ret; +} + +struct o2nm_node *o2nm_get_node_by_ip(__be32 addr) +{ + struct o2nm_node *node = NULL; + struct o2nm_cluster *cluster = o2nm_single_cluster; + + if (cluster == NULL) + goto out; + + read_lock(&cluster->cl_nodes_lock); + node = o2nm_node_ip_tree_lookup(cluster, addr, NULL, NULL); + if (node) + config_item_get(&node->nd_item); + read_unlock(&cluster->cl_nodes_lock); + +out: + return node; +} +EXPORT_SYMBOL_GPL(o2nm_get_node_by_ip); + +void o2nm_node_put(struct o2nm_node *node) +{ + config_item_put(&node->nd_item); +} +EXPORT_SYMBOL_GPL(o2nm_node_put); + +void o2nm_node_get(struct o2nm_node *node) +{ + config_item_get(&node->nd_item); +} +EXPORT_SYMBOL_GPL(o2nm_node_get); + +u8 o2nm_this_node(void) +{ + u8 node_num = O2NM_MAX_NODES; + + if (o2nm_single_cluster && o2nm_single_cluster->cl_has_local) + node_num = o2nm_single_cluster->cl_local_node; + + return node_num; +} +EXPORT_SYMBOL_GPL(o2nm_this_node); + +/* node configfs bits */ + +static struct o2nm_cluster *to_o2nm_cluster(struct config_item *item) +{ + return item ? + container_of(to_config_group(item), struct o2nm_cluster, + cl_group) + : NULL; +} + +static struct o2nm_node *to_o2nm_node(struct config_item *item) +{ + return item ? container_of(item, struct o2nm_node, nd_item) : NULL; +} + +static void o2nm_node_release(struct config_item *item) +{ + struct o2nm_node *node = to_o2nm_node(item); + kfree(node); +} + +static ssize_t o2nm_node_num_read(struct o2nm_node *node, char *page) +{ + return sprintf(page, "%d\n", node->nd_num); +} + +static struct o2nm_cluster *to_o2nm_cluster_from_node(struct o2nm_node *node) +{ + /* through the first node_set .parent + * mycluster/nodes/mynode == o2nm_cluster->o2nm_node_group->o2nm_node */ + return to_o2nm_cluster(node->nd_item.ci_parent->ci_parent); +} + +enum { + O2NM_NODE_ATTR_NUM = 0, + O2NM_NODE_ATTR_PORT, + O2NM_NODE_ATTR_ADDRESS, + O2NM_NODE_ATTR_LOCAL, +}; + +static ssize_t o2nm_node_num_write(struct o2nm_node *node, const char *page, + size_t count) +{ + struct o2nm_cluster *cluster = to_o2nm_cluster_from_node(node); + unsigned long tmp; + char *p = (char *)page; + + tmp = simple_strtoul(p, &p, 0); + if (!p || (*p && (*p != '\n'))) + return -EINVAL; + + if (tmp >= O2NM_MAX_NODES) + return -ERANGE; + + /* once we're in the cl_nodes tree networking can look us up by + * node number and try to use our address and port attributes + * to connect to this node.. make sure that they've been set + * before writing the node attribute? */ + if (!test_bit(O2NM_NODE_ATTR_ADDRESS, &node->nd_set_attributes) || + !test_bit(O2NM_NODE_ATTR_PORT, &node->nd_set_attributes)) + return -EINVAL; /* XXX */ + + write_lock(&cluster->cl_nodes_lock); + if (cluster->cl_nodes[tmp]) + p = NULL; + else { + cluster->cl_nodes[tmp] = node; + node->nd_num = tmp; + set_bit(tmp, cluster->cl_nodes_bitmap); + } + write_unlock(&cluster->cl_nodes_lock); + if (p == NULL) + return -EEXIST; + + return count; +} +static ssize_t o2nm_node_ipv4_port_read(struct o2nm_node *node, char *page) +{ + return sprintf(page, "%u\n", ntohs(node->nd_ipv4_port)); +} + +static ssize_t o2nm_node_ipv4_port_write(struct o2nm_node *node, + const char *page, size_t count) +{ + unsigned long tmp; + char *p = (char *)page; + + tmp = simple_strtoul(p, &p, 0); + if (!p || (*p && (*p != '\n'))) + return -EINVAL; + + if (tmp == 0) + return -EINVAL; + if (tmp >= (u16)-1) + return -ERANGE; + + node->nd_ipv4_port = htons(tmp); + + return count; +} + +static ssize_t o2nm_node_ipv4_address_read(struct o2nm_node *node, char *page) +{ + return sprintf(page, "%pI4\n", &node->nd_ipv4_address); +} + +static ssize_t o2nm_node_ipv4_address_write(struct o2nm_node *node, + const char *page, + size_t count) +{ + struct o2nm_cluster *cluster = to_o2nm_cluster_from_node(node); + int ret, i; + struct rb_node **p, *parent; + unsigned int octets[4]; + __be32 ipv4_addr = 0; + + ret = sscanf(page, "%3u.%3u.%3u.%3u", &octets[3], &octets[2], + &octets[1], &octets[0]); + if (ret != 4) + return -EINVAL; + + for (i = 0; i < ARRAY_SIZE(octets); i++) { + if (octets[i] > 255) + return -ERANGE; + be32_add_cpu(&ipv4_addr, octets[i] << (i * 8)); + } + + ret = 0; + write_lock(&cluster->cl_nodes_lock); + if (o2nm_node_ip_tree_lookup(cluster, ipv4_addr, &p, &parent)) + ret = -EEXIST; + else { + rb_link_node(&node->nd_ip_node, parent, p); + rb_insert_color(&node->nd_ip_node, &cluster->cl_node_ip_tree); + } + write_unlock(&cluster->cl_nodes_lock); + if (ret) + return ret; + + memcpy(&node->nd_ipv4_address, &ipv4_addr, sizeof(ipv4_addr)); + + return count; +} + +static ssize_t o2nm_node_local_read(struct o2nm_node *node, char *page) +{ + return sprintf(page, "%d\n", node->nd_local); +} + +static ssize_t o2nm_node_local_write(struct o2nm_node *node, const char *page, + size_t count) +{ + struct o2nm_cluster *cluster = to_o2nm_cluster_from_node(node); + unsigned long tmp; + char *p = (char *)page; + ssize_t ret; + + tmp = simple_strtoul(p, &p, 0); + if (!p || (*p && (*p != '\n'))) + return -EINVAL; + + tmp = !!tmp; /* boolean of whether this node wants to be local */ + + /* setting local turns on networking rx for now so we require having + * set everything else first */ + if (!test_bit(O2NM_NODE_ATTR_ADDRESS, &node->nd_set_attributes) || + !test_bit(O2NM_NODE_ATTR_NUM, &node->nd_set_attributes) || + !test_bit(O2NM_NODE_ATTR_PORT, &node->nd_set_attributes)) + return -EINVAL; /* XXX */ + + /* the only failure case is trying to set a new local node + * when a different one is already set */ + if (tmp && tmp == cluster->cl_has_local && + cluster->cl_local_node != node->nd_num) + return -EBUSY; + + /* bring up the rx thread if we're setting the new local node. */ + if (tmp && !cluster->cl_has_local) { + ret = o2net_start_listening(node); + if (ret) + return ret; + } + + if (!tmp && cluster->cl_has_local && + cluster->cl_local_node == node->nd_num) { + o2net_stop_listening(node); + cluster->cl_local_node = O2NM_INVALID_NODE_NUM; + } + + node->nd_local = tmp; + if (node->nd_local) { + cluster->cl_has_local = tmp; + cluster->cl_local_node = node->nd_num; + } + + return count; +} + +struct o2nm_node_attribute { + struct configfs_attribute attr; + ssize_t (*show)(struct o2nm_node *, char *); + ssize_t (*store)(struct o2nm_node *, const char *, size_t); +}; + +static struct o2nm_node_attribute o2nm_node_attr_num = { + .attr = { .ca_owner = THIS_MODULE, + .ca_name = "num", + .ca_mode = S_IRUGO | S_IWUSR }, + .show = o2nm_node_num_read, + .store = o2nm_node_num_write, +}; + +static struct o2nm_node_attribute o2nm_node_attr_ipv4_port = { + .attr = { .ca_owner = THIS_MODULE, + .ca_name = "ipv4_port", + .ca_mode = S_IRUGO | S_IWUSR }, + .show = o2nm_node_ipv4_port_read, + .store = o2nm_node_ipv4_port_write, +}; + +static struct o2nm_node_attribute o2nm_node_attr_ipv4_address = { + .attr = { .ca_owner = THIS_MODULE, + .ca_name = "ipv4_address", + .ca_mode = S_IRUGO | S_IWUSR }, + .show = o2nm_node_ipv4_address_read, + .store = o2nm_node_ipv4_address_write, +}; + +static struct o2nm_node_attribute o2nm_node_attr_local = { + .attr = { .ca_owner = THIS_MODULE, + .ca_name = "local", + .ca_mode = S_IRUGO | S_IWUSR }, + .show = o2nm_node_local_read, + .store = o2nm_node_local_write, +}; + +static struct configfs_attribute *o2nm_node_attrs[] = { + [O2NM_NODE_ATTR_NUM] = &o2nm_node_attr_num.attr, + [O2NM_NODE_ATTR_PORT] = &o2nm_node_attr_ipv4_port.attr, + [O2NM_NODE_ATTR_ADDRESS] = &o2nm_node_attr_ipv4_address.attr, + [O2NM_NODE_ATTR_LOCAL] = &o2nm_node_attr_local.attr, + NULL, +}; + +static int o2nm_attr_index(struct configfs_attribute *attr) +{ + int i; + for (i = 0; i < ARRAY_SIZE(o2nm_node_attrs); i++) { + if (attr == o2nm_node_attrs[i]) + return i; + } + BUG(); + return 0; +} + +static ssize_t o2nm_node_show(struct config_item *item, + struct configfs_attribute *attr, + char *page) +{ + struct o2nm_node *node = to_o2nm_node(item); + struct o2nm_node_attribute *o2nm_node_attr = + container_of(attr, struct o2nm_node_attribute, attr); + ssize_t ret = 0; + + if (o2nm_node_attr->show) + ret = o2nm_node_attr->show(node, page); + return ret; +} + +static ssize_t o2nm_node_store(struct config_item *item, + struct configfs_attribute *attr, + const char *page, size_t count) +{ + struct o2nm_node *node = to_o2nm_node(item); + struct o2nm_node_attribute *o2nm_node_attr = + container_of(attr, struct o2nm_node_attribute, attr); + ssize_t ret; + int attr_index = o2nm_attr_index(attr); + + if (o2nm_node_attr->store == NULL) { + ret = -EINVAL; + goto out; + } + + if (test_bit(attr_index, &node->nd_set_attributes)) + return -EBUSY; + + ret = o2nm_node_attr->store(node, page, count); + if (ret < count) + goto out; + + set_bit(attr_index, &node->nd_set_attributes); +out: + return ret; +} + +static struct configfs_item_operations o2nm_node_item_ops = { + .release = o2nm_node_release, + .show_attribute = o2nm_node_show, + .store_attribute = o2nm_node_store, +}; + +static struct config_item_type o2nm_node_type = { + .ct_item_ops = &o2nm_node_item_ops, + .ct_attrs = o2nm_node_attrs, + .ct_owner = THIS_MODULE, +}; + +/* node set */ + +struct o2nm_node_group { + struct config_group ns_group; + /* some stuff? */ +}; + +#if 0 +static struct o2nm_node_group *to_o2nm_node_group(struct config_group *group) +{ + return group ? + container_of(group, struct o2nm_node_group, ns_group) + : NULL; +} +#endif + +struct o2nm_cluster_attribute { + struct configfs_attribute attr; + ssize_t (*show)(struct o2nm_cluster *, char *); + ssize_t (*store)(struct o2nm_cluster *, const char *, size_t); +}; + +static ssize_t o2nm_cluster_attr_write(const char *page, ssize_t count, + unsigned int *val) +{ + unsigned long tmp; + char *p = (char *)page; + + tmp = simple_strtoul(p, &p, 0); + if (!p || (*p && (*p != '\n'))) + return -EINVAL; + + if (tmp == 0) + return -EINVAL; + if (tmp >= (u32)-1) + return -ERANGE; + + *val = tmp; + + return count; +} + +static ssize_t o2nm_cluster_attr_idle_timeout_ms_read( + struct o2nm_cluster *cluster, char *page) +{ + return sprintf(page, "%u\n", cluster->cl_idle_timeout_ms); +} + +static ssize_t o2nm_cluster_attr_idle_timeout_ms_write( + struct o2nm_cluster *cluster, const char *page, size_t count) +{ + ssize_t ret; + unsigned int val; + + ret = o2nm_cluster_attr_write(page, count, &val); + + if (ret > 0) { + if (cluster->cl_idle_timeout_ms != val + && o2net_num_connected_peers()) { + mlog(ML_NOTICE, + "o2net: cannot change idle timeout after " + "the first peer has agreed to it." + " %d connected peers\n", + o2net_num_connected_peers()); + ret = -EINVAL; + } else if (val <= cluster->cl_keepalive_delay_ms) { + mlog(ML_NOTICE, "o2net: idle timeout must be larger " + "than keepalive delay\n"); + ret = -EINVAL; + } else { + cluster->cl_idle_timeout_ms = val; + } + } + + return ret; +} + +static ssize_t o2nm_cluster_attr_keepalive_delay_ms_read( + struct o2nm_cluster *cluster, char *page) +{ + return sprintf(page, "%u\n", cluster->cl_keepalive_delay_ms); +} + +static ssize_t o2nm_cluster_attr_keepalive_delay_ms_write( + struct o2nm_cluster *cluster, const char *page, size_t count) +{ + ssize_t ret; + unsigned int val; + + ret = o2nm_cluster_attr_write(page, count, &val); + + if (ret > 0) { + if (cluster->cl_keepalive_delay_ms != val + && o2net_num_connected_peers()) { + mlog(ML_NOTICE, + "o2net: cannot change keepalive delay after" + " the first peer has agreed to it." + " %d connected peers\n", + o2net_num_connected_peers()); + ret = -EINVAL; + } else if (val >= cluster->cl_idle_timeout_ms) { + mlog(ML_NOTICE, "o2net: keepalive delay must be " + "smaller than idle timeout\n"); + ret = -EINVAL; + } else { + cluster->cl_keepalive_delay_ms = val; + } + } + + return ret; +} + +static ssize_t o2nm_cluster_attr_reconnect_delay_ms_read( + struct o2nm_cluster *cluster, char *page) +{ + return sprintf(page, "%u\n", cluster->cl_reconnect_delay_ms); +} + +static ssize_t o2nm_cluster_attr_reconnect_delay_ms_write( + struct o2nm_cluster *cluster, const char *page, size_t count) +{ + return o2nm_cluster_attr_write(page, count, + &cluster->cl_reconnect_delay_ms); +} + +static ssize_t o2nm_cluster_attr_fence_method_read( + struct o2nm_cluster *cluster, char *page) +{ + ssize_t ret = 0; + + if (cluster) + ret = sprintf(page, "%s\n", + o2nm_fence_method_desc[cluster->cl_fence_method]); + return ret; +} + +static ssize_t o2nm_cluster_attr_fence_method_write( + struct o2nm_cluster *cluster, const char *page, size_t count) +{ + unsigned int i; + + if (page[count - 1] != '\n') + goto bail; + + for (i = 0; i < O2NM_FENCE_METHODS; ++i) { + if (count != strlen(o2nm_fence_method_desc[i]) + 1) + continue; + if (strncasecmp(page, o2nm_fence_method_desc[i], count - 1)) + continue; + if (cluster->cl_fence_method != i) { + printk(KERN_INFO "ocfs2: Changing fence method to %s\n", + o2nm_fence_method_desc[i]); + cluster->cl_fence_method = i; + } + return count; + } + +bail: + return -EINVAL; +} + +static struct o2nm_cluster_attribute o2nm_cluster_attr_idle_timeout_ms = { + .attr = { .ca_owner = THIS_MODULE, + .ca_name = "idle_timeout_ms", + .ca_mode = S_IRUGO | S_IWUSR }, + .show = o2nm_cluster_attr_idle_timeout_ms_read, + .store = o2nm_cluster_attr_idle_timeout_ms_write, +}; + +static struct o2nm_cluster_attribute o2nm_cluster_attr_keepalive_delay_ms = { + .attr = { .ca_owner = THIS_MODULE, + .ca_name = "keepalive_delay_ms", + .ca_mode = S_IRUGO | S_IWUSR }, + .show = o2nm_cluster_attr_keepalive_delay_ms_read, + .store = o2nm_cluster_attr_keepalive_delay_ms_write, +}; + +static struct o2nm_cluster_attribute o2nm_cluster_attr_reconnect_delay_ms = { + .attr = { .ca_owner = THIS_MODULE, + .ca_name = "reconnect_delay_ms", + .ca_mode = S_IRUGO | S_IWUSR }, + .show = o2nm_cluster_attr_reconnect_delay_ms_read, + .store = o2nm_cluster_attr_reconnect_delay_ms_write, +}; + +static struct o2nm_cluster_attribute o2nm_cluster_attr_fence_method = { + .attr = { .ca_owner = THIS_MODULE, + .ca_name = "fence_method", + .ca_mode = S_IRUGO | S_IWUSR }, + .show = o2nm_cluster_attr_fence_method_read, + .store = o2nm_cluster_attr_fence_method_write, +}; + +static struct configfs_attribute *o2nm_cluster_attrs[] = { + &o2nm_cluster_attr_idle_timeout_ms.attr, + &o2nm_cluster_attr_keepalive_delay_ms.attr, + &o2nm_cluster_attr_reconnect_delay_ms.attr, + &o2nm_cluster_attr_fence_method.attr, + NULL, +}; +static ssize_t o2nm_cluster_show(struct config_item *item, + struct configfs_attribute *attr, + char *page) +{ + struct o2nm_cluster *cluster = to_o2nm_cluster(item); + struct o2nm_cluster_attribute *o2nm_cluster_attr = + container_of(attr, struct o2nm_cluster_attribute, attr); + ssize_t ret = 0; + + if (o2nm_cluster_attr->show) + ret = o2nm_cluster_attr->show(cluster, page); + return ret; +} + +static ssize_t o2nm_cluster_store(struct config_item *item, + struct configfs_attribute *attr, + const char *page, size_t count) +{ + struct o2nm_cluster *cluster = to_o2nm_cluster(item); + struct o2nm_cluster_attribute *o2nm_cluster_attr = + container_of(attr, struct o2nm_cluster_attribute, attr); + ssize_t ret; + + if (o2nm_cluster_attr->store == NULL) { + ret = -EINVAL; + goto out; + } + + ret = o2nm_cluster_attr->store(cluster, page, count); + if (ret < count) + goto out; +out: + return ret; +} + +static struct config_item *o2nm_node_group_make_item(struct config_group *group, + const char *name) +{ + struct o2nm_node *node = NULL; + + if (strlen(name) > O2NM_MAX_NAME_LEN) + return ERR_PTR(-ENAMETOOLONG); + + node = kzalloc(sizeof(struct o2nm_node), GFP_KERNEL); + if (node == NULL) + return ERR_PTR(-ENOMEM); + + strcpy(node->nd_name, name); /* use item.ci_namebuf instead? */ + config_item_init_type_name(&node->nd_item, name, &o2nm_node_type); + spin_lock_init(&node->nd_lock); + + mlog(ML_CLUSTER, "o2nm: Registering node %s\n", name); + + return &node->nd_item; +} + +static void o2nm_node_group_drop_item(struct config_group *group, + struct config_item *item) +{ + struct o2nm_node *node = to_o2nm_node(item); + struct o2nm_cluster *cluster = to_o2nm_cluster(group->cg_item.ci_parent); + + o2net_disconnect_node(node); + + if (cluster->cl_has_local && + (cluster->cl_local_node == node->nd_num)) { + cluster->cl_has_local = 0; + cluster->cl_local_node = O2NM_INVALID_NODE_NUM; + o2net_stop_listening(node); + } + + /* XXX call into net to stop this node from trading messages */ + + write_lock(&cluster->cl_nodes_lock); + + /* XXX sloppy */ + if (node->nd_ipv4_address) + rb_erase(&node->nd_ip_node, &cluster->cl_node_ip_tree); + + /* nd_num might be 0 if the node number hasn't been set.. */ + if (cluster->cl_nodes[node->nd_num] == node) { + cluster->cl_nodes[node->nd_num] = NULL; + clear_bit(node->nd_num, cluster->cl_nodes_bitmap); + } + write_unlock(&cluster->cl_nodes_lock); + + mlog(ML_CLUSTER, "o2nm: Unregistered node %s\n", + config_item_name(&node->nd_item)); + + config_item_put(item); +} + +static struct configfs_group_operations o2nm_node_group_group_ops = { + .make_item = o2nm_node_group_make_item, + .drop_item = o2nm_node_group_drop_item, +}; + +static struct config_item_type o2nm_node_group_type = { + .ct_group_ops = &o2nm_node_group_group_ops, + .ct_owner = THIS_MODULE, +}; + +/* cluster */ + +static void o2nm_cluster_release(struct config_item *item) +{ + struct o2nm_cluster *cluster = to_o2nm_cluster(item); + + kfree(cluster->cl_group.default_groups); + kfree(cluster); +} + +static struct configfs_item_operations o2nm_cluster_item_ops = { + .release = o2nm_cluster_release, + .show_attribute = o2nm_cluster_show, + .store_attribute = o2nm_cluster_store, +}; + +static struct config_item_type o2nm_cluster_type = { + .ct_item_ops = &o2nm_cluster_item_ops, + .ct_attrs = o2nm_cluster_attrs, + .ct_owner = THIS_MODULE, +}; + +/* cluster set */ + +struct o2nm_cluster_group { + struct configfs_subsystem cs_subsys; + /* some stuff? */ +}; + +#if 0 +static struct o2nm_cluster_group *to_o2nm_cluster_group(struct config_group *group) +{ + return group ? + container_of(to_configfs_subsystem(group), struct o2nm_cluster_group, cs_subsys) + : NULL; +} +#endif + +static struct config_group *o2nm_cluster_group_make_group(struct config_group *group, + const char *name) +{ + struct o2nm_cluster *cluster = NULL; + struct o2nm_node_group *ns = NULL; + struct config_group *o2hb_group = NULL, *ret = NULL; + void *defs = NULL; + + /* this runs under the parent dir's i_mutex; there can be only + * one caller in here at a time */ + if (o2nm_single_cluster) + return ERR_PTR(-ENOSPC); + + cluster = kzalloc(sizeof(struct o2nm_cluster), GFP_KERNEL); + ns = kzalloc(sizeof(struct o2nm_node_group), GFP_KERNEL); + defs = kcalloc(3, sizeof(struct config_group *), GFP_KERNEL); + o2hb_group = o2hb_alloc_hb_set(); + if (cluster == NULL || ns == NULL || o2hb_group == NULL || defs == NULL) + goto out; + + config_group_init_type_name(&cluster->cl_group, name, + &o2nm_cluster_type); + config_group_init_type_name(&ns->ns_group, "node", + &o2nm_node_group_type); + + cluster->cl_group.default_groups = defs; + cluster->cl_group.default_groups[0] = &ns->ns_group; + cluster->cl_group.default_groups[1] = o2hb_group; + cluster->cl_group.default_groups[2] = NULL; + rwlock_init(&cluster->cl_nodes_lock); + cluster->cl_node_ip_tree = RB_ROOT; + cluster->cl_reconnect_delay_ms = O2NET_RECONNECT_DELAY_MS_DEFAULT; + cluster->cl_idle_timeout_ms = O2NET_IDLE_TIMEOUT_MS_DEFAULT; + cluster->cl_keepalive_delay_ms = O2NET_KEEPALIVE_DELAY_MS_DEFAULT; + cluster->cl_fence_method = O2NM_FENCE_RESET; + + ret = &cluster->cl_group; + o2nm_single_cluster = cluster; + +out: + if (ret == NULL) { + kfree(cluster); + kfree(ns); + o2hb_free_hb_set(o2hb_group); + kfree(defs); + ret = ERR_PTR(-ENOMEM); + } + + return ret; +} + +static void o2nm_cluster_group_drop_item(struct config_group *group, struct config_item *item) +{ + struct o2nm_cluster *cluster = to_o2nm_cluster(item); + int i; + struct config_item *killme; + + BUG_ON(o2nm_single_cluster != cluster); + o2nm_single_cluster = NULL; + + for (i = 0; cluster->cl_group.default_groups[i]; i++) { + killme = &cluster->cl_group.default_groups[i]->cg_item; + cluster->cl_group.default_groups[i] = NULL; + config_item_put(killme); + } + + config_item_put(item); +} + +static struct configfs_group_operations o2nm_cluster_group_group_ops = { + .make_group = o2nm_cluster_group_make_group, + .drop_item = o2nm_cluster_group_drop_item, +}; + +static struct config_item_type o2nm_cluster_group_type = { + .ct_group_ops = &o2nm_cluster_group_group_ops, + .ct_owner = THIS_MODULE, +}; + +static struct o2nm_cluster_group o2nm_cluster_group = { + .cs_subsys = { + .su_group = { + .cg_item = { + .ci_namebuf = "cluster", + .ci_type = &o2nm_cluster_group_type, + }, + }, + }, +}; + +int o2nm_depend_item(struct config_item *item) +{ + return configfs_depend_item(&o2nm_cluster_group.cs_subsys, item); +} + +void o2nm_undepend_item(struct config_item *item) +{ + configfs_undepend_item(&o2nm_cluster_group.cs_subsys, item); +} + +int o2nm_depend_this_node(void) +{ + int ret = 0; + struct o2nm_node *local_node; + + local_node = o2nm_get_node_by_num(o2nm_this_node()); + if (!local_node) { + ret = -EINVAL; + goto out; + } + + ret = o2nm_depend_item(&local_node->nd_item); + o2nm_node_put(local_node); + +out: + return ret; +} + +void o2nm_undepend_this_node(void) +{ + struct o2nm_node *local_node; + + local_node = o2nm_get_node_by_num(o2nm_this_node()); + BUG_ON(!local_node); + + o2nm_undepend_item(&local_node->nd_item); + o2nm_node_put(local_node); +} + + +static void __exit exit_o2nm(void) +{ + /* XXX sync with hb callbacks and shut down hb? */ + o2net_unregister_hb_callbacks(); + configfs_unregister_subsystem(&o2nm_cluster_group.cs_subsys); + o2cb_sys_shutdown(); + + o2net_exit(); + o2hb_exit(); +} + +static int __init init_o2nm(void) +{ + int ret = -1; + + cluster_print_version(); + + ret = o2hb_init(); + if (ret) + goto out; + + ret = o2net_init(); + if (ret) + goto out_o2hb; + + ret = o2net_register_hb_callbacks(); + if (ret) + goto out_o2net; + + config_group_init(&o2nm_cluster_group.cs_subsys.su_group); + mutex_init(&o2nm_cluster_group.cs_subsys.su_mutex); + ret = configfs_register_subsystem(&o2nm_cluster_group.cs_subsys); + if (ret) { + printk(KERN_ERR "nodemanager: Registration returned %d\n", ret); + goto out_callbacks; + } + + ret = o2cb_sys_init(); + if (!ret) + goto out; + + configfs_unregister_subsystem(&o2nm_cluster_group.cs_subsys); +out_callbacks: + o2net_unregister_hb_callbacks(); +out_o2net: + o2net_exit(); +out_o2hb: + o2hb_exit(); +out: + return ret; +} + +MODULE_AUTHOR("Oracle"); +MODULE_LICENSE("GPL"); + +module_init(init_o2nm) +module_exit(exit_o2nm) diff --git a/drivers/staging/ramster/cluster/nodemanager.h b/drivers/staging/ramster/cluster/nodemanager.h new file mode 100644 index 0000000..09ea2d3 --- /dev/null +++ b/drivers/staging/ramster/cluster/nodemanager.h @@ -0,0 +1,88 @@ +/* -*- mode: c; c-basic-offset: 8; -*- + * vim: noexpandtab sw=8 ts=8 sts=0: + * + * nodemanager.h + * + * Function prototypes + * + * Copyright (C) 2004 Oracle. All rights reserved. + * + * 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; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 021110-1307, USA. + * + */ + +#ifndef O2CLUSTER_NODEMANAGER_H +#define O2CLUSTER_NODEMANAGER_H + +#include "ocfs2_nodemanager.h" + +/* This totally doesn't belong here. */ +#include +#include + +enum o2nm_fence_method { + O2NM_FENCE_RESET = 0, + O2NM_FENCE_PANIC, + O2NM_FENCE_METHODS, /* Number of fence methods */ +}; + +struct o2nm_node { + spinlock_t nd_lock; + struct config_item nd_item; + char nd_name[O2NM_MAX_NAME_LEN+1]; /* replace? */ + __u8 nd_num; + /* only one address per node, as attributes, for now. */ + __be32 nd_ipv4_address; + __be16 nd_ipv4_port; + struct rb_node nd_ip_node; + /* there can be only one local node for now */ + int nd_local; + + unsigned long nd_set_attributes; +}; + +struct o2nm_cluster { + struct config_group cl_group; + unsigned cl_has_local:1; + u8 cl_local_node; + rwlock_t cl_nodes_lock; + struct o2nm_node *cl_nodes[O2NM_MAX_NODES]; + struct rb_root cl_node_ip_tree; + unsigned int cl_idle_timeout_ms; + unsigned int cl_keepalive_delay_ms; + unsigned int cl_reconnect_delay_ms; + enum o2nm_fence_method cl_fence_method; + + /* this bitmap is part of a hack for disk bitmap.. will go eventually. - zab */ + unsigned long cl_nodes_bitmap[BITS_TO_LONGS(O2NM_MAX_NODES)]; +}; + +extern struct o2nm_cluster *o2nm_single_cluster; + +u8 o2nm_this_node(void); + +int o2nm_configured_node_map(unsigned long *map, unsigned bytes); +struct o2nm_node *o2nm_get_node_by_num(u8 node_num); +struct o2nm_node *o2nm_get_node_by_ip(__be32 addr); +void o2nm_node_get(struct o2nm_node *node); +void o2nm_node_put(struct o2nm_node *node); + +int o2nm_depend_item(struct config_item *item); +void o2nm_undepend_item(struct config_item *item); +int o2nm_depend_this_node(void); +void o2nm_undepend_this_node(void); + +#endif /* O2CLUSTER_NODEMANAGER_H */ diff --git a/drivers/staging/ramster/cluster/ocfs2_heartbeat.h b/drivers/staging/ramster/cluster/ocfs2_heartbeat.h new file mode 100644 index 0000000..3f4151d --- /dev/null +++ b/drivers/staging/ramster/cluster/ocfs2_heartbeat.h @@ -0,0 +1,38 @@ +/* -*- mode: c; c-basic-offset: 8; -*- + * vim: noexpandtab sw=8 ts=8 sts=0: + * + * ocfs2_heartbeat.h + * + * On-disk structures for ocfs2_heartbeat + * + * Copyright (C) 2002, 2004 Oracle. All rights reserved. + * + * 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; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 021110-1307, USA. + */ + +#ifndef _OCFS2_HEARTBEAT_H +#define _OCFS2_HEARTBEAT_H + +struct o2hb_disk_heartbeat_block { + __le64 hb_seq; + __u8 hb_node; + __u8 hb_pad1[3]; + __le32 hb_cksum; + __le64 hb_generation; + __le32 hb_dead_ms; +}; + +#endif /* _OCFS2_HEARTBEAT_H */ diff --git a/drivers/staging/ramster/cluster/ocfs2_nodemanager.h b/drivers/staging/ramster/cluster/ocfs2_nodemanager.h new file mode 100644 index 0000000..49b5943 --- /dev/null +++ b/drivers/staging/ramster/cluster/ocfs2_nodemanager.h @@ -0,0 +1,45 @@ +/* -*- mode: c; c-basic-offset: 8; -*- + * vim: noexpandtab sw=8 ts=8 sts=0: + * + * ocfs2_nodemanager.h + * + * Header describing the interface between userspace and the kernel + * for the ocfs2_nodemanager module. + * + * Copyright (C) 2002, 2004 Oracle. All rights reserved. + * + * 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; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 021110-1307, USA. + * + */ + +#ifndef _OCFS2_NODEMANAGER_H +#define _OCFS2_NODEMANAGER_H + +#define O2NM_API_VERSION 5 + +#define O2NM_MAX_NODES 255 +#define O2NM_INVALID_NODE_NUM 255 + +/* host name, group name, cluster name all 64 bytes */ +#define O2NM_MAX_NAME_LEN 64 // __NEW_UTS_LEN + +/* + * Maximum number of global heartbeat regions allowed. + * **CAUTION** Changing this number will break dlm compatibility. + */ +#define O2NM_MAX_REGIONS 32 + +#endif /* _OCFS2_NODEMANAGER_H */ diff --git a/drivers/staging/ramster/cluster/quorum.c b/drivers/staging/ramster/cluster/quorum.c new file mode 100644 index 0000000..8f9cea1 --- /dev/null +++ b/drivers/staging/ramster/cluster/quorum.c @@ -0,0 +1,331 @@ +/* -*- mode: c; c-basic-offset: 8; -*- + * + * vim: noexpandtab sw=8 ts=8 sts=0: + * + * Copyright (C) 2005 Oracle. All rights reserved. + * + * 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; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 021110-1307, USA. + */ + +/* This quorum hack is only here until we transition to some more rational + * approach that is driven from userspace. Honest. No foolin'. + * + * Imagine two nodes lose network connectivity to each other but they're still + * up and operating in every other way. Presumably a network timeout indicates + * that a node is broken and should be recovered. They can't both recover each + * other and both carry on without serialising their access to the file system. + * They need to decide who is authoritative. Now extend that problem to + * arbitrary groups of nodes losing connectivity between each other. + * + * So we declare that a node which has given up on connecting to a majority + * of nodes who are still heartbeating will fence itself. + * + * There are huge opportunities for races here. After we give up on a node's + * connection we need to wait long enough to give heartbeat an opportunity + * to declare the node as truly dead. We also need to be careful with the + * race between when we see a node start heartbeating and when we connect + * to it. + * + * So nodes that are in this transtion put a hold on the quorum decision + * with a counter. As they fall out of this transition they drop the count + * and if they're the last, they fire off the decision. + */ +#include +#include +#include + +#include "heartbeat.h" +#include "nodemanager.h" +#define MLOG_MASK_PREFIX ML_QUORUM +#include "masklog.h" +#include "quorum.h" + +static struct o2quo_state { + spinlock_t qs_lock; + struct work_struct qs_work; + int qs_pending; + int qs_heartbeating; + unsigned long qs_hb_bm[BITS_TO_LONGS(O2NM_MAX_NODES)]; + int qs_connected; + unsigned long qs_conn_bm[BITS_TO_LONGS(O2NM_MAX_NODES)]; + int qs_holds; + unsigned long qs_hold_bm[BITS_TO_LONGS(O2NM_MAX_NODES)]; +} o2quo_state; + +/* this is horribly heavy-handed. It should instead flip the file + * system RO and call some userspace script. */ +static void o2quo_fence_self(void) +{ + /* panic spins with interrupts enabled. with preempt + * threads can still schedule, etc, etc */ + o2hb_stop_all_regions(); + + switch (o2nm_single_cluster->cl_fence_method) { + case O2NM_FENCE_PANIC: + panic("*** ocfs2 is very sorry to be fencing this system by " + "panicing ***\n"); + break; + default: + WARN_ON(o2nm_single_cluster->cl_fence_method >= + O2NM_FENCE_METHODS); + case O2NM_FENCE_RESET: + printk(KERN_ERR "*** ocfs2 is very sorry to be fencing this " + "system by restarting ***\n"); + emergency_restart(); + break; + }; +} + +/* Indicate that a timeout occurred on a hearbeat region write. The + * other nodes in the cluster may consider us dead at that time so we + * want to "fence" ourselves so that we don't scribble on the disk + * after they think they've recovered us. This can't solve all + * problems related to writeout after recovery but this hack can at + * least close some of those gaps. When we have real fencing, this can + * go away as our node would be fenced externally before other nodes + * begin recovery. */ +void o2quo_disk_timeout(void) +{ + o2quo_fence_self(); +} + +static void o2quo_make_decision(struct work_struct *work) +{ + int quorum; + int lowest_hb, lowest_reachable = 0, fence = 0; + struct o2quo_state *qs = &o2quo_state; + + spin_lock(&qs->qs_lock); + + lowest_hb = find_first_bit(qs->qs_hb_bm, O2NM_MAX_NODES); + if (lowest_hb != O2NM_MAX_NODES) + lowest_reachable = test_bit(lowest_hb, qs->qs_conn_bm); + + mlog(0, "heartbeating: %d, connected: %d, " + "lowest: %d (%sreachable)\n", qs->qs_heartbeating, + qs->qs_connected, lowest_hb, lowest_reachable ? "" : "un"); + + if (!test_bit(o2nm_this_node(), qs->qs_hb_bm) || + qs->qs_heartbeating == 1) + goto out; + + if (qs->qs_heartbeating & 1) { + /* the odd numbered cluster case is straight forward -- + * if we can't talk to the majority we're hosed */ + quorum = (qs->qs_heartbeating + 1)/2; + if (qs->qs_connected < quorum) { + mlog(ML_ERROR, "fencing this node because it is " + "only connected to %u nodes and %u is needed " + "to make a quorum out of %u heartbeating nodes\n", + qs->qs_connected, quorum, + qs->qs_heartbeating); + fence = 1; + } + } else { + /* the even numbered cluster adds the possibility of each half + * of the cluster being able to talk amongst themselves.. in + * that case we're hosed if we can't talk to the group that has + * the lowest numbered node */ + quorum = qs->qs_heartbeating / 2; + if (qs->qs_connected < quorum) { + mlog(ML_ERROR, "fencing this node because it is " + "only connected to %u nodes and %u is needed " + "to make a quorum out of %u heartbeating nodes\n", + qs->qs_connected, quorum, + qs->qs_heartbeating); + fence = 1; + } + else if ((qs->qs_connected == quorum) && + !lowest_reachable) { + mlog(ML_ERROR, "fencing this node because it is " + "connected to a half-quorum of %u out of %u " + "nodes which doesn't include the lowest active " + "node %u\n", quorum, qs->qs_heartbeating, + lowest_hb); + fence = 1; + } + } + +out: + spin_unlock(&qs->qs_lock); + if (fence) + o2quo_fence_self(); +} + +static void o2quo_set_hold(struct o2quo_state *qs, u8 node) +{ + assert_spin_locked(&qs->qs_lock); + + if (!test_and_set_bit(node, qs->qs_hold_bm)) { + qs->qs_holds++; + mlog_bug_on_msg(qs->qs_holds == O2NM_MAX_NODES, + "node %u\n", node); + mlog(0, "node %u, %d total\n", node, qs->qs_holds); + } +} + +static void o2quo_clear_hold(struct o2quo_state *qs, u8 node) +{ + assert_spin_locked(&qs->qs_lock); + + if (test_and_clear_bit(node, qs->qs_hold_bm)) { + mlog(0, "node %u, %d total\n", node, qs->qs_holds - 1); + if (--qs->qs_holds == 0) { + if (qs->qs_pending) { + qs->qs_pending = 0; + schedule_work(&qs->qs_work); + } + } + mlog_bug_on_msg(qs->qs_holds < 0, "node %u, holds %d\n", + node, qs->qs_holds); + } +} + +/* as a node comes up we delay the quorum decision until we know the fate of + * the connection. the hold will be droped in conn_up or hb_down. it might be + * perpetuated by con_err until hb_down. if we already have a conn, we might + * be dropping a hold that conn_up got. */ +void o2quo_hb_up(u8 node) +{ + struct o2quo_state *qs = &o2quo_state; + + spin_lock(&qs->qs_lock); + + qs->qs_heartbeating++; + mlog_bug_on_msg(qs->qs_heartbeating == O2NM_MAX_NODES, + "node %u\n", node); + mlog_bug_on_msg(test_bit(node, qs->qs_hb_bm), "node %u\n", node); + set_bit(node, qs->qs_hb_bm); + + mlog(0, "node %u, %d total\n", node, qs->qs_heartbeating); + + if (!test_bit(node, qs->qs_conn_bm)) + o2quo_set_hold(qs, node); + else + o2quo_clear_hold(qs, node); + + spin_unlock(&qs->qs_lock); +} + +/* hb going down releases any holds we might have had due to this node from + * conn_up, conn_err, or hb_up */ +void o2quo_hb_down(u8 node) +{ + struct o2quo_state *qs = &o2quo_state; + + spin_lock(&qs->qs_lock); + + qs->qs_heartbeating--; + mlog_bug_on_msg(qs->qs_heartbeating < 0, + "node %u, %d heartbeating\n", + node, qs->qs_heartbeating); + mlog_bug_on_msg(!test_bit(node, qs->qs_hb_bm), "node %u\n", node); + clear_bit(node, qs->qs_hb_bm); + + mlog(0, "node %u, %d total\n", node, qs->qs_heartbeating); + + o2quo_clear_hold(qs, node); + + spin_unlock(&qs->qs_lock); +} + +/* this tells us that we've decided that the node is still heartbeating + * even though we've lost it's conn. it must only be called after conn_err + * and indicates that we must now make a quorum decision in the future, + * though we might be doing so after waiting for holds to drain. Here + * we'll be dropping the hold from conn_err. */ +void o2quo_hb_still_up(u8 node) +{ + struct o2quo_state *qs = &o2quo_state; + + spin_lock(&qs->qs_lock); + + mlog(0, "node %u\n", node); + + qs->qs_pending = 1; + o2quo_clear_hold(qs, node); + + spin_unlock(&qs->qs_lock); +} + +/* This is analogous to hb_up. as a node's connection comes up we delay the + * quorum decision until we see it heartbeating. the hold will be droped in + * hb_up or hb_down. it might be perpetuated by con_err until hb_down. if + * it's already heartbeating we we might be dropping a hold that conn_up got. + * */ +void o2quo_conn_up(u8 node) +{ + struct o2quo_state *qs = &o2quo_state; + + spin_lock(&qs->qs_lock); + + qs->qs_connected++; + mlog_bug_on_msg(qs->qs_connected == O2NM_MAX_NODES, + "node %u\n", node); + mlog_bug_on_msg(test_bit(node, qs->qs_conn_bm), "node %u\n", node); + set_bit(node, qs->qs_conn_bm); + + mlog(0, "node %u, %d total\n", node, qs->qs_connected); + + if (!test_bit(node, qs->qs_hb_bm)) + o2quo_set_hold(qs, node); + else + o2quo_clear_hold(qs, node); + + spin_unlock(&qs->qs_lock); +} + +/* we've decided that we won't ever be connecting to the node again. if it's + * still heartbeating we grab a hold that will delay decisions until either the + * node stops heartbeating from hb_down or the caller decides that the node is + * still up and calls still_up */ +void o2quo_conn_err(u8 node) +{ + struct o2quo_state *qs = &o2quo_state; + + spin_lock(&qs->qs_lock); + + if (test_bit(node, qs->qs_conn_bm)) { + qs->qs_connected--; + mlog_bug_on_msg(qs->qs_connected < 0, + "node %u, connected %d\n", + node, qs->qs_connected); + + clear_bit(node, qs->qs_conn_bm); + } + + mlog(0, "node %u, %d total\n", node, qs->qs_connected); + + if (test_bit(node, qs->qs_hb_bm)) + o2quo_set_hold(qs, node); + + spin_unlock(&qs->qs_lock); +} + +void o2quo_init(void) +{ + struct o2quo_state *qs = &o2quo_state; + + spin_lock_init(&qs->qs_lock); + INIT_WORK(&qs->qs_work, o2quo_make_decision); +} + +void o2quo_exit(void) +{ + struct o2quo_state *qs = &o2quo_state; + + flush_work_sync(&qs->qs_work); +} diff --git a/drivers/staging/ramster/cluster/quorum.h b/drivers/staging/ramster/cluster/quorum.h new file mode 100644 index 0000000..6649cc6 --- /dev/null +++ b/drivers/staging/ramster/cluster/quorum.h @@ -0,0 +1,36 @@ +/* -*- mode: c; c-basic-offset: 8; -*- + * vim: noexpandtab sw=8 ts=8 sts=0: + * + * Copyright (C) 2005 Oracle. All rights reserved. + * + * 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; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 021110-1307, USA. + * + */ + +#ifndef O2CLUSTER_QUORUM_H +#define O2CLUSTER_QUORUM_H + +void o2quo_init(void); +void o2quo_exit(void); + +void o2quo_hb_up(u8 node); +void o2quo_hb_down(u8 node); +void o2quo_hb_still_up(u8 node); +void o2quo_conn_up(u8 node); +void o2quo_conn_err(u8 node); +void o2quo_disk_timeout(void); + +#endif /* O2CLUSTER_QUORUM_H */ diff --git a/drivers/staging/ramster/cluster/sys.c b/drivers/staging/ramster/cluster/sys.c new file mode 100644 index 0000000..a4b0773 --- /dev/null +++ b/drivers/staging/ramster/cluster/sys.c @@ -0,0 +1,82 @@ +/* -*- mode: c; c-basic-offset: 8; -*- + * vim: noexpandtab sw=8 ts=8 sts=0: + * + * sys.c + * + * OCFS2 cluster sysfs interface + * + * Copyright (C) 2005 Oracle. All rights reserved. + * + * 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, + * version 2 of the License. + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 021110-1307, USA. + * + */ + +#include +#include +#include +#include +#include + +#include "ocfs2_nodemanager.h" +#include "masklog.h" +#include "sys.h" + + +static ssize_t version_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%u\n", O2NM_API_VERSION); +} +static struct kobj_attribute attr_version = + __ATTR(interface_revision, S_IFREG | S_IRUGO, version_show, NULL); + +static struct attribute *o2cb_attrs[] = { + &attr_version.attr, + NULL, +}; + +static struct attribute_group o2cb_attr_group = { + .attrs = o2cb_attrs, +}; + +static struct kset *o2cb_kset; + +void o2cb_sys_shutdown(void) +{ + mlog_sys_shutdown(); + kset_unregister(o2cb_kset); +} + +int o2cb_sys_init(void) +{ + int ret; + + o2cb_kset = kset_create_and_add("o2cb", NULL, fs_kobj); + if (!o2cb_kset) + return -ENOMEM; + + ret = sysfs_create_group(&o2cb_kset->kobj, &o2cb_attr_group); + if (ret) + goto error; + + ret = mlog_sys_init(o2cb_kset); + if (ret) + goto error; + return 0; +error: + kset_unregister(o2cb_kset); + return ret; +} diff --git a/drivers/staging/ramster/cluster/sys.h b/drivers/staging/ramster/cluster/sys.h new file mode 100644 index 0000000..d66b8ab --- /dev/null +++ b/drivers/staging/ramster/cluster/sys.h @@ -0,0 +1,33 @@ +/* -*- mode: c; c-basic-offset: 8; -*- + * vim: noexpandtab sw=8 ts=8 sts=0: + * + * sys.h + * + * Function prototypes for o2cb sysfs interface + * + * Copyright (C) 2005 Oracle. All rights reserved. + * + * 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, + * version 2 of the License. + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 021110-1307, USA. + * + */ + +#ifndef O2CLUSTER_SYS_H +#define O2CLUSTER_SYS_H + +void o2cb_sys_shutdown(void); +int o2cb_sys_init(void); + +#endif /* O2CLUSTER_SYS_H */ diff --git a/drivers/staging/ramster/cluster/tcp.c b/drivers/staging/ramster/cluster/tcp.c new file mode 100644 index 0000000..044e7b5 --- /dev/null +++ b/drivers/staging/ramster/cluster/tcp.c @@ -0,0 +1,2150 @@ +/* -*- mode: c; c-basic-offset: 8; -*- + * + * vim: noexpandtab sw=8 ts=8 sts=0: + * + * Copyright (C) 2004 Oracle. All rights reserved. + * + * 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; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 021110-1307, USA. + * + * ---- + * + * Callers for this were originally written against a very simple synchronus + * API. This implementation reflects those simple callers. Some day I'm sure + * we'll need to move to a more robust posting/callback mechanism. + * + * Transmit calls pass in kernel virtual addresses and block copying this into + * the socket's tx buffers via a usual blocking sendmsg. They'll block waiting + * for a failed socket to timeout. TX callers can also pass in a poniter to an + * 'int' which gets filled with an errno off the wire in response to the + * message they send. + * + * Handlers for unsolicited messages are registered. Each socket has a page + * that incoming data is copied into. First the header, then the data. + * Handlers are called from only one thread with a reference to this per-socket + * page. This page is destroyed after the handler call, so it can't be + * referenced beyond the call. Handlers may block but are discouraged from + * doing so. + * + * Any framing errors (bad magic, large payload lengths) close a connection. + * + * Our sock_container holds the state we associate with a socket. It's current + * framing state is held there as well as the refcounting we do around when it + * is safe to tear down the socket. The socket is only finally torn down from + * the container when the container loses all of its references -- so as long + * as you hold a ref on the container you can trust that the socket is valid + * for use with kernel socket APIs. + * + * Connections are initiated between a pair of nodes when the node with the + * higher node number gets a heartbeat callback which indicates that the lower + * numbered node has started heartbeating. The lower numbered node is passive + * and only accepts the connection if the higher numbered node is heartbeating. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "heartbeat.h" +#include "tcp.h" +#include "nodemanager.h" +#define MLOG_MASK_PREFIX ML_TCP +#include "masklog.h" +#include "quorum.h" + +#include "tcp_internal.h" + +#define SC_NODEF_FMT "node %s (num %u) at %pI4:%u" +#define SC_NODEF_ARGS(sc) sc->sc_node->nd_name, sc->sc_node->nd_num, \ + &sc->sc_node->nd_ipv4_address, \ + ntohs(sc->sc_node->nd_ipv4_port) + +/* + * In the following two log macros, the whitespace after the ',' just + * before ##args is intentional. Otherwise, gcc 2.95 will eat the + * previous token if args expands to nothing. + */ +#define msglog(hdr, fmt, args...) do { \ + typeof(hdr) __hdr = (hdr); \ + mlog(ML_MSG, "[mag %u len %u typ %u stat %d sys_stat %d " \ + "key %08x num %u] " fmt, \ + be16_to_cpu(__hdr->magic), be16_to_cpu(__hdr->data_len), \ + be16_to_cpu(__hdr->msg_type), be32_to_cpu(__hdr->status), \ + be32_to_cpu(__hdr->sys_status), be32_to_cpu(__hdr->key), \ + be32_to_cpu(__hdr->msg_num) , ##args); \ +} while (0) + +#define sclog(sc, fmt, args...) do { \ + typeof(sc) __sc = (sc); \ + mlog(ML_SOCKET, "[sc %p refs %d sock %p node %u page %p " \ + "pg_off %zu] " fmt, __sc, \ + atomic_read(&__sc->sc_kref.refcount), __sc->sc_sock, \ + __sc->sc_node->nd_num, __sc->sc_page, __sc->sc_page_off , \ + ##args); \ +} while (0) + +static DEFINE_RWLOCK(o2net_handler_lock); +static struct rb_root o2net_handler_tree = RB_ROOT; + +static struct o2net_node o2net_nodes[O2NM_MAX_NODES]; + +/* XXX someday we'll need better accounting */ +static struct socket *o2net_listen_sock = NULL; + +/* + * listen work is only queued by the listening socket callbacks on the + * o2net_wq. teardown detaches the callbacks before destroying the workqueue. + * quorum work is queued as sock containers are shutdown.. stop_listening + * tears down all the node's sock containers, preventing future shutdowns + * and queued quroum work, before canceling delayed quorum work and + * destroying the work queue. + */ +static struct workqueue_struct *o2net_wq; +static struct work_struct o2net_listen_work; + +static struct o2hb_callback_func o2net_hb_up, o2net_hb_down; +#define O2NET_HB_PRI 0x1 + +static struct o2net_handshake *o2net_hand; +static struct o2net_msg *o2net_keep_req, *o2net_keep_resp; + +static int o2net_sys_err_translations[O2NET_ERR_MAX] = + {[O2NET_ERR_NONE] = 0, + [O2NET_ERR_NO_HNDLR] = -ENOPROTOOPT, + [O2NET_ERR_OVERFLOW] = -EOVERFLOW, + [O2NET_ERR_DIED] = -EHOSTDOWN,}; + +/* can't quite avoid *all* internal declarations :/ */ +static void o2net_sc_connect_completed(struct work_struct *work); +static void o2net_rx_until_empty(struct work_struct *work); +static void o2net_shutdown_sc(struct work_struct *work); +static void o2net_listen_data_ready(struct sock *sk, int bytes); +static void o2net_sc_send_keep_req(struct work_struct *work); +static void o2net_idle_timer(unsigned long data); +static void o2net_sc_postpone_idle(struct o2net_sock_container *sc); +static void o2net_sc_reset_idle_timer(struct o2net_sock_container *sc); + +#ifdef CONFIG_DEBUG_FS +static void o2net_init_nst(struct o2net_send_tracking *nst, u32 msgtype, + u32 msgkey, struct task_struct *task, u8 node) +{ + INIT_LIST_HEAD(&nst->st_net_debug_item); + nst->st_task = task; + nst->st_msg_type = msgtype; + nst->st_msg_key = msgkey; + nst->st_node = node; +} + +static inline void o2net_set_nst_sock_time(struct o2net_send_tracking *nst) +{ + nst->st_sock_time = ktime_get(); +} + +static inline void o2net_set_nst_send_time(struct o2net_send_tracking *nst) +{ + nst->st_send_time = ktime_get(); +} + +static inline void o2net_set_nst_status_time(struct o2net_send_tracking *nst) +{ + nst->st_status_time = ktime_get(); +} + +static inline void o2net_set_nst_sock_container(struct o2net_send_tracking *nst, + struct o2net_sock_container *sc) +{ + nst->st_sc = sc; +} + +static inline void o2net_set_nst_msg_id(struct o2net_send_tracking *nst, + u32 msg_id) +{ + nst->st_id = msg_id; +} + +static inline void o2net_set_sock_timer(struct o2net_sock_container *sc) +{ + sc->sc_tv_timer = ktime_get(); +} + +static inline void o2net_set_data_ready_time(struct o2net_sock_container *sc) +{ + sc->sc_tv_data_ready = ktime_get(); +} + +static inline void o2net_set_advance_start_time(struct o2net_sock_container *sc) +{ + sc->sc_tv_advance_start = ktime_get(); +} + +static inline void o2net_set_advance_stop_time(struct o2net_sock_container *sc) +{ + sc->sc_tv_advance_stop = ktime_get(); +} + +static inline void o2net_set_func_start_time(struct o2net_sock_container *sc) +{ + sc->sc_tv_func_start = ktime_get(); +} + +static inline void o2net_set_func_stop_time(struct o2net_sock_container *sc) +{ + sc->sc_tv_func_stop = ktime_get(); +} + +#else /* CONFIG_DEBUG_FS */ +# define o2net_init_nst(a, b, c, d, e) +# define o2net_set_nst_sock_time(a) +# define o2net_set_nst_send_time(a) +# define o2net_set_nst_status_time(a) +# define o2net_set_nst_sock_container(a, b) +# define o2net_set_nst_msg_id(a, b) +# define o2net_set_sock_timer(a) +# define o2net_set_data_ready_time(a) +# define o2net_set_advance_start_time(a) +# define o2net_set_advance_stop_time(a) +# define o2net_set_func_start_time(a) +# define o2net_set_func_stop_time(a) +#endif /* CONFIG_DEBUG_FS */ + +#ifdef CONFIG_OCFS2_FS_STATS +static ktime_t o2net_get_func_run_time(struct o2net_sock_container *sc) +{ + return ktime_sub(sc->sc_tv_func_stop, sc->sc_tv_func_start); +} + +static void o2net_update_send_stats(struct o2net_send_tracking *nst, + struct o2net_sock_container *sc) +{ + sc->sc_tv_status_total = ktime_add(sc->sc_tv_status_total, + ktime_sub(ktime_get(), + nst->st_status_time)); + sc->sc_tv_send_total = ktime_add(sc->sc_tv_send_total, + ktime_sub(nst->st_status_time, + nst->st_send_time)); + sc->sc_tv_acquiry_total = ktime_add(sc->sc_tv_acquiry_total, + ktime_sub(nst->st_send_time, + nst->st_sock_time)); + sc->sc_send_count++; +} + +static void o2net_update_recv_stats(struct o2net_sock_container *sc) +{ + sc->sc_tv_process_total = ktime_add(sc->sc_tv_process_total, + o2net_get_func_run_time(sc)); + sc->sc_recv_count++; +} + +#else + +# define o2net_update_send_stats(a, b) + +# define o2net_update_recv_stats(sc) + +#endif /* CONFIG_OCFS2_FS_STATS */ + +static inline int o2net_reconnect_delay(void) +{ + return o2nm_single_cluster->cl_reconnect_delay_ms; +} + +static inline int o2net_keepalive_delay(void) +{ + return o2nm_single_cluster->cl_keepalive_delay_ms; +} + +static inline int o2net_idle_timeout(void) +{ + return o2nm_single_cluster->cl_idle_timeout_ms; +} + +static inline int o2net_sys_err_to_errno(enum o2net_system_error err) +{ + int trans; + BUG_ON(err >= O2NET_ERR_MAX); + trans = o2net_sys_err_translations[err]; + + /* Just in case we mess up the translation table above */ + BUG_ON(err != O2NET_ERR_NONE && trans == 0); + return trans; +} + +static struct o2net_node * o2net_nn_from_num(u8 node_num) +{ + BUG_ON(node_num >= ARRAY_SIZE(o2net_nodes)); + return &o2net_nodes[node_num]; +} + +static u8 o2net_num_from_nn(struct o2net_node *nn) +{ + BUG_ON(nn == NULL); + return nn - o2net_nodes; +} + +/* ------------------------------------------------------------ */ + +static int o2net_prep_nsw(struct o2net_node *nn, struct o2net_status_wait *nsw) +{ + int ret = 0; + + do { + if (!idr_pre_get(&nn->nn_status_idr, GFP_ATOMIC)) { + ret = -EAGAIN; + break; + } + spin_lock(&nn->nn_lock); + ret = idr_get_new(&nn->nn_status_idr, nsw, &nsw->ns_id); + if (ret == 0) + list_add_tail(&nsw->ns_node_item, + &nn->nn_status_list); + spin_unlock(&nn->nn_lock); + } while (ret == -EAGAIN); + + if (ret == 0) { + init_waitqueue_head(&nsw->ns_wq); + nsw->ns_sys_status = O2NET_ERR_NONE; + nsw->ns_status = 0; + } + + return ret; +} + +static void o2net_complete_nsw_locked(struct o2net_node *nn, + struct o2net_status_wait *nsw, + enum o2net_system_error sys_status, + s32 status) +{ + assert_spin_locked(&nn->nn_lock); + + if (!list_empty(&nsw->ns_node_item)) { + list_del_init(&nsw->ns_node_item); + nsw->ns_sys_status = sys_status; + nsw->ns_status = status; + idr_remove(&nn->nn_status_idr, nsw->ns_id); + wake_up(&nsw->ns_wq); + } +} + +static void o2net_complete_nsw(struct o2net_node *nn, + struct o2net_status_wait *nsw, + u64 id, enum o2net_system_error sys_status, + s32 status) +{ + spin_lock(&nn->nn_lock); + if (nsw == NULL) { + if (id > INT_MAX) + goto out; + + nsw = idr_find(&nn->nn_status_idr, id); + if (nsw == NULL) + goto out; + } + + o2net_complete_nsw_locked(nn, nsw, sys_status, status); + +out: + spin_unlock(&nn->nn_lock); + return; +} + +static void o2net_complete_nodes_nsw(struct o2net_node *nn) +{ + struct o2net_status_wait *nsw, *tmp; + unsigned int num_kills = 0; + + assert_spin_locked(&nn->nn_lock); + + list_for_each_entry_safe(nsw, tmp, &nn->nn_status_list, ns_node_item) { + o2net_complete_nsw_locked(nn, nsw, O2NET_ERR_DIED, 0); + num_kills++; + } + + mlog(0, "completed %d messages for node %u\n", num_kills, + o2net_num_from_nn(nn)); +} + +static int o2net_nsw_completed(struct o2net_node *nn, + struct o2net_status_wait *nsw) +{ + int completed; + spin_lock(&nn->nn_lock); + completed = list_empty(&nsw->ns_node_item); + spin_unlock(&nn->nn_lock); + return completed; +} + +/* ------------------------------------------------------------ */ + +static void sc_kref_release(struct kref *kref) +{ + struct o2net_sock_container *sc = container_of(kref, + struct o2net_sock_container, sc_kref); + BUG_ON(timer_pending(&sc->sc_idle_timeout)); + + sclog(sc, "releasing\n"); + + if (sc->sc_sock) { + sock_release(sc->sc_sock); + sc->sc_sock = NULL; + } + + o2nm_undepend_item(&sc->sc_node->nd_item); + o2nm_node_put(sc->sc_node); + sc->sc_node = NULL; + + o2net_debug_del_sc(sc); + kfree(sc); +} + +static void sc_put(struct o2net_sock_container *sc) +{ + sclog(sc, "put\n"); + kref_put(&sc->sc_kref, sc_kref_release); +} +static void sc_get(struct o2net_sock_container *sc) +{ + sclog(sc, "get\n"); + kref_get(&sc->sc_kref); +} +static struct o2net_sock_container *sc_alloc(struct o2nm_node *node) +{ + struct o2net_sock_container *sc, *ret = NULL; + struct page *page = NULL; + int status = 0; + + page = alloc_page(GFP_NOFS); + sc = kzalloc(sizeof(*sc), GFP_NOFS); + if (sc == NULL || page == NULL) + goto out; + + kref_init(&sc->sc_kref); + o2nm_node_get(node); + sc->sc_node = node; + + /* pin the node item of the remote node */ + status = o2nm_depend_item(&node->nd_item); + if (status) { + mlog_errno(status); + o2nm_node_put(node); + goto out; + } + INIT_WORK(&sc->sc_connect_work, o2net_sc_connect_completed); + INIT_WORK(&sc->sc_rx_work, o2net_rx_until_empty); + INIT_WORK(&sc->sc_shutdown_work, o2net_shutdown_sc); + INIT_DELAYED_WORK(&sc->sc_keepalive_work, o2net_sc_send_keep_req); + + init_timer(&sc->sc_idle_timeout); + sc->sc_idle_timeout.function = o2net_idle_timer; + sc->sc_idle_timeout.data = (unsigned long)sc; + + sclog(sc, "alloced\n"); + + ret = sc; + sc->sc_page = page; + o2net_debug_add_sc(sc); + sc = NULL; + page = NULL; + +out: + if (page) + __free_page(page); + kfree(sc); + + return ret; +} + +/* ------------------------------------------------------------ */ + +static void o2net_sc_queue_work(struct o2net_sock_container *sc, + struct work_struct *work) +{ + sc_get(sc); + if (!queue_work(o2net_wq, work)) + sc_put(sc); +} +static void o2net_sc_queue_delayed_work(struct o2net_sock_container *sc, + struct delayed_work *work, + int delay) +{ + sc_get(sc); + if (!queue_delayed_work(o2net_wq, work, delay)) + sc_put(sc); +} +static void o2net_sc_cancel_delayed_work(struct o2net_sock_container *sc, + struct delayed_work *work) +{ + if (cancel_delayed_work(work)) + sc_put(sc); +} + +static atomic_t o2net_connected_peers = ATOMIC_INIT(0); + +int o2net_num_connected_peers(void) +{ + return atomic_read(&o2net_connected_peers); +} + +static void o2net_set_nn_state(struct o2net_node *nn, + struct o2net_sock_container *sc, + unsigned valid, int err) +{ + int was_valid = nn->nn_sc_valid; + int was_err = nn->nn_persistent_error; + struct o2net_sock_container *old_sc = nn->nn_sc; + + assert_spin_locked(&nn->nn_lock); + + if (old_sc && !sc) + atomic_dec(&o2net_connected_peers); + else if (!old_sc && sc) + atomic_inc(&o2net_connected_peers); + + /* the node num comparison and single connect/accept path should stop + * an non-null sc from being overwritten with another */ + BUG_ON(sc && nn->nn_sc && nn->nn_sc != sc); + mlog_bug_on_msg(err && valid, "err %d valid %u\n", err, valid); + mlog_bug_on_msg(valid && !sc, "valid %u sc %p\n", valid, sc); + + if (was_valid && !valid && err == 0) + err = -ENOTCONN; + + mlog(ML_CONN, "node %u sc: %p -> %p, valid %u -> %u, err %d -> %d\n", + o2net_num_from_nn(nn), nn->nn_sc, sc, nn->nn_sc_valid, valid, + nn->nn_persistent_error, err); + + nn->nn_sc = sc; + nn->nn_sc_valid = valid ? 1 : 0; + nn->nn_persistent_error = err; + + /* mirrors o2net_tx_can_proceed() */ + if (nn->nn_persistent_error || nn->nn_sc_valid) + wake_up(&nn->nn_sc_wq); + + if (!was_err && nn->nn_persistent_error) { + o2quo_conn_err(o2net_num_from_nn(nn)); + queue_delayed_work(o2net_wq, &nn->nn_still_up, + msecs_to_jiffies(O2NET_QUORUM_DELAY_MS)); + } + + if (was_valid && !valid) { + printk(KERN_NOTICE "o2net: No longer connected to " + SC_NODEF_FMT "\n", SC_NODEF_ARGS(old_sc)); + o2net_complete_nodes_nsw(nn); + } + + if (!was_valid && valid) { + o2quo_conn_up(o2net_num_from_nn(nn)); + cancel_delayed_work(&nn->nn_connect_expired); + printk(KERN_NOTICE "o2net: %s " SC_NODEF_FMT "\n", + o2nm_this_node() > sc->sc_node->nd_num ? + "Connected to" : "Accepted connection from", + SC_NODEF_ARGS(sc)); + } + + /* trigger the connecting worker func as long as we're not valid, + * it will back off if it shouldn't connect. This can be called + * from node config teardown and so needs to be careful about + * the work queue actually being up. */ + if (!valid && o2net_wq) { + unsigned long delay; + /* delay if we're within a RECONNECT_DELAY of the + * last attempt */ + delay = (nn->nn_last_connect_attempt + + msecs_to_jiffies(o2net_reconnect_delay())) + - jiffies; + if (delay > msecs_to_jiffies(o2net_reconnect_delay())) + delay = 0; + mlog(ML_CONN, "queueing conn attempt in %lu jiffies\n", delay); + queue_delayed_work(o2net_wq, &nn->nn_connect_work, delay); + + /* + * Delay the expired work after idle timeout. + * + * We might have lots of failed connection attempts that run + * through here but we only cancel the connect_expired work when + * a connection attempt succeeds. So only the first enqueue of + * the connect_expired work will do anything. The rest will see + * that it's already queued and do nothing. + */ + delay += msecs_to_jiffies(o2net_idle_timeout()); + queue_delayed_work(o2net_wq, &nn->nn_connect_expired, delay); + } + + /* keep track of the nn's sc ref for the caller */ + if ((old_sc == NULL) && sc) + sc_get(sc); + if (old_sc && (old_sc != sc)) { + o2net_sc_queue_work(old_sc, &old_sc->sc_shutdown_work); + sc_put(old_sc); + } +} + +/* see o2net_register_callbacks() */ +static void o2net_data_ready(struct sock *sk, int bytes) +{ + void (*ready)(struct sock *sk, int bytes); + + read_lock(&sk->sk_callback_lock); + if (sk->sk_user_data) { + struct o2net_sock_container *sc = sk->sk_user_data; + sclog(sc, "data_ready hit\n"); + o2net_set_data_ready_time(sc); + o2net_sc_queue_work(sc, &sc->sc_rx_work); + ready = sc->sc_data_ready; + } else { + ready = sk->sk_data_ready; + } + read_unlock(&sk->sk_callback_lock); + + ready(sk, bytes); +} + +/* see o2net_register_callbacks() */ +static void o2net_state_change(struct sock *sk) +{ + void (*state_change)(struct sock *sk); + struct o2net_sock_container *sc; + + read_lock(&sk->sk_callback_lock); + sc = sk->sk_user_data; + if (sc == NULL) { + state_change = sk->sk_state_change; + goto out; + } + + sclog(sc, "state_change to %d\n", sk->sk_state); + + state_change = sc->sc_state_change; + + switch(sk->sk_state) { + /* ignore connecting sockets as they make progress */ + case TCP_SYN_SENT: + case TCP_SYN_RECV: + break; + case TCP_ESTABLISHED: + o2net_sc_queue_work(sc, &sc->sc_connect_work); + break; + default: + printk(KERN_INFO "o2net: Connection to " SC_NODEF_FMT + " shutdown, state %d\n", + SC_NODEF_ARGS(sc), sk->sk_state); + o2net_sc_queue_work(sc, &sc->sc_shutdown_work); + break; + } +out: + read_unlock(&sk->sk_callback_lock); + state_change(sk); +} + +/* + * we register callbacks so we can queue work on events before calling + * the original callbacks. our callbacks our careful to test user_data + * to discover when they've reaced with o2net_unregister_callbacks(). + */ +static void o2net_register_callbacks(struct sock *sk, + struct o2net_sock_container *sc) +{ + write_lock_bh(&sk->sk_callback_lock); + + /* accepted sockets inherit the old listen socket data ready */ + if (sk->sk_data_ready == o2net_listen_data_ready) { + sk->sk_data_ready = sk->sk_user_data; + sk->sk_user_data = NULL; + } + + BUG_ON(sk->sk_user_data != NULL); + sk->sk_user_data = sc; + sc_get(sc); + + sc->sc_data_ready = sk->sk_data_ready; + sc->sc_state_change = sk->sk_state_change; + sk->sk_data_ready = o2net_data_ready; + sk->sk_state_change = o2net_state_change; + + mutex_init(&sc->sc_send_lock); + + write_unlock_bh(&sk->sk_callback_lock); +} + +static int o2net_unregister_callbacks(struct sock *sk, + struct o2net_sock_container *sc) +{ + int ret = 0; + + write_lock_bh(&sk->sk_callback_lock); + if (sk->sk_user_data == sc) { + ret = 1; + sk->sk_user_data = NULL; + sk->sk_data_ready = sc->sc_data_ready; + sk->sk_state_change = sc->sc_state_change; + } + write_unlock_bh(&sk->sk_callback_lock); + + return ret; +} + +/* + * this is a little helper that is called by callers who have seen a problem + * with an sc and want to detach it from the nn if someone already hasn't beat + * them to it. if an error is given then the shutdown will be persistent + * and pending transmits will be canceled. + */ +static void o2net_ensure_shutdown(struct o2net_node *nn, + struct o2net_sock_container *sc, + int err) +{ + spin_lock(&nn->nn_lock); + if (nn->nn_sc == sc) + o2net_set_nn_state(nn, NULL, 0, err); + spin_unlock(&nn->nn_lock); +} + +/* + * This work queue function performs the blocking parts of socket shutdown. A + * few paths lead here. set_nn_state will trigger this callback if it sees an + * sc detached from the nn. state_change will also trigger this callback + * directly when it sees errors. In that case we need to call set_nn_state + * ourselves as state_change couldn't get the nn_lock and call set_nn_state + * itself. + */ +static void o2net_shutdown_sc(struct work_struct *work) +{ + struct o2net_sock_container *sc = + container_of(work, struct o2net_sock_container, + sc_shutdown_work); + struct o2net_node *nn = o2net_nn_from_num(sc->sc_node->nd_num); + + sclog(sc, "shutting down\n"); + + /* drop the callbacks ref and call shutdown only once */ + if (o2net_unregister_callbacks(sc->sc_sock->sk, sc)) { + /* we shouldn't flush as we're in the thread, the + * races with pending sc work structs are harmless */ + del_timer_sync(&sc->sc_idle_timeout); + o2net_sc_cancel_delayed_work(sc, &sc->sc_keepalive_work); + sc_put(sc); + kernel_sock_shutdown(sc->sc_sock, SHUT_RDWR); + } + + /* not fatal so failed connects before the other guy has our + * heartbeat can be retried */ + o2net_ensure_shutdown(nn, sc, 0); + sc_put(sc); +} + +/* ------------------------------------------------------------ */ + +static int o2net_handler_cmp(struct o2net_msg_handler *nmh, u32 msg_type, + u32 key) +{ + int ret = memcmp(&nmh->nh_key, &key, sizeof(key)); + + if (ret == 0) + ret = memcmp(&nmh->nh_msg_type, &msg_type, sizeof(msg_type)); + + return ret; +} + +static struct o2net_msg_handler * +o2net_handler_tree_lookup(u32 msg_type, u32 key, struct rb_node ***ret_p, + struct rb_node **ret_parent) +{ + struct rb_node **p = &o2net_handler_tree.rb_node; + struct rb_node *parent = NULL; + struct o2net_msg_handler *nmh, *ret = NULL; + int cmp; + + while (*p) { + parent = *p; + nmh = rb_entry(parent, struct o2net_msg_handler, nh_node); + cmp = o2net_handler_cmp(nmh, msg_type, key); + + if (cmp < 0) + p = &(*p)->rb_left; + else if (cmp > 0) + p = &(*p)->rb_right; + else { + ret = nmh; + break; + } + } + + if (ret_p != NULL) + *ret_p = p; + if (ret_parent != NULL) + *ret_parent = parent; + + return ret; +} + +static void o2net_handler_kref_release(struct kref *kref) +{ + struct o2net_msg_handler *nmh; + nmh = container_of(kref, struct o2net_msg_handler, nh_kref); + + kfree(nmh); +} + +static void o2net_handler_put(struct o2net_msg_handler *nmh) +{ + kref_put(&nmh->nh_kref, o2net_handler_kref_release); +} + +/* max_len is protection for the handler func. incoming messages won't + * be given to the handler if their payload is longer than the max. */ +int o2net_register_handler(u32 msg_type, u32 key, u32 max_len, + o2net_msg_handler_func *func, void *data, + o2net_post_msg_handler_func *post_func, + struct list_head *unreg_list) +{ + struct o2net_msg_handler *nmh = NULL; + struct rb_node **p, *parent; + int ret = 0; + + if (max_len > O2NET_MAX_PAYLOAD_BYTES) { + mlog(0, "max_len for message handler out of range: %u\n", + max_len); + ret = -EINVAL; + goto out; + } + + if (!msg_type) { + mlog(0, "no message type provided: %u, %p\n", msg_type, func); + ret = -EINVAL; + goto out; + + } + if (!func) { + mlog(0, "no message handler provided: %u, %p\n", + msg_type, func); + ret = -EINVAL; + goto out; + } + + nmh = kzalloc(sizeof(struct o2net_msg_handler), GFP_NOFS); + if (nmh == NULL) { + ret = -ENOMEM; + goto out; + } + + nmh->nh_func = func; + nmh->nh_func_data = data; + nmh->nh_post_func = post_func; + nmh->nh_msg_type = msg_type; + nmh->nh_max_len = max_len; + nmh->nh_key = key; + /* the tree and list get this ref.. they're both removed in + * unregister when this ref is dropped */ + kref_init(&nmh->nh_kref); + INIT_LIST_HEAD(&nmh->nh_unregister_item); + + write_lock(&o2net_handler_lock); + if (o2net_handler_tree_lookup(msg_type, key, &p, &parent)) + ret = -EEXIST; + else { + rb_link_node(&nmh->nh_node, parent, p); + rb_insert_color(&nmh->nh_node, &o2net_handler_tree); + list_add_tail(&nmh->nh_unregister_item, unreg_list); + + mlog(ML_TCP, "registered handler func %p type %u key %08x\n", + func, msg_type, key); + /* we've had some trouble with handlers seemingly vanishing. */ + mlog_bug_on_msg(o2net_handler_tree_lookup(msg_type, key, &p, + &parent) == NULL, + "couldn't find handler we *just* registerd " + "for type %u key %08x\n", msg_type, key); + } + write_unlock(&o2net_handler_lock); + if (ret) + goto out; + +out: + if (ret) + kfree(nmh); + + return ret; +} +EXPORT_SYMBOL_GPL(o2net_register_handler); + +void o2net_unregister_handler_list(struct list_head *list) +{ + struct o2net_msg_handler *nmh, *n; + + write_lock(&o2net_handler_lock); + list_for_each_entry_safe(nmh, n, list, nh_unregister_item) { + mlog(ML_TCP, "unregistering handler func %p type %u key %08x\n", + nmh->nh_func, nmh->nh_msg_type, nmh->nh_key); + rb_erase(&nmh->nh_node, &o2net_handler_tree); + list_del_init(&nmh->nh_unregister_item); + kref_put(&nmh->nh_kref, o2net_handler_kref_release); + } + write_unlock(&o2net_handler_lock); +} +EXPORT_SYMBOL_GPL(o2net_unregister_handler_list); + +static struct o2net_msg_handler *o2net_handler_get(u32 msg_type, u32 key) +{ + struct o2net_msg_handler *nmh; + + read_lock(&o2net_handler_lock); + nmh = o2net_handler_tree_lookup(msg_type, key, NULL, NULL); + if (nmh) + kref_get(&nmh->nh_kref); + read_unlock(&o2net_handler_lock); + + return nmh; +} + +/* ------------------------------------------------------------ */ + +static int o2net_recv_tcp_msg(struct socket *sock, void *data, size_t len) +{ + int ret; + mm_segment_t oldfs; + struct kvec vec = { + .iov_len = len, + .iov_base = data, + }; + struct msghdr msg = { + .msg_iovlen = 1, + .msg_iov = (struct iovec *)&vec, + .msg_flags = MSG_DONTWAIT, + }; + + oldfs = get_fs(); + set_fs(get_ds()); + ret = sock_recvmsg(sock, &msg, len, msg.msg_flags); + set_fs(oldfs); + + return ret; +} + +static int o2net_send_tcp_msg(struct socket *sock, struct kvec *vec, + size_t veclen, size_t total) +{ + int ret; + mm_segment_t oldfs; + struct msghdr msg = { + .msg_iov = (struct iovec *)vec, + .msg_iovlen = veclen, + }; + + if (sock == NULL) { + ret = -EINVAL; + goto out; + } + + oldfs = get_fs(); + set_fs(get_ds()); + ret = sock_sendmsg(sock, &msg, total); + set_fs(oldfs); + if (ret != total) { + mlog(ML_ERROR, "sendmsg returned %d instead of %zu\n", ret, + total); + if (ret >= 0) + ret = -EPIPE; /* should be smarter, I bet */ + goto out; + } + + ret = 0; +out: + if (ret < 0) + mlog(0, "returning error: %d\n", ret); + return ret; +} + +static void o2net_sendpage(struct o2net_sock_container *sc, + void *kmalloced_virt, + size_t size) +{ + struct o2net_node *nn = o2net_nn_from_num(sc->sc_node->nd_num); + ssize_t ret; + + while (1) { + mutex_lock(&sc->sc_send_lock); + ret = sc->sc_sock->ops->sendpage(sc->sc_sock, + virt_to_page(kmalloced_virt), + (long)kmalloced_virt & ~PAGE_MASK, + size, MSG_DONTWAIT); + mutex_unlock(&sc->sc_send_lock); + if (ret == size) + break; + if (ret == (ssize_t)-EAGAIN) { + mlog(0, "sendpage of size %zu to " SC_NODEF_FMT + " returned EAGAIN\n", size, SC_NODEF_ARGS(sc)); + cond_resched(); + continue; + } + mlog(ML_ERROR, "sendpage of size %zu to " SC_NODEF_FMT + " failed with %zd\n", size, SC_NODEF_ARGS(sc), ret); + o2net_ensure_shutdown(nn, sc, 0); + break; + } +} + +static void o2net_init_msg(struct o2net_msg *msg, u16 data_len, u16 msg_type, u32 key) +{ + memset(msg, 0, sizeof(struct o2net_msg)); + msg->magic = cpu_to_be16(O2NET_MSG_MAGIC); + msg->data_len = cpu_to_be16(data_len); + msg->msg_type = cpu_to_be16(msg_type); + msg->sys_status = cpu_to_be32(O2NET_ERR_NONE); + msg->status = 0; + msg->key = cpu_to_be32(key); +} + +static int o2net_tx_can_proceed(struct o2net_node *nn, + struct o2net_sock_container **sc_ret, + int *error) +{ + int ret = 0; + + spin_lock(&nn->nn_lock); + if (nn->nn_persistent_error) { + ret = 1; + *sc_ret = NULL; + *error = nn->nn_persistent_error; + } else if (nn->nn_sc_valid) { + kref_get(&nn->nn_sc->sc_kref); + + ret = 1; + *sc_ret = nn->nn_sc; + *error = 0; + } + spin_unlock(&nn->nn_lock); + + return ret; +} + +/* Get a map of all nodes to which this node is currently connected to */ +void o2net_fill_node_map(unsigned long *map, unsigned bytes) +{ + struct o2net_sock_container *sc; + int node, ret; + + BUG_ON(bytes < (BITS_TO_LONGS(O2NM_MAX_NODES) * sizeof(unsigned long))); + + memset(map, 0, bytes); + for (node = 0; node < O2NM_MAX_NODES; ++node) { + o2net_tx_can_proceed(o2net_nn_from_num(node), &sc, &ret); + if (!ret) { + set_bit(node, map); + sc_put(sc); + } + } +} +EXPORT_SYMBOL_GPL(o2net_fill_node_map); + +int o2net_send_message_vec(u32 msg_type, u32 key, struct kvec *caller_vec, + size_t caller_veclen, u8 target_node, int *status) +{ + int ret = 0; + struct o2net_msg *msg = NULL; + size_t veclen, caller_bytes = 0; + struct kvec *vec = NULL; + struct o2net_sock_container *sc = NULL; + struct o2net_node *nn = o2net_nn_from_num(target_node); + struct o2net_status_wait nsw = { + .ns_node_item = LIST_HEAD_INIT(nsw.ns_node_item), + }; + struct o2net_send_tracking nst; + + o2net_init_nst(&nst, msg_type, key, current, target_node); + + if (o2net_wq == NULL) { + mlog(0, "attempt to tx without o2netd running\n"); + ret = -ESRCH; + goto out; + } + + if (caller_veclen == 0) { + mlog(0, "bad kvec array length\n"); + ret = -EINVAL; + goto out; + } + + caller_bytes = iov_length((struct iovec *)caller_vec, caller_veclen); + if (caller_bytes > O2NET_MAX_PAYLOAD_BYTES) { + mlog(0, "total payload len %zu too large\n", caller_bytes); + ret = -EINVAL; + goto out; + } + + if (target_node == o2nm_this_node()) { + ret = -ELOOP; + goto out; + } + + o2net_debug_add_nst(&nst); + + o2net_set_nst_sock_time(&nst); + + wait_event(nn->nn_sc_wq, o2net_tx_can_proceed(nn, &sc, &ret)); + if (ret) + goto out; + + o2net_set_nst_sock_container(&nst, sc); + + veclen = caller_veclen + 1; + vec = kmalloc(sizeof(struct kvec) * veclen, GFP_ATOMIC); + if (vec == NULL) { + mlog(0, "failed to %zu element kvec!\n", veclen); + ret = -ENOMEM; + goto out; + } + + msg = kmalloc(sizeof(struct o2net_msg), GFP_ATOMIC); + if (!msg) { + mlog(0, "failed to allocate a o2net_msg!\n"); + ret = -ENOMEM; + goto out; + } + + o2net_init_msg(msg, caller_bytes, msg_type, key); + + vec[0].iov_len = sizeof(struct o2net_msg); + vec[0].iov_base = msg; + memcpy(&vec[1], caller_vec, caller_veclen * sizeof(struct kvec)); + + ret = o2net_prep_nsw(nn, &nsw); + if (ret) + goto out; + + msg->msg_num = cpu_to_be32(nsw.ns_id); + o2net_set_nst_msg_id(&nst, nsw.ns_id); + + o2net_set_nst_send_time(&nst); + + /* finally, convert the message header to network byte-order + * and send */ + mutex_lock(&sc->sc_send_lock); + ret = o2net_send_tcp_msg(sc->sc_sock, vec, veclen, + sizeof(struct o2net_msg) + caller_bytes); + mutex_unlock(&sc->sc_send_lock); + msglog(msg, "sending returned %d\n", ret); + if (ret < 0) { + mlog(0, "error returned from o2net_send_tcp_msg=%d\n", ret); + goto out; + } + + /* wait on other node's handler */ + o2net_set_nst_status_time(&nst); + wait_event(nsw.ns_wq, o2net_nsw_completed(nn, &nsw)); + + o2net_update_send_stats(&nst, sc); + + /* Note that we avoid overwriting the callers status return + * variable if a system error was reported on the other + * side. Callers beware. */ + ret = o2net_sys_err_to_errno(nsw.ns_sys_status); + if (status && !ret) + *status = nsw.ns_status; + + mlog(0, "woken, returning system status %d, user status %d\n", + ret, nsw.ns_status); +out: + o2net_debug_del_nst(&nst); /* must be before dropping sc and node */ + if (sc) + sc_put(sc); + if (vec) + kfree(vec); + if (msg) + kfree(msg); + o2net_complete_nsw(nn, &nsw, 0, 0, 0); + return ret; +} +EXPORT_SYMBOL_GPL(o2net_send_message_vec); + +int o2net_send_message(u32 msg_type, u32 key, void *data, u32 len, + u8 target_node, int *status) +{ + struct kvec vec = { + .iov_base = data, + .iov_len = len, + }; + return o2net_send_message_vec(msg_type, key, &vec, 1, + target_node, status); +} +EXPORT_SYMBOL_GPL(o2net_send_message); + +static int o2net_send_status_magic(struct socket *sock, struct o2net_msg *hdr, + enum o2net_system_error syserr, int err) +{ + struct kvec vec = { + .iov_base = hdr, + .iov_len = sizeof(struct o2net_msg), + }; + + BUG_ON(syserr >= O2NET_ERR_MAX); + + /* leave other fields intact from the incoming message, msg_num + * in particular */ + hdr->sys_status = cpu_to_be32(syserr); + hdr->status = cpu_to_be32(err); + hdr->magic = cpu_to_be16(O2NET_MSG_STATUS_MAGIC); // twiddle the magic + hdr->data_len = 0; + + msglog(hdr, "about to send status magic %d\n", err); + /* hdr has been in host byteorder this whole time */ + return o2net_send_tcp_msg(sock, &vec, 1, sizeof(struct o2net_msg)); +} + +/* this returns -errno if the header was unknown or too large, etc. + * after this is called the buffer us reused for the next message */ +static int o2net_process_message(struct o2net_sock_container *sc, + struct o2net_msg *hdr) +{ + struct o2net_node *nn = o2net_nn_from_num(sc->sc_node->nd_num); + int ret = 0, handler_status; + enum o2net_system_error syserr; + struct o2net_msg_handler *nmh = NULL; + void *ret_data = NULL; + + msglog(hdr, "processing message\n"); + + o2net_sc_postpone_idle(sc); + + switch(be16_to_cpu(hdr->magic)) { + case O2NET_MSG_STATUS_MAGIC: + /* special type for returning message status */ + o2net_complete_nsw(nn, NULL, + be32_to_cpu(hdr->msg_num), + be32_to_cpu(hdr->sys_status), + be32_to_cpu(hdr->status)); + goto out; + case O2NET_MSG_KEEP_REQ_MAGIC: + o2net_sendpage(sc, o2net_keep_resp, + sizeof(*o2net_keep_resp)); + goto out; + case O2NET_MSG_KEEP_RESP_MAGIC: + goto out; + case O2NET_MSG_MAGIC: + break; + default: + msglog(hdr, "bad magic\n"); + ret = -EINVAL; + goto out; + break; + } + + /* find a handler for it */ + handler_status = 0; + nmh = o2net_handler_get(be16_to_cpu(hdr->msg_type), + be32_to_cpu(hdr->key)); + if (!nmh) { + mlog(ML_TCP, "couldn't find handler for type %u key %08x\n", + be16_to_cpu(hdr->msg_type), be32_to_cpu(hdr->key)); + syserr = O2NET_ERR_NO_HNDLR; + goto out_respond; + } + + syserr = O2NET_ERR_NONE; + + if (be16_to_cpu(hdr->data_len) > nmh->nh_max_len) + syserr = O2NET_ERR_OVERFLOW; + + if (syserr != O2NET_ERR_NONE) + goto out_respond; + + o2net_set_func_start_time(sc); + sc->sc_msg_key = be32_to_cpu(hdr->key); + sc->sc_msg_type = be16_to_cpu(hdr->msg_type); + handler_status = (nmh->nh_func)(hdr, sizeof(struct o2net_msg) + + be16_to_cpu(hdr->data_len), + nmh->nh_func_data, &ret_data); + o2net_set_func_stop_time(sc); + + o2net_update_recv_stats(sc); + +out_respond: + /* this destroys the hdr, so don't use it after this */ + mutex_lock(&sc->sc_send_lock); + ret = o2net_send_status_magic(sc->sc_sock, hdr, syserr, + handler_status); + mutex_unlock(&sc->sc_send_lock); + hdr = NULL; + mlog(0, "sending handler status %d, syserr %d returned %d\n", + handler_status, syserr, ret); + + if (nmh) { + BUG_ON(ret_data != NULL && nmh->nh_post_func == NULL); + if (nmh->nh_post_func) + (nmh->nh_post_func)(handler_status, nmh->nh_func_data, + ret_data); + } + +out: + if (nmh) + o2net_handler_put(nmh); + return ret; +} + +static int o2net_check_handshake(struct o2net_sock_container *sc) +{ + struct o2net_handshake *hand = page_address(sc->sc_page); + struct o2net_node *nn = o2net_nn_from_num(sc->sc_node->nd_num); + + if (hand->protocol_version != cpu_to_be64(O2NET_PROTOCOL_VERSION)) { + printk(KERN_NOTICE "o2net: " SC_NODEF_FMT " Advertised net " + "protocol version %llu but %llu is required. " + "Disconnecting.\n", SC_NODEF_ARGS(sc), + (unsigned long long)be64_to_cpu(hand->protocol_version), + O2NET_PROTOCOL_VERSION); + + /* don't bother reconnecting if its the wrong version. */ + o2net_ensure_shutdown(nn, sc, -ENOTCONN); + return -1; + } + + /* + * Ensure timeouts are consistent with other nodes, otherwise + * we can end up with one node thinking that the other must be down, + * but isn't. This can ultimately cause corruption. + */ + if (be32_to_cpu(hand->o2net_idle_timeout_ms) != + o2net_idle_timeout()) { + printk(KERN_NOTICE "o2net: " SC_NODEF_FMT " uses a network " + "idle timeout of %u ms, but we use %u ms locally. " + "Disconnecting.\n", SC_NODEF_ARGS(sc), + be32_to_cpu(hand->o2net_idle_timeout_ms), + o2net_idle_timeout()); + o2net_ensure_shutdown(nn, sc, -ENOTCONN); + return -1; + } + + if (be32_to_cpu(hand->o2net_keepalive_delay_ms) != + o2net_keepalive_delay()) { + printk(KERN_NOTICE "o2net: " SC_NODEF_FMT " uses a keepalive " + "delay of %u ms, but we use %u ms locally. " + "Disconnecting.\n", SC_NODEF_ARGS(sc), + be32_to_cpu(hand->o2net_keepalive_delay_ms), + o2net_keepalive_delay()); + o2net_ensure_shutdown(nn, sc, -ENOTCONN); + return -1; + } + + if (be32_to_cpu(hand->o2hb_heartbeat_timeout_ms) != + O2HB_MAX_WRITE_TIMEOUT_MS) { + printk(KERN_NOTICE "o2net: " SC_NODEF_FMT " uses a heartbeat " + "timeout of %u ms, but we use %u ms locally. " + "Disconnecting.\n", SC_NODEF_ARGS(sc), + be32_to_cpu(hand->o2hb_heartbeat_timeout_ms), + O2HB_MAX_WRITE_TIMEOUT_MS); + o2net_ensure_shutdown(nn, sc, -ENOTCONN); + return -1; + } + + sc->sc_handshake_ok = 1; + + spin_lock(&nn->nn_lock); + /* set valid and queue the idle timers only if it hasn't been + * shut down already */ + if (nn->nn_sc == sc) { + o2net_sc_reset_idle_timer(sc); + atomic_set(&nn->nn_timeout, 0); + o2net_set_nn_state(nn, sc, 1, 0); + } + spin_unlock(&nn->nn_lock); + + /* shift everything up as though it wasn't there */ + sc->sc_page_off -= sizeof(struct o2net_handshake); + if (sc->sc_page_off) + memmove(hand, hand + 1, sc->sc_page_off); + + return 0; +} + +/* this demuxes the queued rx bytes into header or payload bits and calls + * handlers as each full message is read off the socket. it returns -error, + * == 0 eof, or > 0 for progress made.*/ +static int o2net_advance_rx(struct o2net_sock_container *sc) +{ + struct o2net_msg *hdr; + int ret = 0; + void *data; + size_t datalen; + + sclog(sc, "receiving\n"); + o2net_set_advance_start_time(sc); + + if (unlikely(sc->sc_handshake_ok == 0)) { + if(sc->sc_page_off < sizeof(struct o2net_handshake)) { + data = page_address(sc->sc_page) + sc->sc_page_off; + datalen = sizeof(struct o2net_handshake) - sc->sc_page_off; + ret = o2net_recv_tcp_msg(sc->sc_sock, data, datalen); + if (ret > 0) + sc->sc_page_off += ret; + } + + if (sc->sc_page_off == sizeof(struct o2net_handshake)) { + o2net_check_handshake(sc); + if (unlikely(sc->sc_handshake_ok == 0)) + ret = -EPROTO; + } + goto out; + } + + /* do we need more header? */ + if (sc->sc_page_off < sizeof(struct o2net_msg)) { + data = page_address(sc->sc_page) + sc->sc_page_off; + datalen = sizeof(struct o2net_msg) - sc->sc_page_off; + ret = o2net_recv_tcp_msg(sc->sc_sock, data, datalen); + if (ret > 0) { + sc->sc_page_off += ret; + /* only swab incoming here.. we can + * only get here once as we cross from + * being under to over */ + if (sc->sc_page_off == sizeof(struct o2net_msg)) { + hdr = page_address(sc->sc_page); + if (be16_to_cpu(hdr->data_len) > + O2NET_MAX_PAYLOAD_BYTES) + ret = -EOVERFLOW; + } + } + if (ret <= 0) + goto out; + } + + if (sc->sc_page_off < sizeof(struct o2net_msg)) { + /* oof, still don't have a header */ + goto out; + } + + /* this was swabbed above when we first read it */ + hdr = page_address(sc->sc_page); + + msglog(hdr, "at page_off %zu\n", sc->sc_page_off); + + /* do we need more payload? */ + if (sc->sc_page_off - sizeof(struct o2net_msg) < be16_to_cpu(hdr->data_len)) { + /* need more payload */ + data = page_address(sc->sc_page) + sc->sc_page_off; + datalen = (sizeof(struct o2net_msg) + be16_to_cpu(hdr->data_len)) - + sc->sc_page_off; + ret = o2net_recv_tcp_msg(sc->sc_sock, data, datalen); + if (ret > 0) + sc->sc_page_off += ret; + if (ret <= 0) + goto out; + } + + if (sc->sc_page_off - sizeof(struct o2net_msg) == be16_to_cpu(hdr->data_len)) { + /* we can only get here once, the first time we read + * the payload.. so set ret to progress if the handler + * works out. after calling this the message is toast */ + ret = o2net_process_message(sc, hdr); + if (ret == 0) + ret = 1; + sc->sc_page_off = 0; + } + +out: + sclog(sc, "ret = %d\n", ret); + o2net_set_advance_stop_time(sc); + return ret; +} + +/* this work func is triggerd by data ready. it reads until it can read no + * more. it interprets 0, eof, as fatal. if data_ready hits while we're doing + * our work the work struct will be marked and we'll be called again. */ +static void o2net_rx_until_empty(struct work_struct *work) +{ + struct o2net_sock_container *sc = + container_of(work, struct o2net_sock_container, sc_rx_work); + int ret; + + do { + ret = o2net_advance_rx(sc); + } while (ret > 0); + + if (ret <= 0 && ret != -EAGAIN) { + struct o2net_node *nn = o2net_nn_from_num(sc->sc_node->nd_num); + sclog(sc, "saw error %d, closing\n", ret); + /* not permanent so read failed handshake can retry */ + o2net_ensure_shutdown(nn, sc, 0); + } + + sc_put(sc); +} + +static int o2net_set_nodelay(struct socket *sock) +{ + int ret, val = 1; + mm_segment_t oldfs; + + oldfs = get_fs(); + set_fs(KERNEL_DS); + + /* + * Dear unsuspecting programmer, + * + * Don't use sock_setsockopt() for SOL_TCP. It doesn't check its level + * argument and assumes SOL_SOCKET so, say, your TCP_NODELAY will + * silently turn into SO_DEBUG. + * + * Yours, + * Keeper of hilariously fragile interfaces. + */ + ret = sock->ops->setsockopt(sock, SOL_TCP, TCP_NODELAY, + (char __user *)&val, sizeof(val)); + + set_fs(oldfs); + return ret; +} + +static void o2net_initialize_handshake(void) +{ + o2net_hand->o2hb_heartbeat_timeout_ms = cpu_to_be32( + O2HB_MAX_WRITE_TIMEOUT_MS); + o2net_hand->o2net_idle_timeout_ms = cpu_to_be32(o2net_idle_timeout()); + o2net_hand->o2net_keepalive_delay_ms = cpu_to_be32( + o2net_keepalive_delay()); + o2net_hand->o2net_reconnect_delay_ms = cpu_to_be32( + o2net_reconnect_delay()); +} + +/* ------------------------------------------------------------ */ + +/* called when a connect completes and after a sock is accepted. the + * rx path will see the response and mark the sc valid */ +static void o2net_sc_connect_completed(struct work_struct *work) +{ + struct o2net_sock_container *sc = + container_of(work, struct o2net_sock_container, + sc_connect_work); + + mlog(ML_MSG, "sc sending handshake with ver %llu id %llx\n", + (unsigned long long)O2NET_PROTOCOL_VERSION, + (unsigned long long)be64_to_cpu(o2net_hand->connector_id)); + + o2net_initialize_handshake(); + o2net_sendpage(sc, o2net_hand, sizeof(*o2net_hand)); + sc_put(sc); +} + +/* this is called as a work_struct func. */ +static void o2net_sc_send_keep_req(struct work_struct *work) +{ + struct o2net_sock_container *sc = + container_of(work, struct o2net_sock_container, + sc_keepalive_work.work); + + o2net_sendpage(sc, o2net_keep_req, sizeof(*o2net_keep_req)); + sc_put(sc); +} + +/* socket shutdown does a del_timer_sync against this as it tears down. + * we can't start this timer until we've got to the point in sc buildup + * where shutdown is going to be involved */ +static void o2net_idle_timer(unsigned long data) +{ + struct o2net_sock_container *sc = (struct o2net_sock_container *)data; + struct o2net_node *nn = o2net_nn_from_num(sc->sc_node->nd_num); +#ifdef CONFIG_DEBUG_FS + unsigned long msecs = ktime_to_ms(ktime_get()) - + ktime_to_ms(sc->sc_tv_timer); +#else + unsigned long msecs = o2net_idle_timeout(); +#endif + + printk(KERN_NOTICE "o2net: Connection to " SC_NODEF_FMT " has been " + "idle for %lu.%lu secs, shutting it down.\n", SC_NODEF_ARGS(sc), + msecs / 1000, msecs % 1000); + + /* + * Initialize the nn_timeout so that the next connection attempt + * will continue in o2net_start_connect. + */ + atomic_set(&nn->nn_timeout, 1); + + o2net_sc_queue_work(sc, &sc->sc_shutdown_work); +} + +static void o2net_sc_reset_idle_timer(struct o2net_sock_container *sc) +{ + o2net_sc_cancel_delayed_work(sc, &sc->sc_keepalive_work); + o2net_sc_queue_delayed_work(sc, &sc->sc_keepalive_work, + msecs_to_jiffies(o2net_keepalive_delay())); + o2net_set_sock_timer(sc); + mod_timer(&sc->sc_idle_timeout, + jiffies + msecs_to_jiffies(o2net_idle_timeout())); +} + +static void o2net_sc_postpone_idle(struct o2net_sock_container *sc) +{ + /* Only push out an existing timer */ + if (timer_pending(&sc->sc_idle_timeout)) + o2net_sc_reset_idle_timer(sc); +} + +/* this work func is kicked whenever a path sets the nn state which doesn't + * have valid set. This includes seeing hb come up, losing a connection, + * having a connect attempt fail, etc. This centralizes the logic which decides + * if a connect attempt should be made or if we should give up and all future + * transmit attempts should fail */ +static void o2net_start_connect(struct work_struct *work) +{ + struct o2net_node *nn = + container_of(work, struct o2net_node, nn_connect_work.work); + struct o2net_sock_container *sc = NULL; + struct o2nm_node *node = NULL, *mynode = NULL; + struct socket *sock = NULL; + struct sockaddr_in myaddr = {0, }, remoteaddr = {0, }; + int ret = 0, stop; + unsigned int timeout; + + /* if we're greater we initiate tx, otherwise we accept */ + if (o2nm_this_node() <= o2net_num_from_nn(nn)) + goto out; + + /* watch for racing with tearing a node down */ + node = o2nm_get_node_by_num(o2net_num_from_nn(nn)); + if (node == NULL) { + ret = 0; + goto out; + } + + mynode = o2nm_get_node_by_num(o2nm_this_node()); + if (mynode == NULL) { + ret = 0; + goto out; + } + + spin_lock(&nn->nn_lock); + /* + * see if we already have one pending or have given up. + * For nn_timeout, it is set when we close the connection + * because of the idle time out. So it means that we have + * at least connected to that node successfully once, + * now try to connect to it again. + */ + timeout = atomic_read(&nn->nn_timeout); + stop = (nn->nn_sc || + (nn->nn_persistent_error && + (nn->nn_persistent_error != -ENOTCONN || timeout == 0))); + spin_unlock(&nn->nn_lock); + if (stop) + goto out; + + nn->nn_last_connect_attempt = jiffies; + + sc = sc_alloc(node); + if (sc == NULL) { + mlog(0, "couldn't allocate sc\n"); + ret = -ENOMEM; + goto out; + } + + ret = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock); + if (ret < 0) { + mlog(0, "can't create socket: %d\n", ret); + goto out; + } + sc->sc_sock = sock; /* freed by sc_kref_release */ + + sock->sk->sk_allocation = GFP_ATOMIC; + + myaddr.sin_family = AF_INET; + myaddr.sin_addr.s_addr = mynode->nd_ipv4_address; + myaddr.sin_port = htons(0); /* any port */ + + ret = sock->ops->bind(sock, (struct sockaddr *)&myaddr, + sizeof(myaddr)); + if (ret) { + mlog(ML_ERROR, "bind failed with %d at address %pI4\n", + ret, &mynode->nd_ipv4_address); + goto out; + } + + ret = o2net_set_nodelay(sc->sc_sock); + if (ret) { + mlog(ML_ERROR, "setting TCP_NODELAY failed with %d\n", ret); + goto out; + } + + o2net_register_callbacks(sc->sc_sock->sk, sc); + + spin_lock(&nn->nn_lock); + /* handshake completion will set nn->nn_sc_valid */ + o2net_set_nn_state(nn, sc, 0, 0); + spin_unlock(&nn->nn_lock); + + remoteaddr.sin_family = AF_INET; + remoteaddr.sin_addr.s_addr = node->nd_ipv4_address; + remoteaddr.sin_port = node->nd_ipv4_port; + + ret = sc->sc_sock->ops->connect(sc->sc_sock, + (struct sockaddr *)&remoteaddr, + sizeof(remoteaddr), + O_NONBLOCK); + if (ret == -EINPROGRESS) + ret = 0; + +out: + if (ret) { + printk(KERN_NOTICE "o2net: Connect attempt to " SC_NODEF_FMT + " failed with errno %d\n", SC_NODEF_ARGS(sc), ret); + /* 0 err so that another will be queued and attempted + * from set_nn_state */ + if (sc) + o2net_ensure_shutdown(nn, sc, 0); + } + if (sc) + sc_put(sc); + if (node) + o2nm_node_put(node); + if (mynode) + o2nm_node_put(mynode); + + return; +} + +static void o2net_connect_expired(struct work_struct *work) +{ + struct o2net_node *nn = + container_of(work, struct o2net_node, nn_connect_expired.work); + + spin_lock(&nn->nn_lock); + if (!nn->nn_sc_valid) { + printk(KERN_NOTICE "o2net: No connection established with " + "node %u after %u.%u seconds, giving up.\n", + o2net_num_from_nn(nn), + o2net_idle_timeout() / 1000, + o2net_idle_timeout() % 1000); + + o2net_set_nn_state(nn, NULL, 0, -ENOTCONN); + } + spin_unlock(&nn->nn_lock); +} + +static void o2net_still_up(struct work_struct *work) +{ + struct o2net_node *nn = + container_of(work, struct o2net_node, nn_still_up.work); + + o2quo_hb_still_up(o2net_num_from_nn(nn)); +} + +/* ------------------------------------------------------------ */ + +void o2net_disconnect_node(struct o2nm_node *node) +{ + struct o2net_node *nn = o2net_nn_from_num(node->nd_num); + + /* don't reconnect until it's heartbeating again */ + spin_lock(&nn->nn_lock); + atomic_set(&nn->nn_timeout, 0); + o2net_set_nn_state(nn, NULL, 0, -ENOTCONN); + spin_unlock(&nn->nn_lock); + + if (o2net_wq) { + cancel_delayed_work(&nn->nn_connect_expired); + cancel_delayed_work(&nn->nn_connect_work); + cancel_delayed_work(&nn->nn_still_up); + flush_workqueue(o2net_wq); + } +} + +static void o2net_hb_node_down_cb(struct o2nm_node *node, int node_num, + void *data) +{ + o2quo_hb_down(node_num); + + if (!node) + return; + + if (node_num != o2nm_this_node()) + o2net_disconnect_node(node); + + BUG_ON(atomic_read(&o2net_connected_peers) < 0); +} + +static void o2net_hb_node_up_cb(struct o2nm_node *node, int node_num, + void *data) +{ + struct o2net_node *nn = o2net_nn_from_num(node_num); + + o2quo_hb_up(node_num); + + BUG_ON(!node); + + /* ensure an immediate connect attempt */ + nn->nn_last_connect_attempt = jiffies - + (msecs_to_jiffies(o2net_reconnect_delay()) + 1); + + if (node_num != o2nm_this_node()) { + /* believe it or not, accept and node hearbeating testing + * can succeed for this node before we got here.. so + * only use set_nn_state to clear the persistent error + * if that hasn't already happened */ + spin_lock(&nn->nn_lock); + atomic_set(&nn->nn_timeout, 0); + if (nn->nn_persistent_error) + o2net_set_nn_state(nn, NULL, 0, 0); + spin_unlock(&nn->nn_lock); + } +} + +void o2net_unregister_hb_callbacks(void) +{ + o2hb_unregister_callback(NULL, &o2net_hb_up); + o2hb_unregister_callback(NULL, &o2net_hb_down); +} + +int o2net_register_hb_callbacks(void) +{ + int ret; + + o2hb_setup_callback(&o2net_hb_down, O2HB_NODE_DOWN_CB, + o2net_hb_node_down_cb, NULL, O2NET_HB_PRI); + o2hb_setup_callback(&o2net_hb_up, O2HB_NODE_UP_CB, + o2net_hb_node_up_cb, NULL, O2NET_HB_PRI); + + ret = o2hb_register_callback(NULL, &o2net_hb_up); + if (ret == 0) + ret = o2hb_register_callback(NULL, &o2net_hb_down); + + if (ret) + o2net_unregister_hb_callbacks(); + + return ret; +} + +/* ------------------------------------------------------------ */ + +static int o2net_accept_one(struct socket *sock) +{ + int ret, slen; + struct sockaddr_in sin; + struct socket *new_sock = NULL; + struct o2nm_node *node = NULL; + struct o2nm_node *local_node = NULL; + struct o2net_sock_container *sc = NULL; + struct o2net_node *nn; + + BUG_ON(sock == NULL); + ret = sock_create_lite(sock->sk->sk_family, sock->sk->sk_type, + sock->sk->sk_protocol, &new_sock); + if (ret) + goto out; + + new_sock->type = sock->type; + new_sock->ops = sock->ops; + ret = sock->ops->accept(sock, new_sock, O_NONBLOCK); + if (ret < 0) + goto out; + + new_sock->sk->sk_allocation = GFP_ATOMIC; + + ret = o2net_set_nodelay(new_sock); + if (ret) { + mlog(ML_ERROR, "setting TCP_NODELAY failed with %d\n", ret); + goto out; + } + + slen = sizeof(sin); + ret = new_sock->ops->getname(new_sock, (struct sockaddr *) &sin, + &slen, 1); + if (ret < 0) + goto out; + + node = o2nm_get_node_by_ip(sin.sin_addr.s_addr); + if (node == NULL) { + printk(KERN_NOTICE "o2net: Attempt to connect from unknown " + "node at %pI4:%d\n", &sin.sin_addr.s_addr, + ntohs(sin.sin_port)); + ret = -EINVAL; + goto out; + } + + if (o2nm_this_node() >= node->nd_num) { + local_node = o2nm_get_node_by_num(o2nm_this_node()); + printk(KERN_NOTICE "o2net: Unexpected connect attempt seen " + "at node '%s' (%u, %pI4:%d) from node '%s' (%u, " + "%pI4:%d)\n", local_node->nd_name, local_node->nd_num, + &(local_node->nd_ipv4_address), + ntohs(local_node->nd_ipv4_port), node->nd_name, + node->nd_num, &sin.sin_addr.s_addr, ntohs(sin.sin_port)); + ret = -EINVAL; + goto out; + } + + /* this happens all the time when the other node sees our heartbeat + * and tries to connect before we see their heartbeat */ + if (!o2hb_check_node_heartbeating_from_callback(node->nd_num)) { + mlog(ML_CONN, "attempt to connect from node '%s' at " + "%pI4:%d but it isn't heartbeating\n", + node->nd_name, &sin.sin_addr.s_addr, + ntohs(sin.sin_port)); + ret = -EINVAL; + goto out; + } + + nn = o2net_nn_from_num(node->nd_num); + + spin_lock(&nn->nn_lock); + if (nn->nn_sc) + ret = -EBUSY; + else + ret = 0; + spin_unlock(&nn->nn_lock); + if (ret) { + printk(KERN_NOTICE "o2net: Attempt to connect from node '%s' " + "at %pI4:%d but it already has an open connection\n", + node->nd_name, &sin.sin_addr.s_addr, + ntohs(sin.sin_port)); + goto out; + } + + sc = sc_alloc(node); + if (sc == NULL) { + ret = -ENOMEM; + goto out; + } + + sc->sc_sock = new_sock; + new_sock = NULL; + + spin_lock(&nn->nn_lock); + atomic_set(&nn->nn_timeout, 0); + o2net_set_nn_state(nn, sc, 0, 0); + spin_unlock(&nn->nn_lock); + + o2net_register_callbacks(sc->sc_sock->sk, sc); + o2net_sc_queue_work(sc, &sc->sc_rx_work); + + o2net_initialize_handshake(); + o2net_sendpage(sc, o2net_hand, sizeof(*o2net_hand)); + +out: + if (new_sock) + sock_release(new_sock); + if (node) + o2nm_node_put(node); + if (local_node) + o2nm_node_put(local_node); + if (sc) + sc_put(sc); + return ret; +} + +static void o2net_accept_many(struct work_struct *work) +{ + struct socket *sock = o2net_listen_sock; + while (o2net_accept_one(sock) == 0) + cond_resched(); +} + +static void o2net_listen_data_ready(struct sock *sk, int bytes) +{ + void (*ready)(struct sock *sk, int bytes); + + read_lock(&sk->sk_callback_lock); + ready = sk->sk_user_data; + if (ready == NULL) { /* check for teardown race */ + ready = sk->sk_data_ready; + goto out; + } + + /* ->sk_data_ready is also called for a newly established child socket + * before it has been accepted and the acceptor has set up their + * data_ready.. we only want to queue listen work for our listening + * socket */ + if (sk->sk_state == TCP_LISTEN) { + mlog(ML_TCP, "bytes: %d\n", bytes); + queue_work(o2net_wq, &o2net_listen_work); + } + +out: + read_unlock(&sk->sk_callback_lock); + ready(sk, bytes); +} + +static int o2net_open_listening_sock(__be32 addr, __be16 port) +{ + struct socket *sock = NULL; + int ret; + struct sockaddr_in sin = { + .sin_family = PF_INET, + .sin_addr = { .s_addr = addr }, + .sin_port = port, + }; + + ret = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock); + if (ret < 0) { + printk(KERN_ERR "o2net: Error %d while creating socket\n", ret); + goto out; + } + + sock->sk->sk_allocation = GFP_ATOMIC; + + write_lock_bh(&sock->sk->sk_callback_lock); + sock->sk->sk_user_data = sock->sk->sk_data_ready; + sock->sk->sk_data_ready = o2net_listen_data_ready; + write_unlock_bh(&sock->sk->sk_callback_lock); + + o2net_listen_sock = sock; + INIT_WORK(&o2net_listen_work, o2net_accept_many); + + sock->sk->sk_reuse = 1; + ret = sock->ops->bind(sock, (struct sockaddr *)&sin, sizeof(sin)); + if (ret < 0) { + printk(KERN_ERR "o2net: Error %d while binding socket at " + "%pI4:%u\n", ret, &addr, ntohs(port)); + goto out; + } + + ret = sock->ops->listen(sock, 64); + if (ret < 0) + printk(KERN_ERR "o2net: Error %d while listening on %pI4:%u\n", + ret, &addr, ntohs(port)); + +out: + if (ret) { + o2net_listen_sock = NULL; + if (sock) + sock_release(sock); + } + return ret; +} + +/* + * called from node manager when we should bring up our network listening + * socket. node manager handles all the serialization to only call this + * once and to match it with o2net_stop_listening(). note, + * o2nm_this_node() doesn't work yet as we're being called while it + * is being set up. + */ +int o2net_start_listening(struct o2nm_node *node) +{ + int ret = 0; + + BUG_ON(o2net_wq != NULL); + BUG_ON(o2net_listen_sock != NULL); + + mlog(ML_KTHREAD, "starting o2net thread...\n"); + o2net_wq = create_singlethread_workqueue("o2net"); + if (o2net_wq == NULL) { + mlog(ML_ERROR, "unable to launch o2net thread\n"); + return -ENOMEM; /* ? */ + } + + ret = o2net_open_listening_sock(node->nd_ipv4_address, + node->nd_ipv4_port); + if (ret) { + destroy_workqueue(o2net_wq); + o2net_wq = NULL; + } else + o2quo_conn_up(node->nd_num); + + return ret; +} + +/* again, o2nm_this_node() doesn't work here as we're involved in + * tearing it down */ +void o2net_stop_listening(struct o2nm_node *node) +{ + struct socket *sock = o2net_listen_sock; + size_t i; + + BUG_ON(o2net_wq == NULL); + BUG_ON(o2net_listen_sock == NULL); + + /* stop the listening socket from generating work */ + write_lock_bh(&sock->sk->sk_callback_lock); + sock->sk->sk_data_ready = sock->sk->sk_user_data; + sock->sk->sk_user_data = NULL; + write_unlock_bh(&sock->sk->sk_callback_lock); + + for (i = 0; i < ARRAY_SIZE(o2net_nodes); i++) { + struct o2nm_node *node = o2nm_get_node_by_num(i); + if (node) { + o2net_disconnect_node(node); + o2nm_node_put(node); + } + } + + /* finish all work and tear down the work queue */ + mlog(ML_KTHREAD, "waiting for o2net thread to exit....\n"); + destroy_workqueue(o2net_wq); + o2net_wq = NULL; + + sock_release(o2net_listen_sock); + o2net_listen_sock = NULL; + + o2quo_conn_err(node->nd_num); +} + +/* ------------------------------------------------------------ */ + +int o2net_init(void) +{ + unsigned long i; + + o2quo_init(); + + if (o2net_debugfs_init()) + return -ENOMEM; + + o2net_hand = kzalloc(sizeof(struct o2net_handshake), GFP_KERNEL); + o2net_keep_req = kzalloc(sizeof(struct o2net_msg), GFP_KERNEL); + o2net_keep_resp = kzalloc(sizeof(struct o2net_msg), GFP_KERNEL); + if (!o2net_hand || !o2net_keep_req || !o2net_keep_resp) { + kfree(o2net_hand); + kfree(o2net_keep_req); + kfree(o2net_keep_resp); + return -ENOMEM; + } + + o2net_hand->protocol_version = cpu_to_be64(O2NET_PROTOCOL_VERSION); + o2net_hand->connector_id = cpu_to_be64(1); + + o2net_keep_req->magic = cpu_to_be16(O2NET_MSG_KEEP_REQ_MAGIC); + o2net_keep_resp->magic = cpu_to_be16(O2NET_MSG_KEEP_RESP_MAGIC); + + for (i = 0; i < ARRAY_SIZE(o2net_nodes); i++) { + struct o2net_node *nn = o2net_nn_from_num(i); + + atomic_set(&nn->nn_timeout, 0); + spin_lock_init(&nn->nn_lock); + INIT_DELAYED_WORK(&nn->nn_connect_work, o2net_start_connect); + INIT_DELAYED_WORK(&nn->nn_connect_expired, + o2net_connect_expired); + INIT_DELAYED_WORK(&nn->nn_still_up, o2net_still_up); + /* until we see hb from a node we'll return einval */ + nn->nn_persistent_error = -ENOTCONN; + init_waitqueue_head(&nn->nn_sc_wq); + idr_init(&nn->nn_status_idr); + INIT_LIST_HEAD(&nn->nn_status_list); + } + + return 0; +} + +void o2net_exit(void) +{ + o2quo_exit(); + kfree(o2net_hand); + kfree(o2net_keep_req); + kfree(o2net_keep_resp); + o2net_debugfs_exit(); +} diff --git a/drivers/staging/ramster/cluster/tcp.h b/drivers/staging/ramster/cluster/tcp.h new file mode 100644 index 0000000..5bada2a --- /dev/null +++ b/drivers/staging/ramster/cluster/tcp.h @@ -0,0 +1,154 @@ +/* -*- mode: c; c-basic-offset: 8; -*- + * vim: noexpandtab sw=8 ts=8 sts=0: + * + * tcp.h + * + * Function prototypes + * + * Copyright (C) 2004 Oracle. All rights reserved. + * + * 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; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 021110-1307, USA. + * + */ + +#ifndef O2CLUSTER_TCP_H +#define O2CLUSTER_TCP_H + +#include +#ifdef __KERNEL__ +#include +#include +#else +#include +#endif +#include +#include + +struct o2net_msg +{ + __be16 magic; + __be16 data_len; + __be16 msg_type; + __be16 pad1; + __be32 sys_status; + __be32 status; + __be32 key; + __be32 msg_num; + __u8 buf[0]; +}; + +typedef int (o2net_msg_handler_func)(struct o2net_msg *msg, u32 len, void *data, + void **ret_data); +typedef void (o2net_post_msg_handler_func)(int status, void *data, + void *ret_data); + +#define O2NET_MAX_PAYLOAD_BYTES (4096 - sizeof(struct o2net_msg)) + +/* same as hb delay, we're waiting for another node to recognize our hb */ +#define O2NET_RECONNECT_DELAY_MS_DEFAULT 2000 + +#define O2NET_KEEPALIVE_DELAY_MS_DEFAULT 2000 +#define O2NET_IDLE_TIMEOUT_MS_DEFAULT 30000 + + +/* TODO: figure this out.... */ +static inline int o2net_link_down(int err, struct socket *sock) +{ + if (sock) { + if (sock->sk->sk_state != TCP_ESTABLISHED && + sock->sk->sk_state != TCP_CLOSE_WAIT) + return 1; + } + + if (err >= 0) + return 0; + switch (err) { + /* ????????????????????????? */ + case -ERESTARTSYS: + case -EBADF: + /* When the server has died, an ICMP port unreachable + * message prompts ECONNREFUSED. */ + case -ECONNREFUSED: + case -ENOTCONN: + case -ECONNRESET: + case -EPIPE: + return 1; + } + return 0; +} + +enum { + O2NET_DRIVER_UNINITED, + O2NET_DRIVER_READY, +}; + +int o2net_send_message(u32 msg_type, u32 key, void *data, u32 len, + u8 target_node, int *status); +int o2net_send_message_vec(u32 msg_type, u32 key, struct kvec *vec, + size_t veclen, u8 target_node, int *status); + +int o2net_register_handler(u32 msg_type, u32 key, u32 max_len, + o2net_msg_handler_func *func, void *data, + o2net_post_msg_handler_func *post_func, + struct list_head *unreg_list); +void o2net_unregister_handler_list(struct list_head *list); + +void o2net_fill_node_map(unsigned long *map, unsigned bytes); + +struct o2nm_node; +int o2net_register_hb_callbacks(void); +void o2net_unregister_hb_callbacks(void); +int o2net_start_listening(struct o2nm_node *node); +void o2net_stop_listening(struct o2nm_node *node); +void o2net_disconnect_node(struct o2nm_node *node); +int o2net_num_connected_peers(void); + +int o2net_init(void); +void o2net_exit(void); + +struct o2net_send_tracking; +struct o2net_sock_container; + +#ifdef CONFIG_DEBUG_FS +int o2net_debugfs_init(void); +void o2net_debugfs_exit(void); +void o2net_debug_add_nst(struct o2net_send_tracking *nst); +void o2net_debug_del_nst(struct o2net_send_tracking *nst); +void o2net_debug_add_sc(struct o2net_sock_container *sc); +void o2net_debug_del_sc(struct o2net_sock_container *sc); +#else +static inline int o2net_debugfs_init(void) +{ + return 0; +} +static inline void o2net_debugfs_exit(void) +{ +} +static inline void o2net_debug_add_nst(struct o2net_send_tracking *nst) +{ +} +static inline void o2net_debug_del_nst(struct o2net_send_tracking *nst) +{ +} +static inline void o2net_debug_add_sc(struct o2net_sock_container *sc) +{ +} +static inline void o2net_debug_del_sc(struct o2net_sock_container *sc) +{ +} +#endif /* CONFIG_DEBUG_FS */ + +#endif /* O2CLUSTER_TCP_H */ diff --git a/drivers/staging/ramster/cluster/tcp_internal.h b/drivers/staging/ramster/cluster/tcp_internal.h new file mode 100644 index 0000000..4cbcb65 --- /dev/null +++ b/drivers/staging/ramster/cluster/tcp_internal.h @@ -0,0 +1,242 @@ +/* -*- mode: c; c-basic-offset: 8; -*- + * vim: noexpandtab sw=8 ts=8 sts=0: + * + * Copyright (C) 2005 Oracle. All rights reserved. + * + * 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; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 021110-1307, USA. + */ + +#ifndef O2CLUSTER_TCP_INTERNAL_H +#define O2CLUSTER_TCP_INTERNAL_H + +#define O2NET_MSG_MAGIC ((u16)0xfa55) +#define O2NET_MSG_STATUS_MAGIC ((u16)0xfa56) +#define O2NET_MSG_KEEP_REQ_MAGIC ((u16)0xfa57) +#define O2NET_MSG_KEEP_RESP_MAGIC ((u16)0xfa58) + +/* we're delaying our quorum decision so that heartbeat will have timed + * out truly dead nodes by the time we come around to making decisions + * on their number */ +#define O2NET_QUORUM_DELAY_MS ((o2hb_dead_threshold + 2) * O2HB_REGION_TIMEOUT_MS) + +/* + * This version number represents quite a lot, unfortunately. It not + * only represents the raw network message protocol on the wire but also + * locking semantics of the file system using the protocol. It should + * be somewhere else, I'm sure, but right now it isn't. + * + * With version 11, we separate out the filesystem locking portion. The + * filesystem now has a major.minor version it negotiates. Version 11 + * introduces this negotiation to the o2dlm protocol, and as such the + * version here in tcp_internal.h should not need to be bumped for + * filesystem locking changes. + * + * New in version 11 + * - Negotiation of filesystem locking in the dlm join. + * + * New in version 10: + * - Meta/data locks combined + * + * New in version 9: + * - All votes removed + * + * New in version 8: + * - Replace delete inode votes with a cluster lock + * + * New in version 7: + * - DLM join domain includes the live nodemap + * + * New in version 6: + * - DLM lockres remote refcount fixes. + * + * New in version 5: + * - Network timeout checking protocol + * + * New in version 4: + * - Remove i_generation from lock names for better stat performance. + * + * New in version 3: + * - Replace dentry votes with a cluster lock + * + * New in version 2: + * - full 64 bit i_size in the metadata lock lvbs + * - introduction of "rw" lock and pushing meta/data locking down + */ +#define O2NET_PROTOCOL_VERSION 11ULL +struct o2net_handshake { + __be64 protocol_version; + __be64 connector_id; + __be32 o2hb_heartbeat_timeout_ms; + __be32 o2net_idle_timeout_ms; + __be32 o2net_keepalive_delay_ms; + __be32 o2net_reconnect_delay_ms; +}; + +struct o2net_node { + /* this is never called from int/bh */ + spinlock_t nn_lock; + + /* set the moment an sc is allocated and a connect is started */ + struct o2net_sock_container *nn_sc; + /* _valid is only set after the handshake passes and tx can happen */ + unsigned nn_sc_valid:1; + /* if this is set tx just returns it */ + int nn_persistent_error; + /* It is only set to 1 after the idle time out. */ + atomic_t nn_timeout; + + /* threads waiting for an sc to arrive wait on the wq for generation + * to increase. it is increased when a connecting socket succeeds + * or fails or when an accepted socket is attached. */ + wait_queue_head_t nn_sc_wq; + + struct idr nn_status_idr; + struct list_head nn_status_list; + + /* connects are attempted from when heartbeat comes up until either hb + * goes down, the node is unconfigured, no connect attempts succeed + * before O2NET_CONN_IDLE_DELAY, or a connect succeeds. connect_work + * is queued from set_nn_state both from hb up and from itself if a + * connect attempt fails and so can be self-arming. shutdown is + * careful to first mark the nn such that no connects will be attempted + * before canceling delayed connect work and flushing the queue. */ + struct delayed_work nn_connect_work; + unsigned long nn_last_connect_attempt; + + /* this is queued as nodes come up and is canceled when a connection is + * established. this expiring gives up on the node and errors out + * transmits */ + struct delayed_work nn_connect_expired; + + /* after we give up on a socket we wait a while before deciding + * that it is still heartbeating and that we should do some + * quorum work */ + struct delayed_work nn_still_up; +}; + +struct o2net_sock_container { + struct kref sc_kref; + /* the next two are valid for the life time of the sc */ + struct socket *sc_sock; + struct o2nm_node *sc_node; + + /* all of these sc work structs hold refs on the sc while they are + * queued. they should not be able to ref a freed sc. the teardown + * race is with o2net_wq destruction in o2net_stop_listening() */ + + /* rx and connect work are generated from socket callbacks. sc + * shutdown removes the callbacks and then flushes the work queue */ + struct work_struct sc_rx_work; + struct work_struct sc_connect_work; + /* shutdown work is triggered in two ways. the simple way is + * for a code path calls ensure_shutdown which gets a lock, removes + * the sc from the nn, and queues the work. in this case the + * work is single-shot. the work is also queued from a sock + * callback, though, and in this case the work will find the sc + * still on the nn and will call ensure_shutdown itself.. this + * ends up triggering the shutdown work again, though nothing + * will be done in that second iteration. so work queue teardown + * has to be careful to remove the sc from the nn before waiting + * on the work queue so that the shutdown work doesn't remove the + * sc and rearm itself. + */ + struct work_struct sc_shutdown_work; + + struct timer_list sc_idle_timeout; + struct delayed_work sc_keepalive_work; + + unsigned sc_handshake_ok:1; + + struct page *sc_page; + size_t sc_page_off; + + /* original handlers for the sockets */ + void (*sc_state_change)(struct sock *sk); + void (*sc_data_ready)(struct sock *sk, int bytes); + + u32 sc_msg_key; + u16 sc_msg_type; + +#ifdef CONFIG_DEBUG_FS + struct list_head sc_net_debug_item; + ktime_t sc_tv_timer; + ktime_t sc_tv_data_ready; + ktime_t sc_tv_advance_start; + ktime_t sc_tv_advance_stop; + ktime_t sc_tv_func_start; + ktime_t sc_tv_func_stop; +#endif +#ifdef CONFIG_OCFS2_FS_STATS + ktime_t sc_tv_acquiry_total; + ktime_t sc_tv_send_total; + ktime_t sc_tv_status_total; + u32 sc_send_count; + u32 sc_recv_count; + ktime_t sc_tv_process_total; +#endif + struct mutex sc_send_lock; +}; + +struct o2net_msg_handler { + struct rb_node nh_node; + u32 nh_max_len; + u32 nh_msg_type; + u32 nh_key; + o2net_msg_handler_func *nh_func; + o2net_msg_handler_func *nh_func_data; + o2net_post_msg_handler_func + *nh_post_func; + struct kref nh_kref; + struct list_head nh_unregister_item; +}; + +enum o2net_system_error { + O2NET_ERR_NONE = 0, + O2NET_ERR_NO_HNDLR, + O2NET_ERR_OVERFLOW, + O2NET_ERR_DIED, + O2NET_ERR_MAX +}; + +struct o2net_status_wait { + enum o2net_system_error ns_sys_status; + s32 ns_status; + int ns_id; + wait_queue_head_t ns_wq; + struct list_head ns_node_item; +}; + +#ifdef CONFIG_DEBUG_FS +/* just for state dumps */ +struct o2net_send_tracking { + struct list_head st_net_debug_item; + struct task_struct *st_task; + struct o2net_sock_container *st_sc; + u32 st_id; + u32 st_msg_type; + u32 st_msg_key; + u8 st_node; + ktime_t st_sock_time; + ktime_t st_send_time; + ktime_t st_status_time; +}; +#else +struct o2net_send_tracking { + u32 dummy; +}; +#endif /* CONFIG_DEBUG_FS */ + +#endif /* O2CLUSTER_TCP_INTERNAL_H */ diff --git a/drivers/staging/ramster/cluster/ver.c b/drivers/staging/ramster/cluster/ver.c new file mode 100644 index 0000000..a56eee6 --- /dev/null +++ b/drivers/staging/ramster/cluster/ver.c @@ -0,0 +1,42 @@ +/* -*- mode: c; c-basic-offset: 8; -*- + * vim: noexpandtab sw=8 ts=8 sts=0: + * + * ver.c + * + * version string + * + * Copyright (C) 2002, 2005 Oracle. All rights reserved. + * + * 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; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 021110-1307, USA. + */ + +#include +#include + +#include "ver.h" + +#define CLUSTER_BUILD_VERSION "1.5.0" + +#define VERSION_STR "OCFS2 Node Manager " CLUSTER_BUILD_VERSION + +void cluster_print_version(void) +{ + printk(KERN_INFO "%s\n", VERSION_STR); +} + +MODULE_DESCRIPTION(VERSION_STR); + +MODULE_VERSION(CLUSTER_BUILD_VERSION); diff --git a/drivers/staging/ramster/cluster/ver.h b/drivers/staging/ramster/cluster/ver.h new file mode 100644 index 0000000..32554c3 --- /dev/null +++ b/drivers/staging/ramster/cluster/ver.h @@ -0,0 +1,31 @@ +/* -*- mode: c; c-basic-offset: 8; -*- + * vim: noexpandtab sw=8 ts=8 sts=0: + * + * ver.h + * + * Function prototypes + * + * Copyright (C) 2005 Oracle. All rights reserved. + * + * 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; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 021110-1307, USA. + */ + +#ifndef O2CLUSTER_VER_H +#define O2CLUSTER_VER_H + +void cluster_print_version(void); + +#endif /* O2CLUSTER_VER_H */ -- cgit v0.10.2 From ba351b02ab11616b08b9220dacd49b20415b1f80 Mon Sep 17 00:00:00 2001 From: Dan Magenheimer Date: Mon, 30 Jan 2012 14:39:18 -0800 Subject: staging: ramster: local compression + tmem Copy files from drivers/staging/zcache. Ramster compresses pages locally before transmitting them to another node, so we can leverage the zcache and tmem code directly. Note: there are no ramster-specific changes yet to these files. (Why copy? The ramster tmem.c/tmem.h changes are definitely shareable between zcache and ramster; the eventual destination for tmem.c is the linux lib directory. Ramster changes to zcache are more substantial and zcache is currently undergoing some significant unrelated changes (including a new allocator and breaking zcache-main.c into smaller files), so it seemed best to branch temporarily and merge later.) Signed-off-by: Dan Magenheimer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/ramster/Kconfig b/drivers/staging/ramster/Kconfig new file mode 100644 index 0000000..7fabcb2 --- /dev/null +++ b/drivers/staging/ramster/Kconfig @@ -0,0 +1,13 @@ +config ZCACHE + tristate "Dynamic compression of swap pages and clean pagecache pages" + depends on CLEANCACHE || FRONTSWAP + select XVMALLOC + select LZO_COMPRESS + select LZO_DECOMPRESS + default n + help + Zcache doubles RAM efficiency while providing a significant + performance boosts on many workloads. Zcache uses lzo1x + compression and an in-kernel implementation of transcendent + memory to store clean page cache pages and swap in RAM, + providing a noticeable reduction in disk I/O. diff --git a/drivers/staging/ramster/Makefile b/drivers/staging/ramster/Makefile new file mode 100644 index 0000000..60daa27 --- /dev/null +++ b/drivers/staging/ramster/Makefile @@ -0,0 +1,3 @@ +zcache-y := zcache-main.o tmem.o + +obj-$(CONFIG_ZCACHE) += zcache.o diff --git a/drivers/staging/ramster/tmem.c b/drivers/staging/ramster/tmem.c new file mode 100644 index 0000000..1ca66ea --- /dev/null +++ b/drivers/staging/ramster/tmem.c @@ -0,0 +1,770 @@ +/* + * In-kernel transcendent memory (generic implementation) + * + * Copyright (c) 2009-2011, Dan Magenheimer, Oracle Corp. + * + * The primary purpose of Transcedent Memory ("tmem") is to map object-oriented + * "handles" (triples containing a pool id, and object id, and an index), to + * pages in a page-accessible memory (PAM). Tmem references the PAM pages via + * an abstract "pampd" (PAM page-descriptor), which can be operated on by a + * set of functions (pamops). Each pampd contains some representation of + * PAGE_SIZE bytes worth of data. Tmem must support potentially millions of + * pages and must be able to insert, find, and delete these pages at a + * potential frequency of thousands per second concurrently across many CPUs, + * (and, if used with KVM, across many vcpus across many guests). + * Tmem is tracked with a hierarchy of data structures, organized by + * the elements in a handle-tuple: pool_id, object_id, and page index. + * One or more "clients" (e.g. guests) each provide one or more tmem_pools. + * Each pool, contains a hash table of rb_trees of tmem_objs. Each + * tmem_obj contains a radix-tree-like tree of pointers, with intermediate + * nodes called tmem_objnodes. Each leaf pointer in this tree points to + * a pampd, which is accessible only through a small set of callbacks + * registered by the PAM implementation (see tmem_register_pamops). Tmem + * does all memory allocation via a set of callbacks registered by the tmem + * host implementation (e.g. see tmem_register_hostops). + */ + +#include +#include +#include + +#include "tmem.h" + +/* data structure sentinels used for debugging... see tmem.h */ +#define POOL_SENTINEL 0x87658765 +#define OBJ_SENTINEL 0x12345678 +#define OBJNODE_SENTINEL 0xfedcba09 + +/* + * A tmem host implementation must use this function to register callbacks + * for memory allocation. + */ +static struct tmem_hostops tmem_hostops; + +static void tmem_objnode_tree_init(void); + +void tmem_register_hostops(struct tmem_hostops *m) +{ + tmem_objnode_tree_init(); + tmem_hostops = *m; +} + +/* + * A tmem host implementation must use this function to register + * callbacks for a page-accessible memory (PAM) implementation + */ +static struct tmem_pamops tmem_pamops; + +void tmem_register_pamops(struct tmem_pamops *m) +{ + tmem_pamops = *m; +} + +/* + * Oid's are potentially very sparse and tmem_objs may have an indeterminately + * short life, being added and deleted at a relatively high frequency. + * So an rb_tree is an ideal data structure to manage tmem_objs. But because + * of the potentially huge number of tmem_objs, each pool manages a hashtable + * of rb_trees to reduce search, insert, delete, and rebalancing time. + * Each hashbucket also has a lock to manage concurrent access. + * + * The following routines manage tmem_objs. When any tmem_obj is accessed, + * the hashbucket lock must be held. + */ + +/* searches for object==oid in pool, returns locked object if found */ +static struct tmem_obj *tmem_obj_find(struct tmem_hashbucket *hb, + struct tmem_oid *oidp) +{ + struct rb_node *rbnode; + struct tmem_obj *obj; + + rbnode = hb->obj_rb_root.rb_node; + while (rbnode) { + BUG_ON(RB_EMPTY_NODE(rbnode)); + obj = rb_entry(rbnode, struct tmem_obj, rb_tree_node); + switch (tmem_oid_compare(oidp, &obj->oid)) { + case 0: /* equal */ + goto out; + case -1: + rbnode = rbnode->rb_left; + break; + case 1: + rbnode = rbnode->rb_right; + break; + } + } + obj = NULL; +out: + return obj; +} + +static void tmem_pampd_destroy_all_in_obj(struct tmem_obj *); + +/* free an object that has no more pampds in it */ +static void tmem_obj_free(struct tmem_obj *obj, struct tmem_hashbucket *hb) +{ + struct tmem_pool *pool; + + BUG_ON(obj == NULL); + ASSERT_SENTINEL(obj, OBJ); + BUG_ON(obj->pampd_count > 0); + pool = obj->pool; + BUG_ON(pool == NULL); + if (obj->objnode_tree_root != NULL) /* may be "stump" with no leaves */ + tmem_pampd_destroy_all_in_obj(obj); + BUG_ON(obj->objnode_tree_root != NULL); + BUG_ON((long)obj->objnode_count != 0); + atomic_dec(&pool->obj_count); + BUG_ON(atomic_read(&pool->obj_count) < 0); + INVERT_SENTINEL(obj, OBJ); + obj->pool = NULL; + tmem_oid_set_invalid(&obj->oid); + rb_erase(&obj->rb_tree_node, &hb->obj_rb_root); +} + +/* + * initialize, and insert an tmem_object_root (called only if find failed) + */ +static void tmem_obj_init(struct tmem_obj *obj, struct tmem_hashbucket *hb, + struct tmem_pool *pool, + struct tmem_oid *oidp) +{ + struct rb_root *root = &hb->obj_rb_root; + struct rb_node **new = &(root->rb_node), *parent = NULL; + struct tmem_obj *this; + + BUG_ON(pool == NULL); + atomic_inc(&pool->obj_count); + obj->objnode_tree_height = 0; + obj->objnode_tree_root = NULL; + obj->pool = pool; + obj->oid = *oidp; + obj->objnode_count = 0; + obj->pampd_count = 0; + (*tmem_pamops.new_obj)(obj); + SET_SENTINEL(obj, OBJ); + while (*new) { + BUG_ON(RB_EMPTY_NODE(*new)); + this = rb_entry(*new, struct tmem_obj, rb_tree_node); + parent = *new; + switch (tmem_oid_compare(oidp, &this->oid)) { + case 0: + BUG(); /* already present; should never happen! */ + break; + case -1: + new = &(*new)->rb_left; + break; + case 1: + new = &(*new)->rb_right; + break; + } + } + rb_link_node(&obj->rb_tree_node, parent, new); + rb_insert_color(&obj->rb_tree_node, root); +} + +/* + * Tmem is managed as a set of tmem_pools with certain attributes, such as + * "ephemeral" vs "persistent". These attributes apply to all tmem_objs + * and all pampds that belong to a tmem_pool. A tmem_pool is created + * or deleted relatively rarely (for example, when a filesystem is + * mounted or unmounted. + */ + +/* flush all data from a pool and, optionally, free it */ +static void tmem_pool_flush(struct tmem_pool *pool, bool destroy) +{ + struct rb_node *rbnode; + struct tmem_obj *obj; + struct tmem_hashbucket *hb = &pool->hashbucket[0]; + int i; + + BUG_ON(pool == NULL); + for (i = 0; i < TMEM_HASH_BUCKETS; i++, hb++) { + spin_lock(&hb->lock); + rbnode = rb_first(&hb->obj_rb_root); + while (rbnode != NULL) { + obj = rb_entry(rbnode, struct tmem_obj, rb_tree_node); + rbnode = rb_next(rbnode); + tmem_pampd_destroy_all_in_obj(obj); + tmem_obj_free(obj, hb); + (*tmem_hostops.obj_free)(obj, pool); + } + spin_unlock(&hb->lock); + } + if (destroy) + list_del(&pool->pool_list); +} + +/* + * A tmem_obj contains a radix-tree-like tree in which the intermediate + * nodes are called tmem_objnodes. (The kernel lib/radix-tree.c implementation + * is very specialized and tuned for specific uses and is not particularly + * suited for use from this code, though some code from the core algorithms has + * been reused, thus the copyright notices below). Each tmem_objnode contains + * a set of pointers which point to either a set of intermediate tmem_objnodes + * or a set of of pampds. + * + * Portions Copyright (C) 2001 Momchil Velikov + * Portions Copyright (C) 2001 Christoph Hellwig + * Portions Copyright (C) 2005 SGI, Christoph Lameter + */ + +struct tmem_objnode_tree_path { + struct tmem_objnode *objnode; + int offset; +}; + +/* objnode height_to_maxindex translation */ +static unsigned long tmem_objnode_tree_h2max[OBJNODE_TREE_MAX_PATH + 1]; + +static void tmem_objnode_tree_init(void) +{ + unsigned int ht, tmp; + + for (ht = 0; ht < ARRAY_SIZE(tmem_objnode_tree_h2max); ht++) { + tmp = ht * OBJNODE_TREE_MAP_SHIFT; + if (tmp >= OBJNODE_TREE_INDEX_BITS) + tmem_objnode_tree_h2max[ht] = ~0UL; + else + tmem_objnode_tree_h2max[ht] = + (~0UL >> (OBJNODE_TREE_INDEX_BITS - tmp - 1)) >> 1; + } +} + +static struct tmem_objnode *tmem_objnode_alloc(struct tmem_obj *obj) +{ + struct tmem_objnode *objnode; + + ASSERT_SENTINEL(obj, OBJ); + BUG_ON(obj->pool == NULL); + ASSERT_SENTINEL(obj->pool, POOL); + objnode = (*tmem_hostops.objnode_alloc)(obj->pool); + if (unlikely(objnode == NULL)) + goto out; + objnode->obj = obj; + SET_SENTINEL(objnode, OBJNODE); + memset(&objnode->slots, 0, sizeof(objnode->slots)); + objnode->slots_in_use = 0; + obj->objnode_count++; +out: + return objnode; +} + +static void tmem_objnode_free(struct tmem_objnode *objnode) +{ + struct tmem_pool *pool; + int i; + + BUG_ON(objnode == NULL); + for (i = 0; i < OBJNODE_TREE_MAP_SIZE; i++) + BUG_ON(objnode->slots[i] != NULL); + ASSERT_SENTINEL(objnode, OBJNODE); + INVERT_SENTINEL(objnode, OBJNODE); + BUG_ON(objnode->obj == NULL); + ASSERT_SENTINEL(objnode->obj, OBJ); + pool = objnode->obj->pool; + BUG_ON(pool == NULL); + ASSERT_SENTINEL(pool, POOL); + objnode->obj->objnode_count--; + objnode->obj = NULL; + (*tmem_hostops.objnode_free)(objnode, pool); +} + +/* + * lookup index in object and return associated pampd (or NULL if not found) + */ +static void **__tmem_pampd_lookup_in_obj(struct tmem_obj *obj, uint32_t index) +{ + unsigned int height, shift; + struct tmem_objnode **slot = NULL; + + BUG_ON(obj == NULL); + ASSERT_SENTINEL(obj, OBJ); + BUG_ON(obj->pool == NULL); + ASSERT_SENTINEL(obj->pool, POOL); + + height = obj->objnode_tree_height; + if (index > tmem_objnode_tree_h2max[obj->objnode_tree_height]) + goto out; + if (height == 0 && obj->objnode_tree_root) { + slot = &obj->objnode_tree_root; + goto out; + } + shift = (height-1) * OBJNODE_TREE_MAP_SHIFT; + slot = &obj->objnode_tree_root; + while (height > 0) { + if (*slot == NULL) + goto out; + slot = (struct tmem_objnode **) + ((*slot)->slots + + ((index >> shift) & OBJNODE_TREE_MAP_MASK)); + shift -= OBJNODE_TREE_MAP_SHIFT; + height--; + } +out: + return slot != NULL ? (void **)slot : NULL; +} + +static void *tmem_pampd_lookup_in_obj(struct tmem_obj *obj, uint32_t index) +{ + struct tmem_objnode **slot; + + slot = (struct tmem_objnode **)__tmem_pampd_lookup_in_obj(obj, index); + return slot != NULL ? *slot : NULL; +} + +static void *tmem_pampd_replace_in_obj(struct tmem_obj *obj, uint32_t index, + void *new_pampd) +{ + struct tmem_objnode **slot; + void *ret = NULL; + + slot = (struct tmem_objnode **)__tmem_pampd_lookup_in_obj(obj, index); + if ((slot != NULL) && (*slot != NULL)) { + void *old_pampd = *(void **)slot; + *(void **)slot = new_pampd; + (*tmem_pamops.free)(old_pampd, obj->pool, NULL, 0); + ret = new_pampd; + } + return ret; +} + +static int tmem_pampd_add_to_obj(struct tmem_obj *obj, uint32_t index, + void *pampd) +{ + int ret = 0; + struct tmem_objnode *objnode = NULL, *newnode, *slot; + unsigned int height, shift; + int offset = 0; + + /* if necessary, extend the tree to be higher */ + if (index > tmem_objnode_tree_h2max[obj->objnode_tree_height]) { + height = obj->objnode_tree_height + 1; + if (index > tmem_objnode_tree_h2max[height]) + while (index > tmem_objnode_tree_h2max[height]) + height++; + if (obj->objnode_tree_root == NULL) { + obj->objnode_tree_height = height; + goto insert; + } + do { + newnode = tmem_objnode_alloc(obj); + if (!newnode) { + ret = -ENOMEM; + goto out; + } + newnode->slots[0] = obj->objnode_tree_root; + newnode->slots_in_use = 1; + obj->objnode_tree_root = newnode; + obj->objnode_tree_height++; + } while (height > obj->objnode_tree_height); + } +insert: + slot = obj->objnode_tree_root; + height = obj->objnode_tree_height; + shift = (height-1) * OBJNODE_TREE_MAP_SHIFT; + while (height > 0) { + if (slot == NULL) { + /* add a child objnode. */ + slot = tmem_objnode_alloc(obj); + if (!slot) { + ret = -ENOMEM; + goto out; + } + if (objnode) { + + objnode->slots[offset] = slot; + objnode->slots_in_use++; + } else + obj->objnode_tree_root = slot; + } + /* go down a level */ + offset = (index >> shift) & OBJNODE_TREE_MAP_MASK; + objnode = slot; + slot = objnode->slots[offset]; + shift -= OBJNODE_TREE_MAP_SHIFT; + height--; + } + BUG_ON(slot != NULL); + if (objnode) { + objnode->slots_in_use++; + objnode->slots[offset] = pampd; + } else + obj->objnode_tree_root = pampd; + obj->pampd_count++; +out: + return ret; +} + +static void *tmem_pampd_delete_from_obj(struct tmem_obj *obj, uint32_t index) +{ + struct tmem_objnode_tree_path path[OBJNODE_TREE_MAX_PATH + 1]; + struct tmem_objnode_tree_path *pathp = path; + struct tmem_objnode *slot = NULL; + unsigned int height, shift; + int offset; + + BUG_ON(obj == NULL); + ASSERT_SENTINEL(obj, OBJ); + BUG_ON(obj->pool == NULL); + ASSERT_SENTINEL(obj->pool, POOL); + height = obj->objnode_tree_height; + if (index > tmem_objnode_tree_h2max[height]) + goto out; + slot = obj->objnode_tree_root; + if (height == 0 && obj->objnode_tree_root) { + obj->objnode_tree_root = NULL; + goto out; + } + shift = (height - 1) * OBJNODE_TREE_MAP_SHIFT; + pathp->objnode = NULL; + do { + if (slot == NULL) + goto out; + pathp++; + offset = (index >> shift) & OBJNODE_TREE_MAP_MASK; + pathp->offset = offset; + pathp->objnode = slot; + slot = slot->slots[offset]; + shift -= OBJNODE_TREE_MAP_SHIFT; + height--; + } while (height > 0); + if (slot == NULL) + goto out; + while (pathp->objnode) { + pathp->objnode->slots[pathp->offset] = NULL; + pathp->objnode->slots_in_use--; + if (pathp->objnode->slots_in_use) { + if (pathp->objnode == obj->objnode_tree_root) { + while (obj->objnode_tree_height > 0 && + obj->objnode_tree_root->slots_in_use == 1 && + obj->objnode_tree_root->slots[0]) { + struct tmem_objnode *to_free = + obj->objnode_tree_root; + + obj->objnode_tree_root = + to_free->slots[0]; + obj->objnode_tree_height--; + to_free->slots[0] = NULL; + to_free->slots_in_use = 0; + tmem_objnode_free(to_free); + } + } + goto out; + } + tmem_objnode_free(pathp->objnode); /* 0 slots used, free it */ + pathp--; + } + obj->objnode_tree_height = 0; + obj->objnode_tree_root = NULL; + +out: + if (slot != NULL) + obj->pampd_count--; + BUG_ON(obj->pampd_count < 0); + return slot; +} + +/* recursively walk the objnode_tree destroying pampds and objnodes */ +static void tmem_objnode_node_destroy(struct tmem_obj *obj, + struct tmem_objnode *objnode, + unsigned int ht) +{ + int i; + + if (ht == 0) + return; + for (i = 0; i < OBJNODE_TREE_MAP_SIZE; i++) { + if (objnode->slots[i]) { + if (ht == 1) { + obj->pampd_count--; + (*tmem_pamops.free)(objnode->slots[i], + obj->pool, NULL, 0); + objnode->slots[i] = NULL; + continue; + } + tmem_objnode_node_destroy(obj, objnode->slots[i], ht-1); + tmem_objnode_free(objnode->slots[i]); + objnode->slots[i] = NULL; + } + } +} + +static void tmem_pampd_destroy_all_in_obj(struct tmem_obj *obj) +{ + if (obj->objnode_tree_root == NULL) + return; + if (obj->objnode_tree_height == 0) { + obj->pampd_count--; + (*tmem_pamops.free)(obj->objnode_tree_root, obj->pool, NULL, 0); + } else { + tmem_objnode_node_destroy(obj, obj->objnode_tree_root, + obj->objnode_tree_height); + tmem_objnode_free(obj->objnode_tree_root); + obj->objnode_tree_height = 0; + } + obj->objnode_tree_root = NULL; + (*tmem_pamops.free_obj)(obj->pool, obj); +} + +/* + * Tmem is operated on by a set of well-defined actions: + * "put", "get", "flush", "flush_object", "new pool" and "destroy pool". + * (The tmem ABI allows for subpages and exchanges but these operations + * are not included in this implementation.) + * + * These "tmem core" operations are implemented in the following functions. + */ + +/* + * "Put" a page, e.g. copy a page from the kernel into newly allocated + * PAM space (if such space is available). Tmem_put is complicated by + * a corner case: What if a page with matching handle already exists in + * tmem? To guarantee coherency, one of two actions is necessary: Either + * the data for the page must be overwritten, or the page must be + * "flushed" so that the data is not accessible to a subsequent "get". + * Since these "duplicate puts" are relatively rare, this implementation + * always flushes for simplicity. + */ +int tmem_put(struct tmem_pool *pool, struct tmem_oid *oidp, uint32_t index, + char *data, size_t size, bool raw, bool ephemeral) +{ + struct tmem_obj *obj = NULL, *objfound = NULL, *objnew = NULL; + void *pampd = NULL, *pampd_del = NULL; + int ret = -ENOMEM; + struct tmem_hashbucket *hb; + + hb = &pool->hashbucket[tmem_oid_hash(oidp)]; + spin_lock(&hb->lock); + obj = objfound = tmem_obj_find(hb, oidp); + if (obj != NULL) { + pampd = tmem_pampd_lookup_in_obj(objfound, index); + if (pampd != NULL) { + /* if found, is a dup put, flush the old one */ + pampd_del = tmem_pampd_delete_from_obj(obj, index); + BUG_ON(pampd_del != pampd); + (*tmem_pamops.free)(pampd, pool, oidp, index); + if (obj->pampd_count == 0) { + objnew = obj; + objfound = NULL; + } + pampd = NULL; + } + } else { + obj = objnew = (*tmem_hostops.obj_alloc)(pool); + if (unlikely(obj == NULL)) { + ret = -ENOMEM; + goto out; + } + tmem_obj_init(obj, hb, pool, oidp); + } + BUG_ON(obj == NULL); + BUG_ON(((objnew != obj) && (objfound != obj)) || (objnew == objfound)); + pampd = (*tmem_pamops.create)(data, size, raw, ephemeral, + obj->pool, &obj->oid, index); + if (unlikely(pampd == NULL)) + goto free; + ret = tmem_pampd_add_to_obj(obj, index, pampd); + if (unlikely(ret == -ENOMEM)) + /* may have partially built objnode tree ("stump") */ + goto delete_and_free; + goto out; + +delete_and_free: + (void)tmem_pampd_delete_from_obj(obj, index); +free: + if (pampd) + (*tmem_pamops.free)(pampd, pool, NULL, 0); + if (objnew) { + tmem_obj_free(objnew, hb); + (*tmem_hostops.obj_free)(objnew, pool); + } +out: + spin_unlock(&hb->lock); + return ret; +} + +/* + * "Get" a page, e.g. if one can be found, copy the tmem page with the + * matching handle from PAM space to the kernel. By tmem definition, + * when a "get" is successful on an ephemeral page, the page is "flushed", + * and when a "get" is successful on a persistent page, the page is retained + * in tmem. Note that to preserve + * coherency, "get" can never be skipped if tmem contains the data. + * That is, if a get is done with a certain handle and fails, any + * subsequent "get" must also fail (unless of course there is a + * "put" done with the same handle). + + */ +int tmem_get(struct tmem_pool *pool, struct tmem_oid *oidp, uint32_t index, + char *data, size_t *size, bool raw, int get_and_free) +{ + struct tmem_obj *obj; + void *pampd; + bool ephemeral = is_ephemeral(pool); + int ret = -1; + struct tmem_hashbucket *hb; + bool free = (get_and_free == 1) || ((get_and_free == 0) && ephemeral); + bool lock_held = false; + + hb = &pool->hashbucket[tmem_oid_hash(oidp)]; + spin_lock(&hb->lock); + lock_held = true; + obj = tmem_obj_find(hb, oidp); + if (obj == NULL) + goto out; + if (free) + pampd = tmem_pampd_delete_from_obj(obj, index); + else + pampd = tmem_pampd_lookup_in_obj(obj, index); + if (pampd == NULL) + goto out; + if (free) { + if (obj->pampd_count == 0) { + tmem_obj_free(obj, hb); + (*tmem_hostops.obj_free)(obj, pool); + obj = NULL; + } + } + if (tmem_pamops.is_remote(pampd)) { + lock_held = false; + spin_unlock(&hb->lock); + } + if (free) + ret = (*tmem_pamops.get_data_and_free)( + data, size, raw, pampd, pool, oidp, index); + else + ret = (*tmem_pamops.get_data)( + data, size, raw, pampd, pool, oidp, index); + if (ret < 0) + goto out; + ret = 0; +out: + if (lock_held) + spin_unlock(&hb->lock); + return ret; +} + +/* + * If a page in tmem matches the handle, "flush" this page from tmem such + * that any subsequent "get" does not succeed (unless, of course, there + * was another "put" with the same handle). + */ +int tmem_flush_page(struct tmem_pool *pool, + struct tmem_oid *oidp, uint32_t index) +{ + struct tmem_obj *obj; + void *pampd; + int ret = -1; + struct tmem_hashbucket *hb; + + hb = &pool->hashbucket[tmem_oid_hash(oidp)]; + spin_lock(&hb->lock); + obj = tmem_obj_find(hb, oidp); + if (obj == NULL) + goto out; + pampd = tmem_pampd_delete_from_obj(obj, index); + if (pampd == NULL) + goto out; + (*tmem_pamops.free)(pampd, pool, oidp, index); + if (obj->pampd_count == 0) { + tmem_obj_free(obj, hb); + (*tmem_hostops.obj_free)(obj, pool); + } + ret = 0; + +out: + spin_unlock(&hb->lock); + return ret; +} + +/* + * If a page in tmem matches the handle, replace the page so that any + * subsequent "get" gets the new page. Returns 0 if + * there was a page to replace, else returns -1. + */ +int tmem_replace(struct tmem_pool *pool, struct tmem_oid *oidp, + uint32_t index, void *new_pampd) +{ + struct tmem_obj *obj; + int ret = -1; + struct tmem_hashbucket *hb; + + hb = &pool->hashbucket[tmem_oid_hash(oidp)]; + spin_lock(&hb->lock); + obj = tmem_obj_find(hb, oidp); + if (obj == NULL) + goto out; + new_pampd = tmem_pampd_replace_in_obj(obj, index, new_pampd); + ret = (*tmem_pamops.replace_in_obj)(new_pampd, obj); +out: + spin_unlock(&hb->lock); + return ret; +} + +/* + * "Flush" all pages in tmem matching this oid. + */ +int tmem_flush_object(struct tmem_pool *pool, struct tmem_oid *oidp) +{ + struct tmem_obj *obj; + struct tmem_hashbucket *hb; + int ret = -1; + + hb = &pool->hashbucket[tmem_oid_hash(oidp)]; + spin_lock(&hb->lock); + obj = tmem_obj_find(hb, oidp); + if (obj == NULL) + goto out; + tmem_pampd_destroy_all_in_obj(obj); + tmem_obj_free(obj, hb); + (*tmem_hostops.obj_free)(obj, pool); + ret = 0; + +out: + spin_unlock(&hb->lock); + return ret; +} + +/* + * "Flush" all pages (and tmem_objs) from this tmem_pool and disable + * all subsequent access to this tmem_pool. + */ +int tmem_destroy_pool(struct tmem_pool *pool) +{ + int ret = -1; + + if (pool == NULL) + goto out; + tmem_pool_flush(pool, 1); + ret = 0; +out: + return ret; +} + +static LIST_HEAD(tmem_global_pool_list); + +/* + * Create a new tmem_pool with the provided flag and return + * a pool id provided by the tmem host implementation. + */ +void tmem_new_pool(struct tmem_pool *pool, uint32_t flags) +{ + int persistent = flags & TMEM_POOL_PERSIST; + int shared = flags & TMEM_POOL_SHARED; + struct tmem_hashbucket *hb = &pool->hashbucket[0]; + int i; + + for (i = 0; i < TMEM_HASH_BUCKETS; i++, hb++) { + hb->obj_rb_root = RB_ROOT; + spin_lock_init(&hb->lock); + } + INIT_LIST_HEAD(&pool->pool_list); + atomic_set(&pool->obj_count, 0); + SET_SENTINEL(pool, POOL); + list_add_tail(&pool->pool_list, &tmem_global_pool_list); + pool->persistent = persistent; + pool->shared = shared; +} diff --git a/drivers/staging/ramster/tmem.h b/drivers/staging/ramster/tmem.h new file mode 100644 index 0000000..ed147c4 --- /dev/null +++ b/drivers/staging/ramster/tmem.h @@ -0,0 +1,206 @@ +/* + * tmem.h + * + * Transcendent memory + * + * Copyright (c) 2009-2011, Dan Magenheimer, Oracle Corp. + */ + +#ifndef _TMEM_H_ +#define _TMEM_H_ + +#include +#include +#include +#include + +/* + * These are pre-defined by the Xen<->Linux ABI + */ +#define TMEM_PUT_PAGE 4 +#define TMEM_GET_PAGE 5 +#define TMEM_FLUSH_PAGE 6 +#define TMEM_FLUSH_OBJECT 7 +#define TMEM_POOL_PERSIST 1 +#define TMEM_POOL_SHARED 2 +#define TMEM_POOL_PRECOMPRESSED 4 +#define TMEM_POOL_PAGESIZE_SHIFT 4 +#define TMEM_POOL_PAGESIZE_MASK 0xf +#define TMEM_POOL_RESERVED_BITS 0x00ffff00 + +/* + * sentinels have proven very useful for debugging but can be removed + * or disabled before final merge. + */ +#define SENTINELS +#ifdef SENTINELS +#define DECL_SENTINEL uint32_t sentinel; +#define SET_SENTINEL(_x, _y) (_x->sentinel = _y##_SENTINEL) +#define INVERT_SENTINEL(_x, _y) (_x->sentinel = ~_y##_SENTINEL) +#define ASSERT_SENTINEL(_x, _y) WARN_ON(_x->sentinel != _y##_SENTINEL) +#define ASSERT_INVERTED_SENTINEL(_x, _y) WARN_ON(_x->sentinel != ~_y##_SENTINEL) +#else +#define DECL_SENTINEL +#define SET_SENTINEL(_x, _y) do { } while (0) +#define INVERT_SENTINEL(_x, _y) do { } while (0) +#define ASSERT_SENTINEL(_x, _y) do { } while (0) +#define ASSERT_INVERTED_SENTINEL(_x, _y) do { } while (0) +#endif + +#define ASSERT_SPINLOCK(_l) WARN_ON(!spin_is_locked(_l)) + +/* + * A pool is the highest-level data structure managed by tmem and + * usually corresponds to a large independent set of pages such as + * a filesystem. Each pool has an id, and certain attributes and counters. + * It also contains a set of hash buckets, each of which contains an rbtree + * of objects and a lock to manage concurrency within the pool. + */ + +#define TMEM_HASH_BUCKET_BITS 8 +#define TMEM_HASH_BUCKETS (1<persistent) +#define is_ephemeral(_p) (!(_p->persistent)) + +/* + * An object id ("oid") is large: 192-bits (to ensure, for example, files + * in a modern filesystem can be uniquely identified). + */ + +struct tmem_oid { + uint64_t oid[3]; +}; + +static inline void tmem_oid_set_invalid(struct tmem_oid *oidp) +{ + oidp->oid[0] = oidp->oid[1] = oidp->oid[2] = -1UL; +} + +static inline bool tmem_oid_valid(struct tmem_oid *oidp) +{ + return oidp->oid[0] != -1UL || oidp->oid[1] != -1UL || + oidp->oid[2] != -1UL; +} + +static inline int tmem_oid_compare(struct tmem_oid *left, + struct tmem_oid *right) +{ + int ret; + + if (left->oid[2] == right->oid[2]) { + if (left->oid[1] == right->oid[1]) { + if (left->oid[0] == right->oid[0]) + ret = 0; + else if (left->oid[0] < right->oid[0]) + ret = -1; + else + return 1; + } else if (left->oid[1] < right->oid[1]) + ret = -1; + else + ret = 1; + } else if (left->oid[2] < right->oid[2]) + ret = -1; + else + ret = 1; + return ret; +} + +static inline unsigned tmem_oid_hash(struct tmem_oid *oidp) +{ + return hash_long(oidp->oid[0] ^ oidp->oid[1] ^ oidp->oid[2], + TMEM_HASH_BUCKET_BITS); +} + +/* + * A tmem_obj contains an identifier (oid), pointers to the parent + * pool and the rb_tree to which it belongs, counters, and an ordered + * set of pampds, structured in a radix-tree-like tree. The intermediate + * nodes of the tree are called tmem_objnodes. + */ + +struct tmem_objnode; + +struct tmem_obj { + struct tmem_oid oid; + struct tmem_pool *pool; + struct rb_node rb_tree_node; + struct tmem_objnode *objnode_tree_root; + unsigned int objnode_tree_height; + unsigned long objnode_count; + long pampd_count; + void *extra; /* for private use by pampd implementation */ + DECL_SENTINEL +}; + +#define OBJNODE_TREE_MAP_SHIFT 6 +#define OBJNODE_TREE_MAP_SIZE (1UL << OBJNODE_TREE_MAP_SHIFT) +#define OBJNODE_TREE_MAP_MASK (OBJNODE_TREE_MAP_SIZE-1) +#define OBJNODE_TREE_INDEX_BITS (8 /* CHAR_BIT */ * sizeof(unsigned long)) +#define OBJNODE_TREE_MAX_PATH \ + (OBJNODE_TREE_INDEX_BITS/OBJNODE_TREE_MAP_SHIFT + 2) + +struct tmem_objnode { + struct tmem_obj *obj; + DECL_SENTINEL + void *slots[OBJNODE_TREE_MAP_SIZE]; + unsigned int slots_in_use; +}; + +/* pampd abstract datatype methods provided by the PAM implementation */ +struct tmem_pamops { + void *(*create)(char *, size_t, bool, int, + struct tmem_pool *, struct tmem_oid *, uint32_t); + int (*get_data)(char *, size_t *, bool, void *, struct tmem_pool *, + struct tmem_oid *, uint32_t); + int (*get_data_and_free)(char *, size_t *, bool, void *, + struct tmem_pool *, struct tmem_oid *, + uint32_t); + void (*free)(void *, struct tmem_pool *, struct tmem_oid *, uint32_t); + void (*free_obj)(struct tmem_pool *, struct tmem_obj *); + bool (*is_remote)(void *); + void (*new_obj)(struct tmem_obj *); + int (*replace_in_obj)(void *, struct tmem_obj *); +}; +extern void tmem_register_pamops(struct tmem_pamops *m); + +/* memory allocation methods provided by the host implementation */ +struct tmem_hostops { + struct tmem_obj *(*obj_alloc)(struct tmem_pool *); + void (*obj_free)(struct tmem_obj *, struct tmem_pool *); + struct tmem_objnode *(*objnode_alloc)(struct tmem_pool *); + void (*objnode_free)(struct tmem_objnode *, struct tmem_pool *); +}; +extern void tmem_register_hostops(struct tmem_hostops *m); + +/* core tmem accessor functions */ +extern int tmem_put(struct tmem_pool *, struct tmem_oid *, uint32_t index, + char *, size_t, bool, bool); +extern int tmem_get(struct tmem_pool *, struct tmem_oid *, uint32_t index, + char *, size_t *, bool, int); +extern int tmem_replace(struct tmem_pool *, struct tmem_oid *, uint32_t index, + void *); +extern int tmem_flush_page(struct tmem_pool *, struct tmem_oid *, + uint32_t index); +extern int tmem_flush_object(struct tmem_pool *, struct tmem_oid *); +extern int tmem_destroy_pool(struct tmem_pool *); +extern void tmem_new_pool(struct tmem_pool *, uint32_t); +#endif /* _TMEM_H */ diff --git a/drivers/staging/ramster/zcache-main.c b/drivers/staging/ramster/zcache-main.c new file mode 100644 index 0000000..49c8791 --- /dev/null +++ b/drivers/staging/ramster/zcache-main.c @@ -0,0 +1,1988 @@ +/* + * zcache.c + * + * Copyright (c) 2010,2011, Dan Magenheimer, Oracle Corp. + * Copyright (c) 2010,2011, Nitin Gupta + * + * Zcache provides an in-kernel "host implementation" for transcendent memory + * and, thus indirectly, for cleancache and frontswap. Zcache includes two + * page-accessible memory [1] interfaces, both utilizing lzo1x compression: + * 1) "compression buddies" ("zbud") is used for ephemeral pages + * 2) xvmalloc is used for persistent pages. + * Xvmalloc (based on the TLSF allocator) has very low fragmentation + * so maximizes space efficiency, while zbud allows pairs (and potentially, + * in the future, more than a pair of) compressed pages to be closely linked + * so that reclaiming can be done via the kernel's physical-page-oriented + * "shrinker" interface. + * + * [1] For a definition of page-accessible memory (aka PAM), see: + * http://marc.info/?l=linux-mm&m=127811271605009 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "tmem.h" + +#include "../zram/xvmalloc.h" /* if built in drivers/staging */ + +#if (!defined(CONFIG_CLEANCACHE) && !defined(CONFIG_FRONTSWAP)) +#error "zcache is useless without CONFIG_CLEANCACHE or CONFIG_FRONTSWAP" +#endif +#ifdef CONFIG_CLEANCACHE +#include +#endif +#ifdef CONFIG_FRONTSWAP +#include +#endif + +#if 0 +/* this is more aggressive but may cause other problems? */ +#define ZCACHE_GFP_MASK (GFP_ATOMIC | __GFP_NORETRY | __GFP_NOWARN) +#else +#define ZCACHE_GFP_MASK \ + (__GFP_FS | __GFP_NORETRY | __GFP_NOWARN | __GFP_NOMEMALLOC) +#endif + +#define MAX_POOLS_PER_CLIENT 16 + +#define MAX_CLIENTS 16 +#define LOCAL_CLIENT ((uint16_t)-1) + +MODULE_LICENSE("GPL"); + +struct zcache_client { + struct tmem_pool *tmem_pools[MAX_POOLS_PER_CLIENT]; + struct xv_pool *xvpool; + bool allocated; + atomic_t refcount; +}; + +static struct zcache_client zcache_host; +static struct zcache_client zcache_clients[MAX_CLIENTS]; + +static inline uint16_t get_client_id_from_client(struct zcache_client *cli) +{ + BUG_ON(cli == NULL); + if (cli == &zcache_host) + return LOCAL_CLIENT; + return cli - &zcache_clients[0]; +} + +static inline bool is_local_client(struct zcache_client *cli) +{ + return cli == &zcache_host; +} + +/********** + * Compression buddies ("zbud") provides for packing two (or, possibly + * in the future, more) compressed ephemeral pages into a single "raw" + * (physical) page and tracking them with data structures so that + * the raw pages can be easily reclaimed. + * + * A zbud page ("zbpg") is an aligned page containing a list_head, + * a lock, and two "zbud headers". The remainder of the physical + * page is divided up into aligned 64-byte "chunks" which contain + * the compressed data for zero, one, or two zbuds. Each zbpg + * resides on: (1) an "unused list" if it has no zbuds; (2) a + * "buddied" list if it is fully populated with two zbuds; or + * (3) one of PAGE_SIZE/64 "unbuddied" lists indexed by how many chunks + * the one unbuddied zbud uses. The data inside a zbpg cannot be + * read or written unless the zbpg's lock is held. + */ + +#define ZBH_SENTINEL 0x43214321 +#define ZBPG_SENTINEL 0xdeadbeef + +#define ZBUD_MAX_BUDS 2 + +struct zbud_hdr { + uint16_t client_id; + uint16_t pool_id; + struct tmem_oid oid; + uint32_t index; + uint16_t size; /* compressed size in bytes, zero means unused */ + DECL_SENTINEL +}; + +struct zbud_page { + struct list_head bud_list; + spinlock_t lock; + struct zbud_hdr buddy[ZBUD_MAX_BUDS]; + DECL_SENTINEL + /* followed by NUM_CHUNK aligned CHUNK_SIZE-byte chunks */ +}; + +#define CHUNK_SHIFT 6 +#define CHUNK_SIZE (1 << CHUNK_SHIFT) +#define CHUNK_MASK (~(CHUNK_SIZE-1)) +#define NCHUNKS (((PAGE_SIZE - sizeof(struct zbud_page)) & \ + CHUNK_MASK) >> CHUNK_SHIFT) +#define MAX_CHUNK (NCHUNKS-1) + +static struct { + struct list_head list; + unsigned count; +} zbud_unbuddied[NCHUNKS]; +/* list N contains pages with N chunks USED and NCHUNKS-N unused */ +/* element 0 is never used but optimizing that isn't worth it */ +static unsigned long zbud_cumul_chunk_counts[NCHUNKS]; + +struct list_head zbud_buddied_list; +static unsigned long zcache_zbud_buddied_count; + +/* protects the buddied list and all unbuddied lists */ +static DEFINE_SPINLOCK(zbud_budlists_spinlock); + +static LIST_HEAD(zbpg_unused_list); +static unsigned long zcache_zbpg_unused_list_count; + +/* protects the unused page list */ +static DEFINE_SPINLOCK(zbpg_unused_list_spinlock); + +static atomic_t zcache_zbud_curr_raw_pages; +static atomic_t zcache_zbud_curr_zpages; +static unsigned long zcache_zbud_curr_zbytes; +static unsigned long zcache_zbud_cumul_zpages; +static unsigned long zcache_zbud_cumul_zbytes; +static unsigned long zcache_compress_poor; +static unsigned long zcache_mean_compress_poor; + +/* forward references */ +static void *zcache_get_free_page(void); +static void zcache_free_page(void *p); + +/* + * zbud helper functions + */ + +static inline unsigned zbud_max_buddy_size(void) +{ + return MAX_CHUNK << CHUNK_SHIFT; +} + +static inline unsigned zbud_size_to_chunks(unsigned size) +{ + BUG_ON(size == 0 || size > zbud_max_buddy_size()); + return (size + CHUNK_SIZE - 1) >> CHUNK_SHIFT; +} + +static inline int zbud_budnum(struct zbud_hdr *zh) +{ + unsigned offset = (unsigned long)zh & (PAGE_SIZE - 1); + struct zbud_page *zbpg = NULL; + unsigned budnum = -1U; + int i; + + for (i = 0; i < ZBUD_MAX_BUDS; i++) + if (offset == offsetof(typeof(*zbpg), buddy[i])) { + budnum = i; + break; + } + BUG_ON(budnum == -1U); + return budnum; +} + +static char *zbud_data(struct zbud_hdr *zh, unsigned size) +{ + struct zbud_page *zbpg; + char *p; + unsigned budnum; + + ASSERT_SENTINEL(zh, ZBH); + budnum = zbud_budnum(zh); + BUG_ON(size == 0 || size > zbud_max_buddy_size()); + zbpg = container_of(zh, struct zbud_page, buddy[budnum]); + ASSERT_SPINLOCK(&zbpg->lock); + p = (char *)zbpg; + if (budnum == 0) + p += ((sizeof(struct zbud_page) + CHUNK_SIZE - 1) & + CHUNK_MASK); + else if (budnum == 1) + p += PAGE_SIZE - ((size + CHUNK_SIZE - 1) & CHUNK_MASK); + return p; +} + +/* + * zbud raw page management + */ + +static struct zbud_page *zbud_alloc_raw_page(void) +{ + struct zbud_page *zbpg = NULL; + struct zbud_hdr *zh0, *zh1; + bool recycled = 0; + + /* if any pages on the zbpg list, use one */ + spin_lock(&zbpg_unused_list_spinlock); + if (!list_empty(&zbpg_unused_list)) { + zbpg = list_first_entry(&zbpg_unused_list, + struct zbud_page, bud_list); + list_del_init(&zbpg->bud_list); + zcache_zbpg_unused_list_count--; + recycled = 1; + } + spin_unlock(&zbpg_unused_list_spinlock); + if (zbpg == NULL) + /* none on zbpg list, try to get a kernel page */ + zbpg = zcache_get_free_page(); + if (likely(zbpg != NULL)) { + INIT_LIST_HEAD(&zbpg->bud_list); + zh0 = &zbpg->buddy[0]; zh1 = &zbpg->buddy[1]; + spin_lock_init(&zbpg->lock); + if (recycled) { + ASSERT_INVERTED_SENTINEL(zbpg, ZBPG); + SET_SENTINEL(zbpg, ZBPG); + BUG_ON(zh0->size != 0 || tmem_oid_valid(&zh0->oid)); + BUG_ON(zh1->size != 0 || tmem_oid_valid(&zh1->oid)); + } else { + atomic_inc(&zcache_zbud_curr_raw_pages); + INIT_LIST_HEAD(&zbpg->bud_list); + SET_SENTINEL(zbpg, ZBPG); + zh0->size = 0; zh1->size = 0; + tmem_oid_set_invalid(&zh0->oid); + tmem_oid_set_invalid(&zh1->oid); + } + } + return zbpg; +} + +static void zbud_free_raw_page(struct zbud_page *zbpg) +{ + struct zbud_hdr *zh0 = &zbpg->buddy[0], *zh1 = &zbpg->buddy[1]; + + ASSERT_SENTINEL(zbpg, ZBPG); + BUG_ON(!list_empty(&zbpg->bud_list)); + ASSERT_SPINLOCK(&zbpg->lock); + BUG_ON(zh0->size != 0 || tmem_oid_valid(&zh0->oid)); + BUG_ON(zh1->size != 0 || tmem_oid_valid(&zh1->oid)); + INVERT_SENTINEL(zbpg, ZBPG); + spin_unlock(&zbpg->lock); + spin_lock(&zbpg_unused_list_spinlock); + list_add(&zbpg->bud_list, &zbpg_unused_list); + zcache_zbpg_unused_list_count++; + spin_unlock(&zbpg_unused_list_spinlock); +} + +/* + * core zbud handling routines + */ + +static unsigned zbud_free(struct zbud_hdr *zh) +{ + unsigned size; + + ASSERT_SENTINEL(zh, ZBH); + BUG_ON(!tmem_oid_valid(&zh->oid)); + size = zh->size; + BUG_ON(zh->size == 0 || zh->size > zbud_max_buddy_size()); + zh->size = 0; + tmem_oid_set_invalid(&zh->oid); + INVERT_SENTINEL(zh, ZBH); + zcache_zbud_curr_zbytes -= size; + atomic_dec(&zcache_zbud_curr_zpages); + return size; +} + +static void zbud_free_and_delist(struct zbud_hdr *zh) +{ + unsigned chunks; + struct zbud_hdr *zh_other; + unsigned budnum = zbud_budnum(zh), size; + struct zbud_page *zbpg = + container_of(zh, struct zbud_page, buddy[budnum]); + + spin_lock(&zbpg->lock); + if (list_empty(&zbpg->bud_list)) { + /* ignore zombie page... see zbud_evict_pages() */ + spin_unlock(&zbpg->lock); + return; + } + size = zbud_free(zh); + ASSERT_SPINLOCK(&zbpg->lock); + zh_other = &zbpg->buddy[(budnum == 0) ? 1 : 0]; + if (zh_other->size == 0) { /* was unbuddied: unlist and free */ + chunks = zbud_size_to_chunks(size) ; + spin_lock(&zbud_budlists_spinlock); + BUG_ON(list_empty(&zbud_unbuddied[chunks].list)); + list_del_init(&zbpg->bud_list); + zbud_unbuddied[chunks].count--; + spin_unlock(&zbud_budlists_spinlock); + zbud_free_raw_page(zbpg); + } else { /* was buddied: move remaining buddy to unbuddied list */ + chunks = zbud_size_to_chunks(zh_other->size) ; + spin_lock(&zbud_budlists_spinlock); + list_del_init(&zbpg->bud_list); + zcache_zbud_buddied_count--; + list_add_tail(&zbpg->bud_list, &zbud_unbuddied[chunks].list); + zbud_unbuddied[chunks].count++; + spin_unlock(&zbud_budlists_spinlock); + spin_unlock(&zbpg->lock); + } +} + +static struct zbud_hdr *zbud_create(uint16_t client_id, uint16_t pool_id, + struct tmem_oid *oid, + uint32_t index, struct page *page, + void *cdata, unsigned size) +{ + struct zbud_hdr *zh0, *zh1, *zh = NULL; + struct zbud_page *zbpg = NULL, *ztmp; + unsigned nchunks; + char *to; + int i, found_good_buddy = 0; + + nchunks = zbud_size_to_chunks(size) ; + for (i = MAX_CHUNK - nchunks + 1; i > 0; i--) { + spin_lock(&zbud_budlists_spinlock); + if (!list_empty(&zbud_unbuddied[i].list)) { + list_for_each_entry_safe(zbpg, ztmp, + &zbud_unbuddied[i].list, bud_list) { + if (spin_trylock(&zbpg->lock)) { + found_good_buddy = i; + goto found_unbuddied; + } + } + } + spin_unlock(&zbud_budlists_spinlock); + } + /* didn't find a good buddy, try allocating a new page */ + zbpg = zbud_alloc_raw_page(); + if (unlikely(zbpg == NULL)) + goto out; + /* ok, have a page, now compress the data before taking locks */ + spin_lock(&zbpg->lock); + spin_lock(&zbud_budlists_spinlock); + list_add_tail(&zbpg->bud_list, &zbud_unbuddied[nchunks].list); + zbud_unbuddied[nchunks].count++; + zh = &zbpg->buddy[0]; + goto init_zh; + +found_unbuddied: + ASSERT_SPINLOCK(&zbpg->lock); + zh0 = &zbpg->buddy[0]; zh1 = &zbpg->buddy[1]; + BUG_ON(!((zh0->size == 0) ^ (zh1->size == 0))); + if (zh0->size != 0) { /* buddy0 in use, buddy1 is vacant */ + ASSERT_SENTINEL(zh0, ZBH); + zh = zh1; + } else if (zh1->size != 0) { /* buddy1 in use, buddy0 is vacant */ + ASSERT_SENTINEL(zh1, ZBH); + zh = zh0; + } else + BUG(); + list_del_init(&zbpg->bud_list); + zbud_unbuddied[found_good_buddy].count--; + list_add_tail(&zbpg->bud_list, &zbud_buddied_list); + zcache_zbud_buddied_count++; + +init_zh: + SET_SENTINEL(zh, ZBH); + zh->size = size; + zh->index = index; + zh->oid = *oid; + zh->pool_id = pool_id; + zh->client_id = client_id; + /* can wait to copy the data until the list locks are dropped */ + spin_unlock(&zbud_budlists_spinlock); + + to = zbud_data(zh, size); + memcpy(to, cdata, size); + spin_unlock(&zbpg->lock); + zbud_cumul_chunk_counts[nchunks]++; + atomic_inc(&zcache_zbud_curr_zpages); + zcache_zbud_cumul_zpages++; + zcache_zbud_curr_zbytes += size; + zcache_zbud_cumul_zbytes += size; +out: + return zh; +} + +static int zbud_decompress(struct page *page, struct zbud_hdr *zh) +{ + struct zbud_page *zbpg; + unsigned budnum = zbud_budnum(zh); + size_t out_len = PAGE_SIZE; + char *to_va, *from_va; + unsigned size; + int ret = 0; + + zbpg = container_of(zh, struct zbud_page, buddy[budnum]); + spin_lock(&zbpg->lock); + if (list_empty(&zbpg->bud_list)) { + /* ignore zombie page... see zbud_evict_pages() */ + ret = -EINVAL; + goto out; + } + ASSERT_SENTINEL(zh, ZBH); + BUG_ON(zh->size == 0 || zh->size > zbud_max_buddy_size()); + to_va = kmap_atomic(page, KM_USER0); + size = zh->size; + from_va = zbud_data(zh, size); + ret = lzo1x_decompress_safe(from_va, size, to_va, &out_len); + BUG_ON(ret != LZO_E_OK); + BUG_ON(out_len != PAGE_SIZE); + kunmap_atomic(to_va, KM_USER0); +out: + spin_unlock(&zbpg->lock); + return ret; +} + +/* + * The following routines handle shrinking of ephemeral pages by evicting + * pages "least valuable" first. + */ + +static unsigned long zcache_evicted_raw_pages; +static unsigned long zcache_evicted_buddied_pages; +static unsigned long zcache_evicted_unbuddied_pages; + +static struct tmem_pool *zcache_get_pool_by_id(uint16_t cli_id, + uint16_t poolid); +static void zcache_put_pool(struct tmem_pool *pool); + +/* + * Flush and free all zbuds in a zbpg, then free the pageframe + */ +static void zbud_evict_zbpg(struct zbud_page *zbpg) +{ + struct zbud_hdr *zh; + int i, j; + uint32_t pool_id[ZBUD_MAX_BUDS], client_id[ZBUD_MAX_BUDS]; + uint32_t index[ZBUD_MAX_BUDS]; + struct tmem_oid oid[ZBUD_MAX_BUDS]; + struct tmem_pool *pool; + + ASSERT_SPINLOCK(&zbpg->lock); + BUG_ON(!list_empty(&zbpg->bud_list)); + for (i = 0, j = 0; i < ZBUD_MAX_BUDS; i++) { + zh = &zbpg->buddy[i]; + if (zh->size) { + client_id[j] = zh->client_id; + pool_id[j] = zh->pool_id; + oid[j] = zh->oid; + index[j] = zh->index; + j++; + zbud_free(zh); + } + } + spin_unlock(&zbpg->lock); + for (i = 0; i < j; i++) { + pool = zcache_get_pool_by_id(client_id[i], pool_id[i]); + if (pool != NULL) { + tmem_flush_page(pool, &oid[i], index[i]); + zcache_put_pool(pool); + } + } + ASSERT_SENTINEL(zbpg, ZBPG); + spin_lock(&zbpg->lock); + zbud_free_raw_page(zbpg); +} + +/* + * Free nr pages. This code is funky because we want to hold the locks + * protecting various lists for as short a time as possible, and in some + * circumstances the list may change asynchronously when the list lock is + * not held. In some cases we also trylock not only to avoid waiting on a + * page in use by another cpu, but also to avoid potential deadlock due to + * lock inversion. + */ +static void zbud_evict_pages(int nr) +{ + struct zbud_page *zbpg; + int i; + + /* first try freeing any pages on unused list */ +retry_unused_list: + spin_lock_bh(&zbpg_unused_list_spinlock); + if (!list_empty(&zbpg_unused_list)) { + /* can't walk list here, since it may change when unlocked */ + zbpg = list_first_entry(&zbpg_unused_list, + struct zbud_page, bud_list); + list_del_init(&zbpg->bud_list); + zcache_zbpg_unused_list_count--; + atomic_dec(&zcache_zbud_curr_raw_pages); + spin_unlock_bh(&zbpg_unused_list_spinlock); + zcache_free_page(zbpg); + zcache_evicted_raw_pages++; + if (--nr <= 0) + goto out; + goto retry_unused_list; + } + spin_unlock_bh(&zbpg_unused_list_spinlock); + + /* now try freeing unbuddied pages, starting with least space avail */ + for (i = 0; i < MAX_CHUNK; i++) { +retry_unbud_list_i: + spin_lock_bh(&zbud_budlists_spinlock); + if (list_empty(&zbud_unbuddied[i].list)) { + spin_unlock_bh(&zbud_budlists_spinlock); + continue; + } + list_for_each_entry(zbpg, &zbud_unbuddied[i].list, bud_list) { + if (unlikely(!spin_trylock(&zbpg->lock))) + continue; + list_del_init(&zbpg->bud_list); + zbud_unbuddied[i].count--; + spin_unlock(&zbud_budlists_spinlock); + zcache_evicted_unbuddied_pages++; + /* want budlists unlocked when doing zbpg eviction */ + zbud_evict_zbpg(zbpg); + local_bh_enable(); + if (--nr <= 0) + goto out; + goto retry_unbud_list_i; + } + spin_unlock_bh(&zbud_budlists_spinlock); + } + + /* as a last resort, free buddied pages */ +retry_bud_list: + spin_lock_bh(&zbud_budlists_spinlock); + if (list_empty(&zbud_buddied_list)) { + spin_unlock_bh(&zbud_budlists_spinlock); + goto out; + } + list_for_each_entry(zbpg, &zbud_buddied_list, bud_list) { + if (unlikely(!spin_trylock(&zbpg->lock))) + continue; + list_del_init(&zbpg->bud_list); + zcache_zbud_buddied_count--; + spin_unlock(&zbud_budlists_spinlock); + zcache_evicted_buddied_pages++; + /* want budlists unlocked when doing zbpg eviction */ + zbud_evict_zbpg(zbpg); + local_bh_enable(); + if (--nr <= 0) + goto out; + goto retry_bud_list; + } + spin_unlock_bh(&zbud_budlists_spinlock); +out: + return; +} + +static void zbud_init(void) +{ + int i; + + INIT_LIST_HEAD(&zbud_buddied_list); + zcache_zbud_buddied_count = 0; + for (i = 0; i < NCHUNKS; i++) { + INIT_LIST_HEAD(&zbud_unbuddied[i].list); + zbud_unbuddied[i].count = 0; + } +} + +#ifdef CONFIG_SYSFS +/* + * These sysfs routines show a nice distribution of how many zbpg's are + * currently (and have ever been placed) in each unbuddied list. It's fun + * to watch but can probably go away before final merge. + */ +static int zbud_show_unbuddied_list_counts(char *buf) +{ + int i; + char *p = buf; + + for (i = 0; i < NCHUNKS; i++) + p += sprintf(p, "%u ", zbud_unbuddied[i].count); + return p - buf; +} + +static int zbud_show_cumul_chunk_counts(char *buf) +{ + unsigned long i, chunks = 0, total_chunks = 0, sum_total_chunks = 0; + unsigned long total_chunks_lte_21 = 0, total_chunks_lte_32 = 0; + unsigned long total_chunks_lte_42 = 0; + char *p = buf; + + for (i = 0; i < NCHUNKS; i++) { + p += sprintf(p, "%lu ", zbud_cumul_chunk_counts[i]); + chunks += zbud_cumul_chunk_counts[i]; + total_chunks += zbud_cumul_chunk_counts[i]; + sum_total_chunks += i * zbud_cumul_chunk_counts[i]; + if (i == 21) + total_chunks_lte_21 = total_chunks; + if (i == 32) + total_chunks_lte_32 = total_chunks; + if (i == 42) + total_chunks_lte_42 = total_chunks; + } + p += sprintf(p, "<=21:%lu <=32:%lu <=42:%lu, mean:%lu\n", + total_chunks_lte_21, total_chunks_lte_32, total_chunks_lte_42, + chunks == 0 ? 0 : sum_total_chunks / chunks); + return p - buf; +} +#endif + +/********** + * This "zv" PAM implementation combines the TLSF-based xvMalloc + * with lzo1x compression to maximize the amount of data that can + * be packed into a physical page. + * + * Zv represents a PAM page with the index and object (plus a "size" value + * necessary for decompression) immediately preceding the compressed data. + */ + +#define ZVH_SENTINEL 0x43214321 + +struct zv_hdr { + uint32_t pool_id; + struct tmem_oid oid; + uint32_t index; + DECL_SENTINEL +}; + +/* rudimentary policy limits */ +/* total number of persistent pages may not exceed this percentage */ +static unsigned int zv_page_count_policy_percent = 75; +/* + * byte count defining poor compression; pages with greater zsize will be + * rejected + */ +static unsigned int zv_max_zsize = (PAGE_SIZE / 8) * 7; +/* + * byte count defining poor *mean* compression; pages with greater zsize + * will be rejected until sufficient better-compressed pages are accepted + * driving the mean below this threshold + */ +static unsigned int zv_max_mean_zsize = (PAGE_SIZE / 8) * 5; + +static unsigned long zv_curr_dist_counts[NCHUNKS]; +static unsigned long zv_cumul_dist_counts[NCHUNKS]; + +static struct zv_hdr *zv_create(struct xv_pool *xvpool, uint32_t pool_id, + struct tmem_oid *oid, uint32_t index, + void *cdata, unsigned clen) +{ + struct page *page; + struct zv_hdr *zv = NULL; + uint32_t offset; + int alloc_size = clen + sizeof(struct zv_hdr); + int chunks = (alloc_size + (CHUNK_SIZE - 1)) >> CHUNK_SHIFT; + int ret; + + BUG_ON(!irqs_disabled()); + BUG_ON(chunks >= NCHUNKS); + ret = xv_malloc(xvpool, alloc_size, + &page, &offset, ZCACHE_GFP_MASK); + if (unlikely(ret)) + goto out; + zv_curr_dist_counts[chunks]++; + zv_cumul_dist_counts[chunks]++; + zv = kmap_atomic(page, KM_USER0) + offset; + zv->index = index; + zv->oid = *oid; + zv->pool_id = pool_id; + SET_SENTINEL(zv, ZVH); + memcpy((char *)zv + sizeof(struct zv_hdr), cdata, clen); + kunmap_atomic(zv, KM_USER0); +out: + return zv; +} + +static void zv_free(struct xv_pool *xvpool, struct zv_hdr *zv) +{ + unsigned long flags; + struct page *page; + uint32_t offset; + uint16_t size = xv_get_object_size(zv); + int chunks = (size + (CHUNK_SIZE - 1)) >> CHUNK_SHIFT; + + ASSERT_SENTINEL(zv, ZVH); + BUG_ON(chunks >= NCHUNKS); + zv_curr_dist_counts[chunks]--; + size -= sizeof(*zv); + BUG_ON(size == 0); + INVERT_SENTINEL(zv, ZVH); + page = virt_to_page(zv); + offset = (unsigned long)zv & ~PAGE_MASK; + local_irq_save(flags); + xv_free(xvpool, page, offset); + local_irq_restore(flags); +} + +static void zv_decompress(struct page *page, struct zv_hdr *zv) +{ + size_t clen = PAGE_SIZE; + char *to_va; + unsigned size; + int ret; + + ASSERT_SENTINEL(zv, ZVH); + size = xv_get_object_size(zv) - sizeof(*zv); + BUG_ON(size == 0); + to_va = kmap_atomic(page, KM_USER0); + ret = lzo1x_decompress_safe((char *)zv + sizeof(*zv), + size, to_va, &clen); + kunmap_atomic(to_va, KM_USER0); + BUG_ON(ret != LZO_E_OK); + BUG_ON(clen != PAGE_SIZE); +} + +#ifdef CONFIG_SYSFS +/* + * show a distribution of compression stats for zv pages. + */ + +static int zv_curr_dist_counts_show(char *buf) +{ + unsigned long i, n, chunks = 0, sum_total_chunks = 0; + char *p = buf; + + for (i = 0; i < NCHUNKS; i++) { + n = zv_curr_dist_counts[i]; + p += sprintf(p, "%lu ", n); + chunks += n; + sum_total_chunks += i * n; + } + p += sprintf(p, "mean:%lu\n", + chunks == 0 ? 0 : sum_total_chunks / chunks); + return p - buf; +} + +static int zv_cumul_dist_counts_show(char *buf) +{ + unsigned long i, n, chunks = 0, sum_total_chunks = 0; + char *p = buf; + + for (i = 0; i < NCHUNKS; i++) { + n = zv_cumul_dist_counts[i]; + p += sprintf(p, "%lu ", n); + chunks += n; + sum_total_chunks += i * n; + } + p += sprintf(p, "mean:%lu\n", + chunks == 0 ? 0 : sum_total_chunks / chunks); + return p - buf; +} + +/* + * setting zv_max_zsize via sysfs causes all persistent (e.g. swap) + * pages that don't compress to less than this value (including metadata + * overhead) to be rejected. We don't allow the value to get too close + * to PAGE_SIZE. + */ +static ssize_t zv_max_zsize_show(struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) +{ + return sprintf(buf, "%u\n", zv_max_zsize); +} + +static ssize_t zv_max_zsize_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t count) +{ + unsigned long val; + int err; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + err = strict_strtoul(buf, 10, &val); + if (err || (val == 0) || (val > (PAGE_SIZE / 8) * 7)) + return -EINVAL; + zv_max_zsize = val; + return count; +} + +/* + * setting zv_max_mean_zsize via sysfs causes all persistent (e.g. swap) + * pages that don't compress to less than this value (including metadata + * overhead) to be rejected UNLESS the mean compression is also smaller + * than this value. In other words, we are load-balancing-by-zsize the + * accepted pages. Again, we don't allow the value to get too close + * to PAGE_SIZE. + */ +static ssize_t zv_max_mean_zsize_show(struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) +{ + return sprintf(buf, "%u\n", zv_max_mean_zsize); +} + +static ssize_t zv_max_mean_zsize_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t count) +{ + unsigned long val; + int err; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + err = strict_strtoul(buf, 10, &val); + if (err || (val == 0) || (val > (PAGE_SIZE / 8) * 7)) + return -EINVAL; + zv_max_mean_zsize = val; + return count; +} + +/* + * setting zv_page_count_policy_percent via sysfs sets an upper bound of + * persistent (e.g. swap) pages that will be retained according to: + * (zv_page_count_policy_percent * totalram_pages) / 100) + * when that limit is reached, further puts will be rejected (until + * some pages have been flushed). Note that, due to compression, + * this number may exceed 100; it defaults to 75 and we set an + * arbitary limit of 150. A poor choice will almost certainly result + * in OOM's, so this value should only be changed prudently. + */ +static ssize_t zv_page_count_policy_percent_show(struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) +{ + return sprintf(buf, "%u\n", zv_page_count_policy_percent); +} + +static ssize_t zv_page_count_policy_percent_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t count) +{ + unsigned long val; + int err; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + err = strict_strtoul(buf, 10, &val); + if (err || (val == 0) || (val > 150)) + return -EINVAL; + zv_page_count_policy_percent = val; + return count; +} + +static struct kobj_attribute zcache_zv_max_zsize_attr = { + .attr = { .name = "zv_max_zsize", .mode = 0644 }, + .show = zv_max_zsize_show, + .store = zv_max_zsize_store, +}; + +static struct kobj_attribute zcache_zv_max_mean_zsize_attr = { + .attr = { .name = "zv_max_mean_zsize", .mode = 0644 }, + .show = zv_max_mean_zsize_show, + .store = zv_max_mean_zsize_store, +}; + +static struct kobj_attribute zcache_zv_page_count_policy_percent_attr = { + .attr = { .name = "zv_page_count_policy_percent", + .mode = 0644 }, + .show = zv_page_count_policy_percent_show, + .store = zv_page_count_policy_percent_store, +}; +#endif + +/* + * zcache core code starts here + */ + +/* useful stats not collected by cleancache or frontswap */ +static unsigned long zcache_flush_total; +static unsigned long zcache_flush_found; +static unsigned long zcache_flobj_total; +static unsigned long zcache_flobj_found; +static unsigned long zcache_failed_eph_puts; +static unsigned long zcache_failed_pers_puts; + +/* + * Tmem operations assume the poolid implies the invoking client. + * Zcache only has one client (the kernel itself): LOCAL_CLIENT. + * RAMster has each client numbered by cluster node, and a KVM version + * of zcache would have one client per guest and each client might + * have a poolid==N. + */ +static struct tmem_pool *zcache_get_pool_by_id(uint16_t cli_id, uint16_t poolid) +{ + struct tmem_pool *pool = NULL; + struct zcache_client *cli = NULL; + + if (cli_id == LOCAL_CLIENT) + cli = &zcache_host; + else { + if (cli_id >= MAX_CLIENTS) + goto out; + cli = &zcache_clients[cli_id]; + if (cli == NULL) + goto out; + atomic_inc(&cli->refcount); + } + if (poolid < MAX_POOLS_PER_CLIENT) { + pool = cli->tmem_pools[poolid]; + if (pool != NULL) + atomic_inc(&pool->refcount); + } +out: + return pool; +} + +static void zcache_put_pool(struct tmem_pool *pool) +{ + struct zcache_client *cli = NULL; + + if (pool == NULL) + BUG(); + cli = pool->client; + atomic_dec(&pool->refcount); + atomic_dec(&cli->refcount); +} + +int zcache_new_client(uint16_t cli_id) +{ + struct zcache_client *cli = NULL; + int ret = -1; + + if (cli_id == LOCAL_CLIENT) + cli = &zcache_host; + else if ((unsigned int)cli_id < MAX_CLIENTS) + cli = &zcache_clients[cli_id]; + if (cli == NULL) + goto out; + if (cli->allocated) + goto out; + cli->allocated = 1; +#ifdef CONFIG_FRONTSWAP + cli->xvpool = xv_create_pool(); + if (cli->xvpool == NULL) + goto out; +#endif + ret = 0; +out: + return ret; +} + +/* counters for debugging */ +static unsigned long zcache_failed_get_free_pages; +static unsigned long zcache_failed_alloc; +static unsigned long zcache_put_to_flush; + +/* + * for now, used named slabs so can easily track usage; later can + * either just use kmalloc, or perhaps add a slab-like allocator + * to more carefully manage total memory utilization + */ +static struct kmem_cache *zcache_objnode_cache; +static struct kmem_cache *zcache_obj_cache; +static atomic_t zcache_curr_obj_count = ATOMIC_INIT(0); +static unsigned long zcache_curr_obj_count_max; +static atomic_t zcache_curr_objnode_count = ATOMIC_INIT(0); +static unsigned long zcache_curr_objnode_count_max; + +/* + * to avoid memory allocation recursion (e.g. due to direct reclaim), we + * preload all necessary data structures so the hostops callbacks never + * actually do a malloc + */ +struct zcache_preload { + void *page; + struct tmem_obj *obj; + int nr; + struct tmem_objnode *objnodes[OBJNODE_TREE_MAX_PATH]; +}; +static DEFINE_PER_CPU(struct zcache_preload, zcache_preloads) = { 0, }; + +static int zcache_do_preload(struct tmem_pool *pool) +{ + struct zcache_preload *kp; + struct tmem_objnode *objnode; + struct tmem_obj *obj; + void *page; + int ret = -ENOMEM; + + if (unlikely(zcache_objnode_cache == NULL)) + goto out; + if (unlikely(zcache_obj_cache == NULL)) + goto out; + preempt_disable(); + kp = &__get_cpu_var(zcache_preloads); + while (kp->nr < ARRAY_SIZE(kp->objnodes)) { + preempt_enable_no_resched(); + objnode = kmem_cache_alloc(zcache_objnode_cache, + ZCACHE_GFP_MASK); + if (unlikely(objnode == NULL)) { + zcache_failed_alloc++; + goto out; + } + preempt_disable(); + kp = &__get_cpu_var(zcache_preloads); + if (kp->nr < ARRAY_SIZE(kp->objnodes)) + kp->objnodes[kp->nr++] = objnode; + else + kmem_cache_free(zcache_objnode_cache, objnode); + } + preempt_enable_no_resched(); + obj = kmem_cache_alloc(zcache_obj_cache, ZCACHE_GFP_MASK); + if (unlikely(obj == NULL)) { + zcache_failed_alloc++; + goto out; + } + page = (void *)__get_free_page(ZCACHE_GFP_MASK); + if (unlikely(page == NULL)) { + zcache_failed_get_free_pages++; + kmem_cache_free(zcache_obj_cache, obj); + goto out; + } + preempt_disable(); + kp = &__get_cpu_var(zcache_preloads); + if (kp->obj == NULL) + kp->obj = obj; + else + kmem_cache_free(zcache_obj_cache, obj); + if (kp->page == NULL) + kp->page = page; + else + free_page((unsigned long)page); + ret = 0; +out: + return ret; +} + +static void *zcache_get_free_page(void) +{ + struct zcache_preload *kp; + void *page; + + kp = &__get_cpu_var(zcache_preloads); + page = kp->page; + BUG_ON(page == NULL); + kp->page = NULL; + return page; +} + +static void zcache_free_page(void *p) +{ + free_page((unsigned long)p); +} + +/* + * zcache implementation for tmem host ops + */ + +static struct tmem_objnode *zcache_objnode_alloc(struct tmem_pool *pool) +{ + struct tmem_objnode *objnode = NULL; + unsigned long count; + struct zcache_preload *kp; + + kp = &__get_cpu_var(zcache_preloads); + if (kp->nr <= 0) + goto out; + objnode = kp->objnodes[kp->nr - 1]; + BUG_ON(objnode == NULL); + kp->objnodes[kp->nr - 1] = NULL; + kp->nr--; + count = atomic_inc_return(&zcache_curr_objnode_count); + if (count > zcache_curr_objnode_count_max) + zcache_curr_objnode_count_max = count; +out: + return objnode; +} + +static void zcache_objnode_free(struct tmem_objnode *objnode, + struct tmem_pool *pool) +{ + atomic_dec(&zcache_curr_objnode_count); + BUG_ON(atomic_read(&zcache_curr_objnode_count) < 0); + kmem_cache_free(zcache_objnode_cache, objnode); +} + +static struct tmem_obj *zcache_obj_alloc(struct tmem_pool *pool) +{ + struct tmem_obj *obj = NULL; + unsigned long count; + struct zcache_preload *kp; + + kp = &__get_cpu_var(zcache_preloads); + obj = kp->obj; + BUG_ON(obj == NULL); + kp->obj = NULL; + count = atomic_inc_return(&zcache_curr_obj_count); + if (count > zcache_curr_obj_count_max) + zcache_curr_obj_count_max = count; + return obj; +} + +static void zcache_obj_free(struct tmem_obj *obj, struct tmem_pool *pool) +{ + atomic_dec(&zcache_curr_obj_count); + BUG_ON(atomic_read(&zcache_curr_obj_count) < 0); + kmem_cache_free(zcache_obj_cache, obj); +} + +static struct tmem_hostops zcache_hostops = { + .obj_alloc = zcache_obj_alloc, + .obj_free = zcache_obj_free, + .objnode_alloc = zcache_objnode_alloc, + .objnode_free = zcache_objnode_free, +}; + +/* + * zcache implementations for PAM page descriptor ops + */ + +static atomic_t zcache_curr_eph_pampd_count = ATOMIC_INIT(0); +static unsigned long zcache_curr_eph_pampd_count_max; +static atomic_t zcache_curr_pers_pampd_count = ATOMIC_INIT(0); +static unsigned long zcache_curr_pers_pampd_count_max; + +/* forward reference */ +static int zcache_compress(struct page *from, void **out_va, size_t *out_len); + +static void *zcache_pampd_create(char *data, size_t size, bool raw, int eph, + struct tmem_pool *pool, struct tmem_oid *oid, + uint32_t index) +{ + void *pampd = NULL, *cdata; + size_t clen; + int ret; + unsigned long count; + struct page *page = (struct page *)(data); + struct zcache_client *cli = pool->client; + uint16_t client_id = get_client_id_from_client(cli); + unsigned long zv_mean_zsize; + unsigned long curr_pers_pampd_count; + u64 total_zsize; + + if (eph) { + ret = zcache_compress(page, &cdata, &clen); + if (ret == 0) + goto out; + if (clen == 0 || clen > zbud_max_buddy_size()) { + zcache_compress_poor++; + goto out; + } + pampd = (void *)zbud_create(client_id, pool->pool_id, oid, + index, page, cdata, clen); + if (pampd != NULL) { + count = atomic_inc_return(&zcache_curr_eph_pampd_count); + if (count > zcache_curr_eph_pampd_count_max) + zcache_curr_eph_pampd_count_max = count; + } + } else { + curr_pers_pampd_count = + atomic_read(&zcache_curr_pers_pampd_count); + if (curr_pers_pampd_count > + (zv_page_count_policy_percent * totalram_pages) / 100) + goto out; + ret = zcache_compress(page, &cdata, &clen); + if (ret == 0) + goto out; + /* reject if compression is too poor */ + if (clen > zv_max_zsize) { + zcache_compress_poor++; + goto out; + } + /* reject if mean compression is too poor */ + if ((clen > zv_max_mean_zsize) && (curr_pers_pampd_count > 0)) { + total_zsize = xv_get_total_size_bytes(cli->xvpool); + zv_mean_zsize = div_u64(total_zsize, + curr_pers_pampd_count); + if (zv_mean_zsize > zv_max_mean_zsize) { + zcache_mean_compress_poor++; + goto out; + } + } + pampd = (void *)zv_create(cli->xvpool, pool->pool_id, + oid, index, cdata, clen); + if (pampd == NULL) + goto out; + count = atomic_inc_return(&zcache_curr_pers_pampd_count); + if (count > zcache_curr_pers_pampd_count_max) + zcache_curr_pers_pampd_count_max = count; + } +out: + return pampd; +} + +/* + * fill the pageframe corresponding to the struct page with the data + * from the passed pampd + */ +static int zcache_pampd_get_data(char *data, size_t *bufsize, bool raw, + void *pampd, struct tmem_pool *pool, + struct tmem_oid *oid, uint32_t index) +{ + int ret = 0; + + BUG_ON(is_ephemeral(pool)); + zv_decompress((struct page *)(data), pampd); + return ret; +} + +/* + * fill the pageframe corresponding to the struct page with the data + * from the passed pampd + */ +static int zcache_pampd_get_data_and_free(char *data, size_t *bufsize, bool raw, + void *pampd, struct tmem_pool *pool, + struct tmem_oid *oid, uint32_t index) +{ + int ret = 0; + + BUG_ON(!is_ephemeral(pool)); + zbud_decompress((struct page *)(data), pampd); + zbud_free_and_delist((struct zbud_hdr *)pampd); + atomic_dec(&zcache_curr_eph_pampd_count); + return ret; +} + +/* + * free the pampd and remove it from any zcache lists + * pampd must no longer be pointed to from any tmem data structures! + */ +static void zcache_pampd_free(void *pampd, struct tmem_pool *pool, + struct tmem_oid *oid, uint32_t index) +{ + struct zcache_client *cli = pool->client; + + if (is_ephemeral(pool)) { + zbud_free_and_delist((struct zbud_hdr *)pampd); + atomic_dec(&zcache_curr_eph_pampd_count); + BUG_ON(atomic_read(&zcache_curr_eph_pampd_count) < 0); + } else { + zv_free(cli->xvpool, (struct zv_hdr *)pampd); + atomic_dec(&zcache_curr_pers_pampd_count); + BUG_ON(atomic_read(&zcache_curr_pers_pampd_count) < 0); + } +} + +static void zcache_pampd_free_obj(struct tmem_pool *pool, struct tmem_obj *obj) +{ +} + +static void zcache_pampd_new_obj(struct tmem_obj *obj) +{ +} + +static int zcache_pampd_replace_in_obj(void *pampd, struct tmem_obj *obj) +{ + return -1; +} + +static bool zcache_pampd_is_remote(void *pampd) +{ + return 0; +} + +static struct tmem_pamops zcache_pamops = { + .create = zcache_pampd_create, + .get_data = zcache_pampd_get_data, + .get_data_and_free = zcache_pampd_get_data_and_free, + .free = zcache_pampd_free, + .free_obj = zcache_pampd_free_obj, + .new_obj = zcache_pampd_new_obj, + .replace_in_obj = zcache_pampd_replace_in_obj, + .is_remote = zcache_pampd_is_remote, +}; + +/* + * zcache compression/decompression and related per-cpu stuff + */ + +#define LZO_WORKMEM_BYTES LZO1X_1_MEM_COMPRESS +#define LZO_DSTMEM_PAGE_ORDER 1 +static DEFINE_PER_CPU(unsigned char *, zcache_workmem); +static DEFINE_PER_CPU(unsigned char *, zcache_dstmem); + +static int zcache_compress(struct page *from, void **out_va, size_t *out_len) +{ + int ret = 0; + unsigned char *dmem = __get_cpu_var(zcache_dstmem); + unsigned char *wmem = __get_cpu_var(zcache_workmem); + char *from_va; + + BUG_ON(!irqs_disabled()); + if (unlikely(dmem == NULL || wmem == NULL)) + goto out; /* no buffer, so can't compress */ + from_va = kmap_atomic(from, KM_USER0); + mb(); + ret = lzo1x_1_compress(from_va, PAGE_SIZE, dmem, out_len, wmem); + BUG_ON(ret != LZO_E_OK); + *out_va = dmem; + kunmap_atomic(from_va, KM_USER0); + ret = 1; +out: + return ret; +} + + +static int zcache_cpu_notifier(struct notifier_block *nb, + unsigned long action, void *pcpu) +{ + int cpu = (long)pcpu; + struct zcache_preload *kp; + + switch (action) { + case CPU_UP_PREPARE: + per_cpu(zcache_dstmem, cpu) = (void *)__get_free_pages( + GFP_KERNEL | __GFP_REPEAT, + LZO_DSTMEM_PAGE_ORDER), + per_cpu(zcache_workmem, cpu) = + kzalloc(LZO1X_MEM_COMPRESS, + GFP_KERNEL | __GFP_REPEAT); + break; + case CPU_DEAD: + case CPU_UP_CANCELED: + free_pages((unsigned long)per_cpu(zcache_dstmem, cpu), + LZO_DSTMEM_PAGE_ORDER); + per_cpu(zcache_dstmem, cpu) = NULL; + kfree(per_cpu(zcache_workmem, cpu)); + per_cpu(zcache_workmem, cpu) = NULL; + kp = &per_cpu(zcache_preloads, cpu); + while (kp->nr) { + kmem_cache_free(zcache_objnode_cache, + kp->objnodes[kp->nr - 1]); + kp->objnodes[kp->nr - 1] = NULL; + kp->nr--; + } + if (kp->obj) { + kmem_cache_free(zcache_obj_cache, kp->obj); + kp->obj = NULL; + } + if (kp->page) { + free_page((unsigned long)kp->page); + kp->page = NULL; + } + break; + default: + break; + } + return NOTIFY_OK; +} + +static struct notifier_block zcache_cpu_notifier_block = { + .notifier_call = zcache_cpu_notifier +}; + +#ifdef CONFIG_SYSFS +#define ZCACHE_SYSFS_RO(_name) \ + static ssize_t zcache_##_name##_show(struct kobject *kobj, \ + struct kobj_attribute *attr, char *buf) \ + { \ + return sprintf(buf, "%lu\n", zcache_##_name); \ + } \ + static struct kobj_attribute zcache_##_name##_attr = { \ + .attr = { .name = __stringify(_name), .mode = 0444 }, \ + .show = zcache_##_name##_show, \ + } + +#define ZCACHE_SYSFS_RO_ATOMIC(_name) \ + static ssize_t zcache_##_name##_show(struct kobject *kobj, \ + struct kobj_attribute *attr, char *buf) \ + { \ + return sprintf(buf, "%d\n", atomic_read(&zcache_##_name)); \ + } \ + static struct kobj_attribute zcache_##_name##_attr = { \ + .attr = { .name = __stringify(_name), .mode = 0444 }, \ + .show = zcache_##_name##_show, \ + } + +#define ZCACHE_SYSFS_RO_CUSTOM(_name, _func) \ + static ssize_t zcache_##_name##_show(struct kobject *kobj, \ + struct kobj_attribute *attr, char *buf) \ + { \ + return _func(buf); \ + } \ + static struct kobj_attribute zcache_##_name##_attr = { \ + .attr = { .name = __stringify(_name), .mode = 0444 }, \ + .show = zcache_##_name##_show, \ + } + +ZCACHE_SYSFS_RO(curr_obj_count_max); +ZCACHE_SYSFS_RO(curr_objnode_count_max); +ZCACHE_SYSFS_RO(flush_total); +ZCACHE_SYSFS_RO(flush_found); +ZCACHE_SYSFS_RO(flobj_total); +ZCACHE_SYSFS_RO(flobj_found); +ZCACHE_SYSFS_RO(failed_eph_puts); +ZCACHE_SYSFS_RO(failed_pers_puts); +ZCACHE_SYSFS_RO(zbud_curr_zbytes); +ZCACHE_SYSFS_RO(zbud_cumul_zpages); +ZCACHE_SYSFS_RO(zbud_cumul_zbytes); +ZCACHE_SYSFS_RO(zbud_buddied_count); +ZCACHE_SYSFS_RO(zbpg_unused_list_count); +ZCACHE_SYSFS_RO(evicted_raw_pages); +ZCACHE_SYSFS_RO(evicted_unbuddied_pages); +ZCACHE_SYSFS_RO(evicted_buddied_pages); +ZCACHE_SYSFS_RO(failed_get_free_pages); +ZCACHE_SYSFS_RO(failed_alloc); +ZCACHE_SYSFS_RO(put_to_flush); +ZCACHE_SYSFS_RO(compress_poor); +ZCACHE_SYSFS_RO(mean_compress_poor); +ZCACHE_SYSFS_RO_ATOMIC(zbud_curr_raw_pages); +ZCACHE_SYSFS_RO_ATOMIC(zbud_curr_zpages); +ZCACHE_SYSFS_RO_ATOMIC(curr_obj_count); +ZCACHE_SYSFS_RO_ATOMIC(curr_objnode_count); +ZCACHE_SYSFS_RO_CUSTOM(zbud_unbuddied_list_counts, + zbud_show_unbuddied_list_counts); +ZCACHE_SYSFS_RO_CUSTOM(zbud_cumul_chunk_counts, + zbud_show_cumul_chunk_counts); +ZCACHE_SYSFS_RO_CUSTOM(zv_curr_dist_counts, + zv_curr_dist_counts_show); +ZCACHE_SYSFS_RO_CUSTOM(zv_cumul_dist_counts, + zv_cumul_dist_counts_show); + +static struct attribute *zcache_attrs[] = { + &zcache_curr_obj_count_attr.attr, + &zcache_curr_obj_count_max_attr.attr, + &zcache_curr_objnode_count_attr.attr, + &zcache_curr_objnode_count_max_attr.attr, + &zcache_flush_total_attr.attr, + &zcache_flobj_total_attr.attr, + &zcache_flush_found_attr.attr, + &zcache_flobj_found_attr.attr, + &zcache_failed_eph_puts_attr.attr, + &zcache_failed_pers_puts_attr.attr, + &zcache_compress_poor_attr.attr, + &zcache_mean_compress_poor_attr.attr, + &zcache_zbud_curr_raw_pages_attr.attr, + &zcache_zbud_curr_zpages_attr.attr, + &zcache_zbud_curr_zbytes_attr.attr, + &zcache_zbud_cumul_zpages_attr.attr, + &zcache_zbud_cumul_zbytes_attr.attr, + &zcache_zbud_buddied_count_attr.attr, + &zcache_zbpg_unused_list_count_attr.attr, + &zcache_evicted_raw_pages_attr.attr, + &zcache_evicted_unbuddied_pages_attr.attr, + &zcache_evicted_buddied_pages_attr.attr, + &zcache_failed_get_free_pages_attr.attr, + &zcache_failed_alloc_attr.attr, + &zcache_put_to_flush_attr.attr, + &zcache_zbud_unbuddied_list_counts_attr.attr, + &zcache_zbud_cumul_chunk_counts_attr.attr, + &zcache_zv_curr_dist_counts_attr.attr, + &zcache_zv_cumul_dist_counts_attr.attr, + &zcache_zv_max_zsize_attr.attr, + &zcache_zv_max_mean_zsize_attr.attr, + &zcache_zv_page_count_policy_percent_attr.attr, + NULL, +}; + +static struct attribute_group zcache_attr_group = { + .attrs = zcache_attrs, + .name = "zcache", +}; + +#endif /* CONFIG_SYSFS */ +/* + * When zcache is disabled ("frozen"), pools can be created and destroyed, + * but all puts (and thus all other operations that require memory allocation) + * must fail. If zcache is unfrozen, accepts puts, then frozen again, + * data consistency requires all puts while frozen to be converted into + * flushes. + */ +static bool zcache_freeze; + +/* + * zcache shrinker interface (only useful for ephemeral pages, so zbud only) + */ +static int shrink_zcache_memory(struct shrinker *shrink, + struct shrink_control *sc) +{ + int ret = -1; + int nr = sc->nr_to_scan; + gfp_t gfp_mask = sc->gfp_mask; + + if (nr >= 0) { + if (!(gfp_mask & __GFP_FS)) + /* does this case really need to be skipped? */ + goto out; + zbud_evict_pages(nr); + } + ret = (int)atomic_read(&zcache_zbud_curr_raw_pages); +out: + return ret; +} + +static struct shrinker zcache_shrinker = { + .shrink = shrink_zcache_memory, + .seeks = DEFAULT_SEEKS, +}; + +/* + * zcache shims between cleancache/frontswap ops and tmem + */ + +static int zcache_put_page(int cli_id, int pool_id, struct tmem_oid *oidp, + uint32_t index, struct page *page) +{ + struct tmem_pool *pool; + int ret = -1; + + BUG_ON(!irqs_disabled()); + pool = zcache_get_pool_by_id(cli_id, pool_id); + if (unlikely(pool == NULL)) + goto out; + if (!zcache_freeze && zcache_do_preload(pool) == 0) { + /* preload does preempt_disable on success */ + ret = tmem_put(pool, oidp, index, (char *)(page), + PAGE_SIZE, 0, is_ephemeral(pool)); + if (ret < 0) { + if (is_ephemeral(pool)) + zcache_failed_eph_puts++; + else + zcache_failed_pers_puts++; + } + zcache_put_pool(pool); + preempt_enable_no_resched(); + } else { + zcache_put_to_flush++; + if (atomic_read(&pool->obj_count) > 0) + /* the put fails whether the flush succeeds or not */ + (void)tmem_flush_page(pool, oidp, index); + zcache_put_pool(pool); + } +out: + return ret; +} + +static int zcache_get_page(int cli_id, int pool_id, struct tmem_oid *oidp, + uint32_t index, struct page *page) +{ + struct tmem_pool *pool; + int ret = -1; + unsigned long flags; + size_t size = PAGE_SIZE; + + local_irq_save(flags); + pool = zcache_get_pool_by_id(cli_id, pool_id); + if (likely(pool != NULL)) { + if (atomic_read(&pool->obj_count) > 0) + ret = tmem_get(pool, oidp, index, (char *)(page), + &size, 0, is_ephemeral(pool)); + zcache_put_pool(pool); + } + local_irq_restore(flags); + return ret; +} + +static int zcache_flush_page(int cli_id, int pool_id, + struct tmem_oid *oidp, uint32_t index) +{ + struct tmem_pool *pool; + int ret = -1; + unsigned long flags; + + local_irq_save(flags); + zcache_flush_total++; + pool = zcache_get_pool_by_id(cli_id, pool_id); + if (likely(pool != NULL)) { + if (atomic_read(&pool->obj_count) > 0) + ret = tmem_flush_page(pool, oidp, index); + zcache_put_pool(pool); + } + if (ret >= 0) + zcache_flush_found++; + local_irq_restore(flags); + return ret; +} + +static int zcache_flush_object(int cli_id, int pool_id, + struct tmem_oid *oidp) +{ + struct tmem_pool *pool; + int ret = -1; + unsigned long flags; + + local_irq_save(flags); + zcache_flobj_total++; + pool = zcache_get_pool_by_id(cli_id, pool_id); + if (likely(pool != NULL)) { + if (atomic_read(&pool->obj_count) > 0) + ret = tmem_flush_object(pool, oidp); + zcache_put_pool(pool); + } + if (ret >= 0) + zcache_flobj_found++; + local_irq_restore(flags); + return ret; +} + +static int zcache_destroy_pool(int cli_id, int pool_id) +{ + struct tmem_pool *pool = NULL; + struct zcache_client *cli = NULL; + int ret = -1; + + if (pool_id < 0) + goto out; + if (cli_id == LOCAL_CLIENT) + cli = &zcache_host; + else if ((unsigned int)cli_id < MAX_CLIENTS) + cli = &zcache_clients[cli_id]; + if (cli == NULL) + goto out; + atomic_inc(&cli->refcount); + pool = cli->tmem_pools[pool_id]; + if (pool == NULL) + goto out; + cli->tmem_pools[pool_id] = NULL; + /* wait for pool activity on other cpus to quiesce */ + while (atomic_read(&pool->refcount) != 0) + ; + atomic_dec(&cli->refcount); + local_bh_disable(); + ret = tmem_destroy_pool(pool); + local_bh_enable(); + kfree(pool); + pr_info("zcache: destroyed pool id=%d, cli_id=%d\n", + pool_id, cli_id); +out: + return ret; +} + +static int zcache_new_pool(uint16_t cli_id, uint32_t flags) +{ + int poolid = -1; + struct tmem_pool *pool; + struct zcache_client *cli = NULL; + + if (cli_id == LOCAL_CLIENT) + cli = &zcache_host; + else if ((unsigned int)cli_id < MAX_CLIENTS) + cli = &zcache_clients[cli_id]; + if (cli == NULL) + goto out; + atomic_inc(&cli->refcount); + pool = kmalloc(sizeof(struct tmem_pool), GFP_ATOMIC); + if (pool == NULL) { + pr_info("zcache: pool creation failed: out of memory\n"); + goto out; + } + + for (poolid = 0; poolid < MAX_POOLS_PER_CLIENT; poolid++) + if (cli->tmem_pools[poolid] == NULL) + break; + if (poolid >= MAX_POOLS_PER_CLIENT) { + pr_info("zcache: pool creation failed: max exceeded\n"); + kfree(pool); + poolid = -1; + goto out; + } + atomic_set(&pool->refcount, 0); + pool->client = cli; + pool->pool_id = poolid; + tmem_new_pool(pool, flags); + cli->tmem_pools[poolid] = pool; + pr_info("zcache: created %s tmem pool, id=%d, client=%d\n", + flags & TMEM_POOL_PERSIST ? "persistent" : "ephemeral", + poolid, cli_id); +out: + if (cli != NULL) + atomic_dec(&cli->refcount); + return poolid; +} + +/********** + * Two kernel functionalities currently can be layered on top of tmem. + * These are "cleancache" which is used as a second-chance cache for clean + * page cache pages; and "frontswap" which is used for swap pages + * to avoid writes to disk. A generic "shim" is provided here for each + * to translate in-kernel semantics to zcache semantics. + */ + +#ifdef CONFIG_CLEANCACHE +static void zcache_cleancache_put_page(int pool_id, + struct cleancache_filekey key, + pgoff_t index, struct page *page) +{ + u32 ind = (u32) index; + struct tmem_oid oid = *(struct tmem_oid *)&key; + + if (likely(ind == index)) + (void)zcache_put_page(LOCAL_CLIENT, pool_id, &oid, index, page); +} + +static int zcache_cleancache_get_page(int pool_id, + struct cleancache_filekey key, + pgoff_t index, struct page *page) +{ + u32 ind = (u32) index; + struct tmem_oid oid = *(struct tmem_oid *)&key; + int ret = -1; + + if (likely(ind == index)) + ret = zcache_get_page(LOCAL_CLIENT, pool_id, &oid, index, page); + return ret; +} + +static void zcache_cleancache_flush_page(int pool_id, + struct cleancache_filekey key, + pgoff_t index) +{ + u32 ind = (u32) index; + struct tmem_oid oid = *(struct tmem_oid *)&key; + + if (likely(ind == index)) + (void)zcache_flush_page(LOCAL_CLIENT, pool_id, &oid, ind); +} + +static void zcache_cleancache_flush_inode(int pool_id, + struct cleancache_filekey key) +{ + struct tmem_oid oid = *(struct tmem_oid *)&key; + + (void)zcache_flush_object(LOCAL_CLIENT, pool_id, &oid); +} + +static void zcache_cleancache_flush_fs(int pool_id) +{ + if (pool_id >= 0) + (void)zcache_destroy_pool(LOCAL_CLIENT, pool_id); +} + +static int zcache_cleancache_init_fs(size_t pagesize) +{ + BUG_ON(sizeof(struct cleancache_filekey) != + sizeof(struct tmem_oid)); + BUG_ON(pagesize != PAGE_SIZE); + return zcache_new_pool(LOCAL_CLIENT, 0); +} + +static int zcache_cleancache_init_shared_fs(char *uuid, size_t pagesize) +{ + /* shared pools are unsupported and map to private */ + BUG_ON(sizeof(struct cleancache_filekey) != + sizeof(struct tmem_oid)); + BUG_ON(pagesize != PAGE_SIZE); + return zcache_new_pool(LOCAL_CLIENT, 0); +} + +static struct cleancache_ops zcache_cleancache_ops = { + .put_page = zcache_cleancache_put_page, + .get_page = zcache_cleancache_get_page, + .invalidate_page = zcache_cleancache_flush_page, + .invalidate_inode = zcache_cleancache_flush_inode, + .invalidate_fs = zcache_cleancache_flush_fs, + .init_shared_fs = zcache_cleancache_init_shared_fs, + .init_fs = zcache_cleancache_init_fs +}; + +struct cleancache_ops zcache_cleancache_register_ops(void) +{ + struct cleancache_ops old_ops = + cleancache_register_ops(&zcache_cleancache_ops); + + return old_ops; +} +#endif + +#ifdef CONFIG_FRONTSWAP +/* a single tmem poolid is used for all frontswap "types" (swapfiles) */ +static int zcache_frontswap_poolid = -1; + +/* + * Swizzling increases objects per swaptype, increasing tmem concurrency + * for heavy swaploads. Later, larger nr_cpus -> larger SWIZ_BITS + * Setting SWIZ_BITS to 27 basically reconstructs the swap entry from + * frontswap_get_page() + */ +#define SWIZ_BITS 27 +#define SWIZ_MASK ((1 << SWIZ_BITS) - 1) +#define _oswiz(_type, _ind) ((_type << SWIZ_BITS) | (_ind & SWIZ_MASK)) +#define iswiz(_ind) (_ind >> SWIZ_BITS) + +static inline struct tmem_oid oswiz(unsigned type, u32 ind) +{ + struct tmem_oid oid = { .oid = { 0 } }; + oid.oid[0] = _oswiz(type, ind); + return oid; +} + +static int zcache_frontswap_put_page(unsigned type, pgoff_t offset, + struct page *page) +{ + u64 ind64 = (u64)offset; + u32 ind = (u32)offset; + struct tmem_oid oid = oswiz(type, ind); + int ret = -1; + unsigned long flags; + + BUG_ON(!PageLocked(page)); + if (likely(ind64 == ind)) { + local_irq_save(flags); + ret = zcache_put_page(LOCAL_CLIENT, zcache_frontswap_poolid, + &oid, iswiz(ind), page); + local_irq_restore(flags); + } + return ret; +} + +/* returns 0 if the page was successfully gotten from frontswap, -1 if + * was not present (should never happen!) */ +static int zcache_frontswap_get_page(unsigned type, pgoff_t offset, + struct page *page) +{ + u64 ind64 = (u64)offset; + u32 ind = (u32)offset; + struct tmem_oid oid = oswiz(type, ind); + int ret = -1; + + BUG_ON(!PageLocked(page)); + if (likely(ind64 == ind)) + ret = zcache_get_page(LOCAL_CLIENT, zcache_frontswap_poolid, + &oid, iswiz(ind), page); + return ret; +} + +/* flush a single page from frontswap */ +static void zcache_frontswap_flush_page(unsigned type, pgoff_t offset) +{ + u64 ind64 = (u64)offset; + u32 ind = (u32)offset; + struct tmem_oid oid = oswiz(type, ind); + + if (likely(ind64 == ind)) + (void)zcache_flush_page(LOCAL_CLIENT, zcache_frontswap_poolid, + &oid, iswiz(ind)); +} + +/* flush all pages from the passed swaptype */ +static void zcache_frontswap_flush_area(unsigned type) +{ + struct tmem_oid oid; + int ind; + + for (ind = SWIZ_MASK; ind >= 0; ind--) { + oid = oswiz(type, ind); + (void)zcache_flush_object(LOCAL_CLIENT, + zcache_frontswap_poolid, &oid); + } +} + +static void zcache_frontswap_init(unsigned ignored) +{ + /* a single tmem poolid is used for all frontswap "types" (swapfiles) */ + if (zcache_frontswap_poolid < 0) + zcache_frontswap_poolid = + zcache_new_pool(LOCAL_CLIENT, TMEM_POOL_PERSIST); +} + +static struct frontswap_ops zcache_frontswap_ops = { + .put_page = zcache_frontswap_put_page, + .get_page = zcache_frontswap_get_page, + .invalidate_page = zcache_frontswap_flush_page, + .invalidate_area = zcache_frontswap_flush_area, + .init = zcache_frontswap_init +}; + +struct frontswap_ops zcache_frontswap_register_ops(void) +{ + struct frontswap_ops old_ops = + frontswap_register_ops(&zcache_frontswap_ops); + + return old_ops; +} +#endif + +/* + * zcache initialization + * NOTE FOR NOW zcache MUST BE PROVIDED AS A KERNEL BOOT PARAMETER OR + * NOTHING HAPPENS! + */ + +static int zcache_enabled; + +static int __init enable_zcache(char *s) +{ + zcache_enabled = 1; + return 1; +} +__setup("zcache", enable_zcache); + +/* allow independent dynamic disabling of cleancache and frontswap */ + +static int use_cleancache = 1; + +static int __init no_cleancache(char *s) +{ + use_cleancache = 0; + return 1; +} + +__setup("nocleancache", no_cleancache); + +static int use_frontswap = 1; + +static int __init no_frontswap(char *s) +{ + use_frontswap = 0; + return 1; +} + +__setup("nofrontswap", no_frontswap); + +static int __init zcache_init(void) +{ + int ret = 0; + +#ifdef CONFIG_SYSFS + ret = sysfs_create_group(mm_kobj, &zcache_attr_group); + if (ret) { + pr_err("zcache: can't create sysfs\n"); + goto out; + } +#endif /* CONFIG_SYSFS */ +#if defined(CONFIG_CLEANCACHE) || defined(CONFIG_FRONTSWAP) + if (zcache_enabled) { + unsigned int cpu; + + tmem_register_hostops(&zcache_hostops); + tmem_register_pamops(&zcache_pamops); + ret = register_cpu_notifier(&zcache_cpu_notifier_block); + if (ret) { + pr_err("zcache: can't register cpu notifier\n"); + goto out; + } + for_each_online_cpu(cpu) { + void *pcpu = (void *)(long)cpu; + zcache_cpu_notifier(&zcache_cpu_notifier_block, + CPU_UP_PREPARE, pcpu); + } + } + zcache_objnode_cache = kmem_cache_create("zcache_objnode", + sizeof(struct tmem_objnode), 0, 0, NULL); + zcache_obj_cache = kmem_cache_create("zcache_obj", + sizeof(struct tmem_obj), 0, 0, NULL); + ret = zcache_new_client(LOCAL_CLIENT); + if (ret) { + pr_err("zcache: can't create client\n"); + goto out; + } +#endif +#ifdef CONFIG_CLEANCACHE + if (zcache_enabled && use_cleancache) { + struct cleancache_ops old_ops; + + zbud_init(); + register_shrinker(&zcache_shrinker); + old_ops = zcache_cleancache_register_ops(); + pr_info("zcache: cleancache enabled using kernel " + "transcendent memory and compression buddies\n"); + if (old_ops.init_fs != NULL) + pr_warning("zcache: cleancache_ops overridden"); + } +#endif +#ifdef CONFIG_FRONTSWAP + if (zcache_enabled && use_frontswap) { + struct frontswap_ops old_ops; + + old_ops = zcache_frontswap_register_ops(); + pr_info("zcache: frontswap enabled using kernel " + "transcendent memory and xvmalloc\n"); + if (old_ops.init != NULL) + pr_warning("zcache: frontswap_ops overridden"); + } +#endif +out: + return ret; +} + +module_init(zcache_init) -- cgit v0.10.2 From b083e8619c84503e80e681504cabfb647e715edc Mon Sep 17 00:00:00 2001 From: Dan Magenheimer Date: Mon, 30 Jan 2012 14:39:18 -0800 Subject: staging: ramster: ramster-specific changes to cluster code Ramster-specific changes to ocfs2 cluster foundation, including: A method for fooling the o2 heartbeat into starting without an ocfs2 filesystem; a new message mechanism ("data magic") for handling a reply to a message requesting data; a hack for keeping the cluster alive even after timeouts so cluster machines can be rebooted separately. Signed-off-by: Dan Magenheimer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/ramster/cluster/Makefile b/drivers/staging/ramster/cluster/Makefile index bc8c5e7..3fc8550 100644 --- a/drivers/staging/ramster/cluster/Makefile +++ b/drivers/staging/ramster/cluster/Makefile @@ -1,4 +1,5 @@ -obj-$(CONFIG_OCFS2_FS) += ocfs2_nodemanager.o +#obj-$(CONFIG_OCFS2_FS) += ocfs2_nodemanager.o +obj-$(CONFIG_RAMSTER) += ocfs2_nodemanager.o ocfs2_nodemanager-objs := heartbeat.o masklog.o sys.o nodemanager.o \ quorum.o tcp.o netdebug.o ver.o diff --git a/drivers/staging/ramster/cluster/heartbeat.c b/drivers/staging/ramster/cluster/heartbeat.c index a4e855e..1f72143 100644 --- a/drivers/staging/ramster/cluster/heartbeat.c +++ b/drivers/staging/ramster/cluster/heartbeat.c @@ -2676,3 +2676,12 @@ int o2hb_global_heartbeat_active(void) return (o2hb_heartbeat_mode == O2HB_HEARTBEAT_GLOBAL); } EXPORT_SYMBOL(o2hb_global_heartbeat_active); + +#ifdef CONFIG_RAMSTER +void o2hb_manual_set_node_heartbeating(int node_num) +{ + if (node_num < O2NM_MAX_NODES) + set_bit(node_num, o2hb_live_node_bitmap); +} +EXPORT_SYMBOL(o2hb_manual_set_node_heartbeating); +#endif diff --git a/drivers/staging/ramster/cluster/heartbeat.h b/drivers/staging/ramster/cluster/heartbeat.h index 00ad8e8..cf1a164 100644 --- a/drivers/staging/ramster/cluster/heartbeat.h +++ b/drivers/staging/ramster/cluster/heartbeat.h @@ -85,5 +85,8 @@ int o2hb_check_local_node_heartbeating(void); void o2hb_stop_all_regions(void); int o2hb_get_all_regions(char *region_uuids, u8 numregions); int o2hb_global_heartbeat_active(void); +#ifdef CONFIG_RAMSTER +void o2hb_manual_set_node_heartbeating(int); +#endif #endif /* O2CLUSTER_HEARTBEAT_H */ diff --git a/drivers/staging/ramster/cluster/tcp.c b/drivers/staging/ramster/cluster/tcp.c index 044e7b5..e9bd00e 100644 --- a/drivers/staging/ramster/cluster/tcp.c +++ b/drivers/staging/ramster/cluster/tcp.c @@ -288,7 +288,11 @@ static inline int o2net_sys_err_to_errno(enum o2net_system_error err) return trans; } +#ifdef CONFIG_RAMSTER +struct o2net_node *o2net_nn_from_num(u8 node_num) +#else static struct o2net_node * o2net_nn_from_num(u8 node_num) +#endif { BUG_ON(node_num >= ARRAY_SIZE(o2net_nodes)); return &o2net_nodes[node_num]; @@ -1068,6 +1072,11 @@ int o2net_send_message_vec(u32 msg_type, u32 key, struct kvec *caller_vec, }; struct o2net_send_tracking nst; +#ifdef CONFIG_RAMSTER + /* this may be a general bug fix */ + init_waitqueue_head(&nsw.ns_wq); +#endif + o2net_init_nst(&nst, msg_type, key, current, target_node); if (o2net_wq == NULL) { @@ -1208,6 +1217,52 @@ static int o2net_send_status_magic(struct socket *sock, struct o2net_msg *hdr, return o2net_send_tcp_msg(sock, &vec, 1, sizeof(struct o2net_msg)); } +#ifdef CONFIG_RAMSTER +/* + * "data magic" is a long version of "status magic" where the message + * payload actually contains data to be passed in reply to certain messages + */ +static int o2net_send_data_magic(struct o2net_sock_container *sc, + struct o2net_msg *hdr, + void *data, size_t data_len, + enum o2net_system_error syserr, int err) +{ + struct kvec vec[2]; + int ret; + + vec[0].iov_base = hdr; + vec[0].iov_len = sizeof(struct o2net_msg); + vec[1].iov_base = data; + vec[1].iov_len = data_len; + + BUG_ON(syserr >= O2NET_ERR_MAX); + + /* leave other fields intact from the incoming message, msg_num + * in particular */ + hdr->sys_status = cpu_to_be32(syserr); + hdr->status = cpu_to_be32(err); + hdr->magic = cpu_to_be16(O2NET_MSG_DATA_MAGIC); /* twiddle magic */ + hdr->data_len = cpu_to_be16(data_len); + + msglog(hdr, "about to send data magic %d\n", err); + /* hdr has been in host byteorder this whole time */ + ret = o2net_send_tcp_msg(sc->sc_sock, vec, 2, + sizeof(struct o2net_msg) + data_len); + return ret; +} + +/* + * called by a message handler to convert an otherwise normal reply + * message into a "data magic" message + */ +void o2net_force_data_magic(struct o2net_msg *hdr, u16 msgtype, u32 msgkey) +{ + hdr->magic = cpu_to_be16(O2NET_MSG_DATA_MAGIC); + hdr->msg_type = cpu_to_be16(msgtype); + hdr->key = cpu_to_be32(msgkey); +} +#endif + /* this returns -errno if the header was unknown or too large, etc. * after this is called the buffer us reused for the next message */ static int o2net_process_message(struct o2net_sock_container *sc, @@ -1218,6 +1273,9 @@ static int o2net_process_message(struct o2net_sock_container *sc, enum o2net_system_error syserr; struct o2net_msg_handler *nmh = NULL; void *ret_data = NULL; +#ifdef CONFIG_RAMSTER + int data_magic = 0; +#endif msglog(hdr, "processing message\n"); @@ -1239,6 +1297,16 @@ static int o2net_process_message(struct o2net_sock_container *sc, goto out; case O2NET_MSG_MAGIC: break; +#ifdef CONFIG_RAMSTER + case O2NET_MSG_DATA_MAGIC: + /* + * unlike a normal status magic, a data magic DOES + * (MUST) have a handler, so the control flow is + * a little funky here as a result + */ + data_magic = 1; + break; +#endif default: msglog(hdr, "bad magic\n"); ret = -EINVAL; @@ -1271,6 +1339,34 @@ static int o2net_process_message(struct o2net_sock_container *sc, handler_status = (nmh->nh_func)(hdr, sizeof(struct o2net_msg) + be16_to_cpu(hdr->data_len), nmh->nh_func_data, &ret_data); +#ifdef CONFIG_RAMSTER + if (data_magic) { + /* + * handler handled data sent in reply to request + * so complete the transaction + */ + o2net_complete_nsw(nn, NULL, be32_to_cpu(hdr->msg_num), + be32_to_cpu(hdr->sys_status), handler_status); + goto out; + } + /* + * handler changed magic to DATA_MAGIC to reply to request for data, + * implies ret_data points to data to return and handler_status + * is the number of bytes of data + */ + if (be16_to_cpu(hdr->magic) == O2NET_MSG_DATA_MAGIC) { + ret = o2net_send_data_magic(sc, hdr, + ret_data, handler_status, + syserr, 0); + hdr = NULL; + mlog(0, "sending data reply %d, syserr %d returned %d\n", + handler_status, syserr, ret); + o2net_set_func_stop_time(sc); + + o2net_update_recv_stats(sc); + goto out; + } +#endif o2net_set_func_stop_time(sc); o2net_update_recv_stats(sc); @@ -1558,7 +1654,9 @@ static void o2net_sc_send_keep_req(struct work_struct *work) static void o2net_idle_timer(unsigned long data) { struct o2net_sock_container *sc = (struct o2net_sock_container *)data; +#ifndef CONFIG_RAMSTER struct o2net_node *nn = o2net_nn_from_num(sc->sc_node->nd_num); +#endif #ifdef CONFIG_DEBUG_FS unsigned long msecs = ktime_to_ms(ktime_get()) - ktime_to_ms(sc->sc_tv_timer); @@ -1574,9 +1672,14 @@ static void o2net_idle_timer(unsigned long data) * Initialize the nn_timeout so that the next connection attempt * will continue in o2net_start_connect. */ +#ifdef CONFIG_RAMSTER + /* Avoid spurious shutdowns... not sure if this is still necessary */ + pr_err("o2net_idle_timer, skipping shutdown work\n"); +#else atomic_set(&nn->nn_timeout, 1); o2net_sc_queue_work(sc, &sc->sc_shutdown_work); +#endif } static void o2net_sc_reset_idle_timer(struct o2net_sock_container *sc) @@ -2094,6 +2197,15 @@ void o2net_stop_listening(struct o2nm_node *node) o2quo_conn_err(node->nd_num); } +#ifdef CONFIG_RAMSTER +void o2net_hb_node_up_manual(int node_num) +{ + struct o2nm_node dummy; + o2hb_manual_set_node_heartbeating(node_num); + o2net_hb_node_up_cb(&dummy, node_num, NULL); +} +#endif + /* ------------------------------------------------------------ */ int o2net_init(void) diff --git a/drivers/staging/ramster/cluster/tcp.h b/drivers/staging/ramster/cluster/tcp.h index 5bada2a..95a991f 100644 --- a/drivers/staging/ramster/cluster/tcp.h +++ b/drivers/staging/ramster/cluster/tcp.h @@ -108,6 +108,12 @@ void o2net_unregister_handler_list(struct list_head *list); void o2net_fill_node_map(unsigned long *map, unsigned bytes); +#ifdef CONFIG_RAMSTER +void o2net_force_data_magic(struct o2net_msg *, u16, u32); +void o2net_hb_node_up_manual(int); +struct o2net_node *o2net_nn_from_num(u8); +#endif + struct o2nm_node; int o2net_register_hb_callbacks(void); void o2net_unregister_hb_callbacks(void); diff --git a/drivers/staging/ramster/cluster/tcp_internal.h b/drivers/staging/ramster/cluster/tcp_internal.h index 4cbcb65..ce17135 100644 --- a/drivers/staging/ramster/cluster/tcp_internal.h +++ b/drivers/staging/ramster/cluster/tcp_internal.h @@ -26,6 +26,13 @@ #define O2NET_MSG_STATUS_MAGIC ((u16)0xfa56) #define O2NET_MSG_KEEP_REQ_MAGIC ((u16)0xfa57) #define O2NET_MSG_KEEP_RESP_MAGIC ((u16)0xfa58) +#ifdef CONFIG_RAMSTER +/* + * "data magic" is a long version of "status magic" where the message + * payload actually contains data to be passed in reply to certain messages + */ +#define O2NET_MSG_DATA_MAGIC ((u16)0xfa59) +#endif /* we're delaying our quorum decision so that heartbeat will have timed * out truly dead nodes by the time we come around to making decisions -- cgit v0.10.2 From 0fb3860a8212bfce09e4c53ab342b84adb934159 Mon Sep 17 00:00:00 2001 From: Dan Magenheimer Date: Mon, 30 Jan 2012 14:39:19 -0800 Subject: staging: ramster: ramster-specific changes to zcache/tmem In tmem.[ch], new "repatriate" (provoke async get) and "localify" (handle incoming data resulting from an async get) routines combine with a handful of changes to existing pamops interfaces allow the generic tmem code to support asynchronous operations. Also, a new tmem_xhandle struct groups together key information that must be passed to remote tmem stores. Zcache-main.c is augmented with a large amount of ramster-specific code to handle remote operations and "foreign" pages on both ends of the "remotify" protocol. New "foreign" pools are auto-created on demand. A "selfshrinker" thread periodically repatriates remote persistent pages when local memory conditions allow. For certain operations, a queue is necessary to guarantee strict ordering as out-of-order puts/flushes can cause strange race conditions. Pampd pointers now either point to local memory OR describe a remote page; to allow the same 64-bits to describe either, the LSB is used to differentiate. Some acrobatics must be performed to ensure local memory is available to handle a remote persistent get, or deal with the data directly anyway if the malloc failed. Lots of ramster-specific statistics are available via sysfs. Note: Some debug ifdefs left in for now. Signed-off-by: Dan Magenheimer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/ramster/Kconfig b/drivers/staging/ramster/Kconfig index 7fabcb2..3957b87 100644 --- a/drivers/staging/ramster/Kconfig +++ b/drivers/staging/ramster/Kconfig @@ -1,13 +1,14 @@ -config ZCACHE - tristate "Dynamic compression of swap pages and clean pagecache pages" - depends on CLEANCACHE || FRONTSWAP +config RAMSTER + tristate "Cross-machine RAM capacity sharing, aka peer-to-peer tmem" + depends on (CLEANCACHE || FRONTSWAP) && CONFIGFS_FS && !OCFS2_FS && !ZCACHE && !HIGHMEM select XVMALLOC select LZO_COMPRESS select LZO_DECOMPRESS default n help - Zcache doubles RAM efficiency while providing a significant - performance boosts on many workloads. Zcache uses lzo1x - compression and an in-kernel implementation of transcendent - memory to store clean page cache pages and swap in RAM, - providing a noticeable reduction in disk I/O. + RAMster allows RAM on other machines in a cluster to be utilized + dynamically and symmetrically instead of swapping to a local swap + disk, thus improving performance on memory-constrained workloads + while minimizing total RAM across the cluster. RAMster, like + zcache, compresses swap pages into local RAM, but then remotifies + the compressed pages to another node in the RAMster cluster. diff --git a/drivers/staging/ramster/Makefile b/drivers/staging/ramster/Makefile index 60daa27..e6c4a2e 100644 --- a/drivers/staging/ramster/Makefile +++ b/drivers/staging/ramster/Makefile @@ -1,3 +1,2 @@ -zcache-y := zcache-main.o tmem.o - -obj-$(CONFIG_ZCACHE) += zcache.o +obj-$(CONFIG_RAMSTER) += zcache-main.o tmem.o +obj-$(CONFIG_RAMSTER) += ramster_o2net.o cluster/ diff --git a/drivers/staging/ramster/tmem.c b/drivers/staging/ramster/tmem.c index 1ca66ea..8f2f689 100644 --- a/drivers/staging/ramster/tmem.c +++ b/drivers/staging/ramster/tmem.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "tmem.h" @@ -316,7 +317,7 @@ static void *tmem_pampd_lookup_in_obj(struct tmem_obj *obj, uint32_t index) } static void *tmem_pampd_replace_in_obj(struct tmem_obj *obj, uint32_t index, - void *new_pampd) + void *new_pampd, bool no_free) { struct tmem_objnode **slot; void *ret = NULL; @@ -325,7 +326,9 @@ static void *tmem_pampd_replace_in_obj(struct tmem_obj *obj, uint32_t index, if ((slot != NULL) && (*slot != NULL)) { void *old_pampd = *(void **)slot; *(void **)slot = new_pampd; - (*tmem_pamops.free)(old_pampd, obj->pool, NULL, 0); + if (!no_free) + (*tmem_pamops.free)(old_pampd, obj->pool, + NULL, 0, false); ret = new_pampd; } return ret; @@ -481,7 +484,7 @@ static void tmem_objnode_node_destroy(struct tmem_obj *obj, if (ht == 1) { obj->pampd_count--; (*tmem_pamops.free)(objnode->slots[i], - obj->pool, NULL, 0); + obj->pool, NULL, 0, true); objnode->slots[i] = NULL; continue; } @@ -498,7 +501,8 @@ static void tmem_pampd_destroy_all_in_obj(struct tmem_obj *obj) return; if (obj->objnode_tree_height == 0) { obj->pampd_count--; - (*tmem_pamops.free)(obj->objnode_tree_root, obj->pool, NULL, 0); + (*tmem_pamops.free)(obj->objnode_tree_root, + obj->pool, NULL, 0, true); } else { tmem_objnode_node_destroy(obj, obj->objnode_tree_root, obj->objnode_tree_height); @@ -529,7 +533,7 @@ static void tmem_pampd_destroy_all_in_obj(struct tmem_obj *obj) * always flushes for simplicity. */ int tmem_put(struct tmem_pool *pool, struct tmem_oid *oidp, uint32_t index, - char *data, size_t size, bool raw, bool ephemeral) + char *data, size_t size, bool raw, int ephemeral) { struct tmem_obj *obj = NULL, *objfound = NULL, *objnew = NULL; void *pampd = NULL, *pampd_del = NULL; @@ -545,7 +549,7 @@ int tmem_put(struct tmem_pool *pool, struct tmem_oid *oidp, uint32_t index, /* if found, is a dup put, flush the old one */ pampd_del = tmem_pampd_delete_from_obj(obj, index); BUG_ON(pampd_del != pampd); - (*tmem_pamops.free)(pampd, pool, oidp, index); + (*tmem_pamops.free)(pampd, pool, oidp, index, true); if (obj->pampd_count == 0) { objnew = obj; objfound = NULL; @@ -576,7 +580,7 @@ delete_and_free: (void)tmem_pampd_delete_from_obj(obj, index); free: if (pampd) - (*tmem_pamops.free)(pampd, pool, NULL, 0); + (*tmem_pamops.free)(pampd, pool, NULL, 0, true); if (objnew) { tmem_obj_free(objnew, hb); (*tmem_hostops.obj_free)(objnew, pool); @@ -586,6 +590,65 @@ out: return ret; } +void *tmem_localify_get_pampd(struct tmem_pool *pool, struct tmem_oid *oidp, + uint32_t index, struct tmem_obj **ret_obj, + void **saved_hb) +{ + struct tmem_hashbucket *hb; + struct tmem_obj *obj = NULL; + void *pampd = NULL; + + hb = &pool->hashbucket[tmem_oid_hash(oidp)]; + spin_lock(&hb->lock); + obj = tmem_obj_find(hb, oidp); + if (likely(obj != NULL)) + pampd = tmem_pampd_lookup_in_obj(obj, index); + *ret_obj = obj; + *saved_hb = (void *)hb; + /* note, hashbucket remains locked */ + return pampd; +} + +void tmem_localify_finish(struct tmem_obj *obj, uint32_t index, + void *pampd, void *saved_hb, bool delete) +{ + struct tmem_hashbucket *hb = (struct tmem_hashbucket *)saved_hb; + + BUG_ON(!spin_is_locked(&hb->lock)); + if (pampd != NULL) { + BUG_ON(obj == NULL); + (void)tmem_pampd_replace_in_obj(obj, index, pampd, 1); + } else if (delete) { + BUG_ON(obj == NULL); + (void)tmem_pampd_delete_from_obj(obj, index); + } + spin_unlock(&hb->lock); +} + +static int tmem_repatriate(void **ppampd, struct tmem_hashbucket *hb, + struct tmem_pool *pool, struct tmem_oid *oidp, + uint32_t index, bool free, char *data) +{ + void *old_pampd = *ppampd, *new_pampd = NULL; + bool intransit = false; + int ret = 0; + + + if (!is_ephemeral(pool)) + new_pampd = (*tmem_pamops.repatriate_preload)( + old_pampd, pool, oidp, index, &intransit); + if (intransit) + ret = -EAGAIN; + else if (new_pampd != NULL) + *ppampd = new_pampd; + /* must release the hb->lock else repatriate can't sleep */ + spin_unlock(&hb->lock); + if (!intransit) + ret = (*tmem_pamops.repatriate)(old_pampd, new_pampd, pool, + oidp, index, free, data); + return ret; +} + /* * "Get" a page, e.g. if one can be found, copy the tmem page with the * matching handle from PAM space to the kernel. By tmem definition, @@ -607,14 +670,36 @@ int tmem_get(struct tmem_pool *pool, struct tmem_oid *oidp, uint32_t index, int ret = -1; struct tmem_hashbucket *hb; bool free = (get_and_free == 1) || ((get_and_free == 0) && ephemeral); - bool lock_held = false; + bool lock_held = 0; + void **ppampd; +again: hb = &pool->hashbucket[tmem_oid_hash(oidp)]; spin_lock(&hb->lock); - lock_held = true; + lock_held = 1; obj = tmem_obj_find(hb, oidp); if (obj == NULL) goto out; + ppampd = __tmem_pampd_lookup_in_obj(obj, index); + if (ppampd == NULL) + goto out; + if (tmem_pamops.is_remote(*ppampd)) { + ret = tmem_repatriate(ppampd, hb, pool, oidp, + index, free, data); + lock_held = 0; /* note hb->lock has been unlocked */ + if (ret == -EAGAIN) { + /* rare I think, but should cond_resched()??? */ + usleep_range(10, 1000); + goto again; + } else if (ret != 0) { + if (ret != -ENOENT) + pr_err("UNTESTED case in tmem_get, ret=%d\n", + ret); + ret = -1; + goto out; + } + goto out; + } if (free) pampd = tmem_pampd_delete_from_obj(obj, index); else @@ -628,10 +713,6 @@ int tmem_get(struct tmem_pool *pool, struct tmem_oid *oidp, uint32_t index, obj = NULL; } } - if (tmem_pamops.is_remote(pampd)) { - lock_held = false; - spin_unlock(&hb->lock); - } if (free) ret = (*tmem_pamops.get_data_and_free)( data, size, raw, pampd, pool, oidp, index); @@ -668,7 +749,7 @@ int tmem_flush_page(struct tmem_pool *pool, pampd = tmem_pampd_delete_from_obj(obj, index); if (pampd == NULL) goto out; - (*tmem_pamops.free)(pampd, pool, oidp, index); + (*tmem_pamops.free)(pampd, pool, oidp, index, true); if (obj->pampd_count == 0) { tmem_obj_free(obj, hb); (*tmem_hostops.obj_free)(obj, pool); @@ -682,8 +763,8 @@ out: /* * If a page in tmem matches the handle, replace the page so that any - * subsequent "get" gets the new page. Returns 0 if - * there was a page to replace, else returns -1. + * subsequent "get" gets the new page. Returns the new page if + * there was a page to replace, else returns NULL. */ int tmem_replace(struct tmem_pool *pool, struct tmem_oid *oidp, uint32_t index, void *new_pampd) @@ -697,7 +778,7 @@ int tmem_replace(struct tmem_pool *pool, struct tmem_oid *oidp, obj = tmem_obj_find(hb, oidp); if (obj == NULL) goto out; - new_pampd = tmem_pampd_replace_in_obj(obj, index, new_pampd); + new_pampd = tmem_pampd_replace_in_obj(obj, index, new_pampd, 0); ret = (*tmem_pamops.replace_in_obj)(new_pampd, obj); out: spin_unlock(&hb->lock); diff --git a/drivers/staging/ramster/tmem.h b/drivers/staging/ramster/tmem.h index ed147c4..47f1918 100644 --- a/drivers/staging/ramster/tmem.h +++ b/drivers/staging/ramster/tmem.h @@ -9,7 +9,6 @@ #ifndef _TMEM_H_ #define _TMEM_H_ -#include #include #include #include @@ -89,6 +88,31 @@ struct tmem_oid { uint64_t oid[3]; }; +struct tmem_xhandle { + uint8_t client_id; + uint8_t xh_data_cksum; + uint16_t xh_data_size; + uint16_t pool_id; + struct tmem_oid oid; + uint32_t index; + void *extra; +}; + +static inline struct tmem_xhandle tmem_xhandle_fill(uint16_t client_id, + struct tmem_pool *pool, + struct tmem_oid *oidp, + uint32_t index) +{ + struct tmem_xhandle xh; + xh.client_id = client_id; + xh.xh_data_cksum = (uint8_t)-1; + xh.xh_data_size = (uint16_t)-1; + xh.pool_id = pool->pool_id; + xh.oid = *oidp; + xh.index = index; + return xh; +} + static inline void tmem_oid_set_invalid(struct tmem_oid *oidp) { oidp->oid[0] = oidp->oid[1] = oidp->oid[2] = -1UL; @@ -147,7 +171,11 @@ struct tmem_obj { unsigned int objnode_tree_height; unsigned long objnode_count; long pampd_count; - void *extra; /* for private use by pampd implementation */ + /* for current design of ramster, all pages belonging to + * an object reside on the same remotenode and extra is + * used to record the number of the remotenode so a + * flush-object operation can specify it */ + void *extra; /* for use by pampd implementation */ DECL_SENTINEL }; @@ -174,9 +202,14 @@ struct tmem_pamops { int (*get_data_and_free)(char *, size_t *, bool, void *, struct tmem_pool *, struct tmem_oid *, uint32_t); - void (*free)(void *, struct tmem_pool *, struct tmem_oid *, uint32_t); + void (*free)(void *, struct tmem_pool *, + struct tmem_oid *, uint32_t, bool); void (*free_obj)(struct tmem_pool *, struct tmem_obj *); bool (*is_remote)(void *); + void *(*repatriate_preload)(void *, struct tmem_pool *, + struct tmem_oid *, uint32_t, bool *); + int (*repatriate)(void *, void *, struct tmem_pool *, + struct tmem_oid *, uint32_t, bool, void *); void (*new_obj)(struct tmem_obj *); int (*replace_in_obj)(void *, struct tmem_obj *); }; @@ -193,11 +226,16 @@ extern void tmem_register_hostops(struct tmem_hostops *m); /* core tmem accessor functions */ extern int tmem_put(struct tmem_pool *, struct tmem_oid *, uint32_t index, - char *, size_t, bool, bool); + char *, size_t, bool, int); extern int tmem_get(struct tmem_pool *, struct tmem_oid *, uint32_t index, char *, size_t *, bool, int); extern int tmem_replace(struct tmem_pool *, struct tmem_oid *, uint32_t index, void *); +extern void *tmem_localify_get_pampd(struct tmem_pool *, struct tmem_oid *, + uint32_t index, struct tmem_obj **, + void **); +extern void tmem_localify_finish(struct tmem_obj *, uint32_t index, + void *, void *, bool); extern int tmem_flush_page(struct tmem_pool *, struct tmem_oid *, uint32_t index); extern int tmem_flush_object(struct tmem_pool *, struct tmem_oid *); diff --git a/drivers/staging/ramster/zcache-main.c b/drivers/staging/ramster/zcache-main.c index 49c8791..851e94a 100644 --- a/drivers/staging/ramster/zcache-main.c +++ b/drivers/staging/ramster/zcache-main.c @@ -1,7 +1,7 @@ /* * zcache.c * - * Copyright (c) 2010,2011, Dan Magenheimer, Oracle Corp. + * Copyright (c) 2010-2012, Dan Magenheimer, Oracle Corp. * Copyright (c) 2010,2011, Nitin Gupta * * Zcache provides an in-kernel "host implementation" for transcendent memory @@ -17,6 +17,9 @@ * * [1] For a definition of page-accessible memory (aka PAM), see: * http://marc.info/?l=linux-mm&m=127811271605009 + * RAMSTER TODO: + * - handle remotifying of buddied pages (see zbud_remotify_zbpg) + * - kernel boot params: nocleancache/nofrontswap don't always work?!? */ #include @@ -30,11 +33,16 @@ #include #include #include "tmem.h" +#include "zcache.h" +#include "ramster.h" +#include "cluster/tcp.h" #include "../zram/xvmalloc.h" /* if built in drivers/staging */ +#define RAMSTER_TESTING + #if (!defined(CONFIG_CLEANCACHE) && !defined(CONFIG_FRONTSWAP)) -#error "zcache is useless without CONFIG_CLEANCACHE or CONFIG_FRONTSWAP" +#error "ramster is useless without CONFIG_CLEANCACHE or CONFIG_FRONTSWAP" #endif #ifdef CONFIG_CLEANCACHE #include @@ -43,6 +51,61 @@ #include #endif +enum ramster_remotify_op { + RAMSTER_REMOTIFY_EPH_PUT, + RAMSTER_REMOTIFY_PERS_PUT, + RAMSTER_REMOTIFY_FLUSH_PAGE, + RAMSTER_REMOTIFY_FLUSH_OBJ, + RAMSTER_INTRANSIT_PERS +}; + +struct ramster_remotify_hdr { + enum ramster_remotify_op op; + struct list_head list; +}; + +#define ZBH_SENTINEL 0x43214321 +#define ZBPG_SENTINEL 0xdeadbeef + +#define ZBUD_MAX_BUDS 2 + +struct zbud_hdr { + struct ramster_remotify_hdr rem_op; + uint16_t client_id; + uint16_t pool_id; + struct tmem_oid oid; + uint32_t index; + uint16_t size; /* compressed size in bytes, zero means unused */ + DECL_SENTINEL +}; + +#define ZVH_SENTINEL 0x43214321 +static const int zv_max_page_size = (PAGE_SIZE / 8) * 7; + +struct zv_hdr { + struct ramster_remotify_hdr rem_op; + uint16_t client_id; + uint16_t pool_id; + struct tmem_oid oid; + uint32_t index; + DECL_SENTINEL +}; + +struct flushlist_node { + struct ramster_remotify_hdr rem_op; + struct tmem_xhandle xh; +}; + +union { + struct ramster_remotify_hdr rem_op; + struct zv_hdr zv; + struct zbud_hdr zbud; + struct flushlist_node flist; +} remotify_list_node; + +static LIST_HEAD(zcache_rem_op_list); +static DEFINE_SPINLOCK(zcache_rem_op_list_lock); + #if 0 /* this is more aggressive but may cause other problems? */ #define ZCACHE_GFP_MASK (GFP_ATOMIC | __GFP_NORETRY | __GFP_NOWARN) @@ -98,20 +161,6 @@ static inline bool is_local_client(struct zcache_client *cli) * read or written unless the zbpg's lock is held. */ -#define ZBH_SENTINEL 0x43214321 -#define ZBPG_SENTINEL 0xdeadbeef - -#define ZBUD_MAX_BUDS 2 - -struct zbud_hdr { - uint16_t client_id; - uint16_t pool_id; - struct tmem_oid oid; - uint32_t index; - uint16_t size; /* compressed size in bytes, zero means unused */ - DECL_SENTINEL -}; - struct zbud_page { struct list_head bud_list; spinlock_t lock; @@ -141,20 +190,43 @@ static unsigned long zcache_zbud_buddied_count; /* protects the buddied list and all unbuddied lists */ static DEFINE_SPINLOCK(zbud_budlists_spinlock); -static LIST_HEAD(zbpg_unused_list); -static unsigned long zcache_zbpg_unused_list_count; - -/* protects the unused page list */ -static DEFINE_SPINLOCK(zbpg_unused_list_spinlock); - static atomic_t zcache_zbud_curr_raw_pages; static atomic_t zcache_zbud_curr_zpages; static unsigned long zcache_zbud_curr_zbytes; static unsigned long zcache_zbud_cumul_zpages; static unsigned long zcache_zbud_cumul_zbytes; static unsigned long zcache_compress_poor; +static unsigned long zcache_policy_percent_exceeded; static unsigned long zcache_mean_compress_poor; +/* + * RAMster counters + * - Remote pages are pages with a local pampd but the data is remote + * - Foreign pages are pages stored locally but belonging to another node + */ +static atomic_t ramster_remote_pers_pages = ATOMIC_INIT(0); +static unsigned long ramster_pers_remotify_enable; +static unsigned long ramster_eph_remotify_enable; +static unsigned long ramster_eph_pages_remoted; +static unsigned long ramster_eph_pages_remote_failed; +static unsigned long ramster_pers_pages_remoted; +static unsigned long ramster_pers_pages_remote_failed; +static unsigned long ramster_pers_pages_remote_nomem; +static unsigned long ramster_remote_objects_flushed; +static unsigned long ramster_remote_object_flushes_failed; +static unsigned long ramster_remote_pages_flushed; +static unsigned long ramster_remote_page_flushes_failed; +static unsigned long ramster_remote_eph_pages_succ_get; +static unsigned long ramster_remote_pers_pages_succ_get; +static unsigned long ramster_remote_eph_pages_unsucc_get; +static unsigned long ramster_remote_pers_pages_unsucc_get; +static atomic_t ramster_curr_flnode_count = ATOMIC_INIT(0); +static unsigned long ramster_curr_flnode_count_max; +static atomic_t ramster_foreign_eph_pampd_count = ATOMIC_INIT(0); +static unsigned long ramster_foreign_eph_pampd_count_max; +static atomic_t ramster_foreign_pers_pampd_count = ATOMIC_INIT(0); +static unsigned long ramster_foreign_pers_pampd_count_max; + /* forward references */ static void *zcache_get_free_page(void); static void zcache_free_page(void *p); @@ -210,6 +282,29 @@ static char *zbud_data(struct zbud_hdr *zh, unsigned size) return p; } +static void zbud_copy_from_pampd(char *data, size_t *size, struct zbud_hdr *zh) +{ + struct zbud_page *zbpg; + char *p; + unsigned budnum; + + ASSERT_SENTINEL(zh, ZBH); + budnum = zbud_budnum(zh); + zbpg = container_of(zh, struct zbud_page, buddy[budnum]); + spin_lock(&zbpg->lock); + BUG_ON(zh->size > *size); + p = (char *)zbpg; + if (budnum == 0) + p += ((sizeof(struct zbud_page) + CHUNK_SIZE - 1) & + CHUNK_MASK); + else if (budnum == 1) + p += PAGE_SIZE - ((zh->size + CHUNK_SIZE - 1) & CHUNK_MASK); + /* client should be filled in by caller */ + memcpy(data, p, zh->size); + *size = zh->size; + spin_unlock(&zbpg->lock); +} + /* * zbud raw page management */ @@ -218,38 +313,17 @@ static struct zbud_page *zbud_alloc_raw_page(void) { struct zbud_page *zbpg = NULL; struct zbud_hdr *zh0, *zh1; - bool recycled = 0; - - /* if any pages on the zbpg list, use one */ - spin_lock(&zbpg_unused_list_spinlock); - if (!list_empty(&zbpg_unused_list)) { - zbpg = list_first_entry(&zbpg_unused_list, - struct zbud_page, bud_list); - list_del_init(&zbpg->bud_list); - zcache_zbpg_unused_list_count--; - recycled = 1; - } - spin_unlock(&zbpg_unused_list_spinlock); - if (zbpg == NULL) - /* none on zbpg list, try to get a kernel page */ zbpg = zcache_get_free_page(); if (likely(zbpg != NULL)) { INIT_LIST_HEAD(&zbpg->bud_list); zh0 = &zbpg->buddy[0]; zh1 = &zbpg->buddy[1]; spin_lock_init(&zbpg->lock); - if (recycled) { - ASSERT_INVERTED_SENTINEL(zbpg, ZBPG); - SET_SENTINEL(zbpg, ZBPG); - BUG_ON(zh0->size != 0 || tmem_oid_valid(&zh0->oid)); - BUG_ON(zh1->size != 0 || tmem_oid_valid(&zh1->oid)); - } else { - atomic_inc(&zcache_zbud_curr_raw_pages); - INIT_LIST_HEAD(&zbpg->bud_list); - SET_SENTINEL(zbpg, ZBPG); - zh0->size = 0; zh1->size = 0; - tmem_oid_set_invalid(&zh0->oid); - tmem_oid_set_invalid(&zh1->oid); - } + atomic_inc(&zcache_zbud_curr_raw_pages); + INIT_LIST_HEAD(&zbpg->bud_list); + SET_SENTINEL(zbpg, ZBPG); + zh0->size = 0; zh1->size = 0; + tmem_oid_set_invalid(&zh0->oid); + tmem_oid_set_invalid(&zh1->oid); } return zbpg; } @@ -265,10 +339,8 @@ static void zbud_free_raw_page(struct zbud_page *zbpg) BUG_ON(zh1->size != 0 || tmem_oid_valid(&zh1->oid)); INVERT_SENTINEL(zbpg, ZBPG); spin_unlock(&zbpg->lock); - spin_lock(&zbpg_unused_list_spinlock); - list_add(&zbpg->bud_list, &zbpg_unused_list); - zcache_zbpg_unused_list_count++; - spin_unlock(&zbpg_unused_list_spinlock); + atomic_dec(&zcache_zbud_curr_raw_pages); + zcache_free_page(zbpg); } /* @@ -299,6 +371,10 @@ static void zbud_free_and_delist(struct zbud_hdr *zh) struct zbud_page *zbpg = container_of(zh, struct zbud_page, buddy[budnum]); + /* FIXME, should be BUG_ON, pool destruction path doesn't disable + * interrupts tmem_destroy_pool()->tmem_pampd_destroy_all_in_obj()-> + * tmem_objnode_node_destroy()-> zcache_pampd_free() */ + WARN_ON(!irqs_disabled()); spin_lock(&zbpg->lock); if (list_empty(&zbpg->bud_list)) { /* ignore zombie page... see zbud_evict_pages() */ @@ -358,8 +434,8 @@ static struct zbud_hdr *zbud_create(uint16_t client_id, uint16_t pool_id, if (unlikely(zbpg == NULL)) goto out; /* ok, have a page, now compress the data before taking locks */ - spin_lock(&zbpg->lock); spin_lock(&zbud_budlists_spinlock); + spin_lock(&zbpg->lock); list_add_tail(&zbpg->bud_list, &zbud_unbuddied[nchunks].list); zbud_unbuddied[nchunks].count++; zh = &zbpg->buddy[0]; @@ -389,12 +465,10 @@ init_zh: zh->oid = *oid; zh->pool_id = pool_id; zh->client_id = client_id; - /* can wait to copy the data until the list locks are dropped */ - spin_unlock(&zbud_budlists_spinlock); - to = zbud_data(zh, size); memcpy(to, cdata, size); spin_unlock(&zbpg->lock); + spin_unlock(&zbud_budlists_spinlock); zbud_cumul_chunk_counts[nchunks]++; atomic_inc(&zcache_zbud_curr_zpages); zcache_zbud_cumul_zpages++; @@ -458,9 +532,9 @@ static void zbud_evict_zbpg(struct zbud_page *zbpg) uint32_t index[ZBUD_MAX_BUDS]; struct tmem_oid oid[ZBUD_MAX_BUDS]; struct tmem_pool *pool; + unsigned long flags; ASSERT_SPINLOCK(&zbpg->lock); - BUG_ON(!list_empty(&zbpg->bud_list)); for (i = 0, j = 0; i < ZBUD_MAX_BUDS; i++) { zh = &zbpg->buddy[i]; if (zh->size) { @@ -469,20 +543,18 @@ static void zbud_evict_zbpg(struct zbud_page *zbpg) oid[j] = zh->oid; index[j] = zh->index; j++; - zbud_free(zh); } } spin_unlock(&zbpg->lock); for (i = 0; i < j; i++) { pool = zcache_get_pool_by_id(client_id[i], pool_id[i]); - if (pool != NULL) { - tmem_flush_page(pool, &oid[i], index[i]); - zcache_put_pool(pool); - } + BUG_ON(pool == NULL); + local_irq_save(flags); + /* these flushes should dispose of any local storage */ + tmem_flush_page(pool, &oid[i], index[i]); + local_irq_restore(flags); + zcache_put_pool(pool); } - ASSERT_SENTINEL(zbpg, ZBPG); - spin_lock(&zbpg->lock); - zbud_free_raw_page(zbpg); } /* @@ -496,26 +568,8 @@ static void zbud_evict_zbpg(struct zbud_page *zbpg) static void zbud_evict_pages(int nr) { struct zbud_page *zbpg; - int i; + int i, newly_unused_pages = 0; - /* first try freeing any pages on unused list */ -retry_unused_list: - spin_lock_bh(&zbpg_unused_list_spinlock); - if (!list_empty(&zbpg_unused_list)) { - /* can't walk list here, since it may change when unlocked */ - zbpg = list_first_entry(&zbpg_unused_list, - struct zbud_page, bud_list); - list_del_init(&zbpg->bud_list); - zcache_zbpg_unused_list_count--; - atomic_dec(&zcache_zbud_curr_raw_pages); - spin_unlock_bh(&zbpg_unused_list_spinlock); - zcache_free_page(zbpg); - zcache_evicted_raw_pages++; - if (--nr <= 0) - goto out; - goto retry_unused_list; - } - spin_unlock_bh(&zbpg_unused_list_spinlock); /* now try freeing unbuddied pages, starting with least space avail */ for (i = 0; i < MAX_CHUNK; i++) { @@ -528,15 +582,15 @@ retry_unbud_list_i: list_for_each_entry(zbpg, &zbud_unbuddied[i].list, bud_list) { if (unlikely(!spin_trylock(&zbpg->lock))) continue; - list_del_init(&zbpg->bud_list); zbud_unbuddied[i].count--; spin_unlock(&zbud_budlists_spinlock); zcache_evicted_unbuddied_pages++; /* want budlists unlocked when doing zbpg eviction */ zbud_evict_zbpg(zbpg); + newly_unused_pages++; local_bh_enable(); if (--nr <= 0) - goto out; + goto evict_unused; goto retry_unbud_list_i; } spin_unlock_bh(&zbud_budlists_spinlock); @@ -547,27 +601,406 @@ retry_bud_list: spin_lock_bh(&zbud_budlists_spinlock); if (list_empty(&zbud_buddied_list)) { spin_unlock_bh(&zbud_budlists_spinlock); - goto out; + goto evict_unused; } list_for_each_entry(zbpg, &zbud_buddied_list, bud_list) { if (unlikely(!spin_trylock(&zbpg->lock))) continue; - list_del_init(&zbpg->bud_list); zcache_zbud_buddied_count--; spin_unlock(&zbud_budlists_spinlock); zcache_evicted_buddied_pages++; /* want budlists unlocked when doing zbpg eviction */ zbud_evict_zbpg(zbpg); + newly_unused_pages++; local_bh_enable(); if (--nr <= 0) - goto out; + goto evict_unused; goto retry_bud_list; } spin_unlock_bh(&zbud_budlists_spinlock); + +evict_unused: + return; +} + +static DEFINE_PER_CPU(unsigned char *, zcache_remoteputmem); + +static int zbud_remotify_zbud(struct tmem_xhandle *xh, char *data, + size_t size) +{ + struct tmem_pool *pool; + int i, remotenode, ret = -1; + unsigned char cksum, *p; + unsigned long flags; + + for (p = data, cksum = 0, i = 0; i < size; i++) + cksum += *p; + ret = ramster_remote_put(xh, data, size, true, &remotenode); + if (ret == 0) { + /* data was successfully remoted so change the local version + * to point to the remote node where it landed */ + pool = zcache_get_pool_by_id(LOCAL_CLIENT, xh->pool_id); + BUG_ON(pool == NULL); + local_irq_save(flags); + /* tmem_replace will also free up any local space */ + (void)tmem_replace(pool, &xh->oid, xh->index, + pampd_make_remote(remotenode, size, cksum)); + local_irq_restore(flags); + zcache_put_pool(pool); + ramster_eph_pages_remoted++; + ret = 0; + } else + ramster_eph_pages_remote_failed++; + return ret; +} + +static int zbud_remotify_zbpg(struct zbud_page *zbpg) +{ + struct zbud_hdr *zh1, *zh2 = NULL; + struct tmem_xhandle xh1, xh2 = { 0 }; + char *data1 = NULL, *data2 = NULL; + size_t size1 = 0, size2 = 0; + int ret = 0; + unsigned char *tmpmem = __get_cpu_var(zcache_remoteputmem); + + ASSERT_SPINLOCK(&zbpg->lock); + if (zbpg->buddy[0].size == 0) + zh1 = &zbpg->buddy[1]; + else if (zbpg->buddy[1].size == 0) + zh1 = &zbpg->buddy[0]; + else { + zh1 = &zbpg->buddy[0]; + zh2 = &zbpg->buddy[1]; + } + /* don't remotify pages that are already remotified */ + if (zh1->client_id != LOCAL_CLIENT) + zh1 = NULL; + if ((zh2 != NULL) && (zh2->client_id != LOCAL_CLIENT)) + zh2 = NULL; + + /* copy the data and metadata so can release lock */ + if (zh1 != NULL) { + xh1.client_id = zh1->client_id; + xh1.pool_id = zh1->pool_id; + xh1.oid = zh1->oid; + xh1.index = zh1->index; + size1 = zh1->size; + data1 = zbud_data(zh1, size1); + memcpy(tmpmem, zbud_data(zh1, size1), size1); + data1 = tmpmem; + tmpmem += size1; + } + if (zh2 != NULL) { + xh2.client_id = zh2->client_id; + xh2.pool_id = zh2->pool_id; + xh2.oid = zh2->oid; + xh2.index = zh2->index; + size2 = zh2->size; + memcpy(tmpmem, zbud_data(zh2, size2), size2); + data2 = tmpmem; + } + spin_unlock(&zbpg->lock); + preempt_enable(); + + /* OK, no locks held anymore, remotify one or both zbuds */ + if (zh1 != NULL) + ret = zbud_remotify_zbud(&xh1, data1, size1); + if (zh2 != NULL) + ret |= zbud_remotify_zbud(&xh2, data2, size2); + return ret; +} + +void zbud_remotify_pages(int nr) +{ + struct zbud_page *zbpg; + int i, ret; + + /* + * for now just try remotifying unbuddied pages, starting with + * least space avail + */ + for (i = 0; i < MAX_CHUNK; i++) { +retry_unbud_list_i: + preempt_disable(); /* enable in zbud_remotify_zbpg */ + spin_lock_bh(&zbud_budlists_spinlock); + if (list_empty(&zbud_unbuddied[i].list)) { + spin_unlock_bh(&zbud_budlists_spinlock); + preempt_enable(); + continue; /* next i in for loop */ + } + list_for_each_entry(zbpg, &zbud_unbuddied[i].list, bud_list) { + if (unlikely(!spin_trylock(&zbpg->lock))) + continue; /* next list_for_each_entry */ + zbud_unbuddied[i].count--; + /* want budlists unlocked when doing zbpg remotify */ + spin_unlock_bh(&zbud_budlists_spinlock); + ret = zbud_remotify_zbpg(zbpg); + /* preemption is re-enabled in zbud_remotify_zbpg */ + if (ret == 0) { + if (--nr <= 0) + goto out; + goto retry_unbud_list_i; + } + /* if fail to remotify any page, quit */ + pr_err("TESTING zbud_remotify_pages failed on page," + " trying to re-add\n"); + spin_lock_bh(&zbud_budlists_spinlock); + spin_lock(&zbpg->lock); + list_add_tail(&zbpg->bud_list, &zbud_unbuddied[i].list); + zbud_unbuddied[i].count++; + spin_unlock(&zbpg->lock); + spin_unlock_bh(&zbud_budlists_spinlock); + pr_err("TESTING zbud_remotify_pages failed on page," + " finished re-add\n"); + goto out; + } + spin_unlock_bh(&zbud_budlists_spinlock); + preempt_enable(); + } + +next_buddied_zbpg: + preempt_disable(); /* enable in zbud_remotify_zbpg */ + spin_lock_bh(&zbud_budlists_spinlock); + if (list_empty(&zbud_buddied_list)) + goto unlock_out; + list_for_each_entry(zbpg, &zbud_buddied_list, bud_list) { + if (unlikely(!spin_trylock(&zbpg->lock))) + continue; /* next list_for_each_entry */ + zcache_zbud_buddied_count--; + /* want budlists unlocked when doing zbpg remotify */ + spin_unlock_bh(&zbud_budlists_spinlock); + ret = zbud_remotify_zbpg(zbpg); + /* preemption is re-enabled in zbud_remotify_zbpg */ + if (ret == 0) { + if (--nr <= 0) + goto out; + goto next_buddied_zbpg; + } + /* if fail to remotify any page, quit */ + pr_err("TESTING zbud_remotify_pages failed on BUDDIED page," + " trying to re-add\n"); + spin_lock_bh(&zbud_budlists_spinlock); + spin_lock(&zbpg->lock); + list_add_tail(&zbpg->bud_list, &zbud_buddied_list); + zcache_zbud_buddied_count++; + spin_unlock(&zbpg->lock); + spin_unlock_bh(&zbud_budlists_spinlock); + pr_err("TESTING zbud_remotify_pages failed on BUDDIED page," + " finished re-add\n"); + goto out; + } +unlock_out: + spin_unlock_bh(&zbud_budlists_spinlock); + preempt_enable(); out: return; } +/* the "flush list" asynchronously collects pages to remotely flush */ +#define FLUSH_ENTIRE_OBJECT ((uint32_t)-1) +static void ramster_flnode_free(struct flushlist_node *, + struct tmem_pool *); + +static void zcache_remote_flush_page(struct flushlist_node *flnode) +{ + struct tmem_xhandle *xh; + int remotenode, ret; + + preempt_disable(); + xh = &flnode->xh; + remotenode = flnode->xh.client_id; + ret = ramster_remote_flush(xh, remotenode); + if (ret >= 0) + ramster_remote_pages_flushed++; + else + ramster_remote_page_flushes_failed++; + preempt_enable_no_resched(); + ramster_flnode_free(flnode, NULL); +} + +static void zcache_remote_flush_object(struct flushlist_node *flnode) +{ + struct tmem_xhandle *xh; + int remotenode, ret; + + preempt_disable(); + xh = &flnode->xh; + remotenode = flnode->xh.client_id; + ret = ramster_remote_flush_object(xh, remotenode); + if (ret >= 0) + ramster_remote_objects_flushed++; + else + ramster_remote_object_flushes_failed++; + preempt_enable_no_resched(); + ramster_flnode_free(flnode, NULL); +} + +static void zcache_remote_eph_put(struct zbud_hdr *zbud) +{ + /* FIXME */ +} + +static void zcache_remote_pers_put(struct zv_hdr *zv) +{ + struct tmem_xhandle xh; + uint16_t size; + bool ephemeral; + int remotenode, ret = -1; + char *data; + struct tmem_pool *pool; + unsigned long flags; + unsigned char cksum; + char *p; + int i; + unsigned char *tmpmem = __get_cpu_var(zcache_remoteputmem); + + ASSERT_SENTINEL(zv, ZVH); + BUG_ON(zv->client_id != LOCAL_CLIENT); + local_bh_disable(); + xh.client_id = zv->client_id; + xh.pool_id = zv->pool_id; + xh.oid = zv->oid; + xh.index = zv->index; + size = xv_get_object_size(zv) - sizeof(*zv); + BUG_ON(size == 0 || size > zv_max_page_size); + data = (char *)zv + sizeof(*zv); + for (p = data, cksum = 0, i = 0; i < size; i++) + cksum += *p; + memcpy(tmpmem, data, size); + data = tmpmem; + pool = zcache_get_pool_by_id(zv->client_id, zv->pool_id); + ephemeral = is_ephemeral(pool); + zcache_put_pool(pool); + /* now OK to release lock set in caller */ + spin_unlock(&zcache_rem_op_list_lock); + local_bh_enable(); + preempt_disable(); + ret = ramster_remote_put(&xh, data, size, ephemeral, &remotenode); + preempt_enable_no_resched(); + if (ret != 0) { + /* + * This is some form of a memory leak... if the remote put + * fails, there will never be another attempt to remotify + * this page. But since we've dropped the zv pointer, + * the page may have been freed or the data replaced + * so we can't just "put it back" in the remote op list. + * Even if we could, not sure where to put it in the list + * because there may be flushes that must be strictly + * ordered vs the put. So leave this as a FIXME for now. + * But count them so we know if it becomes a problem. + */ + ramster_pers_pages_remote_failed++; + goto out; + } else + atomic_inc(&ramster_remote_pers_pages); + ramster_pers_pages_remoted++; + /* + * data was successfully remoted so change the local version to + * point to the remote node where it landed + */ + local_bh_disable(); + pool = zcache_get_pool_by_id(LOCAL_CLIENT, xh.pool_id); + local_irq_save(flags); + (void)tmem_replace(pool, &xh.oid, xh.index, + pampd_make_remote(remotenode, size, cksum)); + local_irq_restore(flags); + zcache_put_pool(pool); + local_bh_enable(); +out: + return; +} + +static void zcache_do_remotify_ops(int nr) +{ + struct ramster_remotify_hdr *rem_op; + union remotify_list_node *u; + + while (1) { + if (!nr) + goto out; + spin_lock(&zcache_rem_op_list_lock); + if (list_empty(&zcache_rem_op_list)) { + spin_unlock(&zcache_rem_op_list_lock); + goto out; + } + rem_op = list_first_entry(&zcache_rem_op_list, + struct ramster_remotify_hdr, list); + list_del_init(&rem_op->list); + if (rem_op->op != RAMSTER_REMOTIFY_PERS_PUT) + spin_unlock(&zcache_rem_op_list_lock); + u = (union remotify_list_node *)rem_op; + switch (rem_op->op) { + case RAMSTER_REMOTIFY_EPH_PUT: +BUG(); + zcache_remote_eph_put((struct zbud_hdr *)rem_op); + break; + case RAMSTER_REMOTIFY_PERS_PUT: + zcache_remote_pers_put((struct zv_hdr *)rem_op); + break; + case RAMSTER_REMOTIFY_FLUSH_PAGE: + zcache_remote_flush_page((struct flushlist_node *)u); + break; + case RAMSTER_REMOTIFY_FLUSH_OBJ: + zcache_remote_flush_object((struct flushlist_node *)u); + break; + default: + BUG(); + } + } +out: + return; +} + +/* + * For now, just push over a few pages every few seconds to + * ensure that it basically works + */ +static struct workqueue_struct *ramster_remotify_workqueue; +static void ramster_remotify_process(struct work_struct *work); +static DECLARE_DELAYED_WORK(ramster_remotify_worker, + ramster_remotify_process); + +static void ramster_remotify_queue_delayed_work(unsigned long delay) +{ + if (!queue_delayed_work(ramster_remotify_workqueue, + &ramster_remotify_worker, delay)) + pr_err("ramster_remotify: bad workqueue\n"); +} + + +static int use_frontswap; +static int use_cleancache; +static void ramster_remotify_process(struct work_struct *work) +{ + static bool remotify_in_progress; + + BUG_ON(irqs_disabled()); + if (remotify_in_progress) + ramster_remotify_queue_delayed_work(HZ); + else { + remotify_in_progress = true; +#ifdef CONFIG_CLEANCACHE + if (use_cleancache && ramster_eph_remotify_enable) + zbud_remotify_pages(5000); /* FIXME is this a good number? */ +#endif +#ifdef CONFIG_FRONTSWAP + if (use_frontswap && ramster_pers_remotify_enable) + zcache_do_remotify_ops(500); /* FIXME is this a good number? */ +#endif + remotify_in_progress = false; + ramster_remotify_queue_delayed_work(HZ); + } +} + +static void ramster_remotify_init(void) +{ + unsigned long n = 60UL; + ramster_remotify_workqueue = + create_singlethread_workqueue("ramster_remotify"); + ramster_remotify_queue_delayed_work(n * HZ); +} + + static void zbud_init(void) { int i; @@ -631,15 +1064,6 @@ static int zbud_show_cumul_chunk_counts(char *buf) * necessary for decompression) immediately preceding the compressed data. */ -#define ZVH_SENTINEL 0x43214321 - -struct zv_hdr { - uint32_t pool_id; - struct tmem_oid oid; - uint32_t index; - DECL_SENTINEL -}; - /* rudimentary policy limits */ /* total number of persistent pages may not exceed this percentage */ static unsigned int zv_page_count_policy_percent = 75; @@ -655,10 +1079,11 @@ static unsigned int zv_max_zsize = (PAGE_SIZE / 8) * 7; */ static unsigned int zv_max_mean_zsize = (PAGE_SIZE / 8) * 5; -static unsigned long zv_curr_dist_counts[NCHUNKS]; -static unsigned long zv_cumul_dist_counts[NCHUNKS]; +static atomic_t zv_curr_dist_counts[NCHUNKS]; +static atomic_t zv_cumul_dist_counts[NCHUNKS]; + -static struct zv_hdr *zv_create(struct xv_pool *xvpool, uint32_t pool_id, +static struct zv_hdr *zv_create(struct zcache_client *cli, uint32_t pool_id, struct tmem_oid *oid, uint32_t index, void *cdata, unsigned clen) { @@ -671,23 +1096,61 @@ static struct zv_hdr *zv_create(struct xv_pool *xvpool, uint32_t pool_id, BUG_ON(!irqs_disabled()); BUG_ON(chunks >= NCHUNKS); - ret = xv_malloc(xvpool, alloc_size, + ret = xv_malloc(cli->xvpool, clen + sizeof(struct zv_hdr), &page, &offset, ZCACHE_GFP_MASK); if (unlikely(ret)) goto out; - zv_curr_dist_counts[chunks]++; - zv_cumul_dist_counts[chunks]++; + atomic_inc(&zv_curr_dist_counts[chunks]); + atomic_inc(&zv_cumul_dist_counts[chunks]); zv = kmap_atomic(page, KM_USER0) + offset; zv->index = index; zv->oid = *oid; zv->pool_id = pool_id; SET_SENTINEL(zv, ZVH); + INIT_LIST_HEAD(&zv->rem_op.list); + zv->client_id = get_client_id_from_client(cli); + zv->rem_op.op = RAMSTER_REMOTIFY_PERS_PUT; + if (zv->client_id == LOCAL_CLIENT) { + spin_lock(&zcache_rem_op_list_lock); + list_add_tail(&zv->rem_op.list, &zcache_rem_op_list); + spin_unlock(&zcache_rem_op_list_lock); + } memcpy((char *)zv + sizeof(struct zv_hdr), cdata, clen); kunmap_atomic(zv, KM_USER0); out: return zv; } +/* similar to zv_create, but just reserve space, no data yet */ +static struct zv_hdr *zv_alloc(struct tmem_pool *pool, + struct tmem_oid *oid, uint32_t index, + unsigned clen) +{ + struct zcache_client *cli = pool->client; + struct page *page; + struct zv_hdr *zv = NULL; + uint32_t offset; + int ret; + + BUG_ON(!irqs_disabled()); + BUG_ON(!is_local_client(pool->client)); + ret = xv_malloc(cli->xvpool, clen + sizeof(struct zv_hdr), + &page, &offset, ZCACHE_GFP_MASK); + if (unlikely(ret)) + goto out; + zv = kmap_atomic(page, KM_USER0) + offset; + SET_SENTINEL(zv, ZVH); + INIT_LIST_HEAD(&zv->rem_op.list); + zv->client_id = LOCAL_CLIENT; + zv->rem_op.op = RAMSTER_INTRANSIT_PERS; + zv->index = index; + zv->oid = *oid; + zv->pool_id = pool->pool_id; + kunmap_atomic(zv, KM_USER0); +out: + return zv; +} + static void zv_free(struct xv_pool *xvpool, struct zv_hdr *zv) { unsigned long flags; @@ -698,10 +1161,15 @@ static void zv_free(struct xv_pool *xvpool, struct zv_hdr *zv) ASSERT_SENTINEL(zv, ZVH); BUG_ON(chunks >= NCHUNKS); - zv_curr_dist_counts[chunks]--; + atomic_dec(&zv_curr_dist_counts[chunks]); size -= sizeof(*zv); + spin_lock(&zcache_rem_op_list_lock); + size = xv_get_object_size(zv) - sizeof(*zv); BUG_ON(size == 0); INVERT_SENTINEL(zv, ZVH); + if (!list_empty(&zv->rem_op.list)) + list_del_init(&zv->rem_op.list); + spin_unlock(&zcache_rem_op_list_lock); page = virt_to_page(zv); offset = (unsigned long)zv & ~PAGE_MASK; local_irq_save(flags); @@ -727,6 +1195,29 @@ static void zv_decompress(struct page *page, struct zv_hdr *zv) BUG_ON(clen != PAGE_SIZE); } +static void zv_copy_from_pampd(char *data, size_t *bufsize, struct zv_hdr *zv) +{ + unsigned size; + + ASSERT_SENTINEL(zv, ZVH); + size = xv_get_object_size(zv) - sizeof(*zv); + BUG_ON(size == 0 || size > zv_max_page_size); + BUG_ON(size > *bufsize); + memcpy(data, (char *)zv + sizeof(*zv), size); + *bufsize = size; +} + +static void zv_copy_to_pampd(struct zv_hdr *zv, char *data, size_t size) +{ + unsigned zv_size; + + ASSERT_SENTINEL(zv, ZVH); + zv_size = xv_get_object_size(zv) - sizeof(*zv); + BUG_ON(zv_size != size); + BUG_ON(zv_size == 0 || zv_size > zv_max_page_size); + memcpy((char *)zv + sizeof(*zv), data, size); +} + #ifdef CONFIG_SYSFS /* * show a distribution of compression stats for zv pages. @@ -738,7 +1229,7 @@ static int zv_curr_dist_counts_show(char *buf) char *p = buf; for (i = 0; i < NCHUNKS; i++) { - n = zv_curr_dist_counts[i]; + n = atomic_read(&zv_curr_dist_counts[i]); p += sprintf(p, "%lu ", n); chunks += n; sum_total_chunks += i * n; @@ -754,7 +1245,7 @@ static int zv_cumul_dist_counts_show(char *buf) char *p = buf; for (i = 0; i < NCHUNKS; i++) { - n = zv_cumul_dist_counts[i]; + n = atomic_read(&zv_cumul_dist_counts[i]); p += sprintf(p, "%lu ", n); chunks += n; sum_total_chunks += i * n; @@ -890,6 +1381,7 @@ static unsigned long zcache_flush_found; static unsigned long zcache_flobj_total; static unsigned long zcache_flobj_found; static unsigned long zcache_failed_eph_puts; +static unsigned long zcache_nonactive_puts; static unsigned long zcache_failed_pers_puts; /* @@ -970,6 +1462,7 @@ static unsigned long zcache_put_to_flush; */ static struct kmem_cache *zcache_objnode_cache; static struct kmem_cache *zcache_obj_cache; +static struct kmem_cache *ramster_flnode_cache; static atomic_t zcache_curr_obj_count = ATOMIC_INIT(0); static unsigned long zcache_curr_obj_count_max; static atomic_t zcache_curr_objnode_count = ATOMIC_INIT(0); @@ -985,6 +1478,7 @@ struct zcache_preload { struct tmem_obj *obj; int nr; struct tmem_objnode *objnodes[OBJNODE_TREE_MAX_PATH]; + struct flushlist_node *flnode; }; static DEFINE_PER_CPU(struct zcache_preload, zcache_preloads) = { 0, }; @@ -993,6 +1487,7 @@ static int zcache_do_preload(struct tmem_pool *pool) struct zcache_preload *kp; struct tmem_objnode *objnode; struct tmem_obj *obj; + struct flushlist_node *flnode; void *page; int ret = -ENOMEM; @@ -1023,27 +1518,61 @@ static int zcache_do_preload(struct tmem_pool *pool) zcache_failed_alloc++; goto out; } - page = (void *)__get_free_page(ZCACHE_GFP_MASK); - if (unlikely(page == NULL)) { - zcache_failed_get_free_pages++; - kmem_cache_free(zcache_obj_cache, obj); + flnode = kmem_cache_alloc(ramster_flnode_cache, ZCACHE_GFP_MASK); + if (unlikely(flnode == NULL)) { + zcache_failed_alloc++; goto out; } + if (is_ephemeral(pool)) { + page = (void *)__get_free_page(ZCACHE_GFP_MASK); + if (unlikely(page == NULL)) { + zcache_failed_get_free_pages++; + kmem_cache_free(zcache_obj_cache, obj); + kmem_cache_free(ramster_flnode_cache, flnode); + goto out; + } + } preempt_disable(); kp = &__get_cpu_var(zcache_preloads); if (kp->obj == NULL) kp->obj = obj; else kmem_cache_free(zcache_obj_cache, obj); - if (kp->page == NULL) - kp->page = page; + if (kp->flnode == NULL) + kp->flnode = flnode; else - free_page((unsigned long)page); + kmem_cache_free(ramster_flnode_cache, flnode); + if (is_ephemeral(pool)) { + if (kp->page == NULL) + kp->page = page; + else + free_page((unsigned long)page); + } ret = 0; out: return ret; } +static int ramster_do_preload_flnode_only(struct tmem_pool *pool) +{ + struct zcache_preload *kp; + struct flushlist_node *flnode; + int ret = -ENOMEM; + + BUG_ON(!irqs_disabled()); + if (unlikely(ramster_flnode_cache == NULL)) + BUG(); + kp = &__get_cpu_var(zcache_preloads); + flnode = kmem_cache_alloc(ramster_flnode_cache, GFP_ATOMIC); + if (unlikely(flnode == NULL) && kp->flnode == NULL) + BUG(); /* FIXME handle more gracefully, but how??? */ + else if (kp->flnode == NULL) + kp->flnode = flnode; + else + kmem_cache_free(ramster_flnode_cache, flnode); + return ret; +} + static void *zcache_get_free_page(void) { struct zcache_preload *kp; @@ -1116,6 +1645,30 @@ static void zcache_obj_free(struct tmem_obj *obj, struct tmem_pool *pool) kmem_cache_free(zcache_obj_cache, obj); } +static struct flushlist_node *ramster_flnode_alloc(struct tmem_pool *pool) +{ + struct flushlist_node *flnode = NULL; + struct zcache_preload *kp; + int count; + + kp = &__get_cpu_var(zcache_preloads); + flnode = kp->flnode; + BUG_ON(flnode == NULL); + kp->flnode = NULL; + count = atomic_inc_return(&ramster_curr_flnode_count); + if (count > ramster_curr_flnode_count_max) + ramster_curr_flnode_count_max = count; + return flnode; +} + +static void ramster_flnode_free(struct flushlist_node *flnode, + struct tmem_pool *pool) +{ + atomic_dec(&ramster_curr_flnode_count); + BUG_ON(atomic_read(&ramster_curr_flnode_count) < 0); + kmem_cache_free(ramster_flnode_cache, flnode); +} + static struct tmem_hostops zcache_hostops = { .obj_alloc = zcache_obj_alloc, .obj_free = zcache_obj_free, @@ -1135,22 +1688,20 @@ static unsigned long zcache_curr_pers_pampd_count_max; /* forward reference */ static int zcache_compress(struct page *from, void **out_va, size_t *out_len); -static void *zcache_pampd_create(char *data, size_t size, bool raw, int eph, +static int zcache_pampd_eph_create(char *data, size_t size, bool raw, struct tmem_pool *pool, struct tmem_oid *oid, - uint32_t index) + uint32_t index, void **pampd) { - void *pampd = NULL, *cdata; - size_t clen; - int ret; - unsigned long count; - struct page *page = (struct page *)(data); + int ret = -1; + void *cdata = data; + size_t clen = size; struct zcache_client *cli = pool->client; uint16_t client_id = get_client_id_from_client(cli); - unsigned long zv_mean_zsize; - unsigned long curr_pers_pampd_count; - u64 total_zsize; + struct page *page = NULL; + unsigned long count; - if (eph) { + if (!raw) { + page = virt_to_page(data); ret = zcache_compress(page, &cdata, &clen); if (ret == 0) goto out; @@ -1158,46 +1709,114 @@ static void *zcache_pampd_create(char *data, size_t size, bool raw, int eph, zcache_compress_poor++; goto out; } - pampd = (void *)zbud_create(client_id, pool->pool_id, oid, - index, page, cdata, clen); - if (pampd != NULL) { - count = atomic_inc_return(&zcache_curr_eph_pampd_count); - if (count > zcache_curr_eph_pampd_count_max) - zcache_curr_eph_pampd_count_max = count; - } - } else { - curr_pers_pampd_count = - atomic_read(&zcache_curr_pers_pampd_count); - if (curr_pers_pampd_count > - (zv_page_count_policy_percent * totalram_pages) / 100) - goto out; - ret = zcache_compress(page, &cdata, &clen); - if (ret == 0) - goto out; - /* reject if compression is too poor */ - if (clen > zv_max_zsize) { - zcache_compress_poor++; + } + *pampd = (void *)zbud_create(client_id, pool->pool_id, oid, + index, page, cdata, clen); + if (*pampd == NULL) { + ret = -ENOMEM; + goto out; + } + ret = 0; + count = atomic_inc_return(&zcache_curr_eph_pampd_count); + if (count > zcache_curr_eph_pampd_count_max) + zcache_curr_eph_pampd_count_max = count; + if (client_id != LOCAL_CLIENT) { + count = atomic_inc_return(&ramster_foreign_eph_pampd_count); + if (count > ramster_foreign_eph_pampd_count_max) + ramster_foreign_eph_pampd_count_max = count; + } +out: + return ret; +} + +static int zcache_pampd_pers_create(char *data, size_t size, bool raw, + struct tmem_pool *pool, struct tmem_oid *oid, + uint32_t index, void **pampd) +{ + int ret = -1; + void *cdata = data; + size_t clen = size; + struct zcache_client *cli = pool->client; + struct page *page; + unsigned long count; + unsigned long zv_mean_zsize; + struct zv_hdr *zv; + long curr_pers_pampd_count; + u64 total_zsize; +#ifdef RAMSTER_TESTING + static bool pampd_neg_warned; +#endif + + curr_pers_pampd_count = atomic_read(&zcache_curr_pers_pampd_count) - + atomic_read(&ramster_remote_pers_pages); +#ifdef RAMSTER_TESTING + /* should always be positive, but warn if accounting is off */ + if (!pampd_neg_warned) { + pr_warn("ramster: bad accounting for curr_pers_pampd_count\n"); + pampd_neg_warned = true; + } +#endif + if (curr_pers_pampd_count > + (zv_page_count_policy_percent * totalram_pages) / 100) { + zcache_policy_percent_exceeded++; + goto out; + } + if (raw) + goto ok_to_create; + page = virt_to_page(data); + if (zcache_compress(page, &cdata, &clen) == 0) + goto out; + /* reject if compression is too poor */ + if (clen > zv_max_zsize) { + zcache_compress_poor++; + goto out; + } + /* reject if mean compression is too poor */ + if ((clen > zv_max_mean_zsize) && (curr_pers_pampd_count > 0)) { + total_zsize = xv_get_total_size_bytes(cli->xvpool); + zv_mean_zsize = div_u64(total_zsize, curr_pers_pampd_count); + if (zv_mean_zsize > zv_max_mean_zsize) { + zcache_mean_compress_poor++; goto out; } - /* reject if mean compression is too poor */ - if ((clen > zv_max_mean_zsize) && (curr_pers_pampd_count > 0)) { - total_zsize = xv_get_total_size_bytes(cli->xvpool); - zv_mean_zsize = div_u64(total_zsize, - curr_pers_pampd_count); - if (zv_mean_zsize > zv_max_mean_zsize) { - zcache_mean_compress_poor++; - goto out; - } - } - pampd = (void *)zv_create(cli->xvpool, pool->pool_id, - oid, index, cdata, clen); - if (pampd == NULL) - goto out; - count = atomic_inc_return(&zcache_curr_pers_pampd_count); - if (count > zcache_curr_pers_pampd_count_max) - zcache_curr_pers_pampd_count_max = count; } +ok_to_create: + *pampd = (void *)zv_create(cli, pool->pool_id, oid, index, cdata, clen); + if (*pampd == NULL) { + ret = -ENOMEM; + goto out; + } + ret = 0; + count = atomic_inc_return(&zcache_curr_pers_pampd_count); + if (count > zcache_curr_pers_pampd_count_max) + zcache_curr_pers_pampd_count_max = count; + if (is_local_client(cli)) + goto out; + zv = *(struct zv_hdr **)pampd; + count = atomic_inc_return(&ramster_foreign_pers_pampd_count); + if (count > ramster_foreign_pers_pampd_count_max) + ramster_foreign_pers_pampd_count_max = count; out: + return ret; +} + +static void *zcache_pampd_create(char *data, size_t size, bool raw, int eph, + struct tmem_pool *pool, struct tmem_oid *oid, + uint32_t index) +{ + void *pampd = NULL; + int ret; + bool ephemeral; + + BUG_ON(preemptible()); + ephemeral = (eph == 1) || ((eph == 0) && is_ephemeral(pool)); + if (ephemeral) + ret = zcache_pampd_eph_create(data, size, raw, pool, + oid, index, &pampd); + else + ret = zcache_pampd_pers_create(data, size, raw, pool, + oid, index, &pampd); + /* FIXME add some counters here for failed creates? */ return pampd; } @@ -1211,75 +1830,359 @@ static int zcache_pampd_get_data(char *data, size_t *bufsize, bool raw, { int ret = 0; - BUG_ON(is_ephemeral(pool)); - zv_decompress((struct page *)(data), pampd); + BUG_ON(preemptible()); + BUG_ON(is_ephemeral(pool)); /* Fix later for shared pools? */ + BUG_ON(pampd_is_remote(pampd)); + if (raw) + zv_copy_from_pampd(data, bufsize, pampd); + else + zv_decompress(virt_to_page(data), pampd); return ret; } -/* - * fill the pageframe corresponding to the struct page with the data - * from the passed pampd - */ static int zcache_pampd_get_data_and_free(char *data, size_t *bufsize, bool raw, void *pampd, struct tmem_pool *pool, struct tmem_oid *oid, uint32_t index) { int ret = 0; + unsigned long flags; + struct zcache_client *cli = pool->client; - BUG_ON(!is_ephemeral(pool)); - zbud_decompress((struct page *)(data), pampd); - zbud_free_and_delist((struct zbud_hdr *)pampd); - atomic_dec(&zcache_curr_eph_pampd_count); + BUG_ON(preemptible()); + BUG_ON(pampd_is_remote(pampd)); + if (is_ephemeral(pool)) { + local_irq_save(flags); + if (raw) + zbud_copy_from_pampd(data, bufsize, pampd); + else + ret = zbud_decompress(virt_to_page(data), pampd); + zbud_free_and_delist((struct zbud_hdr *)pampd); + local_irq_restore(flags); + if (!is_local_client(cli)) { + atomic_dec(&ramster_foreign_eph_pampd_count); + WARN_ON_ONCE(atomic_read(&ramster_foreign_eph_pampd_count) < 0); + } + atomic_dec(&zcache_curr_eph_pampd_count); + WARN_ON_ONCE(atomic_read(&zcache_curr_eph_pampd_count) < 0); + } else { + if (is_local_client(cli)) + BUG(); + if (raw) + zv_copy_from_pampd(data, bufsize, pampd); + else + zv_decompress(virt_to_page(data), pampd); + zv_free(cli->xvpool, pampd); + if (!is_local_client(cli)) { + atomic_dec(&ramster_foreign_pers_pampd_count); + WARN_ON_ONCE(atomic_read(&ramster_foreign_pers_pampd_count) < 0); + } + atomic_dec(&zcache_curr_pers_pampd_count); + WARN_ON_ONCE(atomic_read(&zcache_curr_pers_pampd_count) < 0); + ret = 0; + } return ret; } +static bool zcache_pampd_is_remote(void *pampd) +{ + return pampd_is_remote(pampd); +} + /* * free the pampd and remove it from any zcache lists * pampd must no longer be pointed to from any tmem data structures! */ static void zcache_pampd_free(void *pampd, struct tmem_pool *pool, - struct tmem_oid *oid, uint32_t index) + struct tmem_oid *oid, uint32_t index, bool acct) { struct zcache_client *cli = pool->client; - - if (is_ephemeral(pool)) { + bool eph = is_ephemeral(pool); + struct zv_hdr *zv; + + BUG_ON(preemptible()); + if (pampd_is_remote(pampd)) { + WARN_ON(acct == false); + if (oid == NULL) { + /* + * a NULL oid means to ignore this pampd free + * as the remote freeing will be handled elsewhere + */ + } else if (eph) { + /* FIXME remote flush optional but probably good idea */ + /* FIXME get these working properly again */ + atomic_dec(&zcache_curr_eph_pampd_count); + WARN_ON_ONCE(atomic_read(&zcache_curr_eph_pampd_count) < 0); + } else if (pampd_is_intransit(pampd)) { + /* did a pers remote get_and_free, so just free local */ + pampd = pampd_mask_intransit_and_remote(pampd); + goto local_pers; + } else { + struct flushlist_node *flnode = + ramster_flnode_alloc(pool); + + flnode->xh.client_id = pampd_remote_node(pampd); + flnode->xh.pool_id = pool->pool_id; + flnode->xh.oid = *oid; + flnode->xh.index = index; + flnode->rem_op.op = RAMSTER_REMOTIFY_FLUSH_PAGE; + spin_lock(&zcache_rem_op_list_lock); + list_add(&flnode->rem_op.list, &zcache_rem_op_list); + spin_unlock(&zcache_rem_op_list_lock); + atomic_dec(&zcache_curr_pers_pampd_count); + WARN_ON_ONCE(atomic_read(&zcache_curr_pers_pampd_count) < 0); + atomic_dec(&ramster_remote_pers_pages); + WARN_ON_ONCE(atomic_read(&ramster_remote_pers_pages) < 0); + } + } else if (eph) { zbud_free_and_delist((struct zbud_hdr *)pampd); - atomic_dec(&zcache_curr_eph_pampd_count); - BUG_ON(atomic_read(&zcache_curr_eph_pampd_count) < 0); + if (!is_local_client(pool->client)) { + atomic_dec(&ramster_foreign_eph_pampd_count); + WARN_ON_ONCE(atomic_read(&ramster_foreign_eph_pampd_count) < 0); + } + if (acct) + atomic_dec(&zcache_curr_eph_pampd_count); + /* FIXME get these working properly again */ + WARN_ON_ONCE(atomic_read(&zcache_curr_eph_pampd_count) < 0); } else { - zv_free(cli->xvpool, (struct zv_hdr *)pampd); - atomic_dec(&zcache_curr_pers_pampd_count); - BUG_ON(atomic_read(&zcache_curr_pers_pampd_count) < 0); +local_pers: + zv = (struct zv_hdr *)pampd; + if (!is_local_client(pool->client)) { + atomic_dec(&ramster_foreign_pers_pampd_count); + WARN_ON_ONCE(atomic_read(&ramster_foreign_pers_pampd_count) < 0); + } + zv_free(cli->xvpool, zv); + if (acct) + atomic_dec(&zcache_curr_pers_pampd_count); + /* FIXME get these working properly again */ + WARN_ON_ONCE(atomic_read(&zcache_curr_pers_pampd_count) < 0); } } -static void zcache_pampd_free_obj(struct tmem_pool *pool, struct tmem_obj *obj) +static void zcache_pampd_free_obj(struct tmem_pool *pool, + struct tmem_obj *obj) { + struct flushlist_node *flnode; + + BUG_ON(preemptible()); + if (obj->extra == NULL) + return; + BUG_ON(!pampd_is_remote(obj->extra)); + flnode = ramster_flnode_alloc(pool); + flnode->xh.client_id = pampd_remote_node(obj->extra); + flnode->xh.pool_id = pool->pool_id; + flnode->xh.oid = obj->oid; + flnode->xh.index = FLUSH_ENTIRE_OBJECT; + flnode->rem_op.op = RAMSTER_REMOTIFY_FLUSH_OBJ; + spin_lock(&zcache_rem_op_list_lock); + list_add(&flnode->rem_op.list, &zcache_rem_op_list); + spin_unlock(&zcache_rem_op_list_lock); } -static void zcache_pampd_new_obj(struct tmem_obj *obj) +void zcache_pampd_new_obj(struct tmem_obj *obj) { + obj->extra = NULL; } -static int zcache_pampd_replace_in_obj(void *pampd, struct tmem_obj *obj) +int zcache_pampd_replace_in_obj(void *new_pampd, struct tmem_obj *obj) { - return -1; + int ret = -1; + + if (new_pampd != NULL) { + if (obj->extra == NULL) + obj->extra = new_pampd; + /* enforce that all remote pages in an object reside + * in the same node! */ + else if (pampd_remote_node(new_pampd) != + pampd_remote_node((void *)(obj->extra))) + BUG(); + ret = 0; + } + return ret; } -static bool zcache_pampd_is_remote(void *pampd) +/* + * Called by the message handler after a (still compressed) page has been + * fetched from the remote machine in response to an "is_remote" tmem_get + * or persistent tmem_localify. For a tmem_get, "extra" is the address of + * the page that is to be filled to succesfully resolve the tmem_get; for + * a (persistent) tmem_localify, "extra" is NULL (as the data is placed only + * in the local zcache). "data" points to "size" bytes of (compressed) data + * passed in the message. In the case of a persistent remote get, if + * pre-allocation was successful (see zcache_repatriate_preload), the page + * is placed into both local zcache and at "extra". + */ +int zcache_localify(int pool_id, struct tmem_oid *oidp, + uint32_t index, char *data, size_t size, + void *extra) { - return 0; + int ret = -ENOENT; + unsigned long flags; + struct tmem_pool *pool; + bool ephemeral, delete = false; + size_t clen = PAGE_SIZE; + void *pampd, *saved_hb; + struct tmem_obj *obj; + + pool = zcache_get_pool_by_id(LOCAL_CLIENT, pool_id); + if (unlikely(pool == NULL)) + /* pool doesn't exist anymore */ + goto out; + ephemeral = is_ephemeral(pool); + local_irq_save(flags); /* FIXME: maybe only disable softirqs? */ + pampd = tmem_localify_get_pampd(pool, oidp, index, &obj, &saved_hb); + if (pampd == NULL) { + /* hmmm... must have been a flush while waiting */ +#ifdef RAMSTER_TESTING + pr_err("UNTESTED pampd==NULL in zcache_localify\n"); +#endif + if (ephemeral) + ramster_remote_eph_pages_unsucc_get++; + else + ramster_remote_pers_pages_unsucc_get++; + obj = NULL; + goto finish; + } else if (unlikely(!pampd_is_remote(pampd))) { + /* hmmm... must have been a dup put while waiting */ +#ifdef RAMSTER_TESTING + pr_err("UNTESTED dup while waiting in zcache_localify\n"); +#endif + if (ephemeral) + ramster_remote_eph_pages_unsucc_get++; + else + ramster_remote_pers_pages_unsucc_get++; + obj = NULL; + pampd = NULL; + ret = -EEXIST; + goto finish; + } else if (size == 0) { + /* no remote data, delete the local is_remote pampd */ + pampd = NULL; + if (ephemeral) + ramster_remote_eph_pages_unsucc_get++; + else + BUG(); + delete = true; + goto finish; + } + if (!ephemeral && pampd_is_intransit(pampd)) { + /* localify to zcache */ + pampd = pampd_mask_intransit_and_remote(pampd); + zv_copy_to_pampd(pampd, data, size); + } else { + pampd = NULL; + obj = NULL; + } + if (extra != NULL) { + /* decompress direct-to-memory to complete remotify */ + ret = lzo1x_decompress_safe((char *)data, size, + (char *)extra, &clen); + BUG_ON(ret != LZO_E_OK); + BUG_ON(clen != PAGE_SIZE); + } + if (ephemeral) + ramster_remote_eph_pages_succ_get++; + else + ramster_remote_pers_pages_succ_get++; + ret = 0; +finish: + tmem_localify_finish(obj, index, pampd, saved_hb, delete); + zcache_put_pool(pool); + local_irq_restore(flags); +out: + return ret; +} + +/* + * Called on a remote persistent tmem_get to attempt to preallocate + * local storage for the data contained in the remote persistent page. + * If succesfully preallocated, returns the pampd, marked as remote and + * in_transit. Else returns NULL. Note that the appropriate tmem data + * structure must be locked. + */ +static void *zcache_pampd_repatriate_preload(void *pampd, + struct tmem_pool *pool, + struct tmem_oid *oid, + uint32_t index, + bool *intransit) +{ + int clen = pampd_remote_size(pampd); + void *ret_pampd = NULL; + unsigned long flags; + + if (!pampd_is_remote(pampd)) + BUG(); + if (is_ephemeral(pool)) + BUG(); + if (pampd_is_intransit(pampd)) { + /* + * to avoid multiple allocations (and maybe a memory leak) + * don't preallocate if already in the process of being + * repatriated + */ + *intransit = true; + goto out; + } + *intransit = false; + local_irq_save(flags); + ret_pampd = (void *)zv_alloc(pool, oid, index, clen); + if (ret_pampd != NULL) { + /* + * a pampd is marked intransit if it is remote and space has + * been allocated for it locally (note, only happens for + * persistent pages, in which case the remote copy is freed) + */ + ret_pampd = pampd_mark_intransit(ret_pampd); + atomic_dec(&ramster_remote_pers_pages); + WARN_ON_ONCE(atomic_read(&ramster_remote_pers_pages) < 0); + } else + ramster_pers_pages_remote_nomem++; + local_irq_restore(flags); +out: + return ret_pampd; +} + +/* + * Called on a remote tmem_get to invoke a message to fetch the page. + * Might sleep so no tmem locks can be held. "extra" is passed + * all the way through the round-trip messaging to zcache_localify. + */ +static int zcache_pampd_repatriate(void *fake_pampd, void *real_pampd, + struct tmem_pool *pool, + struct tmem_oid *oid, uint32_t index, + bool free, void *extra) +{ + struct tmem_xhandle xh; + int ret; + + if (pampd_is_intransit(real_pampd)) + /* have local space pre-reserved, so free remote copy */ + free = true; + xh = tmem_xhandle_fill(LOCAL_CLIENT, pool, oid, index); + /* unreliable request/response for now */ + ret = ramster_remote_async_get(&xh, free, + pampd_remote_node(fake_pampd), + pampd_remote_size(fake_pampd), + pampd_remote_cksum(fake_pampd), + extra); +#ifdef RAMSTER_TESTING + if (ret != 0 && ret != -ENOENT) + pr_err("TESTING zcache_pampd_repatriate returns, ret=%d\n", + ret); +#endif + return ret; } static struct tmem_pamops zcache_pamops = { .create = zcache_pampd_create, .get_data = zcache_pampd_get_data, - .get_data_and_free = zcache_pampd_get_data_and_free, .free = zcache_pampd_free, + .get_data_and_free = zcache_pampd_get_data_and_free, .free_obj = zcache_pampd_free_obj, + .is_remote = zcache_pampd_is_remote, + .repatriate_preload = zcache_pampd_repatriate_preload, + .repatriate = zcache_pampd_repatriate, .new_obj = zcache_pampd_new_obj, .replace_in_obj = zcache_pampd_replace_in_obj, - .is_remote = zcache_pampd_is_remote, }; /* @@ -1327,9 +2230,13 @@ static int zcache_cpu_notifier(struct notifier_block *nb, per_cpu(zcache_workmem, cpu) = kzalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL | __GFP_REPEAT); + per_cpu(zcache_remoteputmem, cpu) = + kzalloc(PAGE_SIZE, GFP_KERNEL | __GFP_REPEAT); break; case CPU_DEAD: case CPU_UP_CANCELED: + kfree(per_cpu(zcache_remoteputmem, cpu)); + per_cpu(zcache_remoteputmem, cpu) = NULL; free_pages((unsigned long)per_cpu(zcache_dstmem, cpu), LZO_DSTMEM_PAGE_ORDER); per_cpu(zcache_dstmem, cpu) = NULL; @@ -1346,6 +2253,10 @@ static int zcache_cpu_notifier(struct notifier_block *nb, kmem_cache_free(zcache_obj_cache, kp->obj); kp->obj = NULL; } + if (kp->flnode) { + kmem_cache_free(ramster_flnode_cache, kp->flnode); + kp->flnode = NULL; + } if (kp->page) { free_page((unsigned long)kp->page); kp->page = NULL; @@ -1402,12 +2313,12 @@ ZCACHE_SYSFS_RO(flush_found); ZCACHE_SYSFS_RO(flobj_total); ZCACHE_SYSFS_RO(flobj_found); ZCACHE_SYSFS_RO(failed_eph_puts); +ZCACHE_SYSFS_RO(nonactive_puts); ZCACHE_SYSFS_RO(failed_pers_puts); ZCACHE_SYSFS_RO(zbud_curr_zbytes); ZCACHE_SYSFS_RO(zbud_cumul_zpages); ZCACHE_SYSFS_RO(zbud_cumul_zbytes); ZCACHE_SYSFS_RO(zbud_buddied_count); -ZCACHE_SYSFS_RO(zbpg_unused_list_count); ZCACHE_SYSFS_RO(evicted_raw_pages); ZCACHE_SYSFS_RO(evicted_unbuddied_pages); ZCACHE_SYSFS_RO(evicted_buddied_pages); @@ -1416,6 +2327,7 @@ ZCACHE_SYSFS_RO(failed_alloc); ZCACHE_SYSFS_RO(put_to_flush); ZCACHE_SYSFS_RO(compress_poor); ZCACHE_SYSFS_RO(mean_compress_poor); +ZCACHE_SYSFS_RO(policy_percent_exceeded); ZCACHE_SYSFS_RO_ATOMIC(zbud_curr_raw_pages); ZCACHE_SYSFS_RO_ATOMIC(zbud_curr_zpages); ZCACHE_SYSFS_RO_ATOMIC(curr_obj_count); @@ -1439,7 +2351,9 @@ static struct attribute *zcache_attrs[] = { &zcache_flush_found_attr.attr, &zcache_flobj_found_attr.attr, &zcache_failed_eph_puts_attr.attr, + &zcache_nonactive_puts_attr.attr, &zcache_failed_pers_puts_attr.attr, + &zcache_policy_percent_exceeded_attr.attr, &zcache_compress_poor_attr.attr, &zcache_mean_compress_poor_attr.attr, &zcache_zbud_curr_raw_pages_attr.attr, @@ -1448,7 +2362,6 @@ static struct attribute *zcache_attrs[] = { &zcache_zbud_cumul_zpages_attr.attr, &zcache_zbud_cumul_zbytes_attr.attr, &zcache_zbud_buddied_count_attr.attr, - &zcache_zbpg_unused_list_count_attr.attr, &zcache_evicted_raw_pages_attr.attr, &zcache_evicted_unbuddied_pages_attr.attr, &zcache_evicted_buddied_pages_attr.attr, @@ -1470,6 +2383,150 @@ static struct attribute_group zcache_attr_group = { .name = "zcache", }; +#define RAMSTER_SYSFS_RO(_name) \ + static ssize_t ramster_##_name##_show(struct kobject *kobj, \ + struct kobj_attribute *attr, char *buf) \ + { \ + return sprintf(buf, "%lu\n", ramster_##_name); \ + } \ + static struct kobj_attribute ramster_##_name##_attr = { \ + .attr = { .name = __stringify(_name), .mode = 0444 }, \ + .show = ramster_##_name##_show, \ + } + +#define RAMSTER_SYSFS_RW(_name) \ + static ssize_t ramster_##_name##_show(struct kobject *kobj, \ + struct kobj_attribute *attr, char *buf) \ + { \ + return sprintf(buf, "%lu\n", ramster_##_name); \ + } \ + static ssize_t ramster_##_name##_store(struct kobject *kobj, \ + struct kobj_attribute *attr, const char *buf, size_t count) \ + { \ + int err; \ + unsigned long enable; \ + err = strict_strtoul(buf, 10, &enable); \ + if (err) \ + return -EINVAL; \ + ramster_##_name = enable; \ + return count; \ + } \ + static struct kobj_attribute ramster_##_name##_attr = { \ + .attr = { .name = __stringify(_name), .mode = 0644 }, \ + .show = ramster_##_name##_show, \ + .store = ramster_##_name##_store, \ + } + +#define RAMSTER_SYSFS_RO_ATOMIC(_name) \ + static ssize_t ramster_##_name##_show(struct kobject *kobj, \ + struct kobj_attribute *attr, char *buf) \ + { \ + return sprintf(buf, "%d\n", atomic_read(&ramster_##_name)); \ + } \ + static struct kobj_attribute ramster_##_name##_attr = { \ + .attr = { .name = __stringify(_name), .mode = 0444 }, \ + .show = ramster_##_name##_show, \ + } + +RAMSTER_SYSFS_RO_ATOMIC(remote_pers_pages); +RAMSTER_SYSFS_RW(pers_remotify_enable); +RAMSTER_SYSFS_RW(eph_remotify_enable); +RAMSTER_SYSFS_RO(eph_pages_remoted); +RAMSTER_SYSFS_RO(eph_pages_remote_failed); +RAMSTER_SYSFS_RO(pers_pages_remoted); +RAMSTER_SYSFS_RO(pers_pages_remote_failed); +RAMSTER_SYSFS_RO(pers_pages_remote_nomem); +RAMSTER_SYSFS_RO(remote_pages_flushed); +RAMSTER_SYSFS_RO(remote_page_flushes_failed); +RAMSTER_SYSFS_RO(remote_objects_flushed); +RAMSTER_SYSFS_RO(remote_object_flushes_failed); +RAMSTER_SYSFS_RO(remote_eph_pages_succ_get); +RAMSTER_SYSFS_RO(remote_eph_pages_unsucc_get); +RAMSTER_SYSFS_RO(remote_pers_pages_succ_get); +RAMSTER_SYSFS_RO(remote_pers_pages_unsucc_get); +RAMSTER_SYSFS_RO_ATOMIC(foreign_eph_pampd_count); +RAMSTER_SYSFS_RO(foreign_eph_pampd_count_max); +RAMSTER_SYSFS_RO_ATOMIC(foreign_pers_pampd_count); +RAMSTER_SYSFS_RO(foreign_pers_pampd_count_max); +RAMSTER_SYSFS_RO_ATOMIC(curr_flnode_count); +RAMSTER_SYSFS_RO(curr_flnode_count_max); + +#define MANUAL_NODES 8 +static bool ramster_nodes_manual_up[MANUAL_NODES]; +static ssize_t ramster_manual_node_up_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + int i; + char *p = buf; + for (i = 0; i < MANUAL_NODES; i++) + if (ramster_nodes_manual_up[i]) + p += sprintf(p, "%d ", i); + p += sprintf(p, "\n"); + return p - buf; +} + +static ssize_t ramster_manual_node_up_store(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, size_t count) +{ + int err; + unsigned long node_num; + + err = strict_strtoul(buf, 10, &node_num); + if (err) { + pr_err("bad strtoul?\n"); + return -EINVAL; + } + if (node_num >= MANUAL_NODES) { + pr_err("bad node_num=%lu?\n", node_num); + return -EINVAL; + } + if (ramster_nodes_manual_up[node_num]) { + pr_err("node %d already up, ignoring\n", (int)node_num); + } else { + ramster_nodes_manual_up[node_num] = true; + o2net_hb_node_up_manual((int)node_num); + } + return count; +} + +static struct kobj_attribute ramster_manual_node_up_attr = { + .attr = { .name = "manual_node_up", .mode = 0644 }, + .show = ramster_manual_node_up_show, + .store = ramster_manual_node_up_store, +}; + +static struct attribute *ramster_attrs[] = { + &ramster_pers_remotify_enable_attr.attr, + &ramster_eph_remotify_enable_attr.attr, + &ramster_remote_pers_pages_attr.attr, + &ramster_eph_pages_remoted_attr.attr, + &ramster_eph_pages_remote_failed_attr.attr, + &ramster_pers_pages_remoted_attr.attr, + &ramster_pers_pages_remote_failed_attr.attr, + &ramster_pers_pages_remote_nomem_attr.attr, + &ramster_remote_pages_flushed_attr.attr, + &ramster_remote_page_flushes_failed_attr.attr, + &ramster_remote_objects_flushed_attr.attr, + &ramster_remote_object_flushes_failed_attr.attr, + &ramster_remote_eph_pages_succ_get_attr.attr, + &ramster_remote_eph_pages_unsucc_get_attr.attr, + &ramster_remote_pers_pages_succ_get_attr.attr, + &ramster_remote_pers_pages_unsucc_get_attr.attr, + &ramster_foreign_eph_pampd_count_attr.attr, + &ramster_foreign_eph_pampd_count_max_attr.attr, + &ramster_foreign_pers_pampd_count_attr.attr, + &ramster_foreign_pers_pampd_count_max_attr.attr, + &ramster_curr_flnode_count_attr.attr, + &ramster_curr_flnode_count_max_attr.attr, + &ramster_manual_node_up_attr.attr, + NULL, +}; + +static struct attribute_group ramster_attr_group = { + .attrs = ramster_attrs, + .name = "ramster", +}; + #endif /* CONFIG_SYSFS */ /* * When zcache is disabled ("frozen"), pools can be created and destroyed, @@ -1510,8 +2567,9 @@ static struct shrinker zcache_shrinker = { * zcache shims between cleancache/frontswap ops and tmem */ -static int zcache_put_page(int cli_id, int pool_id, struct tmem_oid *oidp, - uint32_t index, struct page *page) +int zcache_put(int cli_id, int pool_id, struct tmem_oid *oidp, + uint32_t index, char *data, size_t size, + bool raw, int ephemeral) { struct tmem_pool *pool; int ret = -1; @@ -1522,8 +2580,7 @@ static int zcache_put_page(int cli_id, int pool_id, struct tmem_oid *oidp, goto out; if (!zcache_freeze && zcache_do_preload(pool) == 0) { /* preload does preempt_disable on success */ - ret = tmem_put(pool, oidp, index, (char *)(page), - PAGE_SIZE, 0, is_ephemeral(pool)); + ret = tmem_put(pool, oidp, index, data, size, raw, ephemeral); if (ret < 0) { if (is_ephemeral(pool)) zcache_failed_eph_puts++; @@ -1543,27 +2600,38 @@ out: return ret; } -static int zcache_get_page(int cli_id, int pool_id, struct tmem_oid *oidp, - uint32_t index, struct page *page) +int zcache_get(int cli_id, int pool_id, struct tmem_oid *oidp, + uint32_t index, char *data, size_t *sizep, + bool raw, int get_and_free) { struct tmem_pool *pool; int ret = -1; - unsigned long flags; - size_t size = PAGE_SIZE; + bool eph; - local_irq_save(flags); + if (!raw) { + BUG_ON(irqs_disabled()); + BUG_ON(in_softirq()); + } pool = zcache_get_pool_by_id(cli_id, pool_id); + eph = is_ephemeral(pool); if (likely(pool != NULL)) { if (atomic_read(&pool->obj_count) > 0) - ret = tmem_get(pool, oidp, index, (char *)(page), - &size, 0, is_ephemeral(pool)); + ret = tmem_get(pool, oidp, index, data, sizep, + raw, get_and_free); zcache_put_pool(pool); } - local_irq_restore(flags); + WARN_ONCE((!eph && (ret != 0)), "zcache_get fails on persistent pool, " + "bad things are very likely to happen soon\n"); +#ifdef RAMSTER_TESTING + if (ret != 0 && ret != -1 && !(ret == -EINVAL && is_ephemeral(pool))) + pr_err("TESTING zcache_get tmem_get returns ret=%d\n", ret); +#endif + if (ret == -EAGAIN) + BUG(); /* FIXME... don't need this anymore??? let's ensure */ return ret; } -static int zcache_flush_page(int cli_id, int pool_id, +int zcache_flush(int cli_id, int pool_id, struct tmem_oid *oidp, uint32_t index) { struct tmem_pool *pool; @@ -1573,6 +2641,7 @@ static int zcache_flush_page(int cli_id, int pool_id, local_irq_save(flags); zcache_flush_total++; pool = zcache_get_pool_by_id(cli_id, pool_id); + ramster_do_preload_flnode_only(pool); if (likely(pool != NULL)) { if (atomic_read(&pool->obj_count) > 0) ret = tmem_flush_page(pool, oidp, index); @@ -1584,8 +2653,7 @@ static int zcache_flush_page(int cli_id, int pool_id, return ret; } -static int zcache_flush_object(int cli_id, int pool_id, - struct tmem_oid *oidp) +int zcache_flush_object(int cli_id, int pool_id, struct tmem_oid *oidp) { struct tmem_pool *pool; int ret = -1; @@ -1594,6 +2662,7 @@ static int zcache_flush_object(int cli_id, int pool_id, local_irq_save(flags); zcache_flobj_total++; pool = zcache_get_pool_by_id(cli_id, pool_id); + ramster_do_preload_flnode_only(pool); if (likely(pool != NULL)) { if (atomic_read(&pool->obj_count) > 0) ret = tmem_flush_object(pool, oidp); @@ -1605,7 +2674,7 @@ static int zcache_flush_object(int cli_id, int pool_id, return ret; } -static int zcache_destroy_pool(int cli_id, int pool_id) +int zcache_client_destroy_pool(int cli_id, int pool_id) { struct tmem_pool *pool = NULL; struct zcache_client *cli = NULL; @@ -1632,13 +2701,17 @@ static int zcache_destroy_pool(int cli_id, int pool_id) ret = tmem_destroy_pool(pool); local_bh_enable(); kfree(pool); - pr_info("zcache: destroyed pool id=%d, cli_id=%d\n", - pool_id, cli_id); + pr_info("ramster: destroyed pool id=%d cli_id=%d\n", pool_id, cli_id); out: return ret; } -static int zcache_new_pool(uint16_t cli_id, uint32_t flags) +static int zcache_destroy_pool(int pool_id) +{ + return zcache_client_destroy_pool(LOCAL_CLIENT, pool_id); +} + +int zcache_new_pool(uint16_t cli_id, uint32_t flags) { int poolid = -1; struct tmem_pool *pool; @@ -1653,7 +2726,7 @@ static int zcache_new_pool(uint16_t cli_id, uint32_t flags) atomic_inc(&cli->refcount); pool = kmalloc(sizeof(struct tmem_pool), GFP_ATOMIC); if (pool == NULL) { - pr_info("zcache: pool creation failed: out of memory\n"); + pr_info("ramster: pool creation failed: out of memory\n"); goto out; } @@ -1661,7 +2734,7 @@ static int zcache_new_pool(uint16_t cli_id, uint32_t flags) if (cli->tmem_pools[poolid] == NULL) break; if (poolid >= MAX_POOLS_PER_CLIENT) { - pr_info("zcache: pool creation failed: max exceeded\n"); + pr_info("ramster: pool creation failed: max exceeded\n"); kfree(pool); poolid = -1; goto out; @@ -1671,7 +2744,7 @@ static int zcache_new_pool(uint16_t cli_id, uint32_t flags) pool->pool_id = poolid; tmem_new_pool(pool, flags); cli->tmem_pools[poolid] = pool; - pr_info("zcache: created %s tmem pool, id=%d, client=%d\n", + pr_info("ramster: created %s tmem pool, id=%d, client=%d\n", flags & TMEM_POOL_PERSIST ? "persistent" : "ephemeral", poolid, cli_id); out: @@ -1680,6 +2753,64 @@ out: return poolid; } +static int zcache_local_new_pool(uint32_t flags) +{ + return zcache_new_pool(LOCAL_CLIENT, flags); +} + +int zcache_autocreate_pool(int cli_id, int pool_id, bool ephemeral) +{ + struct tmem_pool *pool; + struct zcache_client *cli = NULL; + uint32_t flags = ephemeral ? 0 : TMEM_POOL_PERSIST; + int ret = -1; + + if (cli_id == LOCAL_CLIENT) + goto out; + if (pool_id >= MAX_POOLS_PER_CLIENT) + goto out; + else if ((unsigned int)cli_id < MAX_CLIENTS) + cli = &zcache_clients[cli_id]; + if ((ephemeral && !use_cleancache) || (!ephemeral && !use_frontswap)) + BUG(); /* FIXME, handle more gracefully later */ + if (!cli->allocated) { + if (zcache_new_client(cli_id)) + BUG(); /* FIXME, handle more gracefully later */ + cli = &zcache_clients[cli_id]; + } + atomic_inc(&cli->refcount); + pool = cli->tmem_pools[pool_id]; + if (pool != NULL) { + if (pool->persistent && ephemeral) { + pr_err("zcache_autocreate_pool: type mismatch\n"); + goto out; + } + ret = 0; + goto out; + } + pool = kmalloc(sizeof(struct tmem_pool), GFP_KERNEL); + if (pool == NULL) { + pr_info("ramster: pool creation failed: out of memory\n"); + goto out; + } + atomic_set(&pool->refcount, 0); + pool->client = cli; + pool->pool_id = pool_id; + tmem_new_pool(pool, flags); + cli->tmem_pools[pool_id] = pool; + pr_info("ramster: AUTOcreated %s tmem poolid=%d, for remote client=%d\n", + flags & TMEM_POOL_PERSIST ? "persistent" : "ephemeral", + pool_id, cli_id); + ret = 0; +out: + if (cli == NULL) + BUG(); /* FIXME, handle more gracefully later */ + /* pr_err("zcache_autocreate_pool: failed\n"); */ + if (cli != NULL) + atomic_dec(&cli->refcount); + return ret; +} + /********** * Two kernel functionalities currently can be layered on top of tmem. * These are "cleancache" which is used as a second-chance cache for clean @@ -1696,8 +2827,18 @@ static void zcache_cleancache_put_page(int pool_id, u32 ind = (u32) index; struct tmem_oid oid = *(struct tmem_oid *)&key; - if (likely(ind == index)) - (void)zcache_put_page(LOCAL_CLIENT, pool_id, &oid, index, page); +#ifdef __PG_WAS_ACTIVE + if (!PageWasActive(page)) { + zcache_nonactive_puts++; + return; + } +#endif + if (likely(ind == index)) { + char *kva = page_address(page); + + (void)zcache_put(LOCAL_CLIENT, pool_id, &oid, index, + kva, PAGE_SIZE, 0, 1); + } } static int zcache_cleancache_get_page(int pool_id, @@ -1708,8 +2849,19 @@ static int zcache_cleancache_get_page(int pool_id, struct tmem_oid oid = *(struct tmem_oid *)&key; int ret = -1; - if (likely(ind == index)) - ret = zcache_get_page(LOCAL_CLIENT, pool_id, &oid, index, page); + preempt_disable(); + if (likely(ind == index)) { + char *kva = page_address(page); + size_t size = PAGE_SIZE; + + ret = zcache_get(LOCAL_CLIENT, pool_id, &oid, index, + kva, &size, 0, 0); +#ifdef __PG_WAS_ACTIVE + if (ret == 0) + SetPageWasActive(page); +#endif + } + preempt_enable(); return ret; } @@ -1721,7 +2873,7 @@ static void zcache_cleancache_flush_page(int pool_id, struct tmem_oid oid = *(struct tmem_oid *)&key; if (likely(ind == index)) - (void)zcache_flush_page(LOCAL_CLIENT, pool_id, &oid, ind); + (void)zcache_flush(LOCAL_CLIENT, pool_id, &oid, ind); } static void zcache_cleancache_flush_inode(int pool_id, @@ -1735,7 +2887,7 @@ static void zcache_cleancache_flush_inode(int pool_id, static void zcache_cleancache_flush_fs(int pool_id) { if (pool_id >= 0) - (void)zcache_destroy_pool(LOCAL_CLIENT, pool_id); + (void)zcache_destroy_pool(pool_id); } static int zcache_cleancache_init_fs(size_t pagesize) @@ -1743,7 +2895,7 @@ static int zcache_cleancache_init_fs(size_t pagesize) BUG_ON(sizeof(struct cleancache_filekey) != sizeof(struct tmem_oid)); BUG_ON(pagesize != PAGE_SIZE); - return zcache_new_pool(LOCAL_CLIENT, 0); + return zcache_local_new_pool(0); } static int zcache_cleancache_init_shared_fs(char *uuid, size_t pagesize) @@ -1752,7 +2904,7 @@ static int zcache_cleancache_init_shared_fs(char *uuid, size_t pagesize) BUG_ON(sizeof(struct cleancache_filekey) != sizeof(struct tmem_oid)); BUG_ON(pagesize != PAGE_SIZE); - return zcache_new_pool(LOCAL_CLIENT, 0); + return zcache_local_new_pool(0); } static struct cleancache_ops zcache_cleancache_ops = { @@ -1781,10 +2933,8 @@ static int zcache_frontswap_poolid = -1; /* * Swizzling increases objects per swaptype, increasing tmem concurrency * for heavy swaploads. Later, larger nr_cpus -> larger SWIZ_BITS - * Setting SWIZ_BITS to 27 basically reconstructs the swap entry from - * frontswap_get_page() */ -#define SWIZ_BITS 27 +#define SWIZ_BITS 8 #define SWIZ_MASK ((1 << SWIZ_BITS) - 1) #define _oswiz(_type, _ind) ((_type << SWIZ_BITS) | (_ind & SWIZ_MASK)) #define iswiz(_ind) (_ind >> SWIZ_BITS) @@ -1804,12 +2954,14 @@ static int zcache_frontswap_put_page(unsigned type, pgoff_t offset, struct tmem_oid oid = oswiz(type, ind); int ret = -1; unsigned long flags; + char *kva; BUG_ON(!PageLocked(page)); if (likely(ind64 == ind)) { local_irq_save(flags); - ret = zcache_put_page(LOCAL_CLIENT, zcache_frontswap_poolid, - &oid, iswiz(ind), page); + kva = page_address(page); + ret = zcache_put(LOCAL_CLIENT, zcache_frontswap_poolid, + &oid, iswiz(ind), kva, PAGE_SIZE, 0, 0); local_irq_restore(flags); } return ret; @@ -1825,10 +2977,16 @@ static int zcache_frontswap_get_page(unsigned type, pgoff_t offset, struct tmem_oid oid = oswiz(type, ind); int ret = -1; + preempt_disable(); /* FIXME, remove this? */ BUG_ON(!PageLocked(page)); - if (likely(ind64 == ind)) - ret = zcache_get_page(LOCAL_CLIENT, zcache_frontswap_poolid, - &oid, iswiz(ind), page); + if (likely(ind64 == ind)) { + char *kva = page_address(page); + size_t size = PAGE_SIZE; + + ret = zcache_get(LOCAL_CLIENT, zcache_frontswap_poolid, + &oid, iswiz(ind), kva, &size, 0, -1); + } + preempt_enable(); /* FIXME, remove this? */ return ret; } @@ -1840,7 +2998,7 @@ static void zcache_frontswap_flush_page(unsigned type, pgoff_t offset) struct tmem_oid oid = oswiz(type, ind); if (likely(ind64 == ind)) - (void)zcache_flush_page(LOCAL_CLIENT, zcache_frontswap_poolid, + (void)zcache_flush(LOCAL_CLIENT, zcache_frontswap_poolid, &oid, iswiz(ind)); } @@ -1862,7 +3020,7 @@ static void zcache_frontswap_init(unsigned ignored) /* a single tmem poolid is used for all frontswap "types" (swapfiles) */ if (zcache_frontswap_poolid < 0) zcache_frontswap_poolid = - zcache_new_pool(LOCAL_CLIENT, TMEM_POOL_PERSIST); + zcache_local_new_pool(TMEM_POOL_PERSIST); } static struct frontswap_ops zcache_frontswap_ops = { @@ -1883,19 +3041,125 @@ struct frontswap_ops zcache_frontswap_register_ops(void) #endif /* + * frontswap selfshrinking + */ + +#ifdef CONFIG_FRONTSWAP +/* In HZ, controls frequency of worker invocation. */ +static unsigned int selfshrink_interval __read_mostly = 5; + +static void selfshrink_process(struct work_struct *work); +static DECLARE_DELAYED_WORK(selfshrink_worker, selfshrink_process); + +/* Enable/disable with sysfs. */ +static bool frontswap_selfshrinking __read_mostly; + +/* Enable/disable with kernel boot option. */ +static bool use_frontswap_selfshrink __initdata = true; + +/* + * The default values for the following parameters were deemed reasonable + * by experimentation, may be workload-dependent, and can all be + * adjusted via sysfs. + */ + +/* Control rate for frontswap shrinking. Higher hysteresis is slower. */ +static unsigned int frontswap_hysteresis __read_mostly = 20; + +/* + * Number of selfshrink worker invocations to wait before observing that + * frontswap selfshrinking should commence. Note that selfshrinking does + * not use a separate worker thread. + */ +static unsigned int frontswap_inertia __read_mostly = 3; + +/* Countdown to next invocation of frontswap_shrink() */ +static unsigned long frontswap_inertia_counter; + +/* + * Invoked by the selfshrink worker thread, uses current number of pages + * in frontswap (frontswap_curr_pages()), previous status, and control + * values (hysteresis and inertia) to determine if frontswap should be + * shrunk and what the new frontswap size should be. Note that + * frontswap_shrink is essentially a partial swapoff that immediately + * transfers pages from the "swap device" (frontswap) back into kernel + * RAM; despite the name, frontswap "shrinking" is very different from + * the "shrinker" interface used by the kernel MM subsystem to reclaim + * memory. + */ +static void frontswap_selfshrink(void) +{ + static unsigned long cur_frontswap_pages; + static unsigned long last_frontswap_pages; + static unsigned long tgt_frontswap_pages; + + last_frontswap_pages = cur_frontswap_pages; + cur_frontswap_pages = frontswap_curr_pages(); + if (!cur_frontswap_pages || + (cur_frontswap_pages > last_frontswap_pages)) { + frontswap_inertia_counter = frontswap_inertia; + return; + } + if (frontswap_inertia_counter && --frontswap_inertia_counter) + return; + if (cur_frontswap_pages <= frontswap_hysteresis) + tgt_frontswap_pages = 0; + else + tgt_frontswap_pages = cur_frontswap_pages - + (cur_frontswap_pages / frontswap_hysteresis); + frontswap_shrink(tgt_frontswap_pages); +} + +static int __init ramster_nofrontswap_selfshrink_setup(char *s) +{ + use_frontswap_selfshrink = false; + return 1; +} + +__setup("noselfshrink", ramster_nofrontswap_selfshrink_setup); + +static void selfshrink_process(struct work_struct *work) +{ + if (frontswap_selfshrinking && frontswap_enabled) { + frontswap_selfshrink(); + schedule_delayed_work(&selfshrink_worker, + selfshrink_interval * HZ); + } +} + +static int ramster_enabled; + +static int __init ramster_selfshrink_init(void) +{ + frontswap_selfshrinking = ramster_enabled && use_frontswap_selfshrink; + if (frontswap_selfshrinking) + pr_info("ramster: Initializing frontswap " + "selfshrinking driver.\n"); + else + return -ENODEV; + + schedule_delayed_work(&selfshrink_worker, selfshrink_interval * HZ); + + return 0; +} + +subsys_initcall(ramster_selfshrink_init); +#endif + +/* * zcache initialization - * NOTE FOR NOW zcache MUST BE PROVIDED AS A KERNEL BOOT PARAMETER OR + * NOTE FOR NOW ramster MUST BE PROVIDED AS A KERNEL BOOT PARAMETER OR * NOTHING HAPPENS! */ -static int zcache_enabled; +static int ramster_enabled; -static int __init enable_zcache(char *s) +static int __init enable_ramster(char *s) { - zcache_enabled = 1; + ramster_enabled = 1; return 1; } -__setup("zcache", enable_zcache); +__setup("ramster", enable_ramster); /* allow independent dynamic disabling of cleancache and frontswap */ @@ -1903,16 +3167,22 @@ static int use_cleancache = 1; static int __init no_cleancache(char *s) { + pr_info("INIT no_cleancache called\n"); use_cleancache = 0; return 1; } -__setup("nocleancache", no_cleancache); +/* + * FIXME: need to guarantee this gets checked before zcache_init is called + * What is the correct way to achieve this? + */ +early_param("nocleancache", no_cleancache); static int use_frontswap = 1; static int __init no_frontswap(char *s) { + pr_info("INIT no_frontswap called\n"); use_frontswap = 0; return 1; } @@ -1925,20 +3195,22 @@ static int __init zcache_init(void) #ifdef CONFIG_SYSFS ret = sysfs_create_group(mm_kobj, &zcache_attr_group); + ret = sysfs_create_group(mm_kobj, &ramster_attr_group); if (ret) { - pr_err("zcache: can't create sysfs\n"); + pr_err("ramster: can't create sysfs\n"); goto out; } #endif /* CONFIG_SYSFS */ #if defined(CONFIG_CLEANCACHE) || defined(CONFIG_FRONTSWAP) - if (zcache_enabled) { + if (ramster_enabled) { unsigned int cpu; + (void)ramster_o2net_register_handlers(); tmem_register_hostops(&zcache_hostops); tmem_register_pamops(&zcache_pamops); ret = register_cpu_notifier(&zcache_cpu_notifier_block); if (ret) { - pr_err("zcache: can't register cpu notifier\n"); + pr_err("ramster: can't register cpu notifier\n"); goto out; } for_each_online_cpu(cpu) { @@ -1951,35 +3223,39 @@ static int __init zcache_init(void) sizeof(struct tmem_objnode), 0, 0, NULL); zcache_obj_cache = kmem_cache_create("zcache_obj", sizeof(struct tmem_obj), 0, 0, NULL); - ret = zcache_new_client(LOCAL_CLIENT); - if (ret) { - pr_err("zcache: can't create client\n"); - goto out; - } + ramster_flnode_cache = kmem_cache_create("ramster_flnode", + sizeof(struct flushlist_node), 0, 0, NULL); #endif #ifdef CONFIG_CLEANCACHE - if (zcache_enabled && use_cleancache) { + pr_info("INIT ramster_enabled=%d use_cleancache=%d\n", + ramster_enabled, use_cleancache); + if (ramster_enabled && use_cleancache) { struct cleancache_ops old_ops; zbud_init(); register_shrinker(&zcache_shrinker); old_ops = zcache_cleancache_register_ops(); - pr_info("zcache: cleancache enabled using kernel " + pr_info("ramster: cleancache enabled using kernel " "transcendent memory and compression buddies\n"); if (old_ops.init_fs != NULL) - pr_warning("zcache: cleancache_ops overridden"); + pr_warning("ramster: cleancache_ops overridden"); } #endif #ifdef CONFIG_FRONTSWAP - if (zcache_enabled && use_frontswap) { + pr_info("INIT ramster_enabled=%d use_frontswap=%d\n", + ramster_enabled, use_frontswap); + if (ramster_enabled && use_frontswap) { struct frontswap_ops old_ops; + zcache_new_client(LOCAL_CLIENT); old_ops = zcache_frontswap_register_ops(); - pr_info("zcache: frontswap enabled using kernel " + pr_info("ramster: frontswap enabled using kernel " "transcendent memory and xvmalloc\n"); if (old_ops.init != NULL) - pr_warning("zcache: frontswap_ops overridden"); + pr_warning("ramster: frontswap_ops overridden"); } + if (ramster_enabled && (use_frontswap || use_cleancache)) + ramster_remotify_init(); #endif out: return ret; -- cgit v0.10.2 From 14a3cd58dd4fa10df8d84b37efae1e92962ad372 Mon Sep 17 00:00:00 2001 From: Dan Magenheimer Date: Mon, 30 Jan 2012 14:39:19 -0800 Subject: staging: ramster: ramster-specific new files New files for ramster support: The file ramster.h declares externs and some pampd bitfield manipulation. The file zcache.h declares some zcache functions that now must be accessed from the ramster glue code. The file ramster_o2net.c is the glue between zcache and the o2net messaging code, providing routines called from zcache that initiate messages, and routines that handle messages by calling zcache. TODO explains future plans for merging. Signed-off-by: Dan Magenheimer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/ramster/TODO b/drivers/staging/ramster/TODO new file mode 100644 index 0000000..d4268f0 --- /dev/null +++ b/drivers/staging/ramster/TODO @@ -0,0 +1,9 @@ +For this staging driver, RAMster duplicates code from fs/ocfs2/cluster +and from drivers/staging/zcache, then incorporates changes to the local +copy of the code. Before RAMster can be promoted from staging, this code +duplication must be resolved. Specifically, we will first need to work with +the ocfs2 maintainers to split out the ocfs2 core cluster code so that +it can be easily included by another subsystem, even if ocfs2 is not +configured, and also to merge the handful of functional changes required. +Second, the zcache and RAMster drivers should be either merged or reorganized +to separate out common code. diff --git a/drivers/staging/ramster/ramster.h b/drivers/staging/ramster/ramster.h new file mode 100644 index 0000000..3293512 --- /dev/null +++ b/drivers/staging/ramster/ramster.h @@ -0,0 +1,117 @@ +/* + * ramster.h + * + * Peer-to-peer transcendent memory + * + * Copyright (c) 2009-2012, Dan Magenheimer, Oracle Corp. + */ + +#ifndef _RAMSTER_H_ +#define _RAMSTER_H_ + +/* + * format of remote pampd: + * bit 0 == intransit + * bit 1 == is_remote... if this bit is set, then + * bit 2-9 == remotenode + * bit 10-22 == size + * bit 23-30 == cksum + */ +#define FAKE_PAMPD_INTRANSIT_BITS 1 +#define FAKE_PAMPD_ISREMOTE_BITS 1 +#define FAKE_PAMPD_REMOTENODE_BITS 8 +#define FAKE_PAMPD_REMOTESIZE_BITS 13 +#define FAKE_PAMPD_CHECKSUM_BITS 8 + +#define FAKE_PAMPD_INTRANSIT_SHIFT 0 +#define FAKE_PAMPD_ISREMOTE_SHIFT (FAKE_PAMPD_INTRANSIT_SHIFT + \ + FAKE_PAMPD_INTRANSIT_BITS) +#define FAKE_PAMPD_REMOTENODE_SHIFT (FAKE_PAMPD_ISREMOTE_SHIFT + \ + FAKE_PAMPD_ISREMOTE_BITS) +#define FAKE_PAMPD_REMOTESIZE_SHIFT (FAKE_PAMPD_REMOTENODE_SHIFT + \ + FAKE_PAMPD_REMOTENODE_BITS) +#define FAKE_PAMPD_CHECKSUM_SHIFT (FAKE_PAMPD_REMOTESIZE_SHIFT + \ + FAKE_PAMPD_REMOTESIZE_BITS) + +#define FAKE_PAMPD_MASK(x) ((1UL << (x)) - 1) + +static inline void *pampd_make_remote(int remotenode, size_t size, + unsigned char cksum) +{ + unsigned long fake_pampd = 0; + fake_pampd |= 1UL << FAKE_PAMPD_ISREMOTE_SHIFT; + fake_pampd |= ((unsigned long)remotenode & + FAKE_PAMPD_MASK(FAKE_PAMPD_REMOTENODE_BITS)) << + FAKE_PAMPD_REMOTENODE_SHIFT; + fake_pampd |= ((unsigned long)size & + FAKE_PAMPD_MASK(FAKE_PAMPD_REMOTESIZE_BITS)) << + FAKE_PAMPD_REMOTESIZE_SHIFT; + fake_pampd |= ((unsigned long)cksum & + FAKE_PAMPD_MASK(FAKE_PAMPD_CHECKSUM_BITS)) << + FAKE_PAMPD_CHECKSUM_SHIFT; + return (void *)fake_pampd; +} + +static inline unsigned int pampd_remote_node(void *pampd) +{ + unsigned long fake_pampd = (unsigned long)pampd; + return (fake_pampd >> FAKE_PAMPD_REMOTENODE_SHIFT) & + FAKE_PAMPD_MASK(FAKE_PAMPD_REMOTENODE_BITS); +} + +static inline unsigned int pampd_remote_size(void *pampd) +{ + unsigned long fake_pampd = (unsigned long)pampd; + return (fake_pampd >> FAKE_PAMPD_REMOTESIZE_SHIFT) & + FAKE_PAMPD_MASK(FAKE_PAMPD_REMOTESIZE_BITS); +} + +static inline unsigned char pampd_remote_cksum(void *pampd) +{ + unsigned long fake_pampd = (unsigned long)pampd; + return (fake_pampd >> FAKE_PAMPD_CHECKSUM_SHIFT) & + FAKE_PAMPD_MASK(FAKE_PAMPD_CHECKSUM_BITS); +} + +static inline bool pampd_is_remote(void *pampd) +{ + unsigned long fake_pampd = (unsigned long)pampd; + return (fake_pampd >> FAKE_PAMPD_ISREMOTE_SHIFT) & + FAKE_PAMPD_MASK(FAKE_PAMPD_ISREMOTE_BITS); +} + +static inline bool pampd_is_intransit(void *pampd) +{ + unsigned long fake_pampd = (unsigned long)pampd; + return (fake_pampd >> FAKE_PAMPD_INTRANSIT_SHIFT) & + FAKE_PAMPD_MASK(FAKE_PAMPD_INTRANSIT_BITS); +} + +/* note that it is a BUG for intransit to be set without isremote also set */ +static inline void *pampd_mark_intransit(void *pampd) +{ + unsigned long fake_pampd = (unsigned long)pampd; + + fake_pampd |= 1UL << FAKE_PAMPD_ISREMOTE_SHIFT; + fake_pampd |= 1UL << FAKE_PAMPD_INTRANSIT_SHIFT; + return (void *)fake_pampd; +} + +static inline void *pampd_mask_intransit_and_remote(void *marked_pampd) +{ + unsigned long pampd = (unsigned long)marked_pampd; + + pampd &= ~(1UL << FAKE_PAMPD_INTRANSIT_SHIFT); + pampd &= ~(1UL << FAKE_PAMPD_ISREMOTE_SHIFT); + return (void *)pampd; +} + +extern int ramster_remote_async_get(struct tmem_xhandle *, + bool, int, size_t, uint8_t, void *extra); +extern int ramster_remote_put(struct tmem_xhandle *, char *, size_t, + bool, int *); +extern int ramster_remote_flush(struct tmem_xhandle *, int); +extern int ramster_remote_flush_object(struct tmem_xhandle *, int); +extern int ramster_o2net_register_handlers(void); + +#endif /* _TMEM_H */ diff --git a/drivers/staging/ramster/ramster_o2net.c b/drivers/staging/ramster/ramster_o2net.c new file mode 100644 index 0000000..c5a47cc --- /dev/null +++ b/drivers/staging/ramster/ramster_o2net.c @@ -0,0 +1,402 @@ +/* + * ramster_o2net.c + * + * Copyright (c) 2011, Dan Magenheimer, Oracle Corp. + * + * Ramster_o2net provides an interface between zcache and o2net. + * + * FIXME: support more than two nodes + */ + +#include +#include "cluster/tcp.h" +#include "cluster/nodemanager.h" +#include "tmem.h" +#include "zcache.h" +#include "ramster.h" + +#define RAMSTER_TESTING + +#define RMSTR_KEY 0x77347734 + +enum { + RMSTR_TMEM_PUT_EPH = 100, + RMSTR_TMEM_PUT_PERS, + RMSTR_TMEM_ASYNC_GET_REQUEST, + RMSTR_TMEM_ASYNC_GET_AND_FREE_REQUEST, + RMSTR_TMEM_ASYNC_GET_REPLY, + RMSTR_TMEM_FLUSH, + RMSTR_TMEM_FLOBJ, + RMSTR_TMEM_DESTROY_POOL, +}; + +#define RMSTR_O2NET_MAX_LEN \ + (O2NET_MAX_PAYLOAD_BYTES - sizeof(struct tmem_xhandle)) + +#include "cluster/tcp_internal.h" + +static struct o2nm_node *ramster_choose_node(int *nodenum, + struct tmem_xhandle *xh) +{ + struct o2nm_node *node = NULL; + int i; + +/* FIXME reproducibly pick a node based on xh that is NOT this node */ + i = o2nm_this_node(); + i = !i; /* FIXME ONLY FOR TWO NODES */ + node = o2nm_get_node_by_num(i); + /* WARNING: THIS DOES NOT CHECK TO ENSURE CONNECTED */ + if (node != NULL) + *nodenum = i; + return node; +} + +static void ramster_put_node(struct o2nm_node *node) +{ + o2nm_node_put(node); +} + +/* FIXME following buffer should be per-cpu, protected by preempt_disable */ +static char ramster_async_get_buf[O2NET_MAX_PAYLOAD_BYTES]; + +static int ramster_remote_async_get_request_handler(struct o2net_msg *msg, + u32 len, void *data, void **ret_data) +{ + char *pdata; + struct tmem_xhandle xh; + int found; + size_t size = RMSTR_O2NET_MAX_LEN; + u16 msgtype = be16_to_cpu(msg->msg_type); + bool get_and_free = (msgtype == RMSTR_TMEM_ASYNC_GET_AND_FREE_REQUEST); + unsigned long flags; + + xh = *(struct tmem_xhandle *)msg->buf; + if (xh.xh_data_size > RMSTR_O2NET_MAX_LEN) + BUG(); + pdata = ramster_async_get_buf; + *(struct tmem_xhandle *)pdata = xh; + pdata += sizeof(struct tmem_xhandle); + local_irq_save(flags); + found = zcache_get(xh.client_id, xh.pool_id, &xh.oid, xh.index, + pdata, &size, 1, get_and_free ? 1 : -1); + local_irq_restore(flags); + if (found < 0) { + /* a zero size indicates the get failed */ + size = 0; + } + if (size > RMSTR_O2NET_MAX_LEN) + BUG(); + *ret_data = pdata - sizeof(struct tmem_xhandle); + /* now make caller (o2net_process_message) handle specially */ + o2net_force_data_magic(msg, RMSTR_TMEM_ASYNC_GET_REPLY, RMSTR_KEY); + return size + sizeof(struct tmem_xhandle); +} + +static int ramster_remote_async_get_reply_handler(struct o2net_msg *msg, + u32 len, void *data, void **ret_data) +{ + char *in = (char *)msg->buf; + int datalen = len - sizeof(struct o2net_msg); + int ret = -1; + struct tmem_xhandle *xh = (struct tmem_xhandle *)in; + + in += sizeof(struct tmem_xhandle); + datalen -= sizeof(struct tmem_xhandle); + BUG_ON(datalen < 0 || datalen > PAGE_SIZE); + ret = zcache_localify(xh->pool_id, &xh->oid, xh->index, + in, datalen, xh->extra); +#ifdef RAMSTER_TESTING + if (ret == -EEXIST) + pr_err("TESTING ArrgREP, aborted overwrite on racy put\n"); +#endif + return ret; +} + +int ramster_remote_put_handler(struct o2net_msg *msg, + u32 len, void *data, void **ret_data) +{ + struct tmem_xhandle *xh; + char *p = (char *)msg->buf; + int datalen = len - sizeof(struct o2net_msg) - + sizeof(struct tmem_xhandle); + u16 msgtype = be16_to_cpu(msg->msg_type); + bool ephemeral = (msgtype == RMSTR_TMEM_PUT_EPH); + unsigned long flags; + int ret; + + xh = (struct tmem_xhandle *)p; + p += sizeof(struct tmem_xhandle); + zcache_autocreate_pool(xh->client_id, xh->pool_id, ephemeral); + local_irq_save(flags); + ret = zcache_put(xh->client_id, xh->pool_id, &xh->oid, xh->index, + p, datalen, 1, ephemeral ? 1 : -1); + local_irq_restore(flags); + return ret; +} + +int ramster_remote_flush_handler(struct o2net_msg *msg, + u32 len, void *data, void **ret_data) +{ + struct tmem_xhandle *xh; + char *p = (char *)msg->buf; + + xh = (struct tmem_xhandle *)p; + p += sizeof(struct tmem_xhandle); + (void)zcache_flush(xh->client_id, xh->pool_id, &xh->oid, xh->index); + return 0; +} + +int ramster_remote_flobj_handler(struct o2net_msg *msg, + u32 len, void *data, void **ret_data) +{ + struct tmem_xhandle *xh; + char *p = (char *)msg->buf; + + xh = (struct tmem_xhandle *)p; + p += sizeof(struct tmem_xhandle); + (void)zcache_flush_object(xh->client_id, xh->pool_id, &xh->oid); + return 0; +} + +int ramster_remote_async_get(struct tmem_xhandle *xh, bool free, int remotenode, + size_t expect_size, uint8_t expect_cksum, + void *extra) +{ + int ret = -1, status; + struct o2nm_node *node = NULL; + struct kvec vec[1]; + size_t veclen = 1; + u32 msg_type; + + node = o2nm_get_node_by_num(remotenode); + if (node == NULL) + goto out; + xh->client_id = o2nm_this_node(); /* which node is getting */ + xh->xh_data_cksum = expect_cksum; + xh->xh_data_size = expect_size; + xh->extra = extra; + vec[0].iov_len = sizeof(*xh); + vec[0].iov_base = xh; + if (free) + msg_type = RMSTR_TMEM_ASYNC_GET_AND_FREE_REQUEST; + else + msg_type = RMSTR_TMEM_ASYNC_GET_REQUEST; + ret = o2net_send_message_vec(msg_type, RMSTR_KEY, + vec, veclen, remotenode, &status); + ramster_put_node(node); + if (ret < 0) { + /* FIXME handle bad message possibilities here? */ + pr_err("UNTESTED ret<0 in ramster_remote_async_get\n"); + } + ret = status; +out: + return ret; +} + +#ifdef RAMSTER_TESTING +/* leave me here to see if it catches a weird crash */ +static void ramster_check_irq_counts(void) +{ + static int last_hardirq_cnt, last_softirq_cnt, last_preempt_cnt; + int cur_hardirq_cnt, cur_softirq_cnt, cur_preempt_cnt; + + cur_hardirq_cnt = hardirq_count() >> HARDIRQ_SHIFT; + if (cur_hardirq_cnt > last_hardirq_cnt) { + last_hardirq_cnt = cur_hardirq_cnt; + if (!(last_hardirq_cnt&(last_hardirq_cnt-1))) + pr_err("RAMSTER TESTING RRP hardirq_count=%d\n", + last_hardirq_cnt); + } + cur_softirq_cnt = softirq_count() >> SOFTIRQ_SHIFT; + if (cur_softirq_cnt > last_softirq_cnt) { + last_softirq_cnt = cur_softirq_cnt; + if (!(last_softirq_cnt&(last_softirq_cnt-1))) + pr_err("RAMSTER TESTING RRP softirq_count=%d\n", + last_softirq_cnt); + } + cur_preempt_cnt = preempt_count() & PREEMPT_MASK; + if (cur_preempt_cnt > last_preempt_cnt) { + last_preempt_cnt = cur_preempt_cnt; + if (!(last_preempt_cnt&(last_preempt_cnt-1))) + pr_err("RAMSTER TESTING RRP preempt_count=%d\n", + last_preempt_cnt); + } +} +#endif + +int ramster_remote_put(struct tmem_xhandle *xh, char *data, size_t size, + bool ephemeral, int *remotenode) +{ + int nodenum, ret = -1, status; + struct o2nm_node *node = NULL; + struct kvec vec[2]; + size_t veclen = 2; + u32 msg_type; +#ifdef RAMSTER_TESTING + struct o2net_node *nn; +#endif + + BUG_ON(size > RMSTR_O2NET_MAX_LEN); + xh->client_id = o2nm_this_node(); /* which node is putting */ + vec[0].iov_len = sizeof(*xh); + vec[0].iov_base = xh; + vec[1].iov_len = size; + vec[1].iov_base = data; + node = ramster_choose_node(&nodenum, xh); + if (!node) + goto out; + +#ifdef RAMSTER_TESTING + nn = o2net_nn_from_num(nodenum); + WARN_ON_ONCE(nn->nn_persistent_error || !nn->nn_sc_valid); +#endif + + if (ephemeral) + msg_type = RMSTR_TMEM_PUT_EPH; + else + msg_type = RMSTR_TMEM_PUT_PERS; +#ifdef RAMSTER_TESTING + /* leave me here to see if it catches a weird crash */ + ramster_check_irq_counts(); +#endif + + ret = o2net_send_message_vec(msg_type, RMSTR_KEY, + vec, veclen, nodenum, &status); +#ifdef RAMSTER_TESTING + if (ret != 0) { + static unsigned long cnt; + cnt++; + if (!(cnt&(cnt-1))) + pr_err("ramster_remote_put: message failed, " + "ret=%d, cnt=%lu\n", ret, cnt); + ret = -1; + } +#endif + if (ret < 0) + ret = -1; + else { + ret = status; + *remotenode = nodenum; + } + + ramster_put_node(node); +out: + return ret; +} + +int ramster_remote_flush(struct tmem_xhandle *xh, int remotenode) +{ + int ret = -1, status; + struct o2nm_node *node = NULL; + struct kvec vec[1]; + size_t veclen = 1; + + node = o2nm_get_node_by_num(remotenode); + BUG_ON(node == NULL); + xh->client_id = o2nm_this_node(); /* which node is flushing */ + vec[0].iov_len = sizeof(*xh); + vec[0].iov_base = xh; + BUG_ON(irqs_disabled()); + BUG_ON(in_softirq()); + ret = o2net_send_message_vec(RMSTR_TMEM_FLUSH, RMSTR_KEY, + vec, veclen, remotenode, &status); + ramster_put_node(node); + return ret; +} + +int ramster_remote_flush_object(struct tmem_xhandle *xh, int remotenode) +{ + int ret = -1, status; + struct o2nm_node *node = NULL; + struct kvec vec[1]; + size_t veclen = 1; + + node = o2nm_get_node_by_num(remotenode); + BUG_ON(node == NULL); + xh->client_id = o2nm_this_node(); /* which node is flobjing */ + vec[0].iov_len = sizeof(*xh); + vec[0].iov_base = xh; + ret = o2net_send_message_vec(RMSTR_TMEM_FLOBJ, RMSTR_KEY, + vec, veclen, remotenode, &status); + ramster_put_node(node); + return ret; +} + +/* + * Handler registration + */ + +static LIST_HEAD(ramster_o2net_unreg_list); + +static void ramster_o2net_unregister_handlers(void) +{ + o2net_unregister_handler_list(&ramster_o2net_unreg_list); +} + +int ramster_o2net_register_handlers(void) +{ + int status; + + status = o2net_register_handler(RMSTR_TMEM_PUT_EPH, RMSTR_KEY, + RMSTR_O2NET_MAX_LEN, + ramster_remote_put_handler, + NULL, NULL, &ramster_o2net_unreg_list); + if (status) + goto bail; + + status = o2net_register_handler(RMSTR_TMEM_PUT_PERS, RMSTR_KEY, + RMSTR_O2NET_MAX_LEN, + ramster_remote_put_handler, + NULL, NULL, &ramster_o2net_unreg_list); + if (status) + goto bail; + + status = o2net_register_handler(RMSTR_TMEM_ASYNC_GET_REQUEST, RMSTR_KEY, + RMSTR_O2NET_MAX_LEN, + ramster_remote_async_get_request_handler, + NULL, NULL, + &ramster_o2net_unreg_list); + if (status) + goto bail; + + status = o2net_register_handler(RMSTR_TMEM_ASYNC_GET_AND_FREE_REQUEST, + RMSTR_KEY, RMSTR_O2NET_MAX_LEN, + ramster_remote_async_get_request_handler, + NULL, NULL, + &ramster_o2net_unreg_list); + if (status) + goto bail; + + status = o2net_register_handler(RMSTR_TMEM_ASYNC_GET_REPLY, RMSTR_KEY, + RMSTR_O2NET_MAX_LEN, + ramster_remote_async_get_reply_handler, + NULL, NULL, + &ramster_o2net_unreg_list); + if (status) + goto bail; + + status = o2net_register_handler(RMSTR_TMEM_FLUSH, RMSTR_KEY, + RMSTR_O2NET_MAX_LEN, + ramster_remote_flush_handler, + NULL, NULL, + &ramster_o2net_unreg_list); + if (status) + goto bail; + + status = o2net_register_handler(RMSTR_TMEM_FLOBJ, RMSTR_KEY, + RMSTR_O2NET_MAX_LEN, + ramster_remote_flobj_handler, + NULL, NULL, + &ramster_o2net_unreg_list); + if (status) + goto bail; + + pr_info("ramster_o2net: handlers registered\n"); + +bail: + if (status) { + ramster_o2net_unregister_handlers(); + pr_err("ramster_o2net: couldn't register handlers\n"); + } + return status; +} diff --git a/drivers/staging/ramster/zcache.h b/drivers/staging/ramster/zcache.h new file mode 100644 index 0000000..250b121 --- /dev/null +++ b/drivers/staging/ramster/zcache.h @@ -0,0 +1,22 @@ +/* + * zcache.h + * + * External zcache functions + * + * Copyright (c) 2009-2012, Dan Magenheimer, Oracle Corp. + */ + +#ifndef _ZCACHE_H_ +#define _ZCACHE_H_ + +extern int zcache_put(int, int, struct tmem_oid *, uint32_t, + char *, size_t, bool, int); +extern int zcache_autocreate_pool(int, int, bool); +extern int zcache_get(int, int, struct tmem_oid *, uint32_t, + char *, size_t *, bool, int); +extern int zcache_flush(int, int, struct tmem_oid *, uint32_t); +extern int zcache_flush_object(int, int, struct tmem_oid *); +extern int zcache_localify(int, struct tmem_oid *, uint32_t, + char *, size_t, void *); + +#endif /* _ZCACHE_H */ -- cgit v0.10.2 From 1739441c29e09706a1f82e6e0fecfd946b6f4328 Mon Sep 17 00:00:00 2001 From: Dan Magenheimer Date: Mon, 30 Jan 2012 14:39:19 -0800 Subject: staging: ramster: enable as staging driver Enable build of ramster as a staging driver Signed-off-by: Dan Magenheimer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index aaba36c..76a4c4a 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -134,4 +134,6 @@ source "drivers/staging/android/Kconfig" source "drivers/staging/telephony/Kconfig" +source "drivers/staging/ramster/Kconfig" + endif # STAGING diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 7c5808d..c061be8 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -57,3 +57,4 @@ obj-$(CONFIG_INTEL_MEI) += mei/ obj-$(CONFIG_MFD_NVEC) += nvec/ obj-$(CONFIG_DRM_OMAP) += omapdrm/ obj-$(CONFIG_ANDROID) += android/ +obj-$(CONFIG_RAMSTER) += ramster/ -- cgit v0.10.2 From 09f0355f0612520820ae4b2c342a26e048bef6e7 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 12 Jan 2012 12:37:54 -0800 Subject: Staging: hv: storvsc: Cleanup some comments Use consistent format for comments and get rid of some unnecessary comments. Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index eb853f7..1633b03 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -50,8 +50,10 @@ static int storvsc_ringbuffer_size = STORVSC_RING_BUFFER_SIZE; module_param(storvsc_ringbuffer_size, int, S_IRUGO); MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)"); -/* to alert the user that structure sizes may be mismatched even though the */ -/* protocol versions match. */ +/* + * To alert the user that structure sizes may be mismatched even though the + * protocol versions match. + */ #define REVISION_STRING(REVISION_) #REVISION_ @@ -68,26 +70,36 @@ MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)"); } \ } while (0) -/* Major/minor macros. Minor version is in LSB, meaning that earlier flat */ -/* version numbers will be interpreted as "0.x" (i.e., 1 becomes 0.1). */ +/* + * Major/minor macros. Minor version is in LSB, meaning that earlier flat + * version numbers will be interpreted as "0.x" (i.e., 1 becomes 0.1). + */ + #define VMSTOR_PROTOCOL_MAJOR(VERSION_) (((VERSION_) >> 8) & 0xff) #define VMSTOR_PROTOCOL_MINOR(VERSION_) (((VERSION_)) & 0xff) #define VMSTOR_PROTOCOL_VERSION(MAJOR_, MINOR_) ((((MAJOR_) & 0xff) << 8) | \ (((MINOR_) & 0xff))) #define VMSTOR_INVALID_PROTOCOL_VERSION (-1) -/* Version history: */ -/* V1 Beta 0.1 */ -/* V1 RC < 2008/1/31 1.0 */ -/* V1 RC > 2008/1/31 2.0 */ +/* + * Version history: + * V1 Beta: 0.1 + * V1 RC < 2008/1/31: 1.0 + * V1 RC > 2008/1/31: 2.0 + * Win7: 4.2 + */ + #define VMSTOR_PROTOCOL_VERSION_CURRENT VMSTOR_PROTOCOL_VERSION(4, 2) -/* This will get replaced with the max transfer length that is possible on */ -/* the host adapter. */ -/* The max transfer length will be published when we offer a vmbus channel. */ +/* + * This will get replaced with the max transfer length that is possible on + * the host adapter. + * The max transfer length will be published when we offer a vmbus channel. + */ + #define MAX_TRANSFER_LENGTH 0x40000 #define DEFAULT_PACKET_SIZE (sizeof(struct vmdata_gpa_direct) + \ sizeof(struct vstor_packet) + \ @@ -211,18 +223,19 @@ struct vstor_packet { }; } __packed; -/* Packet flags */ /* + * Packet Flags: + * * This flag indicates that the server should send back a completion for this * packet. */ + #define REQUEST_COMPLETION_FLAG 0x1 /* This is the set of flags that the vsc can set in any packets it sends */ #define VSC_LEGAL_FLAGS (REQUEST_COMPLETION_FLAG) -/* Defines */ #define STORVSC_MAX_IO_REQUESTS 128 @@ -674,7 +687,6 @@ static int storvsc_connect_to_vsp(struct hv_device *device, u32 ring_size) memset(&props, 0, sizeof(struct vmstorage_channel_properties)); - /* Open the channel */ ret = vmbus_open(device->channel, ring_size, ring_size, @@ -1154,9 +1166,6 @@ static int storvsc_host_reset(struct hv_device *device) } -/* - * storvsc_host_reset_handler - Reset the scsi HBA - */ static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd) { struct hv_host_device *host_dev = shost_priv(scmnd->device->host); @@ -1166,9 +1175,6 @@ static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd) } -/* - * storvsc_command_completion - Command completion processing - */ static void storvsc_command_completion(struct hv_storvsc_request *request) { struct storvsc_cmd_request *cmd_request = @@ -1262,9 +1268,6 @@ static bool storvsc_check_scsi_cmd(struct scsi_cmnd *scmnd) return allowed; } -/* - * storvsc_queuecommand - Initiate command processing - */ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) { int ret; @@ -1407,7 +1410,6 @@ retry_request: return ret; } -/* Scsi driver */ static struct scsi_host_template scsi_driver = { .module = THIS_MODULE, .name = "storvsc_host_t", @@ -1448,11 +1450,6 @@ static const struct hv_vmbus_device_id id_table[] = { MODULE_DEVICE_TABLE(vmbus, id_table); - -/* - * storvsc_probe - Add a new device for this driver - */ - static int storvsc_probe(struct hv_device *device, const struct hv_vmbus_device_id *dev_id) { @@ -1542,8 +1539,6 @@ err_out0: return ret; } -/* The one and only one */ - static struct hv_driver storvsc_drv = { .name = KBUILD_MODNAME, .id_table = id_table, -- cgit v0.10.2 From 59d22950b274182b006e4071d6690bfbc94d7267 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 12 Jan 2012 12:37:55 -0800 Subject: Staging: hv: storvsc: Cleanup storvsc_probe() Cleanup storvsc_probe(). As part of this cleanup, get rid of storvsc_get_ide_info() by inlining the necessary code. Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index 1633b03..7561d29 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -791,18 +791,6 @@ static int storvsc_do_io(struct hv_device *device, return ret; } -static void storvsc_get_ide_info(struct hv_device *dev, int *target, int *path) -{ - *target = - dev->dev_instance.b[5] << 8 | dev->dev_instance.b[4]; - - *path = - dev->dev_instance.b[3] << 24 | - dev->dev_instance.b[2] << 16 | - dev->dev_instance.b[1] << 8 | dev->dev_instance.b[0]; -} - - static int storvsc_device_alloc(struct scsi_device *sdevice) { struct stor_mem_pools *memp; @@ -1457,7 +1445,6 @@ static int storvsc_probe(struct hv_device *device, struct Scsi_Host *host; struct hv_host_device *host_dev; bool dev_is_ide = ((dev_id->driver_data == IDE_GUID) ? true : false); - int path = 0; int target = 0; struct storvsc_device *stor_device; @@ -1490,9 +1477,6 @@ static int storvsc_probe(struct hv_device *device, if (ret) goto err_out1; - if (dev_is_ide) - storvsc_get_ide_info(device, &target, &path); - host_dev->path = stor_device->path_id; host_dev->target = stor_device->target_id; @@ -1512,12 +1496,14 @@ static int storvsc_probe(struct hv_device *device, if (!dev_is_ide) { scsi_scan_host(host); - return 0; - } - ret = scsi_add_device(host, 0, target, 0); - if (ret) { - scsi_remove_host(host); - goto err_out2; + } else { + target = (device->dev_instance.b[5] << 8 | + device->dev_instance.b[4]); + ret = scsi_add_device(host, 0, target, 0); + if (ret) { + scsi_remove_host(host); + goto err_out2; + } } return 0; -- cgit v0.10.2 From c77b63b639f52b2e92d0bbaa94f33a78939f3e7c Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 12 Jan 2012 12:37:56 -0800 Subject: Staging: hv: storvsc: Cleanup storvsc_queuecommand() Cleanup storvsc_queuecommand(). As part of this cleanup, rename the function to check if the scsi command can be sent to the host, consolidate error recovery and get rid of some dead code. Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index 7561d29..71e50c3 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -1239,13 +1239,16 @@ static void storvsc_command_completion(struct hv_storvsc_request *request) mempool_free(cmd_request, memp->request_mempool); } -static bool storvsc_check_scsi_cmd(struct scsi_cmnd *scmnd) +static bool storvsc_scsi_cmd_ok(struct scsi_cmnd *scmnd) { bool allowed = true; u8 scsi_op = scmnd->cmnd[0]; switch (scsi_op) { - /* smartd sends this command, which will offline the device */ + /* + * smartd sends this command and the host does not handle + * this. So, don't send it. + */ case SET_WINDOW: scmnd->result = ILLEGAL_REQUEST << 16; allowed = false; @@ -1270,32 +1273,26 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) struct vmscsi_request *vm_srb; struct stor_mem_pools *memp = scmnd->device->hostdata; - if (storvsc_check_scsi_cmd(scmnd) == false) { + if (!storvsc_scsi_cmd_ok(scmnd)) { scmnd->scsi_done(scmnd); return 0; } - /* If retrying, no need to prep the cmd */ - if (scmnd->host_scribble) { - - cmd_request = - (struct storvsc_cmd_request *)scmnd->host_scribble; - - goto retry_request; - } - request_size = sizeof(struct storvsc_cmd_request); cmd_request = mempool_alloc(memp->request_mempool, GFP_ATOMIC); + + /* + * We might be invoked in an interrupt context; hence + * mempool_alloc() can fail. + */ if (!cmd_request) return SCSI_MLQUEUE_DEVICE_BUSY; memset(cmd_request, 0, sizeof(struct storvsc_cmd_request)); /* Setup the cmd request */ - cmd_request->bounce_sgl_count = 0; - cmd_request->bounce_sgl = NULL; cmd_request->cmd = scmnd; scmnd->host_scribble = (unsigned char *)cmd_request; @@ -1344,11 +1341,8 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) scsi_bufflen(scmnd), vm_srb->data_in); if (!cmd_request->bounce_sgl) { - scmnd->host_scribble = NULL; - mempool_free(cmd_request, - memp->request_mempool); - - return SCSI_MLQUEUE_HOST_BUSY; + ret = SCSI_MLQUEUE_HOST_BUSY; + goto queue_error; } cmd_request->bounce_sgl_count = @@ -1377,24 +1371,26 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) virt_to_phys(scsi_sglist(scmnd)) >> PAGE_SHIFT; } -retry_request: /* Invokes the vsc to start an IO */ ret = storvsc_do_io(dev, &cmd_request->request); if (ret == -EAGAIN) { /* no more space */ - if (cmd_request->bounce_sgl_count) + if (cmd_request->bounce_sgl_count) { destroy_bounce_buffer(cmd_request->bounce_sgl, cmd_request->bounce_sgl_count); - mempool_free(cmd_request, memp->request_mempool); - - scmnd->host_scribble = NULL; - - ret = SCSI_MLQUEUE_DEVICE_BUSY; + ret = SCSI_MLQUEUE_DEVICE_BUSY; + goto queue_error; + } } + return 0; + +queue_error: + mempool_free(cmd_request, memp->request_mempool); + scmnd->host_scribble = NULL; return ret; } -- cgit v0.10.2 From 160463204f541cea112fd4d68422f297bd98ec51 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 12 Jan 2012 12:37:57 -0800 Subject: Staging: hv: storvsc: Introduce defines for srb status codes Introduce defines for srb status codes. Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index 71e50c3..979f25b 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -257,6 +257,16 @@ enum storvsc_request_type { UNKNOWN_TYPE, }; +/* + * SRB status codes and masks; a subset of the codes used here. + */ + +#define SRB_STATUS_AUTOSENSE_VALID 0x80 +#define SRB_STATUS_INVALID_LUN 0x20 +#define SRB_STATUS_SUCCESS 0x01 +#define SRB_STATUS_ERROR 0x04 + + struct hv_storvsc_request { struct hv_device *device; @@ -561,7 +571,7 @@ static void storvsc_on_io_completion(struct hv_device *device, if ((stor_pkt->vm_srb.cdb[0] == INQUIRY) || (stor_pkt->vm_srb.cdb[0] == MODE_SENSE)) { vstor_packet->vm_srb.scsi_status = 0; - vstor_packet->vm_srb.srb_status = 0x1; + vstor_packet->vm_srb.srb_status = SRB_STATUS_SUCCESS; } @@ -572,7 +582,7 @@ static void storvsc_on_io_completion(struct hv_device *device, vstor_packet->vm_srb.sense_info_length; if (vstor_packet->vm_srb.scsi_status != 0 || - vstor_packet->vm_srb.srb_status != 1){ + vstor_packet->vm_srb.srb_status != SRB_STATUS_SUCCESS){ dev_warn(&device->device, "cmd 0x%x scsi status 0x%x srb status 0x%x\n", stor_pkt->vm_srb.cdb[0], @@ -582,7 +592,8 @@ static void storvsc_on_io_completion(struct hv_device *device, if ((vstor_packet->vm_srb.scsi_status & 0xFF) == 0x02) { /* CHECK_CONDITION */ - if (vstor_packet->vm_srb.srb_status & 0x80) { + if (vstor_packet->vm_srb.srb_status & + SRB_STATUS_AUTOSENSE_VALID) { /* autosense data available */ dev_warn(&device->device, "stor pkt %p autosense data valid - len %d\n", @@ -1191,7 +1202,7 @@ static void storvsc_command_completion(struct hv_storvsc_request *request) * error recovery strategies would have already been * deployed on the host side. */ - if (vm_srb->srb_status == 0x4) + if (vm_srb->srb_status == SRB_STATUS_ERROR) scmnd->result = DID_TARGET_FAILURE << 16; else scmnd->result = vm_srb->scsi_status; @@ -1199,7 +1210,7 @@ static void storvsc_command_completion(struct hv_storvsc_request *request) /* * If the LUN is invalid; remove the device. */ - if (vm_srb->srb_status == 0x20) { + if (vm_srb->srb_status == SRB_STATUS_INVALID_LUN) { struct storvsc_device *stor_dev; struct hv_device *dev = host_dev->dev; struct Scsi_Host *host; -- cgit v0.10.2 From 4b270c8b23722128adedb5694097aea367284ce1 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 12 Jan 2012 12:37:58 -0800 Subject: Staging: hv: storvsc: Cleanup storvsc_host_reset_handler() Cleanup storvsc_host_reset_handler() by getting rid of storvsc_host_reset(). Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index 979f25b..8340387 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -1122,8 +1122,11 @@ static int storvsc_get_chs(struct scsi_device *sdev, struct block_device * bdev, return 0; } -static int storvsc_host_reset(struct hv_device *device) +static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd) { + struct hv_host_device *host_dev = shost_priv(scmnd->device->host); + struct hv_device *device = host_dev->dev; + struct storvsc_device *stor_device; struct hv_storvsc_request *request; struct vstor_packet *vstor_packet; @@ -1165,15 +1168,6 @@ static int storvsc_host_reset(struct hv_device *device) } -static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd) -{ - struct hv_host_device *host_dev = shost_priv(scmnd->device->host); - struct hv_device *dev = host_dev->dev; - - return storvsc_host_reset(dev); -} - - static void storvsc_command_completion(struct hv_storvsc_request *request) { struct storvsc_cmd_request *cmd_request = -- cgit v0.10.2 From ddcbf65e484c3473d3e808718ddb6c8166822c4c Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 12 Jan 2012 12:37:59 -0800 Subject: Staging: hv: storvsc: Move and cleanup storvsc_remove() Relocate the storvsc_remove() function to a different location in the file and invoke scsi_host_put() only after all the cleanup. Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index 8340387..e0e471c 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -1083,22 +1083,6 @@ static unsigned int copy_to_bounce_buffer(struct scatterlist *orig_sgl, return total_copied; } - -static int storvsc_remove(struct hv_device *dev) -{ - struct storvsc_device *stor_device = hv_get_drvdata(dev); - struct Scsi_Host *host = stor_device->host; - - scsi_remove_host(host); - - scsi_host_put(host); - - storvsc_dev_remove(dev); - - return 0; -} - - static int storvsc_get_chs(struct scsi_device *sdev, struct block_device * bdev, sector_t capacity, int *info) { @@ -1526,6 +1510,18 @@ err_out0: return ret; } +static int storvsc_remove(struct hv_device *dev) +{ + struct storvsc_device *stor_device = hv_get_drvdata(dev); + struct Scsi_Host *host = stor_device->host; + + scsi_remove_host(host); + storvsc_dev_remove(dev); + scsi_host_put(host); + + return 0; +} + static struct hv_driver storvsc_drv = { .name = KBUILD_MODNAME, .id_table = id_table, -- cgit v0.10.2 From a8c18c573bf896f81dbcd68fdb81d81d4200dcad Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 12 Jan 2012 12:38:00 -0800 Subject: Staging: hv: storvsc: Add a comment to explain life-cycle management Add a comment to explain life-cycle management and fix format issue. Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index e0e471c..204b3ca 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -375,6 +375,21 @@ done: kfree(wrk); } +/* + * We can get incoming messages from the host that are not in response to + * messages that we have sent out. An example of this would be messages + * received by the guest to notify dynamic addition/removal of LUNs. To + * deal with potential race conditions where the driver may be in the + * midst of being unloaded when we might receive an unsolicited message + * from the host, we have implemented a mechanism to gurantee sequential + * consistency: + * + * 1) Once the device is marked as being destroyed, we will fail all + * outgoing messages. + * 2) We permit incoming messages when the device is being destroyed, + * only to properly account for messages already sent out. + */ + static inline struct storvsc_device *get_out_stor_device( struct hv_device *device) { @@ -569,7 +584,7 @@ static void storvsc_on_io_completion(struct hv_device *device, */ if ((stor_pkt->vm_srb.cdb[0] == INQUIRY) || - (stor_pkt->vm_srb.cdb[0] == MODE_SENSE)) { + (stor_pkt->vm_srb.cdb[0] == MODE_SENSE)) { vstor_packet->vm_srb.scsi_status = 0; vstor_packet->vm_srb.srb_status = SRB_STATUS_SUCCESS; } -- cgit v0.10.2 From 2707388c7c5c6edf4e646a9013f6b7aa195fb174 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 12 Jan 2012 12:38:01 -0800 Subject: Staging: hv: storvsc: Get rid of the on_io_completion in hv_storvsc_request Get rid of the on_io_completion field in struct hv_storvsc_request. As part of this relocate the bounce buffer handling code (to avoid having forward declarations). Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index 204b3ca..7c9fa19 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -276,7 +276,6 @@ struct hv_storvsc_request { unsigned char *sense_buffer; void *context; - void (*on_io_completion)(struct hv_storvsc_request *request); struct hv_multipage_buffer data_buffer; struct vstor_packet vstor_packet; @@ -436,6 +435,227 @@ get_in_err: } +static void destroy_bounce_buffer(struct scatterlist *sgl, + unsigned int sg_count) +{ + int i; + struct page *page_buf; + + for (i = 0; i < sg_count; i++) { + page_buf = sg_page((&sgl[i])); + if (page_buf != NULL) + __free_page(page_buf); + } + + kfree(sgl); +} + +static int do_bounce_buffer(struct scatterlist *sgl, unsigned int sg_count) +{ + int i; + + /* No need to check */ + if (sg_count < 2) + return -1; + + /* We have at least 2 sg entries */ + for (i = 0; i < sg_count; i++) { + if (i == 0) { + /* make sure 1st one does not have hole */ + if (sgl[i].offset + sgl[i].length != PAGE_SIZE) + return i; + } else if (i == sg_count - 1) { + /* make sure last one does not have hole */ + if (sgl[i].offset != 0) + return i; + } else { + /* make sure no hole in the middle */ + if (sgl[i].length != PAGE_SIZE || sgl[i].offset != 0) + return i; + } + } + return -1; +} + +static struct scatterlist *create_bounce_buffer(struct scatterlist *sgl, + unsigned int sg_count, + unsigned int len, + int write) +{ + int i; + int num_pages; + struct scatterlist *bounce_sgl; + struct page *page_buf; + unsigned int buf_len = ((write == WRITE_TYPE) ? 0 : PAGE_SIZE); + + num_pages = ALIGN(len, PAGE_SIZE) >> PAGE_SHIFT; + + bounce_sgl = kcalloc(num_pages, sizeof(struct scatterlist), GFP_ATOMIC); + if (!bounce_sgl) + return NULL; + + for (i = 0; i < num_pages; i++) { + page_buf = alloc_page(GFP_ATOMIC); + if (!page_buf) + goto cleanup; + sg_set_page(&bounce_sgl[i], page_buf, buf_len, 0); + } + + return bounce_sgl; + +cleanup: + destroy_bounce_buffer(bounce_sgl, num_pages); + return NULL; +} + +/* Assume the original sgl has enough room */ +static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl, + struct scatterlist *bounce_sgl, + unsigned int orig_sgl_count, + unsigned int bounce_sgl_count) +{ + int i; + int j = 0; + unsigned long src, dest; + unsigned int srclen, destlen, copylen; + unsigned int total_copied = 0; + unsigned long bounce_addr = 0; + unsigned long dest_addr = 0; + unsigned long flags; + + local_irq_save(flags); + + for (i = 0; i < orig_sgl_count; i++) { + dest_addr = (unsigned long)kmap_atomic(sg_page((&orig_sgl[i])), + KM_IRQ0) + orig_sgl[i].offset; + dest = dest_addr; + destlen = orig_sgl[i].length; + + if (bounce_addr == 0) + bounce_addr = + (unsigned long)kmap_atomic(sg_page((&bounce_sgl[j])), + KM_IRQ0); + + while (destlen) { + src = bounce_addr + bounce_sgl[j].offset; + srclen = bounce_sgl[j].length - bounce_sgl[j].offset; + + copylen = min(srclen, destlen); + memcpy((void *)dest, (void *)src, copylen); + + total_copied += copylen; + bounce_sgl[j].offset += copylen; + destlen -= copylen; + dest += copylen; + + if (bounce_sgl[j].offset == bounce_sgl[j].length) { + /* full */ + kunmap_atomic((void *)bounce_addr, KM_IRQ0); + j++; + + /* + * It is possible that the number of elements + * in the bounce buffer may not be equal to + * the number of elements in the original + * scatter list. Handle this correctly. + */ + + if (j == bounce_sgl_count) { + /* + * We are done; cleanup and return. + */ + kunmap_atomic((void *)(dest_addr - + orig_sgl[i].offset), + KM_IRQ0); + local_irq_restore(flags); + return total_copied; + } + + /* if we need to use another bounce buffer */ + if (destlen || i != orig_sgl_count - 1) + bounce_addr = + (unsigned long)kmap_atomic( + sg_page((&bounce_sgl[j])), KM_IRQ0); + } else if (destlen == 0 && i == orig_sgl_count - 1) { + /* unmap the last bounce that is < PAGE_SIZE */ + kunmap_atomic((void *)bounce_addr, KM_IRQ0); + } + } + + kunmap_atomic((void *)(dest_addr - orig_sgl[i].offset), + KM_IRQ0); + } + + local_irq_restore(flags); + + return total_copied; +} + +/* Assume the bounce_sgl has enough room ie using the create_bounce_buffer() */ +static unsigned int copy_to_bounce_buffer(struct scatterlist *orig_sgl, + struct scatterlist *bounce_sgl, + unsigned int orig_sgl_count) +{ + int i; + int j = 0; + unsigned long src, dest; + unsigned int srclen, destlen, copylen; + unsigned int total_copied = 0; + unsigned long bounce_addr = 0; + unsigned long src_addr = 0; + unsigned long flags; + + local_irq_save(flags); + + for (i = 0; i < orig_sgl_count; i++) { + src_addr = (unsigned long)kmap_atomic(sg_page((&orig_sgl[i])), + KM_IRQ0) + orig_sgl[i].offset; + src = src_addr; + srclen = orig_sgl[i].length; + + if (bounce_addr == 0) + bounce_addr = + (unsigned long)kmap_atomic(sg_page((&bounce_sgl[j])), + KM_IRQ0); + + while (srclen) { + /* assume bounce offset always == 0 */ + dest = bounce_addr + bounce_sgl[j].length; + destlen = PAGE_SIZE - bounce_sgl[j].length; + + copylen = min(srclen, destlen); + memcpy((void *)dest, (void *)src, copylen); + + total_copied += copylen; + bounce_sgl[j].length += copylen; + srclen -= copylen; + src += copylen; + + if (bounce_sgl[j].length == PAGE_SIZE) { + /* full..move to next entry */ + kunmap_atomic((void *)bounce_addr, KM_IRQ0); + j++; + + /* if we need to use another bounce buffer */ + if (srclen || i != orig_sgl_count - 1) + bounce_addr = + (unsigned long)kmap_atomic( + sg_page((&bounce_sgl[j])), KM_IRQ0); + + } else if (srclen == 0 && i == orig_sgl_count - 1) { + /* unmap the last bounce that is < PAGE_SIZE */ + kunmap_atomic((void *)bounce_addr, KM_IRQ0); + } + } + + kunmap_atomic((void *)(src_addr - orig_sgl[i].offset), KM_IRQ0); + } + + local_irq_restore(flags); + + return total_copied; +} + static int storvsc_channel_init(struct hv_device *device) { struct storvsc_device *stor_device; @@ -562,24 +782,101 @@ cleanup: return ret; } -static void storvsc_on_io_completion(struct hv_device *device, - struct vstor_packet *vstor_packet, - struct hv_storvsc_request *request) + +static void storvsc_command_completion(struct hv_storvsc_request *request) { - struct storvsc_device *stor_device; - struct vstor_packet *stor_pkt; + struct storvsc_cmd_request *cmd_request = + (struct storvsc_cmd_request *)request->context; + struct scsi_cmnd *scmnd = cmd_request->cmd; + struct hv_host_device *host_dev = shost_priv(scmnd->device->host); + void (*scsi_done_fn)(struct scsi_cmnd *); + struct scsi_sense_hdr sense_hdr; + struct vmscsi_request *vm_srb; + struct storvsc_scan_work *wrk; + struct stor_mem_pools *memp = scmnd->device->hostdata; - stor_device = hv_get_drvdata(device); - stor_pkt = &request->vstor_packet; + vm_srb = &request->vstor_packet.vm_srb; + if (cmd_request->bounce_sgl_count) { + if (vm_srb->data_in == READ_TYPE) + copy_from_bounce_buffer(scsi_sglist(scmnd), + cmd_request->bounce_sgl, + scsi_sg_count(scmnd), + cmd_request->bounce_sgl_count); + destroy_bounce_buffer(cmd_request->bounce_sgl, + cmd_request->bounce_sgl_count); + } /* - * The current SCSI handling on the host side does - * not correctly handle: - * INQUIRY command with page code parameter set to 0x80 - * MODE_SENSE command with cmd[2] == 0x1c - * - * Setup srb and scsi status so this won't be fatal. - * We do this so we can distinguish truly fatal failues + * If there is an error; offline the device since all + * error recovery strategies would have already been + * deployed on the host side. + */ + if (vm_srb->srb_status == SRB_STATUS_ERROR) + scmnd->result = DID_TARGET_FAILURE << 16; + else + scmnd->result = vm_srb->scsi_status; + + /* + * If the LUN is invalid; remove the device. + */ + if (vm_srb->srb_status == SRB_STATUS_INVALID_LUN) { + struct storvsc_device *stor_dev; + struct hv_device *dev = host_dev->dev; + struct Scsi_Host *host; + + stor_dev = get_in_stor_device(dev); + host = stor_dev->host; + + wrk = kmalloc(sizeof(struct storvsc_scan_work), + GFP_ATOMIC); + if (!wrk) { + scmnd->result = DID_TARGET_FAILURE << 16; + } else { + wrk->host = host; + wrk->lun = vm_srb->lun; + INIT_WORK(&wrk->work, storvsc_remove_lun); + schedule_work(&wrk->work); + } + } + + if (scmnd->result) { + if (scsi_normalize_sense(scmnd->sense_buffer, + SCSI_SENSE_BUFFERSIZE, &sense_hdr)) + scsi_print_sense_hdr("storvsc", &sense_hdr); + } + + scsi_set_resid(scmnd, + request->data_buffer.len - + vm_srb->data_transfer_length); + + scsi_done_fn = scmnd->scsi_done; + + scmnd->host_scribble = NULL; + scmnd->scsi_done = NULL; + + scsi_done_fn(scmnd); + + mempool_free(cmd_request, memp->request_mempool); +} + +static void storvsc_on_io_completion(struct hv_device *device, + struct vstor_packet *vstor_packet, + struct hv_storvsc_request *request) +{ + struct storvsc_device *stor_device; + struct vstor_packet *stor_pkt; + + stor_device = hv_get_drvdata(device); + stor_pkt = &request->vstor_packet; + + /* + * The current SCSI handling on the host side does + * not correctly handle: + * INQUIRY command with page code parameter set to 0x80 + * MODE_SENSE command with cmd[2] == 0x1c + * + * Setup srb and scsi status so this won't be fatal. + * We do this so we can distinguish truly fatal failues * (srb status == 0x4) and off-line the device in that case. */ @@ -625,7 +922,7 @@ static void storvsc_on_io_completion(struct hv_device *device, stor_pkt->vm_srb.data_transfer_length = vstor_packet->vm_srb.data_transfer_length; - request->on_io_completion(request); + storvsc_command_completion(request); if (atomic_dec_and_test(&stor_device->num_outstanding_req) && stor_device->drain_notify) @@ -875,229 +1172,6 @@ static int storvsc_device_configure(struct scsi_device *sdevice) return 0; } -static void destroy_bounce_buffer(struct scatterlist *sgl, - unsigned int sg_count) -{ - int i; - struct page *page_buf; - - for (i = 0; i < sg_count; i++) { - page_buf = sg_page((&sgl[i])); - if (page_buf != NULL) - __free_page(page_buf); - } - - kfree(sgl); -} - -static int do_bounce_buffer(struct scatterlist *sgl, unsigned int sg_count) -{ - int i; - - /* No need to check */ - if (sg_count < 2) - return -1; - - /* We have at least 2 sg entries */ - for (i = 0; i < sg_count; i++) { - if (i == 0) { - /* make sure 1st one does not have hole */ - if (sgl[i].offset + sgl[i].length != PAGE_SIZE) - return i; - } else if (i == sg_count - 1) { - /* make sure last one does not have hole */ - if (sgl[i].offset != 0) - return i; - } else { - /* make sure no hole in the middle */ - if (sgl[i].length != PAGE_SIZE || sgl[i].offset != 0) - return i; - } - } - return -1; -} - -static struct scatterlist *create_bounce_buffer(struct scatterlist *sgl, - unsigned int sg_count, - unsigned int len, - int write) -{ - int i; - int num_pages; - struct scatterlist *bounce_sgl; - struct page *page_buf; - unsigned int buf_len = ((write == WRITE_TYPE) ? 0 : PAGE_SIZE); - - num_pages = ALIGN(len, PAGE_SIZE) >> PAGE_SHIFT; - - bounce_sgl = kcalloc(num_pages, sizeof(struct scatterlist), GFP_ATOMIC); - if (!bounce_sgl) - return NULL; - - for (i = 0; i < num_pages; i++) { - page_buf = alloc_page(GFP_ATOMIC); - if (!page_buf) - goto cleanup; - sg_set_page(&bounce_sgl[i], page_buf, buf_len, 0); - } - - return bounce_sgl; - -cleanup: - destroy_bounce_buffer(bounce_sgl, num_pages); - return NULL; -} - - -/* Assume the original sgl has enough room */ -static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl, - struct scatterlist *bounce_sgl, - unsigned int orig_sgl_count, - unsigned int bounce_sgl_count) -{ - int i; - int j = 0; - unsigned long src, dest; - unsigned int srclen, destlen, copylen; - unsigned int total_copied = 0; - unsigned long bounce_addr = 0; - unsigned long dest_addr = 0; - unsigned long flags; - - local_irq_save(flags); - - for (i = 0; i < orig_sgl_count; i++) { - dest_addr = (unsigned long)kmap_atomic(sg_page((&orig_sgl[i])), - KM_IRQ0) + orig_sgl[i].offset; - dest = dest_addr; - destlen = orig_sgl[i].length; - - if (bounce_addr == 0) - bounce_addr = - (unsigned long)kmap_atomic(sg_page((&bounce_sgl[j])), - KM_IRQ0); - - while (destlen) { - src = bounce_addr + bounce_sgl[j].offset; - srclen = bounce_sgl[j].length - bounce_sgl[j].offset; - - copylen = min(srclen, destlen); - memcpy((void *)dest, (void *)src, copylen); - - total_copied += copylen; - bounce_sgl[j].offset += copylen; - destlen -= copylen; - dest += copylen; - - if (bounce_sgl[j].offset == bounce_sgl[j].length) { - /* full */ - kunmap_atomic((void *)bounce_addr, KM_IRQ0); - j++; - - /* - * It is possible that the number of elements - * in the bounce buffer may not be equal to - * the number of elements in the original - * scatter list. Handle this correctly. - */ - - if (j == bounce_sgl_count) { - /* - * We are done; cleanup and return. - */ - kunmap_atomic((void *)(dest_addr - - orig_sgl[i].offset), - KM_IRQ0); - local_irq_restore(flags); - return total_copied; - } - - /* if we need to use another bounce buffer */ - if (destlen || i != orig_sgl_count - 1) - bounce_addr = - (unsigned long)kmap_atomic( - sg_page((&bounce_sgl[j])), KM_IRQ0); - } else if (destlen == 0 && i == orig_sgl_count - 1) { - /* unmap the last bounce that is < PAGE_SIZE */ - kunmap_atomic((void *)bounce_addr, KM_IRQ0); - } - } - - kunmap_atomic((void *)(dest_addr - orig_sgl[i].offset), - KM_IRQ0); - } - - local_irq_restore(flags); - - return total_copied; -} - - -/* Assume the bounce_sgl has enough room ie using the create_bounce_buffer() */ -static unsigned int copy_to_bounce_buffer(struct scatterlist *orig_sgl, - struct scatterlist *bounce_sgl, - unsigned int orig_sgl_count) -{ - int i; - int j = 0; - unsigned long src, dest; - unsigned int srclen, destlen, copylen; - unsigned int total_copied = 0; - unsigned long bounce_addr = 0; - unsigned long src_addr = 0; - unsigned long flags; - - local_irq_save(flags); - - for (i = 0; i < orig_sgl_count; i++) { - src_addr = (unsigned long)kmap_atomic(sg_page((&orig_sgl[i])), - KM_IRQ0) + orig_sgl[i].offset; - src = src_addr; - srclen = orig_sgl[i].length; - - if (bounce_addr == 0) - bounce_addr = - (unsigned long)kmap_atomic(sg_page((&bounce_sgl[j])), - KM_IRQ0); - - while (srclen) { - /* assume bounce offset always == 0 */ - dest = bounce_addr + bounce_sgl[j].length; - destlen = PAGE_SIZE - bounce_sgl[j].length; - - copylen = min(srclen, destlen); - memcpy((void *)dest, (void *)src, copylen); - - total_copied += copylen; - bounce_sgl[j].length += copylen; - srclen -= copylen; - src += copylen; - - if (bounce_sgl[j].length == PAGE_SIZE) { - /* full..move to next entry */ - kunmap_atomic((void *)bounce_addr, KM_IRQ0); - j++; - - /* if we need to use another bounce buffer */ - if (srclen || i != orig_sgl_count - 1) - bounce_addr = - (unsigned long)kmap_atomic( - sg_page((&bounce_sgl[j])), KM_IRQ0); - - } else if (srclen == 0 && i == orig_sgl_count - 1) { - /* unmap the last bounce that is < PAGE_SIZE */ - kunmap_atomic((void *)bounce_addr, KM_IRQ0); - } - } - - kunmap_atomic((void *)(src_addr - orig_sgl[i].offset), KM_IRQ0); - } - - local_irq_restore(flags); - - return total_copied; -} - static int storvsc_get_chs(struct scsi_device *sdev, struct block_device * bdev, sector_t capacity, int *info) { @@ -1166,83 +1240,6 @@ static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd) return SUCCESS; } - -static void storvsc_command_completion(struct hv_storvsc_request *request) -{ - struct storvsc_cmd_request *cmd_request = - (struct storvsc_cmd_request *)request->context; - struct scsi_cmnd *scmnd = cmd_request->cmd; - struct hv_host_device *host_dev = shost_priv(scmnd->device->host); - void (*scsi_done_fn)(struct scsi_cmnd *); - struct scsi_sense_hdr sense_hdr; - struct vmscsi_request *vm_srb; - struct storvsc_scan_work *wrk; - struct stor_mem_pools *memp = scmnd->device->hostdata; - - vm_srb = &request->vstor_packet.vm_srb; - if (cmd_request->bounce_sgl_count) { - if (vm_srb->data_in == READ_TYPE) - copy_from_bounce_buffer(scsi_sglist(scmnd), - cmd_request->bounce_sgl, - scsi_sg_count(scmnd), - cmd_request->bounce_sgl_count); - destroy_bounce_buffer(cmd_request->bounce_sgl, - cmd_request->bounce_sgl_count); - } - - /* - * If there is an error; offline the device since all - * error recovery strategies would have already been - * deployed on the host side. - */ - if (vm_srb->srb_status == SRB_STATUS_ERROR) - scmnd->result = DID_TARGET_FAILURE << 16; - else - scmnd->result = vm_srb->scsi_status; - - /* - * If the LUN is invalid; remove the device. - */ - if (vm_srb->srb_status == SRB_STATUS_INVALID_LUN) { - struct storvsc_device *stor_dev; - struct hv_device *dev = host_dev->dev; - struct Scsi_Host *host; - - stor_dev = get_in_stor_device(dev); - host = stor_dev->host; - - wrk = kmalloc(sizeof(struct storvsc_scan_work), - GFP_ATOMIC); - if (!wrk) { - scmnd->result = DID_TARGET_FAILURE << 16; - } else { - wrk->host = host; - wrk->lun = vm_srb->lun; - INIT_WORK(&wrk->work, storvsc_remove_lun); - schedule_work(&wrk->work); - } - } - - if (scmnd->result) { - if (scsi_normalize_sense(scmnd->sense_buffer, - SCSI_SENSE_BUFFERSIZE, &sense_hdr)) - scsi_print_sense_hdr("storvsc", &sense_hdr); - } - - scsi_set_resid(scmnd, - request->data_buffer.len - - vm_srb->data_transfer_length); - - scsi_done_fn = scmnd->scsi_done; - - scmnd->host_scribble = NULL; - scmnd->scsi_done = NULL; - - scsi_done_fn(scmnd); - - mempool_free(cmd_request, memp->request_mempool); -} - static bool storvsc_scsi_cmd_ok(struct scsi_cmnd *scmnd) { bool allowed = true; @@ -1318,7 +1315,6 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) break; } - request->on_io_completion = storvsc_command_completion; request->context = cmd_request;/* scmnd; */ vm_srb->port_number = host_dev->port; -- cgit v0.10.2 From 93a1bf4dd018af2a4931b916dd46fdfb963fa4ad Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 12 Jan 2012 12:38:02 -0800 Subject: Staging: hv: storvsc: Rename the context field in hv_storvsc_request Rename the context field in hv_storvsc_request. As part of this change fix the type of this field. Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index 7c9fa19..0515707 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -275,7 +275,7 @@ struct hv_storvsc_request { struct completion wait_event; unsigned char *sense_buffer; - void *context; + struct storvsc_cmd_request *cmd; struct hv_multipage_buffer data_buffer; struct vstor_packet vstor_packet; @@ -785,8 +785,7 @@ cleanup: static void storvsc_command_completion(struct hv_storvsc_request *request) { - struct storvsc_cmd_request *cmd_request = - (struct storvsc_cmd_request *)request->context; + struct storvsc_cmd_request *cmd_request = request->cmd; struct scsi_cmnd *scmnd = cmd_request->cmd; struct hv_host_device *host_dev = shost_priv(scmnd->device->host); void (*scsi_done_fn)(struct scsi_cmnd *); @@ -1315,7 +1314,7 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) break; } - request->context = cmd_request;/* scmnd; */ + request->cmd = cmd_request; vm_srb->port_number = host_dev->port; vm_srb->path_id = scmnd->device->channel; -- cgit v0.10.2 From c649114a5d99eb10e58f977f82018b1d77191aa7 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 12 Jan 2012 12:38:03 -0800 Subject: Staging: hv: storvsc: Miscellaneous cleanup of storvsc driver Miscellaneous cleanup of storvsc driver - get rid of unnecessary defines and use fixed size types for structures used for communication with the host. Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index 0515707..da71294 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -43,32 +43,18 @@ #include +/* + * We setup a mempool to allocate request structures for this driver + * on a per-lun basis. The following define specifies the number of + * elements in the pool. + */ + #define STORVSC_MIN_BUF_NR 64 -#define STORVSC_RING_BUFFER_SIZE (20*PAGE_SIZE) -static int storvsc_ringbuffer_size = STORVSC_RING_BUFFER_SIZE; +static int storvsc_ringbuffer_size = (20 * PAGE_SIZE); module_param(storvsc_ringbuffer_size, int, S_IRUGO); MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)"); -/* - * To alert the user that structure sizes may be mismatched even though the - * protocol versions match. - */ - - -#define REVISION_STRING(REVISION_) #REVISION_ -#define FILL_VMSTOR_REVISION(RESULT_LVALUE_) \ - do { \ - char *revision_string \ - = REVISION_STRING($Rev : 6 $) + 6; \ - RESULT_LVALUE_ = 0; \ - while (*revision_string >= '0' \ - && *revision_string <= '9') { \ - RESULT_LVALUE_ *= 10; \ - RESULT_LVALUE_ += *revision_string - '0'; \ - revision_string++; \ - } \ - } while (0) /* * Major/minor macros. Minor version is in LSB, meaning that earlier flat @@ -79,7 +65,6 @@ MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)"); #define VMSTOR_PROTOCOL_MINOR(VERSION_) (((VERSION_)) & 0xff) #define VMSTOR_PROTOCOL_VERSION(MAJOR_, MINOR_) ((((MAJOR_) & 0xff) << 8) | \ (((MINOR_) & 0xff))) -#define VMSTOR_INVALID_PROTOCOL_VERSION (-1) /* * Version history: @@ -136,26 +121,26 @@ enum vstor_packet_operation { #define MAX_DATA_BUF_LEN_WITH_PADDING 0x14 struct vmscsi_request { - unsigned short length; - unsigned char srb_status; - unsigned char scsi_status; + u16 length; + u8 srb_status; + u8 scsi_status; - unsigned char port_number; - unsigned char path_id; - unsigned char target_id; - unsigned char lun; + u8 port_number; + u8 path_id; + u8 target_id; + u8 lun; - unsigned char cdb_length; - unsigned char sense_info_length; - unsigned char data_in; - unsigned char reserved; + u8 cdb_length; + u8 sense_info_length; + u8 data_in; + u8 reserved; - unsigned int data_transfer_length; + u32 data_transfer_length; union { - unsigned char cdb[CDB16GENERIC_LENGTH]; - unsigned char sense_data[SENSE_BUFFER_SIZE]; - unsigned char reserved_array[MAX_DATA_BUF_LEN_WITH_PADDING]; + u8 cdb[CDB16GENERIC_LENGTH]; + u8 sense_data[SENSE_BUFFER_SIZE]; + u8 reserved_array[MAX_DATA_BUF_LEN_WITH_PADDING]; }; } __attribute((packed)); @@ -165,18 +150,21 @@ struct vmscsi_request { * properties of the channel. */ struct vmstorage_channel_properties { - unsigned short protocol_version; - unsigned char path_id; - unsigned char target_id; + u16 protocol_version; + u8 path_id; + u8 target_id; /* Note: port number is only really known on the client side */ - unsigned int port_number; - unsigned int flags; - unsigned int max_transfer_bytes; + u32 port_number; + u32 flags; + u32 max_transfer_bytes; - /* This id is unique for each channel and will correspond with */ - /* vendor specific data in the inquirydata */ - unsigned long long unique_id; + /* + * This id is unique for each channel and will correspond with + * vendor specific data in the inquiry data. + */ + + u64 unique_id; } __packed; /* This structure is sent during the storage protocol negotiations. */ @@ -189,6 +177,7 @@ struct vmstorage_protocol_version { * (See FILL_VMSTOR_REVISION macro above). Mismatch does not * definitely indicate incompatibility--but it does indicate mismatched * builds. + * This is only used on the windows side. Just set it to 0. */ unsigned short revision; } __packed; @@ -202,10 +191,10 @@ struct vstor_packet { enum vstor_packet_operation operation; /* Flags - see below for values */ - unsigned int flags; + u32 flags; /* Status of the request returned from the server side. */ - unsigned int status; + u32 status; /* Data payload area */ union { @@ -232,11 +221,6 @@ struct vstor_packet { #define REQUEST_COMPLETION_FLAG 0x1 -/* This is the set of flags that the vsc can set in any packets it sends */ -#define VSC_LEGAL_FLAGS (REQUEST_COMPLETION_FLAG) - - - #define STORVSC_MAX_IO_REQUESTS 128 /* @@ -252,7 +236,7 @@ struct vstor_packet { /* Matches Windows-end */ enum storvsc_request_type { - WRITE_TYPE, + WRITE_TYPE = 0, READ_TYPE, UNKNOWN_TYPE, }; @@ -704,7 +688,7 @@ static int storvsc_channel_init(struct hv_device *device) vstor_packet->flags = REQUEST_COMPLETION_FLAG; vstor_packet->version.major_minor = VMSTOR_PROTOCOL_VERSION_CURRENT; - FILL_VMSTOR_REVISION(vstor_packet->version.revision); + vstor_packet->version.revision = 0; ret = vmbus_sendpacket(device->channel, vstor_packet, sizeof(struct vstor_packet), -- cgit v0.10.2 From 85904a5e553f343243e5cf59f150174159e2e5ea Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 12 Jan 2012 12:38:04 -0800 Subject: Staging: hv: storvsc: Cleanup the code for generating protocol version Cleanup the code for generating protocol version. Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index da71294..629edd1 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -61,10 +61,13 @@ MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)"); * version numbers will be interpreted as "0.x" (i.e., 1 becomes 0.1). */ -#define VMSTOR_PROTOCOL_MAJOR(VERSION_) (((VERSION_) >> 8) & 0xff) -#define VMSTOR_PROTOCOL_MINOR(VERSION_) (((VERSION_)) & 0xff) -#define VMSTOR_PROTOCOL_VERSION(MAJOR_, MINOR_) ((((MAJOR_) & 0xff) << 8) | \ - (((MINOR_) & 0xff))) +static inline u16 storvsc_get_version(u8 major, u8 minor) +{ + u16 version; + + version = ((major << 8) | minor); + return version; +} /* * Version history: @@ -74,9 +77,8 @@ MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)"); * Win7: 4.2 */ -#define VMSTOR_PROTOCOL_VERSION_CURRENT VMSTOR_PROTOCOL_VERSION(4, 2) - - +#define VMSTOR_CURRENT_MAJOR 4 +#define VMSTOR_CURRENT_MINOR 2 /* @@ -170,7 +172,7 @@ struct vmstorage_channel_properties { /* This structure is sent during the storage protocol negotiations. */ struct vmstorage_protocol_version { /* Major (MSW) and minor (LSW) version numbers. */ - unsigned short major_minor; + u16 major_minor; /* * Revision number is auto-incremented whenever this file is changed @@ -179,7 +181,7 @@ struct vmstorage_protocol_version { * builds. * This is only used on the windows side. Just set it to 0. */ - unsigned short revision; + u16 revision; } __packed; /* Channel Property Flags */ @@ -687,7 +689,12 @@ static int storvsc_channel_init(struct hv_device *device) vstor_packet->operation = VSTOR_OPERATION_QUERY_PROTOCOL_VERSION; vstor_packet->flags = REQUEST_COMPLETION_FLAG; - vstor_packet->version.major_minor = VMSTOR_PROTOCOL_VERSION_CURRENT; + vstor_packet->version.major_minor = + storvsc_get_version(VMSTOR_CURRENT_MAJOR, VMSTOR_CURRENT_MINOR); + + /* + * The revision number is only used in Windows; set it to 0. + */ vstor_packet->version.revision = 0; ret = vmbus_sendpacket(device->channel, vstor_packet, -- cgit v0.10.2 From 6b2f949559b26448cc6d161d62341281db42c909 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 12 Jan 2012 12:38:05 -0800 Subject: Staging: hv: storvsc: Cleanup some protocol related constants Cleanup some protocol related constants. Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index 629edd1..9f07458 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -114,13 +114,9 @@ enum vstor_packet_operation { * this remains the same across the write regardless of 32/64 bit * note: it's patterned off the SCSI_PASS_THROUGH structure */ -#define CDB16GENERIC_LENGTH 0x10 - -#ifndef SENSE_BUFFER_SIZE -#define SENSE_BUFFER_SIZE 0x12 -#endif - -#define MAX_DATA_BUF_LEN_WITH_PADDING 0x14 +#define STORVSC_MAX_CMD_LEN 0x10 +#define STORVSC_SENSE_BUFFER_SIZE 0x12 +#define STORVSC_MAX_BUF_LEN_WITH_PADDING 0x14 struct vmscsi_request { u16 length; @@ -140,9 +136,9 @@ struct vmscsi_request { u32 data_transfer_length; union { - u8 cdb[CDB16GENERIC_LENGTH]; - u8 sense_data[SENSE_BUFFER_SIZE]; - u8 reserved_array[MAX_DATA_BUF_LEN_WITH_PADDING]; + u8 cdb[STORVSC_MAX_CMD_LEN]; + u8 sense_data[STORVSC_SENSE_BUFFER_SIZE]; + u8 reserved_array[STORVSC_MAX_BUF_LEN_WITH_PADDING]; }; } __attribute((packed)); @@ -234,7 +230,6 @@ struct vstor_packet { #define STORVSC_MAX_LUNS_PER_TARGET 64 #define STORVSC_MAX_TARGETS 1 #define STORVSC_MAX_CHANNELS 1 -#define STORVSC_MAX_CMD_LEN 16 /* Matches Windows-end */ enum storvsc_request_type { @@ -1074,7 +1069,7 @@ static int storvsc_do_io(struct hv_device *device, vstor_packet->vm_srb.length = sizeof(struct vmscsi_request); - vstor_packet->vm_srb.sense_info_length = SENSE_BUFFER_SIZE; + vstor_packet->vm_srb.sense_info_length = STORVSC_SENSE_BUFFER_SIZE; vstor_packet->vm_srb.data_transfer_length = -- cgit v0.10.2 From 410c52ed66cabd1837a87b37348d92a17f01c199 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 12 Jan 2012 12:38:06 -0800 Subject: Staging: hv: storvsc: Get rid of some unused defines Get rid of some unused defines. Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index 9f07458..d34e3ca 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -81,18 +81,6 @@ static inline u16 storvsc_get_version(u8 major, u8 minor) #define VMSTOR_CURRENT_MINOR 2 -/* - * This will get replaced with the max transfer length that is possible on - * the host adapter. - * The max transfer length will be published when we offer a vmbus channel. - */ - -#define MAX_TRANSFER_LENGTH 0x40000 -#define DEFAULT_PACKET_SIZE (sizeof(struct vmdata_gpa_direct) + \ - sizeof(struct vstor_packet) + \ - sizesizeof(u64) * (MAX_TRANSFER_LENGTH / PAGE_SIZE))) - - /* Packet structure describing virtual storage requests. */ enum vstor_packet_operation { VSTOR_OPERATION_COMPLETE_IO = 1, -- cgit v0.10.2 From 61eaffc91d375e02bc12c2c831478841f5ce4757 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 12 Jan 2012 12:38:07 -0800 Subject: Staging: hv: storvsc: Consolidate the request structure Consolidate the request structure by getting rid of struct hv_storvsc_request. Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index d34e3ca..9ccc1c4 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -236,17 +236,20 @@ enum storvsc_request_type { #define SRB_STATUS_ERROR 0x04 +struct storvsc_cmd_request { + struct list_head entry; + struct scsi_cmnd *cmd; + + unsigned int bounce_sgl_count; + struct scatterlist *bounce_sgl; -struct hv_storvsc_request { struct hv_device *device; /* Synchronize the request/response if needed */ struct completion wait_event; unsigned char *sense_buffer; - struct storvsc_cmd_request *cmd; struct hv_multipage_buffer data_buffer; - struct vstor_packet vstor_packet; }; @@ -272,8 +275,8 @@ struct storvsc_device { unsigned char target_id; /* Used for vsc/vsp channel reset process */ - struct hv_storvsc_request init_request; - struct hv_storvsc_request reset_request; + struct storvsc_cmd_request init_request; + struct storvsc_cmd_request reset_request; }; struct stor_mem_pools { @@ -288,16 +291,6 @@ struct hv_host_device { unsigned char target; }; -struct storvsc_cmd_request { - struct list_head entry; - struct scsi_cmnd *cmd; - - unsigned int bounce_sgl_count; - struct scatterlist *bounce_sgl; - - struct hv_storvsc_request request; -}; - struct storvsc_scan_work { struct work_struct work; struct Scsi_Host *host; @@ -628,7 +621,7 @@ static unsigned int copy_to_bounce_buffer(struct scatterlist *orig_sgl, static int storvsc_channel_init(struct hv_device *device) { struct storvsc_device *stor_device; - struct hv_storvsc_request *request; + struct storvsc_cmd_request *request; struct vstor_packet *vstor_packet; int ret, t; @@ -643,7 +636,7 @@ static int storvsc_channel_init(struct hv_device *device) * Now, initiate the vsc/vsp initialization protocol on the open * channel */ - memset(request, 0, sizeof(struct hv_storvsc_request)); + memset(request, 0, sizeof(struct storvsc_cmd_request)); init_completion(&request->wait_event); vstor_packet->operation = VSTOR_OPERATION_BEGIN_INITIALIZATION; vstor_packet->flags = REQUEST_COMPLETION_FLAG; @@ -757,9 +750,8 @@ cleanup: } -static void storvsc_command_completion(struct hv_storvsc_request *request) +static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request) { - struct storvsc_cmd_request *cmd_request = request->cmd; struct scsi_cmnd *scmnd = cmd_request->cmd; struct hv_host_device *host_dev = shost_priv(scmnd->device->host); void (*scsi_done_fn)(struct scsi_cmnd *); @@ -768,7 +760,7 @@ static void storvsc_command_completion(struct hv_storvsc_request *request) struct storvsc_scan_work *wrk; struct stor_mem_pools *memp = scmnd->device->hostdata; - vm_srb = &request->vstor_packet.vm_srb; + vm_srb = &cmd_request->vstor_packet.vm_srb; if (cmd_request->bounce_sgl_count) { if (vm_srb->data_in == READ_TYPE) copy_from_bounce_buffer(scsi_sglist(scmnd), @@ -819,7 +811,7 @@ static void storvsc_command_completion(struct hv_storvsc_request *request) } scsi_set_resid(scmnd, - request->data_buffer.len - + cmd_request->data_buffer.len - vm_srb->data_transfer_length); scsi_done_fn = scmnd->scsi_done; @@ -834,7 +826,7 @@ static void storvsc_command_completion(struct hv_storvsc_request *request) static void storvsc_on_io_completion(struct hv_device *device, struct vstor_packet *vstor_packet, - struct hv_storvsc_request *request) + struct storvsc_cmd_request *request) { struct storvsc_device *stor_device; struct vstor_packet *stor_pkt; @@ -906,7 +898,7 @@ static void storvsc_on_io_completion(struct hv_device *device, static void storvsc_on_receive(struct hv_device *device, struct vstor_packet *vstor_packet, - struct hv_storvsc_request *request) + struct storvsc_cmd_request *request) { struct storvsc_scan_work *work; struct storvsc_device *stor_device; @@ -940,7 +932,7 @@ static void storvsc_on_channel_callback(void *context) u32 bytes_recvd; u64 request_id; unsigned char packet[ALIGN(sizeof(struct vstor_packet), 8)]; - struct hv_storvsc_request *request; + struct storvsc_cmd_request *request; int ret; @@ -954,7 +946,7 @@ static void storvsc_on_channel_callback(void *context) &bytes_recvd, &request_id); if (ret == 0 && bytes_recvd > 0) { - request = (struct hv_storvsc_request *) + request = (struct storvsc_cmd_request *) (unsigned long)request_id; if ((request == &stor_device->init_request) || @@ -1036,7 +1028,7 @@ static int storvsc_dev_remove(struct hv_device *device) } static int storvsc_do_io(struct hv_device *device, - struct hv_storvsc_request *request) + struct storvsc_cmd_request *request) { struct storvsc_device *stor_device; struct vstor_packet *vstor_packet; @@ -1174,7 +1166,7 @@ static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd) struct hv_device *device = host_dev->dev; struct storvsc_device *stor_device; - struct hv_storvsc_request *request; + struct storvsc_cmd_request *request; struct vstor_packet *vstor_packet; int ret, t; @@ -1238,7 +1230,6 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) int ret; struct hv_host_device *host_dev = shost_priv(host); struct hv_device *dev = host_dev->dev; - struct hv_storvsc_request *request; struct storvsc_cmd_request *cmd_request; unsigned int request_size = 0; int i; @@ -1271,8 +1262,7 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) scmnd->host_scribble = (unsigned char *)cmd_request; - request = &cmd_request->request; - vm_srb = &request->vstor_packet.vm_srb; + vm_srb = &cmd_request->vstor_packet.vm_srb; /* Build the SRB */ @@ -1288,7 +1278,6 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) break; } - request->cmd = cmd_request; vm_srb->port_number = host_dev->port; vm_srb->path_id = scmnd->device->channel; @@ -1299,10 +1288,10 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) memcpy(vm_srb->cdb, scmnd->cmnd, vm_srb->cdb_length); - request->sense_buffer = scmnd->sense_buffer; + cmd_request->sense_buffer = scmnd->sense_buffer; - request->data_buffer.len = scsi_bufflen(scmnd); + cmd_request->data_buffer.len = scsi_bufflen(scmnd); if (scsi_sg_count(scmnd)) { sgl = (struct scatterlist *)scsi_sglist(scmnd); sg_count = scsi_sg_count(scmnd); @@ -1331,21 +1320,21 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) sg_count = cmd_request->bounce_sgl_count; } - request->data_buffer.offset = sgl[0].offset; + cmd_request->data_buffer.offset = sgl[0].offset; for (i = 0; i < sg_count; i++) - request->data_buffer.pfn_array[i] = + cmd_request->data_buffer.pfn_array[i] = page_to_pfn(sg_page((&sgl[i]))); } else if (scsi_sglist(scmnd)) { - request->data_buffer.offset = + cmd_request->data_buffer.offset = virt_to_phys(scsi_sglist(scmnd)) & (PAGE_SIZE-1); - request->data_buffer.pfn_array[0] = + cmd_request->data_buffer.pfn_array[0] = virt_to_phys(scsi_sglist(scmnd)) >> PAGE_SHIFT; } /* Invokes the vsc to start an IO */ - ret = storvsc_do_io(dev, &cmd_request->request); + ret = storvsc_do_io(dev, cmd_request); if (ret == -EAGAIN) { /* no more space */ -- cgit v0.10.2 From af9584b82df77751710db45043cf8d7d7740056d Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 12 Jan 2012 12:38:08 -0800 Subject: Staging: hv: storvsc: Consolidate all the wire protocol definitions Consolidate all definitions that support communication with the host. Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index 9ccc1c4..695ffc3 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -42,33 +42,13 @@ #include #include - -/* - * We setup a mempool to allocate request structures for this driver - * on a per-lun basis. The following define specifies the number of - * elements in the pool. - */ - -#define STORVSC_MIN_BUF_NR 64 -static int storvsc_ringbuffer_size = (20 * PAGE_SIZE); - -module_param(storvsc_ringbuffer_size, int, S_IRUGO); -MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)"); - - /* - * Major/minor macros. Minor version is in LSB, meaning that earlier flat - * version numbers will be interpreted as "0.x" (i.e., 1 becomes 0.1). + * All wire protocol details (storage protocol between the guest and the host) + * are consolidated here. + * + * Begin protocol definitions. */ -static inline u16 storvsc_get_version(u8 major, u8 minor) -{ - u16 version; - - version = ((major << 8) | minor); - return version; -} - /* * Version history: * V1 Beta: 0.1 @@ -207,18 +187,6 @@ struct vstor_packet { #define REQUEST_COMPLETION_FLAG 0x1 -#define STORVSC_MAX_IO_REQUESTS 128 - -/* - * In Hyper-V, each port/path/target maps to 1 scsi host adapter. In - * reality, the path/target is not used (ie always set to 0) so our - * scsi host adapter essentially has 1 bus with 1 target that contains - * up to 256 luns. - */ -#define STORVSC_MAX_LUNS_PER_TARGET 64 -#define STORVSC_MAX_TARGETS 1 -#define STORVSC_MAX_CHANNELS 1 - /* Matches Windows-end */ enum storvsc_request_type { WRITE_TYPE = 0, @@ -235,6 +203,36 @@ enum storvsc_request_type { #define SRB_STATUS_SUCCESS 0x01 #define SRB_STATUS_ERROR 0x04 +/* + * This is the end of Protocol specific defines. + */ + + +/* + * We setup a mempool to allocate request structures for this driver + * on a per-lun basis. The following define specifies the number of + * elements in the pool. + */ + +#define STORVSC_MIN_BUF_NR 64 +static int storvsc_ringbuffer_size = (20 * PAGE_SIZE); + +module_param(storvsc_ringbuffer_size, int, S_IRUGO); +MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)"); + +#define STORVSC_MAX_IO_REQUESTS 128 + +/* + * In Hyper-V, each port/path/target maps to 1 scsi host adapter. In + * reality, the path/target is not used (ie always set to 0) so our + * scsi host adapter essentially has 1 bus with 1 target that contains + * up to 256 luns. + */ +#define STORVSC_MAX_LUNS_PER_TARGET 64 +#define STORVSC_MAX_TARGETS 1 +#define STORVSC_MAX_CHANNELS 1 + + struct storvsc_cmd_request { struct list_head entry; @@ -337,6 +335,19 @@ done: } /* + * Major/minor macros. Minor version is in LSB, meaning that earlier flat + * version numbers will be interpreted as "0.x" (i.e., 1 becomes 0.1). + */ + +static inline u16 storvsc_get_version(u8 major, u8 minor) +{ + u16 version; + + version = ((major << 8) | minor); + return version; +} + +/* * We can get incoming messages from the host that are not in response to * messages that we have sent out. An example of this would be messages * received by the guest to notify dynamic addition/removal of LUNs. To -- cgit v0.10.2 From 17dd9f831a3c70588d54cc3a24594f274f9ec3a1 Mon Sep 17 00:00:00 2001 From: Seth Jennings Date: Tue, 3 Jan 2012 16:31:34 -0600 Subject: staging: zcache: crypto API support This patch allow zcache to use the crypto API for page compression. It replaces the direct LZO compress/decompress calls with calls into the crypto compression API. The compressor to be used is specified in the kernel boot line with the zcache parameter like: zcache=lzo or zcache=deflate. If the specified compressor can't be loaded, zcache uses lzo as the default compressor. Signed-off-by: Seth Jennings Acked-by: Dan Magenheimer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/zcache/Kconfig b/drivers/staging/zcache/Kconfig index 7fabcb2..1b7bba7 100644 --- a/drivers/staging/zcache/Kconfig +++ b/drivers/staging/zcache/Kconfig @@ -1,13 +1,12 @@ config ZCACHE tristate "Dynamic compression of swap pages and clean pagecache pages" - depends on CLEANCACHE || FRONTSWAP + depends on (CLEANCACHE || FRONTSWAP) && CRYPTO select XVMALLOC - select LZO_COMPRESS - select LZO_DECOMPRESS + select CRYPTO_LZO default n help Zcache doubles RAM efficiency while providing a significant - performance boosts on many workloads. Zcache uses lzo1x + performance boosts on many workloads. Zcache uses compression and an in-kernel implementation of transcendent memory to store clean page cache pages and swap in RAM, providing a noticeable reduction in disk I/O. diff --git a/drivers/staging/zcache/zcache-main.c b/drivers/staging/zcache/zcache-main.c index 642840c..da222c2 100644 --- a/drivers/staging/zcache/zcache-main.c +++ b/drivers/staging/zcache/zcache-main.c @@ -6,7 +6,8 @@ * * Zcache provides an in-kernel "host implementation" for transcendent memory * and, thus indirectly, for cleancache and frontswap. Zcache includes two - * page-accessible memory [1] interfaces, both utilizing lzo1x compression: + * page-accessible memory [1] interfaces, both utilizing the crypto compression + * API: * 1) "compression buddies" ("zbud") is used for ephemeral pages * 2) xvmalloc is used for persistent pages. * Xvmalloc (based on the TLSF allocator) has very low fragmentation @@ -23,12 +24,13 @@ #include #include #include -#include #include #include #include #include #include +#include +#include #include "tmem.h" #include "../zram/xvmalloc.h" /* if built in drivers/staging */ @@ -81,6 +83,38 @@ static inline bool is_local_client(struct zcache_client *cli) return cli == &zcache_host; } +/* crypto API for zcache */ +#define ZCACHE_COMP_NAME_SZ CRYPTO_MAX_ALG_NAME +static char zcache_comp_name[ZCACHE_COMP_NAME_SZ]; +static struct crypto_comp * __percpu *zcache_comp_pcpu_tfms; + +enum comp_op { + ZCACHE_COMPOP_COMPRESS, + ZCACHE_COMPOP_DECOMPRESS +}; + +static inline int zcache_comp_op(enum comp_op op, + const u8 *src, unsigned int slen, + u8 *dst, unsigned int *dlen) +{ + struct crypto_comp *tfm; + int ret; + + BUG_ON(!zcache_comp_pcpu_tfms); + tfm = *per_cpu_ptr(zcache_comp_pcpu_tfms, get_cpu()); + BUG_ON(!tfm); + switch (op) { + case ZCACHE_COMPOP_COMPRESS: + ret = crypto_comp_compress(tfm, src, slen, dst, dlen); + break; + case ZCACHE_COMPOP_DECOMPRESS: + ret = crypto_comp_decompress(tfm, src, slen, dst, dlen); + break; + } + put_cpu(); + return ret; +} + /********** * Compression buddies ("zbud") provides for packing two (or, possibly * in the future, more) compressed ephemeral pages into a single "raw" @@ -408,7 +442,7 @@ static int zbud_decompress(struct page *page, struct zbud_hdr *zh) { struct zbud_page *zbpg; unsigned budnum = zbud_budnum(zh); - size_t out_len = PAGE_SIZE; + unsigned int out_len = PAGE_SIZE; char *to_va, *from_va; unsigned size; int ret = 0; @@ -425,8 +459,9 @@ static int zbud_decompress(struct page *page, struct zbud_hdr *zh) to_va = kmap_atomic(page, KM_USER0); size = zh->size; from_va = zbud_data(zh, size); - ret = lzo1x_decompress_safe(from_va, size, to_va, &out_len); - BUG_ON(ret != LZO_E_OK); + ret = zcache_comp_op(ZCACHE_COMPOP_DECOMPRESS, from_va, size, + to_va, &out_len); + BUG_ON(ret); BUG_ON(out_len != PAGE_SIZE); kunmap_atomic(to_va, KM_USER0); out: @@ -624,7 +659,7 @@ static int zbud_show_cumul_chunk_counts(char *buf) /********** * This "zv" PAM implementation combines the TLSF-based xvMalloc - * with lzo1x compression to maximize the amount of data that can + * with the crypto compression API to maximize the amount of data that can * be packed into a physical page. * * Zv represents a PAM page with the index and object (plus a "size" value @@ -711,7 +746,7 @@ static void zv_free(struct xv_pool *xvpool, struct zv_hdr *zv) static void zv_decompress(struct page *page, struct zv_hdr *zv) { - size_t clen = PAGE_SIZE; + unsigned int clen = PAGE_SIZE; char *to_va; unsigned size; int ret; @@ -720,10 +755,10 @@ static void zv_decompress(struct page *page, struct zv_hdr *zv) size = xv_get_object_size(zv) - sizeof(*zv); BUG_ON(size == 0); to_va = kmap_atomic(page, KM_USER0); - ret = lzo1x_decompress_safe((char *)zv + sizeof(*zv), - size, to_va, &clen); + ret = zcache_comp_op(ZCACHE_COMPOP_DECOMPRESS, (char *)zv + sizeof(*zv), + size, to_va, &clen); kunmap_atomic(to_va, KM_USER0); - BUG_ON(ret != LZO_E_OK); + BUG_ON(ret); BUG_ON(clen != PAGE_SIZE); } @@ -1286,25 +1321,24 @@ static struct tmem_pamops zcache_pamops = { * zcache compression/decompression and related per-cpu stuff */ -#define LZO_WORKMEM_BYTES LZO1X_1_MEM_COMPRESS -#define LZO_DSTMEM_PAGE_ORDER 1 -static DEFINE_PER_CPU(unsigned char *, zcache_workmem); static DEFINE_PER_CPU(unsigned char *, zcache_dstmem); +#define ZCACHE_DSTMEM_ORDER 1 static int zcache_compress(struct page *from, void **out_va, size_t *out_len) { int ret = 0; unsigned char *dmem = __get_cpu_var(zcache_dstmem); - unsigned char *wmem = __get_cpu_var(zcache_workmem); char *from_va; BUG_ON(!irqs_disabled()); - if (unlikely(dmem == NULL || wmem == NULL)) - goto out; /* no buffer, so can't compress */ + if (unlikely(dmem == NULL)) + goto out; /* no buffer or no compressor so can't compress */ + *out_len = PAGE_SIZE << ZCACHE_DSTMEM_ORDER; from_va = kmap_atomic(from, KM_USER0); mb(); - ret = lzo1x_1_compress(from_va, PAGE_SIZE, dmem, out_len, wmem); - BUG_ON(ret != LZO_E_OK); + ret = zcache_comp_op(ZCACHE_COMPOP_COMPRESS, from_va, PAGE_SIZE, dmem, + (unsigned int *)out_len); + BUG_ON(ret); *out_va = dmem; kunmap_atomic(from_va, KM_USER0); ret = 1; @@ -1312,29 +1346,48 @@ out: return ret; } +static int zcache_comp_cpu_up(int cpu) +{ + struct crypto_comp *tfm; + + tfm = crypto_alloc_comp(zcache_comp_name, 0, 0); + if (IS_ERR(tfm)) + return NOTIFY_BAD; + *per_cpu_ptr(zcache_comp_pcpu_tfms, cpu) = tfm; + return NOTIFY_OK; +} + +static void zcache_comp_cpu_down(int cpu) +{ + struct crypto_comp *tfm; + + tfm = *per_cpu_ptr(zcache_comp_pcpu_tfms, cpu); + crypto_free_comp(tfm); + *per_cpu_ptr(zcache_comp_pcpu_tfms, cpu) = NULL; +} static int zcache_cpu_notifier(struct notifier_block *nb, unsigned long action, void *pcpu) { - int cpu = (long)pcpu; + int ret, cpu = (long)pcpu; struct zcache_preload *kp; switch (action) { case CPU_UP_PREPARE: + ret = zcache_comp_cpu_up(cpu); + if (ret != NOTIFY_OK) { + pr_err("zcache: can't allocate compressor transform\n"); + return ret; + } per_cpu(zcache_dstmem, cpu) = (void *)__get_free_pages( - GFP_KERNEL | __GFP_REPEAT, - LZO_DSTMEM_PAGE_ORDER), - per_cpu(zcache_workmem, cpu) = - kzalloc(LZO1X_MEM_COMPRESS, - GFP_KERNEL | __GFP_REPEAT); + GFP_KERNEL | __GFP_REPEAT, ZCACHE_DSTMEM_ORDER); break; case CPU_DEAD: case CPU_UP_CANCELED: + zcache_comp_cpu_down(cpu); free_pages((unsigned long)per_cpu(zcache_dstmem, cpu), - LZO_DSTMEM_PAGE_ORDER); + ZCACHE_DSTMEM_ORDER); per_cpu(zcache_dstmem, cpu) = NULL; - kfree(per_cpu(zcache_workmem, cpu)); - per_cpu(zcache_workmem, cpu) = NULL; kp = &per_cpu(zcache_preloads, cpu); while (kp->nr) { kmem_cache_free(zcache_objnode_cache, @@ -1919,6 +1972,44 @@ static int __init no_frontswap(char *s) __setup("nofrontswap", no_frontswap); +static int __init enable_zcache_compressor(char *s) +{ + strncpy(zcache_comp_name, s, ZCACHE_COMP_NAME_SZ); + zcache_enabled = 1; + return 1; +} +__setup("zcache=", enable_zcache_compressor); + + +static int zcache_comp_init(void) +{ + int ret = 0; + + /* check crypto algorithm */ + if (*zcache_comp_name != '\0') { + ret = crypto_has_comp(zcache_comp_name, 0, 0); + if (!ret) + pr_info("zcache: %s not supported\n", + zcache_comp_name); + } + if (!ret) + strcpy(zcache_comp_name, "lzo"); + ret = crypto_has_comp(zcache_comp_name, 0, 0); + if (!ret) { + ret = 1; + goto out; + } + pr_info("zcache: using %s compressor\n", zcache_comp_name); + + /* alloc percpu transforms */ + ret = 0; + zcache_comp_pcpu_tfms = alloc_percpu(struct crypto_comp *); + if (!zcache_comp_pcpu_tfms) + ret = 1; +out: + return ret; +} + static int __init zcache_init(void) { int ret = 0; @@ -1941,6 +2032,11 @@ static int __init zcache_init(void) pr_err("zcache: can't register cpu notifier\n"); goto out; } + ret = zcache_comp_init(); + if (ret) { + pr_err("zcache: compressor initialization failed\n"); + goto out; + } for_each_online_cpu(cpu) { void *pcpu = (void *)(long)cpu; zcache_cpu_notifier(&zcache_cpu_notifier_block, -- cgit v0.10.2 From 61989a80fb3ac9d7837d03053624d5ea034a0d02 Mon Sep 17 00:00:00 2001 From: Nitin Gupta Date: Mon, 9 Jan 2012 16:51:56 -0600 Subject: staging: zsmalloc: zsmalloc memory allocation library This patch creates a new memory allocation library named zsmalloc. NOTE: zsmalloc currently depends on SPARSEMEM for the MAX_PHYSMEM_BITS value needed to determine the format of the object handle. There may be a better way to do this. Feedback is welcome. Signed-off-by: Nitin Gupta Signed-off-by: Seth Jennings Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/zsmalloc/Kconfig b/drivers/staging/zsmalloc/Kconfig new file mode 100644 index 0000000..3e7a8d4 --- /dev/null +++ b/drivers/staging/zsmalloc/Kconfig @@ -0,0 +1,11 @@ +config ZSMALLOC + tristate "Memory allocator for compressed pages" + depends on SPARSEMEM + default n + help + zsmalloc is a slab-based memory allocator designed to store + compressed RAM pages. zsmalloc uses virtual memory mapping + in order to reduce fragmentation. However, this results in a + non-standard allocator interface where a handle, not a pointer, is + returned by an alloc(). This handle must be mapped in order to + access the allocated space. diff --git a/drivers/staging/zsmalloc/Makefile b/drivers/staging/zsmalloc/Makefile new file mode 100644 index 0000000..b134848 --- /dev/null +++ b/drivers/staging/zsmalloc/Makefile @@ -0,0 +1,3 @@ +zsmalloc-y := zsmalloc-main.o + +obj-$(CONFIG_ZSMALLOC) += zsmalloc.o diff --git a/drivers/staging/zsmalloc/zsmalloc-main.c b/drivers/staging/zsmalloc/zsmalloc-main.c new file mode 100644 index 0000000..189fb42 --- /dev/null +++ b/drivers/staging/zsmalloc/zsmalloc-main.c @@ -0,0 +1,756 @@ +/* + * zsmalloc memory allocator + * + * Copyright (C) 2011 Nitin Gupta + * + * This code is released using a dual license strategy: BSD/GPL + * You can choose the license that better fits your requirements. + * + * Released under the terms of 3-clause BSD License + * Released under the terms of GNU General Public License Version 2.0 + */ + +#ifdef CONFIG_ZSMALLOC_DEBUG +#define DEBUG +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "zsmalloc.h" +#include "zsmalloc_int.h" + +/* + * A zspage's class index and fullness group + * are encoded in its (first)page->mapping + */ +#define CLASS_IDX_BITS 28 +#define FULLNESS_BITS 4 +#define CLASS_IDX_MASK ((1 << CLASS_IDX_BITS) - 1) +#define FULLNESS_MASK ((1 << FULLNESS_BITS) - 1) + +/* + * Object location (, ) is encoded as + * as single (void *) handle value. + * + * Note that object index is relative to system + * page it is stored in, so for each sub-page belonging + * to a zspage, obj_idx starts with 0. + */ +#define _PFN_BITS (MAX_PHYSMEM_BITS - PAGE_SHIFT) +#define OBJ_INDEX_BITS (BITS_PER_LONG - _PFN_BITS) +#define OBJ_INDEX_MASK ((_AC(1, UL) << OBJ_INDEX_BITS) - 1) + +/* per-cpu VM mapping areas for zspage accesses that cross page boundaries */ +static DEFINE_PER_CPU(struct mapping_area, zs_map_area); + +static int is_first_page(struct page *page) +{ + return test_bit(PG_private, &page->flags); +} + +static int is_last_page(struct page *page) +{ + return test_bit(PG_private_2, &page->flags); +} + +static void get_zspage_mapping(struct page *page, unsigned int *class_idx, + enum fullness_group *fullness) +{ + unsigned long m; + BUG_ON(!is_first_page(page)); + + m = (unsigned long)page->mapping; + *fullness = m & FULLNESS_MASK; + *class_idx = (m >> FULLNESS_BITS) & CLASS_IDX_MASK; +} + +static void set_zspage_mapping(struct page *page, unsigned int class_idx, + enum fullness_group fullness) +{ + unsigned long m; + BUG_ON(!is_first_page(page)); + + m = ((class_idx & CLASS_IDX_MASK) << FULLNESS_BITS) | + (fullness & FULLNESS_MASK); + page->mapping = (struct address_space *)m; +} + +static int get_size_class_index(int size) +{ + int idx = 0; + + if (likely(size > ZS_MIN_ALLOC_SIZE)) + idx = DIV_ROUND_UP(size - ZS_MIN_ALLOC_SIZE, + ZS_SIZE_CLASS_DELTA); + + return idx; +} + +static enum fullness_group get_fullness_group(struct page *page) +{ + int inuse, max_objects; + enum fullness_group fg; + BUG_ON(!is_first_page(page)); + + inuse = page->inuse; + max_objects = page->objects; + + if (inuse == 0) + fg = ZS_EMPTY; + else if (inuse == max_objects) + fg = ZS_FULL; + else if (inuse <= max_objects / fullness_threshold_frac) + fg = ZS_ALMOST_EMPTY; + else + fg = ZS_ALMOST_FULL; + + return fg; +} + +static void insert_zspage(struct page *page, struct size_class *class, + enum fullness_group fullness) +{ + struct page **head; + + BUG_ON(!is_first_page(page)); + + if (fullness >= _ZS_NR_FULLNESS_GROUPS) + return; + + head = &class->fullness_list[fullness]; + if (*head) + list_add_tail(&page->lru, &(*head)->lru); + + *head = page; +} + +static void remove_zspage(struct page *page, struct size_class *class, + enum fullness_group fullness) +{ + struct page **head; + + BUG_ON(!is_first_page(page)); + + if (fullness >= _ZS_NR_FULLNESS_GROUPS) + return; + + head = &class->fullness_list[fullness]; + BUG_ON(!*head); + if (list_empty(&(*head)->lru)) + *head = NULL; + else if (*head == page) + *head = (struct page *)list_entry((*head)->lru.next, + struct page, lru); + + list_del_init(&page->lru); +} + +static enum fullness_group fix_fullness_group(struct zs_pool *pool, + struct page *page) +{ + int class_idx; + struct size_class *class; + enum fullness_group currfg, newfg; + + BUG_ON(!is_first_page(page)); + + get_zspage_mapping(page, &class_idx, &currfg); + newfg = get_fullness_group(page); + if (newfg == currfg) + goto out; + + class = &pool->size_class[class_idx]; + remove_zspage(page, class, currfg); + insert_zspage(page, class, newfg); + set_zspage_mapping(page, class_idx, newfg); + +out: + return newfg; +} + +/* + * We have to decide on how many pages to link together + * to form a zspage for each size class. This is important + * to reduce wastage due to unusable space left at end of + * each zspage which is given as: + * wastage = Zp - Zp % size_class + * where Zp = zspage size = k * PAGE_SIZE where k = 1, 2, ... + * + * For example, for size class of 3/8 * PAGE_SIZE, we should + * link together 3 PAGE_SIZE sized pages to form a zspage + * since then we can perfectly fit in 8 such objects. + */ +static int get_zspage_order(int class_size) +{ + int i, max_usedpc = 0; + /* zspage order which gives maximum used size per KB */ + int max_usedpc_order = 1; + + for (i = 1; i <= max_zspage_order; i++) { + int zspage_size; + int waste, usedpc; + + zspage_size = i * PAGE_SIZE; + waste = zspage_size % class_size; + usedpc = (zspage_size - waste) * 100 / zspage_size; + + if (usedpc > max_usedpc) { + max_usedpc = usedpc; + max_usedpc_order = i; + } + } + + return max_usedpc_order; +} + +/* + * A single 'zspage' is composed of many system pages which are + * linked together using fields in struct page. This function finds + * the first/head page, given any component page of a zspage. + */ +static struct page *get_first_page(struct page *page) +{ + if (is_first_page(page)) + return page; + else + return page->first_page; +} + +static struct page *get_next_page(struct page *page) +{ + struct page *next; + + if (is_last_page(page)) + next = NULL; + else if (is_first_page(page)) + next = (struct page *)page->private; + else + next = list_entry(page->lru.next, struct page, lru); + + return next; +} + +/* Encode as a single handle value */ +static void *obj_location_to_handle(struct page *page, unsigned long obj_idx) +{ + unsigned long handle; + + if (!page) { + BUG_ON(obj_idx); + return NULL; + } + + handle = page_to_pfn(page) << OBJ_INDEX_BITS; + handle |= (obj_idx & OBJ_INDEX_MASK); + + return (void *)handle; +} + +/* Decode pair from the given object handle */ +static void obj_handle_to_location(void *handle, struct page **page, + unsigned long *obj_idx) +{ + unsigned long hval = (unsigned long)handle; + + *page = pfn_to_page(hval >> OBJ_INDEX_BITS); + *obj_idx = hval & OBJ_INDEX_MASK; +} + +static unsigned long obj_idx_to_offset(struct page *page, + unsigned long obj_idx, int class_size) +{ + unsigned long off = 0; + + if (!is_first_page(page)) + off = page->index; + + return off + obj_idx * class_size; +} + +static void free_zspage(struct page *first_page) +{ + struct page *nextp, *tmp; + + BUG_ON(!is_first_page(first_page)); + BUG_ON(first_page->inuse); + + nextp = (struct page *)page_private(first_page); + + clear_bit(PG_private, &first_page->flags); + clear_bit(PG_private_2, &first_page->flags); + set_page_private(first_page, 0); + first_page->mapping = NULL; + first_page->freelist = NULL; + reset_page_mapcount(first_page); + __free_page(first_page); + + /* zspage with only 1 system page */ + if (!nextp) + return; + + list_for_each_entry_safe(nextp, tmp, &nextp->lru, lru) { + list_del(&nextp->lru); + clear_bit(PG_private_2, &nextp->flags); + nextp->index = 0; + __free_page(nextp); + } +} + +/* Initialize a newly allocated zspage */ +static void init_zspage(struct page *first_page, struct size_class *class) +{ + unsigned long off = 0; + struct page *page = first_page; + + BUG_ON(!is_first_page(first_page)); + while (page) { + struct page *next_page; + struct link_free *link; + unsigned int i, objs_on_page; + + /* + * page->index stores offset of first object starting + * in the page. For the first page, this is always 0, + * so we use first_page->index (aka ->freelist) to store + * head of corresponding zspage's freelist. + */ + if (page != first_page) + page->index = off; + + link = (struct link_free *)kmap_atomic(page) + + off / sizeof(*link); + objs_on_page = (PAGE_SIZE - off) / class->size; + + for (i = 1; i <= objs_on_page; i++) { + off += class->size; + if (off < PAGE_SIZE) { + link->next = obj_location_to_handle(page, i); + link += class->size / sizeof(*link); + } + } + + /* + * We now come to the last (full or partial) object on this + * page, which must point to the first object on the next + * page (if present) + */ + next_page = get_next_page(page); + link->next = obj_location_to_handle(next_page, 0); + kunmap_atomic(link); + page = next_page; + off = (off + class->size) % PAGE_SIZE; + } +} + +/* + * Allocate a zspage for the given size class + */ +static struct page *alloc_zspage(struct size_class *class, gfp_t flags) +{ + int i, error; + struct page *first_page = NULL; + + /* + * Allocate individual pages and link them together as: + * 1. first page->private = first sub-page + * 2. all sub-pages are linked together using page->lru + * 3. each sub-page is linked to the first page using page->first_page + * + * For each size class, First/Head pages are linked together using + * page->lru. Also, we set PG_private to identify the first page + * (i.e. no other sub-page has this flag set) and PG_private_2 to + * identify the last page. + */ + error = -ENOMEM; + for (i = 0; i < class->zspage_order; i++) { + struct page *page, *prev_page; + + page = alloc_page(flags); + if (!page) + goto cleanup; + + INIT_LIST_HEAD(&page->lru); + if (i == 0) { /* first page */ + set_bit(PG_private, &page->flags); + set_page_private(page, 0); + first_page = page; + first_page->inuse = 0; + } + if (i == 1) + first_page->private = (unsigned long)page; + if (i >= 1) + page->first_page = first_page; + if (i >= 2) + list_add(&page->lru, &prev_page->lru); + if (i == class->zspage_order - 1) /* last page */ + set_bit(PG_private_2, &page->flags); + + prev_page = page; + } + + init_zspage(first_page, class); + + first_page->freelist = obj_location_to_handle(first_page, 0); + /* Maximum number of objects we can store in this zspage */ + first_page->objects = class->zspage_order * PAGE_SIZE / class->size; + + error = 0; /* Success */ + +cleanup: + if (unlikely(error) && first_page) { + free_zspage(first_page); + first_page = NULL; + } + + return first_page; +} + +static struct page *find_get_zspage(struct size_class *class) +{ + int i; + struct page *page; + + for (i = 0; i < _ZS_NR_FULLNESS_GROUPS; i++) { + page = class->fullness_list[i]; + if (page) + break; + } + + return page; +} + + +/* + * If this becomes a separate module, register zs_init() with + * module_init(), zs_exit with module_exit(), and remove zs_initialized +*/ +static int zs_initialized; + +static int zs_cpu_notifier(struct notifier_block *nb, unsigned long action, + void *pcpu) +{ + int cpu = (long)pcpu; + struct mapping_area *area; + + switch (action) { + case CPU_UP_PREPARE: + area = &per_cpu(zs_map_area, cpu); + if (area->vm) + break; + area->vm = alloc_vm_area(2 * PAGE_SIZE, area->vm_ptes); + if (!area->vm) + return notifier_from_errno(-ENOMEM); + break; + case CPU_DEAD: + case CPU_UP_CANCELED: + area = &per_cpu(zs_map_area, cpu); + if (area->vm) + free_vm_area(area->vm); + area->vm = NULL; + break; + } + + return NOTIFY_OK; +} + +static struct notifier_block zs_cpu_nb = { + .notifier_call = zs_cpu_notifier +}; + +static void zs_exit(void) +{ + int cpu; + + for_each_online_cpu(cpu) + zs_cpu_notifier(NULL, CPU_DEAD, (void *)(long)cpu); + unregister_cpu_notifier(&zs_cpu_nb); +} + +static int zs_init(void) +{ + int cpu, ret; + + register_cpu_notifier(&zs_cpu_nb); + for_each_online_cpu(cpu) { + ret = zs_cpu_notifier(NULL, CPU_UP_PREPARE, (void *)(long)cpu); + if (notifier_to_errno(ret)) + goto fail; + } + return 0; +fail: + zs_exit(); + return notifier_to_errno(ret); +} + +struct zs_pool *zs_create_pool(const char *name, gfp_t flags) +{ + int i, error, ovhd_size; + struct zs_pool *pool; + + if (!name) + return NULL; + + ovhd_size = roundup(sizeof(*pool), PAGE_SIZE); + pool = kzalloc(ovhd_size, GFP_KERNEL); + if (!pool) + return NULL; + + for (i = 0; i < ZS_SIZE_CLASSES; i++) { + int size; + struct size_class *class; + + size = ZS_MIN_ALLOC_SIZE + i * ZS_SIZE_CLASS_DELTA; + if (size > ZS_MAX_ALLOC_SIZE) + size = ZS_MAX_ALLOC_SIZE; + + class = &pool->size_class[i]; + class->size = size; + class->index = i; + spin_lock_init(&class->lock); + class->zspage_order = get_zspage_order(size); + + } + + /* + * If this becomes a separate module, register zs_init with + * module_init, and remove this block + */ + if (!zs_initialized) { + error = zs_init(); + if (error) + goto cleanup; + zs_initialized = 1; + } + + pool->flags = flags; + pool->name = name; + + error = 0; /* Success */ + +cleanup: + if (error) { + zs_destroy_pool(pool); + pool = NULL; + } + + return pool; +} +EXPORT_SYMBOL_GPL(zs_create_pool); + +void zs_destroy_pool(struct zs_pool *pool) +{ + int i; + + for (i = 0; i < ZS_SIZE_CLASSES; i++) { + int fg; + struct size_class *class = &pool->size_class[i]; + + for (fg = 0; fg < _ZS_NR_FULLNESS_GROUPS; fg++) { + if (class->fullness_list[fg]) { + pr_info("Freeing non-empty class with size " + "%db, fullness group %d\n", + class->size, fg); + } + } + } + kfree(pool); +} +EXPORT_SYMBOL_GPL(zs_destroy_pool); + +/** + * zs_malloc - Allocate block of given size from pool. + * @pool: pool to allocate from + * @size: size of block to allocate + * @page: page no. that holds the object + * @offset: location of object within page + * + * On success, identifies block allocated + * and 0 is returned. On failure, is set to + * 0 and -ENOMEM is returned. + * + * Allocation requests with size > ZS_MAX_ALLOC_SIZE will fail. + */ +void *zs_malloc(struct zs_pool *pool, size_t size) +{ + void *obj; + struct link_free *link; + int class_idx; + struct size_class *class; + + struct page *first_page, *m_page; + unsigned long m_objidx, m_offset; + + if (unlikely(!size || size > ZS_MAX_ALLOC_SIZE)) + return NULL; + + class_idx = get_size_class_index(size); + class = &pool->size_class[class_idx]; + BUG_ON(class_idx != class->index); + + spin_lock(&class->lock); + first_page = find_get_zspage(class); + + if (!first_page) { + spin_unlock(&class->lock); + first_page = alloc_zspage(class, pool->flags); + if (unlikely(!first_page)) + return NULL; + + set_zspage_mapping(first_page, class->index, ZS_EMPTY); + spin_lock(&class->lock); + class->pages_allocated += class->zspage_order; + } + + obj = first_page->freelist; + obj_handle_to_location(obj, &m_page, &m_objidx); + m_offset = obj_idx_to_offset(m_page, m_objidx, class->size); + + link = (struct link_free *)kmap_atomic(m_page) + + m_offset / sizeof(*link); + first_page->freelist = link->next; + memset(link, POISON_INUSE, sizeof(*link)); + kunmap_atomic(link); + + first_page->inuse++; + /* Now move the zspage to another fullness group, if required */ + fix_fullness_group(pool, first_page); + spin_unlock(&class->lock); + + return obj; +} +EXPORT_SYMBOL_GPL(zs_malloc); + +void zs_free(struct zs_pool *pool, void *obj) +{ + struct link_free *link; + struct page *first_page, *f_page; + unsigned long f_objidx, f_offset; + + int class_idx; + struct size_class *class; + enum fullness_group fullness; + + if (unlikely(!obj)) + return; + + obj_handle_to_location(obj, &f_page, &f_objidx); + first_page = get_first_page(f_page); + + get_zspage_mapping(first_page, &class_idx, &fullness); + class = &pool->size_class[class_idx]; + f_offset = obj_idx_to_offset(f_page, f_objidx, class->size); + + spin_lock(&class->lock); + + /* Insert this object in containing zspage's freelist */ + link = (struct link_free *)((unsigned char *)kmap_atomic(f_page) + + f_offset); + link->next = first_page->freelist; + kunmap_atomic(link); + first_page->freelist = obj; + + first_page->inuse--; + fullness = fix_fullness_group(pool, first_page); + + if (fullness == ZS_EMPTY) + class->pages_allocated -= class->zspage_order; + + spin_unlock(&class->lock); + + if (fullness == ZS_EMPTY) + free_zspage(first_page); +} +EXPORT_SYMBOL_GPL(zs_free); + +void *zs_map_object(struct zs_pool *pool, void *handle) +{ + struct page *page; + unsigned long obj_idx, off; + + unsigned int class_idx; + enum fullness_group fg; + struct size_class *class; + struct mapping_area *area; + + BUG_ON(!handle); + + obj_handle_to_location(handle, &page, &obj_idx); + get_zspage_mapping(get_first_page(page), &class_idx, &fg); + class = &pool->size_class[class_idx]; + off = obj_idx_to_offset(page, obj_idx, class->size); + + area = &get_cpu_var(zs_map_area); + if (off + class->size <= PAGE_SIZE) { + /* this object is contained entirely within a page */ + area->vm_addr = kmap_atomic(page); + } else { + /* this object spans two pages */ + struct page *nextp; + + nextp = get_next_page(page); + BUG_ON(!nextp); + + + set_pte(area->vm_ptes[0], mk_pte(page, PAGE_KERNEL)); + set_pte(area->vm_ptes[1], mk_pte(nextp, PAGE_KERNEL)); + + /* We pre-allocated VM area so mapping can never fail */ + area->vm_addr = area->vm->addr; + } + + return area->vm_addr + off; +} +EXPORT_SYMBOL_GPL(zs_map_object); + +void zs_unmap_object(struct zs_pool *pool, void *handle) +{ + struct page *page; + unsigned long obj_idx, off; + + unsigned int class_idx; + enum fullness_group fg; + struct size_class *class; + struct mapping_area *area; + + BUG_ON(!handle); + + obj_handle_to_location(handle, &page, &obj_idx); + get_zspage_mapping(get_first_page(page), &class_idx, &fg); + class = &pool->size_class[class_idx]; + off = obj_idx_to_offset(page, obj_idx, class->size); + + area = &__get_cpu_var(zs_map_area); + if (off + class->size <= PAGE_SIZE) { + kunmap_atomic(area->vm_addr); + } else { + set_pte(area->vm_ptes[0], __pte(0)); + set_pte(area->vm_ptes[1], __pte(0)); + __flush_tlb_one((unsigned long)area->vm_addr); + __flush_tlb_one((unsigned long)area->vm_addr + PAGE_SIZE); + } + put_cpu_var(zs_map_area); +} +EXPORT_SYMBOL_GPL(zs_unmap_object); + +u64 zs_get_total_size_bytes(struct zs_pool *pool) +{ + int i; + u64 npages = 0; + + for (i = 0; i < ZS_SIZE_CLASSES; i++) + npages += pool->size_class[i].pages_allocated; + + return npages << PAGE_SHIFT; +} +EXPORT_SYMBOL_GPL(zs_get_total_size_bytes); diff --git a/drivers/staging/zsmalloc/zsmalloc.h b/drivers/staging/zsmalloc/zsmalloc.h new file mode 100644 index 0000000..949384e --- /dev/null +++ b/drivers/staging/zsmalloc/zsmalloc.h @@ -0,0 +1,31 @@ +/* + * zsmalloc memory allocator + * + * Copyright (C) 2011 Nitin Gupta + * + * This code is released using a dual license strategy: BSD/GPL + * You can choose the license that better fits your requirements. + * + * Released under the terms of 3-clause BSD License + * Released under the terms of GNU General Public License Version 2.0 + */ + +#ifndef _ZS_MALLOC_H_ +#define _ZS_MALLOC_H_ + +#include + +struct zs_pool; + +struct zs_pool *zs_create_pool(const char *name, gfp_t flags); +void zs_destroy_pool(struct zs_pool *pool); + +void *zs_malloc(struct zs_pool *pool, size_t size); +void zs_free(struct zs_pool *pool, void *obj); + +void *zs_map_object(struct zs_pool *pool, void *handle); +void zs_unmap_object(struct zs_pool *pool, void *handle); + +u64 zs_get_total_size_bytes(struct zs_pool *pool); + +#endif diff --git a/drivers/staging/zsmalloc/zsmalloc_int.h b/drivers/staging/zsmalloc/zsmalloc_int.h new file mode 100644 index 0000000..354a020 --- /dev/null +++ b/drivers/staging/zsmalloc/zsmalloc_int.h @@ -0,0 +1,126 @@ +/* + * zsmalloc memory allocator + * + * Copyright (C) 2011 Nitin Gupta + * + * This code is released using a dual license strategy: BSD/GPL + * You can choose the license that better fits your requirements. + * + * Released under the terms of 3-clause BSD License + * Released under the terms of GNU General Public License Version 2.0 + */ + +#ifndef _ZS_MALLOC_INT_H_ +#define _ZS_MALLOC_INT_H_ + +#include +#include +#include + +/* + * This must be power of 2 and greater than of equal to sizeof(link_free). + * These two conditions ensure that any 'struct link_free' itself doesn't + * span more than 1 page which avoids complex case of mapping 2 pages simply + * to restore link_free pointer values. + */ +#define ZS_ALIGN 8 + +/* ZS_MIN_ALLOC_SIZE must be multiple of ZS_ALIGN */ +#define ZS_MIN_ALLOC_SIZE 32 +#define ZS_MAX_ALLOC_SIZE PAGE_SIZE + +/* + * On systems with 4K page size, this gives 254 size classes! There is a + * trader-off here: + * - Large number of size classes is potentially wasteful as free page are + * spread across these classes + * - Small number of size classes causes large internal fragmentation + * - Probably its better to use specific size classes (empirically + * determined). NOTE: all those class sizes must be set as multiple of + * ZS_ALIGN to make sure link_free itself never has to span 2 pages. + * + * ZS_MIN_ALLOC_SIZE and ZS_SIZE_CLASS_DELTA must be multiple of ZS_ALIGN + * (reason above) + */ +#define ZS_SIZE_CLASS_DELTA 16 +#define ZS_SIZE_CLASSES ((ZS_MAX_ALLOC_SIZE - ZS_MIN_ALLOC_SIZE) / \ + ZS_SIZE_CLASS_DELTA + 1) + +/* + * A single 'zspage' is composed of N discontiguous 0-order (single) pages. + * This defines upper limit on N. + */ +static const int max_zspage_order = 4; + +/* + * We do not maintain any list for completely empty or full pages + */ +enum fullness_group { + ZS_ALMOST_FULL, + ZS_ALMOST_EMPTY, + _ZS_NR_FULLNESS_GROUPS, + + ZS_EMPTY, + ZS_FULL +}; + +/* + * We assign a page to ZS_ALMOST_EMPTY fullness group when: + * n <= N / f, where + * n = number of allocated objects + * N = total number of objects zspage can store + * f = 1/fullness_threshold_frac + * + * Similarly, we assign zspage to: + * ZS_ALMOST_FULL when n > N / f + * ZS_EMPTY when n == 0 + * ZS_FULL when n == N + * + * (see: fix_fullness_group()) + */ +static const int fullness_threshold_frac = 4; + +struct mapping_area { + struct vm_struct *vm; + pte_t *vm_ptes[2]; + char *vm_addr; +}; + +struct size_class { + /* + * Size of objects stored in this class. Must be multiple + * of ZS_ALIGN. + */ + int size; + unsigned int index; + + /* Number of PAGE_SIZE sized pages to combine to form a 'zspage' */ + int zspage_order; + + spinlock_t lock; + + /* stats */ + u64 pages_allocated; + + struct page *fullness_list[_ZS_NR_FULLNESS_GROUPS]; +}; + +/* + * Placed within free objects to form a singly linked list. + * For every zspage, first_page->freelist gives head of this list. + * + * This must be power of 2 and less than or equal to ZS_ALIGN + */ +struct link_free { + /* Handle of next free chunk (encodes ) */ + void *next; +}; + +struct zs_pool { + struct size_class size_class[ZS_SIZE_CLASSES]; + + gfp_t flags; /* allocation flags used when growing pool */ + const char *name; +}; + +#endif -- cgit v0.10.2 From 94add674a78c379fe352eacb5137ed77ccb0a979 Mon Sep 17 00:00:00 2001 From: Seth Jennings Date: Mon, 9 Jan 2012 16:51:57 -0600 Subject: staging: add zsmalloc to Kconfig/Makefile Adds the new zsmalloc library to the staging Kconfig and Makefile Signed-off-by: Seth Jennings Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 76a4c4a..783bc0a 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -90,6 +90,8 @@ source "drivers/staging/zram/Kconfig" source "drivers/staging/zcache/Kconfig" +source "drivers/staging/zsmalloc/Kconfig" + source "drivers/staging/wlags49_h2/Kconfig" source "drivers/staging/wlags49_h25/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index c061be8..4fa1e5e 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -37,6 +37,7 @@ obj-$(CONFIG_IIO) += iio/ obj-$(CONFIG_ZRAM) += zram/ obj-$(CONFIG_XVMALLOC) += zram/ obj-$(CONFIG_ZCACHE) += zcache/ +obj-$(CONFIG_ZSMALLOC) += zsmalloc/ obj-$(CONFIG_WLAGS49_H2) += wlags49_h2/ obj-$(CONFIG_WLAGS49_H25) += wlags49_h25/ obj-$(CONFIG_FB_SM7XX) += sm7xx/ -- cgit v0.10.2 From fd1a30dea194002c061503af8425688dcc6f3970 Mon Sep 17 00:00:00 2001 From: Nitin Gupta Date: Mon, 9 Jan 2012 16:51:59 -0600 Subject: staging: zram: replace xvmalloc with zsmalloc Replaces xvmalloc with zsmalloc as the compressed page allocator for zram Signed-off-by: Nitin Gupta Acked-by: Seth Jennings Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/zram/Kconfig b/drivers/staging/zram/Kconfig index 3bec4db..ee23a86 100644 --- a/drivers/staging/zram/Kconfig +++ b/drivers/staging/zram/Kconfig @@ -1,11 +1,7 @@ -config XVMALLOC - bool - default n - config ZRAM tristate "Compressed RAM block device support" depends on BLOCK && SYSFS - select XVMALLOC + select ZSMALLOC select LZO_COMPRESS select LZO_DECOMPRESS default n diff --git a/drivers/staging/zram/Makefile b/drivers/staging/zram/Makefile index 2a6d321..7f4a301 100644 --- a/drivers/staging/zram/Makefile +++ b/drivers/staging/zram/Makefile @@ -1,4 +1,3 @@ zram-y := zram_drv.o zram_sysfs.o obj-$(CONFIG_ZRAM) += zram.o -obj-$(CONFIG_XVMALLOC) += xvmalloc.o \ No newline at end of file diff --git a/drivers/staging/zram/zram_drv.c b/drivers/staging/zram/zram_drv.c index 2a2a92d..5833156 100644 --- a/drivers/staging/zram/zram_drv.c +++ b/drivers/staging/zram/zram_drv.c @@ -135,13 +135,9 @@ static void zram_set_disksize(struct zram *zram, size_t totalram_bytes) static void zram_free_page(struct zram *zram, size_t index) { - u32 clen; - void *obj; + void *handle = zram->table[index].handle; - struct page *page = zram->table[index].page; - u32 offset = zram->table[index].offset; - - if (unlikely(!page)) { + if (unlikely(!handle)) { /* * No memory is allocated for zero filled pages. * Simply clear zero page flag. @@ -154,27 +150,24 @@ static void zram_free_page(struct zram *zram, size_t index) } if (unlikely(zram_test_flag(zram, index, ZRAM_UNCOMPRESSED))) { - clen = PAGE_SIZE; - __free_page(page); + __free_page(handle); zram_clear_flag(zram, index, ZRAM_UNCOMPRESSED); zram_stat_dec(&zram->stats.pages_expand); goto out; } - obj = kmap_atomic(page, KM_USER0) + offset; - clen = xv_get_object_size(obj) - sizeof(struct zobj_header); - kunmap_atomic(obj, KM_USER0); + zs_free(zram->mem_pool, handle); - xv_free(zram->mem_pool, page, offset); - if (clen <= PAGE_SIZE / 2) + if (zram->table[index].size <= PAGE_SIZE / 2) zram_stat_dec(&zram->stats.good_compress); out: - zram_stat64_sub(zram, &zram->stats.compr_size, clen); + zram_stat64_sub(zram, &zram->stats.compr_size, + zram->table[index].size); zram_stat_dec(&zram->stats.pages_stored); - zram->table[index].page = NULL; - zram->table[index].offset = 0; + zram->table[index].handle = NULL; + zram->table[index].size = 0; } static void handle_zero_page(struct bio_vec *bvec) @@ -196,7 +189,7 @@ static void handle_uncompressed_page(struct zram *zram, struct bio_vec *bvec, unsigned char *user_mem, *cmem; user_mem = kmap_atomic(page, KM_USER0); - cmem = kmap_atomic(zram->table[index].page, KM_USER1); + cmem = kmap_atomic(zram->table[index].handle, KM_USER1); memcpy(user_mem + bvec->bv_offset, cmem + offset, bvec->bv_len); kunmap_atomic(cmem, KM_USER1); @@ -227,7 +220,7 @@ static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec, } /* Requested page is not present in compressed area */ - if (unlikely(!zram->table[index].page)) { + if (unlikely(!zram->table[index].handle)) { pr_debug("Read before write: sector=%lu, size=%u", (ulong)(bio->bi_sector), bio->bi_size); handle_zero_page(bvec); @@ -254,11 +247,10 @@ static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec, uncmem = user_mem; clen = PAGE_SIZE; - cmem = kmap_atomic(zram->table[index].page, KM_USER1) + - zram->table[index].offset; + cmem = zs_map_object(zram->mem_pool, zram->table[index].handle); ret = lzo1x_decompress_safe(cmem + sizeof(*zheader), - xv_get_object_size(cmem) - sizeof(*zheader), + zram->table[index].size, uncmem, &clen); if (is_partial_io(bvec)) { @@ -267,7 +259,7 @@ static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec, kfree(uncmem); } - kunmap_atomic(cmem, KM_USER1); + zs_unmap_object(zram->mem_pool, zram->table[index].handle); kunmap_atomic(user_mem, KM_USER0); /* Should NEVER happen. Return bio error if it does. */ @@ -290,13 +282,12 @@ static int zram_read_before_write(struct zram *zram, char *mem, u32 index) unsigned char *cmem; if (zram_test_flag(zram, index, ZRAM_ZERO) || - !zram->table[index].page) { + !zram->table[index].handle) { memset(mem, 0, PAGE_SIZE); return 0; } - cmem = kmap_atomic(zram->table[index].page, KM_USER0) + - zram->table[index].offset; + cmem = zs_map_object(zram->mem_pool, zram->table[index].handle); /* Page is stored uncompressed since it's incompressible */ if (unlikely(zram_test_flag(zram, index, ZRAM_UNCOMPRESSED))) { @@ -306,9 +297,9 @@ static int zram_read_before_write(struct zram *zram, char *mem, u32 index) } ret = lzo1x_decompress_safe(cmem + sizeof(*zheader), - xv_get_object_size(cmem) - sizeof(*zheader), + zram->table[index].size, mem, &clen); - kunmap_atomic(cmem, KM_USER0); + zs_unmap_object(zram->mem_pool, zram->table[index].handle); /* Should NEVER happen. Return bio error if it does. */ if (unlikely(ret != LZO_E_OK)) { @@ -326,6 +317,7 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, int ret; u32 store_offset; size_t clen; + void *handle; struct zobj_header *zheader; struct page *page, *page_store; unsigned char *user_mem, *cmem, *src, *uncmem = NULL; @@ -355,7 +347,7 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, * System overwrites unused sectors. Free memory associated * with this sector now. */ - if (zram->table[index].page || + if (zram->table[index].handle || zram_test_flag(zram, index, ZRAM_ZERO)) zram_free_page(zram, index); @@ -407,26 +399,22 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, store_offset = 0; zram_set_flag(zram, index, ZRAM_UNCOMPRESSED); zram_stat_inc(&zram->stats.pages_expand); - zram->table[index].page = page_store; + handle = page_store; src = kmap_atomic(page, KM_USER0); + cmem = kmap_atomic(page_store, KM_USER1); goto memstore; } - if (xv_malloc(zram->mem_pool, clen + sizeof(*zheader), - &zram->table[index].page, &store_offset, - GFP_NOIO | __GFP_HIGHMEM)) { + handle = zs_malloc(zram->mem_pool, clen + sizeof(*zheader)); + if (!handle) { pr_info("Error allocating memory for compressed " "page: %u, size=%zu\n", index, clen); ret = -ENOMEM; goto out; } + cmem = zs_map_object(zram->mem_pool, handle); memstore: - zram->table[index].offset = store_offset; - - cmem = kmap_atomic(zram->table[index].page, KM_USER1) + - zram->table[index].offset; - #if 0 /* Back-reference needed for memory defragmentation */ if (!zram_test_flag(zram, index, ZRAM_UNCOMPRESSED)) { @@ -438,9 +426,15 @@ memstore: memcpy(cmem, src, clen); - kunmap_atomic(cmem, KM_USER1); - if (unlikely(zram_test_flag(zram, index, ZRAM_UNCOMPRESSED))) + if (unlikely(zram_test_flag(zram, index, ZRAM_UNCOMPRESSED))) { + kunmap_atomic(cmem, KM_USER1); kunmap_atomic(src, KM_USER0); + } else { + zs_unmap_object(zram->mem_pool, handle); + } + + zram->table[index].handle = handle; + zram->table[index].size = clen; /* Update stats */ zram_stat64_add(zram, &zram->stats.compr_size, clen); @@ -598,25 +592,20 @@ void __zram_reset_device(struct zram *zram) /* Free all pages that are still in this zram device */ for (index = 0; index < zram->disksize >> PAGE_SHIFT; index++) { - struct page *page; - u16 offset; - - page = zram->table[index].page; - offset = zram->table[index].offset; - - if (!page) + void *handle = zram->table[index].handle; + if (!handle) continue; if (unlikely(zram_test_flag(zram, index, ZRAM_UNCOMPRESSED))) - __free_page(page); + __free_page(handle); else - xv_free(zram->mem_pool, page, offset); + zs_free(zram->mem_pool, handle); } vfree(zram->table); zram->table = NULL; - xv_destroy_pool(zram->mem_pool); + zs_destroy_pool(zram->mem_pool); zram->mem_pool = NULL; /* Reset stats */ @@ -674,7 +663,7 @@ int zram_init_device(struct zram *zram) /* zram devices sort of resembles non-rotational disks */ queue_flag_set_unlocked(QUEUE_FLAG_NONROT, zram->disk->queue); - zram->mem_pool = xv_create_pool(); + zram->mem_pool = zs_create_pool("zram", GFP_NOIO | __GFP_HIGHMEM); if (!zram->mem_pool) { pr_err("Error creating memory pool\n"); ret = -ENOMEM; diff --git a/drivers/staging/zram/zram_drv.h b/drivers/staging/zram/zram_drv.h index e5cd246..572faa8 100644 --- a/drivers/staging/zram/zram_drv.h +++ b/drivers/staging/zram/zram_drv.h @@ -18,7 +18,7 @@ #include #include -#include "xvmalloc.h" +#include "../zsmalloc/zsmalloc.h" /* * Some arbitrary value. This is just to catch @@ -51,7 +51,7 @@ static const size_t max_zpage_size = PAGE_SIZE / 4 * 3; /* * NOTE: max_zpage_size must be less than or equal to: - * XV_MAX_ALLOC_SIZE - sizeof(struct zobj_header) + * ZS_MAX_ALLOC_SIZE - sizeof(struct zobj_header) * otherwise, xv_malloc() would always return failure. */ @@ -81,8 +81,8 @@ enum zram_pageflags { /* Allocated for each disk page */ struct table { - struct page *page; - u16 offset; + void *handle; + u16 size; /* object size (excluding header) */ u8 count; /* object ref count (not yet used) */ u8 flags; } __attribute__((aligned(4))); @@ -102,7 +102,7 @@ struct zram_stats { }; struct zram { - struct xv_pool *mem_pool; + struct zs_pool *mem_pool; void *compress_workmem; void *compress_buffer; struct table *table; diff --git a/drivers/staging/zram/zram_sysfs.c b/drivers/staging/zram/zram_sysfs.c index d521122..d2875c5 100644 --- a/drivers/staging/zram/zram_sysfs.c +++ b/drivers/staging/zram/zram_sysfs.c @@ -187,7 +187,7 @@ static ssize_t mem_used_total_show(struct device *dev, struct zram *zram = dev_to_zram(dev); if (zram->init_done) { - val = xv_get_total_size_bytes(zram->mem_pool) + + val = zs_get_total_size_bytes(zram->mem_pool) + ((u64)(zram->stats.pages_expand) << PAGE_SHIFT); } -- cgit v0.10.2 From b154ff05e1b0d749231a71896c90e38657f8e675 Mon Sep 17 00:00:00 2001 From: Nitin Gupta Date: Mon, 9 Jan 2012 16:52:00 -0600 Subject: staging: zram: remove xvmalloc Removes the xvmalloc allocator code from the zram driver Signed-off-by: Nitin Gupta Acked-by: Seth Jennings Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 4fa1e5e..31c81fa 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -35,7 +35,6 @@ obj-$(CONFIG_VME_BUS) += vme/ obj-$(CONFIG_DX_SEP) += sep/ obj-$(CONFIG_IIO) += iio/ obj-$(CONFIG_ZRAM) += zram/ -obj-$(CONFIG_XVMALLOC) += zram/ obj-$(CONFIG_ZCACHE) += zcache/ obj-$(CONFIG_ZSMALLOC) += zsmalloc/ obj-$(CONFIG_WLAGS49_H2) += wlags49_h2/ diff --git a/drivers/staging/zram/xvmalloc.c b/drivers/staging/zram/xvmalloc.c deleted file mode 100644 index 1f9c508..0000000 --- a/drivers/staging/zram/xvmalloc.c +++ /dev/null @@ -1,510 +0,0 @@ -/* - * xvmalloc memory allocator - * - * Copyright (C) 2008, 2009, 2010 Nitin Gupta - * - * This code is released using a dual license strategy: BSD/GPL - * You can choose the licence that better fits your requirements. - * - * Released under the terms of 3-clause BSD License - * Released under the terms of GNU General Public License Version 2.0 - */ - -#ifdef CONFIG_ZRAM_DEBUG -#define DEBUG -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "xvmalloc.h" -#include "xvmalloc_int.h" - -static void stat_inc(u64 *value) -{ - *value = *value + 1; -} - -static void stat_dec(u64 *value) -{ - *value = *value - 1; -} - -static int test_flag(struct block_header *block, enum blockflags flag) -{ - return block->prev & BIT(flag); -} - -static void set_flag(struct block_header *block, enum blockflags flag) -{ - block->prev |= BIT(flag); -} - -static void clear_flag(struct block_header *block, enum blockflags flag) -{ - block->prev &= ~BIT(flag); -} - -/* - * Given pair, provide a dereferencable pointer. - * This is called from xv_malloc/xv_free path, so it - * needs to be fast. - */ -static void *get_ptr_atomic(struct page *page, u16 offset, enum km_type type) -{ - unsigned char *base; - - base = kmap_atomic(page, type); - return base + offset; -} - -static void put_ptr_atomic(void *ptr, enum km_type type) -{ - kunmap_atomic(ptr, type); -} - -static u32 get_blockprev(struct block_header *block) -{ - return block->prev & PREV_MASK; -} - -static void set_blockprev(struct block_header *block, u16 new_offset) -{ - block->prev = new_offset | (block->prev & FLAGS_MASK); -} - -static struct block_header *BLOCK_NEXT(struct block_header *block) -{ - return (struct block_header *) - ((char *)block + block->size + XV_ALIGN); -} - -/* - * Get index of free list containing blocks of maximum size - * which is less than or equal to given size. - */ -static u32 get_index_for_insert(u32 size) -{ - if (unlikely(size > XV_MAX_ALLOC_SIZE)) - size = XV_MAX_ALLOC_SIZE; - size &= ~FL_DELTA_MASK; - return (size - XV_MIN_ALLOC_SIZE) >> FL_DELTA_SHIFT; -} - -/* - * Get index of free list having blocks of size greater than - * or equal to requested size. - */ -static u32 get_index(u32 size) -{ - if (unlikely(size < XV_MIN_ALLOC_SIZE)) - size = XV_MIN_ALLOC_SIZE; - size = ALIGN(size, FL_DELTA); - return (size - XV_MIN_ALLOC_SIZE) >> FL_DELTA_SHIFT; -} - -/** - * find_block - find block of at least given size - * @pool: memory pool to search from - * @size: size of block required - * @page: page containing required block - * @offset: offset within the page where block is located. - * - * Searches two level bitmap to locate block of at least - * the given size. If such a block is found, it provides - * to identify this block and returns index - * in freelist where we found this block. - * Otherwise, returns 0 and params are not touched. - */ -static u32 find_block(struct xv_pool *pool, u32 size, - struct page **page, u32 *offset) -{ - ulong flbitmap, slbitmap; - u32 flindex, slindex, slbitstart; - - /* There are no free blocks in this pool */ - if (!pool->flbitmap) - return 0; - - /* Get freelist index correspoding to this size */ - slindex = get_index(size); - slbitmap = pool->slbitmap[slindex / BITS_PER_LONG]; - slbitstart = slindex % BITS_PER_LONG; - - /* - * If freelist is not empty at this index, we found the - * block - head of this list. This is approximate best-fit match. - */ - if (test_bit(slbitstart, &slbitmap)) { - *page = pool->freelist[slindex].page; - *offset = pool->freelist[slindex].offset; - return slindex; - } - - /* - * No best-fit found. Search a bit further in bitmap for a free block. - * Second level bitmap consists of series of 32-bit chunks. Search - * further in the chunk where we expected a best-fit, starting from - * index location found above. - */ - slbitstart++; - slbitmap >>= slbitstart; - - /* Skip this search if we were already at end of this bitmap chunk */ - if ((slbitstart != BITS_PER_LONG) && slbitmap) { - slindex += __ffs(slbitmap) + 1; - *page = pool->freelist[slindex].page; - *offset = pool->freelist[slindex].offset; - return slindex; - } - - /* Now do a full two-level bitmap search to find next nearest fit */ - flindex = slindex / BITS_PER_LONG; - - flbitmap = (pool->flbitmap) >> (flindex + 1); - if (!flbitmap) - return 0; - - flindex += __ffs(flbitmap) + 1; - slbitmap = pool->slbitmap[flindex]; - slindex = (flindex * BITS_PER_LONG) + __ffs(slbitmap); - *page = pool->freelist[slindex].page; - *offset = pool->freelist[slindex].offset; - - return slindex; -} - -/* - * Insert block at in freelist of given pool. - * freelist used depends on block size. - */ -static void insert_block(struct xv_pool *pool, struct page *page, u32 offset, - struct block_header *block) -{ - u32 flindex, slindex; - struct block_header *nextblock; - - slindex = get_index_for_insert(block->size); - flindex = slindex / BITS_PER_LONG; - - block->link.prev_page = NULL; - block->link.prev_offset = 0; - block->link.next_page = pool->freelist[slindex].page; - block->link.next_offset = pool->freelist[slindex].offset; - pool->freelist[slindex].page = page; - pool->freelist[slindex].offset = offset; - - if (block->link.next_page) { - nextblock = get_ptr_atomic(block->link.next_page, - block->link.next_offset, KM_USER1); - nextblock->link.prev_page = page; - nextblock->link.prev_offset = offset; - put_ptr_atomic(nextblock, KM_USER1); - /* If there was a next page then the free bits are set. */ - return; - } - - __set_bit(slindex % BITS_PER_LONG, &pool->slbitmap[flindex]); - __set_bit(flindex, &pool->flbitmap); -} - -/* - * Remove block from freelist. Index 'slindex' identifies the freelist. - */ -static void remove_block(struct xv_pool *pool, struct page *page, u32 offset, - struct block_header *block, u32 slindex) -{ - u32 flindex = slindex / BITS_PER_LONG; - struct block_header *tmpblock; - - if (block->link.prev_page) { - tmpblock = get_ptr_atomic(block->link.prev_page, - block->link.prev_offset, KM_USER1); - tmpblock->link.next_page = block->link.next_page; - tmpblock->link.next_offset = block->link.next_offset; - put_ptr_atomic(tmpblock, KM_USER1); - } - - if (block->link.next_page) { - tmpblock = get_ptr_atomic(block->link.next_page, - block->link.next_offset, KM_USER1); - tmpblock->link.prev_page = block->link.prev_page; - tmpblock->link.prev_offset = block->link.prev_offset; - put_ptr_atomic(tmpblock, KM_USER1); - } - - /* Is this block is at the head of the freelist? */ - if (pool->freelist[slindex].page == page - && pool->freelist[slindex].offset == offset) { - - pool->freelist[slindex].page = block->link.next_page; - pool->freelist[slindex].offset = block->link.next_offset; - - if (pool->freelist[slindex].page) { - struct block_header *tmpblock; - tmpblock = get_ptr_atomic(pool->freelist[slindex].page, - pool->freelist[slindex].offset, - KM_USER1); - tmpblock->link.prev_page = NULL; - tmpblock->link.prev_offset = 0; - put_ptr_atomic(tmpblock, KM_USER1); - } else { - /* This freelist bucket is empty */ - __clear_bit(slindex % BITS_PER_LONG, - &pool->slbitmap[flindex]); - if (!pool->slbitmap[flindex]) - __clear_bit(flindex, &pool->flbitmap); - } - } - - block->link.prev_page = NULL; - block->link.prev_offset = 0; - block->link.next_page = NULL; - block->link.next_offset = 0; -} - -/* - * Allocate a page and add it to freelist of given pool. - */ -static int grow_pool(struct xv_pool *pool, gfp_t flags) -{ - struct page *page; - struct block_header *block; - - page = alloc_page(flags); - if (unlikely(!page)) - return -ENOMEM; - - stat_inc(&pool->total_pages); - - spin_lock(&pool->lock); - block = get_ptr_atomic(page, 0, KM_USER0); - - block->size = PAGE_SIZE - XV_ALIGN; - set_flag(block, BLOCK_FREE); - clear_flag(block, PREV_FREE); - set_blockprev(block, 0); - - insert_block(pool, page, 0, block); - - put_ptr_atomic(block, KM_USER0); - spin_unlock(&pool->lock); - - return 0; -} - -/* - * Create a memory pool. Allocates freelist, bitmaps and other - * per-pool metadata. - */ -struct xv_pool *xv_create_pool(void) -{ - u32 ovhd_size; - struct xv_pool *pool; - - ovhd_size = roundup(sizeof(*pool), PAGE_SIZE); - pool = kzalloc(ovhd_size, GFP_KERNEL); - if (!pool) - return NULL; - - spin_lock_init(&pool->lock); - - return pool; -} -EXPORT_SYMBOL_GPL(xv_create_pool); - -void xv_destroy_pool(struct xv_pool *pool) -{ - kfree(pool); -} -EXPORT_SYMBOL_GPL(xv_destroy_pool); - -/** - * xv_malloc - Allocate block of given size from pool. - * @pool: pool to allocate from - * @size: size of block to allocate - * @page: page no. that holds the object - * @offset: location of object within page - * - * On success, identifies block allocated - * and 0 is returned. On failure, is set to - * 0 and -ENOMEM is returned. - * - * Allocation requests with size > XV_MAX_ALLOC_SIZE will fail. - */ -int xv_malloc(struct xv_pool *pool, u32 size, struct page **page, - u32 *offset, gfp_t flags) -{ - int error; - u32 index, tmpsize, origsize, tmpoffset; - struct block_header *block, *tmpblock; - - *page = NULL; - *offset = 0; - origsize = size; - - if (unlikely(!size || size > XV_MAX_ALLOC_SIZE)) - return -ENOMEM; - - size = ALIGN(size, XV_ALIGN); - - spin_lock(&pool->lock); - - index = find_block(pool, size, page, offset); - - if (!*page) { - spin_unlock(&pool->lock); - if (flags & GFP_NOWAIT) - return -ENOMEM; - error = grow_pool(pool, flags); - if (unlikely(error)) - return error; - - spin_lock(&pool->lock); - index = find_block(pool, size, page, offset); - } - - if (!*page) { - spin_unlock(&pool->lock); - return -ENOMEM; - } - - block = get_ptr_atomic(*page, *offset, KM_USER0); - - remove_block(pool, *page, *offset, block, index); - - /* Split the block if required */ - tmpoffset = *offset + size + XV_ALIGN; - tmpsize = block->size - size; - tmpblock = (struct block_header *)((char *)block + size + XV_ALIGN); - if (tmpsize) { - tmpblock->size = tmpsize - XV_ALIGN; - set_flag(tmpblock, BLOCK_FREE); - clear_flag(tmpblock, PREV_FREE); - - set_blockprev(tmpblock, *offset); - if (tmpblock->size >= XV_MIN_ALLOC_SIZE) - insert_block(pool, *page, tmpoffset, tmpblock); - - if (tmpoffset + XV_ALIGN + tmpblock->size != PAGE_SIZE) { - tmpblock = BLOCK_NEXT(tmpblock); - set_blockprev(tmpblock, tmpoffset); - } - } else { - /* This block is exact fit */ - if (tmpoffset != PAGE_SIZE) - clear_flag(tmpblock, PREV_FREE); - } - - block->size = origsize; - clear_flag(block, BLOCK_FREE); - - put_ptr_atomic(block, KM_USER0); - spin_unlock(&pool->lock); - - *offset += XV_ALIGN; - - return 0; -} -EXPORT_SYMBOL_GPL(xv_malloc); - -/* - * Free block identified with - */ -void xv_free(struct xv_pool *pool, struct page *page, u32 offset) -{ - void *page_start; - struct block_header *block, *tmpblock; - - offset -= XV_ALIGN; - - spin_lock(&pool->lock); - - page_start = get_ptr_atomic(page, 0, KM_USER0); - block = (struct block_header *)((char *)page_start + offset); - - /* Catch double free bugs */ - BUG_ON(test_flag(block, BLOCK_FREE)); - - block->size = ALIGN(block->size, XV_ALIGN); - - tmpblock = BLOCK_NEXT(block); - if (offset + block->size + XV_ALIGN == PAGE_SIZE) - tmpblock = NULL; - - /* Merge next block if its free */ - if (tmpblock && test_flag(tmpblock, BLOCK_FREE)) { - /* - * Blocks smaller than XV_MIN_ALLOC_SIZE - * are not inserted in any free list. - */ - if (tmpblock->size >= XV_MIN_ALLOC_SIZE) { - remove_block(pool, page, - offset + block->size + XV_ALIGN, tmpblock, - get_index_for_insert(tmpblock->size)); - } - block->size += tmpblock->size + XV_ALIGN; - } - - /* Merge previous block if its free */ - if (test_flag(block, PREV_FREE)) { - tmpblock = (struct block_header *)((char *)(page_start) + - get_blockprev(block)); - offset = offset - tmpblock->size - XV_ALIGN; - - if (tmpblock->size >= XV_MIN_ALLOC_SIZE) - remove_block(pool, page, offset, tmpblock, - get_index_for_insert(tmpblock->size)); - - tmpblock->size += block->size + XV_ALIGN; - block = tmpblock; - } - - /* No used objects in this page. Free it. */ - if (block->size == PAGE_SIZE - XV_ALIGN) { - put_ptr_atomic(page_start, KM_USER0); - spin_unlock(&pool->lock); - - __free_page(page); - stat_dec(&pool->total_pages); - return; - } - - set_flag(block, BLOCK_FREE); - if (block->size >= XV_MIN_ALLOC_SIZE) - insert_block(pool, page, offset, block); - - if (offset + block->size + XV_ALIGN != PAGE_SIZE) { - tmpblock = BLOCK_NEXT(block); - set_flag(tmpblock, PREV_FREE); - set_blockprev(tmpblock, offset); - } - - put_ptr_atomic(page_start, KM_USER0); - spin_unlock(&pool->lock); -} -EXPORT_SYMBOL_GPL(xv_free); - -u32 xv_get_object_size(void *obj) -{ - struct block_header *blk; - - blk = (struct block_header *)((char *)(obj) - XV_ALIGN); - return blk->size; -} -EXPORT_SYMBOL_GPL(xv_get_object_size); - -/* - * Returns total memory used by allocator (userdata + metadata) - */ -u64 xv_get_total_size_bytes(struct xv_pool *pool) -{ - return pool->total_pages << PAGE_SHIFT; -} -EXPORT_SYMBOL_GPL(xv_get_total_size_bytes); diff --git a/drivers/staging/zram/xvmalloc.h b/drivers/staging/zram/xvmalloc.h deleted file mode 100644 index 5b1a81a..0000000 --- a/drivers/staging/zram/xvmalloc.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * xvmalloc memory allocator - * - * Copyright (C) 2008, 2009, 2010 Nitin Gupta - * - * This code is released using a dual license strategy: BSD/GPL - * You can choose the licence that better fits your requirements. - * - * Released under the terms of 3-clause BSD License - * Released under the terms of GNU General Public License Version 2.0 - */ - -#ifndef _XV_MALLOC_H_ -#define _XV_MALLOC_H_ - -#include - -struct xv_pool; - -struct xv_pool *xv_create_pool(void); -void xv_destroy_pool(struct xv_pool *pool); - -int xv_malloc(struct xv_pool *pool, u32 size, struct page **page, - u32 *offset, gfp_t flags); -void xv_free(struct xv_pool *pool, struct page *page, u32 offset); - -u32 xv_get_object_size(void *obj); -u64 xv_get_total_size_bytes(struct xv_pool *pool); - -#endif diff --git a/drivers/staging/zram/xvmalloc_int.h b/drivers/staging/zram/xvmalloc_int.h deleted file mode 100644 index b5f1f7f..0000000 --- a/drivers/staging/zram/xvmalloc_int.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * xvmalloc memory allocator - * - * Copyright (C) 2008, 2009, 2010 Nitin Gupta - * - * This code is released using a dual license strategy: BSD/GPL - * You can choose the licence that better fits your requirements. - * - * Released under the terms of 3-clause BSD License - * Released under the terms of GNU General Public License Version 2.0 - */ - -#ifndef _XV_MALLOC_INT_H_ -#define _XV_MALLOC_INT_H_ - -#include -#include - -/* User configurable params */ - -/* Must be power of two */ -#ifdef CONFIG_64BIT -#define XV_ALIGN_SHIFT 3 -#else -#define XV_ALIGN_SHIFT 2 -#endif -#define XV_ALIGN (1 << XV_ALIGN_SHIFT) -#define XV_ALIGN_MASK (XV_ALIGN - 1) - -/* This must be greater than sizeof(link_free) */ -#define XV_MIN_ALLOC_SIZE 32 -#define XV_MAX_ALLOC_SIZE (PAGE_SIZE - XV_ALIGN) - -/* - * Free lists are separated by FL_DELTA bytes - * This value is 3 for 4k pages and 4 for 64k pages, for any - * other page size, a conservative (PAGE_SHIFT - 9) is used. - */ -#if PAGE_SHIFT == 16 -#define FL_DELTA_SHIFT 4 -#else -#define FL_DELTA_SHIFT (PAGE_SHIFT - 9) -#endif -#define FL_DELTA (1 << FL_DELTA_SHIFT) -#define FL_DELTA_MASK (FL_DELTA - 1) -#define NUM_FREE_LISTS ((XV_MAX_ALLOC_SIZE - XV_MIN_ALLOC_SIZE) \ - / FL_DELTA + 1) - -#define MAX_FLI DIV_ROUND_UP(NUM_FREE_LISTS, BITS_PER_LONG) - -/* End of user params */ - -enum blockflags { - BLOCK_FREE, - PREV_FREE, - __NR_BLOCKFLAGS, -}; - -#define FLAGS_MASK XV_ALIGN_MASK -#define PREV_MASK (~FLAGS_MASK) - -struct freelist_entry { - struct page *page; - u16 offset; - u16 pad; -}; - -struct link_free { - struct page *prev_page; - struct page *next_page; - u16 prev_offset; - u16 next_offset; -}; - -struct block_header { - union { - /* This common header must be XV_ALIGN bytes */ - u8 common[XV_ALIGN]; - struct { - u16 size; - u16 prev; - }; - }; - struct link_free link; -}; - -struct xv_pool { - ulong flbitmap; - ulong slbitmap[MAX_FLI]; - u64 total_pages; /* stats */ - struct freelist_entry freelist[NUM_FREE_LISTS]; - spinlock_t lock; -}; - -#endif -- cgit v0.10.2 From 5c9ed5bedf973ab7f4e428f7418d1e72ba3bcbe4 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Wed, 11 Jan 2012 23:22:36 +0100 Subject: Staging: quickstart: Some style, whitespaces and typos fixes Signed-off-by: Szymon Janc Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/quickstart/quickstart.c b/drivers/staging/quickstart/quickstart.c index c60911c..d03b89d 100644 --- a/drivers/staging/quickstart/quickstart.c +++ b/drivers/staging/quickstart/quickstart.c @@ -4,7 +4,7 @@ * * Copyright (C) 2007-2010 Angelo Arrifano * - * Information gathered from disassebled dsdt and from here: + * Information gathered from disassembled dsdt and from here: * * * This program is free software; you can redistribute it and/or modify @@ -37,21 +37,23 @@ MODULE_AUTHOR("Angelo Arrifano"); MODULE_DESCRIPTION("ACPI Direct App Launch driver"); MODULE_LICENSE("GPL"); -#define QUICKSTART_ACPI_DEVICE_NAME "quickstart" -#define QUICKSTART_ACPI_CLASS "quickstart" -#define QUICKSTART_ACPI_HID "PNP0C32" +#define QUICKSTART_ACPI_DEVICE_NAME "quickstart" +#define QUICKSTART_ACPI_CLASS "quickstart" +#define QUICKSTART_ACPI_HID "PNP0C32" -#define QUICKSTART_PF_DRIVER_NAME "quickstart" -#define QUICKSTART_PF_DEVICE_NAME "quickstart" -#define QUICKSTART_PF_DEVATTR_NAME "pressed_button" +#define QUICKSTART_PF_DRIVER_NAME "quickstart" +#define QUICKSTART_PF_DEVICE_NAME "quickstart" +#define QUICKSTART_PF_DEVATTR_NAME "pressed_button" -#define QUICKSTART_MAX_BTN_NAME_LEN 16 +#define QUICKSTART_MAX_BTN_NAME_LEN 16 -/* There will be two events: - * 0x02 - A hot button was pressed while device was off/sleeping. - * 0x80 - A hot button was pressed while device was up. */ -#define QUICKSTART_EVENT_WAKE 0x02 -#define QUICKSTART_EVENT_RUNTIME 0x80 +/* + * There will be two events: + * 0x02 - A hot button was pressed while device was off/sleeping. + * 0x80 - A hot button was pressed while device was up. + */ +#define QUICKSTART_EVENT_WAKE 0x02 +#define QUICKSTART_EVENT_RUNTIME 0x80 struct quickstart_btn { char *name; @@ -64,14 +66,14 @@ static struct quickstart_driver_data { struct quickstart_btn *pressed; } quickstart_data; -/* ACPI driver Structs */ +/* ACPI driver structs */ struct quickstart_acpi { struct acpi_device *device; struct quickstart_btn *btn; }; static int quickstart_acpi_add(struct acpi_device *device); static int quickstart_acpi_remove(struct acpi_device *device, int type); -static const struct acpi_device_id quickstart_device_ids[] = { +static const struct acpi_device_id quickstart_device_ids[] = { {QUICKSTART_ACPI_HID, 0}, {"", 0}, }; @@ -111,12 +113,10 @@ static struct platform_driver pf_driver = { } }; -/* - * Platform driver functions - */ +/* Platform driver functions */ static ssize_t buttons_show(struct device *dev, - struct device_attribute *attr, - char *buf) + struct device_attribute *attr, + char *buf) { int count = 0; struct quickstart_btn *ptr = quickstart_data.btn_lst; @@ -137,8 +137,8 @@ static ssize_t buttons_show(struct device *dev, } static ssize_t pressed_button_show(struct device *dev, - struct device_attribute *attr, - char *buf) + struct device_attribute *attr, + char *buf) { return snprintf(buf, PAGE_SIZE, "%s\n", (quickstart_data.pressed ? @@ -147,8 +147,8 @@ static ssize_t pressed_button_show(struct device *dev, static ssize_t pressed_button_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) + struct device_attribute *attr, + const char *buf, size_t count) { if (count < 2) return -EINVAL; @@ -160,7 +160,7 @@ static ssize_t pressed_button_store(struct device *dev, return count; } -/* Hotstart Helper functions */ +/* Helper functions */ static int quickstart_btnlst_add(struct quickstart_btn **data) { struct quickstart_btn **ptr = &quickstart_data.btn_lst; @@ -240,22 +240,26 @@ static void quickstart_acpi_ghid(struct quickstart_acpi *quickstart) if (!quickstart) return; - /* This returns a buffer telling the button usage ID, - * and triggers pending notify events (The ones before booting). */ - status = acpi_evaluate_object(quickstart->device->handle, - "GHID", NULL, &buffer); + /* + * This returns a buffer telling the button usage ID, + * and triggers pending notify events (The ones before booting). + */ + status = acpi_evaluate_object(quickstart->device->handle, "GHID", NULL, + &buffer); if (ACPI_FAILURE(status) || !buffer.pointer) { printk(KERN_ERR "quickstart: %s GHID method failed.\n", - quickstart->btn->name); + quickstart->btn->name); return; } if (buffer.length < 8) return; - /* <> */ + * order (least significant byte first).>> + */ usageid = *((uint32_t *)(buffer.pointer + (buffer.length - 8))); quickstart->btn->id = usageid; @@ -339,20 +343,17 @@ static int quickstart_acpi_remove(struct acpi_device *device, int type) quickstart = acpi_driver_data(device); - status = acpi_remove_notify_handler(device->handle, - ACPI_ALL_NOTIFY, - quickstart_acpi_notify); + status = acpi_remove_notify_handler(device->handle, ACPI_ALL_NOTIFY, + quickstart_acpi_notify); if (ACPI_FAILURE(status)) printk(KERN_ERR "quickstart: Error removing notify handler\n"); - kfree(quickstart); return 0; } /* Module functions */ - static void quickstart_exit(void) { input_unregister_device(quickstart_input); @@ -367,8 +368,6 @@ static void quickstart_exit(void) acpi_bus_unregister_driver(&quickstart_acpi_driver); quickstart_btnlst_free(); - - return; } static int __init quickstart_init_input(void) @@ -444,14 +443,13 @@ static int __init quickstart_init(void) if (ret) goto fail_dev_file2; - /* Input device */ ret = quickstart_init_input(); if (ret) goto fail_input; printk(KERN_INFO "quickstart: ACPI Direct App Launch ver %s\n", - QUICKSTART_VERSION); + QUICKSTART_VERSION); return 0; fail_input: -- cgit v0.10.2 From 7267d2610a7ed3f56a1f20f58b9ee0d944025b01 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Wed, 11 Jan 2012 23:22:37 +0100 Subject: Staging: quickstart: Prefix remaining functions names with quickstart_ Signed-off-by: Szymon Janc Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/quickstart/quickstart.c b/drivers/staging/quickstart/quickstart.c index d03b89d..adce56b 100644 --- a/drivers/staging/quickstart/quickstart.c +++ b/drivers/staging/quickstart/quickstart.c @@ -92,19 +92,19 @@ static struct acpi_driver quickstart_acpi_driver = { struct input_dev *quickstart_input; /* Platform driver structs */ -static ssize_t buttons_show(struct device *dev, +static ssize_t quickstart_buttons_show(struct device *dev, struct device_attribute *attr, char *buf); -static ssize_t pressed_button_show(struct device *dev, +static ssize_t quickstart_pressed_button_show(struct device *dev, struct device_attribute *attr, char *buf); -static ssize_t pressed_button_store(struct device *dev, +static ssize_t quickstart_pressed_button_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); -static DEVICE_ATTR(pressed_button, 0666, pressed_button_show, - pressed_button_store); -static DEVICE_ATTR(buttons, 0444, buttons_show, NULL); +static DEVICE_ATTR(pressed_button, 0666, quickstart_pressed_button_show, + quickstart_pressed_button_store); +static DEVICE_ATTR(buttons, 0444, quickstart_buttons_show, NULL); static struct platform_device *pf_device; static struct platform_driver pf_driver = { .driver = { @@ -114,7 +114,7 @@ static struct platform_driver pf_driver = { }; /* Platform driver functions */ -static ssize_t buttons_show(struct device *dev, +static ssize_t quickstart_buttons_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -136,7 +136,7 @@ static ssize_t buttons_show(struct device *dev, return count; } -static ssize_t pressed_button_show(struct device *dev, +static ssize_t quickstart_pressed_button_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -146,7 +146,7 @@ static ssize_t pressed_button_show(struct device *dev, } -static ssize_t pressed_button_store(struct device *dev, +static ssize_t quickstart_pressed_button_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { -- cgit v0.10.2 From 605926ef5a8a7f9d778b974c96e90e8f8368a595 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Wed, 11 Jan 2012 23:22:38 +0100 Subject: Staging: quickstart: Move some code to avoid forward declarations Signed-off-by: Szymon Janc Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/quickstart/quickstart.c b/drivers/staging/quickstart/quickstart.c index adce56b..6617761 100644 --- a/drivers/staging/quickstart/quickstart.c +++ b/drivers/staging/quickstart/quickstart.c @@ -61,58 +61,18 @@ struct quickstart_btn { struct quickstart_btn *next; }; -static struct quickstart_driver_data { - struct quickstart_btn *btn_lst; - struct quickstart_btn *pressed; -} quickstart_data; - -/* ACPI driver structs */ struct quickstart_acpi { struct acpi_device *device; struct quickstart_btn *btn; }; -static int quickstart_acpi_add(struct acpi_device *device); -static int quickstart_acpi_remove(struct acpi_device *device, int type); -static const struct acpi_device_id quickstart_device_ids[] = { - {QUICKSTART_ACPI_HID, 0}, - {"", 0}, -}; -static struct acpi_driver quickstart_acpi_driver = { - .name = "quickstart", - .class = QUICKSTART_ACPI_CLASS, - .ids = quickstart_device_ids, - .ops = { - .add = quickstart_acpi_add, - .remove = quickstart_acpi_remove, - }, -}; +static struct quickstart_driver_data { + struct quickstart_btn *btn_lst; + struct quickstart_btn *pressed; +} quickstart_data; -/* Input device structs */ struct input_dev *quickstart_input; -/* Platform driver structs */ -static ssize_t quickstart_buttons_show(struct device *dev, - struct device_attribute *attr, - char *buf); -static ssize_t quickstart_pressed_button_show(struct device *dev, - struct device_attribute *attr, - char *buf); -static ssize_t quickstart_pressed_button_store(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count); -static DEVICE_ATTR(pressed_button, 0666, quickstart_pressed_button_show, - quickstart_pressed_button_store); -static DEVICE_ATTR(buttons, 0444, quickstart_buttons_show, NULL); -static struct platform_device *pf_device; -static struct platform_driver pf_driver = { - .driver = { - .name = QUICKSTART_PF_DRIVER_NAME, - .owner = THIS_MODULE, - } -}; - /* Platform driver functions */ static ssize_t quickstart_buttons_show(struct device *dev, struct device_attribute *attr, @@ -353,6 +313,33 @@ static int quickstart_acpi_remove(struct acpi_device *device, int type) return 0; } +/* Platform driver structs */ +static DEVICE_ATTR(pressed_button, 0666, quickstart_pressed_button_show, + quickstart_pressed_button_store); +static DEVICE_ATTR(buttons, 0444, quickstart_buttons_show, NULL); +static struct platform_device *pf_device; +static struct platform_driver pf_driver = { + .driver = { + .name = QUICKSTART_PF_DRIVER_NAME, + .owner = THIS_MODULE, + } +}; + +static const struct acpi_device_id quickstart_device_ids[] = { + {QUICKSTART_ACPI_HID, 0}, + {"", 0}, +}; + +static struct acpi_driver quickstart_acpi_driver = { + .name = "quickstart", + .class = QUICKSTART_ACPI_CLASS, + .ids = quickstart_device_ids, + .ops = { + .add = quickstart_acpi_add, + .remove = quickstart_acpi_remove, + }, +}; + /* Module functions */ static void quickstart_exit(void) { -- cgit v0.10.2 From 1692caa949728d866238020fe2214bd48f825d62 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Wed, 11 Jan 2012 23:22:39 +0100 Subject: Staging: quickstart: Make quickstart_input static Signed-off-by: Szymon Janc Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/quickstart/quickstart.c b/drivers/staging/quickstart/quickstart.c index 6617761..7b0deb6 100644 --- a/drivers/staging/quickstart/quickstart.c +++ b/drivers/staging/quickstart/quickstart.c @@ -71,7 +71,7 @@ static struct quickstart_driver_data { struct quickstart_btn *pressed; } quickstart_data; -struct input_dev *quickstart_input; +static struct input_dev *quickstart_input; /* Platform driver functions */ static ssize_t quickstart_buttons_show(struct device *dev, -- cgit v0.10.2 From 2ac16967b8de55ec1cfb596717b3a68b0d5b42f7 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Wed, 11 Jan 2012 23:22:40 +0100 Subject: Staging: quickstart: Cleanup quickstart_acpi_ghid Also fix memory leak (buffer.pointer) when returned buffer of length less than 8. Signed-off-by: Szymon Janc Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/quickstart/quickstart.c b/drivers/staging/quickstart/quickstart.c index 7b0deb6..3bae5e7 100644 --- a/drivers/staging/quickstart/quickstart.c +++ b/drivers/staging/quickstart/quickstart.c @@ -191,14 +191,11 @@ static void quickstart_acpi_notify(acpi_handle handle, u32 event, void *data) return; } -static void quickstart_acpi_ghid(struct quickstart_acpi *quickstart) +static int quickstart_acpi_ghid(struct quickstart_acpi *quickstart) { acpi_status status; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - uint32_t usageid = 0; - - if (!quickstart) - return; + int ret = 0; /* * This returns a buffer telling the button usage ID, @@ -206,24 +203,41 @@ static void quickstart_acpi_ghid(struct quickstart_acpi *quickstart) */ status = acpi_evaluate_object(quickstart->device->handle, "GHID", NULL, &buffer); - if (ACPI_FAILURE(status) || !buffer.pointer) { + if (ACPI_FAILURE(status)) { printk(KERN_ERR "quickstart: %s GHID method failed.\n", quickstart->btn->name); - return; + return -EINVAL; } - if (buffer.length < 8) - return; - /* * <> */ - usageid = *((uint32_t *)(buffer.pointer + (buffer.length - 8))); - quickstart->btn->id = usageid; + switch (buffer.length) { + case 1: + quickstart->btn->id = *(uint8_t *)buffer.pointer; + break; + case 2: + quickstart->btn->id = *(uint16_t *)buffer.pointer; + break; + case 4: + quickstart->btn->id = *(uint32_t *)buffer.pointer; + break; + case 8: + quickstart->btn->id = *(uint64_t *)buffer.pointer; + break; + default: + printk(KERN_ERR "quickstart: %s GHID method returned buffer " + "of unexpected length %u\n", + quickstart->btn->name, buffer.length); + ret = -EINVAL; + break; + } kfree(buffer.pointer); + + return ret; } static int quickstart_acpi_config(struct quickstart_acpi *quickstart, char *bid) -- cgit v0.10.2 From 60955f15d93198ef33081e01f46223c7bd534f1e Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Wed, 11 Jan 2012 23:22:41 +0100 Subject: Staging: quickstart: Cleanup quickstart_acpi_remove Signed-off-by: Szymon Janc Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/quickstart/quickstart.c b/drivers/staging/quickstart/quickstart.c index 3bae5e7..de98e18 100644 --- a/drivers/staging/quickstart/quickstart.c +++ b/drivers/staging/quickstart/quickstart.c @@ -309,13 +309,15 @@ fail_config: static int quickstart_acpi_remove(struct acpi_device *device, int type) { - acpi_status status = 0; - struct quickstart_acpi *quickstart = NULL; + acpi_status status; + struct quickstart_acpi *quickstart; - if (!device || !acpi_driver_data(device)) + if (!device) return -EINVAL; quickstart = acpi_driver_data(device); + if (!quickstart) + return -EINVAL; status = acpi_remove_notify_handler(device->handle, ACPI_ALL_NOTIFY, quickstart_acpi_notify); -- cgit v0.10.2 From f27a551968bb8780c8a5255c0ea6c3a2fcaf4a47 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Wed, 11 Jan 2012 23:22:42 +0100 Subject: Staging: quickstart: Cleanup quickstart_acpi_add Signed-off-by: Szymon Janc Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/quickstart/quickstart.c b/drivers/staging/quickstart/quickstart.c index de98e18..97e62e9 100644 --- a/drivers/staging/quickstart/quickstart.c +++ b/drivers/staging/quickstart/quickstart.c @@ -262,29 +262,29 @@ static int quickstart_acpi_config(struct quickstart_acpi *quickstart, char *bid) static int quickstart_acpi_add(struct acpi_device *device) { - int ret = 0; - acpi_status status = AE_OK; - struct quickstart_acpi *quickstart = NULL; + int ret; + acpi_status status; + struct quickstart_acpi *quickstart; if (!device) return -EINVAL; - quickstart = kzalloc(sizeof(struct quickstart_acpi), GFP_KERNEL); + quickstart = kzalloc(sizeof(*quickstart), GFP_KERNEL); if (!quickstart) return -ENOMEM; quickstart->device = device; + strcpy(acpi_device_name(device), QUICKSTART_ACPI_DEVICE_NAME); strcpy(acpi_device_class(device), QUICKSTART_ACPI_CLASS); device->driver_data = quickstart; /* Add button to list and initialize some stuff */ ret = quickstart_acpi_config(quickstart, acpi_device_bid(device)); - if (ret) + if (ret < 0) goto fail_config; - status = acpi_install_notify_handler(device->handle, - ACPI_ALL_NOTIFY, + status = acpi_install_notify_handler(device->handle, ACPI_ALL_NOTIFY, quickstart_acpi_notify, quickstart); if (ACPI_FAILURE(status)) { @@ -293,10 +293,16 @@ static int quickstart_acpi_add(struct acpi_device *device) goto fail_installnotify; } - quickstart_acpi_ghid(quickstart); + ret = quickstart_acpi_ghid(quickstart); + if (ret < 0) + goto fail_ghid; return 0; +fail_ghid: + acpi_remove_notify_handler(device->handle, ACPI_ALL_NOTIFY, + quickstart_acpi_notify); + fail_installnotify: quickstart_btnlst_del(quickstart->btn); -- cgit v0.10.2 From ffe1c0565c27324f6e23a5b47ae5ff873553c62f Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Wed, 11 Jan 2012 23:22:43 +0100 Subject: Staging: quickstart: Cleanup quickstart_acpi_config Signed-off-by: Szymon Janc Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/quickstart/quickstart.c b/drivers/staging/quickstart/quickstart.c index 97e62e9..b183d21 100644 --- a/drivers/staging/quickstart/quickstart.c +++ b/drivers/staging/quickstart/quickstart.c @@ -240,21 +240,24 @@ static int quickstart_acpi_ghid(struct quickstart_acpi *quickstart) return ret; } -static int quickstart_acpi_config(struct quickstart_acpi *quickstart, char *bid) +static int quickstart_acpi_config(struct quickstart_acpi *quickstart) { - int len = strlen(bid); + char *bid = acpi_device_bid(quickstart->device); + char *name; int ret; + name = kmalloc(strlen(bid) + 1, GFP_KERNEL); + if (!name) + return -ENOMEM; + /* Add button to list */ ret = quickstart_btnlst_add(&quickstart->btn); - if (ret) + if (ret < 0) { + kfree(name); return ret; - - quickstart->btn->name = kzalloc(len + 1, GFP_KERNEL); - if (!quickstart->btn->name) { - quickstart_btnlst_free(); - return -ENOMEM; } + + quickstart->btn->name = name; strcpy(quickstart->btn->name, bid); return 0; @@ -280,7 +283,7 @@ static int quickstart_acpi_add(struct acpi_device *device) device->driver_data = quickstart; /* Add button to list and initialize some stuff */ - ret = quickstart_acpi_config(quickstart, acpi_device_bid(device)); + ret = quickstart_acpi_config(quickstart); if (ret < 0) goto fail_config; -- cgit v0.10.2 From 55e403698642fc39e37c2a8d30aa6fa55c9ae116 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Wed, 11 Jan 2012 23:22:44 +0100 Subject: Staging: quickstart: Use switch-case in quickstart_acpi_notify Signed-off-by: Szymon Janc Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/quickstart/quickstart.c b/drivers/staging/quickstart/quickstart.c index b183d21..17e57c0 100644 --- a/drivers/staging/quickstart/quickstart.c +++ b/drivers/staging/quickstart/quickstart.c @@ -180,15 +180,19 @@ static void quickstart_acpi_notify(acpi_handle handle, u32 event, void *data) if (!quickstart) return; - if (event == QUICKSTART_EVENT_WAKE) + switch (event) { + case QUICKSTART_EVENT_WAKE: quickstart_data.pressed = quickstart->btn; - else if (event == QUICKSTART_EVENT_RUNTIME) { + break; + case QUICKSTART_EVENT_RUNTIME: input_report_key(quickstart_input, quickstart->btn->id, 1); input_sync(quickstart_input); input_report_key(quickstart_input, quickstart->btn->id, 0); input_sync(quickstart_input); + break; + default: + break; } - return; } static int quickstart_acpi_ghid(struct quickstart_acpi *quickstart) -- cgit v0.10.2 From 4a0908322a916d15269f2ced8f548ebee9aebd28 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Wed, 11 Jan 2012 23:22:45 +0100 Subject: Staging: quickstart: Remove unused defines Signed-off-by: Szymon Janc Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/quickstart/quickstart.c b/drivers/staging/quickstart/quickstart.c index 17e57c0..9d827f2 100644 --- a/drivers/staging/quickstart/quickstart.c +++ b/drivers/staging/quickstart/quickstart.c @@ -43,9 +43,6 @@ MODULE_LICENSE("GPL"); #define QUICKSTART_PF_DRIVER_NAME "quickstart" #define QUICKSTART_PF_DEVICE_NAME "quickstart" -#define QUICKSTART_PF_DEVATTR_NAME "pressed_button" - -#define QUICKSTART_MAX_BTN_NAME_LEN 16 /* * There will be two events: -- cgit v0.10.2 From 3991eae9437b14454881b64ba5627c3aef9a1ba5 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Wed, 11 Jan 2012 23:22:46 +0100 Subject: Staging: quickstart: Get rid of quickstart_data struct Signed-off-by: Szymon Janc Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/quickstart/quickstart.c b/drivers/staging/quickstart/quickstart.c index 9d827f2..03cb675 100644 --- a/drivers/staging/quickstart/quickstart.c +++ b/drivers/staging/quickstart/quickstart.c @@ -63,10 +63,8 @@ struct quickstart_acpi { struct quickstart_btn *btn; }; -static struct quickstart_driver_data { - struct quickstart_btn *btn_lst; - struct quickstart_btn *pressed; -} quickstart_data; +static struct quickstart_btn *btn_list; +static struct quickstart_btn *pressed; static struct input_dev *quickstart_input; @@ -76,7 +74,7 @@ static ssize_t quickstart_buttons_show(struct device *dev, char *buf) { int count = 0; - struct quickstart_btn *ptr = quickstart_data.btn_lst; + struct quickstart_btn *ptr = btn_list; if (!ptr) return snprintf(buf, PAGE_SIZE, "none"); @@ -98,8 +96,7 @@ static ssize_t quickstart_pressed_button_show(struct device *dev, char *buf) { return snprintf(buf, PAGE_SIZE, "%s\n", - (quickstart_data.pressed ? - quickstart_data.pressed->name : "none")); + (pressed ? pressed->name : "none")); } @@ -113,14 +110,14 @@ static ssize_t quickstart_pressed_button_store(struct device *dev, if (strncasecmp(buf, "none", 4) != 0) return -EINVAL; - quickstart_data.pressed = NULL; + pressed = NULL; return count; } /* Helper functions */ static int quickstart_btnlst_add(struct quickstart_btn **data) { - struct quickstart_btn **ptr = &quickstart_data.btn_lst; + struct quickstart_btn **ptr = &btn_list; while (*ptr) ptr = &((*ptr)->next); @@ -137,7 +134,7 @@ static int quickstart_btnlst_add(struct quickstart_btn **data) static void quickstart_btnlst_del(struct quickstart_btn *data) { - struct quickstart_btn **ptr = &quickstart_data.btn_lst; + struct quickstart_btn **ptr = &btn_list; if (!data) return; @@ -156,7 +153,7 @@ static void quickstart_btnlst_del(struct quickstart_btn *data) static void quickstart_btnlst_free(void) { - struct quickstart_btn *ptr = quickstart_data.btn_lst; + struct quickstart_btn *ptr = btn_list; struct quickstart_btn *lptr = NULL; while (ptr) { @@ -179,7 +176,7 @@ static void quickstart_acpi_notify(acpi_handle handle, u32 event, void *data) switch (event) { case QUICKSTART_EVENT_WAKE: - quickstart_data.pressed = quickstart->btn; + pressed = quickstart->btn; break; case QUICKSTART_EVENT_RUNTIME: input_report_key(quickstart_input, quickstart->btn->id, 1); @@ -385,7 +382,7 @@ static void quickstart_exit(void) static int __init quickstart_init_input(void) { - struct quickstart_btn **ptr = &quickstart_data.btn_lst; + struct quickstart_btn **ptr = &btn_list; int count; int ret; @@ -427,7 +424,7 @@ static int __init quickstart_init(void) return ret; /* If existing bus with no devices */ - if (!quickstart_data.btn_lst) { + if (!btn_list) { ret = -ENODEV; goto fail_pfdrv_reg; } -- cgit v0.10.2 From 505d2ad2277950ee67e8ed4a12a349f18925c0f4 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Wed, 11 Jan 2012 23:22:47 +0100 Subject: Staging: quickstart: Use list.h API for buttons list Signed-off-by: Szymon Janc Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/quickstart/quickstart.c b/drivers/staging/quickstart/quickstart.c index 03cb675..dbed79f 100644 --- a/drivers/staging/quickstart/quickstart.c +++ b/drivers/staging/quickstart/quickstart.c @@ -55,7 +55,7 @@ MODULE_LICENSE("GPL"); struct quickstart_btn { char *name; unsigned int id; - struct quickstart_btn *next; + struct list_head list; }; struct quickstart_acpi { @@ -63,7 +63,7 @@ struct quickstart_acpi { struct quickstart_btn *btn; }; -static struct quickstart_btn *btn_list; +static LIST_HEAD(buttons); static struct quickstart_btn *pressed; static struct input_dev *quickstart_input; @@ -74,18 +74,19 @@ static ssize_t quickstart_buttons_show(struct device *dev, char *buf) { int count = 0; - struct quickstart_btn *ptr = btn_list; + struct quickstart_btn *b; - if (!ptr) + if (list_empty(&buttons)) return snprintf(buf, PAGE_SIZE, "none"); - while (ptr && (count < PAGE_SIZE)) { - if (ptr->name) { - count += snprintf(buf + count, - PAGE_SIZE - count, - "%d\t%s\n", ptr->id, ptr->name); + list_for_each_entry(b, &buttons, list) { + count += snprintf(buf + count, PAGE_SIZE - count, "%d\t%s\n", + b->id, b->name); + + if (count >= PAGE_SIZE) { + count = PAGE_SIZE; + break; } - ptr = ptr->next; } return count; @@ -115,55 +116,35 @@ static ssize_t quickstart_pressed_button_store(struct device *dev, } /* Helper functions */ -static int quickstart_btnlst_add(struct quickstart_btn **data) +static struct quickstart_btn *quickstart_buttons_add(void) { - struct quickstart_btn **ptr = &btn_list; + struct quickstart_btn *b; - while (*ptr) - ptr = &((*ptr)->next); + b = kzalloc(sizeof(*b), GFP_KERNEL); + if (!b) + return NULL; - *ptr = kzalloc(sizeof(struct quickstart_btn), GFP_KERNEL); - if (!*ptr) { - *data = NULL; - return -ENOMEM; - } - *data = *ptr; + list_add_tail(&b->list, &buttons); - return 0; + return b; } -static void quickstart_btnlst_del(struct quickstart_btn *data) +static void quickstart_button_del(struct quickstart_btn *data) { - struct quickstart_btn **ptr = &btn_list; - if (!data) return; - while (*ptr) { - if (*ptr == data) { - *ptr = (*ptr)->next; - kfree(data); - return; - } - ptr = &((*ptr)->next); - } - - return; + list_del(&data->list); + kfree(data->name); + kfree(data); } -static void quickstart_btnlst_free(void) +static void quickstart_buttons_free(void) { - struct quickstart_btn *ptr = btn_list; - struct quickstart_btn *lptr = NULL; - - while (ptr) { - lptr = ptr; - ptr = ptr->next; - kfree(lptr->name); - kfree(lptr); - } + struct quickstart_btn *b, *n; - return; + list_for_each_entry_safe(b, n, &buttons, list) + quickstart_button_del(b); } /* ACPI Driver functions */ @@ -242,17 +223,16 @@ static int quickstart_acpi_config(struct quickstart_acpi *quickstart) { char *bid = acpi_device_bid(quickstart->device); char *name; - int ret; name = kmalloc(strlen(bid) + 1, GFP_KERNEL); if (!name) return -ENOMEM; - /* Add button to list */ - ret = quickstart_btnlst_add(&quickstart->btn); - if (ret < 0) { + /* Add new button to list */ + quickstart->btn = quickstart_buttons_add(); + if (!quickstart->btn) { kfree(name); - return ret; + return -ENOMEM; } quickstart->btn->name = name; @@ -305,7 +285,7 @@ fail_ghid: quickstart_acpi_notify); fail_installnotify: - quickstart_btnlst_del(quickstart->btn); + quickstart_button_del(quickstart->btn); fail_config: @@ -377,13 +357,12 @@ static void quickstart_exit(void) acpi_bus_unregister_driver(&quickstart_acpi_driver); - quickstart_btnlst_free(); + quickstart_buttons_free(); } static int __init quickstart_init_input(void) { - struct quickstart_btn **ptr = &btn_list; - int count; + struct quickstart_btn *b; int ret; quickstart_input = input_allocate_device(); @@ -394,11 +373,9 @@ static int __init quickstart_init_input(void) quickstart_input->name = "Quickstart ACPI Buttons"; quickstart_input->id.bustype = BUS_HOST; - while (*ptr) { - count++; + list_for_each_entry(b, &buttons, list) { set_bit(EV_KEY, quickstart_input->evbit); - set_bit((*ptr)->id, quickstart_input->keybit); - ptr = &((*ptr)->next); + set_bit(b->id, quickstart_input->keybit); } ret = input_register_device(quickstart_input); @@ -424,7 +401,7 @@ static int __init quickstart_init(void) return ret; /* If existing bus with no devices */ - if (!btn_list) { + if (list_empty(&buttons)) { ret = -ENODEV; goto fail_pfdrv_reg; } -- cgit v0.10.2 From 21c1ddf31415f5db34975760e847bf6033b4f9db Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Wed, 11 Jan 2012 23:22:48 +0100 Subject: Staging: quickstart: Use %u for printing button id Button id is of unsigned int type. Signed-off-by: Szymon Janc Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/quickstart/quickstart.c b/drivers/staging/quickstart/quickstart.c index dbed79f..9968a05 100644 --- a/drivers/staging/quickstart/quickstart.c +++ b/drivers/staging/quickstart/quickstart.c @@ -80,7 +80,7 @@ static ssize_t quickstart_buttons_show(struct device *dev, return snprintf(buf, PAGE_SIZE, "none"); list_for_each_entry(b, &buttons, list) { - count += snprintf(buf + count, PAGE_SIZE - count, "%d\t%s\n", + count += snprintf(buf + count, PAGE_SIZE - count, "%u\t%s\n", b->id, b->name); if (count >= PAGE_SIZE) { -- cgit v0.10.2 From 3c92e38dc4d803a7f90a08277a9d59f920963e0c Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Wed, 11 Jan 2012 23:22:49 +0100 Subject: Staging: quickstart: Rename quickstart_btn to quickstart_button Signed-off-by: Szymon Janc Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/quickstart/quickstart.c b/drivers/staging/quickstart/quickstart.c index 9968a05..a67b03a 100644 --- a/drivers/staging/quickstart/quickstart.c +++ b/drivers/staging/quickstart/quickstart.c @@ -52,7 +52,7 @@ MODULE_LICENSE("GPL"); #define QUICKSTART_EVENT_WAKE 0x02 #define QUICKSTART_EVENT_RUNTIME 0x80 -struct quickstart_btn { +struct quickstart_button { char *name; unsigned int id; struct list_head list; @@ -60,11 +60,11 @@ struct quickstart_btn { struct quickstart_acpi { struct acpi_device *device; - struct quickstart_btn *btn; + struct quickstart_button *button; }; static LIST_HEAD(buttons); -static struct quickstart_btn *pressed; +static struct quickstart_button *pressed; static struct input_dev *quickstart_input; @@ -74,7 +74,7 @@ static ssize_t quickstart_buttons_show(struct device *dev, char *buf) { int count = 0; - struct quickstart_btn *b; + struct quickstart_button *b; if (list_empty(&buttons)) return snprintf(buf, PAGE_SIZE, "none"); @@ -116,9 +116,9 @@ static ssize_t quickstart_pressed_button_store(struct device *dev, } /* Helper functions */ -static struct quickstart_btn *quickstart_buttons_add(void) +static struct quickstart_button *quickstart_buttons_add(void) { - struct quickstart_btn *b; + struct quickstart_button *b; b = kzalloc(sizeof(*b), GFP_KERNEL); if (!b) @@ -129,7 +129,7 @@ static struct quickstart_btn *quickstart_buttons_add(void) return b; } -static void quickstart_button_del(struct quickstart_btn *data) +static void quickstart_button_del(struct quickstart_button *data) { if (!data) return; @@ -141,7 +141,7 @@ static void quickstart_button_del(struct quickstart_btn *data) static void quickstart_buttons_free(void) { - struct quickstart_btn *b, *n; + struct quickstart_button *b, *n; list_for_each_entry_safe(b, n, &buttons, list) quickstart_button_del(b); @@ -157,12 +157,12 @@ static void quickstart_acpi_notify(acpi_handle handle, u32 event, void *data) switch (event) { case QUICKSTART_EVENT_WAKE: - pressed = quickstart->btn; + pressed = quickstart->button; break; case QUICKSTART_EVENT_RUNTIME: - input_report_key(quickstart_input, quickstart->btn->id, 1); + input_report_key(quickstart_input, quickstart->button->id, 1); input_sync(quickstart_input); - input_report_key(quickstart_input, quickstart->btn->id, 0); + input_report_key(quickstart_input, quickstart->button->id, 0); input_sync(quickstart_input); break; default: @@ -184,7 +184,7 @@ static int quickstart_acpi_ghid(struct quickstart_acpi *quickstart) &buffer); if (ACPI_FAILURE(status)) { printk(KERN_ERR "quickstart: %s GHID method failed.\n", - quickstart->btn->name); + quickstart->button->name); return -EINVAL; } @@ -195,21 +195,21 @@ static int quickstart_acpi_ghid(struct quickstart_acpi *quickstart) */ switch (buffer.length) { case 1: - quickstart->btn->id = *(uint8_t *)buffer.pointer; + quickstart->button->id = *(uint8_t *)buffer.pointer; break; case 2: - quickstart->btn->id = *(uint16_t *)buffer.pointer; + quickstart->button->id = *(uint16_t *)buffer.pointer; break; case 4: - quickstart->btn->id = *(uint32_t *)buffer.pointer; + quickstart->button->id = *(uint32_t *)buffer.pointer; break; case 8: - quickstart->btn->id = *(uint64_t *)buffer.pointer; + quickstart->button->id = *(uint64_t *)buffer.pointer; break; default: printk(KERN_ERR "quickstart: %s GHID method returned buffer " "of unexpected length %u\n", - quickstart->btn->name, buffer.length); + quickstart->button->name, buffer.length); ret = -EINVAL; break; } @@ -229,14 +229,14 @@ static int quickstart_acpi_config(struct quickstart_acpi *quickstart) return -ENOMEM; /* Add new button to list */ - quickstart->btn = quickstart_buttons_add(); - if (!quickstart->btn) { + quickstart->button = quickstart_buttons_add(); + if (!quickstart->button) { kfree(name); return -ENOMEM; } - quickstart->btn->name = name; - strcpy(quickstart->btn->name, bid); + quickstart->button->name = name; + strcpy(quickstart->button->name, bid); return 0; } @@ -285,7 +285,7 @@ fail_ghid: quickstart_acpi_notify); fail_installnotify: - quickstart_button_del(quickstart->btn); + quickstart_button_del(quickstart->button); fail_config: @@ -362,7 +362,7 @@ static void quickstart_exit(void) static int __init quickstart_init_input(void) { - struct quickstart_btn *b; + struct quickstart_button *b; int ret; quickstart_input = input_allocate_device(); -- cgit v0.10.2 From b71dbbcfaa2a2965e0797db7333396a71062a341 Mon Sep 17 00:00:00 2001 From: Kevin McKinney Date: Tue, 20 Dec 2011 10:41:13 -0500 Subject: Staging: bcm: Fix an integer overflow in IOCTL_BCM_NVM_READ/WRITE Variables stNVMReadWrite.uioffset and stNVMReadWrite.uiNumBytes are chosen from userspace and can be very high. The sum of these two digits would result in a small number. Therefore, this patch verifies a negative number was not entered, and reorganizes the equation to remove the integer overflow. Signed-off-by: Kevin McKinney Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/bcm/Bcmchar.c b/drivers/staging/bcm/Bcmchar.c index 179707b..8bf3f57 100644 --- a/drivers/staging/bcm/Bcmchar.c +++ b/drivers/staging/bcm/Bcmchar.c @@ -1302,8 +1302,10 @@ cntrlEnd: /* * Deny the access if the offset crosses the cal area limit. */ + if (stNVMReadWrite.uiNumBytes > Adapter->uiNVMDSDSize) + return STATUS_FAILURE; - if ((stNVMReadWrite.uiOffset + stNVMReadWrite.uiNumBytes) > Adapter->uiNVMDSDSize) { + if (stNVMReadWrite.uiOffset > Adapter->uiNVMDSDSize - stNVMReadWrite.uiNumBytes) { /* BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Can't allow access beyond NVM Size: 0x%x 0x%x\n", stNVMReadWrite.uiOffset, stNVMReadWrite.uiNumBytes); */ return STATUS_FAILURE; } -- cgit v0.10.2 From 9937fdb022156f285b761bc544d5b910faa2e585 Mon Sep 17 00:00:00 2001 From: Kevin McKinney Date: Wed, 4 Jan 2012 20:29:00 -0500 Subject: Staging: bcm: Fix coding style issues in CmHost.c This patch cleans up several code style issues found in CmHost.c reported by checkpatch.pl. These include: white space, braces, indents, and comments. Signed-off-by: Kevin McKinney Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/bcm/CmHost.c b/drivers/staging/bcm/CmHost.c index c0ee95a..fcb1835 100644 --- a/drivers/staging/bcm/CmHost.c +++ b/drivers/staging/bcm/CmHost.c @@ -1,431 +1,359 @@ /************************************************************ -* CMHOST.C -* This file contains the routines for handling Connection -* Management. -************************************************************/ + * CMHOST.C + * This file contains the routines for handling Connection + * Management. + ************************************************************/ -//#define CONN_MSG +/* #define CONN_MSG */ #include "headers.h" -typedef enum _E_CLASSIFIER_ACTION -{ +typedef enum _E_CLASSIFIER_ACTION { eInvalidClassifierAction, eAddClassifier, eReplaceClassifier, eDeleteClassifier -}E_CLASSIFIER_ACTION; +} E_CLASSIFIER_ACTION; -static ULONG GetNextTargetBufferLocation(PMINI_ADAPTER Adapter,B_UINT16 tid); +static ULONG GetNextTargetBufferLocation(PMINI_ADAPTER Adapter, B_UINT16 tid); /************************************************************ -* Function - SearchSfid -* -* Description - This routinue would search QOS queues having -* specified SFID as input parameter. -* -* Parameters - Adapter: Pointer to the Adapter structure -* uiSfid : Given SFID for matching -* -* Returns - Queue index for this SFID(If matched) - Else Invalid Queue Index(If Not matched) -************************************************************/ -INT SearchSfid(PMINI_ADAPTER Adapter,UINT uiSfid) + * Function - SearchSfid + * + * Description - This routinue would search QOS queues having + * specified SFID as input parameter. + * + * Parameters - Adapter: Pointer to the Adapter structure + * uiSfid : Given SFID for matching + * + * Returns - Queue index for this SFID(If matched) + * Else Invalid Queue Index(If Not matched) + ************************************************************/ +INT SearchSfid(PMINI_ADAPTER Adapter, UINT uiSfid) { - INT iIndex=0; - for(iIndex=(NO_OF_QUEUES-1); iIndex>=0; iIndex--) - if(Adapter->PackInfo[iIndex].ulSFID==uiSfid) + INT iIndex = 0; + + for (iIndex = (NO_OF_QUEUES-1); iIndex >= 0; iIndex--) + if (Adapter->PackInfo[iIndex].ulSFID == uiSfid) return iIndex; + return NO_OF_QUEUES+1; } /*************************************************************** -* Function - SearchFreeSfid -* -* Description - This routinue would search Free available SFID. -* -* Parameter - Adapter: Pointer to the Adapter structure -* -* Returns - Queue index for the free SFID -* Else returns Invalid Index. -****************************************************************/ + * Function -SearchFreeSfid + * + * Description - This routinue would search Free available SFID. + * + * Parameter - Adapter: Pointer to the Adapter structure + * + * Returns - Queue index for the free SFID + * Else returns Invalid Index. + ****************************************************************/ static INT SearchFreeSfid(PMINI_ADAPTER Adapter) { - UINT uiIndex=0; + UINT uiIndex = 0; - for(uiIndex=0; uiIndex < (NO_OF_QUEUES-1); uiIndex++) - if(Adapter->PackInfo[uiIndex].ulSFID==0) + for (uiIndex = 0; uiIndex < (NO_OF_QUEUES-1); uiIndex++) + if (Adapter->PackInfo[uiIndex].ulSFID == 0) return uiIndex; + return NO_OF_QUEUES+1; } /* -Function: SearchClsid -Description: This routinue would search Classifier having specified ClassifierID as input parameter -Input parameters: PMINI_ADAPTER Adapter - Adapter Context - unsigned int uiSfid - The SF in which the classifier is to searched - B_UINT16 uiClassifierID - The classifier ID to be searched -Return: int :Classifier table index of matching entry -*/ - -static int SearchClsid(PMINI_ADAPTER Adapter,ULONG ulSFID,B_UINT16 uiClassifierID) + * Function: SearchClsid + * Description: This routinue would search Classifier having specified ClassifierID as input parameter + * Input parameters: PMINI_ADAPTER Adapter - Adapter Context + * unsigned int uiSfid - The SF in which the classifier is to searched + * B_UINT16 uiClassifierID - The classifier ID to be searched + * Return: int :Classifier table index of matching entry + */ +static int SearchClsid(PMINI_ADAPTER Adapter, ULONG ulSFID, B_UINT16 uiClassifierID) { unsigned int uiClassifierIndex = 0; - for(uiClassifierIndex=0;uiClassifierIndexastClassifierTable[uiClassifierIndex].bUsed) && - (Adapter->astClassifierTable[uiClassifierIndex].uiClassifierRuleIndex == uiClassifierID)&& + + for (uiClassifierIndex = 0; uiClassifierIndex < MAX_CLASSIFIERS; uiClassifierIndex++) { + if ((Adapter->astClassifierTable[uiClassifierIndex].bUsed) && + (Adapter->astClassifierTable[uiClassifierIndex].uiClassifierRuleIndex == uiClassifierID) && (Adapter->astClassifierTable[uiClassifierIndex].ulSFID == ulSFID)) return uiClassifierIndex; } + return MAX_CLASSIFIERS+1; } -/** -@ingroup ctrl_pkt_functions -This routinue would search Free available Classifier entry in classifier table. -@return free Classifier Entry index in classifier table for specified SF -*/ -static int SearchFreeClsid(PMINI_ADAPTER Adapter /**Adapter Context*/ - ) +/* + * @ingroup ctrl_pkt_functions + * This routinue would search Free available Classifier entry in classifier table. + * @return free Classifier Entry index in classifier table for specified SF + */ +static int SearchFreeClsid(PMINI_ADAPTER Adapter /**Adapter Context*/) { unsigned int uiClassifierIndex = 0; - for(uiClassifierIndex=0;uiClassifierIndexastClassifierTable[uiClassifierIndex].bUsed) + + for (uiClassifierIndex = 0; uiClassifierIndex < MAX_CLASSIFIERS; uiClassifierIndex++) { + if (!Adapter->astClassifierTable[uiClassifierIndex].bUsed) return uiClassifierIndex; } + return MAX_CLASSIFIERS+1; } static VOID deleteSFBySfid(PMINI_ADAPTER Adapter, UINT uiSearchRuleIndex) { - //deleting all the packet held in the SF - flush_queue(Adapter,uiSearchRuleIndex); + /* deleting all the packet held in the SF */ + flush_queue(Adapter, uiSearchRuleIndex); - //Deleting the all classifiers for this SF - DeleteAllClassifiersForSF(Adapter,uiSearchRuleIndex); + /* Deleting the all classifiers for this SF */ + DeleteAllClassifiersForSF(Adapter, uiSearchRuleIndex); - //Resetting only MIBS related entries in the SF + /* Resetting only MIBS related entries in the SF */ memset((PVOID)&Adapter->PackInfo[uiSearchRuleIndex], 0, sizeof(S_MIBS_SERVICEFLOW_TABLE)); } static inline VOID -CopyIpAddrToClassifier(S_CLASSIFIER_RULE *pstClassifierEntry , - B_UINT8 u8IpAddressLen , B_UINT8 *pu8IpAddressMaskSrc , - BOOLEAN bIpVersion6 , E_IPADDR_CONTEXT eIpAddrContext) +CopyIpAddrToClassifier(S_CLASSIFIER_RULE *pstClassifierEntry, + B_UINT8 u8IpAddressLen, B_UINT8 *pu8IpAddressMaskSrc, + BOOLEAN bIpVersion6, E_IPADDR_CONTEXT eIpAddrContext) { - UINT ucLoopIndex=0; - UINT nSizeOfIPAddressInBytes = IP_LENGTH_OF_ADDRESS; - UCHAR *ptrClassifierIpAddress = NULL; - UCHAR *ptrClassifierIpMask = NULL; - PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + UINT ucLoopIndex = 0; + UINT nSizeOfIPAddressInBytes = IP_LENGTH_OF_ADDRESS; + UCHAR *ptrClassifierIpAddress = NULL; + UCHAR *ptrClassifierIpMask = NULL; + PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); - if(bIpVersion6) - { + if (bIpVersion6) nSizeOfIPAddressInBytes = IPV6_ADDRESS_SIZEINBYTES; - } - //Destination Ip Address - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"Ip Address Range Length:0x%X ", - u8IpAddressLen); - if((bIpVersion6?(IPV6_ADDRESS_SIZEINBYTES * MAX_IP_RANGE_LENGTH * 2): - (TOTAL_MASKED_ADDRESS_IN_BYTES)) >= u8IpAddressLen) - { + + /* Destination Ip Address */ + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Ip Address Range Length:0x%X ", u8IpAddressLen); + if ((bIpVersion6 ? (IPV6_ADDRESS_SIZEINBYTES * MAX_IP_RANGE_LENGTH * 2) : + (TOTAL_MASKED_ADDRESS_IN_BYTES)) >= u8IpAddressLen) { /* - //checking both the mask and address togethor in Classification. - //So length will be : TotalLengthInBytes/nSizeOfIPAddressInBytes * 2 - //(nSizeOfIPAddressInBytes for address and nSizeOfIPAddressInBytes for mask) - */ - if(eIpAddrContext == eDestIpAddress) - { - pstClassifierEntry->ucIPDestinationAddressLength = - u8IpAddressLen/(nSizeOfIPAddressInBytes * 2); - if(bIpVersion6) - { - ptrClassifierIpAddress = - pstClassifierEntry->stDestIpAddress.ucIpv6Address; - ptrClassifierIpMask = - pstClassifierEntry->stDestIpAddress.ucIpv6Mask; + * checking both the mask and address togethor in Classification. + * So length will be : TotalLengthInBytes/nSizeOfIPAddressInBytes * 2 + * (nSizeOfIPAddressInBytes for address and nSizeOfIPAddressInBytes for mask) + */ + if (eIpAddrContext == eDestIpAddress) { + pstClassifierEntry->ucIPDestinationAddressLength = u8IpAddressLen/(nSizeOfIPAddressInBytes * 2); + if (bIpVersion6) { + ptrClassifierIpAddress = pstClassifierEntry->stDestIpAddress.ucIpv6Address; + ptrClassifierIpMask = pstClassifierEntry->stDestIpAddress.ucIpv6Mask; + } else { + ptrClassifierIpAddress = pstClassifierEntry->stDestIpAddress.ucIpv4Address; + ptrClassifierIpMask = pstClassifierEntry->stDestIpAddress.ucIpv4Mask; } - else - { - ptrClassifierIpAddress = - pstClassifierEntry->stDestIpAddress.ucIpv4Address; - ptrClassifierIpMask = - pstClassifierEntry->stDestIpAddress.ucIpv4Mask; + } else if (eIpAddrContext == eSrcIpAddress) { + pstClassifierEntry->ucIPSourceAddressLength = u8IpAddressLen/(nSizeOfIPAddressInBytes * 2); + if (bIpVersion6) { + ptrClassifierIpAddress = pstClassifierEntry->stSrcIpAddress.ucIpv6Address; + ptrClassifierIpMask = pstClassifierEntry->stSrcIpAddress.ucIpv6Mask; + } else { + ptrClassifierIpAddress = pstClassifierEntry->stSrcIpAddress.ucIpv4Address; + ptrClassifierIpMask = pstClassifierEntry->stSrcIpAddress.ucIpv4Mask; } } - else if(eIpAddrContext == eSrcIpAddress) - { - pstClassifierEntry->ucIPSourceAddressLength = - u8IpAddressLen/(nSizeOfIPAddressInBytes * 2); - if(bIpVersion6) - { - ptrClassifierIpAddress = - pstClassifierEntry->stSrcIpAddress.ucIpv6Address; - ptrClassifierIpMask = - pstClassifierEntry->stSrcIpAddress.ucIpv6Mask; - } - else - { - ptrClassifierIpAddress = - pstClassifierEntry->stSrcIpAddress.ucIpv4Address; - ptrClassifierIpMask = - pstClassifierEntry->stSrcIpAddress.ucIpv4Mask; - } - } - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"Address Length:0x%X \n", - pstClassifierEntry->ucIPDestinationAddressLength); - while((u8IpAddressLen>= nSizeOfIPAddressInBytes) && - (ucLoopIndex < MAX_IP_RANGE_LENGTH)) - { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Address Length:0x%X\n", pstClassifierEntry->ucIPDestinationAddressLength); + while ((u8IpAddressLen >= nSizeOfIPAddressInBytes) && (ucLoopIndex < MAX_IP_RANGE_LENGTH)) { memcpy(ptrClassifierIpAddress + (ucLoopIndex * nSizeOfIPAddressInBytes), (pu8IpAddressMaskSrc+(ucLoopIndex*nSizeOfIPAddressInBytes*2)), nSizeOfIPAddressInBytes); - if(!bIpVersion6) - { - if(eIpAddrContext == eSrcIpAddress) - { - pstClassifierEntry->stSrcIpAddress.ulIpv4Addr[ucLoopIndex]= - ntohl(pstClassifierEntry->stSrcIpAddress. - ulIpv4Addr[ucLoopIndex]); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"Src Ip Address:0x%luX ",pstClassifierEntry->stSrcIpAddress.ulIpv4Addr[ucLoopIndex]); - } - else if(eIpAddrContext == eDestIpAddress) - { - pstClassifierEntry->stDestIpAddress.ulIpv4Addr[ucLoopIndex]= ntohl(pstClassifierEntry->stDestIpAddress. - ulIpv4Addr[ucLoopIndex]); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"Dest Ip Address:0x%luX ",pstClassifierEntry->stDestIpAddress.ulIpv4Addr[ucLoopIndex]); + + if (!bIpVersion6) { + if (eIpAddrContext == eSrcIpAddress) { + pstClassifierEntry->stSrcIpAddress.ulIpv4Addr[ucLoopIndex] = ntohl(pstClassifierEntry->stSrcIpAddress.ulIpv4Addr[ucLoopIndex]); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Src Ip Address:0x%luX ", + pstClassifierEntry->stSrcIpAddress.ulIpv4Addr[ucLoopIndex]); + } else if (eIpAddrContext == eDestIpAddress) { + pstClassifierEntry->stDestIpAddress.ulIpv4Addr[ucLoopIndex] = ntohl(pstClassifierEntry->stDestIpAddress.ulIpv4Addr[ucLoopIndex]); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Dest Ip Address:0x%luX ", + pstClassifierEntry->stDestIpAddress.ulIpv4Addr[ucLoopIndex]); } } - u8IpAddressLen-=nSizeOfIPAddressInBytes; - if(u8IpAddressLen >= nSizeOfIPAddressInBytes) - { + u8IpAddressLen -= nSizeOfIPAddressInBytes; + if (u8IpAddressLen >= nSizeOfIPAddressInBytes) { memcpy(ptrClassifierIpMask + (ucLoopIndex * nSizeOfIPAddressInBytes), (pu8IpAddressMaskSrc+nSizeOfIPAddressInBytes + - (ucLoopIndex*nSizeOfIPAddressInBytes*2)), + (ucLoopIndex*nSizeOfIPAddressInBytes*2)), nSizeOfIPAddressInBytes); - if(!bIpVersion6) - { - if(eIpAddrContext == eSrcIpAddress) - { - pstClassifierEntry->stSrcIpAddress. - ulIpv4Mask[ucLoopIndex]= - ntohl(pstClassifierEntry->stSrcIpAddress. - ulIpv4Mask[ucLoopIndex]); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"Src Ip Mask Address:0x%luX ",pstClassifierEntry->stSrcIpAddress.ulIpv4Mask[ucLoopIndex]); - } - else if(eIpAddrContext == eDestIpAddress) - { - pstClassifierEntry->stDestIpAddress. - ulIpv4Mask[ucLoopIndex] = - ntohl(pstClassifierEntry->stDestIpAddress. - ulIpv4Mask[ucLoopIndex]); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"Dest Ip Mask Address:0x%luX ",pstClassifierEntry->stDestIpAddress.ulIpv4Mask[ucLoopIndex]); + + if (!bIpVersion6) { + if (eIpAddrContext == eSrcIpAddress) { + pstClassifierEntry->stSrcIpAddress.ulIpv4Mask[ucLoopIndex] = + ntohl(pstClassifierEntry->stSrcIpAddress.ulIpv4Mask[ucLoopIndex]); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Src Ip Mask Address:0x%luX ", + pstClassifierEntry->stSrcIpAddress.ulIpv4Mask[ucLoopIndex]); + } else if (eIpAddrContext == eDestIpAddress) { + pstClassifierEntry->stDestIpAddress.ulIpv4Mask[ucLoopIndex] = + ntohl(pstClassifierEntry->stDestIpAddress.ulIpv4Mask[ucLoopIndex]); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Dest Ip Mask Address:0x%luX ", + pstClassifierEntry->stDestIpAddress.ulIpv4Mask[ucLoopIndex]); } } - u8IpAddressLen-=nSizeOfIPAddressInBytes; - } - if(0==u8IpAddressLen) - { - pstClassifierEntry->bDestIpValid=TRUE; + u8IpAddressLen -= nSizeOfIPAddressInBytes; } + if (0 == u8IpAddressLen) + pstClassifierEntry->bDestIpValid = TRUE; + ucLoopIndex++; } - if(bIpVersion6) - { - //Restore EndianNess of Struct - for(ucLoopIndex =0 ; ucLoopIndex < MAX_IP_RANGE_LENGTH * 4 ; - ucLoopIndex++) - { - if(eIpAddrContext == eSrcIpAddress) - { - pstClassifierEntry->stSrcIpAddress.ulIpv6Addr[ucLoopIndex]= - ntohl(pstClassifierEntry->stSrcIpAddress. - ulIpv6Addr[ucLoopIndex]); - pstClassifierEntry->stSrcIpAddress.ulIpv6Mask[ucLoopIndex]= ntohl(pstClassifierEntry->stSrcIpAddress. - ulIpv6Mask[ucLoopIndex]); - } - else if(eIpAddrContext == eDestIpAddress) - { - pstClassifierEntry->stDestIpAddress.ulIpv6Addr[ucLoopIndex]= ntohl(pstClassifierEntry->stDestIpAddress. - ulIpv6Addr[ucLoopIndex]); - pstClassifierEntry->stDestIpAddress.ulIpv6Mask[ucLoopIndex]= ntohl(pstClassifierEntry->stDestIpAddress. - ulIpv6Mask[ucLoopIndex]); + if (bIpVersion6) { + /* Restore EndianNess of Struct */ + for (ucLoopIndex = 0; ucLoopIndex < MAX_IP_RANGE_LENGTH * 4; ucLoopIndex++) { + if (eIpAddrContext == eSrcIpAddress) { + pstClassifierEntry->stSrcIpAddress.ulIpv6Addr[ucLoopIndex] = ntohl(pstClassifierEntry->stSrcIpAddress.ulIpv6Addr[ucLoopIndex]); + pstClassifierEntry->stSrcIpAddress.ulIpv6Mask[ucLoopIndex] = ntohl(pstClassifierEntry->stSrcIpAddress.ulIpv6Mask[ucLoopIndex]); + } else if (eIpAddrContext == eDestIpAddress) { + pstClassifierEntry->stDestIpAddress.ulIpv6Addr[ucLoopIndex] = ntohl(pstClassifierEntry->stDestIpAddress.ulIpv6Addr[ucLoopIndex]); + pstClassifierEntry->stDestIpAddress.ulIpv6Mask[ucLoopIndex] = ntohl(pstClassifierEntry->stDestIpAddress.ulIpv6Mask[ucLoopIndex]); } } } } } - -void ClearTargetDSXBuffer(PMINI_ADAPTER Adapter,B_UINT16 TID,BOOLEAN bFreeAll) +void ClearTargetDSXBuffer(PMINI_ADAPTER Adapter, B_UINT16 TID, BOOLEAN bFreeAll) { - ULONG ulIndex; - for(ulIndex=0; ulIndex < Adapter->ulTotalTargetBuffersAvailable; ulIndex++) - { - if(Adapter->astTargetDsxBuffer[ulIndex].valid) + ULONG ulIndex; + + for (ulIndex = 0; ulIndex < Adapter->ulTotalTargetBuffersAvailable; ulIndex++) { + if (Adapter->astTargetDsxBuffer[ulIndex].valid) continue; - if ((bFreeAll) || (Adapter->astTargetDsxBuffer[ulIndex].tid == TID)){ - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "ClearTargetDSXBuffer: found tid %d buffer cleared %lx\n", - TID, Adapter->astTargetDsxBuffer[ulIndex].ulTargetDsxBuffer); - Adapter->astTargetDsxBuffer[ulIndex].valid=1; - Adapter->astTargetDsxBuffer[ulIndex].tid=0; + + if ((bFreeAll) || (Adapter->astTargetDsxBuffer[ulIndex].tid == TID)) { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "ClearTargetDSXBuffer: found tid %d buffer cleared %lx\n", + TID, Adapter->astTargetDsxBuffer[ulIndex].ulTargetDsxBuffer); + Adapter->astTargetDsxBuffer[ulIndex].valid = 1; + Adapter->astTargetDsxBuffer[ulIndex].tid = 0; Adapter->ulFreeTargetBufferCnt++; - } + } } } -/** -@ingroup ctrl_pkt_functions -copy classifier rule into the specified SF index -*/ -static inline VOID CopyClassifierRuleToSF(PMINI_ADAPTER Adapter,stConvergenceSLTypes *psfCSType,UINT uiSearchRuleIndex,UINT nClassifierIndex) +/* + * @ingroup ctrl_pkt_functions + * copy classifier rule into the specified SF index + */ +static inline VOID CopyClassifierRuleToSF(PMINI_ADAPTER Adapter, stConvergenceSLTypes *psfCSType, UINT uiSearchRuleIndex, UINT nClassifierIndex) { S_CLASSIFIER_RULE *pstClassifierEntry = NULL; - //VOID *pvPhsContext = NULL; - UINT ucLoopIndex=0; - //UCHAR ucProtocolLength=0; - //ULONG ulPhsStatus; + /* VOID *pvPhsContext = NULL; */ + UINT ucLoopIndex = 0; + /* UCHAR ucProtocolLength=0; */ + /* ULONG ulPhsStatus; */ - - if(Adapter->PackInfo[uiSearchRuleIndex].usVCID_Value == 0 || + if (Adapter->PackInfo[uiSearchRuleIndex].usVCID_Value == 0 || nClassifierIndex > (MAX_CLASSIFIERS-1)) return; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Storing Classifier Rule Index : %X", + ntohs(psfCSType->cCPacketClassificationRule.u16PacketClassificationRuleIndex)); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"Storing Classifier Rule Index : %X",ntohs(psfCSType->cCPacketClassificationRule.u16PacketClassificationRuleIndex)); - - if(nClassifierIndex > MAX_CLASSIFIERS-1) + if (nClassifierIndex > MAX_CLASSIFIERS-1) return; pstClassifierEntry = &Adapter->astClassifierTable[nClassifierIndex]; - if(pstClassifierEntry) - { - //Store if Ipv6 - pstClassifierEntry->bIpv6Protocol = - (Adapter->PackInfo[uiSearchRuleIndex].ucIpVersion == IPV6)?TRUE:FALSE; - - //Destinaiton Port - pstClassifierEntry->ucDestPortRangeLength=psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRangeLength/4; - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"Destination Port Range Length:0x%X ",pstClassifierEntry->ucDestPortRangeLength); - if( MAX_PORT_RANGE >= psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRangeLength) - { - for(ucLoopIndex=0;ucLoopIndex<(pstClassifierEntry->ucDestPortRangeLength);ucLoopIndex++) - { - pstClassifierEntry->usDestPortRangeLo[ucLoopIndex] = - *((PUSHORT)(psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange+ucLoopIndex)); + if (pstClassifierEntry) { + /* Store if Ipv6 */ + pstClassifierEntry->bIpv6Protocol = (Adapter->PackInfo[uiSearchRuleIndex].ucIpVersion == IPV6) ? TRUE : FALSE; + + /* Destinaiton Port */ + pstClassifierEntry->ucDestPortRangeLength = psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRangeLength / 4; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Destination Port Range Length:0x%X ", pstClassifierEntry->ucDestPortRangeLength); + + if (MAX_PORT_RANGE >= psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRangeLength) { + for (ucLoopIndex = 0; ucLoopIndex < (pstClassifierEntry->ucDestPortRangeLength); ucLoopIndex++) { + pstClassifierEntry->usDestPortRangeLo[ucLoopIndex] = *((PUSHORT)(psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange+ucLoopIndex)); pstClassifierEntry->usDestPortRangeHi[ucLoopIndex] = *((PUSHORT)(psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange+2+ucLoopIndex)); - pstClassifierEntry->usDestPortRangeLo[ucLoopIndex]=ntohs(pstClassifierEntry->usDestPortRangeLo[ucLoopIndex]); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"Destination Port Range Lo:0x%X ",pstClassifierEntry->usDestPortRangeLo[ucLoopIndex]); - pstClassifierEntry->usDestPortRangeHi[ucLoopIndex]=ntohs(pstClassifierEntry->usDestPortRangeHi[ucLoopIndex]); + pstClassifierEntry->usDestPortRangeLo[ucLoopIndex] = ntohs(pstClassifierEntry->usDestPortRangeLo[ucLoopIndex]); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Destination Port Range Lo:0x%X ", + pstClassifierEntry->usDestPortRangeLo[ucLoopIndex]); + pstClassifierEntry->usDestPortRangeHi[ucLoopIndex] = ntohs(pstClassifierEntry->usDestPortRangeHi[ucLoopIndex]); } + } else { + pstClassifierEntry->ucDestPortRangeLength = 0; } - else - { - pstClassifierEntry->ucDestPortRangeLength=0; - } - //Source Port - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"Source Port Range Length:0x%X ",psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRangeLength); - if(MAX_PORT_RANGE >= - psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRangeLength) - { - pstClassifierEntry->ucSrcPortRangeLength = - psfCSType->cCPacketClassificationRule. - u8ProtocolSourcePortRangeLength/4; - for(ucLoopIndex = 0; ucLoopIndex < - (pstClassifierEntry->ucSrcPortRangeLength); ucLoopIndex++) - { + + /* Source Port */ + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Source Port Range Length:0x%X ", + psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRangeLength); + if (MAX_PORT_RANGE >= psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRangeLength) { + pstClassifierEntry->ucSrcPortRangeLength = psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRangeLength/4; + for (ucLoopIndex = 0; ucLoopIndex < (pstClassifierEntry->ucSrcPortRangeLength); ucLoopIndex++) { pstClassifierEntry->usSrcPortRangeLo[ucLoopIndex] = - *((PUSHORT)(psfCSType->cCPacketClassificationRule. + *((PUSHORT)(psfCSType->cCPacketClassificationRule. u8ProtocolSourcePortRange+ucLoopIndex)); pstClassifierEntry->usSrcPortRangeHi[ucLoopIndex] = - *((PUSHORT)(psfCSType->cCPacketClassificationRule. + *((PUSHORT)(psfCSType->cCPacketClassificationRule. u8ProtocolSourcePortRange+2+ucLoopIndex)); pstClassifierEntry->usSrcPortRangeLo[ucLoopIndex] = ntohs(pstClassifierEntry->usSrcPortRangeLo[ucLoopIndex]); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"Source Port Range Lo:0x%X ",pstClassifierEntry->usSrcPortRangeLo[ucLoopIndex]); - pstClassifierEntry->usSrcPortRangeHi[ucLoopIndex]=ntohs(pstClassifierEntry->usSrcPortRangeHi[ucLoopIndex]); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Source Port Range Lo:0x%X ", + pstClassifierEntry->usSrcPortRangeLo[ucLoopIndex]); + pstClassifierEntry->usSrcPortRangeHi[ucLoopIndex] = ntohs(pstClassifierEntry->usSrcPortRangeHi[ucLoopIndex]); } } - //Destination Ip Address and Mask - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"Ip Destination Parameters : "); - + /* Destination Ip Address and Mask */ + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Ip Destination Parameters : "); CopyIpAddrToClassifier(pstClassifierEntry, - psfCSType->cCPacketClassificationRule.u8IPDestinationAddressLength, - psfCSType->cCPacketClassificationRule.u8IPDestinationAddress, - (Adapter->PackInfo[uiSearchRuleIndex].ucIpVersion == IPV6)? - TRUE:FALSE, eDestIpAddress); + psfCSType->cCPacketClassificationRule.u8IPDestinationAddressLength, + psfCSType->cCPacketClassificationRule.u8IPDestinationAddress, + (Adapter->PackInfo[uiSearchRuleIndex].ucIpVersion == IPV6) ? + TRUE : FALSE, eDestIpAddress); - //Source Ip Address and Mask - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"Ip Source Parameters : "); + /* Source Ip Address and Mask */ + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Ip Source Parameters : "); CopyIpAddrToClassifier(pstClassifierEntry, - psfCSType->cCPacketClassificationRule.u8IPMaskedSourceAddressLength, - psfCSType->cCPacketClassificationRule.u8IPMaskedSourceAddress, - (Adapter->PackInfo[uiSearchRuleIndex].ucIpVersion == IPV6)?TRUE:FALSE, - eSrcIpAddress); - - //TOS - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"TOS Length:0x%X ",psfCSType->cCPacketClassificationRule.u8IPTypeOfServiceLength); - if(3 == psfCSType->cCPacketClassificationRule.u8IPTypeOfServiceLength) - { - pstClassifierEntry->ucIPTypeOfServiceLength = - psfCSType->cCPacketClassificationRule.u8IPTypeOfServiceLength; - pstClassifierEntry->ucTosLow = - psfCSType->cCPacketClassificationRule.u8IPTypeOfService[0]; - pstClassifierEntry->ucTosHigh = - psfCSType->cCPacketClassificationRule.u8IPTypeOfService[1]; - pstClassifierEntry->ucTosMask = - psfCSType->cCPacketClassificationRule.u8IPTypeOfService[2]; + psfCSType->cCPacketClassificationRule.u8IPMaskedSourceAddressLength, + psfCSType->cCPacketClassificationRule.u8IPMaskedSourceAddress, + (Adapter->PackInfo[uiSearchRuleIndex].ucIpVersion == IPV6) ? TRUE : FALSE, + eSrcIpAddress); + + /* TOS */ + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "TOS Length:0x%X ", psfCSType->cCPacketClassificationRule.u8IPTypeOfServiceLength); + if (3 == psfCSType->cCPacketClassificationRule.u8IPTypeOfServiceLength) { + pstClassifierEntry->ucIPTypeOfServiceLength = psfCSType->cCPacketClassificationRule.u8IPTypeOfServiceLength; + pstClassifierEntry->ucTosLow = psfCSType->cCPacketClassificationRule.u8IPTypeOfService[0]; + pstClassifierEntry->ucTosHigh = psfCSType->cCPacketClassificationRule.u8IPTypeOfService[1]; + pstClassifierEntry->ucTosMask = psfCSType->cCPacketClassificationRule.u8IPTypeOfService[2]; pstClassifierEntry->bTOSValid = TRUE; } - if(psfCSType->cCPacketClassificationRule.u8Protocol == 0) - { - //we didn't get protocol field filled in by the BS - pstClassifierEntry->ucProtocolLength=0; - } - else - { - pstClassifierEntry->ucProtocolLength=1;// 1 valid protocol + if (psfCSType->cCPacketClassificationRule.u8Protocol == 0) { + /* we didn't get protocol field filled in by the BS */ + pstClassifierEntry->ucProtocolLength = 0; + } else { + pstClassifierEntry->ucProtocolLength = 1; /* 1 valid protocol */ } - pstClassifierEntry->ucProtocol[0] = - psfCSType->cCPacketClassificationRule.u8Protocol; - - pstClassifierEntry->u8ClassifierRulePriority = - psfCSType->cCPacketClassificationRule.u8ClassifierRulePriority; - - //store the classifier rule ID and set this classifier entry as valid - pstClassifierEntry->ucDirection = - Adapter->PackInfo[uiSearchRuleIndex].ucDirection; - pstClassifierEntry->uiClassifierRuleIndex = ntohs(psfCSType-> - cCPacketClassificationRule.u16PacketClassificationRuleIndex); - pstClassifierEntry->usVCID_Value = - Adapter->PackInfo[uiSearchRuleIndex].usVCID_Value; - pstClassifierEntry->ulSFID = - Adapter->PackInfo[uiSearchRuleIndex].ulSFID; - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Search Index %d Dir: %d, Index: %d, Vcid: %d\n", - uiSearchRuleIndex, pstClassifierEntry->ucDirection, - pstClassifierEntry->uiClassifierRuleIndex, - pstClassifierEntry->usVCID_Value); - - if(psfCSType->cCPacketClassificationRule.u8AssociatedPHSI) - { + pstClassifierEntry->ucProtocol[0] = psfCSType->cCPacketClassificationRule.u8Protocol; + pstClassifierEntry->u8ClassifierRulePriority = psfCSType->cCPacketClassificationRule.u8ClassifierRulePriority; + + /* store the classifier rule ID and set this classifier entry as valid */ + pstClassifierEntry->ucDirection = Adapter->PackInfo[uiSearchRuleIndex].ucDirection; + pstClassifierEntry->uiClassifierRuleIndex = ntohs(psfCSType->cCPacketClassificationRule.u16PacketClassificationRuleIndex); + pstClassifierEntry->usVCID_Value = Adapter->PackInfo[uiSearchRuleIndex].usVCID_Value; + pstClassifierEntry->ulSFID = Adapter->PackInfo[uiSearchRuleIndex].ulSFID; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Search Index %d Dir: %d, Index: %d, Vcid: %d\n", + uiSearchRuleIndex, pstClassifierEntry->ucDirection, + pstClassifierEntry->uiClassifierRuleIndex, + pstClassifierEntry->usVCID_Value); + + if (psfCSType->cCPacketClassificationRule.u8AssociatedPHSI) pstClassifierEntry->u8AssociatedPHSI = psfCSType->cCPacketClassificationRule.u8AssociatedPHSI; - } - //Copy ETH CS Parameters + /* Copy ETH CS Parameters */ pstClassifierEntry->ucEthCSSrcMACLen = (psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddressLength); - memcpy(pstClassifierEntry->au8EThCSSrcMAC,psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress,MAC_ADDRESS_SIZE); - memcpy(pstClassifierEntry->au8EThCSSrcMACMask,psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress+MAC_ADDRESS_SIZE,MAC_ADDRESS_SIZE); + memcpy(pstClassifierEntry->au8EThCSSrcMAC, psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress, MAC_ADDRESS_SIZE); + memcpy(pstClassifierEntry->au8EThCSSrcMACMask, psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress + MAC_ADDRESS_SIZE, MAC_ADDRESS_SIZE); pstClassifierEntry->ucEthCSDestMACLen = (psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddressLength); - memcpy(pstClassifierEntry->au8EThCSDestMAC,psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress,MAC_ADDRESS_SIZE); - memcpy(pstClassifierEntry->au8EThCSDestMACMask,psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress+MAC_ADDRESS_SIZE,MAC_ADDRESS_SIZE); + memcpy(pstClassifierEntry->au8EThCSDestMAC, psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress, MAC_ADDRESS_SIZE); + memcpy(pstClassifierEntry->au8EThCSDestMACMask, psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress + MAC_ADDRESS_SIZE, MAC_ADDRESS_SIZE); pstClassifierEntry->ucEtherTypeLen = (psfCSType->cCPacketClassificationRule.u8EthertypeLength); - memcpy(pstClassifierEntry->au8EthCSEtherType,psfCSType->cCPacketClassificationRule.u8Ethertype,NUM_ETHERTYPE_BYTES); + memcpy(pstClassifierEntry->au8EthCSEtherType, psfCSType->cCPacketClassificationRule.u8Ethertype, NUM_ETHERTYPE_BYTES); memcpy(pstClassifierEntry->usUserPriority, &psfCSType->cCPacketClassificationRule.u16UserPriority, 2); pstClassifierEntry->usVLANID = ntohs(psfCSType->cCPacketClassificationRule.u16VLANID); pstClassifierEntry->usValidityBitMap = ntohs(psfCSType->cCPacketClassificationRule.u16ValidityBitMap); @@ -434,244 +362,199 @@ static inline VOID CopyClassifierRuleToSF(PMINI_ADAPTER Adapter,stConvergenceSLT } } - -/** -@ingroup ctrl_pkt_functions -*/ -static inline VOID DeleteClassifierRuleFromSF(PMINI_ADAPTER Adapter,UINT uiSearchRuleIndex,UINT nClassifierIndex) +/* + * @ingroup ctrl_pkt_functions + */ +static inline VOID DeleteClassifierRuleFromSF(PMINI_ADAPTER Adapter, UINT uiSearchRuleIndex, UINT nClassifierIndex) { S_CLASSIFIER_RULE *pstClassifierEntry = NULL; - B_UINT16 u16PacketClassificationRuleIndex; - USHORT usVCID; - //VOID *pvPhsContext = NULL; - //ULONG ulPhsStatus; + B_UINT16 u16PacketClassificationRuleIndex; + USHORT usVCID; + /* VOID *pvPhsContext = NULL; */ + /*ULONG ulPhsStatus; */ usVCID = Adapter->PackInfo[uiSearchRuleIndex].usVCID_Value; - if(nClassifierIndex > MAX_CLASSIFIERS-1) + if (nClassifierIndex > MAX_CLASSIFIERS-1) return; - if(usVCID == 0) + if (usVCID == 0) return; u16PacketClassificationRuleIndex = Adapter->astClassifierTable[nClassifierIndex].uiClassifierRuleIndex; - - pstClassifierEntry = &Adapter->astClassifierTable[nClassifierIndex]; - if(pstClassifierEntry) - { + if (pstClassifierEntry) { pstClassifierEntry->bUsed = FALSE; pstClassifierEntry->uiClassifierRuleIndex = 0; - memset(pstClassifierEntry,0,sizeof(S_CLASSIFIER_RULE)); + memset(pstClassifierEntry, 0, sizeof(S_CLASSIFIER_RULE)); - //Delete the PHS Rule for this classifier - PhsDeleteClassifierRule( - &Adapter->stBCMPhsContext, - usVCID, - u16PacketClassificationRuleIndex); + /* Delete the PHS Rule for this classifier */ + PhsDeleteClassifierRule(&Adapter->stBCMPhsContext, usVCID, u16PacketClassificationRuleIndex); } } -/** -@ingroup ctrl_pkt_functions -*/ -VOID DeleteAllClassifiersForSF(PMINI_ADAPTER Adapter,UINT uiSearchRuleIndex) +/* + * @ingroup ctrl_pkt_functions + */ +VOID DeleteAllClassifiersForSF(PMINI_ADAPTER Adapter, UINT uiSearchRuleIndex) { S_CLASSIFIER_RULE *pstClassifierEntry = NULL; UINT nClassifierIndex; - //B_UINT16 u16PacketClassificationRuleIndex; - USHORT ulVCID; - //VOID *pvPhsContext = NULL; - //ULONG ulPhsStatus; + /* B_UINT16 u16PacketClassificationRuleIndex; */ + USHORT ulVCID; + /* VOID *pvPhsContext = NULL; */ + /* ULONG ulPhsStatus; */ ulVCID = Adapter->PackInfo[uiSearchRuleIndex].usVCID_Value; - if(ulVCID == 0) + if (ulVCID == 0) return; - - for(nClassifierIndex =0 ; nClassifierIndex < MAX_CLASSIFIERS ; nClassifierIndex++) - { - if(Adapter->astClassifierTable[nClassifierIndex].usVCID_Value == ulVCID) - { + for (nClassifierIndex = 0; nClassifierIndex < MAX_CLASSIFIERS; nClassifierIndex++) { + if (Adapter->astClassifierTable[nClassifierIndex].usVCID_Value == ulVCID) { pstClassifierEntry = &Adapter->astClassifierTable[nClassifierIndex]; - if(pstClassifierEntry->bUsed) - { - DeleteClassifierRuleFromSF(Adapter,uiSearchRuleIndex,nClassifierIndex); - } + + if (pstClassifierEntry->bUsed) + DeleteClassifierRuleFromSF(Adapter, uiSearchRuleIndex, nClassifierIndex); } } - //Delete All Phs Rules Associated with this SF - PhsDeleteSFRules( - &Adapter->stBCMPhsContext, - ulVCID); - + /* Delete All Phs Rules Associated with this SF */ + PhsDeleteSFRules(&Adapter->stBCMPhsContext, ulVCID); } - -/** -This routinue copies the Connection Management -related data into the Adapter structure. -@ingroup ctrl_pkt_functions -*/ - -static VOID CopyToAdapter( register PMINI_ADAPTER Adapter, /**PackInfo[uiSearchRuleIndex].usVCID_Value; UINT UGIValue = 0; - - Adapter->PackInfo[uiSearchRuleIndex].bValid=TRUE; - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Search Rule Index = %d\n", uiSearchRuleIndex); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"%s: SFID= %x ",__FUNCTION__, ntohl(psfLocalSet->u32SFID)); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"Updating Queue %d",uiSearchRuleIndex); + Adapter->PackInfo[uiSearchRuleIndex].bValid = TRUE; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Search Rule Index = %d\n", uiSearchRuleIndex); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "%s: SFID= %x ", __FUNCTION__, ntohl(psfLocalSet->u32SFID)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Updating Queue %d", uiSearchRuleIndex); ulSFID = ntohl(psfLocalSet->u32SFID); - //Store IP Version used - //Get The Version Of IP used (IPv6 or IPv4) from CSSpecification field of SF + /* Store IP Version used */ + /* Get The Version Of IP used (IPv6 or IPv4) from CSSpecification field of SF */ Adapter->PackInfo[uiSearchRuleIndex].bIPCSSupport = 0; Adapter->PackInfo[uiSearchRuleIndex].bEthCSSupport = 0; - /*Enable IP/ETh CS Support As Required*/ - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"CopyToAdapter : u8CSSpecification : %X\n",psfLocalSet->u8CSSpecification); - switch(psfLocalSet->u8CSSpecification) + /* Enable IP/ETh CS Support As Required */ + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "CopyToAdapter : u8CSSpecification : %X\n", psfLocalSet->u8CSSpecification); + switch (psfLocalSet->u8CSSpecification) { + case eCSPacketIPV4: { - case eCSPacketIPV4: - { - Adapter->PackInfo[uiSearchRuleIndex].bIPCSSupport = IPV4_CS; - break; - } - case eCSPacketIPV6: - { - Adapter->PackInfo[uiSearchRuleIndex].bIPCSSupport = IPV6_CS; - break; - } - - case eCS802_3PacketEthernet: - case eCS802_1QPacketVLAN: - { - Adapter->PackInfo[uiSearchRuleIndex].bEthCSSupport = ETH_CS_802_3; - break; - } - - case eCSPacketIPV4Over802_1QVLAN: - case eCSPacketIPV4Over802_3Ethernet: - { - Adapter->PackInfo[uiSearchRuleIndex].bIPCSSupport = IPV4_CS; - Adapter->PackInfo[uiSearchRuleIndex].bEthCSSupport = ETH_CS_802_3; - break; - } - - case eCSPacketIPV6Over802_1QVLAN: - case eCSPacketIPV6Over802_3Ethernet: - { - Adapter->PackInfo[uiSearchRuleIndex].bIPCSSupport = IPV6_CS; - Adapter->PackInfo[uiSearchRuleIndex].bEthCSSupport = ETH_CS_802_3; - break; - } - - default: - { - BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"Error in value of CS Classification.. setting default to IP CS\n"); - Adapter->PackInfo[uiSearchRuleIndex].bIPCSSupport = IPV4_CS; - break; - } + Adapter->PackInfo[uiSearchRuleIndex].bIPCSSupport = IPV4_CS; + break; + } + case eCSPacketIPV6: + { + Adapter->PackInfo[uiSearchRuleIndex].bIPCSSupport = IPV6_CS; + break; + } + case eCS802_3PacketEthernet: + case eCS802_1QPacketVLAN: + { + Adapter->PackInfo[uiSearchRuleIndex].bEthCSSupport = ETH_CS_802_3; + break; + } + case eCSPacketIPV4Over802_1QVLAN: + case eCSPacketIPV4Over802_3Ethernet: + { + Adapter->PackInfo[uiSearchRuleIndex].bIPCSSupport = IPV4_CS; + Adapter->PackInfo[uiSearchRuleIndex].bEthCSSupport = ETH_CS_802_3; + break; + } + case eCSPacketIPV6Over802_1QVLAN: + case eCSPacketIPV6Over802_3Ethernet: + { + Adapter->PackInfo[uiSearchRuleIndex].bIPCSSupport = IPV6_CS; + Adapter->PackInfo[uiSearchRuleIndex].bEthCSSupport = ETH_CS_802_3; + break; + } + default: + { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Error in value of CS Classification.. setting default to IP CS\n"); + Adapter->PackInfo[uiSearchRuleIndex].bIPCSSupport = IPV4_CS; + break; + } } - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"CopyToAdapter : Queue No : %X ETH CS Support : %X , IP CS Support : %X \n", - uiSearchRuleIndex, - Adapter->PackInfo[uiSearchRuleIndex].bEthCSSupport, - Adapter->PackInfo[uiSearchRuleIndex].bIPCSSupport); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "CopyToAdapter : Queue No : %X ETH CS Support : %X , IP CS Support : %X\n", + uiSearchRuleIndex, + Adapter->PackInfo[uiSearchRuleIndex].bEthCSSupport, + Adapter->PackInfo[uiSearchRuleIndex].bIPCSSupport); - //Store IP Version used - //Get The Version Of IP used (IPv6 or IPv4) from CSSpecification field of SF - if(Adapter->PackInfo[uiSearchRuleIndex].bIPCSSupport == IPV6_CS) - { + /* Store IP Version used */ + /* Get The Version Of IP used (IPv6 or IPv4) from CSSpecification field of SF */ + if (Adapter->PackInfo[uiSearchRuleIndex].bIPCSSupport == IPV6_CS) Adapter->PackInfo[uiSearchRuleIndex].ucIpVersion = IPV6; - } else - { Adapter->PackInfo[uiSearchRuleIndex].ucIpVersion = IPV4; - } /* To ensure that the ETH CS code doesn't gets executed if the BS doesn't supports ETH CS */ - if(!Adapter->bETHCSEnabled) + if (!Adapter->bETHCSEnabled) Adapter->PackInfo[uiSearchRuleIndex].bEthCSSupport = 0; - if(psfLocalSet->u8ServiceClassNameLength > 0 && - psfLocalSet->u8ServiceClassNameLength < 32) - { - memcpy(Adapter->PackInfo[uiSearchRuleIndex].ucServiceClassName, - psfLocalSet->u8ServiceClassName, - psfLocalSet->u8ServiceClassNameLength); - } - Adapter->PackInfo[uiSearchRuleIndex].u8QueueType = - psfLocalSet->u8ServiceFlowSchedulingType; + if (psfLocalSet->u8ServiceClassNameLength > 0 && psfLocalSet->u8ServiceClassNameLength < 32) + memcpy(Adapter->PackInfo[uiSearchRuleIndex].ucServiceClassName, psfLocalSet->u8ServiceClassName, psfLocalSet->u8ServiceClassNameLength); - if(Adapter->PackInfo[uiSearchRuleIndex].u8QueueType==BE && - Adapter->PackInfo[uiSearchRuleIndex].ucDirection) - { - Adapter->usBestEffortQueueIndex=uiSearchRuleIndex; - } + Adapter->PackInfo[uiSearchRuleIndex].u8QueueType = psfLocalSet->u8ServiceFlowSchedulingType; + + if (Adapter->PackInfo[uiSearchRuleIndex].u8QueueType == BE && Adapter->PackInfo[uiSearchRuleIndex].ucDirection) + Adapter->usBestEffortQueueIndex = uiSearchRuleIndex; Adapter->PackInfo[uiSearchRuleIndex].ulSFID = ntohl(psfLocalSet->u32SFID); Adapter->PackInfo[uiSearchRuleIndex].u8TrafficPriority = psfLocalSet->u8TrafficPriority; - //copy all the classifier in the Service Flow param structure - for(nIndex=0; nIndexu8TotalClassifiers; nIndex++) - { - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"Classifier index =%d",nIndex); - psfCSType = &psfLocalSet->cConvergenceSLTypes[nIndex]; - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"Classifier index =%d",nIndex); + /* copy all the classifier in the Service Flow param structure */ + for (nIndex = 0; nIndex < psfLocalSet->u8TotalClassifiers; nIndex++) { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Classifier index =%d", nIndex); + psfCSType = &psfLocalSet->cConvergenceSLTypes[nIndex]; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Classifier index =%d", nIndex); - if(psfCSType->cCPacketClassificationRule.u8ClassifierRulePriority) - { - Adapter->PackInfo[uiSearchRuleIndex].bClassifierPriority=TRUE; - } - - if(psfCSType->cCPacketClassificationRule.u8ClassifierRulePriority) - { - Adapter->PackInfo[uiSearchRuleIndex].bClassifierPriority=TRUE; - } + if (psfCSType->cCPacketClassificationRule.u8ClassifierRulePriority) + Adapter->PackInfo[uiSearchRuleIndex].bClassifierPriority = TRUE; + if (psfCSType->cCPacketClassificationRule.u8ClassifierRulePriority) + Adapter->PackInfo[uiSearchRuleIndex].bClassifierPriority = TRUE; - if(ucDsxType== DSA_ACK) - { + if (ucDsxType == DSA_ACK) { eClassifierAction = eAddClassifier; - } - else if(ucDsxType == DSC_ACK) - { - switch(psfCSType->u8ClassfierDSCAction) - { - case 0://DSC Add Classifier + } else if (ucDsxType == DSC_ACK) { + switch (psfCSType->u8ClassfierDSCAction) { + case 0: /* DSC Add Classifier */ { eClassifierAction = eAddClassifier; } break; - case 1://DSC Replace Classifier + case 1: /* DSC Replace Classifier */ { eClassifierAction = eReplaceClassifier; } break; - case 2://DSC Delete Classifier + case 2: /* DSC Delete Classifier */ { eClassifierAction = eDeleteClassifier; - } break; default: @@ -683,163 +566,133 @@ static VOID CopyToAdapter( register PMINI_ADAPTER Adapter, /**cCPacketClassificationRule.u16PacketClassificationRuleIndex); - switch(eClassifierAction) - { + switch (eClassifierAction) { case eAddClassifier: { - //Get a Free Classifier Index From Classifier table for this SF to add the Classifier - //Contained in this message - nClassifierIndex = SearchClsid(Adapter,ulSFID,u16PacketClassificationRuleIndex); + /* Get a Free Classifier Index From Classifier table for this SF to add the Classifier */ + /* Contained in this message */ + nClassifierIndex = SearchClsid(Adapter, ulSFID, u16PacketClassificationRuleIndex); - if(nClassifierIndex > MAX_CLASSIFIERS) - { + if (nClassifierIndex > MAX_CLASSIFIERS) { nClassifierIndex = SearchFreeClsid(Adapter); - if(nClassifierIndex > MAX_CLASSIFIERS) - { - //Failed To get a free Entry - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"Error Failed To get a free Classifier Entry"); + if (nClassifierIndex > MAX_CLASSIFIERS) { + /* Failed To get a free Entry */ + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Error Failed To get a free Classifier Entry"); break; } - //Copy the Classifier Rule for this service flow into our Classifier table maintained per SF. - CopyClassifierRuleToSF(Adapter,psfCSType,uiSearchRuleIndex,nClassifierIndex); - } - - else - { - //This Classifier Already Exists and it is invalid to Add Classifier with existing PCRI - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"CopyToAdapter : Error The Specified Classifier Already Exists \ - and attempted To Add Classifier with Same PCRI : 0x%x\n", u16PacketClassificationRuleIndex); + /* Copy the Classifier Rule for this service flow into our Classifier table maintained per SF. */ + CopyClassifierRuleToSF(Adapter, psfCSType, uiSearchRuleIndex, nClassifierIndex); + } else { + /* This Classifier Already Exists and it is invalid to Add Classifier with existing PCRI */ + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, + "CopyToAdapter: Error The Specified Classifier Already Exists and attempted To Add Classifier with Same PCRI : 0x%x\n", + u16PacketClassificationRuleIndex); } } break; - case eReplaceClassifier: { - //Get the Classifier Index From Classifier table for this SF and replace existing Classifier - //with the new classifier Contained in this message - nClassifierIndex = SearchClsid(Adapter,ulSFID,u16PacketClassificationRuleIndex); - if(nClassifierIndex > MAX_CLASSIFIERS) - { - //Failed To search the classifier - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"Error Search for Classifier To be replaced failed"); + /* Get the Classifier Index From Classifier table for this SF and replace existing Classifier */ + /* with the new classifier Contained in this message */ + nClassifierIndex = SearchClsid(Adapter, ulSFID, u16PacketClassificationRuleIndex); + if (nClassifierIndex > MAX_CLASSIFIERS) { + /* Failed To search the classifier */ + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Error Search for Classifier To be replaced failed"); break; } - //Copy the Classifier Rule for this service flow into our Classifier table maintained per SF. - CopyClassifierRuleToSF(Adapter,psfCSType,uiSearchRuleIndex,nClassifierIndex); + /* Copy the Classifier Rule for this service flow into our Classifier table maintained per SF. */ + CopyClassifierRuleToSF(Adapter, psfCSType, uiSearchRuleIndex, nClassifierIndex); } break; - case eDeleteClassifier: { - //Get the Classifier Index From Classifier table for this SF and replace existing Classifier - //with the new classifier Contained in this message - nClassifierIndex = SearchClsid(Adapter,ulSFID,u16PacketClassificationRuleIndex); - if(nClassifierIndex > MAX_CLASSIFIERS) - { - //Failed To search the classifier - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"Error Search for Classifier To be deleted failed"); + /* Get the Classifier Index From Classifier table for this SF and replace existing Classifier */ + /* with the new classifier Contained in this message */ + nClassifierIndex = SearchClsid(Adapter, ulSFID, u16PacketClassificationRuleIndex); + if (nClassifierIndex > MAX_CLASSIFIERS) { + /* Failed To search the classifier */ + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Error Search for Classifier To be deleted failed"); break; } - //Delete This classifier - DeleteClassifierRuleFromSF(Adapter,uiSearchRuleIndex,nClassifierIndex); + /* Delete This classifier */ + DeleteClassifierRuleFromSF(Adapter, uiSearchRuleIndex, nClassifierIndex); } break; - default: { - //Invalid Action for classifier + /* Invalid Action for classifier */ break; } } } - //Repeat parsing Classification Entries to process PHS Rules - for(nIndex=0; nIndex < psfLocalSet->u8TotalClassifiers; nIndex++) - { - psfCSType = &psfLocalSet->cConvergenceSLTypes[nIndex]; - - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "psfCSType->u8PhsDSCAction : 0x%x\n", - psfCSType->u8PhsDSCAction ); + /* Repeat parsing Classification Entries to process PHS Rules */ + for (nIndex = 0; nIndex < psfLocalSet->u8TotalClassifiers; nIndex++) { + psfCSType = &psfLocalSet->cConvergenceSLTypes[nIndex]; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "psfCSType->u8PhsDSCAction : 0x%x\n", psfCSType->u8PhsDSCAction); - switch (psfCSType->u8PhsDSCAction) - { + switch (psfCSType->u8PhsDSCAction) { case eDeleteAllPHSRules: { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"Deleting All PHS Rules For VCID: 0x%X\n",uVCID); - - //Delete All the PHS rules for this Service flow - - PhsDeleteSFRules( - &Adapter->stBCMPhsContext, - uVCID); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Deleting All PHS Rules For VCID: 0x%X\n", uVCID); + /* Delete All the PHS rules for this Service flow */ + PhsDeleteSFRules(&Adapter->stBCMPhsContext, uVCID); break; } case eDeletePHSRule: { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"PHS DSC Action = Delete PHS Rule \n"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "PHS DSC Action = Delete PHS Rule\n"); + + if (psfCSType->cPhsRule.u8PHSI) + PhsDeletePHSRule(&Adapter->stBCMPhsContext, uVCID, psfCSType->cCPacketClassificationRule.u8AssociatedPHSI); - if(psfCSType->cPhsRule.u8PHSI) - { - PhsDeletePHSRule( - &Adapter->stBCMPhsContext, - uVCID, - psfCSType->cCPacketClassificationRule.u8AssociatedPHSI); - } - else - { - //BCM_DEBUG_PRINT(CONN_MSG,("Error CPHSRule.PHSI is ZERO \n")); - } break; } - default : + default: { - if(ucDsxType == DSC_ACK) - { - //BCM_DEBUG_PRINT(CONN_MSG,("Invalid PHS DSC Action For DSC \n",psfCSType->cPhsRule.u8PHSI)); - break; //FOr DSC ACK Case PHS DSC Action must be in valid set + if (ucDsxType == DSC_ACK) { + /* BCM_DEBUG_PRINT(CONN_MSG,("Invalid PHS DSC Action For DSC\n",psfCSType->cPhsRule.u8PHSI)); */ + break; /* FOr DSC ACK Case PHS DSC Action must be in valid set */ } } - //Proceed To Add PHS rule for DSA_ACK case even if PHS DSC action is unspecified - //No Break Here . Intentionally! + /* Proceed To Add PHS rule for DSA_ACK case even if PHS DSC action is unspecified */ + /* No Break Here . Intentionally! */ case eAddPHSRule: case eSetPHSRule: { - if(psfCSType->cPhsRule.u8PHSI) - { - //Apply This PHS Rule to all classifiers whose Associated PHSI Match + if (psfCSType->cPhsRule.u8PHSI) { + /* Apply This PHS Rule to all classifiers whose Associated PHSI Match */ unsigned int uiClassifierIndex = 0; - if(pstAddIndication->u8Direction == UPLINK_DIR ) - { - for(uiClassifierIndex=0;uiClassifierIndexastClassifierTable[uiClassifierIndex].bUsed) && + if (pstAddIndication->u8Direction == UPLINK_DIR) { + for (uiClassifierIndex = 0; uiClassifierIndex < MAX_CLASSIFIERS; uiClassifierIndex++) { + if ((Adapter->astClassifierTable[uiClassifierIndex].bUsed) && (Adapter->astClassifierTable[uiClassifierIndex].ulSFID == Adapter->PackInfo[uiSearchRuleIndex].ulSFID) && - (Adapter->astClassifierTable[uiClassifierIndex].u8AssociatedPHSI == psfCSType->cPhsRule.u8PHSI)) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Adding PHS Rule For Classifier : 0x%x cPhsRule.u8PHSI : 0x%x\n", - Adapter->astClassifierTable[uiClassifierIndex].uiClassifierRuleIndex, - psfCSType->cPhsRule.u8PHSI); - //Update The PHS Rule for this classifier as Associated PHSI id defined - - //Copy the PHS Rule - sPhsRule.u8PHSI = psfCSType->cPhsRule.u8PHSI; - sPhsRule.u8PHSFLength = psfCSType->cPhsRule.u8PHSFLength; + (Adapter->astClassifierTable[uiClassifierIndex].u8AssociatedPHSI == psfCSType->cPhsRule.u8PHSI)) { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, + "Adding PHS Rule For Classifier: 0x%x cPhsRule.u8PHSI: 0x%x\n", + Adapter->astClassifierTable[uiClassifierIndex].uiClassifierRuleIndex, + psfCSType->cPhsRule.u8PHSI); + /* Update The PHS Rule for this classifier as Associated PHSI id defined */ + + /* Copy the PHS Rule */ + sPhsRule.u8PHSI = psfCSType->cPhsRule.u8PHSI; + sPhsRule.u8PHSFLength = psfCSType->cPhsRule.u8PHSFLength; sPhsRule.u8PHSMLength = psfCSType->cPhsRule.u8PHSMLength; sPhsRule.u8PHSS = psfCSType->cPhsRule.u8PHSS; sPhsRule.u8PHSV = psfCSType->cPhsRule.u8PHSV; - memcpy(sPhsRule.u8PHSF,psfCSType->cPhsRule.u8PHSF,MAX_PHS_LENGTHS); - memcpy(sPhsRule.u8PHSM,psfCSType->cPhsRule.u8PHSM,MAX_PHS_LENGTHS); + memcpy(sPhsRule.u8PHSF, psfCSType->cPhsRule.u8PHSF, MAX_PHS_LENGTHS); + memcpy(sPhsRule.u8PHSM, psfCSType->cPhsRule.u8PHSM, MAX_PHS_LENGTHS); sPhsRule.u8RefCnt = 0; sPhsRule.bUnclassifiedPHSRule = FALSE; sPhsRule.PHSModifiedBytes = 0; sPhsRule.PHSModifiedNumPackets = 0; sPhsRule.PHSErrorNumPackets = 0; - //bPHSRuleAssociated = TRUE; - //Store The PHS Rule for this classifier + /* bPHSRuleAssociated = TRUE; */ + /* Store The PHS Rule for this classifier */ PhsUpdateClassifierRule( &Adapter->stBCMPhsContext, @@ -848,184 +701,157 @@ static VOID CopyToAdapter( register PMINI_ADAPTER Adapter, /**astClassifierTable[uiClassifierIndex].u8AssociatedPHSI); - //Update PHS Rule For the Classifier - if(sPhsRule.u8PHSI) - { + /* Update PHS Rule For the Classifier */ + if (sPhsRule.u8PHSI) { Adapter->astClassifierTable[uiClassifierIndex].u32PHSRuleID = sPhsRule.u8PHSI; - memcpy(&Adapter->astClassifierTable[uiClassifierIndex].sPhsRule,&sPhsRule,sizeof(S_PHS_RULE)); + memcpy(&Adapter->astClassifierTable[uiClassifierIndex].sPhsRule, &sPhsRule, sizeof(S_PHS_RULE)); } - } } + } else { + /* Error PHS Rule specified in signaling could not be applied to any classifier */ + + /* Copy the PHS Rule */ + sPhsRule.u8PHSI = psfCSType->cPhsRule.u8PHSI; + sPhsRule.u8PHSFLength = psfCSType->cPhsRule.u8PHSFLength; + sPhsRule.u8PHSMLength = psfCSType->cPhsRule.u8PHSMLength; + sPhsRule.u8PHSS = psfCSType->cPhsRule.u8PHSS; + sPhsRule.u8PHSV = psfCSType->cPhsRule.u8PHSV; + memcpy(sPhsRule.u8PHSF, psfCSType->cPhsRule.u8PHSF, MAX_PHS_LENGTHS); + memcpy(sPhsRule.u8PHSM, psfCSType->cPhsRule.u8PHSM, MAX_PHS_LENGTHS); + sPhsRule.u8RefCnt = 0; + sPhsRule.bUnclassifiedPHSRule = TRUE; + sPhsRule.PHSModifiedBytes = 0; + sPhsRule.PHSModifiedNumPackets = 0; + sPhsRule.PHSErrorNumPackets = 0; + /* Store The PHS Rule for this classifier */ + + /* + * Passing the argument u8PHSI instead of clsid. Because for DL with no classifier rule, + * clsid will be zero hence we can't have multiple PHS rules for the same SF. + * To support multiple PHS rule, passing u8PHSI. + */ + PhsUpdateClassifierRule( + &Adapter->stBCMPhsContext, + uVCID, + sPhsRule.u8PHSI, + &sPhsRule, + sPhsRule.u8PHSI); } - else - { - //Error PHS Rule specified in signaling could not be applied to any classifier - - //Copy the PHS Rule - sPhsRule.u8PHSI = psfCSType->cPhsRule.u8PHSI; - sPhsRule.u8PHSFLength = psfCSType->cPhsRule.u8PHSFLength; - sPhsRule.u8PHSMLength = psfCSType->cPhsRule.u8PHSMLength; - sPhsRule.u8PHSS = psfCSType->cPhsRule.u8PHSS; - sPhsRule.u8PHSV = psfCSType->cPhsRule.u8PHSV; - memcpy(sPhsRule.u8PHSF,psfCSType->cPhsRule.u8PHSF,MAX_PHS_LENGTHS); - memcpy(sPhsRule.u8PHSM,psfCSType->cPhsRule.u8PHSM,MAX_PHS_LENGTHS); - sPhsRule.u8RefCnt = 0; - sPhsRule.bUnclassifiedPHSRule = TRUE; - sPhsRule.PHSModifiedBytes = 0; - sPhsRule.PHSModifiedNumPackets = 0; - sPhsRule.PHSErrorNumPackets = 0; - //Store The PHS Rule for this classifier - - /* - Passing the argument u8PHSI instead of clsid. Because for DL with no classifier rule, - clsid will be zero hence we can't have multiple PHS rules for the same SF. - To support multiple PHS rule, passing u8PHSI. - */ - - PhsUpdateClassifierRule( - &Adapter->stBCMPhsContext, - uVCID, - sPhsRule.u8PHSI, - &sPhsRule, - sPhsRule.u8PHSI); - - } - } } break; } } - if(psfLocalSet->u32MaxSustainedTrafficRate == 0 ) - { - //No Rate Limit . Set Max Sustained Traffic Rate to Maximum - Adapter->PackInfo[uiSearchRuleIndex].uiMaxAllowedRate = - WIMAX_MAX_ALLOWED_RATE; - - } - else if (ntohl(psfLocalSet->u32MaxSustainedTrafficRate) > - WIMAX_MAX_ALLOWED_RATE) - { - //Too large Allowed Rate specified. Limiting to Wi Max Allowed rate - Adapter->PackInfo[uiSearchRuleIndex].uiMaxAllowedRate = - WIMAX_MAX_ALLOWED_RATE; - } - else - { - Adapter->PackInfo[uiSearchRuleIndex].uiMaxAllowedRate = - ntohl(psfLocalSet->u32MaxSustainedTrafficRate); + if (psfLocalSet->u32MaxSustainedTrafficRate == 0) { + /* No Rate Limit . Set Max Sustained Traffic Rate to Maximum */ + Adapter->PackInfo[uiSearchRuleIndex].uiMaxAllowedRate = WIMAX_MAX_ALLOWED_RATE; + } else if (ntohl(psfLocalSet->u32MaxSustainedTrafficRate) > WIMAX_MAX_ALLOWED_RATE) { + /* Too large Allowed Rate specified. Limiting to Wi Max Allowed rate */ + Adapter->PackInfo[uiSearchRuleIndex].uiMaxAllowedRate = WIMAX_MAX_ALLOWED_RATE; + } else { + Adapter->PackInfo[uiSearchRuleIndex].uiMaxAllowedRate = ntohl(psfLocalSet->u32MaxSustainedTrafficRate); } Adapter->PackInfo[uiSearchRuleIndex].uiMaxLatency = ntohl(psfLocalSet->u32MaximumLatency); - - if(Adapter->PackInfo[uiSearchRuleIndex].uiMaxLatency == 0) /* 0 should be treated as infinite */ + if (Adapter->PackInfo[uiSearchRuleIndex].uiMaxLatency == 0) /* 0 should be treated as infinite */ Adapter->PackInfo[uiSearchRuleIndex].uiMaxLatency = MAX_LATENCY_ALLOWED; + if ((Adapter->PackInfo[uiSearchRuleIndex].u8QueueType == ERTPS || + Adapter->PackInfo[uiSearchRuleIndex].u8QueueType == UGS)) + UGIValue = ntohs(psfLocalSet->u16UnsolicitedGrantInterval); - if(( Adapter->PackInfo[uiSearchRuleIndex].u8QueueType == ERTPS || - Adapter->PackInfo[uiSearchRuleIndex].u8QueueType == UGS ) ) - UGIValue = ntohs(psfLocalSet->u16UnsolicitedGrantInterval); - - if(UGIValue == 0) + if (UGIValue == 0) UGIValue = DEFAULT_UG_INTERVAL; /* - For UGI based connections... - DEFAULT_UGI_FACTOR*UGIInterval worth of data is the max token count at host... - The extra amount of token is to ensure that a large amount of jitter won't have loss in throughput... - In case of non-UGI based connection, 200 frames worth of data is the max token count at host... - */ - + * For UGI based connections... + * DEFAULT_UGI_FACTOR*UGIInterval worth of data is the max token count at host... + * The extra amount of token is to ensure that a large amount of jitter won't have loss in throughput... + * In case of non-UGI based connection, 200 frames worth of data is the max token count at host... + */ Adapter->PackInfo[uiSearchRuleIndex].uiMaxBucketSize = - (DEFAULT_UGI_FACTOR*Adapter->PackInfo[uiSearchRuleIndex].uiMaxAllowedRate*UGIValue)/1000; + (DEFAULT_UGI_FACTOR*Adapter->PackInfo[uiSearchRuleIndex].uiMaxAllowedRate*UGIValue)/1000; - if(Adapter->PackInfo[uiSearchRuleIndex].uiMaxBucketSize < WIMAX_MAX_MTU*8) - { + if (Adapter->PackInfo[uiSearchRuleIndex].uiMaxBucketSize < WIMAX_MAX_MTU*8) { UINT UGIFactor = 0; /* Special Handling to ensure the biggest size of packet can go out from host to FW as follows: - 1. Any packet from Host to FW can go out in different packet size. - 2. So in case the Bucket count is smaller than MTU, the packets of size (Size > TokenCount), will get dropped. - 3. We can allow packets of MaxSize from Host->FW that can go out from FW in multiple SDUs by fragmentation at Wimax Layer - */ + * 1. Any packet from Host to FW can go out in different packet size. + * 2. So in case the Bucket count is smaller than MTU, the packets of size (Size > TokenCount), will get dropped. + * 3. We can allow packets of MaxSize from Host->FW that can go out from FW in multiple SDUs by fragmentation at Wimax Layer + */ UGIFactor = (Adapter->PackInfo[uiSearchRuleIndex].uiMaxLatency/UGIValue + 1); - if(UGIFactor > DEFAULT_UGI_FACTOR) - Adapter->PackInfo[uiSearchRuleIndex].uiMaxBucketSize = - (UGIFactor*Adapter->PackInfo[uiSearchRuleIndex].uiMaxAllowedRate*UGIValue)/1000; + if (UGIFactor > DEFAULT_UGI_FACTOR) + Adapter->PackInfo[uiSearchRuleIndex].uiMaxBucketSize = + (UGIFactor*Adapter->PackInfo[uiSearchRuleIndex].uiMaxAllowedRate*UGIValue)/1000; - if(Adapter->PackInfo[uiSearchRuleIndex].uiMaxBucketSize > WIMAX_MAX_MTU*8) + if (Adapter->PackInfo[uiSearchRuleIndex].uiMaxBucketSize > WIMAX_MAX_MTU*8) Adapter->PackInfo[uiSearchRuleIndex].uiMaxBucketSize = WIMAX_MAX_MTU*8; } + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "LAT: %d, UGI: %d\n", Adapter->PackInfo[uiSearchRuleIndex].uiMaxLatency, UGIValue); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "uiMaxAllowedRate: 0x%x, u32MaxSustainedTrafficRate: 0x%x ,uiMaxBucketSize: 0x%x", + Adapter->PackInfo[uiSearchRuleIndex].uiMaxAllowedRate, + ntohl(psfLocalSet->u32MaxSustainedTrafficRate), + Adapter->PackInfo[uiSearchRuleIndex].uiMaxBucketSize); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"LAT: %d, UGI: %d \n", Adapter->PackInfo[uiSearchRuleIndex].uiMaxLatency, UGIValue); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"uiMaxAllowedRate: 0x%x, u32MaxSustainedTrafficRate: 0x%x ,uiMaxBucketSize: 0x%x", - Adapter->PackInfo[uiSearchRuleIndex].uiMaxAllowedRate, - ntohl(psfLocalSet->u32MaxSustainedTrafficRate), - Adapter->PackInfo[uiSearchRuleIndex].uiMaxBucketSize); + /* copy the extended SF Parameters to Support MIBS */ + CopyMIBSExtendedSFParameters(Adapter, psfLocalSet, uiSearchRuleIndex); - //copy the extended SF Parameters to Support MIBS - CopyMIBSExtendedSFParameters(Adapter,psfLocalSet,uiSearchRuleIndex); - - //store header suppression enabled flag per SF + /* store header suppression enabled flag per SF */ Adapter->PackInfo[uiSearchRuleIndex].bHeaderSuppressionEnabled = - !(psfLocalSet->u8RequesttransmissionPolicy & - MASK_DISABLE_HEADER_SUPPRESSION); + !(psfLocalSet->u8RequesttransmissionPolicy & + MASK_DISABLE_HEADER_SUPPRESSION); kfree(Adapter->PackInfo[uiSearchRuleIndex].pstSFIndication); Adapter->PackInfo[uiSearchRuleIndex].pstSFIndication = pstAddIndication; - //Re Sort the SF list in PackInfo according to Traffic Priority + /* Re Sort the SF list in PackInfo according to Traffic Priority */ SortPackInfo(Adapter); /* Re Sort the Classifier Rules table and re - arrange - according to Classifier Rule Priority */ + * according to Classifier Rule Priority + */ SortClassifiers(Adapter); - DumpPhsRules(&Adapter->stBCMPhsContext); - - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"%s <=====", __FUNCTION__); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "%s <=====", __FUNCTION__); } - /*********************************************************************** -* Function - DumpCmControlPacket -* -* Description - This routinue Dumps the Contents of the AddIndication -* Structure in the Connection Management Control Packet -* -* Parameter - pvBuffer: Pointer to the buffer containing the -* AddIndication data. -* -* Returns - None -*************************************************************************/ + * Function - DumpCmControlPacket + * + * Description - This routinue Dumps the Contents of the AddIndication + * Structure in the Connection Management Control Packet + * + * Parameter - pvBuffer: Pointer to the buffer containing the + * AddIndication data. + * + * Returns - None + *************************************************************************/ static VOID DumpCmControlPacket(PVOID pvBuffer) { - UINT uiLoopIndex; - UINT nIndex; - stLocalSFAddIndicationAlt *pstAddIndication; - UINT nCurClassifierCnt; - PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + UINT uiLoopIndex; + UINT nIndex; + stLocalSFAddIndicationAlt *pstAddIndication; + UINT nCurClassifierCnt; + PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); pstAddIndication = (stLocalSFAddIndicationAlt *)pvBuffer; - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "======>"); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8Type : 0x%X",pstAddIndication->u8Type); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8Direction : 0x%X",pstAddIndication->u8Direction); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16TID: 0x%X", ntohs(pstAddIndication->u16TID)); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16CID : 0x%X",ntohs(pstAddIndication->u16CID)); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16VCID : 0x%X",ntohs(pstAddIndication->u16VCID)); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " AuthorizedSet--->"); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32SFID : 0x%X",htonl(pstAddIndication->sfAuthorizedSet.u32SFID)); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16CID : 0x%X",htons(pstAddIndication->sfAuthorizedSet.u16CID)); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ServiceClassNameLength : 0x%X", - pstAddIndication->sfAuthorizedSet.u8ServiceClassNameLength); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ServiceClassName : 0x%X ,0x%X , 0x%X, 0x%X, 0x%X, 0x%X", + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "======>"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8Type: 0x%X", pstAddIndication->u8Type); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8Direction: 0x%X", pstAddIndication->u8Direction); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16TID: 0x%X", ntohs(pstAddIndication->u16TID)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16CID: 0x%X", ntohs(pstAddIndication->u16CID)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16VCID: 0x%X", ntohs(pstAddIndication->u16VCID)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " AuthorizedSet--->"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32SFID: 0x%X", htonl(pstAddIndication->sfAuthorizedSet.u32SFID)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16CID: 0x%X", htons(pstAddIndication->sfAuthorizedSet.u16CID)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ServiceClassNameLength: 0x%X", + pstAddIndication->sfAuthorizedSet.u8ServiceClassNameLength); + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ServiceClassName: 0x%X ,0x%X , 0x%X, 0x%X, 0x%X, 0x%X", pstAddIndication->sfAuthorizedSet.u8ServiceClassName[0], pstAddIndication->sfAuthorizedSet.u8ServiceClassName[1], pstAddIndication->sfAuthorizedSet.u8ServiceClassName[2], @@ -1033,207 +859,170 @@ static VOID DumpCmControlPacket(PVOID pvBuffer) pstAddIndication->sfAuthorizedSet.u8ServiceClassName[4], pstAddIndication->sfAuthorizedSet.u8ServiceClassName[5]); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8MBSService : 0x%X", - pstAddIndication->sfAuthorizedSet.u8MBSService); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8QosParamSet : 0x%X", - pstAddIndication->sfAuthorizedSet.u8QosParamSet); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8TrafficPriority : 0x%X, %p", - pstAddIndication->sfAuthorizedSet.u8TrafficPriority, &pstAddIndication->sfAuthorizedSet.u8TrafficPriority); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32MaxSustainedTrafficRate : 0x%X 0x%p", - pstAddIndication->sfAuthorizedSet.u32MaxSustainedTrafficRate, + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8MBSService: 0x%X", pstAddIndication->sfAuthorizedSet.u8MBSService); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8QosParamSet: 0x%X", pstAddIndication->sfAuthorizedSet.u8QosParamSet); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8TrafficPriority: 0x%X, %p", + pstAddIndication->sfAuthorizedSet.u8TrafficPriority, &pstAddIndication->sfAuthorizedSet.u8TrafficPriority); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32MaxSustainedTrafficRate: 0x%X 0x%p", + pstAddIndication->sfAuthorizedSet.u32MaxSustainedTrafficRate, &pstAddIndication->sfAuthorizedSet.u32MaxSustainedTrafficRate); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32MaxTrafficBurst : 0x%X", - pstAddIndication->sfAuthorizedSet.u32MaxTrafficBurst); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32MinReservedTrafficRate : 0x%X", - pstAddIndication->sfAuthorizedSet.u32MinReservedTrafficRate); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8VendorSpecificQoSParamLength : 0x%X", - pstAddIndication->sfAuthorizedSet.u8VendorSpecificQoSParamLength); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8VendorSpecificQoSParam : 0x%X", - pstAddIndication->sfAuthorizedSet.u8VendorSpecificQoSParam[0]); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ServiceFlowSchedulingType : 0x%X", - pstAddIndication->sfAuthorizedSet.u8ServiceFlowSchedulingType); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32ToleratedJitter : 0x%X", - pstAddIndication->sfAuthorizedSet.u32ToleratedJitter); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32MaximumLatency : 0x%X", - pstAddIndication->sfAuthorizedSet.u32MaximumLatency); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8FixedLengthVSVariableLengthSDUIndicator: 0x%X", - pstAddIndication->sfAuthorizedSet.u8FixedLengthVSVariableLengthSDUIndicator); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8SDUSize : 0x%X", - pstAddIndication->sfAuthorizedSet.u8SDUSize); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16TargetSAID : 0x%X", - pstAddIndication->sfAuthorizedSet.u16TargetSAID); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ARQEnable : 0x%X", - pstAddIndication->sfAuthorizedSet.u8ARQEnable); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQWindowSize : 0x%X", - pstAddIndication->sfAuthorizedSet.u16ARQWindowSize); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQRetryTxTimeOut : 0x%X", - pstAddIndication->sfAuthorizedSet.u16ARQRetryTxTimeOut); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQRetryRxTimeOut : 0x%X", - pstAddIndication->sfAuthorizedSet.u16ARQRetryRxTimeOut); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQBlockLifeTime : 0x%X", - pstAddIndication->sfAuthorizedSet.u16ARQBlockLifeTime); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQSyncLossTimeOut : 0x%X", - pstAddIndication->sfAuthorizedSet.u16ARQSyncLossTimeOut); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ARQDeliverInOrder : 0x%X", - pstAddIndication->sfAuthorizedSet.u8ARQDeliverInOrder); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQRxPurgeTimeOut : 0x%X", - pstAddIndication->sfAuthorizedSet.u16ARQRxPurgeTimeOut); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQBlockSize : 0x%X", - pstAddIndication->sfAuthorizedSet.u16ARQBlockSize); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8CSSpecification : 0x%X", - pstAddIndication->sfAuthorizedSet.u8CSSpecification); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8TypeOfDataDeliveryService : 0x%X", - pstAddIndication->sfAuthorizedSet.u8TypeOfDataDeliveryService); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16SDUInterArrivalTime : 0x%X", - pstAddIndication->sfAuthorizedSet.u16SDUInterArrivalTime); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16TimeBase : 0x%X", - pstAddIndication->sfAuthorizedSet.u16TimeBase); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8PagingPreference : 0x%X", - pstAddIndication->sfAuthorizedSet.u8PagingPreference); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16UnsolicitedPollingInterval : 0x%X", - pstAddIndication->sfAuthorizedSet.u16UnsolicitedPollingInterval); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "sfAuthorizedSet.u8HARQChannelMapping %x %x %x ", - *(unsigned int*)pstAddIndication->sfAuthorizedSet.u8HARQChannelMapping, - *(unsigned int*)&pstAddIndication->sfAuthorizedSet.u8HARQChannelMapping[4], - *(USHORT*) &pstAddIndication->sfAuthorizedSet.u8HARQChannelMapping[8]); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8TrafficIndicationPreference : 0x%X", - pstAddIndication->sfAuthorizedSet.u8TrafficIndicationPreference); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " Total Classifiers Received : 0x%X",pstAddIndication->sfAuthorizedSet.u8TotalClassifiers); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32MaxTrafficBurst: 0x%X", pstAddIndication->sfAuthorizedSet.u32MaxTrafficBurst); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32MinReservedTrafficRate : 0x%X", + pstAddIndication->sfAuthorizedSet.u32MinReservedTrafficRate); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8VendorSpecificQoSParamLength: 0x%X", + pstAddIndication->sfAuthorizedSet.u8VendorSpecificQoSParamLength); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8VendorSpecificQoSParam: 0x%X", + pstAddIndication->sfAuthorizedSet.u8VendorSpecificQoSParam[0]); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ServiceFlowSchedulingType: 0x%X", + pstAddIndication->sfAuthorizedSet.u8ServiceFlowSchedulingType); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32ToleratedJitter: 0x%X", pstAddIndication->sfAuthorizedSet.u32ToleratedJitter); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32MaximumLatency: 0x%X", pstAddIndication->sfAuthorizedSet.u32MaximumLatency); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8FixedLengthVSVariableLengthSDUIndicator: 0x%X", + pstAddIndication->sfAuthorizedSet.u8FixedLengthVSVariableLengthSDUIndicator); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8SDUSize: 0x%X", pstAddIndication->sfAuthorizedSet.u8SDUSize); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16TargetSAID: 0x%X", pstAddIndication->sfAuthorizedSet.u16TargetSAID); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ARQEnable: 0x%X", pstAddIndication->sfAuthorizedSet.u8ARQEnable); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQWindowSize: 0x%X", pstAddIndication->sfAuthorizedSet.u16ARQWindowSize); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQRetryTxTimeOut: 0x%X", pstAddIndication->sfAuthorizedSet.u16ARQRetryTxTimeOut); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQRetryRxTimeOut: 0x%X", pstAddIndication->sfAuthorizedSet.u16ARQRetryRxTimeOut); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQBlockLifeTime: 0x%X", pstAddIndication->sfAuthorizedSet.u16ARQBlockLifeTime); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQSyncLossTimeOut: 0x%X", pstAddIndication->sfAuthorizedSet.u16ARQSyncLossTimeOut); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ARQDeliverInOrder: 0x%X", pstAddIndication->sfAuthorizedSet.u8ARQDeliverInOrder); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQRxPurgeTimeOut: 0x%X", pstAddIndication->sfAuthorizedSet.u16ARQRxPurgeTimeOut); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQBlockSize: 0x%X", pstAddIndication->sfAuthorizedSet.u16ARQBlockSize); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8CSSpecification: 0x%X", pstAddIndication->sfAuthorizedSet.u8CSSpecification); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8TypeOfDataDeliveryService: 0x%X", + pstAddIndication->sfAuthorizedSet.u8TypeOfDataDeliveryService); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16SDUInterArrivalTime: 0x%X", pstAddIndication->sfAuthorizedSet.u16SDUInterArrivalTime); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16TimeBase: 0x%X", pstAddIndication->sfAuthorizedSet.u16TimeBase); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8PagingPreference: 0x%X", pstAddIndication->sfAuthorizedSet.u8PagingPreference); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16UnsolicitedPollingInterval: 0x%X", + pstAddIndication->sfAuthorizedSet.u16UnsolicitedPollingInterval); + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "sfAuthorizedSet.u8HARQChannelMapping %x %x %x ", + *(unsigned int *)pstAddIndication->sfAuthorizedSet.u8HARQChannelMapping, + *(unsigned int *)&pstAddIndication->sfAuthorizedSet.u8HARQChannelMapping[4], + *(USHORT *)&pstAddIndication->sfAuthorizedSet.u8HARQChannelMapping[8]); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8TrafficIndicationPreference: 0x%X", + pstAddIndication->sfAuthorizedSet.u8TrafficIndicationPreference); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " Total Classifiers Received: 0x%X", pstAddIndication->sfAuthorizedSet.u8TotalClassifiers); nCurClassifierCnt = pstAddIndication->sfAuthorizedSet.u8TotalClassifiers; - - if(nCurClassifierCnt > MAX_CLASSIFIERS_IN_SF) - { + if (nCurClassifierCnt > MAX_CLASSIFIERS_IN_SF) nCurClassifierCnt = MAX_CLASSIFIERS_IN_SF; - } - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "pstAddIndication->sfAuthorizedSet.bValid %d", pstAddIndication->sfAuthorizedSet.bValid); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "pstAddIndication->sfAuthorizedSet.u16MacOverhead %x", pstAddIndication->sfAuthorizedSet.u16MacOverhead); - if(!pstAddIndication->sfAuthorizedSet.bValid) - pstAddIndication->sfAuthorizedSet.bValid=1; - for(nIndex = 0 ; nIndex < nCurClassifierCnt ; nIndex++) - { + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "pstAddIndication->sfAuthorizedSet.bValid %d", pstAddIndication->sfAuthorizedSet.bValid); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "pstAddIndication->sfAuthorizedSet.u16MacOverhead %x", pstAddIndication->sfAuthorizedSet.u16MacOverhead); + if (!pstAddIndication->sfAuthorizedSet.bValid) + pstAddIndication->sfAuthorizedSet.bValid = 1; + for (nIndex = 0; nIndex < nCurClassifierCnt; nIndex++) { stConvergenceSLTypes *psfCSType = NULL; psfCSType = &pstAddIndication->sfAuthorizedSet.cConvergenceSLTypes[nIndex]; - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "psfCSType = %p", psfCSType); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "CCPacketClassificationRuleSI====>"); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ClassifierRulePriority :0x%X ", - psfCSType->cCPacketClassificationRule.u8ClassifierRulePriority); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPTypeOfServiceLength :0x%X ", - psfCSType->cCPacketClassificationRule.u8IPTypeOfServiceLength); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPTypeOfService[3] :0x%X ,0x%X ,0x%X ", - psfCSType->cCPacketClassificationRule.u8IPTypeOfService[0], - psfCSType->cCPacketClassificationRule.u8IPTypeOfService[1], - psfCSType->cCPacketClassificationRule.u8IPTypeOfService[2]); - - for(uiLoopIndex=0; uiLoopIndex < 1; uiLoopIndex++) - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8Protocol : 0x%02X ", - psfCSType->cCPacketClassificationRule.u8Protocol); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPMaskedSourceAddressLength :0x%X ", - psfCSType->cCPacketClassificationRule.u8IPMaskedSourceAddressLength); - - for(uiLoopIndex=0; uiLoopIndex < 32; uiLoopIndex++) - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPMaskedSourceAddress[32] : 0x%02X ", - psfCSType->cCPacketClassificationRule.u8IPMaskedSourceAddress[uiLoopIndex]); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPDestinationAddressLength : 0x%X ", - psfCSType->cCPacketClassificationRule.u8IPDestinationAddressLength); - - for(uiLoopIndex=0; uiLoopIndex < 32; uiLoopIndex++) - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPDestinationAddress[32] : 0x%02X ", - psfCSType->cCPacketClassificationRule.u8IPDestinationAddress[uiLoopIndex]); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ProtocolSourcePortRangeLength:0x%X ", - psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRangeLength); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ProtocolSourcePortRange[4]: 0x%02X ,0x%02X ,0x%02X ,0x%02X ", - psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRange[0], - psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRange[1], - psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRange[2], - psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRange[3]); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ProtocolDestPortRangeLength : 0x%02X ", - psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRangeLength); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ProtocolDestPortRange[4]: 0x%02X ,0x%02X ,0x%02X ,0x%02X ", - psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange[0], - psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange[1], - psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange[2], - psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange[3]); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthernetDestMacAddressLength : 0x%02X ", - psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddressLength); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthernetDestMacAddress[6] : 0x %02X %02X %02X %02X %02X %02X", - psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[0], - psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[1], - psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[2], - psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[3], - psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[4], - psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[5]); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthernetSourceMACAddressLength : 0x%02X ", - psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddressLength); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthernetSourceMACAddress[6] : 0x %02X %02X %02X %02X %02X %02X", - psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[0], - psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[1], - psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[2], - psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[3], - psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[4], - psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[5]); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthertypeLength : 0x%02X ", - psfCSType->cCPacketClassificationRule.u8EthertypeLength); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8Ethertype[3] : 0x%02X ,0x%02X ,0x%02X ", - psfCSType->cCPacketClassificationRule.u8Ethertype[0], - psfCSType->cCPacketClassificationRule.u8Ethertype[1], - psfCSType->cCPacketClassificationRule.u8Ethertype[2]); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16UserPriority : 0x%X ", - psfCSType->cCPacketClassificationRule.u16UserPriority); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16VLANID : 0x%X ", - psfCSType->cCPacketClassificationRule.u16VLANID); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8AssociatedPHSI : 0x%02X ", - psfCSType->cCPacketClassificationRule.u8AssociatedPHSI); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16PacketClassificationRuleIndex : 0x%X ", - psfCSType->cCPacketClassificationRule.u16PacketClassificationRuleIndex); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8VendorSpecificClassifierParamLength : 0x%X ", - psfCSType->cCPacketClassificationRule.u8VendorSpecificClassifierParamLength); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8VendorSpecificClassifierParam[1] : 0x%X ", - psfCSType->cCPacketClassificationRule.u8VendorSpecificClassifierParam[0]); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "psfCSType = %p", psfCSType); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "CCPacketClassificationRuleSI====>"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ClassifierRulePriority: 0x%X ", + psfCSType->cCPacketClassificationRule.u8ClassifierRulePriority); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPTypeOfServiceLength: 0x%X ", + psfCSType->cCPacketClassificationRule.u8IPTypeOfServiceLength); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPTypeOfService[3]: 0x%X ,0x%X ,0x%X ", + psfCSType->cCPacketClassificationRule.u8IPTypeOfService[0], + psfCSType->cCPacketClassificationRule.u8IPTypeOfService[1], + psfCSType->cCPacketClassificationRule.u8IPTypeOfService[2]); + + for (uiLoopIndex = 0; uiLoopIndex < 1; uiLoopIndex++) + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8Protocol: 0x%02X ", + psfCSType->cCPacketClassificationRule.u8Protocol); + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPMaskedSourceAddressLength: 0x%X ", + psfCSType->cCPacketClassificationRule.u8IPMaskedSourceAddressLength); + + for (uiLoopIndex = 0; uiLoopIndex < 32; uiLoopIndex++) + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPMaskedSourceAddress[32]: 0x%02X ", + psfCSType->cCPacketClassificationRule.u8IPMaskedSourceAddress[uiLoopIndex]); + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPDestinationAddressLength: 0x%X ", + psfCSType->cCPacketClassificationRule.u8IPDestinationAddressLength); + + for (uiLoopIndex = 0; uiLoopIndex < 32; uiLoopIndex++) + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPDestinationAddress[32]: 0x%02X ", + psfCSType->cCPacketClassificationRule.u8IPDestinationAddress[uiLoopIndex]); + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ProtocolSourcePortRangeLength:0x%X ", + psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRangeLength); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ProtocolSourcePortRange[4]: 0x%02X ,0x%02X ,0x%02X ,0x%02X ", + psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRange[0], + psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRange[1], + psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRange[2], + psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRange[3]); + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ProtocolDestPortRangeLength: 0x%02X ", + psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRangeLength); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ProtocolDestPortRange[4]: 0x%02X ,0x%02X ,0x%02X ,0x%02X ", + psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange[0], + psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange[1], + psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange[2], + psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange[3]); + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthernetDestMacAddressLength: 0x%02X ", + psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddressLength); + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthernetDestMacAddress[6]: 0x %02X %02X %02X %02X %02X %02X", + psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[0], + psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[1], + psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[2], + psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[3], + psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[4], + psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[5]); + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthernetSourceMACAddressLength: 0x%02X ", + psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddressLength); + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthernetSourceMACAddress[6]: 0x %02X %02X %02X %02X %02X %02X", + psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[0], + psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[1], + psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[2], + psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[3], + psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[4], + psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[5]); + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthertypeLength: 0x%02X ", + psfCSType->cCPacketClassificationRule.u8EthertypeLength); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8Ethertype[3]: 0x%02X ,0x%02X ,0x%02X ", + psfCSType->cCPacketClassificationRule.u8Ethertype[0], + psfCSType->cCPacketClassificationRule.u8Ethertype[1], + psfCSType->cCPacketClassificationRule.u8Ethertype[2]); + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16UserPriority: 0x%X ", psfCSType->cCPacketClassificationRule.u16UserPriority); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16VLANID: 0x%X ", psfCSType->cCPacketClassificationRule.u16VLANID); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8AssociatedPHSI: 0x%02X ", psfCSType->cCPacketClassificationRule.u8AssociatedPHSI); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16PacketClassificationRuleIndex: 0x%X ", + psfCSType->cCPacketClassificationRule.u16PacketClassificationRuleIndex); + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8VendorSpecificClassifierParamLength: 0x%X ", + psfCSType->cCPacketClassificationRule.u8VendorSpecificClassifierParamLength); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8VendorSpecificClassifierParam[1]: 0x%X ", + psfCSType->cCPacketClassificationRule.u8VendorSpecificClassifierParam[0]); #ifdef VERSION_D5 - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPv6FlowLableLength :0x%X ", - psfCSType->cCPacketClassificationRule.u8IPv6FlowLableLength); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPv6FlowLable[6] : 0x %02X %02X %02X %02X %02X %02X ", - psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[0], - psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[1], - psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[2], - psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[3], - psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[4], - psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[5]); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPv6FlowLableLength: 0x%X ", + psfCSType->cCPacketClassificationRule.u8IPv6FlowLableLength); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPv6FlowLable[6]: 0x %02X %02X %02X %02X %02X %02X ", + psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[0], + psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[1], + psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[2], + psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[3], + psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[4], + psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[5]); #endif } - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "bValid : 0x%02X",pstAddIndication->sfAuthorizedSet.bValid); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "AdmittedSet--->"); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32SFID : 0x%X",pstAddIndication->sfAdmittedSet.u32SFID); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16CID : 0x%X",pstAddIndication->sfAdmittedSet.u16CID); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ServiceClassNameLength : 0x%X", - pstAddIndication->sfAdmittedSet.u8ServiceClassNameLength); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ServiceClassName : 0x %02X %02X %02X %02X %02X %02X", + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "bValid: 0x%02X", pstAddIndication->sfAuthorizedSet.bValid); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "AdmittedSet--->"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32SFID: 0x%X", pstAddIndication->sfAdmittedSet.u32SFID); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16CID: 0x%X", pstAddIndication->sfAdmittedSet.u16CID); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ServiceClassNameLength: 0x%X", + pstAddIndication->sfAdmittedSet.u8ServiceClassNameLength); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ServiceClassName: 0x %02X %02X %02X %02X %02X %02X", pstAddIndication->sfAdmittedSet.u8ServiceClassName[0], pstAddIndication->sfAdmittedSet.u8ServiceClassName[1], pstAddIndication->sfAdmittedSet.u8ServiceClassName[2], @@ -1241,429 +1030,338 @@ static VOID DumpCmControlPacket(PVOID pvBuffer) pstAddIndication->sfAdmittedSet.u8ServiceClassName[4], pstAddIndication->sfAdmittedSet.u8ServiceClassName[5]); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8MBSService : 0x%02X", - pstAddIndication->sfAdmittedSet.u8MBSService); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8QosParamSet : 0x%02X", - pstAddIndication->sfAdmittedSet.u8QosParamSet); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8TrafficPriority : 0x%02X", - pstAddIndication->sfAdmittedSet.u8TrafficPriority); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32MaxTrafficBurst : 0x%X", - pstAddIndication->sfAdmittedSet.u32MaxTrafficBurst); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32MinReservedTrafficRate : 0x%X", - pstAddIndication->sfAdmittedSet.u32MinReservedTrafficRate); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8VendorSpecificQoSParamLength : 0x%02X", - pstAddIndication->sfAdmittedSet.u8VendorSpecificQoSParamLength); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8VendorSpecificQoSParam : 0x%02X", - pstAddIndication->sfAdmittedSet.u8VendorSpecificQoSParam[0]); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ServiceFlowSchedulingType : 0x%02X", - pstAddIndication->sfAdmittedSet.u8ServiceFlowSchedulingType); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32ToleratedJitter : 0x%X", - pstAddIndication->sfAdmittedSet.u32ToleratedJitter); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32MaximumLatency : 0x%X", - pstAddIndication->sfAdmittedSet.u32MaximumLatency); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8FixedLengthVSVariableLengthSDUIndicator: 0x%02X", - pstAddIndication->sfAdmittedSet.u8FixedLengthVSVariableLengthSDUIndicator); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8SDUSize : 0x%02X", - pstAddIndication->sfAdmittedSet.u8SDUSize); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16TargetSAID : 0x%02X", - pstAddIndication->sfAdmittedSet.u16TargetSAID); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ARQEnable : 0x%02X", - pstAddIndication->sfAdmittedSet.u8ARQEnable); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQWindowSize : 0x%X", - pstAddIndication->sfAdmittedSet.u16ARQWindowSize); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQRetryTxTimeOut : 0x%X", - pstAddIndication->sfAdmittedSet.u16ARQRetryTxTimeOut); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQRetryRxTimeOut : 0x%X", - pstAddIndication->sfAdmittedSet.u16ARQRetryRxTimeOut); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQBlockLifeTime : 0x%X", - pstAddIndication->sfAdmittedSet.u16ARQBlockLifeTime); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQSyncLossTimeOut : 0x%X", - pstAddIndication->sfAdmittedSet.u16ARQSyncLossTimeOut); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ARQDeliverInOrder : 0x%02X", - pstAddIndication->sfAdmittedSet.u8ARQDeliverInOrder); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQRxPurgeTimeOut : 0x%X", - pstAddIndication->sfAdmittedSet.u16ARQRxPurgeTimeOut); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQBlockSize : 0x%X", - pstAddIndication->sfAdmittedSet.u16ARQBlockSize); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8CSSpecification : 0x%02X", - pstAddIndication->sfAdmittedSet.u8CSSpecification); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8TypeOfDataDeliveryService : 0x%02X", - pstAddIndication->sfAdmittedSet.u8TypeOfDataDeliveryService); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16SDUInterArrivalTime : 0x%X", - pstAddIndication->sfAdmittedSet.u16SDUInterArrivalTime); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16TimeBase : 0x%X", - pstAddIndication->sfAdmittedSet.u16TimeBase); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8PagingPreference : 0x%X", - pstAddIndication->sfAdmittedSet.u8PagingPreference); - - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8TrafficIndicationPreference : 0x%02X", - pstAddIndication->sfAdmittedSet.u8TrafficIndicationPreference); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " Total Classifiers Received : 0x%X",pstAddIndication->sfAdmittedSet.u8TotalClassifiers); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8MBSService: 0x%02X", pstAddIndication->sfAdmittedSet.u8MBSService); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8QosParamSet: 0x%02X", pstAddIndication->sfAdmittedSet.u8QosParamSet); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8TrafficPriority: 0x%02X", pstAddIndication->sfAdmittedSet.u8TrafficPriority); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32MaxTrafficBurst: 0x%X", pstAddIndication->sfAdmittedSet.u32MaxTrafficBurst); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32MinReservedTrafficRate: 0x%X", + pstAddIndication->sfAdmittedSet.u32MinReservedTrafficRate); + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8VendorSpecificQoSParamLength: 0x%02X", + pstAddIndication->sfAdmittedSet.u8VendorSpecificQoSParamLength); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8VendorSpecificQoSParam: 0x%02X", + pstAddIndication->sfAdmittedSet.u8VendorSpecificQoSParam[0]); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ServiceFlowSchedulingType: 0x%02X", + pstAddIndication->sfAdmittedSet.u8ServiceFlowSchedulingType); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32ToleratedJitter: 0x%X", pstAddIndication->sfAdmittedSet.u32ToleratedJitter); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32MaximumLatency: 0x%X", pstAddIndication->sfAdmittedSet.u32MaximumLatency); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8FixedLengthVSVariableLengthSDUIndicator: 0x%02X", + pstAddIndication->sfAdmittedSet.u8FixedLengthVSVariableLengthSDUIndicator); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8SDUSize: 0x%02X", pstAddIndication->sfAdmittedSet.u8SDUSize); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16TargetSAID: 0x%02X", pstAddIndication->sfAdmittedSet.u16TargetSAID); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ARQEnable: 0x%02X", pstAddIndication->sfAdmittedSet.u8ARQEnable); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQWindowSize: 0x%X", pstAddIndication->sfAdmittedSet.u16ARQWindowSize); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQRetryTxTimeOut: 0x%X", pstAddIndication->sfAdmittedSet.u16ARQRetryTxTimeOut); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQRetryRxTimeOut: 0x%X", pstAddIndication->sfAdmittedSet.u16ARQRetryRxTimeOut); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQBlockLifeTime: 0x%X", pstAddIndication->sfAdmittedSet.u16ARQBlockLifeTime); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQSyncLossTimeOut: 0x%X", pstAddIndication->sfAdmittedSet.u16ARQSyncLossTimeOut); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ARQDeliverInOrder: 0x%02X", pstAddIndication->sfAdmittedSet.u8ARQDeliverInOrder); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQRxPurgeTimeOut: 0x%X", pstAddIndication->sfAdmittedSet.u16ARQRxPurgeTimeOut); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQBlockSize: 0x%X", pstAddIndication->sfAdmittedSet.u16ARQBlockSize); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8CSSpecification: 0x%02X", pstAddIndication->sfAdmittedSet.u8CSSpecification); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8TypeOfDataDeliveryService: 0x%02X", + pstAddIndication->sfAdmittedSet.u8TypeOfDataDeliveryService); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16SDUInterArrivalTime: 0x%X", pstAddIndication->sfAdmittedSet.u16SDUInterArrivalTime); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16TimeBase: 0x%X", pstAddIndication->sfAdmittedSet.u16TimeBase); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8PagingPreference: 0x%X", pstAddIndication->sfAdmittedSet.u8PagingPreference); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8TrafficIndicationPreference: 0x%02X", + pstAddIndication->sfAdmittedSet.u8TrafficIndicationPreference); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " Total Classifiers Received: 0x%X", pstAddIndication->sfAdmittedSet.u8TotalClassifiers); nCurClassifierCnt = pstAddIndication->sfAdmittedSet.u8TotalClassifiers; - - if(nCurClassifierCnt > MAX_CLASSIFIERS_IN_SF) - { + if (nCurClassifierCnt > MAX_CLASSIFIERS_IN_SF) nCurClassifierCnt = MAX_CLASSIFIERS_IN_SF; - } - - - for(nIndex = 0 ; nIndex < nCurClassifierCnt ; nIndex++) - { + for (nIndex = 0; nIndex < nCurClassifierCnt; nIndex++) { stConvergenceSLTypes *psfCSType = NULL; - psfCSType = &pstAddIndication->sfAdmittedSet.cConvergenceSLTypes[nIndex]; - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " CCPacketClassificationRuleSI====>"); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ClassifierRulePriority :0x%02X ", - psfCSType->cCPacketClassificationRule.u8ClassifierRulePriority); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPTypeOfServiceLength :0x%02X", - psfCSType->cCPacketClassificationRule.u8IPTypeOfServiceLength); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPTypeOfService[3] :0x%02X %02X %02X", - psfCSType->cCPacketClassificationRule.u8IPTypeOfService[0], - psfCSType->cCPacketClassificationRule.u8IPTypeOfService[1], - psfCSType->cCPacketClassificationRule.u8IPTypeOfService[2]); - for(uiLoopIndex=0; uiLoopIndex < 1; uiLoopIndex++) - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8Protocol: 0x%02X ", - psfCSType->cCPacketClassificationRule.u8Protocol); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPMaskedSourceAddressLength :0x%02X ", - psfCSType->cCPacketClassificationRule.u8IPMaskedSourceAddressLength); - - for(uiLoopIndex=0; uiLoopIndex < 32; uiLoopIndex++) - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPMaskedSourceAddress[32] : 0x%02X ", - psfCSType->cCPacketClassificationRule.u8IPMaskedSourceAddress[uiLoopIndex]); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPDestinationAddressLength : 0x%02X ", - psfCSType->cCPacketClassificationRule.u8IPDestinationAddressLength); - - for(uiLoopIndex=0; uiLoopIndex < 32; uiLoopIndex++) - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPDestinationAddress[32] : 0x%02X ", - psfCSType->cCPacketClassificationRule.u8IPDestinationAddress[uiLoopIndex]); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ProtocolSourcePortRangeLength : 0x%02X ", - psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRangeLength); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ProtocolSourcePortRange[4] : 0x %02X %02X %02X %02X ", - psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRange[0], - psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRange[1], - psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRange[2], - psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRange[3]); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ProtocolDestPortRangeLength : 0x%02X ", - psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRangeLength); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ProtocolDestPortRange[4] : 0x %02X %02X %02X %02X ", - psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange[0], - psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange[1], - psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange[2], - psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange[3]); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthernetDestMacAddressLength : 0x%02X ", - psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddressLength); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthernetDestMacAddress[6] : 0x %02X %02X %02X %02X %02X %02X", - psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[0], - psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[1], - psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[2], - psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[3], - psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[4], - psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[5]); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthernetSourceMACAddressLength : 0x%02X ", - psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddressLength); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthernetSourceMACAddress[6] : 0x %02X %02X %02X %02X %02X %02X", - psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[0], - psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[1], - psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[2], - psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[3], - psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[4], - psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[5]); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthertypeLength : 0x%02X ", - psfCSType->cCPacketClassificationRule.u8EthertypeLength); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8Ethertype[3] : 0x%02X %02X %02X", - psfCSType->cCPacketClassificationRule.u8Ethertype[0], - psfCSType->cCPacketClassificationRule.u8Ethertype[1], - psfCSType->cCPacketClassificationRule.u8Ethertype[2]); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16UserPriority : 0x%X ", - psfCSType->cCPacketClassificationRule.u16UserPriority); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16VLANID : 0x%X ", - psfCSType->cCPacketClassificationRule.u16VLANID); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8AssociatedPHSI : 0x%02X ", - psfCSType->cCPacketClassificationRule.u8AssociatedPHSI); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16PacketClassificationRuleIndex : 0x%X ", - psfCSType->cCPacketClassificationRule.u16PacketClassificationRuleIndex); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8VendorSpecificClassifierParamLength : 0x%02X", - psfCSType->cCPacketClassificationRule.u8VendorSpecificClassifierParamLength); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8VendorSpecificClassifierParam[1] : 0x%02X ", - psfCSType->cCPacketClassificationRule.u8VendorSpecificClassifierParam[0]); + psfCSType = &pstAddIndication->sfAdmittedSet.cConvergenceSLTypes[nIndex]; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " CCPacketClassificationRuleSI====>"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ClassifierRulePriority: 0x%02X ", + psfCSType->cCPacketClassificationRule.u8ClassifierRulePriority); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPTypeOfServiceLength: 0x%02X", + psfCSType->cCPacketClassificationRule.u8IPTypeOfServiceLength); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPTypeOfService[3]: 0x%02X %02X %02X", + psfCSType->cCPacketClassificationRule.u8IPTypeOfService[0], + psfCSType->cCPacketClassificationRule.u8IPTypeOfService[1], + psfCSType->cCPacketClassificationRule.u8IPTypeOfService[2]); + for (uiLoopIndex = 0; uiLoopIndex < 1; uiLoopIndex++) + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8Protocol: 0x%02X ", psfCSType->cCPacketClassificationRule.u8Protocol); + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPMaskedSourceAddressLength: 0x%02X ", + psfCSType->cCPacketClassificationRule.u8IPMaskedSourceAddressLength); + + for (uiLoopIndex = 0; uiLoopIndex < 32; uiLoopIndex++) + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPMaskedSourceAddress[32]: 0x%02X ", + psfCSType->cCPacketClassificationRule.u8IPMaskedSourceAddress[uiLoopIndex]); + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPDestinationAddressLength: 0x%02X ", + psfCSType->cCPacketClassificationRule.u8IPDestinationAddressLength); + + for (uiLoopIndex = 0; uiLoopIndex < 32; uiLoopIndex++) + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPDestinationAddress[32]: 0x%02X ", + psfCSType->cCPacketClassificationRule.u8IPDestinationAddress[uiLoopIndex]); + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ProtocolSourcePortRangeLength: 0x%02X ", + psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRangeLength); + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ProtocolSourcePortRange[4]: 0x %02X %02X %02X %02X ", + psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRange[0], + psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRange[1], + psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRange[2], + psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRange[3]); + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ProtocolDestPortRangeLength: 0x%02X ", + psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRangeLength); + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ProtocolDestPortRange[4]: 0x %02X %02X %02X %02X ", + psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange[0], + psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange[1], + psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange[2], + psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange[3]); + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthernetDestMacAddressLength: 0x%02X ", + psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddressLength); + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthernetDestMacAddress[6]: 0x %02X %02X %02X %02X %02X %02X", + psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[0], + psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[1], + psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[2], + psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[3], + psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[4], + psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[5]); + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthernetSourceMACAddressLength: 0x%02X ", + psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddressLength); + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthernetSourceMACAddress[6]: 0x %02X %02X %02X %02X %02X %02X", + psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[0], + psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[1], + psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[2], + psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[3], + psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[4], + psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[5]); + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthertypeLength: 0x%02X ", psfCSType->cCPacketClassificationRule.u8EthertypeLength); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8Ethertype[3]: 0x%02X %02X %02X", + psfCSType->cCPacketClassificationRule.u8Ethertype[0], + psfCSType->cCPacketClassificationRule.u8Ethertype[1], + psfCSType->cCPacketClassificationRule.u8Ethertype[2]); + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16UserPriority: 0x%X ", psfCSType->cCPacketClassificationRule.u16UserPriority); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16VLANID: 0x%X ", psfCSType->cCPacketClassificationRule.u16VLANID); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8AssociatedPHSI: 0x%02X ", psfCSType->cCPacketClassificationRule.u8AssociatedPHSI); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16PacketClassificationRuleIndex: 0x%X ", + psfCSType->cCPacketClassificationRule.u16PacketClassificationRuleIndex); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8VendorSpecificClassifierParamLength: 0x%02X", + psfCSType->cCPacketClassificationRule.u8VendorSpecificClassifierParamLength); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8VendorSpecificClassifierParam[1]: 0x%02X ", + psfCSType->cCPacketClassificationRule.u8VendorSpecificClassifierParam[0]); #ifdef VERSION_D5 - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPv6FlowLableLength : 0x%X ", - psfCSType->cCPacketClassificationRule.u8IPv6FlowLableLength); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPv6FlowLable[6] : 0x %02X %02X %02X %02X %02X %02X ", - psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[0], - psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[1], - psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[2], - psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[3], - psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[4], - psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[5]); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPv6FlowLableLength: 0x%X ", + psfCSType->cCPacketClassificationRule.u8IPv6FlowLableLength); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPv6FlowLable[6]: 0x %02X %02X %02X %02X %02X %02X ", + psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[0], + psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[1], + psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[2], + psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[3], + psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[4], + psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[5]); #endif } - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "bValid : 0x%X",pstAddIndication->sfAdmittedSet.bValid); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " ActiveSet--->"); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32SFID : 0x%X",pstAddIndication->sfActiveSet.u32SFID); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16CID : 0x%X",pstAddIndication->sfActiveSet.u16CID); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ServiceClassNameLength : 0x%X", - pstAddIndication->sfActiveSet.u8ServiceClassNameLength); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ServiceClassName : 0x %02X %02X %02X %02X %02X %02X", - pstAddIndication->sfActiveSet.u8ServiceClassName[0], - pstAddIndication->sfActiveSet.u8ServiceClassName[1], - pstAddIndication->sfActiveSet.u8ServiceClassName[2], - pstAddIndication->sfActiveSet.u8ServiceClassName[3], - pstAddIndication->sfActiveSet.u8ServiceClassName[4], - pstAddIndication->sfActiveSet.u8ServiceClassName[5]); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8MBSService : 0x%02X", - pstAddIndication->sfActiveSet.u8MBSService); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8QosParamSet : 0x%02X", - pstAddIndication->sfActiveSet.u8QosParamSet); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8TrafficPriority : 0x%02X", - pstAddIndication->sfActiveSet.u8TrafficPriority); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32MaxTrafficBurst : 0x%X", - pstAddIndication->sfActiveSet.u32MaxTrafficBurst); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32MinReservedTrafficRate : 0x%X", - pstAddIndication->sfActiveSet.u32MinReservedTrafficRate); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8VendorSpecificQoSParamLength : 0x%02X", - pstAddIndication->sfActiveSet.u8VendorSpecificQoSParamLength); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8VendorSpecificQoSParam : 0x%02X", - pstAddIndication->sfActiveSet.u8VendorSpecificQoSParam[0]); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ServiceFlowSchedulingType : 0x%02X", - pstAddIndication->sfActiveSet.u8ServiceFlowSchedulingType); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32ToleratedJitter : 0x%X", - pstAddIndication->sfActiveSet.u32ToleratedJitter); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32MaximumLatency : 0x%X", - pstAddIndication->sfActiveSet.u32MaximumLatency); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8FixedLengthVSVariableLengthSDUIndicator: 0x%02X", - pstAddIndication->sfActiveSet.u8FixedLengthVSVariableLengthSDUIndicator); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8SDUSize : 0x%X", - pstAddIndication->sfActiveSet.u8SDUSize); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u16TargetSAID : 0x%X", - pstAddIndication->sfActiveSet.u16TargetSAID); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8ARQEnable : 0x%X", - pstAddIndication->sfActiveSet.u8ARQEnable); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u16ARQWindowSize : 0x%X", - pstAddIndication->sfActiveSet.u16ARQWindowSize); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u16ARQRetryTxTimeOut : 0x%X", - pstAddIndication->sfActiveSet.u16ARQRetryTxTimeOut); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u16ARQRetryRxTimeOut : 0x%X", - pstAddIndication->sfActiveSet.u16ARQRetryRxTimeOut); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u16ARQBlockLifeTime : 0x%X", - pstAddIndication->sfActiveSet.u16ARQBlockLifeTime); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u16ARQSyncLossTimeOut : 0x%X", - pstAddIndication->sfActiveSet.u16ARQSyncLossTimeOut); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8ARQDeliverInOrder : 0x%X", - pstAddIndication->sfActiveSet.u8ARQDeliverInOrder); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u16ARQRxPurgeTimeOut : 0x%X", - pstAddIndication->sfActiveSet.u16ARQRxPurgeTimeOut); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u16ARQBlockSize : 0x%X", - pstAddIndication->sfActiveSet.u16ARQBlockSize); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8CSSpecification : 0x%X", - pstAddIndication->sfActiveSet.u8CSSpecification); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8TypeOfDataDeliveryService : 0x%X", - pstAddIndication->sfActiveSet.u8TypeOfDataDeliveryService); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u16SDUInterArrivalTime : 0x%X", - pstAddIndication->sfActiveSet.u16SDUInterArrivalTime); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u16TimeBase : 0x%X", - pstAddIndication->sfActiveSet.u16TimeBase); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8PagingPreference : 0x%X", - pstAddIndication->sfActiveSet.u8PagingPreference); - - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8TrafficIndicationPreference : 0x%X", - pstAddIndication->sfActiveSet.u8TrafficIndicationPreference); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " Total Classifiers Received : 0x%X",pstAddIndication->sfActiveSet.u8TotalClassifiers); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "bValid: 0x%X", pstAddIndication->sfAdmittedSet.bValid); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " ActiveSet--->"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32SFID: 0x%X", pstAddIndication->sfActiveSet.u32SFID); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16CID: 0x%X", pstAddIndication->sfActiveSet.u16CID); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ServiceClassNameLength: 0x%X", pstAddIndication->sfActiveSet.u8ServiceClassNameLength); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ServiceClassName: 0x %02X %02X %02X %02X %02X %02X", + pstAddIndication->sfActiveSet.u8ServiceClassName[0], + pstAddIndication->sfActiveSet.u8ServiceClassName[1], + pstAddIndication->sfActiveSet.u8ServiceClassName[2], + pstAddIndication->sfActiveSet.u8ServiceClassName[3], + pstAddIndication->sfActiveSet.u8ServiceClassName[4], + pstAddIndication->sfActiveSet.u8ServiceClassName[5]); + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8MBSService: 0x%02X", pstAddIndication->sfActiveSet.u8MBSService); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8QosParamSet: 0x%02X", pstAddIndication->sfActiveSet.u8QosParamSet); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8TrafficPriority: 0x%02X", pstAddIndication->sfActiveSet.u8TrafficPriority); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32MaxTrafficBurst: 0x%X", pstAddIndication->sfActiveSet.u32MaxTrafficBurst); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32MinReservedTrafficRate: 0x%X", + pstAddIndication->sfActiveSet.u32MinReservedTrafficRate); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8VendorSpecificQoSParamLength: 0x%02X", + pstAddIndication->sfActiveSet.u8VendorSpecificQoSParamLength); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8VendorSpecificQoSParam: 0x%02X", + pstAddIndication->sfActiveSet.u8VendorSpecificQoSParam[0]); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ServiceFlowSchedulingType: 0x%02X", + pstAddIndication->sfActiveSet.u8ServiceFlowSchedulingType); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32ToleratedJitter: 0x%X", pstAddIndication->sfActiveSet.u32ToleratedJitter); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32MaximumLatency: 0x%X", pstAddIndication->sfActiveSet.u32MaximumLatency); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8FixedLengthVSVariableLengthSDUIndicator: 0x%02X", + pstAddIndication->sfActiveSet.u8FixedLengthVSVariableLengthSDUIndicator); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8SDUSize: 0x%X", pstAddIndication->sfActiveSet.u8SDUSize); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u16TargetSAID: 0x%X", pstAddIndication->sfActiveSet.u16TargetSAID); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8ARQEnable: 0x%X", pstAddIndication->sfActiveSet.u8ARQEnable); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u16ARQWindowSize: 0x%X", pstAddIndication->sfActiveSet.u16ARQWindowSize); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u16ARQRetryTxTimeOut: 0x%X", pstAddIndication->sfActiveSet.u16ARQRetryTxTimeOut); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u16ARQRetryRxTimeOut: 0x%X", pstAddIndication->sfActiveSet.u16ARQRetryRxTimeOut); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u16ARQBlockLifeTime: 0x%X", pstAddIndication->sfActiveSet.u16ARQBlockLifeTime); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u16ARQSyncLossTimeOut: 0x%X", pstAddIndication->sfActiveSet.u16ARQSyncLossTimeOut); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8ARQDeliverInOrder: 0x%X", pstAddIndication->sfActiveSet.u8ARQDeliverInOrder); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u16ARQRxPurgeTimeOut: 0x%X", pstAddIndication->sfActiveSet.u16ARQRxPurgeTimeOut); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u16ARQBlockSize: 0x%X", pstAddIndication->sfActiveSet.u16ARQBlockSize); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8CSSpecification: 0x%X", pstAddIndication->sfActiveSet.u8CSSpecification); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8TypeOfDataDeliveryService: 0x%X", + pstAddIndication->sfActiveSet.u8TypeOfDataDeliveryService); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u16SDUInterArrivalTime: 0x%X", pstAddIndication->sfActiveSet.u16SDUInterArrivalTime); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u16TimeBase: 0x%X", pstAddIndication->sfActiveSet.u16TimeBase); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8PagingPreference: 0x%X", pstAddIndication->sfActiveSet.u8PagingPreference); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8TrafficIndicationPreference: 0x%X", + pstAddIndication->sfActiveSet.u8TrafficIndicationPreference); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " Total Classifiers Received: 0x%X", pstAddIndication->sfActiveSet.u8TotalClassifiers); nCurClassifierCnt = pstAddIndication->sfActiveSet.u8TotalClassifiers; - - if(nCurClassifierCnt > MAX_CLASSIFIERS_IN_SF) - { + if (nCurClassifierCnt > MAX_CLASSIFIERS_IN_SF) nCurClassifierCnt = MAX_CLASSIFIERS_IN_SF; - } - - for(nIndex = 0 ; nIndex < nCurClassifierCnt ; nIndex++) - { + for (nIndex = 0; nIndex < nCurClassifierCnt; nIndex++) { stConvergenceSLTypes *psfCSType = NULL; - psfCSType = &pstAddIndication->sfActiveSet.cConvergenceSLTypes[nIndex]; - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " CCPacketClassificationRuleSI====>"); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8ClassifierRulePriority :0x%X ", - psfCSType->cCPacketClassificationRule.u8ClassifierRulePriority); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8IPTypeOfServiceLength :0x%X ", - psfCSType->cCPacketClassificationRule.u8IPTypeOfServiceLength); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8IPTypeOfService[3] :0x%X ,0x%X ,0x%X ", - psfCSType->cCPacketClassificationRule.u8IPTypeOfService[0], - psfCSType->cCPacketClassificationRule.u8IPTypeOfService[1], - psfCSType->cCPacketClassificationRule.u8IPTypeOfService[2]); - for(uiLoopIndex=0; uiLoopIndex < 1; uiLoopIndex++) - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8Protocol : 0x%X ", - psfCSType->cCPacketClassificationRule.u8Protocol); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPMaskedSourceAddressLength :0x%X ", - psfCSType->cCPacketClassificationRule.u8IPMaskedSourceAddressLength); - - for(uiLoopIndex=0; uiLoopIndex < 32; uiLoopIndex++) - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPMaskedSourceAddress[32]:0x%X ", - psfCSType->cCPacketClassificationRule.u8IPMaskedSourceAddress[uiLoopIndex]); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPDestinationAddressLength : 0x%02X ", - psfCSType->cCPacketClassificationRule.u8IPDestinationAddressLength); - - for(uiLoopIndex=0;uiLoopIndex<32;uiLoopIndex++) - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8IPDestinationAddress[32]:0x%X ", - psfCSType->cCPacketClassificationRule.u8IPDestinationAddress[uiLoopIndex]); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8ProtocolSourcePortRangeLength:0x%X ", - psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRangeLength); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8ProtocolSourcePortRange[4]:0x%X ,0x%X ,0x%X ,0x%X ", - psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRange[0], - psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRange[1], - psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRange[2], - psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRange[3]); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8ProtocolDestPortRangeLength:0x%X ", - psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRangeLength); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8ProtocolDestPortRange[4]:0x%X ,0x%X ,0x%X ,0x%X ", - psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange[0], - psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange[1], - psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange[2], - psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange[3]); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8EthernetDestMacAddressLength:0x%X ", - psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddressLength); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8EthernetDestMacAddress[6]:0x%X ,0x%X ,0x%X ,0x%X ,0x%X ,0x%X", - psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[0], - psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[1], - psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[2], - psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[3], - psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[4], - psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[5]); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8EthernetSourceMACAddressLength:0x%X ", - psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddressLength); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthernetSourceMACAddress[6]:0x%X ,0x%X ,0x%X ,0x%X ,0x%X ,0x%X", - psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[0], - psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[1], - psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[2], - psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[3], - psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[4], - psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[5]); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8EthertypeLength :0x%X ", - psfCSType->cCPacketClassificationRule.u8EthertypeLength); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8Ethertype[3] :0x%X ,0x%X ,0x%X ", - psfCSType->cCPacketClassificationRule.u8Ethertype[0], - psfCSType->cCPacketClassificationRule.u8Ethertype[1], - psfCSType->cCPacketClassificationRule.u8Ethertype[2]); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u16UserPriority :0x%X ", - psfCSType->cCPacketClassificationRule.u16UserPriority); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u16VLANID :0x%X ", - psfCSType->cCPacketClassificationRule.u16VLANID); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8AssociatedPHSI :0x%X ", - psfCSType->cCPacketClassificationRule.u8AssociatedPHSI); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u16PacketClassificationRuleIndex:0x%X ", - psfCSType->cCPacketClassificationRule.u16PacketClassificationRuleIndex); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8VendorSpecificClassifierParamLength:0x%X ", - psfCSType->cCPacketClassificationRule.u8VendorSpecificClassifierParamLength); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8VendorSpecificClassifierParam[1]:0x%X ", - psfCSType->cCPacketClassificationRule.u8VendorSpecificClassifierParam[0]); + psfCSType = &pstAddIndication->sfActiveSet.cConvergenceSLTypes[nIndex]; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " CCPacketClassificationRuleSI====>"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8ClassifierRulePriority: 0x%X ", + psfCSType->cCPacketClassificationRule.u8ClassifierRulePriority); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8IPTypeOfServiceLength: 0x%X ", + psfCSType->cCPacketClassificationRule.u8IPTypeOfServiceLength); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8IPTypeOfService[3]: 0x%X ,0x%X ,0x%X ", + psfCSType->cCPacketClassificationRule.u8IPTypeOfService[0], + psfCSType->cCPacketClassificationRule.u8IPTypeOfService[1], + psfCSType->cCPacketClassificationRule.u8IPTypeOfService[2]); + + for (uiLoopIndex = 0; uiLoopIndex < 1; uiLoopIndex++) + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8Protocol: 0x%X ", psfCSType->cCPacketClassificationRule.u8Protocol); + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPMaskedSourceAddressLength: 0x%X ", + psfCSType->cCPacketClassificationRule.u8IPMaskedSourceAddressLength); + + for (uiLoopIndex = 0; uiLoopIndex < 32; uiLoopIndex++) + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPMaskedSourceAddress[32]: 0x%X ", + psfCSType->cCPacketClassificationRule.u8IPMaskedSourceAddress[uiLoopIndex]); + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPDestinationAddressLength: 0x%02X ", + psfCSType->cCPacketClassificationRule.u8IPDestinationAddressLength); + + for (uiLoopIndex = 0; uiLoopIndex < 32; uiLoopIndex++) + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8IPDestinationAddress[32]:0x%X ", + psfCSType->cCPacketClassificationRule.u8IPDestinationAddress[uiLoopIndex]); + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8ProtocolSourcePortRangeLength: 0x%X ", + psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRangeLength); + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8ProtocolSourcePortRange[4]: 0x%X ,0x%X ,0x%X ,0x%X ", + psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRange[0], + psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRange[1], + psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRange[2], + psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRange[3]); + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8ProtocolDestPortRangeLength: 0x%X ", + psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRangeLength); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8ProtocolDestPortRange[4]: 0x%X ,0x%X ,0x%X ,0x%X ", + psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange[0], + psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange[1], + psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange[2], + psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange[3]); + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8EthernetDestMacAddressLength: 0x%X ", + psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddressLength); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8EthernetDestMacAddress[6]: 0x%X ,0x%X ,0x%X ,0x%X ,0x%X ,0x%X", + psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[0], + psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[1], + psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[2], + psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[3], + psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[4], + psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[5]); + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8EthernetSourceMACAddressLength: 0x%X ", + psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddressLength); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthernetSourceMACAddress[6]: 0x%X ,0x%X ,0x%X ,0x%X ,0x%X ,0x%X", + psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[0], + psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[1], + psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[2], + psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[3], + psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[4], + psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[5]); + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8EthertypeLength: 0x%X ", + psfCSType->cCPacketClassificationRule.u8EthertypeLength); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8Ethertype[3]: 0x%X ,0x%X ,0x%X ", + psfCSType->cCPacketClassificationRule.u8Ethertype[0], + psfCSType->cCPacketClassificationRule.u8Ethertype[1], + psfCSType->cCPacketClassificationRule.u8Ethertype[2]); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u16UserPriority: 0x%X ", + psfCSType->cCPacketClassificationRule.u16UserPriority); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u16VLANID: 0x%X ", psfCSType->cCPacketClassificationRule.u16VLANID); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8AssociatedPHSI: 0x%X ", psfCSType->cCPacketClassificationRule.u8AssociatedPHSI); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u16PacketClassificationRuleIndex:0x%X ", + psfCSType->cCPacketClassificationRule.u16PacketClassificationRuleIndex); + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8VendorSpecificClassifierParamLength:0x%X ", + psfCSType->cCPacketClassificationRule.u8VendorSpecificClassifierParamLength); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8VendorSpecificClassifierParam[1]:0x%X ", + psfCSType->cCPacketClassificationRule.u8VendorSpecificClassifierParam[0]); #ifdef VERSION_D5 - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8IPv6FlowLableLength :0x%X ", - psfCSType->cCPacketClassificationRule.u8IPv6FlowLableLength); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8IPv6FlowLable[6] :0x%X ,0x%X ,0x%X ,0x%X ,0x%X ,0x%X ", - psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[0], - psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[1], - psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[2], - psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[3], - psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[4], - psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[5]); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8IPv6FlowLableLength: 0x%X ", + psfCSType->cCPacketClassificationRule.u8IPv6FlowLableLength); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8IPv6FlowLable[6]: 0x%X ,0x%X ,0x%X ,0x%X ,0x%X ,0x%X ", + psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[0], + psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[1], + psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[2], + psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[3], + psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[4], + psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[5]); #endif } - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " bValid : 0x%X",pstAddIndication->sfActiveSet.bValid); - + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " bValid: 0x%X", pstAddIndication->sfActiveSet.bValid); } -static inline ULONG RestoreSFParam(PMINI_ADAPTER Adapter, ULONG ulAddrSFParamSet,PUCHAR pucDestBuffer) +static inline ULONG RestoreSFParam(PMINI_ADAPTER Adapter, ULONG ulAddrSFParamSet, PUCHAR pucDestBuffer) { UINT nBytesToRead = sizeof(stServiceFlowParamSI); - if(ulAddrSFParamSet == 0 || NULL == pucDestBuffer) - { - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Got Param address as 0!!"); + if (ulAddrSFParamSet == 0 || NULL == pucDestBuffer) { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Got Param address as 0!!"); return 0; } ulAddrSFParamSet = ntohl(ulAddrSFParamSet); - //Read out the SF Param Set At the indicated Location - if(rdm(Adapter, ulAddrSFParamSet, (PUCHAR)pucDestBuffer, nBytesToRead) < 0) + /* Read out the SF Param Set At the indicated Location */ + if (rdm(Adapter, ulAddrSFParamSet, (PUCHAR)pucDestBuffer, nBytesToRead) < 0) return STATUS_FAILURE; return 1; } - -static ULONG StoreSFParam(PMINI_ADAPTER Adapter,PUCHAR pucSrcBuffer,ULONG ulAddrSFParamSet) +static ULONG StoreSFParam(PMINI_ADAPTER Adapter, PUCHAR pucSrcBuffer, ULONG ulAddrSFParamSet) { - UINT nBytesToWrite = sizeof(stServiceFlowParamSI); + UINT nBytesToWrite = sizeof(stServiceFlowParamSI); int ret = 0; - if(ulAddrSFParamSet == 0 || NULL == pucSrcBuffer) - { + if (ulAddrSFParamSet == 0 || NULL == pucSrcBuffer) return 0; - } ret = wrm(Adapter, ulAddrSFParamSet, (u8 *)pucSrcBuffer, nBytesToWrite); if (ret < 0) { - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "%s:%d WRM failed",__FUNCTION__, __LINE__); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "%s:%d WRM failed", __FUNCTION__, __LINE__); return ret; } return 1; } -ULONG StoreCmControlResponseMessage(PMINI_ADAPTER Adapter,PVOID pvBuffer,UINT *puBufferLength) +ULONG StoreCmControlResponseMessage(PMINI_ADAPTER Adapter, PVOID pvBuffer, UINT *puBufferLength) { stLocalSFAddIndicationAlt *pstAddIndicationAlt = NULL; - stLocalSFAddIndication * pstAddIndication = NULL; + stLocalSFAddIndication *pstAddIndication = NULL; stLocalSFDeleteRequest *pstDeletionRequest; UINT uiSearchRuleIndex; ULONG ulSFID; @@ -1671,52 +1369,47 @@ ULONG StoreCmControlResponseMessage(PMINI_ADAPTER Adapter,PVOID pvBuffer,UINT *p pstAddIndicationAlt = (stLocalSFAddIndicationAlt *)(pvBuffer); /* - * In case of DSD Req By MS, we should immediately delete this SF so that - * we can stop the further classifying the pkt for this SF. - */ - if(pstAddIndicationAlt->u8Type == DSD_REQ) - { + * In case of DSD Req By MS, we should immediately delete this SF so that + * we can stop the further classifying the pkt for this SF. + */ + if (pstAddIndicationAlt->u8Type == DSD_REQ) { pstDeletionRequest = (stLocalSFDeleteRequest *)pvBuffer; ulSFID = ntohl(pstDeletionRequest->u32SFID); - uiSearchRuleIndex=SearchSfid(Adapter,ulSFID); + uiSearchRuleIndex = SearchSfid(Adapter, ulSFID); - if(uiSearchRuleIndex < NO_OF_QUEUES) - { - deleteSFBySfid(Adapter,uiSearchRuleIndex); + if (uiSearchRuleIndex < NO_OF_QUEUES) { + deleteSFBySfid(Adapter, uiSearchRuleIndex); Adapter->u32TotalDSD++; } return 1; } - - if( (pstAddIndicationAlt->u8Type == DSD_RSP) || - (pstAddIndicationAlt->u8Type == DSD_ACK)) - { - //No Special handling send the message as it is + if ((pstAddIndicationAlt->u8Type == DSD_RSP) || + (pstAddIndicationAlt->u8Type == DSD_ACK)) { + /* No Special handling send the message as it is */ return 1; } - // For DSA_REQ, only up to "psfAuthorizedSet" parameter should be accessed by driver! + /* For DSA_REQ, only up to "psfAuthorizedSet" parameter should be accessed by driver! */ - pstAddIndication=kmalloc(sizeof(*pstAddIndication), GFP_KERNEL); - if(NULL==pstAddIndication) + pstAddIndication = kmalloc(sizeof(*pstAddIndication), GFP_KERNEL); + if (NULL == pstAddIndication) return 0; /* AUTHORIZED SET */ pstAddIndication->psfAuthorizedSet = (stServiceFlowParamSI *) GetNextTargetBufferLocation(Adapter, pstAddIndicationAlt->u16TID); - if(!pstAddIndication->psfAuthorizedSet) + if (!pstAddIndication->psfAuthorizedSet) return 0; - if(StoreSFParam(Adapter,(PUCHAR)&pstAddIndicationAlt->sfAuthorizedSet, - (ULONG)pstAddIndication->psfAuthorizedSet)!= 1) + if (StoreSFParam(Adapter, (PUCHAR)&pstAddIndicationAlt->sfAuthorizedSet, + (ULONG)pstAddIndication->psfAuthorizedSet) != 1) return 0; /* this can't possibly be right */ pstAddIndication->psfAuthorizedSet = (stServiceFlowParamSI *)ntohl((ULONG)pstAddIndication->psfAuthorizedSet); - if(pstAddIndicationAlt->u8Type == DSA_REQ) - { + if (pstAddIndicationAlt->u8Type == DSA_REQ) { stLocalSFAddRequest AddRequest; AddRequest.u8Type = pstAddIndicationAlt->u8Type; @@ -1724,18 +1417,17 @@ ULONG StoreCmControlResponseMessage(PMINI_ADAPTER Adapter,PVOID pvBuffer,UINT *p AddRequest.u16TID = pstAddIndicationAlt->u16TID; AddRequest.u16CID = pstAddIndicationAlt->u16CID; AddRequest.u16VCID = pstAddIndicationAlt->u16VCID; - AddRequest.psfParameterSet =pstAddIndication->psfAuthorizedSet ; + AddRequest.psfParameterSet = pstAddIndication->psfAuthorizedSet; (*puBufferLength) = sizeof(stLocalSFAddRequest); - memcpy(pvBuffer,&AddRequest,sizeof(stLocalSFAddRequest)); + memcpy(pvBuffer, &AddRequest, sizeof(stLocalSFAddRequest)); return 1; } - // Since it's not DSA_REQ, we can access all field in pstAddIndicationAlt - - //We need to extract the structure from the buffer and pack it differently + /* Since it's not DSA_REQ, we can access all field in pstAddIndicationAlt */ + /* We need to extract the structure from the buffer and pack it differently */ pstAddIndication->u8Type = pstAddIndicationAlt->u8Type; - pstAddIndication->eConnectionDir= pstAddIndicationAlt->u8Direction ; + pstAddIndication->eConnectionDir = pstAddIndicationAlt->u8Direction; pstAddIndication->u16TID = pstAddIndicationAlt->u16TID; pstAddIndication->u16CID = pstAddIndicationAlt->u16CID; pstAddIndication->u16VCID = pstAddIndicationAlt->u16VCID; @@ -1744,20 +1436,19 @@ ULONG StoreCmControlResponseMessage(PMINI_ADAPTER Adapter,PVOID pvBuffer,UINT *p /* ADMITTED SET */ pstAddIndication->psfAdmittedSet = (stServiceFlowParamSI *) GetNextTargetBufferLocation(Adapter, pstAddIndicationAlt->u16TID); - if(!pstAddIndication->psfAdmittedSet) + if (!pstAddIndication->psfAdmittedSet) return 0; - if(StoreSFParam(Adapter,(PUCHAR)&pstAddIndicationAlt->sfAdmittedSet,(ULONG)pstAddIndication->psfAdmittedSet) != 1) + if (StoreSFParam(Adapter, (PUCHAR)&pstAddIndicationAlt->sfAdmittedSet, (ULONG)pstAddIndication->psfAdmittedSet) != 1) return 0; pstAddIndication->psfAdmittedSet = (stServiceFlowParamSI *)ntohl((ULONG)pstAddIndication->psfAdmittedSet); - /* ACTIVE SET */ pstAddIndication->psfActiveSet = (stServiceFlowParamSI *) GetNextTargetBufferLocation(Adapter, pstAddIndicationAlt->u16TID); - if(!pstAddIndication->psfActiveSet) + if (!pstAddIndication->psfActiveSet) return 0; - if(StoreSFParam(Adapter,(PUCHAR)&pstAddIndicationAlt->sfActiveSet,(ULONG)pstAddIndication->psfActiveSet) != 1) + if (StoreSFParam(Adapter, (PUCHAR)&pstAddIndicationAlt->sfActiveSet, (ULONG)pstAddIndication->psfActiveSet) != 1) return 0; pstAddIndication->psfActiveSet = (stServiceFlowParamSI *)ntohl((ULONG)pstAddIndication->psfActiveSet); @@ -1768,47 +1459,41 @@ ULONG StoreCmControlResponseMessage(PMINI_ADAPTER Adapter,PVOID pvBuffer,UINT *p return 1; } - static inline stLocalSFAddIndicationAlt -*RestoreCmControlResponseMessage(register PMINI_ADAPTER Adapter,register PVOID pvBuffer) +*RestoreCmControlResponseMessage(register PMINI_ADAPTER Adapter, register PVOID pvBuffer) { - ULONG ulStatus=0; + ULONG ulStatus = 0; stLocalSFAddIndication *pstAddIndication = NULL; stLocalSFAddIndicationAlt *pstAddIndicationDest = NULL; - pstAddIndication = (stLocalSFAddIndication *)(pvBuffer); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "=====>" ); + pstAddIndication = (stLocalSFAddIndication *)(pvBuffer); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "=====>"); if ((pstAddIndication->u8Type == DSD_REQ) || (pstAddIndication->u8Type == DSD_RSP) || (pstAddIndication->u8Type == DSD_ACK)) - { return (stLocalSFAddIndicationAlt *)pvBuffer; - } - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Inside RestoreCmControlResponseMessage "); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Inside RestoreCmControlResponseMessage "); /* - //Need to Allocate memory to contain the SUPER Large structures - //Our driver can't create these structures on Stack :( - */ - pstAddIndicationDest=kmalloc(sizeof(stLocalSFAddIndicationAlt), GFP_KERNEL); - - if(pstAddIndicationDest) - { - memset(pstAddIndicationDest,0,sizeof(stLocalSFAddIndicationAlt)); - } - else - { - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Failed to allocate memory for SF Add Indication Structure "); + * Need to Allocate memory to contain the SUPER Large structures + * Our driver can't create these structures on Stack :( + */ + pstAddIndicationDest = kmalloc(sizeof(stLocalSFAddIndicationAlt), GFP_KERNEL); + + if (pstAddIndicationDest) { + memset(pstAddIndicationDest, 0, sizeof(stLocalSFAddIndicationAlt)); + } else { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Failed to allocate memory for SF Add Indication Structure "); return NULL; } - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "AddIndication-u8Type : 0x%X",pstAddIndication->u8Type); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "AddIndication-u8Direction : 0x%X",pstAddIndication->eConnectionDir); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "AddIndication-u8TID : 0x%X",ntohs(pstAddIndication->u16TID)); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "AddIndication-u8CID : 0x%X",ntohs(pstAddIndication->u16CID)); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "AddIndication-u16VCID : 0x%X",ntohs(pstAddIndication->u16VCID)); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "AddIndication-autorized set loc : %p",pstAddIndication->psfAuthorizedSet); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "AddIndication-admitted set loc : %p",pstAddIndication->psfAdmittedSet); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "AddIndication-Active set loc : %p",pstAddIndication->psfActiveSet); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "AddIndication-u8Type : 0x%X", pstAddIndication->u8Type); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "AddIndication-u8Direction : 0x%X", pstAddIndication->eConnectionDir); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "AddIndication-u8TID : 0x%X", ntohs(pstAddIndication->u16TID)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "AddIndication-u8CID : 0x%X", ntohs(pstAddIndication->u16CID)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "AddIndication-u16VCID : 0x%X", ntohs(pstAddIndication->u16VCID)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "AddIndication-autorized set loc : %p", pstAddIndication->psfAuthorizedSet); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "AddIndication-admitted set loc : %p", pstAddIndication->psfAdmittedSet); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "AddIndication-Active set loc : %p", pstAddIndication->psfActiveSet); pstAddIndicationDest->u8Type = pstAddIndication->u8Type; pstAddIndicationDest->u8Direction = pstAddIndication->eConnectionDir; @@ -1817,42 +1502,39 @@ static inline stLocalSFAddIndicationAlt pstAddIndicationDest->u16VCID = pstAddIndication->u16VCID; pstAddIndicationDest->u8CC = pstAddIndication->u8CC; - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Restoring Active Set "); - ulStatus=RestoreSFParam(Adapter,(ULONG)pstAddIndication->psfActiveSet, (PUCHAR)&pstAddIndicationDest->sfActiveSet); - if(ulStatus != 1) - { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Restoring Active Set "); + ulStatus = RestoreSFParam(Adapter, (ULONG)pstAddIndication->psfActiveSet, (PUCHAR)&pstAddIndicationDest->sfActiveSet); + if (ulStatus != 1) goto failed_restore_sf_param; - } - if(pstAddIndicationDest->sfActiveSet.u8TotalClassifiers > MAX_CLASSIFIERS_IN_SF) + + if (pstAddIndicationDest->sfActiveSet.u8TotalClassifiers > MAX_CLASSIFIERS_IN_SF) pstAddIndicationDest->sfActiveSet.u8TotalClassifiers = MAX_CLASSIFIERS_IN_SF; - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Restoring Admitted Set "); - ulStatus=RestoreSFParam(Adapter,(ULONG)pstAddIndication->psfAdmittedSet,(PUCHAR)&pstAddIndicationDest->sfAdmittedSet); - if(ulStatus != 1) - { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Restoring Admitted Set "); + ulStatus = RestoreSFParam(Adapter, (ULONG)pstAddIndication->psfAdmittedSet, (PUCHAR)&pstAddIndicationDest->sfAdmittedSet); + if (ulStatus != 1) goto failed_restore_sf_param; - } - if(pstAddIndicationDest->sfAdmittedSet.u8TotalClassifiers > MAX_CLASSIFIERS_IN_SF) + + if (pstAddIndicationDest->sfAdmittedSet.u8TotalClassifiers > MAX_CLASSIFIERS_IN_SF) pstAddIndicationDest->sfAdmittedSet.u8TotalClassifiers = MAX_CLASSIFIERS_IN_SF; - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Restoring Authorized Set "); - ulStatus=RestoreSFParam(Adapter,(ULONG)pstAddIndication->psfAuthorizedSet,(PUCHAR)&pstAddIndicationDest->sfAuthorizedSet); - if(ulStatus != 1) - { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Restoring Authorized Set "); + ulStatus = RestoreSFParam(Adapter, (ULONG)pstAddIndication->psfAuthorizedSet, (PUCHAR)&pstAddIndicationDest->sfAuthorizedSet); + if (ulStatus != 1) goto failed_restore_sf_param; - } - if(pstAddIndicationDest->sfAuthorizedSet.u8TotalClassifiers > MAX_CLASSIFIERS_IN_SF) + + if (pstAddIndicationDest->sfAuthorizedSet.u8TotalClassifiers > MAX_CLASSIFIERS_IN_SF) pstAddIndicationDest->sfAuthorizedSet.u8TotalClassifiers = MAX_CLASSIFIERS_IN_SF; - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Dumping the whole raw packet"); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "============================================================"); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, " pstAddIndicationDest->sfActiveSet size %zx %p", sizeof(*pstAddIndicationDest), pstAddIndicationDest); - //BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, (unsigned char *)pstAddIndicationDest, sizeof(*pstAddIndicationDest)); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "============================================================"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Dumping the whole raw packet"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "============================================================"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, " pstAddIndicationDest->sfActiveSet size %zx %p", sizeof(*pstAddIndicationDest), pstAddIndicationDest); + /* BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, (unsigned char *)pstAddIndicationDest, sizeof(*pstAddIndicationDest)); */ + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "============================================================"); return pstAddIndicationDest; failed_restore_sf_param: kfree(pstAddIndicationDest); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "<=====" ); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "<====="); return NULL; } @@ -1860,7 +1542,7 @@ ULONG SetUpTargetDsxBuffers(PMINI_ADAPTER Adapter) { ULONG ulTargetDsxBuffersBase = 0; ULONG ulCntTargetBuffers; - ULONG ulIndex=0; + ULONG ulIndex = 0; int Status; if (!Adapter) { @@ -1868,100 +1550,85 @@ ULONG SetUpTargetDsxBuffers(PMINI_ADAPTER Adapter) return 0; } - if(Adapter->astTargetDsxBuffer[0].ulTargetDsxBuffer) + if (Adapter->astTargetDsxBuffer[0].ulTargetDsxBuffer) return 1; - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Size of Each DSX Buffer(Also size of ServiceFlowParamSI): %zx ",sizeof(stServiceFlowParamSI)); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Reading DSX buffer From Target location %x ",DSX_MESSAGE_EXCHANGE_BUFFER); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Size of Each DSX Buffer(Also size of ServiceFlowParamSI): %zx ", sizeof(stServiceFlowParamSI)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Reading DSX buffer From Target location %x ", DSX_MESSAGE_EXCHANGE_BUFFER); - Status = rdmalt(Adapter, DSX_MESSAGE_EXCHANGE_BUFFER, - (PUINT)&ulTargetDsxBuffersBase, sizeof(UINT)); - if(Status < 0) - { - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "RDM failed!!"); + Status = rdmalt(Adapter, DSX_MESSAGE_EXCHANGE_BUFFER, (PUINT)&ulTargetDsxBuffersBase, sizeof(UINT)); + if (Status < 0) { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "RDM failed!!"); return 0; } - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Base Address Of DSX Target Buffer : 0x%lx",ulTargetDsxBuffersBase); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Tgt Buffer is Now %lx :",ulTargetDsxBuffersBase); - - ulCntTargetBuffers = DSX_MESSAGE_EXCHANGE_BUFFER_SIZE/sizeof(stServiceFlowParamSI); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Base Address Of DSX Target Buffer : 0x%lx", ulTargetDsxBuffersBase); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Tgt Buffer is Now %lx :", ulTargetDsxBuffersBase); + ulCntTargetBuffers = DSX_MESSAGE_EXCHANGE_BUFFER_SIZE / sizeof(stServiceFlowParamSI); Adapter->ulTotalTargetBuffersAvailable = ulCntTargetBuffers > MAX_TARGET_DSX_BUFFERS ? MAX_TARGET_DSX_BUFFERS : ulCntTargetBuffers; - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, " Total Target DSX Buffer setup %lx ",Adapter->ulTotalTargetBuffersAvailable); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, " Total Target DSX Buffer setup %lx ", Adapter->ulTotalTargetBuffersAvailable); - for(ulIndex=0; ulIndex < Adapter->ulTotalTargetBuffersAvailable ; ulIndex++) - { + for (ulIndex = 0; ulIndex < Adapter->ulTotalTargetBuffersAvailable; ulIndex++) { Adapter->astTargetDsxBuffer[ulIndex].ulTargetDsxBuffer = ulTargetDsxBuffersBase; - Adapter->astTargetDsxBuffer[ulIndex].valid=1; - Adapter->astTargetDsxBuffer[ulIndex].tid=0; - ulTargetDsxBuffersBase+=sizeof(stServiceFlowParamSI); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, " Target DSX Buffer %lx setup at 0x%lx", - ulIndex, Adapter->astTargetDsxBuffer[ulIndex].ulTargetDsxBuffer); + Adapter->astTargetDsxBuffer[ulIndex].valid = 1; + Adapter->astTargetDsxBuffer[ulIndex].tid = 0; + ulTargetDsxBuffersBase += sizeof(stServiceFlowParamSI); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, " Target DSX Buffer %lx setup at 0x%lx", + ulIndex, Adapter->astTargetDsxBuffer[ulIndex].ulTargetDsxBuffer); } Adapter->ulCurrentTargetBuffer = 0; Adapter->ulFreeTargetBufferCnt = Adapter->ulTotalTargetBuffersAvailable; return 1; } -static ULONG GetNextTargetBufferLocation(PMINI_ADAPTER Adapter,B_UINT16 tid) +static ULONG GetNextTargetBufferLocation(PMINI_ADAPTER Adapter, B_UINT16 tid) { - ULONG ulTargetDSXBufferAddress; - ULONG ulTargetDsxBufferIndexToUse,ulMaxTry; + ULONG ulTargetDSXBufferAddress; + ULONG ulTargetDsxBufferIndexToUse, ulMaxTry; - if((Adapter->ulTotalTargetBuffersAvailable == 0)|| - (Adapter->ulFreeTargetBufferCnt == 0)) - { - ClearTargetDSXBuffer(Adapter,tid,FALSE); + if ((Adapter->ulTotalTargetBuffersAvailable == 0) || (Adapter->ulFreeTargetBufferCnt == 0)) { + ClearTargetDSXBuffer(Adapter, tid, FALSE); return 0; } - ulTargetDsxBufferIndexToUse = Adapter->ulCurrentTargetBuffer; - ulMaxTry = Adapter->ulTotalTargetBuffersAvailable; - while((ulMaxTry)&&(Adapter->astTargetDsxBuffer[ulTargetDsxBufferIndexToUse].valid != 1)) - { - ulTargetDsxBufferIndexToUse = (ulTargetDsxBufferIndexToUse+1)% - Adapter->ulTotalTargetBuffersAvailable; - ulMaxTry--; + ulTargetDsxBufferIndexToUse = Adapter->ulCurrentTargetBuffer; + ulMaxTry = Adapter->ulTotalTargetBuffersAvailable; + while ((ulMaxTry) && (Adapter->astTargetDsxBuffer[ulTargetDsxBufferIndexToUse].valid != 1)) { + ulTargetDsxBufferIndexToUse = (ulTargetDsxBufferIndexToUse+1) % Adapter->ulTotalTargetBuffersAvailable; + ulMaxTry--; } - if(ulMaxTry==0) - { - BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "\n GetNextTargetBufferLocation : Error No Free Target DSX Buffers FreeCnt : %lx ",Adapter->ulFreeTargetBufferCnt); - ClearTargetDSXBuffer(Adapter,tid,FALSE); + if (ulMaxTry == 0) { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "\n GetNextTargetBufferLocation : Error No Free Target DSX Buffers FreeCnt : %lx ", Adapter->ulFreeTargetBufferCnt); + ClearTargetDSXBuffer(Adapter, tid, FALSE); return 0; } - - ulTargetDSXBufferAddress = - Adapter->astTargetDsxBuffer[ulTargetDsxBufferIndexToUse].ulTargetDsxBuffer; - Adapter->astTargetDsxBuffer[ulTargetDsxBufferIndexToUse].valid=0; - Adapter->astTargetDsxBuffer[ulTargetDsxBufferIndexToUse].tid=tid; + ulTargetDSXBufferAddress = Adapter->astTargetDsxBuffer[ulTargetDsxBufferIndexToUse].ulTargetDsxBuffer; + Adapter->astTargetDsxBuffer[ulTargetDsxBufferIndexToUse].valid = 0; + Adapter->astTargetDsxBuffer[ulTargetDsxBufferIndexToUse].tid = tid; Adapter->ulFreeTargetBufferCnt--; - - - ulTargetDsxBufferIndexToUse = - (ulTargetDsxBufferIndexToUse+1)%Adapter->ulTotalTargetBuffersAvailable; + ulTargetDsxBufferIndexToUse = (ulTargetDsxBufferIndexToUse+1)%Adapter->ulTotalTargetBuffersAvailable; Adapter->ulCurrentTargetBuffer = ulTargetDsxBufferIndexToUse; - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "GetNextTargetBufferLocation :Returning address %lx tid %d\n", - ulTargetDSXBufferAddress,tid); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "GetNextTargetBufferLocation :Returning address %lx tid %d\n", ulTargetDSXBufferAddress, tid); + return ulTargetDSXBufferAddress; } - INT AllocAdapterDsxBuffer(PMINI_ADAPTER Adapter) { /* - //Need to Allocate memory to contain the SUPER Large structures - //Our driver can't create these structures on Stack - */ - Adapter->caDsxReqResp=kmalloc(sizeof(stLocalSFAddIndicationAlt)+LEADER_SIZE, GFP_KERNEL); - if(!Adapter->caDsxReqResp) + * Need to Allocate memory to contain the SUPER Large structures + * Our driver can't create these structures on Stack + */ + Adapter->caDsxReqResp = kmalloc(sizeof(stLocalSFAddIndicationAlt)+LEADER_SIZE, GFP_KERNEL); + if (!Adapter->caDsxReqResp) return -ENOMEM; + return 0; } @@ -1969,310 +1636,261 @@ INT FreeAdapterDsxBuffer(PMINI_ADAPTER Adapter) { kfree(Adapter->caDsxReqResp); return 0; - } -/** -@ingroup ctrl_pkt_functions -This routinue would process the Control responses -for the Connection Management. -@return - Queue index for the free SFID else returns Invalid Index. -*/ -BOOLEAN CmControlResponseMessage(PMINI_ADAPTER Adapter, /**u16TID, FALSE); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_PRINTK, 0, 0, "Error in restoring Service Flow param structure from DSx message"); + * Otherwise the message contains a target address from where we need to + * read out the rest of the service flow param structure + */ + if ((pstAddIndication = RestoreCmControlResponseMessage(Adapter, pvBuffer)) == NULL) { + ClearTargetDSXBuffer(Adapter, ((stLocalSFAddIndication *)pvBuffer)->u16TID, FALSE); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Error in restoring Service Flow param structure from DSx message"); return FALSE; } DumpCmControlPacket(pstAddIndication); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "====>"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "====>"); pLeader = (PLEADER)Adapter->caDsxReqResp; - pLeader->Status =CM_CONTROL_NEWDSX_MULTICLASSIFIER_REQ; + pLeader->Status = CM_CONTROL_NEWDSX_MULTICLASSIFIER_REQ; pLeader->Vcid = 0; - ClearTargetDSXBuffer(Adapter,pstAddIndication->u16TID,FALSE); - BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "### TID RECEIVED %d\n",pstAddIndication->u16TID); - switch(pstAddIndication->u8Type) + ClearTargetDSXBuffer(Adapter, pstAddIndication->u16TID, FALSE); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "### TID RECEIVED %d\n", pstAddIndication->u16TID); + switch (pstAddIndication->u8Type) { + case DSA_REQ: { - case DSA_REQ: - { - pLeader->PLength = sizeof(stLocalSFAddIndicationAlt); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Sending DSA Response....\n"); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "SENDING DSA RESPONSE TO MAC %d", pLeader->PLength ); - *((stLocalSFAddIndicationAlt*)&(Adapter->caDsxReqResp[LEADER_SIZE])) - = *pstAddIndication; - ((stLocalSFAddIndicationAlt*)&(Adapter->caDsxReqResp[LEADER_SIZE]))->u8Type = DSA_RSP; - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, " VCID = %x", ntohs(pstAddIndication->u16VCID)); - CopyBufferToControlPacket(Adapter,(PVOID)Adapter->caDsxReqResp); - kfree(pstAddIndication); - } - break; - case DSA_RSP: - { - pLeader->PLength = sizeof(stLocalSFAddIndicationAlt); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "SENDING DSA ACK TO MAC %d", + pLeader->PLength = sizeof(stLocalSFAddIndicationAlt); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Sending DSA Response....\n"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "SENDING DSA RESPONSE TO MAC %d", pLeader->PLength); + *((stLocalSFAddIndicationAlt *)&(Adapter->caDsxReqResp[LEADER_SIZE])) + = *pstAddIndication; + ((stLocalSFAddIndicationAlt *)&(Adapter->caDsxReqResp[LEADER_SIZE]))->u8Type = DSA_RSP; + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, " VCID = %x", ntohs(pstAddIndication->u16VCID)); + CopyBufferToControlPacket(Adapter, (PVOID)Adapter->caDsxReqResp); + kfree(pstAddIndication); + } + break; + case DSA_RSP: + { + pLeader->PLength = sizeof(stLocalSFAddIndicationAlt); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "SENDING DSA ACK TO MAC %d", pLeader->PLength); - *((stLocalSFAddIndicationAlt*)&(Adapter->caDsxReqResp[LEADER_SIZE])) - = *pstAddIndication; - ((stLocalSFAddIndicationAlt*)&(Adapter->caDsxReqResp[LEADER_SIZE]))->u8Type = DSA_ACK; + *((stLocalSFAddIndicationAlt *)&(Adapter->caDsxReqResp[LEADER_SIZE])) + = *pstAddIndication; + ((stLocalSFAddIndicationAlt *)&(Adapter->caDsxReqResp[LEADER_SIZE]))->u8Type = DSA_ACK; - }//no break here..we should go down. - case DSA_ACK: - { - UINT uiSearchRuleIndex=0; + } /* no break here..we should go down. */ + case DSA_ACK: + { + UINT uiSearchRuleIndex = 0; - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "VCID:0x%X", + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "VCID:0x%X", ntohs(pstAddIndication->u16VCID)); - uiSearchRuleIndex=SearchFreeSfid(Adapter); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"uiSearchRuleIndex:0x%X ", + uiSearchRuleIndex = SearchFreeSfid(Adapter); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "uiSearchRuleIndex:0x%X ", uiSearchRuleIndex); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"Direction:0x%X ", + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Direction:0x%X ", pstAddIndication->u8Direction); - if((uiSearchRuleIndex< NO_OF_QUEUES) ) - { - Adapter->PackInfo[uiSearchRuleIndex].ucDirection = - pstAddIndication->u8Direction; - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "bValid:0x%X ", + if ((uiSearchRuleIndex < NO_OF_QUEUES)) { + Adapter->PackInfo[uiSearchRuleIndex].ucDirection = + pstAddIndication->u8Direction; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "bValid:0x%X ", pstAddIndication->sfActiveSet.bValid); - if(pstAddIndication->sfActiveSet.bValid==TRUE) - { - Adapter->PackInfo[uiSearchRuleIndex].bActiveSet=TRUE; - } - if(pstAddIndication->sfAuthorizedSet.bValid==TRUE) - { - Adapter->PackInfo[uiSearchRuleIndex].bAuthorizedSet=TRUE; - } - if(pstAddIndication->sfAdmittedSet.bValid==TRUE) - { - Adapter->PackInfo[uiSearchRuleIndex].bAdmittedSet=TRUE; - } - if(FALSE == pstAddIndication->sfActiveSet.bValid) - { - Adapter->PackInfo[uiSearchRuleIndex].bActive = FALSE; - Adapter->PackInfo[uiSearchRuleIndex].bActivateRequestSent = FALSE; - if(pstAddIndication->sfAdmittedSet.bValid) - { - psfLocalSet = &pstAddIndication->sfAdmittedSet; - } - else if(pstAddIndication->sfAuthorizedSet.bValid) - { - psfLocalSet = &pstAddIndication->sfAuthorizedSet; - } - } - else - { - psfLocalSet = &pstAddIndication->sfActiveSet; - Adapter->PackInfo[uiSearchRuleIndex].bActive=TRUE; - } - - if(!psfLocalSet) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "No set is valid\n"); - Adapter->PackInfo[uiSearchRuleIndex].bActive=FALSE; - Adapter->PackInfo[uiSearchRuleIndex].bValid=FALSE; - Adapter->PackInfo[uiSearchRuleIndex].usVCID_Value=0; - kfree(pstAddIndication); - } + if (pstAddIndication->sfActiveSet.bValid == TRUE) + Adapter->PackInfo[uiSearchRuleIndex].bActiveSet = TRUE; + + if (pstAddIndication->sfAuthorizedSet.bValid == TRUE) + Adapter->PackInfo[uiSearchRuleIndex].bAuthorizedSet = TRUE; + + if (pstAddIndication->sfAdmittedSet.bValid == TRUE) + Adapter->PackInfo[uiSearchRuleIndex].bAdmittedSet = TRUE; + + if (FALSE == pstAddIndication->sfActiveSet.bValid) { + Adapter->PackInfo[uiSearchRuleIndex].bActive = FALSE; + Adapter->PackInfo[uiSearchRuleIndex].bActivateRequestSent = FALSE; + if (pstAddIndication->sfAdmittedSet.bValid) + psfLocalSet = &pstAddIndication->sfAdmittedSet; + else if (pstAddIndication->sfAuthorizedSet.bValid) + psfLocalSet = &pstAddIndication->sfAuthorizedSet; + } else { + psfLocalSet = &pstAddIndication->sfActiveSet; + Adapter->PackInfo[uiSearchRuleIndex].bActive = TRUE; + } - else if(psfLocalSet->bValid && (pstAddIndication->u8CC == 0)) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "DSA ACK"); - Adapter->PackInfo[uiSearchRuleIndex].usVCID_Value = - ntohs(pstAddIndication->u16VCID); - Adapter->PackInfo[uiSearchRuleIndex].usCID = - ntohs(pstAddIndication->u16CID); - - if(UPLINK_DIR == pstAddIndication->u8Direction) - atomic_set(&Adapter->PackInfo[uiSearchRuleIndex].uiPerSFTxResourceCount, DEFAULT_PERSFCOUNT); - CopyToAdapter(Adapter,psfLocalSet,uiSearchRuleIndex, - DSA_ACK, pstAddIndication); - // don't free pstAddIndication - - /* Inside CopyToAdapter, Sorting of all the SFs take place. - Hence any access to the newly added SF through uiSearchRuleIndex is invalid. - SHOULD BE STRICTLY AVOIDED. - */ -// *(PULONG)(((PUCHAR)pvBuffer)+1)=psfLocalSet->u32SFID; - memcpy((((PUCHAR)pvBuffer)+1), &psfLocalSet->u32SFID, 4); - - if(pstAddIndication->sfActiveSet.bValid == TRUE) - { - if(UPLINK_DIR == pstAddIndication->u8Direction) - { - if(!Adapter->LinkUpStatus) - { - netif_carrier_on(Adapter->dev); - netif_start_queue(Adapter->dev); - Adapter->LinkUpStatus = 1; - if (netif_msg_link(Adapter)) - pr_info(PFX "%s: link up\n", Adapter->dev->name); - atomic_set(&Adapter->TxPktAvail, 1); - wake_up(&Adapter->tx_packet_wait_queue); - Adapter->liTimeSinceLastNetEntry = get_seconds(); - } + if (!psfLocalSet) { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "No set is valid\n"); + Adapter->PackInfo[uiSearchRuleIndex].bActive = FALSE; + Adapter->PackInfo[uiSearchRuleIndex].bValid = FALSE; + Adapter->PackInfo[uiSearchRuleIndex].usVCID_Value = 0; + kfree(pstAddIndication); + } else if (psfLocalSet->bValid && (pstAddIndication->u8CC == 0)) { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "DSA ACK"); + Adapter->PackInfo[uiSearchRuleIndex].usVCID_Value = ntohs(pstAddIndication->u16VCID); + Adapter->PackInfo[uiSearchRuleIndex].usCID = ntohs(pstAddIndication->u16CID); + + if (UPLINK_DIR == pstAddIndication->u8Direction) + atomic_set(&Adapter->PackInfo[uiSearchRuleIndex].uiPerSFTxResourceCount, DEFAULT_PERSFCOUNT); + + CopyToAdapter(Adapter, psfLocalSet, uiSearchRuleIndex, DSA_ACK, pstAddIndication); + /* don't free pstAddIndication */ + + /* Inside CopyToAdapter, Sorting of all the SFs take place. + * Hence any access to the newly added SF through uiSearchRuleIndex is invalid. + * SHOULD BE STRICTLY AVOIDED. + */ + /* *(PULONG)(((PUCHAR)pvBuffer)+1)=psfLocalSet->u32SFID; */ + memcpy((((PUCHAR)pvBuffer)+1), &psfLocalSet->u32SFID, 4); + + if (pstAddIndication->sfActiveSet.bValid == TRUE) { + if (UPLINK_DIR == pstAddIndication->u8Direction) { + if (!Adapter->LinkUpStatus) { + netif_carrier_on(Adapter->dev); + netif_start_queue(Adapter->dev); + Adapter->LinkUpStatus = 1; + if (netif_msg_link(Adapter)) + pr_info(PFX "%s: link up\n", Adapter->dev->name); + atomic_set(&Adapter->TxPktAvail, 1); + wake_up(&Adapter->tx_packet_wait_queue); + Adapter->liTimeSinceLastNetEntry = get_seconds(); } } } - - else - { - Adapter->PackInfo[uiSearchRuleIndex].bActive=FALSE; - Adapter->PackInfo[uiSearchRuleIndex].bValid=FALSE; - Adapter->PackInfo[uiSearchRuleIndex].usVCID_Value=0; - kfree(pstAddIndication); - } - } - else - { - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_PRINTK, 0, 0, "DSA ACK did not get valid SFID"); + } else { + Adapter->PackInfo[uiSearchRuleIndex].bActive = FALSE; + Adapter->PackInfo[uiSearchRuleIndex].bValid = FALSE; + Adapter->PackInfo[uiSearchRuleIndex].usVCID_Value = 0; kfree(pstAddIndication); - return FALSE; } - } - break; - case DSC_REQ: - { - pLeader->PLength = sizeof(stLocalSFChangeIndicationAlt); - pstChangeIndication = (stLocalSFChangeIndicationAlt*)pstAddIndication; - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "SENDING DSC RESPONSE TO MAC %d", pLeader->PLength); - - *((stLocalSFChangeIndicationAlt*)&(Adapter->caDsxReqResp[LEADER_SIZE])) = *pstChangeIndication; - ((stLocalSFChangeIndicationAlt*)&(Adapter->caDsxReqResp[LEADER_SIZE]))->u8Type = DSC_RSP; - - CopyBufferToControlPacket(Adapter,(PVOID)Adapter->caDsxReqResp); + } else { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "DSA ACK did not get valid SFID"); kfree(pstAddIndication); + return FALSE; } - break; - case DSC_RSP: - { - pLeader->PLength = sizeof(stLocalSFChangeIndicationAlt); - pstChangeIndication = (stLocalSFChangeIndicationAlt*)pstAddIndication; - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "SENDING DSC ACK TO MAC %d", pLeader->PLength); - *((stLocalSFChangeIndicationAlt*)&(Adapter->caDsxReqResp[LEADER_SIZE])) = *pstChangeIndication; - ((stLocalSFChangeIndicationAlt*)&(Adapter->caDsxReqResp[LEADER_SIZE]))->u8Type = DSC_ACK; - } - case DSC_ACK: - { - UINT uiSearchRuleIndex=0; + } + break; + case DSC_REQ: + { + pLeader->PLength = sizeof(stLocalSFChangeIndicationAlt); + pstChangeIndication = (stLocalSFChangeIndicationAlt *)pstAddIndication; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "SENDING DSC RESPONSE TO MAC %d", pLeader->PLength); - pstChangeIndication = (stLocalSFChangeIndicationAlt *)pstAddIndication; - uiSearchRuleIndex=SearchSfid(Adapter,ntohl(pstChangeIndication->sfActiveSet.u32SFID)); - if(uiSearchRuleIndex > NO_OF_QUEUES-1) - { - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_PRINTK, 0, 0, "SF doesn't exist for which DSC_ACK is received"); - } - if((uiSearchRuleIndex < NO_OF_QUEUES)) - { - Adapter->PackInfo[uiSearchRuleIndex].ucDirection = pstChangeIndication->u8Direction; - if(pstChangeIndication->sfActiveSet.bValid==TRUE) - { - Adapter->PackInfo[uiSearchRuleIndex].bActiveSet=TRUE; - } - if(pstChangeIndication->sfAuthorizedSet.bValid==TRUE) - { - Adapter->PackInfo[uiSearchRuleIndex].bAuthorizedSet=TRUE; - } - if(pstChangeIndication->sfAdmittedSet.bValid==TRUE) - { - Adapter->PackInfo[uiSearchRuleIndex].bAdmittedSet=TRUE; - } + *((stLocalSFChangeIndicationAlt *)&(Adapter->caDsxReqResp[LEADER_SIZE])) = *pstChangeIndication; + ((stLocalSFChangeIndicationAlt *)&(Adapter->caDsxReqResp[LEADER_SIZE]))->u8Type = DSC_RSP; - if(FALSE==pstChangeIndication->sfActiveSet.bValid) - { - Adapter->PackInfo[uiSearchRuleIndex].bActive = FALSE; - Adapter->PackInfo[uiSearchRuleIndex].bActivateRequestSent = FALSE; - if(pstChangeIndication->sfAdmittedSet.bValid) - { - psfLocalSet = &pstChangeIndication->sfAdmittedSet; - } - else if(pstChangeIndication->sfAuthorizedSet.bValid) - { - psfLocalSet = &pstChangeIndication->sfAuthorizedSet; - } - } - - else - { - psfLocalSet = &pstChangeIndication->sfActiveSet; - Adapter->PackInfo[uiSearchRuleIndex].bActive=TRUE; - } - if(psfLocalSet->bValid && (pstChangeIndication->u8CC == 0)) - { - Adapter->PackInfo[uiSearchRuleIndex].usVCID_Value = - ntohs(pstChangeIndication->u16VCID); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "CC field is %d bvalid = %d\n", - pstChangeIndication->u8CC, psfLocalSet->bValid); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "VCID= %d\n", ntohs(pstChangeIndication->u16VCID)); - Adapter->PackInfo[uiSearchRuleIndex].usCID = - ntohs(pstChangeIndication->u16CID); - CopyToAdapter(Adapter,psfLocalSet,uiSearchRuleIndex, - DSC_ACK, pstAddIndication); - - *(PULONG)(((PUCHAR)pvBuffer)+1)=psfLocalSet->u32SFID; - } - else if(pstChangeIndication->u8CC == 6) - { - deleteSFBySfid(Adapter,uiSearchRuleIndex); - kfree(pstAddIndication); - } + CopyBufferToControlPacket(Adapter, (PVOID)Adapter->caDsxReqResp); + kfree(pstAddIndication); + } + break; + case DSC_RSP: + { + pLeader->PLength = sizeof(stLocalSFChangeIndicationAlt); + pstChangeIndication = (stLocalSFChangeIndicationAlt *)pstAddIndication; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "SENDING DSC ACK TO MAC %d", pLeader->PLength); + *((stLocalSFChangeIndicationAlt *)&(Adapter->caDsxReqResp[LEADER_SIZE])) = *pstChangeIndication; + ((stLocalSFChangeIndicationAlt *)&(Adapter->caDsxReqResp[LEADER_SIZE]))->u8Type = DSC_ACK; + } + case DSC_ACK: + { + UINT uiSearchRuleIndex = 0; + + pstChangeIndication = (stLocalSFChangeIndicationAlt *)pstAddIndication; + uiSearchRuleIndex = SearchSfid(Adapter, ntohl(pstChangeIndication->sfActiveSet.u32SFID)); + if (uiSearchRuleIndex > NO_OF_QUEUES-1) + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "SF doesn't exist for which DSC_ACK is received"); + + if ((uiSearchRuleIndex < NO_OF_QUEUES)) { + Adapter->PackInfo[uiSearchRuleIndex].ucDirection = pstChangeIndication->u8Direction; + if (pstChangeIndication->sfActiveSet.bValid == TRUE) + Adapter->PackInfo[uiSearchRuleIndex].bActiveSet = TRUE; + + if (pstChangeIndication->sfAuthorizedSet.bValid == TRUE) + Adapter->PackInfo[uiSearchRuleIndex].bAuthorizedSet = TRUE; + + if (pstChangeIndication->sfAdmittedSet.bValid == TRUE) + Adapter->PackInfo[uiSearchRuleIndex].bAdmittedSet = TRUE; + + if (FALSE == pstChangeIndication->sfActiveSet.bValid) { + Adapter->PackInfo[uiSearchRuleIndex].bActive = FALSE; + Adapter->PackInfo[uiSearchRuleIndex].bActivateRequestSent = FALSE; + + if (pstChangeIndication->sfAdmittedSet.bValid) + psfLocalSet = &pstChangeIndication->sfAdmittedSet; + else if (pstChangeIndication->sfAuthorizedSet.bValid) + psfLocalSet = &pstChangeIndication->sfAuthorizedSet; + } else { + psfLocalSet = &pstChangeIndication->sfActiveSet; + Adapter->PackInfo[uiSearchRuleIndex].bActive = TRUE; } - else - { - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_PRINTK, 0, 0, "DSC ACK did not get valid SFID"); + + if (psfLocalSet->bValid && (pstChangeIndication->u8CC == 0)) { + Adapter->PackInfo[uiSearchRuleIndex].usVCID_Value = ntohs(pstChangeIndication->u16VCID); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "CC field is %d bvalid = %d\n", + pstChangeIndication->u8CC, psfLocalSet->bValid); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "VCID= %d\n", ntohs(pstChangeIndication->u16VCID)); + Adapter->PackInfo[uiSearchRuleIndex].usCID = ntohs(pstChangeIndication->u16CID); + CopyToAdapter(Adapter, psfLocalSet, uiSearchRuleIndex, DSC_ACK, pstAddIndication); + + *(PULONG)(((PUCHAR)pvBuffer)+1) = psfLocalSet->u32SFID; + } else if (pstChangeIndication->u8CC == 6) { + deleteSFBySfid(Adapter, uiSearchRuleIndex); kfree(pstAddIndication); - return FALSE; } + } else { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "DSC ACK did not get valid SFID"); + kfree(pstAddIndication); + return FALSE; } - break; - case DSD_REQ: - { - UINT uiSearchRuleIndex; - ULONG ulSFID; - - pLeader->PLength = sizeof(stLocalSFDeleteIndication); - *((stLocalSFDeleteIndication*)&(Adapter->caDsxReqResp[LEADER_SIZE])) = *((stLocalSFDeleteIndication*)pstAddIndication); + } + break; + case DSD_REQ: + { + UINT uiSearchRuleIndex; + ULONG ulSFID; - ulSFID = ntohl(((stLocalSFDeleteIndication*)pstAddIndication)->u32SFID); - uiSearchRuleIndex=SearchSfid(Adapter,ulSFID); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "DSD - Removing connection %x",uiSearchRuleIndex); + pLeader->PLength = sizeof(stLocalSFDeleteIndication); + *((stLocalSFDeleteIndication *)&(Adapter->caDsxReqResp[LEADER_SIZE])) = *((stLocalSFDeleteIndication *)pstAddIndication); - if(uiSearchRuleIndex < NO_OF_QUEUES) - { - //Delete All Classifiers Associated with this SFID - deleteSFBySfid(Adapter,uiSearchRuleIndex); - Adapter->u32TotalDSD++; - } + ulSFID = ntohl(((stLocalSFDeleteIndication *)pstAddIndication)->u32SFID); + uiSearchRuleIndex = SearchSfid(Adapter, ulSFID); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "DSD - Removing connection %x", uiSearchRuleIndex); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "SENDING DSD RESPONSE TO MAC"); - ((stLocalSFDeleteIndication*)&(Adapter->caDsxReqResp[LEADER_SIZE]))->u8Type = DSD_RSP; - CopyBufferToControlPacket(Adapter,(PVOID)Adapter->caDsxReqResp); - } - case DSD_RSP: - { - //Do nothing as SF has already got Deleted + if (uiSearchRuleIndex < NO_OF_QUEUES) { + /* Delete All Classifiers Associated with this SFID */ + deleteSFBySfid(Adapter, uiSearchRuleIndex); + Adapter->u32TotalDSD++; } - break; + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "SENDING DSD RESPONSE TO MAC"); + ((stLocalSFDeleteIndication *)&(Adapter->caDsxReqResp[LEADER_SIZE]))->u8Type = DSD_RSP; + CopyBufferToControlPacket(Adapter, (PVOID)Adapter->caDsxReqResp); + } + case DSD_RSP: + { + /* Do nothing as SF has already got Deleted */ + } + break; case DSD_ACK: - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "DSD ACK Rcd, let App handle it\n"); - break; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "DSD ACK Rcd, let App handle it\n"); + break; default: kfree(pstAddIndication); - return FALSE ; + return FALSE; } return TRUE; } @@ -2280,78 +1898,67 @@ BOOLEAN CmControlResponseMessage(PMINI_ADAPTER Adapter, /**= NO_OF_QUEUES) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "SFID %d not present in queue !!!", uiSFId ); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "SFID %d not present in queue !!!", uiSFId); return -EINVAL; } - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "status =%d",status); - psSfInfo=&Adapter->PackInfo[status]; - if(psSfInfo->pstSFIndication && copy_to_user(user_buffer, - psSfInfo->pstSFIndication, sizeof(stLocalSFAddIndicationAlt))) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "copy to user failed SFID %d, present in queue !!!", uiSFId ); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "status =%d", status); + psSfInfo = &Adapter->PackInfo[status]; + if (psSfInfo->pstSFIndication && copy_to_user(user_buffer, + psSfInfo->pstSFIndication, sizeof(stLocalSFAddIndicationAlt))) { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "copy to user failed SFID %d, present in queue !!!", uiSFId); status = -EFAULT; return status; } return STATUS_SUCCESS; } -VOID OverrideServiceFlowParams(PMINI_ADAPTER Adapter,PUINT puiBuffer) +VOID OverrideServiceFlowParams(PMINI_ADAPTER Adapter, PUINT puiBuffer) { - B_UINT32 u32NumofSFsinMsg = ntohl(*(puiBuffer + 1)); + B_UINT32 u32NumofSFsinMsg = ntohl(*(puiBuffer + 1)); stIM_SFHostNotify *pHostInfo = NULL; - UINT uiSearchRuleIndex = 0; - ULONG ulSFID = 0; + UINT uiSearchRuleIndex = 0; + ULONG ulSFID = 0; - puiBuffer+=2; + puiBuffer += 2; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "u32NumofSFsinMsg: 0x%x\n", u32NumofSFsinMsg); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "u32NumofSFsinMsg: 0x%x\n",u32NumofSFsinMsg); - - while(u32NumofSFsinMsg != 0 && u32NumofSFsinMsg < NO_OF_QUEUES) - { + while (u32NumofSFsinMsg != 0 && u32NumofSFsinMsg < NO_OF_QUEUES) { u32NumofSFsinMsg--; pHostInfo = (stIM_SFHostNotify *)puiBuffer; puiBuffer = (PUINT)(pHostInfo + 1); ulSFID = ntohl(pHostInfo->SFID); - uiSearchRuleIndex=SearchSfid(Adapter,ulSFID); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"SFID: 0x%lx\n",ulSFID); + uiSearchRuleIndex = SearchSfid(Adapter, ulSFID); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "SFID: 0x%lx\n", ulSFID); - if(uiSearchRuleIndex >= NO_OF_QUEUES || uiSearchRuleIndex == HiPriority) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"The SFID <%lx> doesn't exist in host entry or is Invalid\n", ulSFID); + if (uiSearchRuleIndex >= NO_OF_QUEUES || uiSearchRuleIndex == HiPriority) { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "The SFID <%lx> doesn't exist in host entry or is Invalid\n", ulSFID); continue; } - if(pHostInfo->RetainSF == FALSE) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"Going to Delete SF"); - deleteSFBySfid(Adapter,uiSearchRuleIndex); - } - else - { - + if (pHostInfo->RetainSF == FALSE) { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Going to Delete SF"); + deleteSFBySfid(Adapter, uiSearchRuleIndex); + } else { Adapter->PackInfo[uiSearchRuleIndex].usVCID_Value = ntohs(pHostInfo->VCID); Adapter->PackInfo[uiSearchRuleIndex].usCID = ntohs(pHostInfo->newCID); - Adapter->PackInfo[uiSearchRuleIndex].bActive=FALSE; + Adapter->PackInfo[uiSearchRuleIndex].bActive = FALSE; - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"pHostInfo->QoSParamSet: 0x%x\n",pHostInfo->QoSParamSet); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "pHostInfo->QoSParamSet: 0x%x\n", pHostInfo->QoSParamSet); - if(pHostInfo->QoSParamSet & 0x1) - Adapter->PackInfo[uiSearchRuleIndex].bAuthorizedSet =TRUE; - if(pHostInfo->QoSParamSet & 0x2) - Adapter->PackInfo[uiSearchRuleIndex].bAdmittedSet =TRUE; - if(pHostInfo->QoSParamSet & 0x4) - { - Adapter->PackInfo[uiSearchRuleIndex].bActiveSet =TRUE; - Adapter->PackInfo[uiSearchRuleIndex].bActive=TRUE; + if (pHostInfo->QoSParamSet & 0x1) + Adapter->PackInfo[uiSearchRuleIndex].bAuthorizedSet = TRUE; + if (pHostInfo->QoSParamSet & 0x2) + Adapter->PackInfo[uiSearchRuleIndex].bAdmittedSet = TRUE; + if (pHostInfo->QoSParamSet & 0x4) { + Adapter->PackInfo[uiSearchRuleIndex].bActiveSet = TRUE; + Adapter->PackInfo[uiSearchRuleIndex].bActive = TRUE; } } } } - - - -- cgit v0.10.2 From e4868623bfe1c05e1e17d86729907a3850d12882 Mon Sep 17 00:00:00 2001 From: Kevin McKinney Date: Wed, 4 Jan 2012 20:29:01 -0500 Subject: Staging: bcm: Replace dated variable __FUNCTION__. This patch replaces the obsolete variable, __FUNCTION__, that holds the name of the current function with variable, __func__. Reported by checkpatch.pl. Signed-off-by: Kevin McKinney Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/bcm/CmHost.c b/drivers/staging/bcm/CmHost.c index fcb1835..63d768d 100644 --- a/drivers/staging/bcm/CmHost.c +++ b/drivers/staging/bcm/CmHost.c @@ -447,7 +447,7 @@ static VOID CopyToAdapter(register PMINI_ADAPTER Adapter, /* PackInfo[uiSearchRuleIndex].bValid = TRUE; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Search Rule Index = %d\n", uiSearchRuleIndex); - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "%s: SFID= %x ", __FUNCTION__, ntohl(psfLocalSet->u32SFID)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "%s: SFID= %x ", __func__, ntohl(psfLocalSet->u32SFID)); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Updating Queue %d", uiSearchRuleIndex); ulSFID = ntohl(psfLocalSet->u32SFID); @@ -816,7 +816,7 @@ static VOID CopyToAdapter(register PMINI_ADAPTER Adapter, /* stBCMPhsContext); - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "%s <=====", __FUNCTION__); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "%s <=====", __func__); } /*********************************************************************** @@ -1352,7 +1352,7 @@ static ULONG StoreSFParam(PMINI_ADAPTER Adapter, PUCHAR pucSrcBuffer, ULONG ulAd ret = wrm(Adapter, ulAddrSFParamSet, (u8 *)pucSrcBuffer, nBytesToWrite); if (ret < 0) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "%s:%d WRM failed", __FUNCTION__, __LINE__); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "%s:%d WRM failed", __func__, __LINE__); return ret; } return 1; -- cgit v0.10.2 From 5db125fb5ca2fed67a668c532af576a67a3d3bdc Mon Sep 17 00:00:00 2001 From: Kevin McKinney Date: Wed, 4 Jan 2012 20:29:02 -0500 Subject: Staging: bcm: Remove typedef from CmHost.c and use enum. This patch removes a typedef from a variable definition in CmHost.c, and uses a enum instead. This Warning was reported by checkpatch.pl. Signed-off-by: Kevin McKinney Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/bcm/CmHost.c b/drivers/staging/bcm/CmHost.c index 63d768d..cf4146e 100644 --- a/drivers/staging/bcm/CmHost.c +++ b/drivers/staging/bcm/CmHost.c @@ -7,12 +7,12 @@ /* #define CONN_MSG */ #include "headers.h" -typedef enum _E_CLASSIFIER_ACTION { +enum E_CLASSIFIER_ACTION { eInvalidClassifierAction, eAddClassifier, eReplaceClassifier, eDeleteClassifier -} E_CLASSIFIER_ACTION; +}; static ULONG GetNextTargetBufferLocation(PMINI_ADAPTER Adapter, B_UINT16 tid); @@ -437,7 +437,7 @@ static VOID CopyToAdapter(register PMINI_ADAPTER Adapter, /* Date: Wed, 4 Jan 2012 20:29:03 -0500 Subject: Staging: bcm: Remove assignment from if statement and reverse if logic for readability. This patch removes an assignment from an if statement, and it reverses the logic in several if statements to make them more readable and understandable. Signed-off-by: Kevin McKinney Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/bcm/CmHost.c b/drivers/staging/bcm/CmHost.c index cf4146e..de38bed 100644 --- a/drivers/staging/bcm/CmHost.c +++ b/drivers/staging/bcm/CmHost.c @@ -194,7 +194,7 @@ CopyIpAddrToClassifier(S_CLASSIFIER_RULE *pstClassifierEntry, } u8IpAddressLen -= nSizeOfIPAddressInBytes; } - if (0 == u8IpAddressLen) + if (u8IpAddressLen == 0) pstClassifierEntry->bDestIpValid = TRUE; ucLoopIndex++; @@ -263,7 +263,7 @@ static inline VOID CopyClassifierRuleToSF(PMINI_ADAPTER Adapter, stConvergenceSL pstClassifierEntry->ucDestPortRangeLength = psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRangeLength / 4; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Destination Port Range Length:0x%X ", pstClassifierEntry->ucDestPortRangeLength); - if (MAX_PORT_RANGE >= psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRangeLength) { + if (psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRangeLength <= MAX_PORT_RANGE) { for (ucLoopIndex = 0; ucLoopIndex < (pstClassifierEntry->ucDestPortRangeLength); ucLoopIndex++) { pstClassifierEntry->usDestPortRangeLo[ucLoopIndex] = *((PUSHORT)(psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange+ucLoopIndex)); pstClassifierEntry->usDestPortRangeHi[ucLoopIndex] = @@ -280,7 +280,7 @@ static inline VOID CopyClassifierRuleToSF(PMINI_ADAPTER Adapter, stConvergenceSL /* Source Port */ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Source Port Range Length:0x%X ", psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRangeLength); - if (MAX_PORT_RANGE >= psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRangeLength) { + if (psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRangeLength <= MAX_PORT_RANGE) { pstClassifierEntry->ucSrcPortRangeLength = psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRangeLength/4; for (ucLoopIndex = 0; ucLoopIndex < (pstClassifierEntry->ucSrcPortRangeLength); ucLoopIndex++) { pstClassifierEntry->usSrcPortRangeLo[ucLoopIndex] = @@ -315,7 +315,7 @@ static inline VOID CopyClassifierRuleToSF(PMINI_ADAPTER Adapter, stConvergenceSL /* TOS */ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "TOS Length:0x%X ", psfCSType->cCPacketClassificationRule.u8IPTypeOfServiceLength); - if (3 == psfCSType->cCPacketClassificationRule.u8IPTypeOfServiceLength) { + if (psfCSType->cCPacketClassificationRule.u8IPTypeOfServiceLength == 3) { pstClassifierEntry->ucIPTypeOfServiceLength = psfCSType->cCPacketClassificationRule.u8IPTypeOfServiceLength; pstClassifierEntry->ucTosLow = psfCSType->cCPacketClassificationRule.u8IPTypeOfService[0]; pstClassifierEntry->ucTosHigh = psfCSType->cCPacketClassificationRule.u8IPTypeOfService[1]; @@ -1393,7 +1393,7 @@ ULONG StoreCmControlResponseMessage(PMINI_ADAPTER Adapter, PVOID pvBuffer, UINT /* For DSA_REQ, only up to "psfAuthorizedSet" parameter should be accessed by driver! */ pstAddIndication = kmalloc(sizeof(*pstAddIndication), GFP_KERNEL); - if (NULL == pstAddIndication) + if (pstAddIndication == NULL) return 0; /* AUTHORIZED SET */ @@ -1656,7 +1656,8 @@ BOOLEAN CmControlResponseMessage(PMINI_ADAPTER Adapter, /* u16TID, FALSE); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Error in restoring Service Flow param structure from DSx message"); return FALSE; @@ -1721,7 +1722,7 @@ BOOLEAN CmControlResponseMessage(PMINI_ADAPTER Adapter, /* sfAdmittedSet.bValid == TRUE) Adapter->PackInfo[uiSearchRuleIndex].bAdmittedSet = TRUE; - if (FALSE == pstAddIndication->sfActiveSet.bValid) { + if (pstAddIndication->sfActiveSet.bValid == FALSE) { Adapter->PackInfo[uiSearchRuleIndex].bActive = FALSE; Adapter->PackInfo[uiSearchRuleIndex].bActivateRequestSent = FALSE; if (pstAddIndication->sfAdmittedSet.bValid) @@ -1825,7 +1826,7 @@ BOOLEAN CmControlResponseMessage(PMINI_ADAPTER Adapter, /* sfAdmittedSet.bValid == TRUE) Adapter->PackInfo[uiSearchRuleIndex].bAdmittedSet = TRUE; - if (FALSE == pstChangeIndication->sfActiveSet.bValid) { + if (pstChangeIndication->sfActiveSet.bValid == FALSE) { Adapter->PackInfo[uiSearchRuleIndex].bActive = FALSE; Adapter->PackInfo[uiSearchRuleIndex].bActivateRequestSent = FALSE; -- cgit v0.10.2 From ce4bbc2ae4626f6fdf1af8767d59852978e5f942 Mon Sep 17 00:00:00 2001 From: Kevin McKinney Date: Wed, 4 Jan 2012 20:29:04 -0500 Subject: Staging: bcm: Replace variables and function outputs defined as INT with int. This patch replaces all variables and function output that have a datatype definition of "INT" with "int". Signed-off-by: Kevin McKinney Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/bcm/CmHost.c b/drivers/staging/bcm/CmHost.c index de38bed..941d047 100644 --- a/drivers/staging/bcm/CmHost.c +++ b/drivers/staging/bcm/CmHost.c @@ -28,9 +28,9 @@ static ULONG GetNextTargetBufferLocation(PMINI_ADAPTER Adapter, B_UINT16 tid); * Returns - Queue index for this SFID(If matched) * Else Invalid Queue Index(If Not matched) ************************************************************/ -INT SearchSfid(PMINI_ADAPTER Adapter, UINT uiSfid) +int SearchSfid(PMINI_ADAPTER Adapter, UINT uiSfid) { - INT iIndex = 0; + int iIndex = 0; for (iIndex = (NO_OF_QUEUES-1); iIndex >= 0; iIndex--) if (Adapter->PackInfo[iIndex].ulSFID == uiSfid) @@ -49,7 +49,7 @@ INT SearchSfid(PMINI_ADAPTER Adapter, UINT uiSfid) * Returns - Queue index for the free SFID * Else returns Invalid Index. ****************************************************************/ -static INT SearchFreeSfid(PMINI_ADAPTER Adapter) +static int SearchFreeSfid(PMINI_ADAPTER Adapter) { UINT uiIndex = 0; @@ -1619,7 +1619,7 @@ static ULONG GetNextTargetBufferLocation(PMINI_ADAPTER Adapter, B_UINT16 tid) return ulTargetDSXBufferAddress; } -INT AllocAdapterDsxBuffer(PMINI_ADAPTER Adapter) +int AllocAdapterDsxBuffer(PMINI_ADAPTER Adapter) { /* * Need to Allocate memory to contain the SUPER Large structures @@ -1632,7 +1632,7 @@ INT AllocAdapterDsxBuffer(PMINI_ADAPTER Adapter) return 0; } -INT FreeAdapterDsxBuffer(PMINI_ADAPTER Adapter) +int FreeAdapterDsxBuffer(PMINI_ADAPTER Adapter) { kfree(Adapter->caDsxReqResp); return 0; -- cgit v0.10.2 From 5cf4d6b936ca21f67aa763dd0d3f8fdd9873b22c Mon Sep 17 00:00:00 2001 From: Kevin McKinney Date: Wed, 4 Jan 2012 20:29:05 -0500 Subject: Staging: bcm: Alter name, datatype, and default value of iterator variables. This patch renames variables used in iteration statements with i, changes the datatype to int, and removes any default value. Signed-off-by: Kevin McKinney Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/bcm/CmHost.c b/drivers/staging/bcm/CmHost.c index 941d047..522d005 100644 --- a/drivers/staging/bcm/CmHost.c +++ b/drivers/staging/bcm/CmHost.c @@ -30,11 +30,11 @@ static ULONG GetNextTargetBufferLocation(PMINI_ADAPTER Adapter, B_UINT16 tid); ************************************************************/ int SearchSfid(PMINI_ADAPTER Adapter, UINT uiSfid) { - int iIndex = 0; + int i; - for (iIndex = (NO_OF_QUEUES-1); iIndex >= 0; iIndex--) - if (Adapter->PackInfo[iIndex].ulSFID == uiSfid) - return iIndex; + for (i = (NO_OF_QUEUES-1); i >= 0; i--) + if (Adapter->PackInfo[i].ulSFID == uiSfid) + return i; return NO_OF_QUEUES+1; } @@ -51,11 +51,11 @@ int SearchSfid(PMINI_ADAPTER Adapter, UINT uiSfid) ****************************************************************/ static int SearchFreeSfid(PMINI_ADAPTER Adapter) { - UINT uiIndex = 0; + int i; - for (uiIndex = 0; uiIndex < (NO_OF_QUEUES-1); uiIndex++) - if (Adapter->PackInfo[uiIndex].ulSFID == 0) - return uiIndex; + for (i = 0; i < (NO_OF_QUEUES-1); i++) + if (Adapter->PackInfo[i].ulSFID == 0) + return i; return NO_OF_QUEUES+1; } @@ -70,13 +70,13 @@ static int SearchFreeSfid(PMINI_ADAPTER Adapter) */ static int SearchClsid(PMINI_ADAPTER Adapter, ULONG ulSFID, B_UINT16 uiClassifierID) { - unsigned int uiClassifierIndex = 0; + int i; - for (uiClassifierIndex = 0; uiClassifierIndex < MAX_CLASSIFIERS; uiClassifierIndex++) { - if ((Adapter->astClassifierTable[uiClassifierIndex].bUsed) && - (Adapter->astClassifierTable[uiClassifierIndex].uiClassifierRuleIndex == uiClassifierID) && - (Adapter->astClassifierTable[uiClassifierIndex].ulSFID == ulSFID)) - return uiClassifierIndex; + for (i = 0; i < MAX_CLASSIFIERS; i++) { + if ((Adapter->astClassifierTable[i].bUsed) && + (Adapter->astClassifierTable[i].uiClassifierRuleIndex == uiClassifierID) && + (Adapter->astClassifierTable[i].ulSFID == ulSFID)) + return i; } return MAX_CLASSIFIERS+1; @@ -89,11 +89,11 @@ static int SearchClsid(PMINI_ADAPTER Adapter, ULONG ulSFID, B_UINT16 uiClassifi */ static int SearchFreeClsid(PMINI_ADAPTER Adapter /**Adapter Context*/) { - unsigned int uiClassifierIndex = 0; + int i; - for (uiClassifierIndex = 0; uiClassifierIndex < MAX_CLASSIFIERS; uiClassifierIndex++) { - if (!Adapter->astClassifierTable[uiClassifierIndex].bUsed) - return uiClassifierIndex; + for (i = 0; i < MAX_CLASSIFIERS; i++) { + if (!Adapter->astClassifierTable[i].bUsed) + return i; } return MAX_CLASSIFIERS+1; @@ -116,7 +116,7 @@ CopyIpAddrToClassifier(S_CLASSIFIER_RULE *pstClassifierEntry, B_UINT8 u8IpAddressLen, B_UINT8 *pu8IpAddressMaskSrc, BOOLEAN bIpVersion6, E_IPADDR_CONTEXT eIpAddrContext) { - UINT ucLoopIndex = 0; + int i = 0; UINT nSizeOfIPAddressInBytes = IP_LENGTH_OF_ADDRESS; UCHAR *ptrClassifierIpAddress = NULL; UCHAR *ptrClassifierIpMask = NULL; @@ -154,42 +154,42 @@ CopyIpAddrToClassifier(S_CLASSIFIER_RULE *pstClassifierEntry, } } BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Address Length:0x%X\n", pstClassifierEntry->ucIPDestinationAddressLength); - while ((u8IpAddressLen >= nSizeOfIPAddressInBytes) && (ucLoopIndex < MAX_IP_RANGE_LENGTH)) { + while ((u8IpAddressLen >= nSizeOfIPAddressInBytes) && (i < MAX_IP_RANGE_LENGTH)) { memcpy(ptrClassifierIpAddress + - (ucLoopIndex * nSizeOfIPAddressInBytes), - (pu8IpAddressMaskSrc+(ucLoopIndex*nSizeOfIPAddressInBytes*2)), + (i * nSizeOfIPAddressInBytes), + (pu8IpAddressMaskSrc+(i*nSizeOfIPAddressInBytes*2)), nSizeOfIPAddressInBytes); if (!bIpVersion6) { if (eIpAddrContext == eSrcIpAddress) { - pstClassifierEntry->stSrcIpAddress.ulIpv4Addr[ucLoopIndex] = ntohl(pstClassifierEntry->stSrcIpAddress.ulIpv4Addr[ucLoopIndex]); + pstClassifierEntry->stSrcIpAddress.ulIpv4Addr[i] = ntohl(pstClassifierEntry->stSrcIpAddress.ulIpv4Addr[i]); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Src Ip Address:0x%luX ", - pstClassifierEntry->stSrcIpAddress.ulIpv4Addr[ucLoopIndex]); + pstClassifierEntry->stSrcIpAddress.ulIpv4Addr[i]); } else if (eIpAddrContext == eDestIpAddress) { - pstClassifierEntry->stDestIpAddress.ulIpv4Addr[ucLoopIndex] = ntohl(pstClassifierEntry->stDestIpAddress.ulIpv4Addr[ucLoopIndex]); + pstClassifierEntry->stDestIpAddress.ulIpv4Addr[i] = ntohl(pstClassifierEntry->stDestIpAddress.ulIpv4Addr[i]); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Dest Ip Address:0x%luX ", - pstClassifierEntry->stDestIpAddress.ulIpv4Addr[ucLoopIndex]); + pstClassifierEntry->stDestIpAddress.ulIpv4Addr[i]); } } u8IpAddressLen -= nSizeOfIPAddressInBytes; if (u8IpAddressLen >= nSizeOfIPAddressInBytes) { memcpy(ptrClassifierIpMask + - (ucLoopIndex * nSizeOfIPAddressInBytes), + (i * nSizeOfIPAddressInBytes), (pu8IpAddressMaskSrc+nSizeOfIPAddressInBytes + - (ucLoopIndex*nSizeOfIPAddressInBytes*2)), + (i*nSizeOfIPAddressInBytes*2)), nSizeOfIPAddressInBytes); if (!bIpVersion6) { if (eIpAddrContext == eSrcIpAddress) { - pstClassifierEntry->stSrcIpAddress.ulIpv4Mask[ucLoopIndex] = - ntohl(pstClassifierEntry->stSrcIpAddress.ulIpv4Mask[ucLoopIndex]); + pstClassifierEntry->stSrcIpAddress.ulIpv4Mask[i] = + ntohl(pstClassifierEntry->stSrcIpAddress.ulIpv4Mask[i]); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Src Ip Mask Address:0x%luX ", - pstClassifierEntry->stSrcIpAddress.ulIpv4Mask[ucLoopIndex]); + pstClassifierEntry->stSrcIpAddress.ulIpv4Mask[i]); } else if (eIpAddrContext == eDestIpAddress) { - pstClassifierEntry->stDestIpAddress.ulIpv4Mask[ucLoopIndex] = - ntohl(pstClassifierEntry->stDestIpAddress.ulIpv4Mask[ucLoopIndex]); + pstClassifierEntry->stDestIpAddress.ulIpv4Mask[i] = + ntohl(pstClassifierEntry->stDestIpAddress.ulIpv4Mask[i]); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Dest Ip Mask Address:0x%luX ", - pstClassifierEntry->stDestIpAddress.ulIpv4Mask[ucLoopIndex]); + pstClassifierEntry->stDestIpAddress.ulIpv4Mask[i]); } } u8IpAddressLen -= nSizeOfIPAddressInBytes; @@ -197,17 +197,17 @@ CopyIpAddrToClassifier(S_CLASSIFIER_RULE *pstClassifierEntry, if (u8IpAddressLen == 0) pstClassifierEntry->bDestIpValid = TRUE; - ucLoopIndex++; + i++; } if (bIpVersion6) { /* Restore EndianNess of Struct */ - for (ucLoopIndex = 0; ucLoopIndex < MAX_IP_RANGE_LENGTH * 4; ucLoopIndex++) { + for (i = 0; i < MAX_IP_RANGE_LENGTH * 4; i++) { if (eIpAddrContext == eSrcIpAddress) { - pstClassifierEntry->stSrcIpAddress.ulIpv6Addr[ucLoopIndex] = ntohl(pstClassifierEntry->stSrcIpAddress.ulIpv6Addr[ucLoopIndex]); - pstClassifierEntry->stSrcIpAddress.ulIpv6Mask[ucLoopIndex] = ntohl(pstClassifierEntry->stSrcIpAddress.ulIpv6Mask[ucLoopIndex]); + pstClassifierEntry->stSrcIpAddress.ulIpv6Addr[i] = ntohl(pstClassifierEntry->stSrcIpAddress.ulIpv6Addr[i]); + pstClassifierEntry->stSrcIpAddress.ulIpv6Mask[i] = ntohl(pstClassifierEntry->stSrcIpAddress.ulIpv6Mask[i]); } else if (eIpAddrContext == eDestIpAddress) { - pstClassifierEntry->stDestIpAddress.ulIpv6Addr[ucLoopIndex] = ntohl(pstClassifierEntry->stDestIpAddress.ulIpv6Addr[ucLoopIndex]); - pstClassifierEntry->stDestIpAddress.ulIpv6Mask[ucLoopIndex] = ntohl(pstClassifierEntry->stDestIpAddress.ulIpv6Mask[ucLoopIndex]); + pstClassifierEntry->stDestIpAddress.ulIpv6Addr[i] = ntohl(pstClassifierEntry->stDestIpAddress.ulIpv6Addr[i]); + pstClassifierEntry->stDestIpAddress.ulIpv6Mask[i] = ntohl(pstClassifierEntry->stDestIpAddress.ulIpv6Mask[i]); } } } @@ -216,17 +216,17 @@ CopyIpAddrToClassifier(S_CLASSIFIER_RULE *pstClassifierEntry, void ClearTargetDSXBuffer(PMINI_ADAPTER Adapter, B_UINT16 TID, BOOLEAN bFreeAll) { - ULONG ulIndex; + int i; - for (ulIndex = 0; ulIndex < Adapter->ulTotalTargetBuffersAvailable; ulIndex++) { - if (Adapter->astTargetDsxBuffer[ulIndex].valid) + for (i = 0; i < Adapter->ulTotalTargetBuffersAvailable; i++) { + if (Adapter->astTargetDsxBuffer[i].valid) continue; - if ((bFreeAll) || (Adapter->astTargetDsxBuffer[ulIndex].tid == TID)) { + if ((bFreeAll) || (Adapter->astTargetDsxBuffer[i].tid == TID)) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "ClearTargetDSXBuffer: found tid %d buffer cleared %lx\n", - TID, Adapter->astTargetDsxBuffer[ulIndex].ulTargetDsxBuffer); - Adapter->astTargetDsxBuffer[ulIndex].valid = 1; - Adapter->astTargetDsxBuffer[ulIndex].tid = 0; + TID, Adapter->astTargetDsxBuffer[i].ulTargetDsxBuffer); + Adapter->astTargetDsxBuffer[i].valid = 1; + Adapter->astTargetDsxBuffer[i].tid = 0; Adapter->ulFreeTargetBufferCnt++; } } @@ -240,7 +240,7 @@ static inline VOID CopyClassifierRuleToSF(PMINI_ADAPTER Adapter, stConvergenceSL { S_CLASSIFIER_RULE *pstClassifierEntry = NULL; /* VOID *pvPhsContext = NULL; */ - UINT ucLoopIndex = 0; + int i; /* UCHAR ucProtocolLength=0; */ /* ULONG ulPhsStatus; */ @@ -264,14 +264,14 @@ static inline VOID CopyClassifierRuleToSF(PMINI_ADAPTER Adapter, stConvergenceSL BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Destination Port Range Length:0x%X ", pstClassifierEntry->ucDestPortRangeLength); if (psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRangeLength <= MAX_PORT_RANGE) { - for (ucLoopIndex = 0; ucLoopIndex < (pstClassifierEntry->ucDestPortRangeLength); ucLoopIndex++) { - pstClassifierEntry->usDestPortRangeLo[ucLoopIndex] = *((PUSHORT)(psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange+ucLoopIndex)); - pstClassifierEntry->usDestPortRangeHi[ucLoopIndex] = - *((PUSHORT)(psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange+2+ucLoopIndex)); - pstClassifierEntry->usDestPortRangeLo[ucLoopIndex] = ntohs(pstClassifierEntry->usDestPortRangeLo[ucLoopIndex]); + for (i = 0; i < (pstClassifierEntry->ucDestPortRangeLength); i++) { + pstClassifierEntry->usDestPortRangeLo[i] = *((PUSHORT)(psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange+i)); + pstClassifierEntry->usDestPortRangeHi[i] = + *((PUSHORT)(psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange+2+i)); + pstClassifierEntry->usDestPortRangeLo[i] = ntohs(pstClassifierEntry->usDestPortRangeLo[i]); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Destination Port Range Lo:0x%X ", - pstClassifierEntry->usDestPortRangeLo[ucLoopIndex]); - pstClassifierEntry->usDestPortRangeHi[ucLoopIndex] = ntohs(pstClassifierEntry->usDestPortRangeHi[ucLoopIndex]); + pstClassifierEntry->usDestPortRangeLo[i]); + pstClassifierEntry->usDestPortRangeHi[i] = ntohs(pstClassifierEntry->usDestPortRangeHi[i]); } } else { pstClassifierEntry->ucDestPortRangeLength = 0; @@ -282,18 +282,18 @@ static inline VOID CopyClassifierRuleToSF(PMINI_ADAPTER Adapter, stConvergenceSL psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRangeLength); if (psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRangeLength <= MAX_PORT_RANGE) { pstClassifierEntry->ucSrcPortRangeLength = psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRangeLength/4; - for (ucLoopIndex = 0; ucLoopIndex < (pstClassifierEntry->ucSrcPortRangeLength); ucLoopIndex++) { - pstClassifierEntry->usSrcPortRangeLo[ucLoopIndex] = + for (i = 0; i < (pstClassifierEntry->ucSrcPortRangeLength); i++) { + pstClassifierEntry->usSrcPortRangeLo[i] = *((PUSHORT)(psfCSType->cCPacketClassificationRule. - u8ProtocolSourcePortRange+ucLoopIndex)); - pstClassifierEntry->usSrcPortRangeHi[ucLoopIndex] = + u8ProtocolSourcePortRange+i)); + pstClassifierEntry->usSrcPortRangeHi[i] = *((PUSHORT)(psfCSType->cCPacketClassificationRule. - u8ProtocolSourcePortRange+2+ucLoopIndex)); - pstClassifierEntry->usSrcPortRangeLo[ucLoopIndex] = - ntohs(pstClassifierEntry->usSrcPortRangeLo[ucLoopIndex]); + u8ProtocolSourcePortRange+2+i)); + pstClassifierEntry->usSrcPortRangeLo[i] = + ntohs(pstClassifierEntry->usSrcPortRangeLo[i]); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Source Port Range Lo:0x%X ", - pstClassifierEntry->usSrcPortRangeLo[ucLoopIndex]); - pstClassifierEntry->usSrcPortRangeHi[ucLoopIndex] = ntohs(pstClassifierEntry->usSrcPortRangeHi[ucLoopIndex]); + pstClassifierEntry->usSrcPortRangeLo[i]); + pstClassifierEntry->usSrcPortRangeHi[i] = ntohs(pstClassifierEntry->usSrcPortRangeHi[i]); } } /* Destination Ip Address and Mask */ @@ -399,7 +399,7 @@ static inline VOID DeleteClassifierRuleFromSF(PMINI_ADAPTER Adapter, UINT uiSear VOID DeleteAllClassifiersForSF(PMINI_ADAPTER Adapter, UINT uiSearchRuleIndex) { S_CLASSIFIER_RULE *pstClassifierEntry = NULL; - UINT nClassifierIndex; + int i; /* B_UINT16 u16PacketClassificationRuleIndex; */ USHORT ulVCID; /* VOID *pvPhsContext = NULL; */ @@ -410,12 +410,12 @@ VOID DeleteAllClassifiersForSF(PMINI_ADAPTER Adapter, UINT uiSearchRuleIndex) if (ulVCID == 0) return; - for (nClassifierIndex = 0; nClassifierIndex < MAX_CLASSIFIERS; nClassifierIndex++) { - if (Adapter->astClassifierTable[nClassifierIndex].usVCID_Value == ulVCID) { - pstClassifierEntry = &Adapter->astClassifierTable[nClassifierIndex]; + for (i = 0; i < MAX_CLASSIFIERS; i++) { + if (Adapter->astClassifierTable[i].usVCID_Value == ulVCID) { + pstClassifierEntry = &Adapter->astClassifierTable[i]; if (pstClassifierEntry->bUsed) - DeleteClassifierRuleFromSF(Adapter, uiSearchRuleIndex, nClassifierIndex); + DeleteClassifierRuleFromSF(Adapter, uiSearchRuleIndex, i); } } @@ -439,7 +439,7 @@ static VOID CopyToAdapter(register PMINI_ADAPTER Adapter, /* PackInfo[uiSearchRuleIndex].usVCID_Value; @@ -527,10 +527,10 @@ static VOID CopyToAdapter(register PMINI_ADAPTER Adapter, /* PackInfo[uiSearchRuleIndex].u8TrafficPriority = psfLocalSet->u8TrafficPriority; /* copy all the classifier in the Service Flow param structure */ - for (nIndex = 0; nIndex < psfLocalSet->u8TotalClassifiers; nIndex++) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Classifier index =%d", nIndex); - psfCSType = &psfLocalSet->cConvergenceSLTypes[nIndex]; - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Classifier index =%d", nIndex); + for (i = 0; i < psfLocalSet->u8TotalClassifiers; i++) { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Classifier index =%d", i); + psfCSType = &psfLocalSet->cConvergenceSLTypes[i]; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Classifier index =%d", i); if (psfCSType->cCPacketClassificationRule.u8ClassifierRulePriority) Adapter->PackInfo[uiSearchRuleIndex].bClassifierPriority = TRUE; @@ -628,8 +628,8 @@ static VOID CopyToAdapter(register PMINI_ADAPTER Adapter, /* u8TotalClassifiers; nIndex++) { - psfCSType = &psfLocalSet->cConvergenceSLTypes[nIndex]; + for (i = 0; i < psfLocalSet->u8TotalClassifiers; i++) { + psfCSType = &psfLocalSet->cConvergenceSLTypes[i]; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "psfCSType->u8PhsDSCAction : 0x%x\n", psfCSType->u8PhsDSCAction); switch (psfCSType->u8PhsDSCAction) { @@ -832,8 +832,8 @@ static VOID CopyToAdapter(register PMINI_ADAPTER Adapter, /* ulTotalTargetBuffersAvailable); - for (ulIndex = 0; ulIndex < Adapter->ulTotalTargetBuffersAvailable; ulIndex++) { - Adapter->astTargetDsxBuffer[ulIndex].ulTargetDsxBuffer = ulTargetDsxBuffersBase; - Adapter->astTargetDsxBuffer[ulIndex].valid = 1; - Adapter->astTargetDsxBuffer[ulIndex].tid = 0; + for (i = 0; i < Adapter->ulTotalTargetBuffersAvailable; i++) { + Adapter->astTargetDsxBuffer[i].ulTargetDsxBuffer = ulTargetDsxBuffersBase; + Adapter->astTargetDsxBuffer[i].valid = 1; + Adapter->astTargetDsxBuffer[i].tid = 0; ulTargetDsxBuffersBase += sizeof(stServiceFlowParamSI); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, " Target DSX Buffer %lx setup at 0x%lx", - ulIndex, Adapter->astTargetDsxBuffer[ulIndex].ulTargetDsxBuffer); + i, Adapter->astTargetDsxBuffer[i].ulTargetDsxBuffer); } Adapter->ulCurrentTargetBuffer = 0; Adapter->ulFreeTargetBufferCnt = Adapter->ulTotalTargetBuffersAvailable; -- cgit v0.10.2 From 2d9ebe77b7665a431a9816eff3eb588e05176dfa Mon Sep 17 00:00:00 2001 From: Thomas Meyer Date: Sun, 22 Jan 2012 18:29:51 +0100 Subject: Staging: bcm: Use memdup_user rather than duplicating its implementation This is a little bit restricted to reduce false positives The semantic patch that makes this change is available in scripts/coccinelle/api/memdup_user.cocci. More information about semantic patching is available at http://coccinelle.lip6.fr/ Signed-off-by: Thomas Meyer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/bcm/Bcmchar.c b/drivers/staging/bcm/Bcmchar.c index 8bf3f57..cf30592 100644 --- a/drivers/staging/bcm/Bcmchar.c +++ b/drivers/staging/bcm/Bcmchar.c @@ -728,14 +728,10 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) if (IoBuffer.InputLength > MAX_CNTL_PKT_SIZE) return -EINVAL; - pvBuffer = kmalloc(IoBuffer.InputLength, GFP_KERNEL); - if (!pvBuffer) - return -ENOMEM; - - if (copy_from_user(pvBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength)) { - kfree(pvBuffer); - return -EFAULT; - } + pvBuffer = memdup_user(IoBuffer.InputBuffer, + IoBuffer.InputLength); + if (IS_ERR(pvBuffer)) + return PTR_ERR(pvBuffer); down(&Adapter->LowPowerModeSync); Status = wait_event_interruptible_timeout(Adapter->lowpower_mode_wait_queue, @@ -1140,15 +1136,10 @@ cntrlEnd: if (IoBuffer.InputLength < sizeof(ULONG) * 2) return -EINVAL; - pvBuffer = kmalloc(IoBuffer.InputLength, GFP_KERNEL); - if (!pvBuffer) - return -ENOMEM; - - /* Get WrmBuffer structure */ - if (copy_from_user(pvBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength)) { - kfree(pvBuffer); - return -EFAULT; - } + pvBuffer = memdup_user(IoBuffer.InputBuffer, + IoBuffer.InputLength); + if (IS_ERR(pvBuffer)) + return PTR_ERR(pvBuffer); pBulkBuffer = (PBULKWRM_BUFFER)pvBuffer; @@ -1310,14 +1301,10 @@ cntrlEnd: return STATUS_FAILURE; } - pReadData = kzalloc(stNVMReadWrite.uiNumBytes, GFP_KERNEL); - if (!pReadData) - return -ENOMEM; - - if (copy_from_user(pReadData, stNVMReadWrite.pBuffer, stNVMReadWrite.uiNumBytes)) { - kfree(pReadData); - return -EFAULT; - } + pReadData = memdup_user(stNVMReadWrite.pBuffer, + stNVMReadWrite.uiNumBytes); + if (IS_ERR(pReadData)) + return PTR_ERR(pReadData); do_gettimeofday(&tv0); if (IOCTL_BCM_NVM_READ == cmd) { -- cgit v0.10.2 From d8e4cd99d5a13f65fb961e627b63ae70ab0fe951 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Thu, 9 Feb 2012 14:56:25 +0200 Subject: staging: fix the build breakage cuased by telephony drivers Fix build error caused by commit: 6222d7a17745f6e48fddda7245e4bb0d58bfeaf0 telephony: Move to staging The telephony driver was moved to staging but the Makefiles weren't updated Cc: Joe Perches Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/Makefile b/drivers/Makefile index c07be02..932e8bf 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -86,7 +86,6 @@ obj-$(CONFIG_POWER_SUPPLY) += power/ obj-$(CONFIG_HWMON) += hwmon/ obj-$(CONFIG_THERMAL) += thermal/ obj-$(CONFIG_WATCHDOG) += watchdog/ -obj-$(CONFIG_PHONE) += telephony/ obj-$(CONFIG_MD) += md/ obj-$(CONFIG_BT) += bluetooth/ obj-$(CONFIG_ACCESSIBILITY) += accessibility/ diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 31c81fa..077a3f3 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -58,3 +58,4 @@ obj-$(CONFIG_MFD_NVEC) += nvec/ obj-$(CONFIG_DRM_OMAP) += omapdrm/ obj-$(CONFIG_ANDROID) += android/ obj-$(CONFIG_RAMSTER) += ramster/ +obj-$(CONFIG_PHONE) += telephony/ -- cgit v0.10.2 From 86587b671bf87ed81d2d89cd1199af912402a05f Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Wed, 8 Feb 2012 19:42:03 -0600 Subject: staging: r8712u: Simplify semaphores I am preparing to convert this driver from semaphore to mutex locking, The first step has been to eliminate a number of semaphores that were initialized but never used, and one whose only use was a single "up" after initialization. A total of 9 semaphores were removed in this process. One other change was to remove some inline semaphore routines that were unused. In addition, several cases had the following structure: down() if () { ... } up() The locking overhead was reduced by moving the up/down inside the if block. Signed-off-by: Larry Finger Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8712/drv_types.h b/drivers/staging/rtl8712/drv_types.h index 9b5d771..0735de9 100644 --- a/drivers/staging/rtl8712/drv_types.h +++ b/drivers/staging/rtl8712/drv_types.h @@ -138,7 +138,6 @@ struct dvobj_priv { u8 ishighspeed; uint(*inirp_init)(struct _adapter *adapter); uint(*inirp_deinit)(struct _adapter *adapter); - struct semaphore usb_suspend_sema; struct usb_device *pusbdev; }; diff --git a/drivers/staging/rtl8712/os_intfs.c b/drivers/staging/rtl8712/os_intfs.c index 9a75c6d..250cd11 100644 --- a/drivers/staging/rtl8712/os_intfs.c +++ b/drivers/staging/rtl8712/os_intfs.c @@ -329,7 +329,6 @@ u8 r8712_init_drv_sw(struct _adapter *padapter) padapter->stapriv.padapter = padapter; r8712_init_bcmc_stainfo(padapter); r8712_init_pwrctrl_priv(padapter); - sema_init(&(padapter->pwrctrlpriv.pnp_pwr_mgnt_sema), 0); mp871xinit(padapter); if (init_default_value(padapter) != _SUCCESS) return _FAIL; diff --git a/drivers/staging/rtl8712/osdep_service.h b/drivers/staging/rtl8712/osdep_service.h index 1ee943a..9ba6033 100644 --- a/drivers/staging/rtl8712/osdep_service.h +++ b/drivers/staging/rtl8712/osdep_service.h @@ -72,18 +72,6 @@ static inline struct list_head *get_list_head(struct __queue *queue) #define LIST_CONTAINOR(ptr, type, member) \ ((type *)((char *)(ptr)-(SIZE_T)(&((type *)0)->member))) -static inline void _enter_hwio_critical(struct semaphore *prwlock, - unsigned long *pirqL) -{ - down(prwlock); -} - -static inline void _exit_hwio_critical(struct semaphore *prwlock, - unsigned long *pirqL) -{ - up(prwlock); -} - static inline void list_delete(struct list_head *plist) { list_del_init(plist); @@ -152,11 +140,6 @@ static inline u32 _down_sema(struct semaphore *sema) return _SUCCESS; } -static inline void _rtl_rwlock_init(struct semaphore *prwlock) -{ - sema_init(prwlock, 1); -} - static inline void _init_listhead(struct list_head *list) { INIT_LIST_HEAD(list); diff --git a/drivers/staging/rtl8712/rtl8712_recv.c b/drivers/staging/rtl8712/rtl8712_recv.c index 6d69265..fa6dc9c 100644 --- a/drivers/staging/rtl8712/rtl8712_recv.c +++ b/drivers/staging/rtl8712/rtl8712_recv.c @@ -55,8 +55,6 @@ int r8712_init_recv_priv(struct recv_priv *precvpriv, struct _adapter *padapter) int alignment = 0; struct sk_buff *pskb = NULL; - sema_init(&precvpriv->recv_sema, 0); - sema_init(&precvpriv->terminate_recvthread_sema, 0); /*init recv_buf*/ _init_queue(&precvpriv->free_recv_buf_queue); precvpriv->pallocated_recv_buf = _malloc(NR_RECVBUFF * diff --git a/drivers/staging/rtl8712/rtl871x_io.c b/drivers/staging/rtl8712/rtl871x_io.c index ca84ee0..abc1c97 100644 --- a/drivers/staging/rtl8712/rtl871x_io.c +++ b/drivers/staging/rtl8712/rtl871x_io.c @@ -131,7 +131,6 @@ uint r8712_alloc_io_queue(struct _adapter *adapter) pio_req = (struct io_req *)(pio_queue->free_ioreqs_buf); for (i = 0; i < NUM_IOREQ; i++) { _init_listhead(&pio_req->list); - sema_init(&pio_req->sema, 0); list_insert_tail(&pio_req->list, &pio_queue->free_ioreqs); pio_req++; } diff --git a/drivers/staging/rtl8712/rtl871x_io.h b/drivers/staging/rtl8712/rtl871x_io.h index 86308a0..d3d8727 100644 --- a/drivers/staging/rtl8712/rtl871x_io.h +++ b/drivers/staging/rtl8712/rtl871x_io.h @@ -117,7 +117,6 @@ struct io_req { u32 command; u32 status; u8 *pbuf; - struct semaphore sema; void (*_async_io_callback)(struct _adapter *padater, struct io_req *pio_req, u8 *cnxt); u8 *cnxt; diff --git a/drivers/staging/rtl8712/rtl871x_pwrctrl.c b/drivers/staging/rtl8712/rtl871x_pwrctrl.c index 23e72a0..9fd2ec7 100644 --- a/drivers/staging/rtl8712/rtl871x_pwrctrl.c +++ b/drivers/staging/rtl8712/rtl871x_pwrctrl.c @@ -100,7 +100,6 @@ void r8712_cpwm_int_hdl(struct _adapter *padapter, { struct pwrctrl_priv *pwrpriv = &(padapter->pwrctrlpriv); struct cmd_priv *pcmdpriv = &(padapter->cmdpriv); - struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); if (pwrpriv->cpwm_tog == ((preportpwrstate->state) & 0x80)) return; @@ -110,8 +109,6 @@ void r8712_cpwm_int_hdl(struct _adapter *padapter, if (pwrpriv->cpwm >= PS_STATE_S2) { if (pwrpriv->alives & CMD_ALIVE) up(&(pcmdpriv->cmd_queue_sema)); - if (pwrpriv->alives & XMIT_ALIVE) - up(&(pxmitpriv->xmit_sema)); } pwrpriv->cpwm_tog = (preportpwrstate->state) & 0x80; up(&pwrpriv->lock); @@ -145,12 +142,12 @@ static void SetPSModeWorkItemCallback(struct work_struct *work) struct pwrctrl_priv, SetPSModeWorkItem); struct _adapter *padapter = container_of(pwrpriv, struct _adapter, pwrctrlpriv); - _enter_pwrlock(&pwrpriv->lock); if (!pwrpriv->bSleep) { + _enter_pwrlock(&pwrpriv->lock); if (pwrpriv->pwr_mode == PS_MODE_ACTIVE) r8712_set_rpwm(padapter, PS_STATE_S4); + up(&pwrpriv->lock); } - up(&pwrpriv->lock); } static void rpwm_workitem_callback(struct work_struct *work) @@ -160,13 +157,13 @@ static void rpwm_workitem_callback(struct work_struct *work) struct _adapter *padapter = container_of(pwrpriv, struct _adapter, pwrctrlpriv); u8 cpwm = pwrpriv->cpwm; - _enter_pwrlock(&pwrpriv->lock); if (pwrpriv->cpwm != pwrpriv->rpwm) { + _enter_pwrlock(&pwrpriv->lock); cpwm = r8712_read8(padapter, SDIO_HCPWM); pwrpriv->rpwm_retry = 1; r8712_set_rpwm(padapter, pwrpriv->rpwm); + up(&pwrpriv->lock); } - up(&pwrpriv->lock); } static void rpwm_check_handler (void *FunctionContext) diff --git a/drivers/staging/rtl8712/rtl871x_pwrctrl.h b/drivers/staging/rtl8712/rtl871x_pwrctrl.h index b41ca28..6024c4f 100644 --- a/drivers/staging/rtl8712/rtl871x_pwrctrl.h +++ b/drivers/staging/rtl8712/rtl871x_pwrctrl.h @@ -133,7 +133,6 @@ struct pwrctrl_priv { u8 rpwm_retry; uint bSetPSModeWorkItemInProgress; - struct semaphore pnp_pwr_mgnt_sema; spinlock_t pnp_pwr_mgnt_lock; s32 pnp_current_pwr_state; u8 pnp_bstop_trx; diff --git a/drivers/staging/rtl8712/rtl871x_recv.c b/drivers/staging/rtl8712/rtl871x_recv.c index 7069f06..5b03b40 100644 --- a/drivers/staging/rtl8712/rtl871x_recv.c +++ b/drivers/staging/rtl8712/rtl871x_recv.c @@ -93,7 +93,6 @@ sint _r8712_init_recv_priv(struct recv_priv *precvpriv, precvframe++; } precvpriv->rx_pending_cnt = 1; - sema_init(&precvpriv->allrxreturnevt, 0); return r8712_init_recv_priv(precvpriv, padapter); } diff --git a/drivers/staging/rtl8712/rtl871x_recv.h b/drivers/staging/rtl8712/rtl871x_recv.h index cc7a72f..e42e6f0 100644 --- a/drivers/staging/rtl8712/rtl871x_recv.h +++ b/drivers/staging/rtl8712/rtl871x_recv.h @@ -85,8 +85,6 @@ using enter_critical section to protect */ struct recv_priv { spinlock_t lock; - struct semaphore recv_sema; - struct semaphore terminate_recvthread_sema; struct __queue free_recv_queue; struct __queue recv_pending_queue; u8 *pallocated_frame_buf; @@ -100,7 +98,6 @@ struct recv_priv { uint rx_largepacket_crcerr; uint rx_smallpacket_crcerr; uint rx_middlepacket_crcerr; - struct semaphore allrxreturnevt; u8 rx_pending_cnt; uint ff_hwaddr; struct tasklet_struct recv_tasklet; diff --git a/drivers/staging/rtl8712/rtl871x_xmit.c b/drivers/staging/rtl8712/rtl871x_xmit.c index 8bbdee7..aa57e77 100644 --- a/drivers/staging/rtl8712/rtl871x_xmit.c +++ b/drivers/staging/rtl8712/rtl871x_xmit.c @@ -71,8 +71,6 @@ sint _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv, memset((unsigned char *)pxmitpriv, 0, sizeof(struct xmit_priv)); spin_lock_init(&pxmitpriv->lock); - sema_init(&pxmitpriv->xmit_sema, 0); - sema_init(&pxmitpriv->terminate_xmitthread_sema, 0); /* Please insert all the queue initializaiton using _init_queue below */ @@ -121,7 +119,6 @@ sint _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv, _r8712_init_hw_txqueue(&pxmitpriv->bmc_txqueue, BMC_QUEUE_INX); pxmitpriv->frag_len = MAX_FRAG_THRESHOLD; pxmitpriv->txirp_cnt = 1; - sema_init(&(pxmitpriv->tx_retevt), 0); /*per AC pending irp*/ pxmitpriv->beq_cnt = 0; pxmitpriv->bkq_cnt = 0; diff --git a/drivers/staging/rtl8712/rtl871x_xmit.h b/drivers/staging/rtl8712/rtl871x_xmit.h index a034c0f..638b79b 100644 --- a/drivers/staging/rtl8712/rtl871x_xmit.h +++ b/drivers/staging/rtl8712/rtl871x_xmit.h @@ -202,8 +202,6 @@ struct hw_txqueue { struct xmit_priv { spinlock_t lock; - struct semaphore xmit_sema; - struct semaphore terminate_xmitthread_sema; struct __queue be_pending; struct __queue bk_pending; struct __queue vi_pending; @@ -233,7 +231,6 @@ struct xmit_priv { uint tx_drop; struct hw_xmit *hwxmits; u8 hwxmit_entry; - struct semaphore tx_retevt;/*all tx return event;*/ u8 txirp_cnt; struct tasklet_struct xmit_tasklet; _workitem xmit_pipe4_reset_wi; diff --git a/drivers/staging/rtl8712/usb_intf.c b/drivers/staging/rtl8712/usb_intf.c index 5385da2..01378ea 100644 --- a/drivers/staging/rtl8712/usb_intf.c +++ b/drivers/staging/rtl8712/usb_intf.c @@ -280,7 +280,6 @@ static uint r8712_usb_dvobj_init(struct _adapter *padapter) } if ((r8712_alloc_io_queue(padapter)) == _FAIL) status = _FAIL; - sema_init(&(padapter->dvobjpriv.usb_suspend_sema), 0); return status; } -- cgit v0.10.2 From a2f9dc55345baff05378c23de6e9e026f6838556 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Thu, 12 Jan 2012 22:49:27 +0100 Subject: drivers/staging: adjust double test Rewrite a duplicated test to test the correct value The semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @@ expression E; @@ ( * E || ... || E | * E && ... && E ) // Signed-off-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8192e/rtllib_rx.c b/drivers/staging/rtl8192e/rtllib_rx.c index 6c5061f..13979b5 100644 --- a/drivers/staging/rtl8192e/rtllib_rx.c +++ b/drivers/staging/rtl8192e/rtllib_rx.c @@ -2453,7 +2453,7 @@ static inline void update_network(struct rtllib_network *dst, if (src->wmm_param[0].ac_aci_acm_aifsn || src->wmm_param[1].ac_aci_acm_aifsn || src->wmm_param[2].ac_aci_acm_aifsn || - src->wmm_param[1].ac_aci_acm_aifsn) + src->wmm_param[3].ac_aci_acm_aifsn) memcpy(dst->wmm_param, src->wmm_param, WME_AC_PRAM_LEN); dst->SignalStrength = src->SignalStrength; -- cgit v0.10.2 From 2da57c8e4ac0933417f9fdd141bf5bebc87edc1e Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sun, 15 Jan 2012 14:29:39 +0300 Subject: staging: precedence bug in crystalhd_stop_tx_dma_engine() The intent here is to see if we have cleared the DMA_START_BIT flag. We clear it a couple lines later. The current code has a precedence bug so it is equivalent to "if (!dma_cntrl) { ...". Signed-off-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/crystalhd/crystalhd_hw.c b/drivers/staging/crystalhd/crystalhd_hw.c index 5acf39e..eeddee9 100644 --- a/drivers/staging/crystalhd/crystalhd_hw.c +++ b/drivers/staging/crystalhd/crystalhd_hw.c @@ -868,8 +868,7 @@ static enum BC_STATUS crystalhd_stop_tx_dma_engine(struct crystalhd_hw *hw) BCMLOG(BCMLOG_DBG, "Stopping TX DMA Engine..\n"); - /* FIXME: jarod: invert dma_ctrl and check bit? or are there missing parens? */ - if (!dma_cntrl & DMA_START_BIT) { + if (!(dma_cntrl & DMA_START_BIT)) { BCMLOG(BCMLOG_DBG, "Already Stopped\n"); return BC_STS_SUCCESS; } -- cgit v0.10.2 From 3784129a9de3fc33ffe6c6ece906a9caa1c65fab Mon Sep 17 00:00:00 2001 From: Markus Grabner Date: Fri, 20 Jan 2012 00:09:07 +0100 Subject: staging: line6: removed obsolete code Signed-off-by: Markus Grabner Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/line6/pcm.h b/drivers/staging/line6/pcm.h index 55d8297..47c6d69 100644 --- a/drivers/staging/line6/pcm.h +++ b/drivers/staging/line6/pcm.h @@ -305,13 +305,4 @@ extern void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm); extern int line6_pcm_start(struct snd_line6_pcm *line6pcm, int channels); extern int line6_pcm_stop(struct snd_line6_pcm *line6pcm, int channels); -#define PRINT_FRAME_DIFF(op) { \ - static int diff_prev = 1000; \ - int diff = line6pcm->last_frame_out - line6pcm->last_frame_in; \ - if ((diff != diff_prev) && (abs(diff) < 100)) { \ - printk(KERN_INFO "%s frame diff = %d\n", op, diff); \ - diff_prev = diff; \ - } \ -} - #endif -- cgit v0.10.2 From 12177acdecfcb538b86590036a56fc47b443e135 Mon Sep 17 00:00:00 2001 From: Markus Grabner Date: Fri, 20 Jan 2012 00:09:08 +0100 Subject: staging: line6: use source select control for UX2 devices Signed-off-by: Markus Grabner Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/line6/toneport.c b/drivers/staging/line6/toneport.c index f310578..b776130 100644 --- a/drivers/staging/line6/toneport.c +++ b/drivers/staging/line6/toneport.c @@ -320,7 +320,9 @@ static void toneport_setup(struct usb_line6_toneport *toneport) /* initialize source select: */ switch (usbdev->descriptor.idProduct) { case LINE6_DEVID_TONEPORT_UX1: + case LINE6_DEVID_TONEPORT_UX2: case LINE6_DEVID_PODSTUDIO_UX1: + case LINE6_DEVID_PODSTUDIO_UX2: toneport_send_cmd(usbdev, toneport_source_info[toneport->source].code, 0x0000); @@ -363,7 +365,9 @@ static int toneport_try_init(struct usb_interface *interface, /* register source select control: */ switch (usbdev->descriptor.idProduct) { case LINE6_DEVID_TONEPORT_UX1: + case LINE6_DEVID_TONEPORT_UX2: case LINE6_DEVID_PODSTUDIO_UX1: + case LINE6_DEVID_PODSTUDIO_UX2: err = snd_ctl_add(line6->card, snd_ctl_new1(&toneport_control_source, -- cgit v0.10.2 From 0ca54888060135806d5567f47a6ad54be5297b34 Mon Sep 17 00:00:00 2001 From: Markus Grabner Date: Fri, 20 Jan 2012 00:09:09 +0100 Subject: staging: line6: separate handling of buffer allocation and stream startup There are several features of the Line6 USB driver which require PCM data to be exchanged with the device: *) PCM playback and capture via ALSA *) software monitoring (for devices without hardware monitoring) *) optional impulse response measurement However, from the device's point of view, there is just a single capture and playback stream, which must be shared between these subsystems. It is therefore necessary to maintain the state of the subsystems with respect to PCM usage. We define several constants of the form LINE6_BIT_PCM___ with the following meanings: *) is one of -) ALSA: PCM playback and capture via ALSA -) MONITOR: software monitoring -) IMPULSE: optional impulse response measurement *) is one of -) PLAYBACK: audio output (from host to device) -) CAPTURE: audio input (from device to host) *) is one of -) BUFFER: buffer required by PCM data stream -) STREAM: actual PCM data stream The subsystems call line6_pcm_acquire() to acquire the (shared) resources needed for a particular operation (e.g., allocate the buffer for ALSA playback or start the capture stream for software monitoring). When a resource is no longer needed, it is released by calling line6_pcm_release(). Buffer allocation and stream startup are handled separately to allow the ALSA kernel driver to perform them at appropriate places (since the callback which starts a PCM stream is not allowed to sleep). Signed-off-by: Markus Grabner Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/line6/capture.c b/drivers/staging/line6/capture.c index 127f952..c85c5b6 100644 --- a/drivers/staging/line6/capture.c +++ b/drivers/staging/line6/capture.c @@ -107,7 +107,7 @@ void line6_unlink_audio_in_urbs(struct snd_line6_pcm *line6pcm) Wait until unlinking of all currently active capture URBs has been finished. */ -static void wait_clear_audio_in_urbs(struct snd_line6_pcm *line6pcm) +void line6_wait_clear_audio_in_urbs(struct snd_line6_pcm *line6pcm) { int timeout = HZ; unsigned int i; @@ -134,7 +134,7 @@ static void wait_clear_audio_in_urbs(struct snd_line6_pcm *line6pcm) void line6_unlink_wait_clear_audio_in_urbs(struct snd_line6_pcm *line6pcm) { line6_unlink_audio_in_urbs(line6pcm); - wait_clear_audio_in_urbs(line6pcm); + line6_wait_clear_audio_in_urbs(line6pcm); } /* @@ -193,25 +193,6 @@ void line6_capture_check_period(struct snd_line6_pcm *line6pcm, int length) } } -int line6_alloc_capture_buffer(struct snd_line6_pcm *line6pcm) -{ - /* We may be invoked multiple times in a row so allocate once only */ - if (line6pcm->buffer_in) - return 0; - - line6pcm->buffer_in = - kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS * - line6pcm->max_packet_size, GFP_KERNEL); - - if (!line6pcm->buffer_in) { - dev_err(line6pcm->line6->ifcdev, - "cannot malloc capture buffer\n"); - return -ENOMEM; - } - - return 0; -} - void line6_free_capture_buffer(struct snd_line6_pcm *line6pcm) { kfree(line6pcm->buffer_in); @@ -273,9 +254,9 @@ static void audio_in_callback(struct urb *urb) line6pcm->prev_fsize = fsize; #ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE - if (!(line6pcm->flags & MASK_PCM_IMPULSE)) + if (!(line6pcm->flags & LINE6_BITS_PCM_IMPULSE)) #endif - if (test_bit(BIT_PCM_ALSA_CAPTURE, &line6pcm->flags) + if (test_bit(LINE6_INDEX_PCM_ALSA_CAPTURE_STREAM, &line6pcm->flags) && (fsize > 0)) line6_capture_copy(line6pcm, fbuf, fsize); } @@ -291,9 +272,9 @@ static void audio_in_callback(struct urb *urb) submit_audio_in_urb(line6pcm); #ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE - if (!(line6pcm->flags & MASK_PCM_IMPULSE)) + if (!(line6pcm->flags & LINE6_BITS_PCM_IMPULSE)) #endif - if (test_bit(BIT_PCM_ALSA_CAPTURE, &line6pcm->flags)) + if (test_bit(LINE6_INDEX_PCM_ALSA_CAPTURE_STREAM, &line6pcm->flags)) line6_capture_check_period(line6pcm, length); } } @@ -341,17 +322,17 @@ static int snd_line6_capture_hw_params(struct snd_pcm_substream *substream, } /* -- [FD] end */ - if ((line6pcm->flags & MASK_CAPTURE) == 0) { - ret = line6_alloc_capture_buffer(line6pcm); + ret = line6_pcm_acquire(line6pcm, LINE6_BIT_PCM_ALSA_CAPTURE_BUFFER); - if (ret < 0) - return ret; - } + if (ret < 0) + return ret; ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); - if (ret < 0) + if (ret < 0) { + line6_pcm_release(line6pcm, LINE6_BIT_PCM_ALSA_CAPTURE_BUFFER); return ret; + } line6pcm->period_in = params_period_bytes(hw_params); return 0; @@ -361,12 +342,7 @@ static int snd_line6_capture_hw_params(struct snd_pcm_substream *substream, static int snd_line6_capture_hw_free(struct snd_pcm_substream *substream) { struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); - - if ((line6pcm->flags & MASK_CAPTURE) == 0) { - line6_unlink_wait_clear_audio_in_urbs(line6pcm); - line6_free_capture_buffer(line6pcm); - } - + line6_pcm_release(line6pcm, LINE6_BIT_PCM_ALSA_CAPTURE_BUFFER); return snd_pcm_lib_free_pages(substream); } @@ -380,7 +356,7 @@ int snd_line6_capture_trigger(struct snd_line6_pcm *line6pcm, int cmd) #ifdef CONFIG_PM case SNDRV_PCM_TRIGGER_RESUME: #endif - err = line6_pcm_start(line6pcm, MASK_PCM_ALSA_CAPTURE); + err = line6_pcm_acquire(line6pcm, LINE6_BIT_PCM_ALSA_CAPTURE_STREAM); if (err < 0) return err; @@ -391,7 +367,7 @@ int snd_line6_capture_trigger(struct snd_line6_pcm *line6pcm, int cmd) #ifdef CONFIG_PM case SNDRV_PCM_TRIGGER_SUSPEND: #endif - err = line6_pcm_stop(line6pcm, MASK_PCM_ALSA_CAPTURE); + err = line6_pcm_release(line6pcm, LINE6_BIT_PCM_ALSA_CAPTURE_STREAM); if (err < 0) return err; diff --git a/drivers/staging/line6/capture.h b/drivers/staging/line6/capture.h index 366cbaa..4157bcb 100644 --- a/drivers/staging/line6/capture.h +++ b/drivers/staging/line6/capture.h @@ -19,7 +19,6 @@ extern struct snd_pcm_ops snd_line6_capture_ops; -extern int line6_alloc_capture_buffer(struct snd_line6_pcm *line6pcm); extern void line6_capture_copy(struct snd_line6_pcm *line6pcm, char *fbuf, int fsize); extern void line6_capture_check_period(struct snd_line6_pcm *line6pcm, @@ -30,6 +29,7 @@ extern int line6_submit_audio_in_all_urbs(struct snd_line6_pcm *line6pcm); extern void line6_unlink_audio_in_urbs(struct snd_line6_pcm *line6pcm); extern void line6_unlink_wait_clear_audio_in_urbs(struct snd_line6_pcm *line6pcm); +extern void line6_wait_clear_audio_in_urbs(struct snd_line6_pcm *line6pcm); extern int snd_line6_capture_trigger(struct snd_line6_pcm *line6pcm, int cmd); #endif diff --git a/drivers/staging/line6/driver.c b/drivers/staging/line6/driver.c index 6a1959e..e8023af 100644 --- a/drivers/staging/line6/driver.c +++ b/drivers/staging/line6/driver.c @@ -1346,7 +1346,7 @@ static void __exit line6_exit(void) if (line6pcm == NULL) continue; - line6_pcm_stop(line6pcm, ~0); + line6_pcm_release(line6pcm, ~0); } usb_deregister(&line6_driver); diff --git a/drivers/staging/line6/pcm.c b/drivers/staging/line6/pcm.c index 37675e6..90d2d44 100644 --- a/drivers/staging/line6/pcm.c +++ b/drivers/staging/line6/pcm.c @@ -52,9 +52,9 @@ static ssize_t pcm_set_impulse_volume(struct device *dev, line6pcm->impulse_volume = value; if (value > 0) - line6_pcm_start(line6pcm, MASK_PCM_IMPULSE); + line6_pcm_acquire(line6pcm, LINE6_BITS_PCM_IMPULSE); else - line6_pcm_stop(line6pcm, MASK_PCM_IMPULSE); + line6_pcm_release(line6pcm, LINE6_BITS_PCM_IMPULSE); return count; } @@ -92,29 +92,43 @@ static bool test_flags(unsigned long flags0, unsigned long flags1, return ((flags0 & mask) == 0) && ((flags1 & mask) != 0); } -int line6_pcm_start(struct snd_line6_pcm *line6pcm, int channels) +int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int channels) { unsigned long flags_old = __sync_fetch_and_or(&line6pcm->flags, channels); unsigned long flags_new = flags_old | channels; + unsigned long flags_final = flags_old; int err = 0; line6pcm->prev_fbuf = NULL; - if (test_flags(flags_old, flags_new, MASK_CAPTURE)) { + if (test_flags(flags_old, flags_new, LINE6_BITS_CAPTURE_BUFFER)) { + /* We may be invoked multiple times in a row so allocate once only */ + if (!line6pcm->buffer_in) { + line6pcm->buffer_in = + kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS * + line6pcm->max_packet_size, GFP_KERNEL); + + if (!line6pcm->buffer_in) { + dev_err(line6pcm->line6->ifcdev, + "cannot malloc capture buffer\n"); + err = -ENOMEM; + goto pcm_acquire_error; + } + + flags_final |= channels & LINE6_BITS_CAPTURE_BUFFER; + } + } + + if (test_flags(flags_old, flags_new, LINE6_BITS_CAPTURE_STREAM)) { /* Waiting for completion of active URBs in the stop handler is a bug, we therefore report an error if capturing is restarted too soon. */ - if (line6pcm->active_urb_in | line6pcm->unlink_urb_in) + if (line6pcm->active_urb_in | line6pcm->unlink_urb_in) { + dev_err(line6pcm->line6->ifcdev, "Device not yet ready\n"); return -EBUSY; - - if (!(flags_new & MASK_PCM_ALSA_CAPTURE)) { - err = line6_alloc_capture_buffer(line6pcm); - - if (err < 0) - goto pcm_start_error; } line6pcm->count_in = 0; @@ -122,55 +136,78 @@ int line6_pcm_start(struct snd_line6_pcm *line6pcm, int channels) err = line6_submit_audio_in_all_urbs(line6pcm); if (err < 0) - goto pcm_start_error; + goto pcm_acquire_error; + + flags_final |= channels & LINE6_BITS_CAPTURE_STREAM; } - if (test_flags(flags_old, flags_new, MASK_PLAYBACK)) { - /* - See comment above regarding PCM restart. - */ - if (line6pcm->active_urb_out | line6pcm->unlink_urb_out) - return -EBUSY; + if (test_flags(flags_old, flags_new, LINE6_BITS_PLAYBACK_BUFFER)) { + /* We may be invoked multiple times in a row so allocate once only */ + if (!line6pcm->buffer_out) { + line6pcm->buffer_out = + kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS * + line6pcm->max_packet_size, GFP_KERNEL); + + if (!line6pcm->buffer_out) { + dev_err(line6pcm->line6->ifcdev, + "cannot malloc playback buffer\n"); + err = -ENOMEM; + goto pcm_acquire_error; + } - if (!(flags_new & MASK_PCM_ALSA_PLAYBACK)) { - err = line6_alloc_playback_buffer(line6pcm); + flags_final |= channels & LINE6_BITS_PLAYBACK_BUFFER; + } + } - if (err < 0) - goto pcm_start_error; + if (test_flags(flags_old, flags_new, LINE6_BITS_PLAYBACK_STREAM)) { + /* + See comment above regarding PCM restart. + */ + if (line6pcm->active_urb_out | line6pcm->unlink_urb_out) { + dev_err(line6pcm->line6->ifcdev, "Device not yet ready\n"); + return -EBUSY; } line6pcm->count_out = 0; err = line6_submit_audio_out_all_urbs(line6pcm); if (err < 0) - goto pcm_start_error; + goto pcm_acquire_error; + + flags_final |= channels & LINE6_BITS_PLAYBACK_STREAM; } return 0; -pcm_start_error: - __sync_fetch_and_and(&line6pcm->flags, ~channels); +pcm_acquire_error: + /* + If not all requested resources/streams could be obtained, release + those which were successfully obtained (if any). + */ + line6_pcm_release(line6pcm, flags_final & channels); return err; } -int line6_pcm_stop(struct snd_line6_pcm *line6pcm, int channels) +int line6_pcm_release(struct snd_line6_pcm *line6pcm, int channels) { unsigned long flags_old = __sync_fetch_and_and(&line6pcm->flags, ~channels); unsigned long flags_new = flags_old & ~channels; - if (test_flags(flags_new, flags_old, MASK_CAPTURE)) { + if (test_flags(flags_new, flags_old, LINE6_BITS_CAPTURE_STREAM)) line6_unlink_audio_in_urbs(line6pcm); - if (!(flags_old & MASK_PCM_ALSA_CAPTURE)) - line6_free_capture_buffer(line6pcm); + if (test_flags(flags_new, flags_old, LINE6_BITS_CAPTURE_BUFFER)) { + line6_wait_clear_audio_in_urbs(line6pcm); + line6_free_capture_buffer(line6pcm); } - if (test_flags(flags_new, flags_old, MASK_PLAYBACK)) { + if (test_flags(flags_new, flags_old, LINE6_BITS_PLAYBACK_STREAM)) line6_unlink_audio_out_urbs(line6pcm); - if (!(flags_old & MASK_PCM_ALSA_PLAYBACK)) - line6_free_playback_buffer(line6pcm); + if (test_flags(flags_new, flags_old, LINE6_BITS_PLAYBACK_BUFFER)) { + line6_wait_clear_audio_out_urbs(line6pcm); + line6_free_playback_buffer(line6pcm); } return 0; @@ -185,7 +222,7 @@ int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd) unsigned long flags; spin_lock_irqsave(&line6pcm->lock_trigger, flags); - clear_bit(BIT_PREPARED, &line6pcm->flags); + clear_bit(LINE6_INDEX_PREPARED, &line6pcm->flags); snd_pcm_group_for_each_entry(s, substream) { switch (s->stream) { @@ -498,13 +535,13 @@ int snd_line6_prepare(struct snd_pcm_substream *substream) switch (substream->stream) { case SNDRV_PCM_STREAM_PLAYBACK: - if ((line6pcm->flags & MASK_PLAYBACK) == 0) + if ((line6pcm->flags & LINE6_BITS_PLAYBACK_STREAM) == 0) line6_unlink_wait_clear_audio_out_urbs(line6pcm); break; case SNDRV_PCM_STREAM_CAPTURE: - if ((line6pcm->flags & MASK_CAPTURE) == 0) + if ((line6pcm->flags & LINE6_BITS_CAPTURE_STREAM) == 0) line6_unlink_wait_clear_audio_in_urbs(line6pcm); break; @@ -513,7 +550,7 @@ int snd_line6_prepare(struct snd_pcm_substream *substream) MISSING_CASE; } - if (!test_and_set_bit(BIT_PREPARED, &line6pcm->flags)) { + if (!test_and_set_bit(LINE6_INDEX_PREPARED, &line6pcm->flags)) { line6pcm->count_out = 0; line6pcm->pos_out = 0; line6pcm->pos_out_done = 0; diff --git a/drivers/staging/line6/pcm.h b/drivers/staging/line6/pcm.h index 47c6d69..5210ec8 100644 --- a/drivers/staging/line6/pcm.h +++ b/drivers/staging/line6/pcm.h @@ -46,57 +46,131 @@ (line6pcm->pcm->streams[stream].substream) /* - PCM mode bits and masks. - "ALSA": operations triggered by applications via ALSA - "MONITOR": software monitoring - "IMPULSE": optional impulse response operation + PCM mode bits. + + There are several features of the Line6 USB driver which require PCM + data to be exchanged with the device: + *) PCM playback and capture via ALSA + *) software monitoring (for devices without hardware monitoring) + *) optional impulse response measurement + However, from the device's point of view, there is just a single + capture and playback stream, which must be shared between these + subsystems. It is therefore necessary to maintain the state of the + subsystems with respect to PCM usage. We define several constants of + the form LINE6_BIT_PCM___ with the + following meanings: + *) is one of + -) ALSA: PCM playback and capture via ALSA + -) MONITOR: software monitoring + -) IMPULSE: optional impulse response measurement + *) is one of + -) PLAYBACK: audio output (from host to device) + -) CAPTURE: audio input (from device to host) + *) is one of + -) BUFFER: buffer required by PCM data stream + -) STREAM: actual PCM data stream + + The subsystems call line6_pcm_acquire() to acquire the (shared) + resources needed for a particular operation (e.g., allocate the buffer + for ALSA playback or start the capture stream for software monitoring). + When a resource is no longer needed, it is released by calling + line6_pcm_release(). Buffer allocation and stream startup are handled + separately to allow the ALSA kernel driver to perform them at + appropriate places (since the callback which starts a PCM stream is not + allowed to sleep). */ enum { - /* individual bits: */ - BIT_PCM_ALSA_PLAYBACK, - BIT_PCM_ALSA_CAPTURE, - BIT_PCM_MONITOR_PLAYBACK, - BIT_PCM_MONITOR_CAPTURE, + /* individual bit indices: */ + LINE6_INDEX_PCM_ALSA_PLAYBACK_BUFFER, + LINE6_INDEX_PCM_ALSA_PLAYBACK_STREAM, + LINE6_INDEX_PCM_ALSA_CAPTURE_BUFFER, + LINE6_INDEX_PCM_ALSA_CAPTURE_STREAM, + LINE6_INDEX_PCM_MONITOR_PLAYBACK_BUFFER, + LINE6_INDEX_PCM_MONITOR_PLAYBACK_STREAM, + LINE6_INDEX_PCM_MONITOR_CAPTURE_BUFFER, + LINE6_INDEX_PCM_MONITOR_CAPTURE_STREAM, #ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE - BIT_PCM_IMPULSE_PLAYBACK, - BIT_PCM_IMPULSE_CAPTURE, + LINE6_INDEX_PCM_IMPULSE_PLAYBACK_BUFFER, + LINE6_INDEX_PCM_IMPULSE_PLAYBACK_STREAM, + LINE6_INDEX_PCM_IMPULSE_CAPTURE_BUFFER, + LINE6_INDEX_PCM_IMPULSE_CAPTURE_STREAM, #endif - BIT_PAUSE_PLAYBACK, - BIT_PREPARED, - - /* individual masks: */ -/* *INDENT-OFF* */ - MASK_PCM_ALSA_PLAYBACK = 1 << BIT_PCM_ALSA_PLAYBACK, - MASK_PCM_ALSA_CAPTURE = 1 << BIT_PCM_ALSA_CAPTURE, - MASK_PCM_MONITOR_PLAYBACK = 1 << BIT_PCM_MONITOR_PLAYBACK, - MASK_PCM_MONITOR_CAPTURE = 1 << BIT_PCM_MONITOR_CAPTURE, + LINE6_INDEX_PAUSE_PLAYBACK, + LINE6_INDEX_PREPARED, + + /* individual bit masks: */ + LINE6_BIT(PCM_ALSA_PLAYBACK_BUFFER), + LINE6_BIT(PCM_ALSA_PLAYBACK_STREAM), + LINE6_BIT(PCM_ALSA_CAPTURE_BUFFER), + LINE6_BIT(PCM_ALSA_CAPTURE_STREAM), + LINE6_BIT(PCM_MONITOR_PLAYBACK_BUFFER), + LINE6_BIT(PCM_MONITOR_PLAYBACK_STREAM), + LINE6_BIT(PCM_MONITOR_CAPTURE_BUFFER), + LINE6_BIT(PCM_MONITOR_CAPTURE_STREAM), #ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE - MASK_PCM_IMPULSE_PLAYBACK = 1 << BIT_PCM_IMPULSE_PLAYBACK, - MASK_PCM_IMPULSE_CAPTURE = 1 << BIT_PCM_IMPULSE_CAPTURE, + LINE6_BIT(PCM_IMPULSE_PLAYBACK_BUFFER), + LINE6_BIT(PCM_IMPULSE_PLAYBACK_STREAM), + LINE6_BIT(PCM_IMPULSE_CAPTURE_BUFFER), + LINE6_BIT(PCM_IMPULSE_CAPTURE_STREAM), #endif - MASK_PAUSE_PLAYBACK = 1 << BIT_PAUSE_PLAYBACK, - MASK_PREPARED = 1 << BIT_PREPARED, -/* *INDENT-ON* */ + LINE6_BIT(PAUSE_PLAYBACK), + LINE6_BIT(PREPARED), - /* combined masks (by operation): */ - MASK_PCM_ALSA = MASK_PCM_ALSA_PLAYBACK | MASK_PCM_ALSA_CAPTURE, - MASK_PCM_MONITOR = MASK_PCM_MONITOR_PLAYBACK | MASK_PCM_MONITOR_CAPTURE, + /* combined bit masks (by operation): */ + LINE6_BITS_PCM_ALSA_BUFFER = + LINE6_BIT_PCM_ALSA_PLAYBACK_BUFFER | + LINE6_BIT_PCM_ALSA_CAPTURE_BUFFER, + + LINE6_BITS_PCM_ALSA_STREAM = + LINE6_BIT_PCM_ALSA_PLAYBACK_STREAM | + LINE6_BIT_PCM_ALSA_CAPTURE_STREAM, + + LINE6_BITS_PCM_MONITOR = + LINE6_BIT_PCM_MONITOR_PLAYBACK_BUFFER | + LINE6_BIT_PCM_MONITOR_PLAYBACK_STREAM | + LINE6_BIT_PCM_MONITOR_CAPTURE_BUFFER | + LINE6_BIT_PCM_MONITOR_CAPTURE_STREAM, + +#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE + LINE6_BITS_PCM_IMPULSE = + LINE6_BIT_PCM_IMPULSE_PLAYBACK_BUFFER | + LINE6_BIT_PCM_IMPULSE_PLAYBACK_STREAM | + LINE6_BIT_PCM_IMPULSE_CAPTURE_BUFFER | + LINE6_BIT_PCM_IMPULSE_CAPTURE_STREAM, +#endif + + /* combined bit masks (by direction): */ + LINE6_BITS_PLAYBACK_BUFFER = +#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE + LINE6_BIT_PCM_IMPULSE_PLAYBACK_BUFFER | +#endif + LINE6_BIT_PCM_ALSA_PLAYBACK_BUFFER | + LINE6_BIT_PCM_MONITOR_PLAYBACK_BUFFER , + + LINE6_BITS_PLAYBACK_STREAM = +#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE + LINE6_BIT_PCM_IMPULSE_PLAYBACK_STREAM | +#endif + LINE6_BIT_PCM_ALSA_PLAYBACK_STREAM | + LINE6_BIT_PCM_MONITOR_PLAYBACK_STREAM , + + LINE6_BITS_CAPTURE_BUFFER = #ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE - MASK_PCM_IMPULSE = MASK_PCM_IMPULSE_PLAYBACK | MASK_PCM_IMPULSE_CAPTURE, + LINE6_BIT_PCM_IMPULSE_CAPTURE_BUFFER | #endif + LINE6_BIT_PCM_ALSA_CAPTURE_BUFFER | + LINE6_BIT_PCM_MONITOR_CAPTURE_BUFFER , - /* combined masks (by direction): */ + LINE6_BITS_CAPTURE_STREAM = #ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE - MASK_PLAYBACK = - MASK_PCM_ALSA_PLAYBACK | MASK_PCM_MONITOR_PLAYBACK | - MASK_PCM_IMPULSE_PLAYBACK, - MASK_CAPTURE = - MASK_PCM_ALSA_CAPTURE | MASK_PCM_MONITOR_CAPTURE | - MASK_PCM_IMPULSE_CAPTURE -#else - MASK_PLAYBACK = MASK_PCM_ALSA_PLAYBACK | MASK_PCM_MONITOR_PLAYBACK, - MASK_CAPTURE = MASK_PCM_ALSA_CAPTURE | MASK_PCM_MONITOR_CAPTURE + LINE6_BIT_PCM_IMPULSE_CAPTURE_STREAM | #endif + LINE6_BIT_PCM_ALSA_CAPTURE_STREAM | + LINE6_BIT_PCM_MONITOR_CAPTURE_STREAM, + + LINE6_BITS_STREAM = + LINE6_BITS_PLAYBACK_STREAM | + LINE6_BITS_CAPTURE_STREAM }; struct line6_pcm_properties { @@ -290,7 +364,7 @@ struct snd_line6_pcm { #endif /** - Several status bits (see BIT_*). + Several status bits (see LINE6_BIT_*). */ unsigned long flags; @@ -302,7 +376,7 @@ extern int line6_init_pcm(struct usb_line6 *line6, extern int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd); extern int snd_line6_prepare(struct snd_pcm_substream *substream); extern void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm); -extern int line6_pcm_start(struct snd_line6_pcm *line6pcm, int channels); -extern int line6_pcm_stop(struct snd_line6_pcm *line6pcm, int channels); +extern int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int channels); +extern int line6_pcm_release(struct snd_line6_pcm *line6pcm, int channels); #endif diff --git a/drivers/staging/line6/playback.c b/drivers/staging/line6/playback.c index 4152db2..a0ab9d0 100644 --- a/drivers/staging/line6/playback.c +++ b/drivers/staging/line6/playback.c @@ -166,7 +166,7 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm) struct usb_iso_packet_descriptor *fout = &urb_out->iso_frame_desc[i]; - if (line6pcm->flags & MASK_CAPTURE) + if (line6pcm->flags & LINE6_BITS_CAPTURE_STREAM) fsize = line6pcm->prev_fsize; if (fsize == 0) { @@ -196,8 +196,8 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm) urb_out->transfer_buffer_length = urb_size; urb_out->context = line6pcm; - if (test_bit(BIT_PCM_ALSA_PLAYBACK, &line6pcm->flags) && - !test_bit(BIT_PAUSE_PLAYBACK, &line6pcm->flags)) { + if (test_bit(LINE6_INDEX_PCM_ALSA_PLAYBACK_STREAM, &line6pcm->flags) && + !test_bit(LINE6_INDEX_PAUSE_PLAYBACK, &line6pcm->flags)) { struct snd_pcm_runtime *runtime = get_substream(line6pcm, SNDRV_PCM_STREAM_PLAYBACK)->runtime; @@ -238,10 +238,10 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm) if (line6pcm->prev_fbuf != NULL) { #ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE - if (line6pcm->flags & MASK_PCM_IMPULSE) { + if (line6pcm->flags & LINE6_BITS_PCM_IMPULSE) { create_impulse_test_signal(line6pcm, urb_out, bytes_per_frame); - if (line6pcm->flags & MASK_PCM_ALSA_CAPTURE) { + if (line6pcm->flags & LINE6_BIT_PCM_ALSA_CAPTURE_STREAM) { line6_capture_copy(line6pcm, urb_out->transfer_buffer, urb_out-> @@ -254,8 +254,8 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm) if (! (line6pcm->line6-> properties->capabilities & LINE6_BIT_HWMON) -&& (line6pcm->flags & MASK_PLAYBACK) -&& (line6pcm->flags & MASK_CAPTURE)) + && (line6pcm->flags & LINE6_BITS_PLAYBACK_STREAM) + && (line6pcm->flags & LINE6_BITS_CAPTURE_STREAM)) add_monitor_signal(urb_out, line6pcm->prev_fbuf, line6pcm->volume_monitor, bytes_per_frame); @@ -321,7 +321,7 @@ void line6_unlink_audio_out_urbs(struct snd_line6_pcm *line6pcm) /* Wait until unlinking of all currently active playback URBs has been finished. */ -static void wait_clear_audio_out_urbs(struct snd_line6_pcm *line6pcm) +void line6_wait_clear_audio_out_urbs(struct snd_line6_pcm *line6pcm) { int timeout = HZ; unsigned int i; @@ -348,26 +348,7 @@ static void wait_clear_audio_out_urbs(struct snd_line6_pcm *line6pcm) void line6_unlink_wait_clear_audio_out_urbs(struct snd_line6_pcm *line6pcm) { line6_unlink_audio_out_urbs(line6pcm); - wait_clear_audio_out_urbs(line6pcm); -} - -int line6_alloc_playback_buffer(struct snd_line6_pcm *line6pcm) -{ - /* We may be invoked multiple times in a row so allocate once only */ - if (line6pcm->buffer_out) - return 0; - - line6pcm->buffer_out = - kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS * - line6pcm->max_packet_size, GFP_KERNEL); - - if (!line6pcm->buffer_out) { - dev_err(line6pcm->line6->ifcdev, - "cannot malloc playback buffer\n"); - return -ENOMEM; - } - - return 0; + line6_wait_clear_audio_out_urbs(line6pcm); } void line6_free_playback_buffer(struct snd_line6_pcm *line6pcm) @@ -407,7 +388,7 @@ static void audio_out_callback(struct urb *urb) spin_lock_irqsave(&line6pcm->lock_audio_out, flags); - if (test_bit(BIT_PCM_ALSA_PLAYBACK, &line6pcm->flags)) { + if (test_bit(LINE6_INDEX_PCM_ALSA_PLAYBACK_STREAM, &line6pcm->flags)) { struct snd_pcm_runtime *runtime = substream->runtime; line6pcm->pos_out_done += length / line6pcm->properties->bytes_per_frame; @@ -432,7 +413,7 @@ static void audio_out_callback(struct urb *urb) if (!shutdown) { submit_audio_out_urb(line6pcm); - if (test_bit(BIT_PCM_ALSA_PLAYBACK, &line6pcm->flags)) { + if (test_bit(LINE6_INDEX_PCM_ALSA_PLAYBACK_STREAM, &line6pcm->flags)) { line6pcm->bytes_out += length; if (line6pcm->bytes_out >= line6pcm->period_out) { line6pcm->bytes_out %= line6pcm->period_out; @@ -484,17 +465,17 @@ static int snd_line6_playback_hw_params(struct snd_pcm_substream *substream, } /* -- [FD] end */ - if ((line6pcm->flags & MASK_PLAYBACK) == 0) { - ret = line6_alloc_playback_buffer(line6pcm); + ret = line6_pcm_acquire(line6pcm, LINE6_BIT_PCM_ALSA_PLAYBACK_BUFFER); - if (ret < 0) - return ret; - } + if (ret < 0) + return ret; ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); - if (ret < 0) + if (ret < 0) { + line6_pcm_release(line6pcm, LINE6_BIT_PCM_ALSA_PLAYBACK_BUFFER); return ret; + } line6pcm->period_out = params_period_bytes(hw_params); return 0; @@ -504,12 +485,7 @@ static int snd_line6_playback_hw_params(struct snd_pcm_substream *substream, static int snd_line6_playback_hw_free(struct snd_pcm_substream *substream) { struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); - - if ((line6pcm->flags & MASK_PLAYBACK) == 0) { - line6_unlink_wait_clear_audio_out_urbs(line6pcm); - line6_free_playback_buffer(line6pcm); - } - + line6_pcm_release(line6pcm, LINE6_BIT_PCM_ALSA_PLAYBACK_BUFFER); return snd_pcm_lib_free_pages(substream); } @@ -523,7 +499,7 @@ int snd_line6_playback_trigger(struct snd_line6_pcm *line6pcm, int cmd) #ifdef CONFIG_PM case SNDRV_PCM_TRIGGER_RESUME: #endif - err = line6_pcm_start(line6pcm, MASK_PCM_ALSA_PLAYBACK); + err = line6_pcm_acquire(line6pcm, LINE6_BIT_PCM_ALSA_PLAYBACK_STREAM); if (err < 0) return err; @@ -534,7 +510,7 @@ int snd_line6_playback_trigger(struct snd_line6_pcm *line6pcm, int cmd) #ifdef CONFIG_PM case SNDRV_PCM_TRIGGER_SUSPEND: #endif - err = line6_pcm_stop(line6pcm, MASK_PCM_ALSA_PLAYBACK); + err = line6_pcm_release(line6pcm, LINE6_BIT_PCM_ALSA_PLAYBACK_STREAM); if (err < 0) return err; @@ -542,11 +518,11 @@ int snd_line6_playback_trigger(struct snd_line6_pcm *line6pcm, int cmd) break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - set_bit(BIT_PAUSE_PLAYBACK, &line6pcm->flags); + set_bit(LINE6_INDEX_PAUSE_PLAYBACK, &line6pcm->flags); break; case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - clear_bit(BIT_PAUSE_PLAYBACK, &line6pcm->flags); + clear_bit(LINE6_INDEX_PAUSE_PLAYBACK, &line6pcm->flags); break; default: diff --git a/drivers/staging/line6/playback.h b/drivers/staging/line6/playback.h index 02487ff..743bd6f 100644 --- a/drivers/staging/line6/playback.h +++ b/drivers/staging/line6/playback.h @@ -29,13 +29,13 @@ extern struct snd_pcm_ops snd_line6_playback_ops; -extern int line6_alloc_playback_buffer(struct snd_line6_pcm *line6pcm); extern int line6_create_audio_out_urbs(struct snd_line6_pcm *line6pcm); extern void line6_free_playback_buffer(struct snd_line6_pcm *line6pcm); extern int line6_submit_audio_out_all_urbs(struct snd_line6_pcm *line6pcm); extern void line6_unlink_audio_out_urbs(struct snd_line6_pcm *line6pcm); extern void line6_unlink_wait_clear_audio_out_urbs(struct snd_line6_pcm *line6pcm); +extern void line6_wait_clear_audio_out_urbs(struct snd_line6_pcm *line6pcm); extern int snd_line6_playback_trigger(struct snd_line6_pcm *line6pcm, int cmd); #endif diff --git a/drivers/staging/line6/toneport.c b/drivers/staging/line6/toneport.c index b776130..b754f69 100644 --- a/drivers/staging/line6/toneport.c +++ b/drivers/staging/line6/toneport.c @@ -207,9 +207,9 @@ static int snd_toneport_monitor_put(struct snd_kcontrol *kcontrol, line6pcm->volume_monitor = ucontrol->value.integer.value[0]; if (line6pcm->volume_monitor > 0) - line6_pcm_start(line6pcm, MASK_PCM_MONITOR); + line6_pcm_acquire(line6pcm, LINE6_BITS_PCM_MONITOR); else - line6_pcm_stop(line6pcm, MASK_PCM_MONITOR); + line6_pcm_release(line6pcm, LINE6_BITS_PCM_MONITOR); return 1; } @@ -264,7 +264,7 @@ static void toneport_start_pcm(unsigned long arg) { struct usb_line6_toneport *toneport = (struct usb_line6_toneport *)arg; struct usb_line6 *line6 = &toneport->line6; - line6_pcm_start(line6->line6pcm, MASK_PCM_MONITOR); + line6_pcm_acquire(line6->line6pcm, LINE6_BITS_PCM_MONITOR); } /* control definition */ @@ -446,7 +446,7 @@ void line6_toneport_disconnect(struct usb_interface *interface) struct snd_line6_pcm *line6pcm = toneport->line6.line6pcm; if (line6pcm != NULL) { - line6_pcm_stop(line6pcm, MASK_PCM_MONITOR); + line6_pcm_release(line6pcm, LINE6_BITS_PCM_MONITOR); line6_pcm_disconnect(line6pcm); } } diff --git a/drivers/staging/line6/usbdefs.h b/drivers/staging/line6/usbdefs.h index aff9e5c..353d59d 100644 --- a/drivers/staging/line6/usbdefs.h +++ b/drivers/staging/line6/usbdefs.h @@ -39,31 +39,29 @@ #define LINE6_DEVID_TONEPORT_UX2 0x4142 #define LINE6_DEVID_VARIAX 0x534d -enum { - LINE6_ID_BASSPODXT, - LINE6_ID_BASSPODXTLIVE, - LINE6_ID_BASSPODXTPRO, - LINE6_ID_GUITARPORT, - LINE6_ID_POCKETPOD, - LINE6_ID_PODHD300, - LINE6_ID_PODHD500, - LINE6_ID_PODSTUDIO_GX, - LINE6_ID_PODSTUDIO_UX1, - LINE6_ID_PODSTUDIO_UX2, - LINE6_ID_PODX3, - LINE6_ID_PODX3LIVE, - LINE6_ID_PODXT, - LINE6_ID_PODXTLIVE, - LINE6_ID_PODXTPRO, - LINE6_ID_TONEPORT_GX, - LINE6_ID_TONEPORT_UX1, - LINE6_ID_TONEPORT_UX2, - LINE6_ID_VARIAX -}; - -#define LINE6_BIT(x) LINE6_BIT_ ## x = 1 << LINE6_ID_ ## x +#define LINE6_BIT(x) LINE6_BIT_ ## x = 1 << LINE6_INDEX_ ## x enum { + LINE6_INDEX_BASSPODXT, + LINE6_INDEX_BASSPODXTLIVE, + LINE6_INDEX_BASSPODXTPRO, + LINE6_INDEX_GUITARPORT, + LINE6_INDEX_POCKETPOD, + LINE6_INDEX_PODHD300, + LINE6_INDEX_PODHD500, + LINE6_INDEX_PODSTUDIO_GX, + LINE6_INDEX_PODSTUDIO_UX1, + LINE6_INDEX_PODSTUDIO_UX2, + LINE6_INDEX_PODX3, + LINE6_INDEX_PODX3LIVE, + LINE6_INDEX_PODXT, + LINE6_INDEX_PODXTLIVE, + LINE6_INDEX_PODXTPRO, + LINE6_INDEX_TONEPORT_GX, + LINE6_INDEX_TONEPORT_UX1, + LINE6_INDEX_TONEPORT_UX2, + LINE6_INDEX_VARIAX, + LINE6_BIT(BASSPODXT), LINE6_BIT(BASSPODXTLIVE), LINE6_BIT(BASSPODXTPRO), -- cgit v0.10.2 From 77974a30b94bf51f2a5d6707ba652b7f51c99260 Mon Sep 17 00:00:00 2001 From: Sam Hansen Date: Fri, 20 Jan 2012 01:11:27 -0800 Subject: staging: vme: code convention fix Fixed a code convention violation in vme.h Signed-off-by: Sam Hansen Acked-by: Martyn Welch Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/vme/vme.h b/drivers/staging/vme/vme.h index 9d38cee..c9d65bf 100644 --- a/drivers/staging/vme/vme.h +++ b/drivers/staging/vme/vme.h @@ -156,7 +156,7 @@ int vme_irq_request(struct vme_dev *, int, int, void vme_irq_free(struct vme_dev *, int, int); int vme_irq_generate(struct vme_dev *, int, int); -struct vme_resource * vme_lm_request(struct vme_dev *); +struct vme_resource *vme_lm_request(struct vme_dev *); int vme_lm_count(struct vme_resource *); int vme_lm_set(struct vme_resource *, unsigned long long, u32, u32); int vme_lm_get(struct vme_resource *, unsigned long long *, u32 *, u32 *); -- cgit v0.10.2 From 1a2463f6e22532ad1b036f1cedab33dc998b3088 Mon Sep 17 00:00:00 2001 From: Marcos Paulo de Souza Date: Wed, 28 Dec 2011 21:03:15 +0000 Subject: staging: vt6656: iwctl.c: Remove commented code Signed-off-by: Marcos Paulo de Souza Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/vt6656/iwctl.c b/drivers/staging/vt6656/iwctl.c index ecfda52..480e07f 100644 --- a/drivers/staging/vt6656/iwctl.c +++ b/drivers/staging/vt6656/iwctl.c @@ -46,9 +46,6 @@ #include - -/*--------------------- Static Definitions -------------------------*/ - #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT #define SUPPORTED_WIRELESS_EXT 18 #else @@ -63,19 +60,8 @@ static const long frequency_list[] = { 5700, 5745, 5765, 5785, 5805, 5825 }; - -/*--------------------- Static Classes ----------------------------*/ - - -//static int msglevel =MSG_LEVEL_DEBUG; static int msglevel =MSG_LEVEL_INFO; - -/*--------------------- Static Variables --------------------------*/ -/*--------------------- Static Functions --------------------------*/ - -/*--------------------- Export Variables --------------------------*/ - struct iw_statistics *iwctl_get_wireless_stats(struct net_device *dev) { PSDevice pDevice = netdev_priv(dev); @@ -87,7 +73,6 @@ struct iw_statistics *iwctl_get_wireless_stats(struct net_device *dev) pDevice->wstats.qual.qual =(BYTE) pDevice->scStatistic.LinkQuality; RFvRSSITodBm(pDevice, (BYTE)(pDevice->uCurrRSSI), &ldBm); pDevice->wstats.qual.level = ldBm; - //pDevice->wstats.qual.level = 0x100 - pDevice->uCurrRSSI; pDevice->wstats.qual.noise = 0; pDevice->wstats.qual.updated = 1; pDevice->wstats.discard.nwid = 0; @@ -100,11 +85,6 @@ struct iw_statistics *iwctl_get_wireless_stats(struct net_device *dev) return &pDevice->wstats; } - - -/*------------------------------------------------------------------*/ - - static int iwctl_commit(struct net_device *dev, struct iw_request_info *info, void *wrq, @@ -197,14 +177,12 @@ if(pDevice->byReAssocCount > 0) { //reject scan when re-associating! } pMgmt->eScanType = WMAC_SCAN_PASSIVE; - //printk("SIOCSIWSCAN:WLAN_CMD_BSSID_SCAN\n"); bScheduleCommand((void *) pDevice, WLAN_CMD_BSSID_SCAN, NULL); spin_unlock_irq(&pDevice->lock); return 0; } - /* * Wireless Handler : get scan results */ @@ -708,9 +686,7 @@ int iwctl_giwap(struct net_device *dev, memcpy(wrq->sa_data, pMgmt->abyCurrBSSID, 6); -//20080123-02, by Einsn Liu if ((pDevice->bLinkPass == FALSE) && (pMgmt->eCurrMode != WMAC_MODE_ESS_AP)) - // if ((pDevice->bLinkPass == FALSE) && (pMgmt->eCurrMode == WMAC_MODE_ESS_STA)) memset(wrq->sa_data, 0, 6); if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) { @@ -913,7 +889,6 @@ int iwctl_giwessid(struct net_device *dev, // Get the current SSID pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID; - //pItemSSID = (PWLAN_IE_SSID)pMgmt->abyDesireSSID; memcpy(extra, pItemSSID->abySSID , pItemSSID->len); extra[pItemSSID->len] = '\0'; @@ -1327,55 +1302,6 @@ int iwctl_siwencode(struct net_device *dev, return rc; } -/* - * Wireless Handler : get encode mode - */ -//2008-0409-06, by Einsn Liu - /* -int iwctl_giwencode(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *wrq, - char *extra) -{ - PSDevice pDevice = (PSDevice)netdev_priv(dev); - PSMgmtObject pMgmt = &(pDevice->sMgmtObj); - int rc = 0; - char abyKey[WLAN_WEP232_KEYLEN]; - unsigned int index = (unsigned int)(wrq->flags & IW_ENCODE_INDEX); - PSKeyItem pKey = NULL; - - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWENCODE\n"); - - - memset(abyKey, 0, sizeof(abyKey)); - // Check encryption mode - wrq->flags = IW_ENCODE_NOKEY; - // Is WEP enabled ??? - if (pDevice->bEncryptionEnable) - wrq->flags |= IW_ENCODE_ENABLED; - else - wrq->flags |= IW_ENCODE_DISABLED; - - if (pMgmt->bShareKeyAlgorithm) - wrq->flags |= IW_ENCODE_RESTRICTED; - else - wrq->flags |= IW_ENCODE_OPEN; - - if (KeybGetKey(&(pDevice->sKey), pDevice->abyBroadcastAddr, (BYTE)index , &pKey)){ - wrq->length = pKey->uKeyLength; - memcpy(abyKey, pKey->abyKey, pKey->uKeyLength); - } - else { - rc = -EINVAL; - return rc; - } - wrq->flags |= index; - // Copy the key to the user buffer - memcpy(extra, abyKey, WLAN_WEP232_KEYLEN); - return 0; -} -*/ - int iwctl_giwencode(struct net_device *dev, struct iw_request_info *info, struct iw_point *wrq, @@ -1562,7 +1488,6 @@ int iwctl_siwauth(struct net_device *dev, wpa_version = wrq->value; if(wrq->value == IW_AUTH_WPA_VERSION_DISABLED) { PRINT_K("iwctl_siwauth:set WPADEV to disable at 1??????\n"); - //pDevice->bWPADEVUp = FALSE; } else if(wrq->value == IW_AUTH_WPA_VERSION_WPA) { PRINT_K("iwctl_siwauth:set WPADEV to WPA1******\n"); @@ -1570,7 +1495,6 @@ int iwctl_siwauth(struct net_device *dev, else { PRINT_K("iwctl_siwauth:set WPADEV to WPA2******\n"); } - //pDevice->bWPASuppWextEnabled =TRUE; break; case IW_AUTH_CIPHER_PAIRWISE: pairwise = wrq->value; @@ -1627,11 +1551,6 @@ int iwctl_siwauth(struct net_device *dev, } break; case IW_AUTH_WPA_ENABLED: - //pDevice->bWPADEVUp = !! wrq->value; - //if(pDevice->bWPADEVUp==TRUE) - // printk("iwctl_siwauth:set WPADEV to enable successful*******\n"); - //else - // printk("iwctl_siwauth:set WPADEV to enable fail?????\n"); break; case IW_AUTH_RX_UNENCRYPTED_EAPOL: break; @@ -1646,7 +1565,6 @@ int iwctl_siwauth(struct net_device *dev, pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled; pMgmt->bShareKeyAlgorithm = FALSE; pMgmt->eAuthenMode = WMAC_AUTH_OPEN; - //pDevice->bWPADEVUp = FALSE; PRINT_K("iwctl_siwauth:set WPADEV to disaable at 2?????\n"); } @@ -1655,15 +1573,6 @@ int iwctl_siwauth(struct net_device *dev, ret = -EOPNOTSUPP; break; } -/* - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wpa_version = %d\n",wpa_version); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pairwise = %d\n",pairwise); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pDevice->eEncryptionStatus = %d\n",pDevice->eEncryptionStatus); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pMgmt->eAuthenMode = %d\n",pMgmt->eAuthenMode); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pMgmt->bShareKeyAlgorithm = %s\n",pMgmt->bShareKeyAlgorithm?"TRUE":"FALSE"); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pDevice->bEncryptionEnable = %s\n",pDevice->bEncryptionEnable?"TRUE":"FALSE"); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pDevice->bWPADEVUp = %s\n",pDevice->bWPADEVUp?"TRUE":"FALSE"); -*/ return ret; } @@ -1752,8 +1661,6 @@ int iwctl_siwencodeext(struct net_device *dev, u8 seq[IW_ENCODE_SEQ_MAX_SIZE]; u8 key[64]; size_t seq_len=0,key_len=0; -// - // int ii; u8 *buf; size_t blen; u8 key_array[64]; @@ -1883,7 +1790,6 @@ int iwctl_siwmlme(struct net_device *dev, PSDevice pDevice = (PSDevice)netdev_priv(dev); PSMgmtObject pMgmt = &(pDevice->sMgmtObj); struct iw_mlme *mlme = (struct iw_mlme *)extra; - //u16 reason = cpu_to_le16(mlme->reason_code); int ret = 0; if(memcmp(pMgmt->abyCurrBSSID, mlme->addr.sa_data, ETH_ALEN)){ @@ -1892,12 +1798,6 @@ int iwctl_siwmlme(struct net_device *dev, } switch(mlme->cmd){ case IW_MLME_DEAUTH: - //this command seems to be not complete,please test it --einsnliu - //printk("iwctl_siwmlme--->send DEAUTH\n"); - /* bScheduleCommand((void *) pDevice, - WLAN_CMD_DEAUTH, - (PBYTE)&reason); */ - //break; case IW_MLME_DISASSOC: if(pDevice->bLinkPass == TRUE){ PRINT_K("iwctl_siwmlme--->send DISASSOCIATE\n"); @@ -1916,74 +1816,6 @@ int iwctl_siwmlme(struct net_device *dev, #endif -/*------------------------------------------------------------------*/ -/* - * Structures to export the Wireless Handlers - */ - - -/* -static const iw_handler iwctl_handler[] = -{ - (iw_handler) iwctl_commit, // SIOCSIWCOMMIT - (iw_handler) iwctl_giwname, // SIOCGIWNAME - (iw_handler) NULL, // SIOCSIWNWID - (iw_handler) iwctl_siwfreq, // SIOCSIWFREQ - (iw_handler) iwctl_giwfreq, // SIOCGIWFREQ - (iw_handler) iwctl_siwmode, // SIOCSIWMODE - (iw_handler) iwctl_giwmode, // SIOCGIWMODE - (iw_handler) NULL, // SIOCSIWSENS - (iw_handler) iwctl_giwsens, // SIOCGIWSENS - (iw_handler) NULL, // SIOCSIWRANGE - (iw_handler) iwctl_giwrange, // SIOCGIWRANGE - (iw_handler) NULL, // SIOCSIWPRIV - (iw_handler) NULL, // SIOCGIWPRIV - (iw_handler) NULL, // SIOCSIWSTATS - (iw_handler) NULL, // SIOCGIWSTATS - (iw_handler) NULL, // SIOCSIWSPY - (iw_handler) NULL, // SIOCGIWSPY - (iw_handler) NULL, // -- hole -- - (iw_handler) NULL, // -- hole -- - (iw_handler) iwctl_siwap, // SIOCSIWAP - (iw_handler) iwctl_giwap, // SIOCGIWAP - (iw_handler) NULL, // -- hole -- 0x16 - (iw_handler) iwctl_giwaplist, // SIOCGIWAPLIST - (iw_handler) iwctl_siwscan, // SIOCSIWSCAN - (iw_handler) iwctl_giwscan, // SIOCGIWSCAN - (iw_handler) iwctl_siwessid, // SIOCSIWESSID - (iw_handler) iwctl_giwessid, // SIOCGIWESSID - (iw_handler) NULL, // SIOCSIWNICKN - (iw_handler) NULL, // SIOCGIWNICKN - (iw_handler) NULL, // -- hole -- - (iw_handler) NULL, // -- hole -- - (iw_handler) iwctl_siwrate, // SIOCSIWRATE 0x20 - (iw_handler) iwctl_giwrate, // SIOCGIWRATE - (iw_handler) iwctl_siwrts, // SIOCSIWRTS - (iw_handler) iwctl_giwrts, // SIOCGIWRTS - (iw_handler) iwctl_siwfrag, // SIOCSIWFRAG - (iw_handler) iwctl_giwfrag, // SIOCGIWFRAG - (iw_handler) NULL, // SIOCSIWTXPOW - (iw_handler) NULL, // SIOCGIWTXPOW - (iw_handler) iwctl_siwretry, // SIOCSIWRETRY - (iw_handler) iwctl_giwretry, // SIOCGIWRETRY - (iw_handler) iwctl_siwencode, // SIOCSIWENCODE - (iw_handler) iwctl_giwencode, // SIOCGIWENCODE - (iw_handler) iwctl_siwpower, // SIOCSIWPOWER - (iw_handler) iwctl_giwpower, // SIOCGIWPOWER - (iw_handler) NULL, // -- hole -- - (iw_handler) NULL, // -- hole -- - (iw_handler) iwctl_siwgenie, // SIOCSIWGENIE - (iw_handler) iwctl_giwgenie, // SIOCGIWGENIE - (iw_handler) iwctl_siwauth, // SIOCSIWAUTH - (iw_handler) iwctl_giwauth, // SIOCGIWAUTH - (iw_handler) iwctl_siwencodeext, // SIOCSIWENCODEEXT - (iw_handler) iwctl_giwencodeext, // SIOCGIWENCODEEXT - (iw_handler) NULL, // SIOCSIWPMKSA - (iw_handler) NULL, // -- hole -- - -}; -*/ - static const iw_handler iwctl_handler[] = { (iw_handler) iwctl_commit, // SIOCSIWCOMMIT @@ -2063,13 +1895,9 @@ const struct iw_handler_def iwctl_handler_def = { .get_wireless_stats = &iwctl_get_wireless_stats, .num_standard = sizeof(iwctl_handler)/sizeof(iw_handler), -// .num_private = sizeof(iwctl_private_handler)/sizeof(iw_handler), -// .num_private_args = sizeof(iwctl_private_args)/sizeof(struct iw_priv_args), .num_private = 0, .num_private_args = 0, .standard = (iw_handler *) iwctl_handler, -// .private = (iw_handler *) iwctl_private_handler, -// .private_args = (struct iw_priv_args *)iwctl_private_args, .private = NULL, .private_args = NULL, }; -- cgit v0.10.2 From 506215ba22fea4a9190b7e33413405bd4d4ab1e1 Mon Sep 17 00:00:00 2001 From: Marcos Paulo de Souza Date: Wed, 28 Dec 2011 21:07:40 +0000 Subject: staging: vt6656: iwctl.c: Remove useless function The funciton iwctl_commit does nothing, and can be removed. Signed-off-by: Marcos Paulo de Souza Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/vt6656/iwctl.c b/drivers/staging/vt6656/iwctl.c index 480e07f..d6fd010 100644 --- a/drivers/staging/vt6656/iwctl.c +++ b/drivers/staging/vt6656/iwctl.c @@ -85,16 +85,6 @@ struct iw_statistics *iwctl_get_wireless_stats(struct net_device *dev) return &pDevice->wstats; } -static int iwctl_commit(struct net_device *dev, - struct iw_request_info *info, - void *wrq, - char *extra) -{ - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWCOMMIT\n"); - - return 0; -} - /* * Wireless Handler : get protocol name */ @@ -1818,7 +1808,7 @@ int iwctl_siwmlme(struct net_device *dev, static const iw_handler iwctl_handler[] = { - (iw_handler) iwctl_commit, // SIOCSIWCOMMIT + (iw_handler) NULL, /* SIOCSIWCOMMIT */ (iw_handler) NULL, // SIOCGIWNAME (iw_handler) NULL, // SIOCSIWNWID (iw_handler) NULL, // SIOCGIWNWID -- cgit v0.10.2 From 5d11b1737d52b6f9428c2daea72457cd477e0122 Mon Sep 17 00:00:00 2001 From: Marcos Paulo de Souza Date: Wed, 28 Dec 2011 21:09:13 +0000 Subject: staging: vt6656: Remove return statement of iwctl_giwmode This function will always return 0, and this data is not used by who calls this function. Signed-off-by: Marcos Paulo de Souza Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/vt6656/iwctl.c b/drivers/staging/vt6656/iwctl.c index d6fd010..75b36d3 100644 --- a/drivers/staging/vt6656/iwctl.c +++ b/drivers/staging/vt6656/iwctl.c @@ -471,7 +471,7 @@ int iwctl_siwmode(struct net_device *dev, * Wireless Handler : get operation mode */ -int iwctl_giwmode(struct net_device *dev, +void iwctl_giwmode(struct net_device *dev, struct iw_request_info *info, __u32 *wmode, char *extra) @@ -498,8 +498,6 @@ int iwctl_giwmode(struct net_device *dev, default: *wmode = IW_MODE_ADHOC; } - - return 0; } diff --git a/drivers/staging/vt6656/iwctl.h b/drivers/staging/vt6656/iwctl.h index 10a240e..60180a7 100644 --- a/drivers/staging/vt6656/iwctl.h +++ b/drivers/staging/vt6656/iwctl.h @@ -52,7 +52,7 @@ int iwctl_giwrange(struct net_device *dev, char *extra); -int iwctl_giwmode(struct net_device *dev, +void iwctl_giwmode(struct net_device *dev, struct iw_request_info *info, __u32 *wmode, char *extra); diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index 6a708f4..fdd35c6 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -1733,7 +1733,7 @@ static int device_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { // Get mode of operation case SIOCGIWMODE: - rc = iwctl_giwmode(dev, NULL, &(wrq->u.mode), NULL); + iwctl_giwmode(dev, NULL, &(wrq->u.mode), NULL); break; // Set WEP keys and mode -- cgit v0.10.2 From f9b9f93426139e7525306b94df8f82989c3f6138 Mon Sep 17 00:00:00 2001 From: Marcos Paulo de Souza Date: Wed, 28 Dec 2011 21:10:50 +0000 Subject: staging: vt6656: Remove return statement of iwctl_giwrange The function iwctl_giwrange will always return 0, and this data is not used by who calls this function. Signed-off-by: Marcos Paulo de Souza Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/vt6656/iwctl.c b/drivers/staging/vt6656/iwctl.c index 75b36d3..0e27fb1 100644 --- a/drivers/staging/vt6656/iwctl.c +++ b/drivers/staging/vt6656/iwctl.c @@ -505,7 +505,7 @@ void iwctl_giwmode(struct net_device *dev, * Wireless Handler : get capability range */ -int iwctl_giwrange(struct net_device *dev, +void iwctl_giwrange(struct net_device *dev, struct iw_request_info *info, struct iw_point *wrq, char *extra) @@ -600,9 +600,6 @@ int iwctl_giwrange(struct net_device *dev, range->avg_qual.level = 176; // -80 dBm range->avg_qual.noise = 0; } - - - return 0; } diff --git a/drivers/staging/vt6656/iwctl.h b/drivers/staging/vt6656/iwctl.h index 60180a7..22acf8b 100644 --- a/drivers/staging/vt6656/iwctl.h +++ b/drivers/staging/vt6656/iwctl.h @@ -46,7 +46,7 @@ int iwctl_siwap(struct net_device *dev, struct sockaddr *wrq, char *extra); -int iwctl_giwrange(struct net_device *dev, +void iwctl_giwrange(struct net_device *dev, struct iw_request_info *info, struct iw_point *wrq, char *extra); diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index fdd35c6..6213075 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -1811,7 +1811,7 @@ static int device_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { { struct iw_range range; - rc = iwctl_giwrange(dev, NULL, &(wrq->u.data), (char *) &range); + iwctl_giwrange(dev, NULL, &(wrq->u.data), (char *) &range); if (copy_to_user(wrq->u.data.pointer, &range, sizeof(struct iw_range))) rc = -EFAULT; } -- cgit v0.10.2 From caa20de81635b567ee0114a81ffbbffb3085d727 Mon Sep 17 00:00:00 2001 From: Marcos Paulo de Souza Date: Wed, 28 Dec 2011 21:12:12 +0000 Subject: staging: vt6656: iwctl.c: Remove return statement of iwctl_giwessid This function will always return 0, and this data is not used by who calls this function. Signed-off-by: Marcos Paulo de Souza Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/vt6656/iwctl.c b/drivers/staging/vt6656/iwctl.c index 0e27fb1..d6c969a 100644 --- a/drivers/staging/vt6656/iwctl.c +++ b/drivers/staging/vt6656/iwctl.c @@ -856,8 +856,7 @@ int iwctl_siwessid(struct net_device *dev, /* * Wireless Handler : get essid */ - -int iwctl_giwessid(struct net_device *dev, +void iwctl_giwessid(struct net_device *dev, struct iw_request_info *info, struct iw_point *wrq, char *extra) @@ -879,8 +878,6 @@ int iwctl_giwessid(struct net_device *dev, wrq->length = pItemSSID->len; wrq->flags = 1; // active - - return 0; } /* diff --git a/drivers/staging/vt6656/iwctl.h b/drivers/staging/vt6656/iwctl.h index 22acf8b..0bab0d7 100644 --- a/drivers/staging/vt6656/iwctl.h +++ b/drivers/staging/vt6656/iwctl.h @@ -97,7 +97,7 @@ int iwctl_siwessid(struct net_device *dev, struct iw_point *wrq, char *extra); -int iwctl_giwessid(struct net_device *dev, +void iwctl_giwessid(struct net_device *dev, struct iw_request_info *info, struct iw_point *wrq, char *extra); diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index 6213075..91b953c 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -1657,8 +1657,8 @@ static int device_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { { char essid[IW_ESSID_MAX_SIZE+1]; if (wrq->u.essid.pointer) { - rc = iwctl_giwessid(dev, NULL, - &(wrq->u.essid), essid); + iwctl_giwessid(dev, NULL, + &(wrq->u.essid), essid); if (copy_to_user(wrq->u.essid.pointer, essid, wrq->u.essid.length) ) -- cgit v0.10.2 From 739ea07640f4dd3cc440b836ad6a88388c2dcf28 Mon Sep 17 00:00:00 2001 From: Marcos Paulo de Souza Date: Wed, 28 Dec 2011 21:13:39 +0000 Subject: staging: vt6656: iwctl.c: Remove return statement of iwctl_giwrate This function will always return 0, and this data is not used by who calls this function. Signed-off-by: Marcos Paulo de Souza Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/vt6656/iwctl.c b/drivers/staging/vt6656/iwctl.c index d6c969a..4f33b0c 100644 --- a/drivers/staging/vt6656/iwctl.c +++ b/drivers/staging/vt6656/iwctl.c @@ -965,8 +965,7 @@ int iwctl_siwrate(struct net_device *dev, /* * Wireless Handler : get data rate */ - -int iwctl_giwrate(struct net_device *dev, +void iwctl_giwrate(struct net_device *dev, struct iw_request_info *info, struct iw_param *wrq, char *extra) @@ -1004,9 +1003,6 @@ int iwctl_giwrate(struct net_device *dev, if (pDevice->bFixRate == TRUE) wrq->fixed = TRUE; } - - - return 0; } diff --git a/drivers/staging/vt6656/iwctl.h b/drivers/staging/vt6656/iwctl.h index 0bab0d7..bd38e9d 100644 --- a/drivers/staging/vt6656/iwctl.h +++ b/drivers/staging/vt6656/iwctl.h @@ -107,7 +107,7 @@ int iwctl_siwrate(struct net_device *dev, struct iw_param *wrq, char *extra); -int iwctl_giwrate(struct net_device *dev, +void iwctl_giwrate(struct net_device *dev, struct iw_request_info *info, struct iw_param *wrq, char *extra); diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index 91b953c..33a451c 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -1698,8 +1698,7 @@ static int device_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { // Get the current bit-rate case SIOCGIWRATE: - - rc = iwctl_giwrate(dev, NULL, &(wrq->u.bitrate), NULL); + iwctl_giwrate(dev, NULL, &(wrq->u.bitrate), NULL); break; // Set the desired RTS threshold -- cgit v0.10.2 From 2fdde902ca4b19d051c5fa15f81dd6d900551db8 Mon Sep 17 00:00:00 2001 From: Marcos Paulo de Souza Date: Wed, 28 Dec 2011 21:18:31 +0000 Subject: staging: vt6656: iwctl.c: Rewrite siwrts funciton This function has the following issues: Parameter info and extra are not used Wrong error handling(the function not return -EINVAL when it happens) This patch simplifies this funtion, remove the not used parameters and fix the error handilng. Signed-off-by: Marcos Paulo de Souza Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/vt6656/iwctl.c b/drivers/staging/vt6656/iwctl.c index 4f33b0c..b24e531 100644 --- a/drivers/staging/vt6656/iwctl.c +++ b/drivers/staging/vt6656/iwctl.c @@ -1010,27 +1010,19 @@ void iwctl_giwrate(struct net_device *dev, /* * Wireless Handler : set rts threshold */ - int iwctl_siwrts(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *wrq, - char *extra) + struct iw_param *wrq) { - PSDevice pDevice = (PSDevice)netdev_priv(dev); - int rc = 0; + PSDevice pDevice = (PSDevice)netdev_priv(dev); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWRTS \n"); + if ((wrq->value < 0 || wrq->value > 2312) && !wrq->disabled) + return -EINVAL; - { - int rthr = wrq->value; - if(wrq->disabled) - rthr = 2312; - if((rthr < 0) || (rthr > 2312)) { - rc = -EINVAL; - }else { - pDevice->wRTSThreshold = rthr; - } - } + else if (wrq->disabled) + pDevice->wRTSThreshold = 2312; + + else + pDevice->wRTSThreshold = wrq->value; return 0; } diff --git a/drivers/staging/vt6656/iwctl.h b/drivers/staging/vt6656/iwctl.h index bd38e9d..0c6e049 100644 --- a/drivers/staging/vt6656/iwctl.h +++ b/drivers/staging/vt6656/iwctl.h @@ -113,10 +113,7 @@ void iwctl_giwrate(struct net_device *dev, char *extra); int iwctl_siwrts(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *wrq, - char *extra); - + struct iw_param *wrq); int iwctl_giwrts(struct net_device *dev, struct iw_request_info *info, diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index 33a451c..763e028 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -1704,7 +1704,7 @@ static int device_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { // Set the desired RTS threshold case SIOCSIWRTS: - rc = iwctl_siwrts(dev, NULL, &(wrq->u.rts), NULL); + rc = iwctl_siwrts(dev, &(wrq->u.rts)); break; // Get the current RTS threshold -- cgit v0.10.2 From 08afcf9c9f5b9372e26f3f29313f45528fafc15c Mon Sep 17 00:00:00 2001 From: mahendra singh meena Date: Mon, 16 Jan 2012 23:50:38 +0530 Subject: Staging: vt6655: Fix brace coding style issues in ioctl.c This patch fixes up unnecessary brace warnings found in ioctl.c by checkpatch.pl . Signed-off-by: Mahendra Singh Meena Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/vt6655/ioctl.c b/drivers/staging/vt6655/ioctl.c index 7fd5cc5..ef197ef 100644 --- a/drivers/staging/vt6655/ioctl.c +++ b/drivers/staging/vt6655/ioctl.c @@ -324,16 +324,16 @@ int private_ioctl(PSDevice pDevice, struct ifreq *rq) pItemSSID = (PWLAN_IE_SSID)pBSS->abySSID; memset(pList->sBSSIDList[ii].abySSID, 0, WLAN_SSID_MAXLEN + 1); memcpy(pList->sBSSIDList[ii].abySSID, pItemSSID->abySSID, pItemSSID->len); - if (WLAN_GET_CAP_INFO_ESS(pBSS->wCapInfo)) { + if (WLAN_GET_CAP_INFO_ESS(pBSS->wCapInfo)) pList->sBSSIDList[ii].byNetType = INFRA; - } else { + else pList->sBSSIDList[ii].byNetType = ADHOC; - } - if (WLAN_GET_CAP_INFO_PRIVACY(pBSS->wCapInfo)) { + + if (WLAN_GET_CAP_INFO_PRIVACY(pBSS->wCapInfo)) pList->sBSSIDList[ii].bWEPOn = true; - } else { + else pList->sBSSIDList[ii].bWEPOn = false; - } + ii++; if (ii >= pList->uItem) break; @@ -367,9 +367,9 @@ int private_ioctl(PSDevice pDevice, struct ifreq *rq) netif_stop_queue(pDevice->dev); spin_lock_irq(&pDevice->lock); - if (pDevice->bRadioOff == false) { + if (pDevice->bRadioOff == false) CARDbRadioPowerOff(pDevice); - } + pDevice->bLinkPass = false; memset(pMgmt->abyCurrBSSID, 0, 6); pMgmt->eCurrState = WMAC_STATE_IDLE; @@ -489,13 +489,12 @@ int private_ioctl(PSDevice pDevice, struct ifreq *rq) break; } - if (sStartAPCmd.wBBPType == PHY80211g) { + if (sStartAPCmd.wBBPType == PHY80211g) pMgmt->byAPBBType = PHY_TYPE_11G; - } else if (sStartAPCmd.wBBPType == PHY80211a) { + else if (sStartAPCmd.wBBPType == PHY80211a) pMgmt->byAPBBType = PHY_TYPE_11A; - } else { + else pMgmt->byAPBBType = PHY_TYPE_11B; - } pItemSSID = (PWLAN_IE_SSID)sStartAPCmd.ssid; if (pItemSSID->len > WLAN_SSID_MAXLEN + 1) -- cgit v0.10.2 From 4e1efd6e853977a134ff262230ccb4b69319d926 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Mon, 16 Jan 2012 21:28:23 +0100 Subject: staging, vt6656/wpactl.c: A basic style cleanup This patch cleans up the coding style in drivers/staging/vt6656/wpactl.c to closer match the generally accepted kernel CodingStyle. It is by no means a "make it perfect" patch, but it does get the file a fair bit closer to matching the accepted style (whomever was involved in the evolution of this file seriously need to configure their editors to maintain a consistent style - it was a mess). Besides pure style cleanups I also took the liberty of removing some pointless parens, some unneeded casts and removing some commented out code (it was obviously not used and git has it if it's ever needed in the future). Signed-off-by: Jesper Juhl Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/vt6656/wpactl.c b/drivers/staging/vt6656/wpactl.c index 2fa4f84..9d14868 100644 --- a/drivers/staging/vt6656/wpactl.c +++ b/drivers/staging/vt6656/wpactl.c @@ -46,23 +46,18 @@ #define VIAWGET_WPA_MAX_BUF_SIZE 1024 - - static const int frequency_list[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452, 2457, 2462, 2467, 2472, 2484 }; + /*--------------------- Static Classes ----------------------------*/ /*--------------------- Static Variables --------------------------*/ -//static int msglevel =MSG_LEVEL_DEBUG; -static int msglevel =MSG_LEVEL_INFO; +static int msglevel = MSG_LEVEL_INFO; /*--------------------- Static Functions --------------------------*/ - - - /*--------------------- Export Variables --------------------------*/ static void wpadev_setup(struct net_device *dev) { @@ -72,9 +67,9 @@ static void wpadev_setup(struct net_device *dev) dev->addr_len = ETH_ALEN; dev->tx_queue_len = 1000; - memset(dev->broadcast,0xFF, ETH_ALEN); + memset(dev->broadcast, 0xFF, ETH_ALEN); - dev->flags = IFF_BROADCAST|IFF_MULTICAST; + dev->flags = IFF_BROADCAST | IFF_MULTICAST; } /* @@ -90,45 +85,43 @@ static void wpadev_setup(struct net_device *dev) * Return Value: * */ - static int wpa_init_wpadev(PSDevice pDevice) { - PSDevice wpadev_priv; + PSDevice wpadev_priv; struct net_device *dev = pDevice->dev; - int ret=0; + int ret = 0; pDevice->wpadev = alloc_netdev(sizeof(PSDevice), "vntwpa", wpadev_setup); if (pDevice->wpadev == NULL) return -ENOMEM; - wpadev_priv = netdev_priv(pDevice->wpadev); - *wpadev_priv = *pDevice; + wpadev_priv = netdev_priv(pDevice->wpadev); + *wpadev_priv = *pDevice; memcpy(pDevice->wpadev->dev_addr, dev->dev_addr, ETH_ALEN); - pDevice->wpadev->base_addr = dev->base_addr; + pDevice->wpadev->base_addr = dev->base_addr; pDevice->wpadev->irq = dev->irq; pDevice->wpadev->mem_start = dev->mem_start; pDevice->wpadev->mem_end = dev->mem_end; ret = register_netdev(pDevice->wpadev); if (ret) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: register_netdev(WPA) failed!\n", - dev->name); + dev->name); free_netdev(pDevice->wpadev); return -1; } if (pDevice->skb == NULL) { - pDevice->skb = dev_alloc_skb((int)pDevice->rx_buf_sz); - if (pDevice->skb == NULL) - return -ENOMEM; - } + pDevice->skb = dev_alloc_skb((int)pDevice->rx_buf_sz); + if (pDevice->skb == NULL) + return -ENOMEM; + } - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Registered netdev %s for WPA management\n", - dev->name, pDevice->wpadev->name); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Registered netdev %s for WPA management\n", + dev->name, pDevice->wpadev->name); return 0; } - /* * Description: * unregister net_device (wpadev) @@ -141,29 +134,24 @@ static int wpa_init_wpadev(PSDevice pDevice) * Return Value: * */ - static int wpa_release_wpadev(PSDevice pDevice) { - if (pDevice->skb) { - dev_kfree_skb(pDevice->skb); - pDevice->skb = NULL; - } + if (pDevice->skb) { + dev_kfree_skb(pDevice->skb); + pDevice->skb = NULL; + } - if (pDevice->wpadev) { - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Netdevice %s unregistered\n", - pDevice->dev->name, pDevice->wpadev->name); - unregister_netdev(pDevice->wpadev); - free_netdev(pDevice->wpadev); - pDevice->wpadev = NULL; - } + if (pDevice->wpadev) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Netdevice %s unregistered\n", + pDevice->dev->name, pDevice->wpadev->name); + unregister_netdev(pDevice->wpadev); + free_netdev(pDevice->wpadev); + pDevice->wpadev = NULL; + } return 0; } - - - - /* * Description: * Set enable/disable dev for wpa supplicant deamon @@ -177,13 +165,11 @@ static int wpa_release_wpadev(PSDevice pDevice) * Return Value: * */ - int wpa_set_wpadev(PSDevice pDevice, int val) { if (val) return wpa_init_wpadev(pDevice); - else - return wpa_release_wpadev(pDevice); + return wpa_release_wpadev(pDevice); } /* @@ -199,245 +185,217 @@ int wpa_set_wpadev(PSDevice pDevice, int val) * Return Value: * */ - int wpa_set_keys(PSDevice pDevice, void *ctx, BOOL fcpfkernel) { - struct viawget_wpa_param *param=ctx; - PSMgmtObject pMgmt = &(pDevice->sMgmtObj); - DWORD dwKeyIndex = 0; - BYTE abyKey[MAX_KEY_LEN]; - BYTE abySeq[MAX_KEY_LEN]; - QWORD KeyRSC; -// NDIS_802_11_KEY_RSC KeyRSC; - BYTE byKeyDecMode = KEY_CTL_WEP; + struct viawget_wpa_param *param = ctx; + PSMgmtObject pMgmt = &pDevice->sMgmtObj; + DWORD dwKeyIndex = 0; + BYTE abyKey[MAX_KEY_LEN]; + BYTE abySeq[MAX_KEY_LEN]; + QWORD KeyRSC; + BYTE byKeyDecMode = KEY_CTL_WEP; int ret = 0; - int uu, ii; - + int uu; + int ii; if (param->u.wpa_key.alg_name > WPA_ALG_CCMP) return -EINVAL; - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "param->u.wpa_key.alg_name = %d \n", param->u.wpa_key.alg_name); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "param->u.wpa_key.alg_name = %d \n", + param->u.wpa_key.alg_name); if (param->u.wpa_key.alg_name == WPA_ALG_NONE) { - pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled; - pDevice->bEncryptionEnable = FALSE; - pDevice->byKeyIndex = 0; - pDevice->bTransmitKey = FALSE; - for (uu=0; uueEncryptionStatus = Ndis802_11EncryptionDisabled; + pDevice->bEncryptionEnable = FALSE; + pDevice->byKeyIndex = 0; + pDevice->bTransmitKey = FALSE; + for (uu=0; uuu.wpa_key.key && param->u.wpa_key.key_len > sizeof(abyKey)) return -EINVAL; - spin_unlock_irq(&pDevice->lock); - if(param->u.wpa_key.key && fcpfkernel) { - memcpy(&abyKey[0], param->u.wpa_key.key, param->u.wpa_key.key_len); - } - else { - if (param->u.wpa_key.key && - copy_from_user(&abyKey[0], param->u.wpa_key.key, param->u.wpa_key.key_len)) { - spin_lock_irq(&pDevice->lock); - return -EINVAL; + spin_unlock_irq(&pDevice->lock); + if (param->u.wpa_key.key && fcpfkernel) { + memcpy(&abyKey[0], param->u.wpa_key.key, param->u.wpa_key.key_len); + } else { + if (param->u.wpa_key.key && + copy_from_user(&abyKey[0], param->u.wpa_key.key, + param->u.wpa_key.key_len)) { + spin_lock_irq(&pDevice->lock); + return -EINVAL; + } } - } - spin_lock_irq(&pDevice->lock); + spin_lock_irq(&pDevice->lock); - dwKeyIndex = (DWORD)(param->u.wpa_key.key_index); + dwKeyIndex = (DWORD)(param->u.wpa_key.key_index); if (param->u.wpa_key.alg_name == WPA_ALG_WEP) { - if (dwKeyIndex > 3) { - return -EINVAL; - } - else { - if (param->u.wpa_key.set_tx) { - pDevice->byKeyIndex = (BYTE)dwKeyIndex; - pDevice->bTransmitKey = TRUE; - dwKeyIndex |= (1 << 31); - } - KeybSetDefaultKey( pDevice, - &(pDevice->sKey), - dwKeyIndex & ~(BIT30 | USE_KEYRSC), - param->u.wpa_key.key_len, - NULL, - abyKey, - KEY_CTL_WEP - ); - - } - pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled; - pDevice->bEncryptionEnable = TRUE; - return ret; + if (dwKeyIndex > 3) { + return -EINVAL; + } else { + if (param->u.wpa_key.set_tx) { + pDevice->byKeyIndex = (BYTE)dwKeyIndex; + pDevice->bTransmitKey = TRUE; + dwKeyIndex |= (1 << 31); + } + KeybSetDefaultKey( pDevice, + &(pDevice->sKey), + dwKeyIndex & ~(BIT30 | USE_KEYRSC), + param->u.wpa_key.key_len, + NULL, + abyKey, + KEY_CTL_WEP + ); + + } + pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled; + pDevice->bEncryptionEnable = TRUE; + return ret; } if (param->u.wpa_key.seq && param->u.wpa_key.seq_len > sizeof(abySeq)) return -EINVAL; - spin_unlock_irq(&pDevice->lock); - if(param->u.wpa_key.seq && fcpfkernel) { - memcpy(&abySeq[0], param->u.wpa_key.seq, param->u.wpa_key.seq_len); - } - else { - if (param->u.wpa_key.seq && - copy_from_user(&abySeq[0], param->u.wpa_key.seq, param->u.wpa_key.seq_len)) { - spin_lock_irq(&pDevice->lock); - return -EINVAL; - } + spin_unlock_irq(&pDevice->lock); + if (param->u.wpa_key.seq && fcpfkernel) { + memcpy(&abySeq[0], param->u.wpa_key.seq, param->u.wpa_key.seq_len); + } else { + if (param->u.wpa_key.seq && + copy_from_user(&abySeq[0], param->u.wpa_key.seq, + param->u.wpa_key.seq_len)) { + spin_lock_irq(&pDevice->lock); + return -EINVAL; + } } spin_lock_irq(&pDevice->lock); if (param->u.wpa_key.seq_len > 0) { for (ii = 0 ; ii < param->u.wpa_key.seq_len ; ii++) { - if (ii < 4) - LODWORD(KeyRSC) |= (abySeq[ii] << (ii * 8)); - else - HIDWORD(KeyRSC) |= (abySeq[ii] << ((ii-4) * 8)); - //KeyRSC |= (abySeq[ii] << (ii * 8)); + if (ii < 4) + LODWORD(KeyRSC) |= (abySeq[ii] << (ii * 8)); + else + HIDWORD(KeyRSC) |= (abySeq[ii] << ((ii-4) * 8)); } dwKeyIndex |= 1 << 29; } - if (param->u.wpa_key.key_index >= MAX_GROUP_KEY) { - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "return dwKeyIndex > 3\n"); - return -EINVAL; - } + if (param->u.wpa_key.key_index >= MAX_GROUP_KEY) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "return dwKeyIndex > 3\n"); + return -EINVAL; + } if (param->u.wpa_key.alg_name == WPA_ALG_TKIP) { - pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled; - } + pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled; + } if (param->u.wpa_key.alg_name == WPA_ALG_CCMP) { - pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled; - } + pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled; + } if (param->u.wpa_key.set_tx) dwKeyIndex |= (1 << 31); - if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) - byKeyDecMode = KEY_CTL_CCMP; - else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) - byKeyDecMode = KEY_CTL_TKIP; - else - byKeyDecMode = KEY_CTL_WEP; - - // Fix HCT test that set 256 bits KEY and Ndis802_11Encryption3Enabled - if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) { - if (param->u.wpa_key.key_len == MAX_KEY_LEN) - byKeyDecMode = KEY_CTL_TKIP; - else if (param->u.wpa_key.key_len == WLAN_WEP40_KEYLEN) - byKeyDecMode = KEY_CTL_WEP; - else if (param->u.wpa_key.key_len == WLAN_WEP104_KEYLEN) - byKeyDecMode = KEY_CTL_WEP; - } else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) { - if (param->u.wpa_key.key_len == WLAN_WEP40_KEYLEN) - byKeyDecMode = KEY_CTL_WEP; - else if (param->u.wpa_key.key_len == WLAN_WEP104_KEYLEN) - byKeyDecMode = KEY_CTL_WEP; - } - - // Check TKIP key length - if ((byKeyDecMode == KEY_CTL_TKIP) && - (param->u.wpa_key.key_len != MAX_KEY_LEN)) { - // TKIP Key must be 256 bits - //DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA - TKIP Key must be 256 bits\n")); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "return- TKIP Key must be 256 bits!\n"); - return -EINVAL; - } - // Check AES key length - if ((byKeyDecMode == KEY_CTL_CCMP) && - (param->u.wpa_key.key_len != AES_KEY_LEN)) { - // AES Key must be 128 bits - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "return - AES Key must be 128 bits\n"); - return -EINVAL; - } + if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) + byKeyDecMode = KEY_CTL_CCMP; + else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) + byKeyDecMode = KEY_CTL_TKIP; + else + byKeyDecMode = KEY_CTL_WEP; + + // Fix HCT test that set 256 bits KEY and Ndis802_11Encryption3Enabled + if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) { + if (param->u.wpa_key.key_len == MAX_KEY_LEN) + byKeyDecMode = KEY_CTL_TKIP; + else if (param->u.wpa_key.key_len == WLAN_WEP40_KEYLEN) + byKeyDecMode = KEY_CTL_WEP; + else if (param->u.wpa_key.key_len == WLAN_WEP104_KEYLEN) + byKeyDecMode = KEY_CTL_WEP; + } else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) { + if (param->u.wpa_key.key_len == WLAN_WEP40_KEYLEN) + byKeyDecMode = KEY_CTL_WEP; + else if (param->u.wpa_key.key_len == WLAN_WEP104_KEYLEN) + byKeyDecMode = KEY_CTL_WEP; + } - if (is_broadcast_ether_addr(¶m->addr[0]) || (param->addr == NULL)) { - /* if broadcast, set the key as every key entry's group key */ - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Groupe Key Assign.\n"); - - if ((KeybSetAllGroupKey(pDevice, - &(pDevice->sKey), - dwKeyIndex, - param->u.wpa_key.key_len, - (PQWORD) &(KeyRSC), - (PBYTE)abyKey, - byKeyDecMode - ) == TRUE) && - (KeybSetDefaultKey(pDevice, - &(pDevice->sKey), - dwKeyIndex, - param->u.wpa_key.key_len, - (PQWORD) &(KeyRSC), - (PBYTE)abyKey, - byKeyDecMode - ) == TRUE) ) { - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "GROUP Key Assign.\n"); - - } else { - //DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA -KeybSetDefaultKey Fail.0\n")); - return -EINVAL; - } - - } else { - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key Assign.\n"); - // BSSID not 0xffffffffffff - // Pairwise Key can't be WEP - if (byKeyDecMode == KEY_CTL_WEP) { - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key can't be WEP\n"); - return -EINVAL; - } - - dwKeyIndex |= (1 << 30); // set pairwise key - if (pMgmt->eConfigMode == WMAC_CONFIG_IBSS_STA) { - //DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA - WMAC_CONFIG_IBSS_STA\n")); - return -EINVAL; - } - if (KeybSetKey(pDevice, - &(pDevice->sKey), - ¶m->addr[0], - dwKeyIndex, - param->u.wpa_key.key_len, - (PQWORD) &(KeyRSC), - (PBYTE)abyKey, - byKeyDecMode - ) == TRUE) { - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key Set\n"); - - } else { - // Key Table Full - if (!compare_ether_addr(¶m->addr[0], pDevice->abyBSSID)) { - //DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA -Key Table Full.2\n")); - return -EINVAL; - - } else { - // Save Key and configure just before associate/reassociate to BSSID - // we do not implement now - return -EINVAL; - } - } - } // BSSID not 0xffffffffffff - if ((ret == 0) && ((param->u.wpa_key.set_tx) != 0)) { - pDevice->byKeyIndex = (BYTE)param->u.wpa_key.key_index; - pDevice->bTransmitKey = TRUE; + // Check TKIP key length + if ((byKeyDecMode == KEY_CTL_TKIP) && + (param->u.wpa_key.key_len != MAX_KEY_LEN)) { + // TKIP Key must be 256 bits + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "return- TKIP Key must be 256 bits!\n"); + return -EINVAL; } - pDevice->bEncryptionEnable = TRUE; + // Check AES key length + if ((byKeyDecMode == KEY_CTL_CCMP) && + (param->u.wpa_key.key_len != AES_KEY_LEN)) { + // AES Key must be 128 bits + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "return - AES Key must be 128 bits\n"); + return -EINVAL; + } -/* - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " key=%x-%x-%x-%x-%x-xxxxx \n", - pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[byKeyIndex][0], - pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[byKeyIndex][1], - pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[byKeyIndex][2], - pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[byKeyIndex][3], - pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[byKeyIndex][4] - ); -*/ + if (is_broadcast_ether_addr(¶m->addr[0]) || (param->addr == NULL)) { + /* if broadcast, set the key as every key entry's group key */ + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Groupe Key Assign.\n"); + + if ((KeybSetAllGroupKey(pDevice, &(pDevice->sKey), dwKeyIndex, + param->u.wpa_key.key_len, + (PQWORD) &(KeyRSC), + (PBYTE)abyKey, + byKeyDecMode + ) == TRUE) && + (KeybSetDefaultKey(pDevice, + &(pDevice->sKey), + dwKeyIndex, + param->u.wpa_key.key_len, + (PQWORD) &(KeyRSC), + (PBYTE)abyKey, + byKeyDecMode + ) == TRUE) ) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "GROUP Key Assign.\n"); + } else { + return -EINVAL; + } + } else { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key Assign.\n"); + // BSSID not 0xffffffffffff + // Pairwise Key can't be WEP + if (byKeyDecMode == KEY_CTL_WEP) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key can't be WEP\n"); + return -EINVAL; + } + dwKeyIndex |= (1 << 30); // set pairwise key + if (pMgmt->eConfigMode == WMAC_CONFIG_IBSS_STA) { + //DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA - WMAC_CONFIG_IBSS_STA\n")); + return -EINVAL; + } + if (KeybSetKey(pDevice, &(pDevice->sKey), ¶m->addr[0], + dwKeyIndex, param->u.wpa_key.key_len, + (PQWORD) &(KeyRSC), (PBYTE)abyKey, byKeyDecMode + ) == TRUE) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key Set\n"); + } else { + // Key Table Full + if (!compare_ether_addr(¶m->addr[0], pDevice->abyBSSID)) { + //DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA -Key Table Full.2\n")); + return -EINVAL; + } else { + // Save Key and configure just before associate/reassociate to BSSID + // we do not implement now + return -EINVAL; + } + } + } // BSSID not 0xffffffffffff + if ((ret == 0) && ((param->u.wpa_key.set_tx) != 0)) { + pDevice->byKeyIndex = (BYTE)param->u.wpa_key.key_index; + pDevice->bTransmitKey = TRUE; + } + pDevice->bEncryptionEnable = TRUE; return ret; - } @@ -454,23 +412,17 @@ int wpa_set_wpadev(PSDevice pDevice, int val) * Return Value: * */ - -static int wpa_set_wpa(PSDevice pDevice, - struct viawget_wpa_param *param) +static int wpa_set_wpa(PSDevice pDevice, struct viawget_wpa_param *param) { - - PSMgmtObject pMgmt = &(pDevice->sMgmtObj); + PSMgmtObject pMgmt = &pDevice->sMgmtObj; int ret = 0; - pMgmt->eAuthenMode = WMAC_AUTH_OPEN; - pMgmt->bShareKeyAlgorithm = FALSE; + pMgmt->eAuthenMode = WMAC_AUTH_OPEN; + pMgmt->bShareKeyAlgorithm = FALSE; - return ret; + return ret; } - - - /* * Description: * set disassociate @@ -484,25 +436,21 @@ static int wpa_set_wpa(PSDevice pDevice, * Return Value: * */ - -static int wpa_set_disassociate(PSDevice pDevice, - struct viawget_wpa_param *param) +static int wpa_set_disassociate(PSDevice pDevice, struct viawget_wpa_param *param) { - PSMgmtObject pMgmt = &(pDevice->sMgmtObj); + PSMgmtObject pMgmt = &pDevice->sMgmtObj; int ret = 0; - spin_lock_irq(&pDevice->lock); - if (pDevice->bLinkPass) { - if (!memcmp(param->addr, pMgmt->abyCurrBSSID, 6)) - bScheduleCommand((void *) pDevice, WLAN_CMD_DISASSOCIATE, NULL); - } - spin_unlock_irq(&pDevice->lock); + spin_lock_irq(&pDevice->lock); + if (pDevice->bLinkPass) { + if (!memcmp(param->addr, pMgmt->abyCurrBSSID, 6)) + bScheduleCommand((void *)pDevice, WLAN_CMD_DISASSOCIATE, NULL); + } + spin_unlock_irq(&pDevice->lock); - return ret; + return ret; } - - /* * Description: * enable scan process @@ -516,36 +464,30 @@ static int wpa_set_disassociate(PSDevice pDevice, * Return Value: * */ - -static int wpa_set_scan(PSDevice pDevice, - struct viawget_wpa_param *param) +static int wpa_set_scan(PSDevice pDevice, struct viawget_wpa_param *param) { int ret = 0; /**set ap_scan=1&&scan_ssid=1 under hidden ssid mode**/ - PSMgmtObject pMgmt = &(pDevice->sMgmtObj); - PWLAN_IE_SSID pItemSSID; -printk("wpa_set_scan-->desired [ssid=%s,ssid_len=%d]\n", - param->u.scan_req.ssid,param->u.scan_req.ssid_len); + PSMgmtObject pMgmt = &pDevice->sMgmtObj; + PWLAN_IE_SSID pItemSSID; + printk("wpa_set_scan-->desired [ssid=%s,ssid_len=%d]\n", + param->u.scan_req.ssid,param->u.scan_req.ssid_len); // Set the SSID -memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); -pItemSSID = (PWLAN_IE_SSID)pMgmt->abyDesireSSID; -pItemSSID->byElementID = WLAN_EID_SSID; -memcpy(pItemSSID->abySSID, param->u.scan_req.ssid, param->u.scan_req.ssid_len); -pItemSSID->len = param->u.scan_req.ssid_len; - - spin_lock_irq(&pDevice->lock); - BSSvClearBSSList((void *) pDevice, pDevice->bLinkPass); - /* bScheduleCommand((void *) pDevice, WLAN_CMD_BSSID_SCAN, NULL); */ - bScheduleCommand((void *) pDevice, - WLAN_CMD_BSSID_SCAN, - pMgmt->abyDesireSSID); - spin_unlock_irq(&pDevice->lock); - - return ret; -} + memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); + pItemSSID = (PWLAN_IE_SSID)pMgmt->abyDesireSSID; + pItemSSID->byElementID = WLAN_EID_SSID; + memcpy(pItemSSID->abySSID, param->u.scan_req.ssid, param->u.scan_req.ssid_len); + pItemSSID->len = param->u.scan_req.ssid_len; + spin_lock_irq(&pDevice->lock); + BSSvClearBSSList((void *) pDevice, pDevice->bLinkPass); + bScheduleCommand((void *) pDevice, WLAN_CMD_BSSID_SCAN, + pMgmt->abyDesireSSID); + spin_unlock_irq(&pDevice->lock); + return ret; +} /* * Description: @@ -560,19 +502,15 @@ pItemSSID->len = param->u.scan_req.ssid_len; * Return Value: * */ - -static int wpa_get_bssid(PSDevice pDevice, - struct viawget_wpa_param *param) +static int wpa_get_bssid(PSDevice pDevice, struct viawget_wpa_param *param) { - PSMgmtObject pMgmt = &(pDevice->sMgmtObj); - int ret = 0; - memcpy(param->u.wpa_associate.bssid, pMgmt->abyCurrBSSID , 6); + PSMgmtObject pMgmt = &pDevice->sMgmtObj; + int ret = 0; + memcpy(param->u.wpa_associate.bssid, pMgmt->abyCurrBSSID, 6); return ret; - } - /* * Description: * get bssid @@ -586,24 +524,20 @@ static int wpa_get_bssid(PSDevice pDevice, * Return Value: * */ - -static int wpa_get_ssid(PSDevice pDevice, - struct viawget_wpa_param *param) +static int wpa_get_ssid(PSDevice pDevice, struct viawget_wpa_param *param) { - PSMgmtObject pMgmt = &(pDevice->sMgmtObj); - PWLAN_IE_SSID pItemSSID; + PSMgmtObject pMgmt = &pDevice->sMgmtObj; + PWLAN_IE_SSID pItemSSID; int ret = 0; - pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID; + pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID; - memcpy(param->u.wpa_associate.ssid, pItemSSID->abySSID , pItemSSID->len); + memcpy(param->u.wpa_associate.ssid, pItemSSID->abySSID, pItemSSID->len); param->u.wpa_associate.ssid_len = pItemSSID->len; - return ret; + return ret; } - - /* * Description: * get scan results @@ -617,135 +551,114 @@ static int wpa_get_ssid(PSDevice pDevice, * Return Value: * */ - -static int wpa_get_scan(PSDevice pDevice, - struct viawget_wpa_param *param) +static int wpa_get_scan(PSDevice pDevice, struct viawget_wpa_param *param) { struct viawget_scan_result *scan_buf; - PSMgmtObject pMgmt = &(pDevice->sMgmtObj); - PWLAN_IE_SSID pItemSSID; - PKnownBSS pBSS; - PBYTE pBuf; + PSMgmtObject pMgmt = &pDevice->sMgmtObj; + PWLAN_IE_SSID pItemSSID; + PKnownBSS pBSS; + PBYTE pBuf; int ret = 0; u16 count = 0; - u16 ii, jj; - long ldBm;//James //add + u16 ii; + u16 jj; + long ldBm; //James //add //******mike:bubble sort by stronger RSSI*****// + PBYTE ptempBSS; - PBYTE ptempBSS; - + ptempBSS = kmalloc(sizeof(KnownBSS), GFP_ATOMIC); + if (ptempBSS == NULL) { + printk("bubble sort kmalloc memory fail@@@\n"); + ret = -ENOMEM; + return ret; + } - ptempBSS = kmalloc(sizeof(KnownBSS), (int)GFP_ATOMIC); - - if (ptempBSS == NULL) { - - printk("bubble sort kmalloc memory fail@@@\n"); - - ret = -ENOMEM; - - return ret; - - } - - for (ii = 0; ii < MAX_BSS_NUM; ii++) { - - for (jj = 0; jj < MAX_BSS_NUM - ii - 1; jj++) { - - if ((pMgmt->sBSSList[jj].bActive != TRUE) || - - ((pMgmt->sBSSList[jj].uRSSI>pMgmt->sBSSList[jj+1].uRSSI) &&(pMgmt->sBSSList[jj+1].bActive!=FALSE))) { - - memcpy(ptempBSS,&pMgmt->sBSSList[jj],sizeof(KnownBSS)); - - memcpy(&pMgmt->sBSSList[jj],&pMgmt->sBSSList[jj+1],sizeof(KnownBSS)); - - memcpy(&pMgmt->sBSSList[jj+1],ptempBSS,sizeof(KnownBSS)); - - } - - } - - } - - kfree(ptempBSS); - - // printk("bubble sort result:\n"); + for (ii = 0; ii < MAX_BSS_NUM; ii++) { + for (jj = 0; jj < MAX_BSS_NUM - ii - 1; jj++) { + if ((pMgmt->sBSSList[jj].bActive != TRUE) + || ((pMgmt->sBSSList[jj].uRSSI > pMgmt->sBSSList[jj + 1].uRSSI) + && (pMgmt->sBSSList[jj + 1].bActive != FALSE))) { + memcpy(ptempBSS,&pMgmt->sBSSList[jj], sizeof(KnownBSS)); + memcpy(&pMgmt->sBSSList[jj], &pMgmt->sBSSList[jj + 1], + sizeof(KnownBSS)); + memcpy(&pMgmt->sBSSList[jj + 1], ptempBSS, sizeof(KnownBSS)); + } + } + } + kfree(ptempBSS); count = 0; pBSS = &(pMgmt->sBSSList[0]); - for (ii = 0; ii < MAX_BSS_NUM; ii++) { - pBSS = &(pMgmt->sBSSList[ii]); - if (!pBSS->bActive) - continue; - count++; - } + for (ii = 0; ii < MAX_BSS_NUM; ii++) { + pBSS = &(pMgmt->sBSSList[ii]); + if (!pBSS->bActive) + continue; + count++; + } - pBuf = kcalloc(count, sizeof(struct viawget_scan_result), (int)GFP_ATOMIC); + pBuf = kcalloc(count, sizeof(struct viawget_scan_result), GFP_ATOMIC); - if (pBuf == NULL) { - ret = -ENOMEM; - return ret; - } - scan_buf = (struct viawget_scan_result *)pBuf; + if (pBuf == NULL) { + ret = -ENOMEM; + return ret; + } + scan_buf = (struct viawget_scan_result *)pBuf; pBSS = &(pMgmt->sBSSList[0]); - for (ii = 0, jj = 0; ii < MAX_BSS_NUM ; ii++) { - pBSS = &(pMgmt->sBSSList[ii]); - if (pBSS->bActive) { - if (jj >= count) - break; - memcpy(scan_buf->bssid, pBSS->abyBSSID, WLAN_BSSID_LEN); - pItemSSID = (PWLAN_IE_SSID)pBSS->abySSID; - memcpy(scan_buf->ssid, pItemSSID->abySSID, pItemSSID->len); - scan_buf->ssid_len = pItemSSID->len; - scan_buf->freq = frequency_list[pBSS->uChannel-1]; - scan_buf->caps = pBSS->wCapInfo; //DavidWang for sharemode - - RFvRSSITodBm(pDevice, (BYTE)(pBSS->uRSSI), &ldBm); - if(-ldBm<50){ + for (ii = 0, jj = 0; ii < MAX_BSS_NUM; ii++) { + pBSS = &(pMgmt->sBSSList[ii]); + if (pBSS->bActive) { + if (jj >= count) + break; + memcpy(scan_buf->bssid, pBSS->abyBSSID, WLAN_BSSID_LEN); + pItemSSID = (PWLAN_IE_SSID)pBSS->abySSID; + memcpy(scan_buf->ssid, pItemSSID->abySSID, pItemSSID->len); + scan_buf->ssid_len = pItemSSID->len; + scan_buf->freq = frequency_list[pBSS->uChannel-1]; + scan_buf->caps = pBSS->wCapInfo; // DavidWang for sharemode + + RFvRSSITodBm(pDevice, (BYTE)(pBSS->uRSSI), &ldBm); + if (-ldBm < 50) scan_buf->qual = 100; - }else if(-ldBm > 90) { - scan_buf->qual = 0; - }else { + else if (-ldBm > 90) + scan_buf->qual = 0; + else scan_buf->qual=(40-(-ldBm-50))*100/40; - } //James - //scan_buf->caps = pBSS->wCapInfo; - //scan_buf->qual = - scan_buf->noise = 0; - scan_buf->level = ldBm; - - //scan_buf->maxrate = - if (pBSS->wWPALen != 0) { - scan_buf->wpa_ie_len = pBSS->wWPALen; - memcpy(scan_buf->wpa_ie, pBSS->byWPAIE, pBSS->wWPALen); - } - if (pBSS->wRSNLen != 0) { - scan_buf->rsn_ie_len = pBSS->wRSNLen; - memcpy(scan_buf->rsn_ie, pBSS->byRSNIE, pBSS->wRSNLen); - } - scan_buf = (struct viawget_scan_result *)((PBYTE)scan_buf + sizeof(struct viawget_scan_result)); - jj ++; - } - } + //scan_buf->caps = pBSS->wCapInfo; + //scan_buf->qual = + scan_buf->noise = 0; + scan_buf->level = ldBm; + + //scan_buf->maxrate = + if (pBSS->wWPALen != 0) { + scan_buf->wpa_ie_len = pBSS->wWPALen; + memcpy(scan_buf->wpa_ie, pBSS->byWPAIE, pBSS->wWPALen); + } + if (pBSS->wRSNLen != 0) { + scan_buf->rsn_ie_len = pBSS->wRSNLen; + memcpy(scan_buf->rsn_ie, pBSS->byRSNIE, pBSS->wRSNLen); + } + scan_buf = (struct viawget_scan_result *)((PBYTE)scan_buf + sizeof(struct viawget_scan_result)); + jj ++; + } + } - if (jj < count) - count = jj; + if (jj < count) + count = jj; - if (copy_to_user(param->u.scan_results.buf, pBuf, sizeof(struct viawget_scan_result) * count)) { + if (copy_to_user(param->u.scan_results.buf, pBuf, sizeof(struct viawget_scan_result) * count)) ret = -EFAULT; - } + param->u.scan_results.scan_count = count; - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " param->u.scan_results.scan_count = %d\n", count) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " param->u.scan_results.scan_count = %d\n", count); - kfree(pBuf); - return ret; + kfree(pBuf); + return ret; } - - /* * Description: * set associate with AP @@ -759,25 +672,23 @@ static int wpa_get_scan(PSDevice pDevice, * Return Value: * */ - -static int wpa_set_associate(PSDevice pDevice, - struct viawget_wpa_param *param) +static int wpa_set_associate(PSDevice pDevice, struct viawget_wpa_param *param) { - PSMgmtObject pMgmt = &(pDevice->sMgmtObj); - PWLAN_IE_SSID pItemSSID; - BYTE abyNullAddr[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - BYTE abyWPAIE[64]; - int ret = 0; - BOOL bwepEnabled=FALSE; + PSMgmtObject pMgmt = &pDevice->sMgmtObj; + PWLAN_IE_SSID pItemSSID; + BYTE abyNullAddr[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + BYTE abyWPAIE[64]; + int ret = 0; + BOOL bwepEnabled=FALSE; // set key type & algorithm - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pairwise_suite = %d\n", param->u.wpa_associate.pairwise_suite); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "group_suite = %d\n", param->u.wpa_associate.group_suite); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "key_mgmt_suite = %d\n", param->u.wpa_associate.key_mgmt_suite); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "auth_alg = %d\n", param->u.wpa_associate.auth_alg); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "mode = %d\n", param->u.wpa_associate.mode); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wpa_ie_len = %d\n", param->u.wpa_associate.wpa_ie_len); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Roaming dBm = %d\n", param->u.wpa_associate.roam_dbm); //Davidwang + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pairwise_suite = %d\n", param->u.wpa_associate.pairwise_suite); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "group_suite = %d\n", param->u.wpa_associate.group_suite); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "key_mgmt_suite = %d\n", param->u.wpa_associate.key_mgmt_suite); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "auth_alg = %d\n", param->u.wpa_associate.auth_alg); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "mode = %d\n", param->u.wpa_associate.mode); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wpa_ie_len = %d\n", param->u.wpa_associate.wpa_ie_len); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Roaming dBm = %d\n", param->u.wpa_associate.roam_dbm); // Davidwang if (param->u.wpa_associate.wpa_ie) { if (param->u.wpa_associate.wpa_ie_len > sizeof(abyWPAIE)) @@ -789,25 +700,25 @@ static int wpa_set_associate(PSDevice pDevice, } if (param->u.wpa_associate.mode == 1) - pMgmt->eConfigMode = WMAC_CONFIG_IBSS_STA; + pMgmt->eConfigMode = WMAC_CONFIG_IBSS_STA; else - pMgmt->eConfigMode = WMAC_CONFIG_ESS_STA; + pMgmt->eConfigMode = WMAC_CONFIG_ESS_STA; // set bssid - if (memcmp(param->u.wpa_associate.bssid, &abyNullAddr[0], 6) != 0) - memcpy(pMgmt->abyDesireBSSID, param->u.wpa_associate.bssid, 6); - // set ssid + if (memcmp(param->u.wpa_associate.bssid, &abyNullAddr[0], 6) != 0) + memcpy(pMgmt->abyDesireBSSID, param->u.wpa_associate.bssid, 6); + // set ssid memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); - pItemSSID = (PWLAN_IE_SSID)pMgmt->abyDesireSSID; - pItemSSID->byElementID = WLAN_EID_SSID; + pItemSSID = (PWLAN_IE_SSID)pMgmt->abyDesireSSID; + pItemSSID->byElementID = WLAN_EID_SSID; pItemSSID->len = param->u.wpa_associate.ssid_len; memcpy(pItemSSID->abySSID, param->u.wpa_associate.ssid, pItemSSID->len); - if (param->u.wpa_associate.wpa_ie_len == 0) { - if (param->u.wpa_associate.auth_alg & AUTH_ALG_SHARED_KEY) - pMgmt->eAuthenMode = WMAC_AUTH_SHAREKEY; - else - pMgmt->eAuthenMode = WMAC_AUTH_OPEN; + if (param->u.wpa_associate.wpa_ie_len == 0) { + if (param->u.wpa_associate.auth_alg & AUTH_ALG_SHARED_KEY) + pMgmt->eAuthenMode = WMAC_AUTH_SHAREKEY; + else + pMgmt->eAuthenMode = WMAC_AUTH_OPEN; } else if (abyWPAIE[0] == RSN_INFO_ELEM) { if (param->u.wpa_associate.key_mgmt_suite == KEY_MGMT_PSK) pMgmt->eAuthenMode = WMAC_AUTH_WPA2PSK; @@ -817,9 +728,9 @@ static int wpa_set_associate(PSDevice pDevice, if (param->u.wpa_associate.key_mgmt_suite == KEY_MGMT_WPA_NONE) pMgmt->eAuthenMode = WMAC_AUTH_WPANONE; else if (param->u.wpa_associate.key_mgmt_suite == KEY_MGMT_PSK) - pMgmt->eAuthenMode = WMAC_AUTH_WPAPSK; + pMgmt->eAuthenMode = WMAC_AUTH_WPAPSK; else - pMgmt->eAuthenMode = WMAC_AUTH_WPA; + pMgmt->eAuthenMode = WMAC_AUTH_WPA; } switch (param->u.wpa_associate.pairwise_suite) { @@ -833,7 +744,6 @@ static int wpa_set_associate(PSDevice pDevice, case CIPHER_WEP104: pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled; bwepEnabled = TRUE; - // printk("****************wpa_set_associate:set CIPHER_WEP40_104\n"); break; case CIPHER_NONE: if (param->u.wpa_associate.group_suite == CIPHER_CCMP) @@ -845,70 +755,64 @@ static int wpa_set_associate(PSDevice pDevice, pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled; } - pMgmt->Roam_dbm = param->u.wpa_associate.roam_dbm; - // if ((pMgmt->Roam_dbm > 40)&&(pMgmt->Roam_dbm<80)) - // pDevice->bEnableRoaming = TRUE; - - if (pMgmt->eAuthenMode == WMAC_AUTH_SHAREKEY) { //@wep-sharekey - pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled; - pMgmt->bShareKeyAlgorithm = TRUE; - } - else if (pMgmt->eAuthenMode == WMAC_AUTH_OPEN) { - if(bwepEnabled==TRUE) { //@open-wep - pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled; - } - else { //@only open - pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled; + pMgmt->Roam_dbm = param->u.wpa_associate.roam_dbm; + if (pMgmt->eAuthenMode == WMAC_AUTH_SHAREKEY) { // @wep-sharekey + pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled; + pMgmt->bShareKeyAlgorithm = TRUE; + } else if (pMgmt->eAuthenMode == WMAC_AUTH_OPEN) { + if(bwepEnabled==TRUE) { //@open-wep + pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled; + } else { + // @only open + pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled; } - } -//mike save old encryption status + } + // mike save old encryption status pDevice->eOldEncryptionStatus = pDevice->eEncryptionStatus; - if (pDevice->eEncryptionStatus != Ndis802_11EncryptionDisabled) - pDevice->bEncryptionEnable = TRUE; - else - pDevice->bEncryptionEnable = FALSE; - - if ((pMgmt->eAuthenMode == WMAC_AUTH_SHAREKEY) || - ((pMgmt->eAuthenMode == WMAC_AUTH_OPEN) && (bwepEnabled==TRUE))) { - //mike re-comment:open-wep && sharekey-wep needn't do initial key!! - - } - else - KeyvInitTable(pDevice,&pDevice->sKey); + if (pDevice->eEncryptionStatus != Ndis802_11EncryptionDisabled) + pDevice->bEncryptionEnable = TRUE; + else + pDevice->bEncryptionEnable = FALSE; - spin_lock_irq(&pDevice->lock); - pDevice->bLinkPass = FALSE; - ControlvMaskByte(pDevice,MESSAGE_REQUEST_MACREG,MAC_REG_PAPEDELAY,LEDSTS_STS,LEDSTS_SLOW); - memset(pMgmt->abyCurrBSSID, 0, 6); - pMgmt->eCurrState = WMAC_STATE_IDLE; - netif_stop_queue(pDevice->dev); + if ((pMgmt->eAuthenMode == WMAC_AUTH_SHAREKEY) || + ((pMgmt->eAuthenMode == WMAC_AUTH_OPEN) && (bwepEnabled==TRUE))) { + // mike re-comment:open-wep && sharekey-wep needn't do initial key!! + } else { + KeyvInitTable(pDevice,&pDevice->sKey); + } -/*******search if ap_scan=2 ,which is associating request in hidden ssid mode ****/ -{ - PKnownBSS pCurr = NULL; - pCurr = BSSpSearchBSSList(pDevice, - pMgmt->abyDesireBSSID, - pMgmt->abyDesireSSID, - pDevice->eConfigPHYMode - ); - - if (pCurr == NULL){ - printk("wpa_set_associate---->hidden mode site survey before associate.......\n"); - bScheduleCommand((void *) pDevice, - WLAN_CMD_BSSID_SCAN, - pMgmt->abyDesireSSID); - } -} + spin_lock_irq(&pDevice->lock); + pDevice->bLinkPass = FALSE; + ControlvMaskByte(pDevice, MESSAGE_REQUEST_MACREG, MAC_REG_PAPEDELAY, LEDSTS_STS, LEDSTS_SLOW); + memset(pMgmt->abyCurrBSSID, 0, 6); + pMgmt->eCurrState = WMAC_STATE_IDLE; + netif_stop_queue(pDevice->dev); + +/******* search if ap_scan=2, which is associating request in hidden ssid mode ****/ + { + PKnownBSS pCurr = NULL; + pCurr = BSSpSearchBSSList(pDevice, + pMgmt->abyDesireBSSID, + pMgmt->abyDesireSSID, + pDevice->eConfigPHYMode + ); + + if (pCurr == NULL){ + printk("wpa_set_associate---->hidden mode site survey before associate.......\n"); + bScheduleCommand((void *)pDevice, + WLAN_CMD_BSSID_SCAN, + pMgmt->abyDesireSSID); + } + } /****************************************************************/ - bScheduleCommand((void *) pDevice, WLAN_CMD_SSID, NULL); - spin_unlock_irq(&pDevice->lock); + bScheduleCommand((void *)pDevice, WLAN_CMD_SSID, NULL); + spin_unlock_irq(&pDevice->lock); - return ret; + return ret; } - /* * Description: * wpa_ioctl main function supported for wpa supplicant @@ -922,7 +826,6 @@ static int wpa_set_associate(PSDevice pDevice, * Return Value: * */ - int wpa_ioctl(PSDevice pDevice, struct iw_point *p) { struct viawget_wpa_param *param; @@ -930,10 +833,10 @@ int wpa_ioctl(PSDevice pDevice, struct iw_point *p) int wpa_ioctl = 0; if (p->length < sizeof(struct viawget_wpa_param) || - p->length > VIAWGET_WPA_MAX_BUF_SIZE || !p->pointer) + p->length > VIAWGET_WPA_MAX_BUF_SIZE || !p->pointer) return -EINVAL; - param = kmalloc((int)p->length, (int)GFP_KERNEL); + param = kmalloc((int)p->length, GFP_KERNEL); if (param == NULL) return -ENOMEM; @@ -944,63 +847,62 @@ int wpa_ioctl(PSDevice pDevice, struct iw_point *p) switch (param->cmd) { case VIAWGET_SET_WPA: - ret = wpa_set_wpa(pDevice, param); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_WPA \n"); + ret = wpa_set_wpa(pDevice, param); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_WPA \n"); break; case VIAWGET_SET_KEY: - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_KEY \n"); - spin_lock_irq(&pDevice->lock); - ret = wpa_set_keys(pDevice, param, FALSE); - spin_unlock_irq(&pDevice->lock); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_KEY \n"); + spin_lock_irq(&pDevice->lock); + ret = wpa_set_keys(pDevice, param, FALSE); + spin_unlock_irq(&pDevice->lock); break; case VIAWGET_SET_SCAN: - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_SCAN \n"); - ret = wpa_set_scan(pDevice, param); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_SCAN \n"); + ret = wpa_set_scan(pDevice, param); break; case VIAWGET_GET_SCAN: - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_GET_SCAN\n"); - ret = wpa_get_scan(pDevice, param); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_GET_SCAN\n"); + ret = wpa_get_scan(pDevice, param); wpa_ioctl = 1; break; case VIAWGET_GET_SSID: - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_GET_SSID \n"); - ret = wpa_get_ssid(pDevice, param); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_GET_SSID \n"); + ret = wpa_get_ssid(pDevice, param); wpa_ioctl = 1; break; case VIAWGET_GET_BSSID: - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_GET_BSSID \n"); - ret = wpa_get_bssid(pDevice, param); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_GET_BSSID \n"); + ret = wpa_get_bssid(pDevice, param); wpa_ioctl = 1; break; case VIAWGET_SET_ASSOCIATE: - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_ASSOCIATE \n"); - ret = wpa_set_associate(pDevice, param); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_ASSOCIATE \n"); + ret = wpa_set_associate(pDevice, param); break; case VIAWGET_SET_DISASSOCIATE: - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_DISASSOCIATE \n"); - ret = wpa_set_disassociate(pDevice, param); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_DISASSOCIATE \n"); + ret = wpa_set_disassociate(pDevice, param); break; case VIAWGET_SET_DROP_UNENCRYPT: - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_DROP_UNENCRYPT \n"); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_DROP_UNENCRYPT \n"); break; - case VIAWGET_SET_DEAUTHENTICATE: - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_DEAUTHENTICATE \n"); + case VIAWGET_SET_DEAUTHENTICATE: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_DEAUTHENTICATE \n"); break; default: - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wpa_ioctl: unknown cmd=%d\n", - param->cmd); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wpa_ioctl: unknown cmd=%d\n", + param->cmd); return -EOPNOTSUPP; - break; } if ((ret == 0) && wpa_ioctl) { @@ -1012,7 +914,5 @@ int wpa_ioctl(PSDevice pDevice, struct iw_point *p) out: kfree(param); - return ret; } - -- cgit v0.10.2 From e3b09e4bf6455caccc7ef215256e4f0065fbca7d Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Mon, 16 Jan 2012 21:28:37 +0100 Subject: staging, vt6656/wpactl.c: Fix mem leak in wpa_ioctl() If we hit the default case in the switch statement in wpa_ioctl() we'll leak the memory allocated to 'param' when the variable goes out of scope without having been assigned to anything. This patch fixes the leak by kfree()'ing the memory before we return from the function. Signed-off-by: Jesper Juhl Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/vt6656/wpactl.c b/drivers/staging/vt6656/wpactl.c index 9d14868..5435e82 100644 --- a/drivers/staging/vt6656/wpactl.c +++ b/drivers/staging/vt6656/wpactl.c @@ -902,6 +902,7 @@ int wpa_ioctl(PSDevice pDevice, struct iw_point *p) default: DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wpa_ioctl: unknown cmd=%d\n", param->cmd); + kfree(param); return -EOPNOTSUPP; } -- cgit v0.10.2 From e24b0a3f0c9ab95a7910458f3b4d90fdf19954e2 Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Sun, 15 Jan 2012 20:34:52 +0100 Subject: staging/xgifb: Remove unsupported mode LCD_320x480 This patch removes the probed mode LCD_320x480 which isn't supported anyway since this mode falls through to the default (=invalid) mode in the XGIfb_validate_mode function (see line 529 ff. for details. the commented out code for this mode is also removed). By removing this assignment, we can use the LCD_TYPEs from the sis driver without modifications. Signed-off-by: Peter Huewe Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c index 2502c49..e618aa6 100644 --- a/drivers/staging/xgifb/XGI_main_26.c +++ b/drivers/staging/xgifb/XGI_main_26.c @@ -526,12 +526,6 @@ static int XGIfb_validate_mode(struct xgifb_video_info *xgifb_info, int myindex) xres = 1600; yres = 1200; break; - /* case LCD_320x480: */ /* TW: FSTN */ - /* - xres = 320; - yres = 480; - break; - */ default: xres = 0; yres = 0; @@ -2117,10 +2111,6 @@ static int __devinit xgifb_probe(struct pci_dev *pdev, reg = xgifb_reg_get(XGICR, IND_XGI_LCD_PANEL); reg &= 0x0f; hw_info->ulCRT2LCDType = XGI310paneltype[reg]; - - } else { - /* TW: FSTN/DSTN */ - hw_info->ulCRT2LCDType = LCD_320x480; } } -- cgit v0.10.2 From b33704dffa36f3ed972602ea9ef8b46d3d5e3b06 Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Sun, 15 Jan 2012 19:22:11 +0100 Subject: staging/xgifb: Include sis headers This patch includes the headers of the sis driver and reorders some includes. Since the xgi driver used to redefine a lot of stuff from the sis driver, we can simply include the headers of the sis driver itself, so we can remove duplicated stuff later on. Signed-off-by: Peter Huewe Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/xgifb/XGI_main.h b/drivers/staging/xgifb/XGI_main.h index 35f7b2a..fdee421 100644 --- a/drivers/staging/xgifb/XGI_main.h +++ b/drivers/staging/xgifb/XGI_main.h @@ -7,6 +7,7 @@ #include "XGIfb.h" #include "vb_struct.h" +#include "../../video/sis/sis.h" #include "vb_def.h" #define XGIFAIL(x) do { printk(x "\n"); return -EINVAL; } while (0) diff --git a/drivers/staging/xgifb/XGIfb.h b/drivers/staging/xgifb/XGIfb.h index 2c866bb..37bb730 100644 --- a/drivers/staging/xgifb/XGIfb.h +++ b/drivers/staging/xgifb/XGIfb.h @@ -3,8 +3,8 @@ #include #include -#include "vb_struct.h" #include "vgatypes.h" +#include "vb_struct.h" enum xgifb_display_type { XGIFB_DISP_NONE = 0, diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c index 4ccd988..a53a097 100644 --- a/drivers/staging/xgifb/vb_init.c +++ b/drivers/staging/xgifb/vb_init.c @@ -3,8 +3,8 @@ #include #include -#include "vgatypes.h" #include "XGIfb.h" +#include "vgatypes.h" #include "vb_def.h" #include "vb_struct.h" diff --git a/drivers/staging/xgifb/vb_struct.h b/drivers/staging/xgifb/vb_struct.h index 6556a0d..d70df04 100644 --- a/drivers/staging/xgifb/vb_struct.h +++ b/drivers/staging/xgifb/vb_struct.h @@ -10,6 +10,7 @@ struct XGI_LCDDataStruct { unsigned short LCDVT; }; +#include "../../video/sis/vstruct.h" struct XGI_LVDSCRT1HDataStruct { unsigned char Reg[8]; diff --git a/drivers/staging/xgifb/vgatypes.h b/drivers/staging/xgifb/vgatypes.h index 9e166bb..a7208e3 100644 --- a/drivers/staging/xgifb/vgatypes.h +++ b/drivers/staging/xgifb/vgatypes.h @@ -2,6 +2,9 @@ #define _VGATYPES_ #include +#include /* for struct fb_var_screeninfo for sis.h */ +#include "../../video/sis/vgatypes.h" +#include "../../video/sis/sis.h" /* for LCD_TYPE */ #ifndef XGI_VB_CHIP_TYPE enum XGI_VB_CHIP_TYPE { @@ -19,6 +22,12 @@ enum XGI_VB_CHIP_TYPE { }; #endif + +#define XGI_LCD_TYPE +/* Since the merge with video/sis the LCD_TYPEs are used from + drivers/video/sis/sis.h . Nevertheless we keep this (for the moment) for + future reference until the code is merged completely and we are sure + nothing of this should be added to the sis.h header */ #ifndef XGI_LCD_TYPE enum XGI_LCD_TYPE { LCD_INVALID = 0, -- cgit v0.10.2 From fc39dcb7fa8bb917484a5b229cf3751dd3aa7313 Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Sun, 15 Jan 2012 19:22:12 +0100 Subject: staging/xgifb: Use structs and defines from the sis headers This patch removes the usage of some xgi structs and defines and replaces them with the _identical_ structs from the sis headers. Thus the old structs and defines can be removed. Signed-off-by: Peter Huewe Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c index e618aa6..ff7a144 100644 --- a/drivers/staging/xgifb/XGI_main_26.c +++ b/drivers/staging/xgifb/XGI_main_26.c @@ -805,27 +805,27 @@ static void XGIfb_pre_setmode(struct xgifb_video_info *xgifb_info) switch (xgifb_info->display2) { case XGIFB_DISP_CRT: - cr30 = (XGI_VB_OUTPUT_CRT2 | XGI_SIMULTANEOUS_VIEW_ENABLE); - cr31 |= XGI_DRIVER_MODE; + cr30 = (SIS_VB_OUTPUT_CRT2 | SIS_SIMULTANEOUS_VIEW_ENABLE); + cr31 |= SIS_DRIVER_MODE; break; case XGIFB_DISP_LCD: - cr30 = (XGI_VB_OUTPUT_LCD | XGI_SIMULTANEOUS_VIEW_ENABLE); - cr31 |= XGI_DRIVER_MODE; + cr30 = (SIS_VB_OUTPUT_LCD | SIS_SIMULTANEOUS_VIEW_ENABLE); + cr31 |= SIS_DRIVER_MODE; break; case XGIFB_DISP_TV: if (xgifb_info->TV_type == TVMODE_HIVISION) - cr30 = (XGI_VB_OUTPUT_HIVISION - | XGI_SIMULTANEOUS_VIEW_ENABLE); + cr30 = (SIS_VB_OUTPUT_HIVISION + | SIS_SIMULTANEOUS_VIEW_ENABLE); else if (xgifb_info->TV_plug == TVPLUG_SVIDEO) - cr30 = (XGI_VB_OUTPUT_SVIDEO - | XGI_SIMULTANEOUS_VIEW_ENABLE); + cr30 = (SIS_VB_OUTPUT_SVIDEO + | SIS_SIMULTANEOUS_VIEW_ENABLE); else if (xgifb_info->TV_plug == TVPLUG_COMPOSITE) - cr30 = (XGI_VB_OUTPUT_COMPOSITE - | XGI_SIMULTANEOUS_VIEW_ENABLE); + cr30 = (SIS_VB_OUTPUT_COMPOSITE + | SIS_SIMULTANEOUS_VIEW_ENABLE); else if (xgifb_info->TV_plug == TVPLUG_SCART) - cr30 = (XGI_VB_OUTPUT_SCART - | XGI_SIMULTANEOUS_VIEW_ENABLE); - cr31 |= XGI_DRIVER_MODE; + cr30 = (SIS_VB_OUTPUT_SCART + | SIS_SIMULTANEOUS_VIEW_ENABLE); + cr31 |= SIS_DRIVER_MODE; if (XGIfb_tvmode == 1 || xgifb_info->TV_type == TVMODE_PAL) cr31 |= 0x01; @@ -834,7 +834,7 @@ static void XGIfb_pre_setmode(struct xgifb_video_info *xgifb_info) break; default: /* disable CRT2 */ cr30 = 0x00; - cr31 |= (XGI_DRIVER_MODE | XGI_VB_OUTPUT_DISABLE); + cr31 |= (SIS_DRIVER_MODE | SIS_VB_OUTPUT_DISABLE); } xgifb_reg_set(XGICR, IND_XGI_SCRATCH_REG_CR30, cr30); @@ -848,7 +848,7 @@ static void XGIfb_post_setmode(struct xgifb_video_info *xgifb_info) u8 reg; unsigned char doit = 1; /* - xgifb_reg_set(XGISR,IND_XGI_PASSWORD,XGI_PASSWORD); + xgifb_reg_set(XGISR,IND_SIS_PASSWORD,SIS_PASSWORD); xgifb_reg_set(XGICR, 0x13, 0x00); xgifb_reg_and_or(XGISR,0x0E, 0xF0, 0x01); *test* @@ -884,7 +884,7 @@ static void XGIfb_post_setmode(struct xgifb_video_info *xgifb_info) reg |= 0x80; xgifb_reg_set(XGICR, 0x17, reg); - xgifb_reg_and(XGISR, IND_XGI_RAMDAC_CONTROL, ~0x04); + xgifb_reg_and(XGISR, IND_SIS_RAMDAC_CONTROL, ~0x04); if (xgifb_info->display2 == XGIFB_DISP_TV && xgifb_info->hasVB == HASVB_301) { @@ -917,7 +917,7 @@ static void XGIfb_post_setmode(struct xgifb_video_info *xgifb_info) break; } xgifb_reg_or(XGIPART1, - IND_XGI_CRT2_WRITE_ENABLE_315, + SIS_CRT2_WENABLE_315, 0x01); if (xgifb_info->TV_type == TVMODE_NTSC) { @@ -1178,7 +1178,7 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive, info->fix.line_length = ((info->var.xres_virtual * info->var.bits_per_pixel) >> 6); - xgifb_reg_set(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD); + xgifb_reg_set(XGISR, IND_SIS_PASSWORD, SIS_PASSWORD); xgifb_reg_set(XGICR, 0x13, (info->fix.line_length & 0x00ff)); xgifb_reg_set(XGISR, @@ -1267,7 +1267,7 @@ static int XGIfb_pan_var(struct fb_var_screeninfo *var, struct fb_info *info) break; } - xgifb_reg_set(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD); + xgifb_reg_set(XGISR, IND_SIS_PASSWORD, SIS_PASSWORD); xgifb_reg_set(XGICR, 0x0D, base & 0xFF); xgifb_reg_set(XGICR, 0x0C, (base >> 8) & 0xFF); @@ -1276,7 +1276,7 @@ static int XGIfb_pan_var(struct fb_var_screeninfo *var, struct fb_info *info) xgifb_reg_and_or(XGISR, 0x37, 0xDF, (base >> 21) & 0x04); if (xgifb_info->display2 != XGIFB_DISP_NONE) { - xgifb_reg_or(XGIPART1, IND_XGI_CRT2_WRITE_ENABLE_315, 0x01); + xgifb_reg_or(XGIPART1, SIS_CRT2_WENABLE_315, 0x01); xgifb_reg_set(XGIPART1, 0x06, (base & 0xFF)); xgifb_reg_set(XGIPART1, 0x05, ((base >> 8) & 0xFF)); xgifb_reg_set(XGIPART1, 0x04, ((base >> 16) & 0xFF)); @@ -1381,7 +1381,7 @@ static int XGIfb_get_fix(struct fb_fix_screeninfo *fix, int con, fix->line_length = xgifb_info->video_linelength; fix->mmio_start = xgifb_info->mmio_base; fix->mmio_len = xgifb_info->mmio_size; - fix->accel = FB_ACCEL_XGI_XABRE; + fix->accel = FB_ACCEL_SIS_XABRE; DEBUGPRN("end of get_fix"); return 0; @@ -1628,9 +1628,9 @@ static int XGIfb_get_dram_size(struct xgifb_video_info *xgifb_info) /* xorg driver sets 32MB * 1 channel */ if (xgifb_info->chip == XG27) - xgifb_reg_set(XGISR, IND_XGI_DRAM_SIZE, 0x51); + xgifb_reg_set(XGISR, IND_SIS_DRAM_SIZE, 0x51); - reg = xgifb_reg_get(XGISR, IND_XGI_DRAM_SIZE); + reg = xgifb_reg_get(XGISR, IND_SIS_DRAM_SIZE); switch ((reg & XGI_DRAM_SIZE_MASK) >> 4) { case XGI_DRAM_SIZE_1MB: xgifb_info->video_size = 0x100000; @@ -1730,7 +1730,7 @@ static void XGIfb_detect_VB(struct xgifb_video_info *xgifb_info) cr32 = xgifb_reg_get(XGICR, IND_XGI_SCRATCH_REG_CR32); - if ((cr32 & XGI_CRT1) && !XGIfb_crt1off) + if ((cr32 & SIS_CRT1) && !XGIfb_crt1off) XGIfb_crt1off = 0; else { if (cr32 & 0x5F) @@ -1740,11 +1740,11 @@ static void XGIfb_detect_VB(struct xgifb_video_info *xgifb_info) } if (!xgifb_info->display2_force) { - if (cr32 & XGI_VB_TV) + if (cr32 & SIS_VB_TV) xgifb_info->display2 = XGIFB_DISP_TV; - else if (cr32 & XGI_VB_LCD) + else if (cr32 & SIS_VB_LCD) xgifb_info->display2 = XGIFB_DISP_LCD; - else if (cr32 & XGI_VB_CRT2) + else if (cr32 & SIS_VB_CRT2) xgifb_info->display2 = XGIFB_DISP_CRT; else xgifb_info->display2 = XGIFB_DISP_NONE; @@ -1753,14 +1753,14 @@ static void XGIfb_detect_VB(struct xgifb_video_info *xgifb_info) if (XGIfb_tvplug != -1) /* PR/TW: Override with option */ xgifb_info->TV_plug = XGIfb_tvplug; - else if (cr32 & XGI_VB_HIVISION) { + else if (cr32 & SIS_VB_HIVISION) { xgifb_info->TV_type = TVMODE_HIVISION; xgifb_info->TV_plug = TVPLUG_SVIDEO; - } else if (cr32 & XGI_VB_SVIDEO) + } else if (cr32 & SIS_VB_SVIDEO) xgifb_info->TV_plug = TVPLUG_SVIDEO; - else if (cr32 & XGI_VB_COMPOSITE) + else if (cr32 & SIS_VB_COMPOSITE) xgifb_info->TV_plug = TVPLUG_COMPOSITE; - else if (cr32 & XGI_VB_SCART) + else if (cr32 & SIS_VB_SCART) xgifb_info->TV_plug = TVPLUG_SCART; if (xgifb_info->TV_type == 0) { @@ -1805,11 +1805,11 @@ static void XGIfb_get_VB_type(struct xgifb_video_info *xgifb_info) if (!XGIfb_has_VB(xgifb_info)) { reg = xgifb_reg_get(XGICR, IND_XGI_SCRATCH_REG_CR37); - switch ((reg & XGI_EXTERNAL_CHIP_MASK) >> 1) { - case XGI310_EXTERNAL_CHIP_LVDS: + switch ((reg & SIS_EXTERNAL_CHIP_MASK) >> 1) { + case SIS_EXTERNAL_CHIP_LVDS: xgifb_info->hasVB = HASVB_LVDS; break; - case XGI310_EXTERNAL_CHIP_LVDS_CHRONTEL: + case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL: xgifb_info->hasVB = HASVB_LVDS_CHRONTEL; break; default: @@ -1927,8 +1927,8 @@ static int __devinit xgifb_probe(struct pci_dev *pdev, XGIRegInit(&xgifb_info->dev_info, (unsigned long)hw_info->pjIOAddress); - xgifb_reg_set(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD); - reg1 = xgifb_reg_get(XGISR, IND_XGI_PASSWORD); + xgifb_reg_set(XGISR, IND_SIS_PASSWORD, SIS_PASSWORD); + reg1 = xgifb_reg_get(XGISR, IND_SIS_PASSWORD); if (reg1 != 0xa1) { /*I/O error */ printk("\nXGIfb: I/O error!!!"); @@ -1937,7 +1937,7 @@ static int __devinit xgifb_probe(struct pci_dev *pdev, } switch (xgifb_info->chip_id) { - case PCI_DEVICE_ID_XG_20: + case PCI_DEVICE_ID_XGI_20: xgifb_reg_or(XGICR, Index_CR_GPIO_Reg3, GPIOG_EN); CR48 = xgifb_reg_get(XGICR, Index_CR_GPIO_Reg1); if (CR48&GPIOG_READ) @@ -1945,16 +1945,16 @@ static int __devinit xgifb_probe(struct pci_dev *pdev, else xgifb_info->chip = XG20; break; - case PCI_DEVICE_ID_XG_40: + case PCI_DEVICE_ID_XGI_40: xgifb_info->chip = XG40; break; - case PCI_DEVICE_ID_XG_41: + case PCI_DEVICE_ID_XGI_41: xgifb_info->chip = XG41; break; - case PCI_DEVICE_ID_XG_42: + case PCI_DEVICE_ID_XGI_42: xgifb_info->chip = XG42; break; - case PCI_DEVICE_ID_XG_27: + case PCI_DEVICE_ID_XGI_27: xgifb_info->chip = XG27; break; default: @@ -1973,10 +1973,10 @@ static int __devinit xgifb_probe(struct pci_dev *pdev, /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */ xgifb_reg_or(XGISR, - IND_XGI_PCI_ADDRESS_SET, - (XGI_PCI_ADDR_ENABLE | XGI_MEM_MAP_IO_ENABLE)); + IND_SIS_PCI_ADDRESS_SET, + (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE)); /* Enable 2D accelerator engine */ - xgifb_reg_or(XGISR, IND_XGI_MODULE_ENABLE, XGI_ENABLE_2D); + xgifb_reg_or(XGISR, IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D); hw_info->ulVideoMemorySize = xgifb_info->video_size; diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index 67a316c..fad144c 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -61,20 +61,20 @@ static const unsigned short XGINew_VGA_DAC[] = { void InitTo330Pointer(unsigned char ChipType, struct vb_device_info *pVBInfo) { pVBInfo->SModeIDTable = (struct XGI_StStruct *) XGI330_SModeIDTable; - pVBInfo->StandTable = (struct XGI_StandTableStruct *) XGI330_StandTable; + pVBInfo->StandTable = (struct SiS_StandTable_S *) XGI330_StandTable; pVBInfo->EModeIDTable = (struct XGI_ExtStruct *) XGI330_EModeIDTable; pVBInfo->RefIndex = (struct XGI_Ext2Struct *) XGI330_RefIndex; pVBInfo->XGINEWUB_CRT1Table = (struct XGI_CRT1TableStruct *) XGI_CRT1Table; - pVBInfo->MCLKData = (struct XGI_MCLKDataStruct *) XGI340New_MCLKData; + pVBInfo->MCLKData = (struct SiS_MCLKData *) XGI340New_MCLKData; pVBInfo->ECLKData = (struct XGI_ECLKDataStruct *) XGI340_ECLKData; - pVBInfo->VCLKData = (struct XGI_VCLKDataStruct *) XGI_VCLKData; - pVBInfo->VBVCLKData = (struct XGI_VBVCLKDataStruct *) XGI_VBVCLKData; + pVBInfo->VCLKData = (struct SiS_VCLKData *) XGI_VCLKData; + pVBInfo->VBVCLKData = (struct SiS_VBVCLKData *) XGI_VBVCLKData; pVBInfo->ScreenOffset = XGI330_ScreenOffset; - pVBInfo->StResInfo = (struct XGI_StResInfoStruct *) XGI330_StResInfo; + pVBInfo->StResInfo = (struct SiS_StResInfo_S *) XGI330_StResInfo; pVBInfo->ModeResInfo - = (struct XGI_ModeResInfoStruct *) XGI330_ModeResInfo; + = (struct SiS_ModeResInfo_S *) XGI330_ModeResInfo; pVBInfo->pOutputSelect = &XGI330_OutputSelect; pVBInfo->pSoftSetting = &XGI330_SoftSetting; @@ -153,7 +153,7 @@ void InitTo330Pointer(unsigned char ChipType, struct vb_device_info *pVBInfo) if (ChipType == XG27) { pVBInfo->MCLKData - = (struct XGI_MCLKDataStruct *) XGI27New_MCLKData; + = (struct SiS_MCLKData *) XGI27New_MCLKData; pVBInfo->CR40 = XGI27_cr41; pVBInfo->pXGINew_CR97 = &XG27_CR97; pVBInfo->pSR36 = &XG27_SR36; @@ -3918,8 +3918,8 @@ static void XGI_GetCRT2Data(unsigned short ModeNo, unsigned short ModeIdIndex, { unsigned short tempax = 0, tempbx, modeflag, resinfo; - struct XGI_LCDDataStruct *LCDPtr = NULL; - struct XGI_TVDataStruct *TVPtr = NULL; + struct SiS_LCDData *LCDPtr = NULL; + struct SiS_TVData *TVPtr = NULL; if (ModeNo <= 0x13) { /* si+St_ResInfo */ @@ -3943,7 +3943,7 @@ static void XGI_GetCRT2Data(unsigned short ModeNo, unsigned short ModeIdIndex, tempbx = 4; if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { - LCDPtr = (struct XGI_LCDDataStruct *) XGI_GetLcdPtr(tempbx, + LCDPtr = (struct SiS_LCDData *) XGI_GetLcdPtr(tempbx, ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo); @@ -4028,7 +4028,7 @@ static void XGI_GetCRT2Data(unsigned short ModeNo, unsigned short ModeIdIndex, if (pVBInfo->VBInfo & (SetCRT2ToTV)) { tempbx = 4; - TVPtr = (struct XGI_TVDataStruct *) XGI_GetTVPtr(tempbx, + TVPtr = (struct SiS_TVData *) XGI_GetTVPtr(tempbx, ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo); diff --git a/drivers/staging/xgifb/vb_struct.h b/drivers/staging/xgifb/vb_struct.h index d70df04..76a17c2 100644 --- a/drivers/staging/xgifb/vb_struct.h +++ b/drivers/staging/xgifb/vb_struct.h @@ -351,7 +351,7 @@ struct vb_device_info { unsigned char *pCRT2Data_4_D; unsigned char *pCRT2Data_4_E; unsigned char *pCRT2Data_4_10; - struct XGI_MCLKDataStruct *MCLKData; + struct SiS_MCLKData *MCLKData; struct XGI_ECLKDataStruct *ECLKData; unsigned char *XGI_TVDelayList; @@ -381,15 +381,15 @@ struct vb_device_info { struct XGI_TimingVStruct *TimingV; struct XGI_StStruct *SModeIDTable; - struct XGI_StandTableStruct *StandTable; + struct SiS_StandTable_S *StandTable; struct XGI_ExtStruct *EModeIDTable; struct XGI_Ext2Struct *RefIndex; /* XGINew_CRT1TableStruct *CRT1Table; */ struct XGI_CRT1TableStruct *XGINEWUB_CRT1Table; - struct XGI_VCLKDataStruct *VCLKData; - struct XGI_VBVCLKDataStruct *VBVCLKData; - struct XGI_StResInfoStruct *StResInfo; - struct XGI_ModeResInfoStruct *ModeResInfo; + struct SiS_VCLKData *VCLKData; + struct SiS_VBVCLKData *VBVCLKData; + struct SiS_StResInfo_S *StResInfo; + struct SiS_ModeResInfo_S *ModeResInfo; struct XGI_XG21CRT1Struct *UpdateCRT1; int ram_type; diff --git a/drivers/staging/xgifb/vb_table.h b/drivers/staging/xgifb/vb_table.h index e7946f1..217fb87 100644 --- a/drivers/staging/xgifb/vb_table.h +++ b/drivers/staging/xgifb/vb_table.h @@ -1,5 +1,5 @@ /* yilin modify for xgi20 */ -static struct XGI_MCLKDataStruct XGI340New_MCLKData[] = { +static struct SiS_MCLKData XGI340New_MCLKData[] = { {0x16, 0x01, 0x01, 166}, {0x19, 0x02, 0x01, 124}, {0x7C, 0x08, 0x01, 200}, @@ -10,7 +10,7 @@ static struct XGI_MCLKDataStruct XGI340New_MCLKData[] = { {0x5c, 0x23, 0x01, 166} }; -static struct XGI_MCLKDataStruct XGI27New_MCLKData[] = { +static struct SiS_MCLKData XGI27New_MCLKData[] = { {0x5c, 0x23, 0x01, 166}, {0x19, 0x02, 0x01, 124}, {0x7C, 0x08, 0x80, 200}, @@ -296,7 +296,7 @@ static struct XGI_ExtStruct XGI330_EModeIDTable[] = { 0x00, 0x00, 0x00, 0x00, 0x00} }; -static struct XGI_StandTableStruct XGI330_StandTable[] = { +static struct SiS_StandTable_S XGI330_StandTable[] = { /* MD_0_200 */ { 0x28, 0x18, 0x08, 0x0800, @@ -2729,7 +2729,7 @@ static unsigned char XGI330_ScreenOffset[] = { 0x57, 0x48 }; -static struct XGI_StResInfoStruct XGI330_StResInfo[] = { +static struct SiS_StResInfo_S XGI330_StResInfo[] = { {640, 400}, {640, 350}, {720, 400}, @@ -2737,7 +2737,7 @@ static struct XGI_StResInfoStruct XGI330_StResInfo[] = { {640, 480} }; -static struct XGI_ModeResInfoStruct XGI330_ModeResInfo[] = { +static struct SiS_ModeResInfo_S XGI330_ModeResInfo[] = { { 320, 200, 8, 8}, { 320, 240, 8, 8}, { 320, 400, 8, 8}, -- cgit v0.10.2 From 7ad6651d78dbf269c76f6ca141c2a9629943bb49 Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Sun, 15 Jan 2012 19:22:13 +0100 Subject: staging/xgifb: Remove remaining duplicate structs and defines This patch removes the now unused structs and defines which were mere duplicates of the ones in the sgi headers Signed-off-by: Peter Huewe Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/xgifb/XGI_main.h b/drivers/staging/xgifb/XGI_main.h index fdee421..e828fd4 100644 --- a/drivers/staging/xgifb/XGI_main.h +++ b/drivers/staging/xgifb/XGI_main.h @@ -12,43 +12,27 @@ #define XGIFAIL(x) do { printk(x "\n"); return -EINVAL; } while (0) -#ifndef PCI_VENDOR_ID_XG -#define PCI_VENDOR_ID_XG 0x18CA +#ifndef PCI_DEVICE_ID_XGI_41 +#define PCI_DEVICE_ID_XGI_41 0x041 #endif - -#ifndef PCI_DEVICE_ID_XG_40 -#define PCI_DEVICE_ID_XG_40 0x040 -#endif -#ifndef PCI_DEVICE_ID_XG_41 -#define PCI_DEVICE_ID_XG_41 0x041 -#endif -#ifndef PCI_DEVICE_ID_XG_42 -#define PCI_DEVICE_ID_XG_42 0x042 +#ifndef PCI_DEVICE_ID_XGI_42 +#define PCI_DEVICE_ID_XGI_42 0x042 #endif -#ifndef PCI_DEVICE_ID_XG_20 -#define PCI_DEVICE_ID_XG_20 0x020 -#endif -#ifndef PCI_DEVICE_ID_XG_27 -#define PCI_DEVICE_ID_XG_27 0x027 +#ifndef PCI_DEVICE_ID_XGI_27 +#define PCI_DEVICE_ID_XGI_27 0x027 #endif static DEFINE_PCI_DEVICE_TABLE(xgifb_pci_table) = { - {PCI_DEVICE(PCI_VENDOR_ID_XG, PCI_DEVICE_ID_XG_20)}, - {PCI_DEVICE(PCI_VENDOR_ID_XG, PCI_DEVICE_ID_XG_27)}, - {PCI_DEVICE(PCI_VENDOR_ID_XG, PCI_DEVICE_ID_XG_40)}, - {PCI_DEVICE(PCI_VENDOR_ID_XG, PCI_DEVICE_ID_XG_42)}, + {PCI_DEVICE(PCI_VENDOR_ID_XGI, PCI_DEVICE_ID_XGI_20)}, + {PCI_DEVICE(PCI_VENDOR_ID_XGI, PCI_DEVICE_ID_XGI_27)}, + {PCI_DEVICE(PCI_VENDOR_ID_XGI, PCI_DEVICE_ID_XGI_40)}, + {PCI_DEVICE(PCI_VENDOR_ID_XGI, PCI_DEVICE_ID_XGI_42)}, {0} }; MODULE_DEVICE_TABLE(pci, xgifb_pci_table); /* To be included in fb.h */ -#ifndef FB_ACCEL_XGI_XABRE -#define FB_ACCEL_XGI_XABRE 41 /* XGI 330 ("Xabre") */ -#endif - -#define SEQ_DATA 0x15 - #define XGISR (xgifb_info->dev_info.P3c4) #define XGICR (xgifb_info->dev_info.P3d4) #define XGIDACA (xgifb_info->dev_info.P3c8) @@ -61,12 +45,6 @@ MODULE_DEVICE_TABLE(pci, xgifb_pci_table); #define XGIDAC2A XGIPART5 #define XGIDAC2D (XGIPART5 + 1) -#define IND_XGI_PASSWORD 0x05 /* SRs */ -#define IND_XGI_RAMDAC_CONTROL 0x07 -#define IND_XGI_DRAM_SIZE 0x14 -#define IND_XGI_MODULE_ENABLE 0x1E -#define IND_XGI_PCI_ADDRESS_SET 0x20 - #define IND_XGI_SCRATCH_REG_CR30 0x30 /* CRs */ #define IND_XGI_SCRATCH_REG_CR31 0x31 #define IND_XGI_SCRATCH_REG_CR32 0x32 @@ -74,10 +52,6 @@ MODULE_DEVICE_TABLE(pci, xgifb_pci_table); #define IND_XGI_LCD_PANEL 0x36 #define IND_XGI_SCRATCH_REG_CR37 0x37 -#define IND_XGI_CRT2_WRITE_ENABLE_315 0x2F - -#define XGI_PASSWORD 0x86 /* SR05 */ - #define XGI_DRAM_SIZE_MASK 0xF0 /*SR14 */ #define XGI_DRAM_SIZE_1MB 0x00 #define XGI_DRAM_SIZE_2MB 0x01 @@ -89,37 +63,6 @@ MODULE_DEVICE_TABLE(pci, xgifb_pci_table); #define XGI_DRAM_SIZE_128MB 0x07 #define XGI_DRAM_SIZE_256MB 0x08 -#define XGI_ENABLE_2D 0x40 /* SR1E */ - -#define XGI_MEM_MAP_IO_ENABLE 0x01 /* SR20 */ -#define XGI_PCI_ADDR_ENABLE 0x80 - -#define XGI_SIMULTANEOUS_VIEW_ENABLE 0x01 /* CR30 */ -#define XGI_VB_OUTPUT_COMPOSITE 0x04 -#define XGI_VB_OUTPUT_SVIDEO 0x08 -#define XGI_VB_OUTPUT_SCART 0x10 -#define XGI_VB_OUTPUT_LCD 0x20 -#define XGI_VB_OUTPUT_CRT2 0x40 -#define XGI_VB_OUTPUT_HIVISION 0x80 - -#define XGI_VB_OUTPUT_DISABLE 0x20 /* CR31 */ -#define XGI_DRIVER_MODE 0x40 - -#define XGI_VB_COMPOSITE 0x01 /* CR32 */ -#define XGI_VB_SVIDEO 0x02 -#define XGI_VB_SCART 0x04 -#define XGI_VB_LCD 0x08 -#define XGI_VB_CRT2 0x10 -#define XGI_CRT1 0x20 -#define XGI_VB_HIVISION 0x40 -#define XGI_VB_YPBPR 0x80 -#define XGI_VB_TV (XGI_VB_COMPOSITE | XGI_VB_SVIDEO | \ - XGI_VB_SCART | XGI_VB_HIVISION|XGI_VB_YPBPR) - -#define XGI_EXTERNAL_CHIP_MASK 0x0E /* CR37 */ -#define XGI310_EXTERNAL_CHIP_LVDS 0x02 /* in CR37 << 1 ! */ -#define XGI310_EXTERNAL_CHIP_LVDS_CHRONTEL 0x03 /* in CR37 << 1 ! */ - /* ------------------- Global Variables ----------------------------- */ /* display status */ diff --git a/drivers/staging/xgifb/vb_struct.h b/drivers/staging/xgifb/vb_struct.h index 76a17c2..a5bd56a 100644 --- a/drivers/staging/xgifb/vb_struct.h +++ b/drivers/staging/xgifb/vb_struct.h @@ -1,15 +1,5 @@ #ifndef _VB_STRUCT_ #define _VB_STRUCT_ - -struct XGI_LCDDataStruct { - unsigned short RVBHCMAX; - unsigned short RVBHCFACT; - unsigned short VGAHT; - unsigned short VGAVT; - unsigned short LCDHT; - unsigned short LCDVT; -}; - #include "../../video/sis/vstruct.h" struct XGI_LVDSCRT1HDataStruct { @@ -20,22 +10,6 @@ struct XGI_LVDSCRT1VDataStruct { unsigned char Reg[7]; }; -struct XGI_TVDataStruct { - unsigned short RVBHCMAX; - unsigned short RVBHCFACT; - unsigned short VGAHT; - unsigned short VGAVT; - unsigned short TVHDE; - unsigned short TVVDE; - unsigned short RVBHRS; - unsigned char FlickerMode; - unsigned short HALFRVBHRS; - unsigned char RY1COE; - unsigned char RY2COE; - unsigned char RY3COE; - unsigned char RY4COE; -}; - struct XGI_StStruct { unsigned char St_ModeID; unsigned short St_ModeFlag; @@ -48,18 +22,6 @@ struct XGI_StStruct { unsigned char VB_StTVYFilterIndex; }; -struct XGI_StandTableStruct { - unsigned char CRT_COLS; - unsigned char ROWS; - unsigned char CHAR_HEIGHT; - unsigned short CRT_LEN; - unsigned char SR[4]; - unsigned char MISC; - unsigned char CRTC[0x19]; - unsigned char ATTR[0x14]; - unsigned char GRC[9]; -}; - struct XGI_ExtStruct { unsigned char Ext_ModeID; unsigned short Ext_ModeFlag; @@ -86,39 +48,11 @@ struct XGI_Ext2Struct { /* unsigned short ROM_OFFSET; */ }; - -struct XGI_MCLKDataStruct { - unsigned char SR28, SR29, SR2A; - unsigned short CLOCK; -}; - struct XGI_ECLKDataStruct { unsigned char SR2E, SR2F, SR30; unsigned short CLOCK; }; -struct XGI_VCLKDataStruct { - unsigned char SR2B, SR2C; - unsigned short CLOCK; -}; - -struct XGI_VBVCLKDataStruct { - unsigned char Part4_A, Part4_B; - unsigned short CLOCK; -}; - -struct XGI_StResInfoStruct { - unsigned short HTotal; - unsigned short VTotal; -}; - -struct XGI_ModeResInfoStruct { - unsigned short HTotal; - unsigned short VTotal; - unsigned char XChar; - unsigned char YChar; -}; - /*add for new UNIVGABIOS*/ struct XGI_LCDDesStruct { unsigned short LCDHDES; -- cgit v0.10.2 From 96c66042be64c08c6f0e23a107de0f04bc6c7fd1 Mon Sep 17 00:00:00 2001 From: Sam Hansen Date: Sun, 22 Jan 2012 00:48:25 -0800 Subject: staging: xgifb: pr_fmt kbuild macro Added the kbuild macro pr_fmt() to XGI_main_26.c Signed-off-by: Sam Hansen Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c index ff7a144..bbbbfd1 100644 --- a/drivers/staging/xgifb/XGI_main_26.c +++ b/drivers/staging/xgifb/XGI_main_26.c @@ -4,6 +4,8 @@ * Base on TW's sis fbdev code. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + /* #include */ #include #include -- cgit v0.10.2 From cae9a7bef2c497d40328f7f3fe6384efcf5c13b3 Mon Sep 17 00:00:00 2001 From: Sam Hansen Date: Sun, 22 Jan 2012 16:48:51 -0800 Subject: staging: xgifb: checkpatch cleanup braces Cleaned up XGI_main_26.c and removed some unneeded braces to keep with code conventions. Signed-off-by: Sam Hansen Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c index bbbbfd1..8fe6edab 100644 --- a/drivers/staging/xgifb/XGI_main_26.c +++ b/drivers/staging/xgifb/XGI_main_26.c @@ -2029,13 +2029,12 @@ static int __devinit xgifb_probe(struct pci_dev *pdev, xgifb_info->hasVB = HASVB_NONE; } else if (xgifb_info->chip == XG21) { CR38 = xgifb_reg_get(XGICR, 0x38); - if ((CR38&0xE0) == 0xC0) { + if ((CR38&0xE0) == 0xC0) xgifb_info->display2 = XGIFB_DISP_LCD; - } else if ((CR38&0xE0) == 0x60) { + else if ((CR38&0xE0) == 0x60) xgifb_info->hasVB = HASVB_CHRONTEL; - } else { + else xgifb_info->hasVB = HASVB_NONE; - } } else { XGIfb_get_VB_type(xgifb_info); } @@ -2139,9 +2138,6 @@ static int __devinit xgifb_probe(struct pci_dev *pdev, if (tmp & 0x20) { tmp = xgifb_reg_get( XGIPART1, 0x13); - if (tmp & 0x04) { - /* XGI_Pr.XGI_UseLCDA = 1; */ - } } } } -- cgit v0.10.2 From b4fdf7be0a0e776e4e500e767600e654d8f4f6c2 Mon Sep 17 00:00:00 2001 From: Sam Hansen Date: Sun, 22 Jan 2012 16:48:52 -0800 Subject: staging: xgifb: checkpatch cleanup __func__ Replaced an instance of __FUNCTION__ with __func__ in XGI_main_26.c. Signed-off-by: Sam Hansen Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c index 8fe6edab..a67f65d 100644 --- a/drivers/staging/xgifb/XGI_main_26.c +++ b/drivers/staging/xgifb/XGI_main_26.c @@ -57,7 +57,7 @@ static unsigned int refresh_rate; #undef XGIFBDEBUG #ifdef XGIFBDEBUG -#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) +#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__ , ## args) #else #define DPRINTK(fmt, args...) #endif -- cgit v0.10.2 From 4a6b1518d702d4bf4bb9262993c47263a8573518 Mon Sep 17 00:00:00 2001 From: Sam Hansen Date: Sun, 22 Jan 2012 16:48:53 -0800 Subject: staging: xgifb: checkpatch cleanup printk() -> pr_lvl() Rewrote code to use pr_lvl() instead of printk(). There are still a few instances of printk(), mainly in the debug code which looks like it's going to be dropped/rewrote (most of it is blocked out). Signed-off-by: Sam Hansen Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c index a67f65d..fb9b5b3 100644 --- a/drivers/staging/xgifb/XGI_main_26.c +++ b/drivers/staging/xgifb/XGI_main_26.c @@ -57,7 +57,7 @@ static unsigned int refresh_rate; #undef XGIFBDEBUG #ifdef XGIFBDEBUG -#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__ , ## args) +#define DPRINTK(fmt, args...) pr_debug("%s: " fmt, __func__ , ## args) #else #define DPRINTK(fmt, args...) #endif @@ -144,7 +144,7 @@ static inline void dumpVGAReg(void) #if 1 #define DEBUGPRN(x) #else -#define DEBUGPRN(x) printk(KERN_INFO x "\n"); +#define DEBUGPRN(x) pr_info(x "\n"); #endif /* --------------- Hardware Access Routines -------------------------- */ @@ -426,7 +426,7 @@ static void XGIfb_search_mode(struct xgifb_video_info *xgifb_info, i++; } if (!j) - printk(KERN_INFO "XGIfb: Invalid mode '%s'\n", name); + pr_info("Invalid mode '%s'\n", name); } static void XGIfb_search_vesamode(struct xgifb_video_info *xgifb_info, @@ -451,7 +451,7 @@ static void XGIfb_search_vesamode(struct xgifb_video_info *xgifb_info, invalid: if (!j) - printk(KERN_INFO "XGIfb: Invalid VESA mode 0x%x'\n", vesamode); + pr_info("Invalid VESA mode 0x%x'\n", vesamode); } static int XGIfb_validate_mode(struct xgifb_video_info *xgifb_info, int myindex) @@ -688,7 +688,7 @@ static void XGIfb_search_crt2type(const char *name) i++; } if (XGIfb_crt2type < 0) - printk(KERN_INFO "XGIfb: Invalid CRT2 type: %s\n", name); + pr_info("Invalid CRT2 type: %s\n", name); } static u8 XGIfb_search_refresh_rate(struct xgifb_video_info *xgifb_info, @@ -738,7 +738,7 @@ static u8 XGIfb_search_refresh_rate(struct xgifb_video_info *xgifb_info, if (xgifb_info->rate_idx > 0) { return xgifb_info->rate_idx; } else { - printk(KERN_INFO "XGIfb: Unsupported rate %d for %dx%d\n", + pr_info("Unsupported rate %d for %dx%d\n", rate, xres, yres); return 0; } @@ -1114,7 +1114,7 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive, if (!htotal || !vtotal) { DPRINTK("XGIfb: Invalid 'var' information\n"); return -EINVAL; - } printk(KERN_DEBUG "XGIfb: var->pixclock=%d, htotal=%d, vtotal=%d\n", + } pr_debug("var->pixclock=%d, htotal=%d, vtotal=%d\n", var->pixclock, htotal, vtotal); if (var->pixclock && htotal && vtotal) { @@ -1126,7 +1126,7 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive, xgifb_info->refresh_rate = 60; } - printk(KERN_DEBUG "XGIfb: Change mode to %dx%dx%d-%dHz\n", + pr_debug("Change mode to %dx%dx%d-%dHz\n", var->xres, var->yres, var->bits_per_pixel, @@ -1154,7 +1154,7 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive, xgifb_info->mode_idx = -1; if (xgifb_info->mode_idx < 0) { - printk(KERN_ERR "XGIfb: Mode %dx%dx%d not supported\n", + pr_err("Mode %dx%dx%d not supported\n", var->xres, var->yres, var->bits_per_pixel); xgifb_info->mode_idx = old_mode; return -EINVAL; @@ -1173,7 +1173,7 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive, if (XGISetModeNew(xgifb_info, hw_info, XGIbios_mode[xgifb_info->mode_idx].mode_no) == 0) { - printk(KERN_ERR "XGIfb: Setting mode[0x%x] failed\n", + pr_err("Setting mode[0x%x] failed\n", XGIbios_mode[xgifb_info->mode_idx].mode_no); return -EINVAL; } @@ -1235,7 +1235,7 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive, break; default: xgifb_info->video_cmap_len = 16; - printk(KERN_ERR "XGIfb: Unsupported depth %d", + pr_err("Unsupported depth %d", xgifb_info->video_bpp); break; } @@ -1437,7 +1437,7 @@ static int XGIfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) hrate = (drate * 1000) / htotal; xgifb_info->refresh_rate = (unsigned int) (hrate * 2 / vtotal); - printk(KERN_DEBUG + pr_debug( "%s: pixclock = %d ,htotal=%d, vtotal=%d\n" "%s: drate=%d, hrate=%d, refresh_rate=%d\n", __func__, var->pixclock, htotal, vtotal, @@ -1475,7 +1475,7 @@ static int XGIfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) if (!found_mode) { - printk(KERN_ERR "XGIfb: %dx%dx%d is no valid mode\n", + pr_err("%dx%dx%d is no valid mode\n", var->xres, var->yres, var->bits_per_pixel); search_idx = 0; while (XGIbios_mode[search_idx].mode_no != 0) { @@ -1494,11 +1494,11 @@ static int XGIfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) if (found_mode) { var->xres = XGIbios_mode[search_idx].xres; var->yres = XGIbios_mode[search_idx].yres; - printk(KERN_DEBUG "XGIfb: Adapted to mode %dx%dx%d\n", + pr_debug("Adapted to mode %dx%dx%d\n", var->xres, var->yres, var->bits_per_pixel); } else { - printk(KERN_ERR "XGIfb: Failed to find similar mode to %dx%dx%d\n", + pr_err("Failed to find similar mode to %dx%dx%d\n", var->xres, var->yres, var->bits_per_pixel); return -EINVAL; } @@ -1707,7 +1707,7 @@ static int XGIfb_get_dram_size(struct xgifb_video_info *xgifb_info) /* xgifb_info->video_size = 0x200000; */ /* 1024x768x16 */ /* xgifb_info->video_size = 0x1000000; */ /* benchmark */ - printk("XGIfb: SR14=%x DramSzie %x ChannelNum %x\n", + pr_info("SR14=%x DramSzie %x ChannelNum %x\n", reg, xgifb_info->video_size, ChannelNum); return 0; @@ -1913,7 +1913,7 @@ static int __devinit xgifb_probe(struct pci_dev *pdev, xgifb_info->vga_base = pci_resource_start(pdev, 2) + 0x30; hw_info->pjIOAddress = (unsigned char *)xgifb_info->vga_base; /* XGI_Pr.RelIO = ioremap(pci_resource_start(pdev, 2), 128) + 0x30; */ - printk("XGIfb: Relocate IO address: %lx [%08lx]\n", + pr_info("Relocate IO address: %lx [%08lx]\n", (unsigned long)pci_resource_start(pdev, 2), xgifb_info->dev_info.RelIO); @@ -1933,7 +1933,7 @@ static int __devinit xgifb_probe(struct pci_dev *pdev, reg1 = xgifb_reg_get(XGISR, IND_SIS_PASSWORD); if (reg1 != 0xa1) { /*I/O error */ - printk("\nXGIfb: I/O error!!!"); + pr_err("I/O error!!!"); ret = -EIO; goto error; } @@ -1964,11 +1964,11 @@ static int __devinit xgifb_probe(struct pci_dev *pdev, goto error; } - printk("XGIfb:chipid = %x\n", xgifb_info->chip); + pr_info("chipid = %x\n", xgifb_info->chip); hw_info->jChipType = xgifb_info->chip; if (XGIfb_get_dram_size(xgifb_info)) { - printk(KERN_INFO "XGIfb: Fatal error: Unable to determine RAM size.\n"); + pr_err("Fatal error: Unable to determine RAM size.\n"); ret = -ENODEV; goto error; } @@ -1985,10 +1985,10 @@ static int __devinit xgifb_probe(struct pci_dev *pdev, if (!request_mem_region(xgifb_info->video_base, xgifb_info->video_size, "XGIfb FB")) { - printk("unable request memory size %x", + pr_err("unable request memory size %x\n", xgifb_info->video_size); - printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve frame buffer memory\n"); - printk(KERN_ERR "XGIfb: Is there another framebuffer driver active?\n"); + pr_err("Fatal error: Unable to reserve frame buffer memory\n"); + pr_err("Is there another framebuffer driver active?\n"); ret = -ENODEV; goto error; } @@ -1996,7 +1996,7 @@ static int __devinit xgifb_probe(struct pci_dev *pdev, if (!request_mem_region(xgifb_info->mmio_base, xgifb_info->mmio_size, "XGIfb MMIO")) { - printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve MMIO region\n"); + pr_err("Fatal error: Unable to reserve MMIO region\n"); ret = -ENODEV; goto error_0; } @@ -2006,20 +2006,18 @@ static int __devinit xgifb_probe(struct pci_dev *pdev, xgifb_info->mmio_vbase = ioremap(xgifb_info->mmio_base, xgifb_info->mmio_size); - printk(KERN_INFO "XGIfb: Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n", + pr_info("Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n", xgifb_info->video_base, xgifb_info->video_vbase, xgifb_info->video_size / 1024); - printk(KERN_INFO "XGIfb: MMIO at 0x%lx, mapped to 0x%p, size %ldk\n", + pr_info("MMIO at 0x%lx, mapped to 0x%p, size %ldk\n", xgifb_info->mmio_base, xgifb_info->mmio_vbase, xgifb_info->mmio_size / 1024); - printk("XGIfb: XGIInitNew() ..."); + pci_set_drvdata(pdev, xgifb_info); - if (XGIInitNew(pdev)) - printk("OK\n"); - else - printk("Fail\n"); + if (!XGIInitNew(pdev)) + pr_err("XGIInitNew() failed!\n"); xgifb_info->mtrr = (unsigned int) 0; @@ -2048,10 +2046,10 @@ static int __devinit xgifb_probe(struct pci_dev *pdev, reg = xgifb_reg_get(XGIPART4, 0x01); if (reg >= 0xE0) { hw_info->ujVBChipID = VB_CHIP_302LV; - printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg); + pr_info("XGI302LV bridge detected (revision 0x%02x)\n", reg); } else if (reg >= 0xD0) { hw_info->ujVBChipID = VB_CHIP_301LV; - printk(KERN_INFO "XGIfb: XGI301LV bridge detected (revision 0x%02x)\n", reg); + pr_info("XGI301LV bridge detected (revision 0x%02x)\n", reg); } /* else if (reg >= 0xB0) { hw_info->ujVBChipID = VB_CHIP_301B; @@ -2060,17 +2058,17 @@ static int __devinit xgifb_probe(struct pci_dev *pdev, } */ else { hw_info->ujVBChipID = VB_CHIP_301; - printk("XGIfb: XGI301 bridge detected\n"); + pr_info("XGI301 bridge detected\n"); } break; case HASVB_302: reg = xgifb_reg_get(XGIPART4, 0x01); if (reg >= 0xE0) { hw_info->ujVBChipID = VB_CHIP_302LV; - printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg); + pr_info("XGI302LV bridge detected (revision 0x%02x)\n", reg); } else if (reg >= 0xD0) { hw_info->ujVBChipID = VB_CHIP_301LV; - printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg); + pr_info("XGI302LV bridge detected (revision 0x%02x)\n", reg); } else if (reg >= 0xB0) { reg1 = xgifb_reg_get(XGIPART4, 0x23); @@ -2078,27 +2076,27 @@ static int __devinit xgifb_probe(struct pci_dev *pdev, } else { hw_info->ujVBChipID = VB_CHIP_302; - printk(KERN_INFO "XGIfb: XGI302 bridge detected\n"); + pr_info("XGI302 bridge detected\n"); } break; case HASVB_LVDS: hw_info->ulExternalChip = 0x1; - printk(KERN_INFO "XGIfb: LVDS transmitter detected\n"); + pr_info("LVDS transmitter detected\n"); break; case HASVB_TRUMPION: hw_info->ulExternalChip = 0x2; - printk(KERN_INFO "XGIfb: Trumpion Zurac LVDS scaler detected\n"); + pr_info("Trumpion Zurac LVDS scaler detected\n"); break; case HASVB_CHRONTEL: hw_info->ulExternalChip = 0x4; - printk(KERN_INFO "XGIfb: Chrontel TV encoder detected\n"); + pr_info("Chrontel TV encoder detected\n"); break; case HASVB_LVDS_CHRONTEL: hw_info->ulExternalChip = 0x5; - printk(KERN_INFO "XGIfb: LVDS transmitter and Chrontel TV encoder detected\n"); + pr_info("LVDS transmitter and Chrontel TV encoder detected\n"); break; default: - printk(KERN_INFO "XGIfb: No or unknown bridge type detected\n"); + pr_info("No or unknown bridge type detected\n"); break; } @@ -2210,12 +2208,12 @@ static int __devinit xgifb_probe(struct pci_dev *pdev, break; default: xgifb_info->video_cmap_len = 16; - printk(KERN_INFO "XGIfb: Unsupported depth %d", + pr_info("Unsupported depth %d\n", xgifb_info->video_bpp); break; } - printk(KERN_INFO "XGIfb: Default mode is %dx%dx%d (%dHz)\n", + pr_info("Default mode is %dx%dx%d (%dHz)\n", xgifb_info->video_width, xgifb_info->video_height, xgifb_info->video_bpp, @@ -2392,7 +2390,7 @@ MODULE_PARM_DESC(filter, static void __exit xgifb_remove_module(void) { pci_unregister_driver(&xgifb_driver); - printk(KERN_DEBUG "xgifb: Module unloaded\n"); + pr_debug("Module unloaded\n"); } module_exit(xgifb_remove_module); -- cgit v0.10.2 From 4f1ef76165306577ad0cb708ea90fc19d311e7be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Manuel=20J=C3=A1quez=20Leal?= Date: Tue, 31 Jan 2012 00:12:17 +0100 Subject: staging: tidspbridge: more readable code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Uppercase function names are not pretty. Also the code flow readability is enhanced. Signed-off-by: Víctor Manuel Jáquez Leal Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/tidspbridge/rmgr/drv_interface.c b/drivers/staging/tidspbridge/rmgr/drv_interface.c index 76cfc6e..85f6e8e 100644 --- a/drivers/staging/tidspbridge/rmgr/drv_interface.c +++ b/drivers/staging/tidspbridge/rmgr/drv_interface.c @@ -428,7 +428,7 @@ func_cont: } #ifdef CONFIG_PM -static int BRIDGE_SUSPEND(struct platform_device *pdev, pm_message_t state) +static int bridge_suspend(struct platform_device *pdev, pm_message_t state) { u32 status; u32 command = PWR_EMERGENCYDEEPSLEEP; @@ -441,7 +441,7 @@ static int BRIDGE_SUSPEND(struct platform_device *pdev, pm_message_t state) return 0; } -static int BRIDGE_RESUME(struct platform_device *pdev) +static int bridge_resume(struct platform_device *pdev) { u32 status; @@ -453,9 +453,6 @@ static int BRIDGE_RESUME(struct platform_device *pdev) wake_up(&bridge_suspend_data.suspend_wq); return 0; } -#else -#define BRIDGE_SUSPEND NULL -#define BRIDGE_RESUME NULL #endif static struct platform_driver bridge_driver = { @@ -464,8 +461,10 @@ static struct platform_driver bridge_driver = { }, .probe = omap34_xx_bridge_probe, .remove = __devexit_p(omap34_xx_bridge_remove), - .suspend = BRIDGE_SUSPEND, - .resume = BRIDGE_RESUME, +#ifdef CONFIG_PM + .suspend = bridge_suspend, + .resume = bridge_resume, +#endif }; static int __init bridge_init(void) -- cgit v0.10.2 From 518761dba1270ebb6f735d152f1fd808382705e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Manuel=20J=C3=A1quez=20Leal?= Date: Tue, 31 Jan 2012 00:12:18 +0100 Subject: staging: tidspbridge: remove unused header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No functional changes. The header file drv_interface.h was only used locally, hence there's no need to have it. Also the only prototyped functions were the file_operations callbacks, then this commit moves them up to avoid prototyping too. Signed-off-by: Víctor Manuel Jáquez Leal Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/tidspbridge/rmgr/drv_interface.c b/drivers/staging/tidspbridge/rmgr/drv_interface.c index 85f6e8e..5ea753c 100644 --- a/drivers/staging/tidspbridge/rmgr/drv_interface.c +++ b/drivers/staging/tidspbridge/rmgr/drv_interface.c @@ -48,9 +48,6 @@ /* ----------------------------------- Resource Manager */ #include -/* ----------------------------------- This */ -#include - #include #include #include @@ -133,6 +130,161 @@ MODULE_VERSION(DSPBRIDGE_VERSION); static char *driver_name = DRIVER_NAME; +/* + * This function is called when an application opens handle to the + * bridge driver. + */ +static int bridge_open(struct inode *ip, struct file *filp) +{ + int status = 0; + struct process_context *pr_ctxt = NULL; + + /* + * Allocate a new process context and insert it into global + * process context list. + */ + +#ifdef CONFIG_TIDSPBRIDGE_RECOVERY + if (recover) { + if (filp->f_flags & O_NONBLOCK || + wait_for_completion_interruptible(&bridge_open_comp)) + return -EBUSY; + } +#endif + pr_ctxt = kzalloc(sizeof(struct process_context), GFP_KERNEL); + if (pr_ctxt) { + pr_ctxt->res_state = PROC_RES_ALLOCATED; + spin_lock_init(&pr_ctxt->dmm_map_lock); + INIT_LIST_HEAD(&pr_ctxt->dmm_map_list); + spin_lock_init(&pr_ctxt->dmm_rsv_lock); + INIT_LIST_HEAD(&pr_ctxt->dmm_rsv_list); + + pr_ctxt->node_id = kzalloc(sizeof(struct idr), GFP_KERNEL); + if (pr_ctxt->node_id) { + idr_init(pr_ctxt->node_id); + } else { + status = -ENOMEM; + goto err; + } + + pr_ctxt->stream_id = kzalloc(sizeof(struct idr), GFP_KERNEL); + if (pr_ctxt->stream_id) + idr_init(pr_ctxt->stream_id); + else + status = -ENOMEM; + } else { + status = -ENOMEM; + } +err: + filp->private_data = pr_ctxt; +#ifdef CONFIG_TIDSPBRIDGE_RECOVERY + if (!status) + atomic_inc(&bridge_cref); +#endif + return status; +} + +/* + * This function is called when an application closes handle to the bridge + * driver. + */ +static int bridge_release(struct inode *ip, struct file *filp) +{ + int status = 0; + struct process_context *pr_ctxt; + + if (!filp->private_data) { + status = -EIO; + goto err; + } + + pr_ctxt = filp->private_data; + flush_signals(current); + drv_remove_all_resources(pr_ctxt); + proc_detach(pr_ctxt); + kfree(pr_ctxt); + + filp->private_data = NULL; + +err: +#ifdef CONFIG_TIDSPBRIDGE_RECOVERY + if (!atomic_dec_return(&bridge_cref)) + complete(&bridge_comp); +#endif + return status; +} + +/* This function provides IO interface to the bridge driver. */ +static long bridge_ioctl(struct file *filp, unsigned int code, + unsigned long args) +{ + int status; + u32 retval = 0; + union trapped_args buf_in; + + DBC_REQUIRE(filp != NULL); +#ifdef CONFIG_TIDSPBRIDGE_RECOVERY + if (recover) { + status = -EIO; + goto err; + } +#endif +#ifdef CONFIG_PM + status = omap34_xxbridge_suspend_lockout(&bridge_suspend_data, filp); + if (status != 0) + return status; +#endif + + if (!filp->private_data) { + status = -EIO; + goto err; + } + + status = copy_from_user(&buf_in, (union trapped_args *)args, + sizeof(union trapped_args)); + + if (!status) { + status = api_call_dev_ioctl(code, &buf_in, &retval, + filp->private_data); + + if (!status) { + status = retval; + } else { + dev_dbg(bridge, "%s: IOCTL Failed, code: 0x%x " + "status 0x%x\n", __func__, code, status); + status = -1; + } + + } + +err: + return status; +} + +/* This function maps kernel space memory to user space memory. */ +static int bridge_mmap(struct file *filp, struct vm_area_struct *vma) +{ + u32 offset = vma->vm_pgoff << PAGE_SHIFT; + u32 status; + + DBC_ASSERT(vma->vm_start < vma->vm_end); + + vma->vm_flags |= VM_RESERVED | VM_IO; + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + + dev_dbg(bridge, "%s: vm filp %p offset %x start %lx end %lx page_prot " + "%lx flags %lx\n", __func__, filp, offset, + vma->vm_start, vma->vm_end, vma->vm_page_prot, vma->vm_flags); + + status = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, + vma->vm_end - vma->vm_start, + vma->vm_page_prot); + if (status != 0) + status = -EAGAIN; + + return status; +} + static const struct file_operations bridge_fops = { .open = bridge_open, .release = bridge_release, @@ -477,161 +629,6 @@ static void __exit bridge_exit(void) platform_driver_unregister(&bridge_driver); } -/* - * This function is called when an application opens handle to the - * bridge driver. - */ -static int bridge_open(struct inode *ip, struct file *filp) -{ - int status = 0; - struct process_context *pr_ctxt = NULL; - - /* - * Allocate a new process context and insert it into global - * process context list. - */ - -#ifdef CONFIG_TIDSPBRIDGE_RECOVERY - if (recover) { - if (filp->f_flags & O_NONBLOCK || - wait_for_completion_interruptible(&bridge_open_comp)) - return -EBUSY; - } -#endif - pr_ctxt = kzalloc(sizeof(struct process_context), GFP_KERNEL); - if (pr_ctxt) { - pr_ctxt->res_state = PROC_RES_ALLOCATED; - spin_lock_init(&pr_ctxt->dmm_map_lock); - INIT_LIST_HEAD(&pr_ctxt->dmm_map_list); - spin_lock_init(&pr_ctxt->dmm_rsv_lock); - INIT_LIST_HEAD(&pr_ctxt->dmm_rsv_list); - - pr_ctxt->node_id = kzalloc(sizeof(struct idr), GFP_KERNEL); - if (pr_ctxt->node_id) { - idr_init(pr_ctxt->node_id); - } else { - status = -ENOMEM; - goto err; - } - - pr_ctxt->stream_id = kzalloc(sizeof(struct idr), GFP_KERNEL); - if (pr_ctxt->stream_id) - idr_init(pr_ctxt->stream_id); - else - status = -ENOMEM; - } else { - status = -ENOMEM; - } -err: - filp->private_data = pr_ctxt; -#ifdef CONFIG_TIDSPBRIDGE_RECOVERY - if (!status) - atomic_inc(&bridge_cref); -#endif - return status; -} - -/* - * This function is called when an application closes handle to the bridge - * driver. - */ -static int bridge_release(struct inode *ip, struct file *filp) -{ - int status = 0; - struct process_context *pr_ctxt; - - if (!filp->private_data) { - status = -EIO; - goto err; - } - - pr_ctxt = filp->private_data; - flush_signals(current); - drv_remove_all_resources(pr_ctxt); - proc_detach(pr_ctxt); - kfree(pr_ctxt); - - filp->private_data = NULL; - -err: -#ifdef CONFIG_TIDSPBRIDGE_RECOVERY - if (!atomic_dec_return(&bridge_cref)) - complete(&bridge_comp); -#endif - return status; -} - -/* This function provides IO interface to the bridge driver. */ -static long bridge_ioctl(struct file *filp, unsigned int code, - unsigned long args) -{ - int status; - u32 retval = 0; - union trapped_args buf_in; - - DBC_REQUIRE(filp != NULL); -#ifdef CONFIG_TIDSPBRIDGE_RECOVERY - if (recover) { - status = -EIO; - goto err; - } -#endif -#ifdef CONFIG_PM - status = omap34_xxbridge_suspend_lockout(&bridge_suspend_data, filp); - if (status != 0) - return status; -#endif - - if (!filp->private_data) { - status = -EIO; - goto err; - } - - status = copy_from_user(&buf_in, (union trapped_args *)args, - sizeof(union trapped_args)); - - if (!status) { - status = api_call_dev_ioctl(code, &buf_in, &retval, - filp->private_data); - - if (!status) { - status = retval; - } else { - dev_dbg(bridge, "%s: IOCTL Failed, code: 0x%x " - "status 0x%x\n", __func__, code, status); - status = -1; - } - - } - -err: - return status; -} - -/* This function maps kernel space memory to user space memory. */ -static int bridge_mmap(struct file *filp, struct vm_area_struct *vma) -{ - u32 offset = vma->vm_pgoff << PAGE_SHIFT; - u32 status; - - DBC_ASSERT(vma->vm_start < vma->vm_end); - - vma->vm_flags |= VM_RESERVED | VM_IO; - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - - dev_dbg(bridge, "%s: vm filp %p offset %x start %lx end %lx page_prot " - "%lx flags %lx\n", __func__, filp, offset, - vma->vm_start, vma->vm_end, vma->vm_page_prot, vma->vm_flags); - - status = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, - vma->vm_end - vma->vm_start, - vma->vm_page_prot); - if (status != 0) - status = -EAGAIN; - - return status; -} - /* To remove all process resources before removing the process from the * process context list */ int drv_remove_all_resources(void *process_ctxt) diff --git a/drivers/staging/tidspbridge/rmgr/drv_interface.h b/drivers/staging/tidspbridge/rmgr/drv_interface.h deleted file mode 100644 index ab07060..0000000 --- a/drivers/staging/tidspbridge/rmgr/drv_interface.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * drv_interface.h - * - * DSP-BIOS Bridge driver support functions for TI OMAP processors. - * - * Copyright (C) 2005-2006 Texas Instruments, Inc. - * - * This package is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -#ifndef _DRV_INTERFACE_H_ -#define _DRV_INTERFACE_H_ - -/* Prototypes for all functions in this bridge */ -static int __init bridge_init(void); /* Initialize bridge */ -static void __exit bridge_exit(void); /* Opposite of initialize */ -static int bridge_open(struct inode *ip, struct file *filp); /* Open */ -static int bridge_release(struct inode *ip, struct file *filp); /* Release */ -static long bridge_ioctl(struct file *filp, unsigned int code, - unsigned long args); -static int bridge_mmap(struct file *filp, struct vm_area_struct *vma); -#endif /* ifndef _DRV_INTERFACE_H_ */ -- cgit v0.10.2 From 7724e8bfda8a5e7fd0a1f9819fd9b750c43e0495 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Manuel=20J=C3=A1quez=20Leal?= Date: Tue, 31 Jan 2012 00:12:19 +0100 Subject: staging: tidspbridge: Lindent to drv_interface.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No functional changes. According to Lindent, the file drv_internface.c had some lines with bad indentation. This commit is the output of Lindent. Signed-off-by: Víctor Manuel Jáquez Leal Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/tidspbridge/rmgr/drv_interface.c b/drivers/staging/tidspbridge/rmgr/drv_interface.c index 5ea753c..4316f4e 100644 --- a/drivers/staging/tidspbridge/rmgr/drv_interface.c +++ b/drivers/staging/tidspbridge/rmgr/drv_interface.c @@ -147,7 +147,7 @@ static int bridge_open(struct inode *ip, struct file *filp) #ifdef CONFIG_TIDSPBRIDGE_RECOVERY if (recover) { if (filp->f_flags & O_NONBLOCK || - wait_for_completion_interruptible(&bridge_open_comp)) + wait_for_completion_interruptible(&bridge_open_comp)) return -EBUSY; } #endif @@ -245,7 +245,7 @@ static long bridge_ioctl(struct file *filp, unsigned int code, if (!status) { status = api_call_dev_ioctl(code, &buf_in, &retval, - filp->private_data); + filp->private_data); if (!status) { status = retval; @@ -363,10 +363,10 @@ void bridge_recover_schedule(void) #endif #ifdef CONFIG_TIDSPBRIDGE_DVFS static int dspbridge_scale_notification(struct notifier_block *op, - unsigned long val, void *ptr) + unsigned long val, void *ptr) { struct omap_dsp_platform_data *pdata = - omap_dspbridge_dev->dev.platform_data; + omap_dspbridge_dev->dev.platform_data; if (CPUFREQ_POSTCHANGE == val && pdata->dsp_get_opp) pwr_pm_post_scale(PRCM_VDD1, pdata->dsp_get_opp()); @@ -471,7 +471,7 @@ err2: err1: #ifdef CONFIG_TIDSPBRIDGE_DVFS cpufreq_unregister_notifier(&iva_clk_notifier, - CPUFREQ_TRANSITION_NOTIFIER); + CPUFREQ_TRANSITION_NOTIFIER); #endif dsp_clk_exit(); @@ -550,7 +550,7 @@ static int __devexit omap34_xx_bridge_remove(struct platform_device *pdev) #ifdef CONFIG_TIDSPBRIDGE_DVFS if (cpufreq_unregister_notifier(&iva_clk_notifier, - CPUFREQ_TRANSITION_NOTIFIER)) + CPUFREQ_TRANSITION_NOTIFIER)) pr_err("%s: cpufreq_unregister_notifier failed for iva2_ck\n", __func__); #endif /* #ifdef CONFIG_TIDSPBRIDGE_DVFS */ -- cgit v0.10.2 From 9fdf6550613d1b7ac251a1e254829a4b9636c380 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Manuel=20J=C3=A1quez=20Leal?= Date: Thu, 2 Feb 2012 23:51:08 +0100 Subject: staging: tidspbridge: silence the compiler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When compiling this report is raised by the compiler: CC [M] drivers/staging/tidspbridge/rmgr/drv_interface.o drivers/staging/tidspbridge/rmgr/drv_interface.c: In function 'bridge_mmap': drivers/staging/tidspbridge/rmgr/drv_interface.c:275:2: warning: format '%lx' expects type 'long unsigned int', but argument 9 has type 'pgprot_t' This patch fixes that warning message. Signed-off-by: Víctor Manuel Jáquez Leal Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/tidspbridge/rmgr/drv_interface.c b/drivers/staging/tidspbridge/rmgr/drv_interface.c index 4316f4e..7a6401a 100644 --- a/drivers/staging/tidspbridge/rmgr/drv_interface.c +++ b/drivers/staging/tidspbridge/rmgr/drv_interface.c @@ -273,8 +273,9 @@ static int bridge_mmap(struct file *filp, struct vm_area_struct *vma) vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); dev_dbg(bridge, "%s: vm filp %p offset %x start %lx end %lx page_prot " - "%lx flags %lx\n", __func__, filp, offset, - vma->vm_start, vma->vm_end, vma->vm_page_prot, vma->vm_flags); + "%ulx flags %lx\n", __func__, filp, offset, + vma->vm_start, vma->vm_end, vma->vm_page_prot, + vma->vm_flags); status = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, vma->vm_end - vma->vm_start, -- cgit v0.10.2 From 0b86809a909b61c908281e5b85bfe5abcbf69d1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Manuel=20J=C3=A1quez=20Leal?= Date: Tue, 31 Jan 2012 00:12:21 +0100 Subject: staging: tidspbridge: remove header inclusions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drv_interface.c include several header files that are not really used. Signed-off-by: Víctor Manuel Jáquez Leal Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/tidspbridge/rmgr/drv_interface.c b/drivers/staging/tidspbridge/rmgr/drv_interface.c index 7a6401a..4531920 100644 --- a/drivers/staging/tidspbridge/rmgr/drv_interface.c +++ b/drivers/staging/tidspbridge/rmgr/drv_interface.c @@ -16,11 +16,8 @@ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ -/* ----------------------------------- Host OS */ - #include -#include #include #include #include @@ -38,10 +35,8 @@ /* ----------------------------------- OS Adaptation Layer */ #include -#include /* ----------------------------------- Platform Manager */ -#include #include #include @@ -49,10 +44,8 @@ #include #include -#include #include #include -#include #ifdef CONFIG_TIDSPBRIDGE_DVFS #include -- cgit v0.10.2 From b8bfa4c57c003e85aefbc5aef14f1704ef37b403 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Manuel=20J=C3=A1quez=20Leal?= Date: Tue, 31 Jan 2012 00:12:22 +0100 Subject: staging: tidspbridge: remove trivial assert MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The function dsp_deinit() always return true, so assert its output is pointless. As consequence the variable were the returned value is stored, is no longer needed. Signed-off-by: Víctor Manuel Jáquez Leal Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/tidspbridge/rmgr/drv_interface.c b/drivers/staging/tidspbridge/rmgr/drv_interface.c index 4531920..97c40ff 100644 --- a/drivers/staging/tidspbridge/rmgr/drv_interface.c +++ b/drivers/staging/tidspbridge/rmgr/drv_interface.c @@ -531,7 +531,6 @@ err1: static int __devexit omap34_xx_bridge_remove(struct platform_device *pdev) { dev_t devno; - bool ret; int status = 0; struct drv_data *drv_datap = dev_get_drvdata(bridge); @@ -551,9 +550,8 @@ static int __devexit omap34_xx_bridge_remove(struct platform_device *pdev) if (driver_context) { /* Put the DSP in reset state */ - ret = dsp_deinit(driver_context); + dsp_deinit(driver_context); driver_context = 0; - DBC_ASSERT(ret == true); } func_cont: -- cgit v0.10.2 From 4f8aae5375e429b003a72a37d8ece6e1b99e486e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Manuel=20J=C3=A1quez=20Leal?= Date: Tue, 31 Jan 2012 00:12:23 +0100 Subject: staging: tidspbridge: clean up bridge_mmap() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The variable offset is not used but in the debug log, so I don't see reason to calculate it here. Signed-off-by: Víctor Manuel Jáquez Leal Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/tidspbridge/rmgr/drv_interface.c b/drivers/staging/tidspbridge/rmgr/drv_interface.c index 97c40ff..5f810b6 100644 --- a/drivers/staging/tidspbridge/rmgr/drv_interface.c +++ b/drivers/staging/tidspbridge/rmgr/drv_interface.c @@ -257,7 +257,6 @@ err: /* This function maps kernel space memory to user space memory. */ static int bridge_mmap(struct file *filp, struct vm_area_struct *vma) { - u32 offset = vma->vm_pgoff << PAGE_SHIFT; u32 status; DBC_ASSERT(vma->vm_start < vma->vm_end); @@ -265,8 +264,8 @@ static int bridge_mmap(struct file *filp, struct vm_area_struct *vma) vma->vm_flags |= VM_RESERVED | VM_IO; vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - dev_dbg(bridge, "%s: vm filp %p offset %x start %lx end %lx page_prot " - "%ulx flags %lx\n", __func__, filp, offset, + dev_dbg(bridge, "%s: vm filp %p start %lx end %lx page_prot %ulx " + "flags %lx\n", __func__, filp, vma->vm_start, vma->vm_end, vma->vm_page_prot, vma->vm_flags); -- cgit v0.10.2 From 3bdb54fc548316196f752010a44dd221a220f53b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Manuel=20J=C3=A1quez=20Leal?= Date: Tue, 31 Jan 2012 00:12:24 +0100 Subject: staging: tidspbridge: use the driver name string Instead of assign it to a global variable which is not used anymore. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/tidspbridge/rmgr/drv_interface.c b/drivers/staging/tidspbridge/rmgr/drv_interface.c index 5f810b6..93fc862 100644 --- a/drivers/staging/tidspbridge/rmgr/drv_interface.c +++ b/drivers/staging/tidspbridge/rmgr/drv_interface.c @@ -52,7 +52,6 @@ #endif /* ----------------------------------- Globals */ -#define DRIVER_NAME "DspBridge" #define DSPBRIDGE_VERSION "0.3" s32 dsp_debug; @@ -121,8 +120,6 @@ MODULE_AUTHOR("Texas Instruments"); MODULE_LICENSE("GPL"); MODULE_VERSION(DSPBRIDGE_VERSION); -static char *driver_name = DRIVER_NAME; - /* * This function is called when an application opens handle to the * bridge driver. @@ -490,7 +487,7 @@ static int __devinit omap34_xx_bridge_probe(struct platform_device *pdev) goto err1; /* use 2.6 device model */ - err = alloc_chrdev_region(&dev, 0, 1, driver_name); + err = alloc_chrdev_region(&dev, 0, 1, "DspBridge"); if (err) { pr_err("%s: Can't get major %d\n", __func__, driver_major); goto err1; -- cgit v0.10.2 From 8900f00b1546a32be6b9dd7cf1633560e4381a76 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 24 Jan 2012 13:25:05 -0800 Subject: staging: tidspbridge: Rename module from bridgedriver to tidspbridge tidspbridge when built as a module is named bridgedriver. bridgedriver is not a particularly good module name. tidspbridge is what the source is named. That seems a more appropriate module name too as it describes the hardware function better. Signed-off-by: Joe Perches Acked-by: Omar Ramirez Luna Acked-by: Felipe Contreras Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/tidspbridge/Makefile b/drivers/staging/tidspbridge/Makefile index fd6a276..8c8c92a 100644 --- a/drivers/staging/tidspbridge/Makefile +++ b/drivers/staging/tidspbridge/Makefile @@ -1,4 +1,4 @@ -obj-$(CONFIG_TIDSPBRIDGE) += bridgedriver.o +obj-$(CONFIG_TIDSPBRIDGE) += tidspbridge.o libgen = gen/gh.o gen/uuidutil.o libcore = core/chnl_sm.o core/msg_sm.o core/io_sm.o core/tiomap3430.o \ @@ -13,7 +13,7 @@ libdload = dynload/cload.o dynload/getsection.o dynload/reloc.o \ dynload/tramp.o libhw = hw/hw_mmu.o -bridgedriver-y := $(libgen) $(libservices) $(libcore) $(libpmgr) $(librmgr) \ +tidspbridge-y := $(libgen) $(libservices) $(libcore) $(libpmgr) $(librmgr) \ $(libdload) $(libhw) #Machine dependent -- cgit v0.10.2 From 276cc746d58b73aa4e046745441b8cf56858f9ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Manuel=20J=C3=A1quez=20Leal?= Date: Tue, 7 Feb 2012 00:39:34 +0100 Subject: staging: tidspbridge: remove DBC_ENSURE and DBC_REQUIRED MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The kernel does not use a "Design by Contract" approach, and it is only activated in the module if CONFIG_TIDSPBRDIGE_DEBUG is enabled, so they are executed rarely. It is better to remove them: less code to maintain. Signed-off-by: Víctor Manuel Jáquez Leal Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/tidspbridge/core/chnl_sm.c b/drivers/staging/tidspbridge/core/chnl_sm.c index 6d66e7d..91daf25 100644 --- a/drivers/staging/tidspbridge/core/chnl_sm.c +++ b/drivers/staging/tidspbridge/core/chnl_sm.c @@ -358,13 +358,6 @@ int bridge_chnl_create(struct chnl_mgr **channel_mgr, struct chnl_mgr *chnl_mgr_obj = NULL; u8 max_channels; - /* Check DBC requirements: */ - DBC_REQUIRE(channel_mgr != NULL); - DBC_REQUIRE(mgr_attrts != NULL); - DBC_REQUIRE(mgr_attrts->max_channels > 0); - DBC_REQUIRE(mgr_attrts->max_channels <= CHNL_MAXCHANNELS); - DBC_REQUIRE(mgr_attrts->word_size != 0); - /* Allocate channel manager object */ chnl_mgr_obj = kzalloc(sizeof(struct chnl_mgr), GFP_KERNEL); if (chnl_mgr_obj) { @@ -491,7 +484,6 @@ int bridge_chnl_flush_io(struct chnl_object *chnl_obj, u32 timeout) pchnl->state &= ~CHNL_STATECANCEL; } } - DBC_ENSURE(status || list_empty(&pchnl->io_requests)); return status; } @@ -705,8 +697,6 @@ int bridge_chnl_idle(struct chnl_object *chnl_obj, u32 timeout, struct chnl_mgr *chnl_mgr_obj; int status = 0; - DBC_REQUIRE(chnl_obj); - chnl_mode = chnl_obj->chnl_mode; chnl_mgr_obj = chnl_obj->chnl_mgr_obj; @@ -736,10 +726,7 @@ int bridge_chnl_open(struct chnl_object **chnl, struct chnl_mgr *chnl_mgr_obj = hchnl_mgr; struct chnl_object *pchnl = NULL; struct sync_object *sync_event = NULL; - /* Ensure DBC requirements: */ - DBC_REQUIRE(chnl != NULL); - DBC_REQUIRE(pattrs != NULL); - DBC_REQUIRE(hchnl_mgr != NULL); + *chnl = NULL; /* Validate Args: */ @@ -906,8 +893,6 @@ static void free_chirp_list(struct list_head *chirp_list) { struct chnl_irp *chirp, *tmp; - DBC_REQUIRE(chirp_list != NULL); - list_for_each_entry_safe(chirp, tmp, chirp_list, link) { list_del(&chirp->link); kfree(chirp); @@ -924,8 +909,6 @@ static int search_free_channel(struct chnl_mgr *chnl_mgr_obj, int status = -ENOSR; u32 i; - DBC_REQUIRE(chnl_mgr_obj); - for (i = 0; i < chnl_mgr_obj->max_channels; i++) { if (chnl_mgr_obj->channels[i] == NULL) { status = 0; diff --git a/drivers/staging/tidspbridge/core/tiomap3430.c b/drivers/staging/tidspbridge/core/tiomap3430.c index e1c4492..212cbc9 100644 --- a/drivers/staging/tidspbridge/core/tiomap3430.c +++ b/drivers/staging/tidspbridge/core/tiomap3430.c @@ -256,9 +256,6 @@ static void bad_page_dump(u32 pa, struct page *pg) void bridge_drv_entry(struct bridge_drv_interface **drv_intf, const char *driver_file_name) { - - DBC_REQUIRE(driver_file_name != NULL); - if (strcmp(driver_file_name, "UMA") == 0) *drv_intf = &drv_interface_fxns; else diff --git a/drivers/staging/tidspbridge/gen/uuidutil.c b/drivers/staging/tidspbridge/gen/uuidutil.c index ff6ebad..5797fb5 100644 --- a/drivers/staging/tidspbridge/gen/uuidutil.c +++ b/drivers/staging/tidspbridge/gen/uuidutil.c @@ -41,8 +41,6 @@ void uuid_uuid_to_string(struct dsp_uuid *uuid_obj, char *sz_uuid, { s32 i; /* return result from snprintf. */ - DBC_REQUIRE(uuid_obj && sz_uuid); - i = snprintf(sz_uuid, size, "%.8X_%.4X_%.4X_%.2X%.2X_%.2X%.2X%.2X%.2X%.2X%.2X", uuid_obj->data1, uuid_obj->data2, uuid_obj->data3, @@ -50,8 +48,6 @@ void uuid_uuid_to_string(struct dsp_uuid *uuid_obj, char *sz_uuid, uuid_obj->data6[0], uuid_obj->data6[1], uuid_obj->data6[2], uuid_obj->data6[3], uuid_obj->data6[4], uuid_obj->data6[5]); - - DBC_ENSURE(i != -1); } static s32 uuid_hex_to_bin(char *buf, s32 len) diff --git a/drivers/staging/tidspbridge/include/dspbridge/dbc.h b/drivers/staging/tidspbridge/include/dspbridge/dbc.h index 463760f..dc88f34 100644 --- a/drivers/staging/tidspbridge/include/dspbridge/dbc.h +++ b/drivers/staging/tidspbridge/include/dspbridge/dbc.h @@ -32,15 +32,8 @@ if (!(exp)) \ pr_err("%s, line %d: Assertion (" #exp ") failed.\n", \ __FILE__, __LINE__) -#define DBC_REQUIRE DBC_ASSERT /* Function Precondition. */ -#define DBC_ENSURE DBC_ASSERT /* Function Postcondition. */ - #else - #define DBC_ASSERT(exp) {} -#define DBC_REQUIRE(exp) {} -#define DBC_ENSURE(exp) {} - #endif /* DEBUG */ #endif /* DBC_ */ diff --git a/drivers/staging/tidspbridge/pmgr/chnl.c b/drivers/staging/tidspbridge/pmgr/chnl.c index 245de82..61ee0f0 100644 --- a/drivers/staging/tidspbridge/pmgr/chnl.c +++ b/drivers/staging/tidspbridge/pmgr/chnl.c @@ -58,10 +58,6 @@ int chnl_create(struct chnl_mgr **channel_mgr, struct chnl_mgr *hchnl_mgr; struct chnl_mgr_ *chnl_mgr_obj = NULL; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(channel_mgr != NULL); - DBC_REQUIRE(mgr_attrts != NULL); - *channel_mgr = NULL; /* Validate args: */ @@ -99,8 +95,6 @@ int chnl_create(struct chnl_mgr **channel_mgr, } } - DBC_ENSURE(status || chnl_mgr_obj); - return status; } @@ -115,8 +109,6 @@ int chnl_destroy(struct chnl_mgr *hchnl_mgr) struct bridge_drv_interface *intf_fxns; int status; - DBC_REQUIRE(refs > 0); - if (chnl_mgr_obj) { intf_fxns = chnl_mgr_obj->intf_fxns; /* Let Bridge channel module destroy the chnl_mgr: */ @@ -135,11 +127,7 @@ int chnl_destroy(struct chnl_mgr *hchnl_mgr) */ void chnl_exit(void) { - DBC_REQUIRE(refs > 0); - refs--; - - DBC_ENSURE(refs >= 0); } /* @@ -151,12 +139,8 @@ bool chnl_init(void) { bool ret = true; - DBC_REQUIRE(refs >= 0); - if (ret) refs++; - DBC_ENSURE((ret && (refs > 0)) || (!ret && (refs >= 0))); - return ret; } diff --git a/drivers/staging/tidspbridge/pmgr/cmm.c b/drivers/staging/tidspbridge/pmgr/cmm.c index e6b2c89..2eeb5370 100644 --- a/drivers/staging/tidspbridge/pmgr/cmm.c +++ b/drivers/staging/tidspbridge/pmgr/cmm.c @@ -244,9 +244,6 @@ int cmm_create(struct cmm_object **ph_cmm_mgr, struct cmm_object *cmm_obj = NULL; int status = 0; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(ph_cmm_mgr != NULL); - *ph_cmm_mgr = NULL; /* create, zero, and tag a cmm mgr object */ cmm_obj = kzalloc(sizeof(struct cmm_object), GFP_KERNEL); @@ -283,7 +280,6 @@ int cmm_destroy(struct cmm_object *hcmm_mgr, bool force) s32 slot_seg; struct cmm_mnode *node, *tmp; - DBC_REQUIRE(refs > 0); if (!hcmm_mgr) { status = -EFAULT; return status; @@ -333,8 +329,6 @@ int cmm_destroy(struct cmm_object *hcmm_mgr, bool force) */ void cmm_exit(void) { - DBC_REQUIRE(refs > 0); - refs--; } @@ -351,9 +345,6 @@ int cmm_free_buf(struct cmm_object *hcmm_mgr, void *buf_pa, u32 ul_seg_id) struct cmm_allocator *allocator; struct cmm_attrs *pattrs; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(buf_pa != NULL); - if (ul_seg_id == 0) { pattrs = &cmm_dfltalctattrs; ul_seg_id = pattrs->seg_id; @@ -392,8 +383,6 @@ int cmm_get_handle(void *hprocessor, struct cmm_object ** ph_cmm_mgr) int status = 0; struct dev_object *hdev_obj; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(ph_cmm_mgr != NULL); if (hprocessor != NULL) status = proc_get_dev_object(hprocessor, &hdev_obj); else @@ -419,8 +408,6 @@ int cmm_get_info(struct cmm_object *hcmm_mgr, struct cmm_allocator *altr; struct cmm_mnode *curr; - DBC_REQUIRE(cmm_info_obj != NULL); - if (!hcmm_mgr) { status = -EFAULT; return status; @@ -472,12 +459,9 @@ bool cmm_init(void) { bool ret = true; - DBC_REQUIRE(refs >= 0); if (ret) refs++; - DBC_ENSURE((ret && (refs > 0)) || (!ret && (refs >= 0))); - return ret; } @@ -499,13 +483,6 @@ int cmm_register_gppsm_seg(struct cmm_object *hcmm_mgr, struct cmm_mnode *new_node; s32 slot_seg; - DBC_REQUIRE(ul_size > 0); - DBC_REQUIRE(sgmt_id != NULL); - DBC_REQUIRE(dw_gpp_base_pa != 0); - DBC_REQUIRE(gpp_base_va != 0); - DBC_REQUIRE((c_factor <= CMM_ADDTODSPPA) && - (c_factor >= CMM_SUBFROMDSPPA)); - dev_dbg(bridge, "%s: dw_gpp_base_pa %x ul_size %x dsp_addr_offset %x " "dw_dsp_base %x ul_dsp_size %x gpp_base_va %x\n", __func__, dw_gpp_base_pa, ul_size, dsp_addr_offset, @@ -589,7 +566,6 @@ int cmm_un_register_gppsm_seg(struct cmm_object *hcmm_mgr, struct cmm_allocator *psma; u32 ul_id = ul_seg_id; - DBC_REQUIRE(ul_seg_id > 0); if (!hcmm_mgr) return -EFAULT; @@ -635,8 +611,6 @@ static void un_register_gppsm_seg(struct cmm_allocator *psma) { struct cmm_mnode *curr, *tmp; - DBC_REQUIRE(psma != NULL); - /* free nodes on free list */ list_for_each_entry_safe(curr, tmp, &psma->free_list, link) { list_del(&curr->link); @@ -664,7 +638,6 @@ static void un_register_gppsm_seg(struct cmm_allocator *psma) static s32 get_slot(struct cmm_object *cmm_mgr_obj) { s32 slot_seg = -1; /* neg on failure */ - DBC_REQUIRE(cmm_mgr_obj != NULL); /* get first available slot in cmm mgr SMSegTab[] */ for (slot_seg = 0; slot_seg < CMM_MAXGPPSEGS; slot_seg++) { if (cmm_mgr_obj->pa_gppsm_seg_tab[slot_seg] == NULL) @@ -687,11 +660,6 @@ static struct cmm_mnode *get_node(struct cmm_object *cmm_mgr_obj, u32 dw_pa, { struct cmm_mnode *pnode; - DBC_REQUIRE(cmm_mgr_obj != NULL); - DBC_REQUIRE(dw_pa != 0); - DBC_REQUIRE(dw_va != 0); - DBC_REQUIRE(ul_size != 0); - /* Check cmm mgr's node freelist */ if (list_empty(&cmm_mgr_obj->node_free_list)) { pnode = kzalloc(sizeof(struct cmm_mnode), GFP_KERNEL); @@ -719,7 +687,6 @@ static struct cmm_mnode *get_node(struct cmm_object *cmm_mgr_obj, u32 dw_pa, */ static void delete_node(struct cmm_object *cmm_mgr_obj, struct cmm_mnode *pnode) { - DBC_REQUIRE(pnode != NULL); list_add_tail(&pnode->link, &cmm_mgr_obj->node_free_list); } @@ -794,9 +761,6 @@ static void add_to_free_list(struct cmm_allocator *allocator, static struct cmm_allocator *get_allocator(struct cmm_object *cmm_mgr_obj, u32 ul_seg_id) { - DBC_REQUIRE(cmm_mgr_obj != NULL); - DBC_REQUIRE((ul_seg_id > 0) && (ul_seg_id <= CMM_MAXGPPSEGS)); - return cmm_mgr_obj->pa_gppsm_seg_tab[ul_seg_id - 1]; } @@ -818,10 +782,6 @@ int cmm_xlator_create(struct cmm_xlatorobject **xlator, struct cmm_xlator *xlator_object = NULL; int status = 0; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(xlator != NULL); - DBC_REQUIRE(hcmm_mgr != NULL); - *xlator = NULL; if (xlator_attrs == NULL) xlator_attrs = &cmm_dfltxlatorattrs; /* set defaults */ @@ -851,13 +811,6 @@ void *cmm_xlator_alloc_buf(struct cmm_xlatorobject *xlator, void *va_buf, void *tmp_va_buff; struct cmm_attrs attrs; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(xlator != NULL); - DBC_REQUIRE(xlator_obj->cmm_mgr != NULL); - DBC_REQUIRE(va_buf != NULL); - DBC_REQUIRE(pa_size > 0); - DBC_REQUIRE(xlator_obj->seg_id > 0); - if (xlator_obj) { attrs.seg_id = xlator_obj->seg_id; __raw_writel(0, va_buf); @@ -887,10 +840,6 @@ int cmm_xlator_free_buf(struct cmm_xlatorobject *xlator, void *buf_va) int status = -EPERM; void *buf_pa = NULL; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(buf_va != NULL); - DBC_REQUIRE(xlator_obj->seg_id > 0); - if (xlator_obj) { /* convert Va to Pa so we can free it. */ buf_pa = cmm_xlator_translate(xlator, buf_va, CMM_VA2PA); @@ -918,10 +867,6 @@ int cmm_xlator_info(struct cmm_xlatorobject *xlator, u8 ** paddr, struct cmm_xlator *xlator_obj = (struct cmm_xlator *)xlator; int status = 0; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(paddr != NULL); - DBC_REQUIRE((segm_id > 0) && (segm_id <= CMM_MAXGPPSEGS)); - if (xlator_obj) { if (set_info) { /* set translators virtual address range */ @@ -948,10 +893,6 @@ void *cmm_xlator_translate(struct cmm_xlatorobject *xlator, void *paddr, struct cmm_allocator *allocator = NULL; u32 dw_offset = 0; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(paddr != NULL); - DBC_REQUIRE((xtype >= CMM_VA2PA) && (xtype <= CMM_DSPPA2PA)); - if (!xlator_obj) goto loop_cont; diff --git a/drivers/staging/tidspbridge/pmgr/cod.c b/drivers/staging/tidspbridge/pmgr/cod.c index 1a29264..be7c777 100644 --- a/drivers/staging/tidspbridge/pmgr/cod.c +++ b/drivers/staging/tidspbridge/pmgr/cod.c @@ -183,10 +183,6 @@ void cod_close(struct cod_libraryobj *lib) { struct cod_manager *hmgr; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(lib != NULL); - DBC_REQUIRE(lib->cod_mgr); - hmgr = lib->cod_mgr; hmgr->fxns.close_fxn(lib->dbll_lib); @@ -208,9 +204,6 @@ int cod_create(struct cod_manager **mgr, char *str_zl_file) struct dbll_attrs zl_attrs; int status = 0; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(mgr != NULL); - /* assume failure */ *mgr = NULL; @@ -263,9 +256,6 @@ int cod_create(struct cod_manager **mgr, char *str_zl_file) */ void cod_delete(struct cod_manager *cod_mgr_obj) { - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(cod_mgr_obj); - if (cod_mgr_obj->base_lib) { if (cod_mgr_obj->loaded) cod_mgr_obj->fxns.unload_fxn(cod_mgr_obj->base_lib, @@ -288,11 +278,7 @@ void cod_delete(struct cod_manager *cod_mgr_obj) */ void cod_exit(void) { - DBC_REQUIRE(refs > 0); - refs--; - - DBC_ENSURE(refs >= 0); } /* @@ -305,10 +291,6 @@ int cod_get_base_lib(struct cod_manager *cod_mgr_obj, { int status = 0; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(cod_mgr_obj); - DBC_REQUIRE(plib != NULL); - *plib = (struct dbll_library_obj *)cod_mgr_obj->base_lib; return status; @@ -322,10 +304,6 @@ int cod_get_base_name(struct cod_manager *cod_mgr_obj, char *sz_name, { int status = 0; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(cod_mgr_obj); - DBC_REQUIRE(sz_name != NULL); - if (usize <= COD_MAXPATHLENGTH) strncpy(sz_name, cod_mgr_obj->sz_zl_file, usize); else @@ -342,10 +320,6 @@ int cod_get_base_name(struct cod_manager *cod_mgr_obj, char *sz_name, */ int cod_get_entry(struct cod_manager *cod_mgr_obj, u32 *entry_pt) { - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(cod_mgr_obj); - DBC_REQUIRE(entry_pt != NULL); - *entry_pt = cod_mgr_obj->entry; return 0; @@ -361,10 +335,6 @@ int cod_get_loader(struct cod_manager *cod_mgr_obj, { int status = 0; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(cod_mgr_obj); - DBC_REQUIRE(loader != NULL); - *loader = (struct dbll_tar_obj *)cod_mgr_obj->target; return status; @@ -382,13 +352,6 @@ int cod_get_section(struct cod_libraryobj *lib, char *str_sect, struct cod_manager *cod_mgr_obj; int status = 0; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(lib != NULL); - DBC_REQUIRE(lib->cod_mgr); - DBC_REQUIRE(str_sect != NULL); - DBC_REQUIRE(addr != NULL); - DBC_REQUIRE(len != NULL); - *addr = 0; *len = 0; if (lib != NULL) { @@ -399,8 +362,6 @@ int cod_get_section(struct cod_libraryobj *lib, char *str_sect, status = -ESPIPE; } - DBC_ENSURE(!status || ((*addr == 0) && (*len == 0))); - return status; } @@ -417,11 +378,6 @@ int cod_get_sym_value(struct cod_manager *cod_mgr_obj, char *str_sym, { struct dbll_sym_val *dbll_sym; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(cod_mgr_obj); - DBC_REQUIRE(str_sym != NULL); - DBC_REQUIRE(pul_value != NULL); - dev_dbg(bridge, "%s: cod_mgr_obj: %p str_sym: %s pul_value: %p\n", __func__, cod_mgr_obj, str_sym, pul_value); if (cod_mgr_obj->base_lib) { @@ -451,12 +407,9 @@ bool cod_init(void) { bool ret = true; - DBC_REQUIRE(refs >= 0); - if (ret) refs++; - DBC_ENSURE((ret && refs > 0) || (!ret && refs >= 0)); return ret; } @@ -482,14 +435,6 @@ int cod_load_base(struct cod_manager *cod_mgr_obj, u32 num_argc, char *args[], int status; u32 i; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(cod_mgr_obj); - DBC_REQUIRE(num_argc > 0); - DBC_REQUIRE(args != NULL); - DBC_REQUIRE(args[0] != NULL); - DBC_REQUIRE(pfn_write != NULL); - DBC_REQUIRE(cod_mgr_obj->base_lib != NULL); - /* * Make sure every argv[] stated in argc has a value, or change argc to * reflect true number in NULL terminated argv array. @@ -538,12 +483,6 @@ int cod_open(struct cod_manager *hmgr, char *sz_coff_path, int status = 0; struct cod_libraryobj *lib = NULL; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(hmgr); - DBC_REQUIRE(sz_coff_path != NULL); - DBC_REQUIRE(flags == COD_NOLOAD || flags == COD_SYMB); - DBC_REQUIRE(lib_obj != NULL); - *lib_obj = NULL; lib = kzalloc(sizeof(struct cod_libraryobj), GFP_KERNEL); @@ -575,10 +514,6 @@ int cod_open_base(struct cod_manager *hmgr, char *sz_coff_path, int status = 0; struct dbll_library_obj *lib; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(hmgr); - DBC_REQUIRE(sz_coff_path != NULL); - /* if we previously opened a base image, close it now */ if (hmgr->base_lib) { if (hmgr->loaded) { @@ -612,12 +547,6 @@ int cod_read_section(struct cod_libraryobj *lib, char *str_sect, { int status = 0; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(lib != NULL); - DBC_REQUIRE(lib->cod_mgr); - DBC_REQUIRE(str_sect != NULL); - DBC_REQUIRE(str_content != NULL); - if (lib != NULL) status = lib->cod_mgr->fxns.read_sect_fxn(lib->dbll_lib, str_sect, diff --git a/drivers/staging/tidspbridge/pmgr/dbll.c b/drivers/staging/tidspbridge/pmgr/dbll.c index 31da62b..db1af79 100644 --- a/drivers/staging/tidspbridge/pmgr/dbll.c +++ b/drivers/staging/tidspbridge/pmgr/dbll.c @@ -202,9 +202,6 @@ void dbll_close(struct dbll_library_obj *zl_lib) { struct dbll_tar_obj *zl_target; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(zl_lib); - DBC_REQUIRE(zl_lib->open_ref > 0); zl_target = zl_lib->target_obj; zl_lib->open_ref--; if (zl_lib->open_ref == 0) { @@ -241,10 +238,6 @@ int dbll_create(struct dbll_tar_obj **target_obj, struct dbll_tar_obj *pzl_target; int status = 0; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(pattrs != NULL); - DBC_REQUIRE(target_obj != NULL); - /* Allocate DBL target object */ pzl_target = kzalloc(sizeof(struct dbll_tar_obj), GFP_KERNEL); if (target_obj != NULL) { @@ -255,8 +248,6 @@ int dbll_create(struct dbll_tar_obj **target_obj, pzl_target->attrs = *pattrs; *target_obj = (struct dbll_tar_obj *)pzl_target; } - DBC_ENSURE((!status && *target_obj) || - (status && *target_obj == NULL)); } return status; @@ -269,9 +260,6 @@ void dbll_delete(struct dbll_tar_obj *target) { struct dbll_tar_obj *zl_target = (struct dbll_tar_obj *)target; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(zl_target); - kfree(zl_target); } @@ -282,14 +270,10 @@ void dbll_delete(struct dbll_tar_obj *target) */ void dbll_exit(void) { - DBC_REQUIRE(refs > 0); - refs--; if (refs == 0) gh_exit(); - - DBC_ENSURE(refs >= 0); } /* @@ -302,12 +286,6 @@ bool dbll_get_addr(struct dbll_library_obj *zl_lib, char *name, struct dbll_symbol *sym; bool status = false; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(zl_lib); - DBC_REQUIRE(name != NULL); - DBC_REQUIRE(sym_val != NULL); - DBC_REQUIRE(zl_lib->sym_tab != NULL); - sym = (struct dbll_symbol *)gh_find(zl_lib->sym_tab, name); if (sym != NULL) { *sym_val = &sym->value; @@ -327,10 +305,6 @@ void dbll_get_attrs(struct dbll_tar_obj *target, struct dbll_attrs *pattrs) { struct dbll_tar_obj *zl_target = (struct dbll_tar_obj *)target; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(zl_target); - DBC_REQUIRE(pattrs != NULL); - if ((pattrs != NULL) && (zl_target != NULL)) *pattrs = zl_target->attrs; @@ -347,12 +321,6 @@ bool dbll_get_c_addr(struct dbll_library_obj *zl_lib, char *name, char cname[MAXEXPR + 1]; bool status = false; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(zl_lib); - DBC_REQUIRE(sym_val != NULL); - DBC_REQUIRE(zl_lib->sym_tab != NULL); - DBC_REQUIRE(name != NULL); - cname[0] = '_'; strncpy(cname + 1, name, sizeof(cname) - 2); @@ -382,12 +350,6 @@ int dbll_get_sect(struct dbll_library_obj *lib, char *name, u32 *paddr, struct dbll_library_obj *zl_lib = (struct dbll_library_obj *)lib; int status = 0; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(name != NULL); - DBC_REQUIRE(paddr != NULL); - DBC_REQUIRE(psize != NULL); - DBC_REQUIRE(zl_lib); - /* If DOFF file is not open, we open it. */ if (zl_lib != NULL) { if (zl_lib->fp == NULL) { @@ -434,8 +396,6 @@ int dbll_get_sect(struct dbll_library_obj *lib, char *name, u32 *paddr, */ bool dbll_init(void) { - DBC_REQUIRE(refs >= 0); - if (refs == 0) gh_init(); @@ -456,10 +416,6 @@ int dbll_load(struct dbll_library_obj *lib, dbll_flags flags, s32 err; int status = 0; bool opened_doff = false; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(zl_lib); - DBC_REQUIRE(entry != NULL); - DBC_REQUIRE(attrs != NULL); /* * Load if not already loaded. @@ -558,8 +514,6 @@ int dbll_load(struct dbll_library_obj *lib, dbll_flags flags, if (opened_doff) dof_close(zl_lib); - DBC_ENSURE(status || zl_lib->load_ref > 0); - dev_dbg(bridge, "%s: lib: %p flags: 0x%x entry: %p, status 0x%x\n", __func__, lib, flags, entry, status); @@ -577,12 +531,6 @@ int dbll_open(struct dbll_tar_obj *target, char *file, dbll_flags flags, s32 err; int status = 0; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(zl_target); - DBC_REQUIRE(zl_target->attrs.fopen != NULL); - DBC_REQUIRE(file != NULL); - DBC_REQUIRE(lib_obj != NULL); - zl_lib = zl_target->head; while (zl_lib != NULL) { if (strcmp(zl_lib->file_name, file) == 0) { @@ -699,8 +647,6 @@ func_cont: dbll_close((struct dbll_library_obj *)zl_lib); } - DBC_ENSURE((!status && (zl_lib->open_ref > 0) && *lib_obj) - || (status && *lib_obj == NULL)); dev_dbg(bridge, "%s: target: %p file: %s lib_obj: %p, status 0x%x\n", __func__, target, file, lib_obj, status); @@ -722,12 +668,6 @@ int dbll_read_sect(struct dbll_library_obj *lib, char *name, const struct ldr_section_info *sect = NULL; int status = 0; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(zl_lib); - DBC_REQUIRE(name != NULL); - DBC_REQUIRE(buf != NULL); - DBC_REQUIRE(size != 0); - /* If DOFF file is not open, we open it. */ if (zl_lib != NULL) { if (zl_lib->fp == NULL) { @@ -788,14 +728,11 @@ void dbll_unload(struct dbll_library_obj *lib, struct dbll_attrs *attrs) struct dbll_library_obj *zl_lib = (struct dbll_library_obj *)lib; s32 err = 0; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(zl_lib); - DBC_REQUIRE(zl_lib->load_ref > 0); dev_dbg(bridge, "%s: lib: %p\n", __func__, lib); zl_lib->load_ref--; /* Unload only if reference count is 0 */ if (zl_lib->load_ref != 0) - goto func_end; + return; zl_lib->target_obj->attrs = *attrs; if (zl_lib->dload_mod_obj) { @@ -814,8 +751,6 @@ void dbll_unload(struct dbll_library_obj *lib, struct dbll_attrs *attrs) /* delete DOFF desc since it holds *lots* of host OS * resources */ dof_close(zl_lib); -func_end: - DBC_ENSURE(zl_lib->load_ref >= 0); } /* @@ -874,8 +809,6 @@ static u16 name_hash(void *key, u16 max_bucket) u16 hash; char *name = (char *)key; - DBC_REQUIRE(name != NULL); - hash = 0; while (*name) { @@ -893,9 +826,6 @@ static u16 name_hash(void *key, u16 max_bucket) */ static bool name_match(void *key, void *sp) { - DBC_REQUIRE(key != NULL); - DBC_REQUIRE(sp != NULL); - if ((key != NULL) && (sp != NULL)) { if (strcmp((char *)key, ((struct dbll_symbol *)sp)->name) == 0) @@ -938,10 +868,7 @@ static int dbll_read_buffer(struct dynamic_loader_stream *this, void *buffer, struct dbll_library_obj *lib; int bytes_read = 0; - DBC_REQUIRE(this != NULL); lib = pstream->lib; - DBC_REQUIRE(lib); - if (lib != NULL) { bytes_read = (*(lib->target_obj->attrs.fread)) (buffer, 1, bufsize, @@ -960,10 +887,7 @@ static int dbll_set_file_posn(struct dynamic_loader_stream *this, struct dbll_library_obj *lib; int status = 0; /* Success */ - DBC_REQUIRE(this != NULL); lib = pstream->lib; - DBC_REQUIRE(lib); - if (lib != NULL) { status = (*(lib->target_obj->attrs.fseek)) (lib->fp, (long)pos, SEEK_SET); @@ -986,10 +910,7 @@ static struct dynload_symbol *dbll_find_symbol(struct dynamic_loader_sym *this, struct dbll_sym_val *dbll_sym = NULL; bool status = false; /* Symbol not found yet */ - DBC_REQUIRE(this != NULL); lib = ldr_sym->lib; - DBC_REQUIRE(lib); - if (lib != NULL) { if (lib->target_obj->attrs.sym_lookup) { /* Check current lib + base lib + dep lib + @@ -1034,11 +955,7 @@ static struct dynload_symbol *find_in_symbol_table(struct dynamic_loader_sym struct dbll_library_obj *lib; struct dbll_symbol *sym; - DBC_REQUIRE(this != NULL); lib = ldr_sym->lib; - DBC_REQUIRE(lib); - DBC_REQUIRE(lib->sym_tab != NULL); - sym = (struct dbll_symbol *)gh_find(lib->sym_tab, (char *)name); ret_sym = (struct dynload_symbol *)&sym->value; @@ -1059,10 +976,7 @@ static struct dynload_symbol *dbll_add_to_symbol_table(struct dynamic_loader_sym struct dbll_library_obj *lib; struct dynload_symbol *ret; - DBC_REQUIRE(this != NULL); - DBC_REQUIRE(name); lib = ldr_sym->lib; - DBC_REQUIRE(lib); /* Check to see if symbol is already defined in symbol table */ if (!(lib->target_obj->attrs.base_image)) { @@ -1111,10 +1025,7 @@ static void dbll_purge_symbol_table(struct dynamic_loader_sym *this, struct ldr_symbol *ldr_sym = (struct ldr_symbol *)this; struct dbll_library_obj *lib; - DBC_REQUIRE(this != NULL); lib = ldr_sym->lib; - DBC_REQUIRE(lib); - /* May not need to do anything */ } @@ -1127,9 +1038,7 @@ static void *allocate(struct dynamic_loader_sym *this, unsigned memsize) struct dbll_library_obj *lib; void *buf; - DBC_REQUIRE(this != NULL); lib = ldr_sym->lib; - DBC_REQUIRE(lib); buf = kzalloc(memsize, GFP_KERNEL); @@ -1144,9 +1053,7 @@ static void deallocate(struct dynamic_loader_sym *this, void *mem_ptr) struct ldr_symbol *ldr_sym = (struct ldr_symbol *)this; struct dbll_library_obj *lib; - DBC_REQUIRE(this != NULL); lib = ldr_sym->lib; - DBC_REQUIRE(lib); kfree(mem_ptr); } @@ -1161,9 +1068,7 @@ static void dbll_err_report(struct dynamic_loader_sym *this, const char *errstr, struct dbll_library_obj *lib; char temp_buf[MAXEXPR]; - DBC_REQUIRE(this != NULL); lib = ldr_sym->lib; - DBC_REQUIRE(lib); vsnprintf((char *)temp_buf, MAXEXPR, (char *)errstr, args); dev_dbg(bridge, "%s\n", temp_buf); } @@ -1195,9 +1100,7 @@ static int dbll_rmm_alloc(struct dynamic_loader_allocate *this, u32 alloc_size = 0; u32 run_addr_flag = 0; - DBC_REQUIRE(this != NULL); lib = dbll_alloc_obj->lib; - DBC_REQUIRE(lib); mem_sect_type = (stype == DLOAD_TEXT) ? DBLL_CODE : (stype == @@ -1206,7 +1109,6 @@ static int dbll_rmm_alloc(struct dynamic_loader_allocate *this, /* Attempt to extract the segment ID and requirement information from the name of the section */ - DBC_REQUIRE(info->name); token_len = strlen((char *)(info->name)) + 1; sz_sect_name = kzalloc(token_len, GFP_KERNEL); @@ -1307,9 +1209,7 @@ static void rmm_dealloc(struct dynamic_loader_allocate *this, (stype == DLOAD_TEXT) ? DBLL_CODE : (stype == DLOAD_BSS) ? DBLL_BSS : DBLL_DATA; - DBC_REQUIRE(this != NULL); lib = dbll_alloc_obj->lib; - DBC_REQUIRE(lib); /* segid was set by alloc function */ segid = (u32) info->context; if (mem_sect_type == DBLL_CODE) @@ -1347,9 +1247,7 @@ static int read_mem(struct dynamic_loader_initialize *this, void *buf, struct dbll_library_obj *lib; int bytes_read = 0; - DBC_REQUIRE(this != NULL); lib = init_obj->lib; - DBC_REQUIRE(lib); /* Need bridge_brd_read function */ return bytes_read; } @@ -1368,7 +1266,6 @@ static int write_mem(struct dynamic_loader_initialize *this, void *buf, u32 mem_sect_type; bool ret = true; - DBC_REQUIRE(this != NULL); lib = init_obj->lib; if (!lib) return false; @@ -1415,7 +1312,6 @@ static int fill_mem(struct dynamic_loader_initialize *this, ldr_addr addr, struct dbll_library_obj *lib; struct dbll_init_obj *init_obj = (struct dbll_init_obj *)this; - DBC_REQUIRE(this != NULL); lib = init_obj->lib; pbuf = NULL; /* Pass the NULL pointer to write_mem to get the start address of Shared @@ -1439,9 +1335,7 @@ static int execute(struct dynamic_loader_initialize *this, ldr_addr start) struct dbll_library_obj *lib; bool ret = true; - DBC_REQUIRE(this != NULL); lib = init_obj->lib; - DBC_REQUIRE(lib); /* Save entry point */ if (lib != NULL) lib->entry = (u32) start; diff --git a/drivers/staging/tidspbridge/pmgr/dev.c b/drivers/staging/tidspbridge/pmgr/dev.c index 522810b..e4257fd 100644 --- a/drivers/staging/tidspbridge/pmgr/dev.c +++ b/drivers/staging/tidspbridge/pmgr/dev.c @@ -106,8 +106,6 @@ u32 dev_brd_write_fxn(void *arb, u32 dsp_add, void *host_buf, u32 ul_written = 0; int status; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(host_buf != NULL); /* Required of BrdWrite(). */ if (dev_obj) { /* Require of BrdWrite() */ DBC_ASSERT(dev_obj->bridge_context != NULL); @@ -143,9 +141,6 @@ int dev_create_device(struct dev_object **device_obj, struct drv_object *hdrv_obj = NULL; struct drv_data *drv_datap = dev_get_drvdata(bridge); int status = 0; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(device_obj != NULL); - DBC_REQUIRE(driver_file_name != NULL); status = drv_request_bridge_res_dsp((void *)&host_res); @@ -271,7 +266,6 @@ leave: *device_obj = NULL; } - DBC_ENSURE((!status && *device_obj) || (status && !*device_obj)); return status; } @@ -287,17 +281,12 @@ int dev_create2(struct dev_object *hdev_obj) int status = 0; struct dev_object *dev_obj = hdev_obj; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(hdev_obj); - /* There can be only one Node Manager per DEV object */ DBC_ASSERT(!dev_obj->node_mgr); status = node_create_mgr(&dev_obj->node_mgr, hdev_obj); if (status) dev_obj->node_mgr = NULL; - DBC_ENSURE((!status && dev_obj->node_mgr != NULL) - || (status && dev_obj->node_mgr == NULL)); return status; } @@ -311,9 +300,6 @@ int dev_destroy2(struct dev_object *hdev_obj) int status = 0; struct dev_object *dev_obj = hdev_obj; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(hdev_obj); - if (dev_obj->node_mgr) { if (node_delete_mgr(dev_obj->node_mgr)) status = -EPERM; @@ -322,7 +308,6 @@ int dev_destroy2(struct dev_object *hdev_obj) } - DBC_ENSURE((!status && dev_obj->node_mgr == NULL) || status); return status; } @@ -337,8 +322,6 @@ int dev_destroy_device(struct dev_object *hdev_obj) int status = 0; struct dev_object *dev_obj = hdev_obj; - DBC_REQUIRE(refs > 0); - if (hdev_obj) { if (dev_obj->cod_mgr) { cod_delete(dev_obj->cod_mgr); @@ -415,9 +398,6 @@ int dev_get_chnl_mgr(struct dev_object *hdev_obj, int status = 0; struct dev_object *dev_obj = hdev_obj; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(mgr != NULL); - if (hdev_obj) { *mgr = dev_obj->chnl_mgr; } else { @@ -425,7 +405,6 @@ int dev_get_chnl_mgr(struct dev_object *hdev_obj, status = -EFAULT; } - DBC_ENSURE(!status || (mgr != NULL && *mgr == NULL)); return status; } @@ -441,9 +420,6 @@ int dev_get_cmm_mgr(struct dev_object *hdev_obj, int status = 0; struct dev_object *dev_obj = hdev_obj; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(mgr != NULL); - if (hdev_obj) { *mgr = dev_obj->cmm_mgr; } else { @@ -451,7 +427,6 @@ int dev_get_cmm_mgr(struct dev_object *hdev_obj, status = -EFAULT; } - DBC_ENSURE(!status || (mgr != NULL && *mgr == NULL)); return status; } @@ -467,9 +442,6 @@ int dev_get_dmm_mgr(struct dev_object *hdev_obj, int status = 0; struct dev_object *dev_obj = hdev_obj; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(mgr != NULL); - if (hdev_obj) { *mgr = dev_obj->dmm_mgr; } else { @@ -477,7 +449,6 @@ int dev_get_dmm_mgr(struct dev_object *hdev_obj, status = -EFAULT; } - DBC_ENSURE(!status || (mgr != NULL && *mgr == NULL)); return status; } @@ -492,9 +463,6 @@ int dev_get_cod_mgr(struct dev_object *hdev_obj, int status = 0; struct dev_object *dev_obj = hdev_obj; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(cod_mgr != NULL); - if (hdev_obj) { *cod_mgr = dev_obj->cod_mgr; } else { @@ -502,7 +470,6 @@ int dev_get_cod_mgr(struct dev_object *hdev_obj, status = -EFAULT; } - DBC_ENSURE(!status || (cod_mgr != NULL && *cod_mgr == NULL)); return status; } @@ -514,9 +481,6 @@ int dev_get_deh_mgr(struct dev_object *hdev_obj, { int status = 0; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(deh_manager != NULL); - DBC_REQUIRE(hdev_obj); if (hdev_obj) { *deh_manager = hdev_obj->deh_mgr; } else { @@ -537,9 +501,6 @@ int dev_get_dev_node(struct dev_object *hdev_obj, int status = 0; struct dev_object *dev_obj = hdev_obj; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(dev_nde != NULL); - if (hdev_obj) { *dev_nde = dev_obj->dev_node_obj; } else { @@ -547,7 +508,6 @@ int dev_get_dev_node(struct dev_object *hdev_obj, status = -EFAULT; } - DBC_ENSURE(!status || (dev_nde != NULL && *dev_nde == NULL)); return status; } @@ -578,9 +538,6 @@ int dev_get_intf_fxns(struct dev_object *hdev_obj, int status = 0; struct dev_object *dev_obj = hdev_obj; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(if_fxns != NULL); - if (hdev_obj) { *if_fxns = &dev_obj->bridge_interface; } else { @@ -588,7 +545,6 @@ int dev_get_intf_fxns(struct dev_object *hdev_obj, status = -EFAULT; } - DBC_ENSURE(!status || ((if_fxns != NULL) && (*if_fxns == NULL))); return status; } @@ -600,10 +556,6 @@ int dev_get_io_mgr(struct dev_object *hdev_obj, { int status = 0; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(io_man != NULL); - DBC_REQUIRE(hdev_obj); - if (hdev_obj) { *io_man = hdev_obj->iomgr; } else { @@ -638,10 +590,6 @@ struct dev_object *dev_get_next(struct dev_object *hdev_obj) */ void dev_get_msg_mgr(struct dev_object *hdev_obj, struct msg_mgr **msg_man) { - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(msg_man != NULL); - DBC_REQUIRE(hdev_obj); - *msg_man = hdev_obj->msg_mgr; } @@ -656,9 +604,6 @@ int dev_get_node_manager(struct dev_object *hdev_obj, int status = 0; struct dev_object *dev_obj = hdev_obj; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(node_man != NULL); - if (hdev_obj) { *node_man = dev_obj->node_mgr; } else { @@ -666,7 +611,6 @@ int dev_get_node_manager(struct dev_object *hdev_obj, status = -EFAULT; } - DBC_ENSURE(!status || (node_man != NULL && *node_man == NULL)); return status; } @@ -679,9 +623,6 @@ int dev_get_symbol(struct dev_object *hdev_obj, int status = 0; struct cod_manager *cod_mgr; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(str_sym != NULL && pul_value != NULL); - if (hdev_obj) { status = dev_get_cod_mgr(hdev_obj, &cod_mgr); if (cod_mgr) @@ -706,9 +647,6 @@ int dev_get_bridge_context(struct dev_object *hdev_obj, int status = 0; struct dev_object *dev_obj = hdev_obj; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(phbridge_context != NULL); - if (hdev_obj) { *phbridge_context = dev_obj->bridge_context; } else { @@ -716,8 +654,6 @@ int dev_get_bridge_context(struct dev_object *hdev_obj, status = -EFAULT; } - DBC_ENSURE(!status || ((phbridge_context != NULL) && - (*phbridge_context == NULL))); return status; } @@ -729,16 +665,12 @@ int dev_get_bridge_context(struct dev_object *hdev_obj, */ void dev_exit(void) { - DBC_REQUIRE(refs > 0); - refs--; if (refs == 0) { cmm_exit(); dmm_exit(); } - - DBC_ENSURE(refs >= 0); } /* @@ -750,8 +682,6 @@ bool dev_init(void) { bool cmm_ret, dmm_ret, ret = true; - DBC_REQUIRE(refs >= 0); - if (refs == 0) { cmm_ret = cmm_init(); dmm_ret = dmm_init(); @@ -771,8 +701,6 @@ bool dev_init(void) if (ret) refs++; - DBC_ENSURE((ret && (refs > 0)) || (!ret && (refs >= 0))); - return ret; } @@ -841,14 +769,11 @@ int dev_set_chnl_mgr(struct dev_object *hdev_obj, int status = 0; struct dev_object *dev_obj = hdev_obj; - DBC_REQUIRE(refs > 0); - if (hdev_obj) dev_obj->chnl_mgr = hmgr; else status = -EFAULT; - DBC_ENSURE(status || (dev_obj->chnl_mgr == hmgr)); return status; } @@ -859,9 +784,6 @@ int dev_set_chnl_mgr(struct dev_object *hdev_obj, */ void dev_set_msg_mgr(struct dev_object *hdev_obj, struct msg_mgr *hmgr) { - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(hdev_obj); - hdev_obj->msg_mgr = hmgr; } @@ -879,8 +801,6 @@ int dev_start_device(struct cfg_devnode *dev_node_obj) struct mgr_object *hmgr_obj = NULL; struct drv_data *drv_datap = dev_get_drvdata(bridge); - DBC_REQUIRE(refs > 0); - /* Given all resources, create a device object. */ status = dev_create_device(&hdev_obj, bridge_file_name, dev_node_obj); @@ -944,9 +864,6 @@ static int init_cod_mgr(struct dev_object *dev_obj) int status = 0; char *sz_dummy_file = "dummy"; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(!dev_obj || (dev_obj->cod_mgr == NULL)); - status = cod_create(&dev_obj->cod_mgr, sz_dummy_file); return status; @@ -976,10 +893,6 @@ int dev_insert_proc_object(struct dev_object *hdev_obj, { struct dev_object *dev_obj = (struct dev_object *)hdev_obj; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(dev_obj); - DBC_REQUIRE(proc_obj != 0); - DBC_REQUIRE(already_attached != NULL); if (!list_empty(&dev_obj->proc_list)) *already_attached = true; @@ -1017,10 +930,6 @@ int dev_remove_proc_object(struct dev_object *hdev_obj, u32 proc_obj) struct list_head *cur_elem; struct dev_object *dev_obj = (struct dev_object *)hdev_obj; - DBC_REQUIRE(dev_obj); - DBC_REQUIRE(proc_obj != 0); - DBC_REQUIRE(!list_empty(&dev_obj->proc_list)); - /* Search list for dev_obj: */ list_for_each(cur_elem, &dev_obj->proc_list) { if ((u32) cur_elem == proc_obj) { @@ -1069,10 +978,6 @@ static void store_interface_fxns(struct bridge_drv_interface *drv_fxns, (intf_fxns->pfn = ((drv_fxns->pfn != NULL) ? drv_fxns->pfn : \ (cast)fxn_not_implemented)) - DBC_REQUIRE(intf_fxns != NULL); - DBC_REQUIRE(drv_fxns != NULL); - DBC_REQUIRE(MAKEVERSION(drv_fxns->brd_api_major_version, - drv_fxns->brd_api_minor_version) <= BRD_API_VERSION); bridge_version = MAKEVERSION(drv_fxns->brd_api_major_version, drv_fxns->brd_api_minor_version); intf_fxns->brd_api_major_version = drv_fxns->brd_api_major_version; @@ -1119,33 +1024,5 @@ static void store_interface_fxns(struct bridge_drv_interface *drv_fxns, STORE_FXN(fxn_msg_setqueueid, msg_set_queue_id); } /* Add code for any additional functions in newerBridge versions here */ - /* Ensure postcondition: */ - DBC_ENSURE(intf_fxns->dev_create != NULL); - DBC_ENSURE(intf_fxns->dev_destroy != NULL); - DBC_ENSURE(intf_fxns->dev_cntrl != NULL); - DBC_ENSURE(intf_fxns->brd_monitor != NULL); - DBC_ENSURE(intf_fxns->brd_start != NULL); - DBC_ENSURE(intf_fxns->brd_stop != NULL); - DBC_ENSURE(intf_fxns->brd_status != NULL); - DBC_ENSURE(intf_fxns->brd_read != NULL); - DBC_ENSURE(intf_fxns->brd_write != NULL); - DBC_ENSURE(intf_fxns->chnl_create != NULL); - DBC_ENSURE(intf_fxns->chnl_destroy != NULL); - DBC_ENSURE(intf_fxns->chnl_open != NULL); - DBC_ENSURE(intf_fxns->chnl_close != NULL); - DBC_ENSURE(intf_fxns->chnl_add_io_req != NULL); - DBC_ENSURE(intf_fxns->chnl_get_ioc != NULL); - DBC_ENSURE(intf_fxns->chnl_cancel_io != NULL); - DBC_ENSURE(intf_fxns->chnl_flush_io != NULL); - DBC_ENSURE(intf_fxns->chnl_get_info != NULL); - DBC_ENSURE(intf_fxns->chnl_get_mgr_info != NULL); - DBC_ENSURE(intf_fxns->chnl_idle != NULL); - DBC_ENSURE(intf_fxns->chnl_register_notify != NULL); - DBC_ENSURE(intf_fxns->io_create != NULL); - DBC_ENSURE(intf_fxns->io_destroy != NULL); - DBC_ENSURE(intf_fxns->io_on_loaded != NULL); - DBC_ENSURE(intf_fxns->io_get_proc_load != NULL); - DBC_ENSURE(intf_fxns->msg_set_queue_id != NULL); - #undef STORE_FXN } diff --git a/drivers/staging/tidspbridge/pmgr/dmm.c b/drivers/staging/tidspbridge/pmgr/dmm.c index 8685233..cece780 100644 --- a/drivers/staging/tidspbridge/pmgr/dmm.c +++ b/drivers/staging/tidspbridge/pmgr/dmm.c @@ -123,8 +123,6 @@ int dmm_create(struct dmm_object **dmm_manager, { struct dmm_object *dmm_obj = NULL; int status = 0; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(dmm_manager != NULL); *dmm_manager = NULL; /* create, zero, and tag a cmm mgr object */ @@ -149,7 +147,6 @@ int dmm_destroy(struct dmm_object *dmm_mgr) struct dmm_object *dmm_obj = (struct dmm_object *)dmm_mgr; int status = 0; - DBC_REQUIRE(refs > 0); if (dmm_mgr) { status = dmm_delete_tables(dmm_obj); if (!status) @@ -169,7 +166,6 @@ int dmm_delete_tables(struct dmm_object *dmm_mgr) { int status = 0; - DBC_REQUIRE(refs > 0); /* Delete all DMM tables */ if (dmm_mgr) vfree(virtual_mapping_table); @@ -186,7 +182,6 @@ int dmm_delete_tables(struct dmm_object *dmm_mgr) */ void dmm_exit(void) { - DBC_REQUIRE(refs > 0); refs--; } @@ -202,8 +197,6 @@ int dmm_get_handle(void *hprocessor, struct dmm_object **dmm_manager) int status = 0; struct dev_object *hdev_obj; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(dmm_manager != NULL); if (hprocessor != NULL) status = proc_get_dev_object(hprocessor, &hdev_obj); else @@ -224,13 +217,9 @@ bool dmm_init(void) { bool ret = true; - DBC_REQUIRE(refs >= 0); - if (ret) refs++; - DBC_ENSURE((ret && (refs > 0)) || (!ret && (refs >= 0))); - virtual_mapping_table = NULL; table_size = 0; diff --git a/drivers/staging/tidspbridge/pmgr/dspapi.c b/drivers/staging/tidspbridge/pmgr/dspapi.c index 767ffe2..27c14a5 100644 --- a/drivers/staging/tidspbridge/pmgr/dspapi.c +++ b/drivers/staging/tidspbridge/pmgr/dspapi.c @@ -266,7 +266,6 @@ err: */ void api_exit(void) { - DBC_REQUIRE(api_c_refs > 0); api_c_refs--; if (api_c_refs == 0) { @@ -284,7 +283,6 @@ void api_exit(void) rmm_exit(); drv_exit(); } - DBC_ENSURE(api_c_refs >= 0); } /* @@ -382,8 +380,6 @@ int api_init_complete2(void) struct drv_data *drv_datap; u8 dev_type; - DBC_REQUIRE(api_c_refs > 0); - /* Walk the list of DevObjects, get each devnode, and attempting to * autostart the board. Note that this requires COF loading, which * requires KFILE. */ diff --git a/drivers/staging/tidspbridge/pmgr/io.c b/drivers/staging/tidspbridge/pmgr/io.c index 65245f3..bbfe94c 100644 --- a/drivers/staging/tidspbridge/pmgr/io.c +++ b/drivers/staging/tidspbridge/pmgr/io.c @@ -50,10 +50,6 @@ int io_create(struct io_mgr **io_man, struct dev_object *hdev_obj, struct io_mgr_ *pio_mgr = NULL; int status = 0; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(io_man != NULL); - DBC_REQUIRE(mgr_attrts != NULL); - *io_man = NULL; /* A memory base of 0 implies no memory base: */ @@ -94,8 +90,6 @@ int io_destroy(struct io_mgr *hio_mgr) struct io_mgr_ *pio_mgr = (struct io_mgr_ *)hio_mgr; int status; - DBC_REQUIRE(refs > 0); - intf_fxns = pio_mgr->intf_fxns; /* Let Bridge channel module destroy the io_mgr: */ @@ -111,11 +105,7 @@ int io_destroy(struct io_mgr *hio_mgr) */ void io_exit(void) { - DBC_REQUIRE(refs > 0); - refs--; - - DBC_ENSURE(refs >= 0); } /* @@ -127,12 +117,8 @@ bool io_init(void) { bool ret = true; - DBC_REQUIRE(refs >= 0); - if (ret) refs++; - DBC_ENSURE((ret && (refs > 0)) || (!ret && (refs >= 0))); - return ret; } diff --git a/drivers/staging/tidspbridge/pmgr/msg.c b/drivers/staging/tidspbridge/pmgr/msg.c index a691603..150026d 100644 --- a/drivers/staging/tidspbridge/pmgr/msg.c +++ b/drivers/staging/tidspbridge/pmgr/msg.c @@ -53,11 +53,6 @@ int msg_create(struct msg_mgr **msg_man, struct msg_mgr *hmsg_mgr; int status = 0; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(msg_man != NULL); - DBC_REQUIRE(msg_callback != NULL); - DBC_REQUIRE(hdev_obj != NULL); - *msg_man = NULL; dev_get_intf_fxns(hdev_obj, &intf_fxns); @@ -90,8 +85,6 @@ void msg_delete(struct msg_mgr *hmsg_mgr) struct msg_mgr_ *msg_mgr_obj = (struct msg_mgr_ *)hmsg_mgr; struct bridge_drv_interface *intf_fxns; - DBC_REQUIRE(refs > 0); - if (msg_mgr_obj) { intf_fxns = msg_mgr_obj->intf_fxns; @@ -108,10 +101,7 @@ void msg_delete(struct msg_mgr *hmsg_mgr) */ void msg_exit(void) { - DBC_REQUIRE(refs > 0); refs--; - - DBC_ENSURE(refs >= 0); } /* @@ -119,11 +109,7 @@ void msg_exit(void) */ bool msg_mod_init(void) { - DBC_REQUIRE(refs >= 0); - refs++; - DBC_ENSURE(refs >= 0); - return true; } diff --git a/drivers/staging/tidspbridge/rmgr/dbdcd.c b/drivers/staging/tidspbridge/rmgr/dbdcd.c index fda2402..792b443 100644 --- a/drivers/staging/tidspbridge/rmgr/dbdcd.c +++ b/drivers/staging/tidspbridge/rmgr/dbdcd.c @@ -85,8 +85,6 @@ int dcd_auto_register(struct dcd_manager *hdcd_mgr, { int status = 0; - DBC_REQUIRE(refs > 0); - if (hdcd_mgr) status = dcd_get_objects(hdcd_mgr, sz_coff_path, (dcd_registerfxn) dcd_register_object, @@ -107,8 +105,6 @@ int dcd_auto_unregister(struct dcd_manager *hdcd_mgr, { int status = 0; - DBC_REQUIRE(refs > 0); - if (hdcd_mgr) status = dcd_get_objects(hdcd_mgr, sz_coff_path, (dcd_registerfxn) dcd_register_object, @@ -131,9 +127,6 @@ int dcd_create_manager(char *sz_zl_dll_name, struct dcd_manager *dcd_mgr_obj = NULL; /* DCD Manager pointer */ int status = 0; - DBC_REQUIRE(refs >= 0); - DBC_REQUIRE(dcd_mgr); - status = cod_create(&cod_mgr, sz_zl_dll_name); if (status) goto func_end; @@ -156,9 +149,6 @@ int dcd_create_manager(char *sz_zl_dll_name, cod_delete(cod_mgr); } - DBC_ENSURE((!status) || - ((dcd_mgr_obj == NULL) && (status == -ENOMEM))); - func_end: return status; } @@ -173,8 +163,6 @@ int dcd_destroy_manager(struct dcd_manager *hdcd_mgr) struct dcd_manager *dcd_mgr_obj = hdcd_mgr; int status = -EFAULT; - DBC_REQUIRE(refs >= 0); - if (hdcd_mgr) { /* Delete the COD manager. */ cod_delete(dcd_mgr_obj->cod_mgr); @@ -205,10 +193,6 @@ int dcd_enumerate_object(s32 index, enum dsp_dcdobjtype obj_type, struct dcd_key_elem *dcd_key; int len; - DBC_REQUIRE(refs >= 0); - DBC_REQUIRE(index >= 0); - DBC_REQUIRE(uuid_obj != NULL); - if ((index != 0) && (enum_refs == 0)) { /* * If an enumeration is being performed on an index greater @@ -294,8 +278,6 @@ int dcd_enumerate_object(s32 index, enum dsp_dcdobjtype obj_type, } } - DBC_ENSURE(uuid_obj || (status == -EPERM)); - return status; } @@ -307,7 +289,6 @@ int dcd_enumerate_object(s32 index, enum dsp_dcdobjtype obj_type, void dcd_exit(void) { struct dcd_key_elem *rv, *rv_tmp; - DBC_REQUIRE(refs > 0); refs--; if (refs == 0) { @@ -319,7 +300,6 @@ void dcd_exit(void) } } - DBC_ENSURE(refs >= 0); } /* @@ -333,12 +313,6 @@ int dcd_get_dep_libs(struct dcd_manager *hdcd_mgr, { int status = 0; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(hdcd_mgr); - DBC_REQUIRE(uuid_obj != NULL); - DBC_REQUIRE(dep_lib_uuids != NULL); - DBC_REQUIRE(prstnt_dep_libs != NULL); - status = get_dep_lib_info(hdcd_mgr, uuid_obj, &num_libs, NULL, dep_lib_uuids, prstnt_dep_libs, phase); @@ -356,12 +330,6 @@ int dcd_get_num_dep_libs(struct dcd_manager *hdcd_mgr, { int status = 0; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(hdcd_mgr); - DBC_REQUIRE(num_libs != NULL); - DBC_REQUIRE(num_pers_libs != NULL); - DBC_REQUIRE(uuid_obj != NULL); - status = get_dep_lib_info(hdcd_mgr, uuid_obj, num_libs, num_pers_libs, NULL, NULL, phase); @@ -393,10 +361,6 @@ int dcd_get_object_def(struct dcd_manager *hdcd_mgr, u32 dw_key_len; /* Len of REG key. */ char sz_obj_type[MAX_INT2CHAR_LENGTH]; /* str. rep. of obj_type. */ - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(obj_def != NULL); - DBC_REQUIRE(obj_uuid != NULL); - sz_uuid = kzalloc(MAXUUIDLEN, GFP_KERNEL); if (!sz_uuid) { status = -ENOMEM; @@ -553,7 +517,6 @@ int dcd_get_objects(struct dcd_manager *hdcd_mgr, struct dsp_uuid dsp_uuid_obj; s32 object_type; - DBC_REQUIRE(refs > 0); if (!hdcd_mgr) { status = -EFAULT; goto func_end; @@ -663,11 +626,6 @@ int dcd_get_library_name(struct dcd_manager *hdcd_mgr, int status = 0; struct dcd_key_elem *dcd_key = NULL; - DBC_REQUIRE(uuid_obj != NULL); - DBC_REQUIRE(str_lib_name != NULL); - DBC_REQUIRE(buff_size != NULL); - DBC_REQUIRE(hdcd_mgr); - dev_dbg(bridge, "%s: hdcd_mgr %p, uuid_obj %p, str_lib_name %p," " buff_size %p\n", __func__, hdcd_mgr, uuid_obj, str_lib_name, buff_size); @@ -790,8 +748,6 @@ bool dcd_init(void) bool init_cod; bool ret = true; - DBC_REQUIRE(refs >= 0); - if (refs == 0) { /* Initialize required modules. */ init_cod = cod_init(); @@ -809,8 +765,6 @@ bool dcd_init(void) if (ret) refs++; - DBC_ENSURE((ret && (refs > 0)) || (!ret && (refs == 0))); - return ret; } @@ -832,15 +786,6 @@ int dcd_register_object(struct dsp_uuid *uuid_obj, char sz_obj_type[MAX_INT2CHAR_LENGTH]; /* str. rep. of obj_type. */ struct dcd_key_elem *dcd_key = NULL; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(uuid_obj != NULL); - DBC_REQUIRE((obj_type == DSP_DCDNODETYPE) || - (obj_type == DSP_DCDPROCESSORTYPE) || - (obj_type == DSP_DCDLIBRARYTYPE) || - (obj_type == DSP_DCDCREATELIBTYPE) || - (obj_type == DSP_DCDEXECUTELIBTYPE) || - (obj_type == DSP_DCDDELETELIBTYPE)); - dev_dbg(bridge, "%s: object UUID %p, obj_type %d, szPathName %s\n", __func__, uuid_obj, obj_type, psz_path_name); @@ -987,15 +932,6 @@ int dcd_unregister_object(struct dsp_uuid *uuid_obj, { int status = 0; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(uuid_obj != NULL); - DBC_REQUIRE((obj_type == DSP_DCDNODETYPE) || - (obj_type == DSP_DCDPROCESSORTYPE) || - (obj_type == DSP_DCDLIBRARYTYPE) || - (obj_type == DSP_DCDCREATELIBTYPE) || - (obj_type == DSP_DCDEXECUTELIBTYPE) || - (obj_type == DSP_DCDDELETELIBTYPE)); - /* * When dcd_register_object is called with NULL as pathname, * it indicates an unregister object operation. @@ -1055,12 +991,6 @@ static int get_attrs_from_buf(char *psz_buf, u32 ul_buf_size, s32 entry_id; #endif - DBC_REQUIRE(psz_buf != NULL); - DBC_REQUIRE(ul_buf_size != 0); - DBC_REQUIRE((obj_type == DSP_DCDNODETYPE) - || (obj_type == DSP_DCDPROCESSORTYPE)); - DBC_REQUIRE(gen_obj != NULL); - switch (obj_type) { case DSP_DCDNODETYPE: /* @@ -1082,7 +1012,6 @@ static int get_attrs_from_buf(char *psz_buf, u32 ul_buf_size, token = strsep(&psz_cur, seps); /* ac_name */ - DBC_REQUIRE(token); token_len = strlen(token); if (token_len > DSP_MAXNAMELEN - 1) token_len = DSP_MAXNAMELEN - 1; @@ -1167,7 +1096,6 @@ static int get_attrs_from_buf(char *psz_buf, u32 ul_buf_size, token = strsep(&psz_cur, seps); /* char *str_create_phase_fxn */ - DBC_REQUIRE(token); token_len = strlen(token); gen_obj->obj_data.node_obj.str_create_phase_fxn = kzalloc(token_len + 1, GFP_KERNEL); @@ -1178,7 +1106,6 @@ static int get_attrs_from_buf(char *psz_buf, u32 ul_buf_size, token = strsep(&psz_cur, seps); /* char *str_execute_phase_fxn */ - DBC_REQUIRE(token); token_len = strlen(token); gen_obj->obj_data.node_obj.str_execute_phase_fxn = kzalloc(token_len + 1, GFP_KERNEL); @@ -1189,7 +1116,6 @@ static int get_attrs_from_buf(char *psz_buf, u32 ul_buf_size, token = strsep(&psz_cur, seps); /* char *str_delete_phase_fxn */ - DBC_REQUIRE(token); token_len = strlen(token); gen_obj->obj_data.node_obj.str_delete_phase_fxn = kzalloc(token_len + 1, GFP_KERNEL); @@ -1421,12 +1347,6 @@ static int get_dep_lib_info(struct dcd_manager *hdcd_mgr, u16 dep_libs = 0; int status = 0; - DBC_REQUIRE(refs > 0); - - DBC_REQUIRE(hdcd_mgr); - DBC_REQUIRE(num_libs != NULL); - DBC_REQUIRE(uuid_obj != NULL); - /* Initialize to 0 dependent libraries, if only counting number of * dependent libraries */ if (!get_uuids) { diff --git a/drivers/staging/tidspbridge/rmgr/disp.c b/drivers/staging/tidspbridge/rmgr/disp.c index a9aa22f..04c88a7d 100644 --- a/drivers/staging/tidspbridge/rmgr/disp.c +++ b/drivers/staging/tidspbridge/rmgr/disp.c @@ -96,11 +96,6 @@ int disp_create(struct disp_object **dispatch_obj, int status = 0; u8 dev_type; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(dispatch_obj != NULL); - DBC_REQUIRE(disp_attrs != NULL); - DBC_REQUIRE(hdev_obj != NULL); - *dispatch_obj = NULL; /* Allocate Node Dispatcher object */ @@ -168,8 +163,6 @@ func_cont: else delete_disp(disp_obj); - DBC_ENSURE((status && *dispatch_obj == NULL) || - (!status && *dispatch_obj)); return status; } @@ -179,9 +172,6 @@ func_cont: */ void disp_delete(struct disp_object *disp_obj) { - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(disp_obj); - delete_disp(disp_obj); } @@ -191,11 +181,7 @@ void disp_delete(struct disp_object *disp_obj) */ void disp_exit(void) { - DBC_REQUIRE(refs > 0); - refs--; - - DBC_ENSURE(refs >= 0); } /* @@ -206,12 +192,9 @@ bool disp_init(void) { bool ret = true; - DBC_REQUIRE(refs >= 0); - if (ret) refs++; - DBC_ENSURE((ret && (refs > 0)) || (!ret && (refs >= 0))); return ret; } @@ -227,10 +210,6 @@ int disp_node_change_priority(struct disp_object *disp_obj, struct rms_command *rms_cmd; int status = 0; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(disp_obj); - DBC_REQUIRE(hnode != NULL); - /* Send message to RMS to change priority */ rms_cmd = (struct rms_command *)(disp_obj->buf); rms_cmd->fxn = (rms_word) (rms_fxn); @@ -276,12 +255,6 @@ int disp_node_create(struct disp_object *disp_obj, struct dsp_nodeinfo node_info; u8 dev_type; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(disp_obj); - DBC_REQUIRE(hnode != NULL); - DBC_REQUIRE(node_get_type(hnode) != NODE_DEVICE); - DBC_REQUIRE(node_env != NULL); - status = dev_get_dev_type(disp_obj->dev_obj, &dev_type); if (status) @@ -292,7 +265,6 @@ int disp_node_create(struct disp_object *disp_obj, __func__, dev_type); goto func_end; } - DBC_REQUIRE(pargs != NULL); node_type = node_get_type(hnode); node_msg_args = pargs->asa.node_msg_args; max = disp_obj->bufsize_rms; /*Max # of RMS words that can be sent */ @@ -480,10 +452,6 @@ int disp_node_delete(struct disp_object *disp_obj, int status = 0; u8 dev_type; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(disp_obj); - DBC_REQUIRE(hnode != NULL); - status = dev_get_dev_type(disp_obj->dev_obj, &dev_type); if (!status) { @@ -521,9 +489,6 @@ int disp_node_run(struct disp_object *disp_obj, struct rms_command *rms_cmd; int status = 0; u8 dev_type; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(disp_obj); - DBC_REQUIRE(hnode != NULL); status = dev_get_dev_type(disp_obj->dev_obj, &dev_type); @@ -620,7 +585,6 @@ static int fill_stream_def(rms_word *pdw_buf, u32 *ptotal, u32 offset, * 1 from total. */ total += sizeof(struct rms_strm_def) / sizeof(rms_word) - 1; - DBC_REQUIRE(strm_def.sz_device); dw_length = strlen(strm_def.sz_device) + 1; /* Number of RMS_WORDS needed to hold device name */ @@ -659,8 +623,6 @@ static int send_message(struct disp_object *disp_obj, u32 timeout, struct chnl_ioc chnl_ioc_obj; int status = 0; - DBC_REQUIRE(pdw_arg != NULL); - *pdw_arg = (u32) NULL; intf_fxns = disp_obj->intf_fxns; chnl_obj = disp_obj->chnl_to_dsp; diff --git a/drivers/staging/tidspbridge/rmgr/drv.c b/drivers/staging/tidspbridge/rmgr/drv.c index db8215f..f3bff1b 100644 --- a/drivers/staging/tidspbridge/rmgr/drv.c +++ b/drivers/staging/tidspbridge/rmgr/drv.c @@ -308,9 +308,6 @@ int drv_create(struct drv_object **drv_obj) struct drv_object *pdrv_object = NULL; struct drv_data *drv_datap = dev_get_drvdata(bridge); - DBC_REQUIRE(drv_obj != NULL); - DBC_REQUIRE(refs > 0); - pdrv_object = kzalloc(sizeof(struct drv_object), GFP_KERNEL); if (pdrv_object) { /* Create and Initialize List of device objects */ @@ -336,7 +333,6 @@ int drv_create(struct drv_object **drv_obj) kfree(pdrv_object); } - DBC_ENSURE(status || pdrv_object); return status; } @@ -347,11 +343,7 @@ int drv_create(struct drv_object **drv_obj) */ void drv_exit(void) { - DBC_REQUIRE(refs > 0); - refs--; - - DBC_ENSURE(refs >= 0); } /* @@ -365,9 +357,6 @@ int drv_destroy(struct drv_object *driver_obj) struct drv_object *pdrv_object = (struct drv_object *)driver_obj; struct drv_data *drv_datap = dev_get_drvdata(bridge); - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(pdrv_object); - kfree(pdrv_object); /* Update the DRV Object in the driver data */ if (drv_datap) { @@ -395,10 +384,6 @@ int drv_get_dev_object(u32 index, struct drv_object *hdrv_obj, #endif struct dev_object *dev_obj; u32 i; - DBC_REQUIRE(pdrv_obj); - DBC_REQUIRE(device_obj != NULL); - DBC_REQUIRE(index >= 0); - DBC_REQUIRE(refs > 0); DBC_ASSERT(!(list_empty(&pdrv_obj->dev_list))); dev_obj = (struct dev_object *)drv_get_first_dev_object(); @@ -532,13 +517,9 @@ int drv_init(void) { s32 ret = 1; /* function return value */ - DBC_REQUIRE(refs >= 0); - if (ret) refs++; - DBC_ENSURE((ret && (refs > 0)) || (!ret && (refs >= 0))); - return ret; } @@ -552,10 +533,6 @@ int drv_insert_dev_object(struct drv_object *driver_obj, { struct drv_object *pdrv_object = (struct drv_object *)driver_obj; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(hdev_obj != NULL); - DBC_REQUIRE(pdrv_object); - list_add_tail((struct list_head *)hdev_obj, &pdrv_object->dev_list); return 0; @@ -574,12 +551,6 @@ int drv_remove_dev_object(struct drv_object *driver_obj, struct drv_object *pdrv_object = (struct drv_object *)driver_obj; struct list_head *cur_elem; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(pdrv_object); - DBC_REQUIRE(hdev_obj != NULL); - - DBC_REQUIRE(!list_empty(&pdrv_object->dev_list)); - /* Search list for p_proc_object: */ list_for_each(cur_elem, &pdrv_object->dev_list) { /* If found, remove it. */ @@ -605,9 +576,6 @@ int drv_request_resources(u32 dw_context, u32 *dev_node_strg) struct drv_ext *pszdev_node; struct drv_data *drv_datap = dev_get_drvdata(bridge); - DBC_REQUIRE(dw_context != 0); - DBC_REQUIRE(dev_node_strg != NULL); - /* * Allocate memory to hold the string. This will live until * it is freed in the Release resources. Update the driver object @@ -639,10 +607,6 @@ int drv_request_resources(u32 dw_context, u32 *dev_node_strg) *dev_node_strg = 0; } - DBC_ENSURE((!status && dev_node_strg != NULL && - !list_empty(&pdrv_object->dev_node_string)) || - (status && *dev_node_strg == 0)); - return status; } @@ -900,8 +864,6 @@ void *mem_alloc_phys_mem(u32 byte_size, u32 align_mask, void mem_free_phys_mem(void *virtual_address, u32 physical_address, u32 byte_size) { - DBC_REQUIRE(virtual_address != NULL); - if (!ext_phys_mem_pool_enabled) dma_free_coherent(NULL, byte_size, virtual_address, physical_address); diff --git a/drivers/staging/tidspbridge/rmgr/drv_interface.c b/drivers/staging/tidspbridge/rmgr/drv_interface.c index 93fc862..34730de 100644 --- a/drivers/staging/tidspbridge/rmgr/drv_interface.c +++ b/drivers/staging/tidspbridge/rmgr/drv_interface.c @@ -212,7 +212,6 @@ static long bridge_ioctl(struct file *filp, unsigned int code, u32 retval = 0; union trapped_args buf_in; - DBC_REQUIRE(filp != NULL); #ifdef CONFIG_TIDSPBRIDGE_RECOVERY if (recover) { status = -EIO; diff --git a/drivers/staging/tidspbridge/rmgr/dspdrv.c b/drivers/staging/tidspbridge/rmgr/dspdrv.c index 7a6fc73..5d25763 100644 --- a/drivers/staging/tidspbridge/rmgr/dspdrv.c +++ b/drivers/staging/tidspbridge/rmgr/dspdrv.c @@ -102,8 +102,6 @@ func_cont: } else { dev_dbg(bridge, "%s: Failed\n", __func__); } /* End api_init_complete2 */ - DBC_ENSURE((!status && drv_obj != NULL) || - (status && drv_obj == NULL)); *init_status = status; /* Return the Driver Object */ return (u32) drv_obj; diff --git a/drivers/staging/tidspbridge/rmgr/mgr.c b/drivers/staging/tidspbridge/rmgr/mgr.c index d635c01..1dca953 100644 --- a/drivers/staging/tidspbridge/rmgr/mgr.c +++ b/drivers/staging/tidspbridge/rmgr/mgr.c @@ -62,9 +62,6 @@ int mgr_create(struct mgr_object **mgr_obj, struct mgr_object *pmgr_obj = NULL; struct drv_data *drv_datap = dev_get_drvdata(bridge); - DBC_REQUIRE(mgr_obj != NULL); - DBC_REQUIRE(refs > 0); - pmgr_obj = kzalloc(sizeof(struct mgr_object), GFP_KERNEL); if (pmgr_obj) { status = dcd_create_manager(ZLDLLNAME, &pmgr_obj->dcd_mgr); @@ -92,7 +89,6 @@ int mgr_create(struct mgr_object **mgr_obj, status = -ENOMEM; } - DBC_ENSURE(status || pmgr_obj); return status; } @@ -106,9 +102,6 @@ int mgr_destroy(struct mgr_object *hmgr_obj) struct mgr_object *pmgr_obj = (struct mgr_object *)hmgr_obj; struct drv_data *drv_datap = dev_get_drvdata(bridge); - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(hmgr_obj); - /* Free resources */ if (hmgr_obj->dcd_mgr) dcd_destroy_manager(hmgr_obj->dcd_mgr); @@ -140,11 +133,6 @@ int mgr_enum_node_info(u32 node_id, struct dsp_ndbprops *pndb_props, struct mgr_object *pmgr_obj = NULL; struct drv_data *drv_datap = dev_get_drvdata(bridge); - DBC_REQUIRE(pndb_props != NULL); - DBC_REQUIRE(pu_num_nodes != NULL); - DBC_REQUIRE(undb_props_size >= sizeof(struct dsp_ndbprops)); - DBC_REQUIRE(refs > 0); - *pu_num_nodes = 0; /* Get the Manager Object from the driver data */ if (!drv_datap || !drv_datap->mgr_object) { @@ -205,11 +193,6 @@ int mgr_enum_processor_info(u32 processor_id, struct drv_data *drv_datap = dev_get_drvdata(bridge); bool proc_detect = false; - DBC_REQUIRE(processor_info != NULL); - DBC_REQUIRE(pu_num_procs != NULL); - DBC_REQUIRE(processor_info_size >= sizeof(struct dsp_processorinfo)); - DBC_REQUIRE(refs > 0); - *pu_num_procs = 0; /* Retrieve the Object handle from the driver data */ @@ -310,12 +293,9 @@ func_end: */ void mgr_exit(void) { - DBC_REQUIRE(refs > 0); refs--; if (refs == 0) dcd_exit(); - - DBC_ENSURE(refs >= 0); } /* @@ -328,16 +308,11 @@ int mgr_get_dcd_handle(struct mgr_object *mgr_handle, int status = -EPERM; struct mgr_object *pmgr_obj = (struct mgr_object *)mgr_handle; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(dcd_handle != NULL); - *dcd_handle = (u32) NULL; if (pmgr_obj) { *dcd_handle = (u32) pmgr_obj->dcd_mgr; status = 0; } - DBC_ENSURE((!status && *dcd_handle != (u32) NULL) || - (status && *dcd_handle == (u32) NULL)); return status; } @@ -351,8 +326,6 @@ bool mgr_init(void) bool ret = true; bool init_dcd = false; - DBC_REQUIRE(refs >= 0); - if (refs == 0) { init_dcd = dcd_init(); /* DCD Module */ @@ -363,8 +336,6 @@ bool mgr_init(void) if (ret) refs++; - DBC_ENSURE((ret && (refs > 0)) || (!ret && (refs >= 0))); - return ret; } @@ -380,8 +351,6 @@ int mgr_wait_for_bridge_events(struct dsp_notification **anotifications, struct sync_object *sync_events[MAX_EVENTS]; u32 i; - DBC_REQUIRE(count < MAX_EVENTS); - for (i = 0; i < count; i++) sync_events[i] = anotifications[i]->handle; diff --git a/drivers/staging/tidspbridge/rmgr/nldr.c b/drivers/staging/tidspbridge/rmgr/nldr.c index 0e70cba..6fb19ef 100644 --- a/drivers/staging/tidspbridge/rmgr/nldr.c +++ b/drivers/staging/tidspbridge/rmgr/nldr.c @@ -313,11 +313,6 @@ int nldr_allocate(struct nldr_object *nldr_obj, void *priv_ref, struct nldr_nodeobject *nldr_node_obj = NULL; int status = 0; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(node_props != NULL); - DBC_REQUIRE(nldr_nodeobj != NULL); - DBC_REQUIRE(nldr_obj); - /* Initialize handle in case of failure */ *nldr_nodeobj = NULL; /* Allocate node object */ @@ -398,8 +393,6 @@ int nldr_allocate(struct nldr_object *nldr_obj, void *priv_ref, if (status && nldr_node_obj) kfree(nldr_node_obj); - DBC_ENSURE((!status && *nldr_nodeobj) - || (status && *nldr_nodeobj == NULL)); return status; } @@ -425,12 +418,6 @@ int nldr_create(struct nldr_object **nldr, struct rmm_segment *rmm_segs = NULL; u16 i; int status = 0; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(nldr != NULL); - DBC_REQUIRE(hdev_obj != NULL); - DBC_REQUIRE(pattrs != NULL); - DBC_REQUIRE(pattrs->ovly != NULL); - DBC_REQUIRE(pattrs->write != NULL); /* Allocate dynamic loader object */ nldr_obj = kzalloc(sizeof(struct nldr_object), GFP_KERNEL); @@ -583,7 +570,6 @@ int nldr_create(struct nldr_object **nldr, *nldr = NULL; } /* FIXME:Temp. Fix. Must be removed */ - DBC_ENSURE((!status && *nldr) || (status && *nldr == NULL)); return status; } @@ -595,8 +581,6 @@ void nldr_delete(struct nldr_object *nldr_obj) struct ovly_sect *ovly_section; struct ovly_sect *next; u16 i; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(nldr_obj); nldr_obj->ldr_fxns.exit_fxn(); if (nldr_obj->rmm) @@ -649,14 +633,10 @@ void nldr_delete(struct nldr_object *nldr_obj) */ void nldr_exit(void) { - DBC_REQUIRE(refs > 0); - refs--; if (refs == 0) rmm_exit(); - - DBC_ENSURE(refs >= 0); } /* @@ -671,10 +651,6 @@ int nldr_get_fxn_addr(struct nldr_nodeobject *nldr_node_obj, bool status1 = false; s32 i = 0; struct lib_node root = { NULL, 0, NULL }; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(nldr_node_obj); - DBC_REQUIRE(addr != NULL); - DBC_REQUIRE(str_fxn != NULL); nldr_obj = nldr_node_obj->nldr_obj; /* Called from node_create(), node_delete(), or node_run(). */ @@ -760,7 +736,6 @@ int nldr_get_rmm_manager(struct nldr_object *nldr, { int status = 0; struct nldr_object *nldr_obj = nldr; - DBC_REQUIRE(rmm_mgr != NULL); if (nldr) { *rmm_mgr = nldr_obj->rmm; @@ -769,8 +744,6 @@ int nldr_get_rmm_manager(struct nldr_object *nldr, status = -EFAULT; } - DBC_ENSURE(!status || (rmm_mgr != NULL && *rmm_mgr == NULL)); - return status; } @@ -780,14 +753,11 @@ int nldr_get_rmm_manager(struct nldr_object *nldr, */ bool nldr_init(void) { - DBC_REQUIRE(refs >= 0); - if (refs == 0) rmm_init(); refs++; - DBC_ENSURE(refs > 0); return true; } @@ -801,9 +771,6 @@ int nldr_load(struct nldr_nodeobject *nldr_node_obj, struct dsp_uuid lib_uuid; int status = 0; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(nldr_node_obj); - nldr_obj = nldr_node_obj->nldr_obj; if (nldr_node_obj->dynamic) { @@ -863,9 +830,6 @@ int nldr_unload(struct nldr_nodeobject *nldr_node_obj, struct lib_node *root_lib = NULL; s32 i = 0; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(nldr_node_obj); - if (nldr_node_obj != NULL) { if (nldr_node_obj->dynamic) { if (*nldr_node_obj->phase_split) { @@ -929,7 +893,6 @@ static int add_ovly_info(void *handle, struct dbll_sect_info *sect_info, /* Find the node it belongs to */ for (i = 0; i < nldr_obj->ovly_nodes; i++) { node_name = nldr_obj->ovly_table[i].node_name; - DBC_REQUIRE(node_name); if (strncmp(node_name, sect_name + 1, strlen(node_name)) == 0) { /* Found the node */ break; @@ -1018,8 +981,6 @@ static int add_ovly_node(struct dsp_uuid *uuid_obj, /* Add node to table */ nldr_obj->ovly_table[nldr_obj->ovly_nid].uuid = *uuid_obj; - DBC_REQUIRE(obj_def.obj_data.node_obj.ndb_props. - ac_name); len = strlen(obj_def.obj_data.node_obj.ndb_props.ac_name); node_name = obj_def.obj_data.node_obj.ndb_props.ac_name; @@ -1623,9 +1584,6 @@ static int remote_alloc(void **ref, u16 mem_sect, u32 size, struct rmm_addr *rmm_addr_obj = (struct rmm_addr *)dsp_address; bool mem_load_req = false; int status = -ENOMEM; /* Set to fail */ - DBC_REQUIRE(hnode); - DBC_REQUIRE(mem_sect == DBLL_CODE || mem_sect == DBLL_DATA || - mem_sect == DBLL_BSS); nldr_obj = hnode->nldr_obj; rmm = nldr_obj->rmm; /* Convert size to DSP words */ @@ -1736,8 +1694,6 @@ static int remote_free(void **ref, u16 space, u32 dsp_address, u32 word_size; int status = -ENOMEM; /* Set to fail */ - DBC_REQUIRE(nldr_obj); - rmm = nldr_obj->rmm; /* Convert size to DSP words */ @@ -1897,9 +1853,6 @@ int nldr_find_addr(struct nldr_nodeobject *nldr_node, u32 sym_addr, bool status1 = false; s32 i = 0; struct lib_node root = { NULL, 0, NULL }; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(offset_output != NULL); - DBC_REQUIRE(sym_name != NULL); pr_debug("%s(0x%x, 0x%x, 0x%x, 0x%x, %s)\n", __func__, (u32) nldr_node, sym_addr, offset_range, (u32) offset_output, sym_name); diff --git a/drivers/staging/tidspbridge/rmgr/node.c b/drivers/staging/tidspbridge/rmgr/node.c index 5dadaa4..d23d1d0 100644 --- a/drivers/staging/tidspbridge/rmgr/node.c +++ b/drivers/staging/tidspbridge/rmgr/node.c @@ -326,11 +326,6 @@ int node_allocate(struct proc_object *hprocessor, void *node_res; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(hprocessor != NULL); - DBC_REQUIRE(noderes != NULL); - DBC_REQUIRE(node_uuid != NULL); - *noderes = NULL; status = proc_get_processor_id(hprocessor, &proc_id); @@ -673,7 +668,6 @@ func_cont: drv_proc_node_update_heap_status(node_res, true); drv_proc_node_update_status(node_res, true); } - DBC_ENSURE((status && *noderes == NULL) || (!status && *noderes)); func_end: dev_dbg(bridge, "%s: hprocessor: %p pNodeId: %p pargs: %p attr_in: %p " "node_res: %p status: 0x%x\n", __func__, hprocessor, @@ -696,11 +690,6 @@ DBAPI node_alloc_msg_buf(struct node_object *hnode, u32 usize, bool set_info; u32 proc_id; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(pbuffer != NULL); - - DBC_REQUIRE(usize > 0); - if (!pnode) status = -EFAULT; else if (node_get_type(pnode) == NODE_DEVICE) @@ -782,8 +771,6 @@ int node_change_priority(struct node_object *hnode, s32 prio) int status = 0; u32 proc_id; - DBC_REQUIRE(refs > 0); - if (!hnode || !hnode->node_mgr) { status = -EFAULT; } else { @@ -854,7 +841,6 @@ int node_connect(struct node_object *node1, u32 stream1, s8 chnl_mode; u32 dw_length; int status = 0; - DBC_REQUIRE(refs > 0); if (!node1 || !node2) return -EFAULT; @@ -1139,7 +1125,6 @@ int node_create(struct node_object *hnode) omap_dspbridge_dev->dev.platform_data; #endif - DBC_REQUIRE(refs > 0); if (!pnode) { status = -EFAULT; goto func_end; @@ -1291,10 +1276,6 @@ int node_create_mgr(struct node_mgr **node_man, int status = 0; u8 dev_type; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(node_man != NULL); - DBC_REQUIRE(hdev_obj != NULL); - *node_man = NULL; /* Allocate Node manager object */ node_mgr_obj = kzalloc(sizeof(struct node_mgr), GFP_KERNEL); @@ -1375,8 +1356,6 @@ int node_create_mgr(struct node_mgr **node_man, *node_man = node_mgr_obj; - DBC_ENSURE((status && *node_man == NULL) || (!status && *node_man)); - return status; out_err: delete_node_mgr(node_mgr_obj); @@ -1409,7 +1388,6 @@ int node_delete(struct node_res_object *noderes, void *node_res = noderes; struct dsp_processorstate proc_state; - DBC_REQUIRE(refs > 0); if (!pnode) { status = -EFAULT; @@ -1554,8 +1532,6 @@ func_end: */ int node_delete_mgr(struct node_mgr *hnode_mgr) { - DBC_REQUIRE(refs > 0); - if (!hnode_mgr) return -EFAULT; @@ -1576,10 +1552,6 @@ int node_enum_nodes(struct node_mgr *hnode_mgr, void **node_tab, struct node_object *hnode; u32 i = 0; int status = 0; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(node_tab != NULL || node_tab_size == 0); - DBC_REQUIRE(pu_num_nodes != NULL); - DBC_REQUIRE(pu_allocated != NULL); if (!hnode_mgr) { status = -EFAULT; @@ -1611,11 +1583,7 @@ func_end: */ void node_exit(void) { - DBC_REQUIRE(refs > 0); - refs--; - - DBC_ENSURE(refs >= 0); } /* @@ -1629,10 +1597,6 @@ int node_free_msg_buf(struct node_object *hnode, u8 * pbuffer, struct node_object *pnode = (struct node_object *)hnode; int status = 0; u32 proc_id; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(pbuffer != NULL); - DBC_REQUIRE(pnode != NULL); - DBC_REQUIRE(pnode->xlator != NULL); if (!hnode) { status = -EFAULT; @@ -1669,9 +1633,6 @@ int node_get_attr(struct node_object *hnode, struct dsp_nodeattr *pattr, u32 attr_size) { struct node_mgr *hnode_mgr; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(pattr != NULL); - DBC_REQUIRE(attr_size >= sizeof(struct dsp_nodeattr)); if (!hnode) return -EFAULT; @@ -1713,9 +1674,6 @@ int node_get_channel_id(struct node_object *hnode, u32 dir, u32 index, { enum node_type node_type; int status = -EINVAL; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(dir == DSP_TONODE || dir == DSP_FROMNODE); - DBC_REQUIRE(chan_id != NULL); if (!hnode) { status = -EFAULT; @@ -1761,9 +1719,6 @@ int node_get_message(struct node_object *hnode, struct dsp_processorstate proc_state; struct proc_object *hprocessor; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(message != NULL); - if (!hnode) { status = -EFAULT; goto func_end; @@ -1831,14 +1786,12 @@ int node_get_nldr_obj(struct node_mgr *hnode_mgr, { int status = 0; struct node_mgr *node_mgr_obj = hnode_mgr; - DBC_REQUIRE(nldr_ovlyobj != NULL); if (!hnode_mgr) status = -EFAULT; else *nldr_ovlyobj = node_mgr_obj->nldr_obj; - DBC_ENSURE(!status || (nldr_ovlyobj != NULL && *nldr_ovlyobj == NULL)); return status; } @@ -1852,8 +1805,6 @@ int node_get_strm_mgr(struct node_object *hnode, { int status = 0; - DBC_REQUIRE(refs > 0); - if (!hnode) status = -EFAULT; else @@ -1867,8 +1818,6 @@ int node_get_strm_mgr(struct node_object *hnode, */ enum nldr_loadtype node_get_load_type(struct node_object *hnode) { - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(hnode); if (!hnode) { dev_dbg(bridge, "%s: Failed. hnode: %p\n", __func__, hnode); return -1; @@ -1884,8 +1833,6 @@ enum nldr_loadtype node_get_load_type(struct node_object *hnode) */ u32 node_get_timeout(struct node_object *hnode) { - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(hnode); if (!hnode) { dev_dbg(bridge, "%s: failed. hnode: %p\n", __func__, hnode); return 0; @@ -1921,8 +1868,6 @@ enum node_type node_get_type(struct node_object *hnode) */ bool node_init(void) { - DBC_REQUIRE(refs >= 0); - refs++; return true; @@ -1970,8 +1915,6 @@ int node_pause(struct node_object *hnode) struct dsp_processorstate proc_state; struct proc_object *hprocessor; - DBC_REQUIRE(refs > 0); - if (!hnode) { status = -EFAULT; } else { @@ -2054,9 +1997,6 @@ int node_put_message(struct node_object *hnode, struct dsp_processorstate proc_state; struct proc_object *hprocessor; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(pmsg != NULL); - if (!hnode) { status = -EFAULT; goto func_end; @@ -2146,9 +2086,6 @@ int node_register_notify(struct node_object *hnode, u32 event_mask, struct bridge_drv_interface *intf_fxns; int status = 0; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(hnotification != NULL); - if (!hnode) { status = -EFAULT; } else { @@ -2207,8 +2144,6 @@ int node_run(struct node_object *hnode) struct dsp_processorstate proc_state; struct proc_object *hprocessor; - DBC_REQUIRE(refs > 0); - if (!hnode) { status = -EFAULT; goto func_end; @@ -2326,9 +2261,6 @@ int node_terminate(struct node_object *hnode, int *pstatus) struct deh_mgr *hdeh_mgr; struct dsp_processorstate proc_state; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(pstatus != NULL); - if (!hnode || !hnode->node_mgr) { status = -EFAULT; goto func_end; @@ -2748,9 +2680,6 @@ static int get_fxn_address(struct node_object *hnode, u32 * fxn_addr, char *pstr_fxn_name = NULL; struct node_mgr *hnode_mgr = hnode->node_mgr; int status = 0; - DBC_REQUIRE(node_get_type(hnode) == NODE_TASK || - node_get_type(hnode) == NODE_DAISSOCKET || - node_get_type(hnode) == NODE_MESSAGE); switch (phase) { case CREATEPHASE: @@ -2787,9 +2716,6 @@ void get_node_info(struct node_object *hnode, struct dsp_nodeinfo *node_info) { u32 i; - DBC_REQUIRE(hnode); - DBC_REQUIRE(node_info != NULL); - node_info->cb_struct = sizeof(struct dsp_nodeinfo); node_info->nb_node_database_props = hnode->dcd_props.obj_data.node_obj.ndb_props; @@ -2848,7 +2774,6 @@ static int get_node_props(struct dcd_manager *hdcd_mgr, pmsg_args->max_msgs); } else { /* Copy device name */ - DBC_REQUIRE(pndb_props->ac_name); len = strlen(pndb_props->ac_name); DBC_ASSERT(len < MAXDEVNAMELEN); hnode->str_dev_name = kzalloc(len + 1, GFP_KERNEL); @@ -2938,10 +2863,6 @@ int node_get_uuid_props(void *hprocessor, struct dcd_nodeprops dcd_node_props; struct dsp_processorstate proc_state; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(hprocessor != NULL); - DBC_REQUIRE(node_uuid != NULL); - if (hprocessor == NULL || node_uuid == NULL) { status = -EFAULT; goto func_end; @@ -3063,8 +2984,6 @@ static u32 ovly(void *priv_ref, u32 dsp_run_addr, u32 dsp_load_addr, /* Function interface to Bridge driver*/ struct bridge_drv_interface *intf_fxns; - DBC_REQUIRE(hnode); - hnode_mgr = hnode->node_mgr; ul_size = ul_num_bytes / hnode_mgr->dsp_word_size; @@ -3106,9 +3025,6 @@ static u32 mem_write(void *priv_ref, u32 dsp_add, void *pbuf, /* Function interface to Bridge driver */ struct bridge_drv_interface *intf_fxns; - DBC_REQUIRE(hnode); - DBC_REQUIRE(mem_space & DBLL_CODE || mem_space & DBLL_DATA); - hnode_mgr = hnode->node_mgr; ul_timeout = hnode->timeout; diff --git a/drivers/staging/tidspbridge/rmgr/proc.c b/drivers/staging/tidspbridge/rmgr/proc.c index 242dd13..4e2f2e4 100644 --- a/drivers/staging/tidspbridge/rmgr/proc.c +++ b/drivers/staging/tidspbridge/rmgr/proc.c @@ -281,9 +281,6 @@ proc_attach(u32 processor_id, struct drv_data *drv_datap = dev_get_drvdata(bridge); u8 dev_type; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(ph_processor != NULL); - if (pr_ctxt->processor) { *ph_processor = pr_ctxt->processor; return status; @@ -382,10 +379,6 @@ proc_attach(u32 processor_id, kfree(p_proc_object); } func_end: - DBC_ENSURE((status == -EPERM && *ph_processor == NULL) || - (!status && p_proc_object) || - (status == 0 && p_proc_object)); - return status; } @@ -445,10 +438,6 @@ int proc_auto_start(struct cfg_devnode *dev_node_obj, struct drv_data *drv_datap = dev_get_drvdata(bridge); u8 dev_type; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(dev_node_obj != NULL); - DBC_REQUIRE(hdev_obj != NULL); - /* Create a Dummy PROC Object */ if (!drv_datap || !drv_datap->mgr_object) { status = -ENODATA; @@ -516,8 +505,6 @@ int proc_ctrl(void *hprocessor, u32 dw_cmd, struct dsp_cbdata * arg) struct proc_object *p_proc_object = hprocessor; u32 timeout = 0; - DBC_REQUIRE(refs > 0); - if (p_proc_object) { /* intercept PWR deep sleep command */ if (dw_cmd == BRDIOCTL_DEEPSLEEP) { @@ -565,8 +552,6 @@ int proc_detach(struct process_context *pr_ctxt) int status = 0; struct proc_object *p_proc_object = NULL; - DBC_REQUIRE(refs > 0); - p_proc_object = (struct proc_object *)pr_ctxt->processor; if (p_proc_object) { @@ -607,11 +592,6 @@ int proc_enum_nodes(void *hprocessor, void **node_tab, struct proc_object *p_proc_object = (struct proc_object *)hprocessor; struct node_mgr *hnode_mgr = NULL; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(node_tab != NULL || node_tab_size == 0); - DBC_REQUIRE(pu_num_nodes != NULL); - DBC_REQUIRE(pu_allocated != NULL); - if (p_proc_object) { if (!(dev_get_node_manager(p_proc_object->dev_obj, &hnode_mgr))) { @@ -768,8 +748,6 @@ int proc_begin_dma(void *hprocessor, void *pmpu_addr, u32 ul_size, struct process_context *pr_ctxt = (struct process_context *) hprocessor; struct dmm_map_object *map_obj; - DBC_REQUIRE(refs > 0); - if (!pr_ctxt) { status = -EFAULT; goto err_out; @@ -810,8 +788,6 @@ int proc_end_dma(void *hprocessor, void *pmpu_addr, u32 ul_size, struct process_context *pr_ctxt = (struct process_context *) hprocessor; struct dmm_map_object *map_obj; - DBC_REQUIRE(refs > 0); - if (!pr_ctxt) { status = -EFAULT; goto err_out; @@ -884,10 +860,6 @@ int proc_get_resource_info(void *hprocessor, u32 resource_type, struct rmm_target_obj *rmm = NULL; struct io_mgr *hio_mgr = NULL; /* IO manager handle */ - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(resource_info != NULL); - DBC_REQUIRE(resource_info_size >= sizeof(struct dsp_resourceinfo)); - if (!p_proc_object) { status = -EFAULT; goto func_end; @@ -947,11 +919,7 @@ func_end: */ void proc_exit(void) { - DBC_REQUIRE(refs > 0); - refs--; - - DBC_ENSURE(refs >= 0); } /* @@ -966,9 +934,6 @@ int proc_get_dev_object(void *hprocessor, int status = -EPERM; struct proc_object *p_proc_object = (struct proc_object *)hprocessor; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(device_obj != NULL); - if (p_proc_object) { *device_obj = p_proc_object->dev_obj; status = 0; @@ -977,9 +942,6 @@ int proc_get_dev_object(void *hprocessor, status = -EFAULT; } - DBC_ENSURE((!status && *device_obj != NULL) || - (status && *device_obj == NULL)); - return status; } @@ -996,10 +958,6 @@ int proc_get_state(void *hprocessor, struct proc_object *p_proc_object = (struct proc_object *)hprocessor; int brd_status; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(proc_state_obj != NULL); - DBC_REQUIRE(state_info_size >= sizeof(struct dsp_processorstate)); - if (p_proc_object) { /* First, retrieve BRD state information */ status = (*p_proc_object->intf_fxns->brd_status) @@ -1063,13 +1021,9 @@ bool proc_init(void) { bool ret = true; - DBC_REQUIRE(refs >= 0); - if (ret) refs++; - DBC_ENSURE((ret && (refs > 0)) || (!ret && (refs >= 0))); - return ret; } @@ -1111,10 +1065,6 @@ int proc_load(void *hprocessor, const s32 argc_index, omap_dspbridge_dev->dev.platform_data; #endif - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(argc_index > 0); - DBC_REQUIRE(user_args != NULL); - #ifdef OPT_LOAD_TIME_INSTRUMENTATION do_gettimeofday(&tv1); #endif @@ -1331,9 +1281,6 @@ func_end: pr_err("%s: Processor failed to load\n", __func__); proc_stop(p_proc_object); } - DBC_ENSURE((!status - && p_proc_object->proc_state == PROC_LOADED) - || status); #ifdef OPT_LOAD_TIME_INSTRUMENTATION do_gettimeofday(&tv2); if (tv2.tv_usec < tv1.tv_usec) { @@ -1443,9 +1390,6 @@ int proc_register_notify(void *hprocessor, u32 event_mask, struct proc_object *p_proc_object = (struct proc_object *)hprocessor; struct deh_mgr *hdeh_mgr; - DBC_REQUIRE(hnotification != NULL); - DBC_REQUIRE(refs > 0); - /* Check processor handle */ if (!p_proc_object) { status = -EFAULT; @@ -1567,7 +1511,6 @@ int proc_start(void *hprocessor) u32 dw_dsp_addr; /* Loaded code's entry point. */ int brd_state; - DBC_REQUIRE(refs > 0); if (!p_proc_object) { status = -EFAULT; goto func_end; @@ -1624,8 +1567,6 @@ func_cont: } func_end: - DBC_ENSURE((!status && p_proc_object->proc_state == - PROC_RUNNING) || status); return status; } @@ -1646,7 +1587,6 @@ int proc_stop(void *hprocessor) u32 nodes_allocated = 0; int brd_state; - DBC_REQUIRE(refs > 0); if (!p_proc_object) { status = -EFAULT; goto func_end; @@ -1822,9 +1762,6 @@ static int proc_monitor(struct proc_object *proc_obj) struct msg_mgr *hmsg_mgr; int brd_state; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(proc_obj); - /* This is needed only when Device is loaded when it is * already 'ACTIVE' */ /* Destroy the Node Manager, msg_ctrl Manager */ @@ -1845,8 +1782,6 @@ static int proc_monitor(struct proc_object *proc_obj) DBC_ASSERT(brd_state == BRD_IDLE); } - DBC_ENSURE((!status && brd_state == BRD_IDLE) || - status); return status; } @@ -1880,8 +1815,6 @@ static char **prepend_envp(char **new_envp, char **envp, s32 envp_elems, { char **pp_envp = new_envp; - DBC_REQUIRE(new_envp); - /* Prepend new environ var=value string */ *new_envp++ = sz_var; @@ -1906,9 +1839,6 @@ int proc_notify_clients(void *proc, u32 events) int status = 0; struct proc_object *p_proc_object = (struct proc_object *)proc; - DBC_REQUIRE(p_proc_object); - DBC_REQUIRE(is_valid_proc_event(events)); - DBC_REQUIRE(refs > 0); if (!p_proc_object) { status = -EFAULT; goto func_end; @@ -1930,9 +1860,6 @@ int proc_notify_all_clients(void *proc, u32 events) int status = 0; struct proc_object *p_proc_object = (struct proc_object *)proc; - DBC_REQUIRE(is_valid_proc_event(events)); - DBC_REQUIRE(refs > 0); - if (!p_proc_object) { status = -EFAULT; goto func_end; diff --git a/drivers/staging/tidspbridge/rmgr/rmm.c b/drivers/staging/tidspbridge/rmgr/rmm.c index f3dc0dd..6b41049 100644 --- a/drivers/staging/tidspbridge/rmgr/rmm.c +++ b/drivers/staging/tidspbridge/rmgr/rmm.c @@ -101,12 +101,6 @@ int rmm_alloc(struct rmm_target_obj *target, u32 segid, u32 size, u32 addr; int status = 0; - DBC_REQUIRE(target); - DBC_REQUIRE(dsp_address != NULL); - DBC_REQUIRE(size > 0); - DBC_REQUIRE(reserve || (target->num_segs > 0)); - DBC_REQUIRE(refs > 0); - if (!reserve) { if (!alloc_block(target, segid, size, align, dsp_address)) { status = -ENOMEM; @@ -170,9 +164,6 @@ int rmm_create(struct rmm_target_obj **target_obj, s32 i; int status = 0; - DBC_REQUIRE(target_obj != NULL); - DBC_REQUIRE(num_segs == 0 || seg_tab != NULL); - /* Allocate DBL target object */ target = kzalloc(sizeof(struct rmm_target_obj), GFP_KERNEL); @@ -235,9 +226,6 @@ func_cont: } - DBC_ENSURE((!status && *target_obj) - || (status && *target_obj == NULL)); - return status; } @@ -251,8 +239,6 @@ void rmm_delete(struct rmm_target_obj *target) struct rmm_header *next; u32 i; - DBC_REQUIRE(target); - kfree(target->seg_tab); list_for_each_entry_safe(sect, tmp, &target->ovly_list, list_elem) { @@ -281,11 +267,7 @@ void rmm_delete(struct rmm_target_obj *target) */ void rmm_exit(void) { - DBC_REQUIRE(refs > 0); - refs--; - - DBC_ENSURE(refs >= 0); } /* @@ -297,15 +279,6 @@ bool rmm_free(struct rmm_target_obj *target, u32 segid, u32 dsp_addr, u32 size, struct rmm_ovly_sect *sect, *tmp; bool ret = false; - DBC_REQUIRE(target); - - DBC_REQUIRE(reserved || segid < target->num_segs); - DBC_REQUIRE(reserved || (dsp_addr >= target->seg_tab[segid].base && - (dsp_addr + size) <= (target->seg_tab[segid]. - base + - target->seg_tab[segid]. - length))); - /* * Free or unreserve memory. */ @@ -335,8 +308,6 @@ bool rmm_free(struct rmm_target_obj *target, u32 segid, u32 dsp_addr, u32 size, */ bool rmm_init(void) { - DBC_REQUIRE(refs >= 0); - refs++; return true; @@ -354,7 +325,6 @@ bool rmm_stat(struct rmm_target_obj *target, enum dsp_memtype segid, u32 total_free_size = 0; u32 free_blocks = 0; - DBC_REQUIRE(mem_stat_buf != NULL); DBC_ASSERT(target != NULL); if ((u32) segid < target->num_segs) { diff --git a/drivers/staging/tidspbridge/rmgr/strm.c b/drivers/staging/tidspbridge/rmgr/strm.c index 3fae0e9..8e2d649 100644 --- a/drivers/staging/tidspbridge/rmgr/strm.c +++ b/drivers/staging/tidspbridge/rmgr/strm.c @@ -104,9 +104,6 @@ int strm_allocate_buffer(struct strm_res_object *strmres, u32 usize, u32 i; struct strm_object *stream_obj = strmres->stream; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(ap_buffer != NULL); - if (stream_obj) { /* * Allocate from segment specified at time of stream open. @@ -156,8 +153,6 @@ int strm_close(struct strm_res_object *strmres, int status = 0; struct strm_object *stream_obj = strmres->stream; - DBC_REQUIRE(refs > 0); - if (!stream_obj) { status = -EFAULT; } else { @@ -180,9 +175,6 @@ int strm_close(struct strm_res_object *strmres, idr_remove(pr_ctxt->stream_id, strmres->id); func_end: - DBC_ENSURE(status == 0 || status == -EFAULT || - status == -EPIPE || status == -EPERM); - dev_dbg(bridge, "%s: stream_obj: %p, status 0x%x\n", __func__, stream_obj, status); return status; @@ -199,10 +191,6 @@ int strm_create(struct strm_mgr **strm_man, struct strm_mgr *strm_mgr_obj; int status = 0; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(strm_man != NULL); - DBC_REQUIRE(dev_obj != NULL); - *strm_man = NULL; /* Allocate STRM manager object */ strm_mgr_obj = kzalloc(sizeof(struct strm_mgr), GFP_KERNEL); @@ -226,8 +214,6 @@ int strm_create(struct strm_mgr **strm_man, else kfree(strm_mgr_obj); - DBC_ENSURE((!status && *strm_man) || (status && *strm_man == NULL)); - return status; } @@ -238,9 +224,6 @@ int strm_create(struct strm_mgr **strm_man, */ void strm_delete(struct strm_mgr *strm_mgr_obj) { - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(strm_mgr_obj); - kfree(strm_mgr_obj); } @@ -251,11 +234,7 @@ void strm_delete(struct strm_mgr *strm_mgr_obj) */ void strm_exit(void) { - DBC_REQUIRE(refs > 0); - refs--; - - DBC_ENSURE(refs >= 0); } /* @@ -270,9 +249,6 @@ int strm_free_buffer(struct strm_res_object *strmres, u8 ** ap_buffer, u32 i = 0; struct strm_object *stream_obj = strmres->stream; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(ap_buffer != NULL); - if (!stream_obj) status = -EFAULT; @@ -306,10 +282,6 @@ int strm_get_info(struct strm_object *stream_obj, int status = 0; void *virt_base = NULL; /* NULL if no SM used */ - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(stream_info != NULL); - DBC_REQUIRE(stream_info_size >= sizeof(struct stream_info)); - if (!stream_obj) { status = -EFAULT; } else { @@ -370,8 +342,6 @@ int strm_idle(struct strm_object *stream_obj, bool flush_data) struct bridge_drv_interface *intf_fxns; int status = 0; - DBC_REQUIRE(refs > 0); - if (!stream_obj) { status = -EFAULT; } else { @@ -396,13 +366,9 @@ bool strm_init(void) { bool ret = true; - DBC_REQUIRE(refs >= 0); - if (ret) refs++; - DBC_ENSURE((ret && (refs > 0)) || (!ret && (refs >= 0))); - return ret; } @@ -418,9 +384,6 @@ int strm_issue(struct strm_object *stream_obj, u8 *pbuf, u32 ul_bytes, int status = 0; void *tmp_buf = NULL; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(pbuf != NULL); - if (!stream_obj) { status = -EFAULT; } else { @@ -471,9 +434,6 @@ int strm_open(struct node_object *hnode, u32 dir, u32 index, void *stream_res; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(strmres != NULL); - DBC_REQUIRE(pattr != NULL); *strmres = NULL; if (dir != DSP_TONODE && dir != DSP_FROMNODE) { status = -EPERM; @@ -594,12 +554,6 @@ func_cont: (void)delete_strm(strm_obj); } - /* ensure we return a documented error code */ - DBC_ENSURE((!status && strm_obj) || - (*strmres == NULL && (status == -EFAULT || - status == -EPERM - || status == -EINVAL))); - dev_dbg(bridge, "%s: hnode: %p dir: 0x%x index: 0x%x pattr: %p " "strmres: %p status: 0x%x\n", __func__, hnode, dir, index, pattr, strmres, status); @@ -619,11 +573,6 @@ int strm_reclaim(struct strm_object *stream_obj, u8 ** buf_ptr, int status = 0; void *tmp_buf = NULL; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(buf_ptr != NULL); - DBC_REQUIRE(nbytes != NULL); - DBC_REQUIRE(pdw_arg != NULL); - if (!stream_obj) { status = -EFAULT; goto func_end; @@ -679,11 +628,6 @@ int strm_reclaim(struct strm_object *stream_obj, u8 ** buf_ptr, *buf_ptr = chnl_ioc_obj.buf; } func_end: - /* ensure we return a documented return code */ - DBC_ENSURE(!status || status == -EFAULT || - status == -ETIME || status == -ESRCH || - status == -EPERM); - dev_dbg(bridge, "%s: stream_obj: %p buf_ptr: %p nbytes: %p " "pdw_arg: %p status 0x%x\n", __func__, stream_obj, buf_ptr, nbytes, pdw_arg, status); @@ -702,9 +646,6 @@ int strm_register_notify(struct strm_object *stream_obj, u32 event_mask, struct bridge_drv_interface *intf_fxns; int status = 0; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(hnotification != NULL); - if (!stream_obj) { status = -EFAULT; } else if ((event_mask & ~((DSP_STREAMIOCOMPLETION) | @@ -725,10 +666,7 @@ int strm_register_notify(struct strm_object *stream_obj, u32 event_mask, notify_type, hnotification); } - /* ensure we return a documented return code */ - DBC_ENSURE(!status || status == -EFAULT || - status == -ETIME || status == -ESRCH || - status == -ENOSYS || status == -EPERM); + return status; } @@ -747,11 +685,6 @@ int strm_select(struct strm_object **strm_tab, u32 strms, u32 i; int status = 0; - DBC_REQUIRE(refs > 0); - DBC_REQUIRE(strm_tab != NULL); - DBC_REQUIRE(pmask != NULL); - DBC_REQUIRE(strms > 0); - *pmask = 0; for (i = 0; i < strms; i++) { if (!strm_tab[i]) { @@ -811,9 +744,6 @@ int strm_select(struct strm_object **strm_tab, u32 strms, func_end: kfree(sync_events); - DBC_ENSURE((!status && (*pmask != 0 || utimeout == 0)) || - (status && *pmask == 0)); - return status; } -- cgit v0.10.2 From 40e6336d1bdc10f072b6563dfb1255b5c4b039a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Manuel=20J=C3=A1quez=20Leal?= Date: Tue, 7 Feb 2012 00:39:35 +0100 Subject: staging: tidspbridge: remove DBC_ASSERT macro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This macro is only valid when CONFIG_TIDSPBRDIGE_DEBUG is enabled and it only prints a log message, it is not a real assertion mechanism like BUG_ON() or WARN_ON(). It is better to remove them: less code to maintain. Signed-off-by: Víctor Manuel Jáquez Leal Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/tidspbridge/core/chnl_sm.c b/drivers/staging/tidspbridge/core/chnl_sm.c index 91daf25..3136e8d 100644 --- a/drivers/staging/tidspbridge/core/chnl_sm.c +++ b/drivers/staging/tidspbridge/core/chnl_sm.c @@ -123,7 +123,6 @@ int bridge_chnl_add_io_req(struct chnl_object *chnl_obj, void *host_buf, CHNL_IS_OUTPUT(pchnl->chnl_mode)) return -EPIPE; /* No other possible states left */ - DBC_ASSERT(0); } dev_obj = dev_get_first(); @@ -190,7 +189,6 @@ func_cont: * Note: for dma chans dw_dsp_addr contains dsp address * of SM buffer. */ - DBC_ASSERT(chnl_mgr_obj->word_size != 0); /* DSP address */ chnl_packet_obj->dsp_tx_addr = dw_dsp_addr / chnl_mgr_obj->word_size; chnl_packet_obj->byte_size = byte_size; @@ -201,7 +199,6 @@ func_cont: CHNL_IOCSTATCOMPLETE); list_add_tail(&chnl_packet_obj->link, &pchnl->io_requests); pchnl->cio_reqs++; - DBC_ASSERT(pchnl->cio_reqs <= pchnl->chnl_packets); /* * If end of stream, update the channel state to prevent * more IOR's. @@ -209,8 +206,6 @@ func_cont: if (is_eos) pchnl->state |= CHNL_STATEEOS; - /* Legacy DSM Processor-Copy */ - DBC_ASSERT(pchnl->chnl_type == CHNL_PCPY); /* Request IO from the DSP */ io_request_chnl(chnl_mgr_obj->iomgr, pchnl, (CHNL_IS_INPUT(pchnl->chnl_mode) ? IO_INPUT : @@ -283,7 +278,6 @@ int bridge_chnl_cancel_io(struct chnl_object *chnl_obj) list_add_tail(&chirp->link, &pchnl->io_completions); pchnl->cio_cs++; pchnl->cio_reqs--; - DBC_ASSERT(pchnl->cio_reqs >= 0); } spin_unlock_bh(&chnl_mgr_obj->chnl_mgr_lock); @@ -311,8 +305,6 @@ int bridge_chnl_close(struct chnl_object *chnl_obj) status = bridge_chnl_cancel_io(chnl_obj); if (status) return status; - /* Assert I/O on this channel is now cancelled: Protects from io_dpc */ - DBC_ASSERT((pchnl->state & CHNL_STATECANCEL)); /* Invalidate channel object: Protects from CHNL_GetIOCompletion() */ /* Free the slot in the channel manager: */ pchnl->chnl_mgr_obj->channels[pchnl->chnl_id] = NULL; @@ -367,7 +359,6 @@ int bridge_chnl_create(struct chnl_mgr **channel_mgr, * mgr_attrts->max_channels = CHNL_MAXCHANNELS = * DDMA_MAXDDMACHNLS = DDMA_MAXZCPYCHNLS. */ - DBC_ASSERT(mgr_attrts->max_channels == CHNL_MAXCHANNELS); max_channels = CHNL_MAXCHANNELS + CHNL_MAXCHANNELS * CHNL_PCPY; /* Create array of channels */ chnl_mgr_obj->channels = kzalloc(sizeof(struct chnl_object *) @@ -584,7 +575,6 @@ int bridge_chnl_get_ioc(struct chnl_object *chnl_obj, u32 timeout, omap_mbox_disable_irq(dev_ctxt->mbox, IRQ_RX); if (dequeue_ioc) { /* Dequeue IOC and set chan_ioc; */ - DBC_ASSERT(!list_empty(&pchnl->io_completions)); chnl_packet_obj = list_first_entry(&pchnl->io_completions, struct chnl_irp, link); list_del(&chnl_packet_obj->link); @@ -748,7 +738,6 @@ int bridge_chnl_open(struct chnl_object **chnl, return status; } - DBC_ASSERT(ch_id < chnl_mgr_obj->max_channels); /* Create channel object: */ pchnl = kzalloc(sizeof(struct chnl_object), GFP_KERNEL); @@ -837,7 +826,6 @@ int bridge_chnl_register_notify(struct chnl_object *chnl_obj, { int status = 0; - DBC_ASSERT(!(event_mask & ~(DSP_STREAMDONE | DSP_STREAMIOCOMPLETION))); if (event_mask) status = ntfy_register(chnl_obj->ntfy_obj, hnotification, diff --git a/drivers/staging/tidspbridge/core/io_sm.c b/drivers/staging/tidspbridge/core/io_sm.c index 694c0e5..0930a98 100644 --- a/drivers/staging/tidspbridge/core/io_sm.c +++ b/drivers/staging/tidspbridge/core/io_sm.c @@ -973,29 +973,16 @@ void io_request_chnl(struct io_mgr *io_manager, struct chnl_object *pchnl, chnl_mgr_obj = io_manager->chnl_mgr; sm = io_manager->shared_mem; if (io_mode == IO_INPUT) { - /* - * Assertion fires if CHNL_AddIOReq() called on a stream - * which was cancelled, or attached to a dead board. - */ - DBC_ASSERT((pchnl->state == CHNL_STATEREADY) || - (pchnl->state == CHNL_STATEEOS)); /* Indicate to the DSP we have a buffer available for input */ set_chnl_busy(sm, pchnl->chnl_id); *mbx_val = MBX_PCPY_CLASS; } else if (io_mode == IO_OUTPUT) { /* - * This assertion fails if CHNL_AddIOReq() was called on a - * stream which was cancelled, or attached to a dead board. - */ - DBC_ASSERT((pchnl->state & ~CHNL_STATEEOS) == - CHNL_STATEREADY); - /* * Record the fact that we have a buffer available for * output. */ chnl_mgr_obj->output_mask |= (1 << pchnl->chnl_id); } else { - DBC_ASSERT(io_mode); /* Shouldn't get here. */ } func_end: return; @@ -1087,7 +1074,6 @@ static void input_chnl(struct io_mgr *pio_mgr, struct chnl_object *pchnl, dw_arg = sm->arg; if (chnl_id >= CHNL_MAXCHANNELS) { /* Shouldn't be here: would indicate corrupted shm. */ - DBC_ASSERT(chnl_id); goto func_end; } pchnl = chnl_mgr_obj->channels[chnl_id]; diff --git a/drivers/staging/tidspbridge/core/tiomap3430.c b/drivers/staging/tidspbridge/core/tiomap3430.c index 212cbc9..c3efc2e 100644 --- a/drivers/staging/tidspbridge/core/tiomap3430.c +++ b/drivers/staging/tidspbridge/core/tiomap3430.c @@ -396,16 +396,13 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt, (void)dev_get_symbol(dev_context->dev_obj, SHMBASENAME, &ul_shm_base_virt); ul_shm_base_virt *= DSPWORDSIZE; - DBC_ASSERT(ul_shm_base_virt != 0); /* DSP Virtual address */ ul_tlb_base_virt = dev_context->atlb_entry[0].dsp_va; - DBC_ASSERT(ul_tlb_base_virt <= ul_shm_base_virt); ul_shm_offset_virt = ul_shm_base_virt - (ul_tlb_base_virt * DSPWORDSIZE); /* Kernel logical address */ ul_shm_base = dev_context->atlb_entry[0].gpp_va + ul_shm_offset_virt; - DBC_ASSERT(ul_shm_base != 0); /* 2nd wd is used as sync field */ dw_sync_addr = ul_shm_base + SHMSYNCOFFSET; /* Write a signature into the shm base + offset; this will diff --git a/drivers/staging/tidspbridge/core/tiomap3430_pwr.c b/drivers/staging/tidspbridge/core/tiomap3430_pwr.c index 02dd439..16a4aaf 100644 --- a/drivers/staging/tidspbridge/core/tiomap3430_pwr.c +++ b/drivers/staging/tidspbridge/core/tiomap3430_pwr.c @@ -303,7 +303,6 @@ int dsp_peripheral_clk_ctrl(struct bridge_dev_context *dev_context, } /* TODO -- Assert may be a too hard restriction here.. May be we should * just return with failure when the CLK ID does not match */ - /* DBC_ASSERT(clk_id_index < MBX_PM_MAX_RESOURCES); */ if (clk_id_index == MBX_PM_MAX_RESOURCES) { /* return with a more meaningfull error code */ return -EPERM; diff --git a/drivers/staging/tidspbridge/core/tiomap_io.c b/drivers/staging/tidspbridge/core/tiomap_io.c index dfb356e..9c18873 100644 --- a/drivers/staging/tidspbridge/core/tiomap_io.c +++ b/drivers/staging/tidspbridge/core/tiomap_io.c @@ -68,20 +68,17 @@ int read_ext_dsp_data(struct bridge_dev_context *dev_ctxt, status = dev_get_symbol(dev_context->dev_obj, SHMBASENAME, &ul_shm_base_virt); } - DBC_ASSERT(ul_shm_base_virt != 0); /* Check if it is a read of Trace section */ if (!status && !ul_trace_sec_beg) { status = dev_get_symbol(dev_context->dev_obj, DSP_TRACESEC_BEG, &ul_trace_sec_beg); } - DBC_ASSERT(ul_trace_sec_beg != 0); if (!status && !ul_trace_sec_end) { status = dev_get_symbol(dev_context->dev_obj, DSP_TRACESEC_END, &ul_trace_sec_end); } - DBC_ASSERT(ul_trace_sec_end != 0); if (!status) { if ((dsp_addr <= ul_trace_sec_end) && @@ -105,19 +102,16 @@ int read_ext_dsp_data(struct bridge_dev_context *dev_ctxt, status = dev_get_symbol(dev_context->dev_obj, DYNEXTBASE, &ul_dyn_ext_base); } - DBC_ASSERT(ul_dyn_ext_base != 0); if (!status) { status = dev_get_symbol(dev_context->dev_obj, EXTBASE, &ul_ext_base); } - DBC_ASSERT(ul_ext_base != 0); if (!status) { status = dev_get_symbol(dev_context->dev_obj, EXTEND, &ul_ext_end); } - DBC_ASSERT(ul_ext_end != 0); /* Trace buffer is right after the shm SEG0, * so set the base address to SHMBASE */ @@ -126,8 +120,6 @@ int read_ext_dsp_data(struct bridge_dev_context *dev_ctxt, ul_ext_end = ul_trace_sec_end; } - DBC_ASSERT(ul_ext_end != 0); - DBC_ASSERT(ul_ext_end > ul_ext_base); if (ul_ext_end < ul_ext_base) status = -EPERM; @@ -135,7 +127,6 @@ int read_ext_dsp_data(struct bridge_dev_context *dev_ctxt, if (!status) { ul_tlb_base_virt = dev_context->atlb_entry[0].dsp_va * DSPWORDSIZE; - DBC_ASSERT(ul_tlb_base_virt <= ul_shm_base_virt); dw_ext_prog_virt_mem = dev_context->atlb_entry[0].gpp_va; @@ -271,7 +262,6 @@ int write_ext_dsp_data(struct bridge_dev_context *dev_context, /* Get SHM_BEG EXT_BEG and EXT_END. */ ret = dev_get_symbol(dev_context->dev_obj, SHMBASENAME, &ul_shm_base_virt); - DBC_ASSERT(ul_shm_base_virt != 0); if (dynamic_load) { if (!ret) { if (symbols_reloaded) @@ -280,7 +270,6 @@ int write_ext_dsp_data(struct bridge_dev_context *dev_context, (dev_context->dev_obj, DYNEXTBASE, &ul_ext_base); } - DBC_ASSERT(ul_ext_base != 0); if (!ret) { /* DR OMAPS00013235 : DLModules array may be * in EXTMEM. It is expected that DYNEXTMEM and @@ -299,7 +288,6 @@ int write_ext_dsp_data(struct bridge_dev_context *dev_context, dev_get_symbol (dev_context->dev_obj, EXTBASE, &ul_ext_base); - DBC_ASSERT(ul_ext_base != 0); if (!ret) ret = dev_get_symbol @@ -312,15 +300,12 @@ int write_ext_dsp_data(struct bridge_dev_context *dev_context, if (trace_load) ul_ext_base = ul_shm_base_virt; - DBC_ASSERT(ul_ext_end != 0); - DBC_ASSERT(ul_ext_end > ul_ext_base); if (ul_ext_end < ul_ext_base) ret = -EPERM; if (!ret) { ul_tlb_base_virt = dev_context->atlb_entry[0].dsp_va * DSPWORDSIZE; - DBC_ASSERT(ul_tlb_base_virt <= ul_shm_base_virt); if (symbols_reloaded) { ret = dev_get_symbol diff --git a/drivers/staging/tidspbridge/include/dspbridge/dbc.h b/drivers/staging/tidspbridge/include/dspbridge/dbc.h index dc88f34..90c45f6 100644 --- a/drivers/staging/tidspbridge/include/dspbridge/dbc.h +++ b/drivers/staging/tidspbridge/include/dspbridge/dbc.h @@ -25,15 +25,4 @@ #ifndef DBC_ #define DBC_ -/* Assertion Macros: */ -#ifdef CONFIG_TIDSPBRIDGE_DEBUG - -#define DBC_ASSERT(exp) \ - if (!(exp)) \ - pr_err("%s, line %d: Assertion (" #exp ") failed.\n", \ - __FILE__, __LINE__) -#else -#define DBC_ASSERT(exp) {} -#endif /* DEBUG */ - #endif /* DBC_ */ diff --git a/drivers/staging/tidspbridge/pmgr/cmm.c b/drivers/staging/tidspbridge/pmgr/cmm.c index 2eeb5370..0d19bcd 100644 --- a/drivers/staging/tidspbridge/pmgr/cmm.c +++ b/drivers/staging/tidspbridge/pmgr/cmm.c @@ -253,8 +253,6 @@ int cmm_create(struct cmm_object **ph_cmm_mgr, if (mgr_attrts == NULL) mgr_attrts = &cmm_dfltmgrattrs; /* set defaults */ - /* 4 bytes minimum */ - DBC_ASSERT(mgr_attrts->min_block_size >= 4); /* save away smallest block allocation for this cmm mgr */ cmm_obj->min_block_size = mgr_attrts->min_block_size; cmm_obj->page_size = PAGE_SIZE; @@ -849,7 +847,8 @@ int cmm_xlator_free_buf(struct cmm_xlatorobject *xlator, void *buf_va) if (status) { /* Uh oh, this shouldn't happen. Descriptor * gone! */ - DBC_ASSERT(false); /* CMM is leaking mem */ + pr_err("%s, line %d: Assertion failed\n", + __FILE__, __LINE__); } } } @@ -898,7 +897,6 @@ void *cmm_xlator_translate(struct cmm_xlatorobject *xlator, void *paddr, cmm_mgr_obj = (struct cmm_object *)xlator_obj->cmm_mgr; /* get this translator's default SM allocator */ - DBC_ASSERT(xlator_obj->seg_id > 0); allocator = cmm_mgr_obj->pa_gppsm_seg_tab[xlator_obj->seg_id - 1]; if (!allocator) goto loop_cont; diff --git a/drivers/staging/tidspbridge/pmgr/dbll.c b/drivers/staging/tidspbridge/pmgr/dbll.c index db1af79..997feeb 100644 --- a/drivers/staging/tidspbridge/pmgr/dbll.c +++ b/drivers/staging/tidspbridge/pmgr/dbll.c @@ -936,9 +936,6 @@ static struct dynload_symbol *dbll_find_symbol(struct dynamic_loader_sym *this, if (!status && gbl_search) dev_dbg(bridge, "%s: Symbol not found: %s\n", __func__, name); - DBC_ASSERT((status && (dbll_sym != NULL)) - || (!status && (dbll_sym == NULL))); - ret_sym = (struct dynload_symbol *)dbll_sym; return ret_sym; } diff --git a/drivers/staging/tidspbridge/pmgr/dev.c b/drivers/staging/tidspbridge/pmgr/dev.c index e4257fd..980bd53 100644 --- a/drivers/staging/tidspbridge/pmgr/dev.c +++ b/drivers/staging/tidspbridge/pmgr/dev.c @@ -108,7 +108,6 @@ u32 dev_brd_write_fxn(void *arb, u32 dsp_add, void *host_buf, if (dev_obj) { /* Require of BrdWrite() */ - DBC_ASSERT(dev_obj->bridge_context != NULL); status = (*dev_obj->bridge_interface.brd_write) ( dev_obj->bridge_context, host_buf, dsp_add, ul_num_bytes, mem_space); @@ -164,7 +163,6 @@ int dev_create_device(struct dev_object **device_obj, /* Create the device object, and pass a handle to the Bridge driver for * storage. */ if (!status) { - DBC_ASSERT(drv_fxns); dev_obj = kzalloc(sizeof(struct dev_object), GFP_KERNEL); if (dev_obj) { /* Fill out the rest of the Dev Object structure: */ @@ -186,9 +184,6 @@ int dev_create_device(struct dev_object **device_obj, status = (dev_obj->bridge_interface.dev_create) (&dev_obj->bridge_context, dev_obj, host_res); - /* Assert bridge_dev_create()'s ensure clause: */ - DBC_ASSERT(status - || (dev_obj->bridge_context != NULL)); } else { status = -ENOMEM; } @@ -282,7 +277,6 @@ int dev_create2(struct dev_object *hdev_obj) struct dev_object *dev_obj = hdev_obj; /* There can be only one Node Manager per DEV object */ - DBC_ASSERT(!dev_obj->node_mgr); status = node_create_mgr(&dev_obj->node_mgr, hdev_obj); if (status) dev_obj->node_mgr = NULL; diff --git a/drivers/staging/tidspbridge/rmgr/dbdcd.c b/drivers/staging/tidspbridge/rmgr/dbdcd.c index 792b443..18109fc 100644 --- a/drivers/staging/tidspbridge/rmgr/dbdcd.c +++ b/drivers/staging/tidspbridge/rmgr/dbdcd.c @@ -206,7 +206,6 @@ int dcd_enumerate_object(s32 index, enum dsp_dcdobjtype obj_type, * "_\0" + length of sz_obj_type string + terminating NULL. */ dw_key_len = strlen(DCD_REGKEY) + 1 + sizeof(sz_obj_type) + 1; - DBC_ASSERT(dw_key_len < DCD_MAXPATHLENGTH); /* Create proper REG key; concatenate DCD_REGKEY with * obj_type. */ @@ -375,7 +374,6 @@ int dcd_get_object_def(struct dcd_manager *hdcd_mgr, /* Pre-determine final key length. It's length of DCD_REGKEY + * "_\0" + length of sz_obj_type string + terminating NULL */ dw_key_len = strlen(DCD_REGKEY) + 1 + sizeof(sz_obj_type) + 1; - DBC_ASSERT(dw_key_len < DCD_MAXPATHLENGTH); /* Create proper REG key; concatenate DCD_REGKEY with obj_type. */ strncpy(sz_reg_key, DCD_REGKEY, strlen(DCD_REGKEY) + 1); @@ -434,7 +432,6 @@ int dcd_get_object_def(struct dcd_manager *hdcd_mgr, } /* Ensure sz_uuid + 1 is not greater than sizeof sz_sect_name. */ - DBC_ASSERT((strlen(sz_uuid) + 1) < sizeof(sz_sect_name)); /* Create section name based on node UUID. A period is * pre-pended to the UUID string to form the section name. @@ -635,7 +632,6 @@ int dcd_get_library_name(struct dcd_manager *hdcd_mgr, * "_\0" + length of sz_obj_type string + terminating NULL. */ dw_key_len = strlen(DCD_REGKEY) + 1 + sizeof(sz_obj_type) + 1; - DBC_ASSERT(dw_key_len < DCD_MAXPATHLENGTH); /* Create proper REG key; concatenate DCD_REGKEY with obj_type. */ strncpy(sz_reg_key, DCD_REGKEY, strlen(DCD_REGKEY) + 1); @@ -663,7 +659,6 @@ int dcd_get_library_name(struct dcd_manager *hdcd_mgr, break; default: status = -EINVAL; - DBC_ASSERT(false); } if (!status) { if ((strlen(sz_reg_key) + strlen(sz_obj_type)) < @@ -794,7 +789,6 @@ int dcd_register_object(struct dsp_uuid *uuid_obj, * "_\0" + length of sz_obj_type string + terminating NULL. */ dw_key_len = strlen(DCD_REGKEY) + 1 + sizeof(sz_obj_type) + 1; - DBC_ASSERT(dw_key_len < DCD_MAXPATHLENGTH); /* Create proper REG key; concatenate DCD_REGKEY with obj_type. */ strncpy(sz_reg_key, DCD_REGKEY, strlen(DCD_REGKEY) + 1); diff --git a/drivers/staging/tidspbridge/rmgr/disp.c b/drivers/staging/tidspbridge/rmgr/disp.c index 04c88a7d..63fdf1e 100644 --- a/drivers/staging/tidspbridge/rmgr/disp.c +++ b/drivers/staging/tidspbridge/rmgr/disp.c @@ -268,7 +268,6 @@ int disp_node_create(struct disp_object *disp_obj, node_type = node_get_type(hnode); node_msg_args = pargs->asa.node_msg_args; max = disp_obj->bufsize_rms; /*Max # of RMS words that can be sent */ - DBC_ASSERT(max == RMS_COMMANDBUFSIZE); chars_in_rms_word = sizeof(rms_word) / disp_obj->char_size; /* Number of RMS words needed to hold arg data */ dw_length = @@ -429,7 +428,6 @@ int disp_node_create(struct disp_object *disp_obj, } if (!status) { ul_bytes = total * sizeof(rms_word); - DBC_ASSERT(ul_bytes < (RMS_COMMANDBUFSIZE * sizeof(rms_word))); status = send_message(disp_obj, node_get_timeout(hnode), ul_bytes, node_env); } @@ -665,7 +663,6 @@ static int send_message(struct disp_object *disp_obj, u32 timeout, status = -EPERM; } else { if (CHNL_IS_IO_COMPLETE(chnl_ioc_obj)) { - DBC_ASSERT(chnl_ioc_obj.buf == pbuf); if (*((int *)chnl_ioc_obj.buf) < 0) { /* Translate DSP's to kernel error */ status = -EREMOTEIO; diff --git a/drivers/staging/tidspbridge/rmgr/drv.c b/drivers/staging/tidspbridge/rmgr/drv.c index f3bff1b..cd93c12 100644 --- a/drivers/staging/tidspbridge/rmgr/drv.c +++ b/drivers/staging/tidspbridge/rmgr/drv.c @@ -172,7 +172,6 @@ void drv_proc_node_update_status(void *node_resource, s32 status) { struct node_res_object *node_res_obj = (struct node_res_object *)node_resource; - DBC_ASSERT(node_resource != NULL); node_res_obj->node_allocated = status; } @@ -181,7 +180,6 @@ void drv_proc_node_update_heap_status(void *node_resource, s32 status) { struct node_res_object *node_res_obj = (struct node_res_object *)node_resource; - DBC_ASSERT(node_resource != NULL); node_res_obj->heap_allocated = status; } @@ -378,13 +376,8 @@ int drv_get_dev_object(u32 index, struct drv_object *hdrv_obj, struct dev_object **device_obj) { int status = 0; -#ifdef CONFIG_TIDSPBRIDGE_DEBUG - /* used only for Assertions and debug messages */ - struct drv_object *pdrv_obj = (struct drv_object *)hdrv_obj; -#endif struct dev_object *dev_obj; u32 i; - DBC_ASSERT(!(list_empty(&pdrv_obj->dev_list))); dev_obj = (struct dev_object *)drv_get_first_dev_object(); for (i = 0; i < index; i++) { diff --git a/drivers/staging/tidspbridge/rmgr/drv_interface.c b/drivers/staging/tidspbridge/rmgr/drv_interface.c index 34730de..f0f07ef 100644 --- a/drivers/staging/tidspbridge/rmgr/drv_interface.c +++ b/drivers/staging/tidspbridge/rmgr/drv_interface.c @@ -255,8 +255,6 @@ static int bridge_mmap(struct file *filp, struct vm_area_struct *vma) { u32 status; - DBC_ASSERT(vma->vm_start < vma->vm_end); - vma->vm_flags |= VM_RESERVED | VM_IO; vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); diff --git a/drivers/staging/tidspbridge/rmgr/mgr.c b/drivers/staging/tidspbridge/rmgr/mgr.c index 1dca953..b0ce0bc 100644 --- a/drivers/staging/tidspbridge/rmgr/mgr.c +++ b/drivers/staging/tidspbridge/rmgr/mgr.c @@ -141,7 +141,6 @@ int mgr_enum_node_info(u32 node_id, struct dsp_ndbprops *pndb_props, } pmgr_obj = drv_datap->mgr_object; - DBC_ASSERT(pmgr_obj); /* Forever loop till we hit failed or no more items in the * Enumeration. We will exit the loop other than 0; */ while (!status) { @@ -225,7 +224,6 @@ int mgr_enum_processor_info(u32 processor_id, dev_dbg(bridge, "%s: Failed to get MGR Object\n", __func__); goto func_end; } - DBC_ASSERT(pmgr_obj); /* Forever loop till we hit no more items in the * Enumeration. We will exit the loop other than 0; */ while (status1 == 0) { diff --git a/drivers/staging/tidspbridge/rmgr/nldr.c b/drivers/staging/tidspbridge/rmgr/nldr.c index 6fb19ef..cc20dd9 100644 --- a/drivers/staging/tidspbridge/rmgr/nldr.c +++ b/drivers/staging/tidspbridge/rmgr/nldr.c @@ -427,13 +427,10 @@ int nldr_create(struct nldr_object **nldr, dev_get_cod_mgr(hdev_obj, &cod_mgr); if (cod_mgr) { status = cod_get_loader(cod_mgr, &nldr_obj->dbll); - DBC_ASSERT(!status); status = cod_get_base_lib(cod_mgr, &nldr_obj->base_lib); - DBC_ASSERT(!status); status = cod_get_base_name(cod_mgr, sz_zl_file, COD_MAXPATHLENGTH); - DBC_ASSERT(!status); } status = 0; /* end lazy status checking */ @@ -534,7 +531,6 @@ int nldr_create(struct nldr_object **nldr, status = cod_get_base_name(cod_mgr, sz_zl_file, COD_MAXPATHLENGTH); /* lazy check */ - DBC_ASSERT(!status); /* First count number of overlay nodes */ status = dcd_get_objects(nldr_obj->dcd_mgr, sz_zl_file, @@ -666,7 +662,6 @@ int nldr_get_fxn_addr(struct nldr_nodeobject *nldr_node_obj, root = nldr_node_obj->delete_lib; break; default: - DBC_ASSERT(false); break; } } else { @@ -806,7 +801,6 @@ int nldr_load(struct nldr_nodeobject *nldr_node_obj, break; default: - DBC_ASSERT(false); break; } } @@ -853,7 +847,6 @@ int nldr_unload(struct nldr_nodeobject *nldr_node_obj, nldr_node_obj->pers_libs = 0; break; default: - DBC_ASSERT(false); break; } } else { @@ -1090,7 +1083,6 @@ static void free_sects(struct nldr_object *nldr_obj, ret = rmm_free(nldr_obj->rmm, 0, ovly_section->sect_run_addr, ovly_section->size, true); - DBC_ASSERT(ret); ovly_section = ovly_section->next_sect; i++; } @@ -1210,7 +1202,6 @@ static int load_lib(struct nldr_nodeobject *nldr_node_obj, if (depth > MAXDEPTH) { /* Error */ - DBC_ASSERT(false); } root->lib = NULL; /* Allocate a buffer for library file name of size DBL_MAXPATHLENGTH */ @@ -1273,7 +1264,6 @@ static int load_lib(struct nldr_nodeobject *nldr_node_obj, dcd_get_num_dep_libs(nldr_node_obj->nldr_obj->dcd_mgr, &uuid, &nd_libs, &np_libs, phase); } - DBC_ASSERT(nd_libs >= np_libs); if (!status) { if (!(*nldr_node_obj->phase_split)) np_libs = 0; @@ -1435,7 +1425,6 @@ static int load_ovly(struct nldr_nodeobject *nldr_node_obj, } } - DBC_ASSERT(i < nldr_obj->ovly_nodes); if (!po_node) { status = -ENOENT; @@ -1461,7 +1450,6 @@ static int load_ovly(struct nldr_nodeobject *nldr_node_obj, break; default: - DBC_ASSERT(false); break; } @@ -1609,7 +1597,6 @@ static int remote_alloc(void **ref, u16 mem_sect, u32 size, mem_phase_bit = EXECUTEDATAFLAGBIT; break; default: - DBC_ASSERT(false); break; } if (mem_sect == DBLL_CODE) @@ -1628,11 +1615,9 @@ static int remote_alloc(void **ref, u16 mem_sect, u32 size, /* Find an appropriate segment based on mem_sect */ if (segid == NULLID) { /* No memory requirements of preferences */ - DBC_ASSERT(!mem_load_req); goto func_cont; } if (segid <= MAXSEGID) { - DBC_ASSERT(segid < nldr_obj->dload_segs); /* Attempt to allocate from segid first. */ rmm_addr_obj->segid = segid; status = @@ -1643,7 +1628,6 @@ static int remote_alloc(void **ref, u16 mem_sect, u32 size, } } else { /* segid > MAXSEGID ==> Internal or external memory */ - DBC_ASSERT(segid == MEMINTERNALID || segid == MEMEXTERNALID); /* Check for any internal or external memory segment, * depending on segid. */ mem_sect_type |= segid == MEMINTERNALID ? @@ -1717,7 +1701,6 @@ static void unload_lib(struct nldr_nodeobject *nldr_node_obj, struct nldr_object *nldr_obj = nldr_node_obj->nldr_obj; u16 i; - DBC_ASSERT(root != NULL); /* Unload dependent libraries */ for (i = 0; i < root->dep_libs; i++) @@ -1768,7 +1751,6 @@ static void unload_ovly(struct nldr_nodeobject *nldr_node_obj, } } - DBC_ASSERT(i < nldr_obj->ovly_nodes); if (!po_node) /* TODO: Should we print warning here? */ @@ -1795,14 +1777,11 @@ static void unload_ovly(struct nldr_nodeobject *nldr_node_obj, other_alloc = po_node->other_sects; break; default: - DBC_ASSERT(false); break; } - DBC_ASSERT(ref_count && (*ref_count > 0)); if (ref_count && (*ref_count > 0)) { *ref_count -= 1; if (other_ref) { - DBC_ASSERT(*other_ref > 0); *other_ref -= 1; } } @@ -1868,7 +1847,6 @@ int nldr_find_addr(struct nldr_nodeobject *nldr_node, u32 sym_addr, root = nldr_node->delete_lib; break; default: - DBC_ASSERT(false); break; } } else { diff --git a/drivers/staging/tidspbridge/rmgr/node.c b/drivers/staging/tidspbridge/rmgr/node.c index d23d1d0..83b053f 100644 --- a/drivers/staging/tidspbridge/rmgr/node.c +++ b/drivers/staging/tidspbridge/rmgr/node.c @@ -703,7 +703,6 @@ DBAPI node_alloc_msg_buf(struct node_object *hnode, u32 usize, status = proc_get_processor_id(pnode->processor, &proc_id); if (proc_id != DSP_UNIT) { - DBC_ASSERT(NULL); goto func_end; } /* If segment ID includes MEM_SETVIRTUALSEGID then pbuffer is a @@ -889,7 +888,6 @@ int node_connect(struct node_object *node1, u32 stream1, if (node1_type != NODE_GPP) { hnode_mgr = node1->node_mgr; } else { - DBC_ASSERT(node2 != (struct node_object *)DSP_HGPPNODE); hnode_mgr = node2->node_mgr; } @@ -968,9 +966,6 @@ int node_connect(struct node_object *node1, u32 stream1, goto out_unlock; } - DBC_ASSERT((node1_type == NODE_GPP) || - (node2_type == NODE_GPP)); - chnl_mode = (node1_type == NODE_GPP) ? CHNL_MODETODSP : CHNL_MODEFROMDSP; @@ -1617,7 +1612,6 @@ int node_free_msg_buf(struct node_object *hnode, u8 * pbuffer, status = cmm_xlator_free_buf(pnode->xlator, pbuffer); } } else { - DBC_ASSERT(NULL); /* BUG */ } func_end: return status; @@ -1692,7 +1686,6 @@ int node_get_channel_id(struct node_object *hnode, u32 dir, u32 index, } } } else { - DBC_ASSERT(dir == DSP_FROMNODE); if (index < MAX_OUTPUTS(hnode)) { if (hnode->outputs[index].type == HOSTCONNECT) { *chan_id = hnode->outputs[index].dev_id; @@ -2222,7 +2215,6 @@ int node_run(struct node_object *hnode) NODE_GET_PRIORITY(hnode)); } else { /* We should never get here */ - DBC_ASSERT(false); } func_cont1: /* Update node state. */ @@ -2600,7 +2592,6 @@ static void fill_stream_connect(struct node_object *node1, strm1->connect_type = CONNECTTYPE_GPPOUTPUT; } else { /* GPP == > NODE */ - DBC_ASSERT(node2 != (struct node_object *)DSP_HGPPNODE); strm_index = node2->num_inputs + node2->num_outputs - 1; strm2 = &(node2->stream_connect[strm_index]); strm2->cb_struct = sizeof(struct dsp_streamconnect); @@ -2696,7 +2687,6 @@ static int get_fxn_address(struct node_object *hnode, u32 * fxn_addr, break; default: /* Should never get here */ - DBC_ASSERT(false); break; } @@ -2775,7 +2765,6 @@ static int get_node_props(struct dcd_manager *hdcd_mgr, } else { /* Copy device name */ len = strlen(pndb_props->ac_name); - DBC_ASSERT(len < MAXDEVNAMELEN); hnode->str_dev_name = kzalloc(len + 1, GFP_KERNEL); if (hnode->str_dev_name == NULL) { status = -ENOMEM; diff --git a/drivers/staging/tidspbridge/rmgr/proc.c b/drivers/staging/tidspbridge/rmgr/proc.c index 4e2f2e4..8da5db6 100644 --- a/drivers/staging/tidspbridge/rmgr/proc.c +++ b/drivers/staging/tidspbridge/rmgr/proc.c @@ -1152,8 +1152,6 @@ int proc_load(void *hprocessor, const s32 argc_index, if (status) { status = -EPERM; } else { - DBC_ASSERT(p_proc_object->last_coff == - NULL); /* Allocate memory for pszLastCoff */ p_proc_object->last_coff = kzalloc((strlen(user_args[0]) + @@ -1176,7 +1174,6 @@ int proc_load(void *hprocessor, const s32 argc_index, if (!hmsg_mgr) { status = msg_create(&hmsg_mgr, p_proc_object->dev_obj, (msg_onexit) node_on_exit); - DBC_ASSERT(!status); dev_set_msg_mgr(p_proc_object->dev_obj, hmsg_mgr); } } @@ -1272,7 +1269,6 @@ int proc_load(void *hprocessor, const s32 argc_index, strlen(pargv0) + 1); else status = -ENOMEM; - DBC_ASSERT(brd_state == BRD_LOADED); } } @@ -1559,7 +1555,6 @@ func_cont: if (!((*p_proc_object->intf_fxns->brd_status) (p_proc_object->bridge_context, &brd_state))) { pr_info("%s: dsp in running state\n", __func__); - DBC_ASSERT(brd_state != BRD_HIBERNATION); } } else { pr_err("%s: Failed to start the dsp\n", __func__); @@ -1585,7 +1580,6 @@ int proc_stop(void *hprocessor) u32 node_tab_size = 1; u32 num_nodes = 0; u32 nodes_allocated = 0; - int brd_state; if (!p_proc_object) { status = -EFAULT; @@ -1618,11 +1612,6 @@ int proc_stop(void *hprocessor) msg_delete(hmsg_mgr); dev_set_msg_mgr(p_proc_object->dev_obj, NULL); } - if (!((*p_proc_object-> - intf_fxns->brd_status) (p_proc_object-> - bridge_context, - &brd_state))) - DBC_ASSERT(brd_state == BRD_STOPPED); } } else { pr_err("%s: Failed to stop the processor\n", __func__); @@ -1760,7 +1749,6 @@ static int proc_monitor(struct proc_object *proc_obj) { int status = -EPERM; struct msg_mgr *hmsg_mgr; - int brd_state; /* This is needed only when Device is loaded when it is * already 'ACTIVE' */ @@ -1777,9 +1765,6 @@ static int proc_monitor(struct proc_object *proc_obj) if (!((*proc_obj->intf_fxns->brd_monitor) (proc_obj->bridge_context))) { status = 0; - if (!((*proc_obj->intf_fxns->brd_status) - (proc_obj->bridge_context, &brd_state))) - DBC_ASSERT(brd_state == BRD_IDLE); } return status; diff --git a/drivers/staging/tidspbridge/rmgr/rmm.c b/drivers/staging/tidspbridge/rmgr/rmm.c index 6b41049..fe13a74 100644 --- a/drivers/staging/tidspbridge/rmgr/rmm.c +++ b/drivers/staging/tidspbridge/rmgr/rmm.c @@ -292,7 +292,6 @@ bool rmm_free(struct rmm_target_obj *target, u32 segid, u32 dsp_addr, u32 size, list_for_each_entry_safe(sect, tmp, &target->ovly_list, list_elem) { if (dsp_addr == sect->addr) { - DBC_ASSERT(size == sect->size); /* Remove from list */ list_del(§->list_elem); kfree(sect); @@ -325,8 +324,6 @@ bool rmm_stat(struct rmm_target_obj *target, enum dsp_memtype segid, u32 total_free_size = 0; u32 free_blocks = 0; - DBC_ASSERT(target != NULL); - if ((u32) segid < target->num_segs) { head = target->free_list[segid]; diff --git a/drivers/staging/tidspbridge/rmgr/strm.c b/drivers/staging/tidspbridge/rmgr/strm.c index 8e2d649..80d01e5 100644 --- a/drivers/staging/tidspbridge/rmgr/strm.c +++ b/drivers/staging/tidspbridge/rmgr/strm.c @@ -119,7 +119,6 @@ int strm_allocate_buffer(struct strm_res_object *strmres, u32 usize, goto func_end; for (i = 0; i < num_bufs; i++) { - DBC_ASSERT(stream_obj->xlator != NULL); (void)cmm_xlator_alloc_buf(stream_obj->xlator, &ap_buffer[i], usize); if (ap_buffer[i] == NULL) { @@ -162,7 +161,6 @@ int strm_close(struct strm_res_object *strmres, status = (*intf_fxns->chnl_get_info) (stream_obj->chnl_obj, &chnl_info_obj); - DBC_ASSERT(!status); if (chnl_info_obj.cio_cs > 0 || chnl_info_obj.cio_reqs > 0) status = -EPIPE; @@ -205,7 +203,6 @@ int strm_create(struct strm_mgr **strm_man, if (!status) { (void)dev_get_intf_fxns(dev_obj, &(strm_mgr_obj->intf_fxns)); - DBC_ASSERT(strm_mgr_obj->intf_fxns != NULL); } } @@ -254,7 +251,6 @@ int strm_free_buffer(struct strm_res_object *strmres, u8 ** ap_buffer, if (!status) { for (i = 0; i < num_bufs; i++) { - DBC_ASSERT(stream_obj->xlator != NULL); status = cmm_xlator_free_buf(stream_obj->xlator, ap_buffer[i]); @@ -302,7 +298,6 @@ int strm_get_info(struct strm_object *stream_obj, if (stream_obj->xlator) { /* We have a translator */ - DBC_ASSERT(stream_obj->segment_id > 0); cmm_xlator_info(stream_obj->xlator, (u8 **) &virt_base, 0, stream_obj->segment_id, false); } @@ -496,14 +491,12 @@ int strm_open(struct node_object *hnode, u32 dir, u32 index, goto func_cont; /* No System DMA */ - DBC_ASSERT(strm_obj->strm_mode != STRMMODE_LDMA); /* Get the shared mem mgr for this streams dev object */ status = dev_get_cmm_mgr(strm_mgr_obj->dev_obj, &hcmm_mgr); if (!status) { /*Allocate a SM addr translator for this strm. */ status = cmm_xlator_create(&strm_obj->xlator, hcmm_mgr, NULL); if (!status) { - DBC_ASSERT(strm_obj->segment_id > 0); /* Set translators Virt Addr attributes */ status = cmm_xlator_info(strm_obj->xlator, (u8 **) &pattr->virt_base, @@ -535,10 +528,6 @@ func_cont: * strm_mgr_obj->chnl_mgr better be valid or we * assert here), and then return -EPERM. */ - DBC_ASSERT(status == -ENOSR || - status == -ECHRNG || - status == -EALREADY || - status == -EIO); status = -EPERM; } } -- cgit v0.10.2 From f7c908ef871fcb319096caa7e839091b1feabd24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Manuel=20J=C3=A1quez=20Leal?= Date: Tue, 7 Feb 2012 00:39:36 +0100 Subject: staging: tidspbridge: remove dbc.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All the macros in dbc.h are removed now so this patch removes it completely. Signed-off-by: Víctor Manuel Jáquez Leal Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/tidspbridge/core/chnl_sm.c b/drivers/staging/tidspbridge/core/chnl_sm.c index 3136e8d..e0c7e4c 100644 --- a/drivers/staging/tidspbridge/core/chnl_sm.c +++ b/drivers/staging/tidspbridge/core/chnl_sm.c @@ -50,9 +50,6 @@ /* ----------------------------------- DSP/BIOS Bridge */ #include -/* ----------------------------------- Trace & Debug */ -#include - /* ----------------------------------- OS Adaptation Layer */ #include diff --git a/drivers/staging/tidspbridge/core/dsp-clock.c b/drivers/staging/tidspbridge/core/dsp-clock.c index 7eb5617..c7df34e 100644 --- a/drivers/staging/tidspbridge/core/dsp-clock.c +++ b/drivers/staging/tidspbridge/core/dsp-clock.c @@ -29,9 +29,6 @@ #include #include "_tiomap.h" -/* ----------------------------------- Trace & Debug */ -#include - /* ----------------------------------- This */ #include diff --git a/drivers/staging/tidspbridge/core/io_sm.c b/drivers/staging/tidspbridge/core/io_sm.c index 0930a98..d47b861 100644 --- a/drivers/staging/tidspbridge/core/io_sm.c +++ b/drivers/staging/tidspbridge/core/io_sm.c @@ -33,9 +33,6 @@ /* ----------------------------------- DSP/BIOS Bridge */ #include -/* Trace & Debug */ -#include - /* Services Layer */ #include #include diff --git a/drivers/staging/tidspbridge/core/msg_sm.c b/drivers/staging/tidspbridge/core/msg_sm.c index 94d9e04..ce9557e 100644 --- a/drivers/staging/tidspbridge/core/msg_sm.c +++ b/drivers/staging/tidspbridge/core/msg_sm.c @@ -20,9 +20,6 @@ /* ----------------------------------- DSP/BIOS Bridge */ #include -/* ----------------------------------- Trace & Debug */ -#include - /* ----------------------------------- OS Adaptation Layer */ #include diff --git a/drivers/staging/tidspbridge/core/tiomap3430.c b/drivers/staging/tidspbridge/core/tiomap3430.c index c3efc2e..fd84632 100644 --- a/drivers/staging/tidspbridge/core/tiomap3430.c +++ b/drivers/staging/tidspbridge/core/tiomap3430.c @@ -27,9 +27,6 @@ /* ----------------------------------- DSP/BIOS Bridge */ #include -/* ----------------------------------- Trace & Debug */ -#include - /* ----------------------------------- OS Adaptation Layer */ #include #include diff --git a/drivers/staging/tidspbridge/core/tiomap_io.c b/drivers/staging/tidspbridge/core/tiomap_io.c index 9c18873..7fda10c 100644 --- a/drivers/staging/tidspbridge/core/tiomap_io.c +++ b/drivers/staging/tidspbridge/core/tiomap_io.c @@ -21,9 +21,6 @@ /* ----------------------------------- DSP/BIOS Bridge */ #include -/* ----------------------------------- Trace & Debug */ -#include - /* ----------------------------------- Platform Manager */ #include #include diff --git a/drivers/staging/tidspbridge/gen/uuidutil.c b/drivers/staging/tidspbridge/gen/uuidutil.c index 5797fb5..b44656c 100644 --- a/drivers/staging/tidspbridge/gen/uuidutil.c +++ b/drivers/staging/tidspbridge/gen/uuidutil.c @@ -23,9 +23,6 @@ /* ----------------------------------- DSP/BIOS Bridge */ #include -/* ----------------------------------- Trace & Debug */ -#include - /* ----------------------------------- This */ #include diff --git a/drivers/staging/tidspbridge/include/dspbridge/dbc.h b/drivers/staging/tidspbridge/include/dspbridge/dbc.h deleted file mode 100644 index 90c45f6..0000000 --- a/drivers/staging/tidspbridge/include/dspbridge/dbc.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * dbc.h - * - * DSP-BIOS Bridge driver support functions for TI OMAP processors. - * - * "Design by Contract" programming macros. - * - * Notes: - * Requires that the GT->ERROR function has been defaulted to a valid - * error handler for the given execution environment. - * - * Does not require that GT_init() be called. - * - * Copyright (C) 2008 Texas Instruments, Inc. - * - * This package is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -#ifndef DBC_ -#define DBC_ - -#endif /* DBC_ */ diff --git a/drivers/staging/tidspbridge/pmgr/chnl.c b/drivers/staging/tidspbridge/pmgr/chnl.c index 61ee0f0..825be20 100644 --- a/drivers/staging/tidspbridge/pmgr/chnl.c +++ b/drivers/staging/tidspbridge/pmgr/chnl.c @@ -24,9 +24,6 @@ /* ----------------------------------- DSP/BIOS Bridge */ #include -/* ----------------------------------- Trace & Debug */ -#include - /* ----------------------------------- OS Adaptation Layer */ #include diff --git a/drivers/staging/tidspbridge/pmgr/cmm.c b/drivers/staging/tidspbridge/pmgr/cmm.c index 0d19bcd..3366e60 100644 --- a/drivers/staging/tidspbridge/pmgr/cmm.c +++ b/drivers/staging/tidspbridge/pmgr/cmm.c @@ -35,9 +35,6 @@ /* ----------------------------------- DSP/BIOS Bridge */ #include -/* ----------------------------------- Trace & Debug */ -#include - /* ----------------------------------- OS Adaptation Layer */ #include diff --git a/drivers/staging/tidspbridge/pmgr/cod.c b/drivers/staging/tidspbridge/pmgr/cod.c index be7c777..d01fb8e 100644 --- a/drivers/staging/tidspbridge/pmgr/cod.c +++ b/drivers/staging/tidspbridge/pmgr/cod.c @@ -30,9 +30,6 @@ /* ----------------------------------- DSP/BIOS Bridge */ #include -/* ----------------------------------- Trace & Debug */ -#include - /* ----------------------------------- Platform Manager */ /* Include appropriate loader header file */ #include diff --git a/drivers/staging/tidspbridge/pmgr/dbll.c b/drivers/staging/tidspbridge/pmgr/dbll.c index 997feeb..071ee86 100644 --- a/drivers/staging/tidspbridge/pmgr/dbll.c +++ b/drivers/staging/tidspbridge/pmgr/dbll.c @@ -21,8 +21,6 @@ /* ----------------------------------- DSP/BIOS Bridge */ #include -/* ----------------------------------- Trace & Debug */ -#include #include /* ----------------------------------- OS Adaptation Layer */ diff --git a/drivers/staging/tidspbridge/pmgr/dev.c b/drivers/staging/tidspbridge/pmgr/dev.c index 980bd53..883765e 100644 --- a/drivers/staging/tidspbridge/pmgr/dev.c +++ b/drivers/staging/tidspbridge/pmgr/dev.c @@ -24,9 +24,6 @@ /* ----------------------------------- DSP/BIOS Bridge */ #include -/* ----------------------------------- Trace & Debug */ -#include - /* ----------------------------------- Platform Manager */ #include #include diff --git a/drivers/staging/tidspbridge/pmgr/dmm.c b/drivers/staging/tidspbridge/pmgr/dmm.c index cece780..83faff8 100644 --- a/drivers/staging/tidspbridge/pmgr/dmm.c +++ b/drivers/staging/tidspbridge/pmgr/dmm.c @@ -28,9 +28,6 @@ /* ----------------------------------- DSP/BIOS Bridge */ #include -/* ----------------------------------- Trace & Debug */ -#include - /* ----------------------------------- OS Adaptation Layer */ #include diff --git a/drivers/staging/tidspbridge/pmgr/dspapi.c b/drivers/staging/tidspbridge/pmgr/dspapi.c index 27c14a5..2788946 100644 --- a/drivers/staging/tidspbridge/pmgr/dspapi.c +++ b/drivers/staging/tidspbridge/pmgr/dspapi.c @@ -24,9 +24,6 @@ /* ----------------------------------- DSP/BIOS Bridge */ #include -/* ----------------------------------- Trace & Debug */ -#include - /* ----------------------------------- OS Adaptation Layer */ #include diff --git a/drivers/staging/tidspbridge/pmgr/io.c b/drivers/staging/tidspbridge/pmgr/io.c index bbfe94c..a56b085 100644 --- a/drivers/staging/tidspbridge/pmgr/io.c +++ b/drivers/staging/tidspbridge/pmgr/io.c @@ -23,9 +23,6 @@ /* ----------------------------------- DSP/BIOS Bridge */ #include -/* ----------------------------------- Trace & Debug */ -#include - /* ----------------------------------- Platform Manager */ #include diff --git a/drivers/staging/tidspbridge/pmgr/msg.c b/drivers/staging/tidspbridge/pmgr/msg.c index 150026d..077c118 100644 --- a/drivers/staging/tidspbridge/pmgr/msg.c +++ b/drivers/staging/tidspbridge/pmgr/msg.c @@ -23,9 +23,6 @@ /* ----------------------------------- DSP/BIOS Bridge */ #include -/* ----------------------------------- Trace & Debug */ -#include - /* ----------------------------------- Bridge Driver */ #include diff --git a/drivers/staging/tidspbridge/rmgr/dbdcd.c b/drivers/staging/tidspbridge/rmgr/dbdcd.c index 18109fc..8378b7b 100644 --- a/drivers/staging/tidspbridge/rmgr/dbdcd.c +++ b/drivers/staging/tidspbridge/rmgr/dbdcd.c @@ -29,8 +29,6 @@ /* ----------------------------------- DSP/BIOS Bridge */ #include -/* ----------------------------------- Trace & Debug */ -#include /* ----------------------------------- Platform Manager */ #include diff --git a/drivers/staging/tidspbridge/rmgr/disp.c b/drivers/staging/tidspbridge/rmgr/disp.c index 63fdf1e..e510bb2 100644 --- a/drivers/staging/tidspbridge/rmgr/disp.c +++ b/drivers/staging/tidspbridge/rmgr/disp.c @@ -24,9 +24,6 @@ /* ----------------------------------- DSP/BIOS Bridge */ #include -/* ----------------------------------- Trace & Debug */ -#include - /* ----------------------------------- OS Adaptation Layer */ #include diff --git a/drivers/staging/tidspbridge/rmgr/drv.c b/drivers/staging/tidspbridge/rmgr/drv.c index cd93c12..b34dba7 100644 --- a/drivers/staging/tidspbridge/rmgr/drv.c +++ b/drivers/staging/tidspbridge/rmgr/drv.c @@ -24,9 +24,6 @@ /* ----------------------------------- DSP/BIOS Bridge */ #include -/* ----------------------------------- Trace & Debug */ -#include - /* ----------------------------------- This */ #include #include diff --git a/drivers/staging/tidspbridge/rmgr/drv_interface.c b/drivers/staging/tidspbridge/rmgr/drv_interface.c index f0f07ef..31b5140 100644 --- a/drivers/staging/tidspbridge/rmgr/drv_interface.c +++ b/drivers/staging/tidspbridge/rmgr/drv_interface.c @@ -30,9 +30,6 @@ /* ----------------------------------- DSP/BIOS Bridge */ #include -/* ----------------------------------- Trace & Debug */ -#include - /* ----------------------------------- OS Adaptation Layer */ #include diff --git a/drivers/staging/tidspbridge/rmgr/dspdrv.c b/drivers/staging/tidspbridge/rmgr/dspdrv.c index 5d25763..dc767b1 100644 --- a/drivers/staging/tidspbridge/rmgr/dspdrv.c +++ b/drivers/staging/tidspbridge/rmgr/dspdrv.c @@ -23,9 +23,6 @@ /* ----------------------------------- DSP/BIOS Bridge */ #include -/* ----------------------------------- Trace & Debug */ -#include - /* ----------------------------------- Platform Manager */ #include #include diff --git a/drivers/staging/tidspbridge/rmgr/mgr.c b/drivers/staging/tidspbridge/rmgr/mgr.c index b0ce0bc..938eea5 100644 --- a/drivers/staging/tidspbridge/rmgr/mgr.c +++ b/drivers/staging/tidspbridge/rmgr/mgr.c @@ -26,9 +26,6 @@ /* ----------------------------------- DSP/BIOS Bridge */ #include -/* ----------------------------------- Trace & Debug */ -#include - /* ----------------------------------- OS Adaptation Layer */ #include diff --git a/drivers/staging/tidspbridge/rmgr/nldr.c b/drivers/staging/tidspbridge/rmgr/nldr.c index cc20dd9..5cff46f 100644 --- a/drivers/staging/tidspbridge/rmgr/nldr.c +++ b/drivers/staging/tidspbridge/rmgr/nldr.c @@ -22,8 +22,6 @@ #include -#include - /* Platform manager */ #include #include diff --git a/drivers/staging/tidspbridge/rmgr/node.c b/drivers/staging/tidspbridge/rmgr/node.c index 83b053f..1b24589 100644 --- a/drivers/staging/tidspbridge/rmgr/node.c +++ b/drivers/staging/tidspbridge/rmgr/node.c @@ -26,9 +26,6 @@ /* ----------------------------------- DSP/BIOS Bridge */ #include -/* ----------------------------------- Trace & Debug */ -#include - /* ----------------------------------- OS Adaptation Layer */ #include #include diff --git a/drivers/staging/tidspbridge/rmgr/proc.c b/drivers/staging/tidspbridge/rmgr/proc.c index 8da5db6..b865d64 100644 --- a/drivers/staging/tidspbridge/rmgr/proc.c +++ b/drivers/staging/tidspbridge/rmgr/proc.c @@ -25,9 +25,6 @@ /* ----------------------------------- DSP/BIOS Bridge */ #include -/* ----------------------------------- Trace & Debug */ -#include - /* ----------------------------------- OS Adaptation Layer */ #include #include diff --git a/drivers/staging/tidspbridge/rmgr/rmm.c b/drivers/staging/tidspbridge/rmgr/rmm.c index fe13a74..55acfcd 100644 --- a/drivers/staging/tidspbridge/rmgr/rmm.c +++ b/drivers/staging/tidspbridge/rmgr/rmm.c @@ -46,9 +46,6 @@ /* ----------------------------------- DSP/BIOS Bridge */ #include -/* ----------------------------------- Trace & Debug */ -#include - /* ----------------------------------- This */ #include diff --git a/drivers/staging/tidspbridge/rmgr/strm.c b/drivers/staging/tidspbridge/rmgr/strm.c index 80d01e5..bd684f1 100644 --- a/drivers/staging/tidspbridge/rmgr/strm.c +++ b/drivers/staging/tidspbridge/rmgr/strm.c @@ -24,9 +24,6 @@ /* ----------------------------------- DSP/BIOS Bridge */ #include -/* ----------------------------------- Trace & Debug */ -#include - /* ----------------------------------- OS Adaptation Layer */ #include -- cgit v0.10.2 From 451196a338c681a95a79469cd58a54e657904e06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Manuel=20J=C3=A1quez=20Leal?= Date: Tue, 7 Feb 2012 00:39:37 +0100 Subject: staging: tidspbridge: remove CONFIG_TIDSPBRIDGE_DEBUG MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since all the asserts and DBC macros are gone, the kconfig macro CONFIG_TIDSPBRIDGE_DEBUG is not almost used, but for printing trace messages. Since it is almost not used, I don't see any case for keep it churning the configuration menu. This patch removes completely the kconfig macro CONFIG_TIDSPBRIDGE_DEBUG, using only TIDSPBRIDGE_BACKTRACE for enabling the debug trace messages. Signed-off-by: Víctor Manuel Jáquez Leal Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/tidspbridge/Kconfig b/drivers/staging/tidspbridge/Kconfig index 21a559e..d660891 100644 --- a/drivers/staging/tidspbridge/Kconfig +++ b/drivers/staging/tidspbridge/Kconfig @@ -31,12 +31,6 @@ config TIDSPBRIDGE_MEMPOOL_SIZE Allocate specified size of memory at booting time to avoid allocation failure under heavy memory fragmentation after some use time. -config TIDSPBRIDGE_DEBUG - bool "Debug Support" - depends on TIDSPBRIDGE - help - Say Y to enable Bridge debugging capabilities - config TIDSPBRIDGE_RECOVERY bool "Recovery Support" depends on TIDSPBRIDGE diff --git a/drivers/staging/tidspbridge/core/io_sm.c b/drivers/staging/tidspbridge/core/io_sm.c index d47b861..9b50b5b 100644 --- a/drivers/staging/tidspbridge/core/io_sm.c +++ b/drivers/staging/tidspbridge/core/io_sm.c @@ -111,7 +111,7 @@ struct io_mgr { struct mgr_processorextinfo ext_proc_info; struct cmm_object *cmm_mgr; /* Shared Mem Mngr */ struct work_struct io_workq; /* workqueue */ -#if defined(CONFIG_TIDSPBRIDGE_BACKTRACE) || defined(CONFIG_TIDSPBRIDGE_DEBUG) +#if defined(CONFIG_TIDSPBRIDGE_BACKTRACE) u32 trace_buffer_begin; /* Trace message start address */ u32 trace_buffer_end; /* Trace message end address */ u32 trace_buffer_current; /* Trace message current address */ @@ -243,7 +243,7 @@ int bridge_io_destroy(struct io_mgr *hio_mgr) /* Free IO DPC object */ tasklet_kill(&hio_mgr->dpc_tasklet); -#if defined(CONFIG_TIDSPBRIDGE_BACKTRACE) || defined(CONFIG_TIDSPBRIDGE_DEBUG) +#if defined(CONFIG_TIDSPBRIDGE_BACKTRACE) kfree(hio_mgr->msg); #endif dsp_wdt_exit(); @@ -383,7 +383,7 @@ int bridge_io_on_loaded(struct io_mgr *hio_mgr) status = -EFAULT; } if (!status) { -#if defined(CONFIG_TIDSPBRIDGE_BACKTRACE) || defined(CONFIG_TIDSPBRIDGE_DEBUG) +#if defined(CONFIG_TIDSPBRIDGE_BACKTRACE) status = cod_get_sym_value(cod_man, DSP_TRACESEC_END, &shm0_end); #else @@ -728,7 +728,7 @@ int bridge_io_on_loaded(struct io_mgr *hio_mgr) hmsg_mgr->max_msgs); memset((void *)hio_mgr->shared_mem, 0, sizeof(struct shm)); -#if defined(CONFIG_TIDSPBRIDGE_BACKTRACE) || defined(CONFIG_TIDSPBRIDGE_DEBUG) +#if defined(CONFIG_TIDSPBRIDGE_BACKTRACE) /* Get the start address of trace buffer */ status = cod_get_sym_value(cod_man, SYS_PUTCBEG, &hio_mgr->trace_buffer_begin); @@ -907,7 +907,7 @@ void io_dpc(unsigned long ref_data) } #endif -#ifdef CONFIG_TIDSPBRIDGE_DEBUG +#ifdef CONFIG_TIDSPBRIDGE_BACKTRACE if (pio_mgr->intr_val & MBX_DBG_SYSPRINTF) { /* Notify DSP Trace message */ print_dsp_debug_trace(pio_mgr); @@ -1666,7 +1666,7 @@ int bridge_io_get_proc_load(struct io_mgr *hio_mgr, } -#if defined(CONFIG_TIDSPBRIDGE_BACKTRACE) || defined(CONFIG_TIDSPBRIDGE_DEBUG) +#if defined(CONFIG_TIDSPBRIDGE_BACKTRACE) void print_dsp_debug_trace(struct io_mgr *hio_mgr) { u32 ul_new_message_length = 0, ul_gpp_cur_pointer; diff --git a/drivers/staging/tidspbridge/include/dspbridge/io_sm.h b/drivers/staging/tidspbridge/include/dspbridge/io_sm.h index a054dad..903ff12 100644 --- a/drivers/staging/tidspbridge/include/dspbridge/io_sm.h +++ b/drivers/staging/tidspbridge/include/dspbridge/io_sm.h @@ -154,8 +154,6 @@ int dump_dsp_stack(struct bridge_dev_context *bridge_context); void dump_dl_modules(struct bridge_dev_context *bridge_context); -#endif -#if defined(CONFIG_TIDSPBRIDGE_BACKTRACE) || defined(CONFIG_TIDSPBRIDGE_DEBUG) void print_dsp_debug_trace(struct io_mgr *hio_mgr); #endif -- cgit v0.10.2 From 74eabe4ca2f6cf0e7e60e73017206e963f6b170a Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Sun, 22 Jan 2012 19:50:13 +0100 Subject: Staging: quickstart: Use pr_err and pr_info for logs Signed-off-by: Szymon Janc Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/quickstart/quickstart.c b/drivers/staging/quickstart/quickstart.c index a67b03a..88f8ff3 100644 --- a/drivers/staging/quickstart/quickstart.c +++ b/drivers/staging/quickstart/quickstart.c @@ -25,6 +25,8 @@ #define QUICKSTART_VERSION "1.03" +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -166,6 +168,7 @@ static void quickstart_acpi_notify(acpi_handle handle, u32 event, void *data) input_sync(quickstart_input); break; default: + pr_err("Unexpected ACPI event notify (%u)\n", event); break; } } @@ -183,8 +186,7 @@ static int quickstart_acpi_ghid(struct quickstart_acpi *quickstart) status = acpi_evaluate_object(quickstart->device->handle, "GHID", NULL, &buffer); if (ACPI_FAILURE(status)) { - printk(KERN_ERR "quickstart: %s GHID method failed.\n", - quickstart->button->name); + pr_err("%s GHID method failed\n", quickstart->button->name); return -EINVAL; } @@ -207,8 +209,7 @@ static int quickstart_acpi_ghid(struct quickstart_acpi *quickstart) quickstart->button->id = *(uint64_t *)buffer.pointer; break; default: - printk(KERN_ERR "quickstart: %s GHID method returned buffer " - "of unexpected length %u\n", + pr_err("%s GHID method returned buffer of unexpected length %u\n", quickstart->button->name, buffer.length); ret = -EINVAL; break; @@ -269,7 +270,7 @@ static int quickstart_acpi_add(struct acpi_device *device) quickstart_acpi_notify, quickstart); if (ACPI_FAILURE(status)) { - printk(KERN_ERR "quickstart: Notify handler install error\n"); + pr_err("Notify handler install error\n"); ret = -ENODEV; goto fail_installnotify; } @@ -309,7 +310,7 @@ static int quickstart_acpi_remove(struct acpi_device *device, int type) status = acpi_remove_notify_handler(device->handle, ACPI_ALL_NOTIFY, quickstart_acpi_notify); if (ACPI_FAILURE(status)) - printk(KERN_ERR "quickstart: Error removing notify handler\n"); + pr_err("Error removing notify handler\n"); kfree(quickstart); @@ -435,8 +436,7 @@ static int __init quickstart_init(void) if (ret) goto fail_input; - printk(KERN_INFO "quickstart: ACPI Direct App Launch ver %s\n", - QUICKSTART_VERSION); + pr_info("ACPI Direct App Launch ver %s\n", QUICKSTART_VERSION); return 0; fail_input: -- cgit v0.10.2 From aa2f92ae6b986934ff220eda6b5c91f4ee294b35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rton=20N=C3=A9meth?= Date: Sun, 22 Jan 2012 22:47:15 +0100 Subject: staging: rts5139: fix pointer coding style MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This will remove the following checkpatch.pl error: ERROR: "foo * bar" should be "foo *bar" Signed-off-by: Márton Németh Acked-by: edwin_rong Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rts5139/ms.h b/drivers/staging/rts5139/ms.h index f9d46d2..3ce1dc9 100644 --- a/drivers/staging/rts5139/ms.h +++ b/drivers/staging/rts5139/ms.h @@ -249,9 +249,9 @@ int ms_delay_write(struct rts51x_chip *chip); #ifdef SUPPORT_MAGIC_GATE int ms_switch_clock(struct rts51x_chip *chip); -int ms_write_bytes(struct rts51x_chip *chip, u8 tpc, u8 cnt, u8 cfg, u8 * data, +int ms_write_bytes(struct rts51x_chip *chip, u8 tpc, u8 cnt, u8 cfg, u8 *data, int data_len); -int ms_read_bytes(struct rts51x_chip *chip, u8 tpc, u8 cnt, u8 cfg, u8 * data, +int ms_read_bytes(struct rts51x_chip *chip, u8 tpc, u8 cnt, u8 cfg, u8 *data, int data_len); int ms_set_rw_reg_addr(struct rts51x_chip *chip, u8 read_start, u8 read_cnt, u8 write_start, u8 write_cnt); diff --git a/drivers/staging/rts5139/rts51x_chip.c b/drivers/staging/rts5139/rts51x_chip.c index adc0d00..b3e0bb2 100644 --- a/drivers/staging/rts5139/rts51x_chip.c +++ b/drivers/staging/rts5139/rts51x_chip.c @@ -541,7 +541,7 @@ int rts51x_get_rsp(struct rts51x_chip *chip, int rsp_len, int timeout) return STATUS_SUCCESS; } -int rts51x_get_card_status(struct rts51x_chip *chip, u16 * status) +int rts51x_get_card_status(struct rts51x_chip *chip, u16 *status) { int retval; u16 val; @@ -577,7 +577,7 @@ int rts51x_write_register(struct rts51x_chip *chip, u16 addr, u8 mask, u8 data) return STATUS_SUCCESS; } -int rts51x_read_register(struct rts51x_chip *chip, u16 addr, u8 * data) +int rts51x_read_register(struct rts51x_chip *chip, u16 addr, u8 *data) { int retval; @@ -620,7 +620,7 @@ int rts51x_ep0_write_register(struct rts51x_chip *chip, u16 addr, u8 mask, return STATUS_SUCCESS; } -int rts51x_ep0_read_register(struct rts51x_chip *chip, u16 addr, u8 * data) +int rts51x_ep0_read_register(struct rts51x_chip *chip, u16 addr, u8 *data) { int retval; u16 value = 0; @@ -720,7 +720,7 @@ int rts51x_seq_read_register(struct rts51x_chip *chip, u16 addr, u16 len, return STATUS_SUCCESS; } -int rts51x_read_ppbuf(struct rts51x_chip *chip, u8 * buf, int buf_len) +int rts51x_read_ppbuf(struct rts51x_chip *chip, u8 *buf, int buf_len) { int retval; @@ -735,7 +735,7 @@ int rts51x_read_ppbuf(struct rts51x_chip *chip, u8 * buf, int buf_len) return STATUS_SUCCESS; } -int rts51x_write_ppbuf(struct rts51x_chip *chip, u8 * buf, int buf_len) +int rts51x_write_ppbuf(struct rts51x_chip *chip, u8 *buf, int buf_len) { int retval; @@ -776,7 +776,7 @@ int rts51x_write_phy_register(struct rts51x_chip *chip, u8 addr, u8 val) return STATUS_SUCCESS; } -int rts51x_read_phy_register(struct rts51x_chip *chip, u8 addr, u8 * val) +int rts51x_read_phy_register(struct rts51x_chip *chip, u8 addr, u8 *val) { int retval; @@ -921,7 +921,7 @@ void rts51x_trace_msg(struct rts51x_chip *chip, unsigned char *buf, int clear) } #endif -void rts51x_pp_status(struct rts51x_chip *chip, unsigned int lun, u8 * status, +void rts51x_pp_status(struct rts51x_chip *chip, unsigned int lun, u8 *status, u8 status_len) { struct sd_info *sd_card = &(chip->sd_card); diff --git a/drivers/staging/rts5139/rts51x_chip.h b/drivers/staging/rts5139/rts51x_chip.h index 321ece7..13fc2a4 100644 --- a/drivers/staging/rts5139/rts51x_chip.h +++ b/drivers/staging/rts5139/rts51x_chip.h @@ -857,12 +857,12 @@ static inline u8 *rts51x_get_rsp_data(struct rts51x_chip *chip) return chip->rsp_buf; } -int rts51x_get_card_status(struct rts51x_chip *chip, u16 * status); +int rts51x_get_card_status(struct rts51x_chip *chip, u16 *status); int rts51x_write_register(struct rts51x_chip *chip, u16 addr, u8 mask, u8 data); -int rts51x_read_register(struct rts51x_chip *chip, u16 addr, u8 * data); +int rts51x_read_register(struct rts51x_chip *chip, u16 addr, u8 *data); int rts51x_ep0_write_register(struct rts51x_chip *chip, u16 addr, u8 mask, u8 data); -int rts51x_ep0_read_register(struct rts51x_chip *chip, u16 addr, u8 * data); +int rts51x_ep0_read_register(struct rts51x_chip *chip, u16 addr, u8 *data); int rts51x_seq_write_register(struct rts51x_chip *chip, u16 addr, u16 len, u8 *data); int rts51x_seq_read_register(struct rts51x_chip *chip, u16 addr, u16 len, diff --git a/drivers/staging/rts5139/rts51x_fop.h b/drivers/staging/rts5139/rts51x_fop.h index 0453f57..94d75f0 100644 --- a/drivers/staging/rts5139/rts51x_fop.h +++ b/drivers/staging/rts5139/rts51x_fop.h @@ -48,7 +48,7 @@ int rts51x_open(struct inode *inode, struct file *filp); int rts51x_release(struct inode *inode, struct file *filp); ssize_t rts51x_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos); -ssize_t rts51x_write(struct file *filp, const char __user * buf, size_t count, +ssize_t rts51x_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos); #if 0 /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) */ int rts51x_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, diff --git a/drivers/staging/rts5139/rts51x_transport.c b/drivers/staging/rts5139/rts51x_transport.c index e11467a..da9c83b 100644 --- a/drivers/staging/rts5139/rts51x_transport.c +++ b/drivers/staging/rts5139/rts51x_transport.c @@ -883,7 +883,7 @@ int rts51x_transfer_data_partial(struct rts51x_chip *chip, unsigned int pipe, return result; } -int rts51x_get_epc_status(struct rts51x_chip *chip, u16 * status) +int rts51x_get_epc_status(struct rts51x_chip *chip, u16 *status) { unsigned int pipe = RCV_INTR_PIPE(chip); struct usb_host_endpoint *ep; diff --git a/drivers/staging/rts5139/rts51x_transport.h b/drivers/staging/rts5139/rts51x_transport.h index 8464c48..9dd556e 100644 --- a/drivers/staging/rts5139/rts51x_transport.h +++ b/drivers/staging/rts5139/rts51x_transport.h @@ -73,7 +73,7 @@ int rts51x_start_epc_transfer(struct rts51x_chip *chip); void rts51x_cancel_epc_transfer(struct rts51x_chip *chip); #endif -int rts51x_get_epc_status(struct rts51x_chip *chip, u16 * status); +int rts51x_get_epc_status(struct rts51x_chip *chip, u16 *status); void rts51x_invoke_transport(struct scsi_cmnd *srb, struct rts51x_chip *chip); #endif /* __RTS51X_TRANSPORT_H */ diff --git a/drivers/staging/rts5139/sd_cprm.c b/drivers/staging/rts5139/sd_cprm.c index 407cd43..d5969d9 100644 --- a/drivers/staging/rts5139/sd_cprm.c +++ b/drivers/staging/rts5139/sd_cprm.c @@ -233,7 +233,7 @@ RTY_SEND_CMD: return STATUS_SUCCESS; } -int ext_sd_get_rsp(struct rts51x_chip *chip, int len, u8 * rsp, u8 rsp_type) +int ext_sd_get_rsp(struct rts51x_chip *chip, int len, u8 *rsp, u8 rsp_type) { int retval, rsp_len; u16 reg_addr; -- cgit v0.10.2 From 37fe58ba6832de1df88f3734d8e18f6da6a06971 Mon Sep 17 00:00:00 2001 From: Thomas Meyer Date: Sun, 22 Jan 2012 18:27:21 +0100 Subject: staging: drm/omap: Use ERR_CAST inlined function instead of ERR_PTR(PTR_ERR(.. The semantic patch that makes this change is available in scripts/coccinelle/api/err_cast.cocci. More information about semantic patching is available at http://coccinelle.lip6.fr/ Signed-off-by: Thomas Meyer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/omapdrm/omap_gem_helpers.c b/drivers/staging/omapdrm/omap_gem_helpers.c index 29275c7..f895363 100644 --- a/drivers/staging/omapdrm/omap_gem_helpers.c +++ b/drivers/staging/omapdrm/omap_gem_helpers.c @@ -84,7 +84,7 @@ fail: page_cache_release(pages[i]); } drm_free_large(pages); - return ERR_PTR(PTR_ERR(p)); + return ERR_CAST(p); } /** -- cgit v0.10.2 From 98b9de2189180a1c62ea1ea912e66230908305f0 Mon Sep 17 00:00:00 2001 From: Bart Westgeest Date: Mon, 23 Jan 2012 10:55:45 -0500 Subject: staging: usbip: removed unused structure field Signed-off-by: Bart Westgeest Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/usbip/stub.h b/drivers/staging/usbip/stub.h index d407368..a73e437 100644 --- a/drivers/staging/usbip/stub.h +++ b/drivers/staging/usbip/stub.h @@ -35,7 +35,6 @@ struct stub_device { struct usb_interface *interface; struct usb_device *udev; - struct list_head list; struct usbip_device ud; __u32 devid; -- cgit v0.10.2 From ac2b41acfa3efe4650102067a99251587a806d70 Mon Sep 17 00:00:00 2001 From: Bart Westgeest Date: Mon, 23 Jan 2012 10:55:46 -0500 Subject: staging: usbip: changed function return type to void The function usbip_pad_iso never returns anything but 0 (success). Signed-off-by: Bart Westgeest Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/usbip/usbip_common.c b/drivers/staging/usbip/usbip_common.c index d93e7f1..70f23026 100644 --- a/drivers/staging/usbip/usbip_common.c +++ b/drivers/staging/usbip/usbip_common.c @@ -735,26 +735,25 @@ EXPORT_SYMBOL_GPL(usbip_recv_iso); * buffer and iso packets need to be stored and be in propeper endian in urb * before calling this function */ -int usbip_pad_iso(struct usbip_device *ud, struct urb *urb) +void usbip_pad_iso(struct usbip_device *ud, struct urb *urb) { int np = urb->number_of_packets; int i; - int ret; int actualoffset = urb->actual_length; if (!usb_pipeisoc(urb->pipe)) - return 0; + return; /* if no packets or length of data is 0, then nothing to unpack */ if (np == 0 || urb->actual_length == 0) - return 0; + return; /* * if actual_length is transfer_buffer_length then no padding is * present. */ if (urb->actual_length == urb->transfer_buffer_length) - return 0; + return; /* * loop over all packets from last to first (to prevent overwritting @@ -766,8 +765,6 @@ int usbip_pad_iso(struct usbip_device *ud, struct urb *urb) urb->transfer_buffer + actualoffset, urb->iso_frame_desc[i].actual_length); } - - return ret; } EXPORT_SYMBOL_GPL(usbip_pad_iso); diff --git a/drivers/staging/usbip/usbip_common.h b/drivers/staging/usbip/usbip_common.h index b8f8c48..c7b888c 100644 --- a/drivers/staging/usbip/usbip_common.h +++ b/drivers/staging/usbip/usbip_common.h @@ -306,7 +306,7 @@ void usbip_header_correct_endian(struct usbip_header *pdu, int send); void *usbip_alloc_iso_desc_pdu(struct urb *urb, ssize_t *bufflen); /* some members of urb must be substituted before. */ int usbip_recv_iso(struct usbip_device *ud, struct urb *urb); -int usbip_pad_iso(struct usbip_device *ud, struct urb *urb); +void usbip_pad_iso(struct usbip_device *ud, struct urb *urb); int usbip_recv_xbuff(struct usbip_device *ud, struct urb *urb); /* usbip_event.c */ diff --git a/drivers/staging/usbip/vhci_rx.c b/drivers/staging/usbip/vhci_rx.c index 3f511b4..f5fba732 100644 --- a/drivers/staging/usbip/vhci_rx.c +++ b/drivers/staging/usbip/vhci_rx.c @@ -94,8 +94,7 @@ static void vhci_recv_ret_submit(struct vhci_device *vdev, return; /* restore the padding in iso packets */ - if (usbip_pad_iso(ud, urb) < 0) - return; + usbip_pad_iso(ud, urb); if (usbip_dbg_flag_vhci_rx) usbip_dump_urb(urb); -- cgit v0.10.2 From 34c09578179f5838e5958c45e8aed4edc9c6c3b8 Mon Sep 17 00:00:00 2001 From: Bart Westgeest Date: Mon, 23 Jan 2012 10:55:47 -0500 Subject: staging: usbip: removed #if 0'd out code Signed-off-by: Bart Westgeest Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/usbip/stub_rx.c b/drivers/staging/usbip/stub_rx.c index 27ac363..1d5b3fc 100644 --- a/drivers/staging/usbip/stub_rx.c +++ b/drivers/staging/usbip/stub_rx.c @@ -367,15 +367,6 @@ static int get_pipe(struct stub_device *sdev, int epnum, int dir) } epd = &ep->desc; -#if 0 - /* epnum 0 is always control */ - if (epnum == 0) { - if (dir == USBIP_DIR_OUT) - return usb_sndctrlpipe(udev, 0); - else - return usb_rcvctrlpipe(udev, 0); - } -#endif if (usb_endpoint_xfer_control(epd)) { if (dir == USBIP_DIR_OUT) return usb_sndctrlpipe(udev, epnum); diff --git a/drivers/staging/usbip/vhci_hcd.c b/drivers/staging/usbip/vhci_hcd.c index 2ee97e2..8d96ab0 100644 --- a/drivers/staging/usbip/vhci_hcd.c +++ b/drivers/staging/usbip/vhci_hcd.c @@ -386,29 +386,6 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, dum->port_status[rhport] |= USB_PORT_STAT_ENABLE; } -#if 0 - if (dum->driver) { - dum->port_status[rhport] |= - USB_PORT_STAT_ENABLE; - /* give it the best speed we agree on */ - dum->gadget.speed = dum->driver->speed; - dum->gadget.ep0->maxpacket = 64; - switch (dum->gadget.speed) { - case USB_SPEED_HIGH: - dum->port_status[rhport] |= - USB_PORT_STAT_HIGH_SPEED; - break; - case USB_SPEED_LOW: - dum->gadget.ep0->maxpacket = 8; - dum->port_status[rhport] |= - USB_PORT_STAT_LOW_SPEED; - break; - default: - dum->gadget.speed = USB_SPEED_FULL; - break; - } - } -#endif } ((u16 *) buf)[0] = cpu_to_le16(dum->port_status[rhport]); ((u16 *) buf)[1] = cpu_to_le16(dum->port_status[rhport] >> 16); @@ -425,15 +402,6 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, case USB_PORT_FEAT_SUSPEND: usbip_dbg_vhci_rh(" SetPortFeature: " "USB_PORT_FEAT_SUSPEND\n"); -#if 0 - dum->port_status[rhport] |= - (1 << USB_PORT_FEAT_SUSPEND); - if (dum->driver->suspend) { - spin_unlock(&dum->lock); - dum->driver->suspend(&dum->gadget); - spin_lock(&dum->lock); - } -#endif break; case USB_PORT_FEAT_RESET: usbip_dbg_vhci_rh(" SetPortFeature: " @@ -444,13 +412,6 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, ~(USB_PORT_STAT_ENABLE | USB_PORT_STAT_LOW_SPEED | USB_PORT_STAT_HIGH_SPEED); -#if 0 - if (dum->driver) { - dev_dbg(hardware, "disconnect\n"); - stop_activity(dum, dum->driver); - } -#endif - /* FIXME test that code path! */ } /* 50msec reset signaling */ -- cgit v0.10.2 From 8ebc0b65d77e424ad184357e59ca9c6093eee8f2 Mon Sep 17 00:00:00 2001 From: Kashyap Gada Date: Mon, 6 Feb 2012 02:01:16 +0000 Subject: Staging: ft1000: ft1000-pcmia: fix space required after that ', ' in ft1000_proc.c This is a patch to the ft1000_proc.c that fixes up space required after ',' errors found by the checkpatch.pl tool Signed-off-by: Kashyap Gada Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c index 7faeada..71aaad3 100644 --- a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c +++ b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c @@ -29,10 +29,10 @@ #define FT1000_PROC "ft1000" #define MAX_FILE_LEN 255 -#define PUTM_TO_PAGE(len,page,args...) \ +#define PUTM_TO_PAGE(len, page, args...) \ len += snprintf(page+len, PAGE_SIZE - len, args) -#define PUTX_TO_PAGE(len,page,message,size,var) \ +#define PUTX_TO_PAGE(len, page, message, size, var) \ len += snprintf(page+len, PAGE_SIZE - len, message); \ for(i = 0; i < (size - 1); i++) \ { \ @@ -40,7 +40,7 @@ } \ len += snprintf(page+len, PAGE_SIZE - len, "%02x\n", var[i]) -#define PUTD_TO_PAGE(len,page,message,size,var) \ +#define PUTD_TO_PAGE(len, page, message, size, var) \ len += snprintf(page+len, PAGE_SIZE - len, message); \ for(i = 0; i < (size - 1); i++) \ { \ -- cgit v0.10.2 From 733ba91cc0d5b0a3cc012431b8c5b354697b57c1 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Thu, 9 Feb 2012 19:25:53 +0200 Subject: staging/mei: update copyright year to 2012 1. Update Copyright to 2012 2. Also fix mei.h copyright format checkpaatch complained: WARNING: please, no spaces at the start of a line Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/mei/hw.h b/drivers/staging/mei/hw.h index 9b9008c..b08c901 100644 --- a/drivers/staging/mei/hw.h +++ b/drivers/staging/mei/hw.h @@ -1,7 +1,7 @@ /* * * Intel Management Engine Interface (Intel MEI) Linux driver - * Copyright (c) 2003-2011, Intel Corporation. + * Copyright (c) 2003-2012, Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, diff --git a/drivers/staging/mei/init.c b/drivers/staging/mei/init.c index 4ac3696..393da4b 100644 --- a/drivers/staging/mei/init.c +++ b/drivers/staging/mei/init.c @@ -1,7 +1,7 @@ /* * * Intel Management Engine Interface (Intel MEI) Linux driver - * Copyright (c) 2003-2011, Intel Corporation. + * Copyright (c) 2003-2012, Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, diff --git a/drivers/staging/mei/interface.c b/drivers/staging/mei/interface.c index eb5df7f..951e61f 100644 --- a/drivers/staging/mei/interface.c +++ b/drivers/staging/mei/interface.c @@ -1,7 +1,7 @@ /* * * Intel Management Engine Interface (Intel MEI) Linux driver - * Copyright (c) 2003-2011, Intel Corporation. + * Copyright (c) 2003-2012, Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, diff --git a/drivers/staging/mei/interface.h b/drivers/staging/mei/interface.h index aeae511..3929874 100644 --- a/drivers/staging/mei/interface.h +++ b/drivers/staging/mei/interface.h @@ -1,7 +1,7 @@ /* * * Intel Management Engine Interface (Intel MEI) Linux driver - * Copyright (c) 2003-2011, Intel Corporation. + * Copyright (c) 2003-2012, Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, diff --git a/drivers/staging/mei/interrupt.c b/drivers/staging/mei/interrupt.c index e85a85a..8e16e94 100644 --- a/drivers/staging/mei/interrupt.c +++ b/drivers/staging/mei/interrupt.c @@ -1,7 +1,7 @@ /* * * Intel Management Engine Interface (Intel MEI) Linux driver - * Copyright (c) 2003-2011, Intel Corporation. + * Copyright (c) 2003-2012, Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, diff --git a/drivers/staging/mei/iorw.c b/drivers/staging/mei/iorw.c index 0752ead..a3fbac9 100644 --- a/drivers/staging/mei/iorw.c +++ b/drivers/staging/mei/iorw.c @@ -1,7 +1,7 @@ /* * * Intel Management Engine Interface (Intel MEI) Linux driver - * Copyright (c) 2003-2011, Intel Corporation. + * Copyright (c) 2003-2012, Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, diff --git a/drivers/staging/mei/main.c b/drivers/staging/mei/main.c index 1e1a9f9..22afc92 100644 --- a/drivers/staging/mei/main.c +++ b/drivers/staging/mei/main.c @@ -1,7 +1,7 @@ /* * * Intel Management Engine Interface (Intel MEI) Linux driver - * Copyright (c) 2003-2011, Intel Corporation. + * Copyright (c) 2003-2012, Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, diff --git a/drivers/staging/mei/mei.h b/drivers/staging/mei/mei.h index 6da7c4f..b09b11c 100644 --- a/drivers/staging/mei/mei.h +++ b/drivers/staging/mei/mei.h @@ -1,63 +1,68 @@ -/* - - Intel Management Engine Interface (Intel MEI) Linux driver - Intel MEI Interface Header - - 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) 2003-2011 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. - - Contact Information: - Intel Corporation. - linux-mei@linux.intel.com - http://www.intel.com - - - BSD LICENSE - - Copyright(c) 2003-2011 Intel Corporation. All rights reserved. - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - * Neither the name of Intel Corporation nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - +/****************************************************************************** + * Intel Management Engine Interface (Intel MEI) Linux driver + * Intel MEI Interface Header + * + * 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) 2003 - 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 Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * Contact Information: + * Intel Corporation. + * linux-mei@linux.intel.com + * http://www.intel.com + * + * BSD LICENSE + * + * Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ #ifndef _LINUX_MEI_H #define _LINUX_MEI_H diff --git a/drivers/staging/mei/mei_dev.h b/drivers/staging/mei/mei_dev.h index 82bacfc..b9957e0 100644 --- a/drivers/staging/mei/mei_dev.h +++ b/drivers/staging/mei/mei_dev.h @@ -1,7 +1,7 @@ /* * * Intel Management Engine Interface (Intel MEI) Linux driver - * Copyright (c) 2003-2011, Intel Corporation. + * Copyright (c) 2003-2012, Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, diff --git a/drivers/staging/mei/mei_version.h b/drivers/staging/mei/mei_version.h index 075bad8..21955e7 100644 --- a/drivers/staging/mei/mei_version.h +++ b/drivers/staging/mei/mei_version.h @@ -1,7 +1,7 @@ /* * * Intel Management Engine Interface (Intel MEI) Linux driver - * Copyright (c) 2003-2011, Intel Corporation. + * Copyright (c) 2003-2012, Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, diff --git a/drivers/staging/mei/wd.c b/drivers/staging/mei/wd.c index 8094941..f397835 100644 --- a/drivers/staging/mei/wd.c +++ b/drivers/staging/mei/wd.c @@ -1,7 +1,7 @@ /* * * Intel Management Engine Interface (Intel MEI) Linux driver - * Copyright (c) 2003-2011, Intel Corporation. + * Copyright (c) 2003-2012, Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, -- cgit v0.10.2 From edf1eed46636d0d34473657f24c32dc779afc85f Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Thu, 9 Feb 2012 19:25:54 +0200 Subject: staging/mei: normalize prototypes of all read buffers 1. convert all read buffers to unsigned char and drop useless castings 2. simplify mei_read_slots implementation Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/mei/interface.c b/drivers/staging/mei/interface.c index 951e61f..484be56a 100644 --- a/drivers/staging/mei/interface.c +++ b/drivers/staging/mei/interface.c @@ -215,26 +215,17 @@ int mei_count_full_read_slots(struct mei_device *dev) * @buffer: message buffer will be written * @buffer_length: message size will be read */ -void mei_read_slots(struct mei_device *dev, - unsigned char *buffer, unsigned long buffer_length) +void mei_read_slots(struct mei_device *dev, unsigned char *buffer, + unsigned long buffer_length) { - u32 i = 0; - unsigned char temp_buf[sizeof(u32)]; + u32 *reg_buf = (u32 *)buffer; - while (buffer_length >= sizeof(u32)) { - ((u32 *) buffer)[i] = mei_mecbrw_read(dev); - - dev_dbg(&dev->pdev->dev, - "buffer[%d]= %d\n", - i, ((u32 *) buffer)[i]); - - i++; - buffer_length -= sizeof(u32); - } + for (; buffer_length >= sizeof(u32); buffer_length -= sizeof(u32)) + *reg_buf++ = mei_mecbrw_read(dev); if (buffer_length > 0) { - *((u32 *) &temp_buf) = mei_mecbrw_read(dev); - memcpy(&buffer[i * 4], temp_buf, buffer_length); + u32 reg = mei_mecbrw_read(dev); + memcpy(reg_buf, ®, buffer_length); } dev->host_hw_state |= H_IG; diff --git a/drivers/staging/mei/interface.h b/drivers/staging/mei/interface.h index 3929874..e5bfb18 100644 --- a/drivers/staging/mei/interface.h +++ b/drivers/staging/mei/interface.h @@ -33,7 +33,8 @@ void mei_read_slots(struct mei_device *dev, - unsigned char *buffer, unsigned long buffer_length); + unsigned char *buffer, + unsigned long buffer_length); int mei_write_message(struct mei_device *dev, struct mei_msg_hdr *header, diff --git a/drivers/staging/mei/interrupt.c b/drivers/staging/mei/interrupt.c index 8e16e94..3c21c93 100644 --- a/drivers/staging/mei/interrupt.c +++ b/drivers/staging/mei/interrupt.c @@ -123,8 +123,7 @@ static int mei_irq_thread_read_amthi_message(struct mei_io_list *complete_list, BUG_ON(mei_hdr->me_addr != dev->iamthif_cl.me_client_id); BUG_ON(dev->iamthif_state != MEI_IAMTHIF_READING); - buffer = (unsigned char *) (dev->iamthif_msg_buf + - dev->iamthif_msg_buf_index); + buffer = dev->iamthif_msg_buf + dev->iamthif_msg_buf_index; BUG_ON(dev->iamthif_mtu < dev->iamthif_msg_buf_index + mei_hdr->length); mei_read_slots(dev, buffer, mei_hdr->length); @@ -206,9 +205,7 @@ static int mei_irq_thread_read_client_message(struct mei_io_list *complete_list, cl = (struct mei_cl *)cb_pos->file_private; if (cl && _mei_irq_thread_state_ok(cl, mei_hdr)) { cl->reading_state = MEI_READING; - buffer = (unsigned char *) - (cb_pos->response_buffer.data + - cb_pos->information); + buffer = cb_pos->response_buffer.data + cb_pos->information; if (cb_pos->response_buffer.size < mei_hdr->length + cb_pos->information) { @@ -247,8 +244,7 @@ static int mei_irq_thread_read_client_message(struct mei_io_list *complete_list, quit: dev_dbg(&dev->pdev->dev, "message read\n"); if (!buffer) { - mei_read_slots(dev, (unsigned char *) dev->rd_msg_buf, - mei_hdr->length); + mei_read_slots(dev, dev->rd_msg_buf, mei_hdr->length); dev_dbg(&dev->pdev->dev, "discarding message, header =%08x.\n", *(u32 *) dev->rd_msg_buf); } @@ -632,13 +628,11 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev, struct hbm_host_stop_request *host_stop_req; int res; - unsigned char *buffer; /* read the message to our buffer */ - buffer = (unsigned char *) dev->rd_msg_buf; BUG_ON(mei_hdr->length >= sizeof(dev->rd_msg_buf)); - mei_read_slots(dev, buffer, mei_hdr->length); - mei_msg = (struct mei_bus_message *) buffer; + mei_read_slots(dev, dev->rd_msg_buf, mei_hdr->length); + mei_msg = (struct mei_bus_message *)dev->rd_msg_buf; switch (*(u8 *) mei_msg) { case HOST_START_RES_CMD: diff --git a/drivers/staging/mei/mei_dev.h b/drivers/staging/mei/mei_dev.h index b9957e0..0d937b0 100644 --- a/drivers/staging/mei/mei_dev.h +++ b/drivers/staging/mei/mei_dev.h @@ -30,6 +30,8 @@ #define MEI_WD_PARAMS_SIZE 4 #define MEI_WD_STATE_INDEPENDENCE_MSG_SENT (1 << 0) +#define MEI_RD_MSG_BUF_SIZE (128 * sizeof(u32)) + /* * MEI PCI Device object */ @@ -125,7 +127,7 @@ enum mei_cb_major_types { */ struct mei_message_data { u32 size; - char *data; + unsigned char *data; } __packed; @@ -219,7 +221,7 @@ struct mei_device { bool need_reset; u32 extra_write_index; - u32 rd_msg_buf[128]; /* used for control messages */ + unsigned char rd_msg_buf[MEI_RD_MSG_BUF_SIZE]; /* control messages */ u32 wr_msg_buf[128]; /* used for control messages */ u32 ext_msg_buf[8]; /* for control responses */ u32 rd_msg_hdr; -- cgit v0.10.2 From c52827cc4ddf387c59b605c9d83dcaffbbf465bf Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Thu, 9 Feb 2012 19:25:55 +0200 Subject: staging/mei: add mei user space example this example tries to connect to amt host interface client and retrieve versions of its sub components When AMT is enabled an output might look like that: Intel AMT: ENABLED Flash: 6.1.0 Netstack: 6.1.0 AMTApps: 6.1.0 AMT: 6.1.0 Sku: 258 VendorID: 8086 Build Number: 1042 Recovery Version: 6.1.0 Recovery Build Num: 1042 Legacy Mode: False otherwise: Intel AMT: DISABLED Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/mei/mei-amt-version.c b/drivers/staging/mei/mei-amt-version.c new file mode 100644 index 0000000..be04934 --- /dev/null +++ b/drivers/staging/mei/mei-amt-version.c @@ -0,0 +1,479 @@ +/****************************************************************************** + * Intel Management Engine Interface (Intel MEI) Linux driver + * Intel MEI Interface Header + * + * 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) 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 Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * Contact Information: + * Intel Corporation. + * linux-mei@linux.intel.com + * http://www.intel.com + * + * BSD LICENSE + * + * Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mei.h" + +/***************************************************************************** + * Intel Management Enginin Interface + *****************************************************************************/ + +#define mei_msg(_me, fmt, ARGS...) do { \ + if (_me->verbose) \ + fprintf(stderr, fmt, ##ARGS); \ +} while (0) + +#define mei_err(_me, fmt, ARGS...) do { \ + fprintf(stderr, "Error: " fmt, ##ARGS); \ +} while (0) + +struct mei { + uuid_le guid; + bool initialized; + bool verbose; + unsigned int buf_size; + unsigned char prot_ver; + int fd; +}; + +static void mei_deinit(struct mei *cl) +{ + if (cl->fd != -1) + close(cl->fd); + cl->fd = -1; + cl->buf_size = 0; + cl->prot_ver = 0; + cl->initialized = false; +} + +static bool mei_init(struct mei *me, const uuid_le *guid, + unsigned char req_protocol_version, bool verbose) +{ + int result; + struct mei_client *cl; + struct mei_connect_client_data data; + + mei_deinit(me); + + me->verbose = verbose; + + me->fd = open("/dev/mei", O_RDWR); + if (me->fd == -1) { + mei_err(me, "Cannot establish a handle to the Intel MEI driver\n"); + goto err; + } + memcpy(&me->guid, guid, sizeof(*guid)); + memset(&data, 0, sizeof(data)); + me->initialized = true; + + memcpy(&data.in_client_uuid, &me->guid, sizeof(me->guid)); + result = ioctl(me->fd, IOCTL_MEI_CONNECT_CLIENT, &data); + if (result) { + mei_err(me, "IOCTL_MEI_CONNECT_CLIENT receive message. err=%d\n", result); + goto err; + } + cl = &data.out_client_properties; + mei_msg(me, "max_message_length %d\n", cl->max_msg_length); + mei_msg(me, "protocol_version %d\n", cl->protocol_version); + + if ((req_protocol_version > 0) && + (cl->protocol_version != req_protocol_version)) { + mei_err(me, "Intel MEI protocol version not supported\n"); + goto err; + } + + me->buf_size = cl->max_msg_length; + me->prot_ver = cl->protocol_version; + + return true; +err: + mei_deinit(me); + return false; +} + +static ssize_t mei_recv_msg(struct mei *me, unsigned char *buffer, + ssize_t len, unsigned long timeout) +{ + ssize_t rc; + + mei_msg(me, "call read length = %zd\n", len); + + rc = read(me->fd, buffer, len); + if (rc < 0) { + mei_err(me, "read failed with status %zd %s\n", + rc, strerror(errno)); + mei_deinit(me); + } else { + mei_msg(me, "read succeeded with result %zd\n", rc); + } + return rc; +} + +static ssize_t mei_send_msg(struct mei *me, const unsigned char *buffer, + ssize_t len, unsigned long timeout) +{ + struct timeval tv; + ssize_t written; + ssize_t rc; + fd_set set; + + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000000; + + mei_msg(me, "call write length = %zd\n", len); + + written = write(me->fd, buffer, len); + if (written < 0) { + rc = -errno; + mei_err(me, "write failed with status %zd %s\n", + written, strerror(errno)); + goto out; + } + + FD_ZERO(&set); + FD_SET(me->fd, &set); + rc = select(me->fd + 1 , &set, NULL, NULL, &tv); + if (rc > 0 && FD_ISSET(me->fd, &set)) { + mei_msg(me, "write success\n"); + } else if (rc == 0) { + mei_err(me, "write failed on timeout with status\n"); + goto out; + } else { /* rc < 0 */ + mei_err(me, "write failed on select with status %zd\n", rc); + goto out; + } + + rc = written; +out: + if (rc < 0) + mei_deinit(me); + + return rc; +} + +/*************************************************************************** + * Intel Advanced Management Technolgy ME Client + ***************************************************************************/ + +#define AMT_MAJOR_VERSION 1 +#define AMT_MINOR_VERSION 1 + +#define AMT_STATUS_SUCCESS 0x0 +#define AMT_STATUS_INTERNAL_ERROR 0x1 +#define AMT_STATUS_NOT_READY 0x2 +#define AMT_STATUS_INVALID_AMT_MODE 0x3 +#define AMT_STATUS_INVALID_MESSAGE_LENGTH 0x4 + +#define AMT_STATUS_HOST_IF_EMPTY_RESPONSE 0x4000 +#define AMT_STATUS_SDK_RESOURCES 0x1004 + + +#define AMT_BIOS_VERSION_LEN 65 +#define AMT_VERSIONS_NUMBER 50 +#define AMT_UNICODE_STRING_LEN 20 + +struct amt_unicode_string { + uint16_t length; + char string[AMT_UNICODE_STRING_LEN]; +} __attribute__((packed)); + +struct amt_version_type { + struct amt_unicode_string description; + struct amt_unicode_string version; +} __attribute__((packed)); + +struct amt_version { + uint8_t major; + uint8_t minor; +} __attribute__((packed)); + +struct amt_code_versions { + uint8_t bios[AMT_BIOS_VERSION_LEN]; + uint32_t count; + struct amt_version_type versions[AMT_VERSIONS_NUMBER]; +} __attribute__((packed)); + +/*************************************************************************** + * Intel Advanced Management Technolgy Host Interface + ***************************************************************************/ + +struct amt_host_if_msg_header { + struct amt_version version; + uint16_t _reserved; + uint32_t command; + uint32_t length; +} __attribute__((packed)); + +struct amt_host_if_resp_header { + struct amt_host_if_msg_header header; + uint32_t status; + unsigned char data[0]; +} __attribute__((packed)); + +const uuid_le MEI_IAMTHIF = UUID_LE(0x12f80028, 0xb4b7, 0x4b2d, \ + 0xac, 0xa8, 0x46, 0xe0, 0xff, 0x65, 0x81, 0x4c); + +#define AMT_HOST_IF_CODE_VERSIONS_REQUEST 0x0400001A +#define AMT_HOST_IF_CODE_VERSIONS_RESPONSE 0x0480001A + +const struct amt_host_if_msg_header CODE_VERSION_REQ = { + .version = {AMT_MAJOR_VERSION, AMT_MINOR_VERSION}, + ._reserved = 0, + .command = AMT_HOST_IF_CODE_VERSIONS_REQUEST, + .length = 0 +}; + + +struct amt_host_if { + struct mei mei_cl; + unsigned long send_timeout; + bool initialized; +}; + + +bool amt_host_if_init(struct amt_host_if *acmd, + unsigned long send_timeout, bool verbose) +{ + acmd->send_timeout = (send_timeout) ? send_timeout : 20000; + acmd->initialized = mei_init(&acmd->mei_cl, &MEI_IAMTHIF, 0, verbose); + return acmd->initialized; +} + +void amt_host_if_deinit(struct amt_host_if *acmd) +{ + mei_deinit(&acmd->mei_cl); + acmd->initialized = false; +} + +uint32_t amt_verify_code_versions(const struct amt_host_if_resp_header *resp) +{ + uint32_t status = AMT_STATUS_SUCCESS; + struct amt_code_versions *code_ver; + size_t code_ver_len; + uint32_t ver_type_cnt; + uint32_t len; + uint32_t i; + + code_ver = (struct amt_code_versions *)resp->data; + /* length - sizeof(status) */ + code_ver_len = resp->header.length - sizeof(uint32_t); + ver_type_cnt = code_ver_len - + sizeof(code_ver->bios) - + sizeof(code_ver->count); + if (code_ver->count != ver_type_cnt / sizeof(struct amt_version_type)) { + status = AMT_STATUS_INTERNAL_ERROR; + goto out; + } + + for (i = 0; i < code_ver->count; i++) { + len = code_ver->versions[i].description.length; + + if (len > AMT_UNICODE_STRING_LEN) { + status = AMT_STATUS_INTERNAL_ERROR; + goto out; + } + + len = code_ver->versions[i].version.length; + if (code_ver->versions[i].version.string[len] != '\0' || + len != strlen(code_ver->versions[i].version.string)) { + status = AMT_STATUS_INTERNAL_ERROR; + goto out; + } + } +out: + return status; +} + +uint32_t amt_verify_response_header(uint32_t command, + const struct amt_host_if_msg_header *resp_hdr, + uint32_t response_size) +{ + if (response_size < sizeof(struct amt_host_if_resp_header)) { + return AMT_STATUS_INTERNAL_ERROR; + } else if (response_size != (resp_hdr->length + + sizeof(struct amt_host_if_msg_header))) { + return AMT_STATUS_INTERNAL_ERROR; + } else if (resp_hdr->command != command) { + return AMT_STATUS_INTERNAL_ERROR; + } else if (resp_hdr->_reserved != 0) { + return AMT_STATUS_INTERNAL_ERROR; + } else if (resp_hdr->version.major != AMT_MAJOR_VERSION || + resp_hdr->version.minor < AMT_MINOR_VERSION) { + return AMT_STATUS_INTERNAL_ERROR; + } + return AMT_STATUS_SUCCESS; +} + +static uint32_t amt_host_if_call(struct amt_host_if *acmd, + const unsigned char *command, ssize_t command_sz, + uint8_t **read_buf, uint32_t rcmd, + unsigned int expected_sz) +{ + uint32_t in_buf_sz; + uint32_t out_buf_sz; + ssize_t written; + uint32_t status; + struct amt_host_if_resp_header *msg_hdr; + + in_buf_sz = acmd->mei_cl.buf_size; + *read_buf = (uint8_t *)malloc(sizeof(uint8_t) * in_buf_sz); + if (*read_buf == NULL) + return AMT_STATUS_SDK_RESOURCES; + memset(*read_buf, 0, in_buf_sz); + msg_hdr = (struct amt_host_if_resp_header *)*read_buf; + + written = mei_send_msg(&acmd->mei_cl, + command, command_sz, acmd->send_timeout); + if (written != command_sz) + return AMT_STATUS_INTERNAL_ERROR; + + out_buf_sz = mei_recv_msg(&acmd->mei_cl, *read_buf, in_buf_sz, 2000); + if (out_buf_sz <= 0) + return AMT_STATUS_HOST_IF_EMPTY_RESPONSE; + + status = msg_hdr->status; + if (status != AMT_STATUS_SUCCESS) + return status; + + status = amt_verify_response_header(rcmd, + &msg_hdr->header, out_buf_sz); + if (status != AMT_STATUS_SUCCESS) + return status; + + if (expected_sz && expected_sz != out_buf_sz) + return AMT_STATUS_INTERNAL_ERROR; + + return AMT_STATUS_SUCCESS; +} + + +uint32_t amt_get_code_versions(struct amt_host_if *cmd, + struct amt_code_versions *versions) +{ + struct amt_host_if_resp_header *response = NULL; + uint32_t status; + + status = amt_host_if_call(cmd, + (const unsigned char *)&CODE_VERSION_REQ, + sizeof(CODE_VERSION_REQ), + (uint8_t **)&response, + AMT_HOST_IF_CODE_VERSIONS_RESPONSE, 0); + + if (status != AMT_STATUS_SUCCESS) + goto out; + + status = amt_verify_code_versions(response); + if (status != AMT_STATUS_SUCCESS) + goto out; + + memcpy(versions, response->data, sizeof(struct amt_code_versions)); +out: + if (response != NULL) + free(response); + + return status; +} + +/************************** end of amt_host_if_command ***********************/ +int main(int argc, char **argv) +{ + struct amt_code_versions ver; + struct amt_host_if acmd; + unsigned int i; + uint32_t status; + int ret; + bool verbose; + + verbose = (argc > 1 && strcmp(argv[1], "-v") == 0); + + if (!amt_host_if_init(&acmd, 5000, verbose)) { + ret = 1; + goto out; + } + + status = amt_get_code_versions(&acmd, &ver); + + switch (status) { + case AMT_STATUS_HOST_IF_EMPTY_RESPONSE: + printf("Intel AMT: DISABLED\n"); + ret = 0; + break; + case AMT_STATUS_SUCCESS: + printf("Intel AMT: ENABLED\n"); + for (i = 0; i < ver.count; i++) { + printf("%s:\t%s\n", ver.versions[i].description.string, + ver.versions[i].version.string); + } + ret = 0; + break; + default: + printf("An error has occurred\n"); + ret = 1; + break; + } + +out: + return ret; +} -- cgit v0.10.2 From 190f998b7951bcb8aff7e1fd023f25d0adcc5045 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Thu, 9 Feb 2012 19:25:56 +0200 Subject: staging/mei: TODO : how to handle example code after unstaging Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/mei/TODO b/drivers/staging/mei/TODO index 7d9a13b..fc26601 100644 --- a/drivers/staging/mei/TODO +++ b/drivers/staging/mei/TODO @@ -3,5 +3,8 @@ TODO: Upon Unstaging: - move mei.h to include/linux/mei.h - Documentation/ioctl/ioctl-number.txt + - move mei.txt under Documentation/mei/ + - move mei-amt-version.c under Documentation/mei + - add hostprogs-y for mei-amt-version.c - drop mei_version.h - Updated MAINTAINERS -- cgit v0.10.2 From 3e150cf51d9242ae4ef9c872cdf6766ee5115c44 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 17 Jan 2012 10:31:52 +0300 Subject: Staging: sbe-2t3e3: logical || vs bitwise | Bitwise OR was clearly intended here. Signed-off-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/sbe-2t3e3/intr.c b/drivers/staging/sbe-2t3e3/intr.c index 7ad1a83..1336aab 100644 --- a/drivers/staging/sbe-2t3e3/intr.c +++ b/drivers/staging/sbe-2t3e3/intr.c @@ -188,7 +188,7 @@ void dc_intr_rx(struct channel *sc) } if (sc->s.LOS) { - error_mask &= ~(SBE_2T3E3_RX_DESC_DRIBBLING_BIT || + error_mask &= ~(SBE_2T3E3_RX_DESC_DRIBBLING_BIT | SBE_2T3E3_RX_DESC_MII_ERROR); } -- cgit v0.10.2 From d0bc218b0a75bbddc9ef54aac6d9cc65a7a58661 Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Wed, 25 Jan 2012 00:35:41 +0900 Subject: staging: Fix typo in ieee80211_rx.c Correct spelling "suppported" to "supported" in drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c Signed-off-by: Masanari iida Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c index c9bdc7f..be2a28c 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c @@ -237,7 +237,7 @@ ieee80211_rx_frame_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb, #ifdef NOT_YET if (ieee->iw_mode == IW_MODE_MASTER) { - printk(KERN_DEBUG "%s: Master mode not yet suppported.\n", + printk(KERN_DEBUG "%s: Master mode not yet supported.\n", ieee->dev->name); return 0; /* -- cgit v0.10.2 From 881763361e8283a6d33d5a30ac6edc36e7dc6d44 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Sun, 29 Jan 2012 21:55:28 +0100 Subject: staging, media, easycap: Fix mem leak in easycap_usb_probe() If allocating 'pdata_urb' fails, the function will return -ENOMEM without freeing the memory allocated, just a few lines above, for 'purb' and will leak that memory when 'purb' goes out of scope. This patch resolves the leak by freeing the allocated storage with usb_free_urb() before the return. Signed-off-by: Jesper Juhl Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/media/easycap/easycap_main.c b/drivers/staging/media/easycap/easycap_main.c index 8ff5f38..3d439b7 100644 --- a/drivers/staging/media/easycap/easycap_main.c +++ b/drivers/staging/media/easycap/easycap_main.c @@ -3825,6 +3825,7 @@ static int easycap_usb_probe(struct usb_interface *intf, /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ pdata_urb = kzalloc(sizeof(struct data_urb), GFP_KERNEL); if (!pdata_urb) { + usb_free_urb(purb); SAM("ERROR: Could not allocate struct data_urb.\n"); return -ENOMEM; } -- cgit v0.10.2 From 2e254212942e483eba4753830268045ac87ea224 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 31 Jan 2012 11:45:15 +0300 Subject: Staging: wlan-ng: cap the ssid length We're getting the ssid length from the scan here. Let's cap it before doing the memcpy(). Signed-off-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/wlan-ng/prism2mgmt.c b/drivers/staging/wlan-ng/prism2mgmt.c index 6675c82..c3bb05d 100644 --- a/drivers/staging/wlan-ng/prism2mgmt.c +++ b/drivers/staging/wlan-ng/prism2mgmt.c @@ -406,6 +406,7 @@ int prism2mgmt_scan_results(wlandevice_t *wlandev, void *msgp) /* SSID */ req->ssid.status = P80211ENUM_msgitem_status_data_ok; req->ssid.data.len = le16_to_cpu(item->ssid.len); + req->ssid.data.len = min_t(u16, req->ssid.data.len, WLAN_BSSID_LEN); memcpy(req->ssid.data.data, item->ssid.data, req->ssid.data.len); /* supported rates */ -- cgit v0.10.2 From 586b9839273b3b58b28a26e4518be13366cecaeb Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 9 Jan 2012 15:48:19 +0000 Subject: staging: comedi: ni_pcimio: Add support for NI PXIe-6251 Paul Fulmek reports that PXIe-6251 works the same as the existing PCIe-6251 and just needs the new PCI device ID adding to ni_pci_table[] and a new entry adding to ni_boards[] based on the existing entry for PCIe-6251. The new entry has PCI device ID 0x72e8 and board name "pxie-6251". Thanks Paul! Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c index 0f0d995..27baefa 100644 --- a/drivers/staging/comedi/drivers/ni_pcimio.c +++ b/drivers/staging/comedi/drivers/ni_pcimio.c @@ -29,14 +29,15 @@ Devices: [National Instruments] PCI-MIO-16XE-50 (ni_pcimio), PCI-MIO-16XE-10, PXI-6030E, PCI-MIO-16E-1, PCI-MIO-16E-4, PCI-6014, PCI-6040E, PXI-6040E, PCI-6030E, PCI-6031E, PCI-6032E, PCI-6033E, PCI-6071E, PCI-6023E, PCI-6024E, PCI-6025E, PXI-6025E, PCI-6034E, PCI-6035E, PCI-6052E, - PCI-6110, PCI-6111, PCI-6220, PCI-6221, PCI-6224, PXI-6224, PCI-6225, PXI-6225, - PCI-6229, PCI-6250, PCI-6251, PCIe-6251, PCI-6254, PCI-6259, PCIe-6259, + PCI-6110, PCI-6111, PCI-6220, PCI-6221, PCI-6224, PXI-6224, + PCI-6225, PXI-6225, PCI-6229, PCI-6250, PCI-6251, PCIe-6251, PXIe-6251, + PCI-6254, PCI-6259, PCIe-6259, PCI-6280, PCI-6281, PXI-6281, PCI-6284, PCI-6289, PCI-6711, PXI-6711, PCI-6713, PXI-6713, PXI-6071E, PCI-6070E, PXI-6070E, PXI-6052E, PCI-6036E, PCI-6731, PCI-6733, PXI-6733, PCI-6143, PXI-6143 -Updated: Wed, 03 Dec 2008 10:51:47 +0000 +Updated: Mon, 09 Jan 2012 14:52:48 +0000 These boards are almost identical to the AT-MIO E series, except that they use the PCI bus instead of ISA (i.e., AT). See the notes for @@ -182,6 +183,7 @@ static DEFINE_PCI_DEVICE_TABLE(ni_pci_table) = { {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x717f)}, {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x71bc)}, {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x717d)}, + {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x72e8)}, {0} }; @@ -1046,6 +1048,25 @@ static const struct ni_board_struct ni_boards[] = { .has_8255 = 0, }, { + .device_id = 0x72e8, + .name = "pxie-6251", + .n_adchan = 16, + .adbits = 16, + .ai_fifo_depth = 4095, + .gainlkup = ai_gain_628x, + .ai_speed = 800, + .n_aochan = 2, + .aobits = 16, + .ao_fifo_depth = 8191, + .ao_range_table = &range_ni_M_625x_ao, + .reg_type = ni_reg_625x, + .ao_unipolar = 0, + .ao_speed = 357, + .num_p0_dio_channels = 8, + .caldac = {caldac_none}, + .has_8255 = 0, + }, + { .device_id = 0x70b7, .name = "pci-6254", .n_adchan = 32, -- cgit v0.10.2 From 8383def69b8629df052f917acb844381bdd6e000 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 9 Jan 2012 15:48:35 +0000 Subject: staging: comedi: dt2801: do INSN_CONFIG properly for DIO subdevice. Handle INSN_CONFIG_DIO_INPUT, INSN_CONFIG_DIO_OUTPUT and INSN_CONFIG_DIO_QUERY in data[0]. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/dt2801.c b/drivers/staging/comedi/drivers/dt2801.c index 5cce1b5..b85c836 100644 --- a/drivers/staging/comedi/drivers/dt2801.c +++ b/drivers/staging/comedi/drivers/dt2801.c @@ -720,12 +720,20 @@ static int dt2801_dio_insn_config(struct comedi_device *dev, which = 1; /* configure */ - if (data[0]) { + switch (data[0]) { + case INSN_CONFIG_DIO_OUTPUT: s->io_bits = 0xff; dt2801_writecmd(dev, DT_C_SET_DIGOUT); - } else { + break; + case INSN_CONFIG_DIO_INPUT: s->io_bits = 0; dt2801_writecmd(dev, DT_C_SET_DIGIN); + break; + case INSN_CONFIG_DIO_QUERY: + data[1] = s->io_bits ? COMEDI_OUTPUT : COMEDI_INPUT; + return insn->n; + default: + return -EINVAL; } dt2801_writedata(dev, which); -- cgit v0.10.2 From f3445c1e5915bc554da1ee524b17c5d59e921ebc Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 9 Jan 2012 15:48:56 +0000 Subject: staging: comedi: me4000: Check for unsupported INSN_CONFIG. The INSN_CONFIG handler for the DIO subdevice should error out for unsupported configuration instruction codes. Also fix incorrect use of constant COMEDI_OUTPUT where INSN_CONFIG_DIO_OUTPUT was meant. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c index b692fea..b0bc6bb 100644 --- a/drivers/staging/comedi/drivers/me4000.c +++ b/drivers/staging/comedi/drivers/me4000.c @@ -2098,23 +2098,29 @@ static int me4000_dio_insn_config(struct comedi_device *dev, CALL_PDEBUG("In me4000_dio_insn_config()\n"); - if (data[0] == INSN_CONFIG_DIO_QUERY) { + switch (data[0]) { + default: + return -EINVAL; + case INSN_CONFIG_DIO_QUERY: data[1] = (s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT; return insn->n; + case INSN_CONFIG_DIO_INPUT: + case INSN_CONFIG_DIO_OUTPUT: + break; } /* * The input or output configuration of each digital line is * configured by a special insn_config instruction. chanspec * contains the channel to be changed, and data[0] contains the - * value COMEDI_INPUT or COMEDI_OUTPUT. + * value INSN_CONFIG_DIO_INPUT or INSN_CONFIG_DIO_OUTPUT. * On the ME-4000 it is only possible to switch port wise (8 bit) */ tmp = me4000_inl(dev, info->dio_context.ctrl_reg); - if (data[0] == COMEDI_OUTPUT) { + if (data[0] == INSN_CONFIG_DIO_OUTPUT) { if (chan < 8) { s->io_bits |= 0xFF; tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_0 | -- cgit v0.10.2 From 9e77e6b62e699fe23a4648ac438115c5fc952e42 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 9 Jan 2012 15:45:45 +0000 Subject: staging: comedi: adv_pci_dio: Advantech PCI-1739U support This patch is ported over by me (Ian Abbott) from the out-of-tree Comedi git repository at "git://comedi.org/git/comedi/comedi.git". The original patch is by Nicholas Nell. ----- Advantech PCI-1739U support Hello, I've added a bit of simple configuration to adv_pci_dio.c in order to make the PCI-1739U work with the adv_pci_dio driver. I have tested inputs only so far but they seem to work. A git style patch is attached. Thanks, -- Nicholas Nell Professional Research Assistant University of Colorado ----- Signed-off-by: Ian Abbott Cc: Nico Nell Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig index 4c77e50..12c691d 100644 --- a/drivers/staging/comedi/Kconfig +++ b/drivers/staging/comedi/Kconfig @@ -765,8 +765,9 @@ config COMEDI_ADV_PCI_DIO default N ---help--- Enable support for Advantech PCI DIO cards - PCI-1730, PCI-1733, PCI-1734, PCI-1736UP, PCI-1750, PCI-1751, - PCI-1752, PCI-1753/E, PCI-1754, PCI-1756 and PCI-1762 + PCI-1730, PCI-1733, PCI-1734, PCI-1735U, PCI-1736UP, PCI-1739U, + PCI-1750, PCI-1751, PCI-1752, PCI-1753/E, PCI-1754, PCI-1756, + PCI-1760 and PCI-1762 To compile this driver as a module, choose M here: the module will be called adv_pci_dio. diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c index 537e585..7af068f 100644 --- a/drivers/staging/comedi/drivers/adv_pci_dio.c +++ b/drivers/staging/comedi/drivers/adv_pci_dio.c @@ -8,16 +8,16 @@ /* Driver: adv_pci_dio Description: Advantech PCI-1730, PCI-1733, PCI-1734, PCI-1735U, - PCI-1736UP, PCI-1750, PCI-1751, PCI-1752, PCI-1753/E, - PCI-1754, PCI-1756, PCI-1762 + PCI-1736UP, PCI-1739U, PCI-1750, PCI-1751, PCI-1752, + PCI-1753/E, PCI-1754, PCI-1756, PCI-1760, PCI-1762 Author: Michal Dobes Devices: [Advantech] PCI-1730 (adv_pci_dio), PCI-1733, - PCI-1734, PCI-1735U, PCI-1736UP, PCI-1750, + PCI-1734, PCI-1735U, PCI-1736UP, PCI-1739U, PCI-1750, PCI-1751, PCI-1752, PCI-1753, PCI-1753+PCI-1753E, PCI-1754, PCI-1756, PCI-1760, PCI-1762 Status: untested -Updated: Tue, 04 May 2010 13:00:00 +0000 +Updated: Mon, 09 Jan 2012 12:40:46 +0000 This driver supports now only insn interface for DI/DO/DIO. @@ -51,6 +51,7 @@ Configuration options: /* hardware types of the cards */ enum hw_cards_id { TYPE_PCI1730, TYPE_PCI1733, TYPE_PCI1734, TYPE_PCI1735, TYPE_PCI1736, + TYPE_PCI1739, TYPE_PCI1750, TYPE_PCI1751, TYPE_PCI1752, @@ -109,6 +110,12 @@ enum hw_io_access { #define PCI1736_BOARDID 4 /* R: Board I/D switch for 1736UP */ #define PCI1736_MAINREG 0 /* Normal register (2) doesn't work */ +/* Advantech PCI-1739U */ +#define PCI1739_DIO 0 /* R/W: begin of 8255 registers block */ +#define PCI1739_ICR 32 /* W: Interrupt control register */ +#define PCI1739_ISR 32 /* R: Interrupt status register */ +#define PCI1739_BOARDID 8 /* R: Board I/D switch for 1739U */ + /* Advantech PCI-1750 */ #define PCI1750_IDI 0 /* R: Isolated digital input 0-15 */ #define PCI1750_IDO 0 /* W: Isolated digital output 0-15 */ @@ -262,6 +269,7 @@ static DEFINE_PCI_DEVICE_TABLE(pci_dio_pci_table) = { { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1734) }, { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1735) }, { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1736) }, + { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1739) }, { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1750) }, { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1751) }, { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1752) }, @@ -316,6 +324,14 @@ static const struct dio_boardtype boardtypes[] = { {4, PCI1736_BOARDID, 1, SDF_INTERNAL}, { {0, 0, 0, 0} }, IO_8b}, + {"pci1739", PCI_VENDOR_ID_ADVANTECH, 0x1739, PCIDIO_MAINREG, + TYPE_PCI1739, + { {0, 0, 0, 0}, {0, 0, 0, 0} }, + { {0, 0, 0, 0}, {0, 0, 0, 0} }, + { {48, PCI1739_DIO, 2, 0}, {0, 0, 0, 0} }, + {0, 0, 0, 0}, + { {0, 0, 0, 0} }, + IO_8b}, {"pci1750", PCI_VENDOR_ID_ADVANTECH, 0x1750, PCIDIO_MAINREG, TYPE_PCI1750, { {0, 0, 0, 0}, {16, PCI1750_IDI, 2, 0} }, @@ -883,6 +899,11 @@ static int pci_dio_reset(struct comedi_device *dev) outb(0, dev->iobase + PCI1736_3_INT_RF); break; + case TYPE_PCI1739: + /* disable & clear interrupts */ + outb(0x88, dev->iobase + PCI1739_ICR); + break; + case TYPE_PCI1750: case TYPE_PCI1751: /* disable & clear interrupts */ -- cgit v0.10.2 From 41add2e84bff0c887949698e01dab28105f11a6b Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 9 Jan 2012 15:47:30 +0000 Subject: staging: comedi: ni_pcidio: Mark buffer for writing when setting up DMA. When setting up the DMA for 'read' streaming acquisition on the DIO subdevice, mark the whole buffer as writable before starting the DMA. This prevents a spurious detection of a DMA overwrite of good data during the first interrupt. Problem reported by Nicholas Nell. Fix suggested by Frank Mori Hess. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c index 045a4c0..c9e5f2b 100644 --- a/drivers/staging/comedi/drivers/ni_pcidio.c +++ b/drivers/staging/comedi/drivers/ni_pcidio.c @@ -1012,6 +1012,9 @@ static int setup_mite_dma(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->di_mite_chan->dir = COMEDI_INPUT; + /* write alloc the entire buffer */ + comedi_buf_write_alloc(s->async, s->async->prealloc_bufsz); + mite_prep_dma(devpriv->di_mite_chan, 32, 32); mite_dma_arm(devpriv->di_mite_chan); -- cgit v0.10.2 From e3794b52f56ac20947a2dbdd505e9ad29013c555 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 9 Jan 2012 15:47:31 +0000 Subject: staging: comedi: ni_pcidio: Grab MITE spinlock while preparing DMA. When setting up the DMA for 'read' streaming acquisition command, grab the MITE channel spinlock before preparing and arming the DMA. Change inspired by ni_ai_setup_MITE_dma() in ni_mio_common.c. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c index c9e5f2b..5145bf1 100644 --- a/drivers/staging/comedi/drivers/ni_pcidio.c +++ b/drivers/staging/comedi/drivers/ni_pcidio.c @@ -436,6 +436,7 @@ static int ni_pcidio_request_di_mite_channel(struct comedi_device *dev) comedi_error(dev, "failed to reserve mite dma channel."); return -EBUSY; } + devpriv->di_mite_chan->dir = COMEDI_INPUT; writeb(primary_DMAChannel_bits(devpriv->di_mite_chan->channel) | secondary_DMAChannel_bits(devpriv->di_mite_chan->channel), devpriv->mite->daq_io_addr + DMA_Line_Control_Group1); @@ -1005,20 +1006,24 @@ static int ni_pcidio_cmd(struct comedi_device *dev, struct comedi_subdevice *s) static int setup_mite_dma(struct comedi_device *dev, struct comedi_subdevice *s) { int retval; + unsigned long flags; retval = ni_pcidio_request_di_mite_channel(dev); if (retval) return retval; - devpriv->di_mite_chan->dir = COMEDI_INPUT; - /* write alloc the entire buffer */ comedi_buf_write_alloc(s->async, s->async->prealloc_bufsz); - mite_prep_dma(devpriv->di_mite_chan, 32, 32); + spin_lock_irqsave(&devpriv->mite_channel_lock, flags); + if (devpriv->di_mite_chan) { + mite_prep_dma(devpriv->di_mite_chan, 32, 32); + mite_dma_arm(devpriv->di_mite_chan); + } else + retval = -EIO; + spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); - mite_dma_arm(devpriv->di_mite_chan); - return 0; + return retval; } static int ni_pcidio_inttrig(struct comedi_device *dev, -- cgit v0.10.2 From 02f69d67684b77f7f04e281a026a790f0e08b3a3 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 9 Jan 2012 18:35:53 +0000 Subject: staging: comedi: ni_pcidio: Add comedi_poll support This patch is ported over by me (Ian Abbott) from the out-of-tree Comedi git repository at "git://comedi.org/git/comedi/comedi.git". The original patch is by Nicholas Nell. The patch adds support for the COMEDI_POLL ioctl to the ni_pcidio driver. Signed-off-by: Ian Abbott Cc: Nicholas Nell Cc: Dan Carpenter Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c index 5145bf1..88728bd 100644 --- a/drivers/staging/comedi/drivers/ni_pcidio.c +++ b/drivers/staging/comedi/drivers/ni_pcidio.c @@ -483,6 +483,21 @@ void ni_pcidio_event(struct comedi_device *dev, struct comedi_subdevice *s) comedi_event(dev, s); } +static int ni_pcidio_poll(struct comedi_device *dev, struct comedi_subdevice *s) +{ + unsigned long irq_flags; + int count; + + spin_lock_irqsave(&dev->spinlock, irq_flags); + spin_lock(&devpriv->mite_channel_lock); + if (devpriv->di_mite_chan) + mite_sync_input_dma(devpriv->di_mite_chan, s->async); + spin_unlock(&devpriv->mite_channel_lock); + count = s->async->buf_write_count - s->async->buf_read_count; + spin_unlock_irqrestore(&dev->spinlock, irq_flags); + return count; +} + static irqreturn_t nidio_interrupt(int irq, void *d) { struct comedi_device *dev = d; @@ -498,7 +513,6 @@ static irqreturn_t nidio_interrupt(int irq, void *d) int status; int work = 0; unsigned int m_status = 0; - unsigned long irq_flags; /* interrupcions parasites */ if (dev->attached == 0) { @@ -506,6 +520,9 @@ static irqreturn_t nidio_interrupt(int irq, void *d) return IRQ_NONE; } + /* Lock to avoid race with comedi_poll */ + spin_lock(&dev->spinlock); + status = readb(devpriv->mite->daq_io_addr + Interrupt_And_Window_Status); flags = readb(devpriv->mite->daq_io_addr + Group_1_Flags); @@ -519,7 +536,7 @@ static irqreturn_t nidio_interrupt(int irq, void *d) /* printk("buf[4096]=%08x\n", *(unsigned int *)(async->prealloc_buf+4096)); */ - spin_lock_irqsave(&devpriv->mite_channel_lock, irq_flags); + spin_lock(&devpriv->mite_channel_lock); if (devpriv->di_mite_chan) m_status = mite_get_status(devpriv->di_mite_chan); #ifdef MITE_DEBUG @@ -544,7 +561,7 @@ static irqreturn_t nidio_interrupt(int irq, void *d) disable_irq(dev->irq); } } - spin_unlock_irqrestore(&devpriv->mite_channel_lock, irq_flags); + spin_unlock(&devpriv->mite_channel_lock); while (status & DataLeft) { work++; @@ -646,6 +663,8 @@ out: Master_DMA_And_Interrupt_Control); } #endif + + spin_unlock(&dev->spinlock); return IRQ_HANDLED; } @@ -1252,6 +1271,7 @@ static int nidio_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->len_chanlist = 32; /* XXX */ s->buf_change = &ni_pcidio_change; s->async_dma_dir = DMA_BIDIRECTIONAL; + s->poll = &ni_pcidio_poll; writel(0, devpriv->mite->daq_io_addr + Port_IO(0)); writel(0, devpriv->mite->daq_io_addr + Port_Pin_Directions(0)); -- cgit v0.10.2 From 22494ed9b8e9404d6646f85c835bcd7b37d3f562 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 9 Jan 2012 15:47:33 +0000 Subject: staging: comedi: ni_pcidio: Support trailing edge external trigger This patch is ported over by me (Ian Abbott) from the out-of-tree Comedi git repository at "git://comedi.org/git/comedi/comedi.git". The original patch is by Nicholas Nell. The patch adds support for trailing (falling) edge external triggers for scans in asynchronous command support in the ni_pcidio driver. This is supported at least on the PCI-DIO_32HS and PCI-6533 boards; not sure about the other boards. Signed-off-by: Ian Abbott Cc: Nicholas Nell Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c index 88728bd..1df8fcb 100644 --- a/drivers/staging/comedi/drivers/ni_pcidio.c +++ b/drivers/staging/comedi/drivers/ni_pcidio.c @@ -30,7 +30,7 @@ Status: works Devices: [National Instruments] PCI-DIO-32HS (ni_pcidio), PXI-6533, PCI-DIO-96, PCI-DIO-96B, PXI-6508, PCI-6503, PCI-6503B, PCI-6503X, PXI-6503, PCI-6533, PCI-6534 -Updated: Sun, 21 Apr 2002 21:03:38 -0700 +Updated: Mon, 09 Jan 2012 14:27:23 +0000 The DIO-96 appears as four 8255 subdevices. See the 8255 driver notes for details. @@ -42,6 +42,11 @@ supports simple digital I/O; no handshaking is supported. DMA mostly works for the PCI-DIO32HS, but only in timed input mode. +The PCI-DIO-32HS/PCI-6533 has a configurable external trigger. Setting +scan_begin_arg to 0 or CR_EDGE triggers on the leading edge. Setting +scan_begin_arg to CR_INVERT or (CR_EDGE | CR_INVERT) triggers on the +trailing edge. + This driver could be easily modified to support AT-MIO32HS and AT-MIO96. @@ -845,8 +850,8 @@ static int ni_pcidio_cmdtest(struct comedi_device *dev, } else { /* TRIG_EXT */ /* should be level/edge, hi/lo specification here */ - if (cmd->scan_begin_arg != 0) { - cmd->scan_begin_arg = 0; + if ((cmd->scan_begin_arg & ~(CR_EDGE | CR_INVERT)) != 0) { + cmd->scan_begin_arg &= (CR_EDGE | CR_INVERT); err++; } } @@ -961,7 +966,13 @@ static int ni_pcidio_cmd(struct comedi_device *dev, struct comedi_subdevice *s) writeb(0, devpriv->mite->daq_io_addr + Sequence); writeb(0x00, devpriv->mite->daq_io_addr + ReqReg); writeb(4, devpriv->mite->daq_io_addr + BlockMode); - writeb(0, devpriv->mite->daq_io_addr + LinePolarities); + if (!(cmd->scan_begin_arg & CR_INVERT)) { + /* Leading Edge pulse mode */ + writeb(0, devpriv->mite->daq_io_addr + LinePolarities); + } else { + /* Trailing Edge pulse mode */ + writeb(2, devpriv->mite->daq_io_addr + LinePolarities); + } writeb(0x00, devpriv->mite->daq_io_addr + AckSer); writel(1, devpriv->mite->daq_io_addr + StartDelay); writeb(1, devpriv->mite->daq_io_addr + ReqDelay); -- cgit v0.10.2 From cba2c99363beb532c29f9aebf5b22878d88bcb93 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 17 Jan 2012 10:31:13 +0300 Subject: Staging: comedi: logical || vs bitwise | These are bitfields and the intend was to OR them together. A logical OR here is simply 1. Signed-off-by: Dan Carpenter Acked-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/dt9812.c b/drivers/staging/comedi/drivers/dt9812.c index 32d9c42..e86ab58 100644 --- a/drivers/staging/comedi/drivers/dt9812.c +++ b/drivers/staging/comedi/drivers/dt9812.c @@ -527,7 +527,7 @@ static void dt9812_configure_gain(struct usb_dt9812 *dev, * 11x -> Gain = 0.5 */ case DT9812_GAIN_0PT5: - rmw->or_value = F020_MASK_ADC0CF_AMP0GN2 || + rmw->or_value = F020_MASK_ADC0CF_AMP0GN2 | F020_MASK_ADC0CF_AMP0GN1; break; case DT9812_GAIN_1: @@ -540,7 +540,7 @@ static void dt9812_configure_gain(struct usb_dt9812 *dev, rmw->or_value = F020_MASK_ADC0CF_AMP0GN1; break; case DT9812_GAIN_8: - rmw->or_value = F020_MASK_ADC0CF_AMP0GN1 || + rmw->or_value = F020_MASK_ADC0CF_AMP0GN1 | F020_MASK_ADC0CF_AMP0GN0; break; case DT9812_GAIN_16: -- cgit v0.10.2 From 4ee195241a3d9384ad222da7c593f7565a7cf518 Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Thu, 22 Dec 2011 18:44:43 -0800 Subject: staging:iio: isl29018: add of_match table for device-tree probing As simple as can be right now; just one ID and no custom properties to parse. Signed-off-by: Olof Johansson Acked-by: Grant Likely Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c index 849d6a5..38ec52b 100644 --- a/drivers/staging/iio/light/isl29018.c +++ b/drivers/staging/iio/light/isl29018.c @@ -592,11 +592,18 @@ static const struct i2c_device_id isl29018_id[] = { MODULE_DEVICE_TABLE(i2c, isl29018_id); +static const struct of_device_id isl29018_of_match[] = { + { .compatible = "invn,isl29018", }, + { }, +}; +MODULE_DEVICE_TABLE(of, isl29018_of_match); + static struct i2c_driver isl29018_driver = { .class = I2C_CLASS_HWMON, .driver = { .name = "isl29018", .owner = THIS_MODULE, + .of_match_table = isl29018_of_match, }, .probe = isl29018_probe, .remove = __devexit_p(isl29018_remove), -- cgit v0.10.2 From 54461c3067b2dce5947c9e4f88a8d905dca2c0c9 Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Thu, 22 Dec 2011 18:46:42 -0800 Subject: staging:iio: ak8975: add of_match table for device-tree probing Just like isl29018; trivial addition. Using both asahi-kasei,ak8975 and the non-prefixed version (I couldn't figure out if Asahi Kasei had a stock symbol to use, I only found numerical indexes for their stock info). Signed-off-by: Olof Johansson Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/iio/magnetometer/ak8975.c b/drivers/staging/iio/magnetometer/ak8975.c index 3158f12..d5ddac3 100644 --- a/drivers/staging/iio/magnetometer/ak8975.c +++ b/drivers/staging/iio/magnetometer/ak8975.c @@ -564,9 +564,17 @@ static const struct i2c_device_id ak8975_id[] = { MODULE_DEVICE_TABLE(i2c, ak8975_id); +static const struct of_device_id ak8975_of_match[] = { + { .compatible = "asahi-kasei,ak8975", }, + { .compatible = "ak8975", }, + { } +}; +MODULE_DEVICE_TABLE(of, ak8975_of_match); + static struct i2c_driver ak8975_driver = { .driver = { .name = "ak8975", + .of_match_table = ak8975_of_match, }, .probe = ak8975_probe, .remove = __devexit_p(ak8975_remove), -- cgit v0.10.2 From 7e632344adfe749749aa525f6fbe0ffc05ae3190 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 3 Jan 2012 11:02:51 +0100 Subject: staging:iio: Setup buffer access functions when allocating the buffer Setup the buffer access functions in the buffer allocate function. There is no need to let each driver handle this on its own. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/iio/accel/adis16201_ring.c b/drivers/staging/iio/accel/adis16201_ring.c index 26c610f..97f9e6b 100644 --- a/drivers/staging/iio/accel/adis16201_ring.c +++ b/drivers/staging/iio/accel/adis16201_ring.c @@ -115,9 +115,7 @@ int adis16201_configure_ring(struct iio_dev *indio_dev) return ret; } indio_dev->buffer = ring; - /* Effectively select the ring buffer implementation */ ring->scan_timestamp = true; - ring->access = &ring_sw_access_funcs; indio_dev->setup_ops = &adis16201_ring_setup_ops; indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, diff --git a/drivers/staging/iio/accel/adis16203_ring.c b/drivers/staging/iio/accel/adis16203_ring.c index 064640d..6a8963d 100644 --- a/drivers/staging/iio/accel/adis16203_ring.c +++ b/drivers/staging/iio/accel/adis16203_ring.c @@ -117,9 +117,7 @@ int adis16203_configure_ring(struct iio_dev *indio_dev) return ret; } indio_dev->buffer = ring; - /* Effectively select the ring buffer implementation */ ring->scan_timestamp = true; - ring->access = &ring_sw_access_funcs; indio_dev->setup_ops = &adis16203_ring_setup_ops; indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, diff --git a/drivers/staging/iio/accel/adis16204_ring.c b/drivers/staging/iio/accel/adis16204_ring.c index 4081179..5c8ab73 100644 --- a/drivers/staging/iio/accel/adis16204_ring.c +++ b/drivers/staging/iio/accel/adis16204_ring.c @@ -112,8 +112,6 @@ int adis16204_configure_ring(struct iio_dev *indio_dev) return ret; } indio_dev->buffer = ring; - /* Effectively select the ring buffer implementation */ - ring->access = &ring_sw_access_funcs; ring->scan_timestamp = true; indio_dev->setup_ops = &adis16204_ring_setup_ops; diff --git a/drivers/staging/iio/accel/adis16209_ring.c b/drivers/staging/iio/accel/adis16209_ring.c index 2a6fd334..57254b6b 100644 --- a/drivers/staging/iio/accel/adis16209_ring.c +++ b/drivers/staging/iio/accel/adis16209_ring.c @@ -113,8 +113,6 @@ int adis16209_configure_ring(struct iio_dev *indio_dev) return ret; } indio_dev->buffer = ring; - /* Effectively select the ring buffer implementation */ - ring->access = &ring_sw_access_funcs; ring->scan_timestamp = true; indio_dev->setup_ops = &adis16209_ring_setup_ops; diff --git a/drivers/staging/iio/accel/adis16240_ring.c b/drivers/staging/iio/accel/adis16240_ring.c index e23622d..43ba84e 100644 --- a/drivers/staging/iio/accel/adis16240_ring.c +++ b/drivers/staging/iio/accel/adis16240_ring.c @@ -110,8 +110,6 @@ int adis16240_configure_ring(struct iio_dev *indio_dev) return ret; } indio_dev->buffer = ring; - /* Effectively select the ring buffer implementation */ - ring->access = &ring_sw_access_funcs; ring->scan_timestamp = true; indio_dev->setup_ops = &adis16240_ring_setup_ops; diff --git a/drivers/staging/iio/accel/lis3l02dq.h b/drivers/staging/iio/accel/lis3l02dq.h index 2db383f..ae5f225 100644 --- a/drivers/staging/iio/accel/lis3l02dq.h +++ b/drivers/staging/iio/accel/lis3l02dq.h @@ -187,12 +187,10 @@ void lis3l02dq_unconfigure_buffer(struct iio_dev *indio_dev); #ifdef CONFIG_LIS3L02DQ_BUF_RING_SW #define lis3l02dq_free_buf iio_sw_rb_free #define lis3l02dq_alloc_buf iio_sw_rb_allocate -#define lis3l02dq_access_funcs ring_sw_access_funcs #endif #ifdef CONFIG_LIS3L02DQ_BUF_KFIFO #define lis3l02dq_free_buf iio_kfifo_free #define lis3l02dq_alloc_buf iio_kfifo_allocate -#define lis3l02dq_access_funcs kfifo_access_funcs #endif irqreturn_t lis3l02dq_data_rdy_trig_poll(int irq, void *private); #define lis3l02dq_th lis3l02dq_data_rdy_trig_poll diff --git a/drivers/staging/iio/accel/lis3l02dq_ring.c b/drivers/staging/iio/accel/lis3l02dq_ring.c index 98c5c92..ca0a1fe 100644 --- a/drivers/staging/iio/accel/lis3l02dq_ring.c +++ b/drivers/staging/iio/accel/lis3l02dq_ring.c @@ -406,8 +406,6 @@ int lis3l02dq_configure_buffer(struct iio_dev *indio_dev) return -ENOMEM; indio_dev->buffer = buffer; - /* Effectively select the buffer implementation */ - indio_dev->buffer->access = &lis3l02dq_access_funcs; buffer->scan_timestamp = true; indio_dev->setup_ops = &lis3l02dq_buffer_setup_ops; diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c index 45f4504..9d25165 100644 --- a/drivers/staging/iio/adc/ad7192.c +++ b/drivers/staging/iio/adc/ad7192.c @@ -561,8 +561,6 @@ static int ad7192_register_ring_funcs_and_init(struct iio_dev *indio_dev) ret = -ENOMEM; goto error_ret; } - /* Effectively select the ring buffer implementation */ - indio_dev->buffer->access = &ring_sw_access_funcs; indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, &ad7192_trigger_handler, IRQF_ONESHOT, diff --git a/drivers/staging/iio/adc/ad7298_ring.c b/drivers/staging/iio/adc/ad7298_ring.c index d1a12dd..feeb0ee 100644 --- a/drivers/staging/iio/adc/ad7298_ring.c +++ b/drivers/staging/iio/adc/ad7298_ring.c @@ -131,9 +131,6 @@ int ad7298_register_ring_funcs_and_init(struct iio_dev *indio_dev) ret = -ENOMEM; goto error_ret; } - /* Effectively select the ring buffer implementation */ - indio_dev->buffer->access = &ring_sw_access_funcs; - indio_dev->pollfunc = iio_alloc_pollfunc(NULL, &ad7298_trigger_handler, IRQF_ONESHOT, diff --git a/drivers/staging/iio/adc/ad7476_ring.c b/drivers/staging/iio/adc/ad7476_ring.c index 4e298b2..35a8576 100644 --- a/drivers/staging/iio/adc/ad7476_ring.c +++ b/drivers/staging/iio/adc/ad7476_ring.c @@ -98,8 +98,6 @@ int ad7476_register_ring_funcs_and_init(struct iio_dev *indio_dev) ret = -ENOMEM; goto error_ret; } - /* Effectively select the ring buffer implementation */ - indio_dev->buffer->access = &ring_sw_access_funcs; indio_dev->pollfunc = iio_alloc_pollfunc(NULL, &ad7476_trigger_handler, diff --git a/drivers/staging/iio/adc/ad7606_ring.c b/drivers/staging/iio/adc/ad7606_ring.c index e8f94a1..1ef9fbc 100644 --- a/drivers/staging/iio/adc/ad7606_ring.c +++ b/drivers/staging/iio/adc/ad7606_ring.c @@ -110,8 +110,6 @@ int ad7606_register_ring_funcs_and_init(struct iio_dev *indio_dev) goto error_ret; } - /* Effectively select the ring buffer implementation */ - indio_dev->buffer->access = &ring_sw_access_funcs; indio_dev->pollfunc = iio_alloc_pollfunc(&ad7606_trigger_handler_th_bh, &ad7606_trigger_handler_th_bh, 0, diff --git a/drivers/staging/iio/adc/ad7793.c b/drivers/staging/iio/adc/ad7793.c index 6a058b1..84ecde1 100644 --- a/drivers/staging/iio/adc/ad7793.c +++ b/drivers/staging/iio/adc/ad7793.c @@ -427,8 +427,6 @@ static int ad7793_register_ring_funcs_and_init(struct iio_dev *indio_dev) ret = -ENOMEM; goto error_ret; } - /* Effectively select the ring buffer implementation */ - indio_dev->buffer->access = &ring_sw_access_funcs; indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, &ad7793_trigger_handler, IRQF_ONESHOT, diff --git a/drivers/staging/iio/adc/ad7887_ring.c b/drivers/staging/iio/adc/ad7887_ring.c index 85076cd..d180907 100644 --- a/drivers/staging/iio/adc/ad7887_ring.c +++ b/drivers/staging/iio/adc/ad7887_ring.c @@ -131,8 +131,6 @@ int ad7887_register_ring_funcs_and_init(struct iio_dev *indio_dev) ret = -ENOMEM; goto error_ret; } - /* Effectively select the ring buffer implementation */ - indio_dev->buffer->access = &ring_sw_access_funcs; indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, &ad7887_trigger_handler, IRQF_ONESHOT, diff --git a/drivers/staging/iio/adc/ad799x_ring.c b/drivers/staging/iio/adc/ad799x_ring.c index 5dded9e..28e9a41 100644 --- a/drivers/staging/iio/adc/ad799x_ring.c +++ b/drivers/staging/iio/adc/ad799x_ring.c @@ -141,8 +141,6 @@ int ad799x_register_ring_funcs_and_init(struct iio_dev *indio_dev) ret = -ENOMEM; goto error_ret; } - /* Effectively select the ring buffer implementation */ - indio_dev->buffer->access = &ring_sw_access_funcs; indio_dev->pollfunc = iio_alloc_pollfunc(NULL, &ad799x_trigger_handler, IRQF_ONESHOT, diff --git a/drivers/staging/iio/adc/max1363_ring.c b/drivers/staging/iio/adc/max1363_ring.c index f730b3f..d0a60a3 100644 --- a/drivers/staging/iio/adc/max1363_ring.c +++ b/drivers/staging/iio/adc/max1363_ring.c @@ -116,8 +116,6 @@ int max1363_register_ring_funcs_and_init(struct iio_dev *indio_dev) ret = -ENOMEM; goto error_deallocate_sw_rb; } - /* Effectively select the ring buffer implementation */ - indio_dev->buffer->access = &ring_sw_access_funcs; /* Ring buffer functions - here trigger setup related */ indio_dev->setup_ops = &max1363_ring_setup_ops; diff --git a/drivers/staging/iio/gyro/adis16260_ring.c b/drivers/staging/iio/gyro/adis16260_ring.c index 699a615..711f151 100644 --- a/drivers/staging/iio/gyro/adis16260_ring.c +++ b/drivers/staging/iio/gyro/adis16260_ring.c @@ -115,8 +115,6 @@ int adis16260_configure_ring(struct iio_dev *indio_dev) return ret; } indio_dev->buffer = ring; - /* Effectively select the ring buffer implementation */ - ring->access = &ring_sw_access_funcs; ring->scan_timestamp = true; indio_dev->setup_ops = &adis16260_ring_setup_ops; diff --git a/drivers/staging/iio/iio_simple_dummy_buffer.c b/drivers/staging/iio/iio_simple_dummy_buffer.c index d6a1c0e..bb4daf7 100644 --- a/drivers/staging/iio/iio_simple_dummy_buffer.c +++ b/drivers/staging/iio/iio_simple_dummy_buffer.c @@ -142,8 +142,6 @@ int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev) } indio_dev->buffer = buffer; - /* Tell the core how to access the buffer */ - buffer->access = &kfifo_access_funcs; /* Enable timestamps by default */ buffer->scan_timestamp = true; diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c index 9a2ca55..cd82b56 100644 --- a/drivers/staging/iio/impedance-analyzer/ad5933.c +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c @@ -607,9 +607,6 @@ static int ad5933_register_ring_funcs_and_init(struct iio_dev *indio_dev) if (!indio_dev->buffer) return -ENOMEM; - /* Effectively select the ring buffer implementation */ - indio_dev->buffer->access = &ring_sw_access_funcs; - /* Ring buffer functions - here trigger setup related */ indio_dev->setup_ops = &ad5933_ring_setup_ops; diff --git a/drivers/staging/iio/imu/adis16400_ring.c b/drivers/staging/iio/imu/adis16400_ring.c index ac22de5..8daa038 100644 --- a/drivers/staging/iio/imu/adis16400_ring.c +++ b/drivers/staging/iio/imu/adis16400_ring.c @@ -187,8 +187,6 @@ int adis16400_configure_ring(struct iio_dev *indio_dev) return ret; } indio_dev->buffer = ring; - /* Effectively select the ring buffer implementation */ - ring->access = &ring_sw_access_funcs; ring->scan_timestamp = true; indio_dev->setup_ops = &adis16400_ring_setup_ops; diff --git a/drivers/staging/iio/kfifo_buf.c b/drivers/staging/iio/kfifo_buf.c index e1e9c06..9f3bd59 100644 --- a/drivers/staging/iio/kfifo_buf.c +++ b/drivers/staging/iio/kfifo_buf.c @@ -59,21 +59,6 @@ static struct attribute_group iio_kfifo_attribute_group = { .name = "buffer", }; -struct iio_buffer *iio_kfifo_allocate(struct iio_dev *indio_dev) -{ - struct iio_kfifo *kf; - - kf = kzalloc(sizeof *kf, GFP_KERNEL); - if (!kf) - return NULL; - kf->update_needed = true; - iio_buffer_init(&kf->buffer); - kf->buffer.attrs = &iio_kfifo_attribute_group; - - return &kf->buffer; -} -EXPORT_SYMBOL(iio_kfifo_allocate); - static int iio_get_bytes_per_datum_kfifo(struct iio_buffer *r) { return r->bytes_per_datum; @@ -104,12 +89,6 @@ static int iio_set_length_kfifo(struct iio_buffer *r, int length) return 0; } -void iio_kfifo_free(struct iio_buffer *r) -{ - kfree(iio_to_kfifo(r)); -} -EXPORT_SYMBOL(iio_kfifo_free); - static int iio_store_to_kfifo(struct iio_buffer *r, u8 *data, s64 timestamp) @@ -137,7 +116,7 @@ static int iio_read_first_n_kfifo(struct iio_buffer *r, return copied; } -const struct iio_buffer_access_funcs kfifo_access_funcs = { +static const struct iio_buffer_access_funcs kfifo_access_funcs = { .store_to = &iio_store_to_kfifo, .read_first_n = &iio_read_first_n_kfifo, .request_update = &iio_request_update_kfifo, @@ -146,6 +125,27 @@ const struct iio_buffer_access_funcs kfifo_access_funcs = { .get_length = &iio_get_length_kfifo, .set_length = &iio_set_length_kfifo, }; -EXPORT_SYMBOL(kfifo_access_funcs); + +struct iio_buffer *iio_kfifo_allocate(struct iio_dev *indio_dev) +{ + struct iio_kfifo *kf; + + kf = kzalloc(sizeof *kf, GFP_KERNEL); + if (!kf) + return NULL; + kf->update_needed = true; + iio_buffer_init(&kf->buffer); + kf->buffer.attrs = &iio_kfifo_attribute_group; + kf->buffer.access = &kfifo_access_funcs; + + return &kf->buffer; +} +EXPORT_SYMBOL(iio_kfifo_allocate); + +void iio_kfifo_free(struct iio_buffer *r) +{ + kfree(iio_to_kfifo(r)); +} +EXPORT_SYMBOL(iio_kfifo_free); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/iio/kfifo_buf.h b/drivers/staging/iio/kfifo_buf.h index cc2bd9a..9f7da01 100644 --- a/drivers/staging/iio/kfifo_buf.h +++ b/drivers/staging/iio/kfifo_buf.h @@ -3,8 +3,6 @@ #include "iio.h" #include "buffer.h" -extern const struct iio_buffer_access_funcs kfifo_access_funcs; - struct iio_buffer *iio_kfifo_allocate(struct iio_dev *indio_dev); void iio_kfifo_free(struct iio_buffer *r); diff --git a/drivers/staging/iio/meter/ade7758_ring.c b/drivers/staging/iio/meter/ade7758_ring.c index f29f2b2..c5c522b 100644 --- a/drivers/staging/iio/meter/ade7758_ring.c +++ b/drivers/staging/iio/meter/ade7758_ring.c @@ -144,8 +144,6 @@ int ade7758_configure_ring(struct iio_dev *indio_dev) return ret; } - /* Effectively select the ring buffer implementation */ - indio_dev->buffer->access = &ring_sw_access_funcs; indio_dev->setup_ops = &ade7758_ring_setup_ops; indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, diff --git a/drivers/staging/iio/ring_sw.c b/drivers/staging/iio/ring_sw.c index 3e24ec4..eeac0da 100644 --- a/drivers/staging/iio/ring_sw.c +++ b/drivers/staging/iio/ring_sw.c @@ -329,6 +329,16 @@ static struct attribute_group iio_ring_attribute_group = { .name = "buffer", }; +static const struct iio_buffer_access_funcs ring_sw_access_funcs = { + .store_to = &iio_store_to_sw_rb, + .read_first_n = &iio_read_first_n_sw_rb, + .request_update = &iio_request_update_sw_rb, + .get_bytes_per_datum = &iio_get_bytes_per_datum_sw_rb, + .set_bytes_per_datum = &iio_set_bytes_per_datum_sw_rb, + .get_length = &iio_get_length_sw_rb, + .set_length = &iio_set_length_sw_rb, +}; + struct iio_buffer *iio_sw_rb_allocate(struct iio_dev *indio_dev) { struct iio_buffer *buf; @@ -341,6 +351,7 @@ struct iio_buffer *iio_sw_rb_allocate(struct iio_dev *indio_dev) buf = &ring->buf; iio_buffer_init(buf); buf->attrs = &iio_ring_attribute_group; + buf->access = &ring_sw_access_funcs; return buf; } @@ -352,16 +363,5 @@ void iio_sw_rb_free(struct iio_buffer *r) } EXPORT_SYMBOL(iio_sw_rb_free); -const struct iio_buffer_access_funcs ring_sw_access_funcs = { - .store_to = &iio_store_to_sw_rb, - .read_first_n = &iio_read_first_n_sw_rb, - .request_update = &iio_request_update_sw_rb, - .get_bytes_per_datum = &iio_get_bytes_per_datum_sw_rb, - .set_bytes_per_datum = &iio_set_bytes_per_datum_sw_rb, - .get_length = &iio_get_length_sw_rb, - .set_length = &iio_set_length_sw_rb, -}; -EXPORT_SYMBOL(ring_sw_access_funcs); - MODULE_DESCRIPTION("Industrialio I/O software ring buffer"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/iio/ring_sw.h b/drivers/staging/iio/ring_sw.h index e6a6e2c..7556e21 100644 --- a/drivers/staging/iio/ring_sw.h +++ b/drivers/staging/iio/ring_sw.h @@ -25,11 +25,6 @@ #define _IIO_RING_SW_H_ #include "buffer.h" -/** - * ring_sw_access_funcs - access functions for a software ring buffer - **/ -extern const struct iio_buffer_access_funcs ring_sw_access_funcs; - struct iio_buffer *iio_sw_rb_allocate(struct iio_dev *indio_dev); void iio_sw_rb_free(struct iio_buffer *ring); #endif /* _IIO_RING_SW_H_ */ -- cgit v0.10.2 From 16a39b7a9ccd81458e7e1799c1b213d1d590630c Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 3 Jan 2012 14:59:37 +0100 Subject: staging:iio: Update iio_event_interface documentation The documentation for the iio_event_interface does not match the actual struct anymore. This patch removes the documentation for non-existing fields and adds documentation for missing fields. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/iio/industrialio-core.c b/drivers/staging/iio/industrialio-core.c index 19f897f..580f373 100644 --- a/drivers/staging/iio/industrialio-core.c +++ b/drivers/staging/iio/industrialio-core.c @@ -112,13 +112,14 @@ struct iio_detected_event_list { /** * struct iio_event_interface - chrdev interface for an event line - * @dev: device assocated with event interface * @wait: wait queue to allow blocking reads of events * @event_list_lock: mutex to protect the list of detected events * @det_events: list of detected events * @max_events: maximum number of events before new ones are dropped * @current_events: number of events in detected list + * @dev_attr_list: list of event interface sysfs attribute * @flags: file operations related flags including busy flag. + * @group: event interface sysfs attribute group */ struct iio_event_interface { wait_queue_head_t wait; -- cgit v0.10.2 From 0a769a95334a8819da046f13c2ef8d8b344fc199 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 3 Jan 2012 14:59:38 +0100 Subject: staging:iio: Factor out event handling into its own file The core iio file has gotten quite cluttered over time. This patch moves the event handling code into its own file. Since the event handling code is largely independent from the core code the only code changes necessary for this are to make the moved iio_device_register_eventset, iio_device_unregister_eventset and iio_event_getfd functions non static. This has also the advantage that industrialio-core.c is now closer again to its counterpart in the outofstaging branch. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/iio/Makefile b/drivers/staging/iio/Makefile index 1340aea..657710b 100644 --- a/drivers/staging/iio/Makefile +++ b/drivers/staging/iio/Makefile @@ -3,7 +3,7 @@ # obj-$(CONFIG_IIO) += industrialio.o -industrialio-y := industrialio-core.o +industrialio-y := industrialio-core.o industrialio-event.o industrialio-$(CONFIG_IIO_BUFFER) += industrialio-buffer.o industrialio-$(CONFIG_IIO_TRIGGER) += industrialio-trigger.o diff --git a/drivers/staging/iio/iio_core.h b/drivers/staging/iio/iio_core.h index 107cfb1..c9dfcba 100644 --- a/drivers/staging/iio/iio_core.h +++ b/drivers/staging/iio/iio_core.h @@ -49,4 +49,8 @@ ssize_t iio_buffer_read_first_n_outer(struct file *filp, char __user *buf, #endif +int iio_device_register_eventset(struct iio_dev *indio_dev); +void iio_device_unregister_eventset(struct iio_dev *indio_dev); +int iio_event_getfd(struct iio_dev *indio_dev); + #endif diff --git a/drivers/staging/iio/industrialio-core.c b/drivers/staging/iio/industrialio-core.c index 580f373..e4824fe 100644 --- a/drivers/staging/iio/industrialio-core.c +++ b/drivers/staging/iio/industrialio-core.c @@ -100,72 +100,6 @@ const struct iio_chan_spec return NULL; } -/** - * struct iio_detected_event_list - list element for events that have occurred - * @list: linked list header - * @ev: the event itself - */ -struct iio_detected_event_list { - struct list_head list; - struct iio_event_data ev; -}; - -/** - * struct iio_event_interface - chrdev interface for an event line - * @wait: wait queue to allow blocking reads of events - * @event_list_lock: mutex to protect the list of detected events - * @det_events: list of detected events - * @max_events: maximum number of events before new ones are dropped - * @current_events: number of events in detected list - * @dev_attr_list: list of event interface sysfs attribute - * @flags: file operations related flags including busy flag. - * @group: event interface sysfs attribute group - */ -struct iio_event_interface { - wait_queue_head_t wait; - struct mutex event_list_lock; - struct list_head det_events; - int max_events; - int current_events; - struct list_head dev_attr_list; - unsigned long flags; - struct attribute_group group; -}; - -int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp) -{ - struct iio_event_interface *ev_int = indio_dev->event_interface; - struct iio_detected_event_list *ev; - int ret = 0; - - /* Does anyone care? */ - mutex_lock(&ev_int->event_list_lock); - if (test_bit(IIO_BUSY_BIT_POS, &ev_int->flags)) { - if (ev_int->current_events == ev_int->max_events) { - mutex_unlock(&ev_int->event_list_lock); - return 0; - } - ev = kmalloc(sizeof(*ev), GFP_KERNEL); - if (ev == NULL) { - ret = -ENOMEM; - mutex_unlock(&ev_int->event_list_lock); - goto error_ret; - } - ev->ev.id = ev_code; - ev->ev.timestamp = timestamp; - - list_add_tail(&ev->list, &ev_int->det_events); - ev_int->current_events++; - mutex_unlock(&ev_int->event_list_lock); - wake_up_interruptible(&ev_int->wait); - } else - mutex_unlock(&ev_int->event_list_lock); - -error_ret: - return ret; -} -EXPORT_SYMBOL(iio_push_event); - /* This turns up an awful lot */ ssize_t iio_read_const_attr(struct device *dev, struct device_attribute *attr, @@ -175,110 +109,6 @@ ssize_t iio_read_const_attr(struct device *dev, } EXPORT_SYMBOL(iio_read_const_attr); -static ssize_t iio_event_chrdev_read(struct file *filep, - char __user *buf, - size_t count, - loff_t *f_ps) -{ - struct iio_event_interface *ev_int = filep->private_data; - struct iio_detected_event_list *el; - size_t len = sizeof(el->ev); - int ret; - - if (count < len) - return -EINVAL; - - mutex_lock(&ev_int->event_list_lock); - if (list_empty(&ev_int->det_events)) { - if (filep->f_flags & O_NONBLOCK) { - ret = -EAGAIN; - goto error_mutex_unlock; - } - mutex_unlock(&ev_int->event_list_lock); - /* Blocking on device; waiting for something to be there */ - ret = wait_event_interruptible(ev_int->wait, - !list_empty(&ev_int - ->det_events)); - if (ret) - goto error_ret; - /* Single access device so no one else can get the data */ - mutex_lock(&ev_int->event_list_lock); - } - - el = list_first_entry(&ev_int->det_events, - struct iio_detected_event_list, - list); - if (copy_to_user(buf, &(el->ev), len)) { - ret = -EFAULT; - goto error_mutex_unlock; - } - list_del(&el->list); - ev_int->current_events--; - mutex_unlock(&ev_int->event_list_lock); - kfree(el); - - return len; - -error_mutex_unlock: - mutex_unlock(&ev_int->event_list_lock); -error_ret: - - return ret; -} - -static int iio_event_chrdev_release(struct inode *inode, struct file *filep) -{ - struct iio_event_interface *ev_int = filep->private_data; - struct iio_detected_event_list *el, *t; - - mutex_lock(&ev_int->event_list_lock); - clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags); - /* - * In order to maintain a clean state for reopening, - * clear out any awaiting events. The mask will prevent - * any new __iio_push_event calls running. - */ - list_for_each_entry_safe(el, t, &ev_int->det_events, list) { - list_del(&el->list); - kfree(el); - } - ev_int->current_events = 0; - mutex_unlock(&ev_int->event_list_lock); - - return 0; -} - -static const struct file_operations iio_event_chrdev_fileops = { - .read = iio_event_chrdev_read, - .release = iio_event_chrdev_release, - .owner = THIS_MODULE, - .llseek = noop_llseek, -}; - -static int iio_event_getfd(struct iio_dev *indio_dev) -{ - struct iio_event_interface *ev_int = indio_dev->event_interface; - int fd; - - if (ev_int == NULL) - return -ENODEV; - - mutex_lock(&ev_int->event_list_lock); - if (test_and_set_bit(IIO_BUSY_BIT_POS, &ev_int->flags)) { - mutex_unlock(&ev_int->event_list_lock); - return -EBUSY; - } - mutex_unlock(&ev_int->event_list_lock); - fd = anon_inode_getfd("iio:event", - &iio_event_chrdev_fileops, ev_int, O_RDONLY); - if (fd < 0) { - mutex_lock(&ev_int->event_list_lock); - clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags); - mutex_unlock(&ev_int->event_list_lock); - } - return fd; -} - static int __init iio_init(void) { int ret; @@ -727,295 +557,6 @@ static void iio_device_unregister_sysfs(struct iio_dev *indio_dev) kfree(indio_dev->chan_attr_group.attrs); } -static const char * const iio_ev_type_text[] = { - [IIO_EV_TYPE_THRESH] = "thresh", - [IIO_EV_TYPE_MAG] = "mag", - [IIO_EV_TYPE_ROC] = "roc", - [IIO_EV_TYPE_THRESH_ADAPTIVE] = "thresh_adaptive", - [IIO_EV_TYPE_MAG_ADAPTIVE] = "mag_adaptive", -}; - -static const char * const iio_ev_dir_text[] = { - [IIO_EV_DIR_EITHER] = "either", - [IIO_EV_DIR_RISING] = "rising", - [IIO_EV_DIR_FALLING] = "falling" -}; - -static ssize_t iio_ev_state_store(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - int ret; - bool val; - - ret = strtobool(buf, &val); - if (ret < 0) - return ret; - - ret = indio_dev->info->write_event_config(indio_dev, - this_attr->address, - val); - return (ret < 0) ? ret : len; -} - -static ssize_t iio_ev_state_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - int val = indio_dev->info->read_event_config(indio_dev, - this_attr->address); - - if (val < 0) - return val; - else - return sprintf(buf, "%d\n", val); -} - -static ssize_t iio_ev_value_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - int val, ret; - - ret = indio_dev->info->read_event_value(indio_dev, - this_attr->address, &val); - if (ret < 0) - return ret; - - return sprintf(buf, "%d\n", val); -} - -static ssize_t iio_ev_value_store(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - unsigned long val; - int ret; - - if (!indio_dev->info->write_event_value) - return -EINVAL; - - ret = strict_strtoul(buf, 10, &val); - if (ret) - return ret; - - ret = indio_dev->info->write_event_value(indio_dev, this_attr->address, - val); - if (ret < 0) - return ret; - - return len; -} - -static int iio_device_add_event_sysfs(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan) -{ - int ret = 0, i, attrcount = 0; - u64 mask = 0; - char *postfix; - if (!chan->event_mask) - return 0; - - for_each_set_bit(i, &chan->event_mask, sizeof(chan->event_mask)*8) { - postfix = kasprintf(GFP_KERNEL, "%s_%s_en", - iio_ev_type_text[i/IIO_EV_DIR_MAX], - iio_ev_dir_text[i%IIO_EV_DIR_MAX]); - if (postfix == NULL) { - ret = -ENOMEM; - goto error_ret; - } - if (chan->modified) - mask = IIO_MOD_EVENT_CODE(chan->type, 0, chan->channel, - i/IIO_EV_DIR_MAX, - i%IIO_EV_DIR_MAX); - else if (chan->differential) - mask = IIO_EVENT_CODE(chan->type, - 0, 0, - i%IIO_EV_DIR_MAX, - i/IIO_EV_DIR_MAX, - 0, - chan->channel, - chan->channel2); - else - mask = IIO_UNMOD_EVENT_CODE(chan->type, - chan->channel, - i/IIO_EV_DIR_MAX, - i%IIO_EV_DIR_MAX); - - ret = __iio_add_chan_devattr(postfix, - chan, - &iio_ev_state_show, - iio_ev_state_store, - mask, - 0, - &indio_dev->dev, - &indio_dev->event_interface-> - dev_attr_list); - kfree(postfix); - if (ret) - goto error_ret; - attrcount++; - postfix = kasprintf(GFP_KERNEL, "%s_%s_value", - iio_ev_type_text[i/IIO_EV_DIR_MAX], - iio_ev_dir_text[i%IIO_EV_DIR_MAX]); - if (postfix == NULL) { - ret = -ENOMEM; - goto error_ret; - } - ret = __iio_add_chan_devattr(postfix, chan, - iio_ev_value_show, - iio_ev_value_store, - mask, - 0, - &indio_dev->dev, - &indio_dev->event_interface-> - dev_attr_list); - kfree(postfix); - if (ret) - goto error_ret; - attrcount++; - } - ret = attrcount; -error_ret: - return ret; -} - -static inline void __iio_remove_event_config_attrs(struct iio_dev *indio_dev) -{ - struct iio_dev_attr *p, *n; - list_for_each_entry_safe(p, n, - &indio_dev->event_interface-> - dev_attr_list, l) { - kfree(p->dev_attr.attr.name); - kfree(p); - } -} - -static inline int __iio_add_event_config_attrs(struct iio_dev *indio_dev) -{ - int j, ret, attrcount = 0; - - INIT_LIST_HEAD(&indio_dev->event_interface->dev_attr_list); - /* Dynically created from the channels array */ - for (j = 0; j < indio_dev->num_channels; j++) { - ret = iio_device_add_event_sysfs(indio_dev, - &indio_dev->channels[j]); - if (ret < 0) - goto error_clear_attrs; - attrcount += ret; - } - return attrcount; - -error_clear_attrs: - __iio_remove_event_config_attrs(indio_dev); - - return ret; -} - -static bool iio_check_for_dynamic_events(struct iio_dev *indio_dev) -{ - int j; - - for (j = 0; j < indio_dev->num_channels; j++) - if (indio_dev->channels[j].event_mask != 0) - return true; - return false; -} - -static void iio_setup_ev_int(struct iio_event_interface *ev_int) -{ - mutex_init(&ev_int->event_list_lock); - /* discussion point - make this variable? */ - ev_int->max_events = 10; - ev_int->current_events = 0; - INIT_LIST_HEAD(&ev_int->det_events); - init_waitqueue_head(&ev_int->wait); -} - -static const char *iio_event_group_name = "events"; -static int iio_device_register_eventset(struct iio_dev *indio_dev) -{ - struct iio_dev_attr *p; - int ret = 0, attrcount_orig = 0, attrcount, attrn; - struct attribute **attr; - - if (!(indio_dev->info->event_attrs || - iio_check_for_dynamic_events(indio_dev))) - return 0; - - indio_dev->event_interface = - kzalloc(sizeof(struct iio_event_interface), GFP_KERNEL); - if (indio_dev->event_interface == NULL) { - ret = -ENOMEM; - goto error_ret; - } - - iio_setup_ev_int(indio_dev->event_interface); - if (indio_dev->info->event_attrs != NULL) { - attr = indio_dev->info->event_attrs->attrs; - while (*attr++ != NULL) - attrcount_orig++; - } - attrcount = attrcount_orig; - if (indio_dev->channels) { - ret = __iio_add_event_config_attrs(indio_dev); - if (ret < 0) - goto error_free_setup_event_lines; - attrcount += ret; - } - - indio_dev->event_interface->group.name = iio_event_group_name; - indio_dev->event_interface->group.attrs = kcalloc(attrcount + 1, - sizeof(indio_dev->event_interface->group.attrs[0]), - GFP_KERNEL); - if (indio_dev->event_interface->group.attrs == NULL) { - ret = -ENOMEM; - goto error_free_setup_event_lines; - } - if (indio_dev->info->event_attrs) - memcpy(indio_dev->event_interface->group.attrs, - indio_dev->info->event_attrs->attrs, - sizeof(indio_dev->event_interface->group.attrs[0]) - *attrcount_orig); - attrn = attrcount_orig; - /* Add all elements from the list. */ - list_for_each_entry(p, - &indio_dev->event_interface->dev_attr_list, - l) - indio_dev->event_interface->group.attrs[attrn++] = - &p->dev_attr.attr; - indio_dev->groups[indio_dev->groupcounter++] = - &indio_dev->event_interface->group; - - return 0; - -error_free_setup_event_lines: - __iio_remove_event_config_attrs(indio_dev); - kfree(indio_dev->event_interface); -error_ret: - - return ret; -} - -static void iio_device_unregister_eventset(struct iio_dev *indio_dev) -{ - if (indio_dev->event_interface == NULL) - return; - __iio_remove_event_config_attrs(indio_dev); - kfree(indio_dev->event_interface->group.attrs); - kfree(indio_dev->event_interface); -} - static void iio_dev_release(struct device *device) { struct iio_dev *indio_dev = container_of(device, struct iio_dev, dev); diff --git a/drivers/staging/iio/industrialio-event.c b/drivers/staging/iio/industrialio-event.c new file mode 100644 index 0000000..a7b345d --- /dev/null +++ b/drivers/staging/iio/industrialio-event.c @@ -0,0 +1,483 @@ +/* Industrial I/O event handling + * + * Copyright (c) 2008 Jonathan Cameron + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * Based on elements of hwmon and input subsystems. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "iio.h" +#include "iio_core.h" +#include "sysfs.h" +#include "events.h" + +/** + * struct iio_detected_event_list - list element for events that have occurred + * @list: linked list header + * @ev: the event itself + */ +struct iio_detected_event_list { + struct list_head list; + struct iio_event_data ev; +}; + +/** + * struct iio_event_interface - chrdev interface for an event line + * @wait: wait queue to allow blocking reads of events + * @event_list_lock: mutex to protect the list of detected events + * @det_events: list of detected events + * @max_events: maximum number of events before new ones are dropped + * @current_events: number of events in detected list + * @dev_attr_list: list of event interface sysfs attribute + * @flags: file operations related flags including busy flag. + * @group: event interface sysfs attribute group + */ +struct iio_event_interface { + wait_queue_head_t wait; + struct mutex event_list_lock; + struct list_head det_events; + int max_events; + int current_events; + struct list_head dev_attr_list; + unsigned long flags; + struct attribute_group group; +}; + +int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp) +{ + struct iio_event_interface *ev_int = indio_dev->event_interface; + struct iio_detected_event_list *ev; + int ret = 0; + + /* Does anyone care? */ + mutex_lock(&ev_int->event_list_lock); + if (test_bit(IIO_BUSY_BIT_POS, &ev_int->flags)) { + if (ev_int->current_events == ev_int->max_events) { + mutex_unlock(&ev_int->event_list_lock); + return 0; + } + ev = kmalloc(sizeof(*ev), GFP_KERNEL); + if (ev == NULL) { + ret = -ENOMEM; + mutex_unlock(&ev_int->event_list_lock); + goto error_ret; + } + ev->ev.id = ev_code; + ev->ev.timestamp = timestamp; + + list_add_tail(&ev->list, &ev_int->det_events); + ev_int->current_events++; + mutex_unlock(&ev_int->event_list_lock); + wake_up_interruptible(&ev_int->wait); + } else + mutex_unlock(&ev_int->event_list_lock); + +error_ret: + return ret; +} +EXPORT_SYMBOL(iio_push_event); + +static ssize_t iio_event_chrdev_read(struct file *filep, + char __user *buf, + size_t count, + loff_t *f_ps) +{ + struct iio_event_interface *ev_int = filep->private_data; + struct iio_detected_event_list *el; + size_t len = sizeof(el->ev); + int ret; + + if (count < len) + return -EINVAL; + + mutex_lock(&ev_int->event_list_lock); + if (list_empty(&ev_int->det_events)) { + if (filep->f_flags & O_NONBLOCK) { + ret = -EAGAIN; + goto error_mutex_unlock; + } + mutex_unlock(&ev_int->event_list_lock); + /* Blocking on device; waiting for something to be there */ + ret = wait_event_interruptible(ev_int->wait, + !list_empty(&ev_int + ->det_events)); + if (ret) + goto error_ret; + /* Single access device so no one else can get the data */ + mutex_lock(&ev_int->event_list_lock); + } + + el = list_first_entry(&ev_int->det_events, + struct iio_detected_event_list, + list); + if (copy_to_user(buf, &(el->ev), len)) { + ret = -EFAULT; + goto error_mutex_unlock; + } + list_del(&el->list); + ev_int->current_events--; + mutex_unlock(&ev_int->event_list_lock); + kfree(el); + + return len; + +error_mutex_unlock: + mutex_unlock(&ev_int->event_list_lock); +error_ret: + + return ret; +} + +static int iio_event_chrdev_release(struct inode *inode, struct file *filep) +{ + struct iio_event_interface *ev_int = filep->private_data; + struct iio_detected_event_list *el, *t; + + mutex_lock(&ev_int->event_list_lock); + clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags); + /* + * In order to maintain a clean state for reopening, + * clear out any awaiting events. The mask will prevent + * any new __iio_push_event calls running. + */ + list_for_each_entry_safe(el, t, &ev_int->det_events, list) { + list_del(&el->list); + kfree(el); + } + ev_int->current_events = 0; + mutex_unlock(&ev_int->event_list_lock); + + return 0; +} + +static const struct file_operations iio_event_chrdev_fileops = { + .read = iio_event_chrdev_read, + .release = iio_event_chrdev_release, + .owner = THIS_MODULE, + .llseek = noop_llseek, +}; + +int iio_event_getfd(struct iio_dev *indio_dev) +{ + struct iio_event_interface *ev_int = indio_dev->event_interface; + int fd; + + if (ev_int == NULL) + return -ENODEV; + + mutex_lock(&ev_int->event_list_lock); + if (test_and_set_bit(IIO_BUSY_BIT_POS, &ev_int->flags)) { + mutex_unlock(&ev_int->event_list_lock); + return -EBUSY; + } + mutex_unlock(&ev_int->event_list_lock); + fd = anon_inode_getfd("iio:event", + &iio_event_chrdev_fileops, ev_int, O_RDONLY); + if (fd < 0) { + mutex_lock(&ev_int->event_list_lock); + clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags); + mutex_unlock(&ev_int->event_list_lock); + } + return fd; +} + +static const char * const iio_ev_type_text[] = { + [IIO_EV_TYPE_THRESH] = "thresh", + [IIO_EV_TYPE_MAG] = "mag", + [IIO_EV_TYPE_ROC] = "roc", + [IIO_EV_TYPE_THRESH_ADAPTIVE] = "thresh_adaptive", + [IIO_EV_TYPE_MAG_ADAPTIVE] = "mag_adaptive", +}; + +static const char * const iio_ev_dir_text[] = { + [IIO_EV_DIR_EITHER] = "either", + [IIO_EV_DIR_RISING] = "rising", + [IIO_EV_DIR_FALLING] = "falling" +}; + +static ssize_t iio_ev_state_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + int ret; + bool val; + + ret = strtobool(buf, &val); + if (ret < 0) + return ret; + + ret = indio_dev->info->write_event_config(indio_dev, + this_attr->address, + val); + return (ret < 0) ? ret : len; +} + +static ssize_t iio_ev_state_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + int val = indio_dev->info->read_event_config(indio_dev, + this_attr->address); + + if (val < 0) + return val; + else + return sprintf(buf, "%d\n", val); +} + +static ssize_t iio_ev_value_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + int val, ret; + + ret = indio_dev->info->read_event_value(indio_dev, + this_attr->address, &val); + if (ret < 0) + return ret; + + return sprintf(buf, "%d\n", val); +} + +static ssize_t iio_ev_value_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + unsigned long val; + int ret; + + if (!indio_dev->info->write_event_value) + return -EINVAL; + + ret = strict_strtoul(buf, 10, &val); + if (ret) + return ret; + + ret = indio_dev->info->write_event_value(indio_dev, this_attr->address, + val); + if (ret < 0) + return ret; + + return len; +} + +static int iio_device_add_event_sysfs(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan) +{ + int ret = 0, i, attrcount = 0; + u64 mask = 0; + char *postfix; + if (!chan->event_mask) + return 0; + + for_each_set_bit(i, &chan->event_mask, sizeof(chan->event_mask)*8) { + postfix = kasprintf(GFP_KERNEL, "%s_%s_en", + iio_ev_type_text[i/IIO_EV_DIR_MAX], + iio_ev_dir_text[i%IIO_EV_DIR_MAX]); + if (postfix == NULL) { + ret = -ENOMEM; + goto error_ret; + } + if (chan->modified) + mask = IIO_MOD_EVENT_CODE(chan->type, 0, chan->channel, + i/IIO_EV_DIR_MAX, + i%IIO_EV_DIR_MAX); + else if (chan->differential) + mask = IIO_EVENT_CODE(chan->type, + 0, 0, + i%IIO_EV_DIR_MAX, + i/IIO_EV_DIR_MAX, + 0, + chan->channel, + chan->channel2); + else + mask = IIO_UNMOD_EVENT_CODE(chan->type, + chan->channel, + i/IIO_EV_DIR_MAX, + i%IIO_EV_DIR_MAX); + + ret = __iio_add_chan_devattr(postfix, + chan, + &iio_ev_state_show, + iio_ev_state_store, + mask, + 0, + &indio_dev->dev, + &indio_dev->event_interface-> + dev_attr_list); + kfree(postfix); + if (ret) + goto error_ret; + attrcount++; + postfix = kasprintf(GFP_KERNEL, "%s_%s_value", + iio_ev_type_text[i/IIO_EV_DIR_MAX], + iio_ev_dir_text[i%IIO_EV_DIR_MAX]); + if (postfix == NULL) { + ret = -ENOMEM; + goto error_ret; + } + ret = __iio_add_chan_devattr(postfix, chan, + iio_ev_value_show, + iio_ev_value_store, + mask, + 0, + &indio_dev->dev, + &indio_dev->event_interface-> + dev_attr_list); + kfree(postfix); + if (ret) + goto error_ret; + attrcount++; + } + ret = attrcount; +error_ret: + return ret; +} + +static inline void __iio_remove_event_config_attrs(struct iio_dev *indio_dev) +{ + struct iio_dev_attr *p, *n; + list_for_each_entry_safe(p, n, + &indio_dev->event_interface-> + dev_attr_list, l) { + kfree(p->dev_attr.attr.name); + kfree(p); + } +} + +static inline int __iio_add_event_config_attrs(struct iio_dev *indio_dev) +{ + int j, ret, attrcount = 0; + + INIT_LIST_HEAD(&indio_dev->event_interface->dev_attr_list); + /* Dynically created from the channels array */ + for (j = 0; j < indio_dev->num_channels; j++) { + ret = iio_device_add_event_sysfs(indio_dev, + &indio_dev->channels[j]); + if (ret < 0) + goto error_clear_attrs; + attrcount += ret; + } + return attrcount; + +error_clear_attrs: + __iio_remove_event_config_attrs(indio_dev); + + return ret; +} + +static bool iio_check_for_dynamic_events(struct iio_dev *indio_dev) +{ + int j; + + for (j = 0; j < indio_dev->num_channels; j++) + if (indio_dev->channels[j].event_mask != 0) + return true; + return false; +} + +static void iio_setup_ev_int(struct iio_event_interface *ev_int) +{ + mutex_init(&ev_int->event_list_lock); + /* discussion point - make this variable? */ + ev_int->max_events = 10; + ev_int->current_events = 0; + INIT_LIST_HEAD(&ev_int->det_events); + init_waitqueue_head(&ev_int->wait); +} + +static const char *iio_event_group_name = "events"; +int iio_device_register_eventset(struct iio_dev *indio_dev) +{ + struct iio_dev_attr *p; + int ret = 0, attrcount_orig = 0, attrcount, attrn; + struct attribute **attr; + + if (!(indio_dev->info->event_attrs || + iio_check_for_dynamic_events(indio_dev))) + return 0; + + indio_dev->event_interface = + kzalloc(sizeof(struct iio_event_interface), GFP_KERNEL); + if (indio_dev->event_interface == NULL) { + ret = -ENOMEM; + goto error_ret; + } + + iio_setup_ev_int(indio_dev->event_interface); + if (indio_dev->info->event_attrs != NULL) { + attr = indio_dev->info->event_attrs->attrs; + while (*attr++ != NULL) + attrcount_orig++; + } + attrcount = attrcount_orig; + if (indio_dev->channels) { + ret = __iio_add_event_config_attrs(indio_dev); + if (ret < 0) + goto error_free_setup_event_lines; + attrcount += ret; + } + + indio_dev->event_interface->group.name = iio_event_group_name; + indio_dev->event_interface->group.attrs = kcalloc(attrcount + 1, + sizeof(indio_dev->event_interface->group.attrs[0]), + GFP_KERNEL); + if (indio_dev->event_interface->group.attrs == NULL) { + ret = -ENOMEM; + goto error_free_setup_event_lines; + } + if (indio_dev->info->event_attrs) + memcpy(indio_dev->event_interface->group.attrs, + indio_dev->info->event_attrs->attrs, + sizeof(indio_dev->event_interface->group.attrs[0]) + *attrcount_orig); + attrn = attrcount_orig; + /* Add all elements from the list. */ + list_for_each_entry(p, + &indio_dev->event_interface->dev_attr_list, + l) + indio_dev->event_interface->group.attrs[attrn++] = + &p->dev_attr.attr; + indio_dev->groups[indio_dev->groupcounter++] = + &indio_dev->event_interface->group; + + return 0; + +error_free_setup_event_lines: + __iio_remove_event_config_attrs(indio_dev); + kfree(indio_dev->event_interface); +error_ret: + + return ret; +} + +void iio_device_unregister_eventset(struct iio_dev *indio_dev) +{ + if (indio_dev->event_interface == NULL) + return; + __iio_remove_event_config_attrs(indio_dev); + kfree(indio_dev->event_interface->group.attrs); + kfree(indio_dev->event_interface); +} -- cgit v0.10.2 From 2c00193fa15dc51566dc7931fe32184c99c6b317 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 3 Jan 2012 14:59:39 +0100 Subject: staging:iio:events: Use kfifo for event queue The current IIO event code uses a list to emulate FIFO like behavior. Just use a kfifo directly instead to implement the event queue. As part of this patch the maximum of events in the queue is increased from 10 to 16 since kfifo requires a power of two for the number of FIFO elements. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/iio/industrialio-event.c b/drivers/staging/iio/industrialio-event.c index a7b345d..335b615 100644 --- a/drivers/staging/iio/industrialio-event.c +++ b/drivers/staging/iio/industrialio-event.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -24,22 +25,10 @@ #include "events.h" /** - * struct iio_detected_event_list - list element for events that have occurred - * @list: linked list header - * @ev: the event itself - */ -struct iio_detected_event_list { - struct list_head list; - struct iio_event_data ev; -}; - -/** * struct iio_event_interface - chrdev interface for an event line * @wait: wait queue to allow blocking reads of events * @event_list_lock: mutex to protect the list of detected events * @det_events: list of detected events - * @max_events: maximum number of events before new ones are dropped - * @current_events: number of events in detected list * @dev_attr_list: list of event interface sysfs attribute * @flags: file operations related flags including busy flag. * @group: event interface sysfs attribute group @@ -47,9 +36,8 @@ struct iio_detected_event_list { struct iio_event_interface { wait_queue_head_t wait; struct mutex event_list_lock; - struct list_head det_events; - int max_events; - int current_events; + DECLARE_KFIFO(det_events, struct iio_event_data, 16); + struct list_head dev_attr_list; unsigned long flags; struct attribute_group group; @@ -58,34 +46,25 @@ struct iio_event_interface { int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp) { struct iio_event_interface *ev_int = indio_dev->event_interface; - struct iio_detected_event_list *ev; - int ret = 0; + struct iio_event_data ev; + int copied; /* Does anyone care? */ mutex_lock(&ev_int->event_list_lock); if (test_bit(IIO_BUSY_BIT_POS, &ev_int->flags)) { - if (ev_int->current_events == ev_int->max_events) { - mutex_unlock(&ev_int->event_list_lock); - return 0; - } - ev = kmalloc(sizeof(*ev), GFP_KERNEL); - if (ev == NULL) { - ret = -ENOMEM; - mutex_unlock(&ev_int->event_list_lock); - goto error_ret; - } - ev->ev.id = ev_code; - ev->ev.timestamp = timestamp; - list_add_tail(&ev->list, &ev_int->det_events); - ev_int->current_events++; + ev.id = ev_code; + ev.timestamp = timestamp; + + copied = kfifo_put(&ev_int->det_events, &ev); + mutex_unlock(&ev_int->event_list_lock); - wake_up_interruptible(&ev_int->wait); + if (copied != 0) + wake_up_interruptible(&ev_int->wait); } else mutex_unlock(&ev_int->event_list_lock); -error_ret: - return ret; + return 0; } EXPORT_SYMBOL(iio_push_event); @@ -95,15 +74,14 @@ static ssize_t iio_event_chrdev_read(struct file *filep, loff_t *f_ps) { struct iio_event_interface *ev_int = filep->private_data; - struct iio_detected_event_list *el; - size_t len = sizeof(el->ev); + unsigned int copied; int ret; - if (count < len) + if (count < sizeof(struct iio_event_data)) return -EINVAL; mutex_lock(&ev_int->event_list_lock); - if (list_empty(&ev_int->det_events)) { + if (kfifo_is_empty(&ev_int->det_events)) { if (filep->f_flags & O_NONBLOCK) { ret = -EAGAIN; goto error_mutex_unlock; @@ -111,39 +89,25 @@ static ssize_t iio_event_chrdev_read(struct file *filep, mutex_unlock(&ev_int->event_list_lock); /* Blocking on device; waiting for something to be there */ ret = wait_event_interruptible(ev_int->wait, - !list_empty(&ev_int - ->det_events)); + !kfifo_is_empty(&ev_int->det_events)); if (ret) goto error_ret; /* Single access device so no one else can get the data */ mutex_lock(&ev_int->event_list_lock); } - el = list_first_entry(&ev_int->det_events, - struct iio_detected_event_list, - list); - if (copy_to_user(buf, &(el->ev), len)) { - ret = -EFAULT; - goto error_mutex_unlock; - } - list_del(&el->list); - ev_int->current_events--; mutex_unlock(&ev_int->event_list_lock); - kfree(el); - - return len; + ret = kfifo_to_user(&ev_int->det_events, buf, count, &copied); error_mutex_unlock: mutex_unlock(&ev_int->event_list_lock); error_ret: - - return ret; + return ret ? ret : copied; } static int iio_event_chrdev_release(struct inode *inode, struct file *filep) { struct iio_event_interface *ev_int = filep->private_data; - struct iio_detected_event_list *el, *t; mutex_lock(&ev_int->event_list_lock); clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags); @@ -152,11 +116,7 @@ static int iio_event_chrdev_release(struct inode *inode, struct file *filep) * clear out any awaiting events. The mask will prevent * any new __iio_push_event calls running. */ - list_for_each_entry_safe(el, t, &ev_int->det_events, list) { - list_del(&el->list); - kfree(el); - } - ev_int->current_events = 0; + kfifo_reset_out(&ev_int->det_events); mutex_unlock(&ev_int->event_list_lock); return 0; @@ -401,10 +361,7 @@ static bool iio_check_for_dynamic_events(struct iio_dev *indio_dev) static void iio_setup_ev_int(struct iio_event_interface *ev_int) { mutex_init(&ev_int->event_list_lock); - /* discussion point - make this variable? */ - ev_int->max_events = 10; - ev_int->current_events = 0; - INIT_LIST_HEAD(&ev_int->det_events); + INIT_KFIFO(ev_int->det_events); init_waitqueue_head(&ev_int->wait); } -- cgit v0.10.2 From 43ba1100af11f34cc67bdf6b359667cfa851e6a8 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 3 Jan 2012 14:59:40 +0100 Subject: staging:iio:events: Use waitqueue lock to protect event queue Use the waitqueue lock to protect the event queue instead of a custom mutex. This has the advantage that we can call the waitqueue operations with the lock held, which simplifies the code flow a bit. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/iio/industrialio-event.c b/drivers/staging/iio/industrialio-event.c index 335b615..f0c41f1 100644 --- a/drivers/staging/iio/industrialio-event.c +++ b/drivers/staging/iio/industrialio-event.c @@ -35,7 +35,6 @@ */ struct iio_event_interface { wait_queue_head_t wait; - struct mutex event_list_lock; DECLARE_KFIFO(det_events, struct iio_event_data, 16); struct list_head dev_attr_list; @@ -50,19 +49,17 @@ int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp) int copied; /* Does anyone care? */ - mutex_lock(&ev_int->event_list_lock); + spin_lock(&ev_int->wait.lock); if (test_bit(IIO_BUSY_BIT_POS, &ev_int->flags)) { ev.id = ev_code; ev.timestamp = timestamp; copied = kfifo_put(&ev_int->det_events, &ev); - - mutex_unlock(&ev_int->event_list_lock); if (copied != 0) - wake_up_interruptible(&ev_int->wait); - } else - mutex_unlock(&ev_int->event_list_lock); + wake_up_locked(&ev_int->wait); + } + spin_unlock(&ev_int->wait.lock); return 0; } @@ -80,28 +77,25 @@ static ssize_t iio_event_chrdev_read(struct file *filep, if (count < sizeof(struct iio_event_data)) return -EINVAL; - mutex_lock(&ev_int->event_list_lock); + spin_lock(&ev_int->wait.lock); if (kfifo_is_empty(&ev_int->det_events)) { if (filep->f_flags & O_NONBLOCK) { ret = -EAGAIN; - goto error_mutex_unlock; + goto error_unlock; } - mutex_unlock(&ev_int->event_list_lock); /* Blocking on device; waiting for something to be there */ - ret = wait_event_interruptible(ev_int->wait, + ret = wait_event_interruptible_locked(ev_int->wait, !kfifo_is_empty(&ev_int->det_events)); if (ret) - goto error_ret; + goto error_unlock; /* Single access device so no one else can get the data */ - mutex_lock(&ev_int->event_list_lock); } - mutex_unlock(&ev_int->event_list_lock); ret = kfifo_to_user(&ev_int->det_events, buf, count, &copied); -error_mutex_unlock: - mutex_unlock(&ev_int->event_list_lock); -error_ret: +error_unlock: + spin_unlock(&ev_int->wait.lock); + return ret ? ret : copied; } @@ -109,7 +103,7 @@ static int iio_event_chrdev_release(struct inode *inode, struct file *filep) { struct iio_event_interface *ev_int = filep->private_data; - mutex_lock(&ev_int->event_list_lock); + spin_lock(&ev_int->wait.lock); clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags); /* * In order to maintain a clean state for reopening, @@ -117,7 +111,7 @@ static int iio_event_chrdev_release(struct inode *inode, struct file *filep) * any new __iio_push_event calls running. */ kfifo_reset_out(&ev_int->det_events); - mutex_unlock(&ev_int->event_list_lock); + spin_unlock(&ev_int->wait.lock); return 0; } @@ -137,18 +131,18 @@ int iio_event_getfd(struct iio_dev *indio_dev) if (ev_int == NULL) return -ENODEV; - mutex_lock(&ev_int->event_list_lock); + spin_lock(&ev_int->wait.lock); if (test_and_set_bit(IIO_BUSY_BIT_POS, &ev_int->flags)) { - mutex_unlock(&ev_int->event_list_lock); + spin_unlock(&ev_int->wait.lock); return -EBUSY; } - mutex_unlock(&ev_int->event_list_lock); + spin_unlock(&ev_int->wait.lock); fd = anon_inode_getfd("iio:event", &iio_event_chrdev_fileops, ev_int, O_RDONLY); if (fd < 0) { - mutex_lock(&ev_int->event_list_lock); + spin_lock(&ev_int->wait.lock); clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags); - mutex_unlock(&ev_int->event_list_lock); + spin_unlock(&ev_int->wait.lock); } return fd; } @@ -360,7 +354,6 @@ static bool iio_check_for_dynamic_events(struct iio_dev *indio_dev) static void iio_setup_ev_int(struct iio_event_interface *ev_int) { - mutex_init(&ev_int->event_list_lock); INIT_KFIFO(ev_int->det_events); init_waitqueue_head(&ev_int->wait); } -- cgit v0.10.2 From e18045ed75ec682a26a385b0072dcc030fd12a7e Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 3 Jan 2012 14:59:41 +0100 Subject: staging:iio:events: Add poll support Add poll support to the event queue. This will allow us to check for pending events in a application's event loop using poll() or similar. Since we already have support for blocking reads adding poll support as well is trivial. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/iio/industrialio-event.c b/drivers/staging/iio/industrialio-event.c index f0c41f1..800f67d 100644 --- a/drivers/staging/iio/industrialio-event.c +++ b/drivers/staging/iio/industrialio-event.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -57,7 +58,7 @@ int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp) copied = kfifo_put(&ev_int->det_events, &ev); if (copied != 0) - wake_up_locked(&ev_int->wait); + wake_up_locked_poll(&ev_int->wait, POLLIN); } spin_unlock(&ev_int->wait.lock); @@ -65,6 +66,25 @@ int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp) } EXPORT_SYMBOL(iio_push_event); +/** + * iio_event_poll() - poll the event queue to find out if it has data + */ +static unsigned int iio_event_poll(struct file *filep, + struct poll_table_struct *wait) +{ + struct iio_event_interface *ev_int = filep->private_data; + unsigned int events = 0; + + poll_wait(filep, &ev_int->wait, wait); + + spin_lock(&ev_int->wait.lock); + if (!kfifo_is_empty(&ev_int->det_events)) + events = POLLIN | POLLRDNORM; + spin_unlock(&ev_int->wait.lock); + + return events; +} + static ssize_t iio_event_chrdev_read(struct file *filep, char __user *buf, size_t count, @@ -118,6 +138,7 @@ static int iio_event_chrdev_release(struct inode *inode, struct file *filep) static const struct file_operations iio_event_chrdev_fileops = { .read = iio_event_chrdev_read, + .poll = iio_event_poll, .release = iio_event_chrdev_release, .owner = THIS_MODULE, .llseek = noop_llseek, -- cgit v0.10.2 From a046c1e866673dd334c31d06312283e2bc5b483b Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 3 Jan 2012 14:59:42 +0100 Subject: staging:iio:events: Use non-atmoic bitops We always hold the waitqueue lock when modifying the flags field. So it is safe to use the non-atomic bitops here instead of the atomic versions. The lock has to be held, because we need to clear the busy flag and flush the event FIFO in one atomic operation when closing the event file descriptor. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/iio/industrialio-event.c b/drivers/staging/iio/industrialio-event.c index 800f67d..66d320b 100644 --- a/drivers/staging/iio/industrialio-event.c +++ b/drivers/staging/iio/industrialio-event.c @@ -124,7 +124,7 @@ static int iio_event_chrdev_release(struct inode *inode, struct file *filep) struct iio_event_interface *ev_int = filep->private_data; spin_lock(&ev_int->wait.lock); - clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags); + __clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags); /* * In order to maintain a clean state for reopening, * clear out any awaiting events. The mask will prevent @@ -153,7 +153,7 @@ int iio_event_getfd(struct iio_dev *indio_dev) return -ENODEV; spin_lock(&ev_int->wait.lock); - if (test_and_set_bit(IIO_BUSY_BIT_POS, &ev_int->flags)) { + if (__test_and_set_bit(IIO_BUSY_BIT_POS, &ev_int->flags)) { spin_unlock(&ev_int->wait.lock); return -EBUSY; } @@ -162,7 +162,7 @@ int iio_event_getfd(struct iio_dev *indio_dev) &iio_event_chrdev_fileops, ev_int, O_RDONLY); if (fd < 0) { spin_lock(&ev_int->wait.lock); - clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags); + __clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags); spin_unlock(&ev_int->wait.lock); } return fd; -- cgit v0.10.2 From 15bbb7793ad7f6f106ce09fdfa3956c5aff37cf1 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sun, 29 Jan 2012 11:07:00 +0000 Subject: staging:iio:adc:ad7192 unwind use of is_visible for attribute group. It saves a couple of lines of code but reduces simplicity of code. I generally wish to discourage use of is_visible throughout IIO. Signed-off-by: Jonathan Cameron Acked-by: Lars-Peter Clausen Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c index 9d25165..9fd6d63 100644 --- a/drivers/staging/iio/adc/ad7192.c +++ b/drivers/staging/iio/adc/ad7192.c @@ -822,25 +822,20 @@ static struct attribute *ad7192_attributes[] = { NULL }; -static umode_t ad7192_attr_is_visible(struct kobject *kobj, - struct attribute *attr, int n) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad7192_state *st = iio_priv(indio_dev); - - umode_t mode = attr->mode; - - if ((st->devid != ID_AD7195) && - (attr == &iio_dev_attr_ac_excitation_en.dev_attr.attr)) - mode = 0; - - return mode; -} - static const struct attribute_group ad7192_attribute_group = { .attrs = ad7192_attributes, - .is_visible = ad7192_attr_is_visible, +}; + +static struct attribute *ad7195_attributes[] = { + &iio_dev_attr_sampling_frequency.dev_attr.attr, + &iio_dev_attr_in_v_m_v_scale_available.dev_attr.attr, + &iio_dev_attr_in_voltage_scale_available.dev_attr.attr, + &iio_dev_attr_bridge_switch_en.dev_attr.attr, + NULL +}; + +static const struct attribute_group ad7195_attribute_group = { + .attrs = ad7195_attributes, }; static int ad7192_read_raw(struct iio_dev *indio_dev, @@ -970,6 +965,15 @@ static const struct iio_info ad7192_info = { .driver_module = THIS_MODULE, }; +static const struct iio_info ad7195_info = { + .read_raw = &ad7192_read_raw, + .write_raw = &ad7192_write_raw, + .write_raw_get_fmt = &ad7192_write_raw_get_fmt, + .attrs = &ad7195_attribute_group, + .validate_trigger = ad7192_validate_trigger, + .driver_module = THIS_MODULE, +}; + #define AD7192_CHAN_DIFF(_chan, _chan2, _name, _address, _si) \ { .type = IIO_VOLTAGE, \ .differential = 1, \ @@ -1062,7 +1066,10 @@ static int __devinit ad7192_probe(struct spi_device *spi) indio_dev->channels = ad7192_channels; indio_dev->num_channels = ARRAY_SIZE(ad7192_channels); indio_dev->available_scan_masks = st->available_scan_masks; - indio_dev->info = &ad7192_info; + if (st->devid == ID_AD7195) + indio_dev->info = &ad7195_info; + else + indio_dev->info = &ad7192_info; for (i = 0; i < indio_dev->num_channels; i++) st->available_scan_masks[i] = (1 << i) | (1 << -- cgit v0.10.2 From b2c04a34aa9a1b82af590b7e7cc965e7125ce9fa Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sun, 29 Jan 2012 11:07:01 +0000 Subject: staging:iio:dds:ad9834 unwind use of is_visible for attrs. Trivial usecase in which just having two different attr groups covers all options. Slightly more code, but a simpler to follow result. Signed-off-by: Jonathan Cameron Acked-by: Lars-Peter Clausen Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/iio/dds/ad9834.c b/drivers/staging/iio/dds/ad9834.c index 5e67104..38a2de0 100644 --- a/drivers/staging/iio/dds/ad9834.c +++ b/drivers/staging/iio/dds/ad9834.c @@ -281,29 +281,27 @@ static struct attribute *ad9834_attributes[] = { NULL, }; -static umode_t ad9834_attr_is_visible(struct kobject *kobj, - struct attribute *attr, int n) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad9834_state *st = iio_priv(indio_dev); - - umode_t mode = attr->mode; - - if (((st->devid == ID_AD9833) || (st->devid == ID_AD9837)) && - ((attr == &iio_dev_attr_dds0_out1_enable.dev_attr.attr) || - (attr == &iio_dev_attr_dds0_out1_wavetype.dev_attr.attr) || - (attr == - &iio_dev_attr_dds0_out1_wavetype_available.dev_attr.attr) || - (attr == &iio_dev_attr_dds0_pincontrol_en.dev_attr.attr))) - mode = 0; - - return mode; -} +static struct attribute *ad9833_attributes[] = { + &iio_dev_attr_dds0_freq0.dev_attr.attr, + &iio_dev_attr_dds0_freq1.dev_attr.attr, + &iio_const_attr_dds0_freq_scale.dev_attr.attr, + &iio_dev_attr_dds0_phase0.dev_attr.attr, + &iio_dev_attr_dds0_phase1.dev_attr.attr, + &iio_const_attr_dds0_phase_scale.dev_attr.attr, + &iio_dev_attr_dds0_freqsymbol.dev_attr.attr, + &iio_dev_attr_dds0_phasesymbol.dev_attr.attr, + &iio_dev_attr_dds0_out_enable.dev_attr.attr, + &iio_dev_attr_dds0_out0_wavetype.dev_attr.attr, + &iio_dev_attr_dds0_out0_wavetype_available.dev_attr.attr, + NULL, +}; static const struct attribute_group ad9834_attribute_group = { .attrs = ad9834_attributes, - .is_visible = ad9834_attr_is_visible, +}; + +static const struct attribute_group ad9833_attribute_group = { + .attrs = ad9833_attributes, }; static const struct iio_info ad9834_info = { @@ -311,6 +309,11 @@ static const struct iio_info ad9834_info = { .driver_module = THIS_MODULE, }; +static const struct iio_info ad9833_info = { + .attrs = &ad9833_attribute_group, + .driver_module = THIS_MODULE, +}; + static int __devinit ad9834_probe(struct spi_device *spi) { struct ad9834_platform_data *pdata = spi->dev.platform_data; @@ -344,7 +347,15 @@ static int __devinit ad9834_probe(struct spi_device *spi) st->reg = reg; indio_dev->dev.parent = &spi->dev; indio_dev->name = spi_get_device_id(spi)->name; - indio_dev->info = &ad9834_info; + switch (st->devid) { + case ID_AD9833: + case ID_AD9837: + indio_dev->info = &ad9833_info; + break; + default: + indio_dev->info = &ad9834_info; + break; + } indio_dev->modes = INDIO_DIRECT_MODE; /* Setup default messages */ -- cgit v0.10.2 From 7389266cc9fa4b9b2761785bcc6fba7bbeb8d070 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sun, 29 Jan 2012 11:07:02 +0000 Subject: staging:iio:dac:ad5446 unwind use of is_visible for attrs. Trivial case where no attributes are valid for some parts. Better handled using two iio_info structures and selecting the right one at probe time. Signed-off-by: Jonathan Cameron Acked-by: Lars-Peter Clausen Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/iio/dac/ad5446.c b/drivers/staging/iio/dac/ad5446.c index 693e748..e439bae 100644 --- a/drivers/staging/iio/dac/ad5446.c +++ b/drivers/staging/iio/dac/ad5446.c @@ -149,30 +149,8 @@ static struct attribute *ad5446_attributes[] = { NULL, }; -static umode_t ad5446_attr_is_visible(struct kobject *kobj, - struct attribute *attr, int n) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad5446_state *st = iio_priv(indio_dev); - - umode_t mode = attr->mode; - - if (!st->chip_info->store_pwr_down && - (attr == &iio_dev_attr_out_voltage0_powerdown.dev_attr.attr || - attr == &iio_dev_attr_out_voltage_powerdown_mode. - dev_attr.attr || - attr == - &iio_const_attr_out_voltage_powerdown_mode_available. - dev_attr.attr)) - mode = 0; - - return mode; -} - static const struct attribute_group ad5446_attribute_group = { .attrs = ad5446_attributes, - .is_visible = ad5446_attr_is_visible, }; #define AD5446_CHANNEL(bits, storage, shift) { \ @@ -321,6 +299,12 @@ static const struct iio_info ad5446_info = { .driver_module = THIS_MODULE, }; +static const struct iio_info ad5446_info_no_pwr_down = { + .read_raw = ad5446_read_raw, + .write_raw = ad5446_write_raw, + .driver_module = THIS_MODULE, +}; + static int __devinit ad5446_probe(struct spi_device *spi) { struct ad5446_state *st; @@ -353,7 +337,10 @@ static int __devinit ad5446_probe(struct spi_device *spi) /* Estabilish that the iio_dev is a child of the spi device */ indio_dev->dev.parent = &spi->dev; indio_dev->name = spi_get_device_id(spi)->name; - indio_dev->info = &ad5446_info; + if (st->chip_info->store_pwr_down) + indio_dev->info = &ad5446_info; + else + indio_dev->info = &ad5446_info_no_pwr_down; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = &st->chip_info->channel; indio_dev->num_channels = 1; -- cgit v0.10.2 From 9214cc6e1302f5af5ee76db38d345907806dca67 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sun, 29 Jan 2012 11:07:03 +0000 Subject: staging:iio:adc:ad7606 unwind use of is_visible for attrs. This is the most controversial of this set of is_visible removals. There are two conditions controlling availability of attrs resulting in 4 different attribute groups. Still for a few more lines things are clearer to read to my mind. Signed-off-by: Jonathan Cameron Acked-by: Lars-Peter Clausen Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/iio/adc/ad7606_core.c b/drivers/staging/iio/adc/ad7606_core.c index ddb7ef9..97e8d3d 100644 --- a/drivers/staging/iio/adc/ad7606_core.c +++ b/drivers/staging/iio/adc/ad7606_core.c @@ -197,7 +197,7 @@ static IIO_DEVICE_ATTR(oversampling_ratio, S_IRUGO | S_IWUSR, ad7606_store_oversampling_ratio, 0); static IIO_CONST_ATTR(oversampling_ratio_available, "0 2 4 8 16 32 64"); -static struct attribute *ad7606_attributes[] = { +static struct attribute *ad7606_attributes_os_and_range[] = { &iio_dev_attr_in_voltage_range.dev_attr.attr, &iio_const_attr_in_voltage_range_available.dev_attr.attr, &iio_dev_attr_oversampling_ratio.dev_attr.attr, @@ -205,34 +205,28 @@ static struct attribute *ad7606_attributes[] = { NULL, }; -static umode_t ad7606_attr_is_visible(struct kobject *kobj, - struct attribute *attr, int n) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad7606_state *st = iio_priv(indio_dev); +static const struct attribute_group ad7606_attribute_group_os_and_range = { + .attrs = ad7606_attributes_os_and_range, +}; - umode_t mode = attr->mode; - - if (!(gpio_is_valid(st->pdata->gpio_os0) && - gpio_is_valid(st->pdata->gpio_os1) && - gpio_is_valid(st->pdata->gpio_os2)) && - (attr == &iio_dev_attr_oversampling_ratio.dev_attr.attr || - attr == - &iio_const_attr_oversampling_ratio_available.dev_attr.attr)) - mode = 0; - else if (!gpio_is_valid(st->pdata->gpio_range) && - (attr == &iio_dev_attr_in_voltage_range.dev_attr.attr || - attr == - &iio_const_attr_in_voltage_range_available.dev_attr.attr)) - mode = 0; - - return mode; -} +static struct attribute *ad7606_attributes_os[] = { + &iio_dev_attr_oversampling_ratio.dev_attr.attr, + &iio_const_attr_oversampling_ratio_available.dev_attr.attr, + NULL, +}; -static const struct attribute_group ad7606_attribute_group = { - .attrs = ad7606_attributes, - .is_visible = ad7606_attr_is_visible, +static const struct attribute_group ad7606_attribute_group_os = { + .attrs = ad7606_attributes_os, +}; + +static struct attribute *ad7606_attributes_range[] = { + &iio_dev_attr_in_voltage_range.dev_attr.attr, + &iio_const_attr_in_voltage_range_available.dev_attr.attr, + NULL, +}; + +static const struct attribute_group ad7606_attribute_group_range = { + .attrs = ad7606_attributes_range, }; #define AD7606_CHANNEL(num) \ @@ -435,10 +429,27 @@ static irqreturn_t ad7606_interrupt(int irq, void *dev_id) return IRQ_HANDLED; }; -static const struct iio_info ad7606_info = { +static const struct iio_info ad7606_info_no_os_or_range = { .driver_module = THIS_MODULE, .read_raw = &ad7606_read_raw, - .attrs = &ad7606_attribute_group, +}; + +static const struct iio_info ad7606_info_os_and_range = { + .driver_module = THIS_MODULE, + .read_raw = &ad7606_read_raw, + .attrs = &ad7606_attribute_group_os_and_range, +}; + +static const struct iio_info ad7606_info_os = { + .driver_module = THIS_MODULE, + .read_raw = &ad7606_read_raw, + .attrs = &ad7606_attribute_group_os, +}; + +static const struct iio_info ad7606_info_range = { + .driver_module = THIS_MODULE, + .read_raw = &ad7606_read_raw, + .attrs = &ad7606_attribute_group_range, }; struct iio_dev *ad7606_probe(struct device *dev, int irq, @@ -483,7 +494,19 @@ struct iio_dev *ad7606_probe(struct device *dev, int irq, st->chip_info = &ad7606_chip_info_tbl[id]; indio_dev->dev.parent = dev; - indio_dev->info = &ad7606_info; + if (gpio_is_valid(st->pdata->gpio_os0) && + gpio_is_valid(st->pdata->gpio_os1) && + gpio_is_valid(st->pdata->gpio_os2)) { + if (gpio_is_valid(st->pdata->gpio_range)) + indio_dev->info = &ad7606_info_os_and_range; + else + indio_dev->info = &ad7606_info_os; + } else { + if (gpio_is_valid(st->pdata->gpio_range)) + indio_dev->info = &ad7606_info_range; + else + indio_dev->info = &ad7606_info_no_os_or_range; + } indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->name = st->chip_info->name; indio_dev->channels = st->chip_info->channels; -- cgit v0.10.2 From 8f9cde23c3f7b74dfad617d2ffbbb5c2ba55e1ee Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sun, 29 Jan 2012 11:07:04 +0000 Subject: staging:iio:adc:adt7310/7410 sticking plaster fix for broken event attrs. Neither of these drivers has ever been anywhere near the iio abi. Probably as a result of this the fact they had two event groups each was not picked up when we restricted IIO to having only 1 event line per device (as part of the chrdev merge set). As such these definitely didn't work before. This patch squishes the only element from the 'comparator' event line that isn't in the 'interrupt' one into it and kills off the 'comparator' one. Ultimately both of these drivers belong in hwmon not IIO and are just waiting here because I don't want to kill off a driver that may prove useful to someone. (Ultimately I will ask Greg to scrap these two if no one steps up to deal with them.) Signed-off-by: Jonathan Cameron Acked-by: Lars-Peter Clausen Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/iio/adc/adt7310.c b/drivers/staging/iio/adc/adt7310.c index eec2f32..caf57c1 100644 --- a/drivers/staging/iio/adc/adt7310.c +++ b/drivers/staging/iio/adc/adt7310.c @@ -725,32 +725,19 @@ static struct attribute *adt7310_event_int_attributes[] = { &iio_dev_attr_fault_queue.dev_attr.attr, &iio_dev_attr_t_alarm_high.dev_attr.attr, &iio_dev_attr_t_alarm_low.dev_attr.attr, - &iio_dev_attr_t_hyst.dev_attr.attr, - NULL, -}; - -static struct attribute *adt7310_event_ct_attributes[] = { - &iio_dev_attr_event_mode.dev_attr.attr, - &iio_dev_attr_available_event_modes.dev_attr.attr, - &iio_dev_attr_fault_queue.dev_attr.attr, &iio_dev_attr_t_crit.dev_attr.attr, &iio_dev_attr_t_hyst.dev_attr.attr, NULL, }; -static struct attribute_group adt7310_event_attribute_group[ADT7310_IRQS] = { - { - .attrs = adt7310_event_int_attributes, - .name = "events", - }, { - .attrs = adt7310_event_ct_attributes, - .name = "events", - } +static struct attribute_group adt7310_event_attribute_group = { + .attrs = adt7310_event_int_attributes, + .name = "events", }; static const struct iio_info adt7310_info = { .attrs = &adt7310_attribute_group, - .event_attrs = adt7310_event_attribute_group, + .event_attrs = &adt7310_event_attribute_group, .driver_module = THIS_MODULE, }; diff --git a/drivers/staging/iio/adc/adt7410.c b/drivers/staging/iio/adc/adt7410.c index c62248c..dff3e8c 100644 --- a/drivers/staging/iio/adc/adt7410.c +++ b/drivers/staging/iio/adc/adt7410.c @@ -693,32 +693,19 @@ static struct attribute *adt7410_event_int_attributes[] = { &iio_dev_attr_fault_queue.dev_attr.attr, &iio_dev_attr_t_alarm_high.dev_attr.attr, &iio_dev_attr_t_alarm_low.dev_attr.attr, - &iio_dev_attr_t_hyst.dev_attr.attr, - NULL, -}; - -static struct attribute *adt7410_event_ct_attributes[] = { - &iio_dev_attr_event_mode.dev_attr.attr, - &iio_dev_attr_available_event_modes.dev_attr.attr, - &iio_dev_attr_fault_queue.dev_attr.attr, &iio_dev_attr_t_crit.dev_attr.attr, &iio_dev_attr_t_hyst.dev_attr.attr, NULL, }; -static struct attribute_group adt7410_event_attribute_group[ADT7410_IRQS] = { - { - .attrs = adt7410_event_int_attributes, - .name = "events", - }, { - .attrs = adt7410_event_ct_attributes, - .name = "events", - } +static struct attribute_group adt7410_event_attribute_group = { + .attrs = adt7410_event_int_attributes, + .name = "events", }; static const struct iio_info adt7410_info = { .attrs = &adt7410_attribute_group, - .event_attrs = adt7410_event_attribute_group, + .event_attrs = &adt7410_event_attribute_group, .driver_module = THIS_MODULE, }; -- cgit v0.10.2 From 72a9826b45c0d126f47c1acc8444c5d9ee478fcd Mon Sep 17 00:00:00 2001 From: Seth Jennings Date: Thu, 9 Feb 2012 12:25:02 -0600 Subject: staging: zcache: fix serialization bug in zv stats In a multithreaded workload, the zv_curr_dist_counts and zv_cumul_dist_counts statistics are being corrupted because the increments and decrements in zv_create and zv_free are not atomic. This patch converts these statistics and their corresponding increments/decrements/reads to atomic operations. Signed-off-by: Seth Jennings Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/zcache/zcache-main.c b/drivers/staging/zcache/zcache-main.c index da222c2..8887fd4 100644 --- a/drivers/staging/zcache/zcache-main.c +++ b/drivers/staging/zcache/zcache-main.c @@ -690,8 +690,8 @@ static unsigned int zv_max_zsize = (PAGE_SIZE / 8) * 7; */ static unsigned int zv_max_mean_zsize = (PAGE_SIZE / 8) * 5; -static unsigned long zv_curr_dist_counts[NCHUNKS]; -static unsigned long zv_cumul_dist_counts[NCHUNKS]; +static atomic_t zv_curr_dist_counts[NCHUNKS]; +static atomic_t zv_cumul_dist_counts[NCHUNKS]; static struct zv_hdr *zv_create(struct xv_pool *xvpool, uint32_t pool_id, struct tmem_oid *oid, uint32_t index, @@ -710,8 +710,8 @@ static struct zv_hdr *zv_create(struct xv_pool *xvpool, uint32_t pool_id, &page, &offset, ZCACHE_GFP_MASK); if (unlikely(ret)) goto out; - zv_curr_dist_counts[chunks]++; - zv_cumul_dist_counts[chunks]++; + atomic_inc(&zv_curr_dist_counts[chunks]); + atomic_inc(&zv_cumul_dist_counts[chunks]); zv = kmap_atomic(page, KM_USER0) + offset; zv->index = index; zv->oid = *oid; @@ -733,7 +733,7 @@ static void zv_free(struct xv_pool *xvpool, struct zv_hdr *zv) ASSERT_SENTINEL(zv, ZVH); BUG_ON(chunks >= NCHUNKS); - zv_curr_dist_counts[chunks]--; + atomic_dec(&zv_curr_dist_counts[chunks]); size -= sizeof(*zv); BUG_ON(size == 0); INVERT_SENTINEL(zv, ZVH); @@ -773,7 +773,7 @@ static int zv_curr_dist_counts_show(char *buf) char *p = buf; for (i = 0; i < NCHUNKS; i++) { - n = zv_curr_dist_counts[i]; + n = atomic_read(&zv_curr_dist_counts[i]); p += sprintf(p, "%lu ", n); chunks += n; sum_total_chunks += i * n; @@ -789,7 +789,7 @@ static int zv_cumul_dist_counts_show(char *buf) char *p = buf; for (i = 0; i < NCHUNKS; i++) { - n = zv_cumul_dist_counts[i]; + n = atomic_read(&zv_cumul_dist_counts[i]); p += sprintf(p, "%lu ", n); chunks += n; sum_total_chunks += i * n; -- cgit v0.10.2 From a49aeb1de58557ea6f0293bdd04ddda4c5a3020b Mon Sep 17 00:00:00 2001 From: Seth Jennings Date: Thu, 9 Feb 2012 12:25:03 -0600 Subject: staging: zcache: replace xvmalloc with zsmalloc Replaces xvmalloc with zsmalloc as the persistent memory allocator for zcache Signed-off-by: Seth Jennings Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/zcache/Kconfig b/drivers/staging/zcache/Kconfig index 1b7bba7..94e48aa 100644 --- a/drivers/staging/zcache/Kconfig +++ b/drivers/staging/zcache/Kconfig @@ -1,7 +1,7 @@ config ZCACHE tristate "Dynamic compression of swap pages and clean pagecache pages" depends on (CLEANCACHE || FRONTSWAP) && CRYPTO - select XVMALLOC + select ZSMALLOC select CRYPTO_LZO default n help diff --git a/drivers/staging/zcache/zcache-main.c b/drivers/staging/zcache/zcache-main.c index 8887fd4..04a4a3f 100644 --- a/drivers/staging/zcache/zcache-main.c +++ b/drivers/staging/zcache/zcache-main.c @@ -9,7 +9,7 @@ * page-accessible memory [1] interfaces, both utilizing the crypto compression * API: * 1) "compression buddies" ("zbud") is used for ephemeral pages - * 2) xvmalloc is used for persistent pages. + * 2) zsmalloc is used for persistent pages. * Xvmalloc (based on the TLSF allocator) has very low fragmentation * so maximizes space efficiency, while zbud allows pairs (and potentially, * in the future, more than a pair of) compressed pages to be closely linked @@ -33,7 +33,7 @@ #include #include "tmem.h" -#include "../zram/xvmalloc.h" /* if built in drivers/staging */ +#include "../zsmalloc/zsmalloc.h" #if (!defined(CONFIG_CLEANCACHE) && !defined(CONFIG_FRONTSWAP)) #error "zcache is useless without CONFIG_CLEANCACHE or CONFIG_FRONTSWAP" @@ -62,7 +62,7 @@ MODULE_LICENSE("GPL"); struct zcache_client { struct tmem_pool *tmem_pools[MAX_POOLS_PER_CLIENT]; - struct xv_pool *xvpool; + struct zs_pool *zspool; bool allocated; atomic_t refcount; }; @@ -658,7 +658,7 @@ static int zbud_show_cumul_chunk_counts(char *buf) #endif /********** - * This "zv" PAM implementation combines the TLSF-based xvMalloc + * This "zv" PAM implementation combines the slab-based zsmalloc * with the crypto compression API to maximize the amount of data that can * be packed into a physical page. * @@ -672,6 +672,7 @@ struct zv_hdr { uint32_t pool_id; struct tmem_oid oid; uint32_t index; + size_t size; DECL_SENTINEL }; @@ -693,71 +694,73 @@ static unsigned int zv_max_mean_zsize = (PAGE_SIZE / 8) * 5; static atomic_t zv_curr_dist_counts[NCHUNKS]; static atomic_t zv_cumul_dist_counts[NCHUNKS]; -static struct zv_hdr *zv_create(struct xv_pool *xvpool, uint32_t pool_id, +static struct zv_hdr *zv_create(struct zs_pool *pool, uint32_t pool_id, struct tmem_oid *oid, uint32_t index, void *cdata, unsigned clen) { - struct page *page; - struct zv_hdr *zv = NULL; - uint32_t offset; - int alloc_size = clen + sizeof(struct zv_hdr); - int chunks = (alloc_size + (CHUNK_SIZE - 1)) >> CHUNK_SHIFT; - int ret; + struct zv_hdr *zv; + u32 size = clen + sizeof(struct zv_hdr); + int chunks = (size + (CHUNK_SIZE - 1)) >> CHUNK_SHIFT; + void *handle = NULL; + char *buf; BUG_ON(!irqs_disabled()); BUG_ON(chunks >= NCHUNKS); - ret = xv_malloc(xvpool, alloc_size, - &page, &offset, ZCACHE_GFP_MASK); - if (unlikely(ret)) + handle = zs_malloc(pool, size); + if (!handle) goto out; atomic_inc(&zv_curr_dist_counts[chunks]); atomic_inc(&zv_cumul_dist_counts[chunks]); - zv = kmap_atomic(page, KM_USER0) + offset; + zv = (struct zv_hdr *)((char *)cdata - sizeof(*zv)); zv->index = index; zv->oid = *oid; zv->pool_id = pool_id; + zv->size = clen; SET_SENTINEL(zv, ZVH); - memcpy((char *)zv + sizeof(struct zv_hdr), cdata, clen); - kunmap_atomic(zv, KM_USER0); + buf = zs_map_object(pool, handle); + memcpy(buf, zv, clen + sizeof(*zv)); + zs_unmap_object(pool, handle); out: - return zv; + return handle; } -static void zv_free(struct xv_pool *xvpool, struct zv_hdr *zv) +static void zv_free(struct zs_pool *pool, void *handle) { unsigned long flags; - struct page *page; - uint32_t offset; - uint16_t size = xv_get_object_size(zv); - int chunks = (size + (CHUNK_SIZE - 1)) >> CHUNK_SHIFT; + struct zv_hdr *zv; + uint16_t size; + int chunks; + zv = zs_map_object(pool, handle); ASSERT_SENTINEL(zv, ZVH); + size = zv->size + sizeof(struct zv_hdr); + INVERT_SENTINEL(zv, ZVH); + zs_unmap_object(pool, handle); + + chunks = (size + (CHUNK_SIZE - 1)) >> CHUNK_SHIFT; BUG_ON(chunks >= NCHUNKS); atomic_dec(&zv_curr_dist_counts[chunks]); - size -= sizeof(*zv); - BUG_ON(size == 0); - INVERT_SENTINEL(zv, ZVH); - page = virt_to_page(zv); - offset = (unsigned long)zv & ~PAGE_MASK; + local_irq_save(flags); - xv_free(xvpool, page, offset); + zs_free(pool, handle); local_irq_restore(flags); } -static void zv_decompress(struct page *page, struct zv_hdr *zv) +static void zv_decompress(struct page *page, void *handle) { unsigned int clen = PAGE_SIZE; char *to_va; - unsigned size; int ret; + struct zv_hdr *zv; + zv = zs_map_object(zcache_host.zspool, handle); + BUG_ON(zv->size == 0); ASSERT_SENTINEL(zv, ZVH); - size = xv_get_object_size(zv) - sizeof(*zv); - BUG_ON(size == 0); to_va = kmap_atomic(page, KM_USER0); ret = zcache_comp_op(ZCACHE_COMPOP_DECOMPRESS, (char *)zv + sizeof(*zv), - size, to_va, &clen); + zv->size, to_va, &clen); kunmap_atomic(to_va, KM_USER0); + zs_unmap_object(zcache_host.zspool, handle); BUG_ON(ret); BUG_ON(clen != PAGE_SIZE); } @@ -984,8 +987,8 @@ int zcache_new_client(uint16_t cli_id) goto out; cli->allocated = 1; #ifdef CONFIG_FRONTSWAP - cli->xvpool = xv_create_pool(); - if (cli->xvpool == NULL) + cli->zspool = zs_create_pool("zcache", ZCACHE_GFP_MASK); + if (cli->zspool == NULL) goto out; #endif ret = 0; @@ -1216,7 +1219,7 @@ static void *zcache_pampd_create(char *data, size_t size, bool raw, int eph, } /* reject if mean compression is too poor */ if ((clen > zv_max_mean_zsize) && (curr_pers_pampd_count > 0)) { - total_zsize = xv_get_total_size_bytes(cli->xvpool); + total_zsize = zs_get_total_size_bytes(cli->zspool); zv_mean_zsize = div_u64(total_zsize, curr_pers_pampd_count); if (zv_mean_zsize > zv_max_mean_zsize) { @@ -1224,7 +1227,7 @@ static void *zcache_pampd_create(char *data, size_t size, bool raw, int eph, goto out; } } - pampd = (void *)zv_create(cli->xvpool, pool->pool_id, + pampd = (void *)zv_create(cli->zspool, pool->pool_id, oid, index, cdata, clen); if (pampd == NULL) goto out; @@ -1282,7 +1285,7 @@ static void zcache_pampd_free(void *pampd, struct tmem_pool *pool, atomic_dec(&zcache_curr_eph_pampd_count); BUG_ON(atomic_read(&zcache_curr_eph_pampd_count) < 0); } else { - zv_free(cli->xvpool, (struct zv_hdr *)pampd); + zv_free(cli->zspool, pampd); atomic_dec(&zcache_curr_pers_pampd_count); BUG_ON(atomic_read(&zcache_curr_pers_pampd_count) < 0); } @@ -2072,7 +2075,7 @@ static int __init zcache_init(void) old_ops = zcache_frontswap_register_ops(); pr_info("zcache: frontswap enabled using kernel " - "transcendent memory and xvmalloc\n"); + "transcendent memory and zsmalloc\n"); if (old_ops.init != NULL) pr_warning("zcache: frontswap_ops overridden"); } -- cgit v0.10.2 From c123daaad835681d4acffd7631e448fd2c77677f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 10 Feb 2012 09:45:22 -0800 Subject: staging: ramster: delete the driver Turns out it's not quite ready to be included, thanks to some other work done in the zcache and zram code, which breaks this driver. So, delete it for now, per the recommendation of Dan. Acked-by: Dan Magenheimer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 783bc0a..f916a3f 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -136,6 +136,4 @@ source "drivers/staging/android/Kconfig" source "drivers/staging/telephony/Kconfig" -source "drivers/staging/ramster/Kconfig" - endif # STAGING diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 077a3f3..f6d4a43 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -57,5 +57,4 @@ obj-$(CONFIG_INTEL_MEI) += mei/ obj-$(CONFIG_MFD_NVEC) += nvec/ obj-$(CONFIG_DRM_OMAP) += omapdrm/ obj-$(CONFIG_ANDROID) += android/ -obj-$(CONFIG_RAMSTER) += ramster/ obj-$(CONFIG_PHONE) += telephony/ diff --git a/drivers/staging/ramster/Kconfig b/drivers/staging/ramster/Kconfig deleted file mode 100644 index 3957b87..0000000 --- a/drivers/staging/ramster/Kconfig +++ /dev/null @@ -1,14 +0,0 @@ -config RAMSTER - tristate "Cross-machine RAM capacity sharing, aka peer-to-peer tmem" - depends on (CLEANCACHE || FRONTSWAP) && CONFIGFS_FS && !OCFS2_FS && !ZCACHE && !HIGHMEM - select XVMALLOC - select LZO_COMPRESS - select LZO_DECOMPRESS - default n - help - RAMster allows RAM on other machines in a cluster to be utilized - dynamically and symmetrically instead of swapping to a local swap - disk, thus improving performance on memory-constrained workloads - while minimizing total RAM across the cluster. RAMster, like - zcache, compresses swap pages into local RAM, but then remotifies - the compressed pages to another node in the RAMster cluster. diff --git a/drivers/staging/ramster/Makefile b/drivers/staging/ramster/Makefile deleted file mode 100644 index e6c4a2e..0000000 --- a/drivers/staging/ramster/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -obj-$(CONFIG_RAMSTER) += zcache-main.o tmem.o -obj-$(CONFIG_RAMSTER) += ramster_o2net.o cluster/ diff --git a/drivers/staging/ramster/TODO b/drivers/staging/ramster/TODO deleted file mode 100644 index d4268f0..0000000 --- a/drivers/staging/ramster/TODO +++ /dev/null @@ -1,9 +0,0 @@ -For this staging driver, RAMster duplicates code from fs/ocfs2/cluster -and from drivers/staging/zcache, then incorporates changes to the local -copy of the code. Before RAMster can be promoted from staging, this code -duplication must be resolved. Specifically, we will first need to work with -the ocfs2 maintainers to split out the ocfs2 core cluster code so that -it can be easily included by another subsystem, even if ocfs2 is not -configured, and also to merge the handful of functional changes required. -Second, the zcache and RAMster drivers should be either merged or reorganized -to separate out common code. diff --git a/drivers/staging/ramster/cluster/Makefile b/drivers/staging/ramster/cluster/Makefile deleted file mode 100644 index 3fc8550..0000000 --- a/drivers/staging/ramster/cluster/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -#obj-$(CONFIG_OCFS2_FS) += ocfs2_nodemanager.o -obj-$(CONFIG_RAMSTER) += ocfs2_nodemanager.o - -ocfs2_nodemanager-objs := heartbeat.o masklog.o sys.o nodemanager.o \ - quorum.o tcp.o netdebug.o ver.o diff --git a/drivers/staging/ramster/cluster/heartbeat.c b/drivers/staging/ramster/cluster/heartbeat.c deleted file mode 100644 index 1f72143..0000000 --- a/drivers/staging/ramster/cluster/heartbeat.c +++ /dev/null @@ -1,2687 +0,0 @@ -/* -*- mode: c; c-basic-offset: 8; -*- - * vim: noexpandtab sw=8 ts=8 sts=0: - * - * Copyright (C) 2004, 2005 Oracle. All rights reserved. - * - * 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; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 021110-1307, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "heartbeat.h" -#include "tcp.h" -#include "nodemanager.h" -#include "quorum.h" - -#include "masklog.h" - - -/* - * The first heartbeat pass had one global thread that would serialize all hb - * callback calls. This global serializing sem should only be removed once - * we've made sure that all callees can deal with being called concurrently - * from multiple hb region threads. - */ -static DECLARE_RWSEM(o2hb_callback_sem); - -/* - * multiple hb threads are watching multiple regions. A node is live - * whenever any of the threads sees activity from the node in its region. - */ -static DEFINE_SPINLOCK(o2hb_live_lock); -static struct list_head o2hb_live_slots[O2NM_MAX_NODES]; -static unsigned long o2hb_live_node_bitmap[BITS_TO_LONGS(O2NM_MAX_NODES)]; -static LIST_HEAD(o2hb_node_events); -static DECLARE_WAIT_QUEUE_HEAD(o2hb_steady_queue); - -/* - * In global heartbeat, we maintain a series of region bitmaps. - * - o2hb_region_bitmap allows us to limit the region number to max region. - * - o2hb_live_region_bitmap tracks live regions (seen steady iterations). - * - o2hb_quorum_region_bitmap tracks live regions that have seen all nodes - * heartbeat on it. - * - o2hb_failed_region_bitmap tracks the regions that have seen io timeouts. - */ -static unsigned long o2hb_region_bitmap[BITS_TO_LONGS(O2NM_MAX_REGIONS)]; -static unsigned long o2hb_live_region_bitmap[BITS_TO_LONGS(O2NM_MAX_REGIONS)]; -static unsigned long o2hb_quorum_region_bitmap[BITS_TO_LONGS(O2NM_MAX_REGIONS)]; -static unsigned long o2hb_failed_region_bitmap[BITS_TO_LONGS(O2NM_MAX_REGIONS)]; - -#define O2HB_DB_TYPE_LIVENODES 0 -#define O2HB_DB_TYPE_LIVEREGIONS 1 -#define O2HB_DB_TYPE_QUORUMREGIONS 2 -#define O2HB_DB_TYPE_FAILEDREGIONS 3 -#define O2HB_DB_TYPE_REGION_LIVENODES 4 -#define O2HB_DB_TYPE_REGION_NUMBER 5 -#define O2HB_DB_TYPE_REGION_ELAPSED_TIME 6 -#define O2HB_DB_TYPE_REGION_PINNED 7 -struct o2hb_debug_buf { - int db_type; - int db_size; - int db_len; - void *db_data; -}; - -static struct o2hb_debug_buf *o2hb_db_livenodes; -static struct o2hb_debug_buf *o2hb_db_liveregions; -static struct o2hb_debug_buf *o2hb_db_quorumregions; -static struct o2hb_debug_buf *o2hb_db_failedregions; - -#define O2HB_DEBUG_DIR "o2hb" -#define O2HB_DEBUG_LIVENODES "livenodes" -#define O2HB_DEBUG_LIVEREGIONS "live_regions" -#define O2HB_DEBUG_QUORUMREGIONS "quorum_regions" -#define O2HB_DEBUG_FAILEDREGIONS "failed_regions" -#define O2HB_DEBUG_REGION_NUMBER "num" -#define O2HB_DEBUG_REGION_ELAPSED_TIME "elapsed_time_in_ms" -#define O2HB_DEBUG_REGION_PINNED "pinned" - -static struct dentry *o2hb_debug_dir; -static struct dentry *o2hb_debug_livenodes; -static struct dentry *o2hb_debug_liveregions; -static struct dentry *o2hb_debug_quorumregions; -static struct dentry *o2hb_debug_failedregions; - -static LIST_HEAD(o2hb_all_regions); - -static struct o2hb_callback { - struct list_head list; -} o2hb_callbacks[O2HB_NUM_CB]; - -static struct o2hb_callback *hbcall_from_type(enum o2hb_callback_type type); - -#define O2HB_DEFAULT_BLOCK_BITS 9 - -enum o2hb_heartbeat_modes { - O2HB_HEARTBEAT_LOCAL = 0, - O2HB_HEARTBEAT_GLOBAL, - O2HB_HEARTBEAT_NUM_MODES, -}; - -char *o2hb_heartbeat_mode_desc[O2HB_HEARTBEAT_NUM_MODES] = { - "local", /* O2HB_HEARTBEAT_LOCAL */ - "global", /* O2HB_HEARTBEAT_GLOBAL */ -}; - -unsigned int o2hb_dead_threshold = O2HB_DEFAULT_DEAD_THRESHOLD; -unsigned int o2hb_heartbeat_mode = O2HB_HEARTBEAT_LOCAL; - -/* - * o2hb_dependent_users tracks the number of registered callbacks that depend - * on heartbeat. o2net and o2dlm are two entities that register this callback. - * However only o2dlm depends on the heartbeat. It does not want the heartbeat - * to stop while a dlm domain is still active. - */ -unsigned int o2hb_dependent_users; - -/* - * In global heartbeat mode, all regions are pinned if there are one or more - * dependent users and the quorum region count is <= O2HB_PIN_CUT_OFF. All - * regions are unpinned if the region count exceeds the cut off or the number - * of dependent users falls to zero. - */ -#define O2HB_PIN_CUT_OFF 3 - -/* - * In local heartbeat mode, we assume the dlm domain name to be the same as - * region uuid. This is true for domains created for the file system but not - * necessarily true for userdlm domains. This is a known limitation. - * - * In global heartbeat mode, we pin/unpin all o2hb regions. This solution - * works for both file system and userdlm domains. - */ -static int o2hb_region_pin(const char *region_uuid); -static void o2hb_region_unpin(const char *region_uuid); - -/* Only sets a new threshold if there are no active regions. - * - * No locking or otherwise interesting code is required for reading - * o2hb_dead_threshold as it can't change once regions are active and - * it's not interesting to anyone until then anyway. */ -static void o2hb_dead_threshold_set(unsigned int threshold) -{ - if (threshold > O2HB_MIN_DEAD_THRESHOLD) { - spin_lock(&o2hb_live_lock); - if (list_empty(&o2hb_all_regions)) - o2hb_dead_threshold = threshold; - spin_unlock(&o2hb_live_lock); - } -} - -static int o2hb_global_hearbeat_mode_set(unsigned int hb_mode) -{ - int ret = -1; - - if (hb_mode < O2HB_HEARTBEAT_NUM_MODES) { - spin_lock(&o2hb_live_lock); - if (list_empty(&o2hb_all_regions)) { - o2hb_heartbeat_mode = hb_mode; - ret = 0; - } - spin_unlock(&o2hb_live_lock); - } - - return ret; -} - -struct o2hb_node_event { - struct list_head hn_item; - enum o2hb_callback_type hn_event_type; - struct o2nm_node *hn_node; - int hn_node_num; -}; - -struct o2hb_disk_slot { - struct o2hb_disk_heartbeat_block *ds_raw_block; - u8 ds_node_num; - u64 ds_last_time; - u64 ds_last_generation; - u16 ds_equal_samples; - u16 ds_changed_samples; - struct list_head ds_live_item; -}; - -/* each thread owns a region.. when we're asked to tear down the region - * we ask the thread to stop, who cleans up the region */ -struct o2hb_region { - struct config_item hr_item; - - struct list_head hr_all_item; - unsigned hr_unclean_stop:1, - hr_aborted_start:1, - hr_item_pinned:1, - hr_item_dropped:1; - - /* protected by the hr_callback_sem */ - struct task_struct *hr_task; - - unsigned int hr_blocks; - unsigned long long hr_start_block; - - unsigned int hr_block_bits; - unsigned int hr_block_bytes; - - unsigned int hr_slots_per_page; - unsigned int hr_num_pages; - - struct page **hr_slot_data; - struct block_device *hr_bdev; - struct o2hb_disk_slot *hr_slots; - - /* live node map of this region */ - unsigned long hr_live_node_bitmap[BITS_TO_LONGS(O2NM_MAX_NODES)]; - unsigned int hr_region_num; - - struct dentry *hr_debug_dir; - struct dentry *hr_debug_livenodes; - struct dentry *hr_debug_regnum; - struct dentry *hr_debug_elapsed_time; - struct dentry *hr_debug_pinned; - struct o2hb_debug_buf *hr_db_livenodes; - struct o2hb_debug_buf *hr_db_regnum; - struct o2hb_debug_buf *hr_db_elapsed_time; - struct o2hb_debug_buf *hr_db_pinned; - - /* let the person setting up hb wait for it to return until it - * has reached a 'steady' state. This will be fixed when we have - * a more complete api that doesn't lead to this sort of fragility. */ - atomic_t hr_steady_iterations; - - /* terminate o2hb thread if it does not reach steady state - * (hr_steady_iterations == 0) within hr_unsteady_iterations */ - atomic_t hr_unsteady_iterations; - - char hr_dev_name[BDEVNAME_SIZE]; - - unsigned int hr_timeout_ms; - - /* randomized as the region goes up and down so that a node - * recognizes a node going up and down in one iteration */ - u64 hr_generation; - - struct delayed_work hr_write_timeout_work; - unsigned long hr_last_timeout_start; - - /* Used during o2hb_check_slot to hold a copy of the block - * being checked because we temporarily have to zero out the - * crc field. */ - struct o2hb_disk_heartbeat_block *hr_tmp_block; -}; - -struct o2hb_bio_wait_ctxt { - atomic_t wc_num_reqs; - struct completion wc_io_complete; - int wc_error; -}; - -static int o2hb_pop_count(void *map, int count) -{ - int i = -1, pop = 0; - - while ((i = find_next_bit(map, count, i + 1)) < count) - pop++; - return pop; -} - -static void o2hb_write_timeout(struct work_struct *work) -{ - int failed, quorum; - unsigned long flags; - struct o2hb_region *reg = - container_of(work, struct o2hb_region, - hr_write_timeout_work.work); - - mlog(ML_ERROR, "Heartbeat write timeout to device %s after %u " - "milliseconds\n", reg->hr_dev_name, - jiffies_to_msecs(jiffies - reg->hr_last_timeout_start)); - - if (o2hb_global_heartbeat_active()) { - spin_lock_irqsave(&o2hb_live_lock, flags); - if (test_bit(reg->hr_region_num, o2hb_quorum_region_bitmap)) - set_bit(reg->hr_region_num, o2hb_failed_region_bitmap); - failed = o2hb_pop_count(&o2hb_failed_region_bitmap, - O2NM_MAX_REGIONS); - quorum = o2hb_pop_count(&o2hb_quorum_region_bitmap, - O2NM_MAX_REGIONS); - spin_unlock_irqrestore(&o2hb_live_lock, flags); - - mlog(ML_HEARTBEAT, "Number of regions %d, failed regions %d\n", - quorum, failed); - - /* - * Fence if the number of failed regions >= half the number - * of quorum regions - */ - if ((failed << 1) < quorum) - return; - } - - o2quo_disk_timeout(); -} - -static void o2hb_arm_write_timeout(struct o2hb_region *reg) -{ - /* Arm writeout only after thread reaches steady state */ - if (atomic_read(®->hr_steady_iterations) != 0) - return; - - mlog(ML_HEARTBEAT, "Queue write timeout for %u ms\n", - O2HB_MAX_WRITE_TIMEOUT_MS); - - if (o2hb_global_heartbeat_active()) { - spin_lock(&o2hb_live_lock); - clear_bit(reg->hr_region_num, o2hb_failed_region_bitmap); - spin_unlock(&o2hb_live_lock); - } - cancel_delayed_work(®->hr_write_timeout_work); - reg->hr_last_timeout_start = jiffies; - schedule_delayed_work(®->hr_write_timeout_work, - msecs_to_jiffies(O2HB_MAX_WRITE_TIMEOUT_MS)); -} - -static void o2hb_disarm_write_timeout(struct o2hb_region *reg) -{ - cancel_delayed_work_sync(®->hr_write_timeout_work); -} - -static inline void o2hb_bio_wait_init(struct o2hb_bio_wait_ctxt *wc) -{ - atomic_set(&wc->wc_num_reqs, 1); - init_completion(&wc->wc_io_complete); - wc->wc_error = 0; -} - -/* Used in error paths too */ -static inline void o2hb_bio_wait_dec(struct o2hb_bio_wait_ctxt *wc, - unsigned int num) -{ - /* sadly atomic_sub_and_test() isn't available on all platforms. The - * good news is that the fast path only completes one at a time */ - while(num--) { - if (atomic_dec_and_test(&wc->wc_num_reqs)) { - BUG_ON(num > 0); - complete(&wc->wc_io_complete); - } - } -} - -static void o2hb_wait_on_io(struct o2hb_region *reg, - struct o2hb_bio_wait_ctxt *wc) -{ - o2hb_bio_wait_dec(wc, 1); - wait_for_completion(&wc->wc_io_complete); -} - -static void o2hb_bio_end_io(struct bio *bio, - int error) -{ - struct o2hb_bio_wait_ctxt *wc = bio->bi_private; - - if (error) { - mlog(ML_ERROR, "IO Error %d\n", error); - wc->wc_error = error; - } - - o2hb_bio_wait_dec(wc, 1); - bio_put(bio); -} - -/* Setup a Bio to cover I/O against num_slots slots starting at - * start_slot. */ -static struct bio *o2hb_setup_one_bio(struct o2hb_region *reg, - struct o2hb_bio_wait_ctxt *wc, - unsigned int *current_slot, - unsigned int max_slots) -{ - int len, current_page; - unsigned int vec_len, vec_start; - unsigned int bits = reg->hr_block_bits; - unsigned int spp = reg->hr_slots_per_page; - unsigned int cs = *current_slot; - struct bio *bio; - struct page *page; - - /* Testing has shown this allocation to take long enough under - * GFP_KERNEL that the local node can get fenced. It would be - * nicest if we could pre-allocate these bios and avoid this - * all together. */ - bio = bio_alloc(GFP_ATOMIC, 16); - if (!bio) { - mlog(ML_ERROR, "Could not alloc slots BIO!\n"); - bio = ERR_PTR(-ENOMEM); - goto bail; - } - - /* Must put everything in 512 byte sectors for the bio... */ - bio->bi_sector = (reg->hr_start_block + cs) << (bits - 9); - bio->bi_bdev = reg->hr_bdev; - bio->bi_private = wc; - bio->bi_end_io = o2hb_bio_end_io; - - vec_start = (cs << bits) % PAGE_CACHE_SIZE; - while(cs < max_slots) { - current_page = cs / spp; - page = reg->hr_slot_data[current_page]; - - vec_len = min(PAGE_CACHE_SIZE - vec_start, - (max_slots-cs) * (PAGE_CACHE_SIZE/spp) ); - - mlog(ML_HB_BIO, "page %d, vec_len = %u, vec_start = %u\n", - current_page, vec_len, vec_start); - - len = bio_add_page(bio, page, vec_len, vec_start); - if (len != vec_len) break; - - cs += vec_len / (PAGE_CACHE_SIZE/spp); - vec_start = 0; - } - -bail: - *current_slot = cs; - return bio; -} - -static int o2hb_read_slots(struct o2hb_region *reg, - unsigned int max_slots) -{ - unsigned int current_slot=0; - int status; - struct o2hb_bio_wait_ctxt wc; - struct bio *bio; - - o2hb_bio_wait_init(&wc); - - while(current_slot < max_slots) { - bio = o2hb_setup_one_bio(reg, &wc, ¤t_slot, max_slots); - if (IS_ERR(bio)) { - status = PTR_ERR(bio); - mlog_errno(status); - goto bail_and_wait; - } - - atomic_inc(&wc.wc_num_reqs); - submit_bio(READ, bio); - } - - status = 0; - -bail_and_wait: - o2hb_wait_on_io(reg, &wc); - if (wc.wc_error && !status) - status = wc.wc_error; - - return status; -} - -static int o2hb_issue_node_write(struct o2hb_region *reg, - struct o2hb_bio_wait_ctxt *write_wc) -{ - int status; - unsigned int slot; - struct bio *bio; - - o2hb_bio_wait_init(write_wc); - - slot = o2nm_this_node(); - - bio = o2hb_setup_one_bio(reg, write_wc, &slot, slot+1); - if (IS_ERR(bio)) { - status = PTR_ERR(bio); - mlog_errno(status); - goto bail; - } - - atomic_inc(&write_wc->wc_num_reqs); - submit_bio(WRITE, bio); - - status = 0; -bail: - return status; -} - -static u32 o2hb_compute_block_crc_le(struct o2hb_region *reg, - struct o2hb_disk_heartbeat_block *hb_block) -{ - __le32 old_cksum; - u32 ret; - - /* We want to compute the block crc with a 0 value in the - * hb_cksum field. Save it off here and replace after the - * crc. */ - old_cksum = hb_block->hb_cksum; - hb_block->hb_cksum = 0; - - ret = crc32_le(0, (unsigned char *) hb_block, reg->hr_block_bytes); - - hb_block->hb_cksum = old_cksum; - - return ret; -} - -static void o2hb_dump_slot(struct o2hb_disk_heartbeat_block *hb_block) -{ - mlog(ML_ERROR, "Dump slot information: seq = 0x%llx, node = %u, " - "cksum = 0x%x, generation 0x%llx\n", - (long long)le64_to_cpu(hb_block->hb_seq), - hb_block->hb_node, le32_to_cpu(hb_block->hb_cksum), - (long long)le64_to_cpu(hb_block->hb_generation)); -} - -static int o2hb_verify_crc(struct o2hb_region *reg, - struct o2hb_disk_heartbeat_block *hb_block) -{ - u32 read, computed; - - read = le32_to_cpu(hb_block->hb_cksum); - computed = o2hb_compute_block_crc_le(reg, hb_block); - - return read == computed; -} - -/* - * Compare the slot data with what we wrote in the last iteration. - * If the match fails, print an appropriate error message. This is to - * detect errors like... another node hearting on the same slot, - * flaky device that is losing writes, etc. - * Returns 1 if check succeeds, 0 otherwise. - */ -static int o2hb_check_own_slot(struct o2hb_region *reg) -{ - struct o2hb_disk_slot *slot; - struct o2hb_disk_heartbeat_block *hb_block; - char *errstr; - - slot = ®->hr_slots[o2nm_this_node()]; - /* Don't check on our 1st timestamp */ - if (!slot->ds_last_time) - return 0; - - hb_block = slot->ds_raw_block; - if (le64_to_cpu(hb_block->hb_seq) == slot->ds_last_time && - le64_to_cpu(hb_block->hb_generation) == slot->ds_last_generation && - hb_block->hb_node == slot->ds_node_num) - return 1; - -#define ERRSTR1 "Another node is heartbeating on device" -#define ERRSTR2 "Heartbeat generation mismatch on device" -#define ERRSTR3 "Heartbeat sequence mismatch on device" - - if (hb_block->hb_node != slot->ds_node_num) - errstr = ERRSTR1; - else if (le64_to_cpu(hb_block->hb_generation) != - slot->ds_last_generation) - errstr = ERRSTR2; - else - errstr = ERRSTR3; - - mlog(ML_ERROR, "%s (%s): expected(%u:0x%llx, 0x%llx), " - "ondisk(%u:0x%llx, 0x%llx)\n", errstr, reg->hr_dev_name, - slot->ds_node_num, (unsigned long long)slot->ds_last_generation, - (unsigned long long)slot->ds_last_time, hb_block->hb_node, - (unsigned long long)le64_to_cpu(hb_block->hb_generation), - (unsigned long long)le64_to_cpu(hb_block->hb_seq)); - - return 0; -} - -static inline void o2hb_prepare_block(struct o2hb_region *reg, - u64 generation) -{ - int node_num; - u64 cputime; - struct o2hb_disk_slot *slot; - struct o2hb_disk_heartbeat_block *hb_block; - - node_num = o2nm_this_node(); - slot = ®->hr_slots[node_num]; - - hb_block = (struct o2hb_disk_heartbeat_block *)slot->ds_raw_block; - memset(hb_block, 0, reg->hr_block_bytes); - /* TODO: time stuff */ - cputime = CURRENT_TIME.tv_sec; - if (!cputime) - cputime = 1; - - hb_block->hb_seq = cpu_to_le64(cputime); - hb_block->hb_node = node_num; - hb_block->hb_generation = cpu_to_le64(generation); - hb_block->hb_dead_ms = cpu_to_le32(o2hb_dead_threshold * O2HB_REGION_TIMEOUT_MS); - - /* This step must always happen last! */ - hb_block->hb_cksum = cpu_to_le32(o2hb_compute_block_crc_le(reg, - hb_block)); - - mlog(ML_HB_BIO, "our node generation = 0x%llx, cksum = 0x%x\n", - (long long)generation, - le32_to_cpu(hb_block->hb_cksum)); -} - -static void o2hb_fire_callbacks(struct o2hb_callback *hbcall, - struct o2nm_node *node, - int idx) -{ - struct list_head *iter; - struct o2hb_callback_func *f; - - list_for_each(iter, &hbcall->list) { - f = list_entry(iter, struct o2hb_callback_func, hc_item); - mlog(ML_HEARTBEAT, "calling funcs %p\n", f); - (f->hc_func)(node, idx, f->hc_data); - } -} - -/* Will run the list in order until we process the passed event */ -static void o2hb_run_event_list(struct o2hb_node_event *queued_event) -{ - int empty; - struct o2hb_callback *hbcall; - struct o2hb_node_event *event; - - spin_lock(&o2hb_live_lock); - empty = list_empty(&queued_event->hn_item); - spin_unlock(&o2hb_live_lock); - if (empty) - return; - - /* Holding callback sem assures we don't alter the callback - * lists when doing this, and serializes ourselves with other - * processes wanting callbacks. */ - down_write(&o2hb_callback_sem); - - spin_lock(&o2hb_live_lock); - while (!list_empty(&o2hb_node_events) - && !list_empty(&queued_event->hn_item)) { - event = list_entry(o2hb_node_events.next, - struct o2hb_node_event, - hn_item); - list_del_init(&event->hn_item); - spin_unlock(&o2hb_live_lock); - - mlog(ML_HEARTBEAT, "Node %s event for %d\n", - event->hn_event_type == O2HB_NODE_UP_CB ? "UP" : "DOWN", - event->hn_node_num); - - hbcall = hbcall_from_type(event->hn_event_type); - - /* We should *never* have gotten on to the list with a - * bad type... This isn't something that we should try - * to recover from. */ - BUG_ON(IS_ERR(hbcall)); - - o2hb_fire_callbacks(hbcall, event->hn_node, event->hn_node_num); - - spin_lock(&o2hb_live_lock); - } - spin_unlock(&o2hb_live_lock); - - up_write(&o2hb_callback_sem); -} - -static void o2hb_queue_node_event(struct o2hb_node_event *event, - enum o2hb_callback_type type, - struct o2nm_node *node, - int node_num) -{ - assert_spin_locked(&o2hb_live_lock); - - BUG_ON((!node) && (type != O2HB_NODE_DOWN_CB)); - - event->hn_event_type = type; - event->hn_node = node; - event->hn_node_num = node_num; - - mlog(ML_HEARTBEAT, "Queue node %s event for node %d\n", - type == O2HB_NODE_UP_CB ? "UP" : "DOWN", node_num); - - list_add_tail(&event->hn_item, &o2hb_node_events); -} - -static void o2hb_shutdown_slot(struct o2hb_disk_slot *slot) -{ - struct o2hb_node_event event = - { .hn_item = LIST_HEAD_INIT(event.hn_item), }; - struct o2nm_node *node; - - node = o2nm_get_node_by_num(slot->ds_node_num); - if (!node) - return; - - spin_lock(&o2hb_live_lock); - if (!list_empty(&slot->ds_live_item)) { - mlog(ML_HEARTBEAT, "Shutdown, node %d leaves region\n", - slot->ds_node_num); - - list_del_init(&slot->ds_live_item); - - if (list_empty(&o2hb_live_slots[slot->ds_node_num])) { - clear_bit(slot->ds_node_num, o2hb_live_node_bitmap); - - o2hb_queue_node_event(&event, O2HB_NODE_DOWN_CB, node, - slot->ds_node_num); - } - } - spin_unlock(&o2hb_live_lock); - - o2hb_run_event_list(&event); - - o2nm_node_put(node); -} - -static void o2hb_set_quorum_device(struct o2hb_region *reg) -{ - if (!o2hb_global_heartbeat_active()) - return; - - /* Prevent race with o2hb_heartbeat_group_drop_item() */ - if (kthread_should_stop()) - return; - - /* Tag region as quorum only after thread reaches steady state */ - if (atomic_read(®->hr_steady_iterations) != 0) - return; - - spin_lock(&o2hb_live_lock); - - if (test_bit(reg->hr_region_num, o2hb_quorum_region_bitmap)) - goto unlock; - - /* - * A region can be added to the quorum only when it sees all - * live nodes heartbeat on it. In other words, the region has been - * added to all nodes. - */ - if (memcmp(reg->hr_live_node_bitmap, o2hb_live_node_bitmap, - sizeof(o2hb_live_node_bitmap))) - goto unlock; - - printk(KERN_NOTICE "o2hb: Region %s (%s) is now a quorum device\n", - config_item_name(®->hr_item), reg->hr_dev_name); - - set_bit(reg->hr_region_num, o2hb_quorum_region_bitmap); - - /* - * If global heartbeat active, unpin all regions if the - * region count > CUT_OFF - */ - if (o2hb_pop_count(&o2hb_quorum_region_bitmap, - O2NM_MAX_REGIONS) > O2HB_PIN_CUT_OFF) - o2hb_region_unpin(NULL); -unlock: - spin_unlock(&o2hb_live_lock); -} - -static int o2hb_check_slot(struct o2hb_region *reg, - struct o2hb_disk_slot *slot) -{ - int changed = 0, gen_changed = 0; - struct o2hb_node_event event = - { .hn_item = LIST_HEAD_INIT(event.hn_item), }; - struct o2nm_node *node; - struct o2hb_disk_heartbeat_block *hb_block = reg->hr_tmp_block; - u64 cputime; - unsigned int dead_ms = o2hb_dead_threshold * O2HB_REGION_TIMEOUT_MS; - unsigned int slot_dead_ms; - int tmp; - - memcpy(hb_block, slot->ds_raw_block, reg->hr_block_bytes); - - /* - * If a node is no longer configured but is still in the livemap, we - * may need to clear that bit from the livemap. - */ - node = o2nm_get_node_by_num(slot->ds_node_num); - if (!node) { - spin_lock(&o2hb_live_lock); - tmp = test_bit(slot->ds_node_num, o2hb_live_node_bitmap); - spin_unlock(&o2hb_live_lock); - if (!tmp) - return 0; - } - - if (!o2hb_verify_crc(reg, hb_block)) { - /* all paths from here will drop o2hb_live_lock for - * us. */ - spin_lock(&o2hb_live_lock); - - /* Don't print an error on the console in this case - - * a freshly formatted heartbeat area will not have a - * crc set on it. */ - if (list_empty(&slot->ds_live_item)) - goto out; - - /* The node is live but pushed out a bad crc. We - * consider it a transient miss but don't populate any - * other values as they may be junk. */ - mlog(ML_ERROR, "Node %d has written a bad crc to %s\n", - slot->ds_node_num, reg->hr_dev_name); - o2hb_dump_slot(hb_block); - - slot->ds_equal_samples++; - goto fire_callbacks; - } - - /* we don't care if these wrap.. the state transitions below - * clear at the right places */ - cputime = le64_to_cpu(hb_block->hb_seq); - if (slot->ds_last_time != cputime) - slot->ds_changed_samples++; - else - slot->ds_equal_samples++; - slot->ds_last_time = cputime; - - /* The node changed heartbeat generations. We assume this to - * mean it dropped off but came back before we timed out. We - * want to consider it down for the time being but don't want - * to lose any changed_samples state we might build up to - * considering it live again. */ - if (slot->ds_last_generation != le64_to_cpu(hb_block->hb_generation)) { - gen_changed = 1; - slot->ds_equal_samples = 0; - mlog(ML_HEARTBEAT, "Node %d changed generation (0x%llx " - "to 0x%llx)\n", slot->ds_node_num, - (long long)slot->ds_last_generation, - (long long)le64_to_cpu(hb_block->hb_generation)); - } - - slot->ds_last_generation = le64_to_cpu(hb_block->hb_generation); - - mlog(ML_HEARTBEAT, "Slot %d gen 0x%llx cksum 0x%x " - "seq %llu last %llu changed %u equal %u\n", - slot->ds_node_num, (long long)slot->ds_last_generation, - le32_to_cpu(hb_block->hb_cksum), - (unsigned long long)le64_to_cpu(hb_block->hb_seq), - (unsigned long long)slot->ds_last_time, slot->ds_changed_samples, - slot->ds_equal_samples); - - spin_lock(&o2hb_live_lock); - -fire_callbacks: - /* dead nodes only come to life after some number of - * changes at any time during their dead time */ - if (list_empty(&slot->ds_live_item) && - slot->ds_changed_samples >= O2HB_LIVE_THRESHOLD) { - mlog(ML_HEARTBEAT, "Node %d (id 0x%llx) joined my region\n", - slot->ds_node_num, (long long)slot->ds_last_generation); - - set_bit(slot->ds_node_num, reg->hr_live_node_bitmap); - - /* first on the list generates a callback */ - if (list_empty(&o2hb_live_slots[slot->ds_node_num])) { - mlog(ML_HEARTBEAT, "o2hb: Add node %d to live nodes " - "bitmap\n", slot->ds_node_num); - set_bit(slot->ds_node_num, o2hb_live_node_bitmap); - - o2hb_queue_node_event(&event, O2HB_NODE_UP_CB, node, - slot->ds_node_num); - - changed = 1; - } - - list_add_tail(&slot->ds_live_item, - &o2hb_live_slots[slot->ds_node_num]); - - slot->ds_equal_samples = 0; - - /* We want to be sure that all nodes agree on the - * number of milliseconds before a node will be - * considered dead. The self-fencing timeout is - * computed from this value, and a discrepancy might - * result in heartbeat calling a node dead when it - * hasn't self-fenced yet. */ - slot_dead_ms = le32_to_cpu(hb_block->hb_dead_ms); - if (slot_dead_ms && slot_dead_ms != dead_ms) { - /* TODO: Perhaps we can fail the region here. */ - mlog(ML_ERROR, "Node %d on device %s has a dead count " - "of %u ms, but our count is %u ms.\n" - "Please double check your configuration values " - "for 'O2CB_HEARTBEAT_THRESHOLD'\n", - slot->ds_node_num, reg->hr_dev_name, slot_dead_ms, - dead_ms); - } - goto out; - } - - /* if the list is dead, we're done.. */ - if (list_empty(&slot->ds_live_item)) - goto out; - - /* live nodes only go dead after enough consequtive missed - * samples.. reset the missed counter whenever we see - * activity */ - if (slot->ds_equal_samples >= o2hb_dead_threshold || gen_changed) { - mlog(ML_HEARTBEAT, "Node %d left my region\n", - slot->ds_node_num); - - clear_bit(slot->ds_node_num, reg->hr_live_node_bitmap); - - /* last off the live_slot generates a callback */ - list_del_init(&slot->ds_live_item); - if (list_empty(&o2hb_live_slots[slot->ds_node_num])) { - mlog(ML_HEARTBEAT, "o2hb: Remove node %d from live " - "nodes bitmap\n", slot->ds_node_num); - clear_bit(slot->ds_node_num, o2hb_live_node_bitmap); - - /* node can be null */ - o2hb_queue_node_event(&event, O2HB_NODE_DOWN_CB, - node, slot->ds_node_num); - - changed = 1; - } - - /* We don't clear this because the node is still - * actually writing new blocks. */ - if (!gen_changed) - slot->ds_changed_samples = 0; - goto out; - } - if (slot->ds_changed_samples) { - slot->ds_changed_samples = 0; - slot->ds_equal_samples = 0; - } -out: - spin_unlock(&o2hb_live_lock); - - o2hb_run_event_list(&event); - - if (node) - o2nm_node_put(node); - return changed; -} - -/* This could be faster if we just implmented a find_last_bit, but I - * don't think the circumstances warrant it. */ -static int o2hb_highest_node(unsigned long *nodes, - int numbits) -{ - int highest, node; - - highest = numbits; - node = -1; - while ((node = find_next_bit(nodes, numbits, node + 1)) != -1) { - if (node >= numbits) - break; - - highest = node; - } - - return highest; -} - -static int o2hb_do_disk_heartbeat(struct o2hb_region *reg) -{ - int i, ret, highest_node; - int membership_change = 0, own_slot_ok = 0; - unsigned long configured_nodes[BITS_TO_LONGS(O2NM_MAX_NODES)]; - unsigned long live_node_bitmap[BITS_TO_LONGS(O2NM_MAX_NODES)]; - struct o2hb_bio_wait_ctxt write_wc; - - ret = o2nm_configured_node_map(configured_nodes, - sizeof(configured_nodes)); - if (ret) { - mlog_errno(ret); - goto bail; - } - - /* - * If a node is not configured but is in the livemap, we still need - * to read the slot so as to be able to remove it from the livemap. - */ - o2hb_fill_node_map(live_node_bitmap, sizeof(live_node_bitmap)); - i = -1; - while ((i = find_next_bit(live_node_bitmap, - O2NM_MAX_NODES, i + 1)) < O2NM_MAX_NODES) { - set_bit(i, configured_nodes); - } - - highest_node = o2hb_highest_node(configured_nodes, O2NM_MAX_NODES); - if (highest_node >= O2NM_MAX_NODES) { - mlog(ML_NOTICE, "o2hb: No configured nodes found!\n"); - ret = -EINVAL; - goto bail; - } - - /* No sense in reading the slots of nodes that don't exist - * yet. Of course, if the node definitions have holes in them - * then we're reading an empty slot anyway... Consider this - * best-effort. */ - ret = o2hb_read_slots(reg, highest_node + 1); - if (ret < 0) { - mlog_errno(ret); - goto bail; - } - - /* With an up to date view of the slots, we can check that no - * other node has been improperly configured to heartbeat in - * our slot. */ - own_slot_ok = o2hb_check_own_slot(reg); - - /* fill in the proper info for our next heartbeat */ - o2hb_prepare_block(reg, reg->hr_generation); - - ret = o2hb_issue_node_write(reg, &write_wc); - if (ret < 0) { - mlog_errno(ret); - goto bail; - } - - i = -1; - while((i = find_next_bit(configured_nodes, - O2NM_MAX_NODES, i + 1)) < O2NM_MAX_NODES) { - membership_change |= o2hb_check_slot(reg, ®->hr_slots[i]); - } - - /* - * We have to be sure we've advertised ourselves on disk - * before we can go to steady state. This ensures that - * people we find in our steady state have seen us. - */ - o2hb_wait_on_io(reg, &write_wc); - if (write_wc.wc_error) { - /* Do not re-arm the write timeout on I/O error - we - * can't be sure that the new block ever made it to - * disk */ - mlog(ML_ERROR, "Write error %d on device \"%s\"\n", - write_wc.wc_error, reg->hr_dev_name); - ret = write_wc.wc_error; - goto bail; - } - - /* Skip disarming the timeout if own slot has stale/bad data */ - if (own_slot_ok) { - o2hb_set_quorum_device(reg); - o2hb_arm_write_timeout(reg); - } - -bail: - /* let the person who launched us know when things are steady */ - if (atomic_read(®->hr_steady_iterations) != 0) { - if (!ret && own_slot_ok && !membership_change) { - if (atomic_dec_and_test(®->hr_steady_iterations)) - wake_up(&o2hb_steady_queue); - } - } - - if (atomic_read(®->hr_steady_iterations) != 0) { - if (atomic_dec_and_test(®->hr_unsteady_iterations)) { - printk(KERN_NOTICE "o2hb: Unable to stabilize " - "heartbeart on region %s (%s)\n", - config_item_name(®->hr_item), - reg->hr_dev_name); - atomic_set(®->hr_steady_iterations, 0); - reg->hr_aborted_start = 1; - wake_up(&o2hb_steady_queue); - ret = -EIO; - } - } - - return ret; -} - -/* Subtract b from a, storing the result in a. a *must* have a larger - * value than b. */ -static void o2hb_tv_subtract(struct timeval *a, - struct timeval *b) -{ - /* just return 0 when a is after b */ - if (a->tv_sec < b->tv_sec || - (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec)) { - a->tv_sec = 0; - a->tv_usec = 0; - return; - } - - a->tv_sec -= b->tv_sec; - a->tv_usec -= b->tv_usec; - while ( a->tv_usec < 0 ) { - a->tv_sec--; - a->tv_usec += 1000000; - } -} - -static unsigned int o2hb_elapsed_msecs(struct timeval *start, - struct timeval *end) -{ - struct timeval res = *end; - - o2hb_tv_subtract(&res, start); - - return res.tv_sec * 1000 + res.tv_usec / 1000; -} - -/* - * we ride the region ref that the region dir holds. before the region - * dir is removed and drops it ref it will wait to tear down this - * thread. - */ -static int o2hb_thread(void *data) -{ - int i, ret; - struct o2hb_region *reg = data; - struct o2hb_bio_wait_ctxt write_wc; - struct timeval before_hb, after_hb; - unsigned int elapsed_msec; - - mlog(ML_HEARTBEAT|ML_KTHREAD, "hb thread running\n"); - - set_user_nice(current, -20); - - /* Pin node */ - o2nm_depend_this_node(); - - while (!kthread_should_stop() && - !reg->hr_unclean_stop && !reg->hr_aborted_start) { - /* We track the time spent inside - * o2hb_do_disk_heartbeat so that we avoid more than - * hr_timeout_ms between disk writes. On busy systems - * this should result in a heartbeat which is less - * likely to time itself out. */ - do_gettimeofday(&before_hb); - - ret = o2hb_do_disk_heartbeat(reg); - - do_gettimeofday(&after_hb); - elapsed_msec = o2hb_elapsed_msecs(&before_hb, &after_hb); - - mlog(ML_HEARTBEAT, - "start = %lu.%lu, end = %lu.%lu, msec = %u\n", - before_hb.tv_sec, (unsigned long) before_hb.tv_usec, - after_hb.tv_sec, (unsigned long) after_hb.tv_usec, - elapsed_msec); - - if (!kthread_should_stop() && - elapsed_msec < reg->hr_timeout_ms) { - /* the kthread api has blocked signals for us so no - * need to record the return value. */ - msleep_interruptible(reg->hr_timeout_ms - elapsed_msec); - } - } - - o2hb_disarm_write_timeout(reg); - - /* unclean stop is only used in very bad situation */ - for(i = 0; !reg->hr_unclean_stop && i < reg->hr_blocks; i++) - o2hb_shutdown_slot(®->hr_slots[i]); - - /* Explicit down notification - avoid forcing the other nodes - * to timeout on this region when we could just as easily - * write a clear generation - thus indicating to them that - * this node has left this region. - */ - if (!reg->hr_unclean_stop && !reg->hr_aborted_start) { - o2hb_prepare_block(reg, 0); - ret = o2hb_issue_node_write(reg, &write_wc); - if (ret == 0) - o2hb_wait_on_io(reg, &write_wc); - else - mlog_errno(ret); - } - - /* Unpin node */ - o2nm_undepend_this_node(); - - mlog(ML_HEARTBEAT|ML_KTHREAD, "o2hb thread exiting\n"); - - return 0; -} - -#ifdef CONFIG_DEBUG_FS -static int o2hb_debug_open(struct inode *inode, struct file *file) -{ - struct o2hb_debug_buf *db = inode->i_private; - struct o2hb_region *reg; - unsigned long map[BITS_TO_LONGS(O2NM_MAX_NODES)]; - unsigned long lts; - char *buf = NULL; - int i = -1; - int out = 0; - - /* max_nodes should be the largest bitmap we pass here */ - BUG_ON(sizeof(map) < db->db_size); - - buf = kmalloc(PAGE_SIZE, GFP_KERNEL); - if (!buf) - goto bail; - - switch (db->db_type) { - case O2HB_DB_TYPE_LIVENODES: - case O2HB_DB_TYPE_LIVEREGIONS: - case O2HB_DB_TYPE_QUORUMREGIONS: - case O2HB_DB_TYPE_FAILEDREGIONS: - spin_lock(&o2hb_live_lock); - memcpy(map, db->db_data, db->db_size); - spin_unlock(&o2hb_live_lock); - break; - - case O2HB_DB_TYPE_REGION_LIVENODES: - spin_lock(&o2hb_live_lock); - reg = (struct o2hb_region *)db->db_data; - memcpy(map, reg->hr_live_node_bitmap, db->db_size); - spin_unlock(&o2hb_live_lock); - break; - - case O2HB_DB_TYPE_REGION_NUMBER: - reg = (struct o2hb_region *)db->db_data; - out += snprintf(buf + out, PAGE_SIZE - out, "%d\n", - reg->hr_region_num); - goto done; - - case O2HB_DB_TYPE_REGION_ELAPSED_TIME: - reg = (struct o2hb_region *)db->db_data; - lts = reg->hr_last_timeout_start; - /* If 0, it has never been set before */ - if (lts) - lts = jiffies_to_msecs(jiffies - lts); - out += snprintf(buf + out, PAGE_SIZE - out, "%lu\n", lts); - goto done; - - case O2HB_DB_TYPE_REGION_PINNED: - reg = (struct o2hb_region *)db->db_data; - out += snprintf(buf + out, PAGE_SIZE - out, "%u\n", - !!reg->hr_item_pinned); - goto done; - - default: - goto done; - } - - while ((i = find_next_bit(map, db->db_len, i + 1)) < db->db_len) - out += snprintf(buf + out, PAGE_SIZE - out, "%d ", i); - out += snprintf(buf + out, PAGE_SIZE - out, "\n"); - -done: - i_size_write(inode, out); - - file->private_data = buf; - - return 0; -bail: - return -ENOMEM; -} - -static int o2hb_debug_release(struct inode *inode, struct file *file) -{ - kfree(file->private_data); - return 0; -} - -static ssize_t o2hb_debug_read(struct file *file, char __user *buf, - size_t nbytes, loff_t *ppos) -{ - return simple_read_from_buffer(buf, nbytes, ppos, file->private_data, - i_size_read(file->f_mapping->host)); -} -#else -static int o2hb_debug_open(struct inode *inode, struct file *file) -{ - return 0; -} -static int o2hb_debug_release(struct inode *inode, struct file *file) -{ - return 0; -} -static ssize_t o2hb_debug_read(struct file *file, char __user *buf, - size_t nbytes, loff_t *ppos) -{ - return 0; -} -#endif /* CONFIG_DEBUG_FS */ - -static const struct file_operations o2hb_debug_fops = { - .open = o2hb_debug_open, - .release = o2hb_debug_release, - .read = o2hb_debug_read, - .llseek = generic_file_llseek, -}; - -void o2hb_exit(void) -{ - kfree(o2hb_db_livenodes); - kfree(o2hb_db_liveregions); - kfree(o2hb_db_quorumregions); - kfree(o2hb_db_failedregions); - debugfs_remove(o2hb_debug_failedregions); - debugfs_remove(o2hb_debug_quorumregions); - debugfs_remove(o2hb_debug_liveregions); - debugfs_remove(o2hb_debug_livenodes); - debugfs_remove(o2hb_debug_dir); -} - -static struct dentry *o2hb_debug_create(const char *name, struct dentry *dir, - struct o2hb_debug_buf **db, int db_len, - int type, int size, int len, void *data) -{ - *db = kmalloc(db_len, GFP_KERNEL); - if (!*db) - return NULL; - - (*db)->db_type = type; - (*db)->db_size = size; - (*db)->db_len = len; - (*db)->db_data = data; - - return debugfs_create_file(name, S_IFREG|S_IRUSR, dir, *db, - &o2hb_debug_fops); -} - -static int o2hb_debug_init(void) -{ - int ret = -ENOMEM; - - o2hb_debug_dir = debugfs_create_dir(O2HB_DEBUG_DIR, NULL); - if (!o2hb_debug_dir) { - mlog_errno(ret); - goto bail; - } - - o2hb_debug_livenodes = o2hb_debug_create(O2HB_DEBUG_LIVENODES, - o2hb_debug_dir, - &o2hb_db_livenodes, - sizeof(*o2hb_db_livenodes), - O2HB_DB_TYPE_LIVENODES, - sizeof(o2hb_live_node_bitmap), - O2NM_MAX_NODES, - o2hb_live_node_bitmap); - if (!o2hb_debug_livenodes) { - mlog_errno(ret); - goto bail; - } - - o2hb_debug_liveregions = o2hb_debug_create(O2HB_DEBUG_LIVEREGIONS, - o2hb_debug_dir, - &o2hb_db_liveregions, - sizeof(*o2hb_db_liveregions), - O2HB_DB_TYPE_LIVEREGIONS, - sizeof(o2hb_live_region_bitmap), - O2NM_MAX_REGIONS, - o2hb_live_region_bitmap); - if (!o2hb_debug_liveregions) { - mlog_errno(ret); - goto bail; - } - - o2hb_debug_quorumregions = - o2hb_debug_create(O2HB_DEBUG_QUORUMREGIONS, - o2hb_debug_dir, - &o2hb_db_quorumregions, - sizeof(*o2hb_db_quorumregions), - O2HB_DB_TYPE_QUORUMREGIONS, - sizeof(o2hb_quorum_region_bitmap), - O2NM_MAX_REGIONS, - o2hb_quorum_region_bitmap); - if (!o2hb_debug_quorumregions) { - mlog_errno(ret); - goto bail; - } - - o2hb_debug_failedregions = - o2hb_debug_create(O2HB_DEBUG_FAILEDREGIONS, - o2hb_debug_dir, - &o2hb_db_failedregions, - sizeof(*o2hb_db_failedregions), - O2HB_DB_TYPE_FAILEDREGIONS, - sizeof(o2hb_failed_region_bitmap), - O2NM_MAX_REGIONS, - o2hb_failed_region_bitmap); - if (!o2hb_debug_failedregions) { - mlog_errno(ret); - goto bail; - } - - ret = 0; -bail: - if (ret) - o2hb_exit(); - - return ret; -} - -int o2hb_init(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(o2hb_callbacks); i++) - INIT_LIST_HEAD(&o2hb_callbacks[i].list); - - for (i = 0; i < ARRAY_SIZE(o2hb_live_slots); i++) - INIT_LIST_HEAD(&o2hb_live_slots[i]); - - INIT_LIST_HEAD(&o2hb_node_events); - - memset(o2hb_live_node_bitmap, 0, sizeof(o2hb_live_node_bitmap)); - memset(o2hb_region_bitmap, 0, sizeof(o2hb_region_bitmap)); - memset(o2hb_live_region_bitmap, 0, sizeof(o2hb_live_region_bitmap)); - memset(o2hb_quorum_region_bitmap, 0, sizeof(o2hb_quorum_region_bitmap)); - memset(o2hb_failed_region_bitmap, 0, sizeof(o2hb_failed_region_bitmap)); - - o2hb_dependent_users = 0; - - return o2hb_debug_init(); -} - -/* if we're already in a callback then we're already serialized by the sem */ -static void o2hb_fill_node_map_from_callback(unsigned long *map, - unsigned bytes) -{ - BUG_ON(bytes < (BITS_TO_LONGS(O2NM_MAX_NODES) * sizeof(unsigned long))); - - memcpy(map, &o2hb_live_node_bitmap, bytes); -} - -/* - * get a map of all nodes that are heartbeating in any regions - */ -void o2hb_fill_node_map(unsigned long *map, unsigned bytes) -{ - /* callers want to serialize this map and callbacks so that they - * can trust that they don't miss nodes coming to the party */ - down_read(&o2hb_callback_sem); - spin_lock(&o2hb_live_lock); - o2hb_fill_node_map_from_callback(map, bytes); - spin_unlock(&o2hb_live_lock); - up_read(&o2hb_callback_sem); -} -EXPORT_SYMBOL_GPL(o2hb_fill_node_map); - -/* - * heartbeat configfs bits. The heartbeat set is a default set under - * the cluster set in nodemanager.c. - */ - -static struct o2hb_region *to_o2hb_region(struct config_item *item) -{ - return item ? container_of(item, struct o2hb_region, hr_item) : NULL; -} - -/* drop_item only drops its ref after killing the thread, nothing should - * be using the region anymore. this has to clean up any state that - * attributes might have built up. */ -static void o2hb_region_release(struct config_item *item) -{ - int i; - struct page *page; - struct o2hb_region *reg = to_o2hb_region(item); - - mlog(ML_HEARTBEAT, "hb region release (%s)\n", reg->hr_dev_name); - - if (reg->hr_tmp_block) - kfree(reg->hr_tmp_block); - - if (reg->hr_slot_data) { - for (i = 0; i < reg->hr_num_pages; i++) { - page = reg->hr_slot_data[i]; - if (page) - __free_page(page); - } - kfree(reg->hr_slot_data); - } - - if (reg->hr_bdev) - blkdev_put(reg->hr_bdev, FMODE_READ|FMODE_WRITE); - - if (reg->hr_slots) - kfree(reg->hr_slots); - - kfree(reg->hr_db_regnum); - kfree(reg->hr_db_livenodes); - debugfs_remove(reg->hr_debug_livenodes); - debugfs_remove(reg->hr_debug_regnum); - debugfs_remove(reg->hr_debug_elapsed_time); - debugfs_remove(reg->hr_debug_pinned); - debugfs_remove(reg->hr_debug_dir); - - spin_lock(&o2hb_live_lock); - list_del(®->hr_all_item); - spin_unlock(&o2hb_live_lock); - - kfree(reg); -} - -static int o2hb_read_block_input(struct o2hb_region *reg, - const char *page, - size_t count, - unsigned long *ret_bytes, - unsigned int *ret_bits) -{ - unsigned long bytes; - char *p = (char *)page; - - bytes = simple_strtoul(p, &p, 0); - if (!p || (*p && (*p != '\n'))) - return -EINVAL; - - /* Heartbeat and fs min / max block sizes are the same. */ - if (bytes > 4096 || bytes < 512) - return -ERANGE; - if (hweight16(bytes) != 1) - return -EINVAL; - - if (ret_bytes) - *ret_bytes = bytes; - if (ret_bits) - *ret_bits = ffs(bytes) - 1; - - return 0; -} - -static ssize_t o2hb_region_block_bytes_read(struct o2hb_region *reg, - char *page) -{ - return sprintf(page, "%u\n", reg->hr_block_bytes); -} - -static ssize_t o2hb_region_block_bytes_write(struct o2hb_region *reg, - const char *page, - size_t count) -{ - int status; - unsigned long block_bytes; - unsigned int block_bits; - - if (reg->hr_bdev) - return -EINVAL; - - status = o2hb_read_block_input(reg, page, count, - &block_bytes, &block_bits); - if (status) - return status; - - reg->hr_block_bytes = (unsigned int)block_bytes; - reg->hr_block_bits = block_bits; - - return count; -} - -static ssize_t o2hb_region_start_block_read(struct o2hb_region *reg, - char *page) -{ - return sprintf(page, "%llu\n", reg->hr_start_block); -} - -static ssize_t o2hb_region_start_block_write(struct o2hb_region *reg, - const char *page, - size_t count) -{ - unsigned long long tmp; - char *p = (char *)page; - - if (reg->hr_bdev) - return -EINVAL; - - tmp = simple_strtoull(p, &p, 0); - if (!p || (*p && (*p != '\n'))) - return -EINVAL; - - reg->hr_start_block = tmp; - - return count; -} - -static ssize_t o2hb_region_blocks_read(struct o2hb_region *reg, - char *page) -{ - return sprintf(page, "%d\n", reg->hr_blocks); -} - -static ssize_t o2hb_region_blocks_write(struct o2hb_region *reg, - const char *page, - size_t count) -{ - unsigned long tmp; - char *p = (char *)page; - - if (reg->hr_bdev) - return -EINVAL; - - tmp = simple_strtoul(p, &p, 0); - if (!p || (*p && (*p != '\n'))) - return -EINVAL; - - if (tmp > O2NM_MAX_NODES || tmp == 0) - return -ERANGE; - - reg->hr_blocks = (unsigned int)tmp; - - return count; -} - -static ssize_t o2hb_region_dev_read(struct o2hb_region *reg, - char *page) -{ - unsigned int ret = 0; - - if (reg->hr_bdev) - ret = sprintf(page, "%s\n", reg->hr_dev_name); - - return ret; -} - -static void o2hb_init_region_params(struct o2hb_region *reg) -{ - reg->hr_slots_per_page = PAGE_CACHE_SIZE >> reg->hr_block_bits; - reg->hr_timeout_ms = O2HB_REGION_TIMEOUT_MS; - - mlog(ML_HEARTBEAT, "hr_start_block = %llu, hr_blocks = %u\n", - reg->hr_start_block, reg->hr_blocks); - mlog(ML_HEARTBEAT, "hr_block_bytes = %u, hr_block_bits = %u\n", - reg->hr_block_bytes, reg->hr_block_bits); - mlog(ML_HEARTBEAT, "hr_timeout_ms = %u\n", reg->hr_timeout_ms); - mlog(ML_HEARTBEAT, "dead threshold = %u\n", o2hb_dead_threshold); -} - -static int o2hb_map_slot_data(struct o2hb_region *reg) -{ - int i, j; - unsigned int last_slot; - unsigned int spp = reg->hr_slots_per_page; - struct page *page; - char *raw; - struct o2hb_disk_slot *slot; - - reg->hr_tmp_block = kmalloc(reg->hr_block_bytes, GFP_KERNEL); - if (reg->hr_tmp_block == NULL) { - mlog_errno(-ENOMEM); - return -ENOMEM; - } - - reg->hr_slots = kcalloc(reg->hr_blocks, - sizeof(struct o2hb_disk_slot), GFP_KERNEL); - if (reg->hr_slots == NULL) { - mlog_errno(-ENOMEM); - return -ENOMEM; - } - - for(i = 0; i < reg->hr_blocks; i++) { - slot = ®->hr_slots[i]; - slot->ds_node_num = i; - INIT_LIST_HEAD(&slot->ds_live_item); - slot->ds_raw_block = NULL; - } - - reg->hr_num_pages = (reg->hr_blocks + spp - 1) / spp; - mlog(ML_HEARTBEAT, "Going to require %u pages to cover %u blocks " - "at %u blocks per page\n", - reg->hr_num_pages, reg->hr_blocks, spp); - - reg->hr_slot_data = kcalloc(reg->hr_num_pages, sizeof(struct page *), - GFP_KERNEL); - if (!reg->hr_slot_data) { - mlog_errno(-ENOMEM); - return -ENOMEM; - } - - for(i = 0; i < reg->hr_num_pages; i++) { - page = alloc_page(GFP_KERNEL); - if (!page) { - mlog_errno(-ENOMEM); - return -ENOMEM; - } - - reg->hr_slot_data[i] = page; - - last_slot = i * spp; - raw = page_address(page); - for (j = 0; - (j < spp) && ((j + last_slot) < reg->hr_blocks); - j++) { - BUG_ON((j + last_slot) >= reg->hr_blocks); - - slot = ®->hr_slots[j + last_slot]; - slot->ds_raw_block = - (struct o2hb_disk_heartbeat_block *) raw; - - raw += reg->hr_block_bytes; - } - } - - return 0; -} - -/* Read in all the slots available and populate the tracking - * structures so that we can start with a baseline idea of what's - * there. */ -static int o2hb_populate_slot_data(struct o2hb_region *reg) -{ - int ret, i; - struct o2hb_disk_slot *slot; - struct o2hb_disk_heartbeat_block *hb_block; - - ret = o2hb_read_slots(reg, reg->hr_blocks); - if (ret) { - mlog_errno(ret); - goto out; - } - - /* We only want to get an idea of the values initially in each - * slot, so we do no verification - o2hb_check_slot will - * actually determine if each configured slot is valid and - * whether any values have changed. */ - for(i = 0; i < reg->hr_blocks; i++) { - slot = ®->hr_slots[i]; - hb_block = (struct o2hb_disk_heartbeat_block *) slot->ds_raw_block; - - /* Only fill the values that o2hb_check_slot uses to - * determine changing slots */ - slot->ds_last_time = le64_to_cpu(hb_block->hb_seq); - slot->ds_last_generation = le64_to_cpu(hb_block->hb_generation); - } - -out: - return ret; -} - -/* this is acting as commit; we set up all of hr_bdev and hr_task or nothing */ -static ssize_t o2hb_region_dev_write(struct o2hb_region *reg, - const char *page, - size_t count) -{ - struct task_struct *hb_task; - long fd; - int sectsize; - char *p = (char *)page; - struct file *filp = NULL; - struct inode *inode = NULL; - ssize_t ret = -EINVAL; - int live_threshold; - - if (reg->hr_bdev) - goto out; - - /* We can't heartbeat without having had our node number - * configured yet. */ - if (o2nm_this_node() == O2NM_MAX_NODES) - goto out; - - fd = simple_strtol(p, &p, 0); - if (!p || (*p && (*p != '\n'))) - goto out; - - if (fd < 0 || fd >= INT_MAX) - goto out; - - filp = fget(fd); - if (filp == NULL) - goto out; - - if (reg->hr_blocks == 0 || reg->hr_start_block == 0 || - reg->hr_block_bytes == 0) - goto out; - - inode = igrab(filp->f_mapping->host); - if (inode == NULL) - goto out; - - if (!S_ISBLK(inode->i_mode)) - goto out; - - reg->hr_bdev = I_BDEV(filp->f_mapping->host); - ret = blkdev_get(reg->hr_bdev, FMODE_WRITE | FMODE_READ, NULL); - if (ret) { - reg->hr_bdev = NULL; - goto out; - } - inode = NULL; - - bdevname(reg->hr_bdev, reg->hr_dev_name); - - sectsize = bdev_logical_block_size(reg->hr_bdev); - if (sectsize != reg->hr_block_bytes) { - mlog(ML_ERROR, - "blocksize %u incorrect for device, expected %d", - reg->hr_block_bytes, sectsize); - ret = -EINVAL; - goto out; - } - - o2hb_init_region_params(reg); - - /* Generation of zero is invalid */ - do { - get_random_bytes(®->hr_generation, - sizeof(reg->hr_generation)); - } while (reg->hr_generation == 0); - - ret = o2hb_map_slot_data(reg); - if (ret) { - mlog_errno(ret); - goto out; - } - - ret = o2hb_populate_slot_data(reg); - if (ret) { - mlog_errno(ret); - goto out; - } - - INIT_DELAYED_WORK(®->hr_write_timeout_work, o2hb_write_timeout); - - /* - * A node is considered live after it has beat LIVE_THRESHOLD - * times. We're not steady until we've given them a chance - * _after_ our first read. - * The default threshold is bare minimum so as to limit the delay - * during mounts. For global heartbeat, the threshold doubled for the - * first region. - */ - live_threshold = O2HB_LIVE_THRESHOLD; - if (o2hb_global_heartbeat_active()) { - spin_lock(&o2hb_live_lock); - if (o2hb_pop_count(&o2hb_region_bitmap, O2NM_MAX_REGIONS) == 1) - live_threshold <<= 1; - spin_unlock(&o2hb_live_lock); - } - ++live_threshold; - atomic_set(®->hr_steady_iterations, live_threshold); - /* unsteady_iterations is double the steady_iterations */ - atomic_set(®->hr_unsteady_iterations, (live_threshold << 1)); - - hb_task = kthread_run(o2hb_thread, reg, "o2hb-%s", - reg->hr_item.ci_name); - if (IS_ERR(hb_task)) { - ret = PTR_ERR(hb_task); - mlog_errno(ret); - goto out; - } - - spin_lock(&o2hb_live_lock); - reg->hr_task = hb_task; - spin_unlock(&o2hb_live_lock); - - ret = wait_event_interruptible(o2hb_steady_queue, - atomic_read(®->hr_steady_iterations) == 0); - if (ret) { - atomic_set(®->hr_steady_iterations, 0); - reg->hr_aborted_start = 1; - } - - if (reg->hr_aborted_start) { - ret = -EIO; - goto out; - } - - /* Ok, we were woken. Make sure it wasn't by drop_item() */ - spin_lock(&o2hb_live_lock); - hb_task = reg->hr_task; - if (o2hb_global_heartbeat_active()) - set_bit(reg->hr_region_num, o2hb_live_region_bitmap); - spin_unlock(&o2hb_live_lock); - - if (hb_task) - ret = count; - else - ret = -EIO; - - if (hb_task && o2hb_global_heartbeat_active()) - printk(KERN_NOTICE "o2hb: Heartbeat started on region %s (%s)\n", - config_item_name(®->hr_item), reg->hr_dev_name); - -out: - if (filp) - fput(filp); - if (inode) - iput(inode); - if (ret < 0) { - if (reg->hr_bdev) { - blkdev_put(reg->hr_bdev, FMODE_READ|FMODE_WRITE); - reg->hr_bdev = NULL; - } - } - return ret; -} - -static ssize_t o2hb_region_pid_read(struct o2hb_region *reg, - char *page) -{ - pid_t pid = 0; - - spin_lock(&o2hb_live_lock); - if (reg->hr_task) - pid = task_pid_nr(reg->hr_task); - spin_unlock(&o2hb_live_lock); - - if (!pid) - return 0; - - return sprintf(page, "%u\n", pid); -} - -struct o2hb_region_attribute { - struct configfs_attribute attr; - ssize_t (*show)(struct o2hb_region *, char *); - ssize_t (*store)(struct o2hb_region *, const char *, size_t); -}; - -static struct o2hb_region_attribute o2hb_region_attr_block_bytes = { - .attr = { .ca_owner = THIS_MODULE, - .ca_name = "block_bytes", - .ca_mode = S_IRUGO | S_IWUSR }, - .show = o2hb_region_block_bytes_read, - .store = o2hb_region_block_bytes_write, -}; - -static struct o2hb_region_attribute o2hb_region_attr_start_block = { - .attr = { .ca_owner = THIS_MODULE, - .ca_name = "start_block", - .ca_mode = S_IRUGO | S_IWUSR }, - .show = o2hb_region_start_block_read, - .store = o2hb_region_start_block_write, -}; - -static struct o2hb_region_attribute o2hb_region_attr_blocks = { - .attr = { .ca_owner = THIS_MODULE, - .ca_name = "blocks", - .ca_mode = S_IRUGO | S_IWUSR }, - .show = o2hb_region_blocks_read, - .store = o2hb_region_blocks_write, -}; - -static struct o2hb_region_attribute o2hb_region_attr_dev = { - .attr = { .ca_owner = THIS_MODULE, - .ca_name = "dev", - .ca_mode = S_IRUGO | S_IWUSR }, - .show = o2hb_region_dev_read, - .store = o2hb_region_dev_write, -}; - -static struct o2hb_region_attribute o2hb_region_attr_pid = { - .attr = { .ca_owner = THIS_MODULE, - .ca_name = "pid", - .ca_mode = S_IRUGO | S_IRUSR }, - .show = o2hb_region_pid_read, -}; - -static struct configfs_attribute *o2hb_region_attrs[] = { - &o2hb_region_attr_block_bytes.attr, - &o2hb_region_attr_start_block.attr, - &o2hb_region_attr_blocks.attr, - &o2hb_region_attr_dev.attr, - &o2hb_region_attr_pid.attr, - NULL, -}; - -static ssize_t o2hb_region_show(struct config_item *item, - struct configfs_attribute *attr, - char *page) -{ - struct o2hb_region *reg = to_o2hb_region(item); - struct o2hb_region_attribute *o2hb_region_attr = - container_of(attr, struct o2hb_region_attribute, attr); - ssize_t ret = 0; - - if (o2hb_region_attr->show) - ret = o2hb_region_attr->show(reg, page); - return ret; -} - -static ssize_t o2hb_region_store(struct config_item *item, - struct configfs_attribute *attr, - const char *page, size_t count) -{ - struct o2hb_region *reg = to_o2hb_region(item); - struct o2hb_region_attribute *o2hb_region_attr = - container_of(attr, struct o2hb_region_attribute, attr); - ssize_t ret = -EINVAL; - - if (o2hb_region_attr->store) - ret = o2hb_region_attr->store(reg, page, count); - return ret; -} - -static struct configfs_item_operations o2hb_region_item_ops = { - .release = o2hb_region_release, - .show_attribute = o2hb_region_show, - .store_attribute = o2hb_region_store, -}; - -static struct config_item_type o2hb_region_type = { - .ct_item_ops = &o2hb_region_item_ops, - .ct_attrs = o2hb_region_attrs, - .ct_owner = THIS_MODULE, -}; - -/* heartbeat set */ - -struct o2hb_heartbeat_group { - struct config_group hs_group; - /* some stuff? */ -}; - -static struct o2hb_heartbeat_group *to_o2hb_heartbeat_group(struct config_group *group) -{ - return group ? - container_of(group, struct o2hb_heartbeat_group, hs_group) - : NULL; -} - -static int o2hb_debug_region_init(struct o2hb_region *reg, struct dentry *dir) -{ - int ret = -ENOMEM; - - reg->hr_debug_dir = - debugfs_create_dir(config_item_name(®->hr_item), dir); - if (!reg->hr_debug_dir) { - mlog_errno(ret); - goto bail; - } - - reg->hr_debug_livenodes = - o2hb_debug_create(O2HB_DEBUG_LIVENODES, - reg->hr_debug_dir, - &(reg->hr_db_livenodes), - sizeof(*(reg->hr_db_livenodes)), - O2HB_DB_TYPE_REGION_LIVENODES, - sizeof(reg->hr_live_node_bitmap), - O2NM_MAX_NODES, reg); - if (!reg->hr_debug_livenodes) { - mlog_errno(ret); - goto bail; - } - - reg->hr_debug_regnum = - o2hb_debug_create(O2HB_DEBUG_REGION_NUMBER, - reg->hr_debug_dir, - &(reg->hr_db_regnum), - sizeof(*(reg->hr_db_regnum)), - O2HB_DB_TYPE_REGION_NUMBER, - 0, O2NM_MAX_NODES, reg); - if (!reg->hr_debug_regnum) { - mlog_errno(ret); - goto bail; - } - - reg->hr_debug_elapsed_time = - o2hb_debug_create(O2HB_DEBUG_REGION_ELAPSED_TIME, - reg->hr_debug_dir, - &(reg->hr_db_elapsed_time), - sizeof(*(reg->hr_db_elapsed_time)), - O2HB_DB_TYPE_REGION_ELAPSED_TIME, - 0, 0, reg); - if (!reg->hr_debug_elapsed_time) { - mlog_errno(ret); - goto bail; - } - - reg->hr_debug_pinned = - o2hb_debug_create(O2HB_DEBUG_REGION_PINNED, - reg->hr_debug_dir, - &(reg->hr_db_pinned), - sizeof(*(reg->hr_db_pinned)), - O2HB_DB_TYPE_REGION_PINNED, - 0, 0, reg); - if (!reg->hr_debug_pinned) { - mlog_errno(ret); - goto bail; - } - - ret = 0; -bail: - return ret; -} - -static struct config_item *o2hb_heartbeat_group_make_item(struct config_group *group, - const char *name) -{ - struct o2hb_region *reg = NULL; - int ret; - - reg = kzalloc(sizeof(struct o2hb_region), GFP_KERNEL); - if (reg == NULL) - return ERR_PTR(-ENOMEM); - - if (strlen(name) > O2HB_MAX_REGION_NAME_LEN) { - ret = -ENAMETOOLONG; - goto free; - } - - spin_lock(&o2hb_live_lock); - reg->hr_region_num = 0; - if (o2hb_global_heartbeat_active()) { - reg->hr_region_num = find_first_zero_bit(o2hb_region_bitmap, - O2NM_MAX_REGIONS); - if (reg->hr_region_num >= O2NM_MAX_REGIONS) { - spin_unlock(&o2hb_live_lock); - ret = -EFBIG; - goto free; - } - set_bit(reg->hr_region_num, o2hb_region_bitmap); - } - list_add_tail(®->hr_all_item, &o2hb_all_regions); - spin_unlock(&o2hb_live_lock); - - config_item_init_type_name(®->hr_item, name, &o2hb_region_type); - - ret = o2hb_debug_region_init(reg, o2hb_debug_dir); - if (ret) { - config_item_put(®->hr_item); - goto free; - } - - return ®->hr_item; -free: - kfree(reg); - return ERR_PTR(ret); -} - -static void o2hb_heartbeat_group_drop_item(struct config_group *group, - struct config_item *item) -{ - struct task_struct *hb_task; - struct o2hb_region *reg = to_o2hb_region(item); - int quorum_region = 0; - - /* stop the thread when the user removes the region dir */ - spin_lock(&o2hb_live_lock); - hb_task = reg->hr_task; - reg->hr_task = NULL; - reg->hr_item_dropped = 1; - spin_unlock(&o2hb_live_lock); - - if (hb_task) - kthread_stop(hb_task); - - if (o2hb_global_heartbeat_active()) { - spin_lock(&o2hb_live_lock); - clear_bit(reg->hr_region_num, o2hb_region_bitmap); - clear_bit(reg->hr_region_num, o2hb_live_region_bitmap); - if (test_bit(reg->hr_region_num, o2hb_quorum_region_bitmap)) - quorum_region = 1; - clear_bit(reg->hr_region_num, o2hb_quorum_region_bitmap); - spin_unlock(&o2hb_live_lock); - printk(KERN_NOTICE "o2hb: Heartbeat %s on region %s (%s)\n", - ((atomic_read(®->hr_steady_iterations) == 0) ? - "stopped" : "start aborted"), config_item_name(item), - reg->hr_dev_name); - } - - /* - * If we're racing a dev_write(), we need to wake them. They will - * check reg->hr_task - */ - if (atomic_read(®->hr_steady_iterations) != 0) { - reg->hr_aborted_start = 1; - atomic_set(®->hr_steady_iterations, 0); - wake_up(&o2hb_steady_queue); - } - - config_item_put(item); - - if (!o2hb_global_heartbeat_active() || !quorum_region) - return; - - /* - * If global heartbeat active and there are dependent users, - * pin all regions if quorum region count <= CUT_OFF - */ - spin_lock(&o2hb_live_lock); - - if (!o2hb_dependent_users) - goto unlock; - - if (o2hb_pop_count(&o2hb_quorum_region_bitmap, - O2NM_MAX_REGIONS) <= O2HB_PIN_CUT_OFF) - o2hb_region_pin(NULL); - -unlock: - spin_unlock(&o2hb_live_lock); -} - -struct o2hb_heartbeat_group_attribute { - struct configfs_attribute attr; - ssize_t (*show)(struct o2hb_heartbeat_group *, char *); - ssize_t (*store)(struct o2hb_heartbeat_group *, const char *, size_t); -}; - -static ssize_t o2hb_heartbeat_group_show(struct config_item *item, - struct configfs_attribute *attr, - char *page) -{ - struct o2hb_heartbeat_group *reg = to_o2hb_heartbeat_group(to_config_group(item)); - struct o2hb_heartbeat_group_attribute *o2hb_heartbeat_group_attr = - container_of(attr, struct o2hb_heartbeat_group_attribute, attr); - ssize_t ret = 0; - - if (o2hb_heartbeat_group_attr->show) - ret = o2hb_heartbeat_group_attr->show(reg, page); - return ret; -} - -static ssize_t o2hb_heartbeat_group_store(struct config_item *item, - struct configfs_attribute *attr, - const char *page, size_t count) -{ - struct o2hb_heartbeat_group *reg = to_o2hb_heartbeat_group(to_config_group(item)); - struct o2hb_heartbeat_group_attribute *o2hb_heartbeat_group_attr = - container_of(attr, struct o2hb_heartbeat_group_attribute, attr); - ssize_t ret = -EINVAL; - - if (o2hb_heartbeat_group_attr->store) - ret = o2hb_heartbeat_group_attr->store(reg, page, count); - return ret; -} - -static ssize_t o2hb_heartbeat_group_threshold_show(struct o2hb_heartbeat_group *group, - char *page) -{ - return sprintf(page, "%u\n", o2hb_dead_threshold); -} - -static ssize_t o2hb_heartbeat_group_threshold_store(struct o2hb_heartbeat_group *group, - const char *page, - size_t count) -{ - unsigned long tmp; - char *p = (char *)page; - - tmp = simple_strtoul(p, &p, 10); - if (!p || (*p && (*p != '\n'))) - return -EINVAL; - - /* this will validate ranges for us. */ - o2hb_dead_threshold_set((unsigned int) tmp); - - return count; -} - -static -ssize_t o2hb_heartbeat_group_mode_show(struct o2hb_heartbeat_group *group, - char *page) -{ - return sprintf(page, "%s\n", - o2hb_heartbeat_mode_desc[o2hb_heartbeat_mode]); -} - -static -ssize_t o2hb_heartbeat_group_mode_store(struct o2hb_heartbeat_group *group, - const char *page, size_t count) -{ - unsigned int i; - int ret; - size_t len; - - len = (page[count - 1] == '\n') ? count - 1 : count; - if (!len) - return -EINVAL; - - for (i = 0; i < O2HB_HEARTBEAT_NUM_MODES; ++i) { - if (strnicmp(page, o2hb_heartbeat_mode_desc[i], len)) - continue; - - ret = o2hb_global_hearbeat_mode_set(i); - if (!ret) - printk(KERN_NOTICE "o2hb: Heartbeat mode set to %s\n", - o2hb_heartbeat_mode_desc[i]); - return count; - } - - return -EINVAL; - -} - -static struct o2hb_heartbeat_group_attribute o2hb_heartbeat_group_attr_threshold = { - .attr = { .ca_owner = THIS_MODULE, - .ca_name = "dead_threshold", - .ca_mode = S_IRUGO | S_IWUSR }, - .show = o2hb_heartbeat_group_threshold_show, - .store = o2hb_heartbeat_group_threshold_store, -}; - -static struct o2hb_heartbeat_group_attribute o2hb_heartbeat_group_attr_mode = { - .attr = { .ca_owner = THIS_MODULE, - .ca_name = "mode", - .ca_mode = S_IRUGO | S_IWUSR }, - .show = o2hb_heartbeat_group_mode_show, - .store = o2hb_heartbeat_group_mode_store, -}; - -static struct configfs_attribute *o2hb_heartbeat_group_attrs[] = { - &o2hb_heartbeat_group_attr_threshold.attr, - &o2hb_heartbeat_group_attr_mode.attr, - NULL, -}; - -static struct configfs_item_operations o2hb_hearbeat_group_item_ops = { - .show_attribute = o2hb_heartbeat_group_show, - .store_attribute = o2hb_heartbeat_group_store, -}; - -static struct configfs_group_operations o2hb_heartbeat_group_group_ops = { - .make_item = o2hb_heartbeat_group_make_item, - .drop_item = o2hb_heartbeat_group_drop_item, -}; - -static struct config_item_type o2hb_heartbeat_group_type = { - .ct_group_ops = &o2hb_heartbeat_group_group_ops, - .ct_item_ops = &o2hb_hearbeat_group_item_ops, - .ct_attrs = o2hb_heartbeat_group_attrs, - .ct_owner = THIS_MODULE, -}; - -/* this is just here to avoid touching group in heartbeat.h which the - * entire damn world #includes */ -struct config_group *o2hb_alloc_hb_set(void) -{ - struct o2hb_heartbeat_group *hs = NULL; - struct config_group *ret = NULL; - - hs = kzalloc(sizeof(struct o2hb_heartbeat_group), GFP_KERNEL); - if (hs == NULL) - goto out; - - config_group_init_type_name(&hs->hs_group, "heartbeat", - &o2hb_heartbeat_group_type); - - ret = &hs->hs_group; -out: - if (ret == NULL) - kfree(hs); - return ret; -} - -void o2hb_free_hb_set(struct config_group *group) -{ - struct o2hb_heartbeat_group *hs = to_o2hb_heartbeat_group(group); - kfree(hs); -} - -/* hb callback registration and issuing */ - -static struct o2hb_callback *hbcall_from_type(enum o2hb_callback_type type) -{ - if (type == O2HB_NUM_CB) - return ERR_PTR(-EINVAL); - - return &o2hb_callbacks[type]; -} - -void o2hb_setup_callback(struct o2hb_callback_func *hc, - enum o2hb_callback_type type, - o2hb_cb_func *func, - void *data, - int priority) -{ - INIT_LIST_HEAD(&hc->hc_item); - hc->hc_func = func; - hc->hc_data = data; - hc->hc_priority = priority; - hc->hc_type = type; - hc->hc_magic = O2HB_CB_MAGIC; -} -EXPORT_SYMBOL_GPL(o2hb_setup_callback); - -/* - * In local heartbeat mode, region_uuid passed matches the dlm domain name. - * In global heartbeat mode, region_uuid passed is NULL. - * - * In local, we only pin the matching region. In global we pin all the active - * regions. - */ -static int o2hb_region_pin(const char *region_uuid) -{ - int ret = 0, found = 0; - struct o2hb_region *reg; - char *uuid; - - assert_spin_locked(&o2hb_live_lock); - - list_for_each_entry(reg, &o2hb_all_regions, hr_all_item) { - uuid = config_item_name(®->hr_item); - - /* local heartbeat */ - if (region_uuid) { - if (strcmp(region_uuid, uuid)) - continue; - found = 1; - } - - if (reg->hr_item_pinned || reg->hr_item_dropped) - goto skip_pin; - - /* Ignore ENOENT only for local hb (userdlm domain) */ - ret = o2nm_depend_item(®->hr_item); - if (!ret) { - mlog(ML_CLUSTER, "Pin region %s\n", uuid); - reg->hr_item_pinned = 1; - } else { - if (ret == -ENOENT && found) - ret = 0; - else { - mlog(ML_ERROR, "Pin region %s fails with %d\n", - uuid, ret); - break; - } - } -skip_pin: - if (found) - break; - } - - return ret; -} - -/* - * In local heartbeat mode, region_uuid passed matches the dlm domain name. - * In global heartbeat mode, region_uuid passed is NULL. - * - * In local, we only unpin the matching region. In global we unpin all the - * active regions. - */ -static void o2hb_region_unpin(const char *region_uuid) -{ - struct o2hb_region *reg; - char *uuid; - int found = 0; - - assert_spin_locked(&o2hb_live_lock); - - list_for_each_entry(reg, &o2hb_all_regions, hr_all_item) { - uuid = config_item_name(®->hr_item); - if (region_uuid) { - if (strcmp(region_uuid, uuid)) - continue; - found = 1; - } - - if (reg->hr_item_pinned) { - mlog(ML_CLUSTER, "Unpin region %s\n", uuid); - o2nm_undepend_item(®->hr_item); - reg->hr_item_pinned = 0; - } - if (found) - break; - } -} - -static int o2hb_region_inc_user(const char *region_uuid) -{ - int ret = 0; - - spin_lock(&o2hb_live_lock); - - /* local heartbeat */ - if (!o2hb_global_heartbeat_active()) { - ret = o2hb_region_pin(region_uuid); - goto unlock; - } - - /* - * if global heartbeat active and this is the first dependent user, - * pin all regions if quorum region count <= CUT_OFF - */ - o2hb_dependent_users++; - if (o2hb_dependent_users > 1) - goto unlock; - - if (o2hb_pop_count(&o2hb_quorum_region_bitmap, - O2NM_MAX_REGIONS) <= O2HB_PIN_CUT_OFF) - ret = o2hb_region_pin(NULL); - -unlock: - spin_unlock(&o2hb_live_lock); - return ret; -} - -void o2hb_region_dec_user(const char *region_uuid) -{ - spin_lock(&o2hb_live_lock); - - /* local heartbeat */ - if (!o2hb_global_heartbeat_active()) { - o2hb_region_unpin(region_uuid); - goto unlock; - } - - /* - * if global heartbeat active and there are no dependent users, - * unpin all quorum regions - */ - o2hb_dependent_users--; - if (!o2hb_dependent_users) - o2hb_region_unpin(NULL); - -unlock: - spin_unlock(&o2hb_live_lock); -} - -int o2hb_register_callback(const char *region_uuid, - struct o2hb_callback_func *hc) -{ - struct o2hb_callback_func *tmp; - struct list_head *iter; - struct o2hb_callback *hbcall; - int ret; - - BUG_ON(hc->hc_magic != O2HB_CB_MAGIC); - BUG_ON(!list_empty(&hc->hc_item)); - - hbcall = hbcall_from_type(hc->hc_type); - if (IS_ERR(hbcall)) { - ret = PTR_ERR(hbcall); - goto out; - } - - if (region_uuid) { - ret = o2hb_region_inc_user(region_uuid); - if (ret) { - mlog_errno(ret); - goto out; - } - } - - down_write(&o2hb_callback_sem); - - list_for_each(iter, &hbcall->list) { - tmp = list_entry(iter, struct o2hb_callback_func, hc_item); - if (hc->hc_priority < tmp->hc_priority) { - list_add_tail(&hc->hc_item, iter); - break; - } - } - if (list_empty(&hc->hc_item)) - list_add_tail(&hc->hc_item, &hbcall->list); - - up_write(&o2hb_callback_sem); - ret = 0; -out: - mlog(ML_CLUSTER, "returning %d on behalf of %p for funcs %p\n", - ret, __builtin_return_address(0), hc); - return ret; -} -EXPORT_SYMBOL_GPL(o2hb_register_callback); - -void o2hb_unregister_callback(const char *region_uuid, - struct o2hb_callback_func *hc) -{ - BUG_ON(hc->hc_magic != O2HB_CB_MAGIC); - - mlog(ML_CLUSTER, "on behalf of %p for funcs %p\n", - __builtin_return_address(0), hc); - - /* XXX Can this happen _with_ a region reference? */ - if (list_empty(&hc->hc_item)) - return; - - if (region_uuid) - o2hb_region_dec_user(region_uuid); - - down_write(&o2hb_callback_sem); - - list_del_init(&hc->hc_item); - - up_write(&o2hb_callback_sem); -} -EXPORT_SYMBOL_GPL(o2hb_unregister_callback); - -int o2hb_check_node_heartbeating(u8 node_num) -{ - unsigned long testing_map[BITS_TO_LONGS(O2NM_MAX_NODES)]; - - o2hb_fill_node_map(testing_map, sizeof(testing_map)); - if (!test_bit(node_num, testing_map)) { - mlog(ML_HEARTBEAT, - "node (%u) does not have heartbeating enabled.\n", - node_num); - return 0; - } - - return 1; -} -EXPORT_SYMBOL_GPL(o2hb_check_node_heartbeating); - -int o2hb_check_node_heartbeating_from_callback(u8 node_num) -{ - unsigned long testing_map[BITS_TO_LONGS(O2NM_MAX_NODES)]; - - o2hb_fill_node_map_from_callback(testing_map, sizeof(testing_map)); - if (!test_bit(node_num, testing_map)) { - mlog(ML_HEARTBEAT, - "node (%u) does not have heartbeating enabled.\n", - node_num); - return 0; - } - - return 1; -} -EXPORT_SYMBOL_GPL(o2hb_check_node_heartbeating_from_callback); - -/* Makes sure our local node is configured with a node number, and is - * heartbeating. */ -int o2hb_check_local_node_heartbeating(void) -{ - u8 node_num; - - /* if this node was set then we have networking */ - node_num = o2nm_this_node(); - if (node_num == O2NM_MAX_NODES) { - mlog(ML_HEARTBEAT, "this node has not been configured.\n"); - return 0; - } - - return o2hb_check_node_heartbeating(node_num); -} -EXPORT_SYMBOL_GPL(o2hb_check_local_node_heartbeating); - -/* - * this is just a hack until we get the plumbing which flips file systems - * read only and drops the hb ref instead of killing the node dead. - */ -void o2hb_stop_all_regions(void) -{ - struct o2hb_region *reg; - - mlog(ML_ERROR, "stopping heartbeat on all active regions.\n"); - - spin_lock(&o2hb_live_lock); - - list_for_each_entry(reg, &o2hb_all_regions, hr_all_item) - reg->hr_unclean_stop = 1; - - spin_unlock(&o2hb_live_lock); -} -EXPORT_SYMBOL_GPL(o2hb_stop_all_regions); - -int o2hb_get_all_regions(char *region_uuids, u8 max_regions) -{ - struct o2hb_region *reg; - int numregs = 0; - char *p; - - spin_lock(&o2hb_live_lock); - - p = region_uuids; - list_for_each_entry(reg, &o2hb_all_regions, hr_all_item) { - mlog(0, "Region: %s\n", config_item_name(®->hr_item)); - if (numregs < max_regions) { - memcpy(p, config_item_name(®->hr_item), - O2HB_MAX_REGION_NAME_LEN); - p += O2HB_MAX_REGION_NAME_LEN; - } - numregs++; - } - - spin_unlock(&o2hb_live_lock); - - return numregs; -} -EXPORT_SYMBOL_GPL(o2hb_get_all_regions); - -int o2hb_global_heartbeat_active(void) -{ - return (o2hb_heartbeat_mode == O2HB_HEARTBEAT_GLOBAL); -} -EXPORT_SYMBOL(o2hb_global_heartbeat_active); - -#ifdef CONFIG_RAMSTER -void o2hb_manual_set_node_heartbeating(int node_num) -{ - if (node_num < O2NM_MAX_NODES) - set_bit(node_num, o2hb_live_node_bitmap); -} -EXPORT_SYMBOL(o2hb_manual_set_node_heartbeating); -#endif diff --git a/drivers/staging/ramster/cluster/heartbeat.h b/drivers/staging/ramster/cluster/heartbeat.h deleted file mode 100644 index cf1a164..0000000 --- a/drivers/staging/ramster/cluster/heartbeat.h +++ /dev/null @@ -1,92 +0,0 @@ -/* -*- mode: c; c-basic-offset: 8; -*- - * vim: noexpandtab sw=8 ts=8 sts=0: - * - * heartbeat.h - * - * Function prototypes - * - * Copyright (C) 2004 Oracle. All rights reserved. - * - * 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; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 021110-1307, USA. - * - */ - -#ifndef O2CLUSTER_HEARTBEAT_H -#define O2CLUSTER_HEARTBEAT_H - -#include "ocfs2_heartbeat.h" - -#define O2HB_REGION_TIMEOUT_MS 2000 - -#define O2HB_MAX_REGION_NAME_LEN 32 - -/* number of changes to be seen as live */ -#define O2HB_LIVE_THRESHOLD 2 -/* number of equal samples to be seen as dead */ -extern unsigned int o2hb_dead_threshold; -#define O2HB_DEFAULT_DEAD_THRESHOLD 31 -/* Otherwise MAX_WRITE_TIMEOUT will be zero... */ -#define O2HB_MIN_DEAD_THRESHOLD 2 -#define O2HB_MAX_WRITE_TIMEOUT_MS (O2HB_REGION_TIMEOUT_MS * (o2hb_dead_threshold - 1)) - -#define O2HB_CB_MAGIC 0x51d1e4ec - -/* callback stuff */ -enum o2hb_callback_type { - O2HB_NODE_DOWN_CB = 0, - O2HB_NODE_UP_CB, - O2HB_NUM_CB -}; - -struct o2nm_node; -typedef void (o2hb_cb_func)(struct o2nm_node *, int, void *); - -struct o2hb_callback_func { - u32 hc_magic; - struct list_head hc_item; - o2hb_cb_func *hc_func; - void *hc_data; - int hc_priority; - enum o2hb_callback_type hc_type; -}; - -struct config_group *o2hb_alloc_hb_set(void); -void o2hb_free_hb_set(struct config_group *group); - -void o2hb_setup_callback(struct o2hb_callback_func *hc, - enum o2hb_callback_type type, - o2hb_cb_func *func, - void *data, - int priority); -int o2hb_register_callback(const char *region_uuid, - struct o2hb_callback_func *hc); -void o2hb_unregister_callback(const char *region_uuid, - struct o2hb_callback_func *hc); -void o2hb_fill_node_map(unsigned long *map, - unsigned bytes); -void o2hb_exit(void); -int o2hb_init(void); -int o2hb_check_node_heartbeating(u8 node_num); -int o2hb_check_node_heartbeating_from_callback(u8 node_num); -int o2hb_check_local_node_heartbeating(void); -void o2hb_stop_all_regions(void); -int o2hb_get_all_regions(char *region_uuids, u8 numregions); -int o2hb_global_heartbeat_active(void); -#ifdef CONFIG_RAMSTER -void o2hb_manual_set_node_heartbeating(int); -#endif - -#endif /* O2CLUSTER_HEARTBEAT_H */ diff --git a/drivers/staging/ramster/cluster/masklog.c b/drivers/staging/ramster/cluster/masklog.c deleted file mode 100644 index 07ac24f..0000000 --- a/drivers/staging/ramster/cluster/masklog.c +++ /dev/null @@ -1,155 +0,0 @@ -/* -*- mode: c; c-basic-offset: 8; -*- - * vim: noexpandtab sw=8 ts=8 sts=0: - * - * Copyright (C) 2004, 2005 Oracle. All rights reserved. - * - * 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; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 021110-1307, USA. - */ - -#include -#include -#include -#include -#include -#include - -#include "masklog.h" - -struct mlog_bits mlog_and_bits = MLOG_BITS_RHS(MLOG_INITIAL_AND_MASK); -EXPORT_SYMBOL_GPL(mlog_and_bits); -struct mlog_bits mlog_not_bits = MLOG_BITS_RHS(0); -EXPORT_SYMBOL_GPL(mlog_not_bits); - -static ssize_t mlog_mask_show(u64 mask, char *buf) -{ - char *state; - - if (__mlog_test_u64(mask, mlog_and_bits)) - state = "allow"; - else if (__mlog_test_u64(mask, mlog_not_bits)) - state = "deny"; - else - state = "off"; - - return snprintf(buf, PAGE_SIZE, "%s\n", state); -} - -static ssize_t mlog_mask_store(u64 mask, const char *buf, size_t count) -{ - if (!strnicmp(buf, "allow", 5)) { - __mlog_set_u64(mask, mlog_and_bits); - __mlog_clear_u64(mask, mlog_not_bits); - } else if (!strnicmp(buf, "deny", 4)) { - __mlog_set_u64(mask, mlog_not_bits); - __mlog_clear_u64(mask, mlog_and_bits); - } else if (!strnicmp(buf, "off", 3)) { - __mlog_clear_u64(mask, mlog_not_bits); - __mlog_clear_u64(mask, mlog_and_bits); - } else - return -EINVAL; - - return count; -} - -struct mlog_attribute { - struct attribute attr; - u64 mask; -}; - -#define to_mlog_attr(_attr) container_of(_attr, struct mlog_attribute, attr) - -#define define_mask(_name) { \ - .attr = { \ - .name = #_name, \ - .mode = S_IRUGO | S_IWUSR, \ - }, \ - .mask = ML_##_name, \ -} - -static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = { - define_mask(TCP), - define_mask(MSG), - define_mask(SOCKET), - define_mask(HEARTBEAT), - define_mask(HB_BIO), - define_mask(DLMFS), - define_mask(DLM), - define_mask(DLM_DOMAIN), - define_mask(DLM_THREAD), - define_mask(DLM_MASTER), - define_mask(DLM_RECOVERY), - define_mask(DLM_GLUE), - define_mask(VOTE), - define_mask(CONN), - define_mask(QUORUM), - define_mask(BASTS), - define_mask(CLUSTER), - define_mask(ERROR), - define_mask(NOTICE), - define_mask(KTHREAD), -}; - -static struct attribute *mlog_attr_ptrs[MLOG_MAX_BITS] = {NULL, }; - -static ssize_t mlog_show(struct kobject *obj, struct attribute *attr, - char *buf) -{ - struct mlog_attribute *mlog_attr = to_mlog_attr(attr); - - return mlog_mask_show(mlog_attr->mask, buf); -} - -static ssize_t mlog_store(struct kobject *obj, struct attribute *attr, - const char *buf, size_t count) -{ - struct mlog_attribute *mlog_attr = to_mlog_attr(attr); - - return mlog_mask_store(mlog_attr->mask, buf, count); -} - -static const struct sysfs_ops mlog_attr_ops = { - .show = mlog_show, - .store = mlog_store, -}; - -static struct kobj_type mlog_ktype = { - .default_attrs = mlog_attr_ptrs, - .sysfs_ops = &mlog_attr_ops, -}; - -static struct kset mlog_kset = { - .kobj = {.ktype = &mlog_ktype}, -}; - -int mlog_sys_init(struct kset *o2cb_kset) -{ - int i = 0; - - while (mlog_attrs[i].attr.mode) { - mlog_attr_ptrs[i] = &mlog_attrs[i].attr; - i++; - } - mlog_attr_ptrs[i] = NULL; - - kobject_set_name(&mlog_kset.kobj, "logmask"); - mlog_kset.kobj.kset = o2cb_kset; - return kset_register(&mlog_kset); -} - -void mlog_sys_shutdown(void) -{ - kset_unregister(&mlog_kset); -} diff --git a/drivers/staging/ramster/cluster/masklog.h b/drivers/staging/ramster/cluster/masklog.h deleted file mode 100644 index baa2b9e..0000000 --- a/drivers/staging/ramster/cluster/masklog.h +++ /dev/null @@ -1,219 +0,0 @@ -/* -*- mode: c; c-basic-offset: 8; -*- - * vim: noexpandtab sw=8 ts=8 sts=0: - * - * Copyright (C) 2005 Oracle. All rights reserved. - * - * 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; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 021110-1307, USA. - */ - -#ifndef O2CLUSTER_MASKLOG_H -#define O2CLUSTER_MASKLOG_H - -/* - * For now this is a trivial wrapper around printk() that gives the critical - * ability to enable sets of debugging output at run-time. In the future this - * will almost certainly be redirected to relayfs so that it can pay a - * substantially lower heisenberg tax. - * - * Callers associate the message with a bitmask and a global bitmask is - * maintained with help from /proc. If any of the bits match the message is - * output. - * - * We must have efficient bit tests on i386 and it seems gcc still emits crazy - * code for the 64bit compare. It emits very good code for the dual unsigned - * long tests, though, completely avoiding tests that can never pass if the - * caller gives a constant bitmask that fills one of the longs with all 0s. So - * the desire is to have almost all of the calls decided on by comparing just - * one of the longs. This leads to having infrequently given bits that are - * frequently matched in the high bits. - * - * _ERROR and _NOTICE are used for messages that always go to the console and - * have appropriate KERN_ prefixes. We wrap these in our function instead of - * just calling printk() so that this can eventually make its way through - * relayfs along with the debugging messages. Everything else gets KERN_DEBUG. - * The inline tests and macro dance give GCC the opportunity to quite cleverly - * only emit the appropriage printk() when the caller passes in a constant - * mask, as is almost always the case. - * - * All this bitmask nonsense is managed from the files under - * /sys/fs/o2cb/logmask/. Reading the files gives a straightforward - * indication of which bits are allowed (allow) or denied (off/deny). - * ENTRY deny - * EXIT deny - * TCP off - * MSG off - * SOCKET off - * ERROR allow - * NOTICE allow - * - * Writing changes the state of a given bit and requires a strictly formatted - * single write() call: - * - * write(fd, "allow", 5); - * - * Echoing allow/deny/off string into the logmask files can flip the bits - * on or off as expected; here is the bash script for example: - * - * log_mask="/sys/fs/o2cb/log_mask" - * for node in ENTRY EXIT TCP MSG SOCKET ERROR NOTICE; do - * echo allow >"$log_mask"/"$node" - * done - * - * The debugfs.ocfs2 tool can also flip the bits with the -l option: - * - * debugfs.ocfs2 -l TCP allow - */ - -/* for task_struct */ -#include - -/* bits that are frequently given and infrequently matched in the low word */ -/* NOTE: If you add a flag, you need to also update masklog.c! */ -#define ML_TCP 0x0000000000000001ULL /* net cluster/tcp.c */ -#define ML_MSG 0x0000000000000002ULL /* net network messages */ -#define ML_SOCKET 0x0000000000000004ULL /* net socket lifetime */ -#define ML_HEARTBEAT 0x0000000000000008ULL /* hb all heartbeat tracking */ -#define ML_HB_BIO 0x0000000000000010ULL /* hb io tracing */ -#define ML_DLMFS 0x0000000000000020ULL /* dlm user dlmfs */ -#define ML_DLM 0x0000000000000040ULL /* dlm general debugging */ -#define ML_DLM_DOMAIN 0x0000000000000080ULL /* dlm domain debugging */ -#define ML_DLM_THREAD 0x0000000000000100ULL /* dlm domain thread */ -#define ML_DLM_MASTER 0x0000000000000200ULL /* dlm master functions */ -#define ML_DLM_RECOVERY 0x0000000000000400ULL /* dlm master functions */ -#define ML_DLM_GLUE 0x0000000000000800ULL /* ocfs2 dlm glue layer */ -#define ML_VOTE 0x0000000000001000ULL /* ocfs2 node messaging */ -#define ML_CONN 0x0000000000002000ULL /* net connection management */ -#define ML_QUORUM 0x0000000000004000ULL /* net connection quorum */ -#define ML_BASTS 0x0000000000008000ULL /* dlmglue asts and basts */ -#define ML_CLUSTER 0x0000000000010000ULL /* cluster stack */ - -/* bits that are infrequently given and frequently matched in the high word */ -#define ML_ERROR 0x1000000000000000ULL /* sent to KERN_ERR */ -#define ML_NOTICE 0x2000000000000000ULL /* setn to KERN_NOTICE */ -#define ML_KTHREAD 0x4000000000000000ULL /* kernel thread activity */ - -#define MLOG_INITIAL_AND_MASK (ML_ERROR|ML_NOTICE) -#ifndef MLOG_MASK_PREFIX -#define MLOG_MASK_PREFIX 0 -#endif - -/* - * When logging is disabled, force the bit test to 0 for anything other - * than errors and notices, allowing gcc to remove the code completely. - * When enabled, allow all masks. - */ -#if defined(CONFIG_OCFS2_DEBUG_MASKLOG) -#define ML_ALLOWED_BITS ~0 -#else -#define ML_ALLOWED_BITS (ML_ERROR|ML_NOTICE) -#endif - -#define MLOG_MAX_BITS 64 - -struct mlog_bits { - unsigned long words[MLOG_MAX_BITS / BITS_PER_LONG]; -}; - -extern struct mlog_bits mlog_and_bits, mlog_not_bits; - -#if BITS_PER_LONG == 32 - -#define __mlog_test_u64(mask, bits) \ - ( (u32)(mask & 0xffffffff) & bits.words[0] || \ - ((u64)(mask) >> 32) & bits.words[1] ) -#define __mlog_set_u64(mask, bits) do { \ - bits.words[0] |= (u32)(mask & 0xffffffff); \ - bits.words[1] |= (u64)(mask) >> 32; \ -} while (0) -#define __mlog_clear_u64(mask, bits) do { \ - bits.words[0] &= ~((u32)(mask & 0xffffffff)); \ - bits.words[1] &= ~((u64)(mask) >> 32); \ -} while (0) -#define MLOG_BITS_RHS(mask) { \ - { \ - [0] = (u32)(mask & 0xffffffff), \ - [1] = (u64)(mask) >> 32, \ - } \ -} - -#else /* 32bit long above, 64bit long below */ - -#define __mlog_test_u64(mask, bits) ((mask) & bits.words[0]) -#define __mlog_set_u64(mask, bits) do { \ - bits.words[0] |= (mask); \ -} while (0) -#define __mlog_clear_u64(mask, bits) do { \ - bits.words[0] &= ~(mask); \ -} while (0) -#define MLOG_BITS_RHS(mask) { { (mask) } } - -#endif - -/* - * smp_processor_id() "helpfully" screams when called outside preemptible - * regions in current kernels. sles doesn't have the variants that don't - * scream. just do this instead of trying to guess which we're building - * against.. *sigh*. - */ -#define __mlog_cpu_guess ({ \ - unsigned long _cpu = get_cpu(); \ - put_cpu(); \ - _cpu; \ -}) - -/* In the following two macros, the whitespace after the ',' just - * before ##args is intentional. Otherwise, gcc 2.95 will eat the - * previous token if args expands to nothing. - */ -#define __mlog_printk(level, fmt, args...) \ - printk(level "(%s,%u,%lu):%s:%d " fmt, current->comm, \ - task_pid_nr(current), __mlog_cpu_guess, \ - __PRETTY_FUNCTION__, __LINE__ , ##args) - -#define mlog(mask, fmt, args...) do { \ - u64 __m = MLOG_MASK_PREFIX | (mask); \ - if ((__m & ML_ALLOWED_BITS) && \ - __mlog_test_u64(__m, mlog_and_bits) && \ - !__mlog_test_u64(__m, mlog_not_bits)) { \ - if (__m & ML_ERROR) \ - __mlog_printk(KERN_ERR, "ERROR: "fmt , ##args); \ - else if (__m & ML_NOTICE) \ - __mlog_printk(KERN_NOTICE, fmt , ##args); \ - else __mlog_printk(KERN_INFO, fmt , ##args); \ - } \ -} while (0) - -#define mlog_errno(st) do { \ - int _st = (st); \ - if (_st != -ERESTARTSYS && _st != -EINTR && \ - _st != AOP_TRUNCATED_PAGE && _st != -ENOSPC) \ - mlog(ML_ERROR, "status = %lld\n", (long long)_st); \ -} while (0) - -#define mlog_bug_on_msg(cond, fmt, args...) do { \ - if (cond) { \ - mlog(ML_ERROR, "bug expression: " #cond "\n"); \ - mlog(ML_ERROR, fmt, ##args); \ - BUG(); \ - } \ -} while (0) - -#include -#include -int mlog_sys_init(struct kset *o2cb_subsys); -void mlog_sys_shutdown(void); - -#endif /* O2CLUSTER_MASKLOG_H */ diff --git a/drivers/staging/ramster/cluster/netdebug.c b/drivers/staging/ramster/cluster/netdebug.c deleted file mode 100644 index dc45deb..0000000 --- a/drivers/staging/ramster/cluster/netdebug.c +++ /dev/null @@ -1,579 +0,0 @@ -/* -*- mode: c; c-basic-offset: 8; -*- - * vim: noexpandtab sw=8 ts=8 sts=0: - * - * netdebug.c - * - * debug functionality for o2net - * - * Copyright (C) 2005, 2008 Oracle. All rights reserved. - * - * 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; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 021110-1307, USA. - * - */ - -#ifdef CONFIG_DEBUG_FS - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "tcp.h" -#include "nodemanager.h" -#define MLOG_MASK_PREFIX ML_TCP -#include "masklog.h" - -#include "tcp_internal.h" - -#define O2NET_DEBUG_DIR "o2net" -#define SC_DEBUG_NAME "sock_containers" -#define NST_DEBUG_NAME "send_tracking" -#define STATS_DEBUG_NAME "stats" -#define NODES_DEBUG_NAME "connected_nodes" - -#define SHOW_SOCK_CONTAINERS 0 -#define SHOW_SOCK_STATS 1 - -static struct dentry *o2net_dentry; -static struct dentry *sc_dentry; -static struct dentry *nst_dentry; -static struct dentry *stats_dentry; -static struct dentry *nodes_dentry; - -static DEFINE_SPINLOCK(o2net_debug_lock); - -static LIST_HEAD(sock_containers); -static LIST_HEAD(send_tracking); - -void o2net_debug_add_nst(struct o2net_send_tracking *nst) -{ - spin_lock(&o2net_debug_lock); - list_add(&nst->st_net_debug_item, &send_tracking); - spin_unlock(&o2net_debug_lock); -} - -void o2net_debug_del_nst(struct o2net_send_tracking *nst) -{ - spin_lock(&o2net_debug_lock); - if (!list_empty(&nst->st_net_debug_item)) - list_del_init(&nst->st_net_debug_item); - spin_unlock(&o2net_debug_lock); -} - -static struct o2net_send_tracking - *next_nst(struct o2net_send_tracking *nst_start) -{ - struct o2net_send_tracking *nst, *ret = NULL; - - assert_spin_locked(&o2net_debug_lock); - - list_for_each_entry(nst, &nst_start->st_net_debug_item, - st_net_debug_item) { - /* discover the head of the list */ - if (&nst->st_net_debug_item == &send_tracking) - break; - - /* use st_task to detect real nsts in the list */ - if (nst->st_task != NULL) { - ret = nst; - break; - } - } - - return ret; -} - -static void *nst_seq_start(struct seq_file *seq, loff_t *pos) -{ - struct o2net_send_tracking *nst, *dummy_nst = seq->private; - - spin_lock(&o2net_debug_lock); - nst = next_nst(dummy_nst); - spin_unlock(&o2net_debug_lock); - - return nst; -} - -static void *nst_seq_next(struct seq_file *seq, void *v, loff_t *pos) -{ - struct o2net_send_tracking *nst, *dummy_nst = seq->private; - - spin_lock(&o2net_debug_lock); - nst = next_nst(dummy_nst); - list_del_init(&dummy_nst->st_net_debug_item); - if (nst) - list_add(&dummy_nst->st_net_debug_item, - &nst->st_net_debug_item); - spin_unlock(&o2net_debug_lock); - - return nst; /* unused, just needs to be null when done */ -} - -static int nst_seq_show(struct seq_file *seq, void *v) -{ - struct o2net_send_tracking *nst, *dummy_nst = seq->private; - ktime_t now; - s64 sock, send, status; - - spin_lock(&o2net_debug_lock); - nst = next_nst(dummy_nst); - if (!nst) - goto out; - - now = ktime_get(); - sock = ktime_to_us(ktime_sub(now, nst->st_sock_time)); - send = ktime_to_us(ktime_sub(now, nst->st_send_time)); - status = ktime_to_us(ktime_sub(now, nst->st_status_time)); - - /* get_task_comm isn't exported. oh well. */ - seq_printf(seq, "%p:\n" - " pid: %lu\n" - " tgid: %lu\n" - " process name: %s\n" - " node: %u\n" - " sc: %p\n" - " message id: %d\n" - " message type: %u\n" - " message key: 0x%08x\n" - " sock acquiry: %lld usecs ago\n" - " send start: %lld usecs ago\n" - " wait start: %lld usecs ago\n", - nst, (unsigned long)task_pid_nr(nst->st_task), - (unsigned long)nst->st_task->tgid, - nst->st_task->comm, nst->st_node, - nst->st_sc, nst->st_id, nst->st_msg_type, - nst->st_msg_key, - (long long)sock, - (long long)send, - (long long)status); - -out: - spin_unlock(&o2net_debug_lock); - - return 0; -} - -static void nst_seq_stop(struct seq_file *seq, void *v) -{ -} - -static const struct seq_operations nst_seq_ops = { - .start = nst_seq_start, - .next = nst_seq_next, - .stop = nst_seq_stop, - .show = nst_seq_show, -}; - -static int nst_fop_open(struct inode *inode, struct file *file) -{ - struct o2net_send_tracking *dummy_nst; - struct seq_file *seq; - int ret; - - dummy_nst = kmalloc(sizeof(struct o2net_send_tracking), GFP_KERNEL); - if (dummy_nst == NULL) { - ret = -ENOMEM; - goto out; - } - dummy_nst->st_task = NULL; - - ret = seq_open(file, &nst_seq_ops); - if (ret) - goto out; - - seq = file->private_data; - seq->private = dummy_nst; - o2net_debug_add_nst(dummy_nst); - - dummy_nst = NULL; - -out: - kfree(dummy_nst); - return ret; -} - -static int nst_fop_release(struct inode *inode, struct file *file) -{ - struct seq_file *seq = file->private_data; - struct o2net_send_tracking *dummy_nst = seq->private; - - o2net_debug_del_nst(dummy_nst); - return seq_release_private(inode, file); -} - -static const struct file_operations nst_seq_fops = { - .open = nst_fop_open, - .read = seq_read, - .llseek = seq_lseek, - .release = nst_fop_release, -}; - -void o2net_debug_add_sc(struct o2net_sock_container *sc) -{ - spin_lock(&o2net_debug_lock); - list_add(&sc->sc_net_debug_item, &sock_containers); - spin_unlock(&o2net_debug_lock); -} - -void o2net_debug_del_sc(struct o2net_sock_container *sc) -{ - spin_lock(&o2net_debug_lock); - list_del_init(&sc->sc_net_debug_item); - spin_unlock(&o2net_debug_lock); -} - -struct o2net_sock_debug { - int dbg_ctxt; - struct o2net_sock_container *dbg_sock; -}; - -static struct o2net_sock_container - *next_sc(struct o2net_sock_container *sc_start) -{ - struct o2net_sock_container *sc, *ret = NULL; - - assert_spin_locked(&o2net_debug_lock); - - list_for_each_entry(sc, &sc_start->sc_net_debug_item, - sc_net_debug_item) { - /* discover the head of the list miscast as a sc */ - if (&sc->sc_net_debug_item == &sock_containers) - break; - - /* use sc_page to detect real scs in the list */ - if (sc->sc_page != NULL) { - ret = sc; - break; - } - } - - return ret; -} - -static void *sc_seq_start(struct seq_file *seq, loff_t *pos) -{ - struct o2net_sock_debug *sd = seq->private; - struct o2net_sock_container *sc, *dummy_sc = sd->dbg_sock; - - spin_lock(&o2net_debug_lock); - sc = next_sc(dummy_sc); - spin_unlock(&o2net_debug_lock); - - return sc; -} - -static void *sc_seq_next(struct seq_file *seq, void *v, loff_t *pos) -{ - struct o2net_sock_debug *sd = seq->private; - struct o2net_sock_container *sc, *dummy_sc = sd->dbg_sock; - - spin_lock(&o2net_debug_lock); - sc = next_sc(dummy_sc); - list_del_init(&dummy_sc->sc_net_debug_item); - if (sc) - list_add(&dummy_sc->sc_net_debug_item, &sc->sc_net_debug_item); - spin_unlock(&o2net_debug_lock); - - return sc; /* unused, just needs to be null when done */ -} - -#ifdef CONFIG_OCFS2_FS_STATS -# define sc_send_count(_s) ((_s)->sc_send_count) -# define sc_recv_count(_s) ((_s)->sc_recv_count) -# define sc_tv_acquiry_total_ns(_s) (ktime_to_ns((_s)->sc_tv_acquiry_total)) -# define sc_tv_send_total_ns(_s) (ktime_to_ns((_s)->sc_tv_send_total)) -# define sc_tv_status_total_ns(_s) (ktime_to_ns((_s)->sc_tv_status_total)) -# define sc_tv_process_total_ns(_s) (ktime_to_ns((_s)->sc_tv_process_total)) -#else -# define sc_send_count(_s) (0U) -# define sc_recv_count(_s) (0U) -# define sc_tv_acquiry_total_ns(_s) (0LL) -# define sc_tv_send_total_ns(_s) (0LL) -# define sc_tv_status_total_ns(_s) (0LL) -# define sc_tv_process_total_ns(_s) (0LL) -#endif - -/* So that debugfs.ocfs2 can determine which format is being used */ -#define O2NET_STATS_STR_VERSION 1 -static void sc_show_sock_stats(struct seq_file *seq, - struct o2net_sock_container *sc) -{ - if (!sc) - return; - - seq_printf(seq, "%d,%u,%lu,%lld,%lld,%lld,%lu,%lld\n", O2NET_STATS_STR_VERSION, - sc->sc_node->nd_num, (unsigned long)sc_send_count(sc), - (long long)sc_tv_acquiry_total_ns(sc), - (long long)sc_tv_send_total_ns(sc), - (long long)sc_tv_status_total_ns(sc), - (unsigned long)sc_recv_count(sc), - (long long)sc_tv_process_total_ns(sc)); -} - -static void sc_show_sock_container(struct seq_file *seq, - struct o2net_sock_container *sc) -{ - struct inet_sock *inet = NULL; - __be32 saddr = 0, daddr = 0; - __be16 sport = 0, dport = 0; - - if (!sc) - return; - - if (sc->sc_sock) { - inet = inet_sk(sc->sc_sock->sk); - /* the stack's structs aren't sparse endian clean */ - saddr = (__force __be32)inet->inet_saddr; - daddr = (__force __be32)inet->inet_daddr; - sport = (__force __be16)inet->inet_sport; - dport = (__force __be16)inet->inet_dport; - } - - /* XXX sigh, inet-> doesn't have sparse annotation so any - * use of it here generates a warning with -Wbitwise */ - seq_printf(seq, "%p:\n" - " krefs: %d\n" - " sock: %pI4:%u -> " - "%pI4:%u\n" - " remote node: %s\n" - " page off: %zu\n" - " handshake ok: %u\n" - " timer: %lld usecs\n" - " data ready: %lld usecs\n" - " advance start: %lld usecs\n" - " advance stop: %lld usecs\n" - " func start: %lld usecs\n" - " func stop: %lld usecs\n" - " func key: 0x%08x\n" - " func type: %u\n", - sc, - atomic_read(&sc->sc_kref.refcount), - &saddr, inet ? ntohs(sport) : 0, - &daddr, inet ? ntohs(dport) : 0, - sc->sc_node->nd_name, - sc->sc_page_off, - sc->sc_handshake_ok, - (long long)ktime_to_us(sc->sc_tv_timer), - (long long)ktime_to_us(sc->sc_tv_data_ready), - (long long)ktime_to_us(sc->sc_tv_advance_start), - (long long)ktime_to_us(sc->sc_tv_advance_stop), - (long long)ktime_to_us(sc->sc_tv_func_start), - (long long)ktime_to_us(sc->sc_tv_func_stop), - sc->sc_msg_key, - sc->sc_msg_type); -} - -static int sc_seq_show(struct seq_file *seq, void *v) -{ - struct o2net_sock_debug *sd = seq->private; - struct o2net_sock_container *sc, *dummy_sc = sd->dbg_sock; - - spin_lock(&o2net_debug_lock); - sc = next_sc(dummy_sc); - - if (sc) { - if (sd->dbg_ctxt == SHOW_SOCK_CONTAINERS) - sc_show_sock_container(seq, sc); - else - sc_show_sock_stats(seq, sc); - } - - spin_unlock(&o2net_debug_lock); - - return 0; -} - -static void sc_seq_stop(struct seq_file *seq, void *v) -{ -} - -static const struct seq_operations sc_seq_ops = { - .start = sc_seq_start, - .next = sc_seq_next, - .stop = sc_seq_stop, - .show = sc_seq_show, -}; - -static int sc_common_open(struct file *file, struct o2net_sock_debug *sd) -{ - struct o2net_sock_container *dummy_sc; - struct seq_file *seq; - int ret; - - dummy_sc = kmalloc(sizeof(struct o2net_sock_container), GFP_KERNEL); - if (dummy_sc == NULL) { - ret = -ENOMEM; - goto out; - } - dummy_sc->sc_page = NULL; - - ret = seq_open(file, &sc_seq_ops); - if (ret) - goto out; - - seq = file->private_data; - seq->private = sd; - sd->dbg_sock = dummy_sc; - o2net_debug_add_sc(dummy_sc); - - dummy_sc = NULL; - -out: - kfree(dummy_sc); - return ret; -} - -static int sc_fop_release(struct inode *inode, struct file *file) -{ - struct seq_file *seq = file->private_data; - struct o2net_sock_debug *sd = seq->private; - struct o2net_sock_container *dummy_sc = sd->dbg_sock; - - o2net_debug_del_sc(dummy_sc); - return seq_release_private(inode, file); -} - -static int stats_fop_open(struct inode *inode, struct file *file) -{ - struct o2net_sock_debug *sd; - - sd = kmalloc(sizeof(struct o2net_sock_debug), GFP_KERNEL); - if (sd == NULL) - return -ENOMEM; - - sd->dbg_ctxt = SHOW_SOCK_STATS; - sd->dbg_sock = NULL; - - return sc_common_open(file, sd); -} - -static const struct file_operations stats_seq_fops = { - .open = stats_fop_open, - .read = seq_read, - .llseek = seq_lseek, - .release = sc_fop_release, -}; - -static int sc_fop_open(struct inode *inode, struct file *file) -{ - struct o2net_sock_debug *sd; - - sd = kmalloc(sizeof(struct o2net_sock_debug), GFP_KERNEL); - if (sd == NULL) - return -ENOMEM; - - sd->dbg_ctxt = SHOW_SOCK_CONTAINERS; - sd->dbg_sock = NULL; - - return sc_common_open(file, sd); -} - -static const struct file_operations sc_seq_fops = { - .open = sc_fop_open, - .read = seq_read, - .llseek = seq_lseek, - .release = sc_fop_release, -}; - -static int o2net_fill_bitmap(char *buf, int len) -{ - unsigned long map[BITS_TO_LONGS(O2NM_MAX_NODES)]; - int i = -1, out = 0; - - o2net_fill_node_map(map, sizeof(map)); - - while ((i = find_next_bit(map, O2NM_MAX_NODES, i + 1)) < O2NM_MAX_NODES) - out += snprintf(buf + out, PAGE_SIZE - out, "%d ", i); - out += snprintf(buf + out, PAGE_SIZE - out, "\n"); - - return out; -} - -static int nodes_fop_open(struct inode *inode, struct file *file) -{ - char *buf; - - buf = kmalloc(PAGE_SIZE, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - i_size_write(inode, o2net_fill_bitmap(buf, PAGE_SIZE)); - - file->private_data = buf; - - return 0; -} - -static int o2net_debug_release(struct inode *inode, struct file *file) -{ - kfree(file->private_data); - return 0; -} - -static ssize_t o2net_debug_read(struct file *file, char __user *buf, - size_t nbytes, loff_t *ppos) -{ - return simple_read_from_buffer(buf, nbytes, ppos, file->private_data, - i_size_read(file->f_mapping->host)); -} - -static const struct file_operations nodes_fops = { - .open = nodes_fop_open, - .release = o2net_debug_release, - .read = o2net_debug_read, - .llseek = generic_file_llseek, -}; - -void o2net_debugfs_exit(void) -{ - debugfs_remove(nodes_dentry); - debugfs_remove(stats_dentry); - debugfs_remove(sc_dentry); - debugfs_remove(nst_dentry); - debugfs_remove(o2net_dentry); -} - -int o2net_debugfs_init(void) -{ - mode_t mode = S_IFREG|S_IRUSR; - - o2net_dentry = debugfs_create_dir(O2NET_DEBUG_DIR, NULL); - if (o2net_dentry) - nst_dentry = debugfs_create_file(NST_DEBUG_NAME, mode, - o2net_dentry, NULL, &nst_seq_fops); - if (nst_dentry) - sc_dentry = debugfs_create_file(SC_DEBUG_NAME, mode, - o2net_dentry, NULL, &sc_seq_fops); - if (sc_dentry) - stats_dentry = debugfs_create_file(STATS_DEBUG_NAME, mode, - o2net_dentry, NULL, &stats_seq_fops); - if (stats_dentry) - nodes_dentry = debugfs_create_file(NODES_DEBUG_NAME, mode, - o2net_dentry, NULL, &nodes_fops); - if (nodes_dentry) - return 0; - - o2net_debugfs_exit(); - mlog_errno(-ENOMEM); - return -ENOMEM; -} - -#endif /* CONFIG_DEBUG_FS */ diff --git a/drivers/staging/ramster/cluster/nodemanager.c b/drivers/staging/ramster/cluster/nodemanager.c deleted file mode 100644 index bb24064..0000000 --- a/drivers/staging/ramster/cluster/nodemanager.c +++ /dev/null @@ -1,989 +0,0 @@ -/* -*- mode: c; c-basic-offset: 8; -*- - * vim: noexpandtab sw=8 ts=8 sts=0: - * - * Copyright (C) 2004, 2005 Oracle. All rights reserved. - * - * 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; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 021110-1307, USA. - */ - -#include -#include -#include -#include - -#include "tcp.h" -#include "nodemanager.h" -#include "heartbeat.h" -#include "masklog.h" -#include "sys.h" -#include "ver.h" - -/* for now we operate under the assertion that there can be only one - * cluster active at a time. Changing this will require trickling - * cluster references throughout where nodes are looked up */ -struct o2nm_cluster *o2nm_single_cluster = NULL; - -char *o2nm_fence_method_desc[O2NM_FENCE_METHODS] = { - "reset", /* O2NM_FENCE_RESET */ - "panic", /* O2NM_FENCE_PANIC */ -}; - -struct o2nm_node *o2nm_get_node_by_num(u8 node_num) -{ - struct o2nm_node *node = NULL; - - if (node_num >= O2NM_MAX_NODES || o2nm_single_cluster == NULL) - goto out; - - read_lock(&o2nm_single_cluster->cl_nodes_lock); - node = o2nm_single_cluster->cl_nodes[node_num]; - if (node) - config_item_get(&node->nd_item); - read_unlock(&o2nm_single_cluster->cl_nodes_lock); -out: - return node; -} -EXPORT_SYMBOL_GPL(o2nm_get_node_by_num); - -int o2nm_configured_node_map(unsigned long *map, unsigned bytes) -{ - struct o2nm_cluster *cluster = o2nm_single_cluster; - - BUG_ON(bytes < (sizeof(cluster->cl_nodes_bitmap))); - - if (cluster == NULL) - return -EINVAL; - - read_lock(&cluster->cl_nodes_lock); - memcpy(map, cluster->cl_nodes_bitmap, sizeof(cluster->cl_nodes_bitmap)); - read_unlock(&cluster->cl_nodes_lock); - - return 0; -} -EXPORT_SYMBOL_GPL(o2nm_configured_node_map); - -static struct o2nm_node *o2nm_node_ip_tree_lookup(struct o2nm_cluster *cluster, - __be32 ip_needle, - struct rb_node ***ret_p, - struct rb_node **ret_parent) -{ - struct rb_node **p = &cluster->cl_node_ip_tree.rb_node; - struct rb_node *parent = NULL; - struct o2nm_node *node, *ret = NULL; - - while (*p) { - int cmp; - - parent = *p; - node = rb_entry(parent, struct o2nm_node, nd_ip_node); - - cmp = memcmp(&ip_needle, &node->nd_ipv4_address, - sizeof(ip_needle)); - if (cmp < 0) - p = &(*p)->rb_left; - else if (cmp > 0) - p = &(*p)->rb_right; - else { - ret = node; - break; - } - } - - if (ret_p != NULL) - *ret_p = p; - if (ret_parent != NULL) - *ret_parent = parent; - - return ret; -} - -struct o2nm_node *o2nm_get_node_by_ip(__be32 addr) -{ - struct o2nm_node *node = NULL; - struct o2nm_cluster *cluster = o2nm_single_cluster; - - if (cluster == NULL) - goto out; - - read_lock(&cluster->cl_nodes_lock); - node = o2nm_node_ip_tree_lookup(cluster, addr, NULL, NULL); - if (node) - config_item_get(&node->nd_item); - read_unlock(&cluster->cl_nodes_lock); - -out: - return node; -} -EXPORT_SYMBOL_GPL(o2nm_get_node_by_ip); - -void o2nm_node_put(struct o2nm_node *node) -{ - config_item_put(&node->nd_item); -} -EXPORT_SYMBOL_GPL(o2nm_node_put); - -void o2nm_node_get(struct o2nm_node *node) -{ - config_item_get(&node->nd_item); -} -EXPORT_SYMBOL_GPL(o2nm_node_get); - -u8 o2nm_this_node(void) -{ - u8 node_num = O2NM_MAX_NODES; - - if (o2nm_single_cluster && o2nm_single_cluster->cl_has_local) - node_num = o2nm_single_cluster->cl_local_node; - - return node_num; -} -EXPORT_SYMBOL_GPL(o2nm_this_node); - -/* node configfs bits */ - -static struct o2nm_cluster *to_o2nm_cluster(struct config_item *item) -{ - return item ? - container_of(to_config_group(item), struct o2nm_cluster, - cl_group) - : NULL; -} - -static struct o2nm_node *to_o2nm_node(struct config_item *item) -{ - return item ? container_of(item, struct o2nm_node, nd_item) : NULL; -} - -static void o2nm_node_release(struct config_item *item) -{ - struct o2nm_node *node = to_o2nm_node(item); - kfree(node); -} - -static ssize_t o2nm_node_num_read(struct o2nm_node *node, char *page) -{ - return sprintf(page, "%d\n", node->nd_num); -} - -static struct o2nm_cluster *to_o2nm_cluster_from_node(struct o2nm_node *node) -{ - /* through the first node_set .parent - * mycluster/nodes/mynode == o2nm_cluster->o2nm_node_group->o2nm_node */ - return to_o2nm_cluster(node->nd_item.ci_parent->ci_parent); -} - -enum { - O2NM_NODE_ATTR_NUM = 0, - O2NM_NODE_ATTR_PORT, - O2NM_NODE_ATTR_ADDRESS, - O2NM_NODE_ATTR_LOCAL, -}; - -static ssize_t o2nm_node_num_write(struct o2nm_node *node, const char *page, - size_t count) -{ - struct o2nm_cluster *cluster = to_o2nm_cluster_from_node(node); - unsigned long tmp; - char *p = (char *)page; - - tmp = simple_strtoul(p, &p, 0); - if (!p || (*p && (*p != '\n'))) - return -EINVAL; - - if (tmp >= O2NM_MAX_NODES) - return -ERANGE; - - /* once we're in the cl_nodes tree networking can look us up by - * node number and try to use our address and port attributes - * to connect to this node.. make sure that they've been set - * before writing the node attribute? */ - if (!test_bit(O2NM_NODE_ATTR_ADDRESS, &node->nd_set_attributes) || - !test_bit(O2NM_NODE_ATTR_PORT, &node->nd_set_attributes)) - return -EINVAL; /* XXX */ - - write_lock(&cluster->cl_nodes_lock); - if (cluster->cl_nodes[tmp]) - p = NULL; - else { - cluster->cl_nodes[tmp] = node; - node->nd_num = tmp; - set_bit(tmp, cluster->cl_nodes_bitmap); - } - write_unlock(&cluster->cl_nodes_lock); - if (p == NULL) - return -EEXIST; - - return count; -} -static ssize_t o2nm_node_ipv4_port_read(struct o2nm_node *node, char *page) -{ - return sprintf(page, "%u\n", ntohs(node->nd_ipv4_port)); -} - -static ssize_t o2nm_node_ipv4_port_write(struct o2nm_node *node, - const char *page, size_t count) -{ - unsigned long tmp; - char *p = (char *)page; - - tmp = simple_strtoul(p, &p, 0); - if (!p || (*p && (*p != '\n'))) - return -EINVAL; - - if (tmp == 0) - return -EINVAL; - if (tmp >= (u16)-1) - return -ERANGE; - - node->nd_ipv4_port = htons(tmp); - - return count; -} - -static ssize_t o2nm_node_ipv4_address_read(struct o2nm_node *node, char *page) -{ - return sprintf(page, "%pI4\n", &node->nd_ipv4_address); -} - -static ssize_t o2nm_node_ipv4_address_write(struct o2nm_node *node, - const char *page, - size_t count) -{ - struct o2nm_cluster *cluster = to_o2nm_cluster_from_node(node); - int ret, i; - struct rb_node **p, *parent; - unsigned int octets[4]; - __be32 ipv4_addr = 0; - - ret = sscanf(page, "%3u.%3u.%3u.%3u", &octets[3], &octets[2], - &octets[1], &octets[0]); - if (ret != 4) - return -EINVAL; - - for (i = 0; i < ARRAY_SIZE(octets); i++) { - if (octets[i] > 255) - return -ERANGE; - be32_add_cpu(&ipv4_addr, octets[i] << (i * 8)); - } - - ret = 0; - write_lock(&cluster->cl_nodes_lock); - if (o2nm_node_ip_tree_lookup(cluster, ipv4_addr, &p, &parent)) - ret = -EEXIST; - else { - rb_link_node(&node->nd_ip_node, parent, p); - rb_insert_color(&node->nd_ip_node, &cluster->cl_node_ip_tree); - } - write_unlock(&cluster->cl_nodes_lock); - if (ret) - return ret; - - memcpy(&node->nd_ipv4_address, &ipv4_addr, sizeof(ipv4_addr)); - - return count; -} - -static ssize_t o2nm_node_local_read(struct o2nm_node *node, char *page) -{ - return sprintf(page, "%d\n", node->nd_local); -} - -static ssize_t o2nm_node_local_write(struct o2nm_node *node, const char *page, - size_t count) -{ - struct o2nm_cluster *cluster = to_o2nm_cluster_from_node(node); - unsigned long tmp; - char *p = (char *)page; - ssize_t ret; - - tmp = simple_strtoul(p, &p, 0); - if (!p || (*p && (*p != '\n'))) - return -EINVAL; - - tmp = !!tmp; /* boolean of whether this node wants to be local */ - - /* setting local turns on networking rx for now so we require having - * set everything else first */ - if (!test_bit(O2NM_NODE_ATTR_ADDRESS, &node->nd_set_attributes) || - !test_bit(O2NM_NODE_ATTR_NUM, &node->nd_set_attributes) || - !test_bit(O2NM_NODE_ATTR_PORT, &node->nd_set_attributes)) - return -EINVAL; /* XXX */ - - /* the only failure case is trying to set a new local node - * when a different one is already set */ - if (tmp && tmp == cluster->cl_has_local && - cluster->cl_local_node != node->nd_num) - return -EBUSY; - - /* bring up the rx thread if we're setting the new local node. */ - if (tmp && !cluster->cl_has_local) { - ret = o2net_start_listening(node); - if (ret) - return ret; - } - - if (!tmp && cluster->cl_has_local && - cluster->cl_local_node == node->nd_num) { - o2net_stop_listening(node); - cluster->cl_local_node = O2NM_INVALID_NODE_NUM; - } - - node->nd_local = tmp; - if (node->nd_local) { - cluster->cl_has_local = tmp; - cluster->cl_local_node = node->nd_num; - } - - return count; -} - -struct o2nm_node_attribute { - struct configfs_attribute attr; - ssize_t (*show)(struct o2nm_node *, char *); - ssize_t (*store)(struct o2nm_node *, const char *, size_t); -}; - -static struct o2nm_node_attribute o2nm_node_attr_num = { - .attr = { .ca_owner = THIS_MODULE, - .ca_name = "num", - .ca_mode = S_IRUGO | S_IWUSR }, - .show = o2nm_node_num_read, - .store = o2nm_node_num_write, -}; - -static struct o2nm_node_attribute o2nm_node_attr_ipv4_port = { - .attr = { .ca_owner = THIS_MODULE, - .ca_name = "ipv4_port", - .ca_mode = S_IRUGO | S_IWUSR }, - .show = o2nm_node_ipv4_port_read, - .store = o2nm_node_ipv4_port_write, -}; - -static struct o2nm_node_attribute o2nm_node_attr_ipv4_address = { - .attr = { .ca_owner = THIS_MODULE, - .ca_name = "ipv4_address", - .ca_mode = S_IRUGO | S_IWUSR }, - .show = o2nm_node_ipv4_address_read, - .store = o2nm_node_ipv4_address_write, -}; - -static struct o2nm_node_attribute o2nm_node_attr_local = { - .attr = { .ca_owner = THIS_MODULE, - .ca_name = "local", - .ca_mode = S_IRUGO | S_IWUSR }, - .show = o2nm_node_local_read, - .store = o2nm_node_local_write, -}; - -static struct configfs_attribute *o2nm_node_attrs[] = { - [O2NM_NODE_ATTR_NUM] = &o2nm_node_attr_num.attr, - [O2NM_NODE_ATTR_PORT] = &o2nm_node_attr_ipv4_port.attr, - [O2NM_NODE_ATTR_ADDRESS] = &o2nm_node_attr_ipv4_address.attr, - [O2NM_NODE_ATTR_LOCAL] = &o2nm_node_attr_local.attr, - NULL, -}; - -static int o2nm_attr_index(struct configfs_attribute *attr) -{ - int i; - for (i = 0; i < ARRAY_SIZE(o2nm_node_attrs); i++) { - if (attr == o2nm_node_attrs[i]) - return i; - } - BUG(); - return 0; -} - -static ssize_t o2nm_node_show(struct config_item *item, - struct configfs_attribute *attr, - char *page) -{ - struct o2nm_node *node = to_o2nm_node(item); - struct o2nm_node_attribute *o2nm_node_attr = - container_of(attr, struct o2nm_node_attribute, attr); - ssize_t ret = 0; - - if (o2nm_node_attr->show) - ret = o2nm_node_attr->show(node, page); - return ret; -} - -static ssize_t o2nm_node_store(struct config_item *item, - struct configfs_attribute *attr, - const char *page, size_t count) -{ - struct o2nm_node *node = to_o2nm_node(item); - struct o2nm_node_attribute *o2nm_node_attr = - container_of(attr, struct o2nm_node_attribute, attr); - ssize_t ret; - int attr_index = o2nm_attr_index(attr); - - if (o2nm_node_attr->store == NULL) { - ret = -EINVAL; - goto out; - } - - if (test_bit(attr_index, &node->nd_set_attributes)) - return -EBUSY; - - ret = o2nm_node_attr->store(node, page, count); - if (ret < count) - goto out; - - set_bit(attr_index, &node->nd_set_attributes); -out: - return ret; -} - -static struct configfs_item_operations o2nm_node_item_ops = { - .release = o2nm_node_release, - .show_attribute = o2nm_node_show, - .store_attribute = o2nm_node_store, -}; - -static struct config_item_type o2nm_node_type = { - .ct_item_ops = &o2nm_node_item_ops, - .ct_attrs = o2nm_node_attrs, - .ct_owner = THIS_MODULE, -}; - -/* node set */ - -struct o2nm_node_group { - struct config_group ns_group; - /* some stuff? */ -}; - -#if 0 -static struct o2nm_node_group *to_o2nm_node_group(struct config_group *group) -{ - return group ? - container_of(group, struct o2nm_node_group, ns_group) - : NULL; -} -#endif - -struct o2nm_cluster_attribute { - struct configfs_attribute attr; - ssize_t (*show)(struct o2nm_cluster *, char *); - ssize_t (*store)(struct o2nm_cluster *, const char *, size_t); -}; - -static ssize_t o2nm_cluster_attr_write(const char *page, ssize_t count, - unsigned int *val) -{ - unsigned long tmp; - char *p = (char *)page; - - tmp = simple_strtoul(p, &p, 0); - if (!p || (*p && (*p != '\n'))) - return -EINVAL; - - if (tmp == 0) - return -EINVAL; - if (tmp >= (u32)-1) - return -ERANGE; - - *val = tmp; - - return count; -} - -static ssize_t o2nm_cluster_attr_idle_timeout_ms_read( - struct o2nm_cluster *cluster, char *page) -{ - return sprintf(page, "%u\n", cluster->cl_idle_timeout_ms); -} - -static ssize_t o2nm_cluster_attr_idle_timeout_ms_write( - struct o2nm_cluster *cluster, const char *page, size_t count) -{ - ssize_t ret; - unsigned int val; - - ret = o2nm_cluster_attr_write(page, count, &val); - - if (ret > 0) { - if (cluster->cl_idle_timeout_ms != val - && o2net_num_connected_peers()) { - mlog(ML_NOTICE, - "o2net: cannot change idle timeout after " - "the first peer has agreed to it." - " %d connected peers\n", - o2net_num_connected_peers()); - ret = -EINVAL; - } else if (val <= cluster->cl_keepalive_delay_ms) { - mlog(ML_NOTICE, "o2net: idle timeout must be larger " - "than keepalive delay\n"); - ret = -EINVAL; - } else { - cluster->cl_idle_timeout_ms = val; - } - } - - return ret; -} - -static ssize_t o2nm_cluster_attr_keepalive_delay_ms_read( - struct o2nm_cluster *cluster, char *page) -{ - return sprintf(page, "%u\n", cluster->cl_keepalive_delay_ms); -} - -static ssize_t o2nm_cluster_attr_keepalive_delay_ms_write( - struct o2nm_cluster *cluster, const char *page, size_t count) -{ - ssize_t ret; - unsigned int val; - - ret = o2nm_cluster_attr_write(page, count, &val); - - if (ret > 0) { - if (cluster->cl_keepalive_delay_ms != val - && o2net_num_connected_peers()) { - mlog(ML_NOTICE, - "o2net: cannot change keepalive delay after" - " the first peer has agreed to it." - " %d connected peers\n", - o2net_num_connected_peers()); - ret = -EINVAL; - } else if (val >= cluster->cl_idle_timeout_ms) { - mlog(ML_NOTICE, "o2net: keepalive delay must be " - "smaller than idle timeout\n"); - ret = -EINVAL; - } else { - cluster->cl_keepalive_delay_ms = val; - } - } - - return ret; -} - -static ssize_t o2nm_cluster_attr_reconnect_delay_ms_read( - struct o2nm_cluster *cluster, char *page) -{ - return sprintf(page, "%u\n", cluster->cl_reconnect_delay_ms); -} - -static ssize_t o2nm_cluster_attr_reconnect_delay_ms_write( - struct o2nm_cluster *cluster, const char *page, size_t count) -{ - return o2nm_cluster_attr_write(page, count, - &cluster->cl_reconnect_delay_ms); -} - -static ssize_t o2nm_cluster_attr_fence_method_read( - struct o2nm_cluster *cluster, char *page) -{ - ssize_t ret = 0; - - if (cluster) - ret = sprintf(page, "%s\n", - o2nm_fence_method_desc[cluster->cl_fence_method]); - return ret; -} - -static ssize_t o2nm_cluster_attr_fence_method_write( - struct o2nm_cluster *cluster, const char *page, size_t count) -{ - unsigned int i; - - if (page[count - 1] != '\n') - goto bail; - - for (i = 0; i < O2NM_FENCE_METHODS; ++i) { - if (count != strlen(o2nm_fence_method_desc[i]) + 1) - continue; - if (strncasecmp(page, o2nm_fence_method_desc[i], count - 1)) - continue; - if (cluster->cl_fence_method != i) { - printk(KERN_INFO "ocfs2: Changing fence method to %s\n", - o2nm_fence_method_desc[i]); - cluster->cl_fence_method = i; - } - return count; - } - -bail: - return -EINVAL; -} - -static struct o2nm_cluster_attribute o2nm_cluster_attr_idle_timeout_ms = { - .attr = { .ca_owner = THIS_MODULE, - .ca_name = "idle_timeout_ms", - .ca_mode = S_IRUGO | S_IWUSR }, - .show = o2nm_cluster_attr_idle_timeout_ms_read, - .store = o2nm_cluster_attr_idle_timeout_ms_write, -}; - -static struct o2nm_cluster_attribute o2nm_cluster_attr_keepalive_delay_ms = { - .attr = { .ca_owner = THIS_MODULE, - .ca_name = "keepalive_delay_ms", - .ca_mode = S_IRUGO | S_IWUSR }, - .show = o2nm_cluster_attr_keepalive_delay_ms_read, - .store = o2nm_cluster_attr_keepalive_delay_ms_write, -}; - -static struct o2nm_cluster_attribute o2nm_cluster_attr_reconnect_delay_ms = { - .attr = { .ca_owner = THIS_MODULE, - .ca_name = "reconnect_delay_ms", - .ca_mode = S_IRUGO | S_IWUSR }, - .show = o2nm_cluster_attr_reconnect_delay_ms_read, - .store = o2nm_cluster_attr_reconnect_delay_ms_write, -}; - -static struct o2nm_cluster_attribute o2nm_cluster_attr_fence_method = { - .attr = { .ca_owner = THIS_MODULE, - .ca_name = "fence_method", - .ca_mode = S_IRUGO | S_IWUSR }, - .show = o2nm_cluster_attr_fence_method_read, - .store = o2nm_cluster_attr_fence_method_write, -}; - -static struct configfs_attribute *o2nm_cluster_attrs[] = { - &o2nm_cluster_attr_idle_timeout_ms.attr, - &o2nm_cluster_attr_keepalive_delay_ms.attr, - &o2nm_cluster_attr_reconnect_delay_ms.attr, - &o2nm_cluster_attr_fence_method.attr, - NULL, -}; -static ssize_t o2nm_cluster_show(struct config_item *item, - struct configfs_attribute *attr, - char *page) -{ - struct o2nm_cluster *cluster = to_o2nm_cluster(item); - struct o2nm_cluster_attribute *o2nm_cluster_attr = - container_of(attr, struct o2nm_cluster_attribute, attr); - ssize_t ret = 0; - - if (o2nm_cluster_attr->show) - ret = o2nm_cluster_attr->show(cluster, page); - return ret; -} - -static ssize_t o2nm_cluster_store(struct config_item *item, - struct configfs_attribute *attr, - const char *page, size_t count) -{ - struct o2nm_cluster *cluster = to_o2nm_cluster(item); - struct o2nm_cluster_attribute *o2nm_cluster_attr = - container_of(attr, struct o2nm_cluster_attribute, attr); - ssize_t ret; - - if (o2nm_cluster_attr->store == NULL) { - ret = -EINVAL; - goto out; - } - - ret = o2nm_cluster_attr->store(cluster, page, count); - if (ret < count) - goto out; -out: - return ret; -} - -static struct config_item *o2nm_node_group_make_item(struct config_group *group, - const char *name) -{ - struct o2nm_node *node = NULL; - - if (strlen(name) > O2NM_MAX_NAME_LEN) - return ERR_PTR(-ENAMETOOLONG); - - node = kzalloc(sizeof(struct o2nm_node), GFP_KERNEL); - if (node == NULL) - return ERR_PTR(-ENOMEM); - - strcpy(node->nd_name, name); /* use item.ci_namebuf instead? */ - config_item_init_type_name(&node->nd_item, name, &o2nm_node_type); - spin_lock_init(&node->nd_lock); - - mlog(ML_CLUSTER, "o2nm: Registering node %s\n", name); - - return &node->nd_item; -} - -static void o2nm_node_group_drop_item(struct config_group *group, - struct config_item *item) -{ - struct o2nm_node *node = to_o2nm_node(item); - struct o2nm_cluster *cluster = to_o2nm_cluster(group->cg_item.ci_parent); - - o2net_disconnect_node(node); - - if (cluster->cl_has_local && - (cluster->cl_local_node == node->nd_num)) { - cluster->cl_has_local = 0; - cluster->cl_local_node = O2NM_INVALID_NODE_NUM; - o2net_stop_listening(node); - } - - /* XXX call into net to stop this node from trading messages */ - - write_lock(&cluster->cl_nodes_lock); - - /* XXX sloppy */ - if (node->nd_ipv4_address) - rb_erase(&node->nd_ip_node, &cluster->cl_node_ip_tree); - - /* nd_num might be 0 if the node number hasn't been set.. */ - if (cluster->cl_nodes[node->nd_num] == node) { - cluster->cl_nodes[node->nd_num] = NULL; - clear_bit(node->nd_num, cluster->cl_nodes_bitmap); - } - write_unlock(&cluster->cl_nodes_lock); - - mlog(ML_CLUSTER, "o2nm: Unregistered node %s\n", - config_item_name(&node->nd_item)); - - config_item_put(item); -} - -static struct configfs_group_operations o2nm_node_group_group_ops = { - .make_item = o2nm_node_group_make_item, - .drop_item = o2nm_node_group_drop_item, -}; - -static struct config_item_type o2nm_node_group_type = { - .ct_group_ops = &o2nm_node_group_group_ops, - .ct_owner = THIS_MODULE, -}; - -/* cluster */ - -static void o2nm_cluster_release(struct config_item *item) -{ - struct o2nm_cluster *cluster = to_o2nm_cluster(item); - - kfree(cluster->cl_group.default_groups); - kfree(cluster); -} - -static struct configfs_item_operations o2nm_cluster_item_ops = { - .release = o2nm_cluster_release, - .show_attribute = o2nm_cluster_show, - .store_attribute = o2nm_cluster_store, -}; - -static struct config_item_type o2nm_cluster_type = { - .ct_item_ops = &o2nm_cluster_item_ops, - .ct_attrs = o2nm_cluster_attrs, - .ct_owner = THIS_MODULE, -}; - -/* cluster set */ - -struct o2nm_cluster_group { - struct configfs_subsystem cs_subsys; - /* some stuff? */ -}; - -#if 0 -static struct o2nm_cluster_group *to_o2nm_cluster_group(struct config_group *group) -{ - return group ? - container_of(to_configfs_subsystem(group), struct o2nm_cluster_group, cs_subsys) - : NULL; -} -#endif - -static struct config_group *o2nm_cluster_group_make_group(struct config_group *group, - const char *name) -{ - struct o2nm_cluster *cluster = NULL; - struct o2nm_node_group *ns = NULL; - struct config_group *o2hb_group = NULL, *ret = NULL; - void *defs = NULL; - - /* this runs under the parent dir's i_mutex; there can be only - * one caller in here at a time */ - if (o2nm_single_cluster) - return ERR_PTR(-ENOSPC); - - cluster = kzalloc(sizeof(struct o2nm_cluster), GFP_KERNEL); - ns = kzalloc(sizeof(struct o2nm_node_group), GFP_KERNEL); - defs = kcalloc(3, sizeof(struct config_group *), GFP_KERNEL); - o2hb_group = o2hb_alloc_hb_set(); - if (cluster == NULL || ns == NULL || o2hb_group == NULL || defs == NULL) - goto out; - - config_group_init_type_name(&cluster->cl_group, name, - &o2nm_cluster_type); - config_group_init_type_name(&ns->ns_group, "node", - &o2nm_node_group_type); - - cluster->cl_group.default_groups = defs; - cluster->cl_group.default_groups[0] = &ns->ns_group; - cluster->cl_group.default_groups[1] = o2hb_group; - cluster->cl_group.default_groups[2] = NULL; - rwlock_init(&cluster->cl_nodes_lock); - cluster->cl_node_ip_tree = RB_ROOT; - cluster->cl_reconnect_delay_ms = O2NET_RECONNECT_DELAY_MS_DEFAULT; - cluster->cl_idle_timeout_ms = O2NET_IDLE_TIMEOUT_MS_DEFAULT; - cluster->cl_keepalive_delay_ms = O2NET_KEEPALIVE_DELAY_MS_DEFAULT; - cluster->cl_fence_method = O2NM_FENCE_RESET; - - ret = &cluster->cl_group; - o2nm_single_cluster = cluster; - -out: - if (ret == NULL) { - kfree(cluster); - kfree(ns); - o2hb_free_hb_set(o2hb_group); - kfree(defs); - ret = ERR_PTR(-ENOMEM); - } - - return ret; -} - -static void o2nm_cluster_group_drop_item(struct config_group *group, struct config_item *item) -{ - struct o2nm_cluster *cluster = to_o2nm_cluster(item); - int i; - struct config_item *killme; - - BUG_ON(o2nm_single_cluster != cluster); - o2nm_single_cluster = NULL; - - for (i = 0; cluster->cl_group.default_groups[i]; i++) { - killme = &cluster->cl_group.default_groups[i]->cg_item; - cluster->cl_group.default_groups[i] = NULL; - config_item_put(killme); - } - - config_item_put(item); -} - -static struct configfs_group_operations o2nm_cluster_group_group_ops = { - .make_group = o2nm_cluster_group_make_group, - .drop_item = o2nm_cluster_group_drop_item, -}; - -static struct config_item_type o2nm_cluster_group_type = { - .ct_group_ops = &o2nm_cluster_group_group_ops, - .ct_owner = THIS_MODULE, -}; - -static struct o2nm_cluster_group o2nm_cluster_group = { - .cs_subsys = { - .su_group = { - .cg_item = { - .ci_namebuf = "cluster", - .ci_type = &o2nm_cluster_group_type, - }, - }, - }, -}; - -int o2nm_depend_item(struct config_item *item) -{ - return configfs_depend_item(&o2nm_cluster_group.cs_subsys, item); -} - -void o2nm_undepend_item(struct config_item *item) -{ - configfs_undepend_item(&o2nm_cluster_group.cs_subsys, item); -} - -int o2nm_depend_this_node(void) -{ - int ret = 0; - struct o2nm_node *local_node; - - local_node = o2nm_get_node_by_num(o2nm_this_node()); - if (!local_node) { - ret = -EINVAL; - goto out; - } - - ret = o2nm_depend_item(&local_node->nd_item); - o2nm_node_put(local_node); - -out: - return ret; -} - -void o2nm_undepend_this_node(void) -{ - struct o2nm_node *local_node; - - local_node = o2nm_get_node_by_num(o2nm_this_node()); - BUG_ON(!local_node); - - o2nm_undepend_item(&local_node->nd_item); - o2nm_node_put(local_node); -} - - -static void __exit exit_o2nm(void) -{ - /* XXX sync with hb callbacks and shut down hb? */ - o2net_unregister_hb_callbacks(); - configfs_unregister_subsystem(&o2nm_cluster_group.cs_subsys); - o2cb_sys_shutdown(); - - o2net_exit(); - o2hb_exit(); -} - -static int __init init_o2nm(void) -{ - int ret = -1; - - cluster_print_version(); - - ret = o2hb_init(); - if (ret) - goto out; - - ret = o2net_init(); - if (ret) - goto out_o2hb; - - ret = o2net_register_hb_callbacks(); - if (ret) - goto out_o2net; - - config_group_init(&o2nm_cluster_group.cs_subsys.su_group); - mutex_init(&o2nm_cluster_group.cs_subsys.su_mutex); - ret = configfs_register_subsystem(&o2nm_cluster_group.cs_subsys); - if (ret) { - printk(KERN_ERR "nodemanager: Registration returned %d\n", ret); - goto out_callbacks; - } - - ret = o2cb_sys_init(); - if (!ret) - goto out; - - configfs_unregister_subsystem(&o2nm_cluster_group.cs_subsys); -out_callbacks: - o2net_unregister_hb_callbacks(); -out_o2net: - o2net_exit(); -out_o2hb: - o2hb_exit(); -out: - return ret; -} - -MODULE_AUTHOR("Oracle"); -MODULE_LICENSE("GPL"); - -module_init(init_o2nm) -module_exit(exit_o2nm) diff --git a/drivers/staging/ramster/cluster/nodemanager.h b/drivers/staging/ramster/cluster/nodemanager.h deleted file mode 100644 index 09ea2d3..0000000 --- a/drivers/staging/ramster/cluster/nodemanager.h +++ /dev/null @@ -1,88 +0,0 @@ -/* -*- mode: c; c-basic-offset: 8; -*- - * vim: noexpandtab sw=8 ts=8 sts=0: - * - * nodemanager.h - * - * Function prototypes - * - * Copyright (C) 2004 Oracle. All rights reserved. - * - * 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; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 021110-1307, USA. - * - */ - -#ifndef O2CLUSTER_NODEMANAGER_H -#define O2CLUSTER_NODEMANAGER_H - -#include "ocfs2_nodemanager.h" - -/* This totally doesn't belong here. */ -#include -#include - -enum o2nm_fence_method { - O2NM_FENCE_RESET = 0, - O2NM_FENCE_PANIC, - O2NM_FENCE_METHODS, /* Number of fence methods */ -}; - -struct o2nm_node { - spinlock_t nd_lock; - struct config_item nd_item; - char nd_name[O2NM_MAX_NAME_LEN+1]; /* replace? */ - __u8 nd_num; - /* only one address per node, as attributes, for now. */ - __be32 nd_ipv4_address; - __be16 nd_ipv4_port; - struct rb_node nd_ip_node; - /* there can be only one local node for now */ - int nd_local; - - unsigned long nd_set_attributes; -}; - -struct o2nm_cluster { - struct config_group cl_group; - unsigned cl_has_local:1; - u8 cl_local_node; - rwlock_t cl_nodes_lock; - struct o2nm_node *cl_nodes[O2NM_MAX_NODES]; - struct rb_root cl_node_ip_tree; - unsigned int cl_idle_timeout_ms; - unsigned int cl_keepalive_delay_ms; - unsigned int cl_reconnect_delay_ms; - enum o2nm_fence_method cl_fence_method; - - /* this bitmap is part of a hack for disk bitmap.. will go eventually. - zab */ - unsigned long cl_nodes_bitmap[BITS_TO_LONGS(O2NM_MAX_NODES)]; -}; - -extern struct o2nm_cluster *o2nm_single_cluster; - -u8 o2nm_this_node(void); - -int o2nm_configured_node_map(unsigned long *map, unsigned bytes); -struct o2nm_node *o2nm_get_node_by_num(u8 node_num); -struct o2nm_node *o2nm_get_node_by_ip(__be32 addr); -void o2nm_node_get(struct o2nm_node *node); -void o2nm_node_put(struct o2nm_node *node); - -int o2nm_depend_item(struct config_item *item); -void o2nm_undepend_item(struct config_item *item); -int o2nm_depend_this_node(void); -void o2nm_undepend_this_node(void); - -#endif /* O2CLUSTER_NODEMANAGER_H */ diff --git a/drivers/staging/ramster/cluster/ocfs2_heartbeat.h b/drivers/staging/ramster/cluster/ocfs2_heartbeat.h deleted file mode 100644 index 3f4151d..0000000 --- a/drivers/staging/ramster/cluster/ocfs2_heartbeat.h +++ /dev/null @@ -1,38 +0,0 @@ -/* -*- mode: c; c-basic-offset: 8; -*- - * vim: noexpandtab sw=8 ts=8 sts=0: - * - * ocfs2_heartbeat.h - * - * On-disk structures for ocfs2_heartbeat - * - * Copyright (C) 2002, 2004 Oracle. All rights reserved. - * - * 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; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 021110-1307, USA. - */ - -#ifndef _OCFS2_HEARTBEAT_H -#define _OCFS2_HEARTBEAT_H - -struct o2hb_disk_heartbeat_block { - __le64 hb_seq; - __u8 hb_node; - __u8 hb_pad1[3]; - __le32 hb_cksum; - __le64 hb_generation; - __le32 hb_dead_ms; -}; - -#endif /* _OCFS2_HEARTBEAT_H */ diff --git a/drivers/staging/ramster/cluster/ocfs2_nodemanager.h b/drivers/staging/ramster/cluster/ocfs2_nodemanager.h deleted file mode 100644 index 49b5943..0000000 --- a/drivers/staging/ramster/cluster/ocfs2_nodemanager.h +++ /dev/null @@ -1,45 +0,0 @@ -/* -*- mode: c; c-basic-offset: 8; -*- - * vim: noexpandtab sw=8 ts=8 sts=0: - * - * ocfs2_nodemanager.h - * - * Header describing the interface between userspace and the kernel - * for the ocfs2_nodemanager module. - * - * Copyright (C) 2002, 2004 Oracle. All rights reserved. - * - * 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; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 021110-1307, USA. - * - */ - -#ifndef _OCFS2_NODEMANAGER_H -#define _OCFS2_NODEMANAGER_H - -#define O2NM_API_VERSION 5 - -#define O2NM_MAX_NODES 255 -#define O2NM_INVALID_NODE_NUM 255 - -/* host name, group name, cluster name all 64 bytes */ -#define O2NM_MAX_NAME_LEN 64 // __NEW_UTS_LEN - -/* - * Maximum number of global heartbeat regions allowed. - * **CAUTION** Changing this number will break dlm compatibility. - */ -#define O2NM_MAX_REGIONS 32 - -#endif /* _OCFS2_NODEMANAGER_H */ diff --git a/drivers/staging/ramster/cluster/quorum.c b/drivers/staging/ramster/cluster/quorum.c deleted file mode 100644 index 8f9cea1..0000000 --- a/drivers/staging/ramster/cluster/quorum.c +++ /dev/null @@ -1,331 +0,0 @@ -/* -*- mode: c; c-basic-offset: 8; -*- - * - * vim: noexpandtab sw=8 ts=8 sts=0: - * - * Copyright (C) 2005 Oracle. All rights reserved. - * - * 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; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 021110-1307, USA. - */ - -/* This quorum hack is only here until we transition to some more rational - * approach that is driven from userspace. Honest. No foolin'. - * - * Imagine two nodes lose network connectivity to each other but they're still - * up and operating in every other way. Presumably a network timeout indicates - * that a node is broken and should be recovered. They can't both recover each - * other and both carry on without serialising their access to the file system. - * They need to decide who is authoritative. Now extend that problem to - * arbitrary groups of nodes losing connectivity between each other. - * - * So we declare that a node which has given up on connecting to a majority - * of nodes who are still heartbeating will fence itself. - * - * There are huge opportunities for races here. After we give up on a node's - * connection we need to wait long enough to give heartbeat an opportunity - * to declare the node as truly dead. We also need to be careful with the - * race between when we see a node start heartbeating and when we connect - * to it. - * - * So nodes that are in this transtion put a hold on the quorum decision - * with a counter. As they fall out of this transition they drop the count - * and if they're the last, they fire off the decision. - */ -#include -#include -#include - -#include "heartbeat.h" -#include "nodemanager.h" -#define MLOG_MASK_PREFIX ML_QUORUM -#include "masklog.h" -#include "quorum.h" - -static struct o2quo_state { - spinlock_t qs_lock; - struct work_struct qs_work; - int qs_pending; - int qs_heartbeating; - unsigned long qs_hb_bm[BITS_TO_LONGS(O2NM_MAX_NODES)]; - int qs_connected; - unsigned long qs_conn_bm[BITS_TO_LONGS(O2NM_MAX_NODES)]; - int qs_holds; - unsigned long qs_hold_bm[BITS_TO_LONGS(O2NM_MAX_NODES)]; -} o2quo_state; - -/* this is horribly heavy-handed. It should instead flip the file - * system RO and call some userspace script. */ -static void o2quo_fence_self(void) -{ - /* panic spins with interrupts enabled. with preempt - * threads can still schedule, etc, etc */ - o2hb_stop_all_regions(); - - switch (o2nm_single_cluster->cl_fence_method) { - case O2NM_FENCE_PANIC: - panic("*** ocfs2 is very sorry to be fencing this system by " - "panicing ***\n"); - break; - default: - WARN_ON(o2nm_single_cluster->cl_fence_method >= - O2NM_FENCE_METHODS); - case O2NM_FENCE_RESET: - printk(KERN_ERR "*** ocfs2 is very sorry to be fencing this " - "system by restarting ***\n"); - emergency_restart(); - break; - }; -} - -/* Indicate that a timeout occurred on a hearbeat region write. The - * other nodes in the cluster may consider us dead at that time so we - * want to "fence" ourselves so that we don't scribble on the disk - * after they think they've recovered us. This can't solve all - * problems related to writeout after recovery but this hack can at - * least close some of those gaps. When we have real fencing, this can - * go away as our node would be fenced externally before other nodes - * begin recovery. */ -void o2quo_disk_timeout(void) -{ - o2quo_fence_self(); -} - -static void o2quo_make_decision(struct work_struct *work) -{ - int quorum; - int lowest_hb, lowest_reachable = 0, fence = 0; - struct o2quo_state *qs = &o2quo_state; - - spin_lock(&qs->qs_lock); - - lowest_hb = find_first_bit(qs->qs_hb_bm, O2NM_MAX_NODES); - if (lowest_hb != O2NM_MAX_NODES) - lowest_reachable = test_bit(lowest_hb, qs->qs_conn_bm); - - mlog(0, "heartbeating: %d, connected: %d, " - "lowest: %d (%sreachable)\n", qs->qs_heartbeating, - qs->qs_connected, lowest_hb, lowest_reachable ? "" : "un"); - - if (!test_bit(o2nm_this_node(), qs->qs_hb_bm) || - qs->qs_heartbeating == 1) - goto out; - - if (qs->qs_heartbeating & 1) { - /* the odd numbered cluster case is straight forward -- - * if we can't talk to the majority we're hosed */ - quorum = (qs->qs_heartbeating + 1)/2; - if (qs->qs_connected < quorum) { - mlog(ML_ERROR, "fencing this node because it is " - "only connected to %u nodes and %u is needed " - "to make a quorum out of %u heartbeating nodes\n", - qs->qs_connected, quorum, - qs->qs_heartbeating); - fence = 1; - } - } else { - /* the even numbered cluster adds the possibility of each half - * of the cluster being able to talk amongst themselves.. in - * that case we're hosed if we can't talk to the group that has - * the lowest numbered node */ - quorum = qs->qs_heartbeating / 2; - if (qs->qs_connected < quorum) { - mlog(ML_ERROR, "fencing this node because it is " - "only connected to %u nodes and %u is needed " - "to make a quorum out of %u heartbeating nodes\n", - qs->qs_connected, quorum, - qs->qs_heartbeating); - fence = 1; - } - else if ((qs->qs_connected == quorum) && - !lowest_reachable) { - mlog(ML_ERROR, "fencing this node because it is " - "connected to a half-quorum of %u out of %u " - "nodes which doesn't include the lowest active " - "node %u\n", quorum, qs->qs_heartbeating, - lowest_hb); - fence = 1; - } - } - -out: - spin_unlock(&qs->qs_lock); - if (fence) - o2quo_fence_self(); -} - -static void o2quo_set_hold(struct o2quo_state *qs, u8 node) -{ - assert_spin_locked(&qs->qs_lock); - - if (!test_and_set_bit(node, qs->qs_hold_bm)) { - qs->qs_holds++; - mlog_bug_on_msg(qs->qs_holds == O2NM_MAX_NODES, - "node %u\n", node); - mlog(0, "node %u, %d total\n", node, qs->qs_holds); - } -} - -static void o2quo_clear_hold(struct o2quo_state *qs, u8 node) -{ - assert_spin_locked(&qs->qs_lock); - - if (test_and_clear_bit(node, qs->qs_hold_bm)) { - mlog(0, "node %u, %d total\n", node, qs->qs_holds - 1); - if (--qs->qs_holds == 0) { - if (qs->qs_pending) { - qs->qs_pending = 0; - schedule_work(&qs->qs_work); - } - } - mlog_bug_on_msg(qs->qs_holds < 0, "node %u, holds %d\n", - node, qs->qs_holds); - } -} - -/* as a node comes up we delay the quorum decision until we know the fate of - * the connection. the hold will be droped in conn_up or hb_down. it might be - * perpetuated by con_err until hb_down. if we already have a conn, we might - * be dropping a hold that conn_up got. */ -void o2quo_hb_up(u8 node) -{ - struct o2quo_state *qs = &o2quo_state; - - spin_lock(&qs->qs_lock); - - qs->qs_heartbeating++; - mlog_bug_on_msg(qs->qs_heartbeating == O2NM_MAX_NODES, - "node %u\n", node); - mlog_bug_on_msg(test_bit(node, qs->qs_hb_bm), "node %u\n", node); - set_bit(node, qs->qs_hb_bm); - - mlog(0, "node %u, %d total\n", node, qs->qs_heartbeating); - - if (!test_bit(node, qs->qs_conn_bm)) - o2quo_set_hold(qs, node); - else - o2quo_clear_hold(qs, node); - - spin_unlock(&qs->qs_lock); -} - -/* hb going down releases any holds we might have had due to this node from - * conn_up, conn_err, or hb_up */ -void o2quo_hb_down(u8 node) -{ - struct o2quo_state *qs = &o2quo_state; - - spin_lock(&qs->qs_lock); - - qs->qs_heartbeating--; - mlog_bug_on_msg(qs->qs_heartbeating < 0, - "node %u, %d heartbeating\n", - node, qs->qs_heartbeating); - mlog_bug_on_msg(!test_bit(node, qs->qs_hb_bm), "node %u\n", node); - clear_bit(node, qs->qs_hb_bm); - - mlog(0, "node %u, %d total\n", node, qs->qs_heartbeating); - - o2quo_clear_hold(qs, node); - - spin_unlock(&qs->qs_lock); -} - -/* this tells us that we've decided that the node is still heartbeating - * even though we've lost it's conn. it must only be called after conn_err - * and indicates that we must now make a quorum decision in the future, - * though we might be doing so after waiting for holds to drain. Here - * we'll be dropping the hold from conn_err. */ -void o2quo_hb_still_up(u8 node) -{ - struct o2quo_state *qs = &o2quo_state; - - spin_lock(&qs->qs_lock); - - mlog(0, "node %u\n", node); - - qs->qs_pending = 1; - o2quo_clear_hold(qs, node); - - spin_unlock(&qs->qs_lock); -} - -/* This is analogous to hb_up. as a node's connection comes up we delay the - * quorum decision until we see it heartbeating. the hold will be droped in - * hb_up or hb_down. it might be perpetuated by con_err until hb_down. if - * it's already heartbeating we we might be dropping a hold that conn_up got. - * */ -void o2quo_conn_up(u8 node) -{ - struct o2quo_state *qs = &o2quo_state; - - spin_lock(&qs->qs_lock); - - qs->qs_connected++; - mlog_bug_on_msg(qs->qs_connected == O2NM_MAX_NODES, - "node %u\n", node); - mlog_bug_on_msg(test_bit(node, qs->qs_conn_bm), "node %u\n", node); - set_bit(node, qs->qs_conn_bm); - - mlog(0, "node %u, %d total\n", node, qs->qs_connected); - - if (!test_bit(node, qs->qs_hb_bm)) - o2quo_set_hold(qs, node); - else - o2quo_clear_hold(qs, node); - - spin_unlock(&qs->qs_lock); -} - -/* we've decided that we won't ever be connecting to the node again. if it's - * still heartbeating we grab a hold that will delay decisions until either the - * node stops heartbeating from hb_down or the caller decides that the node is - * still up and calls still_up */ -void o2quo_conn_err(u8 node) -{ - struct o2quo_state *qs = &o2quo_state; - - spin_lock(&qs->qs_lock); - - if (test_bit(node, qs->qs_conn_bm)) { - qs->qs_connected--; - mlog_bug_on_msg(qs->qs_connected < 0, - "node %u, connected %d\n", - node, qs->qs_connected); - - clear_bit(node, qs->qs_conn_bm); - } - - mlog(0, "node %u, %d total\n", node, qs->qs_connected); - - if (test_bit(node, qs->qs_hb_bm)) - o2quo_set_hold(qs, node); - - spin_unlock(&qs->qs_lock); -} - -void o2quo_init(void) -{ - struct o2quo_state *qs = &o2quo_state; - - spin_lock_init(&qs->qs_lock); - INIT_WORK(&qs->qs_work, o2quo_make_decision); -} - -void o2quo_exit(void) -{ - struct o2quo_state *qs = &o2quo_state; - - flush_work_sync(&qs->qs_work); -} diff --git a/drivers/staging/ramster/cluster/quorum.h b/drivers/staging/ramster/cluster/quorum.h deleted file mode 100644 index 6649cc6..0000000 --- a/drivers/staging/ramster/cluster/quorum.h +++ /dev/null @@ -1,36 +0,0 @@ -/* -*- mode: c; c-basic-offset: 8; -*- - * vim: noexpandtab sw=8 ts=8 sts=0: - * - * Copyright (C) 2005 Oracle. All rights reserved. - * - * 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; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 021110-1307, USA. - * - */ - -#ifndef O2CLUSTER_QUORUM_H -#define O2CLUSTER_QUORUM_H - -void o2quo_init(void); -void o2quo_exit(void); - -void o2quo_hb_up(u8 node); -void o2quo_hb_down(u8 node); -void o2quo_hb_still_up(u8 node); -void o2quo_conn_up(u8 node); -void o2quo_conn_err(u8 node); -void o2quo_disk_timeout(void); - -#endif /* O2CLUSTER_QUORUM_H */ diff --git a/drivers/staging/ramster/cluster/sys.c b/drivers/staging/ramster/cluster/sys.c deleted file mode 100644 index a4b0773..0000000 --- a/drivers/staging/ramster/cluster/sys.c +++ /dev/null @@ -1,82 +0,0 @@ -/* -*- mode: c; c-basic-offset: 8; -*- - * vim: noexpandtab sw=8 ts=8 sts=0: - * - * sys.c - * - * OCFS2 cluster sysfs interface - * - * Copyright (C) 2005 Oracle. All rights reserved. - * - * 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, - * version 2 of the License. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 021110-1307, USA. - * - */ - -#include -#include -#include -#include -#include - -#include "ocfs2_nodemanager.h" -#include "masklog.h" -#include "sys.h" - - -static ssize_t version_show(struct kobject *kobj, struct kobj_attribute *attr, - char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%u\n", O2NM_API_VERSION); -} -static struct kobj_attribute attr_version = - __ATTR(interface_revision, S_IFREG | S_IRUGO, version_show, NULL); - -static struct attribute *o2cb_attrs[] = { - &attr_version.attr, - NULL, -}; - -static struct attribute_group o2cb_attr_group = { - .attrs = o2cb_attrs, -}; - -static struct kset *o2cb_kset; - -void o2cb_sys_shutdown(void) -{ - mlog_sys_shutdown(); - kset_unregister(o2cb_kset); -} - -int o2cb_sys_init(void) -{ - int ret; - - o2cb_kset = kset_create_and_add("o2cb", NULL, fs_kobj); - if (!o2cb_kset) - return -ENOMEM; - - ret = sysfs_create_group(&o2cb_kset->kobj, &o2cb_attr_group); - if (ret) - goto error; - - ret = mlog_sys_init(o2cb_kset); - if (ret) - goto error; - return 0; -error: - kset_unregister(o2cb_kset); - return ret; -} diff --git a/drivers/staging/ramster/cluster/sys.h b/drivers/staging/ramster/cluster/sys.h deleted file mode 100644 index d66b8ab..0000000 --- a/drivers/staging/ramster/cluster/sys.h +++ /dev/null @@ -1,33 +0,0 @@ -/* -*- mode: c; c-basic-offset: 8; -*- - * vim: noexpandtab sw=8 ts=8 sts=0: - * - * sys.h - * - * Function prototypes for o2cb sysfs interface - * - * Copyright (C) 2005 Oracle. All rights reserved. - * - * 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, - * version 2 of the License. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 021110-1307, USA. - * - */ - -#ifndef O2CLUSTER_SYS_H -#define O2CLUSTER_SYS_H - -void o2cb_sys_shutdown(void); -int o2cb_sys_init(void); - -#endif /* O2CLUSTER_SYS_H */ diff --git a/drivers/staging/ramster/cluster/tcp.c b/drivers/staging/ramster/cluster/tcp.c deleted file mode 100644 index e9bd00e..0000000 --- a/drivers/staging/ramster/cluster/tcp.c +++ /dev/null @@ -1,2262 +0,0 @@ -/* -*- mode: c; c-basic-offset: 8; -*- - * - * vim: noexpandtab sw=8 ts=8 sts=0: - * - * Copyright (C) 2004 Oracle. All rights reserved. - * - * 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; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 021110-1307, USA. - * - * ---- - * - * Callers for this were originally written against a very simple synchronus - * API. This implementation reflects those simple callers. Some day I'm sure - * we'll need to move to a more robust posting/callback mechanism. - * - * Transmit calls pass in kernel virtual addresses and block copying this into - * the socket's tx buffers via a usual blocking sendmsg. They'll block waiting - * for a failed socket to timeout. TX callers can also pass in a poniter to an - * 'int' which gets filled with an errno off the wire in response to the - * message they send. - * - * Handlers for unsolicited messages are registered. Each socket has a page - * that incoming data is copied into. First the header, then the data. - * Handlers are called from only one thread with a reference to this per-socket - * page. This page is destroyed after the handler call, so it can't be - * referenced beyond the call. Handlers may block but are discouraged from - * doing so. - * - * Any framing errors (bad magic, large payload lengths) close a connection. - * - * Our sock_container holds the state we associate with a socket. It's current - * framing state is held there as well as the refcounting we do around when it - * is safe to tear down the socket. The socket is only finally torn down from - * the container when the container loses all of its references -- so as long - * as you hold a ref on the container you can trust that the socket is valid - * for use with kernel socket APIs. - * - * Connections are initiated between a pair of nodes when the node with the - * higher node number gets a heartbeat callback which indicates that the lower - * numbered node has started heartbeating. The lower numbered node is passive - * and only accepts the connection if the higher numbered node is heartbeating. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "heartbeat.h" -#include "tcp.h" -#include "nodemanager.h" -#define MLOG_MASK_PREFIX ML_TCP -#include "masklog.h" -#include "quorum.h" - -#include "tcp_internal.h" - -#define SC_NODEF_FMT "node %s (num %u) at %pI4:%u" -#define SC_NODEF_ARGS(sc) sc->sc_node->nd_name, sc->sc_node->nd_num, \ - &sc->sc_node->nd_ipv4_address, \ - ntohs(sc->sc_node->nd_ipv4_port) - -/* - * In the following two log macros, the whitespace after the ',' just - * before ##args is intentional. Otherwise, gcc 2.95 will eat the - * previous token if args expands to nothing. - */ -#define msglog(hdr, fmt, args...) do { \ - typeof(hdr) __hdr = (hdr); \ - mlog(ML_MSG, "[mag %u len %u typ %u stat %d sys_stat %d " \ - "key %08x num %u] " fmt, \ - be16_to_cpu(__hdr->magic), be16_to_cpu(__hdr->data_len), \ - be16_to_cpu(__hdr->msg_type), be32_to_cpu(__hdr->status), \ - be32_to_cpu(__hdr->sys_status), be32_to_cpu(__hdr->key), \ - be32_to_cpu(__hdr->msg_num) , ##args); \ -} while (0) - -#define sclog(sc, fmt, args...) do { \ - typeof(sc) __sc = (sc); \ - mlog(ML_SOCKET, "[sc %p refs %d sock %p node %u page %p " \ - "pg_off %zu] " fmt, __sc, \ - atomic_read(&__sc->sc_kref.refcount), __sc->sc_sock, \ - __sc->sc_node->nd_num, __sc->sc_page, __sc->sc_page_off , \ - ##args); \ -} while (0) - -static DEFINE_RWLOCK(o2net_handler_lock); -static struct rb_root o2net_handler_tree = RB_ROOT; - -static struct o2net_node o2net_nodes[O2NM_MAX_NODES]; - -/* XXX someday we'll need better accounting */ -static struct socket *o2net_listen_sock = NULL; - -/* - * listen work is only queued by the listening socket callbacks on the - * o2net_wq. teardown detaches the callbacks before destroying the workqueue. - * quorum work is queued as sock containers are shutdown.. stop_listening - * tears down all the node's sock containers, preventing future shutdowns - * and queued quroum work, before canceling delayed quorum work and - * destroying the work queue. - */ -static struct workqueue_struct *o2net_wq; -static struct work_struct o2net_listen_work; - -static struct o2hb_callback_func o2net_hb_up, o2net_hb_down; -#define O2NET_HB_PRI 0x1 - -static struct o2net_handshake *o2net_hand; -static struct o2net_msg *o2net_keep_req, *o2net_keep_resp; - -static int o2net_sys_err_translations[O2NET_ERR_MAX] = - {[O2NET_ERR_NONE] = 0, - [O2NET_ERR_NO_HNDLR] = -ENOPROTOOPT, - [O2NET_ERR_OVERFLOW] = -EOVERFLOW, - [O2NET_ERR_DIED] = -EHOSTDOWN,}; - -/* can't quite avoid *all* internal declarations :/ */ -static void o2net_sc_connect_completed(struct work_struct *work); -static void o2net_rx_until_empty(struct work_struct *work); -static void o2net_shutdown_sc(struct work_struct *work); -static void o2net_listen_data_ready(struct sock *sk, int bytes); -static void o2net_sc_send_keep_req(struct work_struct *work); -static void o2net_idle_timer(unsigned long data); -static void o2net_sc_postpone_idle(struct o2net_sock_container *sc); -static void o2net_sc_reset_idle_timer(struct o2net_sock_container *sc); - -#ifdef CONFIG_DEBUG_FS -static void o2net_init_nst(struct o2net_send_tracking *nst, u32 msgtype, - u32 msgkey, struct task_struct *task, u8 node) -{ - INIT_LIST_HEAD(&nst->st_net_debug_item); - nst->st_task = task; - nst->st_msg_type = msgtype; - nst->st_msg_key = msgkey; - nst->st_node = node; -} - -static inline void o2net_set_nst_sock_time(struct o2net_send_tracking *nst) -{ - nst->st_sock_time = ktime_get(); -} - -static inline void o2net_set_nst_send_time(struct o2net_send_tracking *nst) -{ - nst->st_send_time = ktime_get(); -} - -static inline void o2net_set_nst_status_time(struct o2net_send_tracking *nst) -{ - nst->st_status_time = ktime_get(); -} - -static inline void o2net_set_nst_sock_container(struct o2net_send_tracking *nst, - struct o2net_sock_container *sc) -{ - nst->st_sc = sc; -} - -static inline void o2net_set_nst_msg_id(struct o2net_send_tracking *nst, - u32 msg_id) -{ - nst->st_id = msg_id; -} - -static inline void o2net_set_sock_timer(struct o2net_sock_container *sc) -{ - sc->sc_tv_timer = ktime_get(); -} - -static inline void o2net_set_data_ready_time(struct o2net_sock_container *sc) -{ - sc->sc_tv_data_ready = ktime_get(); -} - -static inline void o2net_set_advance_start_time(struct o2net_sock_container *sc) -{ - sc->sc_tv_advance_start = ktime_get(); -} - -static inline void o2net_set_advance_stop_time(struct o2net_sock_container *sc) -{ - sc->sc_tv_advance_stop = ktime_get(); -} - -static inline void o2net_set_func_start_time(struct o2net_sock_container *sc) -{ - sc->sc_tv_func_start = ktime_get(); -} - -static inline void o2net_set_func_stop_time(struct o2net_sock_container *sc) -{ - sc->sc_tv_func_stop = ktime_get(); -} - -#else /* CONFIG_DEBUG_FS */ -# define o2net_init_nst(a, b, c, d, e) -# define o2net_set_nst_sock_time(a) -# define o2net_set_nst_send_time(a) -# define o2net_set_nst_status_time(a) -# define o2net_set_nst_sock_container(a, b) -# define o2net_set_nst_msg_id(a, b) -# define o2net_set_sock_timer(a) -# define o2net_set_data_ready_time(a) -# define o2net_set_advance_start_time(a) -# define o2net_set_advance_stop_time(a) -# define o2net_set_func_start_time(a) -# define o2net_set_func_stop_time(a) -#endif /* CONFIG_DEBUG_FS */ - -#ifdef CONFIG_OCFS2_FS_STATS -static ktime_t o2net_get_func_run_time(struct o2net_sock_container *sc) -{ - return ktime_sub(sc->sc_tv_func_stop, sc->sc_tv_func_start); -} - -static void o2net_update_send_stats(struct o2net_send_tracking *nst, - struct o2net_sock_container *sc) -{ - sc->sc_tv_status_total = ktime_add(sc->sc_tv_status_total, - ktime_sub(ktime_get(), - nst->st_status_time)); - sc->sc_tv_send_total = ktime_add(sc->sc_tv_send_total, - ktime_sub(nst->st_status_time, - nst->st_send_time)); - sc->sc_tv_acquiry_total = ktime_add(sc->sc_tv_acquiry_total, - ktime_sub(nst->st_send_time, - nst->st_sock_time)); - sc->sc_send_count++; -} - -static void o2net_update_recv_stats(struct o2net_sock_container *sc) -{ - sc->sc_tv_process_total = ktime_add(sc->sc_tv_process_total, - o2net_get_func_run_time(sc)); - sc->sc_recv_count++; -} - -#else - -# define o2net_update_send_stats(a, b) - -# define o2net_update_recv_stats(sc) - -#endif /* CONFIG_OCFS2_FS_STATS */ - -static inline int o2net_reconnect_delay(void) -{ - return o2nm_single_cluster->cl_reconnect_delay_ms; -} - -static inline int o2net_keepalive_delay(void) -{ - return o2nm_single_cluster->cl_keepalive_delay_ms; -} - -static inline int o2net_idle_timeout(void) -{ - return o2nm_single_cluster->cl_idle_timeout_ms; -} - -static inline int o2net_sys_err_to_errno(enum o2net_system_error err) -{ - int trans; - BUG_ON(err >= O2NET_ERR_MAX); - trans = o2net_sys_err_translations[err]; - - /* Just in case we mess up the translation table above */ - BUG_ON(err != O2NET_ERR_NONE && trans == 0); - return trans; -} - -#ifdef CONFIG_RAMSTER -struct o2net_node *o2net_nn_from_num(u8 node_num) -#else -static struct o2net_node * o2net_nn_from_num(u8 node_num) -#endif -{ - BUG_ON(node_num >= ARRAY_SIZE(o2net_nodes)); - return &o2net_nodes[node_num]; -} - -static u8 o2net_num_from_nn(struct o2net_node *nn) -{ - BUG_ON(nn == NULL); - return nn - o2net_nodes; -} - -/* ------------------------------------------------------------ */ - -static int o2net_prep_nsw(struct o2net_node *nn, struct o2net_status_wait *nsw) -{ - int ret = 0; - - do { - if (!idr_pre_get(&nn->nn_status_idr, GFP_ATOMIC)) { - ret = -EAGAIN; - break; - } - spin_lock(&nn->nn_lock); - ret = idr_get_new(&nn->nn_status_idr, nsw, &nsw->ns_id); - if (ret == 0) - list_add_tail(&nsw->ns_node_item, - &nn->nn_status_list); - spin_unlock(&nn->nn_lock); - } while (ret == -EAGAIN); - - if (ret == 0) { - init_waitqueue_head(&nsw->ns_wq); - nsw->ns_sys_status = O2NET_ERR_NONE; - nsw->ns_status = 0; - } - - return ret; -} - -static void o2net_complete_nsw_locked(struct o2net_node *nn, - struct o2net_status_wait *nsw, - enum o2net_system_error sys_status, - s32 status) -{ - assert_spin_locked(&nn->nn_lock); - - if (!list_empty(&nsw->ns_node_item)) { - list_del_init(&nsw->ns_node_item); - nsw->ns_sys_status = sys_status; - nsw->ns_status = status; - idr_remove(&nn->nn_status_idr, nsw->ns_id); - wake_up(&nsw->ns_wq); - } -} - -static void o2net_complete_nsw(struct o2net_node *nn, - struct o2net_status_wait *nsw, - u64 id, enum o2net_system_error sys_status, - s32 status) -{ - spin_lock(&nn->nn_lock); - if (nsw == NULL) { - if (id > INT_MAX) - goto out; - - nsw = idr_find(&nn->nn_status_idr, id); - if (nsw == NULL) - goto out; - } - - o2net_complete_nsw_locked(nn, nsw, sys_status, status); - -out: - spin_unlock(&nn->nn_lock); - return; -} - -static void o2net_complete_nodes_nsw(struct o2net_node *nn) -{ - struct o2net_status_wait *nsw, *tmp; - unsigned int num_kills = 0; - - assert_spin_locked(&nn->nn_lock); - - list_for_each_entry_safe(nsw, tmp, &nn->nn_status_list, ns_node_item) { - o2net_complete_nsw_locked(nn, nsw, O2NET_ERR_DIED, 0); - num_kills++; - } - - mlog(0, "completed %d messages for node %u\n", num_kills, - o2net_num_from_nn(nn)); -} - -static int o2net_nsw_completed(struct o2net_node *nn, - struct o2net_status_wait *nsw) -{ - int completed; - spin_lock(&nn->nn_lock); - completed = list_empty(&nsw->ns_node_item); - spin_unlock(&nn->nn_lock); - return completed; -} - -/* ------------------------------------------------------------ */ - -static void sc_kref_release(struct kref *kref) -{ - struct o2net_sock_container *sc = container_of(kref, - struct o2net_sock_container, sc_kref); - BUG_ON(timer_pending(&sc->sc_idle_timeout)); - - sclog(sc, "releasing\n"); - - if (sc->sc_sock) { - sock_release(sc->sc_sock); - sc->sc_sock = NULL; - } - - o2nm_undepend_item(&sc->sc_node->nd_item); - o2nm_node_put(sc->sc_node); - sc->sc_node = NULL; - - o2net_debug_del_sc(sc); - kfree(sc); -} - -static void sc_put(struct o2net_sock_container *sc) -{ - sclog(sc, "put\n"); - kref_put(&sc->sc_kref, sc_kref_release); -} -static void sc_get(struct o2net_sock_container *sc) -{ - sclog(sc, "get\n"); - kref_get(&sc->sc_kref); -} -static struct o2net_sock_container *sc_alloc(struct o2nm_node *node) -{ - struct o2net_sock_container *sc, *ret = NULL; - struct page *page = NULL; - int status = 0; - - page = alloc_page(GFP_NOFS); - sc = kzalloc(sizeof(*sc), GFP_NOFS); - if (sc == NULL || page == NULL) - goto out; - - kref_init(&sc->sc_kref); - o2nm_node_get(node); - sc->sc_node = node; - - /* pin the node item of the remote node */ - status = o2nm_depend_item(&node->nd_item); - if (status) { - mlog_errno(status); - o2nm_node_put(node); - goto out; - } - INIT_WORK(&sc->sc_connect_work, o2net_sc_connect_completed); - INIT_WORK(&sc->sc_rx_work, o2net_rx_until_empty); - INIT_WORK(&sc->sc_shutdown_work, o2net_shutdown_sc); - INIT_DELAYED_WORK(&sc->sc_keepalive_work, o2net_sc_send_keep_req); - - init_timer(&sc->sc_idle_timeout); - sc->sc_idle_timeout.function = o2net_idle_timer; - sc->sc_idle_timeout.data = (unsigned long)sc; - - sclog(sc, "alloced\n"); - - ret = sc; - sc->sc_page = page; - o2net_debug_add_sc(sc); - sc = NULL; - page = NULL; - -out: - if (page) - __free_page(page); - kfree(sc); - - return ret; -} - -/* ------------------------------------------------------------ */ - -static void o2net_sc_queue_work(struct o2net_sock_container *sc, - struct work_struct *work) -{ - sc_get(sc); - if (!queue_work(o2net_wq, work)) - sc_put(sc); -} -static void o2net_sc_queue_delayed_work(struct o2net_sock_container *sc, - struct delayed_work *work, - int delay) -{ - sc_get(sc); - if (!queue_delayed_work(o2net_wq, work, delay)) - sc_put(sc); -} -static void o2net_sc_cancel_delayed_work(struct o2net_sock_container *sc, - struct delayed_work *work) -{ - if (cancel_delayed_work(work)) - sc_put(sc); -} - -static atomic_t o2net_connected_peers = ATOMIC_INIT(0); - -int o2net_num_connected_peers(void) -{ - return atomic_read(&o2net_connected_peers); -} - -static void o2net_set_nn_state(struct o2net_node *nn, - struct o2net_sock_container *sc, - unsigned valid, int err) -{ - int was_valid = nn->nn_sc_valid; - int was_err = nn->nn_persistent_error; - struct o2net_sock_container *old_sc = nn->nn_sc; - - assert_spin_locked(&nn->nn_lock); - - if (old_sc && !sc) - atomic_dec(&o2net_connected_peers); - else if (!old_sc && sc) - atomic_inc(&o2net_connected_peers); - - /* the node num comparison and single connect/accept path should stop - * an non-null sc from being overwritten with another */ - BUG_ON(sc && nn->nn_sc && nn->nn_sc != sc); - mlog_bug_on_msg(err && valid, "err %d valid %u\n", err, valid); - mlog_bug_on_msg(valid && !sc, "valid %u sc %p\n", valid, sc); - - if (was_valid && !valid && err == 0) - err = -ENOTCONN; - - mlog(ML_CONN, "node %u sc: %p -> %p, valid %u -> %u, err %d -> %d\n", - o2net_num_from_nn(nn), nn->nn_sc, sc, nn->nn_sc_valid, valid, - nn->nn_persistent_error, err); - - nn->nn_sc = sc; - nn->nn_sc_valid = valid ? 1 : 0; - nn->nn_persistent_error = err; - - /* mirrors o2net_tx_can_proceed() */ - if (nn->nn_persistent_error || nn->nn_sc_valid) - wake_up(&nn->nn_sc_wq); - - if (!was_err && nn->nn_persistent_error) { - o2quo_conn_err(o2net_num_from_nn(nn)); - queue_delayed_work(o2net_wq, &nn->nn_still_up, - msecs_to_jiffies(O2NET_QUORUM_DELAY_MS)); - } - - if (was_valid && !valid) { - printk(KERN_NOTICE "o2net: No longer connected to " - SC_NODEF_FMT "\n", SC_NODEF_ARGS(old_sc)); - o2net_complete_nodes_nsw(nn); - } - - if (!was_valid && valid) { - o2quo_conn_up(o2net_num_from_nn(nn)); - cancel_delayed_work(&nn->nn_connect_expired); - printk(KERN_NOTICE "o2net: %s " SC_NODEF_FMT "\n", - o2nm_this_node() > sc->sc_node->nd_num ? - "Connected to" : "Accepted connection from", - SC_NODEF_ARGS(sc)); - } - - /* trigger the connecting worker func as long as we're not valid, - * it will back off if it shouldn't connect. This can be called - * from node config teardown and so needs to be careful about - * the work queue actually being up. */ - if (!valid && o2net_wq) { - unsigned long delay; - /* delay if we're within a RECONNECT_DELAY of the - * last attempt */ - delay = (nn->nn_last_connect_attempt + - msecs_to_jiffies(o2net_reconnect_delay())) - - jiffies; - if (delay > msecs_to_jiffies(o2net_reconnect_delay())) - delay = 0; - mlog(ML_CONN, "queueing conn attempt in %lu jiffies\n", delay); - queue_delayed_work(o2net_wq, &nn->nn_connect_work, delay); - - /* - * Delay the expired work after idle timeout. - * - * We might have lots of failed connection attempts that run - * through here but we only cancel the connect_expired work when - * a connection attempt succeeds. So only the first enqueue of - * the connect_expired work will do anything. The rest will see - * that it's already queued and do nothing. - */ - delay += msecs_to_jiffies(o2net_idle_timeout()); - queue_delayed_work(o2net_wq, &nn->nn_connect_expired, delay); - } - - /* keep track of the nn's sc ref for the caller */ - if ((old_sc == NULL) && sc) - sc_get(sc); - if (old_sc && (old_sc != sc)) { - o2net_sc_queue_work(old_sc, &old_sc->sc_shutdown_work); - sc_put(old_sc); - } -} - -/* see o2net_register_callbacks() */ -static void o2net_data_ready(struct sock *sk, int bytes) -{ - void (*ready)(struct sock *sk, int bytes); - - read_lock(&sk->sk_callback_lock); - if (sk->sk_user_data) { - struct o2net_sock_container *sc = sk->sk_user_data; - sclog(sc, "data_ready hit\n"); - o2net_set_data_ready_time(sc); - o2net_sc_queue_work(sc, &sc->sc_rx_work); - ready = sc->sc_data_ready; - } else { - ready = sk->sk_data_ready; - } - read_unlock(&sk->sk_callback_lock); - - ready(sk, bytes); -} - -/* see o2net_register_callbacks() */ -static void o2net_state_change(struct sock *sk) -{ - void (*state_change)(struct sock *sk); - struct o2net_sock_container *sc; - - read_lock(&sk->sk_callback_lock); - sc = sk->sk_user_data; - if (sc == NULL) { - state_change = sk->sk_state_change; - goto out; - } - - sclog(sc, "state_change to %d\n", sk->sk_state); - - state_change = sc->sc_state_change; - - switch(sk->sk_state) { - /* ignore connecting sockets as they make progress */ - case TCP_SYN_SENT: - case TCP_SYN_RECV: - break; - case TCP_ESTABLISHED: - o2net_sc_queue_work(sc, &sc->sc_connect_work); - break; - default: - printk(KERN_INFO "o2net: Connection to " SC_NODEF_FMT - " shutdown, state %d\n", - SC_NODEF_ARGS(sc), sk->sk_state); - o2net_sc_queue_work(sc, &sc->sc_shutdown_work); - break; - } -out: - read_unlock(&sk->sk_callback_lock); - state_change(sk); -} - -/* - * we register callbacks so we can queue work on events before calling - * the original callbacks. our callbacks our careful to test user_data - * to discover when they've reaced with o2net_unregister_callbacks(). - */ -static void o2net_register_callbacks(struct sock *sk, - struct o2net_sock_container *sc) -{ - write_lock_bh(&sk->sk_callback_lock); - - /* accepted sockets inherit the old listen socket data ready */ - if (sk->sk_data_ready == o2net_listen_data_ready) { - sk->sk_data_ready = sk->sk_user_data; - sk->sk_user_data = NULL; - } - - BUG_ON(sk->sk_user_data != NULL); - sk->sk_user_data = sc; - sc_get(sc); - - sc->sc_data_ready = sk->sk_data_ready; - sc->sc_state_change = sk->sk_state_change; - sk->sk_data_ready = o2net_data_ready; - sk->sk_state_change = o2net_state_change; - - mutex_init(&sc->sc_send_lock); - - write_unlock_bh(&sk->sk_callback_lock); -} - -static int o2net_unregister_callbacks(struct sock *sk, - struct o2net_sock_container *sc) -{ - int ret = 0; - - write_lock_bh(&sk->sk_callback_lock); - if (sk->sk_user_data == sc) { - ret = 1; - sk->sk_user_data = NULL; - sk->sk_data_ready = sc->sc_data_ready; - sk->sk_state_change = sc->sc_state_change; - } - write_unlock_bh(&sk->sk_callback_lock); - - return ret; -} - -/* - * this is a little helper that is called by callers who have seen a problem - * with an sc and want to detach it from the nn if someone already hasn't beat - * them to it. if an error is given then the shutdown will be persistent - * and pending transmits will be canceled. - */ -static void o2net_ensure_shutdown(struct o2net_node *nn, - struct o2net_sock_container *sc, - int err) -{ - spin_lock(&nn->nn_lock); - if (nn->nn_sc == sc) - o2net_set_nn_state(nn, NULL, 0, err); - spin_unlock(&nn->nn_lock); -} - -/* - * This work queue function performs the blocking parts of socket shutdown. A - * few paths lead here. set_nn_state will trigger this callback if it sees an - * sc detached from the nn. state_change will also trigger this callback - * directly when it sees errors. In that case we need to call set_nn_state - * ourselves as state_change couldn't get the nn_lock and call set_nn_state - * itself. - */ -static void o2net_shutdown_sc(struct work_struct *work) -{ - struct o2net_sock_container *sc = - container_of(work, struct o2net_sock_container, - sc_shutdown_work); - struct o2net_node *nn = o2net_nn_from_num(sc->sc_node->nd_num); - - sclog(sc, "shutting down\n"); - - /* drop the callbacks ref and call shutdown only once */ - if (o2net_unregister_callbacks(sc->sc_sock->sk, sc)) { - /* we shouldn't flush as we're in the thread, the - * races with pending sc work structs are harmless */ - del_timer_sync(&sc->sc_idle_timeout); - o2net_sc_cancel_delayed_work(sc, &sc->sc_keepalive_work); - sc_put(sc); - kernel_sock_shutdown(sc->sc_sock, SHUT_RDWR); - } - - /* not fatal so failed connects before the other guy has our - * heartbeat can be retried */ - o2net_ensure_shutdown(nn, sc, 0); - sc_put(sc); -} - -/* ------------------------------------------------------------ */ - -static int o2net_handler_cmp(struct o2net_msg_handler *nmh, u32 msg_type, - u32 key) -{ - int ret = memcmp(&nmh->nh_key, &key, sizeof(key)); - - if (ret == 0) - ret = memcmp(&nmh->nh_msg_type, &msg_type, sizeof(msg_type)); - - return ret; -} - -static struct o2net_msg_handler * -o2net_handler_tree_lookup(u32 msg_type, u32 key, struct rb_node ***ret_p, - struct rb_node **ret_parent) -{ - struct rb_node **p = &o2net_handler_tree.rb_node; - struct rb_node *parent = NULL; - struct o2net_msg_handler *nmh, *ret = NULL; - int cmp; - - while (*p) { - parent = *p; - nmh = rb_entry(parent, struct o2net_msg_handler, nh_node); - cmp = o2net_handler_cmp(nmh, msg_type, key); - - if (cmp < 0) - p = &(*p)->rb_left; - else if (cmp > 0) - p = &(*p)->rb_right; - else { - ret = nmh; - break; - } - } - - if (ret_p != NULL) - *ret_p = p; - if (ret_parent != NULL) - *ret_parent = parent; - - return ret; -} - -static void o2net_handler_kref_release(struct kref *kref) -{ - struct o2net_msg_handler *nmh; - nmh = container_of(kref, struct o2net_msg_handler, nh_kref); - - kfree(nmh); -} - -static void o2net_handler_put(struct o2net_msg_handler *nmh) -{ - kref_put(&nmh->nh_kref, o2net_handler_kref_release); -} - -/* max_len is protection for the handler func. incoming messages won't - * be given to the handler if their payload is longer than the max. */ -int o2net_register_handler(u32 msg_type, u32 key, u32 max_len, - o2net_msg_handler_func *func, void *data, - o2net_post_msg_handler_func *post_func, - struct list_head *unreg_list) -{ - struct o2net_msg_handler *nmh = NULL; - struct rb_node **p, *parent; - int ret = 0; - - if (max_len > O2NET_MAX_PAYLOAD_BYTES) { - mlog(0, "max_len for message handler out of range: %u\n", - max_len); - ret = -EINVAL; - goto out; - } - - if (!msg_type) { - mlog(0, "no message type provided: %u, %p\n", msg_type, func); - ret = -EINVAL; - goto out; - - } - if (!func) { - mlog(0, "no message handler provided: %u, %p\n", - msg_type, func); - ret = -EINVAL; - goto out; - } - - nmh = kzalloc(sizeof(struct o2net_msg_handler), GFP_NOFS); - if (nmh == NULL) { - ret = -ENOMEM; - goto out; - } - - nmh->nh_func = func; - nmh->nh_func_data = data; - nmh->nh_post_func = post_func; - nmh->nh_msg_type = msg_type; - nmh->nh_max_len = max_len; - nmh->nh_key = key; - /* the tree and list get this ref.. they're both removed in - * unregister when this ref is dropped */ - kref_init(&nmh->nh_kref); - INIT_LIST_HEAD(&nmh->nh_unregister_item); - - write_lock(&o2net_handler_lock); - if (o2net_handler_tree_lookup(msg_type, key, &p, &parent)) - ret = -EEXIST; - else { - rb_link_node(&nmh->nh_node, parent, p); - rb_insert_color(&nmh->nh_node, &o2net_handler_tree); - list_add_tail(&nmh->nh_unregister_item, unreg_list); - - mlog(ML_TCP, "registered handler func %p type %u key %08x\n", - func, msg_type, key); - /* we've had some trouble with handlers seemingly vanishing. */ - mlog_bug_on_msg(o2net_handler_tree_lookup(msg_type, key, &p, - &parent) == NULL, - "couldn't find handler we *just* registerd " - "for type %u key %08x\n", msg_type, key); - } - write_unlock(&o2net_handler_lock); - if (ret) - goto out; - -out: - if (ret) - kfree(nmh); - - return ret; -} -EXPORT_SYMBOL_GPL(o2net_register_handler); - -void o2net_unregister_handler_list(struct list_head *list) -{ - struct o2net_msg_handler *nmh, *n; - - write_lock(&o2net_handler_lock); - list_for_each_entry_safe(nmh, n, list, nh_unregister_item) { - mlog(ML_TCP, "unregistering handler func %p type %u key %08x\n", - nmh->nh_func, nmh->nh_msg_type, nmh->nh_key); - rb_erase(&nmh->nh_node, &o2net_handler_tree); - list_del_init(&nmh->nh_unregister_item); - kref_put(&nmh->nh_kref, o2net_handler_kref_release); - } - write_unlock(&o2net_handler_lock); -} -EXPORT_SYMBOL_GPL(o2net_unregister_handler_list); - -static struct o2net_msg_handler *o2net_handler_get(u32 msg_type, u32 key) -{ - struct o2net_msg_handler *nmh; - - read_lock(&o2net_handler_lock); - nmh = o2net_handler_tree_lookup(msg_type, key, NULL, NULL); - if (nmh) - kref_get(&nmh->nh_kref); - read_unlock(&o2net_handler_lock); - - return nmh; -} - -/* ------------------------------------------------------------ */ - -static int o2net_recv_tcp_msg(struct socket *sock, void *data, size_t len) -{ - int ret; - mm_segment_t oldfs; - struct kvec vec = { - .iov_len = len, - .iov_base = data, - }; - struct msghdr msg = { - .msg_iovlen = 1, - .msg_iov = (struct iovec *)&vec, - .msg_flags = MSG_DONTWAIT, - }; - - oldfs = get_fs(); - set_fs(get_ds()); - ret = sock_recvmsg(sock, &msg, len, msg.msg_flags); - set_fs(oldfs); - - return ret; -} - -static int o2net_send_tcp_msg(struct socket *sock, struct kvec *vec, - size_t veclen, size_t total) -{ - int ret; - mm_segment_t oldfs; - struct msghdr msg = { - .msg_iov = (struct iovec *)vec, - .msg_iovlen = veclen, - }; - - if (sock == NULL) { - ret = -EINVAL; - goto out; - } - - oldfs = get_fs(); - set_fs(get_ds()); - ret = sock_sendmsg(sock, &msg, total); - set_fs(oldfs); - if (ret != total) { - mlog(ML_ERROR, "sendmsg returned %d instead of %zu\n", ret, - total); - if (ret >= 0) - ret = -EPIPE; /* should be smarter, I bet */ - goto out; - } - - ret = 0; -out: - if (ret < 0) - mlog(0, "returning error: %d\n", ret); - return ret; -} - -static void o2net_sendpage(struct o2net_sock_container *sc, - void *kmalloced_virt, - size_t size) -{ - struct o2net_node *nn = o2net_nn_from_num(sc->sc_node->nd_num); - ssize_t ret; - - while (1) { - mutex_lock(&sc->sc_send_lock); - ret = sc->sc_sock->ops->sendpage(sc->sc_sock, - virt_to_page(kmalloced_virt), - (long)kmalloced_virt & ~PAGE_MASK, - size, MSG_DONTWAIT); - mutex_unlock(&sc->sc_send_lock); - if (ret == size) - break; - if (ret == (ssize_t)-EAGAIN) { - mlog(0, "sendpage of size %zu to " SC_NODEF_FMT - " returned EAGAIN\n", size, SC_NODEF_ARGS(sc)); - cond_resched(); - continue; - } - mlog(ML_ERROR, "sendpage of size %zu to " SC_NODEF_FMT - " failed with %zd\n", size, SC_NODEF_ARGS(sc), ret); - o2net_ensure_shutdown(nn, sc, 0); - break; - } -} - -static void o2net_init_msg(struct o2net_msg *msg, u16 data_len, u16 msg_type, u32 key) -{ - memset(msg, 0, sizeof(struct o2net_msg)); - msg->magic = cpu_to_be16(O2NET_MSG_MAGIC); - msg->data_len = cpu_to_be16(data_len); - msg->msg_type = cpu_to_be16(msg_type); - msg->sys_status = cpu_to_be32(O2NET_ERR_NONE); - msg->status = 0; - msg->key = cpu_to_be32(key); -} - -static int o2net_tx_can_proceed(struct o2net_node *nn, - struct o2net_sock_container **sc_ret, - int *error) -{ - int ret = 0; - - spin_lock(&nn->nn_lock); - if (nn->nn_persistent_error) { - ret = 1; - *sc_ret = NULL; - *error = nn->nn_persistent_error; - } else if (nn->nn_sc_valid) { - kref_get(&nn->nn_sc->sc_kref); - - ret = 1; - *sc_ret = nn->nn_sc; - *error = 0; - } - spin_unlock(&nn->nn_lock); - - return ret; -} - -/* Get a map of all nodes to which this node is currently connected to */ -void o2net_fill_node_map(unsigned long *map, unsigned bytes) -{ - struct o2net_sock_container *sc; - int node, ret; - - BUG_ON(bytes < (BITS_TO_LONGS(O2NM_MAX_NODES) * sizeof(unsigned long))); - - memset(map, 0, bytes); - for (node = 0; node < O2NM_MAX_NODES; ++node) { - o2net_tx_can_proceed(o2net_nn_from_num(node), &sc, &ret); - if (!ret) { - set_bit(node, map); - sc_put(sc); - } - } -} -EXPORT_SYMBOL_GPL(o2net_fill_node_map); - -int o2net_send_message_vec(u32 msg_type, u32 key, struct kvec *caller_vec, - size_t caller_veclen, u8 target_node, int *status) -{ - int ret = 0; - struct o2net_msg *msg = NULL; - size_t veclen, caller_bytes = 0; - struct kvec *vec = NULL; - struct o2net_sock_container *sc = NULL; - struct o2net_node *nn = o2net_nn_from_num(target_node); - struct o2net_status_wait nsw = { - .ns_node_item = LIST_HEAD_INIT(nsw.ns_node_item), - }; - struct o2net_send_tracking nst; - -#ifdef CONFIG_RAMSTER - /* this may be a general bug fix */ - init_waitqueue_head(&nsw.ns_wq); -#endif - - o2net_init_nst(&nst, msg_type, key, current, target_node); - - if (o2net_wq == NULL) { - mlog(0, "attempt to tx without o2netd running\n"); - ret = -ESRCH; - goto out; - } - - if (caller_veclen == 0) { - mlog(0, "bad kvec array length\n"); - ret = -EINVAL; - goto out; - } - - caller_bytes = iov_length((struct iovec *)caller_vec, caller_veclen); - if (caller_bytes > O2NET_MAX_PAYLOAD_BYTES) { - mlog(0, "total payload len %zu too large\n", caller_bytes); - ret = -EINVAL; - goto out; - } - - if (target_node == o2nm_this_node()) { - ret = -ELOOP; - goto out; - } - - o2net_debug_add_nst(&nst); - - o2net_set_nst_sock_time(&nst); - - wait_event(nn->nn_sc_wq, o2net_tx_can_proceed(nn, &sc, &ret)); - if (ret) - goto out; - - o2net_set_nst_sock_container(&nst, sc); - - veclen = caller_veclen + 1; - vec = kmalloc(sizeof(struct kvec) * veclen, GFP_ATOMIC); - if (vec == NULL) { - mlog(0, "failed to %zu element kvec!\n", veclen); - ret = -ENOMEM; - goto out; - } - - msg = kmalloc(sizeof(struct o2net_msg), GFP_ATOMIC); - if (!msg) { - mlog(0, "failed to allocate a o2net_msg!\n"); - ret = -ENOMEM; - goto out; - } - - o2net_init_msg(msg, caller_bytes, msg_type, key); - - vec[0].iov_len = sizeof(struct o2net_msg); - vec[0].iov_base = msg; - memcpy(&vec[1], caller_vec, caller_veclen * sizeof(struct kvec)); - - ret = o2net_prep_nsw(nn, &nsw); - if (ret) - goto out; - - msg->msg_num = cpu_to_be32(nsw.ns_id); - o2net_set_nst_msg_id(&nst, nsw.ns_id); - - o2net_set_nst_send_time(&nst); - - /* finally, convert the message header to network byte-order - * and send */ - mutex_lock(&sc->sc_send_lock); - ret = o2net_send_tcp_msg(sc->sc_sock, vec, veclen, - sizeof(struct o2net_msg) + caller_bytes); - mutex_unlock(&sc->sc_send_lock); - msglog(msg, "sending returned %d\n", ret); - if (ret < 0) { - mlog(0, "error returned from o2net_send_tcp_msg=%d\n", ret); - goto out; - } - - /* wait on other node's handler */ - o2net_set_nst_status_time(&nst); - wait_event(nsw.ns_wq, o2net_nsw_completed(nn, &nsw)); - - o2net_update_send_stats(&nst, sc); - - /* Note that we avoid overwriting the callers status return - * variable if a system error was reported on the other - * side. Callers beware. */ - ret = o2net_sys_err_to_errno(nsw.ns_sys_status); - if (status && !ret) - *status = nsw.ns_status; - - mlog(0, "woken, returning system status %d, user status %d\n", - ret, nsw.ns_status); -out: - o2net_debug_del_nst(&nst); /* must be before dropping sc and node */ - if (sc) - sc_put(sc); - if (vec) - kfree(vec); - if (msg) - kfree(msg); - o2net_complete_nsw(nn, &nsw, 0, 0, 0); - return ret; -} -EXPORT_SYMBOL_GPL(o2net_send_message_vec); - -int o2net_send_message(u32 msg_type, u32 key, void *data, u32 len, - u8 target_node, int *status) -{ - struct kvec vec = { - .iov_base = data, - .iov_len = len, - }; - return o2net_send_message_vec(msg_type, key, &vec, 1, - target_node, status); -} -EXPORT_SYMBOL_GPL(o2net_send_message); - -static int o2net_send_status_magic(struct socket *sock, struct o2net_msg *hdr, - enum o2net_system_error syserr, int err) -{ - struct kvec vec = { - .iov_base = hdr, - .iov_len = sizeof(struct o2net_msg), - }; - - BUG_ON(syserr >= O2NET_ERR_MAX); - - /* leave other fields intact from the incoming message, msg_num - * in particular */ - hdr->sys_status = cpu_to_be32(syserr); - hdr->status = cpu_to_be32(err); - hdr->magic = cpu_to_be16(O2NET_MSG_STATUS_MAGIC); // twiddle the magic - hdr->data_len = 0; - - msglog(hdr, "about to send status magic %d\n", err); - /* hdr has been in host byteorder this whole time */ - return o2net_send_tcp_msg(sock, &vec, 1, sizeof(struct o2net_msg)); -} - -#ifdef CONFIG_RAMSTER -/* - * "data magic" is a long version of "status magic" where the message - * payload actually contains data to be passed in reply to certain messages - */ -static int o2net_send_data_magic(struct o2net_sock_container *sc, - struct o2net_msg *hdr, - void *data, size_t data_len, - enum o2net_system_error syserr, int err) -{ - struct kvec vec[2]; - int ret; - - vec[0].iov_base = hdr; - vec[0].iov_len = sizeof(struct o2net_msg); - vec[1].iov_base = data; - vec[1].iov_len = data_len; - - BUG_ON(syserr >= O2NET_ERR_MAX); - - /* leave other fields intact from the incoming message, msg_num - * in particular */ - hdr->sys_status = cpu_to_be32(syserr); - hdr->status = cpu_to_be32(err); - hdr->magic = cpu_to_be16(O2NET_MSG_DATA_MAGIC); /* twiddle magic */ - hdr->data_len = cpu_to_be16(data_len); - - msglog(hdr, "about to send data magic %d\n", err); - /* hdr has been in host byteorder this whole time */ - ret = o2net_send_tcp_msg(sc->sc_sock, vec, 2, - sizeof(struct o2net_msg) + data_len); - return ret; -} - -/* - * called by a message handler to convert an otherwise normal reply - * message into a "data magic" message - */ -void o2net_force_data_magic(struct o2net_msg *hdr, u16 msgtype, u32 msgkey) -{ - hdr->magic = cpu_to_be16(O2NET_MSG_DATA_MAGIC); - hdr->msg_type = cpu_to_be16(msgtype); - hdr->key = cpu_to_be32(msgkey); -} -#endif - -/* this returns -errno if the header was unknown or too large, etc. - * after this is called the buffer us reused for the next message */ -static int o2net_process_message(struct o2net_sock_container *sc, - struct o2net_msg *hdr) -{ - struct o2net_node *nn = o2net_nn_from_num(sc->sc_node->nd_num); - int ret = 0, handler_status; - enum o2net_system_error syserr; - struct o2net_msg_handler *nmh = NULL; - void *ret_data = NULL; -#ifdef CONFIG_RAMSTER - int data_magic = 0; -#endif - - msglog(hdr, "processing message\n"); - - o2net_sc_postpone_idle(sc); - - switch(be16_to_cpu(hdr->magic)) { - case O2NET_MSG_STATUS_MAGIC: - /* special type for returning message status */ - o2net_complete_nsw(nn, NULL, - be32_to_cpu(hdr->msg_num), - be32_to_cpu(hdr->sys_status), - be32_to_cpu(hdr->status)); - goto out; - case O2NET_MSG_KEEP_REQ_MAGIC: - o2net_sendpage(sc, o2net_keep_resp, - sizeof(*o2net_keep_resp)); - goto out; - case O2NET_MSG_KEEP_RESP_MAGIC: - goto out; - case O2NET_MSG_MAGIC: - break; -#ifdef CONFIG_RAMSTER - case O2NET_MSG_DATA_MAGIC: - /* - * unlike a normal status magic, a data magic DOES - * (MUST) have a handler, so the control flow is - * a little funky here as a result - */ - data_magic = 1; - break; -#endif - default: - msglog(hdr, "bad magic\n"); - ret = -EINVAL; - goto out; - break; - } - - /* find a handler for it */ - handler_status = 0; - nmh = o2net_handler_get(be16_to_cpu(hdr->msg_type), - be32_to_cpu(hdr->key)); - if (!nmh) { - mlog(ML_TCP, "couldn't find handler for type %u key %08x\n", - be16_to_cpu(hdr->msg_type), be32_to_cpu(hdr->key)); - syserr = O2NET_ERR_NO_HNDLR; - goto out_respond; - } - - syserr = O2NET_ERR_NONE; - - if (be16_to_cpu(hdr->data_len) > nmh->nh_max_len) - syserr = O2NET_ERR_OVERFLOW; - - if (syserr != O2NET_ERR_NONE) - goto out_respond; - - o2net_set_func_start_time(sc); - sc->sc_msg_key = be32_to_cpu(hdr->key); - sc->sc_msg_type = be16_to_cpu(hdr->msg_type); - handler_status = (nmh->nh_func)(hdr, sizeof(struct o2net_msg) + - be16_to_cpu(hdr->data_len), - nmh->nh_func_data, &ret_data); -#ifdef CONFIG_RAMSTER - if (data_magic) { - /* - * handler handled data sent in reply to request - * so complete the transaction - */ - o2net_complete_nsw(nn, NULL, be32_to_cpu(hdr->msg_num), - be32_to_cpu(hdr->sys_status), handler_status); - goto out; - } - /* - * handler changed magic to DATA_MAGIC to reply to request for data, - * implies ret_data points to data to return and handler_status - * is the number of bytes of data - */ - if (be16_to_cpu(hdr->magic) == O2NET_MSG_DATA_MAGIC) { - ret = o2net_send_data_magic(sc, hdr, - ret_data, handler_status, - syserr, 0); - hdr = NULL; - mlog(0, "sending data reply %d, syserr %d returned %d\n", - handler_status, syserr, ret); - o2net_set_func_stop_time(sc); - - o2net_update_recv_stats(sc); - goto out; - } -#endif - o2net_set_func_stop_time(sc); - - o2net_update_recv_stats(sc); - -out_respond: - /* this destroys the hdr, so don't use it after this */ - mutex_lock(&sc->sc_send_lock); - ret = o2net_send_status_magic(sc->sc_sock, hdr, syserr, - handler_status); - mutex_unlock(&sc->sc_send_lock); - hdr = NULL; - mlog(0, "sending handler status %d, syserr %d returned %d\n", - handler_status, syserr, ret); - - if (nmh) { - BUG_ON(ret_data != NULL && nmh->nh_post_func == NULL); - if (nmh->nh_post_func) - (nmh->nh_post_func)(handler_status, nmh->nh_func_data, - ret_data); - } - -out: - if (nmh) - o2net_handler_put(nmh); - return ret; -} - -static int o2net_check_handshake(struct o2net_sock_container *sc) -{ - struct o2net_handshake *hand = page_address(sc->sc_page); - struct o2net_node *nn = o2net_nn_from_num(sc->sc_node->nd_num); - - if (hand->protocol_version != cpu_to_be64(O2NET_PROTOCOL_VERSION)) { - printk(KERN_NOTICE "o2net: " SC_NODEF_FMT " Advertised net " - "protocol version %llu but %llu is required. " - "Disconnecting.\n", SC_NODEF_ARGS(sc), - (unsigned long long)be64_to_cpu(hand->protocol_version), - O2NET_PROTOCOL_VERSION); - - /* don't bother reconnecting if its the wrong version. */ - o2net_ensure_shutdown(nn, sc, -ENOTCONN); - return -1; - } - - /* - * Ensure timeouts are consistent with other nodes, otherwise - * we can end up with one node thinking that the other must be down, - * but isn't. This can ultimately cause corruption. - */ - if (be32_to_cpu(hand->o2net_idle_timeout_ms) != - o2net_idle_timeout()) { - printk(KERN_NOTICE "o2net: " SC_NODEF_FMT " uses a network " - "idle timeout of %u ms, but we use %u ms locally. " - "Disconnecting.\n", SC_NODEF_ARGS(sc), - be32_to_cpu(hand->o2net_idle_timeout_ms), - o2net_idle_timeout()); - o2net_ensure_shutdown(nn, sc, -ENOTCONN); - return -1; - } - - if (be32_to_cpu(hand->o2net_keepalive_delay_ms) != - o2net_keepalive_delay()) { - printk(KERN_NOTICE "o2net: " SC_NODEF_FMT " uses a keepalive " - "delay of %u ms, but we use %u ms locally. " - "Disconnecting.\n", SC_NODEF_ARGS(sc), - be32_to_cpu(hand->o2net_keepalive_delay_ms), - o2net_keepalive_delay()); - o2net_ensure_shutdown(nn, sc, -ENOTCONN); - return -1; - } - - if (be32_to_cpu(hand->o2hb_heartbeat_timeout_ms) != - O2HB_MAX_WRITE_TIMEOUT_MS) { - printk(KERN_NOTICE "o2net: " SC_NODEF_FMT " uses a heartbeat " - "timeout of %u ms, but we use %u ms locally. " - "Disconnecting.\n", SC_NODEF_ARGS(sc), - be32_to_cpu(hand->o2hb_heartbeat_timeout_ms), - O2HB_MAX_WRITE_TIMEOUT_MS); - o2net_ensure_shutdown(nn, sc, -ENOTCONN); - return -1; - } - - sc->sc_handshake_ok = 1; - - spin_lock(&nn->nn_lock); - /* set valid and queue the idle timers only if it hasn't been - * shut down already */ - if (nn->nn_sc == sc) { - o2net_sc_reset_idle_timer(sc); - atomic_set(&nn->nn_timeout, 0); - o2net_set_nn_state(nn, sc, 1, 0); - } - spin_unlock(&nn->nn_lock); - - /* shift everything up as though it wasn't there */ - sc->sc_page_off -= sizeof(struct o2net_handshake); - if (sc->sc_page_off) - memmove(hand, hand + 1, sc->sc_page_off); - - return 0; -} - -/* this demuxes the queued rx bytes into header or payload bits and calls - * handlers as each full message is read off the socket. it returns -error, - * == 0 eof, or > 0 for progress made.*/ -static int o2net_advance_rx(struct o2net_sock_container *sc) -{ - struct o2net_msg *hdr; - int ret = 0; - void *data; - size_t datalen; - - sclog(sc, "receiving\n"); - o2net_set_advance_start_time(sc); - - if (unlikely(sc->sc_handshake_ok == 0)) { - if(sc->sc_page_off < sizeof(struct o2net_handshake)) { - data = page_address(sc->sc_page) + sc->sc_page_off; - datalen = sizeof(struct o2net_handshake) - sc->sc_page_off; - ret = o2net_recv_tcp_msg(sc->sc_sock, data, datalen); - if (ret > 0) - sc->sc_page_off += ret; - } - - if (sc->sc_page_off == sizeof(struct o2net_handshake)) { - o2net_check_handshake(sc); - if (unlikely(sc->sc_handshake_ok == 0)) - ret = -EPROTO; - } - goto out; - } - - /* do we need more header? */ - if (sc->sc_page_off < sizeof(struct o2net_msg)) { - data = page_address(sc->sc_page) + sc->sc_page_off; - datalen = sizeof(struct o2net_msg) - sc->sc_page_off; - ret = o2net_recv_tcp_msg(sc->sc_sock, data, datalen); - if (ret > 0) { - sc->sc_page_off += ret; - /* only swab incoming here.. we can - * only get here once as we cross from - * being under to over */ - if (sc->sc_page_off == sizeof(struct o2net_msg)) { - hdr = page_address(sc->sc_page); - if (be16_to_cpu(hdr->data_len) > - O2NET_MAX_PAYLOAD_BYTES) - ret = -EOVERFLOW; - } - } - if (ret <= 0) - goto out; - } - - if (sc->sc_page_off < sizeof(struct o2net_msg)) { - /* oof, still don't have a header */ - goto out; - } - - /* this was swabbed above when we first read it */ - hdr = page_address(sc->sc_page); - - msglog(hdr, "at page_off %zu\n", sc->sc_page_off); - - /* do we need more payload? */ - if (sc->sc_page_off - sizeof(struct o2net_msg) < be16_to_cpu(hdr->data_len)) { - /* need more payload */ - data = page_address(sc->sc_page) + sc->sc_page_off; - datalen = (sizeof(struct o2net_msg) + be16_to_cpu(hdr->data_len)) - - sc->sc_page_off; - ret = o2net_recv_tcp_msg(sc->sc_sock, data, datalen); - if (ret > 0) - sc->sc_page_off += ret; - if (ret <= 0) - goto out; - } - - if (sc->sc_page_off - sizeof(struct o2net_msg) == be16_to_cpu(hdr->data_len)) { - /* we can only get here once, the first time we read - * the payload.. so set ret to progress if the handler - * works out. after calling this the message is toast */ - ret = o2net_process_message(sc, hdr); - if (ret == 0) - ret = 1; - sc->sc_page_off = 0; - } - -out: - sclog(sc, "ret = %d\n", ret); - o2net_set_advance_stop_time(sc); - return ret; -} - -/* this work func is triggerd by data ready. it reads until it can read no - * more. it interprets 0, eof, as fatal. if data_ready hits while we're doing - * our work the work struct will be marked and we'll be called again. */ -static void o2net_rx_until_empty(struct work_struct *work) -{ - struct o2net_sock_container *sc = - container_of(work, struct o2net_sock_container, sc_rx_work); - int ret; - - do { - ret = o2net_advance_rx(sc); - } while (ret > 0); - - if (ret <= 0 && ret != -EAGAIN) { - struct o2net_node *nn = o2net_nn_from_num(sc->sc_node->nd_num); - sclog(sc, "saw error %d, closing\n", ret); - /* not permanent so read failed handshake can retry */ - o2net_ensure_shutdown(nn, sc, 0); - } - - sc_put(sc); -} - -static int o2net_set_nodelay(struct socket *sock) -{ - int ret, val = 1; - mm_segment_t oldfs; - - oldfs = get_fs(); - set_fs(KERNEL_DS); - - /* - * Dear unsuspecting programmer, - * - * Don't use sock_setsockopt() for SOL_TCP. It doesn't check its level - * argument and assumes SOL_SOCKET so, say, your TCP_NODELAY will - * silently turn into SO_DEBUG. - * - * Yours, - * Keeper of hilariously fragile interfaces. - */ - ret = sock->ops->setsockopt(sock, SOL_TCP, TCP_NODELAY, - (char __user *)&val, sizeof(val)); - - set_fs(oldfs); - return ret; -} - -static void o2net_initialize_handshake(void) -{ - o2net_hand->o2hb_heartbeat_timeout_ms = cpu_to_be32( - O2HB_MAX_WRITE_TIMEOUT_MS); - o2net_hand->o2net_idle_timeout_ms = cpu_to_be32(o2net_idle_timeout()); - o2net_hand->o2net_keepalive_delay_ms = cpu_to_be32( - o2net_keepalive_delay()); - o2net_hand->o2net_reconnect_delay_ms = cpu_to_be32( - o2net_reconnect_delay()); -} - -/* ------------------------------------------------------------ */ - -/* called when a connect completes and after a sock is accepted. the - * rx path will see the response and mark the sc valid */ -static void o2net_sc_connect_completed(struct work_struct *work) -{ - struct o2net_sock_container *sc = - container_of(work, struct o2net_sock_container, - sc_connect_work); - - mlog(ML_MSG, "sc sending handshake with ver %llu id %llx\n", - (unsigned long long)O2NET_PROTOCOL_VERSION, - (unsigned long long)be64_to_cpu(o2net_hand->connector_id)); - - o2net_initialize_handshake(); - o2net_sendpage(sc, o2net_hand, sizeof(*o2net_hand)); - sc_put(sc); -} - -/* this is called as a work_struct func. */ -static void o2net_sc_send_keep_req(struct work_struct *work) -{ - struct o2net_sock_container *sc = - container_of(work, struct o2net_sock_container, - sc_keepalive_work.work); - - o2net_sendpage(sc, o2net_keep_req, sizeof(*o2net_keep_req)); - sc_put(sc); -} - -/* socket shutdown does a del_timer_sync against this as it tears down. - * we can't start this timer until we've got to the point in sc buildup - * where shutdown is going to be involved */ -static void o2net_idle_timer(unsigned long data) -{ - struct o2net_sock_container *sc = (struct o2net_sock_container *)data; -#ifndef CONFIG_RAMSTER - struct o2net_node *nn = o2net_nn_from_num(sc->sc_node->nd_num); -#endif -#ifdef CONFIG_DEBUG_FS - unsigned long msecs = ktime_to_ms(ktime_get()) - - ktime_to_ms(sc->sc_tv_timer); -#else - unsigned long msecs = o2net_idle_timeout(); -#endif - - printk(KERN_NOTICE "o2net: Connection to " SC_NODEF_FMT " has been " - "idle for %lu.%lu secs, shutting it down.\n", SC_NODEF_ARGS(sc), - msecs / 1000, msecs % 1000); - - /* - * Initialize the nn_timeout so that the next connection attempt - * will continue in o2net_start_connect. - */ -#ifdef CONFIG_RAMSTER - /* Avoid spurious shutdowns... not sure if this is still necessary */ - pr_err("o2net_idle_timer, skipping shutdown work\n"); -#else - atomic_set(&nn->nn_timeout, 1); - - o2net_sc_queue_work(sc, &sc->sc_shutdown_work); -#endif -} - -static void o2net_sc_reset_idle_timer(struct o2net_sock_container *sc) -{ - o2net_sc_cancel_delayed_work(sc, &sc->sc_keepalive_work); - o2net_sc_queue_delayed_work(sc, &sc->sc_keepalive_work, - msecs_to_jiffies(o2net_keepalive_delay())); - o2net_set_sock_timer(sc); - mod_timer(&sc->sc_idle_timeout, - jiffies + msecs_to_jiffies(o2net_idle_timeout())); -} - -static void o2net_sc_postpone_idle(struct o2net_sock_container *sc) -{ - /* Only push out an existing timer */ - if (timer_pending(&sc->sc_idle_timeout)) - o2net_sc_reset_idle_timer(sc); -} - -/* this work func is kicked whenever a path sets the nn state which doesn't - * have valid set. This includes seeing hb come up, losing a connection, - * having a connect attempt fail, etc. This centralizes the logic which decides - * if a connect attempt should be made or if we should give up and all future - * transmit attempts should fail */ -static void o2net_start_connect(struct work_struct *work) -{ - struct o2net_node *nn = - container_of(work, struct o2net_node, nn_connect_work.work); - struct o2net_sock_container *sc = NULL; - struct o2nm_node *node = NULL, *mynode = NULL; - struct socket *sock = NULL; - struct sockaddr_in myaddr = {0, }, remoteaddr = {0, }; - int ret = 0, stop; - unsigned int timeout; - - /* if we're greater we initiate tx, otherwise we accept */ - if (o2nm_this_node() <= o2net_num_from_nn(nn)) - goto out; - - /* watch for racing with tearing a node down */ - node = o2nm_get_node_by_num(o2net_num_from_nn(nn)); - if (node == NULL) { - ret = 0; - goto out; - } - - mynode = o2nm_get_node_by_num(o2nm_this_node()); - if (mynode == NULL) { - ret = 0; - goto out; - } - - spin_lock(&nn->nn_lock); - /* - * see if we already have one pending or have given up. - * For nn_timeout, it is set when we close the connection - * because of the idle time out. So it means that we have - * at least connected to that node successfully once, - * now try to connect to it again. - */ - timeout = atomic_read(&nn->nn_timeout); - stop = (nn->nn_sc || - (nn->nn_persistent_error && - (nn->nn_persistent_error != -ENOTCONN || timeout == 0))); - spin_unlock(&nn->nn_lock); - if (stop) - goto out; - - nn->nn_last_connect_attempt = jiffies; - - sc = sc_alloc(node); - if (sc == NULL) { - mlog(0, "couldn't allocate sc\n"); - ret = -ENOMEM; - goto out; - } - - ret = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock); - if (ret < 0) { - mlog(0, "can't create socket: %d\n", ret); - goto out; - } - sc->sc_sock = sock; /* freed by sc_kref_release */ - - sock->sk->sk_allocation = GFP_ATOMIC; - - myaddr.sin_family = AF_INET; - myaddr.sin_addr.s_addr = mynode->nd_ipv4_address; - myaddr.sin_port = htons(0); /* any port */ - - ret = sock->ops->bind(sock, (struct sockaddr *)&myaddr, - sizeof(myaddr)); - if (ret) { - mlog(ML_ERROR, "bind failed with %d at address %pI4\n", - ret, &mynode->nd_ipv4_address); - goto out; - } - - ret = o2net_set_nodelay(sc->sc_sock); - if (ret) { - mlog(ML_ERROR, "setting TCP_NODELAY failed with %d\n", ret); - goto out; - } - - o2net_register_callbacks(sc->sc_sock->sk, sc); - - spin_lock(&nn->nn_lock); - /* handshake completion will set nn->nn_sc_valid */ - o2net_set_nn_state(nn, sc, 0, 0); - spin_unlock(&nn->nn_lock); - - remoteaddr.sin_family = AF_INET; - remoteaddr.sin_addr.s_addr = node->nd_ipv4_address; - remoteaddr.sin_port = node->nd_ipv4_port; - - ret = sc->sc_sock->ops->connect(sc->sc_sock, - (struct sockaddr *)&remoteaddr, - sizeof(remoteaddr), - O_NONBLOCK); - if (ret == -EINPROGRESS) - ret = 0; - -out: - if (ret) { - printk(KERN_NOTICE "o2net: Connect attempt to " SC_NODEF_FMT - " failed with errno %d\n", SC_NODEF_ARGS(sc), ret); - /* 0 err so that another will be queued and attempted - * from set_nn_state */ - if (sc) - o2net_ensure_shutdown(nn, sc, 0); - } - if (sc) - sc_put(sc); - if (node) - o2nm_node_put(node); - if (mynode) - o2nm_node_put(mynode); - - return; -} - -static void o2net_connect_expired(struct work_struct *work) -{ - struct o2net_node *nn = - container_of(work, struct o2net_node, nn_connect_expired.work); - - spin_lock(&nn->nn_lock); - if (!nn->nn_sc_valid) { - printk(KERN_NOTICE "o2net: No connection established with " - "node %u after %u.%u seconds, giving up.\n", - o2net_num_from_nn(nn), - o2net_idle_timeout() / 1000, - o2net_idle_timeout() % 1000); - - o2net_set_nn_state(nn, NULL, 0, -ENOTCONN); - } - spin_unlock(&nn->nn_lock); -} - -static void o2net_still_up(struct work_struct *work) -{ - struct o2net_node *nn = - container_of(work, struct o2net_node, nn_still_up.work); - - o2quo_hb_still_up(o2net_num_from_nn(nn)); -} - -/* ------------------------------------------------------------ */ - -void o2net_disconnect_node(struct o2nm_node *node) -{ - struct o2net_node *nn = o2net_nn_from_num(node->nd_num); - - /* don't reconnect until it's heartbeating again */ - spin_lock(&nn->nn_lock); - atomic_set(&nn->nn_timeout, 0); - o2net_set_nn_state(nn, NULL, 0, -ENOTCONN); - spin_unlock(&nn->nn_lock); - - if (o2net_wq) { - cancel_delayed_work(&nn->nn_connect_expired); - cancel_delayed_work(&nn->nn_connect_work); - cancel_delayed_work(&nn->nn_still_up); - flush_workqueue(o2net_wq); - } -} - -static void o2net_hb_node_down_cb(struct o2nm_node *node, int node_num, - void *data) -{ - o2quo_hb_down(node_num); - - if (!node) - return; - - if (node_num != o2nm_this_node()) - o2net_disconnect_node(node); - - BUG_ON(atomic_read(&o2net_connected_peers) < 0); -} - -static void o2net_hb_node_up_cb(struct o2nm_node *node, int node_num, - void *data) -{ - struct o2net_node *nn = o2net_nn_from_num(node_num); - - o2quo_hb_up(node_num); - - BUG_ON(!node); - - /* ensure an immediate connect attempt */ - nn->nn_last_connect_attempt = jiffies - - (msecs_to_jiffies(o2net_reconnect_delay()) + 1); - - if (node_num != o2nm_this_node()) { - /* believe it or not, accept and node hearbeating testing - * can succeed for this node before we got here.. so - * only use set_nn_state to clear the persistent error - * if that hasn't already happened */ - spin_lock(&nn->nn_lock); - atomic_set(&nn->nn_timeout, 0); - if (nn->nn_persistent_error) - o2net_set_nn_state(nn, NULL, 0, 0); - spin_unlock(&nn->nn_lock); - } -} - -void o2net_unregister_hb_callbacks(void) -{ - o2hb_unregister_callback(NULL, &o2net_hb_up); - o2hb_unregister_callback(NULL, &o2net_hb_down); -} - -int o2net_register_hb_callbacks(void) -{ - int ret; - - o2hb_setup_callback(&o2net_hb_down, O2HB_NODE_DOWN_CB, - o2net_hb_node_down_cb, NULL, O2NET_HB_PRI); - o2hb_setup_callback(&o2net_hb_up, O2HB_NODE_UP_CB, - o2net_hb_node_up_cb, NULL, O2NET_HB_PRI); - - ret = o2hb_register_callback(NULL, &o2net_hb_up); - if (ret == 0) - ret = o2hb_register_callback(NULL, &o2net_hb_down); - - if (ret) - o2net_unregister_hb_callbacks(); - - return ret; -} - -/* ------------------------------------------------------------ */ - -static int o2net_accept_one(struct socket *sock) -{ - int ret, slen; - struct sockaddr_in sin; - struct socket *new_sock = NULL; - struct o2nm_node *node = NULL; - struct o2nm_node *local_node = NULL; - struct o2net_sock_container *sc = NULL; - struct o2net_node *nn; - - BUG_ON(sock == NULL); - ret = sock_create_lite(sock->sk->sk_family, sock->sk->sk_type, - sock->sk->sk_protocol, &new_sock); - if (ret) - goto out; - - new_sock->type = sock->type; - new_sock->ops = sock->ops; - ret = sock->ops->accept(sock, new_sock, O_NONBLOCK); - if (ret < 0) - goto out; - - new_sock->sk->sk_allocation = GFP_ATOMIC; - - ret = o2net_set_nodelay(new_sock); - if (ret) { - mlog(ML_ERROR, "setting TCP_NODELAY failed with %d\n", ret); - goto out; - } - - slen = sizeof(sin); - ret = new_sock->ops->getname(new_sock, (struct sockaddr *) &sin, - &slen, 1); - if (ret < 0) - goto out; - - node = o2nm_get_node_by_ip(sin.sin_addr.s_addr); - if (node == NULL) { - printk(KERN_NOTICE "o2net: Attempt to connect from unknown " - "node at %pI4:%d\n", &sin.sin_addr.s_addr, - ntohs(sin.sin_port)); - ret = -EINVAL; - goto out; - } - - if (o2nm_this_node() >= node->nd_num) { - local_node = o2nm_get_node_by_num(o2nm_this_node()); - printk(KERN_NOTICE "o2net: Unexpected connect attempt seen " - "at node '%s' (%u, %pI4:%d) from node '%s' (%u, " - "%pI4:%d)\n", local_node->nd_name, local_node->nd_num, - &(local_node->nd_ipv4_address), - ntohs(local_node->nd_ipv4_port), node->nd_name, - node->nd_num, &sin.sin_addr.s_addr, ntohs(sin.sin_port)); - ret = -EINVAL; - goto out; - } - - /* this happens all the time when the other node sees our heartbeat - * and tries to connect before we see their heartbeat */ - if (!o2hb_check_node_heartbeating_from_callback(node->nd_num)) { - mlog(ML_CONN, "attempt to connect from node '%s' at " - "%pI4:%d but it isn't heartbeating\n", - node->nd_name, &sin.sin_addr.s_addr, - ntohs(sin.sin_port)); - ret = -EINVAL; - goto out; - } - - nn = o2net_nn_from_num(node->nd_num); - - spin_lock(&nn->nn_lock); - if (nn->nn_sc) - ret = -EBUSY; - else - ret = 0; - spin_unlock(&nn->nn_lock); - if (ret) { - printk(KERN_NOTICE "o2net: Attempt to connect from node '%s' " - "at %pI4:%d but it already has an open connection\n", - node->nd_name, &sin.sin_addr.s_addr, - ntohs(sin.sin_port)); - goto out; - } - - sc = sc_alloc(node); - if (sc == NULL) { - ret = -ENOMEM; - goto out; - } - - sc->sc_sock = new_sock; - new_sock = NULL; - - spin_lock(&nn->nn_lock); - atomic_set(&nn->nn_timeout, 0); - o2net_set_nn_state(nn, sc, 0, 0); - spin_unlock(&nn->nn_lock); - - o2net_register_callbacks(sc->sc_sock->sk, sc); - o2net_sc_queue_work(sc, &sc->sc_rx_work); - - o2net_initialize_handshake(); - o2net_sendpage(sc, o2net_hand, sizeof(*o2net_hand)); - -out: - if (new_sock) - sock_release(new_sock); - if (node) - o2nm_node_put(node); - if (local_node) - o2nm_node_put(local_node); - if (sc) - sc_put(sc); - return ret; -} - -static void o2net_accept_many(struct work_struct *work) -{ - struct socket *sock = o2net_listen_sock; - while (o2net_accept_one(sock) == 0) - cond_resched(); -} - -static void o2net_listen_data_ready(struct sock *sk, int bytes) -{ - void (*ready)(struct sock *sk, int bytes); - - read_lock(&sk->sk_callback_lock); - ready = sk->sk_user_data; - if (ready == NULL) { /* check for teardown race */ - ready = sk->sk_data_ready; - goto out; - } - - /* ->sk_data_ready is also called for a newly established child socket - * before it has been accepted and the acceptor has set up their - * data_ready.. we only want to queue listen work for our listening - * socket */ - if (sk->sk_state == TCP_LISTEN) { - mlog(ML_TCP, "bytes: %d\n", bytes); - queue_work(o2net_wq, &o2net_listen_work); - } - -out: - read_unlock(&sk->sk_callback_lock); - ready(sk, bytes); -} - -static int o2net_open_listening_sock(__be32 addr, __be16 port) -{ - struct socket *sock = NULL; - int ret; - struct sockaddr_in sin = { - .sin_family = PF_INET, - .sin_addr = { .s_addr = addr }, - .sin_port = port, - }; - - ret = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock); - if (ret < 0) { - printk(KERN_ERR "o2net: Error %d while creating socket\n", ret); - goto out; - } - - sock->sk->sk_allocation = GFP_ATOMIC; - - write_lock_bh(&sock->sk->sk_callback_lock); - sock->sk->sk_user_data = sock->sk->sk_data_ready; - sock->sk->sk_data_ready = o2net_listen_data_ready; - write_unlock_bh(&sock->sk->sk_callback_lock); - - o2net_listen_sock = sock; - INIT_WORK(&o2net_listen_work, o2net_accept_many); - - sock->sk->sk_reuse = 1; - ret = sock->ops->bind(sock, (struct sockaddr *)&sin, sizeof(sin)); - if (ret < 0) { - printk(KERN_ERR "o2net: Error %d while binding socket at " - "%pI4:%u\n", ret, &addr, ntohs(port)); - goto out; - } - - ret = sock->ops->listen(sock, 64); - if (ret < 0) - printk(KERN_ERR "o2net: Error %d while listening on %pI4:%u\n", - ret, &addr, ntohs(port)); - -out: - if (ret) { - o2net_listen_sock = NULL; - if (sock) - sock_release(sock); - } - return ret; -} - -/* - * called from node manager when we should bring up our network listening - * socket. node manager handles all the serialization to only call this - * once and to match it with o2net_stop_listening(). note, - * o2nm_this_node() doesn't work yet as we're being called while it - * is being set up. - */ -int o2net_start_listening(struct o2nm_node *node) -{ - int ret = 0; - - BUG_ON(o2net_wq != NULL); - BUG_ON(o2net_listen_sock != NULL); - - mlog(ML_KTHREAD, "starting o2net thread...\n"); - o2net_wq = create_singlethread_workqueue("o2net"); - if (o2net_wq == NULL) { - mlog(ML_ERROR, "unable to launch o2net thread\n"); - return -ENOMEM; /* ? */ - } - - ret = o2net_open_listening_sock(node->nd_ipv4_address, - node->nd_ipv4_port); - if (ret) { - destroy_workqueue(o2net_wq); - o2net_wq = NULL; - } else - o2quo_conn_up(node->nd_num); - - return ret; -} - -/* again, o2nm_this_node() doesn't work here as we're involved in - * tearing it down */ -void o2net_stop_listening(struct o2nm_node *node) -{ - struct socket *sock = o2net_listen_sock; - size_t i; - - BUG_ON(o2net_wq == NULL); - BUG_ON(o2net_listen_sock == NULL); - - /* stop the listening socket from generating work */ - write_lock_bh(&sock->sk->sk_callback_lock); - sock->sk->sk_data_ready = sock->sk->sk_user_data; - sock->sk->sk_user_data = NULL; - write_unlock_bh(&sock->sk->sk_callback_lock); - - for (i = 0; i < ARRAY_SIZE(o2net_nodes); i++) { - struct o2nm_node *node = o2nm_get_node_by_num(i); - if (node) { - o2net_disconnect_node(node); - o2nm_node_put(node); - } - } - - /* finish all work and tear down the work queue */ - mlog(ML_KTHREAD, "waiting for o2net thread to exit....\n"); - destroy_workqueue(o2net_wq); - o2net_wq = NULL; - - sock_release(o2net_listen_sock); - o2net_listen_sock = NULL; - - o2quo_conn_err(node->nd_num); -} - -#ifdef CONFIG_RAMSTER -void o2net_hb_node_up_manual(int node_num) -{ - struct o2nm_node dummy; - o2hb_manual_set_node_heartbeating(node_num); - o2net_hb_node_up_cb(&dummy, node_num, NULL); -} -#endif - -/* ------------------------------------------------------------ */ - -int o2net_init(void) -{ - unsigned long i; - - o2quo_init(); - - if (o2net_debugfs_init()) - return -ENOMEM; - - o2net_hand = kzalloc(sizeof(struct o2net_handshake), GFP_KERNEL); - o2net_keep_req = kzalloc(sizeof(struct o2net_msg), GFP_KERNEL); - o2net_keep_resp = kzalloc(sizeof(struct o2net_msg), GFP_KERNEL); - if (!o2net_hand || !o2net_keep_req || !o2net_keep_resp) { - kfree(o2net_hand); - kfree(o2net_keep_req); - kfree(o2net_keep_resp); - return -ENOMEM; - } - - o2net_hand->protocol_version = cpu_to_be64(O2NET_PROTOCOL_VERSION); - o2net_hand->connector_id = cpu_to_be64(1); - - o2net_keep_req->magic = cpu_to_be16(O2NET_MSG_KEEP_REQ_MAGIC); - o2net_keep_resp->magic = cpu_to_be16(O2NET_MSG_KEEP_RESP_MAGIC); - - for (i = 0; i < ARRAY_SIZE(o2net_nodes); i++) { - struct o2net_node *nn = o2net_nn_from_num(i); - - atomic_set(&nn->nn_timeout, 0); - spin_lock_init(&nn->nn_lock); - INIT_DELAYED_WORK(&nn->nn_connect_work, o2net_start_connect); - INIT_DELAYED_WORK(&nn->nn_connect_expired, - o2net_connect_expired); - INIT_DELAYED_WORK(&nn->nn_still_up, o2net_still_up); - /* until we see hb from a node we'll return einval */ - nn->nn_persistent_error = -ENOTCONN; - init_waitqueue_head(&nn->nn_sc_wq); - idr_init(&nn->nn_status_idr); - INIT_LIST_HEAD(&nn->nn_status_list); - } - - return 0; -} - -void o2net_exit(void) -{ - o2quo_exit(); - kfree(o2net_hand); - kfree(o2net_keep_req); - kfree(o2net_keep_resp); - o2net_debugfs_exit(); -} diff --git a/drivers/staging/ramster/cluster/tcp.h b/drivers/staging/ramster/cluster/tcp.h deleted file mode 100644 index 95a991f..0000000 --- a/drivers/staging/ramster/cluster/tcp.h +++ /dev/null @@ -1,160 +0,0 @@ -/* -*- mode: c; c-basic-offset: 8; -*- - * vim: noexpandtab sw=8 ts=8 sts=0: - * - * tcp.h - * - * Function prototypes - * - * Copyright (C) 2004 Oracle. All rights reserved. - * - * 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; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 021110-1307, USA. - * - */ - -#ifndef O2CLUSTER_TCP_H -#define O2CLUSTER_TCP_H - -#include -#ifdef __KERNEL__ -#include -#include -#else -#include -#endif -#include -#include - -struct o2net_msg -{ - __be16 magic; - __be16 data_len; - __be16 msg_type; - __be16 pad1; - __be32 sys_status; - __be32 status; - __be32 key; - __be32 msg_num; - __u8 buf[0]; -}; - -typedef int (o2net_msg_handler_func)(struct o2net_msg *msg, u32 len, void *data, - void **ret_data); -typedef void (o2net_post_msg_handler_func)(int status, void *data, - void *ret_data); - -#define O2NET_MAX_PAYLOAD_BYTES (4096 - sizeof(struct o2net_msg)) - -/* same as hb delay, we're waiting for another node to recognize our hb */ -#define O2NET_RECONNECT_DELAY_MS_DEFAULT 2000 - -#define O2NET_KEEPALIVE_DELAY_MS_DEFAULT 2000 -#define O2NET_IDLE_TIMEOUT_MS_DEFAULT 30000 - - -/* TODO: figure this out.... */ -static inline int o2net_link_down(int err, struct socket *sock) -{ - if (sock) { - if (sock->sk->sk_state != TCP_ESTABLISHED && - sock->sk->sk_state != TCP_CLOSE_WAIT) - return 1; - } - - if (err >= 0) - return 0; - switch (err) { - /* ????????????????????????? */ - case -ERESTARTSYS: - case -EBADF: - /* When the server has died, an ICMP port unreachable - * message prompts ECONNREFUSED. */ - case -ECONNREFUSED: - case -ENOTCONN: - case -ECONNRESET: - case -EPIPE: - return 1; - } - return 0; -} - -enum { - O2NET_DRIVER_UNINITED, - O2NET_DRIVER_READY, -}; - -int o2net_send_message(u32 msg_type, u32 key, void *data, u32 len, - u8 target_node, int *status); -int o2net_send_message_vec(u32 msg_type, u32 key, struct kvec *vec, - size_t veclen, u8 target_node, int *status); - -int o2net_register_handler(u32 msg_type, u32 key, u32 max_len, - o2net_msg_handler_func *func, void *data, - o2net_post_msg_handler_func *post_func, - struct list_head *unreg_list); -void o2net_unregister_handler_list(struct list_head *list); - -void o2net_fill_node_map(unsigned long *map, unsigned bytes); - -#ifdef CONFIG_RAMSTER -void o2net_force_data_magic(struct o2net_msg *, u16, u32); -void o2net_hb_node_up_manual(int); -struct o2net_node *o2net_nn_from_num(u8); -#endif - -struct o2nm_node; -int o2net_register_hb_callbacks(void); -void o2net_unregister_hb_callbacks(void); -int o2net_start_listening(struct o2nm_node *node); -void o2net_stop_listening(struct o2nm_node *node); -void o2net_disconnect_node(struct o2nm_node *node); -int o2net_num_connected_peers(void); - -int o2net_init(void); -void o2net_exit(void); - -struct o2net_send_tracking; -struct o2net_sock_container; - -#ifdef CONFIG_DEBUG_FS -int o2net_debugfs_init(void); -void o2net_debugfs_exit(void); -void o2net_debug_add_nst(struct o2net_send_tracking *nst); -void o2net_debug_del_nst(struct o2net_send_tracking *nst); -void o2net_debug_add_sc(struct o2net_sock_container *sc); -void o2net_debug_del_sc(struct o2net_sock_container *sc); -#else -static inline int o2net_debugfs_init(void) -{ - return 0; -} -static inline void o2net_debugfs_exit(void) -{ -} -static inline void o2net_debug_add_nst(struct o2net_send_tracking *nst) -{ -} -static inline void o2net_debug_del_nst(struct o2net_send_tracking *nst) -{ -} -static inline void o2net_debug_add_sc(struct o2net_sock_container *sc) -{ -} -static inline void o2net_debug_del_sc(struct o2net_sock_container *sc) -{ -} -#endif /* CONFIG_DEBUG_FS */ - -#endif /* O2CLUSTER_TCP_H */ diff --git a/drivers/staging/ramster/cluster/tcp_internal.h b/drivers/staging/ramster/cluster/tcp_internal.h deleted file mode 100644 index ce17135..0000000 --- a/drivers/staging/ramster/cluster/tcp_internal.h +++ /dev/null @@ -1,249 +0,0 @@ -/* -*- mode: c; c-basic-offset: 8; -*- - * vim: noexpandtab sw=8 ts=8 sts=0: - * - * Copyright (C) 2005 Oracle. All rights reserved. - * - * 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; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 021110-1307, USA. - */ - -#ifndef O2CLUSTER_TCP_INTERNAL_H -#define O2CLUSTER_TCP_INTERNAL_H - -#define O2NET_MSG_MAGIC ((u16)0xfa55) -#define O2NET_MSG_STATUS_MAGIC ((u16)0xfa56) -#define O2NET_MSG_KEEP_REQ_MAGIC ((u16)0xfa57) -#define O2NET_MSG_KEEP_RESP_MAGIC ((u16)0xfa58) -#ifdef CONFIG_RAMSTER -/* - * "data magic" is a long version of "status magic" where the message - * payload actually contains data to be passed in reply to certain messages - */ -#define O2NET_MSG_DATA_MAGIC ((u16)0xfa59) -#endif - -/* we're delaying our quorum decision so that heartbeat will have timed - * out truly dead nodes by the time we come around to making decisions - * on their number */ -#define O2NET_QUORUM_DELAY_MS ((o2hb_dead_threshold + 2) * O2HB_REGION_TIMEOUT_MS) - -/* - * This version number represents quite a lot, unfortunately. It not - * only represents the raw network message protocol on the wire but also - * locking semantics of the file system using the protocol. It should - * be somewhere else, I'm sure, but right now it isn't. - * - * With version 11, we separate out the filesystem locking portion. The - * filesystem now has a major.minor version it negotiates. Version 11 - * introduces this negotiation to the o2dlm protocol, and as such the - * version here in tcp_internal.h should not need to be bumped for - * filesystem locking changes. - * - * New in version 11 - * - Negotiation of filesystem locking in the dlm join. - * - * New in version 10: - * - Meta/data locks combined - * - * New in version 9: - * - All votes removed - * - * New in version 8: - * - Replace delete inode votes with a cluster lock - * - * New in version 7: - * - DLM join domain includes the live nodemap - * - * New in version 6: - * - DLM lockres remote refcount fixes. - * - * New in version 5: - * - Network timeout checking protocol - * - * New in version 4: - * - Remove i_generation from lock names for better stat performance. - * - * New in version 3: - * - Replace dentry votes with a cluster lock - * - * New in version 2: - * - full 64 bit i_size in the metadata lock lvbs - * - introduction of "rw" lock and pushing meta/data locking down - */ -#define O2NET_PROTOCOL_VERSION 11ULL -struct o2net_handshake { - __be64 protocol_version; - __be64 connector_id; - __be32 o2hb_heartbeat_timeout_ms; - __be32 o2net_idle_timeout_ms; - __be32 o2net_keepalive_delay_ms; - __be32 o2net_reconnect_delay_ms; -}; - -struct o2net_node { - /* this is never called from int/bh */ - spinlock_t nn_lock; - - /* set the moment an sc is allocated and a connect is started */ - struct o2net_sock_container *nn_sc; - /* _valid is only set after the handshake passes and tx can happen */ - unsigned nn_sc_valid:1; - /* if this is set tx just returns it */ - int nn_persistent_error; - /* It is only set to 1 after the idle time out. */ - atomic_t nn_timeout; - - /* threads waiting for an sc to arrive wait on the wq for generation - * to increase. it is increased when a connecting socket succeeds - * or fails or when an accepted socket is attached. */ - wait_queue_head_t nn_sc_wq; - - struct idr nn_status_idr; - struct list_head nn_status_list; - - /* connects are attempted from when heartbeat comes up until either hb - * goes down, the node is unconfigured, no connect attempts succeed - * before O2NET_CONN_IDLE_DELAY, or a connect succeeds. connect_work - * is queued from set_nn_state both from hb up and from itself if a - * connect attempt fails and so can be self-arming. shutdown is - * careful to first mark the nn such that no connects will be attempted - * before canceling delayed connect work and flushing the queue. */ - struct delayed_work nn_connect_work; - unsigned long nn_last_connect_attempt; - - /* this is queued as nodes come up and is canceled when a connection is - * established. this expiring gives up on the node and errors out - * transmits */ - struct delayed_work nn_connect_expired; - - /* after we give up on a socket we wait a while before deciding - * that it is still heartbeating and that we should do some - * quorum work */ - struct delayed_work nn_still_up; -}; - -struct o2net_sock_container { - struct kref sc_kref; - /* the next two are valid for the life time of the sc */ - struct socket *sc_sock; - struct o2nm_node *sc_node; - - /* all of these sc work structs hold refs on the sc while they are - * queued. they should not be able to ref a freed sc. the teardown - * race is with o2net_wq destruction in o2net_stop_listening() */ - - /* rx and connect work are generated from socket callbacks. sc - * shutdown removes the callbacks and then flushes the work queue */ - struct work_struct sc_rx_work; - struct work_struct sc_connect_work; - /* shutdown work is triggered in two ways. the simple way is - * for a code path calls ensure_shutdown which gets a lock, removes - * the sc from the nn, and queues the work. in this case the - * work is single-shot. the work is also queued from a sock - * callback, though, and in this case the work will find the sc - * still on the nn and will call ensure_shutdown itself.. this - * ends up triggering the shutdown work again, though nothing - * will be done in that second iteration. so work queue teardown - * has to be careful to remove the sc from the nn before waiting - * on the work queue so that the shutdown work doesn't remove the - * sc and rearm itself. - */ - struct work_struct sc_shutdown_work; - - struct timer_list sc_idle_timeout; - struct delayed_work sc_keepalive_work; - - unsigned sc_handshake_ok:1; - - struct page *sc_page; - size_t sc_page_off; - - /* original handlers for the sockets */ - void (*sc_state_change)(struct sock *sk); - void (*sc_data_ready)(struct sock *sk, int bytes); - - u32 sc_msg_key; - u16 sc_msg_type; - -#ifdef CONFIG_DEBUG_FS - struct list_head sc_net_debug_item; - ktime_t sc_tv_timer; - ktime_t sc_tv_data_ready; - ktime_t sc_tv_advance_start; - ktime_t sc_tv_advance_stop; - ktime_t sc_tv_func_start; - ktime_t sc_tv_func_stop; -#endif -#ifdef CONFIG_OCFS2_FS_STATS - ktime_t sc_tv_acquiry_total; - ktime_t sc_tv_send_total; - ktime_t sc_tv_status_total; - u32 sc_send_count; - u32 sc_recv_count; - ktime_t sc_tv_process_total; -#endif - struct mutex sc_send_lock; -}; - -struct o2net_msg_handler { - struct rb_node nh_node; - u32 nh_max_len; - u32 nh_msg_type; - u32 nh_key; - o2net_msg_handler_func *nh_func; - o2net_msg_handler_func *nh_func_data; - o2net_post_msg_handler_func - *nh_post_func; - struct kref nh_kref; - struct list_head nh_unregister_item; -}; - -enum o2net_system_error { - O2NET_ERR_NONE = 0, - O2NET_ERR_NO_HNDLR, - O2NET_ERR_OVERFLOW, - O2NET_ERR_DIED, - O2NET_ERR_MAX -}; - -struct o2net_status_wait { - enum o2net_system_error ns_sys_status; - s32 ns_status; - int ns_id; - wait_queue_head_t ns_wq; - struct list_head ns_node_item; -}; - -#ifdef CONFIG_DEBUG_FS -/* just for state dumps */ -struct o2net_send_tracking { - struct list_head st_net_debug_item; - struct task_struct *st_task; - struct o2net_sock_container *st_sc; - u32 st_id; - u32 st_msg_type; - u32 st_msg_key; - u8 st_node; - ktime_t st_sock_time; - ktime_t st_send_time; - ktime_t st_status_time; -}; -#else -struct o2net_send_tracking { - u32 dummy; -}; -#endif /* CONFIG_DEBUG_FS */ - -#endif /* O2CLUSTER_TCP_INTERNAL_H */ diff --git a/drivers/staging/ramster/cluster/ver.c b/drivers/staging/ramster/cluster/ver.c deleted file mode 100644 index a56eee6..0000000 --- a/drivers/staging/ramster/cluster/ver.c +++ /dev/null @@ -1,42 +0,0 @@ -/* -*- mode: c; c-basic-offset: 8; -*- - * vim: noexpandtab sw=8 ts=8 sts=0: - * - * ver.c - * - * version string - * - * Copyright (C) 2002, 2005 Oracle. All rights reserved. - * - * 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; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 021110-1307, USA. - */ - -#include -#include - -#include "ver.h" - -#define CLUSTER_BUILD_VERSION "1.5.0" - -#define VERSION_STR "OCFS2 Node Manager " CLUSTER_BUILD_VERSION - -void cluster_print_version(void) -{ - printk(KERN_INFO "%s\n", VERSION_STR); -} - -MODULE_DESCRIPTION(VERSION_STR); - -MODULE_VERSION(CLUSTER_BUILD_VERSION); diff --git a/drivers/staging/ramster/cluster/ver.h b/drivers/staging/ramster/cluster/ver.h deleted file mode 100644 index 32554c3..0000000 --- a/drivers/staging/ramster/cluster/ver.h +++ /dev/null @@ -1,31 +0,0 @@ -/* -*- mode: c; c-basic-offset: 8; -*- - * vim: noexpandtab sw=8 ts=8 sts=0: - * - * ver.h - * - * Function prototypes - * - * Copyright (C) 2005 Oracle. All rights reserved. - * - * 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; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 021110-1307, USA. - */ - -#ifndef O2CLUSTER_VER_H -#define O2CLUSTER_VER_H - -void cluster_print_version(void); - -#endif /* O2CLUSTER_VER_H */ diff --git a/drivers/staging/ramster/ramster.h b/drivers/staging/ramster/ramster.h deleted file mode 100644 index 3293512..0000000 --- a/drivers/staging/ramster/ramster.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * ramster.h - * - * Peer-to-peer transcendent memory - * - * Copyright (c) 2009-2012, Dan Magenheimer, Oracle Corp. - */ - -#ifndef _RAMSTER_H_ -#define _RAMSTER_H_ - -/* - * format of remote pampd: - * bit 0 == intransit - * bit 1 == is_remote... if this bit is set, then - * bit 2-9 == remotenode - * bit 10-22 == size - * bit 23-30 == cksum - */ -#define FAKE_PAMPD_INTRANSIT_BITS 1 -#define FAKE_PAMPD_ISREMOTE_BITS 1 -#define FAKE_PAMPD_REMOTENODE_BITS 8 -#define FAKE_PAMPD_REMOTESIZE_BITS 13 -#define FAKE_PAMPD_CHECKSUM_BITS 8 - -#define FAKE_PAMPD_INTRANSIT_SHIFT 0 -#define FAKE_PAMPD_ISREMOTE_SHIFT (FAKE_PAMPD_INTRANSIT_SHIFT + \ - FAKE_PAMPD_INTRANSIT_BITS) -#define FAKE_PAMPD_REMOTENODE_SHIFT (FAKE_PAMPD_ISREMOTE_SHIFT + \ - FAKE_PAMPD_ISREMOTE_BITS) -#define FAKE_PAMPD_REMOTESIZE_SHIFT (FAKE_PAMPD_REMOTENODE_SHIFT + \ - FAKE_PAMPD_REMOTENODE_BITS) -#define FAKE_PAMPD_CHECKSUM_SHIFT (FAKE_PAMPD_REMOTESIZE_SHIFT + \ - FAKE_PAMPD_REMOTESIZE_BITS) - -#define FAKE_PAMPD_MASK(x) ((1UL << (x)) - 1) - -static inline void *pampd_make_remote(int remotenode, size_t size, - unsigned char cksum) -{ - unsigned long fake_pampd = 0; - fake_pampd |= 1UL << FAKE_PAMPD_ISREMOTE_SHIFT; - fake_pampd |= ((unsigned long)remotenode & - FAKE_PAMPD_MASK(FAKE_PAMPD_REMOTENODE_BITS)) << - FAKE_PAMPD_REMOTENODE_SHIFT; - fake_pampd |= ((unsigned long)size & - FAKE_PAMPD_MASK(FAKE_PAMPD_REMOTESIZE_BITS)) << - FAKE_PAMPD_REMOTESIZE_SHIFT; - fake_pampd |= ((unsigned long)cksum & - FAKE_PAMPD_MASK(FAKE_PAMPD_CHECKSUM_BITS)) << - FAKE_PAMPD_CHECKSUM_SHIFT; - return (void *)fake_pampd; -} - -static inline unsigned int pampd_remote_node(void *pampd) -{ - unsigned long fake_pampd = (unsigned long)pampd; - return (fake_pampd >> FAKE_PAMPD_REMOTENODE_SHIFT) & - FAKE_PAMPD_MASK(FAKE_PAMPD_REMOTENODE_BITS); -} - -static inline unsigned int pampd_remote_size(void *pampd) -{ - unsigned long fake_pampd = (unsigned long)pampd; - return (fake_pampd >> FAKE_PAMPD_REMOTESIZE_SHIFT) & - FAKE_PAMPD_MASK(FAKE_PAMPD_REMOTESIZE_BITS); -} - -static inline unsigned char pampd_remote_cksum(void *pampd) -{ - unsigned long fake_pampd = (unsigned long)pampd; - return (fake_pampd >> FAKE_PAMPD_CHECKSUM_SHIFT) & - FAKE_PAMPD_MASK(FAKE_PAMPD_CHECKSUM_BITS); -} - -static inline bool pampd_is_remote(void *pampd) -{ - unsigned long fake_pampd = (unsigned long)pampd; - return (fake_pampd >> FAKE_PAMPD_ISREMOTE_SHIFT) & - FAKE_PAMPD_MASK(FAKE_PAMPD_ISREMOTE_BITS); -} - -static inline bool pampd_is_intransit(void *pampd) -{ - unsigned long fake_pampd = (unsigned long)pampd; - return (fake_pampd >> FAKE_PAMPD_INTRANSIT_SHIFT) & - FAKE_PAMPD_MASK(FAKE_PAMPD_INTRANSIT_BITS); -} - -/* note that it is a BUG for intransit to be set without isremote also set */ -static inline void *pampd_mark_intransit(void *pampd) -{ - unsigned long fake_pampd = (unsigned long)pampd; - - fake_pampd |= 1UL << FAKE_PAMPD_ISREMOTE_SHIFT; - fake_pampd |= 1UL << FAKE_PAMPD_INTRANSIT_SHIFT; - return (void *)fake_pampd; -} - -static inline void *pampd_mask_intransit_and_remote(void *marked_pampd) -{ - unsigned long pampd = (unsigned long)marked_pampd; - - pampd &= ~(1UL << FAKE_PAMPD_INTRANSIT_SHIFT); - pampd &= ~(1UL << FAKE_PAMPD_ISREMOTE_SHIFT); - return (void *)pampd; -} - -extern int ramster_remote_async_get(struct tmem_xhandle *, - bool, int, size_t, uint8_t, void *extra); -extern int ramster_remote_put(struct tmem_xhandle *, char *, size_t, - bool, int *); -extern int ramster_remote_flush(struct tmem_xhandle *, int); -extern int ramster_remote_flush_object(struct tmem_xhandle *, int); -extern int ramster_o2net_register_handlers(void); - -#endif /* _TMEM_H */ diff --git a/drivers/staging/ramster/ramster_o2net.c b/drivers/staging/ramster/ramster_o2net.c deleted file mode 100644 index c5a47cc..0000000 --- a/drivers/staging/ramster/ramster_o2net.c +++ /dev/null @@ -1,402 +0,0 @@ -/* - * ramster_o2net.c - * - * Copyright (c) 2011, Dan Magenheimer, Oracle Corp. - * - * Ramster_o2net provides an interface between zcache and o2net. - * - * FIXME: support more than two nodes - */ - -#include -#include "cluster/tcp.h" -#include "cluster/nodemanager.h" -#include "tmem.h" -#include "zcache.h" -#include "ramster.h" - -#define RAMSTER_TESTING - -#define RMSTR_KEY 0x77347734 - -enum { - RMSTR_TMEM_PUT_EPH = 100, - RMSTR_TMEM_PUT_PERS, - RMSTR_TMEM_ASYNC_GET_REQUEST, - RMSTR_TMEM_ASYNC_GET_AND_FREE_REQUEST, - RMSTR_TMEM_ASYNC_GET_REPLY, - RMSTR_TMEM_FLUSH, - RMSTR_TMEM_FLOBJ, - RMSTR_TMEM_DESTROY_POOL, -}; - -#define RMSTR_O2NET_MAX_LEN \ - (O2NET_MAX_PAYLOAD_BYTES - sizeof(struct tmem_xhandle)) - -#include "cluster/tcp_internal.h" - -static struct o2nm_node *ramster_choose_node(int *nodenum, - struct tmem_xhandle *xh) -{ - struct o2nm_node *node = NULL; - int i; - -/* FIXME reproducibly pick a node based on xh that is NOT this node */ - i = o2nm_this_node(); - i = !i; /* FIXME ONLY FOR TWO NODES */ - node = o2nm_get_node_by_num(i); - /* WARNING: THIS DOES NOT CHECK TO ENSURE CONNECTED */ - if (node != NULL) - *nodenum = i; - return node; -} - -static void ramster_put_node(struct o2nm_node *node) -{ - o2nm_node_put(node); -} - -/* FIXME following buffer should be per-cpu, protected by preempt_disable */ -static char ramster_async_get_buf[O2NET_MAX_PAYLOAD_BYTES]; - -static int ramster_remote_async_get_request_handler(struct o2net_msg *msg, - u32 len, void *data, void **ret_data) -{ - char *pdata; - struct tmem_xhandle xh; - int found; - size_t size = RMSTR_O2NET_MAX_LEN; - u16 msgtype = be16_to_cpu(msg->msg_type); - bool get_and_free = (msgtype == RMSTR_TMEM_ASYNC_GET_AND_FREE_REQUEST); - unsigned long flags; - - xh = *(struct tmem_xhandle *)msg->buf; - if (xh.xh_data_size > RMSTR_O2NET_MAX_LEN) - BUG(); - pdata = ramster_async_get_buf; - *(struct tmem_xhandle *)pdata = xh; - pdata += sizeof(struct tmem_xhandle); - local_irq_save(flags); - found = zcache_get(xh.client_id, xh.pool_id, &xh.oid, xh.index, - pdata, &size, 1, get_and_free ? 1 : -1); - local_irq_restore(flags); - if (found < 0) { - /* a zero size indicates the get failed */ - size = 0; - } - if (size > RMSTR_O2NET_MAX_LEN) - BUG(); - *ret_data = pdata - sizeof(struct tmem_xhandle); - /* now make caller (o2net_process_message) handle specially */ - o2net_force_data_magic(msg, RMSTR_TMEM_ASYNC_GET_REPLY, RMSTR_KEY); - return size + sizeof(struct tmem_xhandle); -} - -static int ramster_remote_async_get_reply_handler(struct o2net_msg *msg, - u32 len, void *data, void **ret_data) -{ - char *in = (char *)msg->buf; - int datalen = len - sizeof(struct o2net_msg); - int ret = -1; - struct tmem_xhandle *xh = (struct tmem_xhandle *)in; - - in += sizeof(struct tmem_xhandle); - datalen -= sizeof(struct tmem_xhandle); - BUG_ON(datalen < 0 || datalen > PAGE_SIZE); - ret = zcache_localify(xh->pool_id, &xh->oid, xh->index, - in, datalen, xh->extra); -#ifdef RAMSTER_TESTING - if (ret == -EEXIST) - pr_err("TESTING ArrgREP, aborted overwrite on racy put\n"); -#endif - return ret; -} - -int ramster_remote_put_handler(struct o2net_msg *msg, - u32 len, void *data, void **ret_data) -{ - struct tmem_xhandle *xh; - char *p = (char *)msg->buf; - int datalen = len - sizeof(struct o2net_msg) - - sizeof(struct tmem_xhandle); - u16 msgtype = be16_to_cpu(msg->msg_type); - bool ephemeral = (msgtype == RMSTR_TMEM_PUT_EPH); - unsigned long flags; - int ret; - - xh = (struct tmem_xhandle *)p; - p += sizeof(struct tmem_xhandle); - zcache_autocreate_pool(xh->client_id, xh->pool_id, ephemeral); - local_irq_save(flags); - ret = zcache_put(xh->client_id, xh->pool_id, &xh->oid, xh->index, - p, datalen, 1, ephemeral ? 1 : -1); - local_irq_restore(flags); - return ret; -} - -int ramster_remote_flush_handler(struct o2net_msg *msg, - u32 len, void *data, void **ret_data) -{ - struct tmem_xhandle *xh; - char *p = (char *)msg->buf; - - xh = (struct tmem_xhandle *)p; - p += sizeof(struct tmem_xhandle); - (void)zcache_flush(xh->client_id, xh->pool_id, &xh->oid, xh->index); - return 0; -} - -int ramster_remote_flobj_handler(struct o2net_msg *msg, - u32 len, void *data, void **ret_data) -{ - struct tmem_xhandle *xh; - char *p = (char *)msg->buf; - - xh = (struct tmem_xhandle *)p; - p += sizeof(struct tmem_xhandle); - (void)zcache_flush_object(xh->client_id, xh->pool_id, &xh->oid); - return 0; -} - -int ramster_remote_async_get(struct tmem_xhandle *xh, bool free, int remotenode, - size_t expect_size, uint8_t expect_cksum, - void *extra) -{ - int ret = -1, status; - struct o2nm_node *node = NULL; - struct kvec vec[1]; - size_t veclen = 1; - u32 msg_type; - - node = o2nm_get_node_by_num(remotenode); - if (node == NULL) - goto out; - xh->client_id = o2nm_this_node(); /* which node is getting */ - xh->xh_data_cksum = expect_cksum; - xh->xh_data_size = expect_size; - xh->extra = extra; - vec[0].iov_len = sizeof(*xh); - vec[0].iov_base = xh; - if (free) - msg_type = RMSTR_TMEM_ASYNC_GET_AND_FREE_REQUEST; - else - msg_type = RMSTR_TMEM_ASYNC_GET_REQUEST; - ret = o2net_send_message_vec(msg_type, RMSTR_KEY, - vec, veclen, remotenode, &status); - ramster_put_node(node); - if (ret < 0) { - /* FIXME handle bad message possibilities here? */ - pr_err("UNTESTED ret<0 in ramster_remote_async_get\n"); - } - ret = status; -out: - return ret; -} - -#ifdef RAMSTER_TESTING -/* leave me here to see if it catches a weird crash */ -static void ramster_check_irq_counts(void) -{ - static int last_hardirq_cnt, last_softirq_cnt, last_preempt_cnt; - int cur_hardirq_cnt, cur_softirq_cnt, cur_preempt_cnt; - - cur_hardirq_cnt = hardirq_count() >> HARDIRQ_SHIFT; - if (cur_hardirq_cnt > last_hardirq_cnt) { - last_hardirq_cnt = cur_hardirq_cnt; - if (!(last_hardirq_cnt&(last_hardirq_cnt-1))) - pr_err("RAMSTER TESTING RRP hardirq_count=%d\n", - last_hardirq_cnt); - } - cur_softirq_cnt = softirq_count() >> SOFTIRQ_SHIFT; - if (cur_softirq_cnt > last_softirq_cnt) { - last_softirq_cnt = cur_softirq_cnt; - if (!(last_softirq_cnt&(last_softirq_cnt-1))) - pr_err("RAMSTER TESTING RRP softirq_count=%d\n", - last_softirq_cnt); - } - cur_preempt_cnt = preempt_count() & PREEMPT_MASK; - if (cur_preempt_cnt > last_preempt_cnt) { - last_preempt_cnt = cur_preempt_cnt; - if (!(last_preempt_cnt&(last_preempt_cnt-1))) - pr_err("RAMSTER TESTING RRP preempt_count=%d\n", - last_preempt_cnt); - } -} -#endif - -int ramster_remote_put(struct tmem_xhandle *xh, char *data, size_t size, - bool ephemeral, int *remotenode) -{ - int nodenum, ret = -1, status; - struct o2nm_node *node = NULL; - struct kvec vec[2]; - size_t veclen = 2; - u32 msg_type; -#ifdef RAMSTER_TESTING - struct o2net_node *nn; -#endif - - BUG_ON(size > RMSTR_O2NET_MAX_LEN); - xh->client_id = o2nm_this_node(); /* which node is putting */ - vec[0].iov_len = sizeof(*xh); - vec[0].iov_base = xh; - vec[1].iov_len = size; - vec[1].iov_base = data; - node = ramster_choose_node(&nodenum, xh); - if (!node) - goto out; - -#ifdef RAMSTER_TESTING - nn = o2net_nn_from_num(nodenum); - WARN_ON_ONCE(nn->nn_persistent_error || !nn->nn_sc_valid); -#endif - - if (ephemeral) - msg_type = RMSTR_TMEM_PUT_EPH; - else - msg_type = RMSTR_TMEM_PUT_PERS; -#ifdef RAMSTER_TESTING - /* leave me here to see if it catches a weird crash */ - ramster_check_irq_counts(); -#endif - - ret = o2net_send_message_vec(msg_type, RMSTR_KEY, - vec, veclen, nodenum, &status); -#ifdef RAMSTER_TESTING - if (ret != 0) { - static unsigned long cnt; - cnt++; - if (!(cnt&(cnt-1))) - pr_err("ramster_remote_put: message failed, " - "ret=%d, cnt=%lu\n", ret, cnt); - ret = -1; - } -#endif - if (ret < 0) - ret = -1; - else { - ret = status; - *remotenode = nodenum; - } - - ramster_put_node(node); -out: - return ret; -} - -int ramster_remote_flush(struct tmem_xhandle *xh, int remotenode) -{ - int ret = -1, status; - struct o2nm_node *node = NULL; - struct kvec vec[1]; - size_t veclen = 1; - - node = o2nm_get_node_by_num(remotenode); - BUG_ON(node == NULL); - xh->client_id = o2nm_this_node(); /* which node is flushing */ - vec[0].iov_len = sizeof(*xh); - vec[0].iov_base = xh; - BUG_ON(irqs_disabled()); - BUG_ON(in_softirq()); - ret = o2net_send_message_vec(RMSTR_TMEM_FLUSH, RMSTR_KEY, - vec, veclen, remotenode, &status); - ramster_put_node(node); - return ret; -} - -int ramster_remote_flush_object(struct tmem_xhandle *xh, int remotenode) -{ - int ret = -1, status; - struct o2nm_node *node = NULL; - struct kvec vec[1]; - size_t veclen = 1; - - node = o2nm_get_node_by_num(remotenode); - BUG_ON(node == NULL); - xh->client_id = o2nm_this_node(); /* which node is flobjing */ - vec[0].iov_len = sizeof(*xh); - vec[0].iov_base = xh; - ret = o2net_send_message_vec(RMSTR_TMEM_FLOBJ, RMSTR_KEY, - vec, veclen, remotenode, &status); - ramster_put_node(node); - return ret; -} - -/* - * Handler registration - */ - -static LIST_HEAD(ramster_o2net_unreg_list); - -static void ramster_o2net_unregister_handlers(void) -{ - o2net_unregister_handler_list(&ramster_o2net_unreg_list); -} - -int ramster_o2net_register_handlers(void) -{ - int status; - - status = o2net_register_handler(RMSTR_TMEM_PUT_EPH, RMSTR_KEY, - RMSTR_O2NET_MAX_LEN, - ramster_remote_put_handler, - NULL, NULL, &ramster_o2net_unreg_list); - if (status) - goto bail; - - status = o2net_register_handler(RMSTR_TMEM_PUT_PERS, RMSTR_KEY, - RMSTR_O2NET_MAX_LEN, - ramster_remote_put_handler, - NULL, NULL, &ramster_o2net_unreg_list); - if (status) - goto bail; - - status = o2net_register_handler(RMSTR_TMEM_ASYNC_GET_REQUEST, RMSTR_KEY, - RMSTR_O2NET_MAX_LEN, - ramster_remote_async_get_request_handler, - NULL, NULL, - &ramster_o2net_unreg_list); - if (status) - goto bail; - - status = o2net_register_handler(RMSTR_TMEM_ASYNC_GET_AND_FREE_REQUEST, - RMSTR_KEY, RMSTR_O2NET_MAX_LEN, - ramster_remote_async_get_request_handler, - NULL, NULL, - &ramster_o2net_unreg_list); - if (status) - goto bail; - - status = o2net_register_handler(RMSTR_TMEM_ASYNC_GET_REPLY, RMSTR_KEY, - RMSTR_O2NET_MAX_LEN, - ramster_remote_async_get_reply_handler, - NULL, NULL, - &ramster_o2net_unreg_list); - if (status) - goto bail; - - status = o2net_register_handler(RMSTR_TMEM_FLUSH, RMSTR_KEY, - RMSTR_O2NET_MAX_LEN, - ramster_remote_flush_handler, - NULL, NULL, - &ramster_o2net_unreg_list); - if (status) - goto bail; - - status = o2net_register_handler(RMSTR_TMEM_FLOBJ, RMSTR_KEY, - RMSTR_O2NET_MAX_LEN, - ramster_remote_flobj_handler, - NULL, NULL, - &ramster_o2net_unreg_list); - if (status) - goto bail; - - pr_info("ramster_o2net: handlers registered\n"); - -bail: - if (status) { - ramster_o2net_unregister_handlers(); - pr_err("ramster_o2net: couldn't register handlers\n"); - } - return status; -} diff --git a/drivers/staging/ramster/tmem.c b/drivers/staging/ramster/tmem.c deleted file mode 100644 index 8f2f689..0000000 --- a/drivers/staging/ramster/tmem.c +++ /dev/null @@ -1,851 +0,0 @@ -/* - * In-kernel transcendent memory (generic implementation) - * - * Copyright (c) 2009-2011, Dan Magenheimer, Oracle Corp. - * - * The primary purpose of Transcedent Memory ("tmem") is to map object-oriented - * "handles" (triples containing a pool id, and object id, and an index), to - * pages in a page-accessible memory (PAM). Tmem references the PAM pages via - * an abstract "pampd" (PAM page-descriptor), which can be operated on by a - * set of functions (pamops). Each pampd contains some representation of - * PAGE_SIZE bytes worth of data. Tmem must support potentially millions of - * pages and must be able to insert, find, and delete these pages at a - * potential frequency of thousands per second concurrently across many CPUs, - * (and, if used with KVM, across many vcpus across many guests). - * Tmem is tracked with a hierarchy of data structures, organized by - * the elements in a handle-tuple: pool_id, object_id, and page index. - * One or more "clients" (e.g. guests) each provide one or more tmem_pools. - * Each pool, contains a hash table of rb_trees of tmem_objs. Each - * tmem_obj contains a radix-tree-like tree of pointers, with intermediate - * nodes called tmem_objnodes. Each leaf pointer in this tree points to - * a pampd, which is accessible only through a small set of callbacks - * registered by the PAM implementation (see tmem_register_pamops). Tmem - * does all memory allocation via a set of callbacks registered by the tmem - * host implementation (e.g. see tmem_register_hostops). - */ - -#include -#include -#include -#include - -#include "tmem.h" - -/* data structure sentinels used for debugging... see tmem.h */ -#define POOL_SENTINEL 0x87658765 -#define OBJ_SENTINEL 0x12345678 -#define OBJNODE_SENTINEL 0xfedcba09 - -/* - * A tmem host implementation must use this function to register callbacks - * for memory allocation. - */ -static struct tmem_hostops tmem_hostops; - -static void tmem_objnode_tree_init(void); - -void tmem_register_hostops(struct tmem_hostops *m) -{ - tmem_objnode_tree_init(); - tmem_hostops = *m; -} - -/* - * A tmem host implementation must use this function to register - * callbacks for a page-accessible memory (PAM) implementation - */ -static struct tmem_pamops tmem_pamops; - -void tmem_register_pamops(struct tmem_pamops *m) -{ - tmem_pamops = *m; -} - -/* - * Oid's are potentially very sparse and tmem_objs may have an indeterminately - * short life, being added and deleted at a relatively high frequency. - * So an rb_tree is an ideal data structure to manage tmem_objs. But because - * of the potentially huge number of tmem_objs, each pool manages a hashtable - * of rb_trees to reduce search, insert, delete, and rebalancing time. - * Each hashbucket also has a lock to manage concurrent access. - * - * The following routines manage tmem_objs. When any tmem_obj is accessed, - * the hashbucket lock must be held. - */ - -/* searches for object==oid in pool, returns locked object if found */ -static struct tmem_obj *tmem_obj_find(struct tmem_hashbucket *hb, - struct tmem_oid *oidp) -{ - struct rb_node *rbnode; - struct tmem_obj *obj; - - rbnode = hb->obj_rb_root.rb_node; - while (rbnode) { - BUG_ON(RB_EMPTY_NODE(rbnode)); - obj = rb_entry(rbnode, struct tmem_obj, rb_tree_node); - switch (tmem_oid_compare(oidp, &obj->oid)) { - case 0: /* equal */ - goto out; - case -1: - rbnode = rbnode->rb_left; - break; - case 1: - rbnode = rbnode->rb_right; - break; - } - } - obj = NULL; -out: - return obj; -} - -static void tmem_pampd_destroy_all_in_obj(struct tmem_obj *); - -/* free an object that has no more pampds in it */ -static void tmem_obj_free(struct tmem_obj *obj, struct tmem_hashbucket *hb) -{ - struct tmem_pool *pool; - - BUG_ON(obj == NULL); - ASSERT_SENTINEL(obj, OBJ); - BUG_ON(obj->pampd_count > 0); - pool = obj->pool; - BUG_ON(pool == NULL); - if (obj->objnode_tree_root != NULL) /* may be "stump" with no leaves */ - tmem_pampd_destroy_all_in_obj(obj); - BUG_ON(obj->objnode_tree_root != NULL); - BUG_ON((long)obj->objnode_count != 0); - atomic_dec(&pool->obj_count); - BUG_ON(atomic_read(&pool->obj_count) < 0); - INVERT_SENTINEL(obj, OBJ); - obj->pool = NULL; - tmem_oid_set_invalid(&obj->oid); - rb_erase(&obj->rb_tree_node, &hb->obj_rb_root); -} - -/* - * initialize, and insert an tmem_object_root (called only if find failed) - */ -static void tmem_obj_init(struct tmem_obj *obj, struct tmem_hashbucket *hb, - struct tmem_pool *pool, - struct tmem_oid *oidp) -{ - struct rb_root *root = &hb->obj_rb_root; - struct rb_node **new = &(root->rb_node), *parent = NULL; - struct tmem_obj *this; - - BUG_ON(pool == NULL); - atomic_inc(&pool->obj_count); - obj->objnode_tree_height = 0; - obj->objnode_tree_root = NULL; - obj->pool = pool; - obj->oid = *oidp; - obj->objnode_count = 0; - obj->pampd_count = 0; - (*tmem_pamops.new_obj)(obj); - SET_SENTINEL(obj, OBJ); - while (*new) { - BUG_ON(RB_EMPTY_NODE(*new)); - this = rb_entry(*new, struct tmem_obj, rb_tree_node); - parent = *new; - switch (tmem_oid_compare(oidp, &this->oid)) { - case 0: - BUG(); /* already present; should never happen! */ - break; - case -1: - new = &(*new)->rb_left; - break; - case 1: - new = &(*new)->rb_right; - break; - } - } - rb_link_node(&obj->rb_tree_node, parent, new); - rb_insert_color(&obj->rb_tree_node, root); -} - -/* - * Tmem is managed as a set of tmem_pools with certain attributes, such as - * "ephemeral" vs "persistent". These attributes apply to all tmem_objs - * and all pampds that belong to a tmem_pool. A tmem_pool is created - * or deleted relatively rarely (for example, when a filesystem is - * mounted or unmounted. - */ - -/* flush all data from a pool and, optionally, free it */ -static void tmem_pool_flush(struct tmem_pool *pool, bool destroy) -{ - struct rb_node *rbnode; - struct tmem_obj *obj; - struct tmem_hashbucket *hb = &pool->hashbucket[0]; - int i; - - BUG_ON(pool == NULL); - for (i = 0; i < TMEM_HASH_BUCKETS; i++, hb++) { - spin_lock(&hb->lock); - rbnode = rb_first(&hb->obj_rb_root); - while (rbnode != NULL) { - obj = rb_entry(rbnode, struct tmem_obj, rb_tree_node); - rbnode = rb_next(rbnode); - tmem_pampd_destroy_all_in_obj(obj); - tmem_obj_free(obj, hb); - (*tmem_hostops.obj_free)(obj, pool); - } - spin_unlock(&hb->lock); - } - if (destroy) - list_del(&pool->pool_list); -} - -/* - * A tmem_obj contains a radix-tree-like tree in which the intermediate - * nodes are called tmem_objnodes. (The kernel lib/radix-tree.c implementation - * is very specialized and tuned for specific uses and is not particularly - * suited for use from this code, though some code from the core algorithms has - * been reused, thus the copyright notices below). Each tmem_objnode contains - * a set of pointers which point to either a set of intermediate tmem_objnodes - * or a set of of pampds. - * - * Portions Copyright (C) 2001 Momchil Velikov - * Portions Copyright (C) 2001 Christoph Hellwig - * Portions Copyright (C) 2005 SGI, Christoph Lameter - */ - -struct tmem_objnode_tree_path { - struct tmem_objnode *objnode; - int offset; -}; - -/* objnode height_to_maxindex translation */ -static unsigned long tmem_objnode_tree_h2max[OBJNODE_TREE_MAX_PATH + 1]; - -static void tmem_objnode_tree_init(void) -{ - unsigned int ht, tmp; - - for (ht = 0; ht < ARRAY_SIZE(tmem_objnode_tree_h2max); ht++) { - tmp = ht * OBJNODE_TREE_MAP_SHIFT; - if (tmp >= OBJNODE_TREE_INDEX_BITS) - tmem_objnode_tree_h2max[ht] = ~0UL; - else - tmem_objnode_tree_h2max[ht] = - (~0UL >> (OBJNODE_TREE_INDEX_BITS - tmp - 1)) >> 1; - } -} - -static struct tmem_objnode *tmem_objnode_alloc(struct tmem_obj *obj) -{ - struct tmem_objnode *objnode; - - ASSERT_SENTINEL(obj, OBJ); - BUG_ON(obj->pool == NULL); - ASSERT_SENTINEL(obj->pool, POOL); - objnode = (*tmem_hostops.objnode_alloc)(obj->pool); - if (unlikely(objnode == NULL)) - goto out; - objnode->obj = obj; - SET_SENTINEL(objnode, OBJNODE); - memset(&objnode->slots, 0, sizeof(objnode->slots)); - objnode->slots_in_use = 0; - obj->objnode_count++; -out: - return objnode; -} - -static void tmem_objnode_free(struct tmem_objnode *objnode) -{ - struct tmem_pool *pool; - int i; - - BUG_ON(objnode == NULL); - for (i = 0; i < OBJNODE_TREE_MAP_SIZE; i++) - BUG_ON(objnode->slots[i] != NULL); - ASSERT_SENTINEL(objnode, OBJNODE); - INVERT_SENTINEL(objnode, OBJNODE); - BUG_ON(objnode->obj == NULL); - ASSERT_SENTINEL(objnode->obj, OBJ); - pool = objnode->obj->pool; - BUG_ON(pool == NULL); - ASSERT_SENTINEL(pool, POOL); - objnode->obj->objnode_count--; - objnode->obj = NULL; - (*tmem_hostops.objnode_free)(objnode, pool); -} - -/* - * lookup index in object and return associated pampd (or NULL if not found) - */ -static void **__tmem_pampd_lookup_in_obj(struct tmem_obj *obj, uint32_t index) -{ - unsigned int height, shift; - struct tmem_objnode **slot = NULL; - - BUG_ON(obj == NULL); - ASSERT_SENTINEL(obj, OBJ); - BUG_ON(obj->pool == NULL); - ASSERT_SENTINEL(obj->pool, POOL); - - height = obj->objnode_tree_height; - if (index > tmem_objnode_tree_h2max[obj->objnode_tree_height]) - goto out; - if (height == 0 && obj->objnode_tree_root) { - slot = &obj->objnode_tree_root; - goto out; - } - shift = (height-1) * OBJNODE_TREE_MAP_SHIFT; - slot = &obj->objnode_tree_root; - while (height > 0) { - if (*slot == NULL) - goto out; - slot = (struct tmem_objnode **) - ((*slot)->slots + - ((index >> shift) & OBJNODE_TREE_MAP_MASK)); - shift -= OBJNODE_TREE_MAP_SHIFT; - height--; - } -out: - return slot != NULL ? (void **)slot : NULL; -} - -static void *tmem_pampd_lookup_in_obj(struct tmem_obj *obj, uint32_t index) -{ - struct tmem_objnode **slot; - - slot = (struct tmem_objnode **)__tmem_pampd_lookup_in_obj(obj, index); - return slot != NULL ? *slot : NULL; -} - -static void *tmem_pampd_replace_in_obj(struct tmem_obj *obj, uint32_t index, - void *new_pampd, bool no_free) -{ - struct tmem_objnode **slot; - void *ret = NULL; - - slot = (struct tmem_objnode **)__tmem_pampd_lookup_in_obj(obj, index); - if ((slot != NULL) && (*slot != NULL)) { - void *old_pampd = *(void **)slot; - *(void **)slot = new_pampd; - if (!no_free) - (*tmem_pamops.free)(old_pampd, obj->pool, - NULL, 0, false); - ret = new_pampd; - } - return ret; -} - -static int tmem_pampd_add_to_obj(struct tmem_obj *obj, uint32_t index, - void *pampd) -{ - int ret = 0; - struct tmem_objnode *objnode = NULL, *newnode, *slot; - unsigned int height, shift; - int offset = 0; - - /* if necessary, extend the tree to be higher */ - if (index > tmem_objnode_tree_h2max[obj->objnode_tree_height]) { - height = obj->objnode_tree_height + 1; - if (index > tmem_objnode_tree_h2max[height]) - while (index > tmem_objnode_tree_h2max[height]) - height++; - if (obj->objnode_tree_root == NULL) { - obj->objnode_tree_height = height; - goto insert; - } - do { - newnode = tmem_objnode_alloc(obj); - if (!newnode) { - ret = -ENOMEM; - goto out; - } - newnode->slots[0] = obj->objnode_tree_root; - newnode->slots_in_use = 1; - obj->objnode_tree_root = newnode; - obj->objnode_tree_height++; - } while (height > obj->objnode_tree_height); - } -insert: - slot = obj->objnode_tree_root; - height = obj->objnode_tree_height; - shift = (height-1) * OBJNODE_TREE_MAP_SHIFT; - while (height > 0) { - if (slot == NULL) { - /* add a child objnode. */ - slot = tmem_objnode_alloc(obj); - if (!slot) { - ret = -ENOMEM; - goto out; - } - if (objnode) { - - objnode->slots[offset] = slot; - objnode->slots_in_use++; - } else - obj->objnode_tree_root = slot; - } - /* go down a level */ - offset = (index >> shift) & OBJNODE_TREE_MAP_MASK; - objnode = slot; - slot = objnode->slots[offset]; - shift -= OBJNODE_TREE_MAP_SHIFT; - height--; - } - BUG_ON(slot != NULL); - if (objnode) { - objnode->slots_in_use++; - objnode->slots[offset] = pampd; - } else - obj->objnode_tree_root = pampd; - obj->pampd_count++; -out: - return ret; -} - -static void *tmem_pampd_delete_from_obj(struct tmem_obj *obj, uint32_t index) -{ - struct tmem_objnode_tree_path path[OBJNODE_TREE_MAX_PATH + 1]; - struct tmem_objnode_tree_path *pathp = path; - struct tmem_objnode *slot = NULL; - unsigned int height, shift; - int offset; - - BUG_ON(obj == NULL); - ASSERT_SENTINEL(obj, OBJ); - BUG_ON(obj->pool == NULL); - ASSERT_SENTINEL(obj->pool, POOL); - height = obj->objnode_tree_height; - if (index > tmem_objnode_tree_h2max[height]) - goto out; - slot = obj->objnode_tree_root; - if (height == 0 && obj->objnode_tree_root) { - obj->objnode_tree_root = NULL; - goto out; - } - shift = (height - 1) * OBJNODE_TREE_MAP_SHIFT; - pathp->objnode = NULL; - do { - if (slot == NULL) - goto out; - pathp++; - offset = (index >> shift) & OBJNODE_TREE_MAP_MASK; - pathp->offset = offset; - pathp->objnode = slot; - slot = slot->slots[offset]; - shift -= OBJNODE_TREE_MAP_SHIFT; - height--; - } while (height > 0); - if (slot == NULL) - goto out; - while (pathp->objnode) { - pathp->objnode->slots[pathp->offset] = NULL; - pathp->objnode->slots_in_use--; - if (pathp->objnode->slots_in_use) { - if (pathp->objnode == obj->objnode_tree_root) { - while (obj->objnode_tree_height > 0 && - obj->objnode_tree_root->slots_in_use == 1 && - obj->objnode_tree_root->slots[0]) { - struct tmem_objnode *to_free = - obj->objnode_tree_root; - - obj->objnode_tree_root = - to_free->slots[0]; - obj->objnode_tree_height--; - to_free->slots[0] = NULL; - to_free->slots_in_use = 0; - tmem_objnode_free(to_free); - } - } - goto out; - } - tmem_objnode_free(pathp->objnode); /* 0 slots used, free it */ - pathp--; - } - obj->objnode_tree_height = 0; - obj->objnode_tree_root = NULL; - -out: - if (slot != NULL) - obj->pampd_count--; - BUG_ON(obj->pampd_count < 0); - return slot; -} - -/* recursively walk the objnode_tree destroying pampds and objnodes */ -static void tmem_objnode_node_destroy(struct tmem_obj *obj, - struct tmem_objnode *objnode, - unsigned int ht) -{ - int i; - - if (ht == 0) - return; - for (i = 0; i < OBJNODE_TREE_MAP_SIZE; i++) { - if (objnode->slots[i]) { - if (ht == 1) { - obj->pampd_count--; - (*tmem_pamops.free)(objnode->slots[i], - obj->pool, NULL, 0, true); - objnode->slots[i] = NULL; - continue; - } - tmem_objnode_node_destroy(obj, objnode->slots[i], ht-1); - tmem_objnode_free(objnode->slots[i]); - objnode->slots[i] = NULL; - } - } -} - -static void tmem_pampd_destroy_all_in_obj(struct tmem_obj *obj) -{ - if (obj->objnode_tree_root == NULL) - return; - if (obj->objnode_tree_height == 0) { - obj->pampd_count--; - (*tmem_pamops.free)(obj->objnode_tree_root, - obj->pool, NULL, 0, true); - } else { - tmem_objnode_node_destroy(obj, obj->objnode_tree_root, - obj->objnode_tree_height); - tmem_objnode_free(obj->objnode_tree_root); - obj->objnode_tree_height = 0; - } - obj->objnode_tree_root = NULL; - (*tmem_pamops.free_obj)(obj->pool, obj); -} - -/* - * Tmem is operated on by a set of well-defined actions: - * "put", "get", "flush", "flush_object", "new pool" and "destroy pool". - * (The tmem ABI allows for subpages and exchanges but these operations - * are not included in this implementation.) - * - * These "tmem core" operations are implemented in the following functions. - */ - -/* - * "Put" a page, e.g. copy a page from the kernel into newly allocated - * PAM space (if such space is available). Tmem_put is complicated by - * a corner case: What if a page with matching handle already exists in - * tmem? To guarantee coherency, one of two actions is necessary: Either - * the data for the page must be overwritten, or the page must be - * "flushed" so that the data is not accessible to a subsequent "get". - * Since these "duplicate puts" are relatively rare, this implementation - * always flushes for simplicity. - */ -int tmem_put(struct tmem_pool *pool, struct tmem_oid *oidp, uint32_t index, - char *data, size_t size, bool raw, int ephemeral) -{ - struct tmem_obj *obj = NULL, *objfound = NULL, *objnew = NULL; - void *pampd = NULL, *pampd_del = NULL; - int ret = -ENOMEM; - struct tmem_hashbucket *hb; - - hb = &pool->hashbucket[tmem_oid_hash(oidp)]; - spin_lock(&hb->lock); - obj = objfound = tmem_obj_find(hb, oidp); - if (obj != NULL) { - pampd = tmem_pampd_lookup_in_obj(objfound, index); - if (pampd != NULL) { - /* if found, is a dup put, flush the old one */ - pampd_del = tmem_pampd_delete_from_obj(obj, index); - BUG_ON(pampd_del != pampd); - (*tmem_pamops.free)(pampd, pool, oidp, index, true); - if (obj->pampd_count == 0) { - objnew = obj; - objfound = NULL; - } - pampd = NULL; - } - } else { - obj = objnew = (*tmem_hostops.obj_alloc)(pool); - if (unlikely(obj == NULL)) { - ret = -ENOMEM; - goto out; - } - tmem_obj_init(obj, hb, pool, oidp); - } - BUG_ON(obj == NULL); - BUG_ON(((objnew != obj) && (objfound != obj)) || (objnew == objfound)); - pampd = (*tmem_pamops.create)(data, size, raw, ephemeral, - obj->pool, &obj->oid, index); - if (unlikely(pampd == NULL)) - goto free; - ret = tmem_pampd_add_to_obj(obj, index, pampd); - if (unlikely(ret == -ENOMEM)) - /* may have partially built objnode tree ("stump") */ - goto delete_and_free; - goto out; - -delete_and_free: - (void)tmem_pampd_delete_from_obj(obj, index); -free: - if (pampd) - (*tmem_pamops.free)(pampd, pool, NULL, 0, true); - if (objnew) { - tmem_obj_free(objnew, hb); - (*tmem_hostops.obj_free)(objnew, pool); - } -out: - spin_unlock(&hb->lock); - return ret; -} - -void *tmem_localify_get_pampd(struct tmem_pool *pool, struct tmem_oid *oidp, - uint32_t index, struct tmem_obj **ret_obj, - void **saved_hb) -{ - struct tmem_hashbucket *hb; - struct tmem_obj *obj = NULL; - void *pampd = NULL; - - hb = &pool->hashbucket[tmem_oid_hash(oidp)]; - spin_lock(&hb->lock); - obj = tmem_obj_find(hb, oidp); - if (likely(obj != NULL)) - pampd = tmem_pampd_lookup_in_obj(obj, index); - *ret_obj = obj; - *saved_hb = (void *)hb; - /* note, hashbucket remains locked */ - return pampd; -} - -void tmem_localify_finish(struct tmem_obj *obj, uint32_t index, - void *pampd, void *saved_hb, bool delete) -{ - struct tmem_hashbucket *hb = (struct tmem_hashbucket *)saved_hb; - - BUG_ON(!spin_is_locked(&hb->lock)); - if (pampd != NULL) { - BUG_ON(obj == NULL); - (void)tmem_pampd_replace_in_obj(obj, index, pampd, 1); - } else if (delete) { - BUG_ON(obj == NULL); - (void)tmem_pampd_delete_from_obj(obj, index); - } - spin_unlock(&hb->lock); -} - -static int tmem_repatriate(void **ppampd, struct tmem_hashbucket *hb, - struct tmem_pool *pool, struct tmem_oid *oidp, - uint32_t index, bool free, char *data) -{ - void *old_pampd = *ppampd, *new_pampd = NULL; - bool intransit = false; - int ret = 0; - - - if (!is_ephemeral(pool)) - new_pampd = (*tmem_pamops.repatriate_preload)( - old_pampd, pool, oidp, index, &intransit); - if (intransit) - ret = -EAGAIN; - else if (new_pampd != NULL) - *ppampd = new_pampd; - /* must release the hb->lock else repatriate can't sleep */ - spin_unlock(&hb->lock); - if (!intransit) - ret = (*tmem_pamops.repatriate)(old_pampd, new_pampd, pool, - oidp, index, free, data); - return ret; -} - -/* - * "Get" a page, e.g. if one can be found, copy the tmem page with the - * matching handle from PAM space to the kernel. By tmem definition, - * when a "get" is successful on an ephemeral page, the page is "flushed", - * and when a "get" is successful on a persistent page, the page is retained - * in tmem. Note that to preserve - * coherency, "get" can never be skipped if tmem contains the data. - * That is, if a get is done with a certain handle and fails, any - * subsequent "get" must also fail (unless of course there is a - * "put" done with the same handle). - - */ -int tmem_get(struct tmem_pool *pool, struct tmem_oid *oidp, uint32_t index, - char *data, size_t *size, bool raw, int get_and_free) -{ - struct tmem_obj *obj; - void *pampd; - bool ephemeral = is_ephemeral(pool); - int ret = -1; - struct tmem_hashbucket *hb; - bool free = (get_and_free == 1) || ((get_and_free == 0) && ephemeral); - bool lock_held = 0; - void **ppampd; - -again: - hb = &pool->hashbucket[tmem_oid_hash(oidp)]; - spin_lock(&hb->lock); - lock_held = 1; - obj = tmem_obj_find(hb, oidp); - if (obj == NULL) - goto out; - ppampd = __tmem_pampd_lookup_in_obj(obj, index); - if (ppampd == NULL) - goto out; - if (tmem_pamops.is_remote(*ppampd)) { - ret = tmem_repatriate(ppampd, hb, pool, oidp, - index, free, data); - lock_held = 0; /* note hb->lock has been unlocked */ - if (ret == -EAGAIN) { - /* rare I think, but should cond_resched()??? */ - usleep_range(10, 1000); - goto again; - } else if (ret != 0) { - if (ret != -ENOENT) - pr_err("UNTESTED case in tmem_get, ret=%d\n", - ret); - ret = -1; - goto out; - } - goto out; - } - if (free) - pampd = tmem_pampd_delete_from_obj(obj, index); - else - pampd = tmem_pampd_lookup_in_obj(obj, index); - if (pampd == NULL) - goto out; - if (free) { - if (obj->pampd_count == 0) { - tmem_obj_free(obj, hb); - (*tmem_hostops.obj_free)(obj, pool); - obj = NULL; - } - } - if (free) - ret = (*tmem_pamops.get_data_and_free)( - data, size, raw, pampd, pool, oidp, index); - else - ret = (*tmem_pamops.get_data)( - data, size, raw, pampd, pool, oidp, index); - if (ret < 0) - goto out; - ret = 0; -out: - if (lock_held) - spin_unlock(&hb->lock); - return ret; -} - -/* - * If a page in tmem matches the handle, "flush" this page from tmem such - * that any subsequent "get" does not succeed (unless, of course, there - * was another "put" with the same handle). - */ -int tmem_flush_page(struct tmem_pool *pool, - struct tmem_oid *oidp, uint32_t index) -{ - struct tmem_obj *obj; - void *pampd; - int ret = -1; - struct tmem_hashbucket *hb; - - hb = &pool->hashbucket[tmem_oid_hash(oidp)]; - spin_lock(&hb->lock); - obj = tmem_obj_find(hb, oidp); - if (obj == NULL) - goto out; - pampd = tmem_pampd_delete_from_obj(obj, index); - if (pampd == NULL) - goto out; - (*tmem_pamops.free)(pampd, pool, oidp, index, true); - if (obj->pampd_count == 0) { - tmem_obj_free(obj, hb); - (*tmem_hostops.obj_free)(obj, pool); - } - ret = 0; - -out: - spin_unlock(&hb->lock); - return ret; -} - -/* - * If a page in tmem matches the handle, replace the page so that any - * subsequent "get" gets the new page. Returns the new page if - * there was a page to replace, else returns NULL. - */ -int tmem_replace(struct tmem_pool *pool, struct tmem_oid *oidp, - uint32_t index, void *new_pampd) -{ - struct tmem_obj *obj; - int ret = -1; - struct tmem_hashbucket *hb; - - hb = &pool->hashbucket[tmem_oid_hash(oidp)]; - spin_lock(&hb->lock); - obj = tmem_obj_find(hb, oidp); - if (obj == NULL) - goto out; - new_pampd = tmem_pampd_replace_in_obj(obj, index, new_pampd, 0); - ret = (*tmem_pamops.replace_in_obj)(new_pampd, obj); -out: - spin_unlock(&hb->lock); - return ret; -} - -/* - * "Flush" all pages in tmem matching this oid. - */ -int tmem_flush_object(struct tmem_pool *pool, struct tmem_oid *oidp) -{ - struct tmem_obj *obj; - struct tmem_hashbucket *hb; - int ret = -1; - - hb = &pool->hashbucket[tmem_oid_hash(oidp)]; - spin_lock(&hb->lock); - obj = tmem_obj_find(hb, oidp); - if (obj == NULL) - goto out; - tmem_pampd_destroy_all_in_obj(obj); - tmem_obj_free(obj, hb); - (*tmem_hostops.obj_free)(obj, pool); - ret = 0; - -out: - spin_unlock(&hb->lock); - return ret; -} - -/* - * "Flush" all pages (and tmem_objs) from this tmem_pool and disable - * all subsequent access to this tmem_pool. - */ -int tmem_destroy_pool(struct tmem_pool *pool) -{ - int ret = -1; - - if (pool == NULL) - goto out; - tmem_pool_flush(pool, 1); - ret = 0; -out: - return ret; -} - -static LIST_HEAD(tmem_global_pool_list); - -/* - * Create a new tmem_pool with the provided flag and return - * a pool id provided by the tmem host implementation. - */ -void tmem_new_pool(struct tmem_pool *pool, uint32_t flags) -{ - int persistent = flags & TMEM_POOL_PERSIST; - int shared = flags & TMEM_POOL_SHARED; - struct tmem_hashbucket *hb = &pool->hashbucket[0]; - int i; - - for (i = 0; i < TMEM_HASH_BUCKETS; i++, hb++) { - hb->obj_rb_root = RB_ROOT; - spin_lock_init(&hb->lock); - } - INIT_LIST_HEAD(&pool->pool_list); - atomic_set(&pool->obj_count, 0); - SET_SENTINEL(pool, POOL); - list_add_tail(&pool->pool_list, &tmem_global_pool_list); - pool->persistent = persistent; - pool->shared = shared; -} diff --git a/drivers/staging/ramster/tmem.h b/drivers/staging/ramster/tmem.h deleted file mode 100644 index 47f1918..0000000 --- a/drivers/staging/ramster/tmem.h +++ /dev/null @@ -1,244 +0,0 @@ -/* - * tmem.h - * - * Transcendent memory - * - * Copyright (c) 2009-2011, Dan Magenheimer, Oracle Corp. - */ - -#ifndef _TMEM_H_ -#define _TMEM_H_ - -#include -#include -#include - -/* - * These are pre-defined by the Xen<->Linux ABI - */ -#define TMEM_PUT_PAGE 4 -#define TMEM_GET_PAGE 5 -#define TMEM_FLUSH_PAGE 6 -#define TMEM_FLUSH_OBJECT 7 -#define TMEM_POOL_PERSIST 1 -#define TMEM_POOL_SHARED 2 -#define TMEM_POOL_PRECOMPRESSED 4 -#define TMEM_POOL_PAGESIZE_SHIFT 4 -#define TMEM_POOL_PAGESIZE_MASK 0xf -#define TMEM_POOL_RESERVED_BITS 0x00ffff00 - -/* - * sentinels have proven very useful for debugging but can be removed - * or disabled before final merge. - */ -#define SENTINELS -#ifdef SENTINELS -#define DECL_SENTINEL uint32_t sentinel; -#define SET_SENTINEL(_x, _y) (_x->sentinel = _y##_SENTINEL) -#define INVERT_SENTINEL(_x, _y) (_x->sentinel = ~_y##_SENTINEL) -#define ASSERT_SENTINEL(_x, _y) WARN_ON(_x->sentinel != _y##_SENTINEL) -#define ASSERT_INVERTED_SENTINEL(_x, _y) WARN_ON(_x->sentinel != ~_y##_SENTINEL) -#else -#define DECL_SENTINEL -#define SET_SENTINEL(_x, _y) do { } while (0) -#define INVERT_SENTINEL(_x, _y) do { } while (0) -#define ASSERT_SENTINEL(_x, _y) do { } while (0) -#define ASSERT_INVERTED_SENTINEL(_x, _y) do { } while (0) -#endif - -#define ASSERT_SPINLOCK(_l) WARN_ON(!spin_is_locked(_l)) - -/* - * A pool is the highest-level data structure managed by tmem and - * usually corresponds to a large independent set of pages such as - * a filesystem. Each pool has an id, and certain attributes and counters. - * It also contains a set of hash buckets, each of which contains an rbtree - * of objects and a lock to manage concurrency within the pool. - */ - -#define TMEM_HASH_BUCKET_BITS 8 -#define TMEM_HASH_BUCKETS (1<persistent) -#define is_ephemeral(_p) (!(_p->persistent)) - -/* - * An object id ("oid") is large: 192-bits (to ensure, for example, files - * in a modern filesystem can be uniquely identified). - */ - -struct tmem_oid { - uint64_t oid[3]; -}; - -struct tmem_xhandle { - uint8_t client_id; - uint8_t xh_data_cksum; - uint16_t xh_data_size; - uint16_t pool_id; - struct tmem_oid oid; - uint32_t index; - void *extra; -}; - -static inline struct tmem_xhandle tmem_xhandle_fill(uint16_t client_id, - struct tmem_pool *pool, - struct tmem_oid *oidp, - uint32_t index) -{ - struct tmem_xhandle xh; - xh.client_id = client_id; - xh.xh_data_cksum = (uint8_t)-1; - xh.xh_data_size = (uint16_t)-1; - xh.pool_id = pool->pool_id; - xh.oid = *oidp; - xh.index = index; - return xh; -} - -static inline void tmem_oid_set_invalid(struct tmem_oid *oidp) -{ - oidp->oid[0] = oidp->oid[1] = oidp->oid[2] = -1UL; -} - -static inline bool tmem_oid_valid(struct tmem_oid *oidp) -{ - return oidp->oid[0] != -1UL || oidp->oid[1] != -1UL || - oidp->oid[2] != -1UL; -} - -static inline int tmem_oid_compare(struct tmem_oid *left, - struct tmem_oid *right) -{ - int ret; - - if (left->oid[2] == right->oid[2]) { - if (left->oid[1] == right->oid[1]) { - if (left->oid[0] == right->oid[0]) - ret = 0; - else if (left->oid[0] < right->oid[0]) - ret = -1; - else - return 1; - } else if (left->oid[1] < right->oid[1]) - ret = -1; - else - ret = 1; - } else if (left->oid[2] < right->oid[2]) - ret = -1; - else - ret = 1; - return ret; -} - -static inline unsigned tmem_oid_hash(struct tmem_oid *oidp) -{ - return hash_long(oidp->oid[0] ^ oidp->oid[1] ^ oidp->oid[2], - TMEM_HASH_BUCKET_BITS); -} - -/* - * A tmem_obj contains an identifier (oid), pointers to the parent - * pool and the rb_tree to which it belongs, counters, and an ordered - * set of pampds, structured in a radix-tree-like tree. The intermediate - * nodes of the tree are called tmem_objnodes. - */ - -struct tmem_objnode; - -struct tmem_obj { - struct tmem_oid oid; - struct tmem_pool *pool; - struct rb_node rb_tree_node; - struct tmem_objnode *objnode_tree_root; - unsigned int objnode_tree_height; - unsigned long objnode_count; - long pampd_count; - /* for current design of ramster, all pages belonging to - * an object reside on the same remotenode and extra is - * used to record the number of the remotenode so a - * flush-object operation can specify it */ - void *extra; /* for use by pampd implementation */ - DECL_SENTINEL -}; - -#define OBJNODE_TREE_MAP_SHIFT 6 -#define OBJNODE_TREE_MAP_SIZE (1UL << OBJNODE_TREE_MAP_SHIFT) -#define OBJNODE_TREE_MAP_MASK (OBJNODE_TREE_MAP_SIZE-1) -#define OBJNODE_TREE_INDEX_BITS (8 /* CHAR_BIT */ * sizeof(unsigned long)) -#define OBJNODE_TREE_MAX_PATH \ - (OBJNODE_TREE_INDEX_BITS/OBJNODE_TREE_MAP_SHIFT + 2) - -struct tmem_objnode { - struct tmem_obj *obj; - DECL_SENTINEL - void *slots[OBJNODE_TREE_MAP_SIZE]; - unsigned int slots_in_use; -}; - -/* pampd abstract datatype methods provided by the PAM implementation */ -struct tmem_pamops { - void *(*create)(char *, size_t, bool, int, - struct tmem_pool *, struct tmem_oid *, uint32_t); - int (*get_data)(char *, size_t *, bool, void *, struct tmem_pool *, - struct tmem_oid *, uint32_t); - int (*get_data_and_free)(char *, size_t *, bool, void *, - struct tmem_pool *, struct tmem_oid *, - uint32_t); - void (*free)(void *, struct tmem_pool *, - struct tmem_oid *, uint32_t, bool); - void (*free_obj)(struct tmem_pool *, struct tmem_obj *); - bool (*is_remote)(void *); - void *(*repatriate_preload)(void *, struct tmem_pool *, - struct tmem_oid *, uint32_t, bool *); - int (*repatriate)(void *, void *, struct tmem_pool *, - struct tmem_oid *, uint32_t, bool, void *); - void (*new_obj)(struct tmem_obj *); - int (*replace_in_obj)(void *, struct tmem_obj *); -}; -extern void tmem_register_pamops(struct tmem_pamops *m); - -/* memory allocation methods provided by the host implementation */ -struct tmem_hostops { - struct tmem_obj *(*obj_alloc)(struct tmem_pool *); - void (*obj_free)(struct tmem_obj *, struct tmem_pool *); - struct tmem_objnode *(*objnode_alloc)(struct tmem_pool *); - void (*objnode_free)(struct tmem_objnode *, struct tmem_pool *); -}; -extern void tmem_register_hostops(struct tmem_hostops *m); - -/* core tmem accessor functions */ -extern int tmem_put(struct tmem_pool *, struct tmem_oid *, uint32_t index, - char *, size_t, bool, int); -extern int tmem_get(struct tmem_pool *, struct tmem_oid *, uint32_t index, - char *, size_t *, bool, int); -extern int tmem_replace(struct tmem_pool *, struct tmem_oid *, uint32_t index, - void *); -extern void *tmem_localify_get_pampd(struct tmem_pool *, struct tmem_oid *, - uint32_t index, struct tmem_obj **, - void **); -extern void tmem_localify_finish(struct tmem_obj *, uint32_t index, - void *, void *, bool); -extern int tmem_flush_page(struct tmem_pool *, struct tmem_oid *, - uint32_t index); -extern int tmem_flush_object(struct tmem_pool *, struct tmem_oid *); -extern int tmem_destroy_pool(struct tmem_pool *); -extern void tmem_new_pool(struct tmem_pool *, uint32_t); -#endif /* _TMEM_H */ diff --git a/drivers/staging/ramster/zcache-main.c b/drivers/staging/ramster/zcache-main.c deleted file mode 100644 index 851e94a..0000000 --- a/drivers/staging/ramster/zcache-main.c +++ /dev/null @@ -1,3264 +0,0 @@ -/* - * zcache.c - * - * Copyright (c) 2010-2012, Dan Magenheimer, Oracle Corp. - * Copyright (c) 2010,2011, Nitin Gupta - * - * Zcache provides an in-kernel "host implementation" for transcendent memory - * and, thus indirectly, for cleancache and frontswap. Zcache includes two - * page-accessible memory [1] interfaces, both utilizing lzo1x compression: - * 1) "compression buddies" ("zbud") is used for ephemeral pages - * 2) xvmalloc is used for persistent pages. - * Xvmalloc (based on the TLSF allocator) has very low fragmentation - * so maximizes space efficiency, while zbud allows pairs (and potentially, - * in the future, more than a pair of) compressed pages to be closely linked - * so that reclaiming can be done via the kernel's physical-page-oriented - * "shrinker" interface. - * - * [1] For a definition of page-accessible memory (aka PAM), see: - * http://marc.info/?l=linux-mm&m=127811271605009 - * RAMSTER TODO: - * - handle remotifying of buddied pages (see zbud_remotify_zbpg) - * - kernel boot params: nocleancache/nofrontswap don't always work?!? - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "tmem.h" -#include "zcache.h" -#include "ramster.h" -#include "cluster/tcp.h" - -#include "../zram/xvmalloc.h" /* if built in drivers/staging */ - -#define RAMSTER_TESTING - -#if (!defined(CONFIG_CLEANCACHE) && !defined(CONFIG_FRONTSWAP)) -#error "ramster is useless without CONFIG_CLEANCACHE or CONFIG_FRONTSWAP" -#endif -#ifdef CONFIG_CLEANCACHE -#include -#endif -#ifdef CONFIG_FRONTSWAP -#include -#endif - -enum ramster_remotify_op { - RAMSTER_REMOTIFY_EPH_PUT, - RAMSTER_REMOTIFY_PERS_PUT, - RAMSTER_REMOTIFY_FLUSH_PAGE, - RAMSTER_REMOTIFY_FLUSH_OBJ, - RAMSTER_INTRANSIT_PERS -}; - -struct ramster_remotify_hdr { - enum ramster_remotify_op op; - struct list_head list; -}; - -#define ZBH_SENTINEL 0x43214321 -#define ZBPG_SENTINEL 0xdeadbeef - -#define ZBUD_MAX_BUDS 2 - -struct zbud_hdr { - struct ramster_remotify_hdr rem_op; - uint16_t client_id; - uint16_t pool_id; - struct tmem_oid oid; - uint32_t index; - uint16_t size; /* compressed size in bytes, zero means unused */ - DECL_SENTINEL -}; - -#define ZVH_SENTINEL 0x43214321 -static const int zv_max_page_size = (PAGE_SIZE / 8) * 7; - -struct zv_hdr { - struct ramster_remotify_hdr rem_op; - uint16_t client_id; - uint16_t pool_id; - struct tmem_oid oid; - uint32_t index; - DECL_SENTINEL -}; - -struct flushlist_node { - struct ramster_remotify_hdr rem_op; - struct tmem_xhandle xh; -}; - -union { - struct ramster_remotify_hdr rem_op; - struct zv_hdr zv; - struct zbud_hdr zbud; - struct flushlist_node flist; -} remotify_list_node; - -static LIST_HEAD(zcache_rem_op_list); -static DEFINE_SPINLOCK(zcache_rem_op_list_lock); - -#if 0 -/* this is more aggressive but may cause other problems? */ -#define ZCACHE_GFP_MASK (GFP_ATOMIC | __GFP_NORETRY | __GFP_NOWARN) -#else -#define ZCACHE_GFP_MASK \ - (__GFP_FS | __GFP_NORETRY | __GFP_NOWARN | __GFP_NOMEMALLOC) -#endif - -#define MAX_POOLS_PER_CLIENT 16 - -#define MAX_CLIENTS 16 -#define LOCAL_CLIENT ((uint16_t)-1) - -MODULE_LICENSE("GPL"); - -struct zcache_client { - struct tmem_pool *tmem_pools[MAX_POOLS_PER_CLIENT]; - struct xv_pool *xvpool; - bool allocated; - atomic_t refcount; -}; - -static struct zcache_client zcache_host; -static struct zcache_client zcache_clients[MAX_CLIENTS]; - -static inline uint16_t get_client_id_from_client(struct zcache_client *cli) -{ - BUG_ON(cli == NULL); - if (cli == &zcache_host) - return LOCAL_CLIENT; - return cli - &zcache_clients[0]; -} - -static inline bool is_local_client(struct zcache_client *cli) -{ - return cli == &zcache_host; -} - -/********** - * Compression buddies ("zbud") provides for packing two (or, possibly - * in the future, more) compressed ephemeral pages into a single "raw" - * (physical) page and tracking them with data structures so that - * the raw pages can be easily reclaimed. - * - * A zbud page ("zbpg") is an aligned page containing a list_head, - * a lock, and two "zbud headers". The remainder of the physical - * page is divided up into aligned 64-byte "chunks" which contain - * the compressed data for zero, one, or two zbuds. Each zbpg - * resides on: (1) an "unused list" if it has no zbuds; (2) a - * "buddied" list if it is fully populated with two zbuds; or - * (3) one of PAGE_SIZE/64 "unbuddied" lists indexed by how many chunks - * the one unbuddied zbud uses. The data inside a zbpg cannot be - * read or written unless the zbpg's lock is held. - */ - -struct zbud_page { - struct list_head bud_list; - spinlock_t lock; - struct zbud_hdr buddy[ZBUD_MAX_BUDS]; - DECL_SENTINEL - /* followed by NUM_CHUNK aligned CHUNK_SIZE-byte chunks */ -}; - -#define CHUNK_SHIFT 6 -#define CHUNK_SIZE (1 << CHUNK_SHIFT) -#define CHUNK_MASK (~(CHUNK_SIZE-1)) -#define NCHUNKS (((PAGE_SIZE - sizeof(struct zbud_page)) & \ - CHUNK_MASK) >> CHUNK_SHIFT) -#define MAX_CHUNK (NCHUNKS-1) - -static struct { - struct list_head list; - unsigned count; -} zbud_unbuddied[NCHUNKS]; -/* list N contains pages with N chunks USED and NCHUNKS-N unused */ -/* element 0 is never used but optimizing that isn't worth it */ -static unsigned long zbud_cumul_chunk_counts[NCHUNKS]; - -struct list_head zbud_buddied_list; -static unsigned long zcache_zbud_buddied_count; - -/* protects the buddied list and all unbuddied lists */ -static DEFINE_SPINLOCK(zbud_budlists_spinlock); - -static atomic_t zcache_zbud_curr_raw_pages; -static atomic_t zcache_zbud_curr_zpages; -static unsigned long zcache_zbud_curr_zbytes; -static unsigned long zcache_zbud_cumul_zpages; -static unsigned long zcache_zbud_cumul_zbytes; -static unsigned long zcache_compress_poor; -static unsigned long zcache_policy_percent_exceeded; -static unsigned long zcache_mean_compress_poor; - -/* - * RAMster counters - * - Remote pages are pages with a local pampd but the data is remote - * - Foreign pages are pages stored locally but belonging to another node - */ -static atomic_t ramster_remote_pers_pages = ATOMIC_INIT(0); -static unsigned long ramster_pers_remotify_enable; -static unsigned long ramster_eph_remotify_enable; -static unsigned long ramster_eph_pages_remoted; -static unsigned long ramster_eph_pages_remote_failed; -static unsigned long ramster_pers_pages_remoted; -static unsigned long ramster_pers_pages_remote_failed; -static unsigned long ramster_pers_pages_remote_nomem; -static unsigned long ramster_remote_objects_flushed; -static unsigned long ramster_remote_object_flushes_failed; -static unsigned long ramster_remote_pages_flushed; -static unsigned long ramster_remote_page_flushes_failed; -static unsigned long ramster_remote_eph_pages_succ_get; -static unsigned long ramster_remote_pers_pages_succ_get; -static unsigned long ramster_remote_eph_pages_unsucc_get; -static unsigned long ramster_remote_pers_pages_unsucc_get; -static atomic_t ramster_curr_flnode_count = ATOMIC_INIT(0); -static unsigned long ramster_curr_flnode_count_max; -static atomic_t ramster_foreign_eph_pampd_count = ATOMIC_INIT(0); -static unsigned long ramster_foreign_eph_pampd_count_max; -static atomic_t ramster_foreign_pers_pampd_count = ATOMIC_INIT(0); -static unsigned long ramster_foreign_pers_pampd_count_max; - -/* forward references */ -static void *zcache_get_free_page(void); -static void zcache_free_page(void *p); - -/* - * zbud helper functions - */ - -static inline unsigned zbud_max_buddy_size(void) -{ - return MAX_CHUNK << CHUNK_SHIFT; -} - -static inline unsigned zbud_size_to_chunks(unsigned size) -{ - BUG_ON(size == 0 || size > zbud_max_buddy_size()); - return (size + CHUNK_SIZE - 1) >> CHUNK_SHIFT; -} - -static inline int zbud_budnum(struct zbud_hdr *zh) -{ - unsigned offset = (unsigned long)zh & (PAGE_SIZE - 1); - struct zbud_page *zbpg = NULL; - unsigned budnum = -1U; - int i; - - for (i = 0; i < ZBUD_MAX_BUDS; i++) - if (offset == offsetof(typeof(*zbpg), buddy[i])) { - budnum = i; - break; - } - BUG_ON(budnum == -1U); - return budnum; -} - -static char *zbud_data(struct zbud_hdr *zh, unsigned size) -{ - struct zbud_page *zbpg; - char *p; - unsigned budnum; - - ASSERT_SENTINEL(zh, ZBH); - budnum = zbud_budnum(zh); - BUG_ON(size == 0 || size > zbud_max_buddy_size()); - zbpg = container_of(zh, struct zbud_page, buddy[budnum]); - ASSERT_SPINLOCK(&zbpg->lock); - p = (char *)zbpg; - if (budnum == 0) - p += ((sizeof(struct zbud_page) + CHUNK_SIZE - 1) & - CHUNK_MASK); - else if (budnum == 1) - p += PAGE_SIZE - ((size + CHUNK_SIZE - 1) & CHUNK_MASK); - return p; -} - -static void zbud_copy_from_pampd(char *data, size_t *size, struct zbud_hdr *zh) -{ - struct zbud_page *zbpg; - char *p; - unsigned budnum; - - ASSERT_SENTINEL(zh, ZBH); - budnum = zbud_budnum(zh); - zbpg = container_of(zh, struct zbud_page, buddy[budnum]); - spin_lock(&zbpg->lock); - BUG_ON(zh->size > *size); - p = (char *)zbpg; - if (budnum == 0) - p += ((sizeof(struct zbud_page) + CHUNK_SIZE - 1) & - CHUNK_MASK); - else if (budnum == 1) - p += PAGE_SIZE - ((zh->size + CHUNK_SIZE - 1) & CHUNK_MASK); - /* client should be filled in by caller */ - memcpy(data, p, zh->size); - *size = zh->size; - spin_unlock(&zbpg->lock); -} - -/* - * zbud raw page management - */ - -static struct zbud_page *zbud_alloc_raw_page(void) -{ - struct zbud_page *zbpg = NULL; - struct zbud_hdr *zh0, *zh1; - zbpg = zcache_get_free_page(); - if (likely(zbpg != NULL)) { - INIT_LIST_HEAD(&zbpg->bud_list); - zh0 = &zbpg->buddy[0]; zh1 = &zbpg->buddy[1]; - spin_lock_init(&zbpg->lock); - atomic_inc(&zcache_zbud_curr_raw_pages); - INIT_LIST_HEAD(&zbpg->bud_list); - SET_SENTINEL(zbpg, ZBPG); - zh0->size = 0; zh1->size = 0; - tmem_oid_set_invalid(&zh0->oid); - tmem_oid_set_invalid(&zh1->oid); - } - return zbpg; -} - -static void zbud_free_raw_page(struct zbud_page *zbpg) -{ - struct zbud_hdr *zh0 = &zbpg->buddy[0], *zh1 = &zbpg->buddy[1]; - - ASSERT_SENTINEL(zbpg, ZBPG); - BUG_ON(!list_empty(&zbpg->bud_list)); - ASSERT_SPINLOCK(&zbpg->lock); - BUG_ON(zh0->size != 0 || tmem_oid_valid(&zh0->oid)); - BUG_ON(zh1->size != 0 || tmem_oid_valid(&zh1->oid)); - INVERT_SENTINEL(zbpg, ZBPG); - spin_unlock(&zbpg->lock); - atomic_dec(&zcache_zbud_curr_raw_pages); - zcache_free_page(zbpg); -} - -/* - * core zbud handling routines - */ - -static unsigned zbud_free(struct zbud_hdr *zh) -{ - unsigned size; - - ASSERT_SENTINEL(zh, ZBH); - BUG_ON(!tmem_oid_valid(&zh->oid)); - size = zh->size; - BUG_ON(zh->size == 0 || zh->size > zbud_max_buddy_size()); - zh->size = 0; - tmem_oid_set_invalid(&zh->oid); - INVERT_SENTINEL(zh, ZBH); - zcache_zbud_curr_zbytes -= size; - atomic_dec(&zcache_zbud_curr_zpages); - return size; -} - -static void zbud_free_and_delist(struct zbud_hdr *zh) -{ - unsigned chunks; - struct zbud_hdr *zh_other; - unsigned budnum = zbud_budnum(zh), size; - struct zbud_page *zbpg = - container_of(zh, struct zbud_page, buddy[budnum]); - - /* FIXME, should be BUG_ON, pool destruction path doesn't disable - * interrupts tmem_destroy_pool()->tmem_pampd_destroy_all_in_obj()-> - * tmem_objnode_node_destroy()-> zcache_pampd_free() */ - WARN_ON(!irqs_disabled()); - spin_lock(&zbpg->lock); - if (list_empty(&zbpg->bud_list)) { - /* ignore zombie page... see zbud_evict_pages() */ - spin_unlock(&zbpg->lock); - return; - } - size = zbud_free(zh); - ASSERT_SPINLOCK(&zbpg->lock); - zh_other = &zbpg->buddy[(budnum == 0) ? 1 : 0]; - if (zh_other->size == 0) { /* was unbuddied: unlist and free */ - chunks = zbud_size_to_chunks(size) ; - spin_lock(&zbud_budlists_spinlock); - BUG_ON(list_empty(&zbud_unbuddied[chunks].list)); - list_del_init(&zbpg->bud_list); - zbud_unbuddied[chunks].count--; - spin_unlock(&zbud_budlists_spinlock); - zbud_free_raw_page(zbpg); - } else { /* was buddied: move remaining buddy to unbuddied list */ - chunks = zbud_size_to_chunks(zh_other->size) ; - spin_lock(&zbud_budlists_spinlock); - list_del_init(&zbpg->bud_list); - zcache_zbud_buddied_count--; - list_add_tail(&zbpg->bud_list, &zbud_unbuddied[chunks].list); - zbud_unbuddied[chunks].count++; - spin_unlock(&zbud_budlists_spinlock); - spin_unlock(&zbpg->lock); - } -} - -static struct zbud_hdr *zbud_create(uint16_t client_id, uint16_t pool_id, - struct tmem_oid *oid, - uint32_t index, struct page *page, - void *cdata, unsigned size) -{ - struct zbud_hdr *zh0, *zh1, *zh = NULL; - struct zbud_page *zbpg = NULL, *ztmp; - unsigned nchunks; - char *to; - int i, found_good_buddy = 0; - - nchunks = zbud_size_to_chunks(size) ; - for (i = MAX_CHUNK - nchunks + 1; i > 0; i--) { - spin_lock(&zbud_budlists_spinlock); - if (!list_empty(&zbud_unbuddied[i].list)) { - list_for_each_entry_safe(zbpg, ztmp, - &zbud_unbuddied[i].list, bud_list) { - if (spin_trylock(&zbpg->lock)) { - found_good_buddy = i; - goto found_unbuddied; - } - } - } - spin_unlock(&zbud_budlists_spinlock); - } - /* didn't find a good buddy, try allocating a new page */ - zbpg = zbud_alloc_raw_page(); - if (unlikely(zbpg == NULL)) - goto out; - /* ok, have a page, now compress the data before taking locks */ - spin_lock(&zbud_budlists_spinlock); - spin_lock(&zbpg->lock); - list_add_tail(&zbpg->bud_list, &zbud_unbuddied[nchunks].list); - zbud_unbuddied[nchunks].count++; - zh = &zbpg->buddy[0]; - goto init_zh; - -found_unbuddied: - ASSERT_SPINLOCK(&zbpg->lock); - zh0 = &zbpg->buddy[0]; zh1 = &zbpg->buddy[1]; - BUG_ON(!((zh0->size == 0) ^ (zh1->size == 0))); - if (zh0->size != 0) { /* buddy0 in use, buddy1 is vacant */ - ASSERT_SENTINEL(zh0, ZBH); - zh = zh1; - } else if (zh1->size != 0) { /* buddy1 in use, buddy0 is vacant */ - ASSERT_SENTINEL(zh1, ZBH); - zh = zh0; - } else - BUG(); - list_del_init(&zbpg->bud_list); - zbud_unbuddied[found_good_buddy].count--; - list_add_tail(&zbpg->bud_list, &zbud_buddied_list); - zcache_zbud_buddied_count++; - -init_zh: - SET_SENTINEL(zh, ZBH); - zh->size = size; - zh->index = index; - zh->oid = *oid; - zh->pool_id = pool_id; - zh->client_id = client_id; - to = zbud_data(zh, size); - memcpy(to, cdata, size); - spin_unlock(&zbpg->lock); - spin_unlock(&zbud_budlists_spinlock); - zbud_cumul_chunk_counts[nchunks]++; - atomic_inc(&zcache_zbud_curr_zpages); - zcache_zbud_cumul_zpages++; - zcache_zbud_curr_zbytes += size; - zcache_zbud_cumul_zbytes += size; -out: - return zh; -} - -static int zbud_decompress(struct page *page, struct zbud_hdr *zh) -{ - struct zbud_page *zbpg; - unsigned budnum = zbud_budnum(zh); - size_t out_len = PAGE_SIZE; - char *to_va, *from_va; - unsigned size; - int ret = 0; - - zbpg = container_of(zh, struct zbud_page, buddy[budnum]); - spin_lock(&zbpg->lock); - if (list_empty(&zbpg->bud_list)) { - /* ignore zombie page... see zbud_evict_pages() */ - ret = -EINVAL; - goto out; - } - ASSERT_SENTINEL(zh, ZBH); - BUG_ON(zh->size == 0 || zh->size > zbud_max_buddy_size()); - to_va = kmap_atomic(page, KM_USER0); - size = zh->size; - from_va = zbud_data(zh, size); - ret = lzo1x_decompress_safe(from_va, size, to_va, &out_len); - BUG_ON(ret != LZO_E_OK); - BUG_ON(out_len != PAGE_SIZE); - kunmap_atomic(to_va, KM_USER0); -out: - spin_unlock(&zbpg->lock); - return ret; -} - -/* - * The following routines handle shrinking of ephemeral pages by evicting - * pages "least valuable" first. - */ - -static unsigned long zcache_evicted_raw_pages; -static unsigned long zcache_evicted_buddied_pages; -static unsigned long zcache_evicted_unbuddied_pages; - -static struct tmem_pool *zcache_get_pool_by_id(uint16_t cli_id, - uint16_t poolid); -static void zcache_put_pool(struct tmem_pool *pool); - -/* - * Flush and free all zbuds in a zbpg, then free the pageframe - */ -static void zbud_evict_zbpg(struct zbud_page *zbpg) -{ - struct zbud_hdr *zh; - int i, j; - uint32_t pool_id[ZBUD_MAX_BUDS], client_id[ZBUD_MAX_BUDS]; - uint32_t index[ZBUD_MAX_BUDS]; - struct tmem_oid oid[ZBUD_MAX_BUDS]; - struct tmem_pool *pool; - unsigned long flags; - - ASSERT_SPINLOCK(&zbpg->lock); - for (i = 0, j = 0; i < ZBUD_MAX_BUDS; i++) { - zh = &zbpg->buddy[i]; - if (zh->size) { - client_id[j] = zh->client_id; - pool_id[j] = zh->pool_id; - oid[j] = zh->oid; - index[j] = zh->index; - j++; - } - } - spin_unlock(&zbpg->lock); - for (i = 0; i < j; i++) { - pool = zcache_get_pool_by_id(client_id[i], pool_id[i]); - BUG_ON(pool == NULL); - local_irq_save(flags); - /* these flushes should dispose of any local storage */ - tmem_flush_page(pool, &oid[i], index[i]); - local_irq_restore(flags); - zcache_put_pool(pool); - } -} - -/* - * Free nr pages. This code is funky because we want to hold the locks - * protecting various lists for as short a time as possible, and in some - * circumstances the list may change asynchronously when the list lock is - * not held. In some cases we also trylock not only to avoid waiting on a - * page in use by another cpu, but also to avoid potential deadlock due to - * lock inversion. - */ -static void zbud_evict_pages(int nr) -{ - struct zbud_page *zbpg; - int i, newly_unused_pages = 0; - - - /* now try freeing unbuddied pages, starting with least space avail */ - for (i = 0; i < MAX_CHUNK; i++) { -retry_unbud_list_i: - spin_lock_bh(&zbud_budlists_spinlock); - if (list_empty(&zbud_unbuddied[i].list)) { - spin_unlock_bh(&zbud_budlists_spinlock); - continue; - } - list_for_each_entry(zbpg, &zbud_unbuddied[i].list, bud_list) { - if (unlikely(!spin_trylock(&zbpg->lock))) - continue; - zbud_unbuddied[i].count--; - spin_unlock(&zbud_budlists_spinlock); - zcache_evicted_unbuddied_pages++; - /* want budlists unlocked when doing zbpg eviction */ - zbud_evict_zbpg(zbpg); - newly_unused_pages++; - local_bh_enable(); - if (--nr <= 0) - goto evict_unused; - goto retry_unbud_list_i; - } - spin_unlock_bh(&zbud_budlists_spinlock); - } - - /* as a last resort, free buddied pages */ -retry_bud_list: - spin_lock_bh(&zbud_budlists_spinlock); - if (list_empty(&zbud_buddied_list)) { - spin_unlock_bh(&zbud_budlists_spinlock); - goto evict_unused; - } - list_for_each_entry(zbpg, &zbud_buddied_list, bud_list) { - if (unlikely(!spin_trylock(&zbpg->lock))) - continue; - zcache_zbud_buddied_count--; - spin_unlock(&zbud_budlists_spinlock); - zcache_evicted_buddied_pages++; - /* want budlists unlocked when doing zbpg eviction */ - zbud_evict_zbpg(zbpg); - newly_unused_pages++; - local_bh_enable(); - if (--nr <= 0) - goto evict_unused; - goto retry_bud_list; - } - spin_unlock_bh(&zbud_budlists_spinlock); - -evict_unused: - return; -} - -static DEFINE_PER_CPU(unsigned char *, zcache_remoteputmem); - -static int zbud_remotify_zbud(struct tmem_xhandle *xh, char *data, - size_t size) -{ - struct tmem_pool *pool; - int i, remotenode, ret = -1; - unsigned char cksum, *p; - unsigned long flags; - - for (p = data, cksum = 0, i = 0; i < size; i++) - cksum += *p; - ret = ramster_remote_put(xh, data, size, true, &remotenode); - if (ret == 0) { - /* data was successfully remoted so change the local version - * to point to the remote node where it landed */ - pool = zcache_get_pool_by_id(LOCAL_CLIENT, xh->pool_id); - BUG_ON(pool == NULL); - local_irq_save(flags); - /* tmem_replace will also free up any local space */ - (void)tmem_replace(pool, &xh->oid, xh->index, - pampd_make_remote(remotenode, size, cksum)); - local_irq_restore(flags); - zcache_put_pool(pool); - ramster_eph_pages_remoted++; - ret = 0; - } else - ramster_eph_pages_remote_failed++; - return ret; -} - -static int zbud_remotify_zbpg(struct zbud_page *zbpg) -{ - struct zbud_hdr *zh1, *zh2 = NULL; - struct tmem_xhandle xh1, xh2 = { 0 }; - char *data1 = NULL, *data2 = NULL; - size_t size1 = 0, size2 = 0; - int ret = 0; - unsigned char *tmpmem = __get_cpu_var(zcache_remoteputmem); - - ASSERT_SPINLOCK(&zbpg->lock); - if (zbpg->buddy[0].size == 0) - zh1 = &zbpg->buddy[1]; - else if (zbpg->buddy[1].size == 0) - zh1 = &zbpg->buddy[0]; - else { - zh1 = &zbpg->buddy[0]; - zh2 = &zbpg->buddy[1]; - } - /* don't remotify pages that are already remotified */ - if (zh1->client_id != LOCAL_CLIENT) - zh1 = NULL; - if ((zh2 != NULL) && (zh2->client_id != LOCAL_CLIENT)) - zh2 = NULL; - - /* copy the data and metadata so can release lock */ - if (zh1 != NULL) { - xh1.client_id = zh1->client_id; - xh1.pool_id = zh1->pool_id; - xh1.oid = zh1->oid; - xh1.index = zh1->index; - size1 = zh1->size; - data1 = zbud_data(zh1, size1); - memcpy(tmpmem, zbud_data(zh1, size1), size1); - data1 = tmpmem; - tmpmem += size1; - } - if (zh2 != NULL) { - xh2.client_id = zh2->client_id; - xh2.pool_id = zh2->pool_id; - xh2.oid = zh2->oid; - xh2.index = zh2->index; - size2 = zh2->size; - memcpy(tmpmem, zbud_data(zh2, size2), size2); - data2 = tmpmem; - } - spin_unlock(&zbpg->lock); - preempt_enable(); - - /* OK, no locks held anymore, remotify one or both zbuds */ - if (zh1 != NULL) - ret = zbud_remotify_zbud(&xh1, data1, size1); - if (zh2 != NULL) - ret |= zbud_remotify_zbud(&xh2, data2, size2); - return ret; -} - -void zbud_remotify_pages(int nr) -{ - struct zbud_page *zbpg; - int i, ret; - - /* - * for now just try remotifying unbuddied pages, starting with - * least space avail - */ - for (i = 0; i < MAX_CHUNK; i++) { -retry_unbud_list_i: - preempt_disable(); /* enable in zbud_remotify_zbpg */ - spin_lock_bh(&zbud_budlists_spinlock); - if (list_empty(&zbud_unbuddied[i].list)) { - spin_unlock_bh(&zbud_budlists_spinlock); - preempt_enable(); - continue; /* next i in for loop */ - } - list_for_each_entry(zbpg, &zbud_unbuddied[i].list, bud_list) { - if (unlikely(!spin_trylock(&zbpg->lock))) - continue; /* next list_for_each_entry */ - zbud_unbuddied[i].count--; - /* want budlists unlocked when doing zbpg remotify */ - spin_unlock_bh(&zbud_budlists_spinlock); - ret = zbud_remotify_zbpg(zbpg); - /* preemption is re-enabled in zbud_remotify_zbpg */ - if (ret == 0) { - if (--nr <= 0) - goto out; - goto retry_unbud_list_i; - } - /* if fail to remotify any page, quit */ - pr_err("TESTING zbud_remotify_pages failed on page," - " trying to re-add\n"); - spin_lock_bh(&zbud_budlists_spinlock); - spin_lock(&zbpg->lock); - list_add_tail(&zbpg->bud_list, &zbud_unbuddied[i].list); - zbud_unbuddied[i].count++; - spin_unlock(&zbpg->lock); - spin_unlock_bh(&zbud_budlists_spinlock); - pr_err("TESTING zbud_remotify_pages failed on page," - " finished re-add\n"); - goto out; - } - spin_unlock_bh(&zbud_budlists_spinlock); - preempt_enable(); - } - -next_buddied_zbpg: - preempt_disable(); /* enable in zbud_remotify_zbpg */ - spin_lock_bh(&zbud_budlists_spinlock); - if (list_empty(&zbud_buddied_list)) - goto unlock_out; - list_for_each_entry(zbpg, &zbud_buddied_list, bud_list) { - if (unlikely(!spin_trylock(&zbpg->lock))) - continue; /* next list_for_each_entry */ - zcache_zbud_buddied_count--; - /* want budlists unlocked when doing zbpg remotify */ - spin_unlock_bh(&zbud_budlists_spinlock); - ret = zbud_remotify_zbpg(zbpg); - /* preemption is re-enabled in zbud_remotify_zbpg */ - if (ret == 0) { - if (--nr <= 0) - goto out; - goto next_buddied_zbpg; - } - /* if fail to remotify any page, quit */ - pr_err("TESTING zbud_remotify_pages failed on BUDDIED page," - " trying to re-add\n"); - spin_lock_bh(&zbud_budlists_spinlock); - spin_lock(&zbpg->lock); - list_add_tail(&zbpg->bud_list, &zbud_buddied_list); - zcache_zbud_buddied_count++; - spin_unlock(&zbpg->lock); - spin_unlock_bh(&zbud_budlists_spinlock); - pr_err("TESTING zbud_remotify_pages failed on BUDDIED page," - " finished re-add\n"); - goto out; - } -unlock_out: - spin_unlock_bh(&zbud_budlists_spinlock); - preempt_enable(); -out: - return; -} - -/* the "flush list" asynchronously collects pages to remotely flush */ -#define FLUSH_ENTIRE_OBJECT ((uint32_t)-1) -static void ramster_flnode_free(struct flushlist_node *, - struct tmem_pool *); - -static void zcache_remote_flush_page(struct flushlist_node *flnode) -{ - struct tmem_xhandle *xh; - int remotenode, ret; - - preempt_disable(); - xh = &flnode->xh; - remotenode = flnode->xh.client_id; - ret = ramster_remote_flush(xh, remotenode); - if (ret >= 0) - ramster_remote_pages_flushed++; - else - ramster_remote_page_flushes_failed++; - preempt_enable_no_resched(); - ramster_flnode_free(flnode, NULL); -} - -static void zcache_remote_flush_object(struct flushlist_node *flnode) -{ - struct tmem_xhandle *xh; - int remotenode, ret; - - preempt_disable(); - xh = &flnode->xh; - remotenode = flnode->xh.client_id; - ret = ramster_remote_flush_object(xh, remotenode); - if (ret >= 0) - ramster_remote_objects_flushed++; - else - ramster_remote_object_flushes_failed++; - preempt_enable_no_resched(); - ramster_flnode_free(flnode, NULL); -} - -static void zcache_remote_eph_put(struct zbud_hdr *zbud) -{ - /* FIXME */ -} - -static void zcache_remote_pers_put(struct zv_hdr *zv) -{ - struct tmem_xhandle xh; - uint16_t size; - bool ephemeral; - int remotenode, ret = -1; - char *data; - struct tmem_pool *pool; - unsigned long flags; - unsigned char cksum; - char *p; - int i; - unsigned char *tmpmem = __get_cpu_var(zcache_remoteputmem); - - ASSERT_SENTINEL(zv, ZVH); - BUG_ON(zv->client_id != LOCAL_CLIENT); - local_bh_disable(); - xh.client_id = zv->client_id; - xh.pool_id = zv->pool_id; - xh.oid = zv->oid; - xh.index = zv->index; - size = xv_get_object_size(zv) - sizeof(*zv); - BUG_ON(size == 0 || size > zv_max_page_size); - data = (char *)zv + sizeof(*zv); - for (p = data, cksum = 0, i = 0; i < size; i++) - cksum += *p; - memcpy(tmpmem, data, size); - data = tmpmem; - pool = zcache_get_pool_by_id(zv->client_id, zv->pool_id); - ephemeral = is_ephemeral(pool); - zcache_put_pool(pool); - /* now OK to release lock set in caller */ - spin_unlock(&zcache_rem_op_list_lock); - local_bh_enable(); - preempt_disable(); - ret = ramster_remote_put(&xh, data, size, ephemeral, &remotenode); - preempt_enable_no_resched(); - if (ret != 0) { - /* - * This is some form of a memory leak... if the remote put - * fails, there will never be another attempt to remotify - * this page. But since we've dropped the zv pointer, - * the page may have been freed or the data replaced - * so we can't just "put it back" in the remote op list. - * Even if we could, not sure where to put it in the list - * because there may be flushes that must be strictly - * ordered vs the put. So leave this as a FIXME for now. - * But count them so we know if it becomes a problem. - */ - ramster_pers_pages_remote_failed++; - goto out; - } else - atomic_inc(&ramster_remote_pers_pages); - ramster_pers_pages_remoted++; - /* - * data was successfully remoted so change the local version to - * point to the remote node where it landed - */ - local_bh_disable(); - pool = zcache_get_pool_by_id(LOCAL_CLIENT, xh.pool_id); - local_irq_save(flags); - (void)tmem_replace(pool, &xh.oid, xh.index, - pampd_make_remote(remotenode, size, cksum)); - local_irq_restore(flags); - zcache_put_pool(pool); - local_bh_enable(); -out: - return; -} - -static void zcache_do_remotify_ops(int nr) -{ - struct ramster_remotify_hdr *rem_op; - union remotify_list_node *u; - - while (1) { - if (!nr) - goto out; - spin_lock(&zcache_rem_op_list_lock); - if (list_empty(&zcache_rem_op_list)) { - spin_unlock(&zcache_rem_op_list_lock); - goto out; - } - rem_op = list_first_entry(&zcache_rem_op_list, - struct ramster_remotify_hdr, list); - list_del_init(&rem_op->list); - if (rem_op->op != RAMSTER_REMOTIFY_PERS_PUT) - spin_unlock(&zcache_rem_op_list_lock); - u = (union remotify_list_node *)rem_op; - switch (rem_op->op) { - case RAMSTER_REMOTIFY_EPH_PUT: -BUG(); - zcache_remote_eph_put((struct zbud_hdr *)rem_op); - break; - case RAMSTER_REMOTIFY_PERS_PUT: - zcache_remote_pers_put((struct zv_hdr *)rem_op); - break; - case RAMSTER_REMOTIFY_FLUSH_PAGE: - zcache_remote_flush_page((struct flushlist_node *)u); - break; - case RAMSTER_REMOTIFY_FLUSH_OBJ: - zcache_remote_flush_object((struct flushlist_node *)u); - break; - default: - BUG(); - } - } -out: - return; -} - -/* - * For now, just push over a few pages every few seconds to - * ensure that it basically works - */ -static struct workqueue_struct *ramster_remotify_workqueue; -static void ramster_remotify_process(struct work_struct *work); -static DECLARE_DELAYED_WORK(ramster_remotify_worker, - ramster_remotify_process); - -static void ramster_remotify_queue_delayed_work(unsigned long delay) -{ - if (!queue_delayed_work(ramster_remotify_workqueue, - &ramster_remotify_worker, delay)) - pr_err("ramster_remotify: bad workqueue\n"); -} - - -static int use_frontswap; -static int use_cleancache; -static void ramster_remotify_process(struct work_struct *work) -{ - static bool remotify_in_progress; - - BUG_ON(irqs_disabled()); - if (remotify_in_progress) - ramster_remotify_queue_delayed_work(HZ); - else { - remotify_in_progress = true; -#ifdef CONFIG_CLEANCACHE - if (use_cleancache && ramster_eph_remotify_enable) - zbud_remotify_pages(5000); /* FIXME is this a good number? */ -#endif -#ifdef CONFIG_FRONTSWAP - if (use_frontswap && ramster_pers_remotify_enable) - zcache_do_remotify_ops(500); /* FIXME is this a good number? */ -#endif - remotify_in_progress = false; - ramster_remotify_queue_delayed_work(HZ); - } -} - -static void ramster_remotify_init(void) -{ - unsigned long n = 60UL; - ramster_remotify_workqueue = - create_singlethread_workqueue("ramster_remotify"); - ramster_remotify_queue_delayed_work(n * HZ); -} - - -static void zbud_init(void) -{ - int i; - - INIT_LIST_HEAD(&zbud_buddied_list); - zcache_zbud_buddied_count = 0; - for (i = 0; i < NCHUNKS; i++) { - INIT_LIST_HEAD(&zbud_unbuddied[i].list); - zbud_unbuddied[i].count = 0; - } -} - -#ifdef CONFIG_SYSFS -/* - * These sysfs routines show a nice distribution of how many zbpg's are - * currently (and have ever been placed) in each unbuddied list. It's fun - * to watch but can probably go away before final merge. - */ -static int zbud_show_unbuddied_list_counts(char *buf) -{ - int i; - char *p = buf; - - for (i = 0; i < NCHUNKS; i++) - p += sprintf(p, "%u ", zbud_unbuddied[i].count); - return p - buf; -} - -static int zbud_show_cumul_chunk_counts(char *buf) -{ - unsigned long i, chunks = 0, total_chunks = 0, sum_total_chunks = 0; - unsigned long total_chunks_lte_21 = 0, total_chunks_lte_32 = 0; - unsigned long total_chunks_lte_42 = 0; - char *p = buf; - - for (i = 0; i < NCHUNKS; i++) { - p += sprintf(p, "%lu ", zbud_cumul_chunk_counts[i]); - chunks += zbud_cumul_chunk_counts[i]; - total_chunks += zbud_cumul_chunk_counts[i]; - sum_total_chunks += i * zbud_cumul_chunk_counts[i]; - if (i == 21) - total_chunks_lte_21 = total_chunks; - if (i == 32) - total_chunks_lte_32 = total_chunks; - if (i == 42) - total_chunks_lte_42 = total_chunks; - } - p += sprintf(p, "<=21:%lu <=32:%lu <=42:%lu, mean:%lu\n", - total_chunks_lte_21, total_chunks_lte_32, total_chunks_lte_42, - chunks == 0 ? 0 : sum_total_chunks / chunks); - return p - buf; -} -#endif - -/********** - * This "zv" PAM implementation combines the TLSF-based xvMalloc - * with lzo1x compression to maximize the amount of data that can - * be packed into a physical page. - * - * Zv represents a PAM page with the index and object (plus a "size" value - * necessary for decompression) immediately preceding the compressed data. - */ - -/* rudimentary policy limits */ -/* total number of persistent pages may not exceed this percentage */ -static unsigned int zv_page_count_policy_percent = 75; -/* - * byte count defining poor compression; pages with greater zsize will be - * rejected - */ -static unsigned int zv_max_zsize = (PAGE_SIZE / 8) * 7; -/* - * byte count defining poor *mean* compression; pages with greater zsize - * will be rejected until sufficient better-compressed pages are accepted - * driving the mean below this threshold - */ -static unsigned int zv_max_mean_zsize = (PAGE_SIZE / 8) * 5; - -static atomic_t zv_curr_dist_counts[NCHUNKS]; -static atomic_t zv_cumul_dist_counts[NCHUNKS]; - - -static struct zv_hdr *zv_create(struct zcache_client *cli, uint32_t pool_id, - struct tmem_oid *oid, uint32_t index, - void *cdata, unsigned clen) -{ - struct page *page; - struct zv_hdr *zv = NULL; - uint32_t offset; - int alloc_size = clen + sizeof(struct zv_hdr); - int chunks = (alloc_size + (CHUNK_SIZE - 1)) >> CHUNK_SHIFT; - int ret; - - BUG_ON(!irqs_disabled()); - BUG_ON(chunks >= NCHUNKS); - ret = xv_malloc(cli->xvpool, clen + sizeof(struct zv_hdr), - &page, &offset, ZCACHE_GFP_MASK); - if (unlikely(ret)) - goto out; - atomic_inc(&zv_curr_dist_counts[chunks]); - atomic_inc(&zv_cumul_dist_counts[chunks]); - zv = kmap_atomic(page, KM_USER0) + offset; - zv->index = index; - zv->oid = *oid; - zv->pool_id = pool_id; - SET_SENTINEL(zv, ZVH); - INIT_LIST_HEAD(&zv->rem_op.list); - zv->client_id = get_client_id_from_client(cli); - zv->rem_op.op = RAMSTER_REMOTIFY_PERS_PUT; - if (zv->client_id == LOCAL_CLIENT) { - spin_lock(&zcache_rem_op_list_lock); - list_add_tail(&zv->rem_op.list, &zcache_rem_op_list); - spin_unlock(&zcache_rem_op_list_lock); - } - memcpy((char *)zv + sizeof(struct zv_hdr), cdata, clen); - kunmap_atomic(zv, KM_USER0); -out: - return zv; -} - -/* similar to zv_create, but just reserve space, no data yet */ -static struct zv_hdr *zv_alloc(struct tmem_pool *pool, - struct tmem_oid *oid, uint32_t index, - unsigned clen) -{ - struct zcache_client *cli = pool->client; - struct page *page; - struct zv_hdr *zv = NULL; - uint32_t offset; - int ret; - - BUG_ON(!irqs_disabled()); - BUG_ON(!is_local_client(pool->client)); - ret = xv_malloc(cli->xvpool, clen + sizeof(struct zv_hdr), - &page, &offset, ZCACHE_GFP_MASK); - if (unlikely(ret)) - goto out; - zv = kmap_atomic(page, KM_USER0) + offset; - SET_SENTINEL(zv, ZVH); - INIT_LIST_HEAD(&zv->rem_op.list); - zv->client_id = LOCAL_CLIENT; - zv->rem_op.op = RAMSTER_INTRANSIT_PERS; - zv->index = index; - zv->oid = *oid; - zv->pool_id = pool->pool_id; - kunmap_atomic(zv, KM_USER0); -out: - return zv; -} - -static void zv_free(struct xv_pool *xvpool, struct zv_hdr *zv) -{ - unsigned long flags; - struct page *page; - uint32_t offset; - uint16_t size = xv_get_object_size(zv); - int chunks = (size + (CHUNK_SIZE - 1)) >> CHUNK_SHIFT; - - ASSERT_SENTINEL(zv, ZVH); - BUG_ON(chunks >= NCHUNKS); - atomic_dec(&zv_curr_dist_counts[chunks]); - size -= sizeof(*zv); - spin_lock(&zcache_rem_op_list_lock); - size = xv_get_object_size(zv) - sizeof(*zv); - BUG_ON(size == 0); - INVERT_SENTINEL(zv, ZVH); - if (!list_empty(&zv->rem_op.list)) - list_del_init(&zv->rem_op.list); - spin_unlock(&zcache_rem_op_list_lock); - page = virt_to_page(zv); - offset = (unsigned long)zv & ~PAGE_MASK; - local_irq_save(flags); - xv_free(xvpool, page, offset); - local_irq_restore(flags); -} - -static void zv_decompress(struct page *page, struct zv_hdr *zv) -{ - size_t clen = PAGE_SIZE; - char *to_va; - unsigned size; - int ret; - - ASSERT_SENTINEL(zv, ZVH); - size = xv_get_object_size(zv) - sizeof(*zv); - BUG_ON(size == 0); - to_va = kmap_atomic(page, KM_USER0); - ret = lzo1x_decompress_safe((char *)zv + sizeof(*zv), - size, to_va, &clen); - kunmap_atomic(to_va, KM_USER0); - BUG_ON(ret != LZO_E_OK); - BUG_ON(clen != PAGE_SIZE); -} - -static void zv_copy_from_pampd(char *data, size_t *bufsize, struct zv_hdr *zv) -{ - unsigned size; - - ASSERT_SENTINEL(zv, ZVH); - size = xv_get_object_size(zv) - sizeof(*zv); - BUG_ON(size == 0 || size > zv_max_page_size); - BUG_ON(size > *bufsize); - memcpy(data, (char *)zv + sizeof(*zv), size); - *bufsize = size; -} - -static void zv_copy_to_pampd(struct zv_hdr *zv, char *data, size_t size) -{ - unsigned zv_size; - - ASSERT_SENTINEL(zv, ZVH); - zv_size = xv_get_object_size(zv) - sizeof(*zv); - BUG_ON(zv_size != size); - BUG_ON(zv_size == 0 || zv_size > zv_max_page_size); - memcpy((char *)zv + sizeof(*zv), data, size); -} - -#ifdef CONFIG_SYSFS -/* - * show a distribution of compression stats for zv pages. - */ - -static int zv_curr_dist_counts_show(char *buf) -{ - unsigned long i, n, chunks = 0, sum_total_chunks = 0; - char *p = buf; - - for (i = 0; i < NCHUNKS; i++) { - n = atomic_read(&zv_curr_dist_counts[i]); - p += sprintf(p, "%lu ", n); - chunks += n; - sum_total_chunks += i * n; - } - p += sprintf(p, "mean:%lu\n", - chunks == 0 ? 0 : sum_total_chunks / chunks); - return p - buf; -} - -static int zv_cumul_dist_counts_show(char *buf) -{ - unsigned long i, n, chunks = 0, sum_total_chunks = 0; - char *p = buf; - - for (i = 0; i < NCHUNKS; i++) { - n = atomic_read(&zv_cumul_dist_counts[i]); - p += sprintf(p, "%lu ", n); - chunks += n; - sum_total_chunks += i * n; - } - p += sprintf(p, "mean:%lu\n", - chunks == 0 ? 0 : sum_total_chunks / chunks); - return p - buf; -} - -/* - * setting zv_max_zsize via sysfs causes all persistent (e.g. swap) - * pages that don't compress to less than this value (including metadata - * overhead) to be rejected. We don't allow the value to get too close - * to PAGE_SIZE. - */ -static ssize_t zv_max_zsize_show(struct kobject *kobj, - struct kobj_attribute *attr, - char *buf) -{ - return sprintf(buf, "%u\n", zv_max_zsize); -} - -static ssize_t zv_max_zsize_store(struct kobject *kobj, - struct kobj_attribute *attr, - const char *buf, size_t count) -{ - unsigned long val; - int err; - - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - - err = strict_strtoul(buf, 10, &val); - if (err || (val == 0) || (val > (PAGE_SIZE / 8) * 7)) - return -EINVAL; - zv_max_zsize = val; - return count; -} - -/* - * setting zv_max_mean_zsize via sysfs causes all persistent (e.g. swap) - * pages that don't compress to less than this value (including metadata - * overhead) to be rejected UNLESS the mean compression is also smaller - * than this value. In other words, we are load-balancing-by-zsize the - * accepted pages. Again, we don't allow the value to get too close - * to PAGE_SIZE. - */ -static ssize_t zv_max_mean_zsize_show(struct kobject *kobj, - struct kobj_attribute *attr, - char *buf) -{ - return sprintf(buf, "%u\n", zv_max_mean_zsize); -} - -static ssize_t zv_max_mean_zsize_store(struct kobject *kobj, - struct kobj_attribute *attr, - const char *buf, size_t count) -{ - unsigned long val; - int err; - - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - - err = strict_strtoul(buf, 10, &val); - if (err || (val == 0) || (val > (PAGE_SIZE / 8) * 7)) - return -EINVAL; - zv_max_mean_zsize = val; - return count; -} - -/* - * setting zv_page_count_policy_percent via sysfs sets an upper bound of - * persistent (e.g. swap) pages that will be retained according to: - * (zv_page_count_policy_percent * totalram_pages) / 100) - * when that limit is reached, further puts will be rejected (until - * some pages have been flushed). Note that, due to compression, - * this number may exceed 100; it defaults to 75 and we set an - * arbitary limit of 150. A poor choice will almost certainly result - * in OOM's, so this value should only be changed prudently. - */ -static ssize_t zv_page_count_policy_percent_show(struct kobject *kobj, - struct kobj_attribute *attr, - char *buf) -{ - return sprintf(buf, "%u\n", zv_page_count_policy_percent); -} - -static ssize_t zv_page_count_policy_percent_store(struct kobject *kobj, - struct kobj_attribute *attr, - const char *buf, size_t count) -{ - unsigned long val; - int err; - - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - - err = strict_strtoul(buf, 10, &val); - if (err || (val == 0) || (val > 150)) - return -EINVAL; - zv_page_count_policy_percent = val; - return count; -} - -static struct kobj_attribute zcache_zv_max_zsize_attr = { - .attr = { .name = "zv_max_zsize", .mode = 0644 }, - .show = zv_max_zsize_show, - .store = zv_max_zsize_store, -}; - -static struct kobj_attribute zcache_zv_max_mean_zsize_attr = { - .attr = { .name = "zv_max_mean_zsize", .mode = 0644 }, - .show = zv_max_mean_zsize_show, - .store = zv_max_mean_zsize_store, -}; - -static struct kobj_attribute zcache_zv_page_count_policy_percent_attr = { - .attr = { .name = "zv_page_count_policy_percent", - .mode = 0644 }, - .show = zv_page_count_policy_percent_show, - .store = zv_page_count_policy_percent_store, -}; -#endif - -/* - * zcache core code starts here - */ - -/* useful stats not collected by cleancache or frontswap */ -static unsigned long zcache_flush_total; -static unsigned long zcache_flush_found; -static unsigned long zcache_flobj_total; -static unsigned long zcache_flobj_found; -static unsigned long zcache_failed_eph_puts; -static unsigned long zcache_nonactive_puts; -static unsigned long zcache_failed_pers_puts; - -/* - * Tmem operations assume the poolid implies the invoking client. - * Zcache only has one client (the kernel itself): LOCAL_CLIENT. - * RAMster has each client numbered by cluster node, and a KVM version - * of zcache would have one client per guest and each client might - * have a poolid==N. - */ -static struct tmem_pool *zcache_get_pool_by_id(uint16_t cli_id, uint16_t poolid) -{ - struct tmem_pool *pool = NULL; - struct zcache_client *cli = NULL; - - if (cli_id == LOCAL_CLIENT) - cli = &zcache_host; - else { - if (cli_id >= MAX_CLIENTS) - goto out; - cli = &zcache_clients[cli_id]; - if (cli == NULL) - goto out; - atomic_inc(&cli->refcount); - } - if (poolid < MAX_POOLS_PER_CLIENT) { - pool = cli->tmem_pools[poolid]; - if (pool != NULL) - atomic_inc(&pool->refcount); - } -out: - return pool; -} - -static void zcache_put_pool(struct tmem_pool *pool) -{ - struct zcache_client *cli = NULL; - - if (pool == NULL) - BUG(); - cli = pool->client; - atomic_dec(&pool->refcount); - atomic_dec(&cli->refcount); -} - -int zcache_new_client(uint16_t cli_id) -{ - struct zcache_client *cli = NULL; - int ret = -1; - - if (cli_id == LOCAL_CLIENT) - cli = &zcache_host; - else if ((unsigned int)cli_id < MAX_CLIENTS) - cli = &zcache_clients[cli_id]; - if (cli == NULL) - goto out; - if (cli->allocated) - goto out; - cli->allocated = 1; -#ifdef CONFIG_FRONTSWAP - cli->xvpool = xv_create_pool(); - if (cli->xvpool == NULL) - goto out; -#endif - ret = 0; -out: - return ret; -} - -/* counters for debugging */ -static unsigned long zcache_failed_get_free_pages; -static unsigned long zcache_failed_alloc; -static unsigned long zcache_put_to_flush; - -/* - * for now, used named slabs so can easily track usage; later can - * either just use kmalloc, or perhaps add a slab-like allocator - * to more carefully manage total memory utilization - */ -static struct kmem_cache *zcache_objnode_cache; -static struct kmem_cache *zcache_obj_cache; -static struct kmem_cache *ramster_flnode_cache; -static atomic_t zcache_curr_obj_count = ATOMIC_INIT(0); -static unsigned long zcache_curr_obj_count_max; -static atomic_t zcache_curr_objnode_count = ATOMIC_INIT(0); -static unsigned long zcache_curr_objnode_count_max; - -/* - * to avoid memory allocation recursion (e.g. due to direct reclaim), we - * preload all necessary data structures so the hostops callbacks never - * actually do a malloc - */ -struct zcache_preload { - void *page; - struct tmem_obj *obj; - int nr; - struct tmem_objnode *objnodes[OBJNODE_TREE_MAX_PATH]; - struct flushlist_node *flnode; -}; -static DEFINE_PER_CPU(struct zcache_preload, zcache_preloads) = { 0, }; - -static int zcache_do_preload(struct tmem_pool *pool) -{ - struct zcache_preload *kp; - struct tmem_objnode *objnode; - struct tmem_obj *obj; - struct flushlist_node *flnode; - void *page; - int ret = -ENOMEM; - - if (unlikely(zcache_objnode_cache == NULL)) - goto out; - if (unlikely(zcache_obj_cache == NULL)) - goto out; - preempt_disable(); - kp = &__get_cpu_var(zcache_preloads); - while (kp->nr < ARRAY_SIZE(kp->objnodes)) { - preempt_enable_no_resched(); - objnode = kmem_cache_alloc(zcache_objnode_cache, - ZCACHE_GFP_MASK); - if (unlikely(objnode == NULL)) { - zcache_failed_alloc++; - goto out; - } - preempt_disable(); - kp = &__get_cpu_var(zcache_preloads); - if (kp->nr < ARRAY_SIZE(kp->objnodes)) - kp->objnodes[kp->nr++] = objnode; - else - kmem_cache_free(zcache_objnode_cache, objnode); - } - preempt_enable_no_resched(); - obj = kmem_cache_alloc(zcache_obj_cache, ZCACHE_GFP_MASK); - if (unlikely(obj == NULL)) { - zcache_failed_alloc++; - goto out; - } - flnode = kmem_cache_alloc(ramster_flnode_cache, ZCACHE_GFP_MASK); - if (unlikely(flnode == NULL)) { - zcache_failed_alloc++; - goto out; - } - if (is_ephemeral(pool)) { - page = (void *)__get_free_page(ZCACHE_GFP_MASK); - if (unlikely(page == NULL)) { - zcache_failed_get_free_pages++; - kmem_cache_free(zcache_obj_cache, obj); - kmem_cache_free(ramster_flnode_cache, flnode); - goto out; - } - } - preempt_disable(); - kp = &__get_cpu_var(zcache_preloads); - if (kp->obj == NULL) - kp->obj = obj; - else - kmem_cache_free(zcache_obj_cache, obj); - if (kp->flnode == NULL) - kp->flnode = flnode; - else - kmem_cache_free(ramster_flnode_cache, flnode); - if (is_ephemeral(pool)) { - if (kp->page == NULL) - kp->page = page; - else - free_page((unsigned long)page); - } - ret = 0; -out: - return ret; -} - -static int ramster_do_preload_flnode_only(struct tmem_pool *pool) -{ - struct zcache_preload *kp; - struct flushlist_node *flnode; - int ret = -ENOMEM; - - BUG_ON(!irqs_disabled()); - if (unlikely(ramster_flnode_cache == NULL)) - BUG(); - kp = &__get_cpu_var(zcache_preloads); - flnode = kmem_cache_alloc(ramster_flnode_cache, GFP_ATOMIC); - if (unlikely(flnode == NULL) && kp->flnode == NULL) - BUG(); /* FIXME handle more gracefully, but how??? */ - else if (kp->flnode == NULL) - kp->flnode = flnode; - else - kmem_cache_free(ramster_flnode_cache, flnode); - return ret; -} - -static void *zcache_get_free_page(void) -{ - struct zcache_preload *kp; - void *page; - - kp = &__get_cpu_var(zcache_preloads); - page = kp->page; - BUG_ON(page == NULL); - kp->page = NULL; - return page; -} - -static void zcache_free_page(void *p) -{ - free_page((unsigned long)p); -} - -/* - * zcache implementation for tmem host ops - */ - -static struct tmem_objnode *zcache_objnode_alloc(struct tmem_pool *pool) -{ - struct tmem_objnode *objnode = NULL; - unsigned long count; - struct zcache_preload *kp; - - kp = &__get_cpu_var(zcache_preloads); - if (kp->nr <= 0) - goto out; - objnode = kp->objnodes[kp->nr - 1]; - BUG_ON(objnode == NULL); - kp->objnodes[kp->nr - 1] = NULL; - kp->nr--; - count = atomic_inc_return(&zcache_curr_objnode_count); - if (count > zcache_curr_objnode_count_max) - zcache_curr_objnode_count_max = count; -out: - return objnode; -} - -static void zcache_objnode_free(struct tmem_objnode *objnode, - struct tmem_pool *pool) -{ - atomic_dec(&zcache_curr_objnode_count); - BUG_ON(atomic_read(&zcache_curr_objnode_count) < 0); - kmem_cache_free(zcache_objnode_cache, objnode); -} - -static struct tmem_obj *zcache_obj_alloc(struct tmem_pool *pool) -{ - struct tmem_obj *obj = NULL; - unsigned long count; - struct zcache_preload *kp; - - kp = &__get_cpu_var(zcache_preloads); - obj = kp->obj; - BUG_ON(obj == NULL); - kp->obj = NULL; - count = atomic_inc_return(&zcache_curr_obj_count); - if (count > zcache_curr_obj_count_max) - zcache_curr_obj_count_max = count; - return obj; -} - -static void zcache_obj_free(struct tmem_obj *obj, struct tmem_pool *pool) -{ - atomic_dec(&zcache_curr_obj_count); - BUG_ON(atomic_read(&zcache_curr_obj_count) < 0); - kmem_cache_free(zcache_obj_cache, obj); -} - -static struct flushlist_node *ramster_flnode_alloc(struct tmem_pool *pool) -{ - struct flushlist_node *flnode = NULL; - struct zcache_preload *kp; - int count; - - kp = &__get_cpu_var(zcache_preloads); - flnode = kp->flnode; - BUG_ON(flnode == NULL); - kp->flnode = NULL; - count = atomic_inc_return(&ramster_curr_flnode_count); - if (count > ramster_curr_flnode_count_max) - ramster_curr_flnode_count_max = count; - return flnode; -} - -static void ramster_flnode_free(struct flushlist_node *flnode, - struct tmem_pool *pool) -{ - atomic_dec(&ramster_curr_flnode_count); - BUG_ON(atomic_read(&ramster_curr_flnode_count) < 0); - kmem_cache_free(ramster_flnode_cache, flnode); -} - -static struct tmem_hostops zcache_hostops = { - .obj_alloc = zcache_obj_alloc, - .obj_free = zcache_obj_free, - .objnode_alloc = zcache_objnode_alloc, - .objnode_free = zcache_objnode_free, -}; - -/* - * zcache implementations for PAM page descriptor ops - */ - -static atomic_t zcache_curr_eph_pampd_count = ATOMIC_INIT(0); -static unsigned long zcache_curr_eph_pampd_count_max; -static atomic_t zcache_curr_pers_pampd_count = ATOMIC_INIT(0); -static unsigned long zcache_curr_pers_pampd_count_max; - -/* forward reference */ -static int zcache_compress(struct page *from, void **out_va, size_t *out_len); - -static int zcache_pampd_eph_create(char *data, size_t size, bool raw, - struct tmem_pool *pool, struct tmem_oid *oid, - uint32_t index, void **pampd) -{ - int ret = -1; - void *cdata = data; - size_t clen = size; - struct zcache_client *cli = pool->client; - uint16_t client_id = get_client_id_from_client(cli); - struct page *page = NULL; - unsigned long count; - - if (!raw) { - page = virt_to_page(data); - ret = zcache_compress(page, &cdata, &clen); - if (ret == 0) - goto out; - if (clen == 0 || clen > zbud_max_buddy_size()) { - zcache_compress_poor++; - goto out; - } - } - *pampd = (void *)zbud_create(client_id, pool->pool_id, oid, - index, page, cdata, clen); - if (*pampd == NULL) { - ret = -ENOMEM; - goto out; - } - ret = 0; - count = atomic_inc_return(&zcache_curr_eph_pampd_count); - if (count > zcache_curr_eph_pampd_count_max) - zcache_curr_eph_pampd_count_max = count; - if (client_id != LOCAL_CLIENT) { - count = atomic_inc_return(&ramster_foreign_eph_pampd_count); - if (count > ramster_foreign_eph_pampd_count_max) - ramster_foreign_eph_pampd_count_max = count; - } -out: - return ret; -} - -static int zcache_pampd_pers_create(char *data, size_t size, bool raw, - struct tmem_pool *pool, struct tmem_oid *oid, - uint32_t index, void **pampd) -{ - int ret = -1; - void *cdata = data; - size_t clen = size; - struct zcache_client *cli = pool->client; - struct page *page; - unsigned long count; - unsigned long zv_mean_zsize; - struct zv_hdr *zv; - long curr_pers_pampd_count; - u64 total_zsize; -#ifdef RAMSTER_TESTING - static bool pampd_neg_warned; -#endif - - curr_pers_pampd_count = atomic_read(&zcache_curr_pers_pampd_count) - - atomic_read(&ramster_remote_pers_pages); -#ifdef RAMSTER_TESTING - /* should always be positive, but warn if accounting is off */ - if (!pampd_neg_warned) { - pr_warn("ramster: bad accounting for curr_pers_pampd_count\n"); - pampd_neg_warned = true; - } -#endif - if (curr_pers_pampd_count > - (zv_page_count_policy_percent * totalram_pages) / 100) { - zcache_policy_percent_exceeded++; - goto out; - } - if (raw) - goto ok_to_create; - page = virt_to_page(data); - if (zcache_compress(page, &cdata, &clen) == 0) - goto out; - /* reject if compression is too poor */ - if (clen > zv_max_zsize) { - zcache_compress_poor++; - goto out; - } - /* reject if mean compression is too poor */ - if ((clen > zv_max_mean_zsize) && (curr_pers_pampd_count > 0)) { - total_zsize = xv_get_total_size_bytes(cli->xvpool); - zv_mean_zsize = div_u64(total_zsize, curr_pers_pampd_count); - if (zv_mean_zsize > zv_max_mean_zsize) { - zcache_mean_compress_poor++; - goto out; - } - } -ok_to_create: - *pampd = (void *)zv_create(cli, pool->pool_id, oid, index, cdata, clen); - if (*pampd == NULL) { - ret = -ENOMEM; - goto out; - } - ret = 0; - count = atomic_inc_return(&zcache_curr_pers_pampd_count); - if (count > zcache_curr_pers_pampd_count_max) - zcache_curr_pers_pampd_count_max = count; - if (is_local_client(cli)) - goto out; - zv = *(struct zv_hdr **)pampd; - count = atomic_inc_return(&ramster_foreign_pers_pampd_count); - if (count > ramster_foreign_pers_pampd_count_max) - ramster_foreign_pers_pampd_count_max = count; -out: - return ret; -} - -static void *zcache_pampd_create(char *data, size_t size, bool raw, int eph, - struct tmem_pool *pool, struct tmem_oid *oid, - uint32_t index) -{ - void *pampd = NULL; - int ret; - bool ephemeral; - - BUG_ON(preemptible()); - ephemeral = (eph == 1) || ((eph == 0) && is_ephemeral(pool)); - if (ephemeral) - ret = zcache_pampd_eph_create(data, size, raw, pool, - oid, index, &pampd); - else - ret = zcache_pampd_pers_create(data, size, raw, pool, - oid, index, &pampd); - /* FIXME add some counters here for failed creates? */ - return pampd; -} - -/* - * fill the pageframe corresponding to the struct page with the data - * from the passed pampd - */ -static int zcache_pampd_get_data(char *data, size_t *bufsize, bool raw, - void *pampd, struct tmem_pool *pool, - struct tmem_oid *oid, uint32_t index) -{ - int ret = 0; - - BUG_ON(preemptible()); - BUG_ON(is_ephemeral(pool)); /* Fix later for shared pools? */ - BUG_ON(pampd_is_remote(pampd)); - if (raw) - zv_copy_from_pampd(data, bufsize, pampd); - else - zv_decompress(virt_to_page(data), pampd); - return ret; -} - -static int zcache_pampd_get_data_and_free(char *data, size_t *bufsize, bool raw, - void *pampd, struct tmem_pool *pool, - struct tmem_oid *oid, uint32_t index) -{ - int ret = 0; - unsigned long flags; - struct zcache_client *cli = pool->client; - - BUG_ON(preemptible()); - BUG_ON(pampd_is_remote(pampd)); - if (is_ephemeral(pool)) { - local_irq_save(flags); - if (raw) - zbud_copy_from_pampd(data, bufsize, pampd); - else - ret = zbud_decompress(virt_to_page(data), pampd); - zbud_free_and_delist((struct zbud_hdr *)pampd); - local_irq_restore(flags); - if (!is_local_client(cli)) { - atomic_dec(&ramster_foreign_eph_pampd_count); - WARN_ON_ONCE(atomic_read(&ramster_foreign_eph_pampd_count) < 0); - } - atomic_dec(&zcache_curr_eph_pampd_count); - WARN_ON_ONCE(atomic_read(&zcache_curr_eph_pampd_count) < 0); - } else { - if (is_local_client(cli)) - BUG(); - if (raw) - zv_copy_from_pampd(data, bufsize, pampd); - else - zv_decompress(virt_to_page(data), pampd); - zv_free(cli->xvpool, pampd); - if (!is_local_client(cli)) { - atomic_dec(&ramster_foreign_pers_pampd_count); - WARN_ON_ONCE(atomic_read(&ramster_foreign_pers_pampd_count) < 0); - } - atomic_dec(&zcache_curr_pers_pampd_count); - WARN_ON_ONCE(atomic_read(&zcache_curr_pers_pampd_count) < 0); - ret = 0; - } - return ret; -} - -static bool zcache_pampd_is_remote(void *pampd) -{ - return pampd_is_remote(pampd); -} - -/* - * free the pampd and remove it from any zcache lists - * pampd must no longer be pointed to from any tmem data structures! - */ -static void zcache_pampd_free(void *pampd, struct tmem_pool *pool, - struct tmem_oid *oid, uint32_t index, bool acct) -{ - struct zcache_client *cli = pool->client; - bool eph = is_ephemeral(pool); - struct zv_hdr *zv; - - BUG_ON(preemptible()); - if (pampd_is_remote(pampd)) { - WARN_ON(acct == false); - if (oid == NULL) { - /* - * a NULL oid means to ignore this pampd free - * as the remote freeing will be handled elsewhere - */ - } else if (eph) { - /* FIXME remote flush optional but probably good idea */ - /* FIXME get these working properly again */ - atomic_dec(&zcache_curr_eph_pampd_count); - WARN_ON_ONCE(atomic_read(&zcache_curr_eph_pampd_count) < 0); - } else if (pampd_is_intransit(pampd)) { - /* did a pers remote get_and_free, so just free local */ - pampd = pampd_mask_intransit_and_remote(pampd); - goto local_pers; - } else { - struct flushlist_node *flnode = - ramster_flnode_alloc(pool); - - flnode->xh.client_id = pampd_remote_node(pampd); - flnode->xh.pool_id = pool->pool_id; - flnode->xh.oid = *oid; - flnode->xh.index = index; - flnode->rem_op.op = RAMSTER_REMOTIFY_FLUSH_PAGE; - spin_lock(&zcache_rem_op_list_lock); - list_add(&flnode->rem_op.list, &zcache_rem_op_list); - spin_unlock(&zcache_rem_op_list_lock); - atomic_dec(&zcache_curr_pers_pampd_count); - WARN_ON_ONCE(atomic_read(&zcache_curr_pers_pampd_count) < 0); - atomic_dec(&ramster_remote_pers_pages); - WARN_ON_ONCE(atomic_read(&ramster_remote_pers_pages) < 0); - } - } else if (eph) { - zbud_free_and_delist((struct zbud_hdr *)pampd); - if (!is_local_client(pool->client)) { - atomic_dec(&ramster_foreign_eph_pampd_count); - WARN_ON_ONCE(atomic_read(&ramster_foreign_eph_pampd_count) < 0); - } - if (acct) - atomic_dec(&zcache_curr_eph_pampd_count); - /* FIXME get these working properly again */ - WARN_ON_ONCE(atomic_read(&zcache_curr_eph_pampd_count) < 0); - } else { -local_pers: - zv = (struct zv_hdr *)pampd; - if (!is_local_client(pool->client)) { - atomic_dec(&ramster_foreign_pers_pampd_count); - WARN_ON_ONCE(atomic_read(&ramster_foreign_pers_pampd_count) < 0); - } - zv_free(cli->xvpool, zv); - if (acct) - atomic_dec(&zcache_curr_pers_pampd_count); - /* FIXME get these working properly again */ - WARN_ON_ONCE(atomic_read(&zcache_curr_pers_pampd_count) < 0); - } -} - -static void zcache_pampd_free_obj(struct tmem_pool *pool, - struct tmem_obj *obj) -{ - struct flushlist_node *flnode; - - BUG_ON(preemptible()); - if (obj->extra == NULL) - return; - BUG_ON(!pampd_is_remote(obj->extra)); - flnode = ramster_flnode_alloc(pool); - flnode->xh.client_id = pampd_remote_node(obj->extra); - flnode->xh.pool_id = pool->pool_id; - flnode->xh.oid = obj->oid; - flnode->xh.index = FLUSH_ENTIRE_OBJECT; - flnode->rem_op.op = RAMSTER_REMOTIFY_FLUSH_OBJ; - spin_lock(&zcache_rem_op_list_lock); - list_add(&flnode->rem_op.list, &zcache_rem_op_list); - spin_unlock(&zcache_rem_op_list_lock); -} - -void zcache_pampd_new_obj(struct tmem_obj *obj) -{ - obj->extra = NULL; -} - -int zcache_pampd_replace_in_obj(void *new_pampd, struct tmem_obj *obj) -{ - int ret = -1; - - if (new_pampd != NULL) { - if (obj->extra == NULL) - obj->extra = new_pampd; - /* enforce that all remote pages in an object reside - * in the same node! */ - else if (pampd_remote_node(new_pampd) != - pampd_remote_node((void *)(obj->extra))) - BUG(); - ret = 0; - } - return ret; -} - -/* - * Called by the message handler after a (still compressed) page has been - * fetched from the remote machine in response to an "is_remote" tmem_get - * or persistent tmem_localify. For a tmem_get, "extra" is the address of - * the page that is to be filled to succesfully resolve the tmem_get; for - * a (persistent) tmem_localify, "extra" is NULL (as the data is placed only - * in the local zcache). "data" points to "size" bytes of (compressed) data - * passed in the message. In the case of a persistent remote get, if - * pre-allocation was successful (see zcache_repatriate_preload), the page - * is placed into both local zcache and at "extra". - */ -int zcache_localify(int pool_id, struct tmem_oid *oidp, - uint32_t index, char *data, size_t size, - void *extra) -{ - int ret = -ENOENT; - unsigned long flags; - struct tmem_pool *pool; - bool ephemeral, delete = false; - size_t clen = PAGE_SIZE; - void *pampd, *saved_hb; - struct tmem_obj *obj; - - pool = zcache_get_pool_by_id(LOCAL_CLIENT, pool_id); - if (unlikely(pool == NULL)) - /* pool doesn't exist anymore */ - goto out; - ephemeral = is_ephemeral(pool); - local_irq_save(flags); /* FIXME: maybe only disable softirqs? */ - pampd = tmem_localify_get_pampd(pool, oidp, index, &obj, &saved_hb); - if (pampd == NULL) { - /* hmmm... must have been a flush while waiting */ -#ifdef RAMSTER_TESTING - pr_err("UNTESTED pampd==NULL in zcache_localify\n"); -#endif - if (ephemeral) - ramster_remote_eph_pages_unsucc_get++; - else - ramster_remote_pers_pages_unsucc_get++; - obj = NULL; - goto finish; - } else if (unlikely(!pampd_is_remote(pampd))) { - /* hmmm... must have been a dup put while waiting */ -#ifdef RAMSTER_TESTING - pr_err("UNTESTED dup while waiting in zcache_localify\n"); -#endif - if (ephemeral) - ramster_remote_eph_pages_unsucc_get++; - else - ramster_remote_pers_pages_unsucc_get++; - obj = NULL; - pampd = NULL; - ret = -EEXIST; - goto finish; - } else if (size == 0) { - /* no remote data, delete the local is_remote pampd */ - pampd = NULL; - if (ephemeral) - ramster_remote_eph_pages_unsucc_get++; - else - BUG(); - delete = true; - goto finish; - } - if (!ephemeral && pampd_is_intransit(pampd)) { - /* localify to zcache */ - pampd = pampd_mask_intransit_and_remote(pampd); - zv_copy_to_pampd(pampd, data, size); - } else { - pampd = NULL; - obj = NULL; - } - if (extra != NULL) { - /* decompress direct-to-memory to complete remotify */ - ret = lzo1x_decompress_safe((char *)data, size, - (char *)extra, &clen); - BUG_ON(ret != LZO_E_OK); - BUG_ON(clen != PAGE_SIZE); - } - if (ephemeral) - ramster_remote_eph_pages_succ_get++; - else - ramster_remote_pers_pages_succ_get++; - ret = 0; -finish: - tmem_localify_finish(obj, index, pampd, saved_hb, delete); - zcache_put_pool(pool); - local_irq_restore(flags); -out: - return ret; -} - -/* - * Called on a remote persistent tmem_get to attempt to preallocate - * local storage for the data contained in the remote persistent page. - * If succesfully preallocated, returns the pampd, marked as remote and - * in_transit. Else returns NULL. Note that the appropriate tmem data - * structure must be locked. - */ -static void *zcache_pampd_repatriate_preload(void *pampd, - struct tmem_pool *pool, - struct tmem_oid *oid, - uint32_t index, - bool *intransit) -{ - int clen = pampd_remote_size(pampd); - void *ret_pampd = NULL; - unsigned long flags; - - if (!pampd_is_remote(pampd)) - BUG(); - if (is_ephemeral(pool)) - BUG(); - if (pampd_is_intransit(pampd)) { - /* - * to avoid multiple allocations (and maybe a memory leak) - * don't preallocate if already in the process of being - * repatriated - */ - *intransit = true; - goto out; - } - *intransit = false; - local_irq_save(flags); - ret_pampd = (void *)zv_alloc(pool, oid, index, clen); - if (ret_pampd != NULL) { - /* - * a pampd is marked intransit if it is remote and space has - * been allocated for it locally (note, only happens for - * persistent pages, in which case the remote copy is freed) - */ - ret_pampd = pampd_mark_intransit(ret_pampd); - atomic_dec(&ramster_remote_pers_pages); - WARN_ON_ONCE(atomic_read(&ramster_remote_pers_pages) < 0); - } else - ramster_pers_pages_remote_nomem++; - local_irq_restore(flags); -out: - return ret_pampd; -} - -/* - * Called on a remote tmem_get to invoke a message to fetch the page. - * Might sleep so no tmem locks can be held. "extra" is passed - * all the way through the round-trip messaging to zcache_localify. - */ -static int zcache_pampd_repatriate(void *fake_pampd, void *real_pampd, - struct tmem_pool *pool, - struct tmem_oid *oid, uint32_t index, - bool free, void *extra) -{ - struct tmem_xhandle xh; - int ret; - - if (pampd_is_intransit(real_pampd)) - /* have local space pre-reserved, so free remote copy */ - free = true; - xh = tmem_xhandle_fill(LOCAL_CLIENT, pool, oid, index); - /* unreliable request/response for now */ - ret = ramster_remote_async_get(&xh, free, - pampd_remote_node(fake_pampd), - pampd_remote_size(fake_pampd), - pampd_remote_cksum(fake_pampd), - extra); -#ifdef RAMSTER_TESTING - if (ret != 0 && ret != -ENOENT) - pr_err("TESTING zcache_pampd_repatriate returns, ret=%d\n", - ret); -#endif - return ret; -} - -static struct tmem_pamops zcache_pamops = { - .create = zcache_pampd_create, - .get_data = zcache_pampd_get_data, - .free = zcache_pampd_free, - .get_data_and_free = zcache_pampd_get_data_and_free, - .free_obj = zcache_pampd_free_obj, - .is_remote = zcache_pampd_is_remote, - .repatriate_preload = zcache_pampd_repatriate_preload, - .repatriate = zcache_pampd_repatriate, - .new_obj = zcache_pampd_new_obj, - .replace_in_obj = zcache_pampd_replace_in_obj, -}; - -/* - * zcache compression/decompression and related per-cpu stuff - */ - -#define LZO_WORKMEM_BYTES LZO1X_1_MEM_COMPRESS -#define LZO_DSTMEM_PAGE_ORDER 1 -static DEFINE_PER_CPU(unsigned char *, zcache_workmem); -static DEFINE_PER_CPU(unsigned char *, zcache_dstmem); - -static int zcache_compress(struct page *from, void **out_va, size_t *out_len) -{ - int ret = 0; - unsigned char *dmem = __get_cpu_var(zcache_dstmem); - unsigned char *wmem = __get_cpu_var(zcache_workmem); - char *from_va; - - BUG_ON(!irqs_disabled()); - if (unlikely(dmem == NULL || wmem == NULL)) - goto out; /* no buffer, so can't compress */ - from_va = kmap_atomic(from, KM_USER0); - mb(); - ret = lzo1x_1_compress(from_va, PAGE_SIZE, dmem, out_len, wmem); - BUG_ON(ret != LZO_E_OK); - *out_va = dmem; - kunmap_atomic(from_va, KM_USER0); - ret = 1; -out: - return ret; -} - - -static int zcache_cpu_notifier(struct notifier_block *nb, - unsigned long action, void *pcpu) -{ - int cpu = (long)pcpu; - struct zcache_preload *kp; - - switch (action) { - case CPU_UP_PREPARE: - per_cpu(zcache_dstmem, cpu) = (void *)__get_free_pages( - GFP_KERNEL | __GFP_REPEAT, - LZO_DSTMEM_PAGE_ORDER), - per_cpu(zcache_workmem, cpu) = - kzalloc(LZO1X_MEM_COMPRESS, - GFP_KERNEL | __GFP_REPEAT); - per_cpu(zcache_remoteputmem, cpu) = - kzalloc(PAGE_SIZE, GFP_KERNEL | __GFP_REPEAT); - break; - case CPU_DEAD: - case CPU_UP_CANCELED: - kfree(per_cpu(zcache_remoteputmem, cpu)); - per_cpu(zcache_remoteputmem, cpu) = NULL; - free_pages((unsigned long)per_cpu(zcache_dstmem, cpu), - LZO_DSTMEM_PAGE_ORDER); - per_cpu(zcache_dstmem, cpu) = NULL; - kfree(per_cpu(zcache_workmem, cpu)); - per_cpu(zcache_workmem, cpu) = NULL; - kp = &per_cpu(zcache_preloads, cpu); - while (kp->nr) { - kmem_cache_free(zcache_objnode_cache, - kp->objnodes[kp->nr - 1]); - kp->objnodes[kp->nr - 1] = NULL; - kp->nr--; - } - if (kp->obj) { - kmem_cache_free(zcache_obj_cache, kp->obj); - kp->obj = NULL; - } - if (kp->flnode) { - kmem_cache_free(ramster_flnode_cache, kp->flnode); - kp->flnode = NULL; - } - if (kp->page) { - free_page((unsigned long)kp->page); - kp->page = NULL; - } - break; - default: - break; - } - return NOTIFY_OK; -} - -static struct notifier_block zcache_cpu_notifier_block = { - .notifier_call = zcache_cpu_notifier -}; - -#ifdef CONFIG_SYSFS -#define ZCACHE_SYSFS_RO(_name) \ - static ssize_t zcache_##_name##_show(struct kobject *kobj, \ - struct kobj_attribute *attr, char *buf) \ - { \ - return sprintf(buf, "%lu\n", zcache_##_name); \ - } \ - static struct kobj_attribute zcache_##_name##_attr = { \ - .attr = { .name = __stringify(_name), .mode = 0444 }, \ - .show = zcache_##_name##_show, \ - } - -#define ZCACHE_SYSFS_RO_ATOMIC(_name) \ - static ssize_t zcache_##_name##_show(struct kobject *kobj, \ - struct kobj_attribute *attr, char *buf) \ - { \ - return sprintf(buf, "%d\n", atomic_read(&zcache_##_name)); \ - } \ - static struct kobj_attribute zcache_##_name##_attr = { \ - .attr = { .name = __stringify(_name), .mode = 0444 }, \ - .show = zcache_##_name##_show, \ - } - -#define ZCACHE_SYSFS_RO_CUSTOM(_name, _func) \ - static ssize_t zcache_##_name##_show(struct kobject *kobj, \ - struct kobj_attribute *attr, char *buf) \ - { \ - return _func(buf); \ - } \ - static struct kobj_attribute zcache_##_name##_attr = { \ - .attr = { .name = __stringify(_name), .mode = 0444 }, \ - .show = zcache_##_name##_show, \ - } - -ZCACHE_SYSFS_RO(curr_obj_count_max); -ZCACHE_SYSFS_RO(curr_objnode_count_max); -ZCACHE_SYSFS_RO(flush_total); -ZCACHE_SYSFS_RO(flush_found); -ZCACHE_SYSFS_RO(flobj_total); -ZCACHE_SYSFS_RO(flobj_found); -ZCACHE_SYSFS_RO(failed_eph_puts); -ZCACHE_SYSFS_RO(nonactive_puts); -ZCACHE_SYSFS_RO(failed_pers_puts); -ZCACHE_SYSFS_RO(zbud_curr_zbytes); -ZCACHE_SYSFS_RO(zbud_cumul_zpages); -ZCACHE_SYSFS_RO(zbud_cumul_zbytes); -ZCACHE_SYSFS_RO(zbud_buddied_count); -ZCACHE_SYSFS_RO(evicted_raw_pages); -ZCACHE_SYSFS_RO(evicted_unbuddied_pages); -ZCACHE_SYSFS_RO(evicted_buddied_pages); -ZCACHE_SYSFS_RO(failed_get_free_pages); -ZCACHE_SYSFS_RO(failed_alloc); -ZCACHE_SYSFS_RO(put_to_flush); -ZCACHE_SYSFS_RO(compress_poor); -ZCACHE_SYSFS_RO(mean_compress_poor); -ZCACHE_SYSFS_RO(policy_percent_exceeded); -ZCACHE_SYSFS_RO_ATOMIC(zbud_curr_raw_pages); -ZCACHE_SYSFS_RO_ATOMIC(zbud_curr_zpages); -ZCACHE_SYSFS_RO_ATOMIC(curr_obj_count); -ZCACHE_SYSFS_RO_ATOMIC(curr_objnode_count); -ZCACHE_SYSFS_RO_CUSTOM(zbud_unbuddied_list_counts, - zbud_show_unbuddied_list_counts); -ZCACHE_SYSFS_RO_CUSTOM(zbud_cumul_chunk_counts, - zbud_show_cumul_chunk_counts); -ZCACHE_SYSFS_RO_CUSTOM(zv_curr_dist_counts, - zv_curr_dist_counts_show); -ZCACHE_SYSFS_RO_CUSTOM(zv_cumul_dist_counts, - zv_cumul_dist_counts_show); - -static struct attribute *zcache_attrs[] = { - &zcache_curr_obj_count_attr.attr, - &zcache_curr_obj_count_max_attr.attr, - &zcache_curr_objnode_count_attr.attr, - &zcache_curr_objnode_count_max_attr.attr, - &zcache_flush_total_attr.attr, - &zcache_flobj_total_attr.attr, - &zcache_flush_found_attr.attr, - &zcache_flobj_found_attr.attr, - &zcache_failed_eph_puts_attr.attr, - &zcache_nonactive_puts_attr.attr, - &zcache_failed_pers_puts_attr.attr, - &zcache_policy_percent_exceeded_attr.attr, - &zcache_compress_poor_attr.attr, - &zcache_mean_compress_poor_attr.attr, - &zcache_zbud_curr_raw_pages_attr.attr, - &zcache_zbud_curr_zpages_attr.attr, - &zcache_zbud_curr_zbytes_attr.attr, - &zcache_zbud_cumul_zpages_attr.attr, - &zcache_zbud_cumul_zbytes_attr.attr, - &zcache_zbud_buddied_count_attr.attr, - &zcache_evicted_raw_pages_attr.attr, - &zcache_evicted_unbuddied_pages_attr.attr, - &zcache_evicted_buddied_pages_attr.attr, - &zcache_failed_get_free_pages_attr.attr, - &zcache_failed_alloc_attr.attr, - &zcache_put_to_flush_attr.attr, - &zcache_zbud_unbuddied_list_counts_attr.attr, - &zcache_zbud_cumul_chunk_counts_attr.attr, - &zcache_zv_curr_dist_counts_attr.attr, - &zcache_zv_cumul_dist_counts_attr.attr, - &zcache_zv_max_zsize_attr.attr, - &zcache_zv_max_mean_zsize_attr.attr, - &zcache_zv_page_count_policy_percent_attr.attr, - NULL, -}; - -static struct attribute_group zcache_attr_group = { - .attrs = zcache_attrs, - .name = "zcache", -}; - -#define RAMSTER_SYSFS_RO(_name) \ - static ssize_t ramster_##_name##_show(struct kobject *kobj, \ - struct kobj_attribute *attr, char *buf) \ - { \ - return sprintf(buf, "%lu\n", ramster_##_name); \ - } \ - static struct kobj_attribute ramster_##_name##_attr = { \ - .attr = { .name = __stringify(_name), .mode = 0444 }, \ - .show = ramster_##_name##_show, \ - } - -#define RAMSTER_SYSFS_RW(_name) \ - static ssize_t ramster_##_name##_show(struct kobject *kobj, \ - struct kobj_attribute *attr, char *buf) \ - { \ - return sprintf(buf, "%lu\n", ramster_##_name); \ - } \ - static ssize_t ramster_##_name##_store(struct kobject *kobj, \ - struct kobj_attribute *attr, const char *buf, size_t count) \ - { \ - int err; \ - unsigned long enable; \ - err = strict_strtoul(buf, 10, &enable); \ - if (err) \ - return -EINVAL; \ - ramster_##_name = enable; \ - return count; \ - } \ - static struct kobj_attribute ramster_##_name##_attr = { \ - .attr = { .name = __stringify(_name), .mode = 0644 }, \ - .show = ramster_##_name##_show, \ - .store = ramster_##_name##_store, \ - } - -#define RAMSTER_SYSFS_RO_ATOMIC(_name) \ - static ssize_t ramster_##_name##_show(struct kobject *kobj, \ - struct kobj_attribute *attr, char *buf) \ - { \ - return sprintf(buf, "%d\n", atomic_read(&ramster_##_name)); \ - } \ - static struct kobj_attribute ramster_##_name##_attr = { \ - .attr = { .name = __stringify(_name), .mode = 0444 }, \ - .show = ramster_##_name##_show, \ - } - -RAMSTER_SYSFS_RO_ATOMIC(remote_pers_pages); -RAMSTER_SYSFS_RW(pers_remotify_enable); -RAMSTER_SYSFS_RW(eph_remotify_enable); -RAMSTER_SYSFS_RO(eph_pages_remoted); -RAMSTER_SYSFS_RO(eph_pages_remote_failed); -RAMSTER_SYSFS_RO(pers_pages_remoted); -RAMSTER_SYSFS_RO(pers_pages_remote_failed); -RAMSTER_SYSFS_RO(pers_pages_remote_nomem); -RAMSTER_SYSFS_RO(remote_pages_flushed); -RAMSTER_SYSFS_RO(remote_page_flushes_failed); -RAMSTER_SYSFS_RO(remote_objects_flushed); -RAMSTER_SYSFS_RO(remote_object_flushes_failed); -RAMSTER_SYSFS_RO(remote_eph_pages_succ_get); -RAMSTER_SYSFS_RO(remote_eph_pages_unsucc_get); -RAMSTER_SYSFS_RO(remote_pers_pages_succ_get); -RAMSTER_SYSFS_RO(remote_pers_pages_unsucc_get); -RAMSTER_SYSFS_RO_ATOMIC(foreign_eph_pampd_count); -RAMSTER_SYSFS_RO(foreign_eph_pampd_count_max); -RAMSTER_SYSFS_RO_ATOMIC(foreign_pers_pampd_count); -RAMSTER_SYSFS_RO(foreign_pers_pampd_count_max); -RAMSTER_SYSFS_RO_ATOMIC(curr_flnode_count); -RAMSTER_SYSFS_RO(curr_flnode_count_max); - -#define MANUAL_NODES 8 -static bool ramster_nodes_manual_up[MANUAL_NODES]; -static ssize_t ramster_manual_node_up_show(struct kobject *kobj, - struct kobj_attribute *attr, char *buf) -{ - int i; - char *p = buf; - for (i = 0; i < MANUAL_NODES; i++) - if (ramster_nodes_manual_up[i]) - p += sprintf(p, "%d ", i); - p += sprintf(p, "\n"); - return p - buf; -} - -static ssize_t ramster_manual_node_up_store(struct kobject *kobj, - struct kobj_attribute *attr, const char *buf, size_t count) -{ - int err; - unsigned long node_num; - - err = strict_strtoul(buf, 10, &node_num); - if (err) { - pr_err("bad strtoul?\n"); - return -EINVAL; - } - if (node_num >= MANUAL_NODES) { - pr_err("bad node_num=%lu?\n", node_num); - return -EINVAL; - } - if (ramster_nodes_manual_up[node_num]) { - pr_err("node %d already up, ignoring\n", (int)node_num); - } else { - ramster_nodes_manual_up[node_num] = true; - o2net_hb_node_up_manual((int)node_num); - } - return count; -} - -static struct kobj_attribute ramster_manual_node_up_attr = { - .attr = { .name = "manual_node_up", .mode = 0644 }, - .show = ramster_manual_node_up_show, - .store = ramster_manual_node_up_store, -}; - -static struct attribute *ramster_attrs[] = { - &ramster_pers_remotify_enable_attr.attr, - &ramster_eph_remotify_enable_attr.attr, - &ramster_remote_pers_pages_attr.attr, - &ramster_eph_pages_remoted_attr.attr, - &ramster_eph_pages_remote_failed_attr.attr, - &ramster_pers_pages_remoted_attr.attr, - &ramster_pers_pages_remote_failed_attr.attr, - &ramster_pers_pages_remote_nomem_attr.attr, - &ramster_remote_pages_flushed_attr.attr, - &ramster_remote_page_flushes_failed_attr.attr, - &ramster_remote_objects_flushed_attr.attr, - &ramster_remote_object_flushes_failed_attr.attr, - &ramster_remote_eph_pages_succ_get_attr.attr, - &ramster_remote_eph_pages_unsucc_get_attr.attr, - &ramster_remote_pers_pages_succ_get_attr.attr, - &ramster_remote_pers_pages_unsucc_get_attr.attr, - &ramster_foreign_eph_pampd_count_attr.attr, - &ramster_foreign_eph_pampd_count_max_attr.attr, - &ramster_foreign_pers_pampd_count_attr.attr, - &ramster_foreign_pers_pampd_count_max_attr.attr, - &ramster_curr_flnode_count_attr.attr, - &ramster_curr_flnode_count_max_attr.attr, - &ramster_manual_node_up_attr.attr, - NULL, -}; - -static struct attribute_group ramster_attr_group = { - .attrs = ramster_attrs, - .name = "ramster", -}; - -#endif /* CONFIG_SYSFS */ -/* - * When zcache is disabled ("frozen"), pools can be created and destroyed, - * but all puts (and thus all other operations that require memory allocation) - * must fail. If zcache is unfrozen, accepts puts, then frozen again, - * data consistency requires all puts while frozen to be converted into - * flushes. - */ -static bool zcache_freeze; - -/* - * zcache shrinker interface (only useful for ephemeral pages, so zbud only) - */ -static int shrink_zcache_memory(struct shrinker *shrink, - struct shrink_control *sc) -{ - int ret = -1; - int nr = sc->nr_to_scan; - gfp_t gfp_mask = sc->gfp_mask; - - if (nr >= 0) { - if (!(gfp_mask & __GFP_FS)) - /* does this case really need to be skipped? */ - goto out; - zbud_evict_pages(nr); - } - ret = (int)atomic_read(&zcache_zbud_curr_raw_pages); -out: - return ret; -} - -static struct shrinker zcache_shrinker = { - .shrink = shrink_zcache_memory, - .seeks = DEFAULT_SEEKS, -}; - -/* - * zcache shims between cleancache/frontswap ops and tmem - */ - -int zcache_put(int cli_id, int pool_id, struct tmem_oid *oidp, - uint32_t index, char *data, size_t size, - bool raw, int ephemeral) -{ - struct tmem_pool *pool; - int ret = -1; - - BUG_ON(!irqs_disabled()); - pool = zcache_get_pool_by_id(cli_id, pool_id); - if (unlikely(pool == NULL)) - goto out; - if (!zcache_freeze && zcache_do_preload(pool) == 0) { - /* preload does preempt_disable on success */ - ret = tmem_put(pool, oidp, index, data, size, raw, ephemeral); - if (ret < 0) { - if (is_ephemeral(pool)) - zcache_failed_eph_puts++; - else - zcache_failed_pers_puts++; - } - zcache_put_pool(pool); - preempt_enable_no_resched(); - } else { - zcache_put_to_flush++; - if (atomic_read(&pool->obj_count) > 0) - /* the put fails whether the flush succeeds or not */ - (void)tmem_flush_page(pool, oidp, index); - zcache_put_pool(pool); - } -out: - return ret; -} - -int zcache_get(int cli_id, int pool_id, struct tmem_oid *oidp, - uint32_t index, char *data, size_t *sizep, - bool raw, int get_and_free) -{ - struct tmem_pool *pool; - int ret = -1; - bool eph; - - if (!raw) { - BUG_ON(irqs_disabled()); - BUG_ON(in_softirq()); - } - pool = zcache_get_pool_by_id(cli_id, pool_id); - eph = is_ephemeral(pool); - if (likely(pool != NULL)) { - if (atomic_read(&pool->obj_count) > 0) - ret = tmem_get(pool, oidp, index, data, sizep, - raw, get_and_free); - zcache_put_pool(pool); - } - WARN_ONCE((!eph && (ret != 0)), "zcache_get fails on persistent pool, " - "bad things are very likely to happen soon\n"); -#ifdef RAMSTER_TESTING - if (ret != 0 && ret != -1 && !(ret == -EINVAL && is_ephemeral(pool))) - pr_err("TESTING zcache_get tmem_get returns ret=%d\n", ret); -#endif - if (ret == -EAGAIN) - BUG(); /* FIXME... don't need this anymore??? let's ensure */ - return ret; -} - -int zcache_flush(int cli_id, int pool_id, - struct tmem_oid *oidp, uint32_t index) -{ - struct tmem_pool *pool; - int ret = -1; - unsigned long flags; - - local_irq_save(flags); - zcache_flush_total++; - pool = zcache_get_pool_by_id(cli_id, pool_id); - ramster_do_preload_flnode_only(pool); - if (likely(pool != NULL)) { - if (atomic_read(&pool->obj_count) > 0) - ret = tmem_flush_page(pool, oidp, index); - zcache_put_pool(pool); - } - if (ret >= 0) - zcache_flush_found++; - local_irq_restore(flags); - return ret; -} - -int zcache_flush_object(int cli_id, int pool_id, struct tmem_oid *oidp) -{ - struct tmem_pool *pool; - int ret = -1; - unsigned long flags; - - local_irq_save(flags); - zcache_flobj_total++; - pool = zcache_get_pool_by_id(cli_id, pool_id); - ramster_do_preload_flnode_only(pool); - if (likely(pool != NULL)) { - if (atomic_read(&pool->obj_count) > 0) - ret = tmem_flush_object(pool, oidp); - zcache_put_pool(pool); - } - if (ret >= 0) - zcache_flobj_found++; - local_irq_restore(flags); - return ret; -} - -int zcache_client_destroy_pool(int cli_id, int pool_id) -{ - struct tmem_pool *pool = NULL; - struct zcache_client *cli = NULL; - int ret = -1; - - if (pool_id < 0) - goto out; - if (cli_id == LOCAL_CLIENT) - cli = &zcache_host; - else if ((unsigned int)cli_id < MAX_CLIENTS) - cli = &zcache_clients[cli_id]; - if (cli == NULL) - goto out; - atomic_inc(&cli->refcount); - pool = cli->tmem_pools[pool_id]; - if (pool == NULL) - goto out; - cli->tmem_pools[pool_id] = NULL; - /* wait for pool activity on other cpus to quiesce */ - while (atomic_read(&pool->refcount) != 0) - ; - atomic_dec(&cli->refcount); - local_bh_disable(); - ret = tmem_destroy_pool(pool); - local_bh_enable(); - kfree(pool); - pr_info("ramster: destroyed pool id=%d cli_id=%d\n", pool_id, cli_id); -out: - return ret; -} - -static int zcache_destroy_pool(int pool_id) -{ - return zcache_client_destroy_pool(LOCAL_CLIENT, pool_id); -} - -int zcache_new_pool(uint16_t cli_id, uint32_t flags) -{ - int poolid = -1; - struct tmem_pool *pool; - struct zcache_client *cli = NULL; - - if (cli_id == LOCAL_CLIENT) - cli = &zcache_host; - else if ((unsigned int)cli_id < MAX_CLIENTS) - cli = &zcache_clients[cli_id]; - if (cli == NULL) - goto out; - atomic_inc(&cli->refcount); - pool = kmalloc(sizeof(struct tmem_pool), GFP_ATOMIC); - if (pool == NULL) { - pr_info("ramster: pool creation failed: out of memory\n"); - goto out; - } - - for (poolid = 0; poolid < MAX_POOLS_PER_CLIENT; poolid++) - if (cli->tmem_pools[poolid] == NULL) - break; - if (poolid >= MAX_POOLS_PER_CLIENT) { - pr_info("ramster: pool creation failed: max exceeded\n"); - kfree(pool); - poolid = -1; - goto out; - } - atomic_set(&pool->refcount, 0); - pool->client = cli; - pool->pool_id = poolid; - tmem_new_pool(pool, flags); - cli->tmem_pools[poolid] = pool; - pr_info("ramster: created %s tmem pool, id=%d, client=%d\n", - flags & TMEM_POOL_PERSIST ? "persistent" : "ephemeral", - poolid, cli_id); -out: - if (cli != NULL) - atomic_dec(&cli->refcount); - return poolid; -} - -static int zcache_local_new_pool(uint32_t flags) -{ - return zcache_new_pool(LOCAL_CLIENT, flags); -} - -int zcache_autocreate_pool(int cli_id, int pool_id, bool ephemeral) -{ - struct tmem_pool *pool; - struct zcache_client *cli = NULL; - uint32_t flags = ephemeral ? 0 : TMEM_POOL_PERSIST; - int ret = -1; - - if (cli_id == LOCAL_CLIENT) - goto out; - if (pool_id >= MAX_POOLS_PER_CLIENT) - goto out; - else if ((unsigned int)cli_id < MAX_CLIENTS) - cli = &zcache_clients[cli_id]; - if ((ephemeral && !use_cleancache) || (!ephemeral && !use_frontswap)) - BUG(); /* FIXME, handle more gracefully later */ - if (!cli->allocated) { - if (zcache_new_client(cli_id)) - BUG(); /* FIXME, handle more gracefully later */ - cli = &zcache_clients[cli_id]; - } - atomic_inc(&cli->refcount); - pool = cli->tmem_pools[pool_id]; - if (pool != NULL) { - if (pool->persistent && ephemeral) { - pr_err("zcache_autocreate_pool: type mismatch\n"); - goto out; - } - ret = 0; - goto out; - } - pool = kmalloc(sizeof(struct tmem_pool), GFP_KERNEL); - if (pool == NULL) { - pr_info("ramster: pool creation failed: out of memory\n"); - goto out; - } - atomic_set(&pool->refcount, 0); - pool->client = cli; - pool->pool_id = pool_id; - tmem_new_pool(pool, flags); - cli->tmem_pools[pool_id] = pool; - pr_info("ramster: AUTOcreated %s tmem poolid=%d, for remote client=%d\n", - flags & TMEM_POOL_PERSIST ? "persistent" : "ephemeral", - pool_id, cli_id); - ret = 0; -out: - if (cli == NULL) - BUG(); /* FIXME, handle more gracefully later */ - /* pr_err("zcache_autocreate_pool: failed\n"); */ - if (cli != NULL) - atomic_dec(&cli->refcount); - return ret; -} - -/********** - * Two kernel functionalities currently can be layered on top of tmem. - * These are "cleancache" which is used as a second-chance cache for clean - * page cache pages; and "frontswap" which is used for swap pages - * to avoid writes to disk. A generic "shim" is provided here for each - * to translate in-kernel semantics to zcache semantics. - */ - -#ifdef CONFIG_CLEANCACHE -static void zcache_cleancache_put_page(int pool_id, - struct cleancache_filekey key, - pgoff_t index, struct page *page) -{ - u32 ind = (u32) index; - struct tmem_oid oid = *(struct tmem_oid *)&key; - -#ifdef __PG_WAS_ACTIVE - if (!PageWasActive(page)) { - zcache_nonactive_puts++; - return; - } -#endif - if (likely(ind == index)) { - char *kva = page_address(page); - - (void)zcache_put(LOCAL_CLIENT, pool_id, &oid, index, - kva, PAGE_SIZE, 0, 1); - } -} - -static int zcache_cleancache_get_page(int pool_id, - struct cleancache_filekey key, - pgoff_t index, struct page *page) -{ - u32 ind = (u32) index; - struct tmem_oid oid = *(struct tmem_oid *)&key; - int ret = -1; - - preempt_disable(); - if (likely(ind == index)) { - char *kva = page_address(page); - size_t size = PAGE_SIZE; - - ret = zcache_get(LOCAL_CLIENT, pool_id, &oid, index, - kva, &size, 0, 0); -#ifdef __PG_WAS_ACTIVE - if (ret == 0) - SetPageWasActive(page); -#endif - } - preempt_enable(); - return ret; -} - -static void zcache_cleancache_flush_page(int pool_id, - struct cleancache_filekey key, - pgoff_t index) -{ - u32 ind = (u32) index; - struct tmem_oid oid = *(struct tmem_oid *)&key; - - if (likely(ind == index)) - (void)zcache_flush(LOCAL_CLIENT, pool_id, &oid, ind); -} - -static void zcache_cleancache_flush_inode(int pool_id, - struct cleancache_filekey key) -{ - struct tmem_oid oid = *(struct tmem_oid *)&key; - - (void)zcache_flush_object(LOCAL_CLIENT, pool_id, &oid); -} - -static void zcache_cleancache_flush_fs(int pool_id) -{ - if (pool_id >= 0) - (void)zcache_destroy_pool(pool_id); -} - -static int zcache_cleancache_init_fs(size_t pagesize) -{ - BUG_ON(sizeof(struct cleancache_filekey) != - sizeof(struct tmem_oid)); - BUG_ON(pagesize != PAGE_SIZE); - return zcache_local_new_pool(0); -} - -static int zcache_cleancache_init_shared_fs(char *uuid, size_t pagesize) -{ - /* shared pools are unsupported and map to private */ - BUG_ON(sizeof(struct cleancache_filekey) != - sizeof(struct tmem_oid)); - BUG_ON(pagesize != PAGE_SIZE); - return zcache_local_new_pool(0); -} - -static struct cleancache_ops zcache_cleancache_ops = { - .put_page = zcache_cleancache_put_page, - .get_page = zcache_cleancache_get_page, - .invalidate_page = zcache_cleancache_flush_page, - .invalidate_inode = zcache_cleancache_flush_inode, - .invalidate_fs = zcache_cleancache_flush_fs, - .init_shared_fs = zcache_cleancache_init_shared_fs, - .init_fs = zcache_cleancache_init_fs -}; - -struct cleancache_ops zcache_cleancache_register_ops(void) -{ - struct cleancache_ops old_ops = - cleancache_register_ops(&zcache_cleancache_ops); - - return old_ops; -} -#endif - -#ifdef CONFIG_FRONTSWAP -/* a single tmem poolid is used for all frontswap "types" (swapfiles) */ -static int zcache_frontswap_poolid = -1; - -/* - * Swizzling increases objects per swaptype, increasing tmem concurrency - * for heavy swaploads. Later, larger nr_cpus -> larger SWIZ_BITS - */ -#define SWIZ_BITS 8 -#define SWIZ_MASK ((1 << SWIZ_BITS) - 1) -#define _oswiz(_type, _ind) ((_type << SWIZ_BITS) | (_ind & SWIZ_MASK)) -#define iswiz(_ind) (_ind >> SWIZ_BITS) - -static inline struct tmem_oid oswiz(unsigned type, u32 ind) -{ - struct tmem_oid oid = { .oid = { 0 } }; - oid.oid[0] = _oswiz(type, ind); - return oid; -} - -static int zcache_frontswap_put_page(unsigned type, pgoff_t offset, - struct page *page) -{ - u64 ind64 = (u64)offset; - u32 ind = (u32)offset; - struct tmem_oid oid = oswiz(type, ind); - int ret = -1; - unsigned long flags; - char *kva; - - BUG_ON(!PageLocked(page)); - if (likely(ind64 == ind)) { - local_irq_save(flags); - kva = page_address(page); - ret = zcache_put(LOCAL_CLIENT, zcache_frontswap_poolid, - &oid, iswiz(ind), kva, PAGE_SIZE, 0, 0); - local_irq_restore(flags); - } - return ret; -} - -/* returns 0 if the page was successfully gotten from frontswap, -1 if - * was not present (should never happen!) */ -static int zcache_frontswap_get_page(unsigned type, pgoff_t offset, - struct page *page) -{ - u64 ind64 = (u64)offset; - u32 ind = (u32)offset; - struct tmem_oid oid = oswiz(type, ind); - int ret = -1; - - preempt_disable(); /* FIXME, remove this? */ - BUG_ON(!PageLocked(page)); - if (likely(ind64 == ind)) { - char *kva = page_address(page); - size_t size = PAGE_SIZE; - - ret = zcache_get(LOCAL_CLIENT, zcache_frontswap_poolid, - &oid, iswiz(ind), kva, &size, 0, -1); - } - preempt_enable(); /* FIXME, remove this? */ - return ret; -} - -/* flush a single page from frontswap */ -static void zcache_frontswap_flush_page(unsigned type, pgoff_t offset) -{ - u64 ind64 = (u64)offset; - u32 ind = (u32)offset; - struct tmem_oid oid = oswiz(type, ind); - - if (likely(ind64 == ind)) - (void)zcache_flush(LOCAL_CLIENT, zcache_frontswap_poolid, - &oid, iswiz(ind)); -} - -/* flush all pages from the passed swaptype */ -static void zcache_frontswap_flush_area(unsigned type) -{ - struct tmem_oid oid; - int ind; - - for (ind = SWIZ_MASK; ind >= 0; ind--) { - oid = oswiz(type, ind); - (void)zcache_flush_object(LOCAL_CLIENT, - zcache_frontswap_poolid, &oid); - } -} - -static void zcache_frontswap_init(unsigned ignored) -{ - /* a single tmem poolid is used for all frontswap "types" (swapfiles) */ - if (zcache_frontswap_poolid < 0) - zcache_frontswap_poolid = - zcache_local_new_pool(TMEM_POOL_PERSIST); -} - -static struct frontswap_ops zcache_frontswap_ops = { - .put_page = zcache_frontswap_put_page, - .get_page = zcache_frontswap_get_page, - .invalidate_page = zcache_frontswap_flush_page, - .invalidate_area = zcache_frontswap_flush_area, - .init = zcache_frontswap_init -}; - -struct frontswap_ops zcache_frontswap_register_ops(void) -{ - struct frontswap_ops old_ops = - frontswap_register_ops(&zcache_frontswap_ops); - - return old_ops; -} -#endif - -/* - * frontswap selfshrinking - */ - -#ifdef CONFIG_FRONTSWAP -/* In HZ, controls frequency of worker invocation. */ -static unsigned int selfshrink_interval __read_mostly = 5; - -static void selfshrink_process(struct work_struct *work); -static DECLARE_DELAYED_WORK(selfshrink_worker, selfshrink_process); - -/* Enable/disable with sysfs. */ -static bool frontswap_selfshrinking __read_mostly; - -/* Enable/disable with kernel boot option. */ -static bool use_frontswap_selfshrink __initdata = true; - -/* - * The default values for the following parameters were deemed reasonable - * by experimentation, may be workload-dependent, and can all be - * adjusted via sysfs. - */ - -/* Control rate for frontswap shrinking. Higher hysteresis is slower. */ -static unsigned int frontswap_hysteresis __read_mostly = 20; - -/* - * Number of selfshrink worker invocations to wait before observing that - * frontswap selfshrinking should commence. Note that selfshrinking does - * not use a separate worker thread. - */ -static unsigned int frontswap_inertia __read_mostly = 3; - -/* Countdown to next invocation of frontswap_shrink() */ -static unsigned long frontswap_inertia_counter; - -/* - * Invoked by the selfshrink worker thread, uses current number of pages - * in frontswap (frontswap_curr_pages()), previous status, and control - * values (hysteresis and inertia) to determine if frontswap should be - * shrunk and what the new frontswap size should be. Note that - * frontswap_shrink is essentially a partial swapoff that immediately - * transfers pages from the "swap device" (frontswap) back into kernel - * RAM; despite the name, frontswap "shrinking" is very different from - * the "shrinker" interface used by the kernel MM subsystem to reclaim - * memory. - */ -static void frontswap_selfshrink(void) -{ - static unsigned long cur_frontswap_pages; - static unsigned long last_frontswap_pages; - static unsigned long tgt_frontswap_pages; - - last_frontswap_pages = cur_frontswap_pages; - cur_frontswap_pages = frontswap_curr_pages(); - if (!cur_frontswap_pages || - (cur_frontswap_pages > last_frontswap_pages)) { - frontswap_inertia_counter = frontswap_inertia; - return; - } - if (frontswap_inertia_counter && --frontswap_inertia_counter) - return; - if (cur_frontswap_pages <= frontswap_hysteresis) - tgt_frontswap_pages = 0; - else - tgt_frontswap_pages = cur_frontswap_pages - - (cur_frontswap_pages / frontswap_hysteresis); - frontswap_shrink(tgt_frontswap_pages); -} - -static int __init ramster_nofrontswap_selfshrink_setup(char *s) -{ - use_frontswap_selfshrink = false; - return 1; -} - -__setup("noselfshrink", ramster_nofrontswap_selfshrink_setup); - -static void selfshrink_process(struct work_struct *work) -{ - if (frontswap_selfshrinking && frontswap_enabled) { - frontswap_selfshrink(); - schedule_delayed_work(&selfshrink_worker, - selfshrink_interval * HZ); - } -} - -static int ramster_enabled; - -static int __init ramster_selfshrink_init(void) -{ - frontswap_selfshrinking = ramster_enabled && use_frontswap_selfshrink; - if (frontswap_selfshrinking) - pr_info("ramster: Initializing frontswap " - "selfshrinking driver.\n"); - else - return -ENODEV; - - schedule_delayed_work(&selfshrink_worker, selfshrink_interval * HZ); - - return 0; -} - -subsys_initcall(ramster_selfshrink_init); -#endif - -/* - * zcache initialization - * NOTE FOR NOW ramster MUST BE PROVIDED AS A KERNEL BOOT PARAMETER OR - * NOTHING HAPPENS! - */ - -static int ramster_enabled; - -static int __init enable_ramster(char *s) -{ - ramster_enabled = 1; - return 1; -} -__setup("ramster", enable_ramster); - -/* allow independent dynamic disabling of cleancache and frontswap */ - -static int use_cleancache = 1; - -static int __init no_cleancache(char *s) -{ - pr_info("INIT no_cleancache called\n"); - use_cleancache = 0; - return 1; -} - -/* - * FIXME: need to guarantee this gets checked before zcache_init is called - * What is the correct way to achieve this? - */ -early_param("nocleancache", no_cleancache); - -static int use_frontswap = 1; - -static int __init no_frontswap(char *s) -{ - pr_info("INIT no_frontswap called\n"); - use_frontswap = 0; - return 1; -} - -__setup("nofrontswap", no_frontswap); - -static int __init zcache_init(void) -{ - int ret = 0; - -#ifdef CONFIG_SYSFS - ret = sysfs_create_group(mm_kobj, &zcache_attr_group); - ret = sysfs_create_group(mm_kobj, &ramster_attr_group); - if (ret) { - pr_err("ramster: can't create sysfs\n"); - goto out; - } -#endif /* CONFIG_SYSFS */ -#if defined(CONFIG_CLEANCACHE) || defined(CONFIG_FRONTSWAP) - if (ramster_enabled) { - unsigned int cpu; - - (void)ramster_o2net_register_handlers(); - tmem_register_hostops(&zcache_hostops); - tmem_register_pamops(&zcache_pamops); - ret = register_cpu_notifier(&zcache_cpu_notifier_block); - if (ret) { - pr_err("ramster: can't register cpu notifier\n"); - goto out; - } - for_each_online_cpu(cpu) { - void *pcpu = (void *)(long)cpu; - zcache_cpu_notifier(&zcache_cpu_notifier_block, - CPU_UP_PREPARE, pcpu); - } - } - zcache_objnode_cache = kmem_cache_create("zcache_objnode", - sizeof(struct tmem_objnode), 0, 0, NULL); - zcache_obj_cache = kmem_cache_create("zcache_obj", - sizeof(struct tmem_obj), 0, 0, NULL); - ramster_flnode_cache = kmem_cache_create("ramster_flnode", - sizeof(struct flushlist_node), 0, 0, NULL); -#endif -#ifdef CONFIG_CLEANCACHE - pr_info("INIT ramster_enabled=%d use_cleancache=%d\n", - ramster_enabled, use_cleancache); - if (ramster_enabled && use_cleancache) { - struct cleancache_ops old_ops; - - zbud_init(); - register_shrinker(&zcache_shrinker); - old_ops = zcache_cleancache_register_ops(); - pr_info("ramster: cleancache enabled using kernel " - "transcendent memory and compression buddies\n"); - if (old_ops.init_fs != NULL) - pr_warning("ramster: cleancache_ops overridden"); - } -#endif -#ifdef CONFIG_FRONTSWAP - pr_info("INIT ramster_enabled=%d use_frontswap=%d\n", - ramster_enabled, use_frontswap); - if (ramster_enabled && use_frontswap) { - struct frontswap_ops old_ops; - - zcache_new_client(LOCAL_CLIENT); - old_ops = zcache_frontswap_register_ops(); - pr_info("ramster: frontswap enabled using kernel " - "transcendent memory and xvmalloc\n"); - if (old_ops.init != NULL) - pr_warning("ramster: frontswap_ops overridden"); - } - if (ramster_enabled && (use_frontswap || use_cleancache)) - ramster_remotify_init(); -#endif -out: - return ret; -} - -module_init(zcache_init) diff --git a/drivers/staging/ramster/zcache.h b/drivers/staging/ramster/zcache.h deleted file mode 100644 index 250b121..0000000 --- a/drivers/staging/ramster/zcache.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * zcache.h - * - * External zcache functions - * - * Copyright (c) 2009-2012, Dan Magenheimer, Oracle Corp. - */ - -#ifndef _ZCACHE_H_ -#define _ZCACHE_H_ - -extern int zcache_put(int, int, struct tmem_oid *, uint32_t, - char *, size_t, bool, int); -extern int zcache_autocreate_pool(int, int, bool); -extern int zcache_get(int, int, struct tmem_oid *, uint32_t, - char *, size_t *, bool, int); -extern int zcache_flush(int, int, struct tmem_oid *, uint32_t); -extern int zcache_flush_object(int, int, struct tmem_oid *); -extern int zcache_localify(int, struct tmem_oid *, uint32_t, - char *, size_t, void *); - -#endif /* _ZCACHE_H */ -- cgit v0.10.2 From 84359ef62aa36dc92508547852587b284c2664d2 Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Thu, 9 Feb 2012 21:11:43 +0100 Subject: staging/xgifb: Include sis initdef.h header This patch includes the initdef.h header from the sis driver. Since the xgi driver used to redefine a lot of stuff from the sis driver, we can simply include the headers of the sis driver itself, so we can remove duplicated stuff later on. In order to include the initdef.h we have to rename the header guards. Signed-off-by: Peter Huewe Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/xgifb/vb_def.h b/drivers/staging/xgifb/vb_def.h index 5beeef9..0472c86 100644 --- a/drivers/staging/xgifb/vb_def.h +++ b/drivers/staging/xgifb/vb_def.h @@ -1,7 +1,8 @@ /* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/xgi/initdef.h * ,v 1.4 2000/12/02 01:16:17 dawes Exp $*/ -#ifndef _INITDEF_ -#define _INITDEF_ +#ifndef _VB_DEF_ +#define _VB_DEF_ +#include "../../video/sis/initdef.h" #define VB_XGI301C 0x0020 /* for 301C */ /*end 301b*/ -- cgit v0.10.2 From 255aabd2b8ad98a49d224b243c7b1f82adcdfb4a Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Thu, 9 Feb 2012 21:11:44 +0100 Subject: staging/xgifb: Rename panel defines and remove duplicated defines This patch renames the Panel* defines and their usage to the naming convention of the sis initdef.h and removes the now duplicated defines. Renames: Panel320x480 -> Panel_320x480 Panel800x600 -> Panel_800x600 Panel1024x768 -> Panel_1024x768 Panel1024x768x75 -> Panel_1024x768x75 Panel1280x1024 -> Panel_1280x1024 Panel1280x1024x75 -> Panel_1280x1024x75 Panel1280x960 -> Panel_1280x960 Panel1400x1050 -> Panel_1400x1050 Panel1600x1200 -> Panel_1600x1200 Signed-off-by: Peter Huewe Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/xgifb/vb_def.h b/drivers/staging/xgifb/vb_def.h index 0472c86..9b2937c 100644 --- a/drivers/staging/xgifb/vb_def.h +++ b/drivers/staging/xgifb/vb_def.h @@ -19,18 +19,11 @@ #define PanelRGB18Bit 0x0100 #define PanelRGB24Bit 0x0000 -#define Panel320x480 0x07 /*fstn*/ +#define Panel_320x480 0x07 /*fstn*/ /* [ycchen] 02/12/03 Modify for Multi-Sync. LCD Support */ #define PanelResInfo 0x1F /* CR36 Panel Type/LCDResInfo */ -#define Panel800x600 0x01 -#define Panel1024x768 0x02 -#define Panel1024x768x75 0x22 -#define Panel1280x1024 0x03 -#define Panel1280x1024x75 0x23 -#define Panel640x480 0x04 -#define Panel1280x960 0x07 -#define Panel1400x1050 0x09 -#define Panel1600x1200 0x0B +#define Panel_1024x768x75 0x22 +#define Panel_1280x1024x75 0x23 #define PanelRef60Hz 0x00 #define PanelRef75Hz 0x20 diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index fad144c..25c647b 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -359,8 +359,8 @@ static unsigned char XGI_AjustCRT2Rate(unsigned short ModeNo, if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { tempax |= SupportLCD; - if (pVBInfo->LCDResInfo != Panel1280x1024) { - if (pVBInfo->LCDResInfo != Panel1280x960) { + if (pVBInfo->LCDResInfo != Panel_1280x1024) { + if (pVBInfo->LCDResInfo != Panel_1280x960) { if (pVBInfo->LCDInfo & LCDNonExpanding) { if (resinfo >= 9) { @@ -436,7 +436,7 @@ static unsigned char XGI_AjustCRT2Rate(unsigned short ModeNo, if (resinfo > 0x08) return 0; /* 1024x768 */ - if (pVBInfo->LCDResInfo < Panel1024x768) { + if (pVBInfo->LCDResInfo < Panel_1024x768) { if (resinfo > 0x07) return 0; /* 800x600 */ @@ -1267,7 +1267,7 @@ static unsigned short XGI_GetVCLK2Ptr(unsigned short ModeNo, if (pVBInfo->IF_DEF_LVDS == 0) { CRT2Index = CRT2Index >> 6; /* for LCD */ if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { /*301b*/ - if (pVBInfo->LCDResInfo != Panel1024x768) + if (pVBInfo->LCDResInfo != Panel_1024x768) VCLKIndex = LCDXlat2VCLK[CRT2Index]; else VCLKIndex = LCDXlat1VCLK[CRT2Index]; @@ -1329,11 +1329,11 @@ static unsigned short XGI_GetVCLK2Ptr(unsigned short ModeNo, VCLKIndex = CRT2Index; VCLKIndex = VCLKIndex >> 6; - if ((pVBInfo->LCDResInfo == Panel800x600) || - (pVBInfo->LCDResInfo == Panel320x480)) + if ((pVBInfo->LCDResInfo == Panel_800x600) || + (pVBInfo->LCDResInfo == Panel_320x480)) VCLKIndex = LVDSXlat1VCLK[VCLKIndex]; - else if ((pVBInfo->LCDResInfo == Panel1024x768) || - (pVBInfo->LCDResInfo == Panel1024x768x75)) + else if ((pVBInfo->LCDResInfo == Panel_1024x768) || + (pVBInfo->LCDResInfo == Panel_1024x768x75)) VCLKIndex = LVDSXlat2VCLK[VCLKIndex]; else VCLKIndex = LVDSXlat3VCLK[VCLKIndex]; @@ -2377,15 +2377,15 @@ static void XGI_GetLVDSData(unsigned short ModeNo, unsigned short ModeIdIndex, if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { if (!(pVBInfo->LCDInfo & (SetLCDtoNonExpanding | EnableScalingLCD))) { - if ((pVBInfo->LCDResInfo == Panel1024x768) || - (pVBInfo->LCDResInfo == Panel1024x768x75)) { + if ((pVBInfo->LCDResInfo == Panel_1024x768) || + (pVBInfo->LCDResInfo == Panel_1024x768x75)) { pVBInfo->HDE = 1024; pVBInfo->VDE = 768; - } else if ((pVBInfo->LCDResInfo == Panel1280x1024) || - (pVBInfo->LCDResInfo == Panel1280x1024x75)) { + } else if ((pVBInfo->LCDResInfo == Panel_1280x1024) || + (pVBInfo->LCDResInfo == Panel_1280x1024x75)) { pVBInfo->HDE = 1280; pVBInfo->VDE = 1024; - } else if (pVBInfo->LCDResInfo == Panel1400x1050) { + } else if (pVBInfo->LCDResInfo == Panel_1400x1050) { pVBInfo->HDE = 1400; pVBInfo->VDE = 1050; } else { @@ -2496,7 +2496,7 @@ static unsigned short XGI_GetLCDCapPtr1(struct vb_device_info *pVBInfo) } if (tempbl == 0xFF) { - pVBInfo->LCDResInfo = Panel1024x768; + pVBInfo->LCDResInfo = Panel_1024x768; pVBInfo->LCDTypeInfo = 0; i = 0; } @@ -2556,15 +2556,15 @@ static void XGI_SetLVDSRegs(unsigned short ModeNo, unsigned short ModeIdIndex, push2 = tempax; /* GetLCDResInfo */ - if ((pVBInfo->LCDResInfo == Panel1024x768) || - (pVBInfo->LCDResInfo == Panel1024x768x75)) { + if ((pVBInfo->LCDResInfo == Panel_1024x768) || + (pVBInfo->LCDResInfo == Panel_1024x768x75)) { tempax = 1024; tempbx = 768; - } else if ((pVBInfo->LCDResInfo == Panel1280x1024) || - (pVBInfo->LCDResInfo == Panel1280x1024x75)) { + } else if ((pVBInfo->LCDResInfo == Panel_1280x1024) || + (pVBInfo->LCDResInfo == Panel_1280x1024x75)) { tempax = 1280; tempbx = 1024; - } else if (pVBInfo->LCDResInfo == Panel1400x1050) { + } else if (pVBInfo->LCDResInfo == Panel_1400x1050) { tempax = 1400; tempbx = 1050; } else { @@ -2768,7 +2768,7 @@ static void XGI_SetLVDSRegs(unsigned short ModeNo, unsigned short ModeIdIndex, temp1 = temp1 / push3; tempbx = (unsigned short) (temp1 & 0xffff); - if (pVBInfo->LCDResInfo == Panel1024x768) + if (pVBInfo->LCDResInfo == Panel_1024x768) tempbx -= 1; tempax = ((tempbx >> 8) & 0xff) << 3; @@ -3386,10 +3386,10 @@ static unsigned char XGI_GetLCDInfo(unsigned short ModeNo, tempbx = temp & 0x0F; if (tempbx == 0) - tempbx = Panel1024x768; /* default */ + tempbx = Panel_1024x768; /* default */ /* LCD75 [2003/8/22] Vicent */ - if ((tempbx == Panel1024x768) || (tempbx == Panel1280x1024)) { + if ((tempbx == Panel_1024x768) || (tempbx == Panel_1280x1024)) { if (pVBInfo->VBInfo & DriverMode) { tempax = xgifb_reg_get(pVBInfo->P3d4, 0x33); if (pVBInfo->VBInfo & SetCRT2ToLCDA) @@ -3434,10 +3434,10 @@ static unsigned char XGI_GetLCDInfo(unsigned short ModeNo, } if (pVBInfo->IF_DEF_LVDS == 0) { - if ((pVBInfo->LCDResInfo == Panel1400x1050) && (pVBInfo->VBInfo + if ((pVBInfo->LCDResInfo == Panel_1400x1050) && (pVBInfo->VBInfo & SetCRT2ToLCD) && (ModeNo > 0x13) && (resinfo == 9) && (!(tempbx & EnableScalingLCD))) - /* set to center in 1280x1024 LCDB for Panel1400x1050 */ + /* set to center in 1280x1024 LCDB for Panel_1400x1050 */ tempbx |= SetLCDtoNonExpanding; } @@ -3448,7 +3448,7 @@ static unsigned char XGI_GetLCDInfo(unsigned short ModeNo, } else { if (ModeNo > 0x13) { if (pVBInfo->LCDResInfo - == Panel1024x768) { + == Panel_1024x768) { if (resinfo == 4) {/* 512x384 */ tempbx |= EnableLVDSDDA; } @@ -3801,14 +3801,14 @@ static void XGI_GetCRT2ResInfo(unsigned short ModeNo, if (pVBInfo->VBInfo & SetCRT2ToLCD) { if (pVBInfo->IF_DEF_LVDS == 0) { - if (pVBInfo->LCDResInfo == Panel1600x1200) { + if (pVBInfo->LCDResInfo == Panel_1600x1200) { if (!(pVBInfo->LCDInfo & LCDVESATiming)) { if (yres == 1024) yres = 1056; } } - if (pVBInfo->LCDResInfo == Panel1280x1024) { + if (pVBInfo->LCDResInfo == Panel_1280x1024) { if (yres == 400) yres = 405; else if (yres == 350) @@ -3820,7 +3820,7 @@ static void XGI_GetCRT2ResInfo(unsigned short ModeNo, } } - if (pVBInfo->LCDResInfo == Panel1024x768) { + if (pVBInfo->LCDResInfo == Panel_1024x768) { if (!(pVBInfo->LCDInfo & LCDVESATiming)) { if (!(pVBInfo->LCDInfo & LCDNonExpanding)) { @@ -3954,7 +3954,7 @@ static void XGI_GetCRT2Data(unsigned short ModeNo, unsigned short ModeIdIndex, pVBInfo->HT = LCDPtr->LCDHT; pVBInfo->VT = LCDPtr->LCDVT; - if (pVBInfo->LCDResInfo == Panel1024x768) { + if (pVBInfo->LCDResInfo == Panel_1024x768) { tempax = 1024; tempbx = 768; @@ -3971,10 +3971,10 @@ static void XGI_GetCRT2Data(unsigned short ModeNo, unsigned short ModeIdIndex, tempbx = 768; } else tempbx = 768; - } else if (pVBInfo->LCDResInfo == Panel1024x768x75) { + } else if (pVBInfo->LCDResInfo == Panel_1024x768x75) { tempax = 1024; tempbx = 768; - } else if (pVBInfo->LCDResInfo == Panel1280x1024) { + } else if (pVBInfo->LCDResInfo == Panel_1280x1024) { tempax = 1280; if (pVBInfo->VGAVDE == 360) tempbx = 768; @@ -3984,10 +3984,10 @@ static void XGI_GetCRT2Data(unsigned short ModeNo, unsigned short ModeIdIndex, tempbx = 864; else tempbx = 1024; - } else if (pVBInfo->LCDResInfo == Panel1280x1024x75) { + } else if (pVBInfo->LCDResInfo == Panel_1280x1024x75) { tempax = 1280; tempbx = 1024; - } else if (pVBInfo->LCDResInfo == Panel1280x960) { + } else if (pVBInfo->LCDResInfo == Panel_1280x960) { tempax = 1280; if (pVBInfo->VGAVDE == 350) tempbx = 700; @@ -3997,7 +3997,7 @@ static void XGI_GetCRT2Data(unsigned short ModeNo, unsigned short ModeIdIndex, tempbx = 960; else tempbx = 960; - } else if (pVBInfo->LCDResInfo == Panel1400x1050) { + } else if (pVBInfo->LCDResInfo == Panel_1400x1050) { tempax = 1400; tempbx = 1050; @@ -4005,7 +4005,7 @@ static void XGI_GetCRT2Data(unsigned short ModeNo, unsigned short ModeIdIndex, tempax = 1280; tempbx = 1024; } - } else if (pVBInfo->LCDResInfo == Panel1600x1200) { + } else if (pVBInfo->LCDResInfo == Panel_1600x1200) { tempax = 1600; tempbx = 1200; /* alan 10/14/2003 */ if (!(pVBInfo->LCDInfo & LCDVESATiming)) { @@ -4513,19 +4513,19 @@ static void XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex, } } else if (!(modeflag & HalfDCLK)) { temp -= 4; - if (pVBInfo->LCDResInfo != Panel1280x960 && + if (pVBInfo->LCDResInfo != Panel_1280x960 && pVBInfo->VGAHDE >= 800) { temp -= 7; if (pVBInfo->ModeType == ModeEGA && pVBInfo->VGAVDE == 1024) { temp += 15; if (pVBInfo->LCDResInfo != - Panel1280x1024) + Panel_1280x1024) temp += 7; } if (pVBInfo->VGAHDE >= 1280 && - pVBInfo->LCDResInfo != Panel1280x960 && + pVBInfo->LCDResInfo != Panel_1280x960 && (pVBInfo->LCDInfo & LCDNonExpanding)) temp += 28; } @@ -4619,7 +4619,7 @@ static void XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex, push2 = tempbx; if (pVBInfo->VBInfo & SetCRT2ToLCD) { - if (pVBInfo->LCDResInfo == Panel1024x768) { + if (pVBInfo->LCDResInfo == Panel_1024x768) { if (!(pVBInfo->LCDInfo & LCDVESATiming)) { if (tempbx == 350) tempbx += 5; @@ -5267,7 +5267,7 @@ static void XGI_SetLCDRegs(unsigned short ModeNo, unsigned short ModeIdIndex, xgifb_reg_and_or(pVBInfo->Part2Port, 0x2B, 0x0F, temp); temp = 0x01; - if (pVBInfo->LCDResInfo == Panel1280x1024) { + if (pVBInfo->LCDResInfo == Panel_1280x1024) { if (pVBInfo->ModeType == ModeEGA) { if (pVBInfo->VGAHDE >= 1024) { temp = 0x02; @@ -5305,14 +5305,14 @@ static void XGI_SetLCDRegs(unsigned short ModeNo, unsigned short ModeIdIndex, tempah = pVBInfo->LCDResInfo; tempah &= PanelResInfo; - if ((tempah == Panel1024x768) || (tempah == Panel1024x768x75)) { + if ((tempah == Panel_1024x768) || (tempah == Panel_1024x768x75)) { tempbx = 1024; tempcx = 768; - } else if ((tempah == Panel1280x1024) || - (tempah == Panel1280x1024x75)) { + } else if ((tempah == Panel_1280x1024) || + (tempah == Panel_1280x1024x75)) { tempbx = 1280; tempcx = 1024; - } else if (tempah == Panel1400x1050) { + } else if (tempah == Panel_1400x1050) { tempbx = 1400; tempcx = 1050; } else { @@ -6807,11 +6807,11 @@ static void XGI_SetCRT2ModeRegs(unsigned short ModeNo, tempah |= 0x40; } - if ((pVBInfo->LCDResInfo == Panel1280x1024) - || (pVBInfo->LCDResInfo == Panel1280x1024x75)) + if ((pVBInfo->LCDResInfo == Panel_1280x1024) + || (pVBInfo->LCDResInfo == Panel_1280x1024x75)) tempah |= 0x80; - if (pVBInfo->LCDResInfo == Panel1280x960) + if (pVBInfo->LCDResInfo == Panel_1280x960) tempah |= 0x80; xgifb_reg_set(pVBInfo->Part4Port, 0x0C, tempah); diff --git a/drivers/staging/xgifb/vb_table.h b/drivers/staging/xgifb/vb_table.h index 217fb87..c587d41 100644 --- a/drivers/staging/xgifb/vb_table.h +++ b/drivers/staging/xgifb/vb_table.h @@ -2353,109 +2353,109 @@ static struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11280x1024_2_Vx75[] = { /*add for new UNIVGABIOS*/ static struct XGI330_LCDDataTablStruct XGI_LCDDataTable[] = { - {Panel1024x768, 0x0019, 0x0001, 0}, /* XGI_ExtLCD1024x768Data */ - {Panel1024x768, 0x0019, 0x0000, 1}, /* XGI_StLCD1024x768Data */ - {Panel1024x768, 0x0018, 0x0010, 2}, /* XGI_CetLCD1024x768Data */ - {Panel1280x1024, 0x0019, 0x0001, 3}, /* XGI_ExtLCD1280x1024Data */ - {Panel1280x1024, 0x0019, 0x0000, 4}, /* XGI_StLCD1280x1024Data */ - {Panel1280x1024, 0x0018, 0x0010, 5}, /* XGI_CetLCD1280x1024Data */ - {Panel1400x1050, 0x0019, 0x0001, 6}, /* XGI_ExtLCD1400x1050Data */ - {Panel1400x1050, 0x0019, 0x0000, 7}, /* XGI_StLCD1400x1050Data */ - {Panel1400x1050, 0x0018, 0x0010, 8}, /* XGI_CetLCD1400x1050Data */ - {Panel1600x1200, 0x0019, 0x0001, 9}, /* XGI_ExtLCD1600x1200Data */ - {Panel1600x1200, 0x0019, 0x0000, 10}, /* XGI_StLCD1600x1200Data */ + {Panel_1024x768, 0x0019, 0x0001, 0}, /* XGI_ExtLCD1024x768Data */ + {Panel_1024x768, 0x0019, 0x0000, 1}, /* XGI_StLCD1024x768Data */ + {Panel_1024x768, 0x0018, 0x0010, 2}, /* XGI_CetLCD1024x768Data */ + {Panel_1280x1024, 0x0019, 0x0001, 3}, /* XGI_ExtLCD1280x1024Data */ + {Panel_1280x1024, 0x0019, 0x0000, 4}, /* XGI_StLCD1280x1024Data */ + {Panel_1280x1024, 0x0018, 0x0010, 5}, /* XGI_CetLCD1280x1024Data */ + {Panel_1400x1050, 0x0019, 0x0001, 6}, /* XGI_ExtLCD1400x1050Data */ + {Panel_1400x1050, 0x0019, 0x0000, 7}, /* XGI_StLCD1400x1050Data */ + {Panel_1400x1050, 0x0018, 0x0010, 8}, /* XGI_CetLCD1400x1050Data */ + {Panel_1600x1200, 0x0019, 0x0001, 9}, /* XGI_ExtLCD1600x1200Data */ + {Panel_1600x1200, 0x0019, 0x0000, 10}, /* XGI_StLCD1600x1200Data */ {PanelRef60Hz, 0x0008, 0x0008, 11}, /* XGI_NoScalingData */ - {Panel1024x768x75, 0x0019, 0x0001, 12}, /* XGI_ExtLCD1024x768x75Data */ - {Panel1024x768x75, 0x0019, 0x0000, 13}, /* XGI_StLCD1024x768x75Data */ - {Panel1024x768x75, 0x0018, 0x0010, 14}, /* XGI_CetLCD1024x768x75Data */ - {Panel1280x1024x75, 0x0019, 0x0001, 15}, /* XGI_ExtLCD1280x1024x75Data*/ - {Panel1280x1024x75, 0x0019, 0x0000, 16}, /* XGI_StLCD1280x1024x75Data */ - {Panel1280x1024x75, 0x0018, 0x0010, 17}, /* XGI_CetLCD1280x1024x75Data*/ + {Panel_1024x768x75, 0x0019, 0x0001, 12}, /* XGI_ExtLCD1024x768x75Data */ + {Panel_1024x768x75, 0x0019, 0x0000, 13}, /* XGI_StLCD1024x768x75Data */ + {Panel_1024x768x75, 0x0018, 0x0010, 14}, /* XGI_CetLCD1024x768x75Data */ + {Panel_1280x1024x75, 0x0019, 0x0001, 15}, /* XGI_ExtLCD1280x1024x75Data*/ + {Panel_1280x1024x75, 0x0019, 0x0000, 16}, /* XGI_StLCD1280x1024x75Data */ + {Panel_1280x1024x75, 0x0018, 0x0010, 17}, /* XGI_CetLCD1280x1024x75Data*/ {PanelRef75Hz, 0x0008, 0x0008, 18}, /* XGI_NoScalingDatax75 */ {0xFF, 0x0000, 0x0000, 0} /* End of table */ }; static struct XGI330_LCDDataTablStruct XGI_LCDDesDataTable[] = { - {Panel1024x768, 0x0019, 0x0001, 0}, /* XGI_ExtLCDDes1024x768Data */ - {Panel1024x768, 0x0019, 0x0000, 1}, /* XGI_StLCDDes1024x768Data */ - {Panel1024x768, 0x0018, 0x0010, 2}, /* XGI_CetLCDDes1024x768Data */ - {Panel1280x1024, 0x0019, 0x0001, 3}, /* XGI_ExtLCDDes1280x1024Data */ - {Panel1280x1024, 0x0019, 0x0000, 4}, /* XGI_StLCDDes1280x1024Data */ - {Panel1280x1024, 0x0018, 0x0010, 5}, /* XGI_CetLCDDes1280x1024Data */ - {Panel1400x1050, 0x0019, 0x0001, 6}, /* XGI_ExtLCDDes1400x1050Data */ - {Panel1400x1050, 0x0019, 0x0000, 7}, /* XGI_StLCDDes1400x1050Data */ - {Panel1400x1050, 0x0418, 0x0010, 8}, /* XGI_CetLCDDes1400x1050Data */ - {Panel1400x1050, 0x0418, 0x0410, 9}, /* XGI_CetLCDDes1400x1050Data2 */ - {Panel1600x1200, 0x0019, 0x0001, 10}, /* XGI_ExtLCDDes1600x1200Data */ - {Panel1600x1200, 0x0019, 0x0000, 11}, /* XGI_StLCDDes1600x1200Data */ + {Panel_1024x768, 0x0019, 0x0001, 0}, /* XGI_ExtLCDDes1024x768Data */ + {Panel_1024x768, 0x0019, 0x0000, 1}, /* XGI_StLCDDes1024x768Data */ + {Panel_1024x768, 0x0018, 0x0010, 2}, /* XGI_CetLCDDes1024x768Data */ + {Panel_1280x1024, 0x0019, 0x0001, 3}, /* XGI_ExtLCDDes1280x1024Data */ + {Panel_1280x1024, 0x0019, 0x0000, 4}, /* XGI_StLCDDes1280x1024Data */ + {Panel_1280x1024, 0x0018, 0x0010, 5}, /* XGI_CetLCDDes1280x1024Data */ + {Panel_1400x1050, 0x0019, 0x0001, 6}, /* XGI_ExtLCDDes1400x1050Data */ + {Panel_1400x1050, 0x0019, 0x0000, 7}, /* XGI_StLCDDes1400x1050Data */ + {Panel_1400x1050, 0x0418, 0x0010, 8}, /* XGI_CetLCDDes1400x1050Data */ + {Panel_1400x1050, 0x0418, 0x0410, 9}, /* XGI_CetLCDDes1400x1050Data2 */ + {Panel_1600x1200, 0x0019, 0x0001, 10}, /* XGI_ExtLCDDes1600x1200Data */ + {Panel_1600x1200, 0x0019, 0x0000, 11}, /* XGI_StLCDDes1600x1200Data */ {PanelRef60Hz, 0x0008, 0x0008, 12}, /* XGI_NoScalingDesData */ - {Panel1024x768x75, 0x0019, 0x0001, 13}, /*XGI_ExtLCDDes1024x768x75Data*/ - {Panel1024x768x75, 0x0019, 0x0000, 14}, /* XGI_StLCDDes1024x768x75Data*/ - {Panel1024x768x75, 0x0018, 0x0010, 15}, /*XGI_CetLCDDes1024x768x75Data*/ + {Panel_1024x768x75, 0x0019, 0x0001, 13}, /*XGI_ExtLCDDes1024x768x75Data*/ + {Panel_1024x768x75, 0x0019, 0x0000, 14}, /* XGI_StLCDDes1024x768x75Data*/ + {Panel_1024x768x75, 0x0018, 0x0010, 15}, /*XGI_CetLCDDes1024x768x75Data*/ /* XGI_ExtLCDDes1280x1024x75Data */ - {Panel1280x1024x75, 0x0019, 0x0001, 16}, + {Panel_1280x1024x75, 0x0019, 0x0001, 16}, /* XGI_StLCDDes1280x1024x75Data */ - {Panel1280x1024x75, 0x0019, 0x0000, 17}, + {Panel_1280x1024x75, 0x0019, 0x0000, 17}, /* XGI_CetLCDDes1280x1024x75Data */ - {Panel1280x1024x75, 0x0018, 0x0010, 18}, + {Panel_1280x1024x75, 0x0018, 0x0010, 18}, {PanelRef75Hz, 0x0008, 0x0008, 19}, /* XGI_NoScalingDesDatax75 */ {0xFF, 0x0000, 0x0000, 0} }; static struct XGI330_LCDDataTablStruct xgifb_epllcd_crt1[] = { - {Panel1024x768, 0x0018, 0x0000, 0}, /* XGI_LVDSCRT11024x768_1 */ - {Panel1024x768, 0x0018, 0x0010, 1}, /* XGI_LVDSCRT11024x768_2 */ - {Panel1280x1024, 0x0018, 0x0000, 2}, /* XGI_LVDSCRT11280x1024_1 */ - {Panel1280x1024, 0x0018, 0x0010, 3}, /* XGI_LVDSCRT11280x1024_2 */ - {Panel1400x1050, 0x0018, 0x0000, 4}, /* XGI_LVDSCRT11400x1050_1 */ - {Panel1400x1050, 0x0018, 0x0010, 5}, /* XGI_LVDSCRT11400x1050_2 */ - {Panel1600x1200, 0x0018, 0x0000, 6}, /* XGI_LVDSCRT11600x1200_1 */ - {Panel1024x768x75, 0x0018, 0x0000, 7}, /* XGI_LVDSCRT11024x768_1x75 */ - {Panel1024x768x75, 0x0018, 0x0010, 8}, /* XGI_LVDSCRT11024x768_2x75 */ - {Panel1280x1024x75, 0x0018, 0x0000, 9}, /*XGI_LVDSCRT11280x1024_1x75*/ - {Panel1280x1024x75, 0x0018, 0x0010, 10},/*XGI_LVDSCRT11280x1024_2x75*/ + {Panel_1024x768, 0x0018, 0x0000, 0}, /* XGI_LVDSCRT11024x768_1 */ + {Panel_1024x768, 0x0018, 0x0010, 1}, /* XGI_LVDSCRT11024x768_2 */ + {Panel_1280x1024, 0x0018, 0x0000, 2}, /* XGI_LVDSCRT11280x1024_1 */ + {Panel_1280x1024, 0x0018, 0x0010, 3}, /* XGI_LVDSCRT11280x1024_2 */ + {Panel_1400x1050, 0x0018, 0x0000, 4}, /* XGI_LVDSCRT11400x1050_1 */ + {Panel_1400x1050, 0x0018, 0x0010, 5}, /* XGI_LVDSCRT11400x1050_2 */ + {Panel_1600x1200, 0x0018, 0x0000, 6}, /* XGI_LVDSCRT11600x1200_1 */ + {Panel_1024x768x75, 0x0018, 0x0000, 7}, /* XGI_LVDSCRT11024x768_1x75 */ + {Panel_1024x768x75, 0x0018, 0x0010, 8}, /* XGI_LVDSCRT11024x768_2x75 */ + {Panel_1280x1024x75, 0x0018, 0x0000, 9}, /*XGI_LVDSCRT11280x1024_1x75*/ + {Panel_1280x1024x75, 0x0018, 0x0010, 10},/*XGI_LVDSCRT11280x1024_2x75*/ {0xFF, 0x0000, 0x0000, 0} }; static struct XGI330_LCDDataTablStruct XGI_EPLLCDDataPtr[] = { - {Panel1024x768, 0x0018, 0x0000, 0}, /* XGI_LVDS1024x768Data_1 */ - {Panel1024x768, 0x0018, 0x0010, 1}, /* XGI_LVDS1024x768Data_2 */ - {Panel1280x1024, 0x0018, 0x0000, 2}, /* XGI_LVDS1280x1024Data_1 */ - {Panel1280x1024, 0x0018, 0x0010, 3}, /* XGI_LVDS1280x1024Data_2 */ - {Panel1400x1050, 0x0018, 0x0000, 4}, /* XGI_LVDS1400x1050Data_1 */ - {Panel1400x1050, 0x0018, 0x0010, 5}, /* XGI_LVDS1400x1050Data_2 */ - {Panel1600x1200, 0x0018, 0x0000, 6}, /* XGI_LVDS1600x1200Data_1 */ + {Panel_1024x768, 0x0018, 0x0000, 0}, /* XGI_LVDS1024x768Data_1 */ + {Panel_1024x768, 0x0018, 0x0010, 1}, /* XGI_LVDS1024x768Data_2 */ + {Panel_1280x1024, 0x0018, 0x0000, 2}, /* XGI_LVDS1280x1024Data_1 */ + {Panel_1280x1024, 0x0018, 0x0010, 3}, /* XGI_LVDS1280x1024Data_2 */ + {Panel_1400x1050, 0x0018, 0x0000, 4}, /* XGI_LVDS1400x1050Data_1 */ + {Panel_1400x1050, 0x0018, 0x0010, 5}, /* XGI_LVDS1400x1050Data_2 */ + {Panel_1600x1200, 0x0018, 0x0000, 6}, /* XGI_LVDS1600x1200Data_1 */ {PanelRef60Hz, 0x0008, 0x0008, 7}, /* XGI_LVDSNoScalingData */ - {Panel1024x768x75, 0x0018, 0x0000, 8}, /* XGI_LVDS1024x768Data_1x75 */ - {Panel1024x768x75, 0x0018, 0x0010, 9}, /* XGI_LVDS1024x768Data_2x75 */ - {Panel1280x1024x75, 0x0018, 0x0000, 10}, /* XGI_LVDS1280x1024Data_1x75*/ - {Panel1280x1024x75, 0x0018, 0x0010, 11}, /*XGI_LVDS1280x1024Data_2x75*/ + {Panel_1024x768x75, 0x0018, 0x0000, 8}, /* XGI_LVDS1024x768Data_1x75 */ + {Panel_1024x768x75, 0x0018, 0x0010, 9}, /* XGI_LVDS1024x768Data_2x75 */ + {Panel_1280x1024x75, 0x0018, 0x0000, 10}, /* XGI_LVDS1280x1024Data_1x75*/ + {Panel_1280x1024x75, 0x0018, 0x0010, 11}, /*XGI_LVDS1280x1024Data_2x75*/ {PanelRef75Hz, 0x0008, 0x0008, 12}, /* XGI_LVDSNoScalingDatax75 */ {0xFF, 0x0000, 0x0000, 0} }; static struct XGI330_LCDDataTablStruct XGI_EPLLCDDesDataPtr[] = { - {Panel1024x768, 0x0018, 0x0000, 0}, /* XGI_LVDS1024x768Des_1 */ - {Panel1024x768, 0x0618, 0x0410, 1}, /* XGI_LVDS1024x768Des_3 */ - {Panel1024x768, 0x0018, 0x0010, 2}, /* XGI_LVDS1024x768Des_2 */ - {Panel1280x1024, 0x0018, 0x0000, 3}, /* XGI_LVDS1280x1024Des_1 */ - {Panel1280x1024, 0x0018, 0x0010, 4}, /* XGI_LVDS1280x1024Des_2 */ - {Panel1400x1050, 0x0018, 0x0000, 5}, /* XGI_LVDS1400x1050Des_1 */ - {Panel1400x1050, 0x0018, 0x0010, 6}, /* XGI_LVDS1400x1050Des_2 */ - {Panel1600x1200, 0x0018, 0x0000, 7}, /* XGI_LVDS1600x1200Des_1 */ + {Panel_1024x768, 0x0018, 0x0000, 0}, /* XGI_LVDS1024x768Des_1 */ + {Panel_1024x768, 0x0618, 0x0410, 1}, /* XGI_LVDS1024x768Des_3 */ + {Panel_1024x768, 0x0018, 0x0010, 2}, /* XGI_LVDS1024x768Des_2 */ + {Panel_1280x1024, 0x0018, 0x0000, 3}, /* XGI_LVDS1280x1024Des_1 */ + {Panel_1280x1024, 0x0018, 0x0010, 4}, /* XGI_LVDS1280x1024Des_2 */ + {Panel_1400x1050, 0x0018, 0x0000, 5}, /* XGI_LVDS1400x1050Des_1 */ + {Panel_1400x1050, 0x0018, 0x0010, 6}, /* XGI_LVDS1400x1050Des_2 */ + {Panel_1600x1200, 0x0018, 0x0000, 7}, /* XGI_LVDS1600x1200Des_1 */ {PanelRef60Hz, 0x0008, 0x0008, 8}, /* XGI_LVDSNoScalingDesData */ - {Panel1024x768x75, 0x0018, 0x0000, 9}, /* XGI_LVDS1024x768Des_1x75 */ - {Panel1024x768x75, 0x0618, 0x0410, 10}, /* XGI_LVDS1024x768Des_3x75 */ - {Panel1024x768x75, 0x0018, 0x0010, 11}, /* XGI_LVDS1024x768Des_2x75 */ - {Panel1280x1024x75, 0x0018, 0x0000, 12}, /* XGI_LVDS1280x1024Des_1x75 */ - {Panel1280x1024x75, 0x0018, 0x0010, 13}, /* XGI_LVDS1280x1024Des_2x75 */ + {Panel_1024x768x75, 0x0018, 0x0000, 9}, /* XGI_LVDS1024x768Des_1x75 */ + {Panel_1024x768x75, 0x0618, 0x0410, 10}, /* XGI_LVDS1024x768Des_3x75 */ + {Panel_1024x768x75, 0x0018, 0x0010, 11}, /* XGI_LVDS1024x768Des_2x75 */ + {Panel_1280x1024x75, 0x0018, 0x0000, 12}, /* XGI_LVDS1280x1024Des_1x75 */ + {Panel_1280x1024x75, 0x0018, 0x0010, 13}, /* XGI_LVDS1280x1024Des_2x75 */ {PanelRef75Hz, 0x0008, 0x0008, 14}, /* XGI_LVDSNoScalingDesDatax75 */ {0xFF, 0x0000, 0x0000, 0} }; static struct XGI330_LCDDataTablStruct XGI_EPLCHLCDRegPtr[] = { - {Panel1024x768, 0x0000, 0x0000, 0}, /* XGI_CH7017LV1024x768 */ - {Panel1400x1050, 0x0000, 0x0000, 1}, /* XGI_CH7017LV1400x1050 */ + {Panel_1024x768, 0x0000, 0x0000, 0}, /* XGI_CH7017LV1024x768 */ + {Panel_1400x1050, 0x0000, 0x0000, 1}, /* XGI_CH7017LV1400x1050 */ {0xFF, 0x0000, 0x0000, 0} }; @@ -2501,30 +2501,30 @@ static unsigned short LCDLenList[] = { /* Dual link only */ static struct XGI330_LCDCapStruct XGI_LCDDLCapList[] = { /* LCDCap1024x768 */ - {Panel1024x768, DefaultLCDCap, 0, 0x012, 0x88, 0x06, VCLK65, + {Panel_1024x768, DefaultLCDCap, 0, 0x012, 0x88, 0x06, VCLK65, 0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00, 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10}, /* LCDCap1280x1024 */ - {Panel1280x1024, LCDDualLink+DefaultLCDCap, StLCDBToA, + {Panel_1280x1024, LCDDualLink+DefaultLCDCap, StLCDBToA, 0x012, 0x70, 0x03, VCLK108_2, 0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00, 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, /* LCDCap1400x1050 */ - {Panel1400x1050, LCDDualLink+DefaultLCDCap, StLCDBToA, + {Panel_1400x1050, LCDDualLink+DefaultLCDCap, StLCDBToA, 0x012, 0x70, 0x03, VCLK108_2, 0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00, 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, /* LCDCap1600x1200 */ - {Panel1600x1200, LCDDualLink+DefaultLCDCap, LCDToFull, + {Panel_1600x1200, LCDDualLink+DefaultLCDCap, LCDToFull, 0x012, 0xC0, 0x03, VCLK162, 0x43, 0x22, 0x70, 0x24, 0x02, 0x14, 0x0A, 0x02, 0x00, 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, /* LCDCap1024x768x75 */ - {Panel1024x768x75, DefaultLCDCap, 0, 0x012, 0x60, 0, VCLK78_75, + {Panel_1024x768x75, DefaultLCDCap, 0, 0x012, 0x60, 0, VCLK78_75, 0x2B, 0x61, 0x2B, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00, 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10}, /* LCDCap1280x1024x75 */ - {Panel1280x1024x75, LCDDualLink+DefaultLCDCap, StLCDBToA, + {Panel_1280x1024x75, LCDDualLink+DefaultLCDCap, StLCDBToA, 0x012, 0x90, 0x03, VCLK135_5, 0x54, 0x42, 0x4A, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00, 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, @@ -2536,30 +2536,30 @@ static struct XGI330_LCDCapStruct XGI_LCDDLCapList[] = { static struct XGI330_LCDCapStruct XGI_LCDCapList[] = { /* LCDCap1024x768 */ - {Panel1024x768, DefaultLCDCap, 0, 0x012, 0x88, 0x06, VCLK65, + {Panel_1024x768, DefaultLCDCap, 0, 0x012, 0x88, 0x06, VCLK65, 0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00, 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10}, /* LCDCap1280x1024 */ - {Panel1280x1024, DefaultLCDCap, StLCDBToA, + {Panel_1280x1024, DefaultLCDCap, StLCDBToA, 0x012, 0x70, 0x03, VCLK108_2, 0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00, 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, /* LCDCap1400x1050 */ - {Panel1400x1050, DefaultLCDCap, StLCDBToA, + {Panel_1400x1050, DefaultLCDCap, StLCDBToA, 0x012, 0x70, 0x03, VCLK108_2, 0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00, 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, /* LCDCap1600x1200 */ - {Panel1600x1200, DefaultLCDCap, LCDToFull, + {Panel_1600x1200, DefaultLCDCap, LCDToFull, 0x012, 0xC0, 0x03, VCLK162, 0x5A, 0x23, 0x5A, 0x23, 0x02, 0x14, 0x0A, 0x02, 0x00, 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, /* LCDCap1024x768x75 */ - {Panel1024x768x75, DefaultLCDCap, 0, 0x012, 0x60, 0, VCLK78_75, + {Panel_1024x768x75, DefaultLCDCap, 0, 0x012, 0x60, 0, VCLK78_75, 0x2B, 0x61, 0x2B, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00, 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10}, /* LCDCap1280x1024x75 */ - {Panel1280x1024x75, DefaultLCDCap, StLCDBToA, + {Panel_1280x1024x75, DefaultLCDCap, StLCDBToA, 0x012, 0x90, 0x03, VCLK135_5, 0x54, 0x42, 0x4A, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00, 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, -- cgit v0.10.2 From 599801f9266178ebca7f22996b9e6e00f0e69056 Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Thu, 9 Feb 2012 21:11:45 +0100 Subject: staging/xgifb: Rename Set* defines and remove duplicated defines This patch renames the Set* defines and their usage to the naming convention of the sis initdef.h and removes the now duplicated defines. Renames: SetCRT2ToHiVisionTV -> SetCRT2ToHiVision SetCRT2ToYPbPr -> SetCRT2ToYPbPr525750 SetNTSCJ -> TVSetNTSCJ SetPALMTV -> TVSetPALM SetPALNTV -> TVSetPALN SetPALTV -> TVSetPAL SetYPbPrMode1080i -> TVSetHiVision SetYPbPrMode525i -> TVSetYPbPr525i SetYPbPrMode525p -> TVSetYPbPr525p SetYPbPrMode750p -> TVSetYPbPr750p Signed-off-by: Peter Huewe Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/xgifb/vb_def.h b/drivers/staging/xgifb/vb_def.h index 9b2937c..c368322 100644 --- a/drivers/staging/xgifb/vb_def.h +++ b/drivers/staging/xgifb/vb_def.h @@ -131,11 +131,9 @@ #define SetCRT2ToSCART 0x0010 #define SetCRT2ToLCD 0x0020 #define SetCRT2ToRAMDAC 0x0040 -#define SetCRT2ToHiVisionTV 0x0080 #define SetCRT2ToLCDA 0x0100 #define SetInSlaveMode 0x0200 #define SetNotSimuMode 0x0400 -#define SetCRT2ToYPbPr 0x0800 #define LoadDACFlag 0x1000 #define DisableCRT2Display 0x2000 #define DriverMode 0x4000 @@ -150,14 +148,6 @@ #define EnableChA 0x8000 #define SetNTSCTV 0x0000 /* TV Info */ -#define SetPALTV 0x0001 -#define SetNTSCJ 0x0002 -#define SetPALMTV 0x0004 -#define SetPALNTV 0x0008 -#define SetYPbPrMode525i 0x0020 -#define SetYPbPrMode525p 0x0040 -#define SetYPbPrMode750p 0x0080 -#define SetYPbPrMode1080i 0x0100 #define SetTVLowResolution 0x0400 #define TVSimuMode 0x0800 #define RPLLDIV2XO 0x1000 diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c index a53a097..4c54568 100644 --- a/drivers/staging/xgifb/vb_init.c +++ b/drivers/staging/xgifb/vb_init.c @@ -1268,7 +1268,7 @@ static void XGINew_SetModeScratch(struct xgi_hw_device_info *HwDeviceExtension, if (pVBInfo->IF_DEF_HiVision == 1) { if ((temp >> 8) & ActiveHiTV) - tempcl |= SetCRT2ToHiVisionTV; + tempcl |= SetCRT2ToHiVision; } if (pVBInfo->IF_DEF_YPbPr == 1) { @@ -1287,7 +1287,7 @@ static void XGINew_SetModeScratch(struct xgi_hw_device_info *HwDeviceExtension, if (pVBInfo->IF_DEF_HiVision == 1) { if ((temp >> 8) & ActiveHiTV) - tempcl |= SetCRT2ToHiVisionTV; + tempcl |= SetCRT2ToHiVision; } if (pVBInfo->IF_DEF_YPbPr == 1) { diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index 25c647b..ea142e9 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -372,7 +372,7 @@ static unsigned char XGI_AjustCRT2Rate(unsigned short ModeNo, } } - if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) { /* for HiTV */ + if (pVBInfo->VBInfo & SetCRT2ToHiVision) { /* for HiTV */ if ((pVBInfo->VBType & VB_XGI301LV) && (pVBInfo->VBExtInfo == VB_YPbPr1080i)) { tempax |= SupportYPbPr; @@ -406,8 +406,8 @@ static unsigned char XGI_AjustCRT2Rate(unsigned short ModeNo, if (pVBInfo->VBInfo & (SetCRT2ToAVIDEO | SetCRT2ToSVIDEO | SetCRT2ToSCART | - SetCRT2ToYPbPr | - SetCRT2ToHiVisionTV)) { + SetCRT2ToYPbPr525750 | + SetCRT2ToHiVision)) { tempax |= SupportTV; if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B @@ -416,7 +416,7 @@ static unsigned char XGI_AjustCRT2Rate(unsigned short ModeNo, tempax |= SupportTV1024; } - if (!(pVBInfo->VBInfo & SetPALTV)) { + if (!(pVBInfo->VBInfo & TVSetPAL)) { if (modeflag & NoSupportSimuTV) { if (pVBInfo->VBInfo & SetInSlaveMode) { @@ -1271,7 +1271,7 @@ static unsigned short XGI_GetVCLK2Ptr(unsigned short ModeNo, VCLKIndex = LCDXlat2VCLK[CRT2Index]; else VCLKIndex = LCDXlat1VCLK[CRT2Index]; - } else if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) { + } else if (pVBInfo->VBInfo & SetCRT2ToHiVision) { if (pVBInfo->SetFlag & RPLLDIV2XO) { VCLKIndex = HiTVVCLKDIV2; VCLKIndex += 25; @@ -2844,7 +2844,7 @@ static unsigned char XGI_GetVCLKPtr(unsigned short RefreshRateTableIndex, VB_XGI301LV | VB_XGI302LV | VB_XGI301C)) { - if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) { + if (pVBInfo->VBInfo & SetCRT2ToHiVision) { tempal = HiTVVCLKDIV2; if (!(pVBInfo->TVInfo & RPLLDIV2XO)) tempal = HiTVVCLK; @@ -2857,12 +2857,12 @@ static unsigned char XGI_GetVCLKPtr(unsigned short RefreshRateTableIndex, return tempal; } - if (pVBInfo->TVInfo & SetYPbPrMode750p) { + if (pVBInfo->TVInfo & TVSetYPbPr750p) { tempal = YPbPr750pVCLK; return tempal; } - if (pVBInfo->TVInfo & SetYPbPrMode525p) { + if (pVBInfo->TVInfo & TVSetYPbPr525p) { tempal = YPbPr525pVCLK; return tempal; } @@ -2987,12 +2987,12 @@ static void XGI_UpdateModeInfo(struct xgi_hw_device_info *HwDeviceExtension, if (temp & 0x02) tempch |= ActiveSCART; - if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) { + if (pVBInfo->VBInfo & SetCRT2ToHiVision) { if (temp & 0x01) tempch |= ActiveHiTV; } - if (pVBInfo->VBInfo & SetCRT2ToYPbPr) { + if (pVBInfo->VBInfo & SetCRT2ToYPbPr525750) { temp = xgifb_reg_get( pVBInfo->Part2Port, 0x4d); @@ -3090,7 +3090,7 @@ static void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex, push = push << 8; tempax = temp << 8; tempbx = tempbx | tempax; - temp = (SetCRT2ToDualEdge | SetCRT2ToYPbPr | SetCRT2ToLCDA + temp = (SetCRT2ToDualEdge | SetCRT2ToYPbPr525750 | SetCRT2ToLCDA | SetInSlaveMode | DisableCRT2Display); temp = 0xFFFF ^ temp; tempbx &= temp; @@ -3134,13 +3134,13 @@ static void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex, pVBInfo->P3d4, 0x35); temp &= YPbPrMode; - tempbx |= SetCRT2ToHiVisionTV; + tempbx |= SetCRT2ToHiVision; if (temp != YPbPrMode1080i) { tempbx &= - (~SetCRT2ToHiVisionTV); + (~SetCRT2ToHiVision); tempbx |= - SetCRT2ToYPbPr; + SetCRT2ToYPbPr525750; } } } @@ -3195,7 +3195,7 @@ static void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex, SetCRT2ToRAMDAC | SwitchToCRT2 | SetSimuScanMode); - tempbx &= (0x00FF | (~SetCRT2ToYPbPr)); + tempbx &= (0x00FF | (~SetCRT2ToYPbPr525750)); } } else { tempbx &= (~(SetCRT2ToRAMDAC | @@ -3210,7 +3210,7 @@ static void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex, SetCRT2ToLCD | SwitchToCRT2 | SetSimuScanMode); - tempbx &= (0x00FF | (~SetCRT2ToYPbPr)); + tempbx &= (0x00FF | (~SetCRT2ToYPbPr525750)); } } @@ -3219,20 +3219,20 @@ static void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex, SetCRT2ToSCART | SwitchToCRT2 | SetSimuScanMode); - tempbx &= (0x00FF | (~SetCRT2ToYPbPr)); + tempbx &= (0x00FF | (~SetCRT2ToYPbPr525750)); } if (pVBInfo->IF_DEF_YPbPr == 1) { - if (tempbx & SetCRT2ToYPbPr) + if (tempbx & SetCRT2ToYPbPr525750) tempbx &= (0xFF00 | SwitchToCRT2 | SetSimuScanMode); } if (pVBInfo->IF_DEF_HiVision == 1) { - if (tempbx & SetCRT2ToHiVisionTV) + if (tempbx & SetCRT2ToHiVision) tempbx &= (0xFF00 | - SetCRT2ToHiVisionTV | + SetCRT2ToHiVision | SwitchToCRT2 | SetSimuScanMode); } @@ -3291,43 +3291,43 @@ static void XGI_GetTVInfo(unsigned short ModeNo, unsigned short ModeIdIndex, if (pVBInfo->VBInfo & SetCRT2ToTV) { temp = xgifb_reg_get(pVBInfo->P3d4, 0x35); tempbx = temp; - if (tempbx & SetPALTV) { + if (tempbx & TVSetPAL) { tempbx &= (SetCHTVOverScan | - SetPALMTV | - SetPALNTV | - SetPALTV); - if (tempbx & SetPALMTV) + TVSetPALM | + TVSetPALN | + TVSetPAL); + if (tempbx & TVSetPALM) /* set to NTSC if PAL-M */ - tempbx &= ~SetPALTV; + tempbx &= ~TVSetPAL; } else tempbx &= (SetCHTVOverScan | - SetNTSCJ | - SetPALTV); + TVSetNTSCJ | + TVSetPAL); } if (pVBInfo->IF_DEF_LVDS == 0) { if (pVBInfo->VBInfo & SetCRT2ToSCART) - tempbx |= SetPALTV; + tempbx |= TVSetPAL; } if (pVBInfo->IF_DEF_YPbPr == 1) { - if (pVBInfo->VBInfo & SetCRT2ToYPbPr) { + if (pVBInfo->VBInfo & SetCRT2ToYPbPr525750) { index1 = xgifb_reg_get(pVBInfo->P3d4, 0x35); index1 &= YPbPrMode; if (index1 == YPbPrMode525i) - tempbx |= SetYPbPrMode525i; + tempbx |= TVSetYPbPr525i; if (index1 == YPbPrMode525p) - tempbx = tempbx | SetYPbPrMode525p; + tempbx = tempbx | TVSetYPbPr525p; if (index1 == YPbPrMode750p) - tempbx = tempbx | SetYPbPrMode750p; + tempbx = tempbx | TVSetYPbPr750p; } } if (pVBInfo->IF_DEF_HiVision == 1) { - if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) - tempbx = tempbx | SetYPbPrMode1080i | SetPALTV; + if (pVBInfo->VBInfo & SetCRT2ToHiVision) + tempbx = tempbx | TVSetHiVision | TVSetPAL; } if (pVBInfo->IF_DEF_LVDS == 0) { /* shampoo */ @@ -3335,19 +3335,19 @@ static void XGI_GetTVInfo(unsigned short ModeNo, unsigned short ModeIdIndex, (!(pVBInfo->VBInfo & SetNotSimuMode))) tempbx |= TVSimuMode; - if (!(tempbx & SetPALTV) && + if (!(tempbx & TVSetPAL) && (modeflag > 13) && (resinfo == 8)) /* NTSC 1024x768, */ tempbx |= NTSC1024x768; tempbx |= RPLLDIV2XO; - if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) { + if (pVBInfo->VBInfo & SetCRT2ToHiVision) { if (pVBInfo->VBInfo & SetInSlaveMode) tempbx &= (~RPLLDIV2XO); } else { if (tempbx & - (SetYPbPrMode525p | SetYPbPrMode750p)) + (TVSetYPbPr525p | TVSetYPbPr750p)) tempbx &= (~RPLLDIV2XO); else if (!(pVBInfo->VBType & (VB_XGI301B | @@ -4041,7 +4041,7 @@ static void XGI_GetCRT2Data(unsigned short ModeNo, unsigned short ModeIdIndex, pVBInfo->RVBHRS = TVPtr->RVBHRS; pVBInfo->NewFlickerMode = TVPtr->FlickerMode; - if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) { + if (pVBInfo->VBInfo & SetCRT2ToHiVision) { if (resinfo == 0x08) pVBInfo->NewFlickerMode = 0x40; else if (resinfo == 0x09) @@ -4066,16 +4066,16 @@ static void XGI_GetCRT2Data(unsigned short ModeNo, unsigned short ModeIdIndex, } } } - } else if (pVBInfo->VBInfo & SetCRT2ToYPbPr) { - if (pVBInfo->TVInfo & SetYPbPrMode750p) { + } else if (pVBInfo->VBInfo & SetCRT2ToYPbPr525750) { + if (pVBInfo->TVInfo & TVSetYPbPr750p) { tempax = YPbPrTV750pHT; /* Ext750pTVHT */ tempbx = YPbPrTV750pVT; /* Ext750pTVVT */ } - if (pVBInfo->TVInfo & SetYPbPrMode525p) { + if (pVBInfo->TVInfo & TVSetYPbPr525p) { tempax = YPbPrTV525pHT; /* Ext525pTVHT */ tempbx = YPbPrTV525pVT; /* Ext525pTVVT */ - } else if (pVBInfo->TVInfo & SetYPbPrMode525i) { + } else if (pVBInfo->TVInfo & TVSetYPbPr525i) { tempax = YPbPrTV525iHT; /* Ext525iTVHT */ tempbx = YPbPrTV525iVT; /* Ext525iTVVT */ if (pVBInfo->TVInfo & NTSC1024x768) @@ -4084,7 +4084,7 @@ static void XGI_GetCRT2Data(unsigned short ModeNo, unsigned short ModeIdIndex, } else { tempax = PALHT; tempbx = PALVT; - if (!(pVBInfo->TVInfo & SetPALTV)) { + if (!(pVBInfo->TVInfo & TVSetPAL)) { tempax = NTSCHT; tempbx = NTSCVT; if (pVBInfo->TVInfo & NTSC1024x768) @@ -4455,7 +4455,7 @@ static void XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex, | VB_XGI302LV | VB_XGI301C))) temp += 2; - if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) { + if (pVBInfo->VBInfo & SetCRT2ToHiVision) { if (pVBInfo->VBType & VB_XGI301LV) { if (pVBInfo->VBExtInfo == VB_YPbPr1080i) { if (resinfo == 7) @@ -4487,7 +4487,7 @@ static void XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex, tempax = (tempax / tempcx) - 5; tempcx = tempax; /* 20030401 0x07 horizontal Retrace Start */ - if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) { + if (pVBInfo->VBInfo & SetCRT2ToHiVision) { temp = (tempbx & 0x00FF) - 1; if (!(modeflag & HalfDCLK)) { temp -= 6; @@ -4669,19 +4669,19 @@ static void XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex, tempbx += tempax; } - if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) { + if (pVBInfo->VBInfo & SetCRT2ToHiVision) { if (pVBInfo->VBType & VB_XGI301LV) { - if (pVBInfo->TVInfo & SetYPbPrMode1080i) { + if (pVBInfo->TVInfo & TVSetHiVision) { tempbx -= 10; } else { if (pVBInfo->TVInfo & TVSimuMode) { - if (pVBInfo->TVInfo & SetPALTV) { + if (pVBInfo->TVInfo & TVSetPAL) { if (pVBInfo->VBType & VB_XGI301LV) { if (!(pVBInfo->TVInfo & - (SetYPbPrMode525p | - SetYPbPrMode750p | - SetYPbPrMode1080i))) + (TVSetYPbPr525p | + TVSetYPbPr750p | + TVSetHiVision))) tempbx += 40; } else { tempbx += 40; @@ -4694,12 +4694,12 @@ static void XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex, } } else { if (pVBInfo->TVInfo & TVSimuMode) { - if (pVBInfo->TVInfo & SetPALTV) { + if (pVBInfo->TVInfo & TVSetPAL) { if (pVBInfo->VBType & VB_XGI301LV) { if (!(pVBInfo->TVInfo & - (SetYPbPrMode525p | - SetYPbPrMode750p | - SetYPbPrMode1080i))) + (TVSetYPbPr525p | + TVSetYPbPr750p | + TVSetHiVision))) tempbx += 40; } else { tempbx += 40; @@ -4713,7 +4713,7 @@ static void XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex, tempax += tempbx; push1 = tempax; /* push ax */ - if ((pVBInfo->TVInfo & SetPALTV)) { + if ((pVBInfo->TVInfo & TVSetPAL)) { if (tempbx <= 513) { if (tempax >= 513) tempbx = 513; @@ -4813,13 +4813,13 @@ static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, if (pVBInfo->VBInfo & SetCRT2ToSCART) tempax |= 0x0200; - if (!(pVBInfo->TVInfo & SetPALTV)) + if (!(pVBInfo->TVInfo & TVSetPAL)) tempax |= 0x1000; - if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) + if (pVBInfo->VBInfo & SetCRT2ToHiVision) tempax |= 0x0100; - if (pVBInfo->TVInfo & (SetYPbPrMode525p | SetYPbPrMode750p)) + if (pVBInfo->TVInfo & (TVSetYPbPr525p | TVSetYPbPr750p)) tempax &= 0xfe00; tempax = (tempax & 0xff00) >> 8; @@ -4827,10 +4827,10 @@ static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, xgifb_reg_set(pVBInfo->Part2Port, 0x0, tempax); TimingPoint = pVBInfo->NTSCTiming; - if (pVBInfo->TVInfo & SetPALTV) + if (pVBInfo->TVInfo & TVSetPAL) TimingPoint = pVBInfo->PALTiming; - if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) { + if (pVBInfo->VBInfo & SetCRT2ToHiVision) { TimingPoint = pVBInfo->HiTVExtTiming; if (pVBInfo->VBInfo & SetInSlaveMode) @@ -4843,14 +4843,14 @@ static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, TimingPoint = pVBInfo->HiTVTextTiming; } - if (pVBInfo->VBInfo & SetCRT2ToYPbPr) { - if (pVBInfo->TVInfo & SetYPbPrMode525i) + if (pVBInfo->VBInfo & SetCRT2ToYPbPr525750) { + if (pVBInfo->TVInfo & TVSetYPbPr525i) TimingPoint = pVBInfo->YPbPr525iTiming; - if (pVBInfo->TVInfo & SetYPbPrMode525p) + if (pVBInfo->TVInfo & TVSetYPbPr525p) TimingPoint = pVBInfo->YPbPr525pTiming; - if (pVBInfo->TVInfo & SetYPbPrMode750p) + if (pVBInfo->TVInfo & TVSetYPbPr750p) TimingPoint = pVBInfo->YPbPr750pTiming; } @@ -4868,10 +4868,10 @@ static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, temp &= 0x80; xgifb_reg_and_or(pVBInfo->Part2Port, 0x0A, 0xFF, temp); - if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) + if (pVBInfo->VBInfo & SetCRT2ToHiVision) tempax = 950; - if (pVBInfo->TVInfo & SetPALTV) + if (pVBInfo->TVInfo & TVSetPAL) tempax = 520; else tempax = 440; @@ -4888,11 +4888,11 @@ static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, | VB_XGI302LV | VB_XGI301C)) { if (pVBInfo->VBInfo & (SetCRT2ToAVIDEO | SetCRT2ToSVIDEO | SetCRT2ToSCART - | SetCRT2ToYPbPr)) { + | SetCRT2ToYPbPr525750)) { tempcx = pVBInfo->VGAHDE; if (tempcx >= 1024) { temp = 0x17; /* NTSC */ - if (pVBInfo->TVInfo & SetPALTV) + if (pVBInfo->TVInfo & TVSetPAL) temp = 0x19; /* PAL */ } } @@ -4907,11 +4907,11 @@ static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, | VB_XGI302LV | VB_XGI301C)) { if ((pVBInfo->VBInfo & (SetCRT2ToAVIDEO | SetCRT2ToSVIDEO | SetCRT2ToSCART - | SetCRT2ToYPbPr))) { + | SetCRT2ToYPbPr525750))) { tempcx = pVBInfo->VGAHDE; if (tempcx >= 1024) { temp = 0x1D; /* NTSC */ - if (pVBInfo->TVInfo & SetPALTV) + if (pVBInfo->TVInfo & TVSetPAL) temp = 0x52; /* PAL */ } } @@ -4936,7 +4936,7 @@ static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, push1 = tempcx; /* push cx */ tempcx += 7; - if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) + if (pVBInfo->VBInfo & SetCRT2ToHiVision) tempcx -= 4; temp = tempcx & 0x00FF; @@ -4954,7 +4954,7 @@ static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, tempbx = push2; tempbx = tempbx + 8; - if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) { + if (pVBInfo->VBInfo & SetCRT2ToHiVision) { tempbx = tempbx - 4; tempcx = tempbx; } @@ -4970,7 +4970,7 @@ static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, xgifb_reg_and_or(pVBInfo->Part2Port, 0x28, 0x0F, temp); tempcx += 8; - if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) + if (pVBInfo->VBInfo & SetCRT2ToHiVision) tempcx -= 4; temp = tempcx & 0xFF; @@ -5007,7 +5007,7 @@ static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, if (pVBInfo->VBType & (VB_XGI301LV | VB_XGI302LV | VB_XGI301C)) { if (!(pVBInfo->TVInfo & - (SetYPbPrMode525p | SetYPbPrMode750p))) + (TVSetYPbPr525p | TVSetYPbPr750p))) tempbx = tempbx >> 1; } else tempbx = tempbx >> 1; @@ -5016,9 +5016,9 @@ static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, tempbx -= 2; temp = tempbx & 0x00FF; - if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) { + if (pVBInfo->VBInfo & SetCRT2ToHiVision) { if (pVBInfo->VBType & VB_XGI301LV) { - if (pVBInfo->TVInfo & SetYPbPrMode1080i) { + if (pVBInfo->TVInfo & TVSetHiVision) { if (pVBInfo->VBInfo & SetInSlaveMode) { if (ModeNo == 0x2f) temp += 1; @@ -5037,9 +5037,9 @@ static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, temp = (tempcx & 0xFF00) >> 8; temp |= ((tempbx & 0xFF00) >> 8) << 6; - if (!(pVBInfo->VBInfo & SetCRT2ToHiVisionTV)) { + if (!(pVBInfo->VBInfo & SetCRT2ToHiVision)) { if (pVBInfo->VBType & VB_XGI301LV) { - if (pVBInfo->TVInfo & SetYPbPrMode1080i) { + if (pVBInfo->TVInfo & TVSetHiVision) { temp |= 0x10; if (!(pVBInfo->VBInfo & SetCRT2ToSVIDEO)) @@ -5060,8 +5060,8 @@ static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, tempcx = tempbx - 2; if (pVBInfo->VBInfo & SetCRT2ToTV) { - if (!(pVBInfo->TVInfo & (SetYPbPrMode525p - | SetYPbPrMode750p))) + if (!(pVBInfo->TVInfo & (TVSetYPbPr525p + | TVSetYPbPr750p))) tempbx = tempbx >> 1; } @@ -5161,7 +5161,7 @@ static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, temp |= 0x18; xgifb_reg_and_or(pVBInfo->Part2Port, 0x46, ~0x1F, temp); - if (pVBInfo->TVInfo & SetPALTV) { + if (pVBInfo->TVInfo & TVSetPAL) { tempbx = 0x0382; tempcx = 0x007e; } else { @@ -5178,13 +5178,13 @@ static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, temp = temp << 2; temp |= ((tempbx & 0xFF00) >> 8) & 0x03; - if (pVBInfo->VBInfo & SetCRT2ToYPbPr) { + if (pVBInfo->VBInfo & SetCRT2ToYPbPr525750) { temp |= 0x10; - if (pVBInfo->TVInfo & SetYPbPrMode525p) + if (pVBInfo->TVInfo & TVSetYPbPr525p) temp |= 0x20; - if (pVBInfo->TVInfo & SetYPbPrMode750p) + if (pVBInfo->TVInfo & TVSetYPbPr750p) temp |= 0x60; } @@ -5192,7 +5192,7 @@ static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, temp = xgifb_reg_get(pVBInfo->Part2Port, 0x43); /* 301b change */ xgifb_reg_set(pVBInfo->Part2Port, 0x43, (unsigned short) (temp - 3)); - if (!(pVBInfo->TVInfo & (SetYPbPrMode525p | SetYPbPrMode750p))) { + if (!(pVBInfo->TVInfo & (TVSetYPbPr525p | TVSetYPbPr750p))) { if (pVBInfo->TVInfo & NTSC1024x768) { TimingPoint = XGI_NTSC1024AdjTime; for (i = 0x1c, j = 0; i <= 0x30; i++, j++) { @@ -5205,12 +5205,12 @@ static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, /* [ycchen] 01/14/03 Modify for 301C PALM Support */ if (pVBInfo->VBType & VB_XGI301C) { - if (pVBInfo->TVInfo & SetPALMTV) + if (pVBInfo->TVInfo & TVSetPALM) xgifb_reg_and_or(pVBInfo->Part2Port, 0x4E, ~0x08, 0x08); /* PALM Mode */ } - if (pVBInfo->TVInfo & SetPALMTV) { + if (pVBInfo->TVInfo & TVSetPALM) { tempax = (unsigned char) xgifb_reg_get(pVBInfo->Part2Port, 0x01); tempax--; @@ -5219,7 +5219,7 @@ static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, xgifb_reg_and(pVBInfo->Part2Port, 0x00, 0xEF); } - if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) { + if (pVBInfo->VBInfo & SetCRT2ToHiVision) { if (!(pVBInfo->VBInfo & SetInSlaveMode)) xgifb_reg_set(pVBInfo->Part2Port, 0x0B, 0x00); } @@ -5473,18 +5473,18 @@ static struct XGI301C_Tap4TimingStruct *XGI_GetTap4Ptr(unsigned short tempcx, else Tap4TimingPtr = xgifb_ntsc_525_tap4_timing; /* NTSC */ - if (pVBInfo->TVInfo & SetPALTV) + if (pVBInfo->TVInfo & TVSetPAL) Tap4TimingPtr = PALTap4Timing; - if (pVBInfo->VBInfo & SetCRT2ToYPbPr) { - if ((pVBInfo->TVInfo & SetYPbPrMode525i) || - (pVBInfo->TVInfo & SetYPbPrMode525p)) + if (pVBInfo->VBInfo & SetCRT2ToYPbPr525750) { + if ((pVBInfo->TVInfo & TVSetYPbPr525i) || + (pVBInfo->TVInfo & TVSetYPbPr525p)) Tap4TimingPtr = xgifb_ntsc_525_tap4_timing; - if (pVBInfo->TVInfo & SetYPbPrMode750p) + if (pVBInfo->TVInfo & TVSetYPbPr750p) Tap4TimingPtr = YPbPr750pTap4Timing; } - if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) + if (pVBInfo->VBInfo & SetCRT2ToHiVision) Tap4TimingPtr = xgifb_tap4_timing; i = 0; @@ -5510,7 +5510,7 @@ static void XGI_SetTap4Regs(struct vb_device_info *pVBInfo) xgifb_reg_set(pVBInfo->Part2Port, i, Tap4TimingPtr->Reg[j]); if ((pVBInfo->VBInfo & SetCRT2ToTV) && - (!(pVBInfo->VBInfo & SetCRT2ToHiVisionTV))) { + (!(pVBInfo->VBInfo & SetCRT2ToHiVision))) { /* Set Vertical Scaling */ Tap4TimingPtr = XGI_GetTap4Ptr(1, pVBInfo); for (i = 0xC0, j = 0; i < 0xFF; i++, j++) @@ -5520,7 +5520,7 @@ static void XGI_SetTap4Regs(struct vb_device_info *pVBInfo) } if ((pVBInfo->VBInfo & SetCRT2ToTV) && - (!(pVBInfo->VBInfo & SetCRT2ToHiVisionTV))) + (!(pVBInfo->VBInfo & SetCRT2ToHiVision))) /* Enable V.Scaling */ xgifb_reg_and_or(pVBInfo->Part2Port, 0x4E, ~0x14, 0x04); else @@ -5543,7 +5543,7 @@ static void XGI_SetGroup3(unsigned short ModeNo, unsigned short ModeIdIndex, modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag; xgifb_reg_set(pVBInfo->Part3Port, 0x00, 0x00); - if (pVBInfo->TVInfo & SetPALTV) { + if (pVBInfo->TVInfo & TVSetPAL) { xgifb_reg_set(pVBInfo->Part3Port, 0x13, 0xFA); xgifb_reg_set(pVBInfo->Part3Port, 0x14, 0xC8); } else { @@ -5554,15 +5554,15 @@ static void XGI_SetGroup3(unsigned short ModeNo, unsigned short ModeIdIndex, if (!(pVBInfo->VBInfo & SetCRT2ToTV)) return; - if (pVBInfo->TVInfo & SetPALMTV) { + if (pVBInfo->TVInfo & TVSetPALM) { xgifb_reg_set(pVBInfo->Part3Port, 0x13, 0xFA); xgifb_reg_set(pVBInfo->Part3Port, 0x14, 0xC8); xgifb_reg_set(pVBInfo->Part3Port, 0x3D, 0xA8); } - if ((pVBInfo->VBInfo & SetCRT2ToHiVisionTV) || (pVBInfo->VBInfo - & SetCRT2ToYPbPr)) { - if (pVBInfo->TVInfo & SetYPbPrMode525i) + if ((pVBInfo->VBInfo & SetCRT2ToHiVision) || (pVBInfo->VBInfo + & SetCRT2ToYPbPr525750)) { + if (pVBInfo->TVInfo & TVSetYPbPr525i) return; tempdi = pVBInfo->HiTVGroup3Data; @@ -5572,17 +5572,17 @@ static void XGI_SetGroup3(unsigned short ModeNo, unsigned short ModeIdIndex, tempdi = pVBInfo->HiTVGroup3Text; } - if (pVBInfo->TVInfo & SetYPbPrMode525p) + if (pVBInfo->TVInfo & TVSetYPbPr525p) tempdi = pVBInfo->Ren525pGroup3; - if (pVBInfo->TVInfo & SetYPbPrMode750p) + if (pVBInfo->TVInfo & TVSetYPbPr750p) tempdi = pVBInfo->Ren750pGroup3; for (i = 0; i <= 0x3E; i++) xgifb_reg_set(pVBInfo->Part3Port, i, tempdi[i]); if (pVBInfo->VBType & VB_XGI301C) { /* Marcovision */ - if (pVBInfo->TVInfo & SetYPbPrMode525p) + if (pVBInfo->TVInfo & TVSetYPbPr525p) xgifb_reg_set(pVBInfo->Part3Port, 0x28, 0x3f); } } @@ -5637,7 +5637,7 @@ static void XGI_SetGroup4(unsigned short ModeNo, unsigned short ModeIdIndex, if (XGI_IsLCDDualLink(pVBInfo)) tempbx = tempbx >> 1; - if (tempcx & SetCRT2ToHiVisionTV) { + if (tempcx & SetCRT2ToHiVision) { temp = 0; if (tempbx <= 1024) temp = 0xA0; @@ -5656,7 +5656,7 @@ static void XGI_SetGroup4(unsigned short ModeNo, unsigned short ModeIdIndex, } } - if (pVBInfo->TVInfo & (SetYPbPrMode525p | SetYPbPrMode750p)) { + if (pVBInfo->TVInfo & (TVSetYPbPr525p | TVSetYPbPr750p)) { temp = 0x00; if (pVBInfo->VGAHDE == 1280) temp = 0x40; @@ -5667,7 +5667,7 @@ static void XGI_SetGroup4(unsigned short ModeNo, unsigned short ModeIdIndex, tempebx = pVBInfo->VDE; - if (tempcx & SetCRT2ToHiVisionTV) { + if (tempcx & SetCRT2ToHiVision) { if (!(temp & 0xE000)) tempbx = tempbx >> 1; } @@ -5735,7 +5735,7 @@ static void XGI_SetGroup4(unsigned short ModeNo, unsigned short ModeIdIndex, temp = (tempax & 0x00FF); xgifb_reg_set(pVBInfo->Part4Port, 0x1D, temp); - if (pVBInfo->VBInfo & (SetCRT2ToTV | SetCRT2ToHiVisionTV)) { + if (pVBInfo->VBInfo & (SetCRT2ToTV | SetCRT2ToHiVision)) { if (pVBInfo->VGAHDE > 800) xgifb_reg_or(pVBInfo->Part4Port, 0x1E, 0x08); @@ -5744,8 +5744,8 @@ static void XGI_SetGroup4(unsigned short ModeNo, unsigned short ModeIdIndex, if (pVBInfo->VBInfo & SetCRT2ToTV) { if (!(pVBInfo->TVInfo & (NTSC1024x768 - | SetYPbPrMode525p | SetYPbPrMode750p - | SetYPbPrMode1080i))) { + | TVSetYPbPr525p | TVSetYPbPr750p + | TVSetHiVision))) { temp |= 0x0001; if ((pVBInfo->VBInfo & SetInSlaveMode) && (!(pVBInfo->TVInfo @@ -6254,15 +6254,15 @@ static unsigned short XGI_GetTVPtrIndex(struct vb_device_info *pVBInfo) { unsigned short tempbx = 0; - if (pVBInfo->TVInfo & SetPALTV) + if (pVBInfo->TVInfo & TVSetPAL) tempbx = 2; - if (pVBInfo->TVInfo & SetYPbPrMode1080i) + if (pVBInfo->TVInfo & TVSetHiVision) tempbx = 4; - if (pVBInfo->TVInfo & SetYPbPrMode525i) + if (pVBInfo->TVInfo & TVSetYPbPr525i) tempbx = 6; - if (pVBInfo->TVInfo & SetYPbPrMode525p) + if (pVBInfo->TVInfo & TVSetYPbPr525p) tempbx = 8; - if (pVBInfo->TVInfo & SetYPbPrMode750p) + if (pVBInfo->TVInfo & TVSetYPbPr750p) tempbx = 10; if (pVBInfo->TVInfo & TVSimuMode) tempbx++; @@ -6293,18 +6293,18 @@ static void XGI_GetTVPtrIndex2(unsigned short *tempbx, unsigned char *tempcl, *tempcl = 0; *tempch = 0; - if (pVBInfo->TVInfo & SetPALTV) + if (pVBInfo->TVInfo & TVSetPAL) *tempbx = 1; - if (pVBInfo->TVInfo & SetPALMTV) + if (pVBInfo->TVInfo & TVSetPALM) *tempbx = 2; - if (pVBInfo->TVInfo & SetPALNTV) + if (pVBInfo->TVInfo & TVSetPALN) *tempbx = 3; if (pVBInfo->TVInfo & NTSC1024x768) { *tempbx = 4; - if (pVBInfo->TVInfo & SetPALMTV) + if (pVBInfo->TVInfo & TVSetPALM) *tempbx = 5; } @@ -6524,7 +6524,7 @@ static void XGI_SetAntiFlicker(unsigned short ModeNo, unsigned char tempah; - if (pVBInfo->TVInfo & (SetYPbPrMode525p | SetYPbPrMode750p)) + if (pVBInfo->TVInfo & (TVSetYPbPr525p | TVSetYPbPr750p)) return; tempbx = XGI_GetTVPtrIndex(pVBInfo); -- cgit v0.10.2 From 6896b94e2475948e78948df5a9b2a8c3a27fc6d9 Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Thu, 9 Feb 2012 21:11:46 +0100 Subject: staging/xgifb: Rename remaining sis initdef.h defines and remove duplicates This patch renames the remaining duplicate defines and their usage to the naming convention of the sis initdef.h and removes the now duplicated defines. Renames: CRT2DisplayFlag -> DisableCRT2Display ModeInfoFlag -> ModeTypeMask Support16Bpp -> Mode16Bpp Support32Bpp -> Mode32Bpp SupportHiVisionTV -> SupportHiVision SupportYPbPr -> SupportYPbPr750p SwitchToCRT2 -> SwitchCRT2 VB_XGI301 -> VB_SIS301 VB_XGI301B -> VB_SIS301B VB_XGI301LV -> VB_SIS301LV VB_XGI302B -> VB_SIS302B VB_XGI302LV -> VB_SIS302LV VB_YPbPr525p -> YPbPr525p VB_YPbPr750p -> YPbPr750p VCLK108_2 -> VCLK108_2_315 VCLK65 -> VCLK65_315 XGI_CRT2_PORT_04 -> SIS_CRT2_PORT_04 XGI_CRT2_PORT_10 -> SIS_CRT2_PORT_10 XGI_CRT2_PORT_12 -> SIS_CRT2_PORT_12 XGI_CRT2_PORT_14 -> SIS_CRT2_PORT_14 Signed-off-by: Peter Huewe Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c index fb9b5b3..21c0378 100644 --- a/drivers/staging/xgifb/XGI_main_26.c +++ b/drivers/staging/xgifb/XGI_main_26.c @@ -371,15 +371,15 @@ static void XGIRegInit(struct vb_device_info *XGI_Pr, unsigned long BaseAddr) XGI_Pr->P3c9 = BaseAddr + 0x19; XGI_Pr->P3da = BaseAddr + 0x2A; /* Digital video interface registers (LCD) */ - XGI_Pr->Part1Port = BaseAddr + XGI_CRT2_PORT_04; + XGI_Pr->Part1Port = BaseAddr + SIS_CRT2_PORT_04; /* 301 TV Encoder registers */ - XGI_Pr->Part2Port = BaseAddr + XGI_CRT2_PORT_10; + XGI_Pr->Part2Port = BaseAddr + SIS_CRT2_PORT_10; /* 301 Macrovision registers */ - XGI_Pr->Part3Port = BaseAddr + XGI_CRT2_PORT_12; + XGI_Pr->Part3Port = BaseAddr + SIS_CRT2_PORT_12; /* 301 VGA2 (and LCD) registers */ - XGI_Pr->Part4Port = BaseAddr + XGI_CRT2_PORT_14; + XGI_Pr->Part4Port = BaseAddr + SIS_CRT2_PORT_14; /* 301 palette address port registers */ - XGI_Pr->Part5Port = BaseAddr + XGI_CRT2_PORT_14 + 2; + XGI_Pr->Part5Port = BaseAddr + SIS_CRT2_PORT_14 + 2; } diff --git a/drivers/staging/xgifb/vb_def.h b/drivers/staging/xgifb/vb_def.h index c368322..12454c5 100644 --- a/drivers/staging/xgifb/vb_def.h +++ b/drivers/staging/xgifb/vb_def.h @@ -5,10 +5,6 @@ #include "../../video/sis/initdef.h" #define VB_XGI301C 0x0020 /* for 301C */ -/*end 301b*/ - -#define VB_YPbPr525p 0x01 -#define VB_YPbPr750p 0x02 #define VB_YPbPr1080i 0x03 #define LVDSCRT1Len 15 @@ -28,16 +24,10 @@ #define PanelRef60Hz 0x00 #define PanelRef75Hz 0x20 -#define CRT2DisplayFlag 0x2000 - #define YPbPr525iVCLK 0x03B #define YPbPr525iVCLK_2 0x03A #define XGI_CRT2_PORT_00 (0x00 - 0x030) -#define XGI_CRT2_PORT_04 (0x04 - 0x030) -#define XGI_CRT2_PORT_10 (0x10 - 0x30) -#define XGI_CRT2_PORT_12 (0x12 - 0x30) -#define XGI_CRT2_PORT_14 (0x14 - 0x30) #define _PanelType00 0x00 #define _PanelType01 0x08 @@ -77,15 +67,9 @@ #define VCLKLen 4 #define VGA_XGI340 0x0001 /* 340 series */ -#define VB_XGI301 0x0001 /* VB Type Info */ -#define VB_XGI301B 0x0002 /* 301 series */ -#define VB_XGI302B 0x0004 #define VB_NoLCD 0x8000 -#define VB_XGI301LV 0x0008 -#define VB_XGI302LV 0x0010 #define VB_LVDS_NS 0x0001 /* 3rd party chip */ -#define ModeInfoFlag 0x0007 #define ModeText 0x0000 #define ModeEGA 0x0002 /* 16 colors mode */ #define ModeVGA 0x0003 /* 256 colors mode */ @@ -103,19 +87,14 @@ #define DoubleScanMode 0x8000 /* -------------- Ext_InfoFlag */ -#define Support16Bpp 0x0005 -#define Support32Bpp 0x0007 - #define SupportAllCRT2 0x0078 #define SupportTV 0x0008 -#define SupportHiVisionTV 0x0010 #define SupportLCD 0x0020 #define SupportRAMDAC2 0x0040 #define NoSupportTV 0x0070 #define NoSupportHiVisionTV 0x0060 #define NoSupportLCD 0x0058 #define SupportTV1024 0x0800 /* 301btest */ -#define SupportYPbPr 0x1000 /* 301lv */ #define InterlaceMode 0x0080 #define SyncPP 0x0000 #define SyncPN 0x4000 @@ -124,7 +103,6 @@ /* -------------- SetMode Stack/Scratch */ #define SetSimuScanMode 0x0001 /* VBInfo/CR30 & CR31 */ -#define SwitchToCRT2 0x0002 #define SetCRT2ToTV 0x089C #define SetCRT2ToAVIDEO 0x0004 #define SetCRT2ToSVIDEO 0x0008 @@ -135,7 +113,6 @@ #define SetInSlaveMode 0x0200 #define SetNotSimuMode 0x0400 #define LoadDACFlag 0x1000 -#define DisableCRT2Display 0x2000 #define DriverMode 0x4000 #define SetCRT2ToDualEdge 0x8000 @@ -275,7 +252,6 @@ #define VCLK50 0x08 #define VCLK52_406 0x09 #define VCLK56_25 0x0A -#define VCLK65 0x0B #define VCLK68_179 0x0D #define VCLK72_852 0x0E #define VCLK75 0x0F @@ -284,7 +260,6 @@ #define VCLK83_95 0x13 #define VCLK86_6 0x15 #define VCLK94_5 0x16 -#define VCLK108_2 0x19 #define VCLK113_309 0x1B #define VCLK116_406 0x1C #define VCLK135_5 0x1E diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c index 4c54568..94d5c35 100644 --- a/drivers/staging/xgifb/vb_init.c +++ b/drivers/staging/xgifb/vb_init.c @@ -1299,9 +1299,9 @@ static void XGINew_SetModeScratch(struct xgi_hw_device_info *HwDeviceExtension, tempcl |= SetSimuScanMode; if ((!(temp & ActiveCRT1)) && ((temp & ActiveLCD) || (temp & ActiveTV) || (temp & ActiveCRT2))) - tempcl ^= (SetSimuScanMode | SwitchToCRT2); + tempcl ^= (SetSimuScanMode | SwitchCRT2); if ((temp & ActiveLCD) && (temp & ActiveTV)) - tempcl ^= (SetSimuScanMode | SwitchToCRT2); + tempcl ^= (SetSimuScanMode | SwitchCRT2); xgifb_reg_set(pVBInfo->P3d4, 0x30, tempcl); CR31Data = xgifb_reg_get(pVBInfo->P3d4, 0x31); @@ -1516,11 +1516,11 @@ unsigned char XGIInitNew(struct pci_dev *pdev) pVBInfo->P3c9 = pVBInfo->BaseAddr + 0x19; pVBInfo->P3da = pVBInfo->BaseAddr + 0x2A; pVBInfo->Part0Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_00; - pVBInfo->Part1Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_04; - pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10; - pVBInfo->Part3Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_12; - pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14; - pVBInfo->Part5Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 + 2; + pVBInfo->Part1Port = pVBInfo->BaseAddr + SIS_CRT2_PORT_04; + pVBInfo->Part2Port = pVBInfo->BaseAddr + SIS_CRT2_PORT_10; + pVBInfo->Part3Port = pVBInfo->BaseAddr + SIS_CRT2_PORT_12; + pVBInfo->Part4Port = pVBInfo->BaseAddr + SIS_CRT2_PORT_14; + pVBInfo->Part5Port = pVBInfo->BaseAddr + SIS_CRT2_PORT_14 + 2; printk("5"); if (HwDeviceExtension->jChipType < XG20) /* kuku 2004/06/25 */ diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index ea142e9..ab2157c 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -138,7 +138,7 @@ void InitTo330Pointer(unsigned char ChipType, struct vb_device_info *pVBInfo) pVBInfo->UpdateCRT1 = (struct XGI_XG21CRT1Struct *) XGI_UpdateCRT1Table; /* 310 customization related */ - if ((pVBInfo->VBType & VB_XGI301LV) || (pVBInfo->VBType & VB_XGI302LV)) + if ((pVBInfo->VBType & VB_SIS301LV) || (pVBInfo->VBType & VB_SIS302LV)) pVBInfo->LCDCapList = XGI_LCDDLCapList; else pVBInfo->LCDCapList = XGI_LCDCapList; @@ -373,9 +373,9 @@ static unsigned char XGI_AjustCRT2Rate(unsigned short ModeNo, } if (pVBInfo->VBInfo & SetCRT2ToHiVision) { /* for HiTV */ - if ((pVBInfo->VBType & VB_XGI301LV) && + if ((pVBInfo->VBType & VB_SIS301LV) && (pVBInfo->VBExtInfo == VB_YPbPr1080i)) { - tempax |= SupportYPbPr; + tempax |= SupportYPbPr750p; if (pVBInfo->VBInfo & SetInSlaveMode) { if (resinfo == 4) return 0; @@ -387,7 +387,7 @@ static unsigned char XGI_AjustCRT2Rate(unsigned short ModeNo, return 0; } } else { - tempax |= SupportHiVisionTV; + tempax |= SupportHiVision; if (pVBInfo->VBInfo & SetInSlaveMode) { if (resinfo == 4) return 0; @@ -410,8 +410,8 @@ static unsigned char XGI_AjustCRT2Rate(unsigned short ModeNo, SetCRT2ToHiVision)) { tempax |= SupportTV; - if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B - | VB_XGI301LV | VB_XGI302LV + if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B + | VB_SIS301LV | VB_SIS302LV | VB_XGI301C)) { tempax |= SupportTV1024; } @@ -1230,23 +1230,23 @@ static unsigned short XGI_GetVCLK2Ptr(unsigned short ModeNo, struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo) { - unsigned short LCDXlat1VCLK[4] = { VCLK65 + 2, - VCLK65 + 2, - VCLK65 + 2, - VCLK65 + 2 }; - unsigned short LCDXlat2VCLK[4] = { VCLK108_2 + 5, - VCLK108_2 + 5, - VCLK108_2 + 5, - VCLK108_2 + 5 }; + unsigned short LCDXlat1VCLK[4] = { VCLK65_315 + 2, + VCLK65_315 + 2, + VCLK65_315 + 2, + VCLK65_315 + 2 }; + unsigned short LCDXlat2VCLK[4] = { VCLK108_2_315 + 5, + VCLK108_2_315 + 5, + VCLK108_2_315 + 5, + VCLK108_2_315 + 5 }; unsigned short LVDSXlat1VCLK[4] = { VCLK40, VCLK40, VCLK40, VCLK40 }; - unsigned short LVDSXlat2VCLK[4] = { VCLK65 + 2, - VCLK65 + 2, - VCLK65 + 2, - VCLK65 + 2 }; - unsigned short LVDSXlat3VCLK[4] = { VCLK65 + 2, - VCLK65 + 2, - VCLK65 + 2, - VCLK65 + 2 }; + unsigned short LVDSXlat2VCLK[4] = { VCLK65_315 + 2, + VCLK65_315 + 2, + VCLK65_315 + 2, + VCLK65_315 + 2 }; + unsigned short LVDSXlat3VCLK[4] = { VCLK65_315 + 2, + VCLK65_315 + 2, + VCLK65_315 + 2, + VCLK65_315 + 2 }; unsigned short CRT2Index, VCLKIndex; unsigned short modeflag, resinfo; @@ -1291,11 +1291,11 @@ static unsigned short XGI_GetVCLK2Ptr(unsigned short ModeNo, } /* 301lv */ - if ((pVBInfo->VBType & VB_XGI301LV) && + if ((pVBInfo->VBType & VB_SIS301LV) && !(pVBInfo->VBExtInfo == VB_YPbPr1080i)) { - if (pVBInfo->VBExtInfo == VB_YPbPr750p) + if (pVBInfo->VBExtInfo == YPbPr750p) VCLKIndex = YPbPr750pVCLK; - else if (pVBInfo->VBExtInfo == VB_YPbPr525p) + else if (pVBInfo->VBExtInfo == YPbPr525p) VCLKIndex = YPbPr525pVCLK; else if (pVBInfo->SetFlag & RPLLDIV2XO) VCLKIndex = YPbPr525iVCLK_2; @@ -1360,8 +1360,8 @@ static void XGI_SetCRT1VCLK(unsigned short ModeNo, xgifb_reg_set(pVBInfo->P3c4, 0x2C, pVBInfo->VCLKData[index].SR2C); xgifb_reg_set(pVBInfo->P3c4, 0x2D, 0x01); - } else if ((pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV - | VB_XGI302LV | VB_XGI301C)) && (pVBInfo->VBInfo + } else if ((pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV + | VB_SIS302LV | VB_XGI301C)) && (pVBInfo->VBInfo & SetCRT2ToLCDA)) { vclkindex = XGI_GetVCLK2Ptr(ModeNo, ModeIdIndex, RefreshRateTableIndex, HwDeviceExtension, @@ -2128,30 +2128,30 @@ static void *XGI_GetLcdPtr(unsigned short BX, unsigned short ModeNo, return &XGI_CetLCDDes1024x768Data[tempal]; break; case 3: - if ((pVBInfo->VBType & VB_XGI301LV) || - (pVBInfo->VBType & VB_XGI302LV)) + if ((pVBInfo->VBType & VB_SIS301LV) || + (pVBInfo->VBType & VB_SIS302LV)) return &XGI_ExtLCDDLDes1280x1024Data[tempal]; else return &XGI_ExtLCDDes1280x1024Data[tempal]; break; case 4: - if ((pVBInfo->VBType & VB_XGI301LV) || - (pVBInfo->VBType & VB_XGI302LV)) + if ((pVBInfo->VBType & VB_SIS301LV) || + (pVBInfo->VBType & VB_SIS302LV)) return &XGI_StLCDDLDes1280x1024Data[tempal]; else return &XGI_StLCDDes1280x1024Data[tempal]; break; case 5: - if ((pVBInfo->VBType & VB_XGI301LV) || - (pVBInfo->VBType & VB_XGI302LV)) + if ((pVBInfo->VBType & VB_SIS301LV) || + (pVBInfo->VBType & VB_SIS302LV)) return &XGI_CetLCDDLDes1280x1024Data[tempal]; else return &XGI_CetLCDDes1280x1024Data[tempal]; break; case 6: case 7: - if ((pVBInfo->VBType & VB_XGI301LV) || - (pVBInfo->VBType & VB_XGI302LV)) + if ((pVBInfo->VBType & VB_SIS301LV) || + (pVBInfo->VBType & VB_SIS302LV)) return &xgifb_lcddldes_1400x1050[tempal]; else return &xgifb_lcddes_1400x1050[tempal]; @@ -2163,15 +2163,15 @@ static void *XGI_GetLcdPtr(unsigned short BX, unsigned short ModeNo, return &XGI_CetLCDDes1400x1050Data2[tempal]; break; case 10: - if ((pVBInfo->VBType & VB_XGI301LV) || - (pVBInfo->VBType & VB_XGI302LV)) + if ((pVBInfo->VBType & VB_SIS301LV) || + (pVBInfo->VBType & VB_SIS302LV)) return &XGI_ExtLCDDLDes1600x1200Data[tempal]; else return &XGI_ExtLCDDes1600x1200Data[tempal]; break; case 11: - if ((pVBInfo->VBType & VB_XGI301LV) || - (pVBInfo->VBType & VB_XGI302LV)) + if ((pVBInfo->VBType & VB_SIS301LV) || + (pVBInfo->VBType & VB_SIS302LV)) return &XGI_StLCDDLDes1600x1200Data[tempal]; else return &XGI_StLCDDes1600x1200Data[tempal]; @@ -2188,15 +2188,15 @@ static void *XGI_GetLcdPtr(unsigned short BX, unsigned short ModeNo, break; case 16: case 17: - if ((pVBInfo->VBType & VB_XGI301LV) || - (pVBInfo->VBType & VB_XGI302LV)) + if ((pVBInfo->VBType & VB_SIS301LV) || + (pVBInfo->VBType & VB_SIS302LV)) return &xgifb_lcddldes_1280x1024x75[tempal]; else return &xgifb_lcddes_1280x1024x75[tempal]; break; case 18: - if ((pVBInfo->VBType & VB_XGI301LV) || - (pVBInfo->VBType & VB_XGI302LV)) + if ((pVBInfo->VBType & VB_SIS301LV) || + (pVBInfo->VBType & VB_SIS302LV)) return &XGI_CetLCDDLDes1280x1024x75Data[tempal]; else return &XGI_CetLCDDes1280x1024x75Data[tempal]; @@ -2839,10 +2839,10 @@ static unsigned char XGI_GetVCLKPtr(unsigned short RefreshRateTableIndex, /* {TV} */ if (pVBInfo->VBType & - (VB_XGI301B | - VB_XGI302B | - VB_XGI301LV | - VB_XGI302LV | + (VB_SIS301B | + VB_SIS302B | + VB_SIS301LV | + VB_SIS302LV | VB_XGI301C)) { if (pVBInfo->VBInfo & SetCRT2ToHiVision) { tempal = HiTVVCLKDIV2; @@ -2898,8 +2898,8 @@ static unsigned char XGI_GetVCLKPtr(unsigned short RefreshRateTableIndex, static void XGI_GetVCLKLen(unsigned char tempal, unsigned char *di_0, unsigned char *di_1, struct vb_device_info *pVBInfo) { - if (pVBInfo->VBType & (VB_XGI301 | VB_XGI301B | VB_XGI302B - | VB_XGI301LV | VB_XGI302LV | VB_XGI301C)) { + if (pVBInfo->VBType & (VB_SIS301 | VB_SIS301B | VB_SIS302B + | VB_SIS301LV | VB_SIS302LV | VB_XGI301C)) { if ((!(pVBInfo->VBInfo & SetCRT2ToLCDA)) && (pVBInfo->SetFlag & ProgrammingCRT2)) { *di_0 = (unsigned char) XGI_VBVCLKData[tempal].SR2B; @@ -2942,8 +2942,8 @@ static void XGI_UpdateModeInfo(struct xgi_hw_device_info *HwDeviceExtension, { unsigned short tempcl, tempch, temp, tempbl, tempax; - if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV - | VB_XGI302LV | VB_XGI301C)) { + if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV + | VB_SIS302LV | VB_XGI301C)) { tempcl = 0; tempch = 0; temp = xgifb_reg_get(pVBInfo->P3c4, 0x01); @@ -3029,19 +3029,19 @@ void XGI_GetVBType(struct vb_device_info *pVBInfo) unsigned short flag, tempbx, tempah; if (pVBInfo->IF_DEF_LVDS == 0) { - tempbx = VB_XGI302B; + tempbx = VB_SIS302B; flag = xgifb_reg_get(pVBInfo->Part4Port, 0x00); if (flag != 0x02) { - tempbx = VB_XGI301; + tempbx = VB_SIS301; flag = xgifb_reg_get(pVBInfo->Part4Port, 0x01); if (flag >= 0xB0) { - tempbx = VB_XGI301B; + tempbx = VB_SIS301B; if (flag >= 0xC0) { tempbx = VB_XGI301C; if (flag >= 0xD0) { - tempbx = VB_XGI301LV; + tempbx = VB_SIS301LV; if (flag >= 0xE0) { - tempbx = VB_XGI302LV; + tempbx = VB_SIS302LV; tempah = xgifb_reg_get( pVBInfo->Part4Port, 0x39); @@ -3052,7 +3052,7 @@ void XGI_GetVBType(struct vb_device_info *pVBInfo) } } - if (tempbx & (VB_XGI301B | VB_XGI302B)) { + if (tempbx & (VB_SIS301B | VB_SIS302B)) { flag = xgifb_reg_get( pVBInfo->Part4Port, 0x23); @@ -3078,7 +3078,7 @@ static void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex, modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag; pVBInfo->SetFlag = 0; - pVBInfo->ModeType = modeflag & ModeInfoFlag; + pVBInfo->ModeType = modeflag & ModeTypeMask; tempbx = 0; if (pVBInfo->VBType & 0xFFFF) { @@ -3103,9 +3103,9 @@ static void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex, (HwDeviceExtension->jChipType >= XG40)) { if (pVBInfo->IF_DEF_LVDS == 0) { if (pVBInfo->VBType & - (VB_XGI302B | - VB_XGI301LV | - VB_XGI302LV | + (VB_SIS302B | + VB_SIS301LV | + VB_SIS302LV | VB_XGI301C)) { if (temp & EnableDualEdge) { tempbx |= @@ -3123,8 +3123,8 @@ static void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex, if (pVBInfo->IF_DEF_YPbPr == 1) { /* [Billy] 07/05/04 */ if (((pVBInfo->IF_DEF_LVDS == 0) && - ((pVBInfo->VBType & VB_XGI301LV) || - (pVBInfo->VBType & VB_XGI302LV) || + ((pVBInfo->VBType & VB_SIS301LV) || + (pVBInfo->VBType & VB_SIS302LV) || (pVBInfo->VBType & VB_XGI301C)))) { if (temp & SetYPbPr) { if (pVBInfo->IF_DEF_HiVision == 1) { @@ -3176,24 +3176,24 @@ static void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex, if (tempbx & SetSimuScanMode) tempbx &= (~(SetCRT2ToLCD | SetCRT2ToRAMDAC | - SwitchToCRT2)); + SwitchCRT2)); else tempbx &= (~(SetCRT2ToLCD | SetCRT2ToRAMDAC | SetCRT2ToTV | - SwitchToCRT2)); + SwitchCRT2)); } } } /* shampoo add */ /* for driver abnormal */ - if (!(tempbx & (SwitchToCRT2 | SetSimuScanMode))) { + if (!(tempbx & (SwitchCRT2 | SetSimuScanMode))) { if (pVBInfo->IF_DEF_CRT2Monitor == 1) { if (tempbx & SetCRT2ToRAMDAC) { tempbx &= (0xFF00 | SetCRT2ToRAMDAC | - SwitchToCRT2 | + SwitchCRT2 | SetSimuScanMode); tempbx &= (0x00FF | (~SetCRT2ToYPbPr525750)); } @@ -3208,7 +3208,7 @@ static void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex, if (tempbx & SetCRT2ToLCD) { tempbx &= (0xFF00 | SetCRT2ToLCD | - SwitchToCRT2 | + SwitchCRT2 | SetSimuScanMode); tempbx &= (0x00FF | (~SetCRT2ToYPbPr525750)); } @@ -3217,7 +3217,7 @@ static void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex, if (tempbx & SetCRT2ToSCART) { tempbx &= (0xFF00 | SetCRT2ToSCART | - SwitchToCRT2 | + SwitchCRT2 | SetSimuScanMode); tempbx &= (0x00FF | (~SetCRT2ToYPbPr525750)); } @@ -3225,7 +3225,7 @@ static void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex, if (pVBInfo->IF_DEF_YPbPr == 1) { if (tempbx & SetCRT2ToYPbPr525750) tempbx &= (0xFF00 | - SwitchToCRT2 | + SwitchCRT2 | SetSimuScanMode); } @@ -3233,12 +3233,12 @@ static void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex, if (tempbx & SetCRT2ToHiVision) tempbx &= (0xFF00 | SetCRT2ToHiVision | - SwitchToCRT2 | + SwitchCRT2 | SetSimuScanMode); } if (tempax & DisableCRT2Display) { /* Set Display Device Info */ - if (!(tempbx & (SwitchToCRT2 | SetSimuScanMode))) + if (!(tempbx & (SwitchCRT2 | SetSimuScanMode))) tempbx = DisableCRT2Display; } @@ -3350,10 +3350,10 @@ static void XGI_GetTVInfo(unsigned short ModeNo, unsigned short ModeIdIndex, (TVSetYPbPr525p | TVSetYPbPr750p)) tempbx &= (~RPLLDIV2XO); else if (!(pVBInfo->VBType & - (VB_XGI301B | - VB_XGI302B | - VB_XGI301LV | - VB_XGI302LV | + (VB_SIS301B | + VB_SIS302B | + VB_SIS301LV | + VB_SIS302LV | VB_XGI301C))) { if (tempbx & TVSimuMode) tempbx &= (~RPLLDIV2XO); @@ -3427,7 +3427,7 @@ static unsigned char XGI_GetLCDInfo(unsigned short ModeNo, tempax = pVBInfo->LCDCapList[LCDIdIndex].LCD_Capability; if (pVBInfo->IF_DEF_LVDS == 0) { /* shampoo */ - if (((pVBInfo->VBType & VB_XGI302LV) || (pVBInfo->VBType + if (((pVBInfo->VBType & VB_SIS302LV) || (pVBInfo->VBType & VB_XGI301C)) && (tempax & LCDDualLink)) { tempbx |= SetLCDDualLink; } @@ -4109,7 +4109,7 @@ static void XGI_SetCRT2VCLK(unsigned short ModeNo, unsigned short ModeIdIndex, XGI_GetVCLKLen(tempal, &di_0, &di_1, pVBInfo); XGI_GetLCDVCLKPtr(&di_0, &di_1, pVBInfo); - if (pVBInfo->VBType & VB_XGI301) { /* shampoo 0129 */ + if (pVBInfo->VBType & VB_SIS301) { /* shampoo 0129 */ /* 301 */ xgifb_reg_set(pVBInfo->Part4Port, 0x0A, 0x10); xgifb_reg_set(pVBInfo->Part4Port, 0x0B, di_1); @@ -4139,7 +4139,7 @@ static unsigned short XGI_GetColorDepth(unsigned short ModeNo, else modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag; - index = (modeflag & ModeInfoFlag) - ModeEGA; + index = (modeflag & ModeTypeMask) - ModeEGA; if (index < 0) index = 0; @@ -4435,7 +4435,7 @@ static void XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex, xgifb_reg_set(pVBInfo->Part1Port, 0x03, temp); tempcx = 0x08; - if (pVBInfo->VBType & (VB_XGI301LV | VB_XGI302LV | VB_XGI301C)) + if (pVBInfo->VBType & (VB_SIS301LV | VB_SIS302LV | VB_XGI301C)) modeflag |= Charx8Dot; tempax = pVBInfo->VGAHDE; /* 0x04 Horizontal Display End */ @@ -4451,12 +4451,12 @@ static void XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex, temp = (tempbx & 0xFF00) >> 8; if (pVBInfo->VBInfo & SetCRT2ToTV) { - if (!(pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV - | VB_XGI302LV | VB_XGI301C))) + if (!(pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV + | VB_SIS302LV | VB_XGI301C))) temp += 2; if (pVBInfo->VBInfo & SetCRT2ToHiVision) { - if (pVBInfo->VBType & VB_XGI301LV) { + if (pVBInfo->VBType & VB_SIS301LV) { if (pVBInfo->VBExtInfo == VB_YPbPr1080i) { if (resinfo == 7) temp -= 2; @@ -4670,14 +4670,14 @@ static void XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex, } if (pVBInfo->VBInfo & SetCRT2ToHiVision) { - if (pVBInfo->VBType & VB_XGI301LV) { + if (pVBInfo->VBType & VB_SIS301LV) { if (pVBInfo->TVInfo & TVSetHiVision) { tempbx -= 10; } else { if (pVBInfo->TVInfo & TVSimuMode) { if (pVBInfo->TVInfo & TVSetPAL) { if (pVBInfo->VBType & - VB_XGI301LV) { + VB_SIS301LV) { if (!(pVBInfo->TVInfo & (TVSetYPbPr525p | TVSetYPbPr750p | @@ -4695,7 +4695,7 @@ static void XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex, } else { if (pVBInfo->TVInfo & TVSimuMode) { if (pVBInfo->TVInfo & TVSetPAL) { - if (pVBInfo->VBType & VB_XGI301LV) { + if (pVBInfo->VBType & VB_SIS301LV) { if (!(pVBInfo->TVInfo & (TVSetYPbPr525p | TVSetYPbPr750p | @@ -4761,7 +4761,7 @@ static void XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex, temp = (temp >> 1) & 0x09; - if (pVBInfo->VBType & (VB_XGI301LV | VB_XGI302LV | VB_XGI301C)) + if (pVBInfo->VBType & (VB_SIS301LV | VB_SIS302LV | VB_XGI301C)) temp |= 0x01; xgifb_reg_set(pVBInfo->Part1Port, 0x16, temp); /* 0x16 SR01 */ @@ -4884,8 +4884,8 @@ static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, temp = (tempax & 0xFF00) >> 8; temp += (unsigned short) TimingPoint[0]; - if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV - | VB_XGI302LV | VB_XGI301C)) { + if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV + | VB_SIS302LV | VB_XGI301C)) { if (pVBInfo->VBInfo & (SetCRT2ToAVIDEO | SetCRT2ToSVIDEO | SetCRT2ToSCART | SetCRT2ToYPbPr525750)) { @@ -4903,8 +4903,8 @@ static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, temp = (tempax & 0xFF00) >> 8; temp += TimingPoint[1]; - if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV - | VB_XGI302LV | VB_XGI301C)) { + if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV + | VB_SIS302LV | VB_XGI301C)) { if ((pVBInfo->VBInfo & (SetCRT2ToAVIDEO | SetCRT2ToSVIDEO | SetCRT2ToSCART | SetCRT2ToYPbPr525750))) { @@ -5005,7 +5005,7 @@ static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, if (pVBInfo->VBInfo & SetCRT2ToTV) { if (pVBInfo->VBType & - (VB_XGI301LV | VB_XGI302LV | VB_XGI301C)) { + (VB_SIS301LV | VB_SIS302LV | VB_XGI301C)) { if (!(pVBInfo->TVInfo & (TVSetYPbPr525p | TVSetYPbPr750p))) tempbx = tempbx >> 1; @@ -5017,7 +5017,7 @@ static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, temp = tempbx & 0x00FF; if (pVBInfo->VBInfo & SetCRT2ToHiVision) { - if (pVBInfo->VBType & VB_XGI301LV) { + if (pVBInfo->VBType & VB_SIS301LV) { if (pVBInfo->TVInfo & TVSetHiVision) { if (pVBInfo->VBInfo & SetInSlaveMode) { if (ModeNo == 0x2f) @@ -5038,7 +5038,7 @@ static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, temp |= ((tempbx & 0xFF00) >> 8) << 6; if (!(pVBInfo->VBInfo & SetCRT2ToHiVision)) { - if (pVBInfo->VBType & VB_XGI301LV) { + if (pVBInfo->VBType & VB_SIS301LV) { if (pVBInfo->TVInfo & TVSetHiVision) { temp |= 0x10; @@ -5054,8 +5054,8 @@ static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, xgifb_reg_set(pVBInfo->Part2Port, 0x30, temp); - if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV - | VB_XGI302LV | VB_XGI301C)) { /* TV gatingno */ + if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV + | VB_SIS302LV | VB_XGI301C)) { /* TV gatingno */ tempbx = pVBInfo->VDE; tempcx = tempbx - 2; @@ -5065,7 +5065,7 @@ static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, tempbx = tempbx >> 1; } - if (pVBInfo->VBType & (VB_XGI302LV | VB_XGI301C)) { + if (pVBInfo->VBType & (VB_SIS302LV | VB_XGI301C)) { temp = 0; if (tempcx & 0x0400) temp |= 0x20; @@ -5118,8 +5118,8 @@ static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, /* 301b */ tempecx = 8 * 1024; - if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV - | VB_XGI302LV | VB_XGI301C)) { + if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV + | VB_SIS302LV | VB_XGI301C)) { tempecx = tempecx * 8; } @@ -5133,8 +5133,8 @@ static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, tempax = (unsigned short) tempeax; /* 301b */ - if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV - | VB_XGI302LV | VB_XGI301C)) { + if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV + | VB_SIS302LV | VB_XGI301C)) { tempcx = ((tempax & 0xFF00) >> 5) >> 8; } /* end 301b */ @@ -5375,7 +5375,7 @@ static void XGI_SetLCDRegs(unsigned short ModeNo, unsigned short ModeIdIndex, tempcx = tempcx >> 1; } - if (pVBInfo->VBType & VB_XGI302LV) + if (pVBInfo->VBType & VB_SIS302LV) tempbx += 1; if (pVBInfo->VBType & VB_XGI301C) /* tap4 */ @@ -5405,7 +5405,7 @@ static void XGI_SetLCDRegs(unsigned short ModeNo, unsigned short ModeIdIndex, tempcx = tempcx >> 1; } - if (pVBInfo->VBType & VB_XGI302LV) + if (pVBInfo->VBType & VB_SIS302LV) tempbx += 1; tempcx += tempbx; @@ -5424,8 +5424,8 @@ static void XGI_SetLCDRegs(unsigned short ModeNo, unsigned short ModeIdIndex, if (!(pVBInfo->LCDInfo & LCDVESATiming)) { if (pVBInfo->VGAVDE == 525) { - if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B - | VB_XGI301LV | VB_XGI302LV + if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B + | VB_SIS301LV | VB_SIS302LV | VB_XGI301C)) { temp = 0xC6; } else @@ -5436,8 +5436,8 @@ static void XGI_SetLCDRegs(unsigned short ModeNo, unsigned short ModeIdIndex, } if (pVBInfo->VGAVDE == 420) { - if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B - | VB_XGI301LV | VB_XGI302LV + if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B + | VB_SIS301LV | VB_SIS302LV | VB_XGI301C)) { temp = 0x4F; } else @@ -5705,8 +5705,8 @@ static void XGI_SetGroup4(unsigned short ModeNo, unsigned short ModeIdIndex, xgifb_reg_set(pVBInfo->Part4Port, 0x19, temp); /* 301b */ - if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV - | VB_XGI302LV | VB_XGI301C)) { + if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV + | VB_SIS302LV | VB_XGI301C)) { temp = 0x0028; xgifb_reg_set(pVBInfo->Part4Port, 0x1C, temp); tempax = pVBInfo->VGAHDE; @@ -5785,7 +5785,7 @@ static void XGI_SetGroup5(unsigned short ModeNo, unsigned short ModeIdIndex, Pdata = pVBInfo->Part5Port + 1; if (pVBInfo->ModeType == ModeVGA) { if (!(pVBInfo->VBInfo & (SetInSlaveMode | LoadDACFlag - | CRT2DisplayFlag))) { + | DisableCRT2Display))) { XGINew_EnableCRT2(pVBInfo); } } @@ -6074,7 +6074,7 @@ static unsigned char XGI_IsLCDON(struct vb_device_info *pVBInfo) tempax = pVBInfo->VBInfo; if (tempax & SetCRT2ToDualEdge) return 0; - else if (tempax & (DisableCRT2Display | SwitchToCRT2 | SetSimuScanMode)) + else if (tempax & (DisableCRT2Display | SwitchCRT2 | SetSimuScanMode)) return 1; return 0; @@ -6140,8 +6140,8 @@ static void XGI_DisableBridge(struct xgifb_video_info *xgifb_info, { unsigned short tempah = 0; - if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV - | VB_XGI302LV | VB_XGI301C)) { + if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV + | VB_SIS302LV | VB_XGI301C)) { tempah = 0x3F; if (!(pVBInfo->VBInfo & (DisableCRT2Display | SetSimuScanMode))) { @@ -6166,7 +6166,7 @@ static void XGI_DisableBridge(struct xgifb_video_info *xgifb_info, /* disable part4_1f */ xgifb_reg_and(pVBInfo->Part4Port, 0x1F, tempah); - if (pVBInfo->VBType & (VB_XGI302LV | VB_XGI301C)) { + if (pVBInfo->VBType & (VB_SIS302LV | VB_XGI301C)) { if (((pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA))) || (XGI_DisableChISLCD(pVBInfo)) || (XGI_IsLCDON(pVBInfo))) @@ -6308,8 +6308,8 @@ static void XGI_GetTVPtrIndex2(unsigned short *tempbx, unsigned char *tempcl, *tempbx = 5; } - if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV - | VB_XGI302LV | VB_XGI301C)) { + if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV + | VB_SIS302LV | VB_XGI301C)) { if ((!(pVBInfo->VBInfo & SetInSlaveMode)) || (pVBInfo->TVInfo & TVSimuMode)) { *tempbx += 8; @@ -6317,8 +6317,8 @@ static void XGI_GetTVPtrIndex2(unsigned short *tempbx, unsigned char *tempcl, } } - if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV - | VB_XGI302LV | VB_XGI301C)) + if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV + | VB_SIS302LV | VB_XGI301C)) (*tempch)++; } @@ -6328,8 +6328,8 @@ static void XGI_SetDelayComp(struct vb_device_info *pVBInfo) unsigned char tempah, tempbl, tempbh; - if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV - | VB_XGI302LV | VB_XGI301C)) { + if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV + | VB_SIS302LV | VB_XGI301C)) { if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA | SetCRT2ToTV | SetCRT2ToRAMDAC)) { tempbl = 0; @@ -6338,8 +6338,8 @@ static void XGI_SetDelayComp(struct vb_device_info *pVBInfo) index = XGI_GetTVPtrIndex(pVBInfo); /* Get TV Delay */ tempbl = pVBInfo->XGI_TVDelayList[index]; - if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B - | VB_XGI301LV | VB_XGI302LV + if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B + | VB_SIS301LV | VB_SIS302LV | VB_XGI301C)) tempbl = pVBInfo->XGI_TVDelayList2[index]; @@ -6475,13 +6475,13 @@ static void XGI_SetLCDCap(struct vb_device_info *pVBInfo) tempcx = pVBInfo->LCDCapList[XGI_GetLCDCapPtr(pVBInfo)].LCD_Capability; if (pVBInfo->VBType & - (VB_XGI301B | - VB_XGI302B | - VB_XGI301LV | - VB_XGI302LV | + (VB_SIS301B | + VB_SIS302B | + VB_SIS301LV | + VB_SIS302LV | VB_XGI301C)) { /* 301LV/302LV only */ if (pVBInfo->VBType & - (VB_XGI301LV | VB_XGI302LV | VB_XGI301C)) { + (VB_SIS301LV | VB_SIS302LV | VB_XGI301C)) { /* Set 301LV Capability */ xgifb_reg_set(pVBInfo->Part4Port, 0x24, (unsigned char) (tempcx & 0x1F)); @@ -6493,14 +6493,14 @@ static void XGI_SetLCDCap(struct vb_device_info *pVBInfo) | EnablePLLSPLOW)) >> 8)); } - if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV - | VB_XGI302LV | VB_XGI301C)) { + if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV + | VB_SIS302LV | VB_XGI301C)) { if (pVBInfo->VBInfo & SetCRT2ToLCD) XGI_SetLCDCap_B(tempcx, pVBInfo); else if (pVBInfo->VBInfo & SetCRT2ToLCDA) XGI_SetLCDCap_A(tempcx, pVBInfo); - if (pVBInfo->VBType & (VB_XGI302LV | VB_XGI301C)) { + if (pVBInfo->VBType & (VB_SIS302LV | VB_XGI301C)) { if (tempcx & EnableSpectrum) SetSpectrum(pVBInfo); } @@ -6648,8 +6648,8 @@ static void XGI_SetYFilter(unsigned short ModeNo, unsigned short ModeIdIndex, xgifb_reg_set(pVBInfo->Part2Port, 0x38, filterPtr[index++]); } - if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV - | VB_XGI302LV | VB_XGI301C)) { + if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV + | VB_SIS302LV | VB_XGI301C)) { xgifb_reg_set(pVBInfo->Part2Port, 0x48, filterPtr[index++]); xgifb_reg_set(pVBInfo->Part2Port, 0x49, filterPtr[index++]); xgifb_reg_set(pVBInfo->Part2Port, 0x4A, filterPtr[index++]); @@ -6676,7 +6676,7 @@ static void XGI_OEM310Setting(unsigned short ModeNo, XGI_SetYFilter(ModeNo, ModeIdIndex, pVBInfo); XGI_SetAntiFlicker(ModeNo, ModeIdIndex, pVBInfo); - if (pVBInfo->VBType & VB_XGI301) + if (pVBInfo->VBType & VB_SIS301) XGI_SetEdgeEnhance(ModeNo, ModeIdIndex, pVBInfo); } } @@ -6817,8 +6817,8 @@ static void XGI_SetCRT2ModeRegs(unsigned short ModeNo, xgifb_reg_set(pVBInfo->Part4Port, 0x0C, tempah); } - if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV - | VB_XGI302LV | VB_XGI301C)) { + if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV + | VB_SIS302LV | VB_XGI301C)) { tempah = 0; tempbl = 0xfb; @@ -6857,7 +6857,7 @@ static void XGI_SetCRT2ModeRegs(unsigned short ModeNo, xgifb_reg_and_or(pVBInfo->Part4Port, 0x23, tempbl, tempah); - if (pVBInfo->VBType & (VB_XGI302LV | VB_XGI301C)) { + if (pVBInfo->VBType & (VB_SIS302LV | VB_XGI301C)) { if (pVBInfo->LCDInfo & SetLCDDualLink) { xgifb_reg_or(pVBInfo->Part4Port, 0x27, 0x20); xgifb_reg_or(pVBInfo->Part4Port, 0x34, 0x10); @@ -6939,8 +6939,8 @@ unsigned short XGI_GetRatePtrCRT2(struct xgi_hw_device_info *pXGIHWDE, if (pVBInfo->SetFlag & ProgrammingCRT2) { if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { if (pVBInfo->IF_DEF_LVDS == 0) { - if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B - | VB_XGI301LV | VB_XGI302LV + if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B + | VB_SIS301LV | VB_SIS302LV | VB_XGI301C)) /* 301b */ temp = LCDARefreshIndex[ @@ -6983,7 +6983,7 @@ unsigned short XGI_GetRatePtrCRT2(struct xgi_hw_device_info *pXGIHWDE, break; temp = pVBInfo->RefIndex[RefreshRateTableIndex + i]. Ext_InfoFlag; - temp &= ModeInfoFlag; + temp &= ModeTypeMask; if (temp < pVBInfo->ModeType) break; i++; @@ -7163,8 +7163,8 @@ static void XGI_EnableBridge(struct xgifb_video_info *xgifb_info, { unsigned short tempah; - if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV - | VB_XGI302LV | VB_XGI301C)) { + if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV + | VB_SIS302LV | VB_XGI301C)) { if (!(pVBInfo->SetFlag & DisableChA)) { if (pVBInfo->SetFlag & EnableChA) { /* Power on */ @@ -7207,7 +7207,7 @@ static void XGI_EnableBridge(struct xgifb_video_info *xgifb_info, || (!(pVBInfo->VBInfo & DisableCRT2Display))) { xgifb_reg_and_or(pVBInfo->Part2Port, 0x00, ~0xE0, 0x20); /* shampoo 0129 */ - if (pVBInfo->VBType & (VB_XGI302LV | VB_XGI301C)) { + if (pVBInfo->VBType & (VB_SIS302LV | VB_XGI301C)) { if (!XGI_DisableChISLCD(pVBInfo)) { if (XGI_EnableChISLCD(pVBInfo) || (pVBInfo->VBInfo & @@ -7311,8 +7311,8 @@ static void XGI_SetCRT1Group(struct xgifb_video_info *xgifb_info, pVBInfo->SetFlag &= temp; pVBInfo->SelectCRT2Rate = 0; - if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV - | VB_XGI302LV | VB_XGI301C)) { + if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV + | VB_SIS302LV | VB_XGI301C)) { if (pVBInfo->VBInfo & (SetSimuScanMode | SetCRT2ToLCDA | SetInSlaveMode)) { pVBInfo->SetFlag |= ProgrammingCRT2; @@ -7415,11 +7415,11 @@ unsigned char XGISetModeNew(struct xgifb_video_info *xgifb_info, pVBInfo->P3c9 = pVBInfo->BaseAddr + 0x19; pVBInfo->P3da = pVBInfo->BaseAddr + 0x2A; pVBInfo->Part0Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_00; - pVBInfo->Part1Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_04; - pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10; - pVBInfo->Part3Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_12; - pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14; - pVBInfo->Part5Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 + 2; + pVBInfo->Part1Port = pVBInfo->BaseAddr + SIS_CRT2_PORT_04; + pVBInfo->Part2Port = pVBInfo->BaseAddr + SIS_CRT2_PORT_10; + pVBInfo->Part3Port = pVBInfo->BaseAddr + SIS_CRT2_PORT_12; + pVBInfo->Part4Port = pVBInfo->BaseAddr + SIS_CRT2_PORT_14; + pVBInfo->Part5Port = pVBInfo->BaseAddr + SIS_CRT2_PORT_14 + 2; /* for x86 Linux, XG21 LVDS */ if (HwDeviceExtension->jChipType == XG21) { @@ -7461,7 +7461,7 @@ unsigned char XGISetModeNew(struct xgifb_video_info *xgifb_info, HwDeviceExtension, pVBInfo); } } else { - if (!(pVBInfo->VBInfo & SwitchToCRT2)) { + if (!(pVBInfo->VBInfo & SwitchCRT2)) { XGI_SetCRT1Group(xgifb_info, HwDeviceExtension, ModeNo, ModeIdIndex, pVBInfo); @@ -7473,7 +7473,7 @@ unsigned char XGISetModeNew(struct xgifb_video_info *xgifb_info, } } - if (pVBInfo->VBInfo & (SetSimuScanMode | SwitchToCRT2)) { + if (pVBInfo->VBInfo & (SetSimuScanMode | SwitchCRT2)) { switch (HwDeviceExtension->ujVBChipID) { case VB_CHIP_301: XGI_SetCRT2Group301(ModeNo, HwDeviceExtension, @@ -7504,10 +7504,10 @@ unsigned char XGISetModeNew(struct xgifb_video_info *xgifb_info, if (ModeNo <= 0x13) { pVBInfo->ModeType = pVBInfo->SModeIDTable[ModeIdIndex]. - St_ModeFlag & ModeInfoFlag; + St_ModeFlag & ModeTypeMask; } else { pVBInfo->ModeType = pVBInfo->EModeIDTable[ModeIdIndex]. - Ext_ModeFlag & ModeInfoFlag; + Ext_ModeFlag & ModeTypeMask; } pVBInfo->SetFlag = 0; diff --git a/drivers/staging/xgifb/vb_table.h b/drivers/staging/xgifb/vb_table.h index c587d41..4f803b6 100644 --- a/drivers/staging/xgifb/vb_table.h +++ b/drivers/staging/xgifb/vb_table.h @@ -2501,17 +2501,17 @@ static unsigned short LCDLenList[] = { /* Dual link only */ static struct XGI330_LCDCapStruct XGI_LCDDLCapList[] = { /* LCDCap1024x768 */ - {Panel_1024x768, DefaultLCDCap, 0, 0x012, 0x88, 0x06, VCLK65, + {Panel_1024x768, DefaultLCDCap, 0, 0x012, 0x88, 0x06, VCLK65_315, 0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00, 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10}, /* LCDCap1280x1024 */ {Panel_1280x1024, LCDDualLink+DefaultLCDCap, StLCDBToA, - 0x012, 0x70, 0x03, VCLK108_2, + 0x012, 0x70, 0x03, VCLK108_2_315, 0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00, 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, /* LCDCap1400x1050 */ {Panel_1400x1050, LCDDualLink+DefaultLCDCap, StLCDBToA, - 0x012, 0x70, 0x03, VCLK108_2, + 0x012, 0x70, 0x03, VCLK108_2_315, 0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00, 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, /* LCDCap1600x1200 */ @@ -2529,24 +2529,24 @@ static struct XGI330_LCDCapStruct XGI_LCDDLCapList[] = { 0x54, 0x42, 0x4A, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00, 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, /* LCDCapDefault */ - {0xFF, DefaultLCDCap, 0, 0x012, 0x88, 0x06, VCLK65, + {0xFF, DefaultLCDCap, 0, 0x012, 0x88, 0x06, VCLK65_315, 0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00, 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10} }; static struct XGI330_LCDCapStruct XGI_LCDCapList[] = { /* LCDCap1024x768 */ - {Panel_1024x768, DefaultLCDCap, 0, 0x012, 0x88, 0x06, VCLK65, + {Panel_1024x768, DefaultLCDCap, 0, 0x012, 0x88, 0x06, VCLK65_315, 0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00, 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10}, /* LCDCap1280x1024 */ {Panel_1280x1024, DefaultLCDCap, StLCDBToA, - 0x012, 0x70, 0x03, VCLK108_2, + 0x012, 0x70, 0x03, VCLK108_2_315, 0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00, 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, /* LCDCap1400x1050 */ {Panel_1400x1050, DefaultLCDCap, StLCDBToA, - 0x012, 0x70, 0x03, VCLK108_2, + 0x012, 0x70, 0x03, VCLK108_2_315, 0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00, 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, /* LCDCap1600x1200 */ @@ -2564,162 +2564,162 @@ static struct XGI330_LCDCapStruct XGI_LCDCapList[] = { 0x54, 0x42, 0x4A, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00, 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, /* LCDCapDefault */ - {0xFF, DefaultLCDCap, 0, 0x012, 0x88, 0x06, VCLK65, + {0xFF, DefaultLCDCap, 0, 0x012, 0x88, 0x06, VCLK65_315, 0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00, 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10} }; static struct XGI_Ext2Struct XGI330_RefIndex[] = { - {Support32Bpp + SupportAllCRT2 + SyncPN, RES320x200, VCLK25_175, + {Mode32Bpp + SupportAllCRT2 + SyncPN, RES320x200, VCLK25_175, 0x00, 0x10, 0x59, 320, 200},/* 00 */ - {Support32Bpp + SupportAllCRT2 + SyncPN, RES320x200, VCLK25_175, + {Mode32Bpp + SupportAllCRT2 + SyncPN, RES320x200, VCLK25_175, 0x00, 0x10, 0x00, 320, 400},/* 01 */ - {Support32Bpp + SupportAllCRT2 + SyncNN, RES320x240, VCLK25_175, + {Mode32Bpp + SupportAllCRT2 + SyncNN, RES320x240, VCLK25_175, 0x04, 0x20, 0x50, 320, 240},/* 02 */ - {Support32Bpp + SupportAllCRT2 + SyncPP, RES400x300, VCLK40, + {Mode32Bpp + SupportAllCRT2 + SyncPP, RES400x300, VCLK40, 0x05, 0x32, 0x51, 400, 300},/* 03 */ - {Support32Bpp + NoSupportTV + SyncNN + SupportTV1024, RES512x384, - VCLK65, 0x06, 0x43, 0x52, 512, 384},/* 04 */ - {Support32Bpp + SupportAllCRT2 + SyncPN, RES640x400, VCLK25_175, + {Mode32Bpp + NoSupportTV + SyncNN + SupportTV1024, RES512x384, + VCLK65_315, 0x06, 0x43, 0x52, 512, 384},/* 04 */ + {Mode32Bpp + SupportAllCRT2 + SyncPN, RES640x400, VCLK25_175, 0x00, 0x14, 0x2f, 640, 400},/* 05 */ - {Support32Bpp + SupportAllCRT2 + SyncNN, RES640x480x60, VCLK25_175, + {Mode32Bpp + SupportAllCRT2 + SyncNN, RES640x480x60, VCLK25_175, 0x04, 0x24, 0x2e, 640, 480},/* 06 640x480x60Hz (LCD 640x480x60z) */ - {Support32Bpp + NoSupportHiVisionTV + SyncNN, RES640x480x72, VCLK31_5, + {Mode32Bpp + NoSupportHiVisionTV + SyncNN, RES640x480x72, VCLK31_5, 0x04, 0x24, 0x2e, 640, 480},/* 07 640x480x72Hz (LCD 640x480x70Hz) */ - {Support32Bpp + NoSupportHiVisionTV + SyncNN, RES640x480x75, VCLK31_5, + {Mode32Bpp + NoSupportHiVisionTV + SyncNN, RES640x480x75, VCLK31_5, 0x47, 0x24, 0x2e, 640, 480},/* 08 640x480x75Hz (LCD 640x480x75Hz) */ - {Support32Bpp + SupportRAMDAC2 + SyncNN, RES640x480x85, VCLK36, + {Mode32Bpp + SupportRAMDAC2 + SyncNN, RES640x480x85, VCLK36, 0x8A, 0x24, 0x2e, 640, 480},/* 09 640x480x85Hz */ - {Support32Bpp + SupportRAMDAC2 + SyncPN, RES640x480x100, VCLK43_163, + {Mode32Bpp + SupportRAMDAC2 + SyncPN, RES640x480x100, VCLK43_163, 0x00, 0x24, 0x2e, 640, 480},/* 0a 640x480x100Hz */ - {Support32Bpp + SupportRAMDAC2 + SyncPN, RES640x480x120, VCLK52_406, + {Mode32Bpp + SupportRAMDAC2 + SyncPN, RES640x480x120, VCLK52_406, 0x00, 0x24, 0x2e, 640, 480},/* 0b 640x480x120Hz */ - {Support32Bpp + SupportRAMDAC2 + SyncPN, RES640x480x160, VCLK72_852, + {Mode32Bpp + SupportRAMDAC2 + SyncPN, RES640x480x160, VCLK72_852, 0x00, 0x24, 0x2e, 640, 480},/* 0c 640x480x160Hz */ - {Support32Bpp + SupportRAMDAC2 + SyncNN, RES640x480x200, VCLK86_6, + {Mode32Bpp + SupportRAMDAC2 + SyncNN, RES640x480x200, VCLK86_6, 0x00, 0x24, 0x2e, 640, 480},/* 0d 640x480x200Hz */ - {Support32Bpp + NoSupportLCD + SyncPP, RES800x600x56, VCLK36, + {Mode32Bpp + NoSupportLCD + SyncPP, RES800x600x56, VCLK36, 0x05, 0x36, 0x6a, 800, 600},/* 0e 800x600x56Hz */ - {Support32Bpp + NoSupportTV + SyncPP, RES800x600x60, VCLK40, + {Mode32Bpp + NoSupportTV + SyncPP, RES800x600x60, VCLK40, 0x05, 0x36, 0x6a, 800, 600},/* 0f 800x600x60Hz (LCD 800x600x60Hz) */ - {Support32Bpp + NoSupportHiVisionTV + SyncPP, RES800x600x72, VCLK50, + {Mode32Bpp + NoSupportHiVisionTV + SyncPP, RES800x600x72, VCLK50, 0x48, 0x36, 0x6a, 800, 600},/* 10 800x600x72Hz (LCD 800x600x70Hz) */ - {Support32Bpp + NoSupportHiVisionTV + SyncPP, RES800x600x75, VCLK49_5, + {Mode32Bpp + NoSupportHiVisionTV + SyncPP, RES800x600x75, VCLK49_5, 0x8B, 0x36, 0x6a, 800, 600},/* 11 800x600x75Hz (LCD 800x600x75Hz) */ - {Support32Bpp + SupportRAMDAC2 + SyncPP, RES800x600x85, VCLK56_25, + {Mode32Bpp + SupportRAMDAC2 + SyncPP, RES800x600x85, VCLK56_25, 0x00, 0x36, 0x6a, 800, 600},/* 12 800x600x85Hz */ - {Support32Bpp + SupportRAMDAC2 + SyncPN, RES800x600x100, VCLK68_179, + {Mode32Bpp + SupportRAMDAC2 + SyncPN, RES800x600x100, VCLK68_179, 0x00, 0x36, 0x6a, 800, 600},/* 13 800x600x100Hz */ - {Support32Bpp + SupportRAMDAC2 + SyncPN, RES800x600x120, VCLK83_95, + {Mode32Bpp + SupportRAMDAC2 + SyncPN, RES800x600x120, VCLK83_95, 0x00, 0x36, 0x6a, 800, 600},/* 14 800x600x120Hz */ - {Support32Bpp + SupportRAMDAC2 + SyncPN, RES800x600x160, VCLK116_406, + {Mode32Bpp + SupportRAMDAC2 + SyncPN, RES800x600x160, VCLK116_406, 0x00, 0x36, 0x6a, 800, 600},/* 15 800x600x160Hz */ - {Support32Bpp + InterlaceMode + SyncPP, RES1024x768x43, VCLK44_9, + {Mode32Bpp + InterlaceMode + SyncPP, RES1024x768x43, VCLK44_9, 0x00, 0x47, 0x37, 1024, 768},/* 16 1024x768x43Hz */ /* 17 1024x768x60Hz (LCD 1024x768x60Hz) */ - {Support32Bpp + NoSupportTV + SyncNN + SupportTV1024, RES1024x768x60, - VCLK65, 0x06, 0x47, 0x37, 1024, 768}, - {Support32Bpp + NoSupportHiVisionTV + SyncNN, RES1024x768x70, VCLK75, + {Mode32Bpp + NoSupportTV + SyncNN + SupportTV1024, RES1024x768x60, + VCLK65_315, 0x06, 0x47, 0x37, 1024, 768}, + {Mode32Bpp + NoSupportHiVisionTV + SyncNN, RES1024x768x70, VCLK75, 0x49, 0x47, 0x37, 1024, 768},/* 18 1024x768x70Hz (LCD 1024x768x70Hz) */ - {Support32Bpp + NoSupportHiVisionTV + SyncPP, RES1024x768x75, VCLK78_75, + {Mode32Bpp + NoSupportHiVisionTV + SyncPP, RES1024x768x75, VCLK78_75, 0x00, 0x47, 0x37, 1024, 768},/* 19 1024x768x75Hz (LCD 1024x768x75Hz) */ - {Support32Bpp + SupportRAMDAC2 + SyncPP, RES1024x768x85, VCLK94_5, + {Mode32Bpp + SupportRAMDAC2 + SyncPP, RES1024x768x85, VCLK94_5, 0x8C, 0x47, 0x37, 1024, 768},/* 1a 1024x768x85Hz */ - {Support32Bpp + SupportRAMDAC2 + SyncPN, RES1024x768x100, VCLK113_309, + {Mode32Bpp + SupportRAMDAC2 + SyncPN, RES1024x768x100, VCLK113_309, 0x00, 0x47, 0x37, 1024, 768},/* 1b 1024x768x100Hz */ - {Support32Bpp + SupportRAMDAC2 + SyncPN, RES1024x768x120, VCLK139_054, + {Mode32Bpp + SupportRAMDAC2 + SyncPN, RES1024x768x120, VCLK139_054, 0x00, 0x47, 0x37, 1024, 768},/* 1c 1024x768x120Hz */ - {Support32Bpp + SupportLCD + SyncPP, RES1280x960x60, VCLK108_2, + {Mode32Bpp + SupportLCD + SyncPP, RES1280x960x60, VCLK108_2_315, 0x08, 0x58, 0x7b, 1280, 960},/* 1d 1280x960x60Hz */ - {Support32Bpp + InterlaceMode + SyncPP, RES1280x1024x43, VCLK78_75, + {Mode32Bpp + InterlaceMode + SyncPP, RES1280x1024x43, VCLK78_75, 0x00, 0x58, 0x3a, 1280, 1024},/* 1e 1280x1024x43Hz */ - {Support32Bpp + NoSupportTV + SyncPP, RES1280x1024x60, VCLK108_2, + {Mode32Bpp + NoSupportTV + SyncPP, RES1280x1024x60, VCLK108_2_315, 0x07, 0x58, 0x3a, 1280, 1024},/*1f 1280x1024x60Hz (LCD 1280x1024x60Hz)*/ - {Support32Bpp + NoSupportTV + SyncPP, RES1280x1024x75, VCLK135_5, + {Mode32Bpp + NoSupportTV + SyncPP, RES1280x1024x75, VCLK135_5, 0x00, 0x58, 0x3a, 1280, 1024},/*20 1280x1024x75Hz (LCD 1280x1024x75Hz)*/ - {Support32Bpp + SyncPP, RES1280x1024x85, VCLK157_5, + {Mode32Bpp + SyncPP, RES1280x1024x85, VCLK157_5, 0x00, 0x58, 0x3a, 1280, 1024},/* 21 1280x1024x85Hz */ /* 22 1600x1200x60Hz */ - {Support32Bpp + SupportLCD + SyncPP + SupportCRT2in301C, + {Mode32Bpp + SupportLCD + SyncPP + SupportCRT2in301C, RES1600x1200x60, VCLK162, 0x09, 0x7A, 0x3c, 1600, 1200}, - {Support32Bpp + SyncPP + SupportCRT2in301C, RES1600x1200x65, VCLK175, + {Mode32Bpp + SyncPP + SupportCRT2in301C, RES1600x1200x65, VCLK175, 0x00, 0x69, 0x3c, 1600, 1200},/* 23 1600x1200x65Hz */ - {Support32Bpp + SyncPP + SupportCRT2in301C, RES1600x1200x70, VCLK189, + {Mode32Bpp + SyncPP + SupportCRT2in301C, RES1600x1200x70, VCLK189, 0x00, 0x69, 0x3c, 1600, 1200},/* 24 1600x1200x70Hz */ - {Support32Bpp + SyncPP + SupportCRT2in301C, RES1600x1200x75, VCLK202_5, + {Mode32Bpp + SyncPP + SupportCRT2in301C, RES1600x1200x75, VCLK202_5, 0x00, 0x69, 0x3c, 1600, 1200},/* 25 1600x1200x75Hz */ - {Support32Bpp + SyncPP, RES1600x1200x85, VCLK229_5, + {Mode32Bpp + SyncPP, RES1600x1200x85, VCLK229_5, 0x00, 0x69, 0x3c, 1600, 1200},/* 26 1600x1200x85Hz */ - {Support32Bpp + SyncPP, RES1600x1200x100, VCLK269_655, + {Mode32Bpp + SyncPP, RES1600x1200x100, VCLK269_655, 0x00, 0x69, 0x3c, 1600, 1200},/* 27 1600x1200x100Hz */ - {Support32Bpp + SyncPP, RES1600x1200x120, VCLK323_586, + {Mode32Bpp + SyncPP, RES1600x1200x120, VCLK323_586, 0x00, 0x69, 0x3c, 1600, 1200},/* 28 1600x1200x120Hz */ - {Support32Bpp + SupportLCD + SyncNP, RES1920x1440x60, VCLK234, + {Mode32Bpp + SupportLCD + SyncNP, RES1920x1440x60, VCLK234, 0x00, 0x00, 0x68, 1920, 1440},/* 29 1920x1440x60Hz */ - {Support32Bpp + SyncPN, RES1920x1440x65, VCLK254_817, + {Mode32Bpp + SyncPN, RES1920x1440x65, VCLK254_817, 0x00, 0x00, 0x68, 1920, 1440},/* 2a 1920x1440x65Hz */ - {Support32Bpp + SyncPN, RES1920x1440x70, VCLK277_015, + {Mode32Bpp + SyncPN, RES1920x1440x70, VCLK277_015, 0x00, 0x00, 0x68, 1920, 1440},/* 2b 1920x1440x70Hz */ - {Support32Bpp + SyncPN, RES1920x1440x75, VCLK291_132, + {Mode32Bpp + SyncPN, RES1920x1440x75, VCLK291_132, 0x00, 0x00, 0x68, 1920, 1440},/* 2c 1920x1440x75Hz */ - {Support32Bpp + SyncPN, RES1920x1440x85, VCLK330_615, + {Mode32Bpp + SyncPN, RES1920x1440x85, VCLK330_615, 0x00, 0x00, 0x68, 1920, 1440},/* 2d 1920x1440x85Hz */ - {Support16Bpp + SyncPN, RES1920x1440x100, VCLK388_631, + {Mode16Bpp + SyncPN, RES1920x1440x100, VCLK388_631, 0x00, 0x00, 0x68, 1920, 1440},/* 2e 1920x1440x100Hz */ - {Support32Bpp + SupportLCD + SyncPN, RES2048x1536x60, VCLK266_952, + {Mode32Bpp + SupportLCD + SyncPN, RES2048x1536x60, VCLK266_952, 0x00, 0x00, 0x6c, 2048, 1536},/* 2f 2048x1536x60Hz */ - {Support32Bpp + SyncPN, RES2048x1536x65, VCLK291_766, + {Mode32Bpp + SyncPN, RES2048x1536x65, VCLK291_766, 0x00, 0x00, 0x6c, 2048, 1536},/* 30 2048x1536x65Hz */ - {Support32Bpp + SyncPN, RES2048x1536x70, VCLK315_195, + {Mode32Bpp + SyncPN, RES2048x1536x70, VCLK315_195, 0x00, 0x00, 0x6c, 2048, 1536},/* 31 2048x1536x70Hz */ - {Support32Bpp + SyncPN, RES2048x1536x75, VCLK340_477, + {Mode32Bpp + SyncPN, RES2048x1536x75, VCLK340_477, 0x00, 0x00, 0x6c, 2048, 1536},/* 32 2048x1536x75Hz */ - {Support16Bpp + SyncPN, RES2048x1536x85, VCLK375_847, + {Mode16Bpp + SyncPN, RES2048x1536x85, VCLK375_847, 0x00, 0x00, 0x6c, 2048, 1536},/* 33 2048x1536x85Hz */ - {Support32Bpp + SupportHiVisionTV + SupportRAMDAC2 + - SyncPP + SupportYPbPr, RES800x480x60, VCLK39_77, + {Mode32Bpp + SupportHiVision + SupportRAMDAC2 + + SyncPP + SupportYPbPr750p, RES800x480x60, VCLK39_77, 0x08, 0x00, 0x70, 800, 480},/* 34 800x480x60Hz */ - {Support32Bpp + SupportRAMDAC2 + SyncPP, RES800x480x75, VCLK49_5, + {Mode32Bpp + SupportRAMDAC2 + SyncPP, RES800x480x75, VCLK49_5, 0x08, 0x00, 0x70, 800, 480},/* 35 800x480x75Hz */ - {Support32Bpp + SupportRAMDAC2 + SyncPP, RES800x480x85, VCLK56_25, + {Mode32Bpp + SupportRAMDAC2 + SyncPP, RES800x480x85, VCLK56_25, 0x08, 0x00, 0x70, 800, 480},/* 36 800x480x85Hz */ - {Support32Bpp + SupportHiVisionTV + SupportRAMDAC2 + - SyncPP + SupportYPbPr, RES1024x576x60, VCLK65, + {Mode32Bpp + SupportHiVision + SupportRAMDAC2 + + SyncPP + SupportYPbPr750p, RES1024x576x60, VCLK65_315, 0x09, 0x00, 0x71, 1024, 576},/* 37 1024x576x60Hz */ - {Support32Bpp + SupportRAMDAC2 + SyncPP, RES1024x576x75, VCLK78_75, + {Mode32Bpp + SupportRAMDAC2 + SyncPP, RES1024x576x75, VCLK78_75, 0x09, 0x00, 0x71, 1024, 576},/* 38 1024x576x75Hz */ - {Support32Bpp + SupportRAMDAC2 + SyncPP, RES1024x576x85, VCLK94_5, + {Mode32Bpp + SupportRAMDAC2 + SyncPP, RES1024x576x85, VCLK94_5, 0x09, 0x00, 0x71, 1024, 576},/* 39 1024x576x85Hz */ - {Support32Bpp + SupportHiVisionTV + SupportRAMDAC2 + - SyncPP + SupportYPbPr, RES1280x720x60, VCLK108_2, + {Mode32Bpp + SupportHiVision + SupportRAMDAC2 + + SyncPP + SupportYPbPr750p, RES1280x720x60, VCLK108_2_315, 0x0A, 0x00, 0x75, 1280, 720},/* 3a 1280x720x60Hz*/ - {Support32Bpp + SupportRAMDAC2 + SyncPP, RES1280x720x75, VCLK135_5, + {Mode32Bpp + SupportRAMDAC2 + SyncPP, RES1280x720x75, VCLK135_5, 0x0A, 0x00, 0x75, 1280, 720},/* 3b 1280x720x75Hz */ - {Support32Bpp + SupportRAMDAC2 + SyncPP, RES1280x720x85, VCLK157_5, + {Mode32Bpp + SupportRAMDAC2 + SyncPP, RES1280x720x85, VCLK157_5, 0x0A, 0x00, 0x75, 1280, 720},/* 3c 1280x720x85Hz */ - {Support32Bpp + SupportTV + SyncNN, RES720x480x60, VCLK28_322, + {Mode32Bpp + SupportTV + SyncNN, RES720x480x60, VCLK28_322, 0x06, 0x00, 0x31, 720, 480},/* 3d 720x480x60Hz */ - {Support32Bpp + SupportTV + SyncPP, RES720x576x56, VCLK36, + {Mode32Bpp + SupportTV + SyncPP, RES720x576x56, VCLK36, 0x06, 0x00, 0x32, 720, 576},/* 3e 720x576x56Hz */ - {Support32Bpp + InterlaceMode + NoSupportLCD + SyncPP, RES856x480x79I, + {Mode32Bpp + InterlaceMode + NoSupportLCD + SyncPP, RES856x480x79I, VCLK35_2, 0x00, 0x00, 0x00, 856, 480},/* 3f 856x480x79I */ - {Support32Bpp + NoSupportLCD + SyncNN, RES856x480x60, VCLK35_2, + {Mode32Bpp + NoSupportLCD + SyncNN, RES856x480x60, VCLK35_2, 0x00, 0x00, 0x00, 856, 480},/* 40 856x480x60Hz */ - {Support32Bpp + NoSupportHiVisionTV + SyncPP, RES1280x768x60, + {Mode32Bpp + NoSupportHiVisionTV + SyncPP, RES1280x768x60, VCLK79_411, 0x08, 0x48, 0x23, 1280, 768},/* 41 1280x768x60Hz */ - {Support32Bpp + NoSupportHiVisionTV + SyncPP, RES1400x1050x60, + {Mode32Bpp + NoSupportHiVisionTV + SyncPP, RES1400x1050x60, VCLK122_61, 0x08, 0x69, 0x26, 1400, 1050},/* 42 1400x1050x60Hz */ - {Support32Bpp + SupportRAMDAC2 + SyncPP, RES1152x864x60, VCLK80_350, + {Mode32Bpp + SupportRAMDAC2 + SyncPP, RES1152x864x60, VCLK80_350, 0x37, 0x00, 0x20, 1152, 864},/* 43 1152x864x60Hz */ - {Support32Bpp + SupportRAMDAC2 + SyncPP, RES1152x864x75, VCLK107_385, + {Mode32Bpp + SupportRAMDAC2 + SyncPP, RES1152x864x75, VCLK107_385, 0x37, 0x00, 0x20, 1152, 864},/* 44 1152x864x75Hz */ - {Support32Bpp + SupportLCD + SupportRAMDAC2 + SyncPP, RES1280x960x75, + {Mode32Bpp + SupportLCD + SupportRAMDAC2 + SyncPP, RES1280x960x75, VCLK125_999, 0x3A, 0x88, 0x7b, 1280, 960},/* 45 1280x960x75Hz */ - {Support32Bpp + SupportLCD + SupportRAMDAC2 + SyncPP, RES1280x960x85, + {Mode32Bpp + SupportLCD + SupportRAMDAC2 + SyncPP, RES1280x960x85, VCLK148_5, 0x0A, 0x88, 0x7b, 1280, 960},/* 46 1280x960x85Hz */ - {Support32Bpp + SupportLCD + SupportRAMDAC2 + SyncPP, RES1280x960x120, + {Mode32Bpp + SupportLCD + SupportRAMDAC2 + SyncPP, RES1280x960x120, VCLK217_325, 0x3A, 0x88, 0x7b, 1280, 960},/* 47 1280x960x120Hz */ - {Support32Bpp + SupportRAMDAC2 + SyncPN, RES1024x768x160, VCLK139_054, + {Mode32Bpp + SupportRAMDAC2 + SyncPN, RES1024x768x160, VCLK139_054, 0x30, 0x47, 0x37, 1024, 768},/* 48 1024x768x160Hz */ }; -- cgit v0.10.2 From a3d675c88fe1ede40386e944e1f3ab5988aeb13c Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Thu, 9 Feb 2012 21:11:47 +0100 Subject: staging/xgifb: Rename XGI specific initdef.h defines This patch renames some of the defines that exist in the sis initdef.h but seem to have a different value. In order to preserve the functionality of the driver, we simply prepend these defines with XGI_ (for now) to resolve conflicts and review them later on. Renames: SetCRT2ToLCDA -> XGI_SetCRT2ToLCDA LCDVESATiming -> XGI_LCDVESATiming EnableLVDSDDA -> XGI_EnableLVDSDDA LCDDualLink -> XGI_LCDDualLink ModeSwitchStatus -> XGI_ModeSwitchStatus YPbPr750pVCLK -> XGI_YPbPr750pVCLK Signed-off-by: Peter Huewe Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/xgifb/vb_def.h b/drivers/staging/xgifb/vb_def.h index 12454c5..a4fedbd 100644 --- a/drivers/staging/xgifb/vb_def.h +++ b/drivers/staging/xgifb/vb_def.h @@ -109,7 +109,7 @@ #define SetCRT2ToSCART 0x0010 #define SetCRT2ToLCD 0x0020 #define SetCRT2ToRAMDAC 0x0040 -#define SetCRT2ToLCDA 0x0100 +#define XGI_SetCRT2ToLCDA 0x0100 #define SetInSlaveMode 0x0200 #define SetNotSimuMode 0x0400 #define LoadDACFlag 0x1000 @@ -131,8 +131,8 @@ #define NTSC1024x768 0x2000 #define SetTVLockMode 0x4000 -#define LCDVESATiming 0x0001 /* LCD Info/CR37 */ -#define EnableLVDSDDA 0x0002 +#define XGI_LCDVESATiming 0x0001 /* LCD Info/CR37 */ +#define XGI_EnableLVDSDDA 0x0002 #define EnableScalingLCD 0x0008 #define SetPWDEnable 0x0004 #define SetLCDtoNonExpanding 0x0010 @@ -145,7 +145,7 @@ #define EnableLCD24bpp 0x0004 /* default */ #define DisableLCD24bpp 0x0000 #define LCDPolarity 0x00c0 /* default: SyncNN */ -#define LCDDualLink 0x0100 +#define XGI_LCDDualLink 0x0100 #define EnableSpectrum 0x0200 #define PWDEnable 0x0400 #define EnableVBCLKDRVLOW 0x4000 @@ -191,7 +191,7 @@ #define DisplayDeviceFromCMOS 0x10 /* ---------------------- HK Evnet Definition */ -#define ModeSwitchStatus 0xf0 +#define XGI_ModeSwitchStatus 0xf0 #define ActiveCRT1 0x10 #define ActiveLCD 0x0020 #define ActiveTV 0x40 @@ -286,7 +286,7 @@ #define VCLK125_999 0x51 #define VCLK148_5 0x52 #define VCLK217_325 0x55 -#define YPbPr750pVCLK 0x57 +#define XGI_YPbPr750pVCLK 0x57 #define TVVCLKDIV2 0x3A #define TVVCLK 0x3B diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index ab2157c..42eaec7 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -208,8 +208,8 @@ static void XGI_SetSeqRegs(unsigned short ModeNo, xgifb_reg_set(pVBInfo->P3c4, 0x00, 0x03); /* Set SR0 */ tempah = pVBInfo->StandTable[StandTableIndex].SR[0]; - i = SetCRT2ToLCDA; - if (pVBInfo->VBInfo & SetCRT2ToLCDA) { + i = XGI_SetCRT2ToLCDA; + if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) { tempah |= 0x01; } else { if (pVBInfo->VBInfo & (SetCRT2ToTV | SetCRT2ToLCD)) { @@ -263,7 +263,7 @@ static void XGI_SetATTRegs(unsigned short ModeNo, ARdata = pVBInfo->StandTable[StandTableIndex].ATTR[i]; if (modeflag & Charx8Dot) { /* ifndef Dot9 */ if (i == 0x13) { - if (pVBInfo->VBInfo & SetCRT2ToLCDA) { + if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) { ARdata = 0; } else { if (pVBInfo->VBInfo & (SetCRT2ToTV @@ -356,7 +356,7 @@ static unsigned char XGI_AjustCRT2Rate(unsigned short ModeNo, } /* 301b */ - if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { + if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) { tempax |= SupportLCD; if (pVBInfo->LCDResInfo != Panel_1280x1024) { @@ -1266,7 +1266,7 @@ static unsigned short XGI_GetVCLK2Ptr(unsigned short ModeNo, if (pVBInfo->IF_DEF_LVDS == 0) { CRT2Index = CRT2Index >> 6; /* for LCD */ - if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { /*301b*/ + if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) { /*301b*/ if (pVBInfo->LCDResInfo != Panel_1024x768) VCLKIndex = LCDXlat2VCLK[CRT2Index]; else @@ -1294,7 +1294,7 @@ static unsigned short XGI_GetVCLK2Ptr(unsigned short ModeNo, if ((pVBInfo->VBType & VB_SIS301LV) && !(pVBInfo->VBExtInfo == VB_YPbPr1080i)) { if (pVBInfo->VBExtInfo == YPbPr750p) - VCLKIndex = YPbPr750pVCLK; + VCLKIndex = XGI_YPbPr750pVCLK; else if (pVBInfo->VBExtInfo == YPbPr525p) VCLKIndex = YPbPr525pVCLK; else if (pVBInfo->SetFlag & RPLLDIV2XO) @@ -1362,7 +1362,7 @@ static void XGI_SetCRT1VCLK(unsigned short ModeNo, xgifb_reg_set(pVBInfo->P3c4, 0x2D, 0x01); } else if ((pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV | VB_SIS302LV | VB_XGI301C)) && (pVBInfo->VBInfo - & SetCRT2ToLCDA)) { + & XGI_SetCRT2ToLCDA)) { vclkindex = XGI_GetVCLK2Ptr(ModeNo, ModeIdIndex, RefreshRateTableIndex, HwDeviceExtension, pVBInfo); @@ -1801,7 +1801,7 @@ static void *XGI_GetLcdPtr(unsigned short BX, unsigned short ModeNo, Ext_CRT2CRTC; } - if (pVBInfo->VBInfo & SetCRT2ToLCDA) { + if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) { if (ModeNo <= 0x13) tempal = pVBInfo->SModeIDTable[ModeIdIndex]. St_CRT2CRTC2; @@ -2364,7 +2364,7 @@ static void XGI_GetLVDSData(unsigned short ModeNo, unsigned short ModeIdIndex, tempbx = 2; - if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { + if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) { LCDPtr = (struct XGI330_LVDSDataStruct *) XGI_GetLcdPtr(tempbx, ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo); @@ -2374,7 +2374,7 @@ static void XGI_GetLVDSData(unsigned short ModeNo, unsigned short ModeIdIndex, pVBInfo->VT = LCDPtr->LCDVT; } - if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { + if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) { if (!(pVBInfo->LCDInfo & (SetLCDtoNonExpanding | EnableScalingLCD))) { if ((pVBInfo->LCDResInfo == Panel_1024x768) || @@ -2415,7 +2415,7 @@ static void XGI_ModCRT1Regs(unsigned short ModeNo, unsigned short ModeIdIndex, tempbx = 0; - if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { + if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) { LCDPtr = (struct XGI_LVDSCRT1HDataStruct *) XGI_GetLcdPtr(tempbx, ModeNo, ModeIdIndex, @@ -2430,7 +2430,7 @@ static void XGI_ModCRT1Regs(unsigned short ModeNo, unsigned short ModeIdIndex, tempbx = 1; - if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { + if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) { LCDPtr1 = (struct XGI_LVDSCRT1VDataStruct *) XGI_GetLcdPtr( tempbx, @@ -2682,7 +2682,7 @@ static void XGI_SetLVDSRegs(unsigned short ModeNo, unsigned short ModeIdIndex, if (tempbx != pVBInfo->VDE) tempax |= 0x40; - if (pVBInfo->LCDInfo & EnableLVDSDDA) + if (pVBInfo->LCDInfo & XGI_EnableLVDSDDA) tempax |= 0x40; xgifb_reg_and_or(pVBInfo->Part1Port, 0x1a, 0x07, @@ -2800,7 +2800,7 @@ static void XGI_GetLCDVCLKPtr(unsigned char *di_0, unsigned char *di_1, { unsigned short index; - if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { + if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) { index = XGI_GetLCDCapPtr1(pVBInfo); if (pVBInfo->VBInfo & SetCRT2ToLCD) { /* LCDB */ @@ -2834,7 +2834,7 @@ static unsigned char XGI_GetVCLKPtr(unsigned short RefreshRateTableIndex, index = XGI_GetLCDCapPtr(pVBInfo); tempal = pVBInfo->LCDCapList[index].LCD_VCLK; - if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) + if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) return tempal; /* {TV} */ @@ -2858,7 +2858,7 @@ static unsigned char XGI_GetVCLKPtr(unsigned short RefreshRateTableIndex, } if (pVBInfo->TVInfo & TVSetYPbPr750p) { - tempal = YPbPr750pVCLK; + tempal = XGI_YPbPr750pVCLK; return tempal; } @@ -2900,7 +2900,7 @@ static void XGI_GetVCLKLen(unsigned char tempal, unsigned char *di_0, { if (pVBInfo->VBType & (VB_SIS301 | VB_SIS301B | VB_SIS302B | VB_SIS301LV | VB_SIS302LV | VB_XGI301C)) { - if ((!(pVBInfo->VBInfo & SetCRT2ToLCDA)) && (pVBInfo->SetFlag + if ((!(pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)) && (pVBInfo->SetFlag & ProgrammingCRT2)) { *di_0 = (unsigned char) XGI_VBVCLKData[tempal].SR2B; *di_1 = XGI_VBVCLKData[tempal].SR2C; @@ -2926,7 +2926,7 @@ static void XGI_SetCRT2ECLK(unsigned short ModeNo, unsigned short ModeIdIndex, for (i = 0; i < 4; i++) { xgifb_reg_and_or(pVBInfo->P3d4, 0x31, ~0x30, (unsigned short) (0x10 * i)); - if ((!(pVBInfo->VBInfo & SetCRT2ToLCDA)) + if ((!(pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)) && (!(pVBInfo->VBInfo & SetInSlaveMode))) { xgifb_reg_set(pVBInfo->P3c4, 0x2e, di_0); xgifb_reg_set(pVBInfo->P3c4, 0x2f, di_1); @@ -3014,7 +3014,7 @@ static void XGI_UpdateModeInfo(struct xgi_hw_device_info *HwDeviceExtension, } } temp = tempcl; - tempbl = ~ModeSwitchStatus; + tempbl = ~XGI_ModeSwitchStatus; xgifb_reg_and_or(pVBInfo->P3d4, 0x3d, tempbl, temp); if (!(pVBInfo->SetFlag & ReserveTVOption)) @@ -3090,7 +3090,7 @@ static void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex, push = push << 8; tempax = temp << 8; tempbx = tempbx | tempax; - temp = (SetCRT2ToDualEdge | SetCRT2ToYPbPr525750 | SetCRT2ToLCDA + temp = (SetCRT2ToDualEdge | SetCRT2ToYPbPr525750 | XGI_SetCRT2ToLCDA | SetInSlaveMode | DisableCRT2Display); temp = 0xFFFF ^ temp; tempbx &= temp; @@ -3113,7 +3113,7 @@ static void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex, if (temp & SetToLCDA) tempbx |= - SetCRT2ToLCDA; + XGI_SetCRT2ToLCDA; } } } @@ -3172,7 +3172,7 @@ static void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex, if (pVBInfo->IF_DEF_LCDA == 1) { /* Select Display Device */ if (!(pVBInfo->VBType & VB_NoLCD)) { - if (tempbx & SetCRT2ToLCDA) { + if (tempbx & XGI_SetCRT2ToLCDA) { if (tempbx & SetSimuScanMode) tempbx &= (~(SetCRT2ToLCD | SetCRT2ToRAMDAC | @@ -3246,7 +3246,7 @@ static void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex, if ((!(tempbx & DriverMode)) || (!(modeflag & CRT2Mode))) { if (pVBInfo->IF_DEF_LCDA == 1) { - if (!(tempbx & SetCRT2ToLCDA)) + if (!(tempbx & XGI_SetCRT2ToLCDA)) tempbx |= (SetInSlaveMode | SetSimuScanMode); } @@ -3255,9 +3255,9 @@ static void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex, /* LCD+TV can't support in slave mode * (Force LCDA+TV->LCDB) */ if ((tempbx & SetInSlaveMode) && - (tempbx & SetCRT2ToLCDA)) { + (tempbx & XGI_SetCRT2ToLCDA)) { tempbx ^= (SetCRT2ToLCD | - SetCRT2ToLCDA | + XGI_SetCRT2ToLCDA | SetCRT2ToDualEdge); pVBInfo->SetFlag |= ReserveTVOption; } @@ -3392,7 +3392,7 @@ static unsigned char XGI_GetLCDInfo(unsigned short ModeNo, if ((tempbx == Panel_1024x768) || (tempbx == Panel_1280x1024)) { if (pVBInfo->VBInfo & DriverMode) { tempax = xgifb_reg_get(pVBInfo->P3d4, 0x33); - if (pVBInfo->VBInfo & SetCRT2ToLCDA) + if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) tempax &= 0x0F; else tempax = tempax >> 4; @@ -3411,7 +3411,7 @@ static unsigned char XGI_GetLCDInfo(unsigned short ModeNo, /* End of LCD75 */ - if (!(pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA))) + if (!(pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA))) return 0; tempbx = 0; @@ -3428,7 +3428,7 @@ static unsigned char XGI_GetLCDInfo(unsigned short ModeNo, if (pVBInfo->IF_DEF_LVDS == 0) { /* shampoo */ if (((pVBInfo->VBType & VB_SIS302LV) || (pVBInfo->VBType - & VB_XGI301C)) && (tempax & LCDDualLink)) { + & VB_XGI301C)) && (tempax & XGI_LCDDualLink)) { tempbx |= SetLCDDualLink; } } @@ -3444,13 +3444,13 @@ static unsigned char XGI_GetLCDInfo(unsigned short ModeNo, if (pVBInfo->IF_DEF_ExpLink == 1) { if (modeflag & HalfDCLK) { if (!(tempbx & SetLCDtoNonExpanding)) { - tempbx |= EnableLVDSDDA; + tempbx |= XGI_EnableLVDSDDA; } else { if (ModeNo > 0x13) { if (pVBInfo->LCDResInfo == Panel_1024x768) { if (resinfo == 4) {/* 512x384 */ - tempbx |= EnableLVDSDDA; + tempbx |= XGI_EnableLVDSDDA; } } } @@ -3460,9 +3460,9 @@ static unsigned char XGI_GetLCDInfo(unsigned short ModeNo, if (pVBInfo->VBInfo & SetInSlaveMode) { if (pVBInfo->VBInfo & SetNotSimuMode) - tempbx |= LCDVESATiming; + tempbx |= XGI_LCDVESATiming; } else { - tempbx |= LCDVESATiming; + tempbx |= XGI_LCDVESATiming; } pVBInfo->LCDInfo = tempbx; @@ -3477,7 +3477,7 @@ static unsigned char XGI_GetLCDInfo(unsigned short ModeNo, SetInSlaveMode | SetCRT2ToLCD); pVBInfo->VBInfo |= - SetCRT2ToLCDA | + XGI_SetCRT2ToLCDA | SetCRT2ToDualEdge; } } @@ -3802,7 +3802,7 @@ static void XGI_GetCRT2ResInfo(unsigned short ModeNo, if (pVBInfo->VBInfo & SetCRT2ToLCD) { if (pVBInfo->IF_DEF_LVDS == 0) { if (pVBInfo->LCDResInfo == Panel_1600x1200) { - if (!(pVBInfo->LCDInfo & LCDVESATiming)) { + if (!(pVBInfo->LCDInfo & XGI_LCDVESATiming)) { if (yres == 1024) yres = 1056; } @@ -3814,14 +3814,14 @@ static void XGI_GetCRT2ResInfo(unsigned short ModeNo, else if (yres == 350) yres = 360; - if (pVBInfo->LCDInfo & LCDVESATiming) { + if (pVBInfo->LCDInfo & XGI_LCDVESATiming) { if (yres == 360) yres = 375; } } if (pVBInfo->LCDResInfo == Panel_1024x768) { - if (!(pVBInfo->LCDInfo & LCDVESATiming)) { + if (!(pVBInfo->LCDInfo & XGI_LCDVESATiming)) { if (!(pVBInfo->LCDInfo & LCDNonExpanding)) { if (yres == 350) @@ -3848,7 +3848,7 @@ static void XGI_GetCRT2ResInfo(unsigned short ModeNo, static unsigned char XGI_IsLCDDualLink(struct vb_device_info *pVBInfo) { - if ((pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) && + if ((pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) && (pVBInfo->LCDInfo & SetLCDDualLink)) /* shampoo0129 */ return 1; @@ -3942,7 +3942,7 @@ static void XGI_GetCRT2Data(unsigned short ModeNo, unsigned short ModeIdIndex, tempbx = 4; - if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { + if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) { LCDPtr = (struct SiS_LCDData *) XGI_GetLcdPtr(tempbx, ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo); @@ -3958,7 +3958,7 @@ static void XGI_GetCRT2Data(unsigned short ModeNo, unsigned short ModeIdIndex, tempax = 1024; tempbx = 768; - if (!(pVBInfo->LCDInfo & LCDVESATiming)) { + if (!(pVBInfo->LCDInfo & XGI_LCDVESATiming)) { if (pVBInfo->VGAVDE == 357) tempbx = 527; else if (pVBInfo->VGAVDE == 420) @@ -4008,7 +4008,7 @@ static void XGI_GetCRT2Data(unsigned short ModeNo, unsigned short ModeIdIndex, } else if (pVBInfo->LCDResInfo == Panel_1600x1200) { tempax = 1600; tempbx = 1200; /* alan 10/14/2003 */ - if (!(pVBInfo->LCDInfo & LCDVESATiming)) { + if (!(pVBInfo->LCDInfo & XGI_LCDVESATiming)) { if (pVBInfo->VGAVDE == 350) tempbx = 875; else if (pVBInfo->VGAVDE == 400) @@ -4620,7 +4620,7 @@ static void XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex, if (pVBInfo->VBInfo & SetCRT2ToLCD) { if (pVBInfo->LCDResInfo == Panel_1024x768) { - if (!(pVBInfo->LCDInfo & LCDVESATiming)) { + if (!(pVBInfo->LCDInfo & XGI_LCDVESATiming)) { if (tempbx == 350) tempbx += 5; if (tempbx == 480) @@ -5271,7 +5271,7 @@ static void XGI_SetLCDRegs(unsigned short ModeNo, unsigned short ModeIdIndex, if (pVBInfo->ModeType == ModeEGA) { if (pVBInfo->VGAHDE >= 1024) { temp = 0x02; - if (pVBInfo->LCDInfo & LCDVESATiming) + if (pVBInfo->LCDInfo & XGI_LCDVESATiming) temp = 0x01; } } @@ -5422,7 +5422,7 @@ static void XGI_SetLCDRegs(unsigned short ModeNo, unsigned short ModeIdIndex, temp = tempcx & 0x00FF; /* RHSYEXP2S=lcdhre */ xgifb_reg_set(pVBInfo->Part2Port, 0x21, temp); - if (!(pVBInfo->LCDInfo & LCDVESATiming)) { + if (!(pVBInfo->LCDInfo & XGI_LCDVESATiming)) { if (pVBInfo->VGAVDE == 525) { if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV | VB_SIS302LV @@ -6145,10 +6145,10 @@ static void XGI_DisableBridge(struct xgifb_video_info *xgifb_info, tempah = 0x3F; if (!(pVBInfo->VBInfo & (DisableCRT2Display | SetSimuScanMode))) { - if (pVBInfo->VBInfo & SetCRT2ToLCDA) { + if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) { if (pVBInfo->VBInfo & SetCRT2ToDualEdge) { tempah = 0x7F; /* Disable Channel A */ - if (!(pVBInfo->VBInfo & SetCRT2ToLCDA)) + if (!(pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)) /* Disable Channel B */ tempah = 0xBF; @@ -6167,7 +6167,7 @@ static void XGI_DisableBridge(struct xgifb_video_info *xgifb_info, xgifb_reg_and(pVBInfo->Part4Port, 0x1F, tempah); if (pVBInfo->VBType & (VB_SIS302LV | VB_XGI301C)) { - if (((pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA))) + if (((pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA))) || (XGI_DisableChISLCD(pVBInfo)) || (XGI_IsLCDON(pVBInfo))) /* LVDS Driver power down */ @@ -6175,16 +6175,16 @@ static void XGI_DisableBridge(struct xgifb_video_info *xgifb_info, } if ((pVBInfo->SetFlag & DisableChA) || (pVBInfo->VBInfo - & (DisableCRT2Display | SetCRT2ToLCDA + & (DisableCRT2Display | XGI_SetCRT2ToLCDA | SetSimuScanMode))) { if (pVBInfo->SetFlag & GatingCRT) XGI_EnableGatingCRT(HwDeviceExtension, pVBInfo); XGI_DisplayOff(xgifb_info, HwDeviceExtension, pVBInfo); } - if (pVBInfo->VBInfo & SetCRT2ToLCDA) { + if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) { if ((pVBInfo->SetFlag & DisableChA) || (pVBInfo->VBInfo - & SetCRT2ToLCDA)) + & XGI_SetCRT2ToLCDA)) /* Power down */ xgifb_reg_and(pVBInfo->Part1Port, 0x1e, 0xdf); } @@ -6198,7 +6198,7 @@ static void XGI_DisableBridge(struct xgifb_video_info *xgifb_info, if ((pVBInfo->SetFlag & DisableChB) || (pVBInfo->VBInfo & (DisableCRT2Display | SetSimuScanMode)) || - ((!(pVBInfo->VBInfo & SetCRT2ToLCDA)) && + ((!(pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)) && (pVBInfo->VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToLCD | SetCRT2ToTV)))) xgifb_reg_or(pVBInfo->Part1Port, 0x00, 0x80); @@ -6206,7 +6206,7 @@ static void XGI_DisableBridge(struct xgifb_video_info *xgifb_info, if ((pVBInfo->SetFlag & DisableChB) || (pVBInfo->VBInfo & (DisableCRT2Display | SetSimuScanMode)) || - (!(pVBInfo->VBInfo & SetCRT2ToLCDA)) || + (!(pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)) || (pVBInfo->VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToLCD | SetCRT2ToTV))) { /* save Part1 index 0 */ @@ -6227,7 +6227,7 @@ static void XGI_DisableBridge(struct xgifb_video_info *xgifb_info, xgifb_reg_and(pVBInfo->P3c4, 0x32, 0xDF); } - if (pVBInfo->VBInfo & (DisableCRT2Display | SetCRT2ToLCDA + if (pVBInfo->VBInfo & (DisableCRT2Display | XGI_SetCRT2ToLCDA | SetSimuScanMode)) XGI_DisplayOff(xgifb_info, HwDeviceExtension, pVBInfo); } @@ -6330,7 +6330,7 @@ static void XGI_SetDelayComp(struct vb_device_info *pVBInfo) if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV | VB_SIS302LV | VB_XGI301C)) { - if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA + if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA | SetCRT2ToTV | SetCRT2ToRAMDAC)) { tempbl = 0; tempbh = 0; @@ -6345,13 +6345,13 @@ static void XGI_SetDelayComp(struct vb_device_info *pVBInfo) if (pVBInfo->VBInfo & SetCRT2ToDualEdge) tempbl = tempbl >> 4; - if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { + if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) { /* Get LCD Delay */ index = XGI_GetLCDCapPtr(pVBInfo); tempbh = pVBInfo->LCDCapList[index]. LCD_DelayCompensation; - if (!(pVBInfo->VBInfo & SetCRT2ToLCDA)) + if (!(pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)) tempbl = tempbh; } @@ -6365,7 +6365,7 @@ static void XGI_SetDelayComp(struct vb_device_info *pVBInfo) tempah |= tempbl; } - if (pVBInfo->VBInfo & SetCRT2ToLCDA) { /* Channel A */ + if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) { /* Channel A */ tempah &= 0x0F; tempah |= tempbh; } @@ -6497,7 +6497,7 @@ static void XGI_SetLCDCap(struct vb_device_info *pVBInfo) | VB_SIS302LV | VB_XGI301C)) { if (pVBInfo->VBInfo & SetCRT2ToLCD) XGI_SetLCDCap_B(tempcx, pVBInfo); - else if (pVBInfo->VBInfo & SetCRT2ToLCDA) + else if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) XGI_SetLCDCap_A(tempcx, pVBInfo); if (pVBInfo->VBType & (VB_SIS302LV | VB_XGI301C)) { @@ -6668,7 +6668,7 @@ static void XGI_OEM310Setting(unsigned short ModeNo, { XGI_SetDelayComp(pVBInfo); - if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) + if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) XGI_SetLCDCap(pVBInfo); if (pVBInfo->VBInfo & SetCRT2ToTV) { @@ -6732,15 +6732,15 @@ static void XGI_SetCRT2ModeRegs(unsigned short ModeNo, tempbl = 0xff; if (pVBInfo->VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToTV - | SetCRT2ToLCD | SetCRT2ToLCDA)) { - if ((pVBInfo->VBInfo & SetCRT2ToLCDA) && + | SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) { + if ((pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) && (!(pVBInfo->VBInfo & SetSimuScanMode))) { tempbl &= 0xf7; tempah |= 0x01; xgifb_reg_and_or(pVBInfo->Part1Port, 0x2e, tempbl, tempah); } else { - if (pVBInfo->VBInfo & SetCRT2ToLCDA) { + if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) { tempbl &= 0xf7; tempah |= 0x01; } @@ -6780,7 +6780,7 @@ static void XGI_SetCRT2ModeRegs(unsigned short ModeNo, } if (pVBInfo->VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToTV | SetCRT2ToLCD - | SetCRT2ToLCDA)) { + | XGI_SetCRT2ToLCDA)) { tempah &= (~0x08); if ((pVBInfo->ModeType == ModeVGA) && (!(pVBInfo->VBInfo & SetInSlaveMode))) { @@ -6824,7 +6824,7 @@ static void XGI_SetCRT2ModeRegs(unsigned short ModeNo, if (pVBInfo->VBInfo & SetCRT2ToDualEdge) { tempbl = 0xff; - if (pVBInfo->VBInfo & SetCRT2ToLCDA) + if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) tempah |= 0x04; /* shampoo 0129 */ } @@ -6849,7 +6849,7 @@ static void XGI_SetCRT2ModeRegs(unsigned short ModeNo, tempah = 0; tempbl = 0x7f; - if (!(pVBInfo->VBInfo & SetCRT2ToLCDA)) { + if (!(pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)) { tempbl = 0xff; if (!(pVBInfo->VBInfo & SetCRT2ToDualEdge)) tempah |= 0x80; @@ -6872,7 +6872,7 @@ static void XGI_CloseCRTC(struct xgi_hw_device_info *HwDeviceExtension, tempbx = 0; - if (pVBInfo->VBInfo & SetCRT2ToLCDA) + if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) tempbx = 0x08A0; } @@ -6937,7 +6937,7 @@ unsigned short XGI_GetRatePtrCRT2(struct xgi_hw_device_info *pXGIHWDE, index--; if (pVBInfo->SetFlag & ProgrammingCRT2) { - if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { + if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) { if (pVBInfo->IF_DEF_LVDS == 0) { if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV | VB_SIS302LV @@ -7211,7 +7211,7 @@ static void XGI_EnableBridge(struct xgifb_video_info *xgifb_info, if (!XGI_DisableChISLCD(pVBInfo)) { if (XGI_EnableChISLCD(pVBInfo) || (pVBInfo->VBInfo & - (SetCRT2ToLCD | SetCRT2ToLCDA))) + (SetCRT2ToLCD | XGI_SetCRT2ToLCDA))) /* LVDS PLL power on */ xgifb_reg_and( pVBInfo->Part4Port, @@ -7229,12 +7229,12 @@ static void XGI_EnableBridge(struct xgifb_video_info *xgifb_info, tempah = 0xc0; if (!(pVBInfo->VBInfo & SetSimuScanMode)) { - if (pVBInfo->VBInfo & SetCRT2ToLCDA) { + if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) { if (pVBInfo->VBInfo & SetCRT2ToDualEdge) { tempah = tempah & 0x40; if (pVBInfo->VBInfo & - SetCRT2ToLCDA) + XGI_SetCRT2ToLCDA) tempah = tempah ^ 0xC0; if (pVBInfo->SetFlag & @@ -7271,7 +7271,7 @@ static void XGI_EnableBridge(struct xgifb_video_info *xgifb_info, } /* 301 */ else { /* LVDS */ if (pVBInfo->VBInfo & (SetCRT2ToTV | SetCRT2ToLCD - | SetCRT2ToLCDA)) + | XGI_SetCRT2ToLCDA)) /* enable CRT2 */ xgifb_reg_or(pVBInfo->Part1Port, 0x1E, 0x20); @@ -7313,7 +7313,7 @@ static void XGI_SetCRT1Group(struct xgifb_video_info *xgifb_info, if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV | VB_SIS302LV | VB_XGI301C)) { - if (pVBInfo->VBInfo & (SetSimuScanMode | SetCRT2ToLCDA + if (pVBInfo->VBInfo & (SetSimuScanMode | XGI_SetCRT2ToLCDA | SetInSlaveMode)) { pVBInfo->SetFlag |= ProgrammingCRT2; } @@ -7452,11 +7452,11 @@ unsigned char XGISetModeNew(struct xgifb_video_info *xgifb_info, XGI_GetLCDInfo(ModeNo, ModeIdIndex, pVBInfo); XGI_DisableBridge(xgifb_info, HwDeviceExtension, pVBInfo); - if (pVBInfo->VBInfo & (SetSimuScanMode | SetCRT2ToLCDA)) { + if (pVBInfo->VBInfo & (SetSimuScanMode | XGI_SetCRT2ToLCDA)) { XGI_SetCRT1Group(xgifb_info, HwDeviceExtension, ModeNo, ModeIdIndex, pVBInfo); - if (pVBInfo->VBInfo & SetCRT2ToLCDA) { + if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) { XGI_SetLCDAGroup(ModeNo, ModeIdIndex, HwDeviceExtension, pVBInfo); } @@ -7465,7 +7465,7 @@ unsigned char XGISetModeNew(struct xgifb_video_info *xgifb_info, XGI_SetCRT1Group(xgifb_info, HwDeviceExtension, ModeNo, ModeIdIndex, pVBInfo); - if (pVBInfo->VBInfo & SetCRT2ToLCDA) { + if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) { XGI_SetLCDAGroup(ModeNo, ModeIdIndex, HwDeviceExtension, pVBInfo); diff --git a/drivers/staging/xgifb/vb_table.h b/drivers/staging/xgifb/vb_table.h index 4f803b6..dddf261 100644 --- a/drivers/staging/xgifb/vb_table.h +++ b/drivers/staging/xgifb/vb_table.h @@ -2505,17 +2505,17 @@ static struct XGI330_LCDCapStruct XGI_LCDDLCapList[] = { 0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00, 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10}, /* LCDCap1280x1024 */ - {Panel_1280x1024, LCDDualLink+DefaultLCDCap, StLCDBToA, + {Panel_1280x1024, XGI_LCDDualLink+DefaultLCDCap, StLCDBToA, 0x012, 0x70, 0x03, VCLK108_2_315, 0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00, 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, /* LCDCap1400x1050 */ - {Panel_1400x1050, LCDDualLink+DefaultLCDCap, StLCDBToA, + {Panel_1400x1050, XGI_LCDDualLink+DefaultLCDCap, StLCDBToA, 0x012, 0x70, 0x03, VCLK108_2_315, 0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00, 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, /* LCDCap1600x1200 */ - {Panel_1600x1200, LCDDualLink+DefaultLCDCap, LCDToFull, + {Panel_1600x1200, XGI_LCDDualLink+DefaultLCDCap, LCDToFull, 0x012, 0xC0, 0x03, VCLK162, 0x43, 0x22, 0x70, 0x24, 0x02, 0x14, 0x0A, 0x02, 0x00, 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, @@ -2524,7 +2524,7 @@ static struct XGI330_LCDCapStruct XGI_LCDDLCapList[] = { 0x2B, 0x61, 0x2B, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00, 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10}, /* LCDCap1280x1024x75 */ - {Panel_1280x1024x75, LCDDualLink+DefaultLCDCap, StLCDBToA, + {Panel_1280x1024x75, XGI_LCDDualLink+DefaultLCDCap, StLCDBToA, 0x012, 0x90, 0x03, VCLK135_5, 0x54, 0x42, 0x4A, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00, 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, -- cgit v0.10.2 From ccc8cb25ae7c9213c641efb34a0cb58110315188 Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Thu, 9 Feb 2012 21:11:48 +0100 Subject: staging/xgifb: Use TVCLKBASE_315 as a base address Since the defines TVVCLKDIV2, TVVCLK, HiTVVCLKDIV2, HiTVVCLK, HiTVSimuVCLK and HiTVTextVCLK are now defined as relative values, we have to use TVCLKBASE_315 (0x31) as a base address to get the same values as before the merge. The old and now duplicated defines were removed Signed-off-by: Peter Huewe Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/xgifb/vb_def.h b/drivers/staging/xgifb/vb_def.h index a4fedbd..d2e0bcd 100644 --- a/drivers/staging/xgifb/vb_def.h +++ b/drivers/staging/xgifb/vb_def.h @@ -288,12 +288,6 @@ #define VCLK217_325 0x55 #define XGI_YPbPr750pVCLK 0x57 -#define TVVCLKDIV2 0x3A -#define TVVCLK 0x3B -#define HiTVVCLKDIV2 0x3C -#define HiTVVCLK 0x3D -#define HiTVSimuVCLK 0x3E -#define HiTVTextVCLK 0x3F #define VCLK39_77 0x40 #define YPbPr525pVCLK 0x3A #define NTSC1024VCLK 0x41 diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index 42eaec7..2919924 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -1273,19 +1273,19 @@ static unsigned short XGI_GetVCLK2Ptr(unsigned short ModeNo, VCLKIndex = LCDXlat1VCLK[CRT2Index]; } else if (pVBInfo->VBInfo & SetCRT2ToHiVision) { if (pVBInfo->SetFlag & RPLLDIV2XO) { - VCLKIndex = HiTVVCLKDIV2; + VCLKIndex = TVCLKBASE_315 + HiTVVCLKDIV2; VCLKIndex += 25; } else { - VCLKIndex = HiTVVCLK; + VCLKIndex = TVCLKBASE_315 + HiTVVCLK; VCLKIndex += 25; } if (pVBInfo->SetFlag & TVSimuMode) { if (modeflag & Charx8Dot) { - VCLKIndex = HiTVSimuVCLK; + VCLKIndex = TVCLKBASE_315 + HiTVSimuVCLK; VCLKIndex += 25; } else { - VCLKIndex = HiTVTextVCLK; + VCLKIndex = TVCLKBASE_315 + HiTVTextVCLK; VCLKIndex += 25; } } @@ -1304,10 +1304,10 @@ static unsigned short XGI_GetVCLK2Ptr(unsigned short ModeNo, } } else if (pVBInfo->VBInfo & SetCRT2ToTV) { if (pVBInfo->SetFlag & RPLLDIV2XO) { - VCLKIndex = TVVCLKDIV2; + VCLKIndex = TVCLKBASE_315 + TVVCLKDIV2; VCLKIndex += 25; } else { - VCLKIndex = TVVCLK; + VCLKIndex = TVCLKBASE_315 + TVVCLK; VCLKIndex += 25; } } else { /* for CRT2 */ @@ -2845,13 +2845,13 @@ static unsigned char XGI_GetVCLKPtr(unsigned short RefreshRateTableIndex, VB_SIS302LV | VB_XGI301C)) { if (pVBInfo->VBInfo & SetCRT2ToHiVision) { - tempal = HiTVVCLKDIV2; + tempal = TVCLKBASE_315 + HiTVVCLKDIV2; if (!(pVBInfo->TVInfo & RPLLDIV2XO)) - tempal = HiTVVCLK; + tempal = TVCLKBASE_315 + HiTVVCLK; if (pVBInfo->TVInfo & TVSimuMode) { - tempal = HiTVSimuVCLK; + tempal = TVCLKBASE_315 + HiTVSimuVCLK; if (!(modeflag & Charx8Dot)) - tempal = HiTVTextVCLK; + tempal = TVCLKBASE_315 + HiTVTextVCLK; } return tempal; @@ -2870,9 +2870,9 @@ static unsigned char XGI_GetVCLKPtr(unsigned short RefreshRateTableIndex, tempal = NTSC1024VCLK; if (!(pVBInfo->TVInfo & NTSC1024x768)) { - tempal = TVVCLKDIV2; + tempal = TVCLKBASE_315 + TVVCLKDIV2; if (!(pVBInfo->TVInfo & RPLLDIV2XO)) - tempal = TVVCLK; + tempal = TVCLKBASE_315 + TVVCLK; } if (pVBInfo->VBInfo & SetCRT2ToTV) -- cgit v0.10.2 From c3b3b3f9b0efa20a123244def80698669996b8ec Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Thu, 9 Feb 2012 21:11:49 +0100 Subject: staging/xgifb: remove remaining duplicate initdef.h defines This patch removes the remaining defines that are already defined identically in the sis initdef.h header. Signed-off-by: Peter Huewe Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/xgifb/vb_def.h b/drivers/staging/xgifb/vb_def.h index d2e0bcd..c731793 100644 --- a/drivers/staging/xgifb/vb_def.h +++ b/drivers/staging/xgifb/vb_def.h @@ -8,12 +8,8 @@ #define VB_YPbPr1080i 0x03 #define LVDSCRT1Len 15 - -#define SupportCHTV 0x0800 #define SupportCRT2in301C 0x0100 /* for 301C */ #define SetCHTVOverScan 0x8000 -#define PanelRGB18Bit 0x0100 -#define PanelRGB24Bit 0x0000 #define Panel_320x480 0x07 /*fstn*/ /* [ycchen] 02/12/03 Modify for Multi-Sync. LCD Support */ @@ -29,94 +25,24 @@ #define XGI_CRT2_PORT_00 (0x00 - 0x030) -#define _PanelType00 0x00 -#define _PanelType01 0x08 -#define _PanelType02 0x10 -#define _PanelType03 0x18 -#define _PanelType04 0x20 -#define _PanelType05 0x28 -#define _PanelType06 0x30 -#define _PanelType07 0x38 -#define _PanelType08 0x40 -#define _PanelType09 0x48 -#define _PanelType0A 0x50 -#define _PanelType0B 0x58 -#define _PanelType0C 0x60 -#define _PanelType0D 0x68 -#define _PanelType0E 0x70 -#define _PanelType0F 0x78 - /* ============================================================= for 310 ============================================================== */ -/* add LCDDataList for GetLCDPtr */ -#define LCDDataList (VBIOSTablePointerStart+0x22) -/* */ -/* Modify from 310.inc */ -/* */ -/* */ - #define ModeSoftSetting 0x04 -#define BoardTVType 0x02 - -#define SoftDRAMType 0x80 /* DRAMSetting */ - /* ---------------- SetMode Stack */ #define CRT1Len 15 #define VCLKLen 4 -#define VGA_XGI340 0x0001 /* 340 series */ - -#define VB_NoLCD 0x8000 -#define VB_LVDS_NS 0x0001 /* 3rd party chip */ -#define ModeText 0x0000 -#define ModeEGA 0x0002 /* 16 colors mode */ -#define ModeVGA 0x0003 /* 256 colors mode */ - -#define DACInfoFlag 0x0018 - -#define MemoryInfoFlag 0x01e0 -#define MemorySizeShift 5 - -#define Charx8Dot 0x0200 -#define LineCompareOff 0x0400 -#define CRT2Mode 0x0800 -#define HalfDCLK 0x1000 -#define NoSupportSimuTV 0x2000 -#define DoubleScanMode 0x8000 - -/* -------------- Ext_InfoFlag */ #define SupportAllCRT2 0x0078 -#define SupportTV 0x0008 -#define SupportLCD 0x0020 -#define SupportRAMDAC2 0x0040 #define NoSupportTV 0x0070 #define NoSupportHiVisionTV 0x0060 #define NoSupportLCD 0x0058 -#define SupportTV1024 0x0800 /* 301btest */ -#define InterlaceMode 0x0080 -#define SyncPP 0x0000 -#define SyncPN 0x4000 -#define SyncNP 0x8000 -#define SyncNN 0xC000 /* -------------- SetMode Stack/Scratch */ -#define SetSimuScanMode 0x0001 /* VBInfo/CR30 & CR31 */ -#define SetCRT2ToTV 0x089C -#define SetCRT2ToAVIDEO 0x0004 -#define SetCRT2ToSVIDEO 0x0008 -#define SetCRT2ToSCART 0x0010 -#define SetCRT2ToLCD 0x0020 -#define SetCRT2ToRAMDAC 0x0040 #define XGI_SetCRT2ToLCDA 0x0100 -#define SetInSlaveMode 0x0200 -#define SetNotSimuMode 0x0400 -#define LoadDACFlag 0x1000 -#define DriverMode 0x4000 #define SetCRT2ToDualEdge 0x8000 -#define ProgrammingCRT2 0x0001 /* Set Flag */ #define ReserveTVOption 0x0008 #define GatingCRT 0x0800 #define DisableChB 0x1000 @@ -124,7 +50,6 @@ #define DisableChA 0x4000 #define EnableChA 0x8000 -#define SetNTSCTV 0x0000 /* TV Info */ #define SetTVLowResolution 0x0400 #define TVSimuMode 0x0800 #define RPLLDIV2XO 0x1000 @@ -167,24 +92,14 @@ #define TVSense 0xc7 -#define TVOverScan 0x10 /* CR35 */ - #define YPbPrMode 0xe0 #define YPbPrMode525i 0x00 #define YPbPrMode525p 0x20 #define YPbPrMode750p 0x40 #define YPbPrMode1080i 0x60 - -#define LCDRGB18Bit 0x01 /* CR37 */ -#define LCDNonExpanding 0x10 -#define LCDSync 0x20 -#define LCDSyncBit 0xe0 /* H/V polarity & sync ID */ - #define ScalingLCD 0x08 -#define EnableDualEdge 0x01 /* CR38 */ -#define SetToLCDA 0x02 #define SetYPbPr 0x04 /* ---------------------- VUMA Information */ @@ -207,28 +122,13 @@ /* translated from asm code 301def.h */ /* */ /* --------------------------------------------------------- */ -#define LCDDataLen 8 -#define TVDataLen 12 #define LVDSCRT1Len_H 8 #define LVDSCRT1Len_V 7 -#define LVDSDataLen 6 -#define LVDSDesDataLen 6 #define LCDDesDataLen 6 #define LVDSDesDataLen2 8 #define LCDDesDataLen2 8 -#define CHTVRegLen 16 -#define StHiTVHT 892 -#define StHiTVVT 1126 -#define StHiTextTVHT 1000 -#define StHiTextTVVT 1126 -#define ExtHiTVHT 2100 -#define ExtHiTVVT 1125 -#define NTSCHT 1716 -#define NTSCVT 525 #define NTSC1024x768HT 1908 -#define PALHT 1728 -#define PALVT 625 #define YPbPrTV525iHT 1716 /* YPbPr */ #define YPbPrTV525iVT 525 @@ -237,15 +137,10 @@ #define YPbPrTV750pHT 1650 #define YPbPrTV750pVT 750 -#define CRT2Delay1 0x04 /* XGI301 */ -#define CRT2Delay2 0x0A /* 301B,302 */ - - #define VCLK25_175 0x00 #define VCLK28_322 0x01 #define VCLK31_5 0x02 #define VCLK36 0x03 -#define VCLK40 0x04 #define VCLK43_163 0x05 #define VCLK44_9 0x06 #define VCLK49_5 0x07 @@ -289,7 +184,7 @@ #define XGI_YPbPr750pVCLK 0x57 #define VCLK39_77 0x40 -#define YPbPr525pVCLK 0x3A +#define YPbPr525pVCLK 0x3A #define NTSC1024VCLK 0x41 #define VCLK35_2 0x49 /* ; 800x480 */ #define VCLK122_61 0x4A -- cgit v0.10.2 From 073863432f7eaa23c7c09733414d4be2eabf5eef Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 9 Feb 2012 16:37:17 -0600 Subject: staging: r8712u: Add missing initialization and remove configuration parameter CONFIG_R8712_AP When this driver was upgraded to the vendor 20100831 version in commit 93c55dda092c7 et al,, one listhead initialization was missed. This broke complete operation of the driver whenever AP mode was enabled. This fixes https://bugs.archlinux.org/task/27996. The configuration parameter R8712_AP is misleading as the driver cannot function as an AP without a heavily hacked version of hostapd. Thus, it makes sense to remove the parameter; however the code and data configured for the option is left in. Signed-off-by: Larry Finger Cc: Stable Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8712/Kconfig b/drivers/staging/rtl8712/Kconfig index ea37473..6a43312 100644 --- a/drivers/staging/rtl8712/Kconfig +++ b/drivers/staging/rtl8712/Kconfig @@ -9,13 +9,6 @@ config R8712U This option adds the Realtek RTL8712 USB device such as the D-Link DWA-130. If built as a module, it will be called r8712u. -config R8712_AP - bool "Realtek RTL8712U AP code" - depends on R8712U - default N - ---help--- - This option allows the Realtek RTL8712 USB device to be an Access Point. - config R8712_TX_AGGR bool "Realtek RTL8712U Transmit Aggregation code" depends on R8712U && BROKEN diff --git a/drivers/staging/rtl8712/rtl871x_sta_mgt.c b/drivers/staging/rtl8712/rtl871x_sta_mgt.c index 64f5696..1247b3d 100644 --- a/drivers/staging/rtl8712/rtl871x_sta_mgt.c +++ b/drivers/staging/rtl8712/rtl871x_sta_mgt.c @@ -42,9 +42,8 @@ static void _init_stainfo(struct sta_info *psta) _init_listhead(&psta->hash_list); _r8712_init_sta_xmit_priv(&psta->sta_xmitpriv); _r8712_init_sta_recv_priv(&psta->sta_recvpriv); -#ifdef CONFIG_R8712_AP + _init_listhead(&psta->asoc_list); _init_listhead(&psta->auth_list); -#endif } u32 _r8712_init_sta_priv(struct sta_priv *pstapriv) @@ -71,10 +70,8 @@ u32 _r8712_init_sta_priv(struct sta_priv *pstapriv) get_list_head(&pstapriv->free_sta_queue)); psta++; } -#ifdef CONFIG_R8712_AP _init_listhead(&pstapriv->asoc_list); _init_listhead(&pstapriv->auth_list); -#endif return _SUCCESS; } diff --git a/drivers/staging/rtl8712/sta_info.h b/drivers/staging/rtl8712/sta_info.h index 48d6a14..f8016e9 100644 --- a/drivers/staging/rtl8712/sta_info.h +++ b/drivers/staging/rtl8712/sta_info.h @@ -90,7 +90,6 @@ struct sta_info { * curr_network(mlme_priv/security_priv/qos/ht) : AP CAP/INFO * sta_info: (AP & STA) CAP/INFO */ -#ifdef CONFIG_R8712_AP struct list_head asoc_list; struct list_head auth_list; unsigned int expire_to; @@ -98,7 +97,6 @@ struct sta_info { unsigned int authalg; unsigned char chg_txt[128]; unsigned int tx_ra_bitmap; -#endif }; struct sta_priv { @@ -111,13 +109,11 @@ struct sta_priv { struct __queue sleep_q; struct __queue wakeup_q; struct _adapter *padapter; -#ifdef CONFIG_R8712_AP struct list_head asoc_list; struct list_head auth_list; unsigned int auth_to; /* sec, time to expire in authenticating. */ unsigned int assoc_to; /* sec, time to expire before associating. */ unsigned int expire_to; /* sec , time to expire after associated. */ -#endif }; static inline u32 wifi_mac_hash(u8 *mac) -- cgit v0.10.2 From 242501ce5d5296236701612940ed397a2b3fd4bf Mon Sep 17 00:00:00 2001 From: Gerard Ryan Date: Fri, 10 Feb 2012 01:54:50 +0000 Subject: Staging: bcm: fix CodingStyle warnings/errors reported by checkpatch.pl in led_control.h This is a patch to the led_control.h file that fixes numerous warnings and errors reported by the checkpatch.pl tool. There still remain a few more, but as this is my first attempt at a commit, I'm not going to be too adventurous! Signed-off-by: Gerard Ryan Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/bcm/led_control.h b/drivers/staging/bcm/led_control.h index 0711ac2..84d1a02 100644 --- a/drivers/staging/bcm/led_control.h +++ b/drivers/staging/bcm/led_control.h @@ -4,11 +4,11 @@ /*************************TYPE DEF**********************/ #define NUM_OF_LEDS 4 -#define DSD_START_OFFSET 0x0200 -#define EEPROM_VERSION_OFFSET 0x020E -#define EEPROM_HW_PARAM_POINTER_ADDRESS 0x0218 -#define EEPROM_HW_PARAM_POINTER_ADDRRES_MAP5 0x0220 -#define GPIO_SECTION_START_OFFSET 0x03 +#define DSD_START_OFFSET 0x0200 +#define EEPROM_VERSION_OFFSET 0x020E +#define EEPROM_HW_PARAM_POINTER_ADDRESS 0x0218 +#define EEPROM_HW_PARAM_POINTER_ADDRRES_MAP5 0x0220 +#define GPIO_SECTION_START_OFFSET 0x03 #define COMPATIBILITY_SECTION_LENGTH 42 #define COMPATIBILITY_SECTION_LENGTH_MAP5 84 @@ -18,27 +18,27 @@ #define EEPROM_MAP5_MINORVERSION 0 -#define MAX_NUM_OF_BLINKS 10 -#define NUM_OF_GPIO_PINS 16 +#define MAX_NUM_OF_BLINKS 10 +#define NUM_OF_GPIO_PINS 16 -#define DISABLE_GPIO_NUM 0xFF -#define EVENT_SIGNALED 1 +#define DISABLE_GPIO_NUM 0xFF +#define EVENT_SIGNALED 1 -#define MAX_FILE_NAME_BUFFER_SIZE 100 +#define MAX_FILE_NAME_BUFFER_SIZE 100 -#define TURN_ON_LED(GPIO, index) do{ \ +#define TURN_ON_LED(GPIO, index) do { \ UINT gpio_val = GPIO; \ (Adapter->LEDInfo.LEDState[index].BitPolarity == 1) ? \ - wrmaltWithLock(Adapter,BCM_GPIO_OUTPUT_SET_REG, &gpio_val ,sizeof(gpio_val)) : \ - wrmaltWithLock(Adapter,BCM_GPIO_OUTPUT_CLR_REG, &gpio_val, sizeof(gpio_val)); \ - }while(0); + wrmaltWithLock(Adapter, BCM_GPIO_OUTPUT_SET_REG, &gpio_val, sizeof(gpio_val)) : \ + wrmaltWithLock(Adapter, BCM_GPIO_OUTPUT_CLR_REG, &gpio_val, sizeof(gpio_val)); \ + } while (0); #define TURN_OFF_LED(GPIO, index) do { \ UINT gpio_val = GPIO; \ (Adapter->LEDInfo.LEDState[index].BitPolarity == 1) ? \ - wrmaltWithLock(Adapter,BCM_GPIO_OUTPUT_CLR_REG,&gpio_val ,sizeof(gpio_val)) : \ - wrmaltWithLock(Adapter,BCM_GPIO_OUTPUT_SET_REG,&gpio_val ,sizeof(gpio_val)); \ - }while(0); + wrmaltWithLock(Adapter, BCM_GPIO_OUTPUT_CLR_REG, &gpio_val, sizeof(gpio_val)) : \ + wrmaltWithLock(Adapter, BCM_GPIO_OUTPUT_SET_REG, &gpio_val, sizeof(gpio_val)); \ + } while (0); #define B_ULONG32 unsigned long @@ -50,7 +50,7 @@ typedef enum _LEDColors{ BLUE_LED = 2, YELLOW_LED = 3, GREEN_LED = 4 -} LEDColors; /*Enumerated values of different LED types*/ +} LEDColors; /*Enumerated values of different LED types*/ typedef enum LedEvents { SHUTDOWN_EXIT = 0x00, @@ -62,43 +62,41 @@ typedef enum LedEvents { LOWPOWER_MODE_ENTER = 0x20, IDLEMODE_CONTINUE = 0x40, IDLEMODE_EXIT = 0x80, - LED_THREAD_INACTIVE = 0x100, //Makes the LED thread Inactivce. It wil be equivallent to putting the thread on hold. - LED_THREAD_ACTIVE = 0x200 //Makes the LED Thread Active back. -} LedEventInfo_t; /*Enumerated values of different driver states*/ + LED_THREAD_INACTIVE = 0x100, /* Makes the LED thread Inactivce. It wil be equivallent to putting the thread on hold. */ + LED_THREAD_ACTIVE = 0x200 /* Makes the LED Thread Active back. */ +} LedEventInfo_t; /* Enumerated values of different driver states */ #define DRIVER_HALT 0xff -/*Structure which stores the information of different LED types - * and corresponding LED state information of driver states*/ -typedef struct LedStateInfo_t -{ +/* + * Structure which stores the information of different LED types + * and corresponding LED state information of driver states + */ +typedef struct LedStateInfo_t { UCHAR LED_Type; /* specify GPIO number - use 0xFF if not used */ UCHAR LED_On_State; /* Bits set or reset for different states */ UCHAR LED_Blink_State; /* Bits set or reset for blinking LEDs for different states */ UCHAR GPIO_Num; - UCHAR BitPolarity; /*To represent whether H/W is normal polarity or reverse - polarity*/ -}LEDStateInfo, *pLEDStateInfo; + UCHAR BitPolarity; /* To represent whether H/W is normal polarity or reverse polarity */ +} LEDStateInfo, *pLEDStateInfo; -typedef struct _LED_INFO_STRUCT -{ +typedef struct _LED_INFO_STRUCT { LEDStateInfo LEDState[NUM_OF_LEDS]; - BOOLEAN bIdleMode_tx_from_host; /*Variable to notify whether driver came out - from idlemode due to Host or target*/ + BOOLEAN bIdleMode_tx_from_host; /* Variable to notify whether driver came out from idlemode due to Host or target*/ BOOLEAN bIdle_led_off; wait_queue_head_t notify_led_event; wait_queue_head_t idleModeSyncEvent; - struct task_struct *led_cntrl_threadid; - int led_thread_running; + struct task_struct *led_cntrl_threadid; + int led_thread_running; BOOLEAN bLedInitDone; } LED_INFO_STRUCT, *PLED_INFO_STRUCT; -//LED Thread state. -#define BCM_LED_THREAD_DISABLED 0 //LED Thread is not running. -#define BCM_LED_THREAD_RUNNING_ACTIVELY 1 //LED thread is running. -#define BCM_LED_THREAD_RUNNING_INACTIVELY 2 //LED thread has been put on hold +/* LED Thread state. */ +#define BCM_LED_THREAD_DISABLED 0 /* LED Thread is not running. */ +#define BCM_LED_THREAD_RUNNING_ACTIVELY 1 /* LED thread is running. */ +#define BCM_LED_THREAD_RUNNING_INACTIVELY 2 /*LED thread has been put on hold*/ -- cgit v0.10.2 From 841cb11c6fc7ae559ef2d856932907056b75617d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arve=20Hj=C3=B8nnev=C3=A5g?= Date: Thu, 9 Feb 2012 14:24:30 -0800 Subject: staging: android-alarm: Add android alarm driver & in-kernel alarm interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drivers can now create alarms that will use an hrtimer while the system is running and the rtc to wake up from suspend. CC: Arve HjønnevÃ¥g CC: Android Kernel Team Signed-off-by: Arve HjønnevÃ¥g [Fold and move alarm driver and interface to staging, fix whitespace issue, drop kconfig & make file changes as it currently doesn't build -jstultz] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/android/alarm-dev.c b/drivers/staging/android/alarm-dev.c new file mode 100644 index 0000000..ae56961 --- /dev/null +++ b/drivers/staging/android/alarm-dev.c @@ -0,0 +1,286 @@ +/* drivers/rtc/alarm-dev.c + * + * Copyright (C) 2007-2009 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "android_alarm.h" + +#define ANDROID_ALARM_PRINT_INFO (1U << 0) +#define ANDROID_ALARM_PRINT_IO (1U << 1) +#define ANDROID_ALARM_PRINT_INT (1U << 2) + +static int debug_mask = ANDROID_ALARM_PRINT_INFO; +module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP); + +#define pr_alarm(debug_level_mask, args...) \ + do { \ + if (debug_mask & ANDROID_ALARM_PRINT_##debug_level_mask) { \ + pr_info(args); \ + } \ + } while (0) + +#define ANDROID_ALARM_WAKEUP_MASK ( \ + ANDROID_ALARM_RTC_WAKEUP_MASK | \ + ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP_MASK) + +/* support old usespace code */ +#define ANDROID_ALARM_SET_OLD _IOW('a', 2, time_t) /* set alarm */ +#define ANDROID_ALARM_SET_AND_WAIT_OLD _IOW('a', 3, time_t) + +static int alarm_opened; +static DEFINE_SPINLOCK(alarm_slock); +static struct wake_lock alarm_wake_lock; +static DECLARE_WAIT_QUEUE_HEAD(alarm_wait_queue); +static uint32_t alarm_pending; +static uint32_t alarm_enabled; +static uint32_t wait_pending; + +static struct alarm alarms[ANDROID_ALARM_TYPE_COUNT]; + +static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + int rv = 0; + unsigned long flags; + struct timespec new_alarm_time; + struct timespec new_rtc_time; + struct timespec tmp_time; + enum android_alarm_type alarm_type = ANDROID_ALARM_IOCTL_TO_TYPE(cmd); + uint32_t alarm_type_mask = 1U << alarm_type; + + if (alarm_type >= ANDROID_ALARM_TYPE_COUNT) + return -EINVAL; + + if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_GET_TIME(0)) { + if ((file->f_flags & O_ACCMODE) == O_RDONLY) + return -EPERM; + if (file->private_data == NULL && + cmd != ANDROID_ALARM_SET_RTC) { + spin_lock_irqsave(&alarm_slock, flags); + if (alarm_opened) { + spin_unlock_irqrestore(&alarm_slock, flags); + return -EBUSY; + } + alarm_opened = 1; + file->private_data = (void *)1; + spin_unlock_irqrestore(&alarm_slock, flags); + } + } + + switch (ANDROID_ALARM_BASE_CMD(cmd)) { + case ANDROID_ALARM_CLEAR(0): + spin_lock_irqsave(&alarm_slock, flags); + pr_alarm(IO, "alarm %d clear\n", alarm_type); + alarm_try_to_cancel(&alarms[alarm_type]); + if (alarm_pending) { + alarm_pending &= ~alarm_type_mask; + if (!alarm_pending && !wait_pending) + wake_unlock(&alarm_wake_lock); + } + alarm_enabled &= ~alarm_type_mask; + spin_unlock_irqrestore(&alarm_slock, flags); + break; + + case ANDROID_ALARM_SET_OLD: + case ANDROID_ALARM_SET_AND_WAIT_OLD: + if (get_user(new_alarm_time.tv_sec, (int __user *)arg)) { + rv = -EFAULT; + goto err1; + } + new_alarm_time.tv_nsec = 0; + goto from_old_alarm_set; + + case ANDROID_ALARM_SET_AND_WAIT(0): + case ANDROID_ALARM_SET(0): + if (copy_from_user(&new_alarm_time, (void __user *)arg, + sizeof(new_alarm_time))) { + rv = -EFAULT; + goto err1; + } +from_old_alarm_set: + spin_lock_irqsave(&alarm_slock, flags); + pr_alarm(IO, "alarm %d set %ld.%09ld\n", alarm_type, + new_alarm_time.tv_sec, new_alarm_time.tv_nsec); + alarm_enabled |= alarm_type_mask; + alarm_start_range(&alarms[alarm_type], + timespec_to_ktime(new_alarm_time), + timespec_to_ktime(new_alarm_time)); + spin_unlock_irqrestore(&alarm_slock, flags); + if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_SET_AND_WAIT(0) + && cmd != ANDROID_ALARM_SET_AND_WAIT_OLD) + break; + /* fall though */ + case ANDROID_ALARM_WAIT: + spin_lock_irqsave(&alarm_slock, flags); + pr_alarm(IO, "alarm wait\n"); + if (!alarm_pending && wait_pending) { + wake_unlock(&alarm_wake_lock); + wait_pending = 0; + } + spin_unlock_irqrestore(&alarm_slock, flags); + rv = wait_event_interruptible(alarm_wait_queue, alarm_pending); + if (rv) + goto err1; + spin_lock_irqsave(&alarm_slock, flags); + rv = alarm_pending; + wait_pending = 1; + alarm_pending = 0; + spin_unlock_irqrestore(&alarm_slock, flags); + break; + case ANDROID_ALARM_SET_RTC: + if (copy_from_user(&new_rtc_time, (void __user *)arg, + sizeof(new_rtc_time))) { + rv = -EFAULT; + goto err1; + } + rv = alarm_set_rtc(new_rtc_time); + spin_lock_irqsave(&alarm_slock, flags); + alarm_pending |= ANDROID_ALARM_TIME_CHANGE_MASK; + wake_up(&alarm_wait_queue); + spin_unlock_irqrestore(&alarm_slock, flags); + if (rv < 0) + goto err1; + break; + case ANDROID_ALARM_GET_TIME(0): + switch (alarm_type) { + case ANDROID_ALARM_RTC_WAKEUP: + case ANDROID_ALARM_RTC: + getnstimeofday(&tmp_time); + break; + case ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP: + case ANDROID_ALARM_ELAPSED_REALTIME: + tmp_time = + ktime_to_timespec(alarm_get_elapsed_realtime()); + break; + case ANDROID_ALARM_TYPE_COUNT: + case ANDROID_ALARM_SYSTEMTIME: + ktime_get_ts(&tmp_time); + break; + } + if (copy_to_user((void __user *)arg, &tmp_time, + sizeof(tmp_time))) { + rv = -EFAULT; + goto err1; + } + break; + + default: + rv = -EINVAL; + goto err1; + } +err1: + return rv; +} + +static int alarm_open(struct inode *inode, struct file *file) +{ + file->private_data = NULL; + return 0; +} + +static int alarm_release(struct inode *inode, struct file *file) +{ + int i; + unsigned long flags; + + spin_lock_irqsave(&alarm_slock, flags); + if (file->private_data != 0) { + for (i = 0; i < ANDROID_ALARM_TYPE_COUNT; i++) { + uint32_t alarm_type_mask = 1U << i; + if (alarm_enabled & alarm_type_mask) { + pr_alarm(INFO, "alarm_release: clear alarm, " + "pending %d\n", + !!(alarm_pending & alarm_type_mask)); + alarm_enabled &= ~alarm_type_mask; + } + spin_unlock_irqrestore(&alarm_slock, flags); + alarm_cancel(&alarms[i]); + spin_lock_irqsave(&alarm_slock, flags); + } + if (alarm_pending | wait_pending) { + if (alarm_pending) + pr_alarm(INFO, "alarm_release: clear " + "pending alarms %x\n", alarm_pending); + wake_unlock(&alarm_wake_lock); + wait_pending = 0; + alarm_pending = 0; + } + alarm_opened = 0; + } + spin_unlock_irqrestore(&alarm_slock, flags); + return 0; +} + +static void alarm_triggered(struct alarm *alarm) +{ + unsigned long flags; + uint32_t alarm_type_mask = 1U << alarm->type; + + pr_alarm(INT, "alarm_triggered type %d\n", alarm->type); + spin_lock_irqsave(&alarm_slock, flags); + if (alarm_enabled & alarm_type_mask) { + wake_lock_timeout(&alarm_wake_lock, 5 * HZ); + alarm_enabled &= ~alarm_type_mask; + alarm_pending |= alarm_type_mask; + wake_up(&alarm_wait_queue); + } + spin_unlock_irqrestore(&alarm_slock, flags); +} + +static const struct file_operations alarm_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = alarm_ioctl, + .open = alarm_open, + .release = alarm_release, +}; + +static struct miscdevice alarm_device = { + .minor = MISC_DYNAMIC_MINOR, + .name = "alarm", + .fops = &alarm_fops, +}; + +static int __init alarm_dev_init(void) +{ + int err; + int i; + + err = misc_register(&alarm_device); + if (err) + return err; + + for (i = 0; i < ANDROID_ALARM_TYPE_COUNT; i++) + alarm_init(&alarms[i], i, alarm_triggered); + wake_lock_init(&alarm_wake_lock, WAKE_LOCK_SUSPEND, "alarm"); + + return 0; +} + +static void __exit alarm_dev_exit(void) +{ + misc_deregister(&alarm_device); + wake_lock_destroy(&alarm_wake_lock); +} + +module_init(alarm_dev_init); +module_exit(alarm_dev_exit); + diff --git a/drivers/staging/android/alarm.c b/drivers/staging/android/alarm.c new file mode 100644 index 0000000..c5bd51f --- /dev/null +++ b/drivers/staging/android/alarm.c @@ -0,0 +1,586 @@ +/* drivers/rtc/alarm.c + * + * Copyright (C) 2007-2009 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "android_alarm.h" + +#define ANDROID_ALARM_PRINT_ERROR (1U << 0) +#define ANDROID_ALARM_PRINT_INIT_STATUS (1U << 1) +#define ANDROID_ALARM_PRINT_TSET (1U << 2) +#define ANDROID_ALARM_PRINT_CALL (1U << 3) +#define ANDROID_ALARM_PRINT_SUSPEND (1U << 4) +#define ANDROID_ALARM_PRINT_INT (1U << 5) +#define ANDROID_ALARM_PRINT_FLOW (1U << 6) + +static int debug_mask = ANDROID_ALARM_PRINT_ERROR | \ + ANDROID_ALARM_PRINT_INIT_STATUS; +module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP); + +#define pr_alarm(debug_level_mask, args...) \ + do { \ + if (debug_mask & ANDROID_ALARM_PRINT_##debug_level_mask) { \ + pr_info(args); \ + } \ + } while (0) + +#define ANDROID_ALARM_WAKEUP_MASK ( \ + ANDROID_ALARM_RTC_WAKEUP_MASK | \ + ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP_MASK) + +/* support old usespace code */ +#define ANDROID_ALARM_SET_OLD _IOW('a', 2, time_t) /* set alarm */ +#define ANDROID_ALARM_SET_AND_WAIT_OLD _IOW('a', 3, time_t) + +struct alarm_queue { + struct rb_root alarms; + struct rb_node *first; + struct hrtimer timer; + ktime_t delta; + bool stopped; + ktime_t stopped_time; +}; + +static struct rtc_device *alarm_rtc_dev; +static DEFINE_SPINLOCK(alarm_slock); +static DEFINE_MUTEX(alarm_setrtc_mutex); +static struct wake_lock alarm_rtc_wake_lock; +static struct platform_device *alarm_platform_dev; +struct alarm_queue alarms[ANDROID_ALARM_TYPE_COUNT]; +static bool suspended; + +static void update_timer_locked(struct alarm_queue *base, bool head_removed) +{ + struct alarm *alarm; + bool is_wakeup = base == &alarms[ANDROID_ALARM_RTC_WAKEUP] || + base == &alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP]; + + if (base->stopped) { + pr_alarm(FLOW, "changed alarm while setting the wall time\n"); + return; + } + + if (is_wakeup && !suspended && head_removed) + wake_unlock(&alarm_rtc_wake_lock); + + if (!base->first) + return; + + alarm = container_of(base->first, struct alarm, node); + + pr_alarm(FLOW, "selected alarm, type %d, func %pF at %lld\n", + alarm->type, alarm->function, ktime_to_ns(alarm->expires)); + + if (is_wakeup && suspended) { + pr_alarm(FLOW, "changed alarm while suspened\n"); + wake_lock_timeout(&alarm_rtc_wake_lock, 1 * HZ); + return; + } + + hrtimer_try_to_cancel(&base->timer); + base->timer.node.expires = ktime_add(base->delta, alarm->expires); + base->timer._softexpires = ktime_add(base->delta, alarm->softexpires); + hrtimer_start_expires(&base->timer, HRTIMER_MODE_ABS); +} + +static void alarm_enqueue_locked(struct alarm *alarm) +{ + struct alarm_queue *base = &alarms[alarm->type]; + struct rb_node **link = &base->alarms.rb_node; + struct rb_node *parent = NULL; + struct alarm *entry; + int leftmost = 1; + + pr_alarm(FLOW, "added alarm, type %d, func %pF at %lld\n", + alarm->type, alarm->function, ktime_to_ns(alarm->expires)); + + if (base->first == &alarm->node) + base->first = rb_next(&alarm->node); + if (!RB_EMPTY_NODE(&alarm->node)) { + rb_erase(&alarm->node, &base->alarms); + RB_CLEAR_NODE(&alarm->node); + } + + while (*link) { + parent = *link; + entry = rb_entry(parent, struct alarm, node); + /* + * We dont care about collisions. Nodes with + * the same expiry time stay together. + */ + if (alarm->expires.tv64 < entry->expires.tv64) { + link = &(*link)->rb_left; + } else { + link = &(*link)->rb_right; + leftmost = 0; + } + } + if (leftmost) { + base->first = &alarm->node; + update_timer_locked(base, false); + } + + rb_link_node(&alarm->node, parent, link); + rb_insert_color(&alarm->node, &base->alarms); +} + +/** + * alarm_init - initialize an alarm + * @alarm: the alarm to be initialized + * @type: the alarm type to be used + * @function: alarm callback function + */ +void alarm_init(struct alarm *alarm, + enum android_alarm_type type, void (*function)(struct alarm *)) +{ + RB_CLEAR_NODE(&alarm->node); + alarm->type = type; + alarm->function = function; + + pr_alarm(FLOW, "created alarm, type %d, func %pF\n", type, function); +} + + +/** + * alarm_start_range - (re)start an alarm + * @alarm: the alarm to be added + * @start: earliest expiry time + * @end: expiry time + */ +void alarm_start_range(struct alarm *alarm, ktime_t start, ktime_t end) +{ + unsigned long flags; + + spin_lock_irqsave(&alarm_slock, flags); + alarm->softexpires = start; + alarm->expires = end; + alarm_enqueue_locked(alarm); + spin_unlock_irqrestore(&alarm_slock, flags); +} + +/** + * alarm_try_to_cancel - try to deactivate an alarm + * @alarm: alarm to stop + * + * Returns: + * 0 when the alarm was not active + * 1 when the alarm was active + * -1 when the alarm may currently be excuting the callback function and + * cannot be stopped (it may also be inactive) + */ +int alarm_try_to_cancel(struct alarm *alarm) +{ + struct alarm_queue *base = &alarms[alarm->type]; + unsigned long flags; + bool first = false; + int ret = 0; + + spin_lock_irqsave(&alarm_slock, flags); + if (!RB_EMPTY_NODE(&alarm->node)) { + pr_alarm(FLOW, "canceled alarm, type %d, func %pF at %lld\n", + alarm->type, alarm->function, + ktime_to_ns(alarm->expires)); + ret = 1; + if (base->first == &alarm->node) { + base->first = rb_next(&alarm->node); + first = true; + } + rb_erase(&alarm->node, &base->alarms); + RB_CLEAR_NODE(&alarm->node); + if (first) + update_timer_locked(base, true); + } else + pr_alarm(FLOW, "tried to cancel alarm, type %d, func %pF\n", + alarm->type, alarm->function); + spin_unlock_irqrestore(&alarm_slock, flags); + if (!ret && hrtimer_callback_running(&base->timer)) + ret = -1; + return ret; +} + +/** + * alarm_cancel - cancel an alarm and wait for the handler to finish. + * @alarm: the alarm to be cancelled + * + * Returns: + * 0 when the alarm was not active + * 1 when the alarm was active + */ +int alarm_cancel(struct alarm *alarm) +{ + for (;;) { + int ret = alarm_try_to_cancel(alarm); + if (ret >= 0) + return ret; + cpu_relax(); + } +} + +/** + * alarm_set_rtc - set the kernel and rtc walltime + * @new_time: timespec value containing the new time + */ +int alarm_set_rtc(struct timespec new_time) +{ + int i; + int ret; + unsigned long flags; + struct rtc_time rtc_new_rtc_time; + struct timespec tmp_time; + + rtc_time_to_tm(new_time.tv_sec, &rtc_new_rtc_time); + + pr_alarm(TSET, "set rtc %ld %ld - rtc %02d:%02d:%02d %02d/%02d/%04d\n", + new_time.tv_sec, new_time.tv_nsec, + rtc_new_rtc_time.tm_hour, rtc_new_rtc_time.tm_min, + rtc_new_rtc_time.tm_sec, rtc_new_rtc_time.tm_mon + 1, + rtc_new_rtc_time.tm_mday, + rtc_new_rtc_time.tm_year + 1900); + + mutex_lock(&alarm_setrtc_mutex); + spin_lock_irqsave(&alarm_slock, flags); + wake_lock(&alarm_rtc_wake_lock); + getnstimeofday(&tmp_time); + for (i = 0; i < ANDROID_ALARM_SYSTEMTIME; i++) { + hrtimer_try_to_cancel(&alarms[i].timer); + alarms[i].stopped = true; + alarms[i].stopped_time = timespec_to_ktime(tmp_time); + } + alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP].delta = + alarms[ANDROID_ALARM_ELAPSED_REALTIME].delta = + ktime_sub(alarms[ANDROID_ALARM_ELAPSED_REALTIME].delta, + timespec_to_ktime(timespec_sub(tmp_time, new_time))); + spin_unlock_irqrestore(&alarm_slock, flags); + ret = do_settimeofday(&new_time); + spin_lock_irqsave(&alarm_slock, flags); + for (i = 0; i < ANDROID_ALARM_SYSTEMTIME; i++) { + alarms[i].stopped = false; + update_timer_locked(&alarms[i], false); + } + spin_unlock_irqrestore(&alarm_slock, flags); + if (ret < 0) { + pr_alarm(ERROR, "alarm_set_rtc: Failed to set time\n"); + goto err; + } + if (!alarm_rtc_dev) { + pr_alarm(ERROR, + "alarm_set_rtc: no RTC, time will be lost on reboot\n"); + goto err; + } + ret = rtc_set_time(alarm_rtc_dev, &rtc_new_rtc_time); + if (ret < 0) + pr_alarm(ERROR, "alarm_set_rtc: " + "Failed to set RTC, time will be lost on reboot\n"); +err: + wake_unlock(&alarm_rtc_wake_lock); + mutex_unlock(&alarm_setrtc_mutex); + return ret; +} + +/** + * alarm_get_elapsed_realtime - get the elapsed real time in ktime_t format + * + * returns the time in ktime_t format + */ +ktime_t alarm_get_elapsed_realtime(void) +{ + ktime_t now; + unsigned long flags; + struct alarm_queue *base = &alarms[ANDROID_ALARM_ELAPSED_REALTIME]; + + spin_lock_irqsave(&alarm_slock, flags); + now = base->stopped ? base->stopped_time : ktime_get_real(); + now = ktime_sub(now, base->delta); + spin_unlock_irqrestore(&alarm_slock, flags); + return now; +} + +static enum hrtimer_restart alarm_timer_triggered(struct hrtimer *timer) +{ + struct alarm_queue *base; + struct alarm *alarm; + unsigned long flags; + ktime_t now; + + spin_lock_irqsave(&alarm_slock, flags); + + base = container_of(timer, struct alarm_queue, timer); + now = base->stopped ? base->stopped_time : hrtimer_cb_get_time(timer); + now = ktime_sub(now, base->delta); + + pr_alarm(INT, "alarm_timer_triggered type %d at %lld\n", + base - alarms, ktime_to_ns(now)); + + while (base->first) { + alarm = container_of(base->first, struct alarm, node); + if (alarm->softexpires.tv64 > now.tv64) { + pr_alarm(FLOW, "don't call alarm, %pF, %lld (s %lld)\n", + alarm->function, ktime_to_ns(alarm->expires), + ktime_to_ns(alarm->softexpires)); + break; + } + base->first = rb_next(&alarm->node); + rb_erase(&alarm->node, &base->alarms); + RB_CLEAR_NODE(&alarm->node); + pr_alarm(CALL, "call alarm, type %d, func %pF, %lld (s %lld)\n", + alarm->type, alarm->function, + ktime_to_ns(alarm->expires), + ktime_to_ns(alarm->softexpires)); + spin_unlock_irqrestore(&alarm_slock, flags); + alarm->function(alarm); + spin_lock_irqsave(&alarm_slock, flags); + } + if (!base->first) + pr_alarm(FLOW, "no more alarms of type %d\n", base - alarms); + update_timer_locked(base, true); + spin_unlock_irqrestore(&alarm_slock, flags); + return HRTIMER_NORESTART; +} + +static void alarm_triggered_func(void *p) +{ + struct rtc_device *rtc = alarm_rtc_dev; + if (!(rtc->irq_data & RTC_AF)) + return; + pr_alarm(INT, "rtc alarm triggered\n"); + wake_lock_timeout(&alarm_rtc_wake_lock, 1 * HZ); +} + +static int alarm_suspend(struct platform_device *pdev, pm_message_t state) +{ + int err = 0; + unsigned long flags; + struct rtc_wkalrm rtc_alarm; + struct rtc_time rtc_current_rtc_time; + unsigned long rtc_current_time; + unsigned long rtc_alarm_time; + struct timespec rtc_current_timespec; + struct timespec rtc_delta; + struct alarm_queue *wakeup_queue = NULL; + struct alarm_queue *tmp_queue = NULL; + + pr_alarm(SUSPEND, "alarm_suspend(%p, %d)\n", pdev, state.event); + + spin_lock_irqsave(&alarm_slock, flags); + suspended = true; + spin_unlock_irqrestore(&alarm_slock, flags); + + hrtimer_cancel(&alarms[ANDROID_ALARM_RTC_WAKEUP].timer); + hrtimer_cancel(&alarms[ + ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP_MASK].timer); + + tmp_queue = &alarms[ANDROID_ALARM_RTC_WAKEUP]; + if (tmp_queue->first) + wakeup_queue = tmp_queue; + tmp_queue = &alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP]; + if (tmp_queue->first && (!wakeup_queue || + hrtimer_get_expires(&tmp_queue->timer).tv64 < + hrtimer_get_expires(&wakeup_queue->timer).tv64)) + wakeup_queue = tmp_queue; + if (wakeup_queue) { + rtc_read_time(alarm_rtc_dev, &rtc_current_rtc_time); + rtc_current_timespec.tv_nsec = 0; + rtc_tm_to_time(&rtc_current_rtc_time, + &rtc_current_timespec.tv_sec); + save_time_delta(&rtc_delta, &rtc_current_timespec); + + rtc_alarm_time = timespec_sub(ktime_to_timespec( + hrtimer_get_expires(&wakeup_queue->timer)), + rtc_delta).tv_sec; + + rtc_time_to_tm(rtc_alarm_time, &rtc_alarm.time); + rtc_alarm.enabled = 1; + rtc_set_alarm(alarm_rtc_dev, &rtc_alarm); + rtc_read_time(alarm_rtc_dev, &rtc_current_rtc_time); + rtc_tm_to_time(&rtc_current_rtc_time, &rtc_current_time); + pr_alarm(SUSPEND, + "rtc alarm set at %ld, now %ld, rtc delta %ld.%09ld\n", + rtc_alarm_time, rtc_current_time, + rtc_delta.tv_sec, rtc_delta.tv_nsec); + if (rtc_current_time + 1 >= rtc_alarm_time) { + pr_alarm(SUSPEND, "alarm about to go off\n"); + memset(&rtc_alarm, 0, sizeof(rtc_alarm)); + rtc_alarm.enabled = 0; + rtc_set_alarm(alarm_rtc_dev, &rtc_alarm); + + spin_lock_irqsave(&alarm_slock, flags); + suspended = false; + wake_lock_timeout(&alarm_rtc_wake_lock, 2 * HZ); + update_timer_locked(&alarms[ANDROID_ALARM_RTC_WAKEUP], + false); + update_timer_locked(&alarms[ + ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP], false); + err = -EBUSY; + spin_unlock_irqrestore(&alarm_slock, flags); + } + } + return err; +} + +static int alarm_resume(struct platform_device *pdev) +{ + struct rtc_wkalrm alarm; + unsigned long flags; + + pr_alarm(SUSPEND, "alarm_resume(%p)\n", pdev); + + memset(&alarm, 0, sizeof(alarm)); + alarm.enabled = 0; + rtc_set_alarm(alarm_rtc_dev, &alarm); + + spin_lock_irqsave(&alarm_slock, flags); + suspended = false; + update_timer_locked(&alarms[ANDROID_ALARM_RTC_WAKEUP], false); + update_timer_locked(&alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP], + false); + spin_unlock_irqrestore(&alarm_slock, flags); + + return 0; +} + +static struct rtc_task alarm_rtc_task = { + .func = alarm_triggered_func +}; + +static int rtc_alarm_add_device(struct device *dev, + struct class_interface *class_intf) +{ + int err; + struct rtc_device *rtc = to_rtc_device(dev); + + mutex_lock(&alarm_setrtc_mutex); + + if (alarm_rtc_dev) { + err = -EBUSY; + goto err1; + } + + alarm_platform_dev = + platform_device_register_simple("alarm", -1, NULL, 0); + if (IS_ERR(alarm_platform_dev)) { + err = PTR_ERR(alarm_platform_dev); + goto err2; + } + err = rtc_irq_register(rtc, &alarm_rtc_task); + if (err) + goto err3; + alarm_rtc_dev = rtc; + pr_alarm(INIT_STATUS, "using rtc device, %s, for alarms", rtc->name); + mutex_unlock(&alarm_setrtc_mutex); + + return 0; + +err3: + platform_device_unregister(alarm_platform_dev); +err2: +err1: + mutex_unlock(&alarm_setrtc_mutex); + return err; +} + +static void rtc_alarm_remove_device(struct device *dev, + struct class_interface *class_intf) +{ + if (dev == &alarm_rtc_dev->dev) { + pr_alarm(INIT_STATUS, "lost rtc device for alarms"); + rtc_irq_unregister(alarm_rtc_dev, &alarm_rtc_task); + platform_device_unregister(alarm_platform_dev); + alarm_rtc_dev = NULL; + } +} + +static struct class_interface rtc_alarm_interface = { + .add_dev = &rtc_alarm_add_device, + .remove_dev = &rtc_alarm_remove_device, +}; + +static struct platform_driver alarm_driver = { + .suspend = alarm_suspend, + .resume = alarm_resume, + .driver = { + .name = "alarm" + } +}; + +static int __init alarm_late_init(void) +{ + unsigned long flags; + struct timespec tmp_time, system_time; + + /* this needs to run after the rtc is read at boot */ + spin_lock_irqsave(&alarm_slock, flags); + /* We read the current rtc and system time so we can later calulate + * elasped realtime to be (boot_systemtime + rtc - boot_rtc) == + * (rtc - (boot_rtc - boot_systemtime)) + */ + getnstimeofday(&tmp_time); + ktime_get_ts(&system_time); + alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP].delta = + alarms[ANDROID_ALARM_ELAPSED_REALTIME].delta = + timespec_to_ktime(timespec_sub(tmp_time, system_time)); + + spin_unlock_irqrestore(&alarm_slock, flags); + return 0; +} + +static int __init alarm_driver_init(void) +{ + int err; + int i; + + for (i = 0; i < ANDROID_ALARM_SYSTEMTIME; i++) { + hrtimer_init(&alarms[i].timer, + CLOCK_REALTIME, HRTIMER_MODE_ABS); + alarms[i].timer.function = alarm_timer_triggered; + } + hrtimer_init(&alarms[ANDROID_ALARM_SYSTEMTIME].timer, + CLOCK_MONOTONIC, HRTIMER_MODE_ABS); + alarms[ANDROID_ALARM_SYSTEMTIME].timer.function = alarm_timer_triggered; + err = platform_driver_register(&alarm_driver); + if (err < 0) + goto err1; + wake_lock_init(&alarm_rtc_wake_lock, WAKE_LOCK_SUSPEND, "alarm_rtc"); + rtc_alarm_interface.class = rtc_class; + err = class_interface_register(&rtc_alarm_interface); + if (err < 0) + goto err2; + + return 0; + +err2: + wake_lock_destroy(&alarm_rtc_wake_lock); + platform_driver_unregister(&alarm_driver); +err1: + return err; +} + +static void __exit alarm_exit(void) +{ + class_interface_unregister(&rtc_alarm_interface); + wake_lock_destroy(&alarm_rtc_wake_lock); + platform_driver_unregister(&alarm_driver); +} + +late_initcall(alarm_late_init); +module_init(alarm_driver_init); +module_exit(alarm_exit); + diff --git a/drivers/staging/android/android_alarm.h b/drivers/staging/android/android_alarm.h new file mode 100644 index 0000000..753ed93 --- /dev/null +++ b/drivers/staging/android/android_alarm.h @@ -0,0 +1,106 @@ +/* include/linux/android_alarm.h + * + * Copyright (C) 2006-2007 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +#ifndef _LINUX_ANDROID_ALARM_H +#define _LINUX_ANDROID_ALARM_H + +#include +#include + +enum android_alarm_type { + /* return code bit numbers or set alarm arg */ + ANDROID_ALARM_RTC_WAKEUP, + ANDROID_ALARM_RTC, + ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP, + ANDROID_ALARM_ELAPSED_REALTIME, + ANDROID_ALARM_SYSTEMTIME, + + ANDROID_ALARM_TYPE_COUNT, + + /* return code bit numbers */ + /* ANDROID_ALARM_TIME_CHANGE = 16 */ +}; + +#ifdef __KERNEL__ + +#include +#include + +/* + * The alarm interface is similar to the hrtimer interface but adds support + * for wakeup from suspend. It also adds an elapsed realtime clock that can + * be used for periodic timers that need to keep runing while the system is + * suspended and not be disrupted when the wall time is set. + */ + +/** + * struct alarm - the basic alarm structure + * @node: red black tree node for time ordered insertion + * @type: alarm type. rtc/elapsed-realtime/systemtime, wakeup/non-wakeup. + * @softexpires: the absolute earliest expiry time of the alarm. + * @expires: the absolute expiry time. + * @function: alarm expiry callback function + * + * The alarm structure must be initialized by alarm_init() + * + */ + +struct alarm { + struct rb_node node; + enum android_alarm_type type; + ktime_t softexpires; + ktime_t expires; + void (*function)(struct alarm *); +}; + +void alarm_init(struct alarm *alarm, + enum android_alarm_type type, void (*function)(struct alarm *)); +void alarm_start_range(struct alarm *alarm, ktime_t start, ktime_t end); +int alarm_try_to_cancel(struct alarm *alarm); +int alarm_cancel(struct alarm *alarm); +ktime_t alarm_get_elapsed_realtime(void); + +/* set rtc while preserving elapsed realtime */ +int alarm_set_rtc(const struct timespec ts); + +#endif + +enum android_alarm_return_flags { + ANDROID_ALARM_RTC_WAKEUP_MASK = 1U << ANDROID_ALARM_RTC_WAKEUP, + ANDROID_ALARM_RTC_MASK = 1U << ANDROID_ALARM_RTC, + ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP_MASK = + 1U << ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP, + ANDROID_ALARM_ELAPSED_REALTIME_MASK = + 1U << ANDROID_ALARM_ELAPSED_REALTIME, + ANDROID_ALARM_SYSTEMTIME_MASK = 1U << ANDROID_ALARM_SYSTEMTIME, + ANDROID_ALARM_TIME_CHANGE_MASK = 1U << 16 +}; + +/* Disable alarm */ +#define ANDROID_ALARM_CLEAR(type) _IO('a', 0 | ((type) << 4)) + +/* Ack last alarm and wait for next */ +#define ANDROID_ALARM_WAIT _IO('a', 1) + +#define ALARM_IOW(c, type, size) _IOW('a', (c) | ((type) << 4), size) +/* Set alarm */ +#define ANDROID_ALARM_SET(type) ALARM_IOW(2, type, struct timespec) +#define ANDROID_ALARM_SET_AND_WAIT(type) ALARM_IOW(3, type, struct timespec) +#define ANDROID_ALARM_GET_TIME(type) ALARM_IOW(4, type, struct timespec) +#define ANDROID_ALARM_SET_RTC _IOW('a', 5, struct timespec) +#define ANDROID_ALARM_BASE_CMD(cmd) (cmd & ~(_IOC(0, 0, 0xf0, 0))) +#define ANDROID_ALARM_IOCTL_TO_TYPE(cmd) (_IOC_NR(cmd) >> 4) + +#endif -- cgit v0.10.2 From 5dd12c29b45f27d059e4bd58ff1854bc6a236804 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arve=20Hj=C3=B8nnev=C3=A5g?= Date: Thu, 9 Feb 2012 14:24:31 -0800 Subject: staging: android-alarm: Don't use save_time_delta. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove references to non-existant save_time_delta. Change-Id: Iaefeca497de02fe36b7f5d79075912f6e349ec53 CC: Arve HjønnevÃ¥g CC: Android Kernel Team Signed-off-by: Arve HjønnevÃ¥g [Added commit message -jstultz] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/android/alarm.c b/drivers/staging/android/alarm.c index c5bd51f..bc59ac4 100644 --- a/drivers/staging/android/alarm.c +++ b/drivers/staging/android/alarm.c @@ -373,8 +373,8 @@ static int alarm_suspend(struct platform_device *pdev, pm_message_t state) struct rtc_time rtc_current_rtc_time; unsigned long rtc_current_time; unsigned long rtc_alarm_time; - struct timespec rtc_current_timespec; struct timespec rtc_delta; + struct timespec wall_time; struct alarm_queue *wakeup_queue = NULL; struct alarm_queue *tmp_queue = NULL; @@ -398,10 +398,11 @@ static int alarm_suspend(struct platform_device *pdev, pm_message_t state) wakeup_queue = tmp_queue; if (wakeup_queue) { rtc_read_time(alarm_rtc_dev, &rtc_current_rtc_time); - rtc_current_timespec.tv_nsec = 0; - rtc_tm_to_time(&rtc_current_rtc_time, - &rtc_current_timespec.tv_sec); - save_time_delta(&rtc_delta, &rtc_current_timespec); + getnstimeofday(&wall_time); + rtc_tm_to_time(&rtc_current_rtc_time, &rtc_current_time); + set_normalized_timespec(&rtc_delta, + wall_time.tv_sec - rtc_current_time, + wall_time.tv_nsec); rtc_alarm_time = timespec_sub(ktime_to_timespec( hrtimer_get_expires(&wakeup_queue->timer)), -- cgit v0.10.2 From bf647ea717e529fc4f3dfa17dffd40da10522b00 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 9 Feb 2012 14:24:32 -0800 Subject: staging: android-alarm: Add needed module.h includes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add module.h includes required to build CC: Arve HjønnevÃ¥g CC: Android Kernel Team CC: Andy Green Signed-off-by: Andy Green [jstultz: Tweaked commit subject, folded two patches into one] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/android/alarm-dev.c b/drivers/staging/android/alarm-dev.c index ae56961..7391f40 100644 --- a/drivers/staging/android/alarm-dev.c +++ b/drivers/staging/android/alarm-dev.c @@ -14,6 +14,7 @@ */ #include +#include #include #include #include diff --git a/drivers/staging/android/alarm.c b/drivers/staging/android/alarm.c index bc59ac4..c16032b 100644 --- a/drivers/staging/android/alarm.c +++ b/drivers/staging/android/alarm.c @@ -14,6 +14,7 @@ */ #include +#include #include #include #include -- cgit v0.10.2 From d47908b20c4cc22c2700ca737252bdc555d4f28a Mon Sep 17 00:00:00 2001 From: John Stultz Date: Thu, 9 Feb 2012 14:24:33 -0800 Subject: staging: android-alarm: Fix include compile issues MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The file asm/mach/time.h doesn't exist on all arches, so include . Also linux/sysdev.h is gone so kill it. CC: Arve HjønnevÃ¥g CC: Android Kernel Team Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/android/alarm-dev.c b/drivers/staging/android/alarm-dev.c index 7391f40..80ea850 100644 --- a/drivers/staging/android/alarm-dev.c +++ b/drivers/staging/android/alarm-dev.c @@ -13,7 +13,7 @@ * */ -#include +#include #include #include #include @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include "android_alarm.h" diff --git a/drivers/staging/android/alarm.c b/drivers/staging/android/alarm.c index c16032b..7aaf5b8 100644 --- a/drivers/staging/android/alarm.c +++ b/drivers/staging/android/alarm.c @@ -13,7 +13,7 @@ * */ -#include +#include #include #include #include @@ -21,7 +21,6 @@ #include #include #include -#include #include #include "android_alarm.h" -- cgit v0.10.2 From f2f28eacf240baffbba5e9744278f85fc62ddd60 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Thu, 9 Feb 2012 14:24:34 -0800 Subject: staging: android-alarm: Fix namespace collision with upstreamed alarmtimers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The upstreamed alarmtimers are similar but not quite 100% API compatibile with the android in-kernel alarm api. To aid the transition, prefix the the android in-kernel api with android_ CC: Arve HjønnevÃ¥g CC: Android Kernel Team Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/android/alarm-dev.c b/drivers/staging/android/alarm-dev.c index 80ea850..758d828 100644 --- a/drivers/staging/android/alarm-dev.c +++ b/drivers/staging/android/alarm-dev.c @@ -55,7 +55,7 @@ static uint32_t alarm_pending; static uint32_t alarm_enabled; static uint32_t wait_pending; -static struct alarm alarms[ANDROID_ALARM_TYPE_COUNT]; +static struct android_alarm alarms[ANDROID_ALARM_TYPE_COUNT]; static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { @@ -90,7 +90,7 @@ static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case ANDROID_ALARM_CLEAR(0): spin_lock_irqsave(&alarm_slock, flags); pr_alarm(IO, "alarm %d clear\n", alarm_type); - alarm_try_to_cancel(&alarms[alarm_type]); + android_alarm_try_to_cancel(&alarms[alarm_type]); if (alarm_pending) { alarm_pending &= ~alarm_type_mask; if (!alarm_pending && !wait_pending) @@ -121,7 +121,7 @@ from_old_alarm_set: pr_alarm(IO, "alarm %d set %ld.%09ld\n", alarm_type, new_alarm_time.tv_sec, new_alarm_time.tv_nsec); alarm_enabled |= alarm_type_mask; - alarm_start_range(&alarms[alarm_type], + android_alarm_start_range(&alarms[alarm_type], timespec_to_ktime(new_alarm_time), timespec_to_ktime(new_alarm_time)); spin_unlock_irqrestore(&alarm_slock, flags); @@ -152,7 +152,7 @@ from_old_alarm_set: rv = -EFAULT; goto err1; } - rv = alarm_set_rtc(new_rtc_time); + rv = android_alarm_set_rtc(new_rtc_time); spin_lock_irqsave(&alarm_slock, flags); alarm_pending |= ANDROID_ALARM_TIME_CHANGE_MASK; wake_up(&alarm_wait_queue); @@ -213,7 +213,7 @@ static int alarm_release(struct inode *inode, struct file *file) alarm_enabled &= ~alarm_type_mask; } spin_unlock_irqrestore(&alarm_slock, flags); - alarm_cancel(&alarms[i]); + android_alarm_cancel(&alarms[i]); spin_lock_irqsave(&alarm_slock, flags); } if (alarm_pending | wait_pending) { @@ -230,7 +230,7 @@ static int alarm_release(struct inode *inode, struct file *file) return 0; } -static void alarm_triggered(struct alarm *alarm) +static void alarm_triggered(struct android_alarm *alarm) { unsigned long flags; uint32_t alarm_type_mask = 1U << alarm->type; @@ -269,7 +269,7 @@ static int __init alarm_dev_init(void) return err; for (i = 0; i < ANDROID_ALARM_TYPE_COUNT; i++) - alarm_init(&alarms[i], i, alarm_triggered); + android_alarm_init(&alarms[i], i, alarm_triggered); wake_lock_init(&alarm_wake_lock, WAKE_LOCK_SUSPEND, "alarm"); return 0; diff --git a/drivers/staging/android/alarm.c b/drivers/staging/android/alarm.c index 7aaf5b8..1f8bb5c 100644 --- a/drivers/staging/android/alarm.c +++ b/drivers/staging/android/alarm.c @@ -70,7 +70,7 @@ static bool suspended; static void update_timer_locked(struct alarm_queue *base, bool head_removed) { - struct alarm *alarm; + struct android_alarm *alarm; bool is_wakeup = base == &alarms[ANDROID_ALARM_RTC_WAKEUP] || base == &alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP]; @@ -85,7 +85,7 @@ static void update_timer_locked(struct alarm_queue *base, bool head_removed) if (!base->first) return; - alarm = container_of(base->first, struct alarm, node); + alarm = container_of(base->first, struct android_alarm, node); pr_alarm(FLOW, "selected alarm, type %d, func %pF at %lld\n", alarm->type, alarm->function, ktime_to_ns(alarm->expires)); @@ -102,12 +102,12 @@ static void update_timer_locked(struct alarm_queue *base, bool head_removed) hrtimer_start_expires(&base->timer, HRTIMER_MODE_ABS); } -static void alarm_enqueue_locked(struct alarm *alarm) +static void alarm_enqueue_locked(struct android_alarm *alarm) { struct alarm_queue *base = &alarms[alarm->type]; struct rb_node **link = &base->alarms.rb_node; struct rb_node *parent = NULL; - struct alarm *entry; + struct android_alarm *entry; int leftmost = 1; pr_alarm(FLOW, "added alarm, type %d, func %pF at %lld\n", @@ -122,7 +122,7 @@ static void alarm_enqueue_locked(struct alarm *alarm) while (*link) { parent = *link; - entry = rb_entry(parent, struct alarm, node); + entry = rb_entry(parent, struct android_alarm, node); /* * We dont care about collisions. Nodes with * the same expiry time stay together. @@ -144,13 +144,13 @@ static void alarm_enqueue_locked(struct alarm *alarm) } /** - * alarm_init - initialize an alarm + * android_alarm_init - initialize an alarm * @alarm: the alarm to be initialized * @type: the alarm type to be used * @function: alarm callback function */ -void alarm_init(struct alarm *alarm, - enum android_alarm_type type, void (*function)(struct alarm *)) +void android_alarm_init(struct android_alarm *alarm, + enum android_alarm_type type, void (*function)(struct android_alarm *)) { RB_CLEAR_NODE(&alarm->node); alarm->type = type; @@ -161,12 +161,13 @@ void alarm_init(struct alarm *alarm, /** - * alarm_start_range - (re)start an alarm + * android_alarm_start_range - (re)start an alarm * @alarm: the alarm to be added * @start: earliest expiry time * @end: expiry time */ -void alarm_start_range(struct alarm *alarm, ktime_t start, ktime_t end) +void android_alarm_start_range(struct android_alarm *alarm, ktime_t start, + ktime_t end) { unsigned long flags; @@ -178,7 +179,7 @@ void alarm_start_range(struct alarm *alarm, ktime_t start, ktime_t end) } /** - * alarm_try_to_cancel - try to deactivate an alarm + * android_alarm_try_to_cancel - try to deactivate an alarm * @alarm: alarm to stop * * Returns: @@ -187,7 +188,7 @@ void alarm_start_range(struct alarm *alarm, ktime_t start, ktime_t end) * -1 when the alarm may currently be excuting the callback function and * cannot be stopped (it may also be inactive) */ -int alarm_try_to_cancel(struct alarm *alarm) +int android_alarm_try_to_cancel(struct android_alarm *alarm) { struct alarm_queue *base = &alarms[alarm->type]; unsigned long flags; @@ -218,17 +219,17 @@ int alarm_try_to_cancel(struct alarm *alarm) } /** - * alarm_cancel - cancel an alarm and wait for the handler to finish. + * android_alarm_cancel - cancel an alarm and wait for the handler to finish. * @alarm: the alarm to be cancelled * * Returns: * 0 when the alarm was not active * 1 when the alarm was active */ -int alarm_cancel(struct alarm *alarm) +int android_alarm_cancel(struct android_alarm *alarm) { for (;;) { - int ret = alarm_try_to_cancel(alarm); + int ret = android_alarm_try_to_cancel(alarm); if (ret >= 0) return ret; cpu_relax(); @@ -239,7 +240,7 @@ int alarm_cancel(struct alarm *alarm) * alarm_set_rtc - set the kernel and rtc walltime * @new_time: timespec value containing the new time */ -int alarm_set_rtc(struct timespec new_time) +int android_alarm_set_rtc(struct timespec new_time) { int i; int ret; @@ -317,7 +318,7 @@ ktime_t alarm_get_elapsed_realtime(void) static enum hrtimer_restart alarm_timer_triggered(struct hrtimer *timer) { struct alarm_queue *base; - struct alarm *alarm; + struct android_alarm *alarm; unsigned long flags; ktime_t now; @@ -331,7 +332,7 @@ static enum hrtimer_restart alarm_timer_triggered(struct hrtimer *timer) base - alarms, ktime_to_ns(now)); while (base->first) { - alarm = container_of(base->first, struct alarm, node); + alarm = container_of(base->first, struct android_alarm, node); if (alarm->softexpires.tv64 > now.tv64) { pr_alarm(FLOW, "don't call alarm, %pF, %lld (s %lld)\n", alarm->function, ktime_to_ns(alarm->expires), diff --git a/drivers/staging/android/android_alarm.h b/drivers/staging/android/android_alarm.h index 753ed93..9213581 100644 --- a/drivers/staging/android/android_alarm.h +++ b/drivers/staging/android/android_alarm.h @@ -57,23 +57,24 @@ enum android_alarm_type { * */ -struct alarm { +struct android_alarm { struct rb_node node; enum android_alarm_type type; ktime_t softexpires; ktime_t expires; - void (*function)(struct alarm *); + void (*function)(struct android_alarm *); }; -void alarm_init(struct alarm *alarm, - enum android_alarm_type type, void (*function)(struct alarm *)); -void alarm_start_range(struct alarm *alarm, ktime_t start, ktime_t end); -int alarm_try_to_cancel(struct alarm *alarm); -int alarm_cancel(struct alarm *alarm); +void android_alarm_init(struct android_alarm *alarm, + enum android_alarm_type type, void (*function)(struct android_alarm *)); +void android_alarm_start_range(struct android_alarm *alarm, ktime_t start, + ktime_t end); +int android_alarm_try_to_cancel(struct android_alarm *alarm); +int android_alarm_cancel(struct android_alarm *alarm); ktime_t alarm_get_elapsed_realtime(void); /* set rtc while preserving elapsed realtime */ -int alarm_set_rtc(const struct timespec ts); +int android_alarm_set_rtc(const struct timespec ts); #endif -- cgit v0.10.2 From 79ef07162fb088f8afe7709881e2b5e2a4098202 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Thu, 9 Feb 2012 14:24:35 -0800 Subject: staging: android-alarm: HACK: wakelock workaround MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allow Android alarmtimer device to build while wakelocks are still out of tree. CC: Arve HjønnevÃ¥g CC: Android Kernel Team Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/android/alarm-dev.c b/drivers/staging/android/alarm-dev.c index 758d828..03efb34 100644 --- a/drivers/staging/android/alarm-dev.c +++ b/drivers/staging/android/alarm-dev.c @@ -22,13 +22,24 @@ #include #include #include -#include #include "android_alarm.h" +/* XXX - Hack out wakelocks, while they are out of tree */ +struct wake_lock { + int i; +}; +#define wake_lock(x) +#define wake_lock_timeout(x, y) +#define wake_unlock(x) +#define WAKE_LOCK_SUSPEND 0 +#define wake_lock_init(x, y, z) ((x)->i = 1) +#define wake_lock_destroy(x) + #define ANDROID_ALARM_PRINT_INFO (1U << 0) #define ANDROID_ALARM_PRINT_IO (1U << 1) #define ANDROID_ALARM_PRINT_INT (1U << 2) + static int debug_mask = ANDROID_ALARM_PRINT_INFO; module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP); diff --git a/drivers/staging/android/alarm.c b/drivers/staging/android/alarm.c index 1f8bb5c..5370fdc 100644 --- a/drivers/staging/android/alarm.c +++ b/drivers/staging/android/alarm.c @@ -21,9 +21,19 @@ #include #include #include -#include #include "android_alarm.h" +/* XXX - Hack out wakelocks, while they are out of tree */ +struct wake_lock { + int i; +}; +#define wake_lock(x) +#define wake_lock_timeout(x, y) +#define wake_unlock(x) +#define WAKE_LOCK_SUSPEND 0 +#define wake_lock_init(x, y, z) ((x)->i = 1) +#define wake_lock_destroy(x) + #define ANDROID_ALARM_PRINT_ERROR (1U << 0) #define ANDROID_ALARM_PRINT_INIT_STATUS (1U << 1) #define ANDROID_ALARM_PRINT_TSET (1U << 2) -- cgit v0.10.2 From fe8d2727ffa65bcb516b4947bec1c546841e7d25 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Thu, 9 Feb 2012 14:24:36 -0800 Subject: staging: android-alarm: Reenable android alarm driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that it builds, re-enable android alarm driver in the makefile and kconfig CC: Arve HjønnevÃ¥g CC: Android Kernel Team Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig index becf711..2a2b386 100644 --- a/drivers/staging/android/Kconfig +++ b/drivers/staging/android/Kconfig @@ -105,6 +105,23 @@ config ANDROID_PMEM source "drivers/staging/android/switch/Kconfig" +config ANDROID_INTF_ALARM + bool "Android alarm driver" + depends on RTC_CLASS + default y + help + Provides non-wakeup and rtc backed wakeup alarms based on rtc or + elapsed realtime, and a non-wakeup alarm on the monotonic clock. + Also provides an interface to set the wall time which must be used + for elapsed realtime to work. + +config ANDROID_INTF_ALARM_DEV + bool "Android alarm device" + depends on ANDROID_INTF_ALARM + default y + help + Exports the alarm interface to user-space. + endif # if ANDROID endmenu diff --git a/drivers/staging/android/Makefile b/drivers/staging/android/Makefile index eaed1ff..7c6e53b 100644 --- a/drivers/staging/android/Makefile +++ b/drivers/staging/android/Makefile @@ -7,3 +7,5 @@ obj-$(CONFIG_ANDROID_TIMED_GPIO) += timed_gpio.o obj-$(CONFIG_ANDROID_LOW_MEMORY_KILLER) += lowmemorykiller.o obj-$(CONFIG_ANDROID_PMEM) += pmem.o obj-$(CONFIG_ANDROID_SWITCH) += switch/ +obj-$(CONFIG_ANDROID_INTF_ALARM) += alarm.o +obj-$(CONFIG_ANDROID_INTF_ALARM_DEV) += alarm-dev.o -- cgit v0.10.2 From 58a38ff3b12ebd103e3ca2c5dea3292ffbfd0f02 Mon Sep 17 00:00:00 2001 From: Praneeth Kumar Bajjuri Date: Thu, 9 Feb 2012 14:24:37 -0800 Subject: staging: android-alarm: Disable Android alarm driver by default MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Do not enable Android alarm driver by default CC: Arve HjønnevÃ¥g CC: Android Kernel Team CC: Praneeth Bajjuri Change-Id: Iff8f7a65c4eceecfd084074937c72824697b5e7f Signed-off-by: Praneeth Bajjuri [jstultz: tweaked commit subject & msg] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig index 2a2b386..6bb4fa8 100644 --- a/drivers/staging/android/Kconfig +++ b/drivers/staging/android/Kconfig @@ -108,7 +108,7 @@ source "drivers/staging/android/switch/Kconfig" config ANDROID_INTF_ALARM bool "Android alarm driver" depends on RTC_CLASS - default y + default n help Provides non-wakeup and rtc backed wakeup alarms based on rtc or elapsed realtime, and a non-wakeup alarm on the monotonic clock. -- cgit v0.10.2 From 66c48107719b751e8ec360034bc84ee1511147e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arve=20Hj=C3=B8nnev=C3=A5g?= Date: Thu, 9 Feb 2012 14:24:38 -0800 Subject: staging: android-alarm: Update hrtimer if alarm at the head of the queue is reprogrammed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If an alarm was restarted with a value that moved it away from the head of a queue, the hrtimer would not be updated. This would cause unnecessary wakeups. CC: Arve HjønnevÃ¥g CC: Android Kernel Team Change-Id: If379f8dd92b0bdb3173bd8d057adfe0dc1d15259 Signed-off-by: Arve HjønnevÃ¥g Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/android/alarm.c b/drivers/staging/android/alarm.c index 5370fdc..445c0b1 100644 --- a/drivers/staging/android/alarm.c +++ b/drivers/staging/android/alarm.c @@ -119,12 +119,15 @@ static void alarm_enqueue_locked(struct android_alarm *alarm) struct rb_node *parent = NULL; struct android_alarm *entry; int leftmost = 1; + bool was_first = false; pr_alarm(FLOW, "added alarm, type %d, func %pF at %lld\n", alarm->type, alarm->function, ktime_to_ns(alarm->expires)); - if (base->first == &alarm->node) + if (base->first == &alarm->node) { base->first = rb_next(&alarm->node); + was_first = true; + } if (!RB_EMPTY_NODE(&alarm->node)) { rb_erase(&alarm->node, &base->alarms); RB_CLEAR_NODE(&alarm->node); @@ -144,10 +147,10 @@ static void alarm_enqueue_locked(struct android_alarm *alarm) leftmost = 0; } } - if (leftmost) { + if (leftmost) base->first = &alarm->node; - update_timer_locked(base, false); - } + if (leftmost || was_first) + update_timer_locked(base, was_first); rb_link_node(&alarm->node, parent, link); rb_insert_color(&alarm->node, &base->alarms); -- cgit v0.10.2 From f2d3c6898abd6c5d69e6d1504413434df1ea2538 Mon Sep 17 00:00:00 2001 From: JP Abgrall Date: Thu, 9 Feb 2012 14:24:39 -0800 Subject: staging: android-alarm: Fix bad index when canceling alarms[] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It was using ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP_MASK as an index. CC: Arve HjønnevÃ¥g CC: Android Kernel Team CC: JP Abgrall Change-Id: I919860cc71254453e382616bce9fd5455802cb3d Signed-off-by: JP Abgrall [jstultz: Tweaked commit subject] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/android/alarm.c b/drivers/staging/android/alarm.c index 445c0b1..642a22f 100644 --- a/drivers/staging/android/alarm.c +++ b/drivers/staging/android/alarm.c @@ -400,7 +400,7 @@ static int alarm_suspend(struct platform_device *pdev, pm_message_t state) hrtimer_cancel(&alarms[ANDROID_ALARM_RTC_WAKEUP].timer); hrtimer_cancel(&alarms[ - ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP_MASK].timer); + ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP].timer); tmp_queue = &alarms[ANDROID_ALARM_RTC_WAKEUP]; if (tmp_queue->first) -- cgit v0.10.2 From 7f9b98a39bdd12db051514eb0daff689c34b8b4e Mon Sep 17 00:00:00 2001 From: John Stultz Date: Thu, 9 Feb 2012 14:24:40 -0800 Subject: staging: android-alarm: Fixup minor pr_alarm warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch fixes the following warnings: drivers/staging/android/alarm.c: In function ‘alarm_timer_triggered’: drivers/staging/android/alarm.c:344: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘long int’ drivers/staging/android/alarm.c:367: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘long int’ CC: Arve HjønnevÃ¥g CC: Android Kernel Team Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/android/alarm.c b/drivers/staging/android/alarm.c index 642a22f..c68950b 100644 --- a/drivers/staging/android/alarm.c +++ b/drivers/staging/android/alarm.c @@ -341,7 +341,7 @@ static enum hrtimer_restart alarm_timer_triggered(struct hrtimer *timer) now = base->stopped ? base->stopped_time : hrtimer_cb_get_time(timer); now = ktime_sub(now, base->delta); - pr_alarm(INT, "alarm_timer_triggered type %d at %lld\n", + pr_alarm(INT, "alarm_timer_triggered type %ld at %lld\n", base - alarms, ktime_to_ns(now)); while (base->first) { @@ -364,7 +364,7 @@ static enum hrtimer_restart alarm_timer_triggered(struct hrtimer *timer) spin_lock_irqsave(&alarm_slock, flags); } if (!base->first) - pr_alarm(FLOW, "no more alarms of type %d\n", base - alarms); + pr_alarm(FLOW, "no more alarms of type %ld\n", base - alarms); update_timer_locked(base, true); spin_unlock_irqrestore(&alarm_slock, flags); return HRTIMER_NORESTART; -- cgit v0.10.2 From 2157f896774ace6e98c851878f8089fb861502e2 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Thu, 9 Feb 2012 14:24:41 -0800 Subject: staging: android-alarm: Support old drivers via preprocessor aliasing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Older out of tree drivers that were desgined to the Android Alarm in-kernel API may not build due to the namespace collision fixed in an earlier patch. Per Arve's suggestion, this patch provides preprocessor macros that allow older drivers to build. CC: Arve HjønnevÃ¥g CC: Android Kernel Team Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig index 6bb4fa8..75ca225 100644 --- a/drivers/staging/android/Kconfig +++ b/drivers/staging/android/Kconfig @@ -122,6 +122,15 @@ config ANDROID_INTF_ALARM_DEV help Exports the alarm interface to user-space. +config ANDROID_ALARM_OLDDRV_COMPAT + bool "Android Alarm compatability with old drivers" + depends on ANDROID_INTF_ALARM + default n + help + Provides preprocessor alias to aid compatability with + older out-of-tree drivers that use the Android Alarm + in-kernel API. This will be removed eventually. + endif # if ANDROID endmenu diff --git a/drivers/staging/android/android_alarm.h b/drivers/staging/android/android_alarm.h index 9213581..6eecbde 100644 --- a/drivers/staging/android/android_alarm.h +++ b/drivers/staging/android/android_alarm.h @@ -76,6 +76,20 @@ ktime_t alarm_get_elapsed_realtime(void); /* set rtc while preserving elapsed realtime */ int android_alarm_set_rtc(const struct timespec ts); +#ifdef CONFIG_ANDROID_ALARM_OLDDRV_COMPAT +/* + * Some older drivers depend on the old API, + * so provide compatability macros for now. + */ +#define alarm android_alarm +#define alarm_init(x, y, z) android_alarm_init(x, y, z) +#define alarm_start_range(x, y, z) android_alarm_start_range(x, y, z) +#define alarm_try_to_cancel(x) android_alarm_try_to_cancel(x) +#define alarm_cancel(x) android_alarm_cancel(x) +#define alarm_set_rtc(x) android_alarm_set_rtc(x) +#endif + + #endif enum android_alarm_return_flags { -- cgit v0.10.2 From ffcf12810ca11891deb580d166af13fae294fe2e Mon Sep 17 00:00:00 2001 From: "Mark A. Allyn" Date: Fri, 10 Feb 2012 13:52:27 +0000 Subject: staging: sep: Add new PCI identifier [This is picked out of the differences between the upstream driver and the staging driver. I'm resolving the differences as a series of updates -AC] Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/sep/sep_driver_hw_defs.h b/drivers/staging/sep/sep_driver_hw_defs.h index c48e49a..a6a4481 100644 --- a/drivers/staging/sep/sep_driver_hw_defs.h +++ b/drivers/staging/sep/sep_driver_hw_defs.h @@ -33,9 +33,6 @@ #ifndef SEP_DRIVER_HW_DEFS__H #define SEP_DRIVER_HW_DEFS__H -/* PCI ID's */ -#define MFLD_PCI_DEVICE_ID 0x0826 - /*----------------------- */ /* HW Registers Defines. */ /* */ diff --git a/drivers/staging/sep/sep_main.c b/drivers/staging/sep/sep_main.c index 7f8362c..421a2b1 100644 --- a/drivers/staging/sep/sep_main.c +++ b/drivers/staging/sep/sep_main.c @@ -4085,8 +4085,9 @@ static void sep_remove(struct pci_dev *pdev) /* Initialize struct pci_device_id for our driver */ static DEFINE_PCI_DEVICE_TABLE(sep_pci_id_tbl) = { - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MFLD_PCI_DEVICE_ID)}, - {0} + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0826)}, + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x08e9)}, + {0} }; /* Export our pci_device_id structure to user space */ -- cgit v0.10.2 From aca58ec828af52516816ec48e75a78f043e508c7 Mon Sep 17 00:00:00 2001 From: "Mark A. Allyn" Date: Fri, 10 Feb 2012 13:52:42 +0000 Subject: staging: sep: Basic infrastructure for SEP DMA access to non CPU regions [This is picked out of the differences between the upstream driver and the staging driver. I'm resolving the differences as a series of updates -AC] Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/sep/sep_driver_api.h b/drivers/staging/sep/sep_driver_api.h index 78a4b69..8b797d5 100644 --- a/drivers/staging/sep/sep_driver_api.h +++ b/drivers/staging/sep/sep_driver_api.h @@ -61,7 +61,9 @@ enum hash_stage { HASH_INIT, HASH_UPDATE, HASH_FINISH, - HASH_DIGEST + HASH_DIGEST, + HASH_FINUP_DATA, + HASH_FINUP_FINISH }; /* @@ -205,6 +207,7 @@ struct sep_lli_entry { */ struct sep_fastcall_hdr { u32 magic; + u32 secure_dma; u32 msg_len; u32 num_dcbs; }; @@ -231,6 +234,8 @@ struct sep_dma_context { u32 dmatables_len; /* size of input data */ u32 input_data_len; + /* secure dma use (for imr memory restriced area in output */ + bool secure_dma; struct sep_dma_resource dma_res_arr[SEP_MAX_NUM_SYNC_DMA_OPS]; /* Scatter gather for kernel crypto */ struct scatterlist *src_sg; @@ -317,6 +322,7 @@ ssize_t sep_activate_dcb_dmatables_context(struct sep_device *sep, * @tail_block_size: u32; for size of tail block * @isapplet: bool; to indicate external app * @is_kva: bool; kernel buffer; only used for kernel crypto module + * @secure_dma; indicates whether this is secure_dma using IMR * * This function prepares the linked DMA tables and puts the * address for the linked list of tables inta a DCB (data control @@ -332,6 +338,7 @@ int sep_prepare_input_output_dma_table_in_dcb(struct sep_device *sep, u32 tail_block_size, bool isapplet, bool is_kva, + bool secure_dma, struct sep_dcblock *dcb_region, void **dmatables_region, struct sep_dma_context **dma_ctx, @@ -386,4 +393,10 @@ int sep_wait_transaction(struct sep_device *sep); struct sep_device; +#define SEP_IOCPREPAREDCB_SECURE_DMA \ + _IOW(SEP_IOC_MAGIC_NUMBER, 38, struct build_dcb_struct) + +#define SEP_IOCFREEDCB_SECURE_DMA \ + _IO(SEP_IOC_MAGIC_NUMBER, 39) + #endif diff --git a/drivers/staging/sep/sep_main.c b/drivers/staging/sep/sep_main.c index 421a2b1..7d7cb48 100644 --- a/drivers/staging/sep/sep_main.c +++ b/drivers/staging/sep/sep_main.c @@ -485,8 +485,15 @@ int sep_free_dma_table_data_handler(struct sep_device *sep, kfree(dma->in_map_array); } - /* Unmap output map array, DON'T free it yet */ - if (dma->out_map_array) { + /** + * Output is handled different. If + * this was a secure dma into restricted memory, + * then we skip this step altogether as restricted + * memory is not available to the o/s at all. + */ + if (((*dma_ctx)->secure_dma == false) && + (dma->out_map_array)) { + for (count = 0; count < dma->out_num_pages; count++) { dma_unmap_page(&sep->pdev->dev, dma->out_map_array[count].dma_addr, @@ -505,7 +512,10 @@ int sep_free_dma_table_data_handler(struct sep_device *sep, kfree(dma->in_page_array); } - if (dma->out_page_array) { + /* Again, we do this only for non secure dma */ + if (((*dma_ctx)->secure_dma == false) && + (dma->out_page_array)) { + for (count = 0; count < dma->out_num_pages; count++) { if (!PageReserved(dma->out_page_array[count])) @@ -1383,6 +1393,128 @@ end_function: } /** + * sep_lli_table_secure_dma - get lli array for IMR addresses + * @sep: pointer to struct sep_device + * @app_virt_addr: user memory data buffer + * @data_size: size of data buffer + * @lli_array_ptr: lli array + * @in_out_flag: not used + * @dma_ctx: pointer to struct sep_dma_context + * + * This function creates lli tables for outputting data to + * IMR memory, which is memory that cannot be accessed by the + * the x86 processor. + */ +static int sep_lli_table_secure_dma(struct sep_device *sep, + u32 app_virt_addr, + u32 data_size, + struct sep_lli_entry **lli_array_ptr, + int in_out_flag, + struct sep_dma_context *dma_ctx) + +{ + int error = 0; + u32 count; + /* The the page of the end address of the user space buffer */ + u32 end_page; + /* The page of the start address of the user space buffer */ + u32 start_page; + /* The range in pages */ + u32 num_pages; + /* Array of lli */ + struct sep_lli_entry *lli_array; + + /* Set start and end pages and num pages */ + end_page = (app_virt_addr + data_size - 1) >> PAGE_SHIFT; + start_page = app_virt_addr >> PAGE_SHIFT; + num_pages = end_page - start_page + 1; + + dev_dbg(&sep->pdev->dev, "[PID%d] lock user pages" + " app_virt_addr is %x\n", current->pid, app_virt_addr); + + dev_dbg(&sep->pdev->dev, "[PID%d] data_size is (hex) %x\n", + current->pid, data_size); + dev_dbg(&sep->pdev->dev, "[PID%d] start_page is (hex) %x\n", + current->pid, start_page); + dev_dbg(&sep->pdev->dev, "[PID%d] end_page is (hex) %x\n", + current->pid, end_page); + dev_dbg(&sep->pdev->dev, "[PID%d] num_pages is (hex) %x\n", + current->pid, num_pages); + + lli_array = kmalloc(sizeof(struct sep_lli_entry) * num_pages, + GFP_ATOMIC); + + if (!lli_array) { + dev_warn(&sep->pdev->dev, + "[PID%d] kmalloc for lli_array failed\n", + current->pid); + return -ENOMEM; + } + + /* + * Fill the lli_array + */ + start_page = start_page << PAGE_SHIFT; + for (count = 0; count < num_pages; count++) { + /* Fill the lli array entry */ + lli_array[count].bus_address = start_page; + lli_array[count].block_size = PAGE_SIZE; + + start_page += PAGE_SIZE; + + dev_dbg(&sep->pdev->dev, + "[PID%d] lli_array[%x].bus_address is %08lx, " + "lli_array[%x].block_size is (hex) %x\n", + current->pid, + count, (unsigned long)lli_array[count].bus_address, + count, lli_array[count].block_size); + } + + /* Check the offset for the first page */ + lli_array[0].bus_address = + lli_array[0].bus_address + (app_virt_addr & (~PAGE_MASK)); + + /* Check that not all the data is in the first page only */ + if ((PAGE_SIZE - (app_virt_addr & (~PAGE_MASK))) >= data_size) + lli_array[0].block_size = data_size; + else + lli_array[0].block_size = + PAGE_SIZE - (app_virt_addr & (~PAGE_MASK)); + + dev_dbg(&sep->pdev->dev, + "[PID%d] After check if page 0 has all data\n" + "lli_array[0].bus_address is (hex) %08lx, " + "lli_array[0].block_size is (hex) %x\n", + current->pid, + (unsigned long)lli_array[0].bus_address, + lli_array[0].block_size); + + /* Check the size of the last page */ + if (num_pages > 1) { + lli_array[num_pages - 1].block_size = + (app_virt_addr + data_size) & (~PAGE_MASK); + if (lli_array[num_pages - 1].block_size == 0) + lli_array[num_pages - 1].block_size = PAGE_SIZE; + + dev_dbg(&sep->pdev->dev, + "[PID%d] After last page size adjustment\n" + "lli_array[%x].bus_address is (hex) %08lx, " + "lli_array[%x].block_size is (hex) %x\n", + current->pid, num_pages - 1, + (unsigned long)lli_array[num_pages - 1].bus_address, + num_pages - 1, + lli_array[num_pages - 1].block_size); + } + *lli_array_ptr = lli_array; + dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].out_num_pages = num_pages; + dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].out_page_array = NULL; + dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].out_map_array = NULL; + dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].out_map_num_entries = 0; + + return error; +} + +/** * sep_calculate_lli_table_max_size - size the LLI table * @sep: pointer to struct sep_device * @lli_in_array_ptr @@ -1613,6 +1745,7 @@ static void sep_debug_print_lli_tables(struct sep_device *sep, unsigned long num_table_entries, unsigned long table_data_size) { +#ifdef DEBUG unsigned long table_count = 1; unsigned long entries_count = 0; @@ -1686,6 +1819,7 @@ static void sep_debug_print_lli_tables(struct sep_device *sep, } dev_dbg(&sep->pdev->dev, "[PID%d] sep_debug_print_lli_tables end\n", current->pid); +#endif } @@ -1956,8 +2090,10 @@ update_dcb_counter: end_function_error: /* Free all the allocated resources */ kfree(dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_map_array); + dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_map_array = NULL; kfree(lli_array_ptr); kfree(dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_page_array); + dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_page_array = NULL; end_function: return error; @@ -2360,20 +2496,42 @@ static int sep_prepare_input_output_dma_table(struct sep_device *sep, goto end_function; } - dev_dbg(&sep->pdev->dev, "[PID%d] Locking user output pages\n", + if (dma_ctx->secure_dma == true) { + /* secure_dma requires use of non accessible memory */ + dev_dbg(&sep->pdev->dev, "[PID%d] in secure_dma\n", + current->pid); + error = sep_lli_table_secure_dma(sep, + app_virt_out_addr, data_size, &lli_out_array, + SEP_DRIVER_OUT_FLAG, dma_ctx); + if (error) { + dev_warn(&sep->pdev->dev, + "[PID%d] secure dma table setup " + " for output virtual buffer failed\n", + current->pid); + + goto end_function_free_lli_in; + } + } else { + /* For normal, non-secure dma */ + dev_dbg(&sep->pdev->dev, "[PID%d] not in secure_dma\n", current->pid); - error = sep_lock_user_pages(sep, app_virt_out_addr, + dev_dbg(&sep->pdev->dev, + "[PID%d] Locking user output pages\n", + current->pid); + + error = sep_lock_user_pages(sep, app_virt_out_addr, data_size, &lli_out_array, SEP_DRIVER_OUT_FLAG, dma_ctx); - if (error) { - dev_warn(&sep->pdev->dev, + if (error) { + dev_warn(&sep->pdev->dev, "[PID%d] sep_lock_user_pages" " for output virtual buffer failed\n", current->pid); - goto end_function_free_lli_in; + goto end_function_free_lli_in; + } } } @@ -2421,13 +2579,17 @@ update_dcb_counter: end_function_with_error: kfree(dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].out_map_array); + dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].out_map_array = NULL; kfree(dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].out_page_array); + dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].out_page_array = NULL; kfree(lli_out_array); end_function_free_lli_in: kfree(dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_map_array); + dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_map_array = NULL; kfree(dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_page_array); + dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].in_page_array = NULL; kfree(lli_in_array); end_function: @@ -2445,6 +2607,7 @@ end_function: * @tail_block_size: u32; for size of tail block * @isapplet: bool; to indicate external app * @is_kva: bool; kernel buffer; only used for kernel crypto module + * @secure_dma; indicates whether this is secure_dma using IMR * * This function prepares the linked DMA tables and puts the * address for the linked list of tables inta a DCB (data control @@ -2460,6 +2623,7 @@ int sep_prepare_input_output_dma_table_in_dcb(struct sep_device *sep, u32 tail_block_size, bool isapplet, bool is_kva, + bool secure_dma, struct sep_dcblock *dcb_region, void **dmatables_region, struct sep_dma_context **dma_ctx, @@ -2534,6 +2698,8 @@ int sep_prepare_input_output_dma_table_in_dcb(struct sep_device *sep, current->pid, *dma_ctx); } + (*dma_ctx)->secure_dma = secure_dma; + /* these are for kernel crypto only */ (*dma_ctx)->src_sg = src_sg; (*dma_ctx)->dst_sg = dst_sg; @@ -2690,6 +2856,7 @@ int sep_prepare_input_output_dma_table_in_dcb(struct sep_device *sep, end_function_error: kfree(*dma_ctx); + *dma_ctx = NULL; end_function: return error; @@ -2719,15 +2886,22 @@ static int sep_free_dma_tables_and_dcb(struct sep_device *sep, bool isapplet, dev_dbg(&sep->pdev->dev, "[PID%d] sep_free_dma_tables_and_dcb\n", current->pid); - if (isapplet == true) { + if (((*dma_ctx)->secure_dma == false) && (isapplet == true)) { + dev_dbg(&sep->pdev->dev, "[PID%d] handling applet\n", + current->pid); + + /* Tail stuff is only for non secure_dma */ /* Set pointer to first DCB table */ dcb_table_ptr = (struct sep_dcblock *) (sep->shared_addr + SEP_DRIVER_SYSTEM_DCB_MEMORY_OFFSET_IN_BYTES); - /* Go over each DCB and see if tail pointer must be updated */ - for (i = 0; - i < (*dma_ctx)->nr_dcb_creat; i++, dcb_table_ptr++) { + /** + * Go over each DCB and see if + * tail pointer must be updated + */ + for (i = 0; dma_ctx && *dma_ctx && + i < (*dma_ctx)->nr_dcb_creat; i++, dcb_table_ptr++) { if (dcb_table_ptr->out_vr_tail_pt) { pt_hold = (unsigned long)dcb_table_ptr-> out_vr_tail_pt; @@ -2749,6 +2923,7 @@ static int sep_free_dma_tables_and_dcb(struct sep_device *sep, bool isapplet, } } } + /* Free the output pages, if any */ sep_free_dma_table_data_handler(sep, dma_ctx); @@ -2762,11 +2937,13 @@ static int sep_free_dma_tables_and_dcb(struct sep_device *sep, bool isapplet, * sep_prepare_dcb_handler - prepare a control block * @sep: pointer to struct sep_device * @arg: pointer to user parameters + * @secure_dma: indicate whether we are using secure_dma on IMR * * This function will retrieve the RAR buffer physical addresses, type * & size corresponding to the RAR handles provided in the buffers vector. */ static int sep_prepare_dcb_handler(struct sep_device *sep, unsigned long arg, + bool secure_dma, struct sep_dma_context **dma_ctx) { int error; @@ -2812,7 +2989,7 @@ static int sep_prepare_dcb_handler(struct sep_device *sep, unsigned long arg, command_args.data_in_size, command_args.block_size, command_args.tail_block_size, command_args.is_applet, false, - NULL, NULL, dma_ctx, NULL, NULL); + secure_dma, NULL, NULL, dma_ctx, NULL, NULL); end_function: return error; @@ -2829,21 +3006,18 @@ end_function: static int sep_free_dcb_handler(struct sep_device *sep, struct sep_dma_context **dma_ctx) { - int error = 0; - if (!dma_ctx || !(*dma_ctx)) { - dev_dbg(&sep->pdev->dev, "[PID%d] no dma context defined, nothing to free\n", + dev_dbg(&sep->pdev->dev, + "[PID%d] no dma context defined, nothing to free\n", current->pid); - return error; + return -EINVAL; } dev_dbg(&sep->pdev->dev, "[PID%d] free dcbs num of DCBs %x\n", current->pid, (*dma_ctx)->nr_dcb_creat); - error = sep_free_dma_tables_and_dcb(sep, false, false, dma_ctx); - - return error; + return sep_free_dma_tables_and_dcb(sep, false, false, dma_ctx); } /** @@ -2931,7 +3105,7 @@ static long sep_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) goto end_function; } - error = sep_prepare_dcb_handler(sep, arg, dma_ctx); + error = sep_prepare_dcb_handler(sep, arg, false, dma_ctx); dev_dbg(&sep->pdev->dev, "[PID%d] SEP_IOCPREPAREDCB end\n", current->pid); break; @@ -3170,13 +3344,14 @@ end_function: * @dma_ctx: DMA context buf to create for current transaction * @user_dcb_args: User arguments for DCB/MLLI creation * @num_dcbs: Number of DCBs to create + * @secure_dma: Indicate use of IMR restricted memory secure dma */ static ssize_t sep_create_dcb_dmatables_context(struct sep_device *sep, struct sep_dcblock **dcb_region, void **dmatables_region, struct sep_dma_context **dma_ctx, const struct build_dcb_struct __user *user_dcb_args, - const u32 num_dcbs) + const u32 num_dcbs, bool secure_dma) { int error = 0; int i = 0; @@ -3231,7 +3406,7 @@ static ssize_t sep_create_dcb_dmatables_context(struct sep_device *sep, dcb_args[i].block_size, dcb_args[i].tail_block_size, dcb_args[i].is_applet, - false, + false, secure_dma, *dcb_region, dmatables_region, dma_ctx, NULL, @@ -3242,6 +3417,9 @@ static ssize_t sep_create_dcb_dmatables_context(struct sep_device *sep, current->pid); goto end_function; } + + if (dcb_args[i].app_in_address != 0) + (*dma_ctx)->input_data_len += dcb_args[i].data_in_size; } end_function: @@ -3311,6 +3489,7 @@ int sep_create_dcb_dmatables_context_kernel(struct sep_device *sep, dcb_data->tail_block_size, dcb_data->is_applet, true, + false, *dcb_region, dmatables_region, dma_ctx, dcb_data->src_sg, @@ -3597,6 +3776,7 @@ static ssize_t sep_write(struct file *filp, struct sep_dcblock *dcb_region = NULL; ssize_t error = 0; struct sep_queue_info *my_queue_elem = NULL; + bool my_secure_dma; /* are we using secure_dma (IMR)? */ dev_dbg(&sep->pdev->dev, "[PID%d] sep dev is 0x%p\n", current->pid, sep); @@ -3609,6 +3789,11 @@ static ssize_t sep_write(struct file *filp, buf_user += sizeof(struct sep_fastcall_hdr); + if (call_hdr.secure_dma == 0) + my_secure_dma = false; + else + my_secure_dma = true; + /* * Controlling driver memory usage by limiting amount of * buffers created. Only SEP_DOUBLEBUF_USERS_LIMIT number @@ -3636,7 +3821,7 @@ static ssize_t sep_write(struct file *filp, &dma_ctx, (const struct build_dcb_struct __user *) buf_user, - call_hdr.num_dcbs); + call_hdr.num_dcbs, my_secure_dma); if (error) goto end_function_error_doublebuf; -- cgit v0.10.2 From 6ab80c26085b91f4a6c0336bbc99b18e9938cfb2 Mon Sep 17 00:00:00 2001 From: "Mark A. Allyn" Date: Fri, 10 Feb 2012 13:52:55 +0000 Subject: staging: sep: Add interfaces for the new functions [This is picked out of the differences between the upstream driver and the staging driver. I'm resolving the differences as a series of updates -AC] Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/sep/sep_main.c b/drivers/staging/sep/sep_main.c index 7d7cb48..1fcabca 100644 --- a/drivers/staging/sep/sep_main.c +++ b/drivers/staging/sep/sep_main.c @@ -3067,9 +3067,13 @@ static long sep_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) switch (cmd) { case SEP_IOCSENDSEPCOMMAND: + dev_dbg(&sep->pdev->dev, + "[PID%d] SEP_IOCSENDSEPCOMMAND start\n", + current->pid); if (1 == test_bit(SEP_LEGACY_SENDMSG_DONE_OFFSET, &call_status->status)) { - dev_dbg(&sep->pdev->dev, "[PID%d] send msg already done\n", + dev_warn(&sep->pdev->dev, + "[PID%d] send msg already done\n", current->pid); error = -EPROTO; goto end_function; @@ -3079,37 +3083,71 @@ static long sep_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (!error) set_bit(SEP_LEGACY_SENDMSG_DONE_OFFSET, &call_status->status); - dev_dbg(&sep->pdev->dev, "[PID%d] SEP_IOCSENDSEPCOMMAND end\n", + dev_dbg(&sep->pdev->dev, + "[PID%d] SEP_IOCSENDSEPCOMMAND end\n", current->pid); break; case SEP_IOCENDTRANSACTION: + dev_dbg(&sep->pdev->dev, + "[PID%d] SEP_IOCENDTRANSACTION start\n", + current->pid); error = sep_end_transaction_handler(sep, dma_ctx, call_status, - my_queue_elem); - dev_dbg(&sep->pdev->dev, "[PID%d] SEP_IOCENDTRANSACTION end\n", + my_queue_elem); + dev_dbg(&sep->pdev->dev, + "[PID%d] SEP_IOCENDTRANSACTION end\n", current->pid); break; case SEP_IOCPREPAREDCB: + dev_dbg(&sep->pdev->dev, + "[PID%d] SEP_IOCPREPAREDCB start\n", + current->pid); + case SEP_IOCPREPAREDCB_SECURE_DMA: + dev_dbg(&sep->pdev->dev, + "[PID%d] SEP_IOCPREPAREDCB_SECURE_DMA start\n", + current->pid); if (1 == test_bit(SEP_LEGACY_SENDMSG_DONE_OFFSET, &call_status->status)) { - dev_dbg(&sep->pdev->dev, - "[PID%d] dcb preparation needed before send msg\n", + dev_warn(&sep->pdev->dev, + "[PID%d] dcb prep needed before send msg\n", current->pid); error = -EPROTO; goto end_function; } if (!arg) { - dev_dbg(&sep->pdev->dev, - "[PID%d] dcb prep null arg\n", current->pid); - error = -EINVAL; + dev_warn(&sep->pdev->dev, + "[PID%d] dcb null arg\n", current->pid); + error = EINVAL; goto end_function; } - error = sep_prepare_dcb_handler(sep, arg, false, dma_ctx); - dev_dbg(&sep->pdev->dev, "[PID%d] SEP_IOCPREPAREDCB end\n", + if (cmd == SEP_IOCPREPAREDCB) { + /* No secure dma */ + dev_dbg(&sep->pdev->dev, + "[PID%d] SEP_IOCPREPAREDCB (no secure_dma)\n", + current->pid); + + error = sep_prepare_dcb_handler(sep, arg, false, + dma_ctx); + } else { + /* Secure dma */ + dev_dbg(&sep->pdev->dev, + "[PID%d] SEP_IOC_POC (with secure_dma)\n", + current->pid); + + error = sep_prepare_dcb_handler(sep, arg, true, + dma_ctx); + } + dev_dbg(&sep->pdev->dev, "[PID%d] dcb's end\n", current->pid); break; case SEP_IOCFREEDCB: + dev_dbg(&sep->pdev->dev, "[PID%d] SEP_IOCFREEDCB start\n", + current->pid); + case SEP_IOCFREEDCB_SECURE_DMA: + dev_dbg(&sep->pdev->dev, + "[PID%d] SEP_IOCFREEDCB_SECURE_DMA start\n", + current->pid); error = sep_free_dcb_handler(sep, dma_ctx); dev_dbg(&sep->pdev->dev, "[PID%d] SEP_IOCFREEDCB end\n", current->pid); -- cgit v0.10.2 From ecd0cb003fda30702c6c1f007a58bef885f5cb42 Mon Sep 17 00:00:00 2001 From: "Mark A. Allyn" Date: Fri, 10 Feb 2012 13:53:08 +0000 Subject: staging: sep: update initialisation In particular we want to always do the reconfigure [This is picked out of the differences between the upstream driver and the staging driver. I'm resolving the differences as a series of updates -AC] Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/sep/sep_main.c b/drivers/staging/sep/sep_main.c index 1fcabca..db51895 100644 --- a/drivers/staging/sep/sep_main.c +++ b/drivers/staging/sep/sep_main.c @@ -4150,7 +4150,6 @@ static int __devinit sep_probe(struct pci_dev *pdev, dev_dbg(&sep->pdev->dev, "sep probe: PCI obtained, " "device being prepared\n"); - dev_dbg(&sep->pdev->dev, "revision is %d\n", sep->pdev->revision); /* Set up our register area */ sep->reg_physical_addr = pci_resource_start(sep->pdev, 0); @@ -4213,38 +4212,39 @@ static int __devinit sep_probe(struct pci_dev *pdev, goto end_function_deallocate_sep_shared_area; /* The new chip requires a shared area reconfigure */ - if (sep->pdev->revision != 0) { /* Only for new chip */ - error = sep_reconfig_shared_area(sep); - if (error) - goto end_function_free_irq; - } + error = sep_reconfig_shared_area(sep); + if (error) + goto end_function_free_irq; sep->in_use = 1; /* Finally magic up the device nodes */ /* Register driver with the fs */ error = sep_register_driver_with_fs(sep); - if (error) + + if (error) { + dev_err(&sep->pdev->dev, "error registering dev file\n"); goto end_function_free_irq; + } + sep->in_use = 0; /* through touching the device */ #ifdef SEP_ENABLE_RUNTIME_PM pm_runtime_put_noidle(&sep->pdev->dev); pm_runtime_allow(&sep->pdev->dev); pm_runtime_set_autosuspend_delay(&sep->pdev->dev, SUSPEND_DELAY); pm_runtime_use_autosuspend(&sep->pdev->dev); + pm_runtime_mark_last_busy(&sep->pdev->dev); sep->power_save_setup = 1; #endif - - sep->in_use = 0; - /* register kernel crypto driver */ +#if defined(CONFIG_CRYPTO) error = sep_crypto_setup(); if (error) { - dev_dbg(&sep->pdev->dev, "crypto setup fail\n"); + dev_err(&sep->pdev->dev, "crypto setup failed\n"); goto end_function_free_irq; } - +#endif goto end_function; end_function_free_irq: @@ -4292,7 +4292,7 @@ static void sep_remove(struct pci_dev *pdev) /* Free the shared area */ sep_unmap_and_free_shared_area(sep_dev); - iounmap((void __iomem *)sep_dev->reg_addr); + iounmap(sep_dev->reg_addr); #ifdef SEP_ENABLE_RUNTIME_PM if (sep->in_use) { -- cgit v0.10.2 From ab8ef35131ee42963abe87b2b1d2911bda4a8a48 Mon Sep 17 00:00:00 2001 From: "Mark A. Allyn" Date: Fri, 10 Feb 2012 13:53:21 +0000 Subject: staging: sep: NULL out pointers, mark debug code DEBUG to fix warnings [This is picked out of the differences between the upstream driver and the staging driver. I'm resolving the differences as a series of updates -AC] Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/sep/sep_main.c b/drivers/staging/sep/sep_main.c index db51895..cf420f6 100644 --- a/drivers/staging/sep/sep_main.c +++ b/drivers/staging/sep/sep_main.c @@ -40,6 +40,7 @@ /* #define SEP_PERF_DEBUG */ #include +#include #include #include #include @@ -197,9 +198,9 @@ static int sep_allocate_dmatables_region(struct sep_device *sep, struct sep_dma_context *dma_ctx, const u32 table_count) { - const size_t new_len = table_count * - sizeof(struct sep_lli_entry) * - SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP; + const size_t new_len = + SYNCHRONIC_DMA_TABLES_AREA_SIZE_BYTES - 1; + void *tmp_region = NULL; dev_dbg(&sep->pdev->dev, "[PID%d] dma_ctx = 0x%p\n", @@ -230,6 +231,7 @@ static int sep_allocate_dmatables_region(struct sep_device *sep, if (*dmatables_region) { memcpy(tmp_region, *dmatables_region, dma_ctx->dmatables_len); kfree(*dmatables_region); + *dmatables_region = NULL; } *dmatables_region = tmp_region; @@ -342,11 +344,12 @@ static void _sep_dump_message(struct sep_device *sep) u32 *p = sep->shared_addr; - for (count = 0; count < 40 * 4; count += 4) + for (count = 0; count < 10 * 4; count += 4) dev_dbg(&sep->pdev->dev, "[PID%d] Word %d of the message is %x\n", current->pid, count/4, *p++); } + #endif /** @@ -384,6 +387,8 @@ static void sep_unmap_and_free_shared_area(struct sep_device *sep) sep->shared_addr, sep->shared_bus); } +#ifdef DEBUG + /** * sep_shared_bus_to_virt - convert bus/virt addresses * @sep: pointer to struct sep_device @@ -398,6 +403,8 @@ static void *sep_shared_bus_to_virt(struct sep_device *sep, return sep->shared_addr + (bus_address - sep->shared_bus); } +#endif + /** * sep_open - device open method * @inode: inode of SEP device -- cgit v0.10.2 From 9196dc1129fbb3ecf93027224a6bdbc86d086e3a Mon Sep 17 00:00:00 2001 From: "Mark A. Allyn" Date: Fri, 10 Feb 2012 13:53:36 +0000 Subject: staging: sep: reworked crypto layer This gets the SEP crypto layer up and running with things like dmcrypt. It's a fairly big set of changes because it has to rework the whole context handling system. [This is picked out of the differences between the upstream driver and the staging driver. I'm resolving the differences as a series of updates -AC] Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/sep/sep_crypto.c b/drivers/staging/sep/sep_crypto.c index a6b0f83..89b6814 100644 --- a/drivers/staging/sep/sep_crypto.c +++ b/drivers/staging/sep/sep_crypto.c @@ -88,17 +88,17 @@ static void sep_dequeuer(void *data); * This will only print dump if DEBUG is set; it does * follow kernel debug print enabling */ -static void crypto_sep_dump_message(struct sep_system_ctx *sctx) +static void crypto_sep_dump_message(struct sep_device *sep, void *msg) { #if 0 u32 *p; u32 *i; int count; - p = sctx->sep_used->shared_addr; - i = (u32 *)sctx->msg; - for (count = 0; count < 40 * 4; count += 4) - dev_dbg(&sctx->sep_used->pdev->dev, + p = sep->shared_addr; + i = (u32 *)msg; + for (count = 0; count < 10 * 4; count += 4) + dev_dbg(&sep->pdev->dev, "[PID%d] Word %d of the message is %x (local)%x\n", current->pid, count/4, *p++, *i++); #endif @@ -534,6 +534,67 @@ static void sep_dump_sg(struct sep_device *sep, char *stg, #endif } +/* Debug - prints only if DEBUG is defined */ +static void sep_dump_ivs(struct ablkcipher_request *req, char *reason) + + { + unsigned char *cptr; + struct sep_aes_internal_context *aes_internal; + struct sep_des_internal_context *des_internal; + int ct1; + + struct this_task_ctx *ta_ctx; + struct crypto_ablkcipher *tfm; + struct sep_system_ctx *sctx; + + ta_ctx = ablkcipher_request_ctx(req); + tfm = crypto_ablkcipher_reqtfm(req); + sctx = crypto_ablkcipher_ctx(tfm); + + dev_dbg(&ta_ctx->sep_used->pdev->dev, "IV DUMP - %s\n", reason); + if ((ta_ctx->current_request == DES_CBC) && + (ta_ctx->des_opmode == SEP_DES_CBC)) { + + des_internal = (struct sep_des_internal_context *) + sctx->des_private_ctx.ctx_buf; + /* print vendor */ + dev_dbg(&ta_ctx->sep_used->pdev->dev, + "sep - vendor iv for DES\n"); + cptr = (unsigned char *)des_internal->iv_context; + for (ct1 = 0; ct1 < crypto_ablkcipher_ivsize(tfm); ct1 += 1) + dev_dbg(&ta_ctx->sep_used->pdev->dev, + "%02x\n", *(cptr + ct1)); + + /* print walk */ + dev_dbg(&ta_ctx->sep_used->pdev->dev, + "sep - walk from kernel crypto iv for DES\n"); + cptr = (unsigned char *)ta_ctx->walk.iv; + for (ct1 = 0; ct1 < crypto_ablkcipher_ivsize(tfm); ct1 += 1) + dev_dbg(&ta_ctx->sep_used->pdev->dev, + "%02x\n", *(cptr + ct1)); + } else if ((ta_ctx->current_request == AES_CBC) && + (ta_ctx->aes_opmode == SEP_AES_CBC)) { + + aes_internal = (struct sep_aes_internal_context *) + sctx->aes_private_ctx.cbuff; + /* print vendor */ + dev_dbg(&ta_ctx->sep_used->pdev->dev, + "sep - vendor iv for AES\n"); + cptr = (unsigned char *)aes_internal->aes_ctx_iv; + for (ct1 = 0; ct1 < crypto_ablkcipher_ivsize(tfm); ct1 += 1) + dev_dbg(&ta_ctx->sep_used->pdev->dev, + "%02x\n", *(cptr + ct1)); + + /* print walk */ + dev_dbg(&ta_ctx->sep_used->pdev->dev, + "sep - walk from kernel crypto iv for AES\n"); + cptr = (unsigned char *)ta_ctx->walk.iv; + for (ct1 = 0; ct1 < crypto_ablkcipher_ivsize(tfm); ct1 += 1) + dev_dbg(&ta_ctx->sep_used->pdev->dev, + "%02x\n", *(cptr + ct1)); + } +} + /** * RFC2451: Weak key check * Returns: 1 (weak), 0 (not weak) @@ -671,61 +732,61 @@ static u32 sep_sg_nents(struct scatterlist *sg) /** * sep_start_msg - - * @sctx: pointer to struct sep_system_ctx + * @ta_ctx: pointer to struct this_task_ctx * @returns: offset to place for the next word in the message * Set up pointer in message pool for new message */ -static u32 sep_start_msg(struct sep_system_ctx *sctx) +static u32 sep_start_msg(struct this_task_ctx *ta_ctx) { u32 *word_ptr; - sctx->msg_len_words = 2; - sctx->msgptr = sctx->msg; - memset(sctx->msg, 0, SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES); - sctx->msgptr += sizeof(u32) * 2; - word_ptr = (u32 *)sctx->msgptr; + ta_ctx->msg_len_words = 2; + ta_ctx->msgptr = ta_ctx->msg; + memset(ta_ctx->msg, 0, SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES); + ta_ctx->msgptr += sizeof(u32) * 2; + word_ptr = (u32 *)ta_ctx->msgptr; *word_ptr = SEP_START_MSG_TOKEN; return sizeof(u32) * 2; } /** * sep_end_msg - - * @sctx: pointer to struct sep_system_ctx + * @ta_ctx: pointer to struct this_task_ctx * @messages_offset: current message offset * Returns: 0 for success; <0 otherwise * End message; set length and CRC; and * send interrupt to the SEP */ -static void sep_end_msg(struct sep_system_ctx *sctx, u32 msg_offset) +static void sep_end_msg(struct this_task_ctx *ta_ctx, u32 msg_offset) { u32 *word_ptr; /* Msg size goes into msg after token */ - sctx->msg_len_words = msg_offset / sizeof(u32) + 1; - word_ptr = (u32 *)sctx->msgptr; + ta_ctx->msg_len_words = msg_offset / sizeof(u32) + 1; + word_ptr = (u32 *)ta_ctx->msgptr; word_ptr += 1; - *word_ptr = sctx->msg_len_words; + *word_ptr = ta_ctx->msg_len_words; /* CRC (currently 0) goes at end of msg */ - word_ptr = (u32 *)(sctx->msgptr + msg_offset); + word_ptr = (u32 *)(ta_ctx->msgptr + msg_offset); *word_ptr = 0; } /** * sep_start_inbound_msg - - * @sctx: pointer to struct sep_system_ctx + * @ta_ctx: pointer to struct this_task_ctx * @msg_offset: offset to place for the next word in the message * @returns: 0 for success; error value for failure * Set up pointer in message pool for inbound message */ -static u32 sep_start_inbound_msg(struct sep_system_ctx *sctx, u32 *msg_offset) +static u32 sep_start_inbound_msg(struct this_task_ctx *ta_ctx, u32 *msg_offset) { u32 *word_ptr; u32 token; u32 error = SEP_OK; *msg_offset = sizeof(u32) * 2; - word_ptr = (u32 *)sctx->msgptr; + word_ptr = (u32 *)ta_ctx->msgptr; token = *word_ptr; - sctx->msg_len_words = *(word_ptr + 1); + ta_ctx->msg_len_words = *(word_ptr + 1); if (token != SEP_START_MSG_TOKEN) { error = SEP_INVALID_START; @@ -739,7 +800,7 @@ end_function: /** * sep_write_msg - - * @sctx: pointer to struct sep_system_ctx + * @ta_ctx: pointer to struct this_task_ctx * @in_addr: pointer to start of parameter * @size: size of parameter to copy (in bytes) * @max_size: size to move up offset; SEP mesg is in word sizes @@ -747,12 +808,12 @@ end_function: * @byte_array: flag ti indicate wheter endian must be changed * Copies data into the message area from caller */ -static void sep_write_msg(struct sep_system_ctx *sctx, void *in_addr, +static void sep_write_msg(struct this_task_ctx *ta_ctx, void *in_addr, u32 size, u32 max_size, u32 *msg_offset, u32 byte_array) { u32 *word_ptr; void *void_ptr; - void_ptr = sctx->msgptr + *msg_offset; + void_ptr = ta_ctx->msgptr + *msg_offset; word_ptr = (u32 *)void_ptr; memcpy(void_ptr, in_addr, size); *msg_offset += max_size; @@ -767,18 +828,18 @@ static void sep_write_msg(struct sep_system_ctx *sctx, void *in_addr, /** * sep_make_header - * @sctx: pointer to struct sep_system_ctx + * @ta_ctx: pointer to struct this_task_ctx * @msg_offset: pointer to current offset (is updated) * @op_code: op code to put into message * Puts op code into message and updates offset */ -static void sep_make_header(struct sep_system_ctx *sctx, u32 *msg_offset, +static void sep_make_header(struct this_task_ctx *ta_ctx, u32 *msg_offset, u32 op_code) { u32 *word_ptr; - *msg_offset = sep_start_msg(sctx); - word_ptr = (u32 *)(sctx->msgptr + *msg_offset); + *msg_offset = sep_start_msg(ta_ctx); + word_ptr = (u32 *)(ta_ctx->msgptr + *msg_offset); *word_ptr = op_code; *msg_offset += sizeof(u32); } @@ -787,7 +848,7 @@ static void sep_make_header(struct sep_system_ctx *sctx, u32 *msg_offset, /** * sep_read_msg - - * @sctx: pointer to struct sep_system_ctx + * @ta_ctx: pointer to struct this_task_ctx * @in_addr: pointer to start of parameter * @size: size of parameter to copy (in bytes) * @max_size: size to move up offset; SEP mesg is in word sizes @@ -795,12 +856,12 @@ static void sep_make_header(struct sep_system_ctx *sctx, u32 *msg_offset, * @byte_array: flag ti indicate wheter endian must be changed * Copies data out of the message area to caller */ -static void sep_read_msg(struct sep_system_ctx *sctx, void *in_addr, +static void sep_read_msg(struct this_task_ctx *ta_ctx, void *in_addr, u32 size, u32 max_size, u32 *msg_offset, u32 byte_array) { u32 *word_ptr; void *void_ptr; - void_ptr = sctx->msgptr + *msg_offset; + void_ptr = ta_ctx->msgptr + *msg_offset; word_ptr = (u32 *)void_ptr; /* Do we need to manipulate endian? */ @@ -816,28 +877,28 @@ static void sep_read_msg(struct sep_system_ctx *sctx, void *in_addr, /** * sep_verify_op - - * @sctx: pointer to struct sep_system_ctx + * @ta_ctx: pointer to struct this_task_ctx * @op_code: expected op_code * @msg_offset: pointer to current offset (is updated) * @returns: 0 for success; error for failure */ -static u32 sep_verify_op(struct sep_system_ctx *sctx, u32 op_code, +static u32 sep_verify_op(struct this_task_ctx *ta_ctx, u32 op_code, u32 *msg_offset) { u32 error; u32 in_ary[2]; - struct sep_device *sep = sctx->sep_used; + struct sep_device *sep = ta_ctx->sep_used; dev_dbg(&sep->pdev->dev, "dumping return message\n"); - error = sep_start_inbound_msg(sctx, msg_offset); + error = sep_start_inbound_msg(ta_ctx, msg_offset); if (error) { dev_warn(&sep->pdev->dev, "sep_start_inbound_msg error\n"); return error; } - sep_read_msg(sctx, in_ary, sizeof(u32) * 2, sizeof(u32) * 2, + sep_read_msg(ta_ctx, in_ary, sizeof(u32) * 2, sizeof(u32) * 2, msg_offset, 0); if (in_ary[0] != op_code) { @@ -863,7 +924,7 @@ return 0; /** * sep_read_context - - * @sctx: pointer to struct sep_system_ctx + * @ta_ctx: pointer to struct this_task_ctx * @msg_offset: point to current place in SEP msg; is updated * @dst: pointer to place to put the context * @len: size of the context structure (differs for crypro/hash) @@ -873,16 +934,16 @@ return 0; * it skips over some words in the msg area depending on the size * of the context */ -static void sep_read_context(struct sep_system_ctx *sctx, u32 *msg_offset, +static void sep_read_context(struct this_task_ctx *ta_ctx, u32 *msg_offset, void *dst, u32 len) { u32 max_length = ((len + 3) / sizeof(u32)) * sizeof(u32); - sep_read_msg(sctx, dst, len, max_length, msg_offset, 0); + sep_read_msg(ta_ctx, dst, len, max_length, msg_offset, 0); } /** * sep_write_context - - * @sctx: pointer to struct sep_system_ctx + * @ta_ctx: pointer to struct this_task_ctx * @msg_offset: point to current place in SEP msg; is updated * @src: pointer to the current context * @len: size of the context structure (differs for crypro/hash) @@ -892,76 +953,77 @@ static void sep_read_context(struct sep_system_ctx *sctx, u32 *msg_offset, * it skips over some words in the msg area depending on the size * of the context */ -static void sep_write_context(struct sep_system_ctx *sctx, u32 *msg_offset, +static void sep_write_context(struct this_task_ctx *ta_ctx, u32 *msg_offset, void *src, u32 len) { u32 max_length = ((len + 3) / sizeof(u32)) * sizeof(u32); - sep_write_msg(sctx, src, len, max_length, msg_offset, 0); + sep_write_msg(ta_ctx, src, len, max_length, msg_offset, 0); } /** * sep_clear_out - - * @sctx: pointer to struct sep_system_ctx + * @ta_ctx: pointer to struct this_task_ctx * Clear out crypto related values in sep device structure * to enable device to be used by anyone; either kernel * crypto or userspace app via middleware */ -static void sep_clear_out(struct sep_system_ctx *sctx) +static void sep_clear_out(struct this_task_ctx *ta_ctx) { - if (sctx->src_sg_hold) { - sep_free_sg_buf(sctx->src_sg_hold); - sctx->src_sg_hold = NULL; + if (ta_ctx->src_sg_hold) { + sep_free_sg_buf(ta_ctx->src_sg_hold); + ta_ctx->src_sg_hold = NULL; } - if (sctx->dst_sg_hold) { - sep_free_sg_buf(sctx->dst_sg_hold); - sctx->dst_sg_hold = NULL; + if (ta_ctx->dst_sg_hold) { + sep_free_sg_buf(ta_ctx->dst_sg_hold); + ta_ctx->dst_sg_hold = NULL; } - sctx->src_sg = NULL; - sctx->dst_sg = NULL; + ta_ctx->src_sg = NULL; + ta_ctx->dst_sg = NULL; - sep_free_dma_table_data_handler(sctx->sep_used, &sctx->dma_ctx); + sep_free_dma_table_data_handler(ta_ctx->sep_used, &ta_ctx->dma_ctx); - if (sctx->i_own_sep) { + if (ta_ctx->i_own_sep) { /** * The following unlocks the sep and makes it available * to any other application * First, null out crypto entries in sep before relesing it */ - sctx->sep_used->current_hash_req = NULL; - sctx->sep_used->current_cypher_req = NULL; - sctx->sep_used->current_request = 0; - sctx->sep_used->current_hash_stage = 0; - sctx->sep_used->sctx = NULL; - sctx->sep_used->in_kernel = 0; + ta_ctx->sep_used->current_hash_req = NULL; + ta_ctx->sep_used->current_cypher_req = NULL; + ta_ctx->sep_used->current_request = 0; + ta_ctx->sep_used->current_hash_stage = 0; + ta_ctx->sep_used->ta_ctx = NULL; + ta_ctx->sep_used->in_kernel = 0; - sctx->call_status.status = 0; + ta_ctx->call_status.status = 0; /* Remove anything confidentail */ - memset(sctx->sep_used->shared_addr, 0, + memset(ta_ctx->sep_used->shared_addr, 0, SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES); - sep_queue_status_remove(sctx->sep_used, &sctx->queue_elem); + sep_queue_status_remove(ta_ctx->sep_used, &ta_ctx->queue_elem); #ifdef SEP_ENABLE_RUNTIME_PM - sctx->sep_used->in_use = 0; - pm_runtime_mark_last_busy(&sctx->sep_used->pdev->dev); - pm_runtime_put_autosuspend(&sctx->sep_used->pdev->dev); + ta_ctx->sep_used->in_use = 0; + pm_runtime_mark_last_busy(&ta_ctx->sep_used->pdev->dev); + pm_runtime_put_autosuspend(&ta_ctx->sep_used->pdev->dev); #endif - clear_bit(SEP_WORKING_LOCK_BIT, &sctx->sep_used->in_use_flags); - sctx->sep_used->pid_doing_transaction = 0; + clear_bit(SEP_WORKING_LOCK_BIT, + &ta_ctx->sep_used->in_use_flags); + ta_ctx->sep_used->pid_doing_transaction = 0; - dev_dbg(&sctx->sep_used->pdev->dev, + dev_dbg(&ta_ctx->sep_used->pdev->dev, "[PID%d] waking up next transaction\n", current->pid); clear_bit(SEP_TRANSACTION_STARTED_LOCK_BIT, - &sctx->sep_used->in_use_flags); - wake_up(&sctx->sep_used->event_transactions); + &ta_ctx->sep_used->in_use_flags); + wake_up(&ta_ctx->sep_used->event_transactions); - sctx->i_own_sep = 0; + ta_ctx->i_own_sep = 0; } } @@ -969,22 +1031,34 @@ static void sep_clear_out(struct sep_system_ctx *sctx) * Release crypto infrastructure from EINPROGRESS and * clear sep_dev so that SEP is available to anyone */ -static void sep_crypto_release(struct sep_system_ctx *sctx, u32 error) +static void sep_crypto_release(struct sep_system_ctx *sctx, + struct this_task_ctx *ta_ctx, u32 error) { - struct ahash_request *hash_req = sctx->current_hash_req; + struct ahash_request *hash_req = ta_ctx->current_hash_req; struct ablkcipher_request *cypher_req = - sctx->current_cypher_req; - struct sep_device *sep = sctx->sep_used; + ta_ctx->current_cypher_req; + struct sep_device *sep = ta_ctx->sep_used; + + sep_clear_out(ta_ctx); - sep_clear_out(sctx); + /** + * This may not yet exist depending when we + * chose to bail out. If it does exist, set + * it to 1 + */ + if (ta_ctx->are_we_done_yet != NULL) + *ta_ctx->are_we_done_yet = 1; if (cypher_req != NULL) { - if (cypher_req->base.complete == NULL) { - dev_dbg(&sep->pdev->dev, - "release is null for cypher!"); - } else { - cypher_req->base.complete( - &cypher_req->base, error); + if ((sctx->key_sent == 1) || + ((error != 0) && (error != -EINPROGRESS))) { + if (cypher_req->base.complete == NULL) { + dev_dbg(&sep->pdev->dev, + "release is null for cypher!"); + } else { + cypher_req->base.complete( + &cypher_req->base, error); + } } } @@ -1005,20 +1079,20 @@ static void sep_crypto_release(struct sep_system_ctx *sctx, u32 error) * and it will return 0 if sep is now ours; error value if there * were problems */ -static int sep_crypto_take_sep(struct sep_system_ctx *sctx) +static int sep_crypto_take_sep(struct this_task_ctx *ta_ctx) { - struct sep_device *sep = sctx->sep_used; + struct sep_device *sep = ta_ctx->sep_used; int result; struct sep_msgarea_hdr *my_msg_header; - my_msg_header = (struct sep_msgarea_hdr *)sctx->msg; + my_msg_header = (struct sep_msgarea_hdr *)ta_ctx->msg; /* add to status queue */ - sctx->queue_elem = sep_queue_status_add(sep, my_msg_header->opcode, - sctx->nbytes, current->pid, + ta_ctx->queue_elem = sep_queue_status_add(sep, my_msg_header->opcode, + ta_ctx->nbytes, current->pid, current->comm, sizeof(current->comm)); - if (!sctx->queue_elem) { + if (!ta_ctx->queue_elem) { dev_dbg(&sep->pdev->dev, "[PID%d] updating queue" " status error\n", current->pid); return -EINVAL; @@ -1033,48 +1107,61 @@ static int sep_crypto_take_sep(struct sep_system_ctx *sctx) pm_runtime_get_sync(&sep_dev->pdev->dev); /* Copy in the message */ - memcpy(sep->shared_addr, sctx->msg, + memcpy(sep->shared_addr, ta_ctx->msg, SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES); /* Copy in the dcb information if there is any */ - if (sctx->dcb_region) { + if (ta_ctx->dcb_region) { result = sep_activate_dcb_dmatables_context(sep, - &sctx->dcb_region, &sctx->dmatables_region, - sctx->dma_ctx); + &ta_ctx->dcb_region, &ta_ctx->dmatables_region, + ta_ctx->dma_ctx); if (result) return result; } /* Mark the device so we know how to finish the job in the tasklet */ - if (sctx->current_hash_req) - sep->current_hash_req = sctx->current_hash_req; + if (ta_ctx->current_hash_req) + sep->current_hash_req = ta_ctx->current_hash_req; else - sep->current_cypher_req = sctx->current_cypher_req; + sep->current_cypher_req = ta_ctx->current_cypher_req; - sep->current_request = sctx->current_request; - sep->current_hash_stage = sctx->current_hash_stage; - sep->sctx = sctx; + sep->current_request = ta_ctx->current_request; + sep->current_hash_stage = ta_ctx->current_hash_stage; + sep->ta_ctx = ta_ctx; sep->in_kernel = 1; - sctx->i_own_sep = 1; + ta_ctx->i_own_sep = 1; + + /* need to set bit first to avoid race condition with interrupt */ + set_bit(SEP_LEGACY_SENDMSG_DONE_OFFSET, &ta_ctx->call_status.status); result = sep_send_command_handler(sep); dev_dbg(&sep->pdev->dev, "[PID%d]: sending command to the sep\n", current->pid); - if (!result) { - set_bit(SEP_LEGACY_SENDMSG_DONE_OFFSET, - &sctx->call_status.status); + if (!result) dev_dbg(&sep->pdev->dev, "[PID%d]: command sent okay\n", current->pid); + else { + dev_dbg(&sep->pdev->dev, "[PID%d]: cant send command\n", + current->pid); + clear_bit(SEP_LEGACY_SENDMSG_DONE_OFFSET, + &ta_ctx->call_status.status); } return result; } -/* This needs to be run as a work queue as it can be put asleep */ -static void sep_crypto_block(void *data) +/** + * This function sets things up for a crypto data block process + * This does all preparation, but does not try to grab the + * sep + * @req: pointer to struct ablkcipher_request + * returns: 0 if all went well, non zero if error + */ +static int sep_crypto_block_data(struct ablkcipher_request *req) { + int int_error; u32 msg_offset; static u32 msg[10]; @@ -1085,318 +1172,440 @@ static void sep_crypto_block(void *data) ssize_t copy_result; int result; - u32 max_length; struct scatterlist *new_sg; - struct ablkcipher_request *req; - struct sep_block_ctx *bctx; + struct this_task_ctx *ta_ctx; struct crypto_ablkcipher *tfm; struct sep_system_ctx *sctx; - req = (struct ablkcipher_request *)data; - bctx = ablkcipher_request_ctx(req); + struct sep_des_internal_context *des_internal; + struct sep_aes_internal_context *aes_internal; + + ta_ctx = ablkcipher_request_ctx(req); tfm = crypto_ablkcipher_reqtfm(req); sctx = crypto_ablkcipher_ctx(tfm); /* start the walk on scatterlists */ - ablkcipher_walk_init(&bctx->walk, req->src, req->dst, req->nbytes); - dev_dbg(&sctx->sep_used->pdev->dev, "sep crypto block data size of %x\n", + ablkcipher_walk_init(&ta_ctx->walk, req->src, req->dst, req->nbytes); + dev_dbg(&ta_ctx->sep_used->pdev->dev, "sep crypto block data size of %x\n", req->nbytes); - int_error = ablkcipher_walk_phys(req, &bctx->walk); + int_error = ablkcipher_walk_phys(req, &ta_ctx->walk); if (int_error) { - dev_warn(&sctx->sep_used->pdev->dev, "walk phys error %x\n", + dev_warn(&ta_ctx->sep_used->pdev->dev, "walk phys error %x\n", int_error); - sep_crypto_release(sctx, -ENOMEM); - return; - } - - /* check iv */ - if (bctx->des_opmode == SEP_DES_CBC) { - if (!bctx->walk.iv) { - dev_warn(&sctx->sep_used->pdev->dev, "no iv found\n"); - sep_crypto_release(sctx, -EINVAL); - return; - } - - memcpy(bctx->iv, bctx->walk.iv, SEP_DES_IV_SIZE_BYTES); - sep_dump(sctx->sep_used, "iv", bctx->iv, SEP_DES_IV_SIZE_BYTES); - } - - if (bctx->aes_opmode == SEP_AES_CBC) { - if (!bctx->walk.iv) { - dev_warn(&sctx->sep_used->pdev->dev, "no iv found\n"); - sep_crypto_release(sctx, -EINVAL); - return; - } - - memcpy(bctx->iv, bctx->walk.iv, SEP_AES_IV_SIZE_BYTES); - sep_dump(sctx->sep_used, "iv", bctx->iv, SEP_AES_IV_SIZE_BYTES); + return -ENOMEM; } - dev_dbg(&sctx->sep_used->pdev->dev, + dev_dbg(&ta_ctx->sep_used->pdev->dev, "crypto block: src is %lx dst is %lx\n", (unsigned long)req->src, (unsigned long)req->dst); /* Make sure all pages are even block */ - int_error = sep_oddball_pages(sctx->sep_used, req->src, - req->nbytes, bctx->walk.blocksize, &new_sg, 1); + int_error = sep_oddball_pages(ta_ctx->sep_used, req->src, + req->nbytes, ta_ctx->walk.blocksize, &new_sg, 1); if (int_error < 0) { - dev_warn(&sctx->sep_used->pdev->dev, "oddball page eerror\n"); - sep_crypto_release(sctx, -ENOMEM); - return; + dev_warn(&ta_ctx->sep_used->pdev->dev, "oddball page eerror\n"); + return -ENOMEM; } else if (int_error == 1) { - sctx->src_sg = new_sg; - sctx->src_sg_hold = new_sg; + ta_ctx->src_sg = new_sg; + ta_ctx->src_sg_hold = new_sg; } else { - sctx->src_sg = req->src; - sctx->src_sg_hold = NULL; + ta_ctx->src_sg = req->src; + ta_ctx->src_sg_hold = NULL; } - int_error = sep_oddball_pages(sctx->sep_used, req->dst, - req->nbytes, bctx->walk.blocksize, &new_sg, 0); + int_error = sep_oddball_pages(ta_ctx->sep_used, req->dst, + req->nbytes, ta_ctx->walk.blocksize, &new_sg, 0); if (int_error < 0) { - dev_warn(&sctx->sep_used->pdev->dev, "walk phys error %x\n", + dev_warn(&ta_ctx->sep_used->pdev->dev, "walk phys error %x\n", int_error); - sep_crypto_release(sctx, -ENOMEM); - return; + return -ENOMEM; } else if (int_error == 1) { - sctx->dst_sg = new_sg; - sctx->dst_sg_hold = new_sg; + ta_ctx->dst_sg = new_sg; + ta_ctx->dst_sg_hold = new_sg; } else { - sctx->dst_sg = req->dst; - sctx->dst_sg_hold = NULL; + ta_ctx->dst_sg = req->dst; + ta_ctx->dst_sg_hold = NULL; } - /* Do we need to perform init; ie; send key to sep? */ - if (sctx->key_sent == 0) { + /* set nbytes for queue status */ + ta_ctx->nbytes = req->nbytes; - dev_dbg(&sctx->sep_used->pdev->dev, "sending key\n"); + /* Key already done; this is for data */ + dev_dbg(&ta_ctx->sep_used->pdev->dev, "sending data\n"); - /* put together message to SEP */ - /* Start with op code */ - sep_make_header(sctx, &msg_offset, bctx->init_opcode); + sep_dump_sg(ta_ctx->sep_used, + "block sg in", ta_ctx->src_sg); - /* now deal with IV */ - if (bctx->init_opcode == SEP_DES_INIT_OPCODE) { - if (bctx->des_opmode == SEP_DES_CBC) { - sep_write_msg(sctx, bctx->iv, - SEP_DES_IV_SIZE_BYTES, sizeof(u32) * 4, - &msg_offset, 1); - sep_dump(sctx->sep_used, "initial IV", - bctx->walk.iv, SEP_DES_IV_SIZE_BYTES); - } else { - /* Skip if ECB */ - msg_offset += 4 * sizeof(u32); - } - } else { - max_length = ((SEP_AES_IV_SIZE_BYTES + 3) / - sizeof(u32)) * sizeof(u32); - if (bctx->aes_opmode == SEP_AES_CBC) { - sep_write_msg(sctx, bctx->iv, - SEP_AES_IV_SIZE_BYTES, max_length, - &msg_offset, 1); - sep_dump(sctx->sep_used, "initial IV", - bctx->walk.iv, SEP_AES_IV_SIZE_BYTES); - } else { - /* Skip if ECB */ - msg_offset += max_length; - } - } + /* check for valid data and proper spacing */ + src_ptr = sg_virt(ta_ctx->src_sg); + dst_ptr = sg_virt(ta_ctx->dst_sg); - /* load the key */ - if (bctx->init_opcode == SEP_DES_INIT_OPCODE) { - sep_write_msg(sctx, (void *)&sctx->key.des.key1, - sizeof(u32) * 8, sizeof(u32) * 8, - &msg_offset, 1); + if (!src_ptr || !dst_ptr || + (ta_ctx->current_cypher_req->nbytes % + crypto_ablkcipher_blocksize(tfm))) { + + dev_warn(&ta_ctx->sep_used->pdev->dev, + "cipher block size odd\n"); + dev_warn(&ta_ctx->sep_used->pdev->dev, + "cipher block size is %x\n", + crypto_ablkcipher_blocksize(tfm)); + dev_warn(&ta_ctx->sep_used->pdev->dev, + "cipher data size is %x\n", + ta_ctx->current_cypher_req->nbytes); + return -EINVAL; + } - msg[0] = (u32)sctx->des_nbr_keys; - msg[1] = (u32)bctx->des_encmode; - msg[2] = (u32)bctx->des_opmode; + if (partial_overlap(src_ptr, dst_ptr, + ta_ctx->current_cypher_req->nbytes)) { + dev_warn(&ta_ctx->sep_used->pdev->dev, + "block partial overlap\n"); + return -EINVAL; + } - sep_write_msg(sctx, (void *)msg, - sizeof(u32) * 3, sizeof(u32) * 3, - &msg_offset, 0); - } else { - sep_write_msg(sctx, (void *)&sctx->key.aes, - sctx->keylen, - SEP_AES_MAX_KEY_SIZE_BYTES, - &msg_offset, 1); + /* Put together the message */ + sep_make_header(ta_ctx, &msg_offset, ta_ctx->block_opcode); + + /* If des, and size is 1 block, put directly in msg */ + if ((ta_ctx->block_opcode == SEP_DES_BLOCK_OPCODE) && + (req->nbytes == crypto_ablkcipher_blocksize(tfm))) { + + dev_dbg(&ta_ctx->sep_used->pdev->dev, + "writing out one block des\n"); + + copy_result = sg_copy_to_buffer( + ta_ctx->src_sg, sep_sg_nents(ta_ctx->src_sg), + small_buf, crypto_ablkcipher_blocksize(tfm)); - msg[0] = (u32)sctx->aes_key_size; - msg[1] = (u32)bctx->aes_encmode; - msg[2] = (u32)bctx->aes_opmode; - msg[3] = (u32)0; /* Secret key is not used */ - sep_write_msg(sctx, (void *)msg, - sizeof(u32) * 4, sizeof(u32) * 4, - &msg_offset, 0); + if (copy_result != crypto_ablkcipher_blocksize(tfm)) { + dev_warn(&ta_ctx->sep_used->pdev->dev, + "des block copy faild\n"); + return -ENOMEM; } + /* Put data into message */ + sep_write_msg(ta_ctx, small_buf, + crypto_ablkcipher_blocksize(tfm), + crypto_ablkcipher_blocksize(tfm) * 2, + &msg_offset, 1); + + /* Put size into message */ + sep_write_msg(ta_ctx, &req->nbytes, + sizeof(u32), sizeof(u32), &msg_offset, 0); } else { + /* Otherwise, fill out dma tables */ + ta_ctx->dcb_input_data.app_in_address = src_ptr; + ta_ctx->dcb_input_data.data_in_size = req->nbytes; + ta_ctx->dcb_input_data.app_out_address = dst_ptr; + ta_ctx->dcb_input_data.block_size = + crypto_ablkcipher_blocksize(tfm); + ta_ctx->dcb_input_data.tail_block_size = 0; + ta_ctx->dcb_input_data.is_applet = 0; + ta_ctx->dcb_input_data.src_sg = ta_ctx->src_sg; + ta_ctx->dcb_input_data.dst_sg = ta_ctx->dst_sg; + + result = sep_create_dcb_dmatables_context_kernel( + ta_ctx->sep_used, + &ta_ctx->dcb_region, + &ta_ctx->dmatables_region, + &ta_ctx->dma_ctx, + &ta_ctx->dcb_input_data, + 1); + if (result) { + dev_warn(&ta_ctx->sep_used->pdev->dev, + "crypto dma table create failed\n"); + return -EINVAL; + } + + /* Portion of msg is nulled (no data) */ + msg[0] = (u32)0; + msg[1] = (u32)0; + msg[2] = (u32)0; + msg[3] = (u32)0; + msg[4] = (u32)0; + sep_write_msg(ta_ctx, (void *)msg, sizeof(u32) * 5, + sizeof(u32) * 5, &msg_offset, 0); + } - /* set nbytes for queue status */ - sctx->nbytes = req->nbytes; + /** + * Before we write the message, we need to overwrite the + * vendor's IV with the one from our own ablkcipher walk + * iv because this is needed for dm-crypt + */ + sep_dump_ivs(req, "sending data block to sep\n"); + if ((ta_ctx->current_request == DES_CBC) && + (ta_ctx->des_opmode == SEP_DES_CBC)) { + + dev_dbg(&ta_ctx->sep_used->pdev->dev, + "overwrite vendor iv on DES\n"); + des_internal = (struct sep_des_internal_context *) + sctx->des_private_ctx.ctx_buf; + memcpy((void *)des_internal->iv_context, + ta_ctx->walk.iv, crypto_ablkcipher_ivsize(tfm)); + } else if ((ta_ctx->current_request == AES_CBC) && + (ta_ctx->aes_opmode == SEP_AES_CBC)) { + + dev_dbg(&ta_ctx->sep_used->pdev->dev, + "overwrite vendor iv on AES\n"); + aes_internal = (struct sep_aes_internal_context *) + sctx->aes_private_ctx.cbuff; + memcpy((void *)aes_internal->aes_ctx_iv, + ta_ctx->walk.iv, crypto_ablkcipher_ivsize(tfm)); + } + + /* Write context into message */ + if (ta_ctx->block_opcode == SEP_DES_BLOCK_OPCODE) { + sep_write_context(ta_ctx, &msg_offset, + &sctx->des_private_ctx, + sizeof(struct sep_des_private_context)); + sep_dump(ta_ctx->sep_used, "ctx to block des", + &sctx->des_private_ctx, 40); + } else { + sep_write_context(ta_ctx, &msg_offset, + &sctx->aes_private_ctx, + sizeof(struct sep_aes_private_context)); + sep_dump(ta_ctx->sep_used, "ctx to block aes", + &sctx->aes_private_ctx, 20); + } - /* Key already done; this is for data */ - dev_dbg(&sctx->sep_used->pdev->dev, "sending data\n"); + /* conclude message */ + sep_end_msg(ta_ctx, msg_offset); - sep_dump_sg(sctx->sep_used, - "block sg in", sctx->src_sg); + /* Parent (caller) is now ready to tell the sep to do ahead */ + return 0; +} - /* check for valid data and proper spacing */ - src_ptr = sg_virt(sctx->src_sg); - dst_ptr = sg_virt(sctx->dst_sg); - if (!src_ptr || !dst_ptr || - (sctx->current_cypher_req->nbytes % - crypto_ablkcipher_blocksize(tfm))) { +/** + * This function sets things up for a crypto key submit process + * This does all preparation, but does not try to grab the + * sep + * @req: pointer to struct ablkcipher_request + * returns: 0 if all went well, non zero if error + */ +static int sep_crypto_send_key(struct ablkcipher_request *req) +{ - dev_warn(&sctx->sep_used->pdev->dev, - "cipher block size odd\n"); - dev_warn(&sctx->sep_used->pdev->dev, - "cipher block size is %x\n", - crypto_ablkcipher_blocksize(tfm)); - dev_warn(&sctx->sep_used->pdev->dev, - "cipher data size is %x\n", - sctx->current_cypher_req->nbytes); - sep_crypto_release(sctx, -EINVAL); - return; - } + int int_error; + u32 msg_offset; + static u32 msg[10]; - if (partial_overlap(src_ptr, dst_ptr, - sctx->current_cypher_req->nbytes)) { - dev_warn(&sctx->sep_used->pdev->dev, - "block partial overlap\n"); - sep_crypto_release(sctx, -EINVAL); - return; - } + u32 max_length; + struct this_task_ctx *ta_ctx; + struct crypto_ablkcipher *tfm; + struct sep_system_ctx *sctx; - /* Put together the message */ - sep_make_header(sctx, &msg_offset, bctx->block_opcode); + ta_ctx = ablkcipher_request_ctx(req); + tfm = crypto_ablkcipher_reqtfm(req); + sctx = crypto_ablkcipher_ctx(tfm); - /* If des, and size is 1 block, put directly in msg */ - if ((bctx->block_opcode == SEP_DES_BLOCK_OPCODE) && - (req->nbytes == crypto_ablkcipher_blocksize(tfm))) { + dev_dbg(&ta_ctx->sep_used->pdev->dev, "sending key\n"); - dev_dbg(&sctx->sep_used->pdev->dev, - "writing out one block des\n"); + /* start the walk on scatterlists */ + ablkcipher_walk_init(&ta_ctx->walk, req->src, req->dst, req->nbytes); + dev_dbg(&ta_ctx->sep_used->pdev->dev, + "sep crypto block data size of %x\n", req->nbytes); - copy_result = sg_copy_to_buffer( - sctx->src_sg, sep_sg_nents(sctx->src_sg), - small_buf, crypto_ablkcipher_blocksize(tfm)); + int_error = ablkcipher_walk_phys(req, &ta_ctx->walk); + if (int_error) { + dev_warn(&ta_ctx->sep_used->pdev->dev, "walk phys error %x\n", + int_error); + return -ENOMEM; + } - if (copy_result != crypto_ablkcipher_blocksize(tfm)) { - dev_warn(&sctx->sep_used->pdev->dev, - "des block copy faild\n"); - sep_crypto_release(sctx, -ENOMEM); - return; - } + /* check iv */ + if ((ta_ctx->current_request == DES_CBC) && + (ta_ctx->des_opmode == SEP_DES_CBC)) { + if (!ta_ctx->walk.iv) { + dev_warn(&ta_ctx->sep_used->pdev->dev, "no iv found\n"); + return -EINVAL; + } - /* Put data into message */ - sep_write_msg(sctx, small_buf, - crypto_ablkcipher_blocksize(tfm), - crypto_ablkcipher_blocksize(tfm) * 2, - &msg_offset, 1); + memcpy(ta_ctx->iv, ta_ctx->walk.iv, SEP_DES_IV_SIZE_BYTES); + sep_dump(ta_ctx->sep_used, "iv", + ta_ctx->iv, SEP_DES_IV_SIZE_BYTES); + } - /* Put size into message */ - sep_write_msg(sctx, &req->nbytes, - sizeof(u32), sizeof(u32), &msg_offset, 0); + if ((ta_ctx->current_request == AES_CBC) && + (ta_ctx->aes_opmode == SEP_AES_CBC)) { + if (!ta_ctx->walk.iv) { + dev_warn(&ta_ctx->sep_used->pdev->dev, "no iv found\n"); + return -EINVAL; + } + + memcpy(ta_ctx->iv, ta_ctx->walk.iv, SEP_AES_IV_SIZE_BYTES); + sep_dump(ta_ctx->sep_used, "iv", + ta_ctx->iv, SEP_AES_IV_SIZE_BYTES); + } + + /* put together message to SEP */ + /* Start with op code */ + sep_make_header(ta_ctx, &msg_offset, ta_ctx->init_opcode); + + /* now deal with IV */ + if (ta_ctx->init_opcode == SEP_DES_INIT_OPCODE) { + if (ta_ctx->des_opmode == SEP_DES_CBC) { + sep_write_msg(ta_ctx, ta_ctx->iv, + SEP_DES_IV_SIZE_BYTES, sizeof(u32) * 4, + &msg_offset, 1); + sep_dump(ta_ctx->sep_used, "initial IV", + ta_ctx->walk.iv, SEP_DES_IV_SIZE_BYTES); + } else { + /* Skip if ECB */ + msg_offset += 4 * sizeof(u32); + } + } else { + max_length = ((SEP_AES_IV_SIZE_BYTES + 3) / + sizeof(u32)) * sizeof(u32); + if (ta_ctx->aes_opmode == SEP_AES_CBC) { + sep_write_msg(ta_ctx, ta_ctx->iv, + SEP_AES_IV_SIZE_BYTES, max_length, + &msg_offset, 1); + sep_dump(ta_ctx->sep_used, "initial IV", + ta_ctx->walk.iv, SEP_AES_IV_SIZE_BYTES); } else { - /* Otherwise, fill out dma tables */ - sctx->dcb_input_data.app_in_address = src_ptr; - sctx->dcb_input_data.data_in_size = req->nbytes; - sctx->dcb_input_data.app_out_address = dst_ptr; - sctx->dcb_input_data.block_size = - crypto_ablkcipher_blocksize(tfm); - sctx->dcb_input_data.tail_block_size = 0; - sctx->dcb_input_data.is_applet = 0; - sctx->dcb_input_data.src_sg = sctx->src_sg; - sctx->dcb_input_data.dst_sg = sctx->dst_sg; - - result = sep_create_dcb_dmatables_context_kernel( - sctx->sep_used, - &sctx->dcb_region, - &sctx->dmatables_region, - &sctx->dma_ctx, - &sctx->dcb_input_data, - 1); - if (result) { - dev_warn(&sctx->sep_used->pdev->dev, - "crypto dma table create failed\n"); - sep_crypto_release(sctx, -EINVAL); - return; + /* Skip if ECB */ + msg_offset += max_length; } + } + + /* load the key */ + if (ta_ctx->init_opcode == SEP_DES_INIT_OPCODE) { + sep_write_msg(ta_ctx, (void *)&sctx->key.des.key1, + sizeof(u32) * 8, sizeof(u32) * 8, + &msg_offset, 1); + + msg[0] = (u32)sctx->des_nbr_keys; + msg[1] = (u32)ta_ctx->des_encmode; + msg[2] = (u32)ta_ctx->des_opmode; - /* Portion of msg is nulled (no data) */ - msg[0] = (u32)0; - msg[1] = (u32)0; - msg[2] = (u32)0; - msg[3] = (u32)0; - msg[4] = (u32)0; - sep_write_msg(sctx, (void *)msg, - sizeof(u32) * 5, - sizeof(u32) * 5, - &msg_offset, 0); + sep_write_msg(ta_ctx, (void *)msg, + sizeof(u32) * 3, sizeof(u32) * 3, + &msg_offset, 0); + } else { + sep_write_msg(ta_ctx, (void *)&sctx->key.aes, + sctx->keylen, + SEP_AES_MAX_KEY_SIZE_BYTES, + &msg_offset, 1); + + msg[0] = (u32)sctx->aes_key_size; + msg[1] = (u32)ta_ctx->aes_encmode; + msg[2] = (u32)ta_ctx->aes_opmode; + msg[3] = (u32)0; /* Secret key is not used */ + sep_write_msg(ta_ctx, (void *)msg, + sizeof(u32) * 4, sizeof(u32) * 4, + &msg_offset, 0); + } + + /* conclude message */ + sep_end_msg(ta_ctx, msg_offset); + + /* Parent (caller) is now ready to tell the sep to do ahead */ + return 0; +} + + +/* This needs to be run as a work queue as it can be put asleep */ +static void sep_crypto_block(void *data) +{ + unsigned long end_time; + + int result; + + struct ablkcipher_request *req; + struct this_task_ctx *ta_ctx; + struct crypto_ablkcipher *tfm; + struct sep_system_ctx *sctx; + int are_we_done_yet; + + req = (struct ablkcipher_request *)data; + ta_ctx = ablkcipher_request_ctx(req); + tfm = crypto_ablkcipher_reqtfm(req); + sctx = crypto_ablkcipher_ctx(tfm); + + ta_ctx->are_we_done_yet = &are_we_done_yet; + + pr_debug("sep_crypto_block\n"); + pr_debug("tfm is %p sctx is %p ta_ctx is %p\n", + tfm, sctx, ta_ctx); + pr_debug("key_sent is %d\n", sctx->key_sent); + + /* do we need to send the key */ + if (sctx->key_sent == 0) { + are_we_done_yet = 0; + result = sep_crypto_send_key(req); /* prep to send key */ + if (result != 0) { + dev_dbg(&ta_ctx->sep_used->pdev->dev, + "could not prep key %x\n", result); + sep_crypto_release(sctx, ta_ctx, result); + return; } - /* Write context into message */ - if (bctx->block_opcode == SEP_DES_BLOCK_OPCODE) { - sep_write_context(sctx, &msg_offset, - &bctx->des_private_ctx, - sizeof(struct sep_des_private_context)); - sep_dump(sctx->sep_used, "ctx to block des", - &bctx->des_private_ctx, 40); - } else { - sep_write_context(sctx, &msg_offset, - &bctx->aes_private_ctx, - sizeof(struct sep_aes_private_context)); - sep_dump(sctx->sep_used, "ctx to block aes", - &bctx->aes_private_ctx, 20); + result = sep_crypto_take_sep(ta_ctx); + if (result) { + dev_warn(&ta_ctx->sep_used->pdev->dev, + "sep_crypto_take_sep for key send failed\n"); + sep_crypto_release(sctx, ta_ctx, result); + return; + } + + /* now we sit and wait up to a fixed time for completion */ + end_time = jiffies + (WAIT_TIME * HZ); + while ((time_before(jiffies, end_time)) && + (are_we_done_yet == 0)) + schedule(); + + /* Done waiting; still not done yet? */ + if (are_we_done_yet == 0) { + dev_dbg(&ta_ctx->sep_used->pdev->dev, + "Send key job never got done\n"); + sep_crypto_release(sctx, ta_ctx, -EINVAL); + return; } + + /* Set the key sent variable so this can be skipped later */ + sctx->key_sent = 1; } - /* conclude message and then tell sep to do its thing */ - sctx->done_with_transaction = 0; + /* Key sent (or maybe not if we did not have to), now send block */ + are_we_done_yet = 0; - sep_end_msg(sctx, msg_offset); - result = sep_crypto_take_sep(sctx); - if (result) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep_crypto_take_sep failed\n"); - sep_crypto_release(sctx, -EINVAL); + result = sep_crypto_block_data(req); + + if (result != 0) { + dev_dbg(&ta_ctx->sep_used->pdev->dev, + "could prep not send block %x\n", result); + sep_crypto_release(sctx, ta_ctx, result); return; } - /** - * Sep is now working. Lets wait up to 5 seconds - * for completion. If it does not complete, we will do - * a crypto release with -EINVAL to release the - * kernel crypto infrastructure and let the system - * continue to boot up - * We have to wait this long because some crypto - * operations can take a while - */ - - dev_dbg(&sctx->sep_used->pdev->dev, - "waiting for done with transaction\n"); + result = sep_crypto_take_sep(ta_ctx); + if (result) { + dev_warn(&ta_ctx->sep_used->pdev->dev, + "sep_crypto_take_sep for block send failed\n"); + sep_crypto_release(sctx, ta_ctx, result); + return; + } - sctx->end_time = jiffies + (SEP_TRANSACTION_WAIT_TIME * HZ); - while ((time_before(jiffies, sctx->end_time)) && - (!sctx->done_with_transaction)) + /* now we sit and wait up to a fixed time for completion */ + end_time = jiffies + (WAIT_TIME * HZ); + while ((time_before(jiffies, end_time)) && (are_we_done_yet == 0)) schedule(); - dev_dbg(&sctx->sep_used->pdev->dev, - "done waiting for done with transaction\n"); - - /* are we done? */ - if (!sctx->done_with_transaction) { - /* Nope, lets release and tell crypto no */ - dev_warn(&sctx->sep_used->pdev->dev, - "[PID%d] sep_crypto_block never finished\n", - current->pid); - sep_crypto_release(sctx, -EINVAL); + /* Done waiting; still not done yet? */ + if (are_we_done_yet == 0) { + dev_dbg(&ta_ctx->sep_used->pdev->dev, + "Send block job never got done\n"); + sep_crypto_release(sctx, ta_ctx, -EINVAL); + return; } + + /* That's it; entire thing done, get out of queue */ + + pr_debug("crypto_block leaving\n"); + pr_debug("tfm is %p sctx is %p ta_ctx is %p\n", tfm, sctx, ta_ctx); } /** @@ -1405,7 +1614,6 @@ static void sep_crypto_block(void *data) static u32 crypto_post_op(struct sep_device *sep) { /* HERE */ - int int_error; u32 u32_error; u32 msg_offset; @@ -1413,169 +1621,185 @@ static u32 crypto_post_op(struct sep_device *sep) static char small_buf[100]; struct ablkcipher_request *req; - struct sep_block_ctx *bctx; + struct this_task_ctx *ta_ctx; struct sep_system_ctx *sctx; struct crypto_ablkcipher *tfm; + struct sep_des_internal_context *des_internal; + struct sep_aes_internal_context *aes_internal; + if (!sep->current_cypher_req) return -EINVAL; /* hold req since we need to submit work after clearing sep */ req = sep->current_cypher_req; - bctx = ablkcipher_request_ctx(sep->current_cypher_req); + ta_ctx = ablkcipher_request_ctx(sep->current_cypher_req); tfm = crypto_ablkcipher_reqtfm(sep->current_cypher_req); sctx = crypto_ablkcipher_ctx(tfm); - dev_dbg(&sctx->sep_used->pdev->dev, "crypto post_op\n"); - dev_dbg(&sctx->sep_used->pdev->dev, "crypto post_op message dump\n"); - crypto_sep_dump_message(sctx); + pr_debug("crypto_post op\n"); + pr_debug("key_sent is %d tfm is %p sctx is %p ta_ctx is %p\n", + sctx->key_sent, tfm, sctx, ta_ctx); - sctx->done_with_transaction = 1; + dev_dbg(&ta_ctx->sep_used->pdev->dev, "crypto post_op\n"); + dev_dbg(&ta_ctx->sep_used->pdev->dev, "crypto post_op message dump\n"); + crypto_sep_dump_message(ta_ctx->sep_used, ta_ctx->msg); /* first bring msg from shared area to local area */ - memcpy(sctx->msg, sep->shared_addr, + memcpy(ta_ctx->msg, sep->shared_addr, SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES); /* Is this the result of performing init (key to SEP */ if (sctx->key_sent == 0) { /* Did SEP do it okay */ - u32_error = sep_verify_op(sctx, bctx->init_opcode, + u32_error = sep_verify_op(ta_ctx, ta_ctx->init_opcode, &msg_offset); if (u32_error) { - dev_warn(&sctx->sep_used->pdev->dev, + dev_warn(&ta_ctx->sep_used->pdev->dev, "aes init error %x\n", u32_error); - sep_crypto_release(sctx, u32_error); + sep_crypto_release(sctx, ta_ctx, u32_error); return u32_error; } /* Read Context */ - if (bctx->init_opcode == SEP_DES_INIT_OPCODE) { - sep_read_context(sctx, &msg_offset, - &bctx->des_private_ctx, + if (ta_ctx->init_opcode == SEP_DES_INIT_OPCODE) { + sep_read_context(ta_ctx, &msg_offset, + &sctx->des_private_ctx, sizeof(struct sep_des_private_context)); - sep_dump(sctx->sep_used, "ctx init des", - &bctx->des_private_ctx, 40); + sep_dump(ta_ctx->sep_used, "ctx init des", + &sctx->des_private_ctx, 40); } else { - sep_read_context(sctx, &msg_offset, - &bctx->aes_private_ctx, - sizeof(struct sep_des_private_context)); - - sep_dump(sctx->sep_used, "ctx init aes", - &bctx->aes_private_ctx, 20); - } - - /* We are done with init. Now send out the data */ - /* first release the sep */ - sctx->key_sent = 1; - sep_crypto_release(sctx, -EINPROGRESS); + sep_read_context(ta_ctx, &msg_offset, + &sctx->aes_private_ctx, + sizeof(struct sep_aes_private_context)); - spin_lock_irq(&queue_lock); - int_error = crypto_enqueue_request(&sep_queue, &req->base); - spin_unlock_irq(&queue_lock); - - if ((int_error != 0) && (int_error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "spe cypher post op cant queue\n"); - sep_crypto_release(sctx, int_error); - return int_error; + sep_dump(ta_ctx->sep_used, "ctx init aes", + &sctx->aes_private_ctx, 20); } - /* schedule the data send */ - int_error = sep_submit_work(sep->workqueue, sep_dequeuer, - (void *)&sep_queue); + sep_dump_ivs(req, "after sending key to sep\n"); - if (int_error) { - dev_warn(&sep->pdev->dev, - "cant submit work sep_crypto_block\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } + /* key sent went okay; release sep, and set are_we_done_yet */ + sctx->key_sent = 1; + sep_crypto_release(sctx, ta_ctx, -EINPROGRESS); } else { /** * This is the result of a block request */ - dev_dbg(&sctx->sep_used->pdev->dev, + dev_dbg(&ta_ctx->sep_used->pdev->dev, "crypto_post_op block response\n"); - u32_error = sep_verify_op(sctx, bctx->block_opcode, + u32_error = sep_verify_op(ta_ctx, ta_ctx->block_opcode, &msg_offset); if (u32_error) { - dev_warn(&sctx->sep_used->pdev->dev, + dev_warn(&ta_ctx->sep_used->pdev->dev, "sep block error %x\n", u32_error); - sep_crypto_release(sctx, u32_error); + sep_crypto_release(sctx, ta_ctx, u32_error); return -EINVAL; } - if (bctx->block_opcode == SEP_DES_BLOCK_OPCODE) { + if (ta_ctx->block_opcode == SEP_DES_BLOCK_OPCODE) { - dev_dbg(&sctx->sep_used->pdev->dev, + dev_dbg(&ta_ctx->sep_used->pdev->dev, "post op for DES\n"); /* special case for 1 block des */ if (sep->current_cypher_req->nbytes == crypto_ablkcipher_blocksize(tfm)) { - sep_read_msg(sctx, small_buf, + sep_read_msg(ta_ctx, small_buf, crypto_ablkcipher_blocksize(tfm), crypto_ablkcipher_blocksize(tfm) * 2, &msg_offset, 1); - dev_dbg(&sctx->sep_used->pdev->dev, + dev_dbg(&ta_ctx->sep_used->pdev->dev, "reading in block des\n"); copy_result = sg_copy_from_buffer( - sctx->dst_sg, - sep_sg_nents(sctx->dst_sg), + ta_ctx->dst_sg, + sep_sg_nents(ta_ctx->dst_sg), small_buf, crypto_ablkcipher_blocksize(tfm)); if (copy_result != crypto_ablkcipher_blocksize(tfm)) { - dev_warn(&sctx->sep_used->pdev->dev, + dev_warn(&ta_ctx->sep_used->pdev->dev, "des block copy faild\n"); - sep_crypto_release(sctx, -ENOMEM); + sep_crypto_release(sctx, ta_ctx, + -ENOMEM); return -ENOMEM; } } /* Read Context */ - sep_read_context(sctx, &msg_offset, - &bctx->des_private_ctx, + sep_read_context(ta_ctx, &msg_offset, + &sctx->des_private_ctx, sizeof(struct sep_des_private_context)); } else { - dev_dbg(&sctx->sep_used->pdev->dev, + dev_dbg(&ta_ctx->sep_used->pdev->dev, "post op for AES\n"); /* Skip the MAC Output */ msg_offset += (sizeof(u32) * 4); /* Read Context */ - sep_read_context(sctx, &msg_offset, - &bctx->aes_private_ctx, + sep_read_context(ta_ctx, &msg_offset, + &sctx->aes_private_ctx, sizeof(struct sep_aes_private_context)); } - sep_dump_sg(sctx->sep_used, - "block sg out", sctx->dst_sg); + sep_dump_sg(ta_ctx->sep_used, + "block sg out", ta_ctx->dst_sg); /* Copy to correct sg if this block had oddball pages */ - if (sctx->dst_sg_hold) - sep_copy_sg(sctx->sep_used, - sctx->dst_sg, - sctx->current_cypher_req->dst, - sctx->current_cypher_req->nbytes); + if (ta_ctx->dst_sg_hold) + sep_copy_sg(ta_ctx->sep_used, + ta_ctx->dst_sg, + ta_ctx->current_cypher_req->dst, + ta_ctx->current_cypher_req->nbytes); + + /** + * Copy the iv's back to the walk.iv + * This is required for dm_crypt + */ + sep_dump_ivs(req, "got data block from sep\n"); + if ((ta_ctx->current_request == DES_CBC) && + (ta_ctx->des_opmode == SEP_DES_CBC)) { + + dev_dbg(&ta_ctx->sep_used->pdev->dev, + "returning result iv to walk on DES\n"); + des_internal = (struct sep_des_internal_context *) + sctx->des_private_ctx.ctx_buf; + memcpy(ta_ctx->walk.iv, + (void *)des_internal->iv_context, + crypto_ablkcipher_ivsize(tfm)); + } else if ((ta_ctx->current_request == AES_CBC) && + (ta_ctx->aes_opmode == SEP_AES_CBC)) { + + dev_dbg(&ta_ctx->sep_used->pdev->dev, + "returning result iv to walk on AES\n"); + aes_internal = (struct sep_aes_internal_context *) + sctx->aes_private_ctx.cbuff; + memcpy(ta_ctx->walk.iv, + (void *)aes_internal->aes_ctx_iv, + crypto_ablkcipher_ivsize(tfm)); + } /* finished, release everything */ - sep_crypto_release(sctx, 0); + sep_crypto_release(sctx, ta_ctx, 0); } + pr_debug("crypto_post_op done\n"); + pr_debug("key_sent is %d tfm is %p sctx is %p ta_ctx is %p\n", + sctx->key_sent, tfm, sctx, ta_ctx); + return 0; } @@ -1584,35 +1808,33 @@ static u32 hash_init_post_op(struct sep_device *sep) u32 u32_error; u32 msg_offset; struct crypto_ahash *tfm = crypto_ahash_reqtfm(sep->current_hash_req); - struct sep_hash_ctx *ctx = ahash_request_ctx(sep->current_hash_req); + struct this_task_ctx *ta_ctx = ahash_request_ctx(sep->current_hash_req); struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); - dev_dbg(&sctx->sep_used->pdev->dev, + dev_dbg(&ta_ctx->sep_used->pdev->dev, "hash init post op\n"); - sctx->done_with_transaction = 1; - /* first bring msg from shared area to local area */ - memcpy(sctx->msg, sep->shared_addr, + memcpy(ta_ctx->msg, sep->shared_addr, SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES); - u32_error = sep_verify_op(sctx, SEP_HASH_INIT_OPCODE, + u32_error = sep_verify_op(ta_ctx, SEP_HASH_INIT_OPCODE, &msg_offset); if (u32_error) { - dev_warn(&sctx->sep_used->pdev->dev, "hash init error %x\n", + dev_warn(&ta_ctx->sep_used->pdev->dev, "hash init error %x\n", u32_error); - sep_crypto_release(sctx, u32_error); + sep_crypto_release(sctx, ta_ctx, u32_error); return u32_error; } /* Read Context */ - sep_read_context(sctx, &msg_offset, - &ctx->hash_private_ctx, + sep_read_context(ta_ctx, &msg_offset, + &sctx->hash_private_ctx, sizeof(struct sep_hash_private_context)); /* Signal to crypto infrastructure and clear out */ - dev_dbg(&sctx->sep_used->pdev->dev, "hash init post op done\n"); - sep_crypto_release(sctx, 0); + dev_dbg(&ta_ctx->sep_used->pdev->dev, "hash init post op done\n"); + sep_crypto_release(sctx, ta_ctx, 0); return 0; } @@ -1621,33 +1843,69 @@ static u32 hash_update_post_op(struct sep_device *sep) u32 u32_error; u32 msg_offset; struct crypto_ahash *tfm = crypto_ahash_reqtfm(sep->current_hash_req); - struct sep_hash_ctx *ctx = ahash_request_ctx(sep->current_hash_req); + struct this_task_ctx *ta_ctx = ahash_request_ctx(sep->current_hash_req); struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); - dev_dbg(&sctx->sep_used->pdev->dev, + dev_dbg(&ta_ctx->sep_used->pdev->dev, "hash update post op\n"); - sctx->done_with_transaction = 1; - /* first bring msg from shared area to local area */ - memcpy(sctx->msg, sep->shared_addr, + memcpy(ta_ctx->msg, sep->shared_addr, SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES); - u32_error = sep_verify_op(sctx, SEP_HASH_UPDATE_OPCODE, + u32_error = sep_verify_op(ta_ctx, SEP_HASH_UPDATE_OPCODE, &msg_offset); if (u32_error) { - dev_warn(&sctx->sep_used->pdev->dev, "hash init error %x\n", + dev_warn(&ta_ctx->sep_used->pdev->dev, "hash init error %x\n", u32_error); - sep_crypto_release(sctx, u32_error); + sep_crypto_release(sctx, ta_ctx, u32_error); return u32_error; } /* Read Context */ - sep_read_context(sctx, &msg_offset, - &ctx->hash_private_ctx, + sep_read_context(ta_ctx, &msg_offset, + &sctx->hash_private_ctx, sizeof(struct sep_hash_private_context)); - sep_crypto_release(sctx, 0); + /** + * Following is only for finup; if we just completd the + * data portion of finup, we now need to kick off the + * finish portion of finup. + */ + + if (ta_ctx->sep_used->current_hash_stage == HASH_FINUP_DATA) { + + /* first reset stage to HASH_FINUP_FINISH */ + ta_ctx->sep_used->current_hash_stage = HASH_FINUP_FINISH; + + /* now enqueue the finish operation */ + spin_lock_irq(&queue_lock); + u32_error = crypto_enqueue_request(&sep_queue, + &ta_ctx->sep_used->current_hash_req->base); + spin_unlock_irq(&queue_lock); + + if ((u32_error != 0) && (u32_error != -EINPROGRESS)) { + dev_warn(&ta_ctx->sep_used->pdev->dev, + "spe cypher post op cant queue\n"); + sep_crypto_release(sctx, ta_ctx, u32_error); + return u32_error; + } + + /* schedule the data send */ + u32_error = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + + if (u32_error) { + dev_warn(&ta_ctx->sep_used->pdev->dev, + "cant submit work sep_crypto_block\n"); + sep_crypto_release(sctx, ta_ctx, -EINVAL); + return -EINVAL; + } + } + + /* Signal to crypto infrastructure and clear out */ + dev_dbg(&ta_ctx->sep_used->pdev->dev, "hash update post op done\n"); + sep_crypto_release(sctx, ta_ctx, 0); return 0; } @@ -1658,45 +1916,44 @@ static u32 hash_final_post_op(struct sep_device *sep) u32 msg_offset; struct crypto_ahash *tfm = crypto_ahash_reqtfm(sep->current_hash_req); struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); - dev_dbg(&sctx->sep_used->pdev->dev, + struct this_task_ctx *ta_ctx = ahash_request_ctx(sep->current_hash_req); + dev_dbg(&ta_ctx->sep_used->pdev->dev, "hash final post op\n"); - sctx->done_with_transaction = 1; - /* first bring msg from shared area to local area */ - memcpy(sctx->msg, sep->shared_addr, + memcpy(ta_ctx->msg, sep->shared_addr, SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES); - u32_error = sep_verify_op(sctx, SEP_HASH_FINISH_OPCODE, + u32_error = sep_verify_op(ta_ctx, SEP_HASH_FINISH_OPCODE, &msg_offset); if (u32_error) { - dev_warn(&sctx->sep_used->pdev->dev, "hash finish error %x\n", + dev_warn(&ta_ctx->sep_used->pdev->dev, "hash finish error %x\n", u32_error); - sep_crypto_release(sctx, u32_error); + sep_crypto_release(sctx, ta_ctx, u32_error); return u32_error; } /* Grab the result */ - if (sctx->current_hash_req->result == NULL) { + if (ta_ctx->current_hash_req->result == NULL) { /* Oops, null buffer; error out here */ - dev_warn(&sctx->sep_used->pdev->dev, + dev_warn(&ta_ctx->sep_used->pdev->dev, "hash finish null buffer\n"); - sep_crypto_release(sctx, (u32)-ENOMEM); + sep_crypto_release(sctx, ta_ctx, (u32)-ENOMEM); return -ENOMEM; } max_length = (((SEP_HASH_RESULT_SIZE_WORDS * sizeof(u32)) + 3) / sizeof(u32)) * sizeof(u32); - sep_read_msg(sctx, - sctx->current_hash_req->result, + sep_read_msg(ta_ctx, + ta_ctx->current_hash_req->result, crypto_ahash_digestsize(tfm), max_length, &msg_offset, 0); /* Signal to crypto infrastructure and clear out */ - dev_dbg(&sctx->sep_used->pdev->dev, "hash finish post op done\n"); - sep_crypto_release(sctx, 0); + dev_dbg(&ta_ctx->sep_used->pdev->dev, "hash finish post op done\n"); + sep_crypto_release(sctx, ta_ctx, 0); return 0; } @@ -1707,48 +1964,47 @@ static u32 hash_digest_post_op(struct sep_device *sep) u32 msg_offset; struct crypto_ahash *tfm = crypto_ahash_reqtfm(sep->current_hash_req); struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); - dev_dbg(&sctx->sep_used->pdev->dev, + struct this_task_ctx *ta_ctx = ahash_request_ctx(sep->current_hash_req); + dev_dbg(&ta_ctx->sep_used->pdev->dev, "hash digest post op\n"); - sctx->done_with_transaction = 1; - /* first bring msg from shared area to local area */ - memcpy(sctx->msg, sep->shared_addr, + memcpy(ta_ctx->msg, sep->shared_addr, SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES); - u32_error = sep_verify_op(sctx, SEP_HASH_SINGLE_OPCODE, + u32_error = sep_verify_op(ta_ctx, SEP_HASH_SINGLE_OPCODE, &msg_offset); if (u32_error) { - dev_warn(&sctx->sep_used->pdev->dev, + dev_warn(&ta_ctx->sep_used->pdev->dev, "hash digest finish error %x\n", u32_error); - sep_crypto_release(sctx, u32_error); + sep_crypto_release(sctx, ta_ctx, u32_error); return u32_error; } /* Grab the result */ - if (sctx->current_hash_req->result == NULL) { + if (ta_ctx->current_hash_req->result == NULL) { /* Oops, null buffer; error out here */ - dev_warn(&sctx->sep_used->pdev->dev, + dev_warn(&ta_ctx->sep_used->pdev->dev, "hash digest finish null buffer\n"); - sep_crypto_release(sctx, (u32)-ENOMEM); + sep_crypto_release(sctx, ta_ctx, (u32)-ENOMEM); return -ENOMEM; } max_length = (((SEP_HASH_RESULT_SIZE_WORDS * sizeof(u32)) + 3) / sizeof(u32)) * sizeof(u32); - sep_read_msg(sctx, - sctx->current_hash_req->result, + sep_read_msg(ta_ctx, + ta_ctx->current_hash_req->result, crypto_ahash_digestsize(tfm), max_length, &msg_offset, 0); /* Signal to crypto infrastructure and clear out */ - dev_dbg(&sctx->sep_used->pdev->dev, + dev_dbg(&ta_ctx->sep_used->pdev->dev, "hash digest finish post op done\n"); - sep_crypto_release(sctx, 0); + sep_crypto_release(sctx, ta_ctx, 0); return 0; } @@ -1759,7 +2015,6 @@ static u32 hash_digest_post_op(struct sep_device *sep) */ static void sep_finish(unsigned long data) { - unsigned long flags; struct sep_device *sep_dev; int res; @@ -1776,18 +2031,15 @@ static void sep_finish(unsigned long data) return; } - spin_lock_irqsave(&sep_dev->busy_lock, flags); if (sep_dev->in_kernel == (u32)0) { - spin_unlock_irqrestore(&sep_dev->busy_lock, flags); dev_warn(&sep_dev->pdev->dev, "sep_finish; not in kernel operation\n"); return; } - spin_unlock_irqrestore(&sep_dev->busy_lock, flags); /* Did we really do a sep command prior to this? */ if (0 == test_bit(SEP_LEGACY_SENDMSG_DONE_OFFSET, - &sep_dev->sctx->call_status.status)) { + &sep_dev->ta_ctx->call_status.status)) { dev_warn(&sep_dev->pdev->dev, "[PID%d] sendmsg not called\n", current->pid); @@ -1856,8 +2108,10 @@ static void sep_finish(unsigned long data) res = hash_init_post_op(sep_dev); break; case HASH_UPDATE: + case HASH_FINUP_DATA: res = hash_update_post_op(sep_dev); break; + case HASH_FINUP_FINISH: case HASH_FINISH: res = hash_final_post_op(sep_dev); break; @@ -1865,43 +2119,31 @@ static void sep_finish(unsigned long data) res = hash_digest_post_op(sep_dev); break; default: - dev_warn(&sep_dev->pdev->dev, - "invalid stage for hash finish\n"); + pr_debug("sep - invalid stage for hash finish\n"); } break; default: - dev_warn(&sep_dev->pdev->dev, - "invalid request for finish\n"); + pr_debug("sep - invalid request for finish\n"); } - if (res) { - dev_warn(&sep_dev->pdev->dev, - "finish returned error %x\n", res); - } + if (res) + pr_debug("sep - finish returned error %x\n", res); } static int sep_hash_cra_init(struct crypto_tfm *tfm) { - struct sep_system_ctx *sctx = crypto_tfm_ctx(tfm); const char *alg_name = crypto_tfm_alg_name(tfm); - sctx->sep_used = sep_dev; - - dev_dbg(&sctx->sep_used->pdev->dev, - "sep_hash_cra_init name is %s\n", alg_name); + pr_debug("sep_hash_cra_init name is %s\n", alg_name); crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), - sizeof(struct sep_hash_ctx)); + sizeof(struct this_task_ctx)); return 0; } static void sep_hash_cra_exit(struct crypto_tfm *tfm) { - struct sep_system_ctx *sctx = crypto_tfm_ctx(tfm); - - dev_dbg(&sctx->sep_used->pdev->dev, - "sep_hash_cra_exit\n"); - sctx->sep_used = NULL; + pr_debug("sep_hash_cra_exit\n"); } static void sep_hash_init(void *data) @@ -1910,60 +2152,49 @@ static void sep_hash_init(void *data) int result; struct ahash_request *req; struct crypto_ahash *tfm; - struct sep_hash_ctx *ctx; + struct this_task_ctx *ta_ctx; struct sep_system_ctx *sctx; + unsigned long end_time; + int are_we_done_yet; req = (struct ahash_request *)data; tfm = crypto_ahash_reqtfm(req); - ctx = ahash_request_ctx(req); sctx = crypto_ahash_ctx(tfm); + ta_ctx = ahash_request_ctx(req); + ta_ctx->sep_used = sep_dev; + + ta_ctx->are_we_done_yet = &are_we_done_yet; - dev_dbg(&sctx->sep_used->pdev->dev, + dev_dbg(&ta_ctx->sep_used->pdev->dev, "sep_hash_init\n"); - sctx->current_hash_stage = HASH_INIT; + ta_ctx->current_hash_stage = HASH_INIT; /* opcode and mode */ - sep_make_header(sctx, &msg_offset, SEP_HASH_INIT_OPCODE); - sep_write_msg(sctx, &ctx->hash_opmode, + sep_make_header(ta_ctx, &msg_offset, SEP_HASH_INIT_OPCODE); + sep_write_msg(ta_ctx, &ta_ctx->hash_opmode, sizeof(u32), sizeof(u32), &msg_offset, 0); - sep_end_msg(sctx, msg_offset); + sep_end_msg(ta_ctx, msg_offset); - sctx->done_with_transaction = 0; - - result = sep_crypto_take_sep(sctx); + are_we_done_yet = 0; + result = sep_crypto_take_sep(ta_ctx); if (result) { - dev_warn(&sctx->sep_used->pdev->dev, + dev_warn(&ta_ctx->sep_used->pdev->dev, "sep_hash_init take sep failed\n"); - sep_crypto_release(sctx, -EINVAL); + sep_crypto_release(sctx, ta_ctx, -EINVAL); } - /** - * Sep is now working. Lets wait up to 5 seconds - * for completion. If it does not complete, we will do - * a crypto release with -EINVAL to release the - * kernel crypto infrastructure and let the system - * continue to boot up - * We have to wait this long because some crypto - * operations can take a while - */ - dev_dbg(&sctx->sep_used->pdev->dev, - "waiting for done with transaction\n"); - - sctx->end_time = jiffies + (SEP_TRANSACTION_WAIT_TIME * HZ); - while ((time_before(jiffies, sctx->end_time)) && - (!sctx->done_with_transaction)) + /* now we sit and wait up to a fixed time for completion */ + end_time = jiffies + (WAIT_TIME * HZ); + while ((time_before(jiffies, end_time)) && (are_we_done_yet == 0)) schedule(); - dev_dbg(&sctx->sep_used->pdev->dev, - "done waiting for done with transaction\n"); - - /* are we done? */ - if (!sctx->done_with_transaction) { - /* Nope, lets release and tell crypto no */ - dev_warn(&sctx->sep_used->pdev->dev, - "[PID%d] sep_hash_init never finished\n", - current->pid); - sep_crypto_release(sctx, -EINVAL); + /* Done waiting; still not done yet? */ + if (are_we_done_yet == 0) { + dev_dbg(&ta_ctx->sep_used->pdev->dev, + "hash init never got done\n"); + sep_crypto_release(sctx, ta_ctx, -EINVAL); + return; } + } static void sep_hash_update(void *data) @@ -1975,6 +2206,8 @@ static void sep_hash_update(void *data) u32 block_size; u32 head_len; u32 tail_len; + int are_we_done_yet; + static u32 msg[10]; static char small_buf[100]; void *src_ptr; @@ -1982,184 +2215,174 @@ static void sep_hash_update(void *data) ssize_t copy_result; struct ahash_request *req; struct crypto_ahash *tfm; - struct sep_hash_ctx *ctx; + struct this_task_ctx *ta_ctx; struct sep_system_ctx *sctx; + unsigned long end_time; req = (struct ahash_request *)data; tfm = crypto_ahash_reqtfm(req); - ctx = ahash_request_ctx(req); sctx = crypto_ahash_ctx(tfm); + ta_ctx = ahash_request_ctx(req); + ta_ctx->sep_used = sep_dev; + + ta_ctx->are_we_done_yet = &are_we_done_yet; /* length for queue status */ - sctx->nbytes = req->nbytes; + ta_ctx->nbytes = req->nbytes; - dev_dbg(&sctx->sep_used->pdev->dev, + dev_dbg(&ta_ctx->sep_used->pdev->dev, "sep_hash_update\n"); - sctx->current_hash_stage = HASH_UPDATE; + ta_ctx->current_hash_stage = HASH_UPDATE; len = req->nbytes; block_size = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm)); tail_len = req->nbytes % block_size; - dev_dbg(&sctx->sep_used->pdev->dev, "length is %x\n", len); - dev_dbg(&sctx->sep_used->pdev->dev, "block_size is %x\n", block_size); - dev_dbg(&sctx->sep_used->pdev->dev, "tail len is %x\n", tail_len); + dev_dbg(&ta_ctx->sep_used->pdev->dev, "length is %x\n", len); + dev_dbg(&ta_ctx->sep_used->pdev->dev, "block_size is %x\n", block_size); + dev_dbg(&ta_ctx->sep_used->pdev->dev, "tail len is %x\n", tail_len); /* Compute header/tail sizes */ - int_ctx = (struct sep_hash_internal_context *)&ctx-> + int_ctx = (struct sep_hash_internal_context *)&sctx-> hash_private_ctx.internal_context; head_len = (block_size - int_ctx->prev_update_bytes) % block_size; tail_len = (req->nbytes - head_len) % block_size; /* Make sure all pages are even block */ - int_error = sep_oddball_pages(sctx->sep_used, req->src, + int_error = sep_oddball_pages(ta_ctx->sep_used, req->src, req->nbytes, block_size, &new_sg, 1); if (int_error < 0) { - dev_warn(&sctx->sep_used->pdev->dev, + dev_warn(&ta_ctx->sep_used->pdev->dev, "oddball pages error in crash update\n"); - sep_crypto_release(sctx, -ENOMEM); + sep_crypto_release(sctx, ta_ctx, -ENOMEM); return; } else if (int_error == 1) { - sctx->src_sg = new_sg; - sctx->src_sg_hold = new_sg; + ta_ctx->src_sg = new_sg; + ta_ctx->src_sg_hold = new_sg; } else { - sctx->src_sg = req->src; - sctx->src_sg_hold = NULL; + ta_ctx->src_sg = req->src; + ta_ctx->src_sg_hold = NULL; } - src_ptr = sg_virt(sctx->src_sg); + src_ptr = sg_virt(ta_ctx->src_sg); - if ((!req->nbytes) || (!ctx->sg)) { + if ((!req->nbytes) || (!ta_ctx->src_sg)) { /* null data */ src_ptr = NULL; } - sep_dump_sg(sctx->sep_used, "hash block sg in", sctx->src_sg); + sep_dump_sg(ta_ctx->sep_used, "hash block sg in", ta_ctx->src_sg); - sctx->dcb_input_data.app_in_address = src_ptr; - sctx->dcb_input_data.data_in_size = req->nbytes - (head_len + tail_len); - sctx->dcb_input_data.app_out_address = NULL; - sctx->dcb_input_data.block_size = block_size; - sctx->dcb_input_data.tail_block_size = 0; - sctx->dcb_input_data.is_applet = 0; - sctx->dcb_input_data.src_sg = sctx->src_sg; - sctx->dcb_input_data.dst_sg = NULL; + ta_ctx->dcb_input_data.app_in_address = src_ptr; + ta_ctx->dcb_input_data.data_in_size = + req->nbytes - (head_len + tail_len); + ta_ctx->dcb_input_data.app_out_address = NULL; + ta_ctx->dcb_input_data.block_size = block_size; + ta_ctx->dcb_input_data.tail_block_size = 0; + ta_ctx->dcb_input_data.is_applet = 0; + ta_ctx->dcb_input_data.src_sg = ta_ctx->src_sg; + ta_ctx->dcb_input_data.dst_sg = NULL; int_error = sep_create_dcb_dmatables_context_kernel( - sctx->sep_used, - &sctx->dcb_region, - &sctx->dmatables_region, - &sctx->dma_ctx, - &sctx->dcb_input_data, + ta_ctx->sep_used, + &ta_ctx->dcb_region, + &ta_ctx->dmatables_region, + &ta_ctx->dma_ctx, + &ta_ctx->dcb_input_data, 1); if (int_error) { - dev_warn(&sctx->sep_used->pdev->dev, + dev_warn(&ta_ctx->sep_used->pdev->dev, "hash update dma table create failed\n"); - sep_crypto_release(sctx, -EINVAL); + sep_crypto_release(sctx, ta_ctx, -EINVAL); return; } /* Construct message to SEP */ - sep_make_header(sctx, &msg_offset, SEP_HASH_UPDATE_OPCODE); + sep_make_header(ta_ctx, &msg_offset, SEP_HASH_UPDATE_OPCODE); msg[0] = (u32)0; msg[1] = (u32)0; msg[2] = (u32)0; - sep_write_msg(sctx, msg, sizeof(u32) * 3, sizeof(u32) * 3, + sep_write_msg(ta_ctx, msg, sizeof(u32) * 3, sizeof(u32) * 3, &msg_offset, 0); /* Handle remainders */ /* Head */ - sep_write_msg(sctx, &head_len, sizeof(u32), + sep_write_msg(ta_ctx, &head_len, sizeof(u32), sizeof(u32), &msg_offset, 0); if (head_len) { copy_result = sg_copy_to_buffer( req->src, - sep_sg_nents(sctx->src_sg), + sep_sg_nents(ta_ctx->src_sg), small_buf, head_len); if (copy_result != head_len) { - dev_warn(&sctx->sep_used->pdev->dev, + dev_warn(&ta_ctx->sep_used->pdev->dev, "sg head copy failure in hash block\n"); - sep_crypto_release(sctx, -ENOMEM); + sep_crypto_release(sctx, ta_ctx, -ENOMEM); return; } - sep_write_msg(sctx, small_buf, head_len, + sep_write_msg(ta_ctx, small_buf, head_len, sizeof(u32) * 32, &msg_offset, 1); } else { msg_offset += sizeof(u32) * 32; } /* Tail */ - sep_write_msg(sctx, &tail_len, sizeof(u32), + sep_write_msg(ta_ctx, &tail_len, sizeof(u32), sizeof(u32), &msg_offset, 0); if (tail_len) { copy_result = sep_copy_offset_sg( - sctx->sep_used, - sctx->src_sg, + ta_ctx->sep_used, + ta_ctx->src_sg, req->nbytes - tail_len, small_buf, tail_len); if (copy_result != tail_len) { - dev_warn(&sctx->sep_used->pdev->dev, + dev_warn(&ta_ctx->sep_used->pdev->dev, "sg tail copy failure in hash block\n"); - sep_crypto_release(sctx, -ENOMEM); + sep_crypto_release(sctx, ta_ctx, -ENOMEM); return; } - sep_write_msg(sctx, small_buf, tail_len, + sep_write_msg(ta_ctx, small_buf, tail_len, sizeof(u32) * 32, &msg_offset, 1); } else { msg_offset += sizeof(u32) * 32; } /* Context */ - sep_write_context(sctx, &msg_offset, &ctx->hash_private_ctx, + sep_write_context(ta_ctx, &msg_offset, &sctx->hash_private_ctx, sizeof(struct sep_hash_private_context)); - sep_end_msg(sctx, msg_offset); - sctx->done_with_transaction = 0; - int_error = sep_crypto_take_sep(sctx); + sep_end_msg(ta_ctx, msg_offset); + are_we_done_yet = 0; + int_error = sep_crypto_take_sep(ta_ctx); if (int_error) { - dev_warn(&sctx->sep_used->pdev->dev, + dev_warn(&ta_ctx->sep_used->pdev->dev, "sep_hash_update take sep failed\n"); - sep_crypto_release(sctx, -EINVAL); + sep_crypto_release(sctx, ta_ctx, -EINVAL); } - /** - * Sep is now working. Lets wait up to 5 seconds - * for completion. If it does not complete, we will do - * a crypto release with -EINVAL to release the - * kernel crypto infrastructure and let the system - * continue to boot up - * We have to wait this long because some crypto - * operations can take a while - */ - dev_dbg(&sctx->sep_used->pdev->dev, - "waiting for done with transaction\n"); - - sctx->end_time = jiffies + (SEP_TRANSACTION_WAIT_TIME * HZ); - while ((time_before(jiffies, sctx->end_time)) && - (!sctx->done_with_transaction)) + /* now we sit and wait up to a fixed time for completion */ + end_time = jiffies + (WAIT_TIME * HZ); + while ((time_before(jiffies, end_time)) && (are_we_done_yet == 0)) schedule(); - dev_dbg(&sctx->sep_used->pdev->dev, - "done waiting for done with transaction\n"); - - /* are we done? */ - if (!sctx->done_with_transaction) { - /* Nope, lets release and tell crypto no */ - dev_warn(&sctx->sep_used->pdev->dev, - "[PID%d] sep_hash_update never finished\n", - current->pid); - sep_crypto_release(sctx, -EINVAL); + /* Done waiting; still not done yet? */ + if (are_we_done_yet == 0) { + dev_dbg(&ta_ctx->sep_used->pdev->dev, + "hash update never got done\n"); + sep_crypto_release(sctx, ta_ctx, -EINVAL); + return; } + } static void sep_hash_final(void *data) @@ -2167,63 +2390,53 @@ static void sep_hash_final(void *data) u32 msg_offset; struct ahash_request *req; struct crypto_ahash *tfm; - struct sep_hash_ctx *ctx; + struct this_task_ctx *ta_ctx; struct sep_system_ctx *sctx; int result; + unsigned long end_time; + int are_we_done_yet; req = (struct ahash_request *)data; tfm = crypto_ahash_reqtfm(req); - ctx = ahash_request_ctx(req); sctx = crypto_ahash_ctx(tfm); + ta_ctx = ahash_request_ctx(req); + ta_ctx->sep_used = sep_dev; - dev_dbg(&sctx->sep_used->pdev->dev, + dev_dbg(&ta_ctx->sep_used->pdev->dev, "sep_hash_final\n"); - sctx->current_hash_stage = HASH_FINISH; + ta_ctx->current_hash_stage = HASH_FINISH; + + ta_ctx->are_we_done_yet = &are_we_done_yet; /* opcode and mode */ - sep_make_header(sctx, &msg_offset, SEP_HASH_FINISH_OPCODE); + sep_make_header(ta_ctx, &msg_offset, SEP_HASH_FINISH_OPCODE); /* Context */ - sep_write_context(sctx, &msg_offset, &ctx->hash_private_ctx, + sep_write_context(ta_ctx, &msg_offset, &sctx->hash_private_ctx, sizeof(struct sep_hash_private_context)); - sep_end_msg(sctx, msg_offset); - sctx->done_with_transaction = 0; - result = sep_crypto_take_sep(sctx); + sep_end_msg(ta_ctx, msg_offset); + are_we_done_yet = 0; + result = sep_crypto_take_sep(ta_ctx); if (result) { - dev_warn(&sctx->sep_used->pdev->dev, + dev_warn(&ta_ctx->sep_used->pdev->dev, "sep_hash_final take sep failed\n"); - sep_crypto_release(sctx, -EINVAL); + sep_crypto_release(sctx, ta_ctx, -EINVAL); } - /** - * Sep is now working. Lets wait up to 5 seconds - * for completion. If it does not complete, we will do - * a crypto release with -EINVAL to release the - * kernel crypto infrastructure and let the system - * continue to boot up - * We have to wait this long because some crypto - * operations can take a while - */ - dev_dbg(&sctx->sep_used->pdev->dev, - "waiting for done with transaction\n"); - - sctx->end_time = jiffies + (SEP_TRANSACTION_WAIT_TIME * HZ); - while ((time_before(jiffies, sctx->end_time)) && - (!sctx->done_with_transaction)) + /* now we sit and wait up to a fixed time for completion */ + end_time = jiffies + (WAIT_TIME * HZ); + while ((time_before(jiffies, end_time)) && (are_we_done_yet == 0)) schedule(); - dev_dbg(&sctx->sep_used->pdev->dev, - "done waiting for done with transaction\n"); - - /* are we done? */ - if (!sctx->done_with_transaction) { - /* Nope, lets release and tell crypto no */ - dev_warn(&sctx->sep_used->pdev->dev, - "[PID%d] sep_hash_final never finished\n", - current->pid); - sep_crypto_release(sctx, -EINVAL); + /* Done waiting; still not done yet? */ + if (are_we_done_yet == 0) { + dev_dbg(&ta_ctx->sep_used->pdev->dev, + "hash final job never got done\n"); + sep_crypto_release(sctx, ta_ctx, -EINVAL); + return; } + } static void sep_hash_digest(void *data) @@ -2234,6 +2447,7 @@ static void sep_hash_digest(void *data) u32 msg[10]; size_t copy_result; int result; + int are_we_done_yet; u32 tail_len; static char small_buf[100]; struct scatterlist *new_sg; @@ -2241,152 +2455,140 @@ static void sep_hash_digest(void *data) struct ahash_request *req; struct crypto_ahash *tfm; - struct sep_hash_ctx *ctx; + struct this_task_ctx *ta_ctx; struct sep_system_ctx *sctx; + unsigned long end_time; req = (struct ahash_request *)data; tfm = crypto_ahash_reqtfm(req); - ctx = ahash_request_ctx(req); sctx = crypto_ahash_ctx(tfm); + ta_ctx = ahash_request_ctx(req); + ta_ctx->sep_used = sep_dev; - dev_dbg(&sctx->sep_used->pdev->dev, + dev_dbg(&ta_ctx->sep_used->pdev->dev, "sep_hash_digest\n"); - sctx->current_hash_stage = HASH_DIGEST; + ta_ctx->current_hash_stage = HASH_DIGEST; + + ta_ctx->are_we_done_yet = &are_we_done_yet; /* length for queue status */ - sctx->nbytes = req->nbytes; + ta_ctx->nbytes = req->nbytes; block_size = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm)); tail_len = req->nbytes % block_size; - dev_dbg(&sctx->sep_used->pdev->dev, "length is %x\n", req->nbytes); - dev_dbg(&sctx->sep_used->pdev->dev, "block_size is %x\n", block_size); - dev_dbg(&sctx->sep_used->pdev->dev, "tail len is %x\n", tail_len); + dev_dbg(&ta_ctx->sep_used->pdev->dev, "length is %x\n", req->nbytes); + dev_dbg(&ta_ctx->sep_used->pdev->dev, "block_size is %x\n", block_size); + dev_dbg(&ta_ctx->sep_used->pdev->dev, "tail len is %x\n", tail_len); /* Make sure all pages are even block */ - int_error = sep_oddball_pages(sctx->sep_used, req->src, + int_error = sep_oddball_pages(ta_ctx->sep_used, req->src, req->nbytes, block_size, &new_sg, 1); if (int_error < 0) { - dev_warn(&sctx->sep_used->pdev->dev, + dev_warn(&ta_ctx->sep_used->pdev->dev, "oddball pages error in crash update\n"); - sep_crypto_release(sctx, -ENOMEM); + sep_crypto_release(sctx, ta_ctx, -ENOMEM); return; } else if (int_error == 1) { - sctx->src_sg = new_sg; - sctx->src_sg_hold = new_sg; + ta_ctx->src_sg = new_sg; + ta_ctx->src_sg_hold = new_sg; } else { - sctx->src_sg = req->src; - sctx->src_sg_hold = NULL; + ta_ctx->src_sg = req->src; + ta_ctx->src_sg_hold = NULL; } - src_ptr = sg_virt(sctx->src_sg); + src_ptr = sg_virt(ta_ctx->src_sg); - if ((!req->nbytes) || (!ctx->sg)) { + if ((!req->nbytes) || (!ta_ctx->src_sg)) { /* null data */ src_ptr = NULL; } - sep_dump_sg(sctx->sep_used, "hash block sg in", sctx->src_sg); + sep_dump_sg(ta_ctx->sep_used, "hash block sg in", ta_ctx->src_sg); - sctx->dcb_input_data.app_in_address = src_ptr; - sctx->dcb_input_data.data_in_size = req->nbytes - tail_len; - sctx->dcb_input_data.app_out_address = NULL; - sctx->dcb_input_data.block_size = block_size; - sctx->dcb_input_data.tail_block_size = 0; - sctx->dcb_input_data.is_applet = 0; - sctx->dcb_input_data.src_sg = sctx->src_sg; - sctx->dcb_input_data.dst_sg = NULL; + ta_ctx->dcb_input_data.app_in_address = src_ptr; + ta_ctx->dcb_input_data.data_in_size = req->nbytes - tail_len; + ta_ctx->dcb_input_data.app_out_address = NULL; + ta_ctx->dcb_input_data.block_size = block_size; + ta_ctx->dcb_input_data.tail_block_size = 0; + ta_ctx->dcb_input_data.is_applet = 0; + ta_ctx->dcb_input_data.src_sg = ta_ctx->src_sg; + ta_ctx->dcb_input_data.dst_sg = NULL; int_error = sep_create_dcb_dmatables_context_kernel( - sctx->sep_used, - &sctx->dcb_region, - &sctx->dmatables_region, - &sctx->dma_ctx, - &sctx->dcb_input_data, + ta_ctx->sep_used, + &ta_ctx->dcb_region, + &ta_ctx->dmatables_region, + &ta_ctx->dma_ctx, + &ta_ctx->dcb_input_data, 1); if (int_error) { - dev_warn(&sctx->sep_used->pdev->dev, + dev_warn(&ta_ctx->sep_used->pdev->dev, "hash update dma table create failed\n"); - sep_crypto_release(sctx, -EINVAL); + sep_crypto_release(sctx, ta_ctx, -EINVAL); return; } /* Construct message to SEP */ - sep_make_header(sctx, &msg_offset, SEP_HASH_SINGLE_OPCODE); - sep_write_msg(sctx, &ctx->hash_opmode, + sep_make_header(ta_ctx, &msg_offset, SEP_HASH_SINGLE_OPCODE); + sep_write_msg(ta_ctx, &ta_ctx->hash_opmode, sizeof(u32), sizeof(u32), &msg_offset, 0); msg[0] = (u32)0; msg[1] = (u32)0; msg[2] = (u32)0; - sep_write_msg(sctx, msg, sizeof(u32) * 3, sizeof(u32) * 3, + sep_write_msg(ta_ctx, msg, sizeof(u32) * 3, sizeof(u32) * 3, &msg_offset, 0); /* Tail */ - sep_write_msg(sctx, &tail_len, sizeof(u32), + sep_write_msg(ta_ctx, &tail_len, sizeof(u32), sizeof(u32), &msg_offset, 0); if (tail_len) { copy_result = sep_copy_offset_sg( - sctx->sep_used, - sctx->src_sg, + ta_ctx->sep_used, + ta_ctx->src_sg, req->nbytes - tail_len, small_buf, tail_len); if (copy_result != tail_len) { - dev_warn(&sctx->sep_used->pdev->dev, + dev_warn(&ta_ctx->sep_used->pdev->dev, "sg tail copy failure in hash block\n"); - sep_crypto_release(sctx, -ENOMEM); + sep_crypto_release(sctx, ta_ctx, -ENOMEM); return; } - sep_write_msg(sctx, small_buf, tail_len, + sep_write_msg(ta_ctx, small_buf, tail_len, sizeof(u32) * 32, &msg_offset, 1); } else { msg_offset += sizeof(u32) * 32; } - sep_end_msg(sctx, msg_offset); + sep_end_msg(ta_ctx, msg_offset); - sctx->done_with_transaction = 0; - - result = sep_crypto_take_sep(sctx); + are_we_done_yet = 0; + result = sep_crypto_take_sep(ta_ctx); if (result) { - dev_warn(&sctx->sep_used->pdev->dev, + dev_warn(&ta_ctx->sep_used->pdev->dev, "sep_hash_digest take sep failed\n"); - sep_crypto_release(sctx, -EINVAL); + sep_crypto_release(sctx, ta_ctx, -EINVAL); } - /** - * Sep is now working. Lets wait up to 5 seconds - * for completion. If it does not complete, we will do - * a crypto release with -EINVAL to release the - * kernel crypto infrastructure and let the system - * continue to boot up - * We have to wait this long because some crypto - * operations can take a while - */ - dev_dbg(&sctx->sep_used->pdev->dev, - "waiting for done with transaction\n"); - - sctx->end_time = jiffies + (SEP_TRANSACTION_WAIT_TIME * HZ); - while ((time_before(jiffies, sctx->end_time)) && - (!sctx->done_with_transaction)) + /* now we sit and wait up to a fixed time for completion */ + end_time = jiffies + (WAIT_TIME * HZ); + while ((time_before(jiffies, end_time)) && (are_we_done_yet == 0)) schedule(); - dev_dbg(&sctx->sep_used->pdev->dev, - "done waiting for done with transaction\n"); - - /* are we done? */ - if (!sctx->done_with_transaction) { - /* Nope, lets release and tell crypto no */ - dev_warn(&sctx->sep_used->pdev->dev, - "[PID%d] sep_hash_digest never finished\n", - current->pid); - sep_crypto_release(sctx, -EINVAL); + /* Done waiting; still not done yet? */ + if (are_we_done_yet == 0) { + dev_dbg(&ta_ctx->sep_used->pdev->dev, + "hash digest job never got done\n"); + sep_crypto_release(sctx, ta_ctx, -EINVAL); + return; } + } /** @@ -2404,6 +2606,7 @@ static void sep_dequeuer(void *data) struct ahash_request *hash_req; struct sep_system_ctx *sctx; struct crypto_ahash *hash_tfm; + struct this_task_ctx *ta_ctx; this_queue = (struct crypto_queue *)data; @@ -2481,22 +2684,32 @@ static void sep_dequeuer(void *data) return; } - if (sctx->current_hash_stage == HASH_INIT) { + ta_ctx = ahash_request_ctx(hash_req); + + if (ta_ctx->current_hash_stage == HASH_INIT) { pr_debug("sep crypto queue hash init\n"); sep_hash_init((void *)hash_req); return; - } else if (sctx->current_hash_stage == HASH_UPDATE) { + } else if (ta_ctx->current_hash_stage == HASH_UPDATE) { pr_debug("sep crypto queue hash update\n"); sep_hash_update((void *)hash_req); return; - } else if (sctx->current_hash_stage == HASH_FINISH) { + } else if (ta_ctx->current_hash_stage == HASH_FINISH) { pr_debug("sep crypto queue hash final\n"); sep_hash_final((void *)hash_req); return; - } else if (sctx->current_hash_stage == HASH_DIGEST) { + } else if (ta_ctx->current_hash_stage == HASH_DIGEST) { pr_debug("sep crypto queue hash digest\n"); sep_hash_digest((void *)hash_req); return; + } else if (ta_ctx->current_hash_stage == HASH_FINUP_DATA) { + pr_debug("sep crypto queue hash digest\n"); + sep_hash_update((void *)hash_req); + return; + } else if (ta_ctx->current_hash_stage == HASH_FINUP_FINISH) { + pr_debug("sep crypto queue hash digest\n"); + sep_hash_final((void *)hash_req); + return; } else { pr_debug("sep crypto queue hash oops nothing\n"); return; @@ -2507,605 +2720,671 @@ static void sep_dequeuer(void *data) static int sep_sha1_init(struct ahash_request *req) { int error; - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sep_hash_ctx *ctx = ahash_request_ctx(req); - struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); + int error1; + struct this_task_ctx *ta_ctx = ahash_request_ctx(req); + + pr_debug("sep - doing sha1 init\n"); - dev_dbg(&sctx->sep_used->pdev->dev, "doing sha1 init\n"); - sctx->current_request = SHA1; - sctx->current_hash_req = req; - sctx->current_cypher_req = NULL; - ctx->hash_opmode = SEP_HASH_SHA1; - sctx->current_hash_stage = HASH_INIT; + /* Clear out task context */ + memset(ta_ctx, 0, sizeof(struct this_task_ctx)); + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = SHA1; + ta_ctx->current_hash_req = req; + ta_ctx->current_cypher_req = NULL; + ta_ctx->hash_opmode = SEP_HASH_SHA1; + ta_ctx->current_hash_stage = HASH_INIT; + + /* lock necessary so that only one entity touches the queues */ spin_lock_irq(&queue_lock); error = crypto_enqueue_request(&sep_queue, &req->base); - spin_unlock_irq(&queue_lock); - - if ((error != 0) && (error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep sha1 init cant enqueue\n"); - sep_crypto_release(sctx, error); - return error; - } - error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, - (void *)&sep_queue); - if (error) { - dev_warn(&sctx->sep_used->pdev->dev, - "sha1 init cannot submit queue\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } - return -EINPROGRESS; + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); + spin_unlock_irq(&queue_lock); + /* We return result of crypto enqueue */ + return error; } static int sep_sha1_update(struct ahash_request *req) { int error; - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sep_hash_ctx *ctx = ahash_request_ctx(req); - struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); + int error1; + struct this_task_ctx *ta_ctx = ahash_request_ctx(req); - dev_dbg(&sctx->sep_used->pdev->dev, "doing sha1 update\n"); - sctx->current_request = SHA1; - sctx->current_hash_req = req; - sctx->current_cypher_req = NULL; - ctx->hash_opmode = SEP_HASH_SHA1; - sctx->current_hash_stage = HASH_INIT; + pr_debug("sep - doing sha1 update\n"); + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = SHA1; + ta_ctx->current_hash_req = req; + ta_ctx->current_cypher_req = NULL; + ta_ctx->hash_opmode = SEP_HASH_SHA1; + ta_ctx->current_hash_stage = HASH_UPDATE; + + /* lock necessary so that only one entity touches the queues */ spin_lock_irq(&queue_lock); error = crypto_enqueue_request(&sep_queue, &req->base); - spin_unlock_irq(&queue_lock); - - if ((error != 0) && (error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep sha1 update cant enqueue\n"); - sep_crypto_release(sctx, error); - return error; - } - error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, - (void *)&sep_queue); - if (error) { - dev_warn(&sctx->sep_used->pdev->dev, - "sha1 update cannot submit queue\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } - return -EINPROGRESS; + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); + spin_unlock_irq(&queue_lock); + /* We return result of crypto enqueue */ + return error; } static int sep_sha1_final(struct ahash_request *req) { int error; - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sep_hash_ctx *ctx = ahash_request_ctx(req); - struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); - dev_dbg(&sctx->sep_used->pdev->dev, "doing sha1 final\n"); - - sctx->current_request = SHA1; - sctx->current_hash_req = req; - sctx->current_cypher_req = NULL; - ctx->hash_opmode = SEP_HASH_SHA1; - sctx->current_hash_stage = HASH_FINISH; - + int error1; + struct this_task_ctx *ta_ctx = ahash_request_ctx(req); + pr_debug("sep - doing sha1 final\n"); + + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = SHA1; + ta_ctx->current_hash_req = req; + ta_ctx->current_cypher_req = NULL; + ta_ctx->hash_opmode = SEP_HASH_SHA1; + ta_ctx->current_hash_stage = HASH_FINISH; + + /* lock necessary so that only one entity touches the queues */ spin_lock_irq(&queue_lock); error = crypto_enqueue_request(&sep_queue, &req->base); - spin_unlock_irq(&queue_lock); - - if ((error != 0) && (error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep sha1 final cant enqueue\n"); - sep_crypto_release(sctx, error); - return error; - } - - error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, - (void *)&sep_queue); - if (error) { - dev_warn(&sctx->sep_used->pdev->dev, - "sha1 final cannot submit queue\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } - return -EINPROGRESS; + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); + spin_unlock_irq(&queue_lock); + /* We return result of crypto enqueue */ + return error; } static int sep_sha1_digest(struct ahash_request *req) { int error; - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sep_hash_ctx *ctx = ahash_request_ctx(req); - struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); - dev_dbg(&sctx->sep_used->pdev->dev, "doing sha1 digest\n"); + int error1; + struct this_task_ctx *ta_ctx = ahash_request_ctx(req); + pr_debug("sep - doing sha1 digest\n"); - sctx->current_request = SHA1; - sctx->current_hash_req = req; - sctx->current_cypher_req = NULL; - ctx->hash_opmode = SEP_HASH_SHA1; - sctx->current_hash_stage = HASH_DIGEST; + /* Clear out task context */ + memset(ta_ctx, 0, sizeof(struct this_task_ctx)); + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = SHA1; + ta_ctx->current_hash_req = req; + ta_ctx->current_cypher_req = NULL; + ta_ctx->hash_opmode = SEP_HASH_SHA1; + ta_ctx->current_hash_stage = HASH_DIGEST; + + /* lock necessary so that only one entity touches the queues */ spin_lock_irq(&queue_lock); error = crypto_enqueue_request(&sep_queue, &req->base); - spin_unlock_irq(&queue_lock); - if ((error != 0) && (error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep sha1 digest cant enqueue\n"); - sep_crypto_release(sctx, error); - return error; - } + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); + spin_unlock_irq(&queue_lock); + /* We return result of crypto enqueue */ + return error; +} - error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, - (void *)&sep_queue); - if (error) { - dev_warn(&sctx->sep_used->pdev->dev, - "sha1 digest cannot submit queue\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } - return -EINPROGRESS; +static int sep_sha1_finup(struct ahash_request *req) +{ + int error; + int error1; + struct this_task_ctx *ta_ctx = ahash_request_ctx(req); + pr_debug("sep - doing sha1 finup\n"); + + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = SHA1; + ta_ctx->current_hash_req = req; + ta_ctx->current_cypher_req = NULL; + ta_ctx->hash_opmode = SEP_HASH_SHA1; + ta_ctx->current_hash_stage = HASH_FINUP_DATA; + + /* lock necessary so that only one entity touches the queues */ + spin_lock_irq(&queue_lock); + error = crypto_enqueue_request(&sep_queue, &req->base); + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); + spin_unlock_irq(&queue_lock); + /* We return result of crypto enqueue */ + return error; } static int sep_md5_init(struct ahash_request *req) { int error; - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sep_hash_ctx *ctx = ahash_request_ctx(req); - struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); - dev_dbg(&sctx->sep_used->pdev->dev, "doing md5 init\n"); + int error1; + struct this_task_ctx *ta_ctx = ahash_request_ctx(req); + pr_debug("sep - doing md5 init\n"); + + /* Clear out task context */ + memset(ta_ctx, 0, sizeof(struct this_task_ctx)); - sctx->current_request = MD5; - sctx->current_hash_req = req; - sctx->current_cypher_req = NULL; - ctx->hash_opmode = SEP_HASH_MD5; - sctx->current_hash_stage = HASH_INIT; + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = MD5; + ta_ctx->current_hash_req = req; + ta_ctx->current_cypher_req = NULL; + ta_ctx->hash_opmode = SEP_HASH_MD5; + ta_ctx->current_hash_stage = HASH_INIT; + /* lock necessary so that only one entity touches the queues */ spin_lock_irq(&queue_lock); error = crypto_enqueue_request(&sep_queue, &req->base); - spin_unlock_irq(&queue_lock); - - if ((error != 0) && (error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep md5 init cant enqueue\n"); - sep_crypto_release(sctx, error); - return error; - } - - error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, - (void *)&sep_queue); - if (error) { - dev_warn(&sctx->sep_used->pdev->dev, - "md5 init cannot submit queue\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } - return -EINPROGRESS; + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); + spin_unlock_irq(&queue_lock); + /* We return result of crypto enqueue */ + return error; } static int sep_md5_update(struct ahash_request *req) { int error; - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sep_hash_ctx *ctx = ahash_request_ctx(req); - struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); - dev_dbg(&sctx->sep_used->pdev->dev, "doing md5 update\n"); - - sctx->current_request = MD5; - sctx->current_hash_req = req; - sctx->current_cypher_req = NULL; - ctx->hash_opmode = SEP_HASH_MD5; - sctx->current_hash_stage = HASH_UPDATE; - + int error1; + struct this_task_ctx *ta_ctx = ahash_request_ctx(req); + pr_debug("sep - doing md5 update\n"); + + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = MD5; + ta_ctx->current_hash_req = req; + ta_ctx->current_cypher_req = NULL; + ta_ctx->hash_opmode = SEP_HASH_MD5; + ta_ctx->current_hash_stage = HASH_UPDATE; + + /* lock necessary so that only one entity touches the queues */ spin_lock_irq(&queue_lock); error = crypto_enqueue_request(&sep_queue, &req->base); - spin_unlock_irq(&queue_lock); - if ((error != 0) && (error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "md5 update cant enqueue\n"); - sep_crypto_release(sctx, error); - return error; - } - - error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, - (void *)&sep_queue); - if (error) { - dev_warn(&sctx->sep_used->pdev->dev, - "md5 update cannot submit queue\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } - return -EINPROGRESS; + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); + spin_unlock_irq(&queue_lock); + /* We return result of crypto enqueue */ + return error; } static int sep_md5_final(struct ahash_request *req) { int error; - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sep_hash_ctx *ctx = ahash_request_ctx(req); - struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); - dev_dbg(&sctx->sep_used->pdev->dev, "doing md5 final\n"); - - sctx->current_request = MD5; - sctx->current_hash_req = req; - sctx->current_cypher_req = NULL; - ctx->hash_opmode = SEP_HASH_MD5; - sctx->current_hash_stage = HASH_FINISH; - + int error1; + struct this_task_ctx *ta_ctx = ahash_request_ctx(req); + pr_debug("sep - doing md5 final\n"); + + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = MD5; + ta_ctx->current_hash_req = req; + ta_ctx->current_cypher_req = NULL; + ta_ctx->hash_opmode = SEP_HASH_MD5; + ta_ctx->current_hash_stage = HASH_FINISH; + + /* lock necessary so that only one entity touches the queues */ spin_lock_irq(&queue_lock); error = crypto_enqueue_request(&sep_queue, &req->base); - spin_unlock_irq(&queue_lock); - - if ((error != 0) && (error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep md5 final cant enqueue\n"); - sep_crypto_release(sctx, error); - return error; - } - - error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, - (void *)&sep_queue); - if (error) { - dev_warn(&sctx->sep_used->pdev->dev, - "md5 final cannot submit queue\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } - return -EINPROGRESS; + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); + spin_unlock_irq(&queue_lock); + /* We return result of crypto enqueue */ + return error; } static int sep_md5_digest(struct ahash_request *req) { int error; - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sep_hash_ctx *ctx = ahash_request_ctx(req); - struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); + int error1; + struct this_task_ctx *ta_ctx = ahash_request_ctx(req); - dev_dbg(&sctx->sep_used->pdev->dev, "doing md5 digest\n"); - sctx->current_request = MD5; - sctx->current_hash_req = req; - sctx->current_cypher_req = NULL; - ctx->hash_opmode = SEP_HASH_MD5; - sctx->current_hash_stage = HASH_DIGEST; + pr_debug("sep - doing md5 digest\n"); + /* Clear out task context */ + memset(ta_ctx, 0, sizeof(struct this_task_ctx)); + + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = MD5; + ta_ctx->current_hash_req = req; + ta_ctx->current_cypher_req = NULL; + ta_ctx->hash_opmode = SEP_HASH_MD5; + ta_ctx->current_hash_stage = HASH_DIGEST; + + /* lock necessary so that only one entity touches the queues */ spin_lock_irq(&queue_lock); error = crypto_enqueue_request(&sep_queue, &req->base); - spin_unlock_irq(&queue_lock); - - if ((error != 0) && (error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep md5 digest cant enqueue\n"); - sep_crypto_release(sctx, error); - return error; - } - error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, - (void *)&sep_queue); - if (error) { - dev_warn(&sctx->sep_used->pdev->dev, - "md5 digest cannot submit queue\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } - return -EINPROGRESS; + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); + spin_unlock_irq(&queue_lock); + /* We return result of crypto enqueue */ + return error; } -static int sep_sha224_init(struct ahash_request *req) +static int sep_md5_finup(struct ahash_request *req) { int error; - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sep_hash_ctx *ctx = ahash_request_ctx(req); - struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); - dev_dbg(&sctx->sep_used->pdev->dev, "doing sha224 init\n"); + int error1; + struct this_task_ctx *ta_ctx = ahash_request_ctx(req); + + pr_debug("sep - doing md5 finup\n"); - sctx->current_request = SHA224; - sctx->current_hash_req = req; - sctx->current_cypher_req = NULL; - ctx->hash_opmode = SEP_HASH_SHA224; - sctx->current_hash_stage = HASH_INIT; + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = MD5; + ta_ctx->current_hash_req = req; + ta_ctx->current_cypher_req = NULL; + ta_ctx->hash_opmode = SEP_HASH_MD5; + ta_ctx->current_hash_stage = HASH_FINUP_DATA; + /* lock necessary so that only one entity touches the queues */ spin_lock_irq(&queue_lock); error = crypto_enqueue_request(&sep_queue, &req->base); - spin_unlock_irq(&queue_lock); - - if ((error != 0) && (error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep sha224 init cant enqueue\n"); - sep_crypto_release(sctx, error); - return error; - } - error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, - (void *)&sep_queue); - if (error) { - dev_warn(&sctx->sep_used->pdev->dev, - "sha224 init cannot submit queue\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } - return -EINPROGRESS; + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); + spin_unlock_irq(&queue_lock); + /* We return result of crypto enqueue */ + return error; } -static int sep_sha224_update(struct ahash_request *req) +static int sep_sha224_init(struct ahash_request *req) { int error; - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sep_hash_ctx *ctx = ahash_request_ctx(req); - struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); - dev_dbg(&sctx->sep_used->pdev->dev, "doing sha224 update\n"); + int error1; + struct this_task_ctx *ta_ctx = ahash_request_ctx(req); + pr_debug("sep - doing sha224 init\n"); + + /* Clear out task context */ + memset(ta_ctx, 0, sizeof(struct this_task_ctx)); - sctx->current_request = SHA224; - sctx->current_hash_req = req; - sctx->current_cypher_req = NULL; - ctx->hash_opmode = SEP_HASH_SHA224; - sctx->current_hash_stage = HASH_UPDATE; + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = SHA224; + ta_ctx->current_hash_req = req; + ta_ctx->current_cypher_req = NULL; + ta_ctx->hash_opmode = SEP_HASH_SHA224; + ta_ctx->current_hash_stage = HASH_INIT; + /* lock necessary so that only one entity touches the queues */ spin_lock_irq(&queue_lock); error = crypto_enqueue_request(&sep_queue, &req->base); + + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); spin_unlock_irq(&queue_lock); + /* We return result of crypto enqueue */ + return error; +} - if ((error != 0) && (error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep sha224 update cant enqueue\n"); - sep_crypto_release(sctx, error); - return error; - } +static int sep_sha224_update(struct ahash_request *req) +{ + int error; + int error1; + struct this_task_ctx *ta_ctx = ahash_request_ctx(req); + pr_debug("sep - doing sha224 update\n"); + + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = SHA224; + ta_ctx->current_hash_req = req; + ta_ctx->current_cypher_req = NULL; + ta_ctx->hash_opmode = SEP_HASH_SHA224; + ta_ctx->current_hash_stage = HASH_UPDATE; + + /* lock necessary so that only one entity touches the queues */ + spin_lock_irq(&queue_lock); + error = crypto_enqueue_request(&sep_queue, &req->base); - error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, - (void *)&sep_queue); - if (error) { - dev_warn(&sctx->sep_used->pdev->dev, - "sha224 update cannot submit queue\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } - return -EINPROGRESS; + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); + spin_unlock_irq(&queue_lock); + /* We return result of crypto enqueue */ + return error; } static int sep_sha224_final(struct ahash_request *req) { int error; - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sep_hash_ctx *ctx = ahash_request_ctx(req); - struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); - dev_dbg(&sctx->sep_used->pdev->dev, "doing sha224 final\n"); - - sctx->current_request = SHA224; - sctx->current_hash_req = req; - sctx->current_cypher_req = NULL; - ctx->hash_opmode = SEP_HASH_SHA224; - sctx->current_hash_stage = HASH_FINISH; - + int error1; + struct this_task_ctx *ta_ctx = ahash_request_ctx(req); + pr_debug("sep - doing sha224 final\n"); + + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = SHA224; + ta_ctx->current_hash_req = req; + ta_ctx->current_cypher_req = NULL; + ta_ctx->hash_opmode = SEP_HASH_SHA224; + ta_ctx->current_hash_stage = HASH_FINISH; + + /* lock necessary so that only one entity touches the queues */ spin_lock_irq(&queue_lock); error = crypto_enqueue_request(&sep_queue, &req->base); - spin_unlock_irq(&queue_lock); - if ((error != 0) && (error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep sha224 final cant enqueue\n"); - sep_crypto_release(sctx, error); - return error; - } - - error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, - (void *)&sep_queue); - if (error) { - dev_warn(&sctx->sep_used->pdev->dev, - "sha224 final cannot submit queue\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } - return -EINPROGRESS; + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); + spin_unlock_irq(&queue_lock); + /* We return result of crypto enqueue */ + return error; } static int sep_sha224_digest(struct ahash_request *req) { int error; - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sep_hash_ctx *ctx = ahash_request_ctx(req); - struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); + int error1; + struct this_task_ctx *ta_ctx = ahash_request_ctx(req); + + pr_debug("sep - doing sha224 digest\n"); - dev_dbg(&sctx->sep_used->pdev->dev, "doing 224 digest\n"); - sctx->current_request = SHA224; - sctx->current_hash_req = req; - sctx->current_cypher_req = NULL; - ctx->hash_opmode = SEP_HASH_SHA224; - sctx->current_hash_stage = HASH_DIGEST; + /* Clear out task context */ + memset(ta_ctx, 0, sizeof(struct this_task_ctx)); + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = SHA224; + ta_ctx->current_hash_req = req; + ta_ctx->current_cypher_req = NULL; + ta_ctx->hash_opmode = SEP_HASH_SHA224; + ta_ctx->current_hash_stage = HASH_DIGEST; + + /* lock necessary so that only one entity touches the queues */ spin_lock_irq(&queue_lock); error = crypto_enqueue_request(&sep_queue, &req->base); - spin_unlock_irq(&queue_lock); - if ((error != 0) && (error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep sha224 digest cant enqueue\n"); - sep_crypto_release(sctx, error); - return error; - } - - error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, - (void *)&sep_queue); - if (error) { - dev_warn(&sctx->sep_used->pdev->dev, - "sha256 digest cannot submit queue\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } - return -EINPROGRESS; + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); + spin_unlock_irq(&queue_lock); + /* We return result of crypto enqueue */ + return error; } -static int sep_sha256_init(struct ahash_request *req) +static int sep_sha224_finup(struct ahash_request *req) { int error; - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sep_hash_ctx *ctx = ahash_request_ctx(req); - struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); - dev_dbg(&sctx->sep_used->pdev->dev, "doing sha256 init\n"); + int error1; + struct this_task_ctx *ta_ctx = ahash_request_ctx(req); + + pr_debug("sep - doing sha224 finup\n"); - sctx->current_request = SHA256; - sctx->current_hash_req = req; - sctx->current_cypher_req = NULL; - ctx->hash_opmode = SEP_HASH_SHA256; - sctx->current_hash_stage = HASH_INIT; + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = SHA224; + ta_ctx->current_hash_req = req; + ta_ctx->current_cypher_req = NULL; + ta_ctx->hash_opmode = SEP_HASH_SHA224; + ta_ctx->current_hash_stage = HASH_FINUP_DATA; + /* lock necessary so that only one entity touches the queues */ spin_lock_irq(&queue_lock); error = crypto_enqueue_request(&sep_queue, &req->base); - spin_unlock_irq(&queue_lock); - if ((error != 0) && (error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep sha256 init cant enqueue\n"); - sep_crypto_release(sctx, error); - return error; - } - - error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, - (void *)&sep_queue); - if (error) { - dev_warn(&sctx->sep_used->pdev->dev, - "sha256 init cannot submit queue\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } - return -EINPROGRESS; + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); + spin_unlock_irq(&queue_lock); + /* We return result of crypto enqueue */ + return error; } -static int sep_sha256_update(struct ahash_request *req) +static int sep_sha256_init(struct ahash_request *req) { int error; - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sep_hash_ctx *ctx = ahash_request_ctx(req); - struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); - dev_dbg(&sctx->sep_used->pdev->dev, "doing sha256 update\n"); + int error1; + struct this_task_ctx *ta_ctx = ahash_request_ctx(req); + pr_debug("sep - doing sha256 init\n"); + + /* Clear out task context */ + memset(ta_ctx, 0, sizeof(struct this_task_ctx)); - sctx->current_request = SHA256; - sctx->current_hash_req = req; - sctx->current_cypher_req = NULL; - ctx->hash_opmode = SEP_HASH_SHA256; - sctx->current_hash_stage = HASH_UPDATE; + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = SHA256; + ta_ctx->current_hash_req = req; + ta_ctx->current_cypher_req = NULL; + ta_ctx->hash_opmode = SEP_HASH_SHA256; + ta_ctx->current_hash_stage = HASH_INIT; + /* lock necessary so that only one entity touches the queues */ spin_lock_irq(&queue_lock); error = crypto_enqueue_request(&sep_queue, &req->base); + + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); spin_unlock_irq(&queue_lock); + /* We return result of crypto enqueue */ + return error; +} - if ((error != 0) && (error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep sha256 update cant enqueue\n"); - sep_crypto_release(sctx, error); - return error; - } +static int sep_sha256_update(struct ahash_request *req) +{ + int error; + int error1; + struct this_task_ctx *ta_ctx = ahash_request_ctx(req); + pr_debug("sep - doing sha256 update\n"); + + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = SHA256; + ta_ctx->current_hash_req = req; + ta_ctx->current_cypher_req = NULL; + ta_ctx->hash_opmode = SEP_HASH_SHA256; + ta_ctx->current_hash_stage = HASH_UPDATE; + + /* lock necessary so that only one entity touches the queues */ + spin_lock_irq(&queue_lock); + error = crypto_enqueue_request(&sep_queue, &req->base); - error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, - (void *)&sep_queue); - if (error) { - dev_warn(&sctx->sep_used->pdev->dev, - "sha256 update cannot submit queue\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } - return -EINPROGRESS; + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); + spin_unlock_irq(&queue_lock); + /* We return result of crypto enqueue */ + return error; } static int sep_sha256_final(struct ahash_request *req) { int error; - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sep_hash_ctx *ctx = ahash_request_ctx(req); - struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); - dev_dbg(&sctx->sep_used->pdev->dev, "doing sha256 final\n"); - - sctx->current_request = SHA256; - sctx->current_hash_req = req; - sctx->current_cypher_req = NULL; - ctx->hash_opmode = SEP_HASH_SHA256; - sctx->current_hash_stage = HASH_FINISH; - + int error1; + struct this_task_ctx *ta_ctx = ahash_request_ctx(req); + pr_debug("sep - doing sha256 final\n"); + + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = SHA256; + ta_ctx->current_hash_req = req; + ta_ctx->current_cypher_req = NULL; + ta_ctx->hash_opmode = SEP_HASH_SHA256; + ta_ctx->current_hash_stage = HASH_FINISH; + + /* lock necessary so that only one entity touches the queues */ spin_lock_irq(&queue_lock); error = crypto_enqueue_request(&sep_queue, &req->base); - spin_unlock_irq(&queue_lock); - if ((error != 0) && (error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep sha256 final cant enqueue\n"); - sep_crypto_release(sctx, error); - return error; - } - - error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, - (void *)&sep_queue); - if (error) { - dev_warn(&sctx->sep_used->pdev->dev, - "sha256 final cannot submit queue\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } - return -EINPROGRESS; + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); + spin_unlock_irq(&queue_lock); + /* We return result of crypto enqueue */ + return error; } static int sep_sha256_digest(struct ahash_request *req) { int error; - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sep_hash_ctx *ctx = ahash_request_ctx(req); - struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); + int error1; + struct this_task_ctx *ta_ctx = ahash_request_ctx(req); + + pr_debug("sep - doing sha256 digest\n"); + + /* Clear out task context */ + memset(ta_ctx, 0, sizeof(struct this_task_ctx)); - dev_dbg(&sctx->sep_used->pdev->dev, "doing sha256 digest\n"); - sctx->current_request = SHA256; - sctx->current_hash_req = req; - sctx->current_cypher_req = NULL; - ctx->hash_opmode = SEP_HASH_SHA256; - sctx->current_hash_stage = HASH_DIGEST; + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = SHA256; + ta_ctx->current_hash_req = req; + ta_ctx->current_cypher_req = NULL; + ta_ctx->hash_opmode = SEP_HASH_SHA256; + ta_ctx->current_hash_stage = HASH_DIGEST; + /* lock necessary so that only one entity touches the queues */ spin_lock_irq(&queue_lock); error = crypto_enqueue_request(&sep_queue, &req->base); + + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); spin_unlock_irq(&queue_lock); + /* We return result of crypto enqueue */ + return error; +} - if ((error != 0) && (error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep sha256 digest cant enqueue\n"); - sep_crypto_release(sctx, error); - return error; - } +static int sep_sha256_finup(struct ahash_request *req) +{ + int error; + int error1; + struct this_task_ctx *ta_ctx = ahash_request_ctx(req); - error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, - (void *)&sep_queue); - if (error) { - dev_warn(&sctx->sep_used->pdev->dev, - "sha256 digest cannot submit queue\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } - return -EINPROGRESS; + pr_debug("sep - doing sha256 finup\n"); + + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = SHA256; + ta_ctx->current_hash_req = req; + ta_ctx->current_cypher_req = NULL; + ta_ctx->hash_opmode = SEP_HASH_SHA256; + ta_ctx->current_hash_stage = HASH_FINUP_DATA; + + /* lock necessary so that only one entity touches the queues */ + spin_lock_irq(&queue_lock); + error = crypto_enqueue_request(&sep_queue, &req->base); + + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); + spin_unlock_irq(&queue_lock); + /* We return result of crypto enqueue */ + return error; } static int sep_crypto_init(struct crypto_tfm *tfm) { - struct sep_system_ctx *sctx = crypto_tfm_ctx(tfm); const char *alg_name = crypto_tfm_alg_name(tfm); - sctx->sep_used = sep_dev; - if (alg_name == NULL) - dev_dbg(&sctx->sep_used->pdev->dev, "alg is NULL\n"); + pr_debug("sep_crypto_init alg is NULL\n"); else - dev_dbg(&sctx->sep_used->pdev->dev, "alg is %s\n", alg_name); + pr_debug("sep_crypto_init alg is %s\n", alg_name); - tfm->crt_ablkcipher.reqsize = sizeof(struct sep_block_ctx); - dev_dbg(&sctx->sep_used->pdev->dev, "sep_crypto_init\n"); + tfm->crt_ablkcipher.reqsize = sizeof(struct this_task_ctx); return 0; } static void sep_crypto_exit(struct crypto_tfm *tfm) { - struct sep_system_ctx *sctx = crypto_tfm_ctx(tfm); - dev_dbg(&sctx->sep_used->pdev->dev, "sep_crypto_exit\n"); - sctx->sep_used = NULL; + pr_debug("sep_crypto_exit\n"); } static int sep_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key, @@ -3113,8 +3392,9 @@ static int sep_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key, { struct sep_system_ctx *sctx = crypto_ablkcipher_ctx(tfm); - dev_dbg(&sctx->sep_used->pdev->dev, "sep aes setkey\n"); + pr_debug("sep aes setkey\n"); + pr_debug("tfm is %p sctx is %p\n", tfm, sctx); switch (keylen) { case SEP_AES_KEY_128_SIZE: sctx->aes_key_size = AES_128; @@ -3129,7 +3409,7 @@ static int sep_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key, sctx->aes_key_size = AES_512; break; default: - dev_warn(&sctx->sep_used->pdev->dev, "sep aes key size %x\n", + pr_debug("invalid sep aes key size %x\n", keylen); return -EINVAL; } @@ -3140,7 +3420,6 @@ static int sep_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key, sctx->keylen = keylen; /* Indicate to encrypt/decrypt function to send key to SEP */ sctx->key_sent = 0; - sctx->last_block = 0; return 0; } @@ -3148,153 +3427,159 @@ static int sep_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key, static int sep_aes_ecb_encrypt(struct ablkcipher_request *req) { int error; - struct sep_block_ctx *bctx = ablkcipher_request_ctx(req); - struct sep_system_ctx *sctx = crypto_ablkcipher_ctx( - crypto_ablkcipher_reqtfm(req)); + int error1; + struct this_task_ctx *ta_ctx = ablkcipher_request_ctx(req); + + pr_debug("sep - doing aes ecb encrypt\n"); - dev_dbg(&sctx->sep_used->pdev->dev, "sep aes ecb encrypt\n"); - sctx->current_request = AES_ECB; - sctx->current_hash_req = NULL; - sctx->current_cypher_req = req; - bctx->aes_encmode = SEP_AES_ENCRYPT; - bctx->aes_opmode = SEP_AES_ECB; - bctx->init_opcode = SEP_AES_INIT_OPCODE; - bctx->block_opcode = SEP_AES_BLOCK_OPCODE; + /* Clear out task context */ + memset(ta_ctx, 0, sizeof(struct this_task_ctx)); + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = AES_ECB; + ta_ctx->current_hash_req = NULL; + ta_ctx->current_cypher_req = req; + ta_ctx->aes_encmode = SEP_AES_ENCRYPT; + ta_ctx->aes_opmode = SEP_AES_ECB; + ta_ctx->init_opcode = SEP_AES_INIT_OPCODE; + ta_ctx->block_opcode = SEP_AES_BLOCK_OPCODE; + + /* lock necessary so that only one entity touches the queues */ spin_lock_irq(&queue_lock); error = crypto_enqueue_request(&sep_queue, &req->base); - spin_unlock_irq(&queue_lock); - - if ((error != 0) && (error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep_aes_ecb_encrypt cant enqueue\n"); - sep_crypto_release(sctx, error); - return error; - } - error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, - (void *)&sep_queue); - if (error) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep_aes_ecb_encrypt cannot submit queue\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } - return -EINPROGRESS; + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); + spin_unlock_irq(&queue_lock); + /* We return result of crypto enqueue */ + return error; } static int sep_aes_ecb_decrypt(struct ablkcipher_request *req) { int error; - struct sep_block_ctx *bctx = ablkcipher_request_ctx(req); - struct sep_system_ctx *sctx = crypto_ablkcipher_ctx( - crypto_ablkcipher_reqtfm(req)); + int error1; + struct this_task_ctx *ta_ctx = ablkcipher_request_ctx(req); + + pr_debug("sep - doing aes ecb decrypt\n"); - dev_dbg(&sctx->sep_used->pdev->dev, "sep aes ecb decrypt\n"); - sctx->current_request = AES_ECB; - sctx->current_hash_req = NULL; - sctx->current_cypher_req = req; - bctx->aes_encmode = SEP_AES_DECRYPT; - bctx->aes_opmode = SEP_AES_ECB; - bctx->init_opcode = SEP_AES_INIT_OPCODE; - bctx->block_opcode = SEP_AES_BLOCK_OPCODE; + /* Clear out task context */ + memset(ta_ctx, 0, sizeof(struct this_task_ctx)); + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = AES_ECB; + ta_ctx->current_hash_req = NULL; + ta_ctx->current_cypher_req = req; + ta_ctx->aes_encmode = SEP_AES_DECRYPT; + ta_ctx->aes_opmode = SEP_AES_ECB; + ta_ctx->init_opcode = SEP_AES_INIT_OPCODE; + ta_ctx->block_opcode = SEP_AES_BLOCK_OPCODE; + + /* lock necessary so that only one entity touches the queues */ spin_lock_irq(&queue_lock); error = crypto_enqueue_request(&sep_queue, &req->base); - spin_unlock_irq(&queue_lock); - if ((error != 0) && (error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep_aes_ecb_decrypt cant enqueue\n"); - sep_crypto_release(sctx, error); - return error; - } - - error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, - (void *)&sep_queue); - if (error) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep_aes_ecb_decrypt cannot submit queue\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } - return -EINPROGRESS; + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); + spin_unlock_irq(&queue_lock); + /* We return result of crypto enqueue */ + return error; } static int sep_aes_cbc_encrypt(struct ablkcipher_request *req) { int error; - struct sep_block_ctx *bctx = ablkcipher_request_ctx(req); + int error1; + struct this_task_ctx *ta_ctx = ablkcipher_request_ctx(req); struct sep_system_ctx *sctx = crypto_ablkcipher_ctx( crypto_ablkcipher_reqtfm(req)); - dev_dbg(&sctx->sep_used->pdev->dev, "sep aes cbc encrypt\n"); - sctx->current_request = AES_CBC; - sctx->current_hash_req = NULL; - sctx->current_cypher_req = req; - bctx->aes_encmode = SEP_AES_ENCRYPT; - bctx->aes_opmode = SEP_AES_CBC; - bctx->init_opcode = SEP_AES_INIT_OPCODE; - bctx->block_opcode = SEP_AES_BLOCK_OPCODE; + pr_debug("sep - doing aes cbc encrypt\n"); + + /* Clear out task context */ + memset(ta_ctx, 0, sizeof(struct this_task_ctx)); + + pr_debug("tfm is %p sctx is %p and ta_ctx is %p\n", + crypto_ablkcipher_reqtfm(req), sctx, ta_ctx); + + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = AES_CBC; + ta_ctx->current_hash_req = NULL; + ta_ctx->current_cypher_req = req; + ta_ctx->aes_encmode = SEP_AES_ENCRYPT; + ta_ctx->aes_opmode = SEP_AES_CBC; + ta_ctx->init_opcode = SEP_AES_INIT_OPCODE; + ta_ctx->block_opcode = SEP_AES_BLOCK_OPCODE; + /* lock necessary so that only one entity touches the queues */ spin_lock_irq(&queue_lock); error = crypto_enqueue_request(&sep_queue, &req->base); - spin_unlock_irq(&queue_lock); - if ((error != 0) && (error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep_aes_cbc_encrypt cant enqueue\n"); - sep_crypto_release(sctx, error); - return error; - } - - error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, - (void *)&sep_queue); - if (error) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep_aes_cbc_encrypt cannot submit queue\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } - return -EINPROGRESS; + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); + spin_unlock_irq(&queue_lock); + /* We return result of crypto enqueue */ + return error; } static int sep_aes_cbc_decrypt(struct ablkcipher_request *req) { int error; - struct sep_block_ctx *bctx = ablkcipher_request_ctx(req); + int error1; + struct this_task_ctx *ta_ctx = ablkcipher_request_ctx(req); struct sep_system_ctx *sctx = crypto_ablkcipher_ctx( crypto_ablkcipher_reqtfm(req)); - dev_dbg(&sctx->sep_used->pdev->dev, "sep aes cbc decrypt\n"); - sctx->current_request = AES_CBC; - sctx->current_hash_req = NULL; - sctx->current_cypher_req = req; - bctx->aes_encmode = SEP_AES_DECRYPT; - bctx->aes_opmode = SEP_AES_CBC; - bctx->init_opcode = SEP_AES_INIT_OPCODE; - bctx->block_opcode = SEP_AES_BLOCK_OPCODE; + pr_debug("sep - doing aes cbc decrypt\n"); + + pr_debug("tfm is %p sctx is %p and ta_ctx is %p\n", + crypto_ablkcipher_reqtfm(req), sctx, ta_ctx); + /* Clear out task context */ + memset(ta_ctx, 0, sizeof(struct this_task_ctx)); + + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = AES_CBC; + ta_ctx->current_hash_req = NULL; + ta_ctx->current_cypher_req = req; + ta_ctx->aes_encmode = SEP_AES_DECRYPT; + ta_ctx->aes_opmode = SEP_AES_CBC; + ta_ctx->init_opcode = SEP_AES_INIT_OPCODE; + ta_ctx->block_opcode = SEP_AES_BLOCK_OPCODE; + + /* lock necessary so that only one entity touches the queues */ spin_lock_irq(&queue_lock); error = crypto_enqueue_request(&sep_queue, &req->base); - spin_unlock_irq(&queue_lock); - - if ((error != 0) && (error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep_aes_cbc_decrypt cant enqueue\n"); - sep_crypto_release(sctx, error); - return error; - } - error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, - (void *)&sep_queue); - if (error) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep_aes_cbc_decrypt cannot submit queue\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } - return -EINPROGRESS; + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); + spin_unlock_irq(&queue_lock); + /* We return result of crypto enqueue */ + return error; } static int sep_des_setkey(struct crypto_ablkcipher *tfm, const u8 *key, @@ -3304,7 +3589,7 @@ static int sep_des_setkey(struct crypto_ablkcipher *tfm, const u8 *key, struct crypto_tfm *ctfm = crypto_ablkcipher_tfm(tfm); u32 *flags = &ctfm->crt_flags; - dev_dbg(&sctx->sep_used->pdev->dev, "sep des setkey\n"); + pr_debug("sep des setkey\n"); switch (keylen) { case DES_KEY_SIZE: @@ -3317,7 +3602,7 @@ static int sep_des_setkey(struct crypto_ablkcipher *tfm, const u8 *key, sctx->des_nbr_keys = DES_KEY_3; break; default: - dev_dbg(&sctx->sep_used->pdev->dev, "invalid key size %x\n", + pr_debug("invalid key size %x\n", keylen); return -EINVAL; } @@ -3326,7 +3611,7 @@ static int sep_des_setkey(struct crypto_ablkcipher *tfm, const u8 *key, (sep_weak_key(key, keylen))) { *flags |= CRYPTO_TFM_RES_WEAK_KEY; - dev_warn(&sctx->sep_used->pdev->dev, "weak key\n"); + pr_debug("weak key\n"); return -EINVAL; } @@ -3335,7 +3620,6 @@ static int sep_des_setkey(struct crypto_ablkcipher *tfm, const u8 *key, sctx->keylen = keylen; /* Indicate to encrypt/decrypt function to send key to SEP */ sctx->key_sent = 0; - sctx->last_block = 0; return 0; } @@ -3343,153 +3627,149 @@ static int sep_des_setkey(struct crypto_ablkcipher *tfm, const u8 *key, static int sep_des_ebc_encrypt(struct ablkcipher_request *req) { int error; - struct sep_block_ctx *bctx = ablkcipher_request_ctx(req); - struct sep_system_ctx *sctx = crypto_ablkcipher_ctx( - crypto_ablkcipher_reqtfm(req)); + int error1; + struct this_task_ctx *ta_ctx = ablkcipher_request_ctx(req); + + pr_debug("sep - doing des ecb encrypt\n"); - dev_dbg(&sctx->sep_used->pdev->dev, "sep des ecb encrypt\n"); - sctx->current_request = DES_ECB; - sctx->current_hash_req = NULL; - sctx->current_cypher_req = req; - bctx->des_encmode = SEP_DES_ENCRYPT; - bctx->des_opmode = SEP_DES_ECB; - bctx->init_opcode = SEP_DES_INIT_OPCODE; - bctx->block_opcode = SEP_DES_BLOCK_OPCODE; + /* Clear out task context */ + memset(ta_ctx, 0, sizeof(struct this_task_ctx)); + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = DES_ECB; + ta_ctx->current_hash_req = NULL; + ta_ctx->current_cypher_req = req; + ta_ctx->des_encmode = SEP_DES_ENCRYPT; + ta_ctx->des_opmode = SEP_DES_ECB; + ta_ctx->init_opcode = SEP_DES_INIT_OPCODE; + ta_ctx->block_opcode = SEP_DES_BLOCK_OPCODE; + + /* lock necessary so that only one entity touches the queues */ spin_lock_irq(&queue_lock); error = crypto_enqueue_request(&sep_queue, &req->base); - spin_unlock_irq(&queue_lock); - if ((error != 0) && (error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep_des_ecb_encrypt cant enqueue\n"); - sep_crypto_release(sctx, error); - return error; - } - - error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, - (void *)&sep_queue); - if (error) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep_des_ecb_encrypt cannot submit queue\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } - return -EINPROGRESS; + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); + spin_unlock_irq(&queue_lock); + /* We return result of crypto enqueue */ + return error; } static int sep_des_ebc_decrypt(struct ablkcipher_request *req) { int error; - struct sep_block_ctx *bctx = ablkcipher_request_ctx(req); - struct sep_system_ctx *sctx = crypto_ablkcipher_ctx( - crypto_ablkcipher_reqtfm(req)); + int error1; + struct this_task_ctx *ta_ctx = ablkcipher_request_ctx(req); + + pr_debug("sep - doing des ecb decrypt\n"); - dev_dbg(&sctx->sep_used->pdev->dev, "sep des ecb decrypt\n"); - sctx->current_request = DES_ECB; - sctx->current_hash_req = NULL; - sctx->current_cypher_req = req; - bctx->des_encmode = SEP_DES_DECRYPT; - bctx->des_opmode = SEP_DES_ECB; - bctx->init_opcode = SEP_DES_INIT_OPCODE; - bctx->block_opcode = SEP_DES_BLOCK_OPCODE; + /* Clear out task context */ + memset(ta_ctx, 0, sizeof(struct this_task_ctx)); + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = DES_ECB; + ta_ctx->current_hash_req = NULL; + ta_ctx->current_cypher_req = req; + ta_ctx->des_encmode = SEP_DES_DECRYPT; + ta_ctx->des_opmode = SEP_DES_ECB; + ta_ctx->init_opcode = SEP_DES_INIT_OPCODE; + ta_ctx->block_opcode = SEP_DES_BLOCK_OPCODE; + + /* lock necessary so that only one entity touches the queues */ spin_lock_irq(&queue_lock); error = crypto_enqueue_request(&sep_queue, &req->base); - spin_unlock_irq(&queue_lock); - - if ((error != 0) && (error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep_des_ecb_decrypt cant enqueue\n"); - sep_crypto_release(sctx, error); - return error; - } - error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, - (void *)&sep_queue); - if (error) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep_des_ecb_decrypt cannot submit queue\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } - return -EINPROGRESS; + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); + spin_unlock_irq(&queue_lock); + /* We return result of crypto enqueue */ + return error; } static int sep_des_cbc_encrypt(struct ablkcipher_request *req) { int error; - struct sep_block_ctx *bctx = ablkcipher_request_ctx(req); - struct sep_system_ctx *sctx = crypto_ablkcipher_ctx( - crypto_ablkcipher_reqtfm(req)); + int error1; + struct this_task_ctx *ta_ctx = ablkcipher_request_ctx(req); + + pr_debug("sep - doing des cbc encrypt\n"); - dev_dbg(&sctx->sep_used->pdev->dev, "sep des cbc encrypt\n"); - sctx->current_request = DES_CBC; - sctx->current_hash_req = NULL; - sctx->current_cypher_req = req; - bctx->des_encmode = SEP_DES_ENCRYPT; - bctx->des_opmode = SEP_DES_CBC; - bctx->init_opcode = SEP_DES_INIT_OPCODE; - bctx->block_opcode = SEP_DES_BLOCK_OPCODE; + /* Clear out task context */ + memset(ta_ctx, 0, sizeof(struct this_task_ctx)); + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = DES_CBC; + ta_ctx->current_hash_req = NULL; + ta_ctx->current_cypher_req = req; + ta_ctx->des_encmode = SEP_DES_ENCRYPT; + ta_ctx->des_opmode = SEP_DES_CBC; + ta_ctx->init_opcode = SEP_DES_INIT_OPCODE; + ta_ctx->block_opcode = SEP_DES_BLOCK_OPCODE; + + /* lock necessary so that only one entity touches the queues */ spin_lock_irq(&queue_lock); error = crypto_enqueue_request(&sep_queue, &req->base); - spin_unlock_irq(&queue_lock); - if ((error != 0) && (error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep_des_cbc_encrypt cant enqueue\n"); - sep_crypto_release(sctx, error); - return error; - } - - error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, - (void *)&sep_queue); - if (error) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep_des_cbc_encrypt cannot submit queue\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } - return -EINPROGRESS; + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); + spin_unlock_irq(&queue_lock); + /* We return result of crypto enqueue */ + return error; } static int sep_des_cbc_decrypt(struct ablkcipher_request *req) { int error; - struct sep_block_ctx *bctx = ablkcipher_request_ctx(req); - struct sep_system_ctx *sctx = crypto_ablkcipher_ctx( - crypto_ablkcipher_reqtfm(req)); + int error1; + struct this_task_ctx *ta_ctx = ablkcipher_request_ctx(req); + + pr_debug("sep - doing des ecb decrypt\n"); - dev_dbg(&sctx->sep_used->pdev->dev, "sep des cbc decrypt\n"); - sctx->current_request = DES_CBC; - sctx->current_hash_req = NULL; - sctx->current_cypher_req = req; - bctx->des_encmode = SEP_DES_DECRYPT; - bctx->des_opmode = SEP_DES_CBC; - bctx->init_opcode = SEP_DES_INIT_OPCODE; - bctx->block_opcode = SEP_DES_BLOCK_OPCODE; + /* Clear out task context */ + memset(ta_ctx, 0, sizeof(struct this_task_ctx)); + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = DES_CBC; + ta_ctx->current_hash_req = NULL; + ta_ctx->current_cypher_req = req; + ta_ctx->des_encmode = SEP_DES_DECRYPT; + ta_ctx->des_opmode = SEP_DES_CBC; + ta_ctx->init_opcode = SEP_DES_INIT_OPCODE; + ta_ctx->block_opcode = SEP_DES_BLOCK_OPCODE; + + /* lock necessary so that only one entity touches the queues */ spin_lock_irq(&queue_lock); error = crypto_enqueue_request(&sep_queue, &req->base); - spin_unlock_irq(&queue_lock); - - if ((error != 0) && (error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep_des_cbc_decrypt cant enqueue\n"); - sep_crypto_release(sctx, error); - return error; - } - error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, - (void *)&sep_queue); - if (error) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep_des_cbc_decrypt cannot submit queue\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } - return -EINPROGRESS; + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); + spin_unlock_irq(&queue_lock); + /* We return result of crypto enqueue */ + return error; } static struct ahash_alg hash_algs[] = { @@ -3498,6 +3778,7 @@ static struct ahash_alg hash_algs[] = { .update = sep_sha1_update, .final = sep_sha1_final, .digest = sep_sha1_digest, + .finup = sep_sha1_finup, .halg = { .digestsize = SHA1_DIGEST_SIZE, .base = { @@ -3520,6 +3801,7 @@ static struct ahash_alg hash_algs[] = { .update = sep_md5_update, .final = sep_md5_final, .digest = sep_md5_digest, + .finup = sep_md5_finup, .halg = { .digestsize = MD5_DIGEST_SIZE, .base = { @@ -3542,6 +3824,7 @@ static struct ahash_alg hash_algs[] = { .update = sep_sha224_update, .final = sep_sha224_final, .digest = sep_sha224_digest, + .finup = sep_sha224_finup, .halg = { .digestsize = SHA224_DIGEST_SIZE, .base = { @@ -3564,6 +3847,7 @@ static struct ahash_alg hash_algs[] = { .update = sep_sha256_update, .final = sep_sha256_final, .digest = sep_sha256_digest, + .finup = sep_sha256_finup, .halg = { .digestsize = SHA256_DIGEST_SIZE, .base = { @@ -3621,6 +3905,7 @@ static struct crypto_alg crypto_algs[] = { .max_keysize = AES_MAX_KEY_SIZE, .setkey = sep_aes_setkey, .encrypt = sep_aes_cbc_encrypt, + .ivsize = AES_BLOCK_SIZE, .decrypt = sep_aes_cbc_decrypt, } }, @@ -3661,6 +3946,7 @@ static struct crypto_alg crypto_algs[] = { .max_keysize = DES_KEY_SIZE, .setkey = sep_des_setkey, .encrypt = sep_des_cbc_encrypt, + .ivsize = DES_BLOCK_SIZE, .decrypt = sep_des_cbc_decrypt, } }, @@ -3714,7 +4000,8 @@ int sep_crypto_setup(void) crypto_init_queue(&sep_queue, SEP_QUEUE_LENGTH); - sep_dev->workqueue = create_workqueue("sep_crypto_workqueue"); + sep_dev->workqueue = create_singlethread_workqueue( + "sep_crypto_workqueue"); if (!sep_dev->workqueue) { dev_warn(&sep_dev->pdev->dev, "cant create workqueue\n"); return -ENOMEM; @@ -3723,7 +4010,6 @@ int sep_crypto_setup(void) i = 0; j = 0; - spin_lock_init(&sep_dev->busy_lock); spin_lock_init(&queue_lock); err = 0; diff --git a/drivers/staging/sep/sep_crypto.h b/drivers/staging/sep/sep_crypto.h index 52c58c4..155c3c9 100644 --- a/drivers/staging/sep/sep_crypto.h +++ b/drivers/staging/sep/sep_crypto.h @@ -117,7 +117,7 @@ #define SEP_TRANSACTION_WAIT_TIME 5 -#define SEP_QUEUE_LENGTH 10 +#define SEP_QUEUE_LENGTH 2 /* Macros */ #ifndef __LITTLE_ENDIAN #define CHG_ENDIAN(val) \ @@ -270,9 +270,26 @@ struct sep_hash_private_context { u8 internal_context[sizeof(struct sep_hash_internal_context)]; }; +union key_t { + struct sep_des_key des; + u32 aes[SEP_AES_MAX_KEY_SIZE_WORDS]; +}; + /* Context structures for crypto API */ -struct sep_block_ctx { - struct sep_device *sep; +/** + * Structure for this current task context + * This same structure is used for both hash + * and crypt in order to reduce duplicate code + * for stuff that is done for both hash operations + * and crypto operations. We cannot trust that the + * system context is not pulled out from under + * us during operation to operation, so all + * critical stuff such as data pointers must + * be in in a context that is exclusive for this + * particular task at hand. + */ +struct this_task_ctx { + struct sep_device *sep_used; u32 done; unsigned char iv[100]; enum des_enc_mode des_encmode; @@ -284,36 +301,7 @@ struct sep_block_ctx { size_t data_length; size_t ivlen; struct ablkcipher_walk walk; - struct sep_des_private_context des_private_ctx; - struct sep_aes_private_context aes_private_ctx; - }; - -struct sep_hash_ctx { - u32 done; - unsigned char *buf; - size_t buflen; - unsigned char *dgst; - int digest_size_words; - int digest_size_bytes; - int block_size_words; - int block_size_bytes; - struct scatterlist *sg; - enum hash_op_mode hash_opmode; - struct sep_hash_private_context hash_private_ctx; - }; - -struct sep_system_ctx { - struct sep_device *sep_used; - union key_t { - struct sep_des_key des; - u32 aes[SEP_AES_MAX_KEY_SIZE_WORDS]; - } key; int i_own_sep; /* Do I have custody of the sep? */ - size_t keylen; - enum des_numkey des_nbr_keys; - enum aes_keysize aes_key_size; - u32 key_sent; /* Indicate if key is sent to sep */ - u32 last_block; /* Indicate that this is the final block */ struct sep_call_status call_status; struct build_dcb_struct_kernel dcb_input_data; struct sep_dma_context *dma_ctx; @@ -331,9 +319,32 @@ struct sep_system_ctx { struct ahash_request *current_hash_req; struct ablkcipher_request *current_cypher_req; enum type_of_request current_request; + int digest_size_words; + int digest_size_bytes; + int block_size_words; + int block_size_bytes; + enum hash_op_mode hash_opmode; enum hash_stage current_hash_stage; - int done_with_transaction; + /** + * Not that this is a pointer. The are_we_done_yet variable is + * allocated by the task function. This way, even if the kernel + * crypto infrastructure has grabbed the task structure out from + * under us, the task function can still see this variable. + */ + int *are_we_done_yet; + unsigned long end_time; + }; + +struct sep_system_ctx { + union key_t key; + size_t keylen; + int key_sent; + enum des_numkey des_nbr_keys; + enum aes_keysize aes_key_size; unsigned long end_time; + struct sep_des_private_context des_private_ctx; + struct sep_aes_private_context aes_private_ctx; + struct sep_hash_private_context hash_private_ctx; }; /* work queue structures */ diff --git a/drivers/staging/sep/sep_dev.h b/drivers/staging/sep/sep_dev.h index 66d8e95..5f6a07f 100644 --- a/drivers/staging/sep/sep_dev.h +++ b/drivers/staging/sep/sep_dev.h @@ -93,8 +93,7 @@ struct sep_device { enum hash_stage current_hash_stage; struct ahash_request *current_hash_req; struct ablkcipher_request *current_cypher_req; - struct sep_system_ctx *sctx; - spinlock_t busy_lock; + struct this_task_ctx *ta_ctx; struct workqueue_struct *workqueue; }; -- cgit v0.10.2