static int __init rp5c01_rtc_probe(struct platform_device *dev) { struct resource *res; struct rp5c01_priv *priv; struct rtc_device *rtc; int error; struct nvmem_config nvmem_cfg = { .name = "rp5c01_nvram", .word_size = 1, .stride = 1, .size = RP5C01_MODE, .reg_read = rp5c01_nvram_read, .reg_write = rp5c01_nvram_write, }; res = platform_get_resource(dev, IORESOURCE_MEM, 0); if (!res) return -ENODEV; priv = devm_kzalloc(&dev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; priv->regs = devm_ioremap(&dev->dev, res->start, resource_size(res)); if (!priv->regs) return -ENOMEM; spin_lock_init(&priv->lock); platform_set_drvdata(dev, priv); rtc = devm_rtc_allocate_device(&dev->dev); if (IS_ERR(rtc)) return PTR_ERR(rtc); rtc->ops = &rp5c01_rtc_ops; rtc->nvram_old_abi = true; priv->rtc = rtc; nvmem_cfg.priv = priv; error = rtc_nvmem_register(rtc, &nvmem_cfg); if (error) return error; return rtc_register_device(rtc); } static struct platform_driver rp5c01_rtc_driver = { .driver = { .name = "rtc-rp5c01", }, }; module_platform_driver_probe(rp5c01_rtc_driver, rp5c01_rtc_probe); MODULE_AUTHOR("Geert Uytterhoeven <*****@*****.**>"); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Ricoh RP5C01 RTC driver"); MODULE_ALIAS("platform:rtc-rp5c01");
static int omap_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { int new_margin; static struct watchdog_info ident = { .identity = "OMAP Watchdog", .options = WDIOF_SETTIMEOUT, .firmware_version = 0, }; switch (cmd) { default: return -ENOTTY; case WDIOC_GETSUPPORT: return copy_to_user((struct watchdog_info __user *)arg, &ident, sizeof(ident)); case WDIOC_GETSTATUS: return put_user(0, (int __user *)arg); case WDIOC_GETBOOTSTATUS: if (cpu_is_omap16xx()) return put_user(omap_readw(ARM_SYSST), (int __user *)arg); if (cpu_is_omap24xx()) return put_user(omap_prcm_get_reset_sources(), (int __user *)arg); case WDIOC_KEEPALIVE: omap_wdt_ping(); return 0; case WDIOC_SETTIMEOUT: if (get_user(new_margin, (int __user *)arg)) return -EFAULT; omap_wdt_adjust_timeout(new_margin); omap_wdt_disable(); omap_wdt_set_timeout(); omap_wdt_enable(); omap_wdt_ping(); /* Fall */ case WDIOC_GETTIMEOUT: return put_user(timer_margin, (int __user *)arg); } } static const struct file_operations omap_wdt_fops = { .owner = THIS_MODULE, .write = omap_wdt_write, .ioctl = omap_wdt_ioctl, .open = omap_wdt_open, .release = omap_wdt_release, }; static struct miscdevice omap_wdt_miscdev = { .minor = WATCHDOG_MINOR, .name = "watchdog", .fops = &omap_wdt_fops }; static int __init omap_wdt_probe(struct platform_device *pdev) { struct resource *res, *mem; int ret; /* reserve static register mappings */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) return -ENOENT; mem = request_mem_region(res->start, res->end - res->start + 1, pdev->name); if (mem == NULL) return -EBUSY; platform_set_drvdata(pdev, mem); omap_wdt_users = 0; if (cpu_is_omap16xx()) { armwdt_ck = clk_get(&pdev->dev, "armwdt_ck"); if (IS_ERR(armwdt_ck)) { ret = PTR_ERR(armwdt_ck); armwdt_ck = NULL; goto fail; } } if (cpu_is_omap24xx()) { mpu_wdt_ick = clk_get(&pdev->dev, "mpu_wdt_ick"); if (IS_ERR(mpu_wdt_ick)) { ret = PTR_ERR(mpu_wdt_ick); mpu_wdt_ick = NULL; goto fail; } mpu_wdt_fck = clk_get(&pdev->dev, "mpu_wdt_fck"); if (IS_ERR(mpu_wdt_fck)) { ret = PTR_ERR(mpu_wdt_fck); mpu_wdt_fck = NULL; goto fail; } } omap_wdt_disable(); omap_wdt_adjust_timeout(timer_margin); omap_wdt_miscdev.parent = &pdev->dev; ret = misc_register(&omap_wdt_miscdev); if (ret) goto fail; pr_info("OMAP Watchdog Timer: initial timeout %d sec\n", timer_margin); /* autogate OCP interface clock */ omap_writel(0x01, OMAP_WATCHDOG_SYS_CONFIG); return 0; fail: if (armwdt_ck) clk_put(armwdt_ck); if (mpu_wdt_ick) clk_put(mpu_wdt_ick); if (mpu_wdt_fck) clk_put(mpu_wdt_fck); release_resource(mem); return ret; } static void omap_wdt_shutdown(struct platform_device *pdev) { omap_wdt_disable(); } static int omap_wdt_remove(struct platform_device *pdev) { struct resource *mem = platform_get_drvdata(pdev); misc_deregister(&omap_wdt_miscdev); release_resource(mem); if (armwdt_ck) clk_put(armwdt_ck); if (mpu_wdt_ick) clk_put(mpu_wdt_ick); if (mpu_wdt_fck) clk_put(mpu_wdt_fck); return 0; } #ifdef CONFIG_PM /* REVISIT ... not clear this is the best way to handle system suspend; and * it's very inappropriate for selective device suspend (e.g. suspending this * through sysfs rather than by stopping the watchdog daemon). Also, this * may not play well enough with NOWAYOUT... */ static int omap_wdt_suspend(struct platform_device *pdev, pm_message_t state) { if (omap_wdt_users) omap_wdt_disable(); return 0; } static int omap_wdt_resume(struct platform_device *pdev) { if (omap_wdt_users) { omap_wdt_enable(); omap_wdt_ping(); } return 0; } #else #define omap_wdt_suspend NULL #define omap_wdt_resume NULL #endif static struct platform_driver omap_wdt_driver = { .probe = omap_wdt_probe, .remove = omap_wdt_remove, .shutdown = omap_wdt_shutdown, .suspend = omap_wdt_suspend, .resume = omap_wdt_resume, .driver = { .owner = THIS_MODULE, .name = "omap_wdt", }, }; static int __init omap_wdt_init(void) { return platform_driver_register(&omap_wdt_driver); } static void __exit omap_wdt_exit(void) { platform_driver_unregister(&omap_wdt_driver); } module_init(omap_wdt_init); module_exit(omap_wdt_exit); MODULE_AUTHOR("George G. Davis"); MODULE_LICENSE("GPL"); MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); MODULE_ALIAS("platform:omap_wdt");
/* * keypad controller should be initialized in the following sequence * only, otherwise it might get into FSM stuck state. * * - Initialize keypad control parameters, like no. of rows, columns, * timing values etc., * - configure rows and column gpios pull up/down. * - set irq edge type. * - enable the keypad controller. */ static int __devinit pmic8xxx_kp_probe(struct platform_device *pdev) { const struct pm8xxx_keypad_platform_data *pdata = dev_get_platdata(&pdev->dev); const struct matrix_keymap_data *keymap_data; struct pmic8xxx_kp *kp; int rc; u8 ctrl_val; struct pm_gpio kypd_drv = { .direction = PM_GPIO_DIR_OUT, .output_buffer = PM_GPIO_OUT_BUF_OPEN_DRAIN, .output_value = 0, .pull = PM_GPIO_PULL_NO, .vin_sel = PM_GPIO_VIN_S4, .out_strength = PM_GPIO_STRENGTH_LOW, .function = PM_GPIO_FUNC_1, .inv_int_pol = 1, }; struct pm_gpio kypd_sns = { .direction = PM_GPIO_DIR_IN, .pull = PM_GPIO_PULL_UP_31P5, .vin_sel = PM_GPIO_VIN_S4, .out_strength = PM_GPIO_STRENGTH_NO, .function = PM_GPIO_FUNC_NORMAL, .inv_int_pol = 1, }; if (!pdata || !pdata->num_cols || !pdata->num_rows || pdata->num_cols > PM8XXX_MAX_COLS || pdata->num_rows > PM8XXX_MAX_ROWS || pdata->num_cols < PM8XXX_MIN_COLS) { dev_err(&pdev->dev, "invalid platform data\n"); return -EINVAL; } if (!pdata->scan_delay_ms || pdata->scan_delay_ms > MAX_SCAN_DELAY || pdata->scan_delay_ms < MIN_SCAN_DELAY || !is_power_of_2(pdata->scan_delay_ms)) { dev_err(&pdev->dev, "invalid keypad scan time supplied\n"); return -EINVAL; } if (!pdata->row_hold_ns || pdata->row_hold_ns > MAX_ROW_HOLD_DELAY || pdata->row_hold_ns < MIN_ROW_HOLD_DELAY || ((pdata->row_hold_ns % MIN_ROW_HOLD_DELAY) != 0)) { dev_err(&pdev->dev, "invalid keypad row hold time supplied\n"); return -EINVAL; } if (!pdata->debounce_ms || ((pdata->debounce_ms % 5) != 0) || pdata->debounce_ms > MAX_DEBOUNCE_TIME || pdata->debounce_ms < MIN_DEBOUNCE_TIME) { dev_err(&pdev->dev, "invalid debounce time supplied\n"); return -EINVAL; } keymap_data = pdata->keymap_data; if (!keymap_data) { dev_err(&pdev->dev, "no keymap data supplied\n"); return -EINVAL; } kp = kzalloc(sizeof(*kp), GFP_KERNEL); if (!kp) return -ENOMEM; platform_set_drvdata(pdev, kp); kp->pdata = pdata; kp->dev = &pdev->dev; kp->input = input_allocate_device(); if (!kp->input) { dev_err(&pdev->dev, "unable to allocate input device\n"); rc = -ENOMEM; goto err_alloc_device; } kp->key_sense_irq = platform_get_irq(pdev, 0); if (kp->key_sense_irq < 0) { dev_err(&pdev->dev, "unable to get keypad sense irq\n"); rc = -ENXIO; goto err_get_irq; } kp->key_stuck_irq = platform_get_irq(pdev, 1); if (kp->key_stuck_irq < 0) { dev_err(&pdev->dev, "unable to get keypad stuck irq\n"); rc = -ENXIO; goto err_get_irq; } kp->input->name = pdata->input_name ? : "PMIC8XXX keypad"; kp->input->phys = pdata->input_phys_device ? : "pmic8xxx_keypad/input0"; kp->input->dev.parent = &pdev->dev; kp->input->id.bustype = BUS_I2C; kp->input->id.version = 0x0001; kp->input->id.product = 0x0001; kp->input->id.vendor = 0x0001; kp->input->evbit[0] = BIT_MASK(EV_KEY); if (pdata->rep) __set_bit(EV_REP, kp->input->evbit); kp->input->keycode = kp->keycodes; kp->input->keycodemax = PM8XXX_MATRIX_MAX_SIZE; kp->input->keycodesize = sizeof(kp->keycodes); kp->input->open = pmic8xxx_kp_open; kp->input->close = pmic8xxx_kp_close; matrix_keypad_build_keymap(keymap_data, PM8XXX_ROW_SHIFT, kp->input->keycode, kp->input->keybit); input_set_capability(kp->input, EV_MSC, MSC_SCAN); input_set_drvdata(kp->input, kp); /* initialize keypad state */ memset(kp->keystate, 0xff, sizeof(kp->keystate)); memset(kp->stuckstate, 0xff, sizeof(kp->stuckstate)); rc = pmic8xxx_kpd_init(kp); if (rc < 0) { dev_err(&pdev->dev, "unable to initialize keypad controller\n"); goto err_get_irq; } rc = pmic8xxx_kp_config_gpio(pdata->cols_gpio_start, pdata->num_cols, kp, &kypd_sns); if (rc < 0) { dev_err(&pdev->dev, "unable to configure keypad sense lines\n"); goto err_gpio_config; } rc = pmic8xxx_kp_config_gpio(pdata->rows_gpio_start, pdata->num_rows, kp, &kypd_drv); if (rc < 0) { dev_err(&pdev->dev, "unable to configure keypad drive lines\n"); goto err_gpio_config; } rc = request_any_context_irq(kp->key_sense_irq, pmic8xxx_kp_irq, IRQF_TRIGGER_RISING, "pmic-keypad", kp); if (rc < 0) { dev_err(&pdev->dev, "failed to request keypad sense irq\n"); goto err_get_irq; } rc = request_any_context_irq(kp->key_stuck_irq, pmic8xxx_kp_stuck_irq, IRQF_TRIGGER_RISING, "pmic-keypad-stuck", kp); if (rc < 0) { dev_err(&pdev->dev, "failed to request keypad stuck irq\n"); goto err_req_stuck_irq; } rc = pmic8xxx_kp_read_u8(kp, &ctrl_val, KEYP_CTRL); if (rc < 0) { dev_err(&pdev->dev, "failed to read KEYP_CTRL register\n"); goto err_pmic_reg_read; } kp->ctrl_reg = ctrl_val; rc = input_register_device(kp->input); if (rc < 0) { dev_err(&pdev->dev, "unable to register keypad input device\n"); goto err_pmic_reg_read; } device_init_wakeup(&pdev->dev, pdata->wakeup); #if defined(CONFIG_MACH_KS02) /*sysfs*/ kp->sec_keypad = device_create(sec_class, NULL, 0, kp, "sec_keypad"); if (IS_ERR(kp->sec_keypad)) dev_err(&pdev->dev, "Failed to create sec_key device\n"); rc = sysfs_create_group(&kp->sec_keypad->kobj, &key_attr_group); if (rc) { dev_err(&pdev->dev, "Failed to create the test sysfs: %d\n", rc); } #endif return 0; err_pmic_reg_read: free_irq(kp->key_stuck_irq, kp); err_req_stuck_irq: free_irq(kp->key_sense_irq, kp); err_gpio_config: err_get_irq: input_free_device(kp->input); err_alloc_device: platform_set_drvdata(pdev, NULL); kfree(kp); return rc; } static int __devexit pmic8xxx_kp_remove(struct platform_device *pdev) { struct pmic8xxx_kp *kp = platform_get_drvdata(pdev); device_init_wakeup(&pdev->dev, 0); free_irq(kp->key_stuck_irq, kp); free_irq(kp->key_sense_irq, kp); input_unregister_device(kp->input); kfree(kp); platform_set_drvdata(pdev, NULL); return 0; } #ifdef CONFIG_PM_SLEEP static int pmic8xxx_kp_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct pmic8xxx_kp *kp = platform_get_drvdata(pdev); struct input_dev *input_dev = kp->input; if (device_may_wakeup(dev)) { enable_irq_wake(kp->key_sense_irq); } else { mutex_lock(&input_dev->mutex); if (input_dev->users) pmic8xxx_kp_disable(kp); mutex_unlock(&input_dev->mutex); } key_suspend = 1; return 0; } static int pmic8xxx_kp_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct pmic8xxx_kp *kp = platform_get_drvdata(pdev); struct input_dev *input_dev = kp->input; if (device_may_wakeup(dev)) { disable_irq_wake(kp->key_sense_irq); } else { mutex_lock(&input_dev->mutex); if (input_dev->users) pmic8xxx_kp_enable(kp); mutex_unlock(&input_dev->mutex); } key_suspend = 0; return 0; } #endif static SIMPLE_DEV_PM_OPS(pm8xxx_kp_pm_ops, pmic8xxx_kp_suspend, pmic8xxx_kp_resume); static struct platform_driver pmic8xxx_kp_driver = { .probe = pmic8xxx_kp_probe, .remove = __devexit_p(pmic8xxx_kp_remove), .driver = { .name = PM8XXX_KEYPAD_DEV_NAME, .owner = THIS_MODULE, .pm = &pm8xxx_kp_pm_ops, }, }; module_platform_driver(pmic8xxx_kp_driver); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("PMIC8XXX keypad driver"); MODULE_VERSION("1.0"); MODULE_ALIAS("platform:pmic8xxx_keypad"); MODULE_AUTHOR("Trilok Soni <*****@*****.**>");
static int axp20x_regulator_probe(struct platform_device *pdev) { struct regulator_dev *rdev; struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent); const struct regulator_desc *regulators; struct regulator_config config = { .dev = pdev->dev.parent, .regmap = axp20x->regmap, .driver_data = axp20x, }; int ret, i, nregulators; u32 workmode; switch (axp20x->variant) { case AXP202_ID: case AXP209_ID: regulators = axp20x_regulators; nregulators = AXP20X_REG_ID_MAX; break; case AXP221_ID: regulators = axp22x_regulators; nregulators = AXP22X_REG_ID_MAX; break; default: dev_err(&pdev->dev, "Unsupported AXP variant: %ld\n", axp20x->variant); return -EINVAL; } /* This only sets the dcdc freq. Ignore any errors */ axp20x_regulator_parse_dt(pdev); for (i = 0; i < nregulators; i++) { rdev = devm_regulator_register(&pdev->dev, ®ulators[i], &config); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "Failed to register %s\n", regulators[i].name); return PTR_ERR(rdev); } ret = of_property_read_u32(rdev->dev.of_node, "x-powers,dcdc-workmode", &workmode); if (!ret) { if (axp20x_set_dcdc_workmode(rdev, i, workmode)) dev_err(&pdev->dev, "Failed to set workmode on %s\n", rdev->desc->name); } } return 0; } static struct platform_driver axp20x_regulator_driver = { .probe = axp20x_regulator_probe, .driver = { .name = "axp20x-regulator", }, }; module_platform_driver(axp20x_regulator_driver); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Carlo Caione <*****@*****.**>"); MODULE_DESCRIPTION("Regulator Driver for AXP20X PMIC"); MODULE_ALIAS("platform:axp20x-regulator");
static long mtx1_wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *)arg; int __user *p = (int __user *)argp; unsigned int value; static const struct watchdog_info ident = { .options = WDIOF_CARDRESET, .identity = "MTX-1 WDT", }; switch (cmd) { case WDIOC_GETSUPPORT: if (copy_to_user(argp, &ident, sizeof(ident))) return -EFAULT; break; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: put_user(0, p); break; case WDIOC_SETOPTIONS: if (get_user(value, p)) return -EFAULT; if (value & WDIOS_ENABLECARD) mtx1_wdt_start(); else if (value & WDIOS_DISABLECARD) mtx1_wdt_stop(); else return -EINVAL; return 0; case WDIOC_KEEPALIVE: mtx1_wdt_reset(); break; default: return -ENOTTY; } return 0; } static ssize_t mtx1_wdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos) { if (!count) return -EIO; mtx1_wdt_reset(); return count; } static const struct file_operations mtx1_wdt_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .unlocked_ioctl = mtx1_wdt_ioctl, .open = mtx1_wdt_open, .write = mtx1_wdt_write, .release = mtx1_wdt_release, }; static struct miscdevice mtx1_wdt_misc = { .minor = WATCHDOG_MINOR, .name = "watchdog", .fops = &mtx1_wdt_fops, }; static int mtx1_wdt_probe(struct platform_device *pdev) { int ret; mtx1_wdt_device.gpio = pdev->resource[0].start; spin_lock_init(&mtx1_wdt_device.lock); init_completion(&mtx1_wdt_device.stop); mtx1_wdt_device.queue = 0; clear_bit(0, &mtx1_wdt_device.inuse); setup_timer(&mtx1_wdt_device.timer, mtx1_wdt_trigger, 0L); mtx1_wdt_device.default_ticks = ticks; ret = misc_register(&mtx1_wdt_misc); if (ret < 0) { printk(KERN_ERR " mtx-1_wdt : failed to register\n"); return ret; } mtx1_wdt_start(); printk(KERN_INFO "MTX-1 Watchdog driver\n"); return 0; } static int mtx1_wdt_remove(struct platform_device *pdev) { /* FIXME: do we need to lock this test ? */ if (mtx1_wdt_device.queue) { mtx1_wdt_device.queue = 0; wait_for_completion(&mtx1_wdt_device.stop); } misc_deregister(&mtx1_wdt_misc); return 0; } static struct platform_driver mtx1_wdt = { .probe = mtx1_wdt_probe, .remove = mtx1_wdt_remove, .driver.name = "mtx1-wdt", .driver.owner = THIS_MODULE, }; static int __init mtx1_wdt_init(void) { return platform_driver_register(&mtx1_wdt); } static void __exit mtx1_wdt_exit(void) { platform_driver_unregister(&mtx1_wdt); } module_init(mtx1_wdt_init); module_exit(mtx1_wdt_exit); MODULE_AUTHOR("Michael Stickel, Florian Fainelli"); MODULE_DESCRIPTION("Driver for the MTX-1 watchdog"); MODULE_LICENSE("GPL"); MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); MODULE_ALIAS("platform:mtx1-wdt");
static int gpio_keys_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); #ifndef CONFIG_MACH_Q1_REV02 struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev); #endif struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; int i; if (device_may_wakeup(&pdev->dev)) { for (i = 0; i < pdata->nbuttons; i++) { struct gpio_keys_button *button = &pdata->buttons[i]; #ifdef CONFIG_MACH_Q1_REV02 if (button->wakeup) { #else struct gpio_button_data *bdata = &ddata->data[i]; if (button->wakeup && !bdata->disabled) { #endif int irq = gpio_to_irq(button->gpio); enable_irq_wake(irq); } } } return 0; } static int gpio_keys_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev); struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; int i; for (i = 0; i < pdata->nbuttons; i++) { struct gpio_keys_button *button = &pdata->buttons[i]; #ifdef CONFIG_MACH_Q1_REV02 if (button->wakeup && device_may_wakeup(&pdev->dev)) { #else struct gpio_button_data *bdata = &ddata->data[i]; if (button->wakeup && !bdata->disabled && device_may_wakeup(&pdev->dev)) { #endif int irq = gpio_to_irq(button->gpio); disable_irq_wake(irq); } gpio_keys_report_event(&ddata->data[i]); } input_sync(ddata->input); return 0; } static const struct dev_pm_ops gpio_keys_pm_ops = { .suspend = gpio_keys_suspend, .resume = gpio_keys_resume, }; #endif static struct platform_driver gpio_keys_device_driver = { .probe = gpio_keys_probe, .remove = __devexit_p(gpio_keys_remove), .driver = { .name = "sec_key", .owner = THIS_MODULE, #ifdef CONFIG_PM .pm = &gpio_keys_pm_ops, #endif } }; static int __init gpio_keys_init(void) { return platform_driver_register(&gpio_keys_device_driver); } static void __exit gpio_keys_exit(void) { platform_driver_unregister(&gpio_keys_device_driver); } module_init(gpio_keys_init); module_exit(gpio_keys_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Phil Blundell <*****@*****.**>"); MODULE_DESCRIPTION("Keyboard driver for CPU GPIOs"); MODULE_ALIAS("platform:gpio-keys");
static void scsifront_free(struct vscsifrnt_info *info) { struct Scsi_Host *host = info->host; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14) if (host->shost_state != SHOST_DEL) { #else if (!test_bit(SHOST_DEL, &host->shost_state)) { #endif scsi_remove_host(info->host); } if (info->ring_ref != GRANT_INVALID_REF) { gnttab_end_foreign_access(info->ring_ref, (unsigned long)info->ring.sring); info->ring_ref = GRANT_INVALID_REF; info->ring.sring = NULL; } if (info->irq) unbind_from_irqhandler(info->irq, info); info->irq = 0; scsi_host_put(info->host); } static int scsifront_alloc_ring(struct vscsifrnt_info *info) { struct xenbus_device *dev = info->dev; struct vscsiif_sring *sring; int err = -ENOMEM; info->ring_ref = GRANT_INVALID_REF; /***** Frontend to Backend ring start *****/ sring = (struct vscsiif_sring *) __get_free_page(GFP_KERNEL); if (!sring) { xenbus_dev_fatal(dev, err, "fail to allocate shared ring (Front to Back)"); return err; } SHARED_RING_INIT(sring); FRONT_RING_INIT(&info->ring, sring, PAGE_SIZE); err = xenbus_grant_ring(dev, virt_to_mfn(sring)); if (err < 0) { free_page((unsigned long) sring); info->ring.sring = NULL; xenbus_dev_fatal(dev, err, "fail to grant shared ring (Front to Back)"); goto free_sring; } info->ring_ref = err; err = bind_listening_port_to_irqhandler( dev->otherend_id, scsifront_intr, SA_SAMPLE_RANDOM, "scsifront", info); if (err <= 0) { xenbus_dev_fatal(dev, err, "bind_listening_port_to_irqhandler"); goto free_sring; } info->irq = err; return 0; /* free resource */ free_sring: scsifront_free(info); return err; } static int scsifront_init_ring(struct vscsifrnt_info *info) { struct xenbus_device *dev = info->dev; struct xenbus_transaction xbt; int err; DPRINTK("%s\n",__FUNCTION__); err = scsifront_alloc_ring(info); if (err) return err; DPRINTK("%u %u\n", info->ring_ref, info->evtchn); again: err = xenbus_transaction_start(&xbt); if (err) { xenbus_dev_fatal(dev, err, "starting transaction"); } err = xenbus_printf(xbt, dev->nodename, "ring-ref", "%u", info->ring_ref); if (err) { xenbus_dev_fatal(dev, err, "%s", "writing ring-ref"); goto fail; } err = xenbus_printf(xbt, dev->nodename, "event-channel", "%u", irq_to_evtchn_port(info->irq)); if (err) { xenbus_dev_fatal(dev, err, "%s", "writing event-channel"); goto fail; } err = xenbus_transaction_end(xbt, 0); if (err) { if (err == -EAGAIN) goto again; xenbus_dev_fatal(dev, err, "completing transaction"); goto free_sring; } return 0; fail: xenbus_transaction_end(xbt, 1); free_sring: /* free resource */ scsifront_free(info); return err; } static int scsifront_probe(struct xenbus_device *dev, const struct xenbus_device_id *id) { struct vscsifrnt_info *info; struct Scsi_Host *host; int i, err = -ENOMEM; char name[DEFAULT_TASK_COMM_LEN]; host = scsi_host_alloc(&scsifront_sht, sizeof(*info)); if (!host) { xenbus_dev_fatal(dev, err, "fail to allocate scsi host"); return err; } info = (struct vscsifrnt_info *) host->hostdata; info->host = host; dev->dev.driver_data = info; info->dev = dev; for (i = 0; i < VSCSIIF_MAX_REQS; i++) { info->shadow[i].next_free = i + 1; init_waitqueue_head(&(info->shadow[i].wq_reset)); info->shadow[i].wait_reset = 0; } info->shadow[VSCSIIF_MAX_REQS - 1].next_free = 0x0fff; err = scsifront_init_ring(info); if (err) { scsi_host_put(host); return err; } init_waitqueue_head(&info->wq); spin_lock_init(&info->io_lock); spin_lock_init(&info->shadow_lock); snprintf(name, DEFAULT_TASK_COMM_LEN, "vscsiif.%d", info->host->host_no); info->kthread = kthread_run(scsifront_schedule, info, name); if (IS_ERR(info->kthread)) { err = PTR_ERR(info->kthread); info->kthread = NULL; printk(KERN_ERR "scsifront: kthread start err %d\n", err); goto free_sring; } host->max_id = VSCSIIF_MAX_TARGET; host->max_channel = 0; host->max_lun = VSCSIIF_MAX_LUN; host->max_sectors = (VSCSIIF_SG_TABLESIZE - 1) * PAGE_SIZE / 512; err = scsi_add_host(host, &dev->dev); if (err) { printk(KERN_ERR "scsifront: fail to add scsi host %d\n", err); goto free_sring; } xenbus_switch_state(dev, XenbusStateInitialised); return 0; free_sring: /* free resource */ scsifront_free(info); return err; } static int scsifront_remove(struct xenbus_device *dev) { struct vscsifrnt_info *info = dev->dev.driver_data; DPRINTK("%s: %s removed\n",__FUNCTION__ ,dev->nodename); if (info->kthread) { kthread_stop(info->kthread); info->kthread = NULL; } scsifront_free(info); return 0; } static int scsifront_disconnect(struct vscsifrnt_info *info) { struct xenbus_device *dev = info->dev; struct Scsi_Host *host = info->host; DPRINTK("%s: %s disconnect\n",__FUNCTION__ ,dev->nodename); /* When this function is executed, all devices of Frontend have been deleted. Therefore, it need not block I/O before remove_host. */ scsi_remove_host(host); xenbus_frontend_closed(dev); return 0; } #define VSCSIFRONT_OP_ADD_LUN 1 #define VSCSIFRONT_OP_DEL_LUN 2 static void scsifront_do_lun_hotplug(struct vscsifrnt_info *info, int op) { struct xenbus_device *dev = info->dev; int i, err = 0; char str[64], state_str[64]; char **dir; unsigned int dir_n = 0; unsigned int device_state; unsigned int hst, chn, tgt, lun; struct scsi_device *sdev; dir = xenbus_directory(XBT_NIL, dev->otherend, "vscsi-devs", &dir_n); if (IS_ERR(dir)) return; for (i = 0; i < dir_n; i++) { /* read status */ snprintf(str, sizeof(str), "vscsi-devs/%s/state", dir[i]); err = xenbus_scanf(XBT_NIL, dev->otherend, str, "%u", &device_state); if (XENBUS_EXIST_ERR(err)) continue; /* virtual SCSI device */ snprintf(str, sizeof(str), "vscsi-devs/%s/v-dev", dir[i]); err = xenbus_scanf(XBT_NIL, dev->otherend, str, "%u:%u:%u:%u", &hst, &chn, &tgt, &lun); if (XENBUS_EXIST_ERR(err)) continue; /* front device state path */ snprintf(state_str, sizeof(state_str), "vscsi-devs/%s/state", dir[i]); switch (op) { case VSCSIFRONT_OP_ADD_LUN: if (device_state == XenbusStateInitialised) { sdev = scsi_device_lookup(info->host, chn, tgt, lun); if (sdev) { printk(KERN_ERR "scsifront: Device already in use.\n"); scsi_device_put(sdev); xenbus_printf(XBT_NIL, dev->nodename, state_str, "%d", XenbusStateClosed); } else { scsi_add_device(info->host, chn, tgt, lun); xenbus_printf(XBT_NIL, dev->nodename, state_str, "%d", XenbusStateConnected); } } break; case VSCSIFRONT_OP_DEL_LUN: if (device_state == XenbusStateClosing) { sdev = scsi_device_lookup(info->host, chn, tgt, lun); if (sdev) { scsi_remove_device(sdev); scsi_device_put(sdev); xenbus_printf(XBT_NIL, dev->nodename, state_str, "%d", XenbusStateClosed); } } break; default: break; } } kfree(dir); return; } static void scsifront_backend_changed(struct xenbus_device *dev, enum xenbus_state backend_state) { struct vscsifrnt_info *info = dev->dev.driver_data; DPRINTK("%p %u %u\n", dev, dev->state, backend_state); switch (backend_state) { case XenbusStateUnknown: case XenbusStateInitialising: case XenbusStateInitWait: case XenbusStateClosed: break; case XenbusStateInitialised: break; case XenbusStateConnected: if (xenbus_read_driver_state(dev->nodename) == XenbusStateInitialised) { scsifront_do_lun_hotplug(info, VSCSIFRONT_OP_ADD_LUN); } if (dev->state == XenbusStateConnected) break; xenbus_switch_state(dev, XenbusStateConnected); break; case XenbusStateClosing: scsifront_disconnect(info); break; case XenbusStateReconfiguring: scsifront_do_lun_hotplug(info, VSCSIFRONT_OP_DEL_LUN); xenbus_switch_state(dev, XenbusStateReconfiguring); break; case XenbusStateReconfigured: scsifront_do_lun_hotplug(info, VSCSIFRONT_OP_ADD_LUN); xenbus_switch_state(dev, XenbusStateConnected); break; } } static struct xenbus_device_id scsifront_ids[] = { { "vscsi" }, { "" } }; MODULE_ALIAS("xen:vscsi"); static struct xenbus_driver scsifront_driver = { .name = "vscsi", .owner = THIS_MODULE, .ids = scsifront_ids, .probe = scsifront_probe, .remove = scsifront_remove, /* .resume = scsifront_resume, */ .otherend_changed = scsifront_backend_changed, }; int scsifront_xenbus_init(void) { return xenbus_register_frontend(&scsifront_driver); } void scsifront_xenbus_unregister(void) { xenbus_unregister_driver(&scsifront_driver); }
static int ixp4xx_flash_probe(struct platform_device *dev) { struct flash_platform_data *plat = dev_get_platdata(&dev->dev); struct ixp4xx_flash_info *info; struct mtd_part_parser_data ppdata = { .origin = dev->resource->start, }; int err = -1; if (!plat) return -ENODEV; if (plat->init) { err = plat->init(); if (err) return err; } info = devm_kzalloc(&dev->dev, sizeof(struct ixp4xx_flash_info), GFP_KERNEL); if(!info) { err = -ENOMEM; goto Error; } platform_set_drvdata(dev, info); /* * Tell the MTD layer we're not 1:1 mapped so that it does * not attempt to do a direct access on us. */ info->map.phys = NO_XIP; info->map.size = resource_size(dev->resource); /* * We only support 16-bit accesses for now. If and when * any board use 8-bit access, we'll fixup the driver to * handle that. */ info->map.bankwidth = 2; info->map.name = dev_name(&dev->dev); info->map.read = ixp4xx_read16; info->map.write = ixp4xx_probe_write16; info->map.copy_from = ixp4xx_copy_from; info->map.virt = devm_ioremap_resource(&dev->dev, dev->resource); if (IS_ERR(info->map.virt)) { err = PTR_ERR(info->map.virt); goto Error; } info->mtd = do_map_probe(plat->map_name, &info->map); if (!info->mtd) { printk(KERN_ERR "IXP4XXFlash: map_probe failed\n"); err = -ENXIO; goto Error; } info->mtd->owner = THIS_MODULE; /* Use the fast version */ info->map.write = ixp4xx_write16; err = mtd_device_parse_register(info->mtd, probes, &ppdata, plat->parts, plat->nr_parts); if (err) { printk(KERN_ERR "Could not parse partitions\n"); goto Error; } return 0; Error: ixp4xx_flash_remove(dev); return err; } static struct platform_driver ixp4xx_flash_driver = { .probe = ixp4xx_flash_probe, .remove = ixp4xx_flash_remove, .driver = { .name = "IXP4XX-Flash", .owner = THIS_MODULE, }, }; module_platform_driver(ixp4xx_flash_driver); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("MTD map driver for Intel IXP4xx systems"); MODULE_AUTHOR("Deepak Saxena"); MODULE_ALIAS("platform:IXP4XX-Flash");
static int axp20x_regulator_probe(struct platform_device *pdev) { struct regulator_dev *rdev; struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent); const struct regulator_desc *regulators; struct regulator_config config = { .dev = pdev->dev.parent, .regmap = axp20x->regmap, .driver_data = axp20x, }; int ret, i, nregulators; u32 workmode; const char *dcdc1_name = axp22x_regulators[AXP22X_DCDC1].name; const char *dcdc5_name = axp22x_regulators[AXP22X_DCDC5].name; bool drivevbus = false; switch (axp20x->variant) { case AXP202_ID: case AXP209_ID: regulators = axp20x_regulators; nregulators = AXP20X_REG_ID_MAX; break; case AXP221_ID: case AXP223_ID: regulators = axp22x_regulators; nregulators = AXP22X_REG_ID_MAX; drivevbus = of_property_read_bool(pdev->dev.parent->of_node, "x-powers,drive-vbus-en"); break; case AXP809_ID: regulators = axp809_regulators; nregulators = AXP809_REG_ID_MAX; break; default: dev_err(&pdev->dev, "Unsupported AXP variant: %ld\n", axp20x->variant); return -EINVAL; } /* This only sets the dcdc freq. Ignore any errors */ axp20x_regulator_parse_dt(pdev); for (i = 0; i < nregulators; i++) { const struct regulator_desc *desc = ®ulators[i]; struct regulator_desc *new_desc; /* * Regulators DC1SW and DC5LDO are connected internally, * so we have to handle their supply names separately. * * We always register the regulators in proper sequence, * so the supply names are correctly read. See the last * part of this loop to see where we save the DT defined * name. */ if ((regulators == axp22x_regulators && i == AXP22X_DC1SW) || (regulators == axp809_regulators && i == AXP809_DC1SW)) { new_desc = devm_kzalloc(&pdev->dev, sizeof(*desc), GFP_KERNEL); *new_desc = regulators[i]; new_desc->supply_name = dcdc1_name; desc = new_desc; } if ((regulators == axp22x_regulators && i == AXP22X_DC5LDO) || (regulators == axp809_regulators && i == AXP809_DC5LDO)) { new_desc = devm_kzalloc(&pdev->dev, sizeof(*desc), GFP_KERNEL); *new_desc = regulators[i]; new_desc->supply_name = dcdc5_name; desc = new_desc; } rdev = devm_regulator_register(&pdev->dev, desc, &config); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "Failed to register %s\n", regulators[i].name); return PTR_ERR(rdev); } ret = of_property_read_u32(rdev->dev.of_node, "x-powers,dcdc-workmode", &workmode); if (!ret) { if (axp20x_set_dcdc_workmode(rdev, i, workmode)) dev_err(&pdev->dev, "Failed to set workmode on %s\n", rdev->desc->name); } /* * Save AXP22X DCDC1 / DCDC5 regulator names for later. */ if ((regulators == axp22x_regulators && i == AXP22X_DCDC1) || (regulators == axp809_regulators && i == AXP809_DCDC1)) of_property_read_string(rdev->dev.of_node, "regulator-name", &dcdc1_name); if ((regulators == axp22x_regulators && i == AXP22X_DCDC5) || (regulators == axp809_regulators && i == AXP809_DCDC5)) of_property_read_string(rdev->dev.of_node, "regulator-name", &dcdc5_name); } if (drivevbus) { /* Change N_VBUSEN sense pin to DRIVEVBUS output pin */ regmap_update_bits(axp20x->regmap, AXP20X_OVER_TMP, AXP22X_MISC_N_VBUSEN_FUNC, 0); rdev = devm_regulator_register(&pdev->dev, &axp22x_drivevbus_regulator, &config); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "Failed to register drivevbus\n"); return PTR_ERR(rdev); } } return 0; } static struct platform_driver axp20x_regulator_driver = { .probe = axp20x_regulator_probe, .driver = { .name = "axp20x-regulator", }, }; module_platform_driver(axp20x_regulator_driver); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Carlo Caione <*****@*****.**>"); MODULE_DESCRIPTION("Regulator Driver for AXP20X PMIC"); MODULE_ALIAS("platform:axp20x-regulator");
static int __devinit pmic8xxx_kp_probe(struct platform_device *pdev) { const struct pm8xxx_keypad_platform_data *pdata = dev_get_platdata(&pdev->dev); const struct matrix_keymap_data *keymap_data; struct pmic8xxx_kp *kp; int rc; u8 ctrl_val; struct device *sec_key; struct pm_gpio kypd_drv = { .direction = PM_GPIO_DIR_OUT, .output_buffer = PM_GPIO_OUT_BUF_OPEN_DRAIN, .output_value = 0, .pull = PM_GPIO_PULL_NO, .vin_sel = PM_GPIO_VIN_S4, .out_strength = PM_GPIO_STRENGTH_LOW, .function = PM_GPIO_FUNC_1, .inv_int_pol = 1, }; struct pm_gpio kypd_sns = { .direction = PM_GPIO_DIR_IN, .pull = PM_GPIO_PULL_UP_31P5, .vin_sel = PM_GPIO_VIN_S4, .out_strength = PM_GPIO_STRENGTH_NO, .function = PM_GPIO_FUNC_NORMAL, .inv_int_pol = 1, }; if (!pdata || !pdata->num_cols || !pdata->num_rows || pdata->num_cols > PM8XXX_MAX_COLS || pdata->num_rows > PM8XXX_MAX_ROWS || pdata->num_cols < PM8XXX_MIN_COLS) { dev_err(&pdev->dev, "invalid platform data\n"); return -EINVAL; } if (!pdata->scan_delay_ms || pdata->scan_delay_ms > MAX_SCAN_DELAY || pdata->scan_delay_ms < MIN_SCAN_DELAY || !is_power_of_2(pdata->scan_delay_ms)) { dev_err(&pdev->dev, "invalid keypad scan time supplied\n"); return -EINVAL; } if (!pdata->row_hold_ns || pdata->row_hold_ns > MAX_ROW_HOLD_DELAY || pdata->row_hold_ns < MIN_ROW_HOLD_DELAY || ((pdata->row_hold_ns % MIN_ROW_HOLD_DELAY) != 0)) { dev_err(&pdev->dev, "invalid keypad row hold time supplied\n"); return -EINVAL; } if (!pdata->debounce_ms || ((pdata->debounce_ms % 5) != 0) || pdata->debounce_ms > MAX_DEBOUNCE_TIME || pdata->debounce_ms < MIN_DEBOUNCE_TIME) { dev_err(&pdev->dev, "invalid debounce time supplied\n"); return -EINVAL; } keymap_data = pdata->keymap_data; if (!keymap_data) { dev_err(&pdev->dev, "no keymap data supplied\n"); return -EINVAL; } kp = kzalloc(sizeof(*kp), GFP_KERNEL); if (!kp) return -ENOMEM; platform_set_drvdata(pdev, kp); kp->pdata = pdata; kp->dev = &pdev->dev; kp->input = input_allocate_device(); if (!kp->input) { dev_err(&pdev->dev, "unable to allocate input device\n"); rc = -ENOMEM; goto err_alloc_device; } kp->key_sense_irq = platform_get_irq(pdev, 0); if (kp->key_sense_irq < 0) { dev_err(&pdev->dev, "unable to get keypad sense irq\n"); rc = -ENXIO; goto err_get_irq; } kp->key_stuck_irq = platform_get_irq(pdev, 1); if (kp->key_stuck_irq < 0) { dev_err(&pdev->dev, "unable to get keypad stuck irq\n"); rc = -ENXIO; goto err_get_irq; } kp->input->name = pdata->input_name ? : "PMIC8XXX keypad"; kp->input->phys = pdata->input_phys_device ? : "pmic8xxx_keypad/input0"; kp->input->dev.parent = &pdev->dev; kp->input->id.bustype = BUS_I2C; kp->input->id.version = 0x0001; kp->input->id.product = 0x0001; kp->input->id.vendor = 0x0001; kp->input->evbit[0] = BIT_MASK(EV_KEY); if (pdata->rep) __set_bit(EV_REP, kp->input->evbit); kp->input->keycode = kp->keycodes; kp->input->keycodemax = PM8XXX_MATRIX_MAX_SIZE; kp->input->keycodesize = sizeof(kp->keycodes); kp->input->open = pmic8xxx_kp_open; kp->input->close = pmic8xxx_kp_close; matrix_keypad_build_keymap(keymap_data, PM8XXX_ROW_SHIFT, kp->input->keycode, kp->input->keybit); get_volumekey_matrix(keymap_data, &volup_matrix, &voldown_matrix); input_set_capability(kp->input, EV_MSC, MSC_SCAN); input_set_drvdata(kp->input, kp); /* initialize keypad state */ memset(kp->keystate, 0xff, sizeof(kp->keystate)); memset(kp->stuckstate, 0xff, sizeof(kp->stuckstate)); rc = pmic8xxx_kpd_init(kp); if (rc < 0) { dev_err(&pdev->dev, "unable to initialize keypad controller\n"); goto err_get_irq; } rc = pmic8xxx_kp_config_gpio(pdata->cols_gpio_start, pdata->num_cols, kp, &kypd_sns); if (rc < 0) { dev_err(&pdev->dev, "unable to configure keypad sense lines\n"); goto err_gpio_config; } rc = pmic8xxx_kp_config_gpio(pdata->rows_gpio_start, pdata->num_rows, kp, &kypd_drv); if (rc < 0) { dev_err(&pdev->dev, "unable to configure keypad drive lines\n"); goto err_gpio_config; } rc = request_any_context_irq(kp->key_sense_irq, pmic8xxx_kp_irq, IRQF_TRIGGER_RISING, "pmic-keypad", kp); if (rc < 0) { dev_err(&pdev->dev, "failed to request keypad sense irq\n"); goto err_get_irq; } rc = request_any_context_irq(kp->key_stuck_irq, pmic8xxx_kp_stuck_irq, IRQF_TRIGGER_RISING, "pmic-keypad-stuck", kp); if (rc < 0) { dev_err(&pdev->dev, "failed to request keypad stuck irq\n"); goto err_req_stuck_irq; } rc = pmic8xxx_kp_read_u8(kp, &ctrl_val, KEYP_CTRL); if (rc < 0) { dev_err(&pdev->dev, "failed to read KEYP_CTRL register\n"); goto err_pmic_reg_read; } rc = request_threaded_irq(MSM_GPIO_KEY_VOLUP_IRQ , NULL, pmic8058_volume_up_irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "vol_up", kp); if (rc < 0) { dev_err(&pdev->dev, "failed to request vol_up irq\n"); goto err_req_sense_irq; } rc = request_threaded_irq(MSM_GPIO_KEY_VOLDOWN_IRQ , NULL, pmic8058_volume_down_irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "vol_down", kp); if (rc < 0) { dev_err(&pdev->dev, "failed to request vol_down irq\n"); goto err_req_sense_irq; } kp->ctrl_reg = ctrl_val; #if defined CONFIG_MACH_VITAL2REFRESH gpio_tlmm_config(GPIO_CFG(MSM_HALL_IC, 1, GPIO_CFG_INPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA), GPIO_CFG_ENABLE); input_set_capability(kp->input, EV_SW, SW_LID); if (gpio_get_value(MSM_HALL_IC)) { input_report_switch(kp->input, SW_LID, 1); } else { input_report_switch(kp->input, SW_LID, 0); } input_sync(kp->input); printk(KERN_INFO "[input_report_switch] slide_int - !gpio_hall_ic %s\n", gpio_get_value(MSM_HALL_IC) == 0 ? "OPEN" : "CLOSE"); rc = request_threaded_irq(MSM_GPIO_TO_INT(MSM_HALL_IC), NULL, hall_ic_irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "hall_ic", kp); if (rc < 0) { dev_err(&pdev->dev, "failed to request hall_ic irq\n"); goto err_hall_ic_irq; } #endif rc = input_register_device(kp->input); if (rc < 0) { dev_err(&pdev->dev, "unable to register keypad input device\n"); goto err_pmic_reg_read; } sec_key = device_create(sec_class, NULL, 0, NULL, "sec_key"); if (IS_ERR(sec_key)) pr_err("Failed to create device(sec_key)!\n"); rc = device_create_file(sec_key, &dev_attr_sec_key_pressed); if (rc) { pr_err("Failed to create device file - pressed(%s), err(%d)!\n", dev_attr_sec_key_pressed.attr.name, rc); } dev_set_drvdata(sec_key, kp); device_init_wakeup(&pdev->dev, pdata->wakeup); return 0; err_pmic_reg_read: free_irq(kp->key_stuck_irq, kp); err_req_stuck_irq: free_irq(kp->key_sense_irq, kp); #if defined CONFIG_MACH_VITAL2REFRESH err_hall_ic_irq: #endif err_req_sense_irq: err_gpio_config: err_get_irq: input_free_device(kp->input); err_alloc_device: platform_set_drvdata(pdev, NULL); kfree(kp); return rc; } static int __devexit pmic8xxx_kp_remove(struct platform_device *pdev) { struct pmic8xxx_kp *kp = platform_get_drvdata(pdev); device_init_wakeup(&pdev->dev, 0); free_irq(kp->key_stuck_irq, kp); free_irq(kp->key_sense_irq, kp); input_unregister_device(kp->input); kfree(kp); platform_set_drvdata(pdev, NULL); return 0; } #ifdef CONFIG_PM_SLEEP static int pmic8xxx_kp_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct pmic8xxx_kp *kp = platform_get_drvdata(pdev); struct input_dev *input_dev = kp->input; if (device_may_wakeup(dev)) { enable_irq_wake(kp->key_sense_irq); } else { mutex_lock(&input_dev->mutex); #if defined CONFIG_MACH_VITAL2REFRESH enable_irq_wake(MSM_GPIO_TO_INT(MSM_HALL_IC)); /* to wakeup in case of sleep */ #endif if (input_dev->users) pmic8xxx_kp_disable(kp); mutex_unlock(&input_dev->mutex); } return 0; } static int pmic8xxx_kp_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct pmic8xxx_kp *kp = platform_get_drvdata(pdev); struct input_dev *input_dev = kp->input; if (device_may_wakeup(dev)) { disable_irq_wake(kp->key_sense_irq); } else { mutex_lock(&input_dev->mutex); #if defined CONFIG_MACH_VITAL2REFRESH disable_irq_wake(MSM_GPIO_TO_INT(MSM_HALL_IC)); /* to match irq pair */ #endif if (input_dev->users) pmic8xxx_kp_enable(kp); mutex_unlock(&input_dev->mutex); } return 0; } #endif static SIMPLE_DEV_PM_OPS(pm8xxx_kp_pm_ops, pmic8xxx_kp_suspend, pmic8xxx_kp_resume); static struct platform_driver pmic8xxx_kp_driver = { .probe = pmic8xxx_kp_probe, .remove = __devexit_p(pmic8xxx_kp_remove), .driver = { .name = PM8XXX_KEYPAD_DEV_NAME, .owner = THIS_MODULE, .pm = &pm8xxx_kp_pm_ops, }, }; static int __init pmic8xxx_kp_init(void) { return platform_driver_register(&pmic8xxx_kp_driver); } module_init(pmic8xxx_kp_init); static void __exit pmic8xxx_kp_exit(void) { platform_driver_unregister(&pmic8xxx_kp_driver); } module_exit(pmic8xxx_kp_exit); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("PMIC8XXX keypad driver"); MODULE_VERSION("1.0"); MODULE_ALIAS("platform:pmic8xxx_keypad"); MODULE_AUTHOR("Trilok Soni <*****@*****.**>");
/* * sysfs hook function */ static ssize_t madc_read(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct twl4030_madc_request req = { .channels = 1 << attr->index, .method = TWL4030_MADC_SW2, .type = TWL4030_MADC_WAIT, }; long val; val = twl4030_madc_conversion(&req); if (val < 0) return val; return sprintf(buf, "%d\n", req.rbuf[attr->index]); } /* sysfs nodes to read individual channels from user side */ static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, madc_read, NULL, 0); static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, madc_read, NULL, 1); static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, madc_read, NULL, 2); static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, madc_read, NULL, 3); static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, madc_read, NULL, 4); static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, madc_read, NULL, 5); static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, madc_read, NULL, 6); static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, madc_read, NULL, 7); static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, madc_read, NULL, 8); static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, madc_read, NULL, 9); static SENSOR_DEVICE_ATTR(curr10_input, S_IRUGO, madc_read, NULL, 10); static SENSOR_DEVICE_ATTR(in11_input, S_IRUGO, madc_read, NULL, 11); static SENSOR_DEVICE_ATTR(in12_input, S_IRUGO, madc_read, NULL, 12); static SENSOR_DEVICE_ATTR(in15_input, S_IRUGO, madc_read, NULL, 15); static struct attribute *twl4030_madc_attrs[] = { &sensor_dev_attr_in0_input.dev_attr.attr, &sensor_dev_attr_temp1_input.dev_attr.attr, &sensor_dev_attr_in2_input.dev_attr.attr, &sensor_dev_attr_in3_input.dev_attr.attr, &sensor_dev_attr_in4_input.dev_attr.attr, &sensor_dev_attr_in5_input.dev_attr.attr, &sensor_dev_attr_in6_input.dev_attr.attr, &sensor_dev_attr_in7_input.dev_attr.attr, &sensor_dev_attr_in8_input.dev_attr.attr, &sensor_dev_attr_in9_input.dev_attr.attr, &sensor_dev_attr_curr10_input.dev_attr.attr, &sensor_dev_attr_in11_input.dev_attr.attr, &sensor_dev_attr_in12_input.dev_attr.attr, &sensor_dev_attr_in15_input.dev_attr.attr, NULL }; ATTRIBUTE_GROUPS(twl4030_madc); static int twl4030_madc_hwmon_probe(struct platform_device *pdev) { struct device *hwmon; hwmon = devm_hwmon_device_register_with_groups(&pdev->dev, "twl4030_madc", NULL, twl4030_madc_groups); return PTR_ERR_OR_ZERO(hwmon); } static struct platform_driver twl4030_madc_hwmon_driver = { .probe = twl4030_madc_hwmon_probe, .driver = { .name = "twl4030_madc_hwmon", .owner = THIS_MODULE, }, }; module_platform_driver(twl4030_madc_hwmon_driver); MODULE_DESCRIPTION("TWL4030 ADC Hwmon driver"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("J Keerthy"); MODULE_ALIAS("platform:twl4030_madc_hwmon");
static int micro_bl_update_status(struct backlight_device *bd) { struct ipaq_micro *micro = dev_get_drvdata(&bd->dev); int intensity = bd->props.brightness; struct ipaq_micro_msg msg = { .id = MSG_BACKLIGHT, .tx_len = 3, }; if (bd->props.power != FB_BLANK_UNBLANK) intensity = 0; if (bd->props.state & (BL_CORE_FBBLANK | BL_CORE_SUSPENDED)) intensity = 0; /* * Message format: * Byte 0: backlight instance (usually 1) * Byte 1: on/off * Byte 2: intensity, 0-255 */ msg.tx_data[0] = 0x01; msg.tx_data[1] = intensity > 0 ? 1 : 0; msg.tx_data[2] = intensity; return ipaq_micro_tx_msg_sync(micro, &msg); } static const struct backlight_ops micro_bl_ops = { .options = BL_CORE_SUSPENDRESUME, .update_status = micro_bl_update_status, }; static struct backlight_properties micro_bl_props = { .type = BACKLIGHT_RAW, .max_brightness = 255, .power = FB_BLANK_UNBLANK, .brightness = 64, }; static int micro_backlight_probe(struct platform_device *pdev) { struct backlight_device *bd; struct ipaq_micro *micro = dev_get_drvdata(pdev->dev.parent); bd = devm_backlight_device_register(&pdev->dev, "ipaq-micro-backlight", &pdev->dev, micro, µ_bl_ops, µ_bl_props); if (IS_ERR(bd)) return PTR_ERR(bd); platform_set_drvdata(pdev, bd); backlight_update_status(bd); return 0; } static struct platform_driver micro_backlight_device_driver = { .driver = { .name = "ipaq-micro-backlight", }, .probe = micro_backlight_probe, }; module_platform_driver(micro_backlight_device_driver); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("driver for iPAQ Atmel micro backlight"); MODULE_ALIAS("platform:ipaq-micro-backlight");
static int micro_leds_brightness_set(struct led_classdev *led_cdev, enum led_brightness value) { struct ipaq_micro *micro = dev_get_drvdata(led_cdev->dev->parent->parent); /* * In this message: * Byte 0 = LED color: 0 = yellow, 1 = green * yellow LED is always ~30 blinks per minute * Byte 1 = duration (flags?) appears to be ignored * Byte 2 = green ontime in 1/10 sec (deciseconds) * 1 = 1/10 second * 0 = 256/10 second * Byte 3 = green offtime in 1/10 sec (deciseconds) * 1 = 1/10 second * 0 = 256/10 seconds */ struct ipaq_micro_msg msg = { .id = MSG_NOTIFY_LED, .tx_len = 4, }; msg.tx_data[0] = LED_GREEN; msg.tx_data[1] = 0; if (value) { msg.tx_data[2] = 0; /* Duty cycle 256 */ msg.tx_data[3] = 1; } else { msg.tx_data[2] = 1; msg.tx_data[3] = 0; /* Duty cycle 256 */ } return ipaq_micro_tx_msg_sync(micro, &msg); } /* Maximum duty cycle in ms 256/10 sec = 25600 ms */ #define IPAQ_LED_MAX_DUTY 25600 static int micro_leds_blink_set(struct led_classdev *led_cdev, unsigned long *delay_on, unsigned long *delay_off) { struct ipaq_micro *micro = dev_get_drvdata(led_cdev->dev->parent->parent); /* * In this message: * Byte 0 = LED color: 0 = yellow, 1 = green * yellow LED is always ~30 blinks per minute * Byte 1 = duration (flags?) appears to be ignored * Byte 2 = green ontime in 1/10 sec (deciseconds) * 1 = 1/10 second * 0 = 256/10 second * Byte 3 = green offtime in 1/10 sec (deciseconds) * 1 = 1/10 second * 0 = 256/10 seconds */ struct ipaq_micro_msg msg = { .id = MSG_NOTIFY_LED, .tx_len = 4, }; msg.tx_data[0] = LED_GREEN; if (*delay_on > IPAQ_LED_MAX_DUTY || *delay_off > IPAQ_LED_MAX_DUTY) return -EINVAL; if (*delay_on == 0 && *delay_off == 0) { *delay_on = 100; *delay_off = 100; } msg.tx_data[1] = 0; if (*delay_on >= IPAQ_LED_MAX_DUTY) msg.tx_data[2] = 0; else msg.tx_data[2] = (u8) DIV_ROUND_CLOSEST(*delay_on, 100); if (*delay_off >= IPAQ_LED_MAX_DUTY) msg.tx_data[3] = 0; else msg.tx_data[3] = (u8) DIV_ROUND_CLOSEST(*delay_off, 100); return ipaq_micro_tx_msg_sync(micro, &msg); } static struct led_classdev micro_led = { .name = "led-ipaq-micro", .brightness_set_blocking = micro_leds_brightness_set, .blink_set = micro_leds_blink_set, .flags = LED_CORE_SUSPENDRESUME, }; static int micro_leds_probe(struct platform_device *pdev) { int ret; ret = devm_led_classdev_register(&pdev->dev, µ_led); if (ret) { dev_err(&pdev->dev, "registering led failed: %d\n", ret); return ret; } dev_info(&pdev->dev, "iPAQ micro notification LED driver\n"); return 0; } static struct platform_driver micro_leds_device_driver = { .driver = { .name = "ipaq-micro-leds", }, .probe = micro_leds_probe, }; module_platform_driver(micro_leds_device_driver); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("driver for iPAQ Atmel micro leds"); MODULE_ALIAS("platform:ipaq-micro-leds");
static int m48t59_rtc_probe(struct platform_device *pdev) { struct m48t59_plat_data *pdata = dev_get_platdata(&pdev->dev); struct m48t59_private *m48t59 = NULL; struct resource *res; int ret = -ENOMEM; char *name; const struct rtc_class_ops *ops; struct nvmem_config nvmem_cfg = { .name = "m48t59-", .word_size = 1, .stride = 1, .reg_read = m48t59_nvram_read, .reg_write = m48t59_nvram_write, .priv = pdev, }; /* This chip could be memory-mapped or I/O-mapped */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { res = platform_get_resource(pdev, IORESOURCE_IO, 0); if (!res) return -EINVAL; } if (res->flags & IORESOURCE_IO) { /* If we are I/O-mapped, the platform should provide * the operations accessing chip registers. */ if (!pdata || !pdata->write_byte || !pdata->read_byte) return -EINVAL; } else if (res->flags & IORESOURCE_MEM) { /* we are memory-mapped */ if (!pdata) { pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) return -ENOMEM; /* Ensure we only kmalloc platform data once */ pdev->dev.platform_data = pdata; } if (!pdata->type) pdata->type = M48T59RTC_TYPE_M48T59; /* Try to use the generic memory read/write ops */ if (!pdata->write_byte) pdata->write_byte = m48t59_mem_writeb; if (!pdata->read_byte) pdata->read_byte = m48t59_mem_readb; } m48t59 = devm_kzalloc(&pdev->dev, sizeof(*m48t59), GFP_KERNEL); if (!m48t59) return -ENOMEM; m48t59->ioaddr = pdata->ioaddr; if (!m48t59->ioaddr) { /* ioaddr not mapped externally */ m48t59->ioaddr = devm_ioremap(&pdev->dev, res->start, resource_size(res)); if (!m48t59->ioaddr) return ret; } /* Try to get irq number. We also can work in * the mode without IRQ. */ m48t59->irq = platform_get_irq(pdev, 0); if (m48t59->irq <= 0) m48t59->irq = NO_IRQ; if (m48t59->irq != NO_IRQ) { ret = devm_request_irq(&pdev->dev, m48t59->irq, m48t59_rtc_interrupt, IRQF_SHARED, "rtc-m48t59", &pdev->dev); if (ret) return ret; } switch (pdata->type) { case M48T59RTC_TYPE_M48T59: name = "m48t59"; ops = &m48t59_rtc_ops; pdata->offset = 0x1ff0; break; case M48T59RTC_TYPE_M48T02: name = "m48t02"; ops = &m48t02_rtc_ops; pdata->offset = 0x7f0; break; case M48T59RTC_TYPE_M48T08: name = "m48t08"; ops = &m48t02_rtc_ops; pdata->offset = 0x1ff0; break; default: dev_err(&pdev->dev, "Unknown RTC type\n"); return -ENODEV; } spin_lock_init(&m48t59->lock); platform_set_drvdata(pdev, m48t59); m48t59->rtc = devm_rtc_allocate_device(&pdev->dev); if (IS_ERR(m48t59->rtc)) return PTR_ERR(m48t59->rtc); m48t59->rtc->nvram_old_abi = true; m48t59->rtc->ops = ops; nvmem_cfg.size = pdata->offset; ret = rtc_nvmem_register(m48t59->rtc, &nvmem_cfg); if (ret) return ret; ret = rtc_register_device(m48t59->rtc); if (ret) return ret; return 0; } /* work with hotplug and coldplug */ MODULE_ALIAS("platform:rtc-m48t59"); static struct platform_driver m48t59_rtc_driver = { .driver = { .name = "rtc-m48t59", }, .probe = m48t59_rtc_probe, };
static int hvfb_probe(struct hv_device *hdev, const struct hv_vmbus_device_id *dev_id) { struct fb_info *info; struct hvfb_par *par; int ret; info = framebuffer_alloc(sizeof(struct hvfb_par), &hdev->device); if (!info) { pr_err("No memory for framebuffer info\n"); return -ENOMEM; } par = info->par; par->info = info; par->fb_ready = false; init_completion(&par->wait); INIT_DELAYED_WORK(&par->dwork, hvfb_update_work); /* Connect to VSP */ hv_set_drvdata(hdev, info); ret = synthvid_connect_vsp(hdev); if (ret) { pr_err("Unable to connect to VSP\n"); goto error1; } ret = hvfb_getmem(info); if (ret) { pr_err("No memory for framebuffer\n"); goto error2; } hvfb_get_option(info); pr_info("Screen resolution: %dx%d, Color depth: %d\n", screen_width, screen_height, screen_depth); /* Set up fb_info */ info->flags = FBINFO_DEFAULT; info->var.xres_virtual = info->var.xres = screen_width; info->var.yres_virtual = info->var.yres = screen_height; info->var.bits_per_pixel = screen_depth; if (info->var.bits_per_pixel == 16) { info->var.red = (struct fb_bitfield){11, 5, 0}; info->var.green = (struct fb_bitfield){5, 6, 0}; info->var.blue = (struct fb_bitfield){0, 5, 0}; info->var.transp = (struct fb_bitfield){0, 0, 0}; } else { info->var.red = (struct fb_bitfield){16, 8, 0}; info->var.green = (struct fb_bitfield){8, 8, 0}; info->var.blue = (struct fb_bitfield){0, 8, 0}; info->var.transp = (struct fb_bitfield){24, 8, 0}; } info->var.activate = FB_ACTIVATE_NOW; info->var.height = -1; info->var.width = -1; info->var.vmode = FB_VMODE_NONINTERLACED; strcpy(info->fix.id, KBUILD_MODNAME); info->fix.type = FB_TYPE_PACKED_PIXELS; info->fix.visual = FB_VISUAL_TRUECOLOR; info->fix.line_length = screen_width * screen_depth / 8; info->fix.accel = FB_ACCEL_NONE; info->fbops = &hvfb_ops; info->pseudo_palette = par->pseudo_palette; /* Send config to host */ ret = synthvid_send_config(hdev); if (ret) goto error; ret = register_framebuffer(info); if (ret) { pr_err("Unable to register framebuffer\n"); goto error; } par->fb_ready = true; return 0; error: hvfb_putmem(info); error2: vmbus_close(hdev->channel); error1: cancel_delayed_work_sync(&par->dwork); hv_set_drvdata(hdev, NULL); framebuffer_release(info); return ret; } static int hvfb_remove(struct hv_device *hdev) { struct fb_info *info = hv_get_drvdata(hdev); struct hvfb_par *par = info->par; par->update = false; par->fb_ready = false; unregister_framebuffer(info); cancel_delayed_work_sync(&par->dwork); vmbus_close(hdev->channel); hv_set_drvdata(hdev, NULL); hvfb_putmem(info); framebuffer_release(info); return 0; } static DEFINE_PCI_DEVICE_TABLE(pci_stub_id_table) = { { .vendor = PCI_VENDOR_ID_MICROSOFT, .device = PCI_DEVICE_ID_HYPERV_VIDEO, }, { /* end of list */ } }; static const struct hv_vmbus_device_id id_table[] = { /* Synthetic Video Device GUID */ {HV_SYNTHVID_GUID}, {} }; MODULE_DEVICE_TABLE(pci, pci_stub_id_table); MODULE_DEVICE_TABLE(vmbus, id_table); static struct hv_driver hvfb_drv = { .name = KBUILD_MODNAME, .id_table = id_table, .probe = hvfb_probe, .remove = hvfb_remove, }; static int hvfb_pci_stub_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { return 0; } static void hvfb_pci_stub_remove(struct pci_dev *pdev) { } static struct pci_driver hvfb_pci_stub_driver = { .name = KBUILD_MODNAME, .id_table = pci_stub_id_table, .probe = hvfb_pci_stub_probe, .remove = hvfb_pci_stub_remove, }; static int __init hvfb_drv_init(void) { int ret; ret = vmbus_driver_register(&hvfb_drv); if (ret != 0) return ret; ret = pci_register_driver(&hvfb_pci_stub_driver); if (ret != 0) { vmbus_driver_unregister(&hvfb_drv); return ret; } return 0; } static void __exit hvfb_drv_exit(void) { pci_unregister_driver(&hvfb_pci_stub_driver); vmbus_driver_unregister(&hvfb_drv); } module_init(hvfb_drv_init); module_exit(hvfb_drv_exit); MODULE_LICENSE("GPL"); MODULE_VERSION(HV_DRV_VERSION); MODULE_DESCRIPTION("Microsoft Hyper-V Synthetic Video Frame Buffer Driver"); MODULE_ALIAS("vmbus:02780ada77e3ac4a8e770558eb1073f8");
/* CHAOS functions */ static void xt_chaos_total(struct sk_buff *skb, const struct xt_action_param *par) { const struct xt_chaos_tginfo *info = par->targinfo; const struct iphdr *iph = ip_hdr(skb); const int thoff = 4 * iph->ihl; const int fragoff = ntohs(iph->frag_off) & IP_OFFSET; typeof(xt_tarpit) destiny; bool ret; #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 22) int hotdrop = false; #else bool hotdrop = false; #endif #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27) ret = xm_tcp->match(skb, par->in, par->out, xm_tcp, &tcp_params, fragoff, thoff, &hotdrop); #elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 34) { struct xt_match_param local_par = { .in = par->in, .out = par->out, .match = xm_tcp, .matchinfo = &tcp_params, .fragoff = fragoff, .thoff = thoff, .hotdrop = &hotdrop, }; ret = xm_tcp->match(skb, &local_par); } #else { struct xt_action_param local_par; local_par.in = par->in, local_par.out = par->out, local_par.match = xm_tcp; local_par.matchinfo = &tcp_params; local_par.fragoff = fragoff; local_par.thoff = thoff; local_par.hotdrop = false; ret = xm_tcp->match(skb, &local_par); hotdrop = local_par.hotdrop; } #endif if (!ret || hotdrop || (unsigned int)net_random() > delude_percentage) return; destiny = (info->variant == XTCHAOS_TARPIT) ? xt_tarpit : xt_delude; #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18) destiny->target(&skb, par->in, par->out, par->hooknum, destiny, NULL, NULL); #elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23) destiny->target(&skb, par->in, par->out, par->hooknum, destiny, NULL); #elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27) destiny->target(skb, par->in, par->out, par->hooknum, destiny, NULL); #elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 34) { struct xt_target_param local_par = { .in = par->in, .out = par->out, .hooknum = par->hooknum, .target = destiny, .targinfo = par->targinfo, .family = par->family, }; destiny->target(skb, &local_par); } #else { struct xt_action_param local_par; local_par.in = par->in; local_par.out = par->out; local_par.hooknum = par->hooknum; local_par.target = destiny; local_par.targinfo = par->targinfo; local_par.family = par->family; destiny->target(skb, &local_par); } #endif } static unsigned int chaos_tg(struct sk_buff **pskb, const struct xt_action_param *par) { /* * Equivalent to: * -A chaos -m statistic --mode random --probability \ * $reject_percentage -j REJECT --reject-with host-unreach; * -A chaos -p tcp -m statistic --mode random --probability \ * $delude_percentage -j DELUDE; * -A chaos -j DROP; */ const struct xt_chaos_tginfo *info = par->targinfo; struct sk_buff *skb = *pskb; const struct iphdr *iph = ip_hdr(skb); if ((unsigned int)net_random() <= reject_percentage) { #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18) return xt_reject->target(pskb, par->in, par->out, par->hooknum, xt_reject, &reject_params, NULL); #elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23) return xt_reject->target(pskb, par->in, par->out, par->hooknum, xt_reject, &reject_params); #elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27) return xt_reject->target(skb, par->in, par->out, par->hooknum, xt_reject, &reject_params); #elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 34) struct xt_target_param local_par = { .in = par->in, .out = par->out, .hooknum = par->hooknum, .target = xt_reject, .targinfo = &reject_params, }; return xt_reject->target(skb, &local_par); #else struct xt_action_param local_par; local_par.in = par->in; local_par.out = par->out; local_par.hooknum = par->hooknum; local_par.target = xt_reject; local_par.targinfo = &reject_params; return xt_reject->target(skb, &local_par); #endif } /* TARPIT/DELUDE may not be called from the OUTPUT chain */ if (iph->protocol == IPPROTO_TCP && info->variant != XTCHAOS_NORMAL && par->hooknum != NF_INET_LOCAL_OUT) xt_chaos_total(skb, par); return NF_DROP; } static int chaos_tg_check(const struct xt_tgchk_param *par) { const struct xt_chaos_tginfo *info = par->targinfo; if (info->variant == XTCHAOS_DELUDE && !have_delude) { printk(KERN_WARNING PFX "Error: Cannot use --delude when " "DELUDE module not available\n"); return -EINVAL; } if (info->variant == XTCHAOS_TARPIT && !have_tarpit) { printk(KERN_WARNING PFX "Error: Cannot use --tarpit when " "TARPIT module not available\n"); return -EINVAL; } return 0; } static struct xt_target chaos_tg_reg = { .name = "CHAOS", .revision = 0, .family = NFPROTO_IPV4, .table = "filter", .hooks = (1 << NF_INET_LOCAL_IN) | (1 << NF_INET_FORWARD) | (1 << NF_INET_LOCAL_OUT), .target = chaos_tg, .checkentry = chaos_tg_check, .targetsize = sizeof(struct xt_chaos_tginfo), .me = THIS_MODULE, }; static int __init chaos_tg_init(void) { int ret = -EINVAL; xm_tcp = xt_request_find_match(NFPROTO_IPV4, "tcp", 0); if (xm_tcp == NULL) { printk(KERN_WARNING PFX "Error: Could not find or load " "\"tcp\" match\n"); return -EINVAL; } xt_reject = xt_request_find_target(NFPROTO_IPV4, "REJECT", 0); if (xt_reject == NULL) { printk(KERN_WARNING PFX "Error: Could not find or load " "\"REJECT\" target\n"); goto out2; } xt_tarpit = xt_request_find_target(NFPROTO_IPV4, "TARPIT", 0); have_tarpit = xt_tarpit != NULL; if (!have_tarpit) printk(KERN_WARNING PFX "Warning: Could not find or load " "\"TARPIT\" target\n"); xt_delude = xt_request_find_target(NFPROTO_IPV4, "DELUDE", 0); have_delude = xt_delude != NULL; if (!have_delude) printk(KERN_WARNING PFX "Warning: Could not find or load " "\"DELUDE\" target\n"); if ((ret = xt_register_target(&chaos_tg_reg)) != 0) { printk(KERN_WARNING PFX "xt_register_target returned " "error %d\n", ret); goto out3; } return 0; out3: if (have_delude) module_put(xt_delude->me); if (have_tarpit) module_put(xt_tarpit->me); module_put(xt_reject->me); out2: module_put(xm_tcp->me); return ret; } static void __exit chaos_tg_exit(void) { xt_unregister_target(&chaos_tg_reg); module_put(xm_tcp->me); module_put(xt_reject->me); if (have_delude) module_put(xt_delude->me); if (have_tarpit) module_put(xt_tarpit->me); } module_init(chaos_tg_init); module_exit(chaos_tg_exit); MODULE_DESCRIPTION("Xtables: Network scan slowdown with non-deterministic results"); MODULE_AUTHOR("Jan Engelhardt <*****@*****.**>"); MODULE_LICENSE("GPL"); MODULE_ALIAS("ipt_CHAOS");