1fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V/* Copyright (c) 2012, Code Aurora Forum. All rights reserved. 2fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V * 3fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V * This program is free software; you can redistribute it and/or modify 4fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V * it under the terms of the GNU General Public License version 2 and 5fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V * only version 2 as published by the Free Software Foundation. 6fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V * 7fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V * This program is distributed in the hope that it will be useful, 8fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V * but WITHOUT ANY WARRANTY; without even the implied warranty of 9fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V * GNU General Public License for more details. 11fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V */ 12fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V 13fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V#include <linux/kernel.h> 14fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V#include <linux/init.h> 15fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V#include <linux/module.h> 16fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V#include <linux/interrupt.h> 17fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V#include <linux/gpio.h> 18fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V#include <linux/slab.h> 19fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V#include <linux/platform_device.h> 20fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V#include <linux/irq.h> 21fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V#include <media/rc-core.h> 22fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V#include <media/gpio-ir-recv.h> 23fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V 24fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V#define GPIO_IR_DRIVER_NAME "gpio-rc-recv" 25fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V#define GPIO_IR_DEVICE_NAME "gpio_ir_recv" 26fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V 27fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar Vstruct gpio_rc_dev { 28fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V struct rc_dev *rcdev; 29955b44304afca143b82304fe421e990ec607834aDan Carpenter int gpio_nr; 30fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V bool active_low; 31fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V}; 32fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V 33fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar Vstatic irqreturn_t gpio_ir_recv_irq(int irq, void *dev_id) 34fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V{ 35fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V struct gpio_rc_dev *gpio_dev = dev_id; 36955b44304afca143b82304fe421e990ec607834aDan Carpenter int gval; 37fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V int rc = 0; 38fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V enum raw_event_type type = IR_SPACE; 39fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V 40fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V gval = gpio_get_value_cansleep(gpio_dev->gpio_nr); 41fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V 42fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V if (gval < 0) 43fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V goto err_get_value; 44fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V 45fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V if (gpio_dev->active_low) 46fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V gval = !gval; 47fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V 48fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V if (gval == 1) 49fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V type = IR_PULSE; 50fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V 51fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V rc = ir_raw_event_store_edge(gpio_dev->rcdev, type); 52fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V if (rc < 0) 53fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V goto err_get_value; 54fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V 55fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V ir_raw_event_handle(gpio_dev->rcdev); 56fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V 57fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar Verr_get_value: 58fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V return IRQ_HANDLED; 59fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V} 60fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V 61fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar Vstatic int __devinit gpio_ir_recv_probe(struct platform_device *pdev) 62fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V{ 63fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V struct gpio_rc_dev *gpio_dev; 64fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V struct rc_dev *rcdev; 65fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V const struct gpio_ir_recv_platform_data *pdata = 66fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V pdev->dev.platform_data; 67fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V int rc; 68fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V 69fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V if (!pdata) 70fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V return -EINVAL; 71fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V 72fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V if (pdata->gpio_nr < 0) 73fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V return -EINVAL; 74fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V 75fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V gpio_dev = kzalloc(sizeof(struct gpio_rc_dev), GFP_KERNEL); 76fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V if (!gpio_dev) 77fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V return -ENOMEM; 78fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V 79fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V rcdev = rc_allocate_device(); 80fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V if (!rcdev) { 81fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V rc = -ENOMEM; 82fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V goto err_allocate_device; 83fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V } 84fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V 85fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V rcdev->driver_type = RC_DRIVER_IR_RAW; 86fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V rcdev->allowed_protos = RC_TYPE_ALL; 87fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V rcdev->input_name = GPIO_IR_DEVICE_NAME; 88fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V rcdev->input_id.bustype = BUS_HOST; 89fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V rcdev->driver_name = GPIO_IR_DRIVER_NAME; 90fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V rcdev->map_name = RC_MAP_EMPTY; 91fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V 92fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V gpio_dev->rcdev = rcdev; 93fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V gpio_dev->gpio_nr = pdata->gpio_nr; 94fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V gpio_dev->active_low = pdata->active_low; 95fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V 96fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V rc = gpio_request(pdata->gpio_nr, "gpio-ir-recv"); 97fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V if (rc < 0) 98fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V goto err_gpio_request; 99fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V rc = gpio_direction_input(pdata->gpio_nr); 100fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V if (rc < 0) 101fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V goto err_gpio_direction_input; 102fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V 103fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V rc = rc_register_device(rcdev); 104fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V if (rc < 0) { 105fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V dev_err(&pdev->dev, "failed to register rc device\n"); 106fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V goto err_register_rc_device; 107fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V } 108fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V 109fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V platform_set_drvdata(pdev, gpio_dev); 110fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V 111fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V rc = request_any_context_irq(gpio_to_irq(pdata->gpio_nr), 112fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V gpio_ir_recv_irq, 113fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, 114fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V "gpio-ir-recv-irq", gpio_dev); 115fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V if (rc < 0) 116fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V goto err_request_irq; 117fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V 118fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V return 0; 119fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V 120fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar Verr_request_irq: 121fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V platform_set_drvdata(pdev, NULL); 122fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V rc_unregister_device(rcdev); 123fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar Verr_register_rc_device: 124fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar Verr_gpio_direction_input: 125fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V gpio_free(pdata->gpio_nr); 126fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar Verr_gpio_request: 127fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V rc_free_device(rcdev); 128fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V rcdev = NULL; 129fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar Verr_allocate_device: 130fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V kfree(gpio_dev); 131fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V return rc; 132fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V} 133fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V 134fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar Vstatic int __devexit gpio_ir_recv_remove(struct platform_device *pdev) 135fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V{ 136fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V struct gpio_rc_dev *gpio_dev = platform_get_drvdata(pdev); 137fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V 138fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V free_irq(gpio_to_irq(gpio_dev->gpio_nr), gpio_dev); 139fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V platform_set_drvdata(pdev, NULL); 140fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V rc_unregister_device(gpio_dev->rcdev); 141fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V gpio_free(gpio_dev->gpio_nr); 142fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V rc_free_device(gpio_dev->rcdev); 143fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V kfree(gpio_dev); 144fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V return 0; 145fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V} 146fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V 147fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V#ifdef CONFIG_PM 148fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar Vstatic int gpio_ir_recv_suspend(struct device *dev) 149fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V{ 150fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V struct platform_device *pdev = to_platform_device(dev); 151fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V struct gpio_rc_dev *gpio_dev = platform_get_drvdata(pdev); 152fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V 153fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V if (device_may_wakeup(dev)) 154fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V enable_irq_wake(gpio_to_irq(gpio_dev->gpio_nr)); 155fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V else 156fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V disable_irq(gpio_to_irq(gpio_dev->gpio_nr)); 157fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V 158fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V return 0; 159fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V} 160fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V 161fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar Vstatic int gpio_ir_recv_resume(struct device *dev) 162fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V{ 163fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V struct platform_device *pdev = to_platform_device(dev); 164fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V struct gpio_rc_dev *gpio_dev = platform_get_drvdata(pdev); 165fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V 166fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V if (device_may_wakeup(dev)) 167fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V disable_irq_wake(gpio_to_irq(gpio_dev->gpio_nr)); 168fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V else 169fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V enable_irq(gpio_to_irq(gpio_dev->gpio_nr)); 170fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V 171fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V return 0; 172fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V} 173fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V 174fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar Vstatic const struct dev_pm_ops gpio_ir_recv_pm_ops = { 175fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V .suspend = gpio_ir_recv_suspend, 176fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V .resume = gpio_ir_recv_resume, 177fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V}; 178fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V#endif 179fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V 180fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar Vstatic struct platform_driver gpio_ir_recv_driver = { 181fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V .probe = gpio_ir_recv_probe, 182fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V .remove = __devexit_p(gpio_ir_recv_remove), 183fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V .driver = { 184fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V .name = GPIO_IR_DRIVER_NAME, 185fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V .owner = THIS_MODULE, 186fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V#ifdef CONFIG_PM 187fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V .pm = &gpio_ir_recv_pm_ops, 188fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V#endif 189fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V }, 190fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V}; 191fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V 192fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar Vstatic int __init gpio_ir_recv_init(void) 193fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V{ 194fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V return platform_driver_register(&gpio_ir_recv_driver); 195fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V} 196fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar Vmodule_init(gpio_ir_recv_init); 197fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V 198fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar Vstatic void __exit gpio_ir_recv_exit(void) 199fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V{ 200fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V platform_driver_unregister(&gpio_ir_recv_driver); 201fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V} 202fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar Vmodule_exit(gpio_ir_recv_exit); 203fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar V 204fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar VMODULE_DESCRIPTION("GPIO IR Receiver driver"); 205fd0f6851eb46512a6df2961923a0c24edc0a55b9Ravi Kumar VMODULE_LICENSE("GPL v2"); 206