/* * reg_dev() - registers a device & initializes the structure components */ static int reg_dev(int base_addr, int minor, int irq) { int err; err = register_chrdev_region(MKDEV(major, minor), 1, MODULE_NAME); if (err != 0) { printk(LOG_LEVEL "ERROR registering chrdev region: error %d\n", err); goto out_reg_chrdev; } if ((request_irq(irq, uart_interrupt_handler, IRQF_SHARED, MODULE_NAME, &devs[minor])) != 0) { printk(LOG_LEVEL "ERROR requesting irq: error %d\n", err); goto out_req_irq; } if (!request_region(base_addr, COM_NR_PORTS, MODULE_NAME)) { printk(LOG_LEVEL "ERROR registering region\n"); err = -ENODEV; goto out_req_reg; } atomic_set(&devs[minor].access, 1); devs[minor].base_addr = base_addr; INIT_KFIFO(devs[minor].read_buffer); spin_lock_init(&devs[minor].read_lock); init_waitqueue_head(&devs[minor].read_wq); INIT_KFIFO(devs[minor].write_buffer); spin_lock_init(&devs[minor].write_lock); init_waitqueue_head(&devs[minor].write_wq); outb(0x0, base_addr + IER); outb(0x1, base_addr + IER); outb(0x0, base_addr + FCR); outb(0x7, base_addr + FCR); outb(0xb, base_addr + MCR); cdev_init(&devs[minor].cdev, &uart_fops); cdev_add(&devs[minor].cdev, MKDEV(major, minor), 1); return 0; out_reg_chrdev: return err; out_req_reg: free_irq(irq, &devs[minor]); out_req_irq: unregister_chrdev_region(MKDEV(major, minor), 1); return err; }
static int __init example_init(void) { #ifdef DYNAMIC int ret; ret = kfifo_alloc(&test, FIFO_SIZE, GFP_KERNEL); if (ret) { printk(KERN_ERR "error kfifo_alloc\n"); return ret; } #else INIT_KFIFO(test); #endif if (testfunc() < 0) { #ifdef DYNAMIC kfifo_free(&test); #endif return -EIO; } if (proc_create(PROC_FIFO, 0, NULL, &fifo_fops) == NULL) { #ifdef DYNAMIC kfifo_free(&test); #endif return -ENOMEM; } return 0; }
static int kgdb_nmi_tty_install(struct tty_driver *drv, struct tty_struct *tty) { struct kgdb_nmi_tty_priv *priv; int ret; priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; INIT_KFIFO(priv->fifo); setup_timer(&priv->timer, kgdb_nmi_tty_receiver, (unsigned long)priv); tty_port_init(&priv->port); priv->port.ops = &kgdb_nmi_tty_port_ops; tty->driver_data = priv; ret = tty_port_install(&priv->port, drv, tty); if (ret) { pr_err("%s: can't install tty port: %d\n", __func__, ret); goto err; } return 0; err: tty_port_destroy(&priv->port); kfree(priv); return ret; }
static int uart16550_open(struct inode *inode, struct file *file){ struct device_data *devicedata; devicedata=kmalloc(sizeof(struct device_data), GFP_KERNEL); if(!devicedata){ return -1; } file -> private_data=devicedata; INIT_KFIFO(devicedata->data_from_user); INIT_KFIFO(devicedata->data_from_device); devicedata -> task_user_push_data = kmalloc(sizeof(struct task_struct*),GFP_KERNEL); devicedata -> task_user_get_data = kmalloc(sizeof(struct task_struct*),GFP_KERNEL); *(devicedata -> task_user_push_data) = NULL; *(devicedata -> task_user_get_data) = NULL; return 0; }
/* Module initialization and release */ static int __init parrot_module_init(void) { int retval; dbg(""); /* First, see if we can dynamically allocate a major for our device */ parrot_major = register_chrdev(0, DEVICE_NAME, &fops); if (parrot_major < 0) { err("failed to register device: error %d\n", parrot_major); retval = parrot_major; goto failed_chrdevreg; } /* We can either tie our device to a bus (existing, or one that we create) * or use a "virtual" device class. For this example, we choose the latter */ parrot_class = class_create(THIS_MODULE, CLASS_NAME); if (IS_ERR(parrot_class)) { err("failed to register device class '%s'\n", CLASS_NAME); retval = PTR_ERR(parrot_class); goto failed_classreg; } /* With a class, the easiest way to instantiate a device is to call device_create() */ parrot_device = device_create(parrot_class, NULL, MKDEV(parrot_major, 0), NULL, CLASS_NAME "_" DEVICE_NAME); if (IS_ERR(parrot_device)) { err("failed to create device '%s_%s'\n", CLASS_NAME, DEVICE_NAME); retval = PTR_ERR(parrot_device); goto failed_devreg; } /* Now we can create the sysfs endpoints (don't care about errors). * dev_attr_fifo and dev_attr_reset come from the DEVICE_ATTR(...) earlier */ retval = device_create_file(parrot_device, &dev_attr_fifo); if (retval < 0) { warn("failed to create write /sys endpoint - continuing without\n"); } retval = device_create_file(parrot_device, &dev_attr_reset); if (retval < 0) { warn("failed to create reset /sys endpoint - continuing without\n"); } mutex_init(&parrot_device_mutex); /* This device uses a Kernel FIFO for its read operation */ INIT_KFIFO(parrot_msg_fifo); parrot_msg_idx_rd = parrot_msg_idx_wr = 0; return 0; failed_devreg: class_unregister(parrot_class); class_destroy(parrot_class); failed_classreg: unregister_chrdev(parrot_major, DEVICE_NAME); failed_chrdevreg: return -1; }
int __init initialise(void) { data1 = "procEntry"; data2 = "rwCount"; pfs = proc_create_data(file1, 0, NULL, &pfs_fops, data1); pfsCount = proc_create_data(file2, 0, NULL, &pfsCount_fops, data2); INIT_KFIFO(myfifo); if(pfs == NULL) { remove_proc_entry(file1,NULL); kfifo_free(&myfifo); printk(KERN_ALERT "Error : Couldn't initialise /proc/%s\n", file1); return -ENOMEM; } if(pfsCount == NULL) { remove_proc_entry(file2,NULL); printk(KERN_ALERT "Error : Couldn't initialise /proc/%s\n", file2); return -ENOMEM; } return 0; }
/***************************************************************************** Syntax: Init_FIFO_voice_rtp_buf (); Remarks: This Function Init FIFO buffers Return Value: Returns 1 on success and negative value on failure. Value Description -------------------------------------------------------------- = 1 Success =-1 Failure *******************************************************************************/ void Init_FIFO_voice_rtp_buf () { #ifdef DYNAMIC int ret; ret = kfifo_alloc(&test, FIFO_SIZE, GFP_KERNEL); if (ret) { printk("?error kfifo_alloc?\n"); return ret; } #else INIT_KFIFO(test); #endif /* if (testfunc() < 0) { #ifdef DYNAMIC kfifo_free(&test); #endif */ return -EIO; }
/* Main entry */ static int r592_probe(struct pci_dev *pdev, const struct pci_device_id *id) { int error = -ENOMEM; struct memstick_host *host; struct r592_device *dev; /* Allocate memory */ host = memstick_alloc_host(sizeof(struct r592_device), &pdev->dev); if (!host) goto error1; dev = memstick_priv(host); dev->host = host; dev->pci_dev = pdev; pci_set_drvdata(pdev, dev); /* pci initialization */ error = pci_enable_device(pdev); if (error) goto error2; pci_set_master(pdev); error = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); if (error) goto error3; error = pci_request_regions(pdev, DRV_NAME); if (error) goto error3; dev->mmio = pci_ioremap_bar(pdev, 0); if (!dev->mmio) goto error4; dev->irq = pdev->irq; spin_lock_init(&dev->irq_lock); spin_lock_init(&dev->io_thread_lock); init_completion(&dev->dma_done); INIT_KFIFO(dev->pio_fifo); setup_timer(&dev->detect_timer, r592_detect_timer, (long unsigned int)dev); /* Host initialization */ host->caps = MEMSTICK_CAP_PAR4; host->request = r592_submit_req; host->set_param = r592_set_param; r592_check_dma(dev); dev->io_thread = kthread_run(r592_process_thread, dev, "r592_io"); if (IS_ERR(dev->io_thread)) { error = PTR_ERR(dev->io_thread); goto error5; } /* This is just a precation, so don't fail */ dev->dummy_dma_page = pci_alloc_consistent(pdev, PAGE_SIZE, &dev->dummy_dma_page_physical_address); r592_stop_dma(dev , 0); if (request_irq(dev->irq, &r592_irq, IRQF_SHARED, DRV_NAME, dev)) goto error6; r592_update_card_detect(dev); if (memstick_add_host(host)) goto error7; message("driver successfully loaded"); return 0; error7: free_irq(dev->irq, dev); error6: if (dev->dummy_dma_page) pci_free_consistent(pdev, PAGE_SIZE, dev->dummy_dma_page, dev->dummy_dma_page_physical_address); kthread_stop(dev->io_thread); error5: iounmap(dev->mmio); error4: pci_release_regions(pdev); error3: pci_disable_device(pdev); error2: memstick_free_host(host); error1: return error; }
static int armada_drm_load(struct drm_device *dev, unsigned long flags) { const struct platform_device_id *id; const struct armada_variant *variant; struct armada_private *priv; struct resource *res[ARRAY_SIZE(priv->dcrtc)]; struct resource *mem = NULL; int ret, n, i; memset(res, 0, sizeof(res)); for (n = i = 0; ; n++) { struct resource *r = platform_get_resource(dev->platformdev, IORESOURCE_MEM, n); if (!r) break; /* Resources above 64K are graphics memory */ if (resource_size(r) > SZ_64K) mem = r; else if (i < ARRAY_SIZE(priv->dcrtc)) res[i++] = r; else return -EINVAL; } if (!mem) return -ENXIO; if (!devm_request_mem_region(dev->dev, mem->start, resource_size(mem), "armada-drm")) return -EBUSY; priv = devm_kzalloc(dev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) { DRM_ERROR("failed to allocate private\n"); return -ENOMEM; } platform_set_drvdata(dev->platformdev, dev); dev->dev_private = priv; /* Get the implementation specific driver data. */ id = platform_get_device_id(dev->platformdev); if (!id) return -ENXIO; variant = (const struct armada_variant *)id->driver_data; INIT_WORK(&priv->fb_unref_work, armada_drm_unref_work); INIT_KFIFO(priv->fb_unref); /* Mode setting support */ drm_mode_config_init(dev); dev->mode_config.min_width = 320; dev->mode_config.min_height = 200; /* * With vscale enabled, the maximum width is 1920 due to the * 1920 by 3 lines RAM */ dev->mode_config.max_width = 1920; dev->mode_config.max_height = 2048; dev->mode_config.preferred_depth = 24; dev->mode_config.funcs = &armada_drm_mode_config_funcs; drm_mm_init(&priv->linear, mem->start, resource_size(mem)); /* Create all LCD controllers */ for (n = 0; n < ARRAY_SIZE(priv->dcrtc); n++) { int irq; if (!res[n]) break; irq = platform_get_irq(dev->platformdev, n); if (irq < 0) goto err_kms; ret = armada_drm_crtc_create(dev, dev->dev, res[n], irq, variant, NULL); if (ret) goto err_kms; } if (is_componentized(dev->dev)) { ret = component_bind_all(dev->dev, dev); if (ret) goto err_kms; } else { #ifdef CONFIG_DRM_ARMADA_TDA1998X ret = armada_drm_connector_slave_create(dev, &tda19988_config); if (ret) goto err_kms; #endif } ret = drm_vblank_init(dev, dev->mode_config.num_crtc); if (ret) goto err_comp; dev->irq_enabled = true; dev->vblank_disable_allowed = 1; ret = armada_fbdev_init(dev); if (ret) goto err_comp; drm_kms_helper_poll_init(dev); return 0; err_comp: if (is_componentized(dev->dev)) component_unbind_all(dev->dev, dev); err_kms: drm_mode_config_cleanup(dev); drm_mm_takedown(&priv->linear); flush_work(&priv->fb_unref_work); return ret; }
static int armada_drm_load(struct drm_device *dev, unsigned long flags) { struct armada_private *priv; struct resource *mem = NULL; int ret, n; for (n = 0; ; n++) { struct resource *r = platform_get_resource(dev->platformdev, IORESOURCE_MEM, n); if (!r) break; /* Resources above 64K are graphics memory */ if (resource_size(r) > SZ_64K) mem = r; else return -EINVAL; } if (!mem) return -ENXIO; if (!devm_request_mem_region(dev->dev, mem->start, resource_size(mem), "armada-drm")) return -EBUSY; priv = devm_kzalloc(dev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) { DRM_ERROR("failed to allocate private\n"); return -ENOMEM; } platform_set_drvdata(dev->platformdev, dev); dev->dev_private = priv; INIT_WORK(&priv->fb_unref_work, armada_drm_unref_work); INIT_KFIFO(priv->fb_unref); /* Mode setting support */ drm_mode_config_init(dev); dev->mode_config.min_width = 320; dev->mode_config.min_height = 200; /* * With vscale enabled, the maximum width is 1920 due to the * 1920 by 3 lines RAM */ dev->mode_config.max_width = 1920; dev->mode_config.max_height = 2048; dev->mode_config.preferred_depth = 24; dev->mode_config.funcs = &armada_drm_mode_config_funcs; drm_mm_init(&priv->linear, mem->start, resource_size(mem)); mutex_init(&priv->linear_lock); ret = component_bind_all(dev->dev, dev); if (ret) goto err_kms; ret = drm_vblank_init(dev, dev->mode_config.num_crtc); if (ret) goto err_comp; dev->irq_enabled = true; dev->vblank_disable_allowed = 1; ret = armada_fbdev_init(dev); if (ret) goto err_comp; drm_kms_helper_poll_init(dev); return 0; err_comp: component_unbind_all(dev->dev, dev); err_kms: drm_mode_config_cleanup(dev); drm_mm_takedown(&priv->linear); flush_work(&priv->fb_unref_work); return ret; }
/* * The ES2 USB Bridge device has 15 endpoints * 1 Control - usual USB stuff + AP -> APBridgeA messages * 7 Bulk IN - CPort data in * 7 Bulk OUT - CPort data out */ static int ap_probe(struct usb_interface *interface, const struct usb_device_id *id) { struct es2_ap_dev *es2; struct gb_host_device *hd; struct usb_device *udev; struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; int bulk_in = 0; int bulk_out = 0; int retval = -ENOMEM; int i; int num_cports; int cport_id; udev = usb_get_dev(interface_to_usbdev(interface)); num_cports = apb_get_cport_count(udev); if (num_cports < 0) { usb_put_dev(udev); dev_err(&udev->dev, "Cannot retrieve CPort count: %d\n", num_cports); return num_cports; } hd = gb_hd_create(&es2_driver, &udev->dev, ES2_GBUF_MSG_SIZE_MAX, num_cports); if (IS_ERR(hd)) { usb_put_dev(udev); return PTR_ERR(hd); } /* * CPorts 16 and 17 are reserved for CDSI0 and CDSI1, make sure they * won't be allocated dynamically. */ do { cport_id = ida_simple_get(&hd->cport_id_map, 16, 18, GFP_KERNEL); } while (cport_id > 0); es2 = hd_to_es2(hd); es2->hd = hd; es2->usb_intf = interface; es2->usb_dev = udev; spin_lock_init(&es2->cport_out_urb_lock); INIT_KFIFO(es2->apb_log_fifo); usb_set_intfdata(interface, es2); es2->cport_to_ep = kcalloc(hd->num_cports, sizeof(*es2->cport_to_ep), GFP_KERNEL); if (!es2->cport_to_ep) { retval = -ENOMEM; goto error; } /* find all bulk endpoints */ iface_desc = interface->cur_altsetting; for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { endpoint = &iface_desc->endpoint[i].desc; if (usb_endpoint_is_bulk_in(endpoint)) { es2->cport_in[bulk_in++].endpoint = endpoint->bEndpointAddress; } else if (usb_endpoint_is_bulk_out(endpoint)) { es2->cport_out[bulk_out++].endpoint = endpoint->bEndpointAddress; } else { dev_err(&udev->dev, "Unknown endpoint type found, address 0x%02x\n", endpoint->bEndpointAddress); } } if (bulk_in != NUM_BULKS || bulk_out != NUM_BULKS) { dev_err(&udev->dev, "Not enough endpoints found in device, aborting!\n"); goto error; } /* Allocate buffers for our cport in messages */ for (bulk_in = 0; bulk_in < NUM_BULKS; bulk_in++) { struct es2_cport_in *cport_in = &es2->cport_in[bulk_in]; for (i = 0; i < NUM_CPORT_IN_URB; ++i) { struct urb *urb; u8 *buffer; urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) goto error; buffer = kmalloc(ES2_GBUF_MSG_SIZE_MAX, GFP_KERNEL); if (!buffer) goto error; usb_fill_bulk_urb(urb, udev, usb_rcvbulkpipe(udev, cport_in->endpoint), buffer, ES2_GBUF_MSG_SIZE_MAX, cport_in_callback, hd); cport_in->urb[i] = urb; cport_in->buffer[i] = buffer; } } /* Allocate urbs for our CPort OUT messages */ for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { struct urb *urb; urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) goto error; es2->cport_out_urb[i] = urb; es2->cport_out_urb_busy[i] = false; /* just to be anal */ } /* XXX We will need to rename this per APB */ es2->apb_log_enable_dentry = debugfs_create_file("apb_log_enable", (S_IWUSR | S_IRUGO), gb_debugfs_get(), es2, &apb_log_enable_fops); retval = gb_hd_add(hd); if (retval) goto error; for (i = 0; i < NUM_BULKS; ++i) { retval = es2_cport_in_enable(es2, &es2->cport_in[i]); if (retval) goto err_disable_cport_in; } return 0; err_disable_cport_in: for (--i; i >= 0; --i) es2_cport_in_disable(es2, &es2->cport_in[i]); gb_hd_del(hd); error: es2_destroy(es2); return retval; }
/*---------------------------------------------------------------------------*/ static int __devinit ami_probe(struct i2c_client *client, const struct i2c_device_id *devid) { int res = 0; struct ami306_dev_data *pdev = NULL; struct ami306_platform_data *pdata = NULL; AMI_LOG("%s %s %s", AMI_DRV_NAME, __func__, "start"); if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { AMI_LOG("AMI : adapter can NOT support I2C_FUNC_I2C."); return -ENODEV; } pdev = (struct ami306_dev_data *)kzalloc(sizeof(struct ami306_dev_data), GFP_KERNEL); if (!pdev) { AMI_LOG("AMI: no memory to allocate ami306_dev_data\n"); return -ENOMEM; } pdata = (struct ami306_platform_data *)client->dev.platform_data; if (!pdata) { printk("ami_probe: missing platform data info\n"); } else { /* Set up axis */ pdev->ami_dir = pdata->dir; pdev->ami_polarity = pdata->polarity; pdev->gpio_drdy = pdata->gpio_drdy; pdev->gpio_intr = pdata->gpio_intr; /* Init gpio */ if(pdata->gpio_drdy) { if((res = gpio_request(pdata->gpio_drdy, "AMI306 DRDY"))) { printk(KERN_ERR "ami_probe: failed to request GPIO %d err=%d\n", pdata->gpio_drdy, res); goto err_free_pdev; } if((res = gpio_direction_input(pdata->gpio_drdy))) { printk(KERN_ERR "ami_probe: failed to set input direction for GPIO %d err=%d\n", pdata->gpio_drdy, res); goto err_free_pdev; } } if(pdata->gpio_intr) { if((res = gpio_request(pdata->gpio_intr, "AMI306 INTR"))) { printk(KERN_ERR "ami_probe: failed to request GPIO %d err=%d\n", pdata->gpio_intr, res); goto err_free_pdev; } if((res = gpio_direction_input(pdata->gpio_intr))) { printk(KERN_ERR "ami_probe: failed to set input direction for GPIO %d err=%d\n", pdata->gpio_intr, res); goto err_free_pdev; } } printk("ami_probe: setup ami_dir:%d, ami_polarity:%d, intr:%d, drdy:%d\n", pdev->ami_dir, pdev->ami_polarity, pdata->gpio_intr, pdata->gpio_drdy); } sema_init(&pdev->mutex, 1); pdev->dev.minor = MISC_DYNAMIC_MINOR; pdev->dev.name = AMI_DRV_NAME; pdev->dev.fops = &ami_fops; res = misc_register(&pdev->dev); if(res < 0) { printk(KERN_ERR "ami_probe: failed to do misc_regsiter return %d\n", res); goto err_free_pdev; } #ifdef USER_MEMORY /* Initialize driver command */ k_mem = kmalloc(AMI_GetMemSize(), GFP_KERNEL); if(k_mem == NULL) { printk(KERN_ERR "ami_probe: kmalloc error"); res = -ENODEV; goto err_misc_deregister; } pdev->handle = AMI_InitDriver(k_mem, client, pdev->ami_dir, pdev->ami_polarity); #else pdev->handle = AMI_InitDriver(client, pdev->ami_dir, pdev->ami_polarity); #endif if(pdev->handle == NULL) { AMI_LOG("AMI : AMI_InitDriver error."); res = -ENODEV; goto err_free_kmem; } pdev->client = client; i2c_set_clientdata(client, pdev); /* initialize the waitq */ init_waitqueue_head(&pdev->waitq); /* initialize the kfifo */ INIT_KFIFO(pdev->ebuff); /* create workqueue */ pdev->wq = create_singlethread_workqueue("ami306_wq"); if (!pdev->wq) { AMI_LOG("AMI: Failed to create workqueue\n"); res = -ENOMEM; goto err_free_kmem; } /* initialize the work struct */ INIT_WORK(&pdev->work, ami_work_func); pdev->enable_wq = 0; /* create hrtimer, we don't just do msleep_interruptible as android would pass something in unit of nanoseconds */ hrtimer_init(&pdev->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); pdev->poll_delay = ns_to_ktime(500 * NSEC_PER_MSEC); pdev->timer.function = ami_timer_func; /* Register sysfs hooks */ res = sysfs_create_group(&client->dev.kobj, &ami_attr_group); if (res) { AMI_LOG("AMI: sysfs_create_group failed with error %d\n", res); res = -ENODEV; goto err_destroy_workqueue; } #ifdef CONFIG_ARCH_KONA pdev->regulator = regulator_get(&client->dev, "hv8"); res = IS_ERR_OR_NULL(pdev->regulator); if (res) { pdev->regulator = NULL; AMI_LOG("AMI: %s, can't get hv8 regulator!\n", __func__); res = -EIO; goto err_destroy_workqueue; } /* make sure that regulator is enabled if device is successfully bound */ res = regulator_enable(pdev->regulator); AMI_LOG("AMI: %s, called regulator_enable for hv8 regulator. " "Status: %d\n", __func__, res); if (res) { AMI_LOG("AMI: %s, regulator_enable for hv8 regulator " "failed with status: %d\n", __func__, res); regulator_put(pdev->regulator); } #endif AMI_LOG("%s %s %s", AMI_DRV_NAME, __func__, "end"); return res; err_destroy_workqueue: destroy_workqueue(pdev->wq); err_free_kmem: #ifdef USER_MEMORY if(k_mem) { kfree(k_mem); k_mem = NULL; } err_misc_deregister: #endif misc_deregister(&pdev->dev); err_free_pdev: kfree(pdev); i2c_set_clientdata(client, NULL); return res; }
static int pi433_probe(struct spi_device *spi) { struct pi433_device *device; int retval; /* setup spi parameters */ spi->mode = 0x00; spi->bits_per_word = 8; /* * spi->max_speed_hz = 10000000; * 1MHz already set by device tree overlay */ retval = spi_setup(spi); if (retval) { dev_dbg(&spi->dev, "configuration of SPI interface failed!\n"); return retval; } dev_dbg(&spi->dev, "spi interface setup: mode 0x%2x, %d bits per word, %dhz max speed", spi->mode, spi->bits_per_word, spi->max_speed_hz); /* Ping the chip by reading the version register */ retval = spi_w8r8(spi, 0x10); if (retval < 0) return retval; switch (retval) { case 0x24: dev_dbg(&spi->dev, "found pi433 (ver. 0x%x)", retval); break; default: dev_dbg(&spi->dev, "unknown chip version: 0x%x", retval); return -ENODEV; } /* Allocate driver data */ device = kzalloc(sizeof(*device), GFP_KERNEL); if (!device) return -ENOMEM; /* Initialize the driver data */ device->spi = spi; device->rx_active = false; device->tx_active = false; device->interrupt_rx_allowed = false; /* init rx buffer */ device->rx_buffer = kmalloc(MAX_MSG_SIZE, GFP_KERNEL); if (!device->rx_buffer) { retval = -ENOMEM; goto RX_failed; } /* init wait queues */ init_waitqueue_head(&device->tx_wait_queue); init_waitqueue_head(&device->rx_wait_queue); init_waitqueue_head(&device->fifo_wait_queue); /* init fifo */ INIT_KFIFO(device->tx_fifo); /* init mutexes and locks */ mutex_init(&device->tx_fifo_lock); mutex_init(&device->rx_lock); /* setup GPIO (including irq_handler) for the different DIOs */ retval = setup_gpio(device); if (retval) { dev_dbg(&spi->dev, "setup of GPIOs failed"); goto GPIO_failed; } /* setup the radio module */ retval = rf69_set_mode(spi, standby); if (retval < 0) goto minor_failed; retval = rf69_set_data_mode(spi, DATAMODUL_MODE_PACKET); if (retval < 0) goto minor_failed; retval = rf69_enable_amplifier(spi, MASK_PALEVEL_PA0); if (retval < 0) goto minor_failed; retval = rf69_disable_amplifier(spi, MASK_PALEVEL_PA1); if (retval < 0) goto minor_failed; retval = rf69_disable_amplifier(spi, MASK_PALEVEL_PA2); if (retval < 0) goto minor_failed; retval = rf69_set_output_power_level(spi, 13); if (retval < 0) goto minor_failed; retval = rf69_set_antenna_impedance(spi, fifty_ohm); if (retval < 0) goto minor_failed; /* determ minor number */ retval = pi433_get_minor(device); if (retval) { dev_dbg(&spi->dev, "get of minor number failed"); goto minor_failed; } /* create device */ device->devt = MKDEV(MAJOR(pi433_dev), device->minor); device->dev = device_create(pi433_class, &spi->dev, device->devt, device, "pi433.%d", device->minor); if (IS_ERR(device->dev)) { pr_err("pi433: device register failed\n"); retval = PTR_ERR(device->dev); goto device_create_failed; } else { dev_dbg(device->dev, "created device for major %d, minor %d\n", MAJOR(pi433_dev), device->minor); } /* start tx thread */ device->tx_task_struct = kthread_run(pi433_tx_thread, device, "pi433.%d_tx_task", device->minor); if (IS_ERR(device->tx_task_struct)) { dev_dbg(device->dev, "start of send thread failed"); retval = PTR_ERR(device->tx_task_struct); goto send_thread_failed; } /* create cdev */ device->cdev = cdev_alloc(); if (!device->cdev) { dev_dbg(device->dev, "allocation of cdev failed"); goto cdev_failed; } device->cdev->owner = THIS_MODULE; cdev_init(device->cdev, &pi433_fops); retval = cdev_add(device->cdev, device->devt, 1); if (retval) { dev_dbg(device->dev, "register of cdev failed"); goto del_cdev; } /* spi setup */ spi_set_drvdata(spi, device); return 0; del_cdev: cdev_del(device->cdev); cdev_failed: kthread_stop(device->tx_task_struct); send_thread_failed: device_destroy(pi433_class, device->devt); device_create_failed: pi433_free_minor(device); minor_failed: free_gpio(device); GPIO_failed: kfree(device->rx_buffer); RX_failed: kfree(device); return retval; }