diff options
author | Stephen Rothwell <sfr@canb.auug.org.au> | 2013-03-22 15:35:12 +1100 |
---|---|---|
committer | Stephen Rothwell <sfr@canb.auug.org.au> | 2013-03-22 15:35:12 +1100 |
commit | bcc94e162326c90edc1e72dfbf0874869ee53caf (patch) | |
tree | c4f753ff71487cc87bd9da5453e79116fa8a132b /drivers | |
parent | 5119bb9078f599d5340a912f0fac6d88e2ce0f4b (diff) | |
parent | 889fc8ba21f58a4a39fa675bd7624c83222cf829 (diff) |
Merge branch 'akpm/master'
Diffstat (limited to 'drivers')
163 files changed, 2477 insertions, 1285 deletions
diff --git a/drivers/Kconfig b/drivers/Kconfig index 202fa6d051b9..4606d7558dd8 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -118,6 +118,8 @@ source "drivers/vfio/Kconfig" source "drivers/vlynq/Kconfig" +source "drivers/virt/Kconfig" + source "drivers/virtio/Kconfig" source "drivers/hv/Kconfig" @@ -142,8 +144,6 @@ source "drivers/remoteproc/Kconfig" source "drivers/rpmsg/Kconfig" -source "drivers/virt/Kconfig" - source "drivers/devfreq/Kconfig" source "drivers/extcon/Kconfig" diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index ade58bc8f3c4..1c1b8e544aa2 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -4206,7 +4206,7 @@ static int cciss_find_cfgtables(ctlr_info_t *h) if (rc) return rc; h->cfgtable = remap_pci_mem(pci_resource_start(h->pdev, - cfg_base_addr_index) + cfg_offset, sizeof(h->cfgtable)); + cfg_base_addr_index) + cfg_offset, sizeof(*h->cfgtable)); if (!h->cfgtable) return -ENOMEM; rc = write_driver_ver_to_cfgtable(h->cfgtable); diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index a9eccfc6079b..83c5ae0ed56b 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -757,7 +757,8 @@ static struct socket *drbd_wait_for_connect(struct drbd_tconn *tconn, struct acc rcu_read_unlock(); timeo = connect_int * HZ; - timeo += (random32() & 1) ? timeo / 7 : -timeo / 7; /* 28.5% random jitter */ + /* 28.5% random jitter */ + timeo += (prandom_u32() & 1) ? timeo / 7 : -timeo / 7; err = wait_for_completion_interruptible_timeout(&ad->door_bell, timeo); if (err <= 0) @@ -953,7 +954,7 @@ retry: conn_warn(tconn, "Error receiving initial packet\n"); sock_release(s); randomize: - if (random32() & 1) + if (prandom_u32() & 1) goto retry; } } diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 747bb2af69dc..1e0cc5a9ff8d 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -1044,12 +1044,27 @@ static int loop_clr_fd(struct loop_device *lo) lo->lo_state = Lo_unbound; /* This is safe: open() is still holding a reference. */ module_put(THIS_MODULE); - if (lo->lo_flags & LO_FLAGS_PARTSCAN && bdev) - ioctl_by_bdev(bdev, BLKRRPART, 0); lo->lo_flags = 0; if (!part_shift) lo->lo_disk->flags |= GENHD_FL_NO_PART_SCAN; mutex_unlock(&lo->lo_ctl_mutex); + if (bdev) { + /* + * Remove all partitions, since BLKRRPART won't remove user + * added partitions when max_part=0. + */ + struct disk_part_iter piter; + struct hd_struct *part; + + mutex_lock_nested(&bdev->bd_mutex, 1); + invalidate_partition(bdev->bd_disk, 0); + disk_part_iter_init(&piter, bdev->bd_disk, DISK_PITER_INCL_EMPTY); + while ((part = disk_part_iter_next(&piter))) + delete_partition(bdev->bd_disk, part->partno); + disk_part_iter_exit(&piter); + mutex_unlock(&bdev->bd_mutex); + } + /* * Need not hold lo_ctl_mutex to fput backing file. * Calling fput holding lo_ctl_mutex triggers a circular diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c index 11cc9522cdd4..b84dda58c33c 100644 --- a/drivers/block/mtip32xx/mtip32xx.c +++ b/drivers/block/mtip32xx/mtip32xx.c @@ -146,6 +146,9 @@ static void mtip_command_cleanup(struct driver_data *dd) struct mtip_cmd *command; struct mtip_port *port = dd->port; static int in_progress; + struct batch_complete batch; + + batch_complete_init(&batch); if (in_progress) return; @@ -161,11 +164,9 @@ static void mtip_command_cleanup(struct driver_data *dd) command = &port->commands[commandindex]; if (atomic_read(&command->active) - && (command->async_callback)) { - command->async_callback(command->async_data, - -ENODEV); - command->async_callback = NULL; - command->async_data = NULL; + && (command->bio)) { + bio_endio_batch(command->bio, -ENODEV, &batch); + command->bio = NULL; } dma_unmap_sg(&port->dd->pdev->dev, @@ -173,9 +174,10 @@ static void mtip_command_cleanup(struct driver_data *dd) command->scatter_ents, command->direction); } + up(&port->cmd_slot); } - up(&port->cmd_slot); + batch_complete(&batch); set_bit(MTIP_DDF_CLEANUP_BIT, &dd->dd_flag); in_progress = 0; @@ -564,6 +566,9 @@ static void mtip_timeout_function(unsigned long int data) unsigned int bit, group; unsigned int num_command_slots; unsigned long to, tagaccum[SLOTBITS_IN_LONGS]; + struct batch_complete batch; + + batch_complete_init(&batch); if (unlikely(!port)) return; @@ -606,11 +611,9 @@ static void mtip_timeout_function(unsigned long int data) writel(1 << bit, port->completed[group]); /* Call the async completion callback. */ - if (likely(command->async_callback)) - command->async_callback(command->async_data, - -EIO); - command->async_callback = NULL; - command->comp_func = NULL; + if (likely(command->bio)) + bio_endio_batch(command->bio, -EIO, &batch); + command->bio = NULL; /* Unmap the DMA scatter list entries */ dma_unmap_sg(&port->dd->pdev->dev, @@ -629,6 +632,8 @@ static void mtip_timeout_function(unsigned long int data) } } + batch_complete(&batch); + if (cmdto_cnt) { print_tags(port->dd, "timed out", tagaccum, cmdto_cnt); if (!test_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags)) { @@ -679,7 +684,8 @@ static void mtip_timeout_function(unsigned long int data) static void mtip_async_complete(struct mtip_port *port, int tag, void *data, - int status) + int status, + struct batch_complete *batch) { struct mtip_cmd *command; struct driver_data *dd = data; @@ -696,11 +702,10 @@ static void mtip_async_complete(struct mtip_port *port, } /* Upper layer callback */ - if (likely(command->async_callback)) - command->async_callback(command->async_data, cb_status); + if (likely(command->bio)) + bio_endio_batch(command->bio, cb_status, batch); - command->async_callback = NULL; - command->comp_func = NULL; + command->bio = NULL; /* Unmap the DMA scatter list entries */ dma_unmap_sg(&dd->pdev->dev, @@ -733,24 +738,22 @@ static void mtip_async_complete(struct mtip_port *port, static void mtip_completion(struct mtip_port *port, int tag, void *data, - int status) + int status, + struct batch_complete *batch) { - struct mtip_cmd *command = &port->commands[tag]; struct completion *waiting = data; if (unlikely(status == PORT_IRQ_TF_ERR)) dev_warn(&port->dd->pdev->dev, "Internal command %d completed with TFE\n", tag); - command->async_callback = NULL; - command->comp_func = NULL; - complete(waiting); } static void mtip_null_completion(struct mtip_port *port, int tag, void *data, - int status) + int status, + struct batch_complete *batch) { return; } @@ -779,6 +782,7 @@ static void mtip_handle_tfe(struct driver_data *dd) unsigned char *buf; char *fail_reason = NULL; int fail_all_ncq_write = 0, fail_all_ncq_cmds = 0; + struct batch_complete batch; dev_warn(&dd->pdev->dev, "Taskfile error\n"); @@ -796,13 +800,14 @@ static void mtip_handle_tfe(struct driver_data *dd) atomic_inc(&cmd->active); /* active > 1 indicates error */ if (cmd->comp_data && cmd->comp_func) { cmd->comp_func(port, MTIP_TAG_INTERNAL, - cmd->comp_data, PORT_IRQ_TF_ERR); + cmd->comp_data, PORT_IRQ_TF_ERR, NULL); } goto handle_tfe_exit; } /* clear the tag accumulator */ memset(tagaccum, 0, SLOTBITS_IN_LONGS * sizeof(long)); + batch_complete_init(&batch); /* Loop through all the groups */ for (group = 0; group < dd->slot_groups; group++) { @@ -829,7 +834,7 @@ static void mtip_handle_tfe(struct driver_data *dd) cmd->comp_func(port, tag, cmd->comp_data, - 0); + 0, &batch); } else { dev_err(&port->dd->pdev->dev, "Missing completion func for tag %d", @@ -842,6 +847,7 @@ static void mtip_handle_tfe(struct driver_data *dd) } } } + batch_complete(&batch); print_tags(dd, "completed (TFE)", tagaccum, cmd_cnt); @@ -883,6 +889,7 @@ static void mtip_handle_tfe(struct driver_data *dd) /* clear the tag accumulator */ memset(tagaccum, 0, SLOTBITS_IN_LONGS * sizeof(long)); + batch_complete_init(&batch); /* Loop through all the groups */ for (group = 0; group < dd->slot_groups; group++) { @@ -916,7 +923,7 @@ static void mtip_handle_tfe(struct driver_data *dd) if (cmd->comp_func) { cmd->comp_func(port, tag, cmd->comp_data, - -ENODATA); + -ENODATA, &batch); } continue; } @@ -946,13 +953,15 @@ static void mtip_handle_tfe(struct driver_data *dd) port, tag, cmd->comp_data, - PORT_IRQ_TF_ERR); + PORT_IRQ_TF_ERR, &batch); else dev_warn(&port->dd->pdev->dev, "Bad completion for tag %d\n", tag); } } + + batch_complete(&batch); print_tags(dd, "reissued (TFE)", tagaccum, cmd_cnt); handle_tfe_exit: @@ -973,6 +982,9 @@ static inline void mtip_workq_sdbfx(struct mtip_port *port, int group, struct driver_data *dd = port->dd; int tag, bit; struct mtip_cmd *command; + struct batch_complete batch; + + batch_complete_init(&batch); if (!completed) { WARN_ON_ONCE(!completed); @@ -997,7 +1009,8 @@ static inline void mtip_workq_sdbfx(struct mtip_port *port, int group, port, tag, command->comp_data, - 0); + 0, + &batch); } else { dev_warn(&dd->pdev->dev, "Null completion " @@ -1007,13 +1020,16 @@ static inline void mtip_workq_sdbfx(struct mtip_port *port, int group, if (mtip_check_surprise_removal( dd->pdev)) { mtip_command_cleanup(dd); - return; + goto out; } } } completed >>= 1; } +out: + batch_complete(&batch); + /* If last, re-enable interrupts */ if (atomic_dec_return(&dd->irq_workers_active) == 0) writel(0xffffffff, dd->mmio + HOST_IRQ_STAT); @@ -1034,7 +1050,7 @@ static inline void mtip_process_legacy(struct driver_data *dd, u32 port_stat) cmd->comp_func(port, MTIP_TAG_INTERNAL, cmd->comp_data, - 0); + 0, NULL); return; } } @@ -2554,8 +2570,8 @@ static int mtip_hw_ioctl(struct driver_data *dd, unsigned int cmd, * None */ static void mtip_hw_submit_io(struct driver_data *dd, sector_t sector, - int nsect, int nents, int tag, void *callback, - void *data, int dir) + int nsect, int nents, int tag, + struct bio *bio, int dir) { struct host_to_dev_fis *fis; struct mtip_port *port = dd->port; @@ -2610,12 +2626,7 @@ static void mtip_hw_submit_io(struct driver_data *dd, sector_t sector, command->comp_func = mtip_async_complete; command->direction = dma_dir; - /* - * Set the completion function and data for the command passed - * from the upper layer. - */ - command->async_data = data; - command->async_callback = callback; + command->bio = bio; /* * To prevent this command from being issued @@ -3795,7 +3806,6 @@ static void mtip_make_request(struct request_queue *queue, struct bio *bio) bio_sectors(bio), nents, tag, - bio_endio, bio, bio_data_dir(bio)); } else diff --git a/drivers/block/mtip32xx/mtip32xx.h b/drivers/block/mtip32xx/mtip32xx.h index 3bffff5f670c..af8c6f79a8d8 100644 --- a/drivers/block/mtip32xx/mtip32xx.h +++ b/drivers/block/mtip32xx/mtip32xx.h @@ -325,11 +325,9 @@ struct mtip_cmd { void (*comp_func)(struct mtip_port *port, int tag, void *data, - int status); - /* Additional callback function that may be called by comp_func() */ - void (*async_callback)(void *data, int status); - - void *async_data; /* Addl. data passed to async_callback() */ + int status, + struct batch_complete *batch); + struct bio *bio; int scatter_ents; /* Number of scatter list entries used */ diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c index 758f2ac878cf..deb722d63d68 100644 --- a/drivers/block/swim3.c +++ b/drivers/block/swim3.c @@ -775,7 +775,7 @@ static irqreturn_t swim3_interrupt(int irq, void *dev_id) if (intr & ERROR_INTR) { n = fs->scount - 1 - resid / 512; if (n > 0) { - blk_update_request(req, 0, n << 9); + blk_update_request(req, 0, n << 9, NULL); fs->req_sector += n; } if (fs->retries < 5) { diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 64723953e1c9..49d0ec2472c5 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -217,7 +217,8 @@ static void virtblk_bio_send_flush_work(struct work_struct *work) virtblk_bio_send_flush(vbr); } -static inline void virtblk_request_done(struct virtblk_req *vbr) +static inline void virtblk_request_done(struct virtblk_req *vbr, + struct batch_complete *batch) { struct virtio_blk *vblk = vbr->vblk; struct request *req = vbr->req; @@ -231,11 +232,12 @@ static inline void virtblk_request_done(struct virtblk_req *vbr) req->errors = (error != 0); } - __blk_end_request_all(req, error); + blk_end_request_all_batch(req, error, batch); mempool_free(vbr, vblk->pool); } -static inline void virtblk_bio_flush_done(struct virtblk_req *vbr) +static inline void virtblk_bio_flush_done(struct virtblk_req *vbr, + struct batch_complete *batch) { struct virtio_blk *vblk = vbr->vblk; @@ -244,12 +246,13 @@ static inline void virtblk_bio_flush_done(struct virtblk_req *vbr) INIT_WORK(&vbr->work, virtblk_bio_send_data_work); queue_work(virtblk_wq, &vbr->work); } else { - bio_endio(vbr->bio, virtblk_result(vbr)); + bio_endio_batch(vbr->bio, virtblk_result(vbr), batch); mempool_free(vbr, vblk->pool); } } -static inline void virtblk_bio_data_done(struct virtblk_req *vbr) +static inline void virtblk_bio_data_done(struct virtblk_req *vbr, + struct batch_complete *batch) { struct virtio_blk *vblk = vbr->vblk; @@ -259,17 +262,18 @@ static inline void virtblk_bio_data_done(struct virtblk_req *vbr) INIT_WORK(&vbr->work, virtblk_bio_send_flush_work); queue_work(virtblk_wq, &vbr->work); } else { - bio_endio(vbr->bio, virtblk_result(vbr)); + bio_endio_batch(vbr->bio, virtblk_result(vbr), batch); mempool_free(vbr, vblk->pool); } } -static inline void virtblk_bio_done(struct virtblk_req *vbr) +static inline void virtblk_bio_done(struct virtblk_req *vbr, + struct batch_complete *batch) { if (unlikely(vbr->flags & VBLK_IS_FLUSH)) - virtblk_bio_flush_done(vbr); + virtblk_bio_flush_done(vbr, batch); else - virtblk_bio_data_done(vbr); + virtblk_bio_data_done(vbr, batch); } static void virtblk_done(struct virtqueue *vq) @@ -279,16 +283,19 @@ static void virtblk_done(struct virtqueue *vq) struct virtblk_req *vbr; unsigned long flags; unsigned int len; + struct batch_complete batch; + + batch_complete_init(&batch); spin_lock_irqsave(vblk->disk->queue->queue_lock, flags); do { virtqueue_disable_cb(vq); while ((vbr = virtqueue_get_buf(vblk->vq, &len)) != NULL) { if (vbr->bio) { - virtblk_bio_done(vbr); + virtblk_bio_done(vbr, &batch); bio_done = true; } else { - virtblk_request_done(vbr); + virtblk_request_done(vbr, &batch); req_done = true; } } @@ -298,6 +305,8 @@ static void virtblk_done(struct virtqueue *vq) blk_start_queue(vblk->disk->queue); spin_unlock_irqrestore(vblk->disk->queue->queue_lock, flags); + batch_complete(&batch); + if (bio_done) wake_up(&vblk->queue_wait); } diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 2c644afbcdd4..1ccbe9482faa 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -28,6 +28,7 @@ #include <linux/pfn.h> #include <linux/export.h> #include <linux/io.h> +#include <linux/aio.h> #include <asm/uaccess.h> @@ -627,6 +628,18 @@ static ssize_t write_null(struct file *file, const char __user *buf, return count; } +static ssize_t aio_read_null(struct kiocb *iocb, const struct iovec *iov, + unsigned long nr_segs, loff_t pos) +{ + return 0; +} + +static ssize_t aio_write_null(struct kiocb *iocb, const struct iovec *iov, + unsigned long nr_segs, loff_t pos) +{ + return iov_length(iov, nr_segs); +} + static int pipe_to_null(struct pipe_inode_info *info, struct pipe_buffer *buf, struct splice_desc *sd) { @@ -670,6 +683,24 @@ static ssize_t read_zero(struct file *file, char __user *buf, return written ? written : -EFAULT; } +static ssize_t aio_read_zero(struct kiocb *iocb, const struct iovec *iov, + unsigned long nr_segs, loff_t pos) +{ + size_t written = 0; + unsigned long i; + ssize_t ret; + + for (i = 0; i < nr_segs; i++) { + ret = read_zero(iocb->ki_filp, iov[i].iov_base, iov[i].iov_len, + &pos); + if (ret < 0) + break; + written += ret; + } + + return written ? written : -EFAULT; +} + static int mmap_zero(struct file *file, struct vm_area_struct *vma) { #ifndef CONFIG_MMU @@ -738,6 +769,7 @@ static int open_port(struct inode *inode, struct file *filp) #define full_lseek null_lseek #define write_zero write_null #define read_full read_zero +#define aio_write_zero aio_write_null #define open_mem open_port #define open_kmem open_mem #define open_oldmem open_mem @@ -766,6 +798,8 @@ static const struct file_operations null_fops = { .llseek = null_lseek, .read = read_null, .write = write_null, + .aio_read = aio_read_null, + .aio_write = aio_write_null, .splice_write = splice_write_null, }; @@ -782,6 +816,8 @@ static const struct file_operations zero_fops = { .llseek = zero_lseek, .read = read_zero, .write = write_zero, + .aio_read = aio_read_zero, + .aio_write = aio_write_zero, .mmap = mmap_zero, }; diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index 4cd392dbf115..40e940d4db6b 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c @@ -410,22 +410,45 @@ static void __init dmi_dump_ids(void) printk(KERN_CONT "\n"); } -static int __init dmi_present(const char __iomem *p) +static int __init dmi_present(const u8 *buf) { - u8 buf[15]; + int smbios_ver; - memcpy_fromio(buf, p, 15); - if (dmi_checksum(buf, 15)) { + if (memcmp(buf, "_SM_", 4) == 0 && + buf[5] < 32 && dmi_checksum(buf, buf[5])) { + smbios_ver = (buf[6] << 8) + buf[7]; + + /* Some BIOS report weird SMBIOS version, fix that up */ + switch (smbios_ver) { + case 0x021F: + case 0x0221: + pr_debug("SMBIOS version fixup(2.%d->2.%d)\n", + smbios_ver & 0xFF, 3); + smbios_ver = 0x0203; + break; + case 0x0233: + pr_debug("SMBIOS version fixup(2.%d->2.%d)\n", 51, 6); + smbios_ver = 0x0206; + break; + } + } else { + smbios_ver = 0; + } + + buf += 16; + + if (memcmp(buf, "_DMI_", 5) == 0 && dmi_checksum(buf, 15)) { dmi_num = (buf[13] << 8) | buf[12]; dmi_len = (buf[7] << 8) | buf[6]; dmi_base = (buf[11] << 24) | (buf[10] << 16) | (buf[9] << 8) | buf[8]; if (dmi_walk_early(dmi_decode) == 0) { - if (dmi_ver) + if (smbios_ver) { + dmi_ver = smbios_ver; pr_info("SMBIOS %d.%d present.\n", dmi_ver >> 8, dmi_ver & 0xFF); - else { + } else { dmi_ver = (buf[14] & 0xF0) << 4 | (buf[14] & 0x0F); pr_info("Legacy DMI %d.%d present.\n", @@ -435,40 +458,14 @@ static int __init dmi_present(const char __iomem *p) return 0; } } - dmi_ver = 0; - return 1; -} -static int __init smbios_present(const char __iomem *p) -{ - u8 buf[32]; - - memcpy_fromio(buf, p, 32); - if ((buf[5] < 32) && dmi_checksum(buf, buf[5])) { - dmi_ver = (buf[6] << 8) + buf[7]; - - /* Some BIOS report weird SMBIOS version, fix that up */ - switch (dmi_ver) { - case 0x021F: - case 0x0221: - pr_debug("SMBIOS version fixup(2.%d->2.%d)\n", - dmi_ver & 0xFF, 3); - dmi_ver = 0x0203; - break; - case 0x0233: - pr_debug("SMBIOS version fixup(2.%d->2.%d)\n", 51, 6); - dmi_ver = 0x0206; - break; - } - return memcmp(p + 16, "_DMI_", 5) || dmi_present(p + 16); - } return 1; } void __init dmi_scan_machine(void) { char __iomem *p, *q; - int rc; + char buf[32]; if (efi_enabled(EFI_CONFIG_TABLES)) { if (efi.smbios == EFI_INVALID_TABLE_ADDR) @@ -481,10 +478,10 @@ void __init dmi_scan_machine(void) p = dmi_ioremap(efi.smbios, 32); if (p == NULL) goto error; - - rc = smbios_present(p); + memcpy_fromio(buf, p, 32); dmi_iounmap(p, 32); - if (!rc) { + + if (!dmi_present(buf)) { dmi_available = 1; goto out; } @@ -499,18 +496,15 @@ void __init dmi_scan_machine(void) if (p == NULL) goto error; + memset(buf, 0, 16); for (q = p; q < p + 0x10000; q += 16) { - if (memcmp(q, "_SM_", 4) == 0 && q - p <= 0xFFE0) - rc = smbios_present(q); - else if (memcmp(q, "_DMI_", 5) == 0) - rc = dmi_present(q); - else - continue; - if (!rc) { + memcpy_fromio(buf + 16, q, 16); + if (!dmi_present(buf)) { dmi_available = 1; dmi_iounmap(p, 0x10000); goto out; } + memcpy(buf, buf + 16, 16); } dmi_iounmap(p, 0x10000); } diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 59d6b9bf204b..cf71f1d627fe 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -399,6 +399,14 @@ static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode) return; /* + * fbdev->blank can be called from irq context in case of a panic. + * Since we already have our own special panic handler which will + * restore the fbdev console mode completely, just bail out early. + */ + if (oops_in_progress) + return; + + /* * For each CRTC in this fb, turn the connectors on/off. */ drm_modeset_lock_all(dev); diff --git a/drivers/infiniband/hw/cxgb3/cxio_resource.c b/drivers/infiniband/hw/cxgb3/cxio_resource.c index 31f9201b2980..c40088ecf9f3 100644 --- a/drivers/infiniband/hw/cxgb3/cxio_resource.c +++ b/drivers/infiniband/hw/cxgb3/cxio_resource.c @@ -62,13 +62,13 @@ static int __cxio_init_resource_fifo(struct kfifo *fifo, kfifo_in(fifo, (unsigned char *) &entry, sizeof(u32)); if (random) { j = 0; - random_bytes = random32(); + random_bytes = prandom_u32(); for (i = 0; i < RANDOM_SIZE; i++) rarray[i] = i + skip_low; for (i = skip_low + RANDOM_SIZE; i < nr - skip_high; i++) { if (j >= RANDOM_SIZE) { j = 0; - random_bytes = random32(); + random_bytes = prandom_u32(); } idx = (random_bytes >> (j * 2)) & 0xF; kfifo_in(fifo, diff --git a/drivers/infiniband/hw/cxgb4/id_table.c b/drivers/infiniband/hw/cxgb4/id_table.c index f95e5df30db2..0161ae6ad629 100644 --- a/drivers/infiniband/hw/cxgb4/id_table.c +++ b/drivers/infiniband/hw/cxgb4/id_table.c @@ -54,7 +54,7 @@ u32 c4iw_id_alloc(struct c4iw_id_table *alloc) if (obj < alloc->max) { if (alloc->flags & C4IW_ID_TABLE_F_RANDOM) - alloc->last += random32() % RANDOM_SKIP; + alloc->last += prandom_u32() % RANDOM_SKIP; else alloc->last = obj + 1; if (alloc->last >= alloc->max) @@ -88,7 +88,7 @@ int c4iw_id_table_alloc(struct c4iw_id_table *alloc, u32 start, u32 num, alloc->start = start; alloc->flags = flags; if (flags & C4IW_ID_TABLE_F_RANDOM) - alloc->last = random32() % RANDOM_SKIP; + alloc->last = prandom_u32() % RANDOM_SKIP; else alloc->last = 0; alloc->max = num; diff --git a/drivers/infiniband/hw/ipath/ipath_file_ops.c b/drivers/infiniband/hw/ipath/ipath_file_ops.c index aed8afee56da..6d7f453b4d05 100644 --- a/drivers/infiniband/hw/ipath/ipath_file_ops.c +++ b/drivers/infiniband/hw/ipath/ipath_file_ops.c @@ -40,6 +40,7 @@ #include <linux/slab.h> #include <linux/highmem.h> #include <linux/io.h> +#include <linux/aio.h> #include <linux/jiffies.h> #include <linux/cpu.h> #include <asm/pgtable.h> diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c index 934792c477bc..4d599cedbb0b 100644 --- a/drivers/infiniband/hw/mlx4/mad.c +++ b/drivers/infiniband/hw/mlx4/mad.c @@ -93,7 +93,7 @@ static void __propagate_pkey_ev(struct mlx4_ib_dev *dev, int port_num, __be64 mlx4_ib_gen_node_guid(void) { #define NODE_GUID_HI ((u64) (((u64)IB_OPENIB_OUI) << 40)) - return cpu_to_be64(NODE_GUID_HI | random32()); + return cpu_to_be64(NODE_GUID_HI | prandom_u32()); } __be64 mlx4_ib_get_new_demux_tid(struct mlx4_ib_demux_ctx *ctx) diff --git a/drivers/infiniband/hw/qib/qib_file_ops.c b/drivers/infiniband/hw/qib/qib_file_ops.c index 4f7aa301b3b1..b56c9428f3c5 100644 --- a/drivers/infiniband/hw/qib/qib_file_ops.c +++ b/drivers/infiniband/hw/qib/qib_file_ops.c @@ -39,7 +39,7 @@ #include <linux/vmalloc.h> #include <linux/highmem.h> #include <linux/io.h> -#include <linux/uio.h> +#include <linux/aio.h> #include <linux/jiffies.h> #include <asm/pgtable.h> #include <linux/delay.h> diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c index 67b0c1d23678..249976cfb28a 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c @@ -460,7 +460,7 @@ static int ipoib_cm_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *even goto err_qp; } - psn = random32() & 0xffffff; + psn = prandom_u32() & 0xffffff; ret = ipoib_cm_modify_rx_qp(dev, cm_id, p->qp, psn); if (ret) goto err_modify; diff --git a/drivers/leds/leds-ot200.c b/drivers/leds/leds-ot200.c index ee14662ed5ce..98cae529373f 100644 --- a/drivers/leds/leds-ot200.c +++ b/drivers/leds/leds-ot200.c @@ -47,37 +47,37 @@ static struct ot200_led leds[] = { { .name = "led_1", .port = 0x49, - .mask = BIT(7), + .mask = BIT(6), }, { .name = "led_2", .port = 0x49, - .mask = BIT(6), + .mask = BIT(5), }, { .name = "led_3", .port = 0x49, - .mask = BIT(5), + .mask = BIT(4), }, { .name = "led_4", .port = 0x49, - .mask = BIT(4), + .mask = BIT(3), }, { .name = "led_5", .port = 0x49, - .mask = BIT(3), + .mask = BIT(2), }, { .name = "led_6", .port = 0x49, - .mask = BIT(2), + .mask = BIT(1), }, { .name = "led_7", .port = 0x49, - .mask = BIT(1), + .mask = BIT(0), } }; diff --git a/drivers/lguest/page_tables.c b/drivers/lguest/page_tables.c index 3b62be160a6e..864baabaee25 100644 --- a/drivers/lguest/page_tables.c +++ b/drivers/lguest/page_tables.c @@ -686,7 +686,7 @@ static unsigned int new_pgdir(struct lg_cpu *cpu, * We pick one entry at random to throw out. Choosing the Least * Recently Used might be better, but this is easy. */ - next = random32() % ARRAY_SIZE(cpu->lg->pgdirs); + next = prandom_u32() % ARRAY_SIZE(cpu->lg->pgdirs); /* If it's never been allocated at all before, try now. */ if (!cpu->lg->pgdirs[next].pgdir) { cpu->lg->pgdirs[next].pgdir = diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 7e469260fe5e..e52880f6b589 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -695,7 +695,7 @@ static void end_clone_bio(struct bio *clone, int error) * Do not use blk_end_request() here, because it may complete * the original request before the clone, and break the ordering. */ - blk_update_request(tio->orig, 0, nr_bytes); + blk_update_request(tio->orig, 0, nr_bytes, NULL); } /* diff --git a/drivers/memstick/host/r592.c b/drivers/memstick/host/r592.c index a7c5b31c0d50..9718661c1fb6 100644 --- a/drivers/memstick/host/r592.c +++ b/drivers/memstick/host/r592.c @@ -847,7 +847,7 @@ static void r592_remove(struct pci_dev *pdev) dev->dummy_dma_page_physical_address); } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int r592_suspend(struct device *core_dev) { struct pci_dev *pdev = to_pci_dev(core_dev); @@ -870,10 +870,10 @@ static int r592_resume(struct device *core_dev) r592_update_card_detect(dev); return 0; } - -SIMPLE_DEV_PM_OPS(r592_pm_ops, r592_suspend, r592_resume); #endif +static SIMPLE_DEV_PM_OPS(r592_pm_ops, r592_suspend, r592_resume); + MODULE_DEVICE_TABLE(pci, r592_pci_id_tbl); static struct pci_driver r852_pci_driver = { @@ -881,9 +881,7 @@ static struct pci_driver r852_pci_driver = { .id_table = r592_pci_id_tbl, .probe = r592_probe, .remove = r592_remove, -#ifdef CONFIG_PM .driver.pm = &r592_pm_ops, -#endif }; static __init int r592_module_init(void) diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c index 5451beff183f..a60c188c2bd9 100644 --- a/drivers/message/i2o/i2o_config.c +++ b/drivers/message/i2o/i2o_config.c @@ -687,6 +687,11 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, } size = size >> 16; size *= 4; + if (size > sizeof(rmsg)) { + rcode = -EINVAL; + goto sg_list_cleanup; + } + /* Copy in the user's I2O command */ if (copy_from_user(rmsg, user_msg, size)) { rcode = -EFAULT; @@ -922,6 +927,11 @@ static int i2o_cfg_passthru(unsigned long arg) } size = size >> 16; size *= 4; + if (size > sizeof(rmsg)) { + rcode = -EFAULT; + goto sg_list_cleanup; + } + /* Copy in the user's I2O command */ if (copy_from_user(rmsg, user_msg, size)) { rcode = -EFAULT; diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 08a3cf2a7610..9290bb51a06a 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -120,8 +120,8 @@ static void mmc_should_fail_request(struct mmc_host *host, !should_fail(&host->fail_mmc_request, data->blksz * data->blocks)) return; - data->error = data_errors[random32() % ARRAY_SIZE(data_errors)]; - data->bytes_xfered = (random32() % (data->bytes_xfered >> 9)) << 9; + data->error = data_errors[prandom_u32() % ARRAY_SIZE(data_errors)]; + data->bytes_xfered = (prandom_u32() % (data->bytes_xfered >> 9)) << 9; } #else /* CONFIG_FAIL_MMC_REQUEST */ diff --git a/drivers/net/ethernet/broadcom/cnic.c b/drivers/net/ethernet/broadcom/cnic.c index 149a3a038491..5abdd4894082 100644 --- a/drivers/net/ethernet/broadcom/cnic.c +++ b/drivers/net/ethernet/broadcom/cnic.c @@ -4085,7 +4085,7 @@ static int cnic_cm_alloc_mem(struct cnic_dev *dev) if (!cp->csk_tbl) return -ENOMEM; - port_id = random32(); + port_id = prandom_u32(); port_id %= CNIC_LOCAL_PORT_RANGE; if (cnic_init_id_tbl(&cp->csk_port_tbl, CNIC_LOCAL_PORT_RANGE, CNIC_LOCAL_PORT_MIN, port_id)) { @@ -4145,7 +4145,7 @@ static int cnic_cm_init_bnx2_hw(struct cnic_dev *dev) { u32 seed; - seed = random32(); + seed = prandom_u32(); cnic_ctx_wr(dev, 45, 0, seed); return 0; } diff --git a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c index 49b8b58fc5c6..484f77ec2ce1 100644 --- a/drivers/net/hamradio/baycom_epp.c +++ b/drivers/net/hamradio/baycom_epp.c @@ -449,7 +449,7 @@ static int transmit(struct baycom_state *bc, int cnt, unsigned char stat) if ((--bc->hdlctx.slotcnt) > 0) return 0; bc->hdlctx.slotcnt = bc->ch_params.slottime; - if ((random32() % 256) > bc->ch_params.ppersist) + if ((prandom_u32() % 256) > bc->ch_params.ppersist) return 0; } } diff --git a/drivers/net/hamradio/hdlcdrv.c b/drivers/net/hamradio/hdlcdrv.c index a4a3516b6bbf..3169252613fa 100644 --- a/drivers/net/hamradio/hdlcdrv.c +++ b/drivers/net/hamradio/hdlcdrv.c @@ -389,7 +389,7 @@ void hdlcdrv_arbitrate(struct net_device *dev, struct hdlcdrv_state *s) if ((--s->hdlctx.slotcnt) > 0) return; s->hdlctx.slotcnt = s->ch_params.slottime; - if ((random32() % 256) > s->ch_params.ppersist) + if ((prandom_u32() % 256) > s->ch_params.ppersist) return; start_tx(dev, s); } diff --git a/drivers/net/hamradio/yam.c b/drivers/net/hamradio/yam.c index 4cf8f1017aad..ae3feb074f00 100644 --- a/drivers/net/hamradio/yam.c +++ b/drivers/net/hamradio/yam.c @@ -638,7 +638,7 @@ static void yam_arbitrate(struct net_device *dev) yp->slotcnt = yp->slot / 10; /* is random > persist ? */ - if ((random32() % 256) > yp->pers) + if ((prandom_u32() % 256) > yp->pers) return; yam_start_tx(dev, yp); diff --git a/drivers/net/team/team_mode_random.c b/drivers/net/team/team_mode_random.c index 9eabfaa22f3e..5ca14d463ba7 100644 --- a/drivers/net/team/team_mode_random.c +++ b/drivers/net/team/team_mode_random.c @@ -18,7 +18,7 @@ static u32 random_N(unsigned int N) { - return reciprocal_divide(random32(), N); + return reciprocal_divide(prandom_u32(), N); } static bool rnd_transmit(struct team *team, struct sk_buff *skb) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c index 4166e642068b..bca31a855875 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c @@ -1118,7 +1118,7 @@ static void brcmf_p2p_afx_handler(struct work_struct *work) if (afx_hdl->is_listen && afx_hdl->my_listen_chan) /* 100ms ~ 300ms */ err = brcmf_p2p_discover_listen(p2p, afx_hdl->my_listen_chan, - 100 * (1 + (random32() % 3))); + 100 * (1 + (prandom_u32() % 3))); else err = brcmf_p2p_act_frm_search(p2p, afx_hdl->peer_listen_chan); diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index dbf5b1289516..aebf66cdd71f 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -216,7 +216,7 @@ mwifiex_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, mwifiex_form_mgmt_frame(skb, buf, len); mwifiex_queue_tx_pkt(priv, skb); - *cookie = random32() | 1; + *cookie = prandom_u32() | 1; cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, true, GFP_ATOMIC); wiphy_dbg(wiphy, "info: management frame transmitted\n"); @@ -271,7 +271,7 @@ mwifiex_cfg80211_remain_on_channel(struct wiphy *wiphy, duration); if (!ret) { - *cookie = random32() | 1; + *cookie = prandom_u32() | 1; priv->roc_cfg.cookie = *cookie; priv->roc_cfg.chan = *chan; diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 9a907567f41e..edec135b1685 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -1964,9 +1964,6 @@ struct tp_nvram_state { /* kthread for the hotkey poller */ static struct task_struct *tpacpi_hotkey_task; -/* Acquired while the poller kthread is running, use to sync start/stop */ -static struct mutex hotkey_thread_mutex; - /* * Acquire mutex to write poller control variables as an * atomic block. @@ -2462,8 +2459,6 @@ static int hotkey_kthread(void *data) unsigned int poll_freq; bool was_frozen; - mutex_lock(&hotkey_thread_mutex); - if (tpacpi_lifecycle == TPACPI_LIFE_EXITING) goto exit; @@ -2523,7 +2518,6 @@ static int hotkey_kthread(void *data) } exit: - mutex_unlock(&hotkey_thread_mutex); return 0; } @@ -2533,9 +2527,6 @@ static void hotkey_poll_stop_sync(void) if (tpacpi_hotkey_task) { kthread_stop(tpacpi_hotkey_task); tpacpi_hotkey_task = NULL; - mutex_lock(&hotkey_thread_mutex); - /* at this point, the thread did exit */ - mutex_unlock(&hotkey_thread_mutex); } } @@ -3234,7 +3225,6 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) mutex_init(&hotkey_mutex); #ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL - mutex_init(&hotkey_thread_mutex); mutex_init(&hotkey_thread_data_mutex); #endif diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 9b742d3ffb94..66385402d20e 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c @@ -259,6 +259,76 @@ void rtc_device_unregister(struct rtc_device *rtc) } EXPORT_SYMBOL_GPL(rtc_device_unregister); +static void devm_rtc_device_release(struct device *dev, void *res) +{ + struct rtc_device *rtc = *(struct rtc_device **)res; + + rtc_device_unregister(rtc); +} + +static int devm_rtc_device_match(struct device *dev, void *res, void *data) +{ + struct rtc **r = res; + + return *r == data; +} + +/** + * devm_rtc_device_register - resource managed rtc_device_register() + * @dev: the device to register + * @name: the name of the device + * @ops: the rtc operations structure + * @owner: the module owner + * + * @return a struct rtc on success, or an ERR_PTR on error + * + * Managed rtc_device_register(). The rtc_device returned from this function + * are automatically freed on driver detach. See rtc_device_register() + * for more information. + */ + +struct rtc_device *devm_rtc_device_register(struct device *dev, + const char *name, + const struct rtc_class_ops *ops, + struct module *owner) +{ + struct rtc_device **ptr, *rtc; + + ptr = devres_alloc(devm_rtc_device_release, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return ERR_PTR(-ENOMEM); + + rtc = rtc_device_register(name, dev, ops, owner); + if (!IS_ERR(rtc)) { + *ptr = rtc; + devres_add(dev, ptr); + } else { + devres_free(ptr); + } + + return rtc; +} +EXPORT_SYMBOL_GPL(devm_rtc_device_register); + +/** + * devm_rtc_device_unregister - resource managed devm_rtc_device_unregister() + * @dev: the device to unregister + * @rtc: the RTC class device to unregister + * + * Deallocated a rtc allocated with devm_rtc_device_register(). Normally this + * function will not need to be called and the resource management code will + * ensure that the resource is freed. + */ +void devm_rtc_device_unregister(struct device *dev, struct rtc_device *rtc) +{ + int rc; + + rc = devres_release(dev, devm_rtc_device_release, + devm_rtc_device_match, rtc); + WARN_ON(rc); +} +EXPORT_SYMBOL_GPL(devm_rtc_device_unregister); + static int __init rtc_init(void) { rtc_class = class_create(THIS_MODULE, "rtc"); diff --git a/drivers/rtc/rtc-88pm80x.c b/drivers/rtc/rtc-88pm80x.c index 63b17ebe90e8..76f9505ff7c5 100644 --- a/drivers/rtc/rtc-88pm80x.c +++ b/drivers/rtc/rtc-88pm80x.c @@ -312,7 +312,7 @@ static int pm80x_rtc_probe(struct platform_device *pdev) } rtc_tm_to_time(&tm, &ticks); - info->rtc_dev = rtc_device_register("88pm80x-rtc", &pdev->dev, + info->rtc_dev = devm_rtc_device_register(&pdev->dev, "88pm80x-rtc", &pm80x_rtc_ops, THIS_MODULE); if (IS_ERR(info->rtc_dev)) { ret = PTR_ERR(info->rtc_dev); @@ -346,7 +346,6 @@ static int pm80x_rtc_remove(struct platform_device *pdev) { struct pm80x_rtc_info *info = platform_get_drvdata(pdev); platform_set_drvdata(pdev, NULL); - rtc_device_unregister(info->rtc_dev); pm80x_free_irq(info->chip, info->irq, info); return 0; } diff --git a/drivers/rtc/rtc-ab3100.c b/drivers/rtc/rtc-ab3100.c index 261a07e0fb24..47a4f2c4d30e 100644 --- a/drivers/rtc/rtc-ab3100.c +++ b/drivers/rtc/rtc-ab3100.c @@ -229,8 +229,8 @@ static int __init ab3100_rtc_probe(struct platform_device *pdev) /* Ignore any error on this write */ } - rtc = rtc_device_register("ab3100-rtc", &pdev->dev, &ab3100_rtc_ops, - THIS_MODULE); + rtc = devm_rtc_device_register(&pdev->dev, "ab3100-rtc", + &ab3100_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) { err = PTR_ERR(rtc); return err; @@ -242,9 +242,6 @@ static int __init ab3100_rtc_probe(struct platform_device *pdev) static int __exit ab3100_rtc_remove(struct platform_device *pdev) { - struct rtc_device *rtc = platform_get_drvdata(pdev); - - rtc_device_unregister(rtc); platform_set_drvdata(pdev, NULL); return 0; } @@ -257,19 +254,7 @@ static struct platform_driver ab3100_rtc_driver = { .remove = __exit_p(ab3100_rtc_remove), }; -static int __init ab3100_rtc_init(void) -{ - return platform_driver_probe(&ab3100_rtc_driver, - ab3100_rtc_probe); -} - -static void __exit ab3100_rtc_exit(void) -{ - platform_driver_unregister(&ab3100_rtc_driver); -} - -module_init(ab3100_rtc_init); -module_exit(ab3100_rtc_exit); +module_platform_driver_probe(ab3100_rtc_driver, ab3100_rtc_probe); MODULE_AUTHOR("Linus Walleij <linus.walleij@stericsson.com>"); MODULE_DESCRIPTION("AB3100 RTC Driver"); diff --git a/drivers/rtc/rtc-at32ap700x.c b/drivers/rtc/rtc-at32ap700x.c index 8dd08305aae1..619c8877f2f1 100644 --- a/drivers/rtc/rtc-at32ap700x.c +++ b/drivers/rtc/rtc-at32ap700x.c @@ -302,17 +302,7 @@ static struct platform_driver at32_rtc_driver = { }, }; -static int __init at32_rtc_init(void) -{ - return platform_driver_probe(&at32_rtc_driver, at32_rtc_probe); -} -module_init(at32_rtc_init); - -static void __exit at32_rtc_exit(void) -{ - platform_driver_unregister(&at32_rtc_driver); -} -module_exit(at32_rtc_exit); +module_platform_driver_probe(at32_rtc_driver, at32_rtc_probe); MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>"); MODULE_DESCRIPTION("Real time clock for AVR32 AT32AP700x"); diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c index 434ebc3a99dc..f07bd318260c 100644 --- a/drivers/rtc/rtc-at91rm9200.c +++ b/drivers/rtc/rtc-at91rm9200.c @@ -337,7 +337,7 @@ static int __exit at91_rtc_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP /* AT91RM9200 RTC Power management control */ @@ -369,39 +369,20 @@ static int at91_rtc_resume(struct device *dev) } return 0; } - -static const struct dev_pm_ops at91_rtc_pm = { - .suspend = at91_rtc_suspend, - .resume = at91_rtc_resume, -}; - -#define at91_rtc_pm_ptr &at91_rtc_pm - -#else -#define at91_rtc_pm_ptr NULL #endif +static SIMPLE_DEV_PM_OPS(at91_rtc_pm_ops, at91_rtc_suspend, at91_rtc_resume); + static struct platform_driver at91_rtc_driver = { .remove = __exit_p(at91_rtc_remove), .driver = { .name = "at91_rtc", .owner = THIS_MODULE, - .pm = at91_rtc_pm_ptr, + .pm = &at91_rtc_pm_ops, }, }; -static int __init at91_rtc_init(void) -{ - return platform_driver_probe(&at91_rtc_driver, at91_rtc_probe); -} - -static void __exit at91_rtc_exit(void) -{ - platform_driver_unregister(&at91_rtc_driver); -} - -module_init(at91_rtc_init); -module_exit(at91_rtc_exit); +module_platform_driver_probe(at91_rtc_driver, at91_rtc_probe); MODULE_AUTHOR("Rick Bronson"); MODULE_DESCRIPTION("RTC driver for Atmel AT91RM9200"); diff --git a/drivers/rtc/rtc-au1xxx.c b/drivers/rtc/rtc-au1xxx.c index b309da4ec745..7995abc391fc 100644 --- a/drivers/rtc/rtc-au1xxx.c +++ b/drivers/rtc/rtc-au1xxx.c @@ -101,7 +101,7 @@ static int au1xtoy_rtc_probe(struct platform_device *pdev) while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S) msleep(1); - rtcdev = rtc_device_register("rtc-au1xxx", &pdev->dev, + rtcdev = devm_rtc_device_register(&pdev->dev, "rtc-au1xxx", &au1xtoy_rtc_ops, THIS_MODULE); if (IS_ERR(rtcdev)) { ret = PTR_ERR(rtcdev); @@ -118,9 +118,6 @@ out_err: static int au1xtoy_rtc_remove(struct platform_device *pdev) { - struct rtc_device *rtcdev = platform_get_drvdata(pdev); - - rtc_device_unregister(rtcdev); platform_set_drvdata(pdev, NULL); return 0; @@ -134,18 +131,7 @@ static struct platform_driver au1xrtc_driver = { .remove = au1xtoy_rtc_remove, }; -static int __init au1xtoy_rtc_init(void) -{ - return platform_driver_probe(&au1xrtc_driver, au1xtoy_rtc_probe); -} - -static void __exit au1xtoy_rtc_exit(void) -{ - platform_driver_unregister(&au1xrtc_driver); -} - -module_init(au1xtoy_rtc_init); -module_exit(au1xtoy_rtc_exit); +module_platform_driver_probe(au1xrtc_driver, au1xtoy_rtc_probe); MODULE_DESCRIPTION("Au1xxx TOY-counter-based RTC driver"); MODULE_AUTHOR("Manuel Lauss <manuel.lauss@gmail.com>"); diff --git a/drivers/rtc/rtc-bq32k.c b/drivers/rtc/rtc-bq32k.c index 036cb89f8188..fea78bc713ca 100644 --- a/drivers/rtc/rtc-bq32k.c +++ b/drivers/rtc/rtc-bq32k.c @@ -153,7 +153,7 @@ static int bq32k_probe(struct i2c_client *client, if (error) return error; - rtc = rtc_device_register(bq32k_driver.driver.name, &client->dev, + rtc = devm_rtc_device_register(&client->dev, bq32k_driver.driver.name, &bq32k_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) return PTR_ERR(rtc); @@ -165,9 +165,6 @@ static int bq32k_probe(struct i2c_client *client, static int bq32k_remove(struct i2c_client *client) { - struct rtc_device *rtc = i2c_get_clientdata(client); - - rtc_device_unregister(rtc); return 0; } diff --git a/drivers/rtc/rtc-coh901331.c b/drivers/rtc/rtc-coh901331.c index 2d28ec1aa1cd..bf0387f80d2d 100644 --- a/drivers/rtc/rtc-coh901331.c +++ b/drivers/rtc/rtc-coh901331.c @@ -155,7 +155,6 @@ static int __exit coh901331_remove(struct platform_device *pdev) struct coh901331_port *rtap = dev_get_drvdata(&pdev->dev); if (rtap) { - rtc_device_unregister(rtap->rtc); clk_unprepare(rtap->clk); platform_set_drvdata(pdev, NULL); } @@ -211,8 +210,8 @@ static int __init coh901331_probe(struct platform_device *pdev) clk_disable(rtap->clk); platform_set_drvdata(pdev, rtap); - rtap->rtc = rtc_device_register("coh901331", &pdev->dev, &coh901331_ops, - THIS_MODULE); + rtap->rtc = devm_rtc_device_register(&pdev->dev, "coh901331", + &coh901331_ops, THIS_MODULE); if (IS_ERR(rtap->rtc)) { ret = PTR_ERR(rtap->rtc); goto out_no_rtc; @@ -287,18 +286,7 @@ static struct platform_driver coh901331_driver = { .shutdown = coh901331_shutdown, }; -static int __init coh901331_init(void) -{ - return platform_driver_probe(&coh901331_driver, coh901331_probe); -} - -static void __exit coh901331_exit(void) -{ - platform_driver_unregister(&coh901331_driver); -} - -module_init(coh901331_init); -module_exit(coh901331_exit); +module_platform_driver_probe(coh901331_driver, coh901331_probe); MODULE_AUTHOR("Linus Walleij <linus.walleij@stericsson.com>"); MODULE_DESCRIPTION("ST-Ericsson AB COH 901 331 RTC Driver"); diff --git a/drivers/rtc/rtc-da9052.c b/drivers/rtc/rtc-da9052.c index 0dde688ca09b..7286b279cf2d 100644 --- a/drivers/rtc/rtc-da9052.c +++ b/drivers/rtc/rtc-da9052.c @@ -239,17 +239,15 @@ static int da9052_rtc_probe(struct platform_device *pdev) rtc->da9052 = dev_get_drvdata(pdev->dev.parent); platform_set_drvdata(pdev, rtc); - rtc->irq = platform_get_irq_byname(pdev, "ALM"); - ret = devm_request_threaded_irq(&pdev->dev, rtc->irq, NULL, - da9052_rtc_irq, - IRQF_TRIGGER_LOW | IRQF_ONESHOT, - "ALM", rtc); + rtc->irq = DA9052_IRQ_ALARM; + ret = da9052_request_irq(rtc->da9052, rtc->irq, "ALM", + da9052_rtc_irq, rtc); if (ret != 0) { rtc_err(rtc->da9052, "irq registration failed: %d\n", ret); return ret; } - rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, + rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, &da9052_rtc_ops, THIS_MODULE); if (IS_ERR(rtc->rtc)) return PTR_ERR(rtc->rtc); @@ -259,9 +257,6 @@ static int da9052_rtc_probe(struct platform_device *pdev) static int da9052_rtc_remove(struct platform_device *pdev) { - struct da9052_rtc *rtc = pdev->dev.platform_data; - - rtc_device_unregister(rtc->rtc); platform_set_drvdata(pdev, NULL); return 0; diff --git a/drivers/rtc/rtc-da9055.c b/drivers/rtc/rtc-da9055.c index 8f0dcfedb83c..73858ca9709a 100644 --- a/drivers/rtc/rtc-da9055.c +++ b/drivers/rtc/rtc-da9055.c @@ -294,7 +294,7 @@ static int da9055_rtc_probe(struct platform_device *pdev) device_init_wakeup(&pdev->dev, 1); - rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, + rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, &da9055_rtc_ops, THIS_MODULE); if (IS_ERR(rtc->rtc)) { ret = PTR_ERR(rtc->rtc); @@ -317,9 +317,6 @@ err_rtc: static int da9055_rtc_remove(struct platform_device *pdev) { - struct da9055_rtc *rtc = pdev->dev.platform_data; - - rtc_device_unregister(rtc->rtc); platform_set_drvdata(pdev, NULL); return 0; diff --git a/drivers/rtc/rtc-davinci.c b/drivers/rtc/rtc-davinci.c index 56b73089bb29..a55048c3e26f 100644 --- a/drivers/rtc/rtc-davinci.c +++ b/drivers/rtc/rtc-davinci.c @@ -523,7 +523,7 @@ static int __init davinci_rtc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, davinci_rtc); - davinci_rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, + davinci_rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, &davinci_rtc_ops, THIS_MODULE); if (IS_ERR(davinci_rtc->rtc)) { ret = PTR_ERR(davinci_rtc->rtc); @@ -543,7 +543,7 @@ static int __init davinci_rtc_probe(struct platform_device *pdev) 0, "davinci_rtc", davinci_rtc); if (ret < 0) { dev_err(dev, "unable to register davinci RTC interrupt\n"); - goto fail2; + goto fail1; } /* Enable interrupts */ @@ -557,14 +557,12 @@ static int __init davinci_rtc_probe(struct platform_device *pdev) return 0; -fail2: - rtc_device_unregister(davinci_rtc->rtc); fail1: platform_set_drvdata(pdev, NULL); return ret; } -static int davinci_rtc_remove(struct platform_device *pdev) +static int __exit davinci_rtc_remove(struct platform_device *pdev) { struct davinci_rtc *davinci_rtc = platform_get_drvdata(pdev); @@ -572,8 +570,6 @@ static int davinci_rtc_remove(struct platform_device *pdev) rtcif_write(davinci_rtc, 0, PRTCIF_INTEN); - rtc_device_unregister(davinci_rtc->rtc); - platform_set_drvdata(pdev, NULL); return 0; @@ -581,24 +577,14 @@ static int davinci_rtc_remove(struct platform_device *pdev) static struct platform_driver davinci_rtc_driver = { .probe = davinci_rtc_probe, - .remove = davinci_rtc_remove, + .remove = __exit_p(davinci_rtc_remove), .driver = { .name = "rtc_davinci", .owner = THIS_MODULE, }, }; -static int __init rtc_init(void) -{ - return platform_driver_probe(&davinci_rtc_driver, davinci_rtc_probe); -} -module_init(rtc_init); - -static void __exit rtc_exit(void) -{ - platform_driver_unregister(&davinci_rtc_driver); -} -module_exit(rtc_exit); +module_platform_driver_probe(davinci_rtc_driver, davinci_rtc_probe); MODULE_AUTHOR("Miguel Aguilar <miguel.aguilar@ridgerun.com>"); MODULE_DESCRIPTION("Texas Instruments DaVinci PRTC Driver"); diff --git a/drivers/rtc/rtc-dm355evm.c b/drivers/rtc/rtc-dm355evm.c index b2ed2c94b081..1e1ca63d58a9 100644 --- a/drivers/rtc/rtc-dm355evm.c +++ b/drivers/rtc/rtc-dm355evm.c @@ -127,8 +127,8 @@ static int dm355evm_rtc_probe(struct platform_device *pdev) { struct rtc_device *rtc; - rtc = rtc_device_register(pdev->name, - &pdev->dev, &dm355evm_rtc_ops, THIS_MODULE); + rtc = devm_rtc_device_register(&pdev->dev, pdev->name, + &dm355evm_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) { dev_err(&pdev->dev, "can't register RTC device, err %ld\n", PTR_ERR(rtc)); @@ -141,9 +141,6 @@ static int dm355evm_rtc_probe(struct platform_device *pdev) static int dm355evm_rtc_remove(struct platform_device *pdev) { - struct rtc_device *rtc = platform_get_drvdata(pdev); - - rtc_device_unregister(rtc); platform_set_drvdata(pdev, NULL); return 0; } diff --git a/drivers/rtc/rtc-ds1286.c b/drivers/rtc/rtc-ds1286.c index d989412a348a..d120cb8bfcbe 100644 --- a/drivers/rtc/rtc-ds1286.c +++ b/drivers/rtc/rtc-ds1286.c @@ -270,7 +270,6 @@ static int ds1286_set_time(struct device *dev, struct rtc_time *tm) static int ds1286_read_alarm(struct device *dev, struct rtc_wkalrm *alm) { struct ds1286_priv *priv = dev_get_drvdata(dev); - unsigned char cmd; unsigned long flags; /* @@ -281,7 +280,7 @@ static int ds1286_read_alarm(struct device *dev, struct rtc_wkalrm *alm) alm->time.tm_min = ds1286_rtc_read(priv, RTC_MINUTES_ALARM) & 0x7f; alm->time.tm_hour = ds1286_rtc_read(priv, RTC_HOURS_ALARM) & 0x1f; alm->time.tm_wday = ds1286_rtc_read(priv, RTC_DAY_ALARM) & 0x07; - cmd = ds1286_rtc_read(priv, RTC_CMD); + ds1286_rtc_read(priv, RTC_CMD); spin_unlock_irqrestore(&priv->lock, flags); alm->time.tm_min = bcd2bin(alm->time.tm_min); diff --git a/drivers/rtc/rtc-ds1302.c b/drivers/rtc/rtc-ds1302.c index fdbcdb289d60..d13954346286 100644 --- a/drivers/rtc/rtc-ds1302.c +++ b/drivers/rtc/rtc-ds1302.c @@ -224,7 +224,7 @@ static int __init ds1302_rtc_probe(struct platform_device *pdev) return -ENODEV; } - rtc = rtc_device_register("ds1302", &pdev->dev, + rtc = devm_rtc_device_register(&pdev->dev, "ds1302", &ds1302_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) return PTR_ERR(rtc); @@ -234,11 +234,8 @@ static int __init ds1302_rtc_probe(struct platform_device *pdev) return 0; } -static int ds1302_rtc_remove(struct platform_device *pdev) +static int __exit ds1302_rtc_remove(struct platform_device *pdev) { - struct rtc_device *rtc = platform_get_drvdata(pdev); - - rtc_device_unregister(rtc); platform_set_drvdata(pdev, NULL); return 0; @@ -249,21 +246,10 @@ static struct platform_driver ds1302_platform_driver = { .name = DRV_NAME, .owner = THIS_MODULE, }, - .remove = ds1302_rtc_remove, + .remove = __exit_p(ds1302_rtc_remove), }; -static int __init ds1302_rtc_init(void) -{ - return platform_driver_probe(&ds1302_platform_driver, ds1302_rtc_probe); -} - -static void __exit ds1302_rtc_exit(void) -{ - platform_driver_unregister(&ds1302_platform_driver); -} - -module_init(ds1302_rtc_init); -module_exit(ds1302_rtc_exit); +module_platform_driver_probe(ds1302_platform_driver, ds1302_rtc_probe); MODULE_DESCRIPTION("Dallas DS1302 RTC driver"); MODULE_VERSION(DRV_VERSION); diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index 970a236b147a..b859d3c67f11 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c @@ -4,6 +4,7 @@ * Copyright (C) 2005 James Chapman (ds1337 core) * Copyright (C) 2006 David Brownell * Copyright (C) 2009 Matthias Fuchs (rx8025 support) + * Copyright (C) 2012 Bertrand Achard (nvram access fixes) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -196,7 +197,7 @@ static s32 ds1307_read_block_data_once(const struct i2c_client *client, static s32 ds1307_read_block_data(const struct i2c_client *client, u8 command, u8 length, u8 *values) { - u8 oldvalues[I2C_SMBUS_BLOCK_MAX]; + u8 oldvalues[255]; s32 ret; int tries = 0; @@ -222,7 +223,7 @@ static s32 ds1307_read_block_data(const struct i2c_client *client, u8 command, static s32 ds1307_write_block_data(const struct i2c_client *client, u8 command, u8 length, const u8 *values) { - u8 currvalues[I2C_SMBUS_BLOCK_MAX]; + u8 currvalues[255]; int tries = 0; dev_dbg(&client->dev, "ds1307_write_block_data (length=%d)\n", length); @@ -250,6 +251,57 @@ static s32 ds1307_write_block_data(const struct i2c_client *client, u8 command, /*----------------------------------------------------------------------*/ +/* These RTC devices are not designed to be connected to a SMbus adapter. + SMbus limits block operations length to 32 bytes, whereas it's not + limited on I2C buses. As a result, accesses may exceed 32 bytes; + in that case, split them into smaller blocks */ + +static s32 ds1307_native_smbus_write_block_data(const struct i2c_client *client, + u8 command, u8 length, const u8 *values) +{ + u8 suboffset = 0; + + if (length <= I2C_SMBUS_BLOCK_MAX) + return i2c_smbus_write_i2c_block_data(client, + command, length, values); + + while (suboffset < length) { + s32 retval = i2c_smbus_write_i2c_block_data(client, + command + suboffset, + min(I2C_SMBUS_BLOCK_MAX, length - suboffset), + values + suboffset); + if (retval < 0) + return retval; + + suboffset += I2C_SMBUS_BLOCK_MAX; + } + return length; +} + +static s32 ds1307_native_smbus_read_block_data(const struct i2c_client *client, + u8 command, u8 length, u8 *values) +{ + u8 suboffset = 0; + + if (length <= I2C_SMBUS_BLOCK_MAX) + return i2c_smbus_read_i2c_block_data(client, + command, length, values); + + while (suboffset < length) { + s32 retval = i2c_smbus_read_i2c_block_data(client, + command + suboffset, + min(I2C_SMBUS_BLOCK_MAX, length - suboffset), + values + suboffset); + if (retval < 0) + return retval; + + suboffset += I2C_SMBUS_BLOCK_MAX; + } + return length; +} + +/*----------------------------------------------------------------------*/ + /* * The IRQ logic includes a "real" handler running in IRQ context just * long enough to schedule this workqueue entry. We need a task context @@ -646,8 +698,8 @@ static int ds1307_probe(struct i2c_client *client, buf = ds1307->regs; if (i2c_check_functionality(adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { - ds1307->read_block_data = i2c_smbus_read_i2c_block_data; - ds1307->write_block_data = i2c_smbus_write_i2c_block_data; + ds1307->read_block_data = ds1307_native_smbus_read_block_data; + ds1307->write_block_data = ds1307_native_smbus_write_block_data; } else { ds1307->read_block_data = ds1307_read_block_data; ds1307->write_block_data = ds1307_write_block_data; @@ -661,7 +713,7 @@ static int ds1307_probe(struct i2c_client *client, tmp = ds1307->read_block_data(ds1307->client, DS1337_REG_CONTROL, 2, buf); if (tmp != 2) { - pr_debug("read error %d\n", tmp); + dev_dbg(&client->dev, "read error %d\n", tmp); err = -EIO; goto exit_free; } @@ -700,7 +752,7 @@ static int ds1307_probe(struct i2c_client *client, tmp = i2c_smbus_read_i2c_block_data(ds1307->client, RX8025_REG_CTRL1 << 4 | 0x08, 2, buf); if (tmp != 2) { - pr_debug("read error %d\n", tmp); + dev_dbg(&client->dev, "read error %d\n", tmp); err = -EIO; goto exit_free; } @@ -744,7 +796,7 @@ static int ds1307_probe(struct i2c_client *client, tmp = i2c_smbus_read_i2c_block_data(ds1307->client, RX8025_REG_CTRL1 << 4 | 0x08, 2, buf); if (tmp != 2) { - pr_debug("read error %d\n", tmp); + dev_dbg(&client->dev, "read error %d\n", tmp); err = -EIO; goto exit_free; } @@ -772,7 +824,7 @@ read_rtc: /* read RTC registers */ tmp = ds1307->read_block_data(ds1307->client, ds1307->offset, 8, buf); if (tmp != 8) { - pr_debug("read error %d\n", tmp); + dev_dbg(&client->dev, "read error %d\n", tmp); err = -EIO; goto exit_free; } @@ -814,7 +866,7 @@ read_rtc: tmp = i2c_smbus_read_byte_data(client, DS1340_REG_FLAG); if (tmp < 0) { - pr_debug("read error %d\n", tmp); + dev_dbg(&client->dev, "read error %d\n", tmp); err = -EIO; goto exit_free; } diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c index 6a3fcfe3b0e7..6ce8a997cf51 100644 --- a/drivers/rtc/rtc-ds1511.c +++ b/drivers/rtc/rtc-ds1511.c @@ -538,15 +538,14 @@ static int ds1511_rtc_probe(struct platform_device *pdev) } } - rtc = rtc_device_register(pdev->name, &pdev->dev, &ds1511_rtc_ops, - THIS_MODULE); + rtc = devm_rtc_device_register(&pdev->dev, pdev->name, &ds1511_rtc_ops, + THIS_MODULE); if (IS_ERR(rtc)) return PTR_ERR(rtc); pdata->rtc = rtc; ret = sysfs_create_bin_file(&pdev->dev.kobj, &ds1511_nvram_attr); - if (ret) - rtc_device_unregister(pdata->rtc); + return ret; } @@ -555,7 +554,6 @@ static int ds1511_rtc_remove(struct platform_device *pdev) struct rtc_plat_data *pdata = platform_get_drvdata(pdev); sysfs_remove_bin_file(&pdev->dev.kobj, &ds1511_nvram_attr); - rtc_device_unregister(pdata->rtc); if (pdata->irq > 0) { /* * disable the alarm interrupt diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c index 25ce0621ade9..8c6c952e90b1 100644 --- a/drivers/rtc/rtc-ds1553.c +++ b/drivers/rtc/rtc-ds1553.c @@ -326,15 +326,14 @@ static int ds1553_rtc_probe(struct platform_device *pdev) } } - rtc = rtc_device_register(pdev->name, &pdev->dev, + rtc = devm_rtc_device_register(&pdev->dev, pdev->name, &ds1553_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) return PTR_ERR(rtc); pdata->rtc = rtc; ret = sysfs_create_bin_file(&pdev->dev.kobj, &ds1553_nvram_attr); - if (ret) - rtc_device_unregister(rtc); + return ret; } @@ -343,7 +342,6 @@ static int ds1553_rtc_remove(struct platform_device *pdev) struct rtc_plat_data *pdata = platform_get_drvdata(pdev); sysfs_remove_bin_file(&pdev->dev.kobj, &ds1553_nvram_attr); - rtc_device_unregister(pdata->rtc); if (pdata->irq > 0) writeb(0, pdata->ioaddr + RTC_INTERRUPTS); return 0; diff --git a/drivers/rtc/rtc-ds1672.c b/drivers/rtc/rtc-ds1672.c index 45d65c0b3a85..3fc2a4738027 100644 --- a/drivers/rtc/rtc-ds1672.c +++ b/drivers/rtc/rtc-ds1672.c @@ -155,11 +155,6 @@ static const struct rtc_class_ops ds1672_rtc_ops = { static int ds1672_remove(struct i2c_client *client) { - struct rtc_device *rtc = i2c_get_clientdata(client); - - if (rtc) - rtc_device_unregister(rtc); - return 0; } @@ -177,7 +172,7 @@ static int ds1672_probe(struct i2c_client *client, dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); - rtc = rtc_device_register(ds1672_driver.driver.name, &client->dev, + rtc = devm_rtc_device_register(&client->dev, ds1672_driver.driver.name, &ds1672_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) @@ -202,7 +197,6 @@ static int ds1672_probe(struct i2c_client *client, return 0; exit_devreg: - rtc_device_unregister(rtc); return err; } diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c index 609c870e2cc5..eccdc62ae1c0 100644 --- a/drivers/rtc/rtc-ds1742.c +++ b/drivers/rtc/rtc-ds1742.c @@ -208,17 +208,14 @@ static int ds1742_rtc_probe(struct platform_device *pdev) pdata->last_jiffies = jiffies; platform_set_drvdata(pdev, pdata); - rtc = rtc_device_register(pdev->name, &pdev->dev, + rtc = devm_rtc_device_register(&pdev->dev, pdev->name, &ds1742_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) return PTR_ERR(rtc); pdata->rtc = rtc; ret = sysfs_create_bin_file(&pdev->dev.kobj, &pdata->nvram_attr); - if (ret) { - dev_err(&pdev->dev, "creating nvram file in sysfs failed\n"); - rtc_device_unregister(rtc); - } + return ret; } @@ -227,7 +224,6 @@ static int ds1742_rtc_remove(struct platform_device *pdev) struct rtc_plat_data *pdata = platform_get_drvdata(pdev); sysfs_remove_bin_file(&pdev->dev.kobj, &pdata->nvram_attr); - rtc_device_unregister(pdata->rtc); return 0; } diff --git a/drivers/rtc/rtc-ds3234.c b/drivers/rtc/rtc-ds3234.c index 7a4495ef1c39..a66efd49430e 100644 --- a/drivers/rtc/rtc-ds3234.c +++ b/drivers/rtc/rtc-ds3234.c @@ -146,8 +146,8 @@ static int ds3234_probe(struct spi_device *spi) ds3234_get_reg(&spi->dev, DS3234_REG_CONT_STAT, &tmp); dev_info(&spi->dev, "Ctrl/Stat Reg: 0x%02x\n", tmp); - rtc = rtc_device_register("ds3234", - &spi->dev, &ds3234_rtc_ops, THIS_MODULE); + rtc = devm_rtc_device_register(&spi->dev, "ds3234", + &ds3234_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) return PTR_ERR(rtc); @@ -158,9 +158,6 @@ static int ds3234_probe(struct spi_device *spi) static int ds3234_remove(struct spi_device *spi) { - struct rtc_device *rtc = spi_get_drvdata(spi); - - rtc_device_unregister(rtc); return 0; } diff --git a/drivers/rtc/rtc-efi.c b/drivers/rtc/rtc-efi.c index 1a0c37c9152b..b3c8c0b1709d 100644 --- a/drivers/rtc/rtc-efi.c +++ b/drivers/rtc/rtc-efi.c @@ -191,7 +191,7 @@ static int __init efi_rtc_probe(struct platform_device *dev) { struct rtc_device *rtc; - rtc = rtc_device_register("rtc-efi", &dev->dev, &efi_rtc_ops, + rtc = devm_rtc_device_register(&dev->dev, "rtc-efi", &efi_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) return PTR_ERR(rtc); @@ -203,10 +203,6 @@ static int __init efi_rtc_probe(struct platform_device *dev) static int __exit efi_rtc_remove(struct platform_device *dev) { - struct rtc_device *rtc = platform_get_drvdata(dev); - - rtc_device_unregister(rtc); - return 0; } @@ -218,18 +214,7 @@ static struct platform_driver efi_rtc_driver = { .remove = __exit_p(efi_rtc_remove), }; -static int __init efi_rtc_init(void) -{ - return platform_driver_probe(&efi_rtc_driver, efi_rtc_probe); -} - -static void __exit efi_rtc_exit(void) -{ - platform_driver_unregister(&efi_rtc_driver); -} - -module_init(efi_rtc_init); -module_exit(efi_rtc_exit); +module_platform_driver_probe(efi_rtc_driver, efi_rtc_probe); MODULE_AUTHOR("dann frazier <dannf@hp.com>"); MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-em3027.c b/drivers/rtc/rtc-em3027.c index f6c24ce35d36..3f9eb57d0486 100644 --- a/drivers/rtc/rtc-em3027.c +++ b/drivers/rtc/rtc-em3027.c @@ -121,7 +121,7 @@ static int em3027_probe(struct i2c_client *client, if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) return -ENODEV; - rtc = rtc_device_register(em3027_driver.driver.name, &client->dev, + rtc = devm_rtc_device_register(&client->dev, em3027_driver.driver.name, &em3027_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) return PTR_ERR(rtc); @@ -133,11 +133,6 @@ static int em3027_probe(struct i2c_client *client, static int em3027_remove(struct i2c_client *client) { - struct rtc_device *rtc = i2c_get_clientdata(client); - - if (rtc) - rtc_device_unregister(rtc); - return 0; } diff --git a/drivers/rtc/rtc-ep93xx.c b/drivers/rtc/rtc-ep93xx.c index 1a4e5e4a70cd..5807b77c444a 100644 --- a/drivers/rtc/rtc-ep93xx.c +++ b/drivers/rtc/rtc-ep93xx.c @@ -153,8 +153,8 @@ static int ep93xx_rtc_probe(struct platform_device *pdev) pdev->dev.platform_data = ep93xx_rtc; platform_set_drvdata(pdev, ep93xx_rtc); - ep93xx_rtc->rtc = rtc_device_register(pdev->name, - &pdev->dev, &ep93xx_rtc_ops, THIS_MODULE); + ep93xx_rtc->rtc = devm_rtc_device_register(&pdev->dev, + pdev->name, &ep93xx_rtc_ops, THIS_MODULE); if (IS_ERR(ep93xx_rtc->rtc)) { err = PTR_ERR(ep93xx_rtc->rtc); goto exit; @@ -162,12 +162,10 @@ static int ep93xx_rtc_probe(struct platform_device *pdev) err = sysfs_create_group(&pdev->dev.kobj, &ep93xx_rtc_sysfs_files); if (err) - goto fail; + goto exit; return 0; -fail: - rtc_device_unregister(ep93xx_rtc->rtc); exit: platform_set_drvdata(pdev, NULL); pdev->dev.platform_data = NULL; @@ -176,11 +174,8 @@ exit: static int ep93xx_rtc_remove(struct platform_device *pdev) { - struct ep93xx_rtc *ep93xx_rtc = platform_get_drvdata(pdev); - sysfs_remove_group(&pdev->dev.kobj, &ep93xx_rtc_sysfs_files); platform_set_drvdata(pdev, NULL); - rtc_device_unregister(ep93xx_rtc->rtc); pdev->dev.platform_data = NULL; return 0; diff --git a/drivers/rtc/rtc-fm3130.c b/drivers/rtc/rtc-fm3130.c index bff3cdc5140e..4d4ad3fcb5e9 100644 --- a/drivers/rtc/rtc-fm3130.c +++ b/drivers/rtc/rtc-fm3130.c @@ -395,7 +395,7 @@ static int fm3130_probe(struct i2c_client *client, tmp = i2c_transfer(adapter, fm3130->msg, 4); if (tmp != 4) { - pr_debug("read error %d\n", tmp); + dev_dbg(&client->dev, "read error %d\n", tmp); err = -EIO; goto exit_free; } diff --git a/drivers/rtc/rtc-generic.c b/drivers/rtc/rtc-generic.c index 98322004ad2e..06279ce6bff2 100644 --- a/drivers/rtc/rtc-generic.c +++ b/drivers/rtc/rtc-generic.c @@ -38,8 +38,8 @@ static int __init generic_rtc_probe(struct platform_device *dev) { struct rtc_device *rtc; - rtc = rtc_device_register("rtc-generic", &dev->dev, &generic_rtc_ops, - THIS_MODULE); + rtc = devm_rtc_device_register(&dev->dev, "rtc-generic", + &generic_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) return PTR_ERR(rtc); @@ -50,10 +50,6 @@ static int __init generic_rtc_probe(struct platform_device *dev) static int __exit generic_rtc_remove(struct platform_device *dev) { - struct rtc_device *rtc = platform_get_drvdata(dev); - - rtc_device_unregister(rtc); - return 0; } @@ -65,18 +61,7 @@ static struct platform_driver generic_rtc_driver = { .remove = __exit_p(generic_rtc_remove), }; -static int __init generic_rtc_init(void) -{ - return platform_driver_probe(&generic_rtc_driver, generic_rtc_probe); -} - -static void __exit generic_rtc_fini(void) -{ - platform_driver_unregister(&generic_rtc_driver); -} - -module_init(generic_rtc_init); -module_exit(generic_rtc_fini); +module_platform_driver_probe(generic_rtc_driver, generic_rtc_probe); MODULE_AUTHOR("Kyle McMartin <kyle@mcmartin.ca>"); MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-hid-sensor-time.c b/drivers/rtc/rtc-hid-sensor-time.c index 31c5728ef629..63024505dddc 100644 --- a/drivers/rtc/rtc-hid-sensor-time.c +++ b/drivers/rtc/rtc-hid-sensor-time.c @@ -255,8 +255,9 @@ static int hid_time_probe(struct platform_device *pdev) return ret; } - time_state->rtc = rtc_device_register("hid-sensor-time", - &pdev->dev, &hid_time_rtc_ops, THIS_MODULE); + time_state->rtc = devm_rtc_device_register(&pdev->dev, + "hid-sensor-time", &hid_time_rtc_ops, + THIS_MODULE); if (IS_ERR(time_state->rtc)) { dev_err(&pdev->dev, "rtc device register failed!\n"); @@ -269,9 +270,7 @@ static int hid_time_probe(struct platform_device *pdev) static int hid_time_remove(struct platform_device *pdev) { struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; - struct hid_time_state *time_state = platform_get_drvdata(pdev); - rtc_device_unregister(time_state->rtc); sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_TIME); return 0; diff --git a/drivers/rtc/rtc-imxdi.c b/drivers/rtc/rtc-imxdi.c index 82aad695979e..d3a8c8e255de 100644 --- a/drivers/rtc/rtc-imxdi.c +++ b/drivers/rtc/rtc-imxdi.c @@ -369,7 +369,7 @@ static void dryice_work(struct work_struct *work) /* * probe for dryice rtc device */ -static int dryice_rtc_probe(struct platform_device *pdev) +static int __init dryice_rtc_probe(struct platform_device *pdev) { struct resource *res; struct imxdi_dev *imxdi; @@ -464,7 +464,7 @@ static int dryice_rtc_probe(struct platform_device *pdev) } platform_set_drvdata(pdev, imxdi); - imxdi->rtc = rtc_device_register(pdev->name, &pdev->dev, + imxdi->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, &dryice_rtc_ops, THIS_MODULE); if (IS_ERR(imxdi->rtc)) { rc = PTR_ERR(imxdi->rtc); @@ -479,7 +479,7 @@ err: return rc; } -static int dryice_rtc_remove(struct platform_device *pdev) +static int __exit dryice_rtc_remove(struct platform_device *pdev) { struct imxdi_dev *imxdi = platform_get_drvdata(pdev); @@ -488,8 +488,6 @@ static int dryice_rtc_remove(struct platform_device *pdev) /* mask all interrupts */ __raw_writel(0, imxdi->ioaddr + DIER); - rtc_device_unregister(imxdi->rtc); - clk_disable_unprepare(imxdi->clk); return 0; @@ -510,21 +508,10 @@ static struct platform_driver dryice_rtc_driver = { .owner = THIS_MODULE, .of_match_table = of_match_ptr(dryice_dt_ids), }, - .remove = dryice_rtc_remove, + .remove = __exit_p(dryice_rtc_remove), }; -static int __init dryice_rtc_init(void) -{ - return platform_driver_probe(&dryice_rtc_driver, dryice_rtc_probe); -} - -static void __exit dryice_rtc_exit(void) -{ - platform_driver_unregister(&dryice_rtc_driver); -} - -module_init(dryice_rtc_init); -module_exit(dryice_rtc_exit); +module_platform_driver_probe(dryice_rtc_driver, dryice_rtc_probe); MODULE_AUTHOR("Freescale Semiconductor, Inc."); MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>"); diff --git a/drivers/rtc/rtc-lp8788.c b/drivers/rtc/rtc-lp8788.c index 9a4631218f41..9853ac15b296 100644 --- a/drivers/rtc/rtc-lp8788.c +++ b/drivers/rtc/rtc-lp8788.c @@ -299,7 +299,7 @@ static int lp8788_rtc_probe(struct platform_device *pdev) device_init_wakeup(dev, 1); - rtc->rdev = rtc_device_register("lp8788_rtc", dev, + rtc->rdev = devm_rtc_device_register(dev, "lp8788_rtc", &lp8788_rtc_ops, THIS_MODULE); if (IS_ERR(rtc->rdev)) { dev_err(dev, "can not register rtc device\n"); @@ -314,9 +314,6 @@ static int lp8788_rtc_probe(struct platform_device *pdev) static int lp8788_rtc_remove(struct platform_device *pdev) { - struct lp8788_rtc *rtc = platform_get_drvdata(pdev); - - rtc_device_unregister(rtc->rdev); platform_set_drvdata(pdev, NULL); return 0; diff --git a/drivers/rtc/rtc-lpc32xx.c b/drivers/rtc/rtc-lpc32xx.c index 40a598332bac..787550d756e9 100644 --- a/drivers/rtc/rtc-lpc32xx.c +++ b/drivers/rtc/rtc-lpc32xx.c @@ -273,8 +273,8 @@ static int lpc32xx_rtc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, rtc); - rtc->rtc = rtc_device_register(RTC_NAME, &pdev->dev, &lpc32xx_rtc_ops, - THIS_MODULE); + rtc->rtc = devm_rtc_device_register(&pdev->dev, RTC_NAME, + &lpc32xx_rtc_ops, THIS_MODULE); if (IS_ERR(rtc->rtc)) { dev_err(&pdev->dev, "Can't get RTC\n"); platform_set_drvdata(pdev, NULL); @@ -307,7 +307,6 @@ static int lpc32xx_rtc_remove(struct platform_device *pdev) device_init_wakeup(&pdev->dev, 0); platform_set_drvdata(pdev, NULL); - rtc_device_unregister(rtc->rtc); return 0; } diff --git a/drivers/rtc/rtc-ls1x.c b/drivers/rtc/rtc-ls1x.c index f59b6349551a..db82f91f4562 100644 --- a/drivers/rtc/rtc-ls1x.c +++ b/drivers/rtc/rtc-ls1x.c @@ -172,7 +172,7 @@ static int ls1x_rtc_probe(struct platform_device *pdev) while (readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_TTS) usleep_range(1000, 3000); - rtcdev = rtc_device_register("ls1x-rtc", &pdev->dev, + rtcdev = devm_rtc_device_register(&pdev->dev, "ls1x-rtc", &ls1x_rtc_ops , THIS_MODULE); if (IS_ERR(rtcdev)) { ret = PTR_ERR(rtcdev); @@ -187,9 +187,6 @@ err: static int ls1x_rtc_remove(struct platform_device *pdev) { - struct rtc_device *rtcdev = platform_get_drvdata(pdev); - - rtc_device_unregister(rtcdev); platform_set_drvdata(pdev, NULL); return 0; diff --git a/drivers/rtc/rtc-m41t93.c b/drivers/rtc/rtc-m41t93.c index 49169680786e..cfc21a1608ab 100644 --- a/drivers/rtc/rtc-m41t93.c +++ b/drivers/rtc/rtc-m41t93.c @@ -184,8 +184,8 @@ static int m41t93_probe(struct spi_device *spi) return -ENODEV; } - rtc = rtc_device_register(m41t93_driver.driver.name, - &spi->dev, &m41t93_rtc_ops, THIS_MODULE); + rtc = devm_rtc_device_register(&spi->dev, m41t93_driver.driver.name, + &m41t93_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) return PTR_ERR(rtc); @@ -197,11 +197,6 @@ static int m41t93_probe(struct spi_device *spi) static int m41t93_remove(struct spi_device *spi) { - struct rtc_device *rtc = spi_get_drvdata(spi); - - if (rtc) - rtc_device_unregister(rtc); - return 0; } diff --git a/drivers/rtc/rtc-m41t94.c b/drivers/rtc/rtc-m41t94.c index 89266c6764bc..cf655a91e385 100644 --- a/drivers/rtc/rtc-m41t94.c +++ b/drivers/rtc/rtc-m41t94.c @@ -124,8 +124,8 @@ static int m41t94_probe(struct spi_device *spi) return res; } - rtc = rtc_device_register(m41t94_driver.driver.name, - &spi->dev, &m41t94_rtc_ops, THIS_MODULE); + rtc = devm_rtc_device_register(&spi->dev, m41t94_driver.driver.name, + &m41t94_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) return PTR_ERR(rtc); @@ -136,11 +136,6 @@ static int m41t94_probe(struct spi_device *spi) static int m41t94_remove(struct spi_device *spi) { - struct rtc_device *rtc = spi_get_drvdata(spi); - - if (rtc) - rtc_device_unregister(rtc); - return 0; } diff --git a/drivers/rtc/rtc-m48t86.c b/drivers/rtc/rtc-m48t86.c index 2ffbcacd2439..33a91c484533 100644 --- a/drivers/rtc/rtc-m48t86.c +++ b/drivers/rtc/rtc-m48t86.c @@ -148,8 +148,10 @@ static int m48t86_rtc_probe(struct platform_device *dev) { unsigned char reg; struct m48t86_ops *ops = dev->dev.platform_data; - struct rtc_device *rtc = rtc_device_register("m48t86", - &dev->dev, &m48t86_rtc_ops, THIS_MODULE); + struct rtc_device *rtc; + + rtc = devm_rtc_device_register(&dev->dev, "m48t86", + &m48t86_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) return PTR_ERR(rtc); @@ -166,11 +168,6 @@ static int m48t86_rtc_probe(struct platform_device *dev) static int m48t86_rtc_remove(struct platform_device *dev) { - struct rtc_device *rtc = platform_get_drvdata(dev); - - if (rtc) - rtc_device_unregister(rtc); - platform_set_drvdata(dev, NULL); return 0; diff --git a/drivers/rtc/rtc-max6900.c b/drivers/rtc/rtc-max6900.c index a00e33204b91..8669d6d09a00 100644 --- a/drivers/rtc/rtc-max6900.c +++ b/drivers/rtc/rtc-max6900.c @@ -214,11 +214,6 @@ static int max6900_rtc_set_time(struct device *dev, struct rtc_time *tm) static int max6900_remove(struct i2c_client *client) { - struct rtc_device *rtc = i2c_get_clientdata(client); - - if (rtc) - rtc_device_unregister(rtc); - return 0; } @@ -237,8 +232,8 @@ max6900_probe(struct i2c_client *client, const struct i2c_device_id *id) dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); - rtc = rtc_device_register(max6900_driver.driver.name, - &client->dev, &max6900_rtc_ops, THIS_MODULE); + rtc = devm_rtc_device_register(&client->dev, max6900_driver.driver.name, + &max6900_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) return PTR_ERR(rtc); diff --git a/drivers/rtc/rtc-max6902.c b/drivers/rtc/rtc-max6902.c index 7d0bf698b79e..7e4491b1f90b 100644 --- a/drivers/rtc/rtc-max6902.c +++ b/drivers/rtc/rtc-max6902.c @@ -134,8 +134,8 @@ static int max6902_probe(struct spi_device *spi) if (res != 0) return res; - rtc = rtc_device_register("max6902", - &spi->dev, &max6902_rtc_ops, THIS_MODULE); + rtc = devm_rtc_device_register(&spi->dev, "max6902", + &max6902_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) return PTR_ERR(rtc); @@ -145,9 +145,6 @@ static int max6902_probe(struct spi_device *spi) static int max6902_remove(struct spi_device *spi) { - struct rtc_device *rtc = dev_get_drvdata(&spi->dev); - - rtc_device_unregister(rtc); return 0; } diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c index 6b1337f9baf4..5a12b32f77ec 100644 --- a/drivers/rtc/rtc-max77686.c +++ b/drivers/rtc/rtc-max77686.c @@ -24,7 +24,7 @@ /* RTC Control Register */ #define BCD_EN_SHIFT 0 -#define BCD_EN_MASK (1 << BCD_EN_SHIFT) +#define BCD_EN_MASK (1 << BCD_EN_SHIFT) #define MODEL24_SHIFT 1 #define MODEL24_MASK (1 << MODEL24_SHIFT) /* RTC Update Register1 */ @@ -33,12 +33,12 @@ #define RTC_RBUDR_SHIFT 4 #define RTC_RBUDR_MASK (1 << RTC_RBUDR_SHIFT) /* WTSR and SMPL Register */ -#define WTSRT_SHIFT 0 -#define SMPLT_SHIFT 2 +#define WTSRT_SHIFT 0 +#define SMPLT_SHIFT 2 #define WTSR_EN_SHIFT 6 #define SMPL_EN_SHIFT 7 -#define WTSRT_MASK (3 << WTSRT_SHIFT) -#define SMPLT_MASK (3 << SMPLT_SHIFT) +#define WTSRT_MASK (3 << WTSRT_SHIFT) +#define SMPLT_MASK (3 << SMPLT_SHIFT) #define WTSR_EN_MASK (1 << WTSR_EN_SHIFT) #define SMPL_EN_MASK (1 << SMPL_EN_SHIFT) /* RTC Hour register */ @@ -466,7 +466,7 @@ static void max77686_rtc_enable_smpl(struct max77686_rtc_info *info, bool enable val = 0; regmap_read(info->max77686->rtc_regmap, MAX77686_WTSR_SMPL_CNTL, &val); - pr_info("%s: WTSR_SMPL(0x%02x)\n", __func__, val); + dev_info(info->dev, "%s: WTSR_SMPL(0x%02x)\n", __func__, val); } #endif /* MAX77686_RTC_WTSR_SMPL */ @@ -505,7 +505,8 @@ static int max77686_rtc_probe(struct platform_device *pdev) dev_info(&pdev->dev, "%s\n", __func__); - info = kzalloc(sizeof(struct max77686_rtc_info), GFP_KERNEL); + info = devm_kzalloc(&pdev->dev, sizeof(struct max77686_rtc_info), + GFP_KERNEL); if (!info) return -ENOMEM; @@ -519,7 +520,6 @@ static int max77686_rtc_probe(struct platform_device *pdev) ret = PTR_ERR(info->max77686->rtc_regmap); dev_err(info->max77686->dev, "Failed to allocate register map: %d\n", ret); - kfree(info); return ret; } platform_set_drvdata(pdev, info); @@ -538,8 +538,8 @@ static int max77686_rtc_probe(struct platform_device *pdev) device_init_wakeup(&pdev->dev, 1); - info->rtc_dev = rtc_device_register("max77686-rtc", &pdev->dev, - &max77686_rtc_ops, THIS_MODULE); + info->rtc_dev = devm_rtc_device_register(&pdev->dev, "max77686-rtc", + &max77686_rtc_ops, THIS_MODULE); if (IS_ERR(info->rtc_dev)) { dev_info(&pdev->dev, "%s: fail\n", __func__); @@ -555,32 +555,20 @@ static int max77686_rtc_probe(struct platform_device *pdev) goto err_rtc; info->virq = virq; - ret = request_threaded_irq(virq, NULL, max77686_rtc_alarm_irq, 0, - "rtc-alarm0", info); + ret = devm_request_threaded_irq(&pdev->dev, virq, NULL, + max77686_rtc_alarm_irq, 0, "rtc-alarm0", info); if (ret < 0) { dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n", info->virq, ret); goto err_rtc; } - goto out; err_rtc: - kfree(info); - return ret; -out: return ret; } static int max77686_rtc_remove(struct platform_device *pdev) { - struct max77686_rtc_info *info = platform_get_drvdata(pdev); - - if (info) { - free_irq(info->virq, info); - rtc_device_unregister(info->rtc_dev); - kfree(info); - } - return 0; } @@ -594,11 +582,14 @@ static void max77686_rtc_shutdown(struct platform_device *pdev) for (i = 0; i < 3; i++) { max77686_rtc_enable_wtsr(info, false); regmap_read(info->max77686->rtc_regmap, MAX77686_WTSR_SMPL_CNTL, &val); - pr_info("%s: WTSR_SMPL reg(0x%02x)\n", __func__, val); - if (val & WTSR_EN_MASK) - pr_emerg("%s: fail to disable WTSR\n", __func__); - else { - pr_info("%s: success to disable WTSR\n", __func__); + dev_info(info->dev, "%s: WTSR_SMPL reg(0x%02x)\n", __func__, + val); + if (val & WTSR_EN_MASK) { + dev_emerg(info->dev, "%s: fail to disable WTSR\n", + __func__); + } else { + dev_info(info->dev, "%s: success to disable WTSR\n", + __func__); break; } } @@ -624,18 +615,8 @@ static struct platform_driver max77686_rtc_driver = { .id_table = rtc_id, }; -static int __init max77686_rtc_init(void) -{ - return platform_driver_register(&max77686_rtc_driver); -} -module_init(max77686_rtc_init); - -static void __exit max77686_rtc_exit(void) -{ - platform_driver_unregister(&max77686_rtc_driver); -} -module_exit(max77686_rtc_exit); +module_platform_driver(max77686_rtc_driver); MODULE_DESCRIPTION("Maxim MAX77686 RTC driver"); -MODULE_AUTHOR("<woong.byun@samsung.com>"); +MODULE_AUTHOR("Chiwoong Byun <woong.byun@samsung.com>"); MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-max8907.c b/drivers/rtc/rtc-max8907.c index 31ca8faf9f05..9d62cdb83d11 100644 --- a/drivers/rtc/rtc-max8907.c +++ b/drivers/rtc/rtc-max8907.c @@ -190,7 +190,7 @@ static int max8907_rtc_probe(struct platform_device *pdev) rtc->max8907 = max8907; rtc->regmap = max8907->regmap_rtc; - rtc->rtc_dev = rtc_device_register("max8907-rtc", &pdev->dev, + rtc->rtc_dev = devm_rtc_device_register(&pdev->dev, "max8907-rtc", &max8907_rtc_ops, THIS_MODULE); if (IS_ERR(rtc->rtc_dev)) { ret = PTR_ERR(rtc->rtc_dev); @@ -217,16 +217,11 @@ static int max8907_rtc_probe(struct platform_device *pdev) return 0; err_unregister: - rtc_device_unregister(rtc->rtc_dev); return ret; } static int max8907_rtc_remove(struct platform_device *pdev) { - struct max8907_rtc *rtc = platform_get_drvdata(pdev); - - rtc_device_unregister(rtc->rtc_dev); - return 0; } diff --git a/drivers/rtc/rtc-max8997.c b/drivers/rtc/rtc-max8997.c index 00e505b6bee3..d12acc49c822 100644 --- a/drivers/rtc/rtc-max8997.c +++ b/drivers/rtc/rtc-max8997.c @@ -479,8 +479,8 @@ static int max8997_rtc_probe(struct platform_device *pdev) device_init_wakeup(&pdev->dev, 1); - info->rtc_dev = rtc_device_register("max8997-rtc", &pdev->dev, - &max8997_rtc_ops, THIS_MODULE); + info->rtc_dev = devm_rtc_device_register(&pdev->dev, "max8997-rtc", + &max8997_rtc_ops, THIS_MODULE); if (IS_ERR(info->rtc_dev)) { ret = PTR_ERR(info->rtc_dev); @@ -507,17 +507,11 @@ static int max8997_rtc_probe(struct platform_device *pdev) return ret; err_out: - rtc_device_unregister(info->rtc_dev); return ret; } static int max8997_rtc_remove(struct platform_device *pdev) { - struct max8997_rtc_info *info = platform_get_drvdata(pdev); - - if (info) - rtc_device_unregister(info->rtc_dev); - return 0; } diff --git a/drivers/rtc/rtc-mc13xxx.c b/drivers/rtc/rtc-mc13xxx.c index 2643d8874925..5391b154b43c 100644 --- a/drivers/rtc/rtc-mc13xxx.c +++ b/drivers/rtc/rtc-mc13xxx.c @@ -420,17 +420,7 @@ static struct platform_driver mc13xxx_rtc_driver = { }, }; -static int __init mc13xxx_rtc_init(void) -{ - return platform_driver_probe(&mc13xxx_rtc_driver, &mc13xxx_rtc_probe); -} -module_init(mc13xxx_rtc_init); - -static void __exit mc13xxx_rtc_exit(void) -{ - platform_driver_unregister(&mc13xxx_rtc_driver); -} -module_exit(mc13xxx_rtc_exit); +module_platform_driver_probe(mc13xxx_rtc_driver, &mc13xxx_rtc_probe); MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); MODULE_DESCRIPTION("RTC driver for Freescale MC13XXX PMIC"); diff --git a/drivers/rtc/rtc-msm6242.c b/drivers/rtc/rtc-msm6242.c index fcb113c11122..3ac1e8eca89d 100644 --- a/drivers/rtc/rtc-msm6242.c +++ b/drivers/rtc/rtc-msm6242.c @@ -252,18 +252,7 @@ static struct platform_driver msm6242_rtc_driver = { .remove = __exit_p(msm6242_rtc_remove), }; -static int __init msm6242_rtc_init(void) -{ - return platform_driver_probe(&msm6242_rtc_driver, msm6242_rtc_probe); -} - -static void __exit msm6242_rtc_fini(void) -{ - platform_driver_unregister(&msm6242_rtc_driver); -} - -module_init(msm6242_rtc_init); -module_exit(msm6242_rtc_fini); +module_platform_driver_probe(msm6242_rtc_driver, msm6242_rtc_probe); MODULE_AUTHOR("Geert Uytterhoeven <geert@linux-m68k.org>"); MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-mv.c b/drivers/rtc/rtc-mv.c index 8f87fec27ce7..baab802f2153 100644 --- a/drivers/rtc/rtc-mv.c +++ b/drivers/rtc/rtc-mv.c @@ -217,7 +217,7 @@ static const struct rtc_class_ops mv_rtc_alarm_ops = { .alarm_irq_enable = mv_rtc_alarm_irq_enable, }; -static int mv_rtc_probe(struct platform_device *pdev) +static int __init mv_rtc_probe(struct platform_device *pdev) { struct resource *res; struct rtc_plat_data *pdata; @@ -272,12 +272,13 @@ static int mv_rtc_probe(struct platform_device *pdev) if (pdata->irq >= 0) { device_init_wakeup(&pdev->dev, 1); - pdata->rtc = rtc_device_register(pdev->name, &pdev->dev, + pdata->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, &mv_rtc_alarm_ops, THIS_MODULE); - } else - pdata->rtc = rtc_device_register(pdev->name, &pdev->dev, + } else { + pdata->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, &mv_rtc_ops, THIS_MODULE); + } if (IS_ERR(pdata->rtc)) { ret = PTR_ERR(pdata->rtc); goto out; @@ -308,7 +309,6 @@ static int __exit mv_rtc_remove(struct platform_device *pdev) if (pdata->irq >= 0) device_init_wakeup(&pdev->dev, 0); - rtc_device_unregister(pdata->rtc); if (!IS_ERR(pdata->clk)) clk_disable_unprepare(pdata->clk); @@ -331,18 +331,7 @@ static struct platform_driver mv_rtc_driver = { }, }; -static __init int mv_init(void) -{ - return platform_driver_probe(&mv_rtc_driver, mv_rtc_probe); -} - -static __exit void mv_exit(void) -{ - platform_driver_unregister(&mv_rtc_driver); -} - -module_init(mv_init); -module_exit(mv_exit); +module_platform_driver_probe(mv_rtc_driver, mv_rtc_probe); MODULE_AUTHOR("Saeed Bishara <saeed@marvell.com>"); MODULE_DESCRIPTION("Marvell RTC driver"); diff --git a/drivers/rtc/rtc-mxc.c b/drivers/rtc/rtc-mxc.c index 1c3ef7289565..9a3895bc4f4d 100644 --- a/drivers/rtc/rtc-mxc.c +++ b/drivers/rtc/rtc-mxc.c @@ -439,7 +439,7 @@ static int mxc_rtc_probe(struct platform_device *pdev) if (pdata->irq >=0) device_init_wakeup(&pdev->dev, 1); - rtc = rtc_device_register(pdev->name, &pdev->dev, &mxc_rtc_ops, + rtc = devm_rtc_device_register(&pdev->dev, pdev->name, &mxc_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) { ret = PTR_ERR(rtc); @@ -464,15 +464,13 @@ static int mxc_rtc_remove(struct platform_device *pdev) { struct rtc_plat_data *pdata = platform_get_drvdata(pdev); - rtc_device_unregister(pdata->rtc); - clk_disable_unprepare(pdata->clk); platform_set_drvdata(pdev, NULL); return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int mxc_rtc_suspend(struct device *dev) { struct rtc_plat_data *pdata = dev_get_drvdata(dev); @@ -492,19 +490,14 @@ static int mxc_rtc_resume(struct device *dev) return 0; } - -static struct dev_pm_ops mxc_rtc_pm_ops = { - .suspend = mxc_rtc_suspend, - .resume = mxc_rtc_resume, -}; #endif +static SIMPLE_DEV_PM_OPS(mxc_rtc_pm_ops, mxc_rtc_suspend, mxc_rtc_resume); + static struct platform_driver mxc_rtc_driver = { .driver = { .name = "mxc_rtc", -#ifdef CONFIG_PM .pm = &mxc_rtc_pm_ops, -#endif .owner = THIS_MODULE, }, .id_table = imx_rtc_devtype, diff --git a/drivers/rtc/rtc-nuc900.c b/drivers/rtc/rtc-nuc900.c index a63680850fef..4d9525cc1cf4 100644 --- a/drivers/rtc/rtc-nuc900.c +++ b/drivers/rtc/rtc-nuc900.c @@ -222,7 +222,7 @@ static struct rtc_class_ops nuc900_rtc_ops = { .alarm_irq_enable = nuc900_alarm_irq_enable, }; -static int nuc900_rtc_probe(struct platform_device *pdev) +static int __init nuc900_rtc_probe(struct platform_device *pdev) { struct resource *res; struct nuc900_rtc *nuc900_rtc; @@ -284,7 +284,7 @@ fail1: kfree(nuc900_rtc); return err; } -static int nuc900_rtc_remove(struct platform_device *pdev) +static int __exit nuc900_rtc_remove(struct platform_device *pdev) { struct nuc900_rtc *nuc900_rtc = platform_get_drvdata(pdev); struct resource *res; @@ -304,25 +304,14 @@ static int nuc900_rtc_remove(struct platform_device *pdev) } static struct platform_driver nuc900_rtc_driver = { - .remove = nuc900_rtc_remove, + .remove = __exit_p(nuc900_rtc_remove), .driver = { .name = "nuc900-rtc", .owner = THIS_MODULE, }, }; -static int __init nuc900_rtc_init(void) -{ - return platform_driver_probe(&nuc900_rtc_driver, nuc900_rtc_probe); -} - -static void __exit nuc900_rtc_exit(void) -{ - platform_driver_unregister(&nuc900_rtc_driver); -} - -module_init(nuc900_rtc_init); -module_exit(nuc900_rtc_exit); +module_platform_driver_probe(nuc900_rtc_driver, nuc900_rtc_probe); MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>"); MODULE_DESCRIPTION("nuc910/nuc920 RTC driver"); diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index 600971407aac..172cc5ca7489 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c @@ -550,17 +550,7 @@ static struct platform_driver omap_rtc_driver = { .id_table = omap_rtc_devtype, }; -static int __init rtc_init(void) -{ - return platform_driver_probe(&omap_rtc_driver, omap_rtc_probe); -} -module_init(rtc_init); - -static void __exit rtc_exit(void) -{ - platform_driver_unregister(&omap_rtc_driver); -} -module_exit(rtc_exit); +module_platform_driver_probe(omap_rtc_driver, omap_rtc_probe); MODULE_AUTHOR("George G. Davis (and others)"); MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-palmas.c b/drivers/rtc/rtc-palmas.c index 59c42986254e..bbc3b9efdeb2 100644 --- a/drivers/rtc/rtc-palmas.c +++ b/drivers/rtc/rtc-palmas.c @@ -264,7 +264,7 @@ static int palmas_rtc_probe(struct platform_device *pdev) palmas_rtc->irq = platform_get_irq(pdev, 0); - palmas_rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, + palmas_rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, &palmas_rtc_ops, THIS_MODULE); if (IS_ERR(palmas_rtc->rtc)) { ret = PTR_ERR(palmas_rtc->rtc); @@ -272,14 +272,13 @@ static int palmas_rtc_probe(struct platform_device *pdev) return ret; } - ret = request_threaded_irq(palmas_rtc->irq, NULL, + ret = devm_request_threaded_irq(&pdev->dev, palmas_rtc->irq, NULL, palmas_rtc_interrupt, IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_EARLY_RESUME, dev_name(&pdev->dev), palmas_rtc); if (ret < 0) { dev_err(&pdev->dev, "IRQ request failed, err = %d\n", ret); - rtc_device_unregister(palmas_rtc->rtc); return ret; } @@ -289,11 +288,7 @@ static int palmas_rtc_probe(struct platform_device *pdev) static int palmas_rtc_remove(struct platform_device *pdev) { - struct palmas_rtc *palmas_rtc = platform_get_drvdata(pdev); - palmas_rtc_alarm_irq_enable(&pdev->dev, 0); - free_irq(palmas_rtc->irq, palmas_rtc); - rtc_device_unregister(palmas_rtc->rtc); return 0; } diff --git a/drivers/rtc/rtc-pcap.c b/drivers/rtc/rtc-pcap.c index e0019cd0bf71..ce0982490e8c 100644 --- a/drivers/rtc/rtc-pcap.c +++ b/drivers/rtc/rtc-pcap.c @@ -139,7 +139,7 @@ static const struct rtc_class_ops pcap_rtc_ops = { .alarm_irq_enable = pcap_rtc_alarm_irq_enable, }; -static int pcap_rtc_probe(struct platform_device *pdev) +static int __init pcap_rtc_probe(struct platform_device *pdev) { struct pcap_rtc *pcap_rtc; int timer_irq, alarm_irq; @@ -183,7 +183,7 @@ fail_rtc: return err; } -static int pcap_rtc_remove(struct platform_device *pdev) +static int __exit pcap_rtc_remove(struct platform_device *pdev) { struct pcap_rtc *pcap_rtc = platform_get_drvdata(pdev); @@ -196,25 +196,14 @@ static int pcap_rtc_remove(struct platform_device *pdev) } static struct platform_driver pcap_rtc_driver = { - .remove = pcap_rtc_remove, + .remove = __exit_p(pcap_rtc_remove), .driver = { .name = "pcap-rtc", .owner = THIS_MODULE, }, }; -static int __init rtc_pcap_init(void) -{ - return platform_driver_probe(&pcap_rtc_driver, pcap_rtc_probe); -} - -static void __exit rtc_pcap_exit(void) -{ - platform_driver_unregister(&pcap_rtc_driver); -} - -module_init(rtc_pcap_init); -module_exit(rtc_pcap_exit); +module_platform_driver_probe(pcap_rtc_driver, pcap_rtc_probe); MODULE_DESCRIPTION("Motorola pcap rtc driver"); MODULE_AUTHOR("guiming zhuo <gmzhuo@gmail.com>"); diff --git a/drivers/rtc/rtc-pcf8523.c b/drivers/rtc/rtc-pcf8523.c index 889e3160e701..305c9515e5bb 100644 --- a/drivers/rtc/rtc-pcf8523.c +++ b/drivers/rtc/rtc-pcf8523.c @@ -307,7 +307,7 @@ static int pcf8523_probe(struct i2c_client *client, if (err < 0) return err; - pcf->rtc = rtc_device_register(DRIVER_NAME, &client->dev, + pcf->rtc = devm_rtc_device_register(&client->dev, DRIVER_NAME, &pcf8523_rtc_ops, THIS_MODULE); if (IS_ERR(pcf->rtc)) return PTR_ERR(pcf->rtc); @@ -319,10 +319,6 @@ static int pcf8523_probe(struct i2c_client *client, static int pcf8523_remove(struct i2c_client *client) { - struct pcf8523 *pcf = i2c_get_clientdata(client); - - rtc_device_unregister(pcf->rtc); - return 0; } diff --git a/drivers/rtc/rtc-ps3.c b/drivers/rtc/rtc-ps3.c index 968133ce1ee8..4bb825bb5804 100644 --- a/drivers/rtc/rtc-ps3.c +++ b/drivers/rtc/rtc-ps3.c @@ -62,7 +62,7 @@ static int __init ps3_rtc_probe(struct platform_device *dev) { struct rtc_device *rtc; - rtc = rtc_device_register("rtc-ps3", &dev->dev, &ps3_rtc_ops, + rtc = devm_rtc_device_register(&dev->dev, "rtc-ps3", &ps3_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) return PTR_ERR(rtc); @@ -73,7 +73,6 @@ static int __init ps3_rtc_probe(struct platform_device *dev) static int __exit ps3_rtc_remove(struct platform_device *dev) { - rtc_device_unregister(platform_get_drvdata(dev)); return 0; } @@ -85,18 +84,7 @@ static struct platform_driver ps3_rtc_driver = { .remove = __exit_p(ps3_rtc_remove), }; -static int __init ps3_rtc_init(void) -{ - return platform_driver_probe(&ps3_rtc_driver, ps3_rtc_probe); -} - -static void __exit ps3_rtc_fini(void) -{ - platform_driver_unregister(&ps3_rtc_driver); -} - -module_init(ps3_rtc_init); -module_exit(ps3_rtc_fini); +module_platform_driver_probe(ps3_rtc_driver, ps3_rtc_probe); MODULE_AUTHOR("Sony Corporation"); MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-pxa.c b/drivers/rtc/rtc-pxa.c index 03c85ee719a7..a2c75c1ed4cc 100644 --- a/drivers/rtc/rtc-pxa.c +++ b/drivers/rtc/rtc-pxa.c @@ -19,6 +19,7 @@ * */ +#include <linux/delay.h> #include <linux/init.h> #include <linux/platform_device.h> #include <linux/module.h> @@ -80,22 +81,29 @@ #define RYAR1 0x1c #define RTCPICR 0x34 #define PIAR 0x38 +#define PSBR_RTC 0x00 #define rtc_readl(pxa_rtc, reg) \ __raw_readl((pxa_rtc)->base + (reg)) #define rtc_writel(pxa_rtc, reg, value) \ __raw_writel((value), (pxa_rtc)->base + (reg)) +#define rtc_readl_psbr(pxa_rtc, reg) \ + __raw_readl((pxa_rtc)->base_psbr + (reg)) +#define rtc_writel_psbr(pxa_rtc, reg, value) \ + __raw_writel((value), (pxa_rtc)->base_psbr + (reg)) struct pxa_rtc { struct resource *ress; + struct resource *ress_psbr; void __iomem *base; + void __iomem *base_psbr; int irq_1Hz; int irq_Alrm; struct rtc_device *rtc; spinlock_t lock; /* Protects this structure */ }; - +static struct pxa_rtc *rtc_info; static u32 ryxr_calc(struct rtc_time *tm) { return ((tm->tm_year + 1900) << RYxR_YEAR_S) @@ -117,7 +125,7 @@ static void tm_calc(u32 rycr, u32 rdcr, struct rtc_time *tm) tm->tm_year = ((rycr & RYxR_YEAR_MASK) >> RYxR_YEAR_S) - 1900; tm->tm_mon = (((rycr & RYxR_MONTH_MASK) >> RYxR_MONTH_S)) - 1; tm->tm_mday = (rycr & RYxR_DAY_MASK); - tm->tm_wday = ((rycr & RDxR_DOW_MASK) >> RDxR_DOW_S) - 1; + tm->tm_wday = ((rdcr & RDxR_DOW_MASK) >> RDxR_DOW_S) - 1; tm->tm_hour = (rdcr & RDxR_HOUR_MASK) >> RDxR_HOUR_S; tm->tm_min = (rdcr & RDxR_MIN_MASK) >> RDxR_MIN_S; tm->tm_sec = rdcr & RDxR_SEC_MASK; @@ -175,7 +183,6 @@ static irqreturn_t pxa_rtc_irq(int irq, void *dev_id) /* enable back rtc interrupts */ rtc_writel(pxa_rtc, RTSR, rtsr & ~RTSR_TRIG_MASK); - spin_unlock(&pxa_rtc->lock); return IRQ_HANDLED; } @@ -250,12 +257,45 @@ static int pxa_rtc_read_time(struct device *dev, struct rtc_time *tm) static int pxa_rtc_set_time(struct device *dev, struct rtc_time *tm) { struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev); - + /* sequence to wirte pxa rtc register RCNR RDCR RYCR is + *1. set PSBR[RWE] bit, take 2x32-khz to complete + *2. write to RTC register,take 2x32-khz to complete + *3. clear PSBR[RWE] bit,take 2x32-khz to complete + */ + if ((tm->tm_year < 70) || (tm->tm_year > 138)) + return -EINVAL; + rtc_writel_psbr(rtc_info, PSBR_RTC, 0x01); + udelay(100); rtc_writel(pxa_rtc, RYCR, ryxr_calc(tm)); rtc_writel(pxa_rtc, RDCR, rdxr_calc(tm)); + udelay(100); + rtc_writel_psbr(rtc_info, PSBR_RTC, 0x00); + udelay(100); + pxa_rtc_read_time(dev, tm); + dev_info(dev, "tm.year = %d, tm.month = %d, tm.day = %d\n", + tm->tm_year + 1900, tm->tm_mon, tm->tm_mday); + return 0; +} +int pxa_rtc_sync_time(unsigned int ticks) +{ + /* sequence to wirte pxa rtc register RCNR RDCR RYCR is + *1. set PSBR[RWE] bit, take 2x32-khz to complete + *2. write to RTC register,take 2x32-khz to complete + *3. clear PSBR[RWE] bit,take 2x32-khz to complete + */ + struct rtc_time tm; + rtc_time_to_tm(ticks, &tm); + rtc_writel_psbr(rtc_info, PSBR_RTC, 0x01); + udelay(100); + rtc_writel(rtc_info, RYCR, ryxr_calc(&tm)); + rtc_writel(rtc_info, RDCR, rdxr_calc(&tm)); + udelay(100); + rtc_writel_psbr(rtc_info, PSBR_RTC, 0x00); + udelay(100); return 0; } +EXPORT_SYMBOL(pxa_rtc_sync_time); static int pxa_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) { @@ -327,7 +367,7 @@ static int __init pxa_rtc_probe(struct platform_device *pdev) pxa_rtc = kzalloc(sizeof(struct pxa_rtc), GFP_KERNEL); if (!pxa_rtc) return -ENOMEM; - + rtc_info = pxa_rtc; spin_lock_init(&pxa_rtc->lock); platform_set_drvdata(pdev, pxa_rtc); @@ -337,6 +377,11 @@ static int __init pxa_rtc_probe(struct platform_device *pdev) dev_err(dev, "No I/O memory resource defined\n"); goto err_ress; } + pxa_rtc->ress_psbr = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (!pxa_rtc->ress_psbr) { + dev_err(dev, "No I/O memory resource defined\n"); + goto err_ress; + } pxa_rtc->irq_1Hz = platform_get_irq(pdev, 0); if (pxa_rtc->irq_1Hz < 0) { @@ -348,7 +393,6 @@ static int __init pxa_rtc_probe(struct platform_device *pdev) dev_err(dev, "No alarm IRQ resource defined\n"); goto err_ress; } - pxa_rtc_open(dev); ret = -ENOMEM; pxa_rtc->base = ioremap(pxa_rtc->ress->start, resource_size(pxa_rtc->ress)); @@ -357,6 +401,12 @@ static int __init pxa_rtc_probe(struct platform_device *pdev) goto err_map; } + pxa_rtc->base_psbr = ioremap(pxa_rtc->ress_psbr->start, + resource_size(pxa_rtc->ress_psbr)); + if (!pxa_rtc->base_psbr) { + dev_err(&pdev->dev, "Unable to map pxa RTC PSBR I/O memory\n"); + goto err_map; + } /* * If the clock divider is uninitialized then reset it to the * default value to get the 1Hz clock. @@ -379,7 +429,7 @@ static int __init pxa_rtc_probe(struct platform_device *pdev) } device_init_wakeup(dev, 1); - + pxa_rtc_open(dev); return 0; err_rtc_reg: @@ -416,7 +466,7 @@ static struct of_device_id pxa_rtc_dt_ids[] = { MODULE_DEVICE_TABLE(of, pxa_rtc_dt_ids); #endif -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int pxa_rtc_suspend(struct device *dev) { struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev); @@ -434,36 +484,20 @@ static int pxa_rtc_resume(struct device *dev) disable_irq_wake(pxa_rtc->irq_Alrm); return 0; } - -static const struct dev_pm_ops pxa_rtc_pm_ops = { - .suspend = pxa_rtc_suspend, - .resume = pxa_rtc_resume, -}; #endif +static SIMPLE_DEV_PM_OPS(pxa_rtc_pm_ops, pxa_rtc_suspend, pxa_rtc_resume); + static struct platform_driver pxa_rtc_driver = { .remove = __exit_p(pxa_rtc_remove), .driver = { .name = "pxa-rtc", .of_match_table = of_match_ptr(pxa_rtc_dt_ids), -#ifdef CONFIG_PM .pm = &pxa_rtc_pm_ops, -#endif }, }; -static int __init pxa_rtc_init(void) -{ - return platform_driver_probe(&pxa_rtc_driver, pxa_rtc_probe); -} - -static void __exit pxa_rtc_exit(void) -{ - platform_driver_unregister(&pxa_rtc_driver); -} - -module_init(pxa_rtc_init); -module_exit(pxa_rtc_exit); +module_platform_driver_probe(pxa_rtc_driver, pxa_rtc_probe); MODULE_AUTHOR("Robert Jarzmik <robert.jarzmik@free.fr>"); MODULE_DESCRIPTION("PXA27x/PXA3xx Realtime Clock Driver (RTC)"); diff --git a/drivers/rtc/rtc-r9701.c b/drivers/rtc/rtc-r9701.c index 7726f4a4f2d0..0adf5b528129 100644 --- a/drivers/rtc/rtc-r9701.c +++ b/drivers/rtc/rtc-r9701.c @@ -154,8 +154,8 @@ static int r9701_probe(struct spi_device *spi) } } - rtc = rtc_device_register("r9701", - &spi->dev, &r9701_rtc_ops, THIS_MODULE); + rtc = devm_rtc_device_register(&spi->dev, "r9701", + &r9701_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) return PTR_ERR(rtc); @@ -166,9 +166,6 @@ static int r9701_probe(struct spi_device *spi) static int r9701_remove(struct spi_device *spi) { - struct rtc_device *rtc = dev_get_drvdata(&spi->dev); - - rtc_device_unregister(rtc); return 0; } diff --git a/drivers/rtc/rtc-rc5t583.c b/drivers/rtc/rtc-rc5t583.c index eb3194d664a8..8eabcf51b35a 100644 --- a/drivers/rtc/rtc-rc5t583.c +++ b/drivers/rtc/rtc-rc5t583.c @@ -256,7 +256,7 @@ static int rc5t583_rtc_probe(struct platform_device *pdev) } device_init_wakeup(&pdev->dev, 1); - ricoh_rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, + ricoh_rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, &rc5t583_rtc_ops, THIS_MODULE); if (IS_ERR(ricoh_rtc->rtc)) { ret = PTR_ERR(ricoh_rtc->rtc); @@ -276,13 +276,10 @@ static int rc5t583_rtc_remove(struct platform_device *pdev) struct rc5t583_rtc *rc5t583_rtc = dev_get_drvdata(&pdev->dev); rc5t583_rtc_alarm_irq_enable(&rc5t583_rtc->rtc->dev, 0); - - rtc_device_unregister(rc5t583_rtc->rtc); return 0; } #ifdef CONFIG_PM_SLEEP - static int rc5t583_rtc_suspend(struct device *dev) { struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent); @@ -304,24 +301,18 @@ static int rc5t583_rtc_resume(struct device *dev) return regmap_write(rc5t583->regmap, RC5T583_RTC_CTL1, rc5t583_rtc->irqen); } - -static const struct dev_pm_ops rc5t583_rtc_pm_ops = { - .suspend = rc5t583_rtc_suspend, - .resume = rc5t583_rtc_resume, -}; - -#define DEV_PM_OPS (&rc5t583_rtc_pm_ops) -#else -#define DEV_PM_OPS NULL #endif +static SIMPLE_DEV_PM_OPS(rc5t583_rtc_pm_ops, rc5t583_rtc_suspend, + rc5t583_rtc_resume); + static struct platform_driver rc5t583_rtc_driver = { .probe = rc5t583_rtc_probe, .remove = rc5t583_rtc_remove, .driver = { .owner = THIS_MODULE, .name = "rtc-rc5t583", - .pm = DEV_PM_OPS, + .pm = &rc5t583_rtc_pm_ops, }, }; diff --git a/drivers/rtc/rtc-rp5c01.c b/drivers/rtc/rtc-rp5c01.c index 359da6d020b9..d25d2f6c0cad 100644 --- a/drivers/rtc/rtc-rp5c01.c +++ b/drivers/rtc/rtc-rp5c01.c @@ -294,18 +294,7 @@ static struct platform_driver rp5c01_rtc_driver = { .remove = __exit_p(rp5c01_rtc_remove), }; -static int __init rp5c01_rtc_init(void) -{ - return platform_driver_probe(&rp5c01_rtc_driver, rp5c01_rtc_probe); -} - -static void __exit rp5c01_rtc_fini(void) -{ - platform_driver_unregister(&rp5c01_rtc_driver); -} - -module_init(rp5c01_rtc_init); -module_exit(rp5c01_rtc_fini); +module_platform_driver_probe(rp5c01_rtc_driver, rp5c01_rtc_probe); MODULE_AUTHOR("Geert Uytterhoeven <geert@linux-m68k.org>"); MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-rs5c313.c b/drivers/rtc/rtc-rs5c313.c index d98ea5b759c8..8089fc63e403 100644 --- a/drivers/rtc/rtc-rs5c313.c +++ b/drivers/rtc/rtc-rs5c313.c @@ -367,7 +367,7 @@ static const struct rtc_class_ops rs5c313_rtc_ops = { static int rs5c313_rtc_probe(struct platform_device *pdev) { - struct rtc_device *rtc = rtc_device_register("rs5c313", &pdev->dev, + struct rtc_device *rtc = devm_rtc_device_register(&pdev->dev, "rs5c313", &rs5c313_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) @@ -380,10 +380,6 @@ static int rs5c313_rtc_probe(struct platform_device *pdev) static int rs5c313_rtc_remove(struct platform_device *pdev) { - struct rtc_device *rtc = platform_get_drvdata( pdev ); - - rtc_device_unregister(rtc); - return 0; } diff --git a/drivers/rtc/rtc-rv3029c2.c b/drivers/rtc/rtc-rv3029c2.c index f8ee8ad7825e..5032c24ec159 100644 --- a/drivers/rtc/rtc-rv3029c2.c +++ b/drivers/rtc/rtc-rv3029c2.c @@ -395,9 +395,8 @@ static int rv3029c2_probe(struct i2c_client *client, if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_EMUL)) return -ENODEV; - rtc = rtc_device_register(client->name, - &client->dev, &rv3029c2_rtc_ops, - THIS_MODULE); + rtc = devm_rtc_device_register(&client->dev, client->name, + &rv3029c2_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) return PTR_ERR(rtc); @@ -407,23 +406,14 @@ static int rv3029c2_probe(struct i2c_client *client, rc = rv3029c2_i2c_get_sr(client, buf); if (rc < 0) { dev_err(&client->dev, "reading status failed\n"); - goto exit_unregister; + return rc; } return 0; - -exit_unregister: - rtc_device_unregister(rtc); - - return rc; } static int rv3029c2_remove(struct i2c_client *client) { - struct rtc_device *rtc = i2c_get_clientdata(client); - - rtc_device_unregister(rtc); - return 0; } diff --git a/drivers/rtc/rtc-rx4581.c b/drivers/rtc/rtc-rx4581.c index 599ec73ec886..d1b88dbc5c2c 100644 --- a/drivers/rtc/rtc-rx4581.c +++ b/drivers/rtc/rtc-rx4581.c @@ -273,8 +273,8 @@ static int rx4581_probe(struct spi_device *spi) if (res != 0) return res; - rtc = rtc_device_register("rx4581", - &spi->dev, &rx4581_rtc_ops, THIS_MODULE); + rtc = devm_rtc_device_register(&spi->dev, "rx4581", + &rx4581_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) return PTR_ERR(rtc); @@ -284,9 +284,6 @@ static int rx4581_probe(struct spi_device *spi) static int rx4581_remove(struct spi_device *spi) { - struct rtc_device *rtc = dev_get_drvdata(&spi->dev); - - rtc_device_unregister(rtc); return 0; } diff --git a/drivers/rtc/rtc-rx8581.c b/drivers/rtc/rtc-rx8581.c index b0c272658fa2..07f3037b18f4 100644 --- a/drivers/rtc/rtc-rx8581.c +++ b/drivers/rtc/rtc-rx8581.c @@ -240,8 +240,8 @@ static int rx8581_probe(struct i2c_client *client, dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); - rtc = rtc_device_register(rx8581_driver.driver.name, - &client->dev, &rx8581_rtc_ops, THIS_MODULE); + rtc = devm_rtc_device_register(&client->dev, rx8581_driver.driver.name, + &rx8581_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) return PTR_ERR(rtc); @@ -253,10 +253,6 @@ static int rx8581_probe(struct i2c_client *client, static int rx8581_remove(struct i2c_client *client) { - struct rtc_device *rtc = i2c_get_clientdata(client); - - rtc_device_unregister(rtc); - return 0; } diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index fb994e9ddc15..653a4dcbfe7d 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c @@ -51,7 +51,6 @@ static struct clk *rtc_clk; static void __iomem *s3c_rtc_base; static int s3c_rtc_alarmno = NO_IRQ; static int s3c_rtc_tickno = NO_IRQ; -static bool wake_en; static enum s3c_cpu_type s3c_rtc_cpu_type; static DEFINE_SPINLOCK(s3c_rtc_pie_lock); @@ -423,10 +422,7 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en) static int s3c_rtc_remove(struct platform_device *dev) { - struct rtc_device *rtc = platform_get_drvdata(dev); - platform_set_drvdata(dev, NULL); - rtc_device_unregister(rtc); s3c_rtc_setaie(&dev->dev, 0); @@ -511,7 +507,7 @@ static int s3c_rtc_probe(struct platform_device *pdev) /* register RTC and exit */ - rtc = rtc_device_register("s3c", &pdev->dev, &s3c_rtcops, + rtc = devm_rtc_device_register(&pdev->dev, "s3c", &s3c_rtcops, THIS_MODULE); if (IS_ERR(rtc)) { @@ -574,7 +570,6 @@ static int s3c_rtc_probe(struct platform_device *pdev) err_alarm_irq: platform_set_drvdata(pdev, NULL); - rtc_device_unregister(rtc); err_nortc: s3c_rtc_enable(pdev, 0); @@ -583,14 +578,16 @@ static int s3c_rtc_probe(struct platform_device *pdev) return ret; } -#ifdef CONFIG_PM - +#ifdef CONFIG_PM_SLEEP /* RTC Power management control */ static int ticnt_save, ticnt_en_save; +static bool wake_en; -static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state) +static int s3c_rtc_suspend(struct device *dev) { + struct platform_device *pdev = to_platform_device(dev); + clk_enable(rtc_clk); /* save TICNT for anyone using periodic interrupts */ ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT); @@ -600,19 +597,20 @@ static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state) } s3c_rtc_enable(pdev, 0); - if (device_may_wakeup(&pdev->dev) && !wake_en) { + if (device_may_wakeup(dev) && !wake_en) { if (enable_irq_wake(s3c_rtc_alarmno) == 0) wake_en = true; else - dev_err(&pdev->dev, "enable_irq_wake failed\n"); + dev_err(dev, "enable_irq_wake failed\n"); } clk_disable(rtc_clk); return 0; } -static int s3c_rtc_resume(struct platform_device *pdev) +static int s3c_rtc_resume(struct device *dev) { + struct platform_device *pdev = to_platform_device(dev); unsigned int tmp; clk_enable(rtc_clk); @@ -623,7 +621,7 @@ static int s3c_rtc_resume(struct platform_device *pdev) writew(tmp | ticnt_en_save, s3c_rtc_base + S3C2410_RTCCON); } - if (device_may_wakeup(&pdev->dev) && wake_en) { + if (device_may_wakeup(dev) && wake_en) { disable_irq_wake(s3c_rtc_alarmno); wake_en = false; } @@ -631,11 +629,10 @@ static int s3c_rtc_resume(struct platform_device *pdev) return 0; } -#else -#define s3c_rtc_suspend NULL -#define s3c_rtc_resume NULL #endif +static SIMPLE_DEV_PM_OPS(s3c_rtc_pm_ops, s3c_rtc_suspend, s3c_rtc_resume); + #ifdef CONFIG_OF static struct s3c_rtc_drv_data s3c_rtc_drv_data_array[] = { [TYPE_S3C2410] = { TYPE_S3C2410 }, @@ -685,12 +682,11 @@ MODULE_DEVICE_TABLE(platform, s3c_rtc_driver_ids); static struct platform_driver s3c_rtc_driver = { .probe = s3c_rtc_probe, .remove = s3c_rtc_remove, - .suspend = s3c_rtc_suspend, - .resume = s3c_rtc_resume, .id_table = s3c_rtc_driver_ids, .driver = { .name = "s3c-rtc", .owner = THIS_MODULE, + .pm = &s3c_rtc_pm_ops, .of_match_table = of_match_ptr(s3c_rtc_dt_match), }, }; diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c index 5ec5036df0bc..7e0a0887c256 100644 --- a/drivers/rtc/rtc-sa1100.c +++ b/drivers/rtc/rtc-sa1100.c @@ -327,7 +327,7 @@ static int sa1100_rtc_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int sa1100_rtc_suspend(struct device *dev) { struct sa1100_rtc *info = dev_get_drvdata(dev); @@ -343,13 +343,11 @@ static int sa1100_rtc_resume(struct device *dev) disable_irq_wake(info->irq_alarm); return 0; } - -static const struct dev_pm_ops sa1100_rtc_pm_ops = { - .suspend = sa1100_rtc_suspend, - .resume = sa1100_rtc_resume, -}; #endif +static SIMPLE_DEV_PM_OPS(sa1100_rtc_pm_ops, sa1100_rtc_suspend, + sa1100_rtc_resume); + #ifdef CONFIG_OF static struct of_device_id sa1100_rtc_dt_ids[] = { { .compatible = "mrvl,sa1100-rtc", }, @@ -364,9 +362,7 @@ static struct platform_driver sa1100_rtc_driver = { .remove = sa1100_rtc_remove, .driver = { .name = "sa1100-rtc", -#ifdef CONFIG_PM .pm = &sa1100_rtc_pm_ops, -#endif .of_match_table = of_match_ptr(sa1100_rtc_dt_ids), }, }; diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c index e55a7635ae5f..8d5bd2e36776 100644 --- a/drivers/rtc/rtc-sh.c +++ b/drivers/rtc/rtc-sh.c @@ -790,6 +790,7 @@ static void sh_rtc_set_irq_wake(struct device *dev, int enabled) } } +#ifdef CONFIG_PM_SLEEP static int sh_rtc_suspend(struct device *dev) { if (device_may_wakeup(dev)) @@ -805,33 +806,20 @@ static int sh_rtc_resume(struct device *dev) return 0; } +#endif -static const struct dev_pm_ops sh_rtc_dev_pm_ops = { - .suspend = sh_rtc_suspend, - .resume = sh_rtc_resume, -}; +static SIMPLE_DEV_PM_OPS(sh_rtc_pm_ops, sh_rtc_suspend, sh_rtc_resume); static struct platform_driver sh_rtc_platform_driver = { .driver = { .name = DRV_NAME, .owner = THIS_MODULE, - .pm = &sh_rtc_dev_pm_ops, + .pm = &sh_rtc_pm_ops, }, .remove = __exit_p(sh_rtc_remove), }; -static int __init sh_rtc_init(void) -{ - return platform_driver_probe(&sh_rtc_platform_driver, sh_rtc_probe); -} - -static void __exit sh_rtc_exit(void) -{ - platform_driver_unregister(&sh_rtc_platform_driver); -} - -module_init(sh_rtc_init); -module_exit(sh_rtc_exit); +module_platform_driver_probe(sh_rtc_platform_driver, sh_rtc_probe); MODULE_DESCRIPTION("SuperH on-chip RTC driver"); MODULE_VERSION(DRV_VERSION); diff --git a/drivers/rtc/rtc-snvs.c b/drivers/rtc/rtc-snvs.c index f7d90703db5e..b04f09a1df2a 100644 --- a/drivers/rtc/rtc-snvs.c +++ b/drivers/rtc/rtc-snvs.c @@ -283,7 +283,7 @@ static int snvs_rtc_probe(struct platform_device *pdev) return ret; } - data->rtc = rtc_device_register(pdev->name, &pdev->dev, + data->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, &snvs_rtc_ops, THIS_MODULE); if (IS_ERR(data->rtc)) { ret = PTR_ERR(data->rtc); @@ -296,10 +296,6 @@ static int snvs_rtc_probe(struct platform_device *pdev) static int snvs_rtc_remove(struct platform_device *pdev) { - struct snvs_rtc_data *data = platform_get_drvdata(pdev); - - rtc_device_unregister(data->rtc); - return 0; } diff --git a/drivers/rtc/rtc-spear.c b/drivers/rtc/rtc-spear.c index a18c3192ed40..db3ef610dd7c 100644 --- a/drivers/rtc/rtc-spear.c +++ b/drivers/rtc/rtc-spear.c @@ -400,8 +400,8 @@ static int spear_rtc_probe(struct platform_device *pdev) spin_lock_init(&config->lock); platform_set_drvdata(pdev, config); - config->rtc = rtc_device_register(pdev->name, &pdev->dev, - &spear_rtc_ops, THIS_MODULE); + config->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, + &spear_rtc_ops, THIS_MODULE); if (IS_ERR(config->rtc)) { dev_err(&pdev->dev, "can't register RTC device, err %ld\n", PTR_ERR(config->rtc)); @@ -427,7 +427,6 @@ static int spear_rtc_remove(struct platform_device *pdev) { struct spear_rtc_config *config = platform_get_drvdata(pdev); - rtc_device_unregister(config->rtc); spear_rtc_disable_interrupt(config); clk_disable_unprepare(config->clk); device_init_wakeup(&pdev->dev, 0); diff --git a/drivers/rtc/rtc-starfire.c b/drivers/rtc/rtc-starfire.c index 5be98bfd7ed3..987b5ec0ae56 100644 --- a/drivers/rtc/rtc-starfire.c +++ b/drivers/rtc/rtc-starfire.c @@ -39,8 +39,10 @@ static const struct rtc_class_ops starfire_rtc_ops = { static int __init starfire_rtc_probe(struct platform_device *pdev) { - struct rtc_device *rtc = rtc_device_register("starfire", &pdev->dev, - &starfire_rtc_ops, THIS_MODULE); + struct rtc_device *rtc; + + rtc = devm_rtc_device_register(&pdev->dev, "starfire", + &starfire_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) return PTR_ERR(rtc); @@ -51,10 +53,6 @@ static int __init starfire_rtc_probe(struct platform_device *pdev) static int __exit starfire_rtc_remove(struct platform_device *pdev) { - struct rtc_device *rtc = platform_get_drvdata(pdev); - - rtc_device_unregister(rtc); - return 0; } @@ -66,15 +64,4 @@ static struct platform_driver starfire_rtc_driver = { .remove = __exit_p(starfire_rtc_remove), }; -static int __init starfire_rtc_init(void) -{ - return platform_driver_probe(&starfire_rtc_driver, starfire_rtc_probe); -} - -static void __exit starfire_rtc_exit(void) -{ - platform_driver_unregister(&starfire_rtc_driver); -} - -module_init(starfire_rtc_init); -module_exit(starfire_rtc_exit); +module_platform_driver_probe(starfire_rtc_driver, starfire_rtc_probe); diff --git a/drivers/rtc/rtc-stk17ta8.c b/drivers/rtc/rtc-stk17ta8.c index 7e4a6f65cb91..af5e97e3f272 100644 --- a/drivers/rtc/rtc-stk17ta8.c +++ b/drivers/rtc/rtc-stk17ta8.c @@ -336,14 +336,13 @@ static int stk17ta8_rtc_probe(struct platform_device *pdev) } } - pdata->rtc = rtc_device_register(pdev->name, &pdev->dev, + pdata->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, &stk17ta8_rtc_ops, THIS_MODULE); if (IS_ERR(pdata->rtc)) return PTR_ERR(pdata->rtc); ret = sysfs_create_bin_file(&pdev->dev.kobj, &stk17ta8_nvram_attr); - if (ret) - rtc_device_unregister(pdata->rtc); + return ret; } @@ -352,7 +351,6 @@ static int stk17ta8_rtc_remove(struct platform_device *pdev) struct rtc_plat_data *pdata = platform_get_drvdata(pdev); sysfs_remove_bin_file(&pdev->dev.kobj, &stk17ta8_nvram_attr); - rtc_device_unregister(pdata->rtc); if (pdata->irq > 0) writeb(0, pdata->ioaddr + RTC_INTERRUPTS); return 0; diff --git a/drivers/rtc/rtc-sun4v.c b/drivers/rtc/rtc-sun4v.c index 59b5c2dcb58c..ce42e5fa9e09 100644 --- a/drivers/rtc/rtc-sun4v.c +++ b/drivers/rtc/rtc-sun4v.c @@ -81,8 +81,10 @@ static const struct rtc_class_ops sun4v_rtc_ops = { static int __init sun4v_rtc_probe(struct platform_device *pdev) { - struct rtc_device *rtc = rtc_device_register("sun4v", &pdev->dev, - &sun4v_rtc_ops, THIS_MODULE); + struct rtc_device *rtc; + + rtc = devm_rtc_device_register(&pdev->dev, "sun4v", + &sun4v_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) return PTR_ERR(rtc); @@ -92,9 +94,6 @@ static int __init sun4v_rtc_probe(struct platform_device *pdev) static int __exit sun4v_rtc_remove(struct platform_device *pdev) { - struct rtc_device *rtc = platform_get_drvdata(pdev); - - rtc_device_unregister(rtc); return 0; } @@ -106,18 +105,7 @@ static struct platform_driver sun4v_rtc_driver = { .remove = __exit_p(sun4v_rtc_remove), }; -static int __init sun4v_rtc_init(void) -{ - return platform_driver_probe(&sun4v_rtc_driver, sun4v_rtc_probe); -} - -static void __exit sun4v_rtc_exit(void) -{ - platform_driver_unregister(&sun4v_rtc_driver); -} - -module_init(sun4v_rtc_init); -module_exit(sun4v_rtc_exit); +module_platform_driver_probe(sun4v_rtc_driver, sun4v_rtc_probe); MODULE_AUTHOR("David S. Miller <davem@davemloft.net>"); MODULE_DESCRIPTION("SUN4V RTC driver"); diff --git a/drivers/rtc/rtc-tegra.c b/drivers/rtc/rtc-tegra.c index 7c033756d6b5..7cb3da0e879a 100644 --- a/drivers/rtc/rtc-tegra.c +++ b/drivers/rtc/rtc-tegra.c @@ -26,6 +26,7 @@ #include <linux/delay.h> #include <linux/rtc.h> #include <linux/platform_device.h> +#include <linux/pm.h> /* set to 1 = busy every eight 32kHz clocks during copy of sec+msec to AHB */ #define TEGRA_RTC_REG_BUSY 0x004 @@ -309,7 +310,7 @@ static const struct of_device_id tegra_rtc_dt_match[] = { }; MODULE_DEVICE_TABLE(of, tegra_rtc_dt_match); -static int tegra_rtc_probe(struct platform_device *pdev) +static int __init tegra_rtc_probe(struct platform_device *pdev) { struct tegra_rtc_info *info; struct resource *res; @@ -348,53 +349,34 @@ static int tegra_rtc_probe(struct platform_device *pdev) device_init_wakeup(&pdev->dev, 1); - info->rtc_dev = rtc_device_register( - pdev->name, &pdev->dev, &tegra_rtc_ops, THIS_MODULE); + info->rtc_dev = devm_rtc_device_register(dev_name(&pdev->dev), + &pdev->dev, &tegra_rtc_ops, THIS_MODULE); if (IS_ERR(info->rtc_dev)) { ret = PTR_ERR(info->rtc_dev); - info->rtc_dev = NULL; - dev_err(&pdev->dev, - "Unable to register device (err=%d).\n", + dev_err(&pdev->dev, "Unable to register device (err=%d).\n", ret); return ret; } ret = devm_request_irq(&pdev->dev, info->tegra_rtc_irq, tegra_rtc_irq_handler, IRQF_TRIGGER_HIGH, - "rtc alarm", &pdev->dev); + dev_name(&pdev->dev), &pdev->dev); if (ret) { dev_err(&pdev->dev, "Unable to request interrupt for device (err=%d).\n", ret); - goto err_dev_unreg; + return ret; } dev_notice(&pdev->dev, "Tegra internal Real Time Clock\n"); return 0; - -err_dev_unreg: - rtc_device_unregister(info->rtc_dev); - - return ret; } -static int tegra_rtc_remove(struct platform_device *pdev) +#ifdef CONFIG_PM_SLEEP +static int tegra_rtc_suspend(struct device *dev) { - struct tegra_rtc_info *info = platform_get_drvdata(pdev); - - rtc_device_unregister(info->rtc_dev); - - platform_set_drvdata(pdev, NULL); - - return 0; -} - -#ifdef CONFIG_PM -static int tegra_rtc_suspend(struct platform_device *pdev, pm_message_t state) -{ - struct device *dev = &pdev->dev; - struct tegra_rtc_info *info = platform_get_drvdata(pdev); + struct tegra_rtc_info *info = dev_get_drvdata(dev); tegra_rtc_wait_while_busy(dev); @@ -416,10 +398,9 @@ static int tegra_rtc_suspend(struct platform_device *pdev, pm_message_t state) return 0; } -static int tegra_rtc_resume(struct platform_device *pdev) +static int tegra_rtc_resume(struct device *dev) { - struct device *dev = &pdev->dev; - struct tegra_rtc_info *info = platform_get_drvdata(pdev); + struct tegra_rtc_info *info = dev_get_drvdata(dev); dev_vdbg(dev, "Resume (device_may_wakeup=%d)\n", device_may_wakeup(dev)); @@ -431,6 +412,8 @@ static int tegra_rtc_resume(struct platform_device *pdev) } #endif +static SIMPLE_DEV_PM_OPS(tegra_rtc_pm_ops, tegra_rtc_suspend, tegra_rtc_resume); + static void tegra_rtc_shutdown(struct platform_device *pdev) { dev_vdbg(&pdev->dev, "disabling interrupts.\n"); @@ -439,30 +422,16 @@ static void tegra_rtc_shutdown(struct platform_device *pdev) MODULE_ALIAS("platform:tegra_rtc"); static struct platform_driver tegra_rtc_driver = { - .remove = tegra_rtc_remove, .shutdown = tegra_rtc_shutdown, .driver = { .name = "tegra_rtc", .owner = THIS_MODULE, .of_match_table = tegra_rtc_dt_match, + .pm = &tegra_rtc_pm_ops, }, -#ifdef CONFIG_PM - .suspend = tegra_rtc_suspend, - .resume = tegra_rtc_resume, -#endif }; -static int __init tegra_rtc_init(void) -{ - return platform_driver_probe(&tegra_rtc_driver, tegra_rtc_probe); -} -module_init(tegra_rtc_init); - -static void __exit tegra_rtc_exit(void) -{ - platform_driver_unregister(&tegra_rtc_driver); -} -module_exit(tegra_rtc_exit); +module_platform_driver_probe(tegra_rtc_driver, tegra_rtc_probe); MODULE_AUTHOR("Jon Mayo <jmayo@nvidia.com>"); MODULE_DESCRIPTION("driver for Tegra internal RTC"); diff --git a/drivers/rtc/rtc-test.c b/drivers/rtc/rtc-test.c index b92e0f6383e6..7746e65b93f2 100644 --- a/drivers/rtc/rtc-test.c +++ b/drivers/rtc/rtc-test.c @@ -99,8 +99,10 @@ static DEVICE_ATTR(irq, S_IRUGO | S_IWUSR, test_irq_show, test_irq_store); static int test_probe(struct platform_device *plat_dev) { int err; - struct rtc_device *rtc = rtc_device_register("test", &plat_dev->dev, - &test_rtc_ops, THIS_MODULE); + struct rtc_device *rtc; + + rtc = devm_rtc_device_register(&plat_dev->dev, "test", + &test_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) { err = PTR_ERR(rtc); return err; @@ -115,15 +117,11 @@ static int test_probe(struct platform_device *plat_dev) return 0; err: - rtc_device_unregister(rtc); return err; } static int test_remove(struct platform_device *plat_dev) { - struct rtc_device *rtc = platform_get_drvdata(plat_dev); - - rtc_device_unregister(rtc); device_remove_file(&plat_dev->dev, &dev_attr_irq); return 0; diff --git a/drivers/rtc/rtc-tile.c b/drivers/rtc/rtc-tile.c index 62db4841078b..249b6531f119 100644 --- a/drivers/rtc/rtc-tile.c +++ b/drivers/rtc/rtc-tile.c @@ -80,8 +80,8 @@ static int tile_rtc_probe(struct platform_device *dev) { struct rtc_device *rtc; - rtc = rtc_device_register("tile", - &dev->dev, &tile_rtc_ops, THIS_MODULE); + rtc = devm_rtc_device_register(&dev->dev, "tile", + &tile_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) return PTR_ERR(rtc); @@ -96,11 +96,6 @@ static int tile_rtc_probe(struct platform_device *dev) */ static int tile_rtc_remove(struct platform_device *dev) { - struct rtc_device *rtc = platform_get_drvdata(dev); - - if (rtc) - rtc_device_unregister(rtc); - platform_set_drvdata(dev, NULL); return 0; diff --git a/drivers/rtc/rtc-tps6586x.c b/drivers/rtc/rtc-tps6586x.c index aab4e8c93622..badfea491a93 100644 --- a/drivers/rtc/rtc-tps6586x.c +++ b/drivers/rtc/rtc-tps6586x.c @@ -274,7 +274,7 @@ static int tps6586x_rtc_probe(struct platform_device *pdev) } platform_set_drvdata(pdev, rtc); - rtc->rtc = rtc_device_register(dev_name(&pdev->dev), &pdev->dev, + rtc->rtc = devm_rtc_device_register(&pdev->dev, dev_name(&pdev->dev), &tps6586x_rtc_ops, THIS_MODULE); if (IS_ERR(rtc->rtc)) { ret = PTR_ERR(rtc->rtc); @@ -306,12 +306,10 @@ fail_rtc_register: static int tps6586x_rtc_remove(struct platform_device *pdev) { - struct tps6586x_rtc *rtc = platform_get_drvdata(pdev); struct device *tps_dev = to_tps6586x_dev(&pdev->dev); tps6586x_update(tps_dev, RTC_CTRL, 0, RTC_ENABLE | OSC_SRC_SEL | PRE_BYPASS | CL_SEL_MASK); - rtc_device_unregister(rtc->rtc); return 0; } @@ -335,9 +333,8 @@ static int tps6586x_rtc_resume(struct device *dev) } #endif -static const struct dev_pm_ops tps6586x_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(tps6586x_rtc_suspend, tps6586x_rtc_resume) -}; +static SIMPLE_DEV_PM_OPS(tps6586x_pm_ops, tps6586x_rtc_suspend, + tps6586x_rtc_resume); static struct platform_driver tps6586x_rtc_driver = { .driver = { diff --git a/drivers/rtc/rtc-tps65910.c b/drivers/rtc/rtc-tps65910.c index 8bd8115329b5..26b8bd252769 100644 --- a/drivers/rtc/rtc-tps65910.c +++ b/drivers/rtc/rtc-tps65910.c @@ -276,7 +276,7 @@ static int tps65910_rtc_probe(struct platform_device *pdev) tps_rtc->irq = irq; device_set_wakeup_capable(&pdev->dev, 1); - tps_rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, + tps_rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, &tps65910_rtc_ops, THIS_MODULE); if (IS_ERR(tps_rtc->rtc)) { ret = PTR_ERR(tps_rtc->rtc); @@ -295,12 +295,8 @@ static int tps65910_rtc_probe(struct platform_device *pdev) */ static int tps65910_rtc_remove(struct platform_device *pdev) { - /* leave rtc running, but disable irqs */ - struct tps65910_rtc *tps_rtc = platform_get_drvdata(pdev); - tps65910_rtc_alarm_irq_enable(&pdev->dev, 0); - rtc_device_unregister(tps_rtc->rtc); return 0; } @@ -324,9 +320,8 @@ static int tps65910_rtc_resume(struct device *dev) } #endif -static const struct dev_pm_ops tps65910_rtc_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(tps65910_rtc_suspend, tps65910_rtc_resume) -}; +static SIMPLE_DEV_PM_OPS(tps65910_rtc_pm_ops, tps65910_rtc_suspend, + tps65910_rtc_resume); static struct platform_driver tps65910_rtc_driver = { .probe = tps65910_rtc_probe, diff --git a/drivers/rtc/rtc-tps80031.c b/drivers/rtc/rtc-tps80031.c index 9aaf8aaebae9..72662eafb938 100644 --- a/drivers/rtc/rtc-tps80031.c +++ b/drivers/rtc/rtc-tps80031.c @@ -277,7 +277,7 @@ static int tps80031_rtc_probe(struct platform_device *pdev) return ret; } - rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, + rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, &tps80031_rtc_ops, THIS_MODULE); if (IS_ERR(rtc->rtc)) { ret = PTR_ERR(rtc->rtc); @@ -292,7 +292,6 @@ static int tps80031_rtc_probe(struct platform_device *pdev) if (ret < 0) { dev_err(&pdev->dev, "request IRQ:%d failed, err = %d\n", rtc->irq, ret); - rtc_device_unregister(rtc->rtc); return ret; } device_set_wakeup_capable(&pdev->dev, 1); @@ -301,9 +300,6 @@ static int tps80031_rtc_probe(struct platform_device *pdev) static int tps80031_rtc_remove(struct platform_device *pdev) { - struct tps80031_rtc *rtc = platform_get_drvdata(pdev); - - rtc_device_unregister(rtc->rtc); return 0; } @@ -327,9 +323,8 @@ static int tps80031_rtc_resume(struct device *dev) }; #endif -static const struct dev_pm_ops tps80031_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(tps80031_rtc_suspend, tps80031_rtc_resume) -}; +static SIMPLE_DEV_PM_OPS(tps80031_pm_ops, tps80031_rtc_suspend, + tps80031_rtc_resume); static struct platform_driver tps80031_rtc_driver = { .driver = { diff --git a/drivers/rtc/rtc-tx4939.c b/drivers/rtc/rtc-tx4939.c index a12bfac49d36..f9a0677e4e3b 100644 --- a/drivers/rtc/rtc-tx4939.c +++ b/drivers/rtc/rtc-tx4939.c @@ -268,14 +268,13 @@ static int __init tx4939_rtc_probe(struct platform_device *pdev) if (devm_request_irq(&pdev->dev, irq, tx4939_rtc_interrupt, 0, pdev->name, &pdev->dev) < 0) return -EBUSY; - rtc = rtc_device_register(pdev->name, &pdev->dev, + rtc = devm_rtc_device_register(&pdev->dev, pdev->name, &tx4939_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) return PTR_ERR(rtc); pdata->rtc = rtc; ret = sysfs_create_bin_file(&pdev->dev.kobj, &tx4939_rtc_nvram_attr); - if (ret) - rtc_device_unregister(rtc); + return ret; } @@ -284,7 +283,6 @@ static int __exit tx4939_rtc_remove(struct platform_device *pdev) struct tx4939rtc_plat_data *pdata = platform_get_drvdata(pdev); sysfs_remove_bin_file(&pdev->dev.kobj, &tx4939_rtc_nvram_attr); - rtc_device_unregister(pdata->rtc); spin_lock_irq(&pdata->lock); tx4939_rtc_cmd(pdata->rtcreg, TX4939_RTCCTL_COMMAND_NOP); spin_unlock_irq(&pdata->lock); @@ -299,18 +297,7 @@ static struct platform_driver tx4939_rtc_driver = { }, }; -static int __init tx4939rtc_init(void) -{ - return platform_driver_probe(&tx4939_rtc_driver, tx4939_rtc_probe); -} - -static void __exit tx4939rtc_exit(void) -{ - platform_driver_unregister(&tx4939_rtc_driver); -} - -module_init(tx4939rtc_init); -module_exit(tx4939rtc_exit); +module_platform_driver_probe(tx4939_rtc_driver, tx4939_rtc_probe); MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>"); MODULE_DESCRIPTION("TX4939 internal RTC driver"); diff --git a/drivers/rtc/rtc-v3020.c b/drivers/rtc/rtc-v3020.c index bca5d677bc85..600798cd4d0c 100644 --- a/drivers/rtc/rtc-v3020.c +++ b/drivers/rtc/rtc-v3020.c @@ -49,18 +49,13 @@ struct v3020_chip_ops { #define V3020_RD 2 #define V3020_IO 3 -struct v3020_gpio { - const char *name; - unsigned int gpio; -}; - struct v3020 { /* MMIO access */ void __iomem *ioaddress; int leftshift; /* GPIO access */ - struct v3020_gpio *gpio; + struct gpio *gpio; struct v3020_chip_ops *ops; @@ -107,48 +102,40 @@ static struct v3020_chip_ops v3020_mmio_ops = { .write_bit = v3020_mmio_write_bit, }; -static struct v3020_gpio v3020_gpio[] = { - { "RTC CS", 0 }, - { "RTC WR", 0 }, - { "RTC RD", 0 }, - { "RTC IO", 0 }, +static struct gpio v3020_gpio[] = { + { 0, GPIOF_OUT_INIT_HIGH, "RTC CS"}, + { 0, GPIOF_OUT_INIT_HIGH, "RTC WR"}, + { 0, GPIOF_OUT_INIT_HIGH, "RTC RD"}, + { 0, GPIOF_OUT_INIT_HIGH, "RTC IO"}, }; static int v3020_gpio_map(struct v3020 *chip, struct platform_device *pdev, struct v3020_platform_data *pdata) { - int i, err; + int err; v3020_gpio[V3020_CS].gpio = pdata->gpio_cs; v3020_gpio[V3020_WR].gpio = pdata->gpio_wr; v3020_gpio[V3020_RD].gpio = pdata->gpio_rd; v3020_gpio[V3020_IO].gpio = pdata->gpio_io; - for (i = 0; i < ARRAY_SIZE(v3020_gpio); i++) { - err = gpio_request(v3020_gpio[i].gpio, v3020_gpio[i].name); - if (err) - goto err_request; - - gpio_direction_output(v3020_gpio[i].gpio, 1); - } + err = gpio_request_array(v3020_gpio, ARRAY_SIZE(v3020_gpio)); + if (err) + goto err_request; chip->gpio = v3020_gpio; return 0; err_request: - while (--i >= 0) - gpio_free(v3020_gpio[i].gpio); + gpio_free_array(v3020_gpio, ARRAY_SIZE(v3020_gpio)); return err; } static void v3020_gpio_unmap(struct v3020 *chip) { - int i; - - for (i = 0; i < ARRAY_SIZE(v3020_gpio); i++) - gpio_free(v3020_gpio[i].gpio); + gpio_free_array(v3020_gpio, ARRAY_SIZE(v3020_gpio)); } static void v3020_gpio_write_bit(struct v3020 *chip, unsigned char bit) diff --git a/drivers/rtc/rtc-vt8500.c b/drivers/rtc/rtc-vt8500.c index a000bc0a8bff..d89efee6d29e 100644 --- a/drivers/rtc/rtc-vt8500.c +++ b/drivers/rtc/rtc-vt8500.c @@ -252,7 +252,7 @@ static int vt8500_rtc_probe(struct platform_device *pdev) writel(VT8500_RTC_CR_ENABLE, vt8500_rtc->regbase + VT8500_RTC_CR); - vt8500_rtc->rtc = rtc_device_register("vt8500-rtc", &pdev->dev, + vt8500_rtc->rtc = devm_rtc_device_register(&pdev->dev, "vt8500-rtc", &vt8500_rtc_ops, THIS_MODULE); if (IS_ERR(vt8500_rtc->rtc)) { ret = PTR_ERR(vt8500_rtc->rtc); @@ -266,13 +266,11 @@ static int vt8500_rtc_probe(struct platform_device *pdev) if (ret < 0) { dev_err(&pdev->dev, "can't get irq %i, err %d\n", vt8500_rtc->irq_alarm, ret); - goto err_unreg; + goto err_return; } return 0; -err_unreg: - rtc_device_unregister(vt8500_rtc->rtc); err_return: return ret; } @@ -281,8 +279,6 @@ static int vt8500_rtc_remove(struct platform_device *pdev) { struct vt8500_rtc *vt8500_rtc = platform_get_drvdata(pdev); - rtc_device_unregister(vt8500_rtc->rtc); - /* Disable alarm matching */ writel(0, vt8500_rtc->regbase + VT8500_RTC_IS); diff --git a/drivers/rtc/rtc-wm831x.c b/drivers/rtc/rtc-wm831x.c index 2f0ac7b30a0c..8d65b94e5a7e 100644 --- a/drivers/rtc/rtc-wm831x.c +++ b/drivers/rtc/rtc-wm831x.c @@ -436,7 +436,7 @@ static int wm831x_rtc_probe(struct platform_device *pdev) device_init_wakeup(&pdev->dev, 1); - wm831x_rtc->rtc = rtc_device_register("wm831x", &pdev->dev, + wm831x_rtc->rtc = devm_rtc_device_register(&pdev->dev, "wm831x", &wm831x_rtc_ops, THIS_MODULE); if (IS_ERR(wm831x_rtc->rtc)) { ret = PTR_ERR(wm831x_rtc->rtc); @@ -462,10 +462,6 @@ err: static int wm831x_rtc_remove(struct platform_device *pdev) { - struct wm831x_rtc *wm831x_rtc = platform_get_drvdata(pdev); - - rtc_device_unregister(wm831x_rtc->rtc); - return 0; } diff --git a/drivers/rtc/rtc-wm8350.c b/drivers/rtc/rtc-wm8350.c index 8ad86ae0d30f..fa247deb9cf4 100644 --- a/drivers/rtc/rtc-wm8350.c +++ b/drivers/rtc/rtc-wm8350.c @@ -339,7 +339,7 @@ static const struct rtc_class_ops wm8350_rtc_ops = { .alarm_irq_enable = wm8350_rtc_alarm_irq_enable, }; -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int wm8350_rtc_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); @@ -375,10 +375,6 @@ static int wm8350_rtc_resume(struct device *dev) return 0; } - -#else -#define wm8350_rtc_suspend NULL -#define wm8350_rtc_resume NULL #endif static int wm8350_rtc_probe(struct platform_device *pdev) @@ -439,8 +435,8 @@ static int wm8350_rtc_probe(struct platform_device *pdev) device_init_wakeup(&pdev->dev, 1); - wm_rtc->rtc = rtc_device_register("wm8350", &pdev->dev, - &wm8350_rtc_ops, THIS_MODULE); + wm_rtc->rtc = devm_rtc_device_register(&pdev->dev, "wm8350", + &wm8350_rtc_ops, THIS_MODULE); if (IS_ERR(wm_rtc->rtc)) { ret = PTR_ERR(wm_rtc->rtc); dev_err(&pdev->dev, "failed to register RTC: %d\n", ret); @@ -462,20 +458,15 @@ static int wm8350_rtc_probe(struct platform_device *pdev) static int wm8350_rtc_remove(struct platform_device *pdev) { struct wm8350 *wm8350 = platform_get_drvdata(pdev); - struct wm8350_rtc *wm_rtc = &wm8350->rtc; wm8350_free_irq(wm8350, WM8350_IRQ_RTC_SEC, wm8350); wm8350_free_irq(wm8350, WM8350_IRQ_RTC_ALM, wm8350); - rtc_device_unregister(wm_rtc->rtc); - return 0; } -static struct dev_pm_ops wm8350_rtc_pm_ops = { - .suspend = wm8350_rtc_suspend, - .resume = wm8350_rtc_resume, -}; +static SIMPLE_DEV_PM_OPS(wm8350_rtc_pm_ops, wm8350_rtc_suspend, + wm8350_rtc_resume); static struct platform_driver wm8350_rtc_driver = { .probe = wm8350_rtc_probe, diff --git a/drivers/rtc/rtc-x1205.c b/drivers/rtc/rtc-x1205.c index f36e59c6bc01..fa9b0679fb60 100644 --- a/drivers/rtc/rtc-x1205.c +++ b/drivers/rtc/rtc-x1205.c @@ -630,8 +630,8 @@ static int x1205_probe(struct i2c_client *client, dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); - rtc = rtc_device_register(x1205_driver.driver.name, &client->dev, - &x1205_rtc_ops, THIS_MODULE); + rtc = devm_rtc_device_register(&client->dev, x1205_driver.driver.name, + &x1205_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) return PTR_ERR(rtc); @@ -653,21 +653,13 @@ static int x1205_probe(struct i2c_client *client, err = x1205_sysfs_register(&client->dev); if (err) - goto exit_devreg; + return err; return 0; - -exit_devreg: - rtc_device_unregister(rtc); - - return err; } static int x1205_remove(struct i2c_client *client) { - struct rtc_device *rtc = i2c_get_clientdata(client); - - rtc_device_unregister(rtc); x1205_sysfs_unregister(&client->dev); return 0; } diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c index 08c3bc398da2..43bb55827f30 100644 --- a/drivers/scsi/fcoe/fcoe_ctlr.c +++ b/drivers/scsi/fcoe/fcoe_ctlr.c @@ -2161,7 +2161,7 @@ static void fcoe_ctlr_vn_restart(struct fcoe_ctlr *fip) if (fip->probe_tries < FIP_VN_RLIM_COUNT) { fip->probe_tries++; - wait = random32() % FIP_VN_PROBE_WAIT; + wait = prandom_u32() % FIP_VN_PROBE_WAIT; } else wait = FIP_VN_RLIM_INT; mod_timer(&fip->timer, jiffies + msecs_to_jiffies(wait)); @@ -2794,7 +2794,7 @@ static void fcoe_ctlr_vn_timeout(struct fcoe_ctlr *fip) fcoe_all_vn2vn, 0); fip->port_ka_time = jiffies + msecs_to_jiffies(FIP_VN_BEACON_INT + - (random32() % FIP_VN_BEACON_FUZZ)); + (prandom_u32() % FIP_VN_BEACON_FUZZ)); } if (time_before(fip->port_ka_time, next_time)) next_time = fip->port_ka_time; diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index d7096ad94d3f..bfda18467ee6 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -1732,7 +1732,7 @@ lpfc_check_pending_fcoe_event(struct lpfc_hba *phba, uint8_t unreg_fcf) * use through a sequence of @fcf_cnt eligible FCF records with equal * probability. To perform integer manunipulation of random numbers with * size unit32_t, the lower 16 bits of the 32-bit random number returned - * from random32() are taken as the random random number generated. + * from prandom_u32() are taken as the random random number generated. * * Returns true when outcome is for the newly read FCF record should be * chosen; otherwise, return false when outcome is for keeping the previously @@ -1744,7 +1744,7 @@ lpfc_sli4_new_fcf_random_select(struct lpfc_hba *phba, uint32_t fcf_cnt) uint32_t rand_num; /* Get 16-bit uniform random number */ - rand_num = (0xFFFF & random32()); + rand_num = 0xFFFF & prandom_u32(); /* Decision with probability 1/fcf_cnt */ if ((fcf_cnt * rand_num) < 0xFFFF) @@ -2380,7 +2380,7 @@ lpfc_mbx_cmpl_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) phba->fcf.eligible_fcf_cnt = 1; /* Seeding the random number generator for random selection */ seed = (uint32_t)(0xFFFFFFFF & jiffies); - srandom32(seed); + prandom_seed(seed); } spin_unlock_irq(&phba->hbalock); goto read_next_fcf; diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 1d82eef4e1eb..e44d47e23fe8 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -1939,10 +1939,13 @@ qla24xx_vport_delete(struct fc_vport *fc_vport) } /* No pending activities shall be there on the vha now */ - if (ql2xextended_error_logging & ql_dbg_user) - msleep(random32()%10); /* Just to see if something falls on - * the net we have placed below */ - + if (ql2xextended_error_logging & ql_dbg_user) { + /* + * Just to see if something falls on the net we have placed + * below + */ + msleep(prandom_u32() % 10); + } BUG_ON(atomic_read(&vha->vref_count)); qla2x00_free_fcports(vha); diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 9f0c46547459..df5e961484e1 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -35,6 +35,7 @@ static int sg_version_num = 30534; /* 2 digits for each component */ #include <linux/sched.h> #include <linux/string.h> #include <linux/mm.h> +#include <linux/aio.h> #include <linux/errno.h> #include <linux/mtio.h> #include <linux/ioctl.h> diff --git a/drivers/staging/android/logger.c b/drivers/staging/android/logger.c index b14a55742559..b040200a5a55 100644 --- a/drivers/staging/android/logger.c +++ b/drivers/staging/android/logger.c @@ -28,6 +28,7 @@ #include <linux/slab.h> #include <linux/time.h> #include <linux/vmalloc.h> +#include <linux/aio.h> #include "logger.h" #include <asm/ioctls.h> diff --git a/drivers/staging/zcache/Kconfig b/drivers/staging/zcache/Kconfig index c3b8a10e170f..d30722fe5730 100644 --- a/drivers/staging/zcache/Kconfig +++ b/drivers/staging/zcache/Kconfig @@ -1,5 +1,5 @@ config ZCACHE - bool "Dynamic compression of swap pages and clean pagecache pages" + tristate "Dynamic compression of swap pages and clean pagecache pages" depends on CRYPTO=y && SWAP=y && CLEANCACHE && FRONTSWAP select CRYPTO_LZO default n @@ -19,8 +19,8 @@ config ZCACHE_DEBUG how zcache is doing. You probably want to set this to 'N'. config RAMSTER - bool "Cross-machine RAM capacity sharing, aka peer-to-peer tmem" - depends on CONFIGFS_FS=y && SYSFS=y && !HIGHMEM && ZCACHE=y + tristate "Cross-machine RAM capacity sharing, aka peer-to-peer tmem" + depends on CONFIGFS_FS=y && SYSFS=y && !HIGHMEM && ZCACHE depends on NET # must ensure struct page is 8-byte aligned select HAVE_ALIGNED_STRUCT_PAGE if !64BIT diff --git a/drivers/staging/zcache/ramster.h b/drivers/staging/zcache/ramster.h index 1b71aea2ff62..e1f91d5a0f6a 100644 --- a/drivers/staging/zcache/ramster.h +++ b/drivers/staging/zcache/ramster.h @@ -11,10 +11,14 @@ #ifndef _ZCACHE_RAMSTER_H_ #define _ZCACHE_RAMSTER_H_ +#ifdef CONFIG_RAMSTER_MODULE +#define CONFIG_RAMSTER +#endif + #ifdef CONFIG_RAMSTER #include "ramster/ramster.h" #else -static inline void ramster_init(bool x, bool y, bool z) +static inline void ramster_init(bool x, bool y, bool z, bool w) { } diff --git a/drivers/staging/zcache/ramster/nodemanager.c b/drivers/staging/zcache/ramster/nodemanager.c index c0f48158735d..2cfe93342c0d 100644 --- a/drivers/staging/zcache/ramster/nodemanager.c +++ b/drivers/staging/zcache/ramster/nodemanager.c @@ -949,7 +949,7 @@ static void __exit exit_r2nm(void) r2hb_exit(); } -static int __init init_r2nm(void) +int r2nm_init(void) { int ret = -1; @@ -986,10 +986,11 @@ out_r2hb: out: return ret; } +EXPORT_SYMBOL_GPL(r2nm_init); MODULE_AUTHOR("Oracle"); MODULE_LICENSE("GPL"); -/* module_init(init_r2nm) */ -late_initcall(init_r2nm); -/* module_exit(exit_r2nm) */ +#ifndef CONFIG_RAMSTER_MODULE +late_initcall(r2nm_init); +#endif diff --git a/drivers/staging/zcache/ramster/ramster.c b/drivers/staging/zcache/ramster/ramster.c index bf96a1cbf7c1..4f715c791188 100644 --- a/drivers/staging/zcache/ramster/ramster.c +++ b/drivers/staging/zcache/ramster/ramster.c @@ -92,7 +92,7 @@ static ssize_t ramster_remote_page_flushes_failed; #include <linux/debugfs.h> #define zdfs debugfs_create_size_t #define zdfs64 debugfs_create_u64 -static int __init ramster_debugfs_init(void) +static int ramster_debugfs_init(void) { struct dentry *root = debugfs_create_dir("ramster", NULL); if (root == NULL) @@ -191,6 +191,7 @@ int ramster_do_preload_flnode(struct tmem_pool *pool) kmem_cache_free(ramster_flnode_cache, flnode); return ret; } +EXPORT_SYMBOL_GPL(ramster_do_preload_flnode); /* * Called by the message handler after a (still compressed) page has been @@ -458,6 +459,7 @@ void *ramster_pampd_free(void *pampd, struct tmem_pool *pool, } return local_pampd; } +EXPORT_SYMBOL_GPL(ramster_pampd_free); void ramster_count_foreign_pages(bool eph, int count) { @@ -489,6 +491,7 @@ void ramster_count_foreign_pages(bool eph, int count) ramster_foreign_pers_pages = c; } } +EXPORT_SYMBOL_GPL(ramster_count_foreign_pages); /* * For now, just push over a few pages every few seconds to @@ -674,7 +677,7 @@ requeue: ramster_remotify_queue_delayed_work(HZ); } -void __init ramster_remotify_init(void) +void ramster_remotify_init(void) { unsigned long n = 60UL; ramster_remotify_workqueue = @@ -849,8 +852,10 @@ static bool frontswap_selfshrinking __read_mostly; static void selfshrink_process(struct work_struct *work); static DECLARE_DELAYED_WORK(selfshrink_worker, selfshrink_process); +#ifndef CONFIG_RAMSTER_MODULE /* Enable/disable with kernel boot option. */ static bool use_frontswap_selfshrink __initdata = true; +#endif /* * The default values for the following parameters were deemed reasonable @@ -905,6 +910,7 @@ static void frontswap_selfshrink(void) frontswap_shrink(tgt_frontswap_pages); } +#ifndef CONFIG_RAMSTER_MODULE static int __init ramster_nofrontswap_selfshrink_setup(char *s) { use_frontswap_selfshrink = false; @@ -912,6 +918,7 @@ static int __init ramster_nofrontswap_selfshrink_setup(char *s) } __setup("noselfshrink", ramster_nofrontswap_selfshrink_setup); +#endif static void selfshrink_process(struct work_struct *work) { @@ -930,6 +937,7 @@ void ramster_cpu_up(int cpu) per_cpu(ramster_remoteputmem1, cpu) = p1; per_cpu(ramster_remoteputmem2, cpu) = p2; } +EXPORT_SYMBOL_GPL(ramster_cpu_up); void ramster_cpu_down(int cpu) { @@ -945,6 +953,7 @@ void ramster_cpu_down(int cpu) kp->flnode = NULL; } } +EXPORT_SYMBOL_GPL(ramster_cpu_down); void ramster_register_pamops(struct tmem_pamops *pamops) { @@ -955,9 +964,11 @@ void ramster_register_pamops(struct tmem_pamops *pamops) pamops->repatriate = ramster_pampd_repatriate; pamops->repatriate_preload = ramster_pampd_repatriate_preload; } +EXPORT_SYMBOL_GPL(ramster_register_pamops); -void __init ramster_init(bool cleancache, bool frontswap, - bool frontswap_exclusive_gets) +void ramster_init(bool cleancache, bool frontswap, + bool frontswap_exclusive_gets, + bool frontswap_selfshrink) { int ret = 0; @@ -972,10 +983,17 @@ void __init ramster_init(bool cleancache, bool frontswap, if (ret) pr_err("ramster: can't create sysfs for ramster\n"); (void)r2net_register_handlers(); +#ifdef CONFIG_RAMSTER_MODULE + ret = r2nm_init(); + if (ret) + pr_err("ramster: can't init r2net\n"); + frontswap_selfshrinking = frontswap_selfshrink; +#else + frontswap_selfshrinking = use_frontswap_selfshrink; +#endif INIT_LIST_HEAD(&ramster_rem_op_list); ramster_flnode_cache = kmem_cache_create("ramster_flnode", sizeof(struct flushlist_node), 0, 0, NULL); - frontswap_selfshrinking = use_frontswap_selfshrink; if (frontswap_selfshrinking) { pr_info("ramster: Initializing frontswap selfshrink driver.\n"); schedule_delayed_work(&selfshrink_worker, @@ -983,3 +1001,4 @@ void __init ramster_init(bool cleancache, bool frontswap, } ramster_remotify_init(); } +EXPORT_SYMBOL_GPL(ramster_init); diff --git a/drivers/staging/zcache/ramster/ramster.h b/drivers/staging/zcache/ramster/ramster.h index 12ae56f09ca4..6d41a7a772e3 100644 --- a/drivers/staging/zcache/ramster/ramster.h +++ b/drivers/staging/zcache/ramster/ramster.h @@ -147,7 +147,7 @@ extern int r2net_register_handlers(void); extern int r2net_remote_target_node_set(int); extern int ramster_remotify_pageframe(bool); -extern void ramster_init(bool, bool, bool); +extern void ramster_init(bool, bool, bool, bool); extern void ramster_register_pamops(struct tmem_pamops *); extern int ramster_localify(int, struct tmem_oid *oidp, uint32_t, char *, unsigned int, void *); diff --git a/drivers/staging/zcache/ramster/ramster_nodemanager.h b/drivers/staging/zcache/ramster/ramster_nodemanager.h index 49f879d943ab..dbaae34ea613 100644 --- a/drivers/staging/zcache/ramster/ramster_nodemanager.h +++ b/drivers/staging/zcache/ramster/ramster_nodemanager.h @@ -36,4 +36,6 @@ /* host name, group name, cluster name all 64 bytes */ #define R2NM_MAX_NAME_LEN 64 /* __NEW_UTS_LEN */ +extern int r2nm_init(void); + #endif /* _RAMSTER_NODEMANAGER_H */ diff --git a/drivers/staging/zcache/tmem.c b/drivers/staging/zcache/tmem.c index a2b7e03b6062..d7e51e4152eb 100644 --- a/drivers/staging/zcache/tmem.c +++ b/drivers/staging/zcache/tmem.c @@ -35,7 +35,8 @@ #include <linux/list.h> #include <linux/spinlock.h> #include <linux/atomic.h> -#ifdef CONFIG_RAMSTER +#include <linux/export.h> +#if defined(CONFIG_RAMSTER) || defined(CONFIG_RAMSTER_MODULE) #include <linux/delay.h> #endif @@ -641,6 +642,7 @@ void *tmem_localify_get_pampd(struct tmem_pool *pool, struct tmem_oid *oidp, /* note, hashbucket remains locked */ return pampd; } +EXPORT_SYMBOL_GPL(tmem_localify_get_pampd); void tmem_localify_finish(struct tmem_obj *obj, uint32_t index, void *pampd, void *saved_hb, bool delete) @@ -658,6 +660,7 @@ void tmem_localify_finish(struct tmem_obj *obj, uint32_t index, } spin_unlock(&hb->lock); } +EXPORT_SYMBOL_GPL(tmem_localify_finish); /* * For ramster only. Helper function to support asynchronous tmem_get. @@ -719,6 +722,7 @@ out: spin_unlock(&hb->lock); return ret; } +EXPORT_SYMBOL_GPL(tmem_replace); #endif /* diff --git a/drivers/staging/zcache/tmem.h b/drivers/staging/zcache/tmem.h index adbe5a8f28aa..d128ce290f1f 100644 --- a/drivers/staging/zcache/tmem.h +++ b/drivers/staging/zcache/tmem.h @@ -126,7 +126,7 @@ static inline unsigned tmem_oid_hash(struct tmem_oid *oidp) TMEM_HASH_BUCKET_BITS); } -#ifdef CONFIG_RAMSTER +#if defined(CONFIG_RAMSTER) || defined(CONFIG_RAMSTER_MODULE) struct tmem_xhandle { uint8_t client_id; uint8_t xh_data_cksum; @@ -171,7 +171,7 @@ struct tmem_obj { unsigned int objnode_tree_height; unsigned long objnode_count; long pampd_count; -#ifdef CONFIG_RAMSTER +#if defined(CONFIG_RAMSTER) || defined(CONFIG_RAMSTER_MODULE) /* * for current design of ramster, all pages belonging to * an object reside on the same remotenode and extra is @@ -215,7 +215,7 @@ struct tmem_pamops { uint32_t); void (*free)(void *, struct tmem_pool *, struct tmem_oid *, uint32_t, bool); -#ifdef CONFIG_RAMSTER +#if defined(CONFIG_RAMSTER) || defined(CONFIG_RAMSTER_MODULE) void (*new_obj)(struct tmem_obj *); void (*free_obj)(struct tmem_pool *, struct tmem_obj *, bool); void *(*repatriate_preload)(void *, struct tmem_pool *, @@ -247,7 +247,7 @@ extern int tmem_flush_page(struct tmem_pool *, struct tmem_oid *, extern int tmem_flush_object(struct tmem_pool *, struct tmem_oid *); extern int tmem_destroy_pool(struct tmem_pool *); extern void tmem_new_pool(struct tmem_pool *, uint32_t); -#ifdef CONFIG_RAMSTER +#if defined(CONFIG_RAMSTER) || defined(CONFIG_RAMSTER_MODULE) extern int tmem_replace(struct tmem_pool *, struct tmem_oid *, uint32_t index, void *); extern void *tmem_localify_get_pampd(struct tmem_pool *, struct tmem_oid *, diff --git a/drivers/staging/zcache/zcache-main.c b/drivers/staging/zcache/zcache-main.c index 86ead8d96796..00c3e9aad74f 100644 --- a/drivers/staging/zcache/zcache-main.c +++ b/drivers/staging/zcache/zcache-main.c @@ -37,8 +37,10 @@ #include "debug.h" #ifdef CONFIG_RAMSTER static bool ramster_enabled __read_mostly; +static int disable_frontswap_selfshrink; #else #define ramster_enabled false +#define disable_frontswap_selfshrink 0 #endif #ifndef __PG_WAS_ACTIVE @@ -75,8 +77,12 @@ static char *namestr __read_mostly = "zcache"; (__GFP_FS | __GFP_NORETRY | __GFP_NOWARN | __GFP_NOMEMALLOC) /* crypto API for zcache */ +#ifdef CONFIG_ZCACHE_MODULE +static char *zcache_comp_name = "lzo"; +#else #define ZCACHE_COMP_NAME_SZ CRYPTO_MAX_ALG_NAME static char zcache_comp_name[ZCACHE_COMP_NAME_SZ] __read_mostly; +#endif static struct crypto_comp * __percpu *zcache_comp_pcpu_tfms __read_mostly; enum comp_op { @@ -1509,9 +1515,9 @@ static struct cleancache_ops zcache_cleancache_ops = { .init_fs = zcache_cleancache_init_fs }; -struct cleancache_ops zcache_cleancache_register_ops(void) +struct cleancache_ops *zcache_cleancache_register_ops(void) { - struct cleancache_ops old_ops = + struct cleancache_ops *old_ops = cleancache_register_ops(&zcache_cleancache_ops); return old_ops; @@ -1640,9 +1646,9 @@ static struct frontswap_ops zcache_frontswap_ops = { .init = zcache_frontswap_init }; -struct frontswap_ops zcache_frontswap_register_ops(void) +struct frontswap_ops *zcache_frontswap_register_ops(void) { - struct frontswap_ops old_ops = + struct frontswap_ops *old_ops = frontswap_register_ops(&zcache_frontswap_ops); return old_ops; @@ -1654,6 +1660,7 @@ struct frontswap_ops zcache_frontswap_register_ops(void) * OR NOTHING HAPPENS! */ +#ifndef CONFIG_ZCACHE_MODULE static int __init enable_zcache(char *s) { zcache_enabled = true; @@ -1720,18 +1727,27 @@ static int __init enable_zcache_compressor(char *s) return 1; } __setup("zcache=", enable_zcache_compressor); +#endif -static int __init zcache_comp_init(void) +static int zcache_comp_init(void) { int ret = 0; /* check crypto algorithm */ +#ifdef CONFIG_ZCACHE_MODULE + ret = crypto_has_comp(zcache_comp_name, 0, 0); + if (!ret) { + ret = -1; + goto out; + } +#else if (*zcache_comp_name != '\0') { ret = crypto_has_comp(zcache_comp_name, 0, 0); if (!ret) pr_info("zcache: %s not supported\n", zcache_comp_name); + goto out; } if (!ret) strcpy(zcache_comp_name, "lzo"); @@ -1740,6 +1756,7 @@ static int __init zcache_comp_init(void) ret = 1; goto out; } +#endif pr_info("zcache: using %s compressor\n", zcache_comp_name); /* alloc percpu transforms */ @@ -1751,10 +1768,13 @@ out: return ret; } -static int __init zcache_init(void) +static int zcache_init(void) { int ret = 0; +#ifdef CONFIG_ZCACHE_MODULE + zcache_enabled = 1; +#endif if (ramster_enabled) { namestr = "ramster"; ramster_register_pamops(&zcache_pamops); @@ -1795,7 +1815,7 @@ static int __init zcache_init(void) } zbud_init(); if (zcache_enabled && !disable_cleancache) { - struct cleancache_ops old_ops; + struct cleancache_ops *old_ops; register_shrinker(&zcache_shrinker); old_ops = zcache_cleancache_register_ops(); @@ -1805,11 +1825,11 @@ static int __init zcache_init(void) pr_info("%s: cleancache: ignorenonactive = %d\n", namestr, !disable_cleancache_ignore_nonactive); #endif - if (old_ops.init_fs != NULL) + if (old_ops != NULL) pr_warn("%s: cleancache_ops overridden\n", namestr); } if (zcache_enabled && !disable_frontswap) { - struct frontswap_ops old_ops; + struct frontswap_ops *old_ops; old_ops = zcache_frontswap_register_ops(); if (frontswap_has_exclusive_gets) @@ -1821,14 +1841,36 @@ static int __init zcache_init(void) namestr, frontswap_has_exclusive_gets, !disable_frontswap_ignore_nonactive); #endif - if (old_ops.init != NULL) + if (IS_ERR(old_ops) || old_ops) { + if (IS_ERR(old_ops)) + return PTR_RET(old_ops); pr_warn("%s: frontswap_ops overridden\n", namestr); + } } if (ramster_enabled) ramster_init(!disable_cleancache, !disable_frontswap, - frontswap_has_exclusive_gets); + frontswap_has_exclusive_gets, + !disable_frontswap_selfshrink); out: return ret; } +#ifdef CONFIG_ZCACHE_MODULE +#ifdef CONFIG_RAMSTER +module_param(ramster_enabled, int, S_IRUGO); +module_param(disable_frontswap_selfshrink, int, S_IRUGO); +#endif +module_param(disable_cleancache, int, S_IRUGO); +module_param(disable_frontswap, int, S_IRUGO); +#ifdef FRONTSWAP_HAS_EXCLUSIVE_GETS +module_param(frontswap_has_exclusive_gets, bool, S_IRUGO); +#endif +module_param(disable_frontswap_ignore_nonactive, int, S_IRUGO); +module_param(zcache_comp_name, charp, S_IRUGO); +module_init(zcache_init); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Dan Magenheimer <dan.magenheimer@oracle.com>"); +MODULE_DESCRIPTION("In-kernel compression of cleancache/frontswap pages"); +#else late_initcall(zcache_init); +#endif diff --git a/drivers/staging/zcache/zcache.h b/drivers/staging/zcache/zcache.h index 81722b33b087..849120095e79 100644 --- a/drivers/staging/zcache/zcache.h +++ b/drivers/staging/zcache/zcache.h @@ -39,7 +39,7 @@ extern int zcache_flush_page(int, int, struct tmem_oid *, uint32_t); extern int zcache_flush_object(int, int, struct tmem_oid *); extern void zcache_decompress_to_page(char *, unsigned int, struct page *); -#ifdef CONFIG_RAMSTER +#if defined(CONFIG_RAMSTER) || defined(CONFIG_RAMSTER_MODULE) extern void *zcache_pampd_create(char *, unsigned int, bool, int, struct tmem_handle *); int zcache_autocreate_pool(unsigned int cli_id, unsigned int pool_id, bool eph); diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c index f52dcfe8f545..24bd363ca351 100644 --- a/drivers/usb/gadget/amd5536udc.c +++ b/drivers/usb/gadget/amd5536udc.c @@ -3099,7 +3099,7 @@ static int init_dma_pools(struct udc *dev) } /* DMA setup */ - dev->data_requests = dma_pool_create("data_requests", NULL, + dev->data_requests = dma_pool_create("data_requests", &dev->pdev->dev, sizeof(struct udc_data_dma), 0, 0); if (!dev->data_requests) { DBG(dev, "can't get request data pool\n"); @@ -3111,7 +3111,7 @@ static int init_dma_pools(struct udc *dev) dev->ep[UDC_EP0IN_IX].dma = &dev->regs->ctl; /* dma desc for setup data */ - dev->stp_requests = dma_pool_create("setup requests", NULL, + dev->stp_requests = dma_pool_create("setup requests", &dev->pdev->dev, sizeof(struct udc_stp_dma), 0, 0); if (!dev->stp_requests) { DBG(dev, "can't get stp request pool\n"); diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index e2b2e9cf254a..5cc4e7eed4a9 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c @@ -24,6 +24,8 @@ #include <linux/sched.h> #include <linux/slab.h> #include <linux/poll.h> +#include <linux/mmu_context.h> +#include <linux/aio.h> #include <linux/device.h> #include <linux/moduleparam.h> @@ -513,6 +515,9 @@ static long ep_ioctl(struct file *fd, unsigned code, unsigned long value) struct kiocb_priv { struct usb_request *req; struct ep_data *epdata; + struct kiocb *iocb; + struct mm_struct *mm; + struct work_struct work; void *buf; const struct iovec *iv; unsigned long nr_segs; @@ -528,7 +533,6 @@ static int ep_aio_cancel(struct kiocb *iocb, struct io_event *e) local_irq_disable(); epdata = priv->epdata; // spin_lock(&epdata->dev->lock); - kiocbSetCancelled(iocb); if (likely(epdata && epdata->ep && priv->req)) value = usb_ep_dequeue (epdata->ep, priv->req); else @@ -540,15 +544,12 @@ static int ep_aio_cancel(struct kiocb *iocb, struct io_event *e) return value; } -static ssize_t ep_aio_read_retry(struct kiocb *iocb) +static ssize_t ep_copy_to_user(struct kiocb_priv *priv) { - struct kiocb_priv *priv = iocb->private; ssize_t len, total; void *to_copy; int i; - /* we "retry" to get the right mm context for this: */ - /* copy stuff into user buffers */ total = priv->actual; len = 0; @@ -568,9 +569,26 @@ static ssize_t ep_aio_read_retry(struct kiocb *iocb) if (total == 0) break; } + + return len; +} + +static void ep_user_copy_worker(struct work_struct *work) +{ + struct kiocb_priv *priv = container_of(work, struct kiocb_priv, work); + struct mm_struct *mm = priv->mm; + struct kiocb *iocb = priv->iocb; + size_t ret; + + use_mm(mm); + ret = ep_copy_to_user(priv); + unuse_mm(mm); + + /* completing the iocb can drop the ctx and mm, don't touch mm after */ + aio_complete(iocb, ret, ret); + kfree(priv->buf); kfree(priv); - return len; } static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req) @@ -596,14 +614,14 @@ static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req) aio_complete(iocb, req->actual ? req->actual : req->status, req->status); } else { - /* retry() won't report both; so we hide some faults */ + /* ep_copy_to_user() won't report both; we hide some faults */ if (unlikely(0 != req->status)) DBG(epdata->dev, "%s fault %d len %d\n", ep->name, req->status, req->actual); priv->buf = req->buf; priv->actual = req->actual; - kick_iocb(iocb); + schedule_work(&priv->work); } spin_unlock(&epdata->dev->lock); @@ -633,8 +651,10 @@ fail: return value; } iocb->private = priv; + priv->iocb = iocb; priv->iv = iv; priv->nr_segs = nr_segs; + INIT_WORK(&priv->work, ep_user_copy_worker); value = get_ready_ep(iocb->ki_filp->f_flags, epdata); if (unlikely(value < 0)) { @@ -642,10 +662,11 @@ fail: goto fail; } - iocb->ki_cancel = ep_aio_cancel; + kiocb_set_cancel_fn(iocb, ep_aio_cancel); get_ep(epdata); priv->epdata = epdata; priv->actual = 0; + priv->mm = current->mm; /* mm teardown waits for iocbs in exit_aio() */ /* each kiocb is coupled to one usb_request, but we can't * allocate or submit those if the host disconnected. @@ -674,7 +695,7 @@ fail: kfree(priv); put_ep(epdata); } else - value = (iv ? -EIOCBRETRY : -EIOCBQUEUED); + value = -EIOCBQUEUED; return value; } @@ -692,7 +713,6 @@ ep_aio_read(struct kiocb *iocb, const struct iovec *iov, if (unlikely(!buf)) return -ENOMEM; - iocb->ki_retry = ep_aio_read_retry; return ep_aio_rwtail(iocb, buf, iocb->ki_left, epdata, iov, nr_segs); } diff --git a/drivers/uwb/rsv.c b/drivers/uwb/rsv.c index 0b0d8bce842e..f4ae05f78c42 100644 --- a/drivers/uwb/rsv.c +++ b/drivers/uwb/rsv.c @@ -231,7 +231,7 @@ void uwb_rsv_backoff_win_increment(struct uwb_rc *rc) return; bow->window <<= 1; - bow->n = random32() & (bow->window - 1); + bow->n = prandom_u32() & (bow->window - 1); dev_dbg(dev, "new_window=%d, n=%d\n: ", bow->window, bow->n); /* reset the timer associated variables */ @@ -557,7 +557,7 @@ int uwb_rsv_establish(struct uwb_rsv *rsv) if (ret) goto out; - rsv->tiebreaker = random32() & 1; + rsv->tiebreaker = prandom_u32() & 1; /* get available mas bitmap */ uwb_drp_available(rc, &available); diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index e7718fdad1e1..0181a87dc4bc 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -2453,6 +2453,15 @@ config FB_PUV3_UNIGFX Choose this option if you want to use the Unigfx device as a framebuffer device. Without the support of PCI & AGP. +config FB_HYPERV + tristate "Microsoft Hyper-V Synthetic Video support" + depends on FB && HYPERV + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This framebuffer driver supports Microsoft Hyper-V Synthetic Video. + source "drivers/video/omap/Kconfig" source "drivers/video/omap2/Kconfig" source "drivers/video/exynos/Kconfig" diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 9df387334cb7..97f7b6d6a0b2 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -149,6 +149,7 @@ obj-$(CONFIG_FB_MSM) += msm/ obj-$(CONFIG_FB_NUC900) += nuc900fb.o obj-$(CONFIG_FB_JZ4740) += jz4740_fb.o obj-$(CONFIG_FB_PUV3_UNIGFX) += fb-puv3.o +obj-$(CONFIG_FB_HYPERV) += hyperv_fb.o # Platform or fallback drivers go here obj-$(CONFIG_FB_UVESA) += uvesafb.o diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index db10d0120d2b..2e166c3fc4c3 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig @@ -59,6 +59,13 @@ config LCD_LTV350QV The LTV350QV panel is present on all ATSTK1000 boards. +config LCD_ILI922X + tristate "ILI Technology ILI9221/ILI9222 support" + depends on SPI + help + If you have a panel based on the ILI9221/9222 controller + chip then say y to include a driver for it. + config LCD_ILI9320 tristate "ILI Technology ILI9320 controller support" depends on SPI @@ -161,7 +168,7 @@ if BACKLIGHT_CLASS_DEVICE config BACKLIGHT_ATMEL_LCDC bool "Atmel LCDC Contrast-as-Backlight control" depends on FB_ATMEL - default y if MACH_SAM9261EK || MACH_SAM9G10EK || MACH_SAM9263EK + default y if MACH_AT91SAM9261EK || MACH_AT91SAM9G10EK || MACH_AT91SAM9263EK help This provides a backlight control internal to the Atmel LCDC driver. If the LCD "contrast control" on your board is wired diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile index 96c4d620c5ce..92711fe60464 100644 --- a/drivers/video/backlight/Makefile +++ b/drivers/video/backlight/Makefile @@ -5,6 +5,7 @@ obj-$(CONFIG_LCD_CLASS_DEVICE) += lcd.o obj-$(CONFIG_LCD_CORGI) += corgi_lcd.o obj-$(CONFIG_LCD_HP700) += jornada720_lcd.o obj-$(CONFIG_LCD_HX8357) += hx8357.o +obj-$(CONFIG_LCD_ILI922X) += ili922x.o obj-$(CONFIG_LCD_ILI9320) += ili9320.o obj-$(CONFIG_LCD_L4F00242T03) += l4f00242t03.o obj-$(CONFIG_LCD_LD9040) += ld9040.o diff --git a/drivers/video/backlight/adp5520_bl.c b/drivers/video/backlight/adp5520_bl.c index a1e41d4faa71..c84701b7ca6e 100644 --- a/drivers/video/backlight/adp5520_bl.c +++ b/drivers/video/backlight/adp5520_bl.c @@ -143,13 +143,16 @@ static int adp5520_bl_setup(struct backlight_device *bl) static ssize_t adp5520_show(struct device *dev, char *buf, int reg) { struct adp5520_bl *data = dev_get_drvdata(dev); - int error; + int ret; uint8_t reg_val; mutex_lock(&data->lock); - error = adp5520_read(data->master, reg, ®_val); + ret = adp5520_read(data->master, reg, ®_val); mutex_unlock(&data->lock); + if (ret < 0) + return ret; + return sprintf(buf, "%u\n", reg_val); } @@ -349,35 +352,34 @@ static int adp5520_bl_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM -static int adp5520_bl_suspend(struct platform_device *pdev, - pm_message_t state) +#ifdef CONFIG_PM_SLEEP +static int adp5520_bl_suspend(struct device *dev) { - struct backlight_device *bl = platform_get_drvdata(pdev); + struct backlight_device *bl = dev_get_drvdata(dev); + return adp5520_bl_set(bl, 0); } -static int adp5520_bl_resume(struct platform_device *pdev) +static int adp5520_bl_resume(struct device *dev) { - struct backlight_device *bl = platform_get_drvdata(pdev); + struct backlight_device *bl = dev_get_drvdata(dev); backlight_update_status(bl); return 0; } -#else -#define adp5520_bl_suspend NULL -#define adp5520_bl_resume NULL #endif +static SIMPLE_DEV_PM_OPS(adp5520_bl_pm_ops, adp5520_bl_suspend, + adp5520_bl_resume); + static struct platform_driver adp5520_bl_driver = { .driver = { .name = "adp5520-backlight", .owner = THIS_MODULE, + .pm = &adp5520_bl_pm_ops, }, .probe = adp5520_bl_probe, .remove = adp5520_bl_remove, - .suspend = adp5520_bl_suspend, - .resume = adp5520_bl_resume, }; module_platform_driver(adp5520_bl_driver); diff --git a/drivers/video/backlight/adp8860_bl.c b/drivers/video/backlight/adp8860_bl.c index a77c9cad3320..6bb7f3644b3d 100644 --- a/drivers/video/backlight/adp8860_bl.c +++ b/drivers/video/backlight/adp8860_bl.c @@ -773,25 +773,29 @@ static int adp8860_remove(struct i2c_client *client) return 0; } -#ifdef CONFIG_PM -static int adp8860_i2c_suspend(struct i2c_client *client, pm_message_t message) +#ifdef CONFIG_PM_SLEEP +static int adp8860_i2c_suspend(struct device *dev) { + struct i2c_client *client = to_i2c_client(dev); + adp8860_clr_bits(client, ADP8860_MDCR, NSTBY); return 0; } -static int adp8860_i2c_resume(struct i2c_client *client) +static int adp8860_i2c_resume(struct device *dev) { + struct i2c_client *client = to_i2c_client(dev); + adp8860_set_bits(client, ADP8860_MDCR, NSTBY | BLEN); return 0; } -#else -#define adp8860_i2c_suspend NULL -#define adp8860_i2c_resume NULL #endif +static SIMPLE_DEV_PM_OPS(adp8860_i2c_pm_ops, adp8860_i2c_suspend, + adp8860_i2c_resume); + static const struct i2c_device_id adp8860_id[] = { { "adp8860", adp8860 }, { "adp8861", adp8861 }, @@ -802,12 +806,11 @@ MODULE_DEVICE_TABLE(i2c, adp8860_id); static struct i2c_driver adp8860_driver = { .driver = { - .name = KBUILD_MODNAME, + .name = KBUILD_MODNAME, + .pm = &adp8860_i2c_pm_ops, }, .probe = adp8860_probe, .remove = adp8860_remove, - .suspend = adp8860_i2c_suspend, - .resume = adp8860_i2c_resume, .id_table = adp8860_id, }; diff --git a/drivers/video/backlight/adp8870_bl.c b/drivers/video/backlight/adp8870_bl.c index 712c25a0d8fe..302c8009a7dc 100644 --- a/drivers/video/backlight/adp8870_bl.c +++ b/drivers/video/backlight/adp8870_bl.c @@ -895,13 +895,13 @@ static int adp8870_probe(struct i2c_client *client, data->bl = bl; - if (pdata->en_ambl_sens) + if (pdata->en_ambl_sens) { ret = sysfs_create_group(&bl->dev.kobj, &adp8870_bl_attr_group); - - if (ret) { - dev_err(&client->dev, "failed to register sysfs\n"); - goto out1; + if (ret) { + dev_err(&client->dev, "failed to register sysfs\n"); + goto out1; + } } ret = adp8870_bl_setup(bl); @@ -947,25 +947,29 @@ static int adp8870_remove(struct i2c_client *client) return 0; } -#ifdef CONFIG_PM -static int adp8870_i2c_suspend(struct i2c_client *client, pm_message_t message) +#ifdef CONFIG_PM_SLEEP +static int adp8870_i2c_suspend(struct device *dev) { + struct i2c_client *client = to_i2c_client(dev); + adp8870_clr_bits(client, ADP8870_MDCR, NSTBY); return 0; } -static int adp8870_i2c_resume(struct i2c_client *client) +static int adp8870_i2c_resume(struct device *dev) { + struct i2c_client *client = to_i2c_client(dev); + adp8870_set_bits(client, ADP8870_MDCR, NSTBY | BLEN); return 0; } -#else -#define adp8870_i2c_suspend NULL -#define adp8870_i2c_resume NULL #endif +static SIMPLE_DEV_PM_OPS(adp8870_i2c_pm_ops, adp8870_i2c_suspend, + adp8870_i2c_resume); + static const struct i2c_device_id adp8870_id[] = { { "adp8870", 0 }, { } @@ -974,12 +978,11 @@ MODULE_DEVICE_TABLE(i2c, adp8870_id); static struct i2c_driver adp8870_driver = { .driver = { - .name = KBUILD_MODNAME, + .name = KBUILD_MODNAME, + .pm = &adp8870_i2c_pm_ops, }, .probe = adp8870_probe, .remove = adp8870_remove, - .suspend = adp8870_i2c_suspend, - .resume = adp8870_i2c_resume, .id_table = adp8870_id, }; diff --git a/drivers/video/backlight/ams369fg06.c b/drivers/video/backlight/ams369fg06.c index c02aa2c2575a..319fef6cb422 100644 --- a/drivers/video/backlight/ams369fg06.c +++ b/drivers/video/backlight/ams369fg06.c @@ -533,12 +533,12 @@ static int ams369fg06_remove(struct spi_device *spi) return 0; } -#if defined(CONFIG_PM) -static int ams369fg06_suspend(struct spi_device *spi, pm_message_t mesg) +#ifdef CONFIG_PM_SLEEP +static int ams369fg06_suspend(struct device *dev) { - struct ams369fg06 *lcd = spi_get_drvdata(spi); + struct ams369fg06 *lcd = dev_get_drvdata(dev); - dev_dbg(&spi->dev, "lcd->power = %d\n", lcd->power); + dev_dbg(dev, "lcd->power = %d\n", lcd->power); /* * when lcd panel is suspend, lcd panel becomes off @@ -547,19 +547,19 @@ static int ams369fg06_suspend(struct spi_device *spi, pm_message_t mesg) return ams369fg06_power(lcd, FB_BLANK_POWERDOWN); } -static int ams369fg06_resume(struct spi_device *spi) +static int ams369fg06_resume(struct device *dev) { - struct ams369fg06 *lcd = spi_get_drvdata(spi); + struct ams369fg06 *lcd = dev_get_drvdata(dev); lcd->power = FB_BLANK_POWERDOWN; return ams369fg06_power(lcd, FB_BLANK_UNBLANK); } -#else -#define ams369fg06_suspend NULL -#define ams369fg06_resume NULL #endif +static SIMPLE_DEV_PM_OPS(ams369fg06_pm_ops, ams369fg06_suspend, + ams369fg06_resume); + static void ams369fg06_shutdown(struct spi_device *spi) { struct ams369fg06 *lcd = spi_get_drvdata(spi); @@ -571,12 +571,11 @@ static struct spi_driver ams369fg06_driver = { .driver = { .name = "ams369fg06", .owner = THIS_MODULE, + .pm = &ams369fg06_pm_ops, }, .probe = ams369fg06_probe, .remove = ams369fg06_remove, .shutdown = ams369fg06_shutdown, - .suspend = ams369fg06_suspend, - .resume = ams369fg06_resume, }; module_spi_driver(ams369fg06_driver); diff --git a/drivers/video/backlight/atmel-pwm-bl.c b/drivers/video/backlight/atmel-pwm-bl.c index de5e5e74e2a7..a60d6afca97c 100644 --- a/drivers/video/backlight/atmel-pwm-bl.c +++ b/drivers/video/backlight/atmel-pwm-bl.c @@ -118,7 +118,7 @@ static const struct backlight_ops atmel_pwm_bl_ops = { .update_status = atmel_pwm_bl_set_intensity, }; -static int atmel_pwm_bl_probe(struct platform_device *pdev) +static int __init atmel_pwm_bl_probe(struct platform_device *pdev) { struct backlight_properties props; const struct atmel_pwm_bl_platform_data *pdata; @@ -225,17 +225,7 @@ static struct platform_driver atmel_pwm_bl_driver = { .remove = __exit_p(atmel_pwm_bl_remove), }; -static int __init atmel_pwm_bl_init(void) -{ - return platform_driver_probe(&atmel_pwm_bl_driver, atmel_pwm_bl_probe); -} -module_init(atmel_pwm_bl_init); - -static void __exit atmel_pwm_bl_exit(void) -{ - platform_driver_unregister(&atmel_pwm_bl_driver); -} -module_exit(atmel_pwm_bl_exit); +module_platform_driver_probe(atmel_pwm_bl_driver, atmel_pwm_bl_probe); MODULE_AUTHOR("Hans-Christian egtvedt <hans-christian.egtvedt@atmel.com>"); MODULE_DESCRIPTION("Atmel PWM backlight driver"); diff --git a/drivers/video/backlight/corgi_lcd.c b/drivers/video/backlight/corgi_lcd.c index aa782f302983..c97867a717a7 100644 --- a/drivers/video/backlight/corgi_lcd.c +++ b/drivers/video/backlight/corgi_lcd.c @@ -457,10 +457,10 @@ static const struct backlight_ops corgi_bl_ops = { .update_status = corgi_bl_update_status, }; -#ifdef CONFIG_PM -static int corgi_lcd_suspend(struct spi_device *spi, pm_message_t state) +#ifdef CONFIG_PM_SLEEP +static int corgi_lcd_suspend(struct device *dev) { - struct corgi_lcd *lcd = spi_get_drvdata(spi); + struct corgi_lcd *lcd = dev_get_drvdata(dev); corgibl_flags |= CORGIBL_SUSPENDED; corgi_bl_set_intensity(lcd, 0); @@ -468,20 +468,19 @@ static int corgi_lcd_suspend(struct spi_device *spi, pm_message_t state) return 0; } -static int corgi_lcd_resume(struct spi_device *spi) +static int corgi_lcd_resume(struct device *dev) { - struct corgi_lcd *lcd = spi_get_drvdata(spi); + struct corgi_lcd *lcd = dev_get_drvdata(dev); corgibl_flags &= ~CORGIBL_SUSPENDED; corgi_lcd_set_power(lcd->lcd_dev, FB_BLANK_UNBLANK); backlight_update_status(lcd->bl_dev); return 0; } -#else -#define corgi_lcd_suspend NULL -#define corgi_lcd_resume NULL #endif +static SIMPLE_DEV_PM_OPS(corgi_lcd_pm_ops, corgi_lcd_suspend, corgi_lcd_resume); + static int setup_gpio_backlight(struct corgi_lcd *lcd, struct corgi_lcd_platform_data *pdata) { @@ -611,11 +610,10 @@ static struct spi_driver corgi_lcd_driver = { .driver = { .name = "corgi-lcd", .owner = THIS_MODULE, + .pm = &corgi_lcd_pm_ops, }, .probe = corgi_lcd_probe, .remove = corgi_lcd_remove, - .suspend = corgi_lcd_suspend, - .resume = corgi_lcd_resume, }; module_spi_driver(corgi_lcd_driver); diff --git a/drivers/video/backlight/da903x_bl.c b/drivers/video/backlight/da903x_bl.c index 8179cef0730f..67cadd30e273 100644 --- a/drivers/video/backlight/da903x_bl.c +++ b/drivers/video/backlight/da903x_bl.c @@ -88,16 +88,21 @@ static int da903x_backlight_update_status(struct backlight_device *bl) if (bl->props.fb_blank != FB_BLANK_UNBLANK) brightness = 0; + if (bl->props.state & BL_CORE_SUSPENDED) + brightness = 0; + return da903x_backlight_set(bl, brightness); } static int da903x_backlight_get_brightness(struct backlight_device *bl) { struct da903x_backlight_data *data = bl_get_data(bl); + return data->current_brightness; } static const struct backlight_ops da903x_backlight_ops = { + .options = BL_CORE_SUSPENDRESUME, .update_status = da903x_backlight_update_status, .get_brightness = da903x_backlight_get_brightness, }; @@ -161,35 +166,10 @@ static int da903x_backlight_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM -static int da903x_backlight_suspend(struct device *dev) -{ - struct backlight_device *bl = dev_get_drvdata(dev); - - return da903x_backlight_set(bl, 0); -} - -static int da903x_backlight_resume(struct device *dev) -{ - struct backlight_device *bl = dev_get_drvdata(dev); - - backlight_update_status(bl); - return 0; -} - -static const struct dev_pm_ops da903x_backlight_pm_ops = { - .suspend = da903x_backlight_suspend, - .resume = da903x_backlight_resume, -}; -#endif - static struct platform_driver da903x_backlight_driver = { .driver = { .name = "da903x-backlight", .owner = THIS_MODULE, -#ifdef CONFIG_PM - .pm = &da903x_backlight_pm_ops, -#endif }, .probe = da903x_backlight_probe, .remove = da903x_backlight_remove, diff --git a/drivers/video/backlight/ep93xx_bl.c b/drivers/video/backlight/ep93xx_bl.c index ef3e21e8f825..33455821dd31 100644 --- a/drivers/video/backlight/ep93xx_bl.c +++ b/drivers/video/backlight/ep93xx_bl.c @@ -60,7 +60,7 @@ static const struct backlight_ops ep93xxbl_ops = { .get_brightness = ep93xxbl_get_brightness, }; -static int __init ep93xxbl_probe(struct platform_device *dev) +static int ep93xxbl_probe(struct platform_device *dev) { struct ep93xxbl *ep93xxbl; struct backlight_device *bl; @@ -115,35 +115,33 @@ static int ep93xxbl_remove(struct platform_device *dev) return 0; } -#ifdef CONFIG_PM -static int ep93xxbl_suspend(struct platform_device *dev, pm_message_t state) +#ifdef CONFIG_PM_SLEEP +static int ep93xxbl_suspend(struct device *dev) { - struct backlight_device *bl = platform_get_drvdata(dev); + struct backlight_device *bl = dev_get_drvdata(dev); return ep93xxbl_set(bl, 0); } -static int ep93xxbl_resume(struct platform_device *dev) +static int ep93xxbl_resume(struct device *dev) { - struct backlight_device *bl = platform_get_drvdata(dev); + struct backlight_device *bl = dev_get_drvdata(dev); backlight_update_status(bl); return 0; } -#else -#define ep93xxbl_suspend NULL -#define ep93xxbl_resume NULL #endif +static SIMPLE_DEV_PM_OPS(ep93xxbl_pm_ops, ep93xxbl_suspend, ep93xxbl_resume); + static struct platform_driver ep93xxbl_driver = { .driver = { .name = "ep93xx-bl", .owner = THIS_MODULE, + .pm = &ep93xxbl_pm_ops, }, .probe = ep93xxbl_probe, .remove = ep93xxbl_remove, - .suspend = ep93xxbl_suspend, - .resume = ep93xxbl_resume, }; module_platform_driver(ep93xxbl_driver); diff --git a/drivers/video/backlight/generic_bl.c b/drivers/video/backlight/generic_bl.c index 0ae155be9c89..19e393b41438 100644 --- a/drivers/video/backlight/generic_bl.c +++ b/drivers/video/backlight/generic_bl.c @@ -9,8 +9,6 @@ * */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> @@ -108,7 +106,7 @@ static int genericbl_probe(struct platform_device *pdev) generic_backlight_device = bd; - pr_info("Generic Backlight Driver Initialized.\n"); + dev_info(&pdev->dev, "Generic Backlight Driver Initialized.\n"); return 0; } @@ -122,7 +120,7 @@ static int genericbl_remove(struct platform_device *pdev) backlight_device_unregister(bd); - pr_info("Generic Backlight Driver Unloaded\n"); + dev_info(&pdev->dev, "Generic Backlight Driver Unloaded\n"); return 0; } diff --git a/drivers/video/backlight/hp680_bl.c b/drivers/video/backlight/hp680_bl.c index 5cefd73526f8..00076ecfe9b8 100644 --- a/drivers/video/backlight/hp680_bl.c +++ b/drivers/video/backlight/hp680_bl.c @@ -64,29 +64,28 @@ static void hp680bl_send_intensity(struct backlight_device *bd) } -#ifdef CONFIG_PM -static int hp680bl_suspend(struct platform_device *pdev, pm_message_t state) +#ifdef CONFIG_PM_SLEEP +static int hp680bl_suspend(struct device *dev) { - struct backlight_device *bd = platform_get_drvdata(pdev); + struct backlight_device *bd = dev_get_drvdata(dev); hp680bl_suspended = 1; hp680bl_send_intensity(bd); return 0; } -static int hp680bl_resume(struct platform_device *pdev) +static int hp680bl_resume(struct device *dev) { - struct backlight_device *bd = platform_get_drvdata(pdev); + struct backlight_device *bd = dev_get_drvdata(dev); hp680bl_suspended = 0; hp680bl_send_intensity(bd); return 0; } -#else -#define hp680bl_suspend NULL -#define hp680bl_resume NULL #endif +static SIMPLE_DEV_PM_OPS(hp680bl_pm_ops, hp680bl_suspend, hp680bl_resume); + static int hp680bl_set_intensity(struct backlight_device *bd) { hp680bl_send_intensity(bd); @@ -140,10 +139,9 @@ static int hp680bl_remove(struct platform_device *pdev) static struct platform_driver hp680bl_driver = { .probe = hp680bl_probe, .remove = hp680bl_remove, - .suspend = hp680bl_suspend, - .resume = hp680bl_resume, .driver = { .name = "hp680-bl", + .pm = &hp680bl_pm_ops, }, }; diff --git a/drivers/video/backlight/ili922x.c b/drivers/video/backlight/ili922x.c new file mode 100644 index 000000000000..8b8465ed0014 --- /dev/null +++ b/drivers/video/backlight/ili922x.c @@ -0,0 +1,555 @@ +/* + * (C) Copyright 2008 + * Stefano Babic, DENX Software Engineering, sbabic@denx.de. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This driver implements a lcd device for the ILITEK 922x display + * controller. The interface to the display is SPI and the display's + * memory is cyclically updated over the RGB interface. + */ + +#include <linux/fb.h> +#include <linux/delay.h> +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/lcd.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/slab.h> +#include <linux/spi/spi.h> +#include <linux/string.h> + +/* Register offset, see manual section 8.2 */ +#define REG_START_OSCILLATION 0x00 +#define REG_DRIVER_CODE_READ 0x00 +#define REG_DRIVER_OUTPUT_CONTROL 0x01 +#define REG_LCD_AC_DRIVEING_CONTROL 0x02 +#define REG_ENTRY_MODE 0x03 +#define REG_COMPARE_1 0x04 +#define REG_COMPARE_2 0x05 +#define REG_DISPLAY_CONTROL_1 0x07 +#define REG_DISPLAY_CONTROL_2 0x08 +#define REG_DISPLAY_CONTROL_3 0x09 +#define REG_FRAME_CYCLE_CONTROL 0x0B +#define REG_EXT_INTF_CONTROL 0x0C +#define REG_POWER_CONTROL_1 0x10 +#define REG_POWER_CONTROL_2 0x11 +#define REG_POWER_CONTROL_3 0x12 +#define REG_POWER_CONTROL_4 0x13 +#define REG_RAM_ADDRESS_SET 0x21 +#define REG_WRITE_DATA_TO_GRAM 0x22 +#define REG_RAM_WRITE_MASK1 0x23 +#define REG_RAM_WRITE_MASK2 0x24 +#define REG_GAMMA_CONTROL_1 0x30 +#define REG_GAMMA_CONTROL_2 0x31 +#define REG_GAMMA_CONTROL_3 0x32 +#define REG_GAMMA_CONTROL_4 0x33 +#define REG_GAMMA_CONTROL_5 0x34 +#define REG_GAMMA_CONTROL_6 0x35 +#define REG_GAMMA_CONTROL_7 0x36 +#define REG_GAMMA_CONTROL_8 0x37 +#define REG_GAMMA_CONTROL_9 0x38 +#define REG_GAMMA_CONTROL_10 0x39 +#define REG_GATE_SCAN_CONTROL 0x40 +#define REG_VERT_SCROLL_CONTROL 0x41 +#define REG_FIRST_SCREEN_DRIVE_POS 0x42 +#define REG_SECOND_SCREEN_DRIVE_POS 0x43 +#define REG_RAM_ADDR_POS_H 0x44 +#define REG_RAM_ADDR_POS_V 0x45 +#define REG_OSCILLATOR_CONTROL 0x4F +#define REG_GPIO 0x60 +#define REG_OTP_VCM_PROGRAMMING 0x61 +#define REG_OTP_VCM_STATUS_ENABLE 0x62 +#define REG_OTP_PROGRAMMING_ID_KEY 0x65 + +/* + * maximum frequency for register access + * (not for the GRAM access) + */ +#define ILITEK_MAX_FREQ_REG 4000000 + +/* + * Device ID as found in the datasheet (supports 9221 and 9222) + */ +#define ILITEK_DEVICE_ID 0x9220 +#define ILITEK_DEVICE_ID_MASK 0xFFF0 + +/* Last two bits in the START BYTE */ +#define START_RS_INDEX 0 +#define START_RS_REG 1 +#define START_RW_WRITE 0 +#define START_RW_READ 1 + +/** + * START_BYTE(id, rs, rw) + * + * Set the start byte according to the required operation. + * The start byte is defined as: + * ---------------------------------- + * | 0 | 1 | 1 | 1 | 0 | ID | RS | RW | + * ---------------------------------- + * @id: display's id as set by the manufacturer + * @rs: operation type bit, one of: + * - START_RS_INDEX set the index register + * - START_RS_REG write/read registers/GRAM + * @rw: read/write operation + * - START_RW_WRITE write + * - START_RW_READ read + */ +#define START_BYTE(id, rs, rw) \ + (0x70 | (((id) & 0x01) << 2) | (((rs) & 0x01) << 1) | ((rw) & 0x01)) + +/** + * CHECK_FREQ_REG(spi_device s, spi_transfer x) - Check the frequency + * for the SPI transfer. According to the datasheet, the controller + * accept higher frequency for the GRAM transfer, but it requires + * lower frequency when the registers are read/written. + * The macro sets the frequency in the spi_transfer structure if + * the frequency exceeds the maximum value. + */ +#define CHECK_FREQ_REG(s, x) \ + do { \ + if (s->max_speed_hz > ILITEK_MAX_FREQ_REG) \ + ((struct spi_transfer *)x)->speed_hz = \ + ILITEK_MAX_FREQ_REG; \ + } while (0) + +#define CMD_BUFSIZE 16 + +#define POWER_IS_ON(pwr) ((pwr) <= FB_BLANK_NORMAL) + +#define set_tx_byte(b) (tx_invert ? ~(b) : b) + +/** + * ili922x_id - id as set by manufacturer + */ +static int ili922x_id = 1; +module_param(ili922x_id, int, 0); + +static int tx_invert; +module_param(tx_invert, int, 0); + +/** + * driver's private structure + */ +struct ili922x { + struct spi_device *spi; + struct lcd_device *ld; + int power; +}; + +/** + * ili922x_read_status - read status register from display + * @spi: spi device + * @rs: output value + */ +static int ili922x_read_status(struct spi_device *spi, u16 *rs) +{ + struct spi_message msg; + struct spi_transfer xfer; + unsigned char tbuf[CMD_BUFSIZE]; + unsigned char rbuf[CMD_BUFSIZE]; + int ret, i; + + memset(&xfer, 0, sizeof(struct spi_transfer)); + spi_message_init(&msg); + xfer.tx_buf = tbuf; + xfer.rx_buf = rbuf; + xfer.cs_change = 1; + CHECK_FREQ_REG(spi, &xfer); + + tbuf[0] = set_tx_byte(START_BYTE(ili922x_id, START_RS_INDEX, + START_RW_READ)); + /* + * we need 4-byte xfer here due to invalid dummy byte + * received after start byte + */ + for (i = 1; i < 4; i++) + tbuf[i] = set_tx_byte(0); /* dummy */ + + xfer.bits_per_word = 8; + xfer.len = 4; + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(spi, &msg); + if (ret < 0) { + dev_dbg(&spi->dev, "Error sending SPI message 0x%x", ret); + return ret; + } + + *rs = (rbuf[2] << 8) + rbuf[3]; + return 0; +} + +/** + * ili922x_read - read register from display + * @spi: spi device + * @reg: offset of the register to be read + * @rx: output value + */ +static int ili922x_read(struct spi_device *spi, u8 reg, u16 *rx) +{ + struct spi_message msg; + struct spi_transfer xfer_regindex, xfer_regvalue; + unsigned char tbuf[CMD_BUFSIZE]; + unsigned char rbuf[CMD_BUFSIZE]; + int ret, len = 0, send_bytes; + + memset(&xfer_regindex, 0, sizeof(struct spi_transfer)); + memset(&xfer_regvalue, 0, sizeof(struct spi_transfer)); + spi_message_init(&msg); + xfer_regindex.tx_buf = tbuf; + xfer_regindex.rx_buf = rbuf; + xfer_regindex.cs_change = 1; + CHECK_FREQ_REG(spi, &xfer_regindex); + + tbuf[0] = set_tx_byte(START_BYTE(ili922x_id, START_RS_INDEX, + START_RW_WRITE)); + tbuf[1] = set_tx_byte(0); + tbuf[2] = set_tx_byte(reg); + xfer_regindex.bits_per_word = 8; + len = xfer_regindex.len = 3; + spi_message_add_tail(&xfer_regindex, &msg); + + send_bytes = len; + + tbuf[len++] = set_tx_byte(START_BYTE(ili922x_id, START_RS_REG, + START_RW_READ)); + tbuf[len++] = set_tx_byte(0); + tbuf[len] = set_tx_byte(0); + + xfer_regvalue.cs_change = 1; + xfer_regvalue.len = 3; + xfer_regvalue.tx_buf = &tbuf[send_bytes]; + xfer_regvalue.rx_buf = &rbuf[send_bytes]; + CHECK_FREQ_REG(spi, &xfer_regvalue); + + spi_message_add_tail(&xfer_regvalue, &msg); + ret = spi_sync(spi, &msg); + if (ret < 0) { + dev_dbg(&spi->dev, "Error sending SPI message 0x%x", ret); + return ret; + } + + *rx = (rbuf[1 + send_bytes] << 8) + rbuf[2 + send_bytes]; + return 0; +} + +/** + * ili922x_write - write a controller register + * @spi: struct spi_device * + * @reg: offset of the register to be written + * @value: value to be written + */ +static int ili922x_write(struct spi_device *spi, u8 reg, u16 value) +{ + struct spi_message msg; + struct spi_transfer xfer_regindex, xfer_regvalue; + unsigned char tbuf[CMD_BUFSIZE]; + unsigned char rbuf[CMD_BUFSIZE]; + int ret, len = 0; + + memset(&xfer_regindex, 0, sizeof(struct spi_transfer)); + memset(&xfer_regvalue, 0, sizeof(struct spi_transfer)); + + spi_message_init(&msg); + xfer_regindex.tx_buf = tbuf; + xfer_regindex.rx_buf = rbuf; + xfer_regindex.cs_change = 1; + CHECK_FREQ_REG(spi, &xfer_regindex); + + tbuf[0] = set_tx_byte(START_BYTE(ili922x_id, START_RS_INDEX, + START_RW_WRITE)); + tbuf[1] = set_tx_byte(0); + tbuf[2] = set_tx_byte(reg); + xfer_regindex.bits_per_word = 8; + xfer_regindex.len = 3; + spi_message_add_tail(&xfer_regindex, &msg); + + ret = spi_sync(spi, &msg); + + spi_message_init(&msg); + len = 0; + tbuf[0] = set_tx_byte(START_BYTE(ili922x_id, START_RS_REG, + START_RW_WRITE)); + tbuf[1] = set_tx_byte((value & 0xFF00) >> 8); + tbuf[2] = set_tx_byte(value & 0x00FF); + + xfer_regvalue.cs_change = 1; + xfer_regvalue.len = 3; + xfer_regvalue.tx_buf = tbuf; + xfer_regvalue.rx_buf = rbuf; + CHECK_FREQ_REG(spi, &xfer_regvalue); + + spi_message_add_tail(&xfer_regvalue, &msg); + + ret = spi_sync(spi, &msg); + if (ret < 0) { + dev_err(&spi->dev, "Error sending SPI message 0x%x", ret); + return ret; + } + return 0; +} + +#ifdef DEBUG +/** + * ili922x_reg_dump - dump all registers + */ +static void ili922x_reg_dump(struct spi_device *spi) +{ + u8 reg; + u16 rx; + + dev_dbg(&spi->dev, "ILI922x configuration registers:\n"); + for (reg = REG_START_OSCILLATION; + reg <= REG_OTP_PROGRAMMING_ID_KEY; reg++) { + ili922x_read(spi, reg, &rx); + dev_dbg(&spi->dev, "reg @ 0x%02X: 0x%04X\n", reg, rx); + } +} +#else +static inline void ili922x_reg_dump(struct spi_device *spi) {} +#endif + +/** + * set_write_to_gram_reg - initialize the display to write the GRAM + * @spi: spi device + */ +static void set_write_to_gram_reg(struct spi_device *spi) +{ + struct spi_message msg; + struct spi_transfer xfer; + unsigned char tbuf[CMD_BUFSIZE]; + + memset(&xfer, 0, sizeof(struct spi_transfer)); + + spi_message_init(&msg); + xfer.tx_buf = tbuf; + xfer.rx_buf = NULL; + xfer.cs_change = 1; + + tbuf[0] = START_BYTE(ili922x_id, START_RS_INDEX, START_RW_WRITE); + tbuf[1] = 0; + tbuf[2] = REG_WRITE_DATA_TO_GRAM; + + xfer.bits_per_word = 8; + xfer.len = 3; + spi_message_add_tail(&xfer, &msg); + spi_sync(spi, &msg); +} + +/** + * ili922x_poweron - turn the display on + * @spi: spi device + * + * The sequence to turn on the display is taken from + * the datasheet and/or the example code provided by the + * manufacturer. + */ +static int ili922x_poweron(struct spi_device *spi) +{ + int ret; + + /* Power on */ + ret = ili922x_write(spi, REG_POWER_CONTROL_1, 0x0000); + usleep_range(10000, 10500); + ret += ili922x_write(spi, REG_POWER_CONTROL_2, 0x0000); + ret += ili922x_write(spi, REG_POWER_CONTROL_3, 0x0000); + msleep(40); + ret += ili922x_write(spi, REG_POWER_CONTROL_4, 0x0000); + msleep(40); + /* register 0x56 is not documented in the datasheet */ + ret += ili922x_write(spi, 0x56, 0x080F); + ret += ili922x_write(spi, REG_POWER_CONTROL_1, 0x4240); + usleep_range(10000, 10500); + ret += ili922x_write(spi, REG_POWER_CONTROL_2, 0x0000); + ret += ili922x_write(spi, REG_POWER_CONTROL_3, 0x0014); + msleep(40); + ret += ili922x_write(spi, REG_POWER_CONTROL_4, 0x1319); + msleep(40); + + return ret; +} + +/** + * ili922x_poweroff - turn the display off + * @spi: spi device + */ +static int ili922x_poweroff(struct spi_device *spi) +{ + int ret; + + /* Power off */ + ret = ili922x_write(spi, REG_POWER_CONTROL_1, 0x0000); + usleep_range(10000, 10500); + ret += ili922x_write(spi, REG_POWER_CONTROL_2, 0x0000); + ret += ili922x_write(spi, REG_POWER_CONTROL_3, 0x0000); + msleep(40); + ret += ili922x_write(spi, REG_POWER_CONTROL_4, 0x0000); + msleep(40); + + return ret; +} + +/** + * ili922x_display_init - initialize the display by setting + * the configuration registers + * @spi: spi device + */ +static void ili922x_display_init(struct spi_device *spi) +{ + ili922x_write(spi, REG_START_OSCILLATION, 1); + usleep_range(10000, 10500); + ili922x_write(spi, REG_DRIVER_OUTPUT_CONTROL, 0x691B); + ili922x_write(spi, REG_LCD_AC_DRIVEING_CONTROL, 0x0700); + ili922x_write(spi, REG_ENTRY_MODE, 0x1030); + ili922x_write(spi, REG_COMPARE_1, 0x0000); + ili922x_write(spi, REG_COMPARE_2, 0x0000); + ili922x_write(spi, REG_DISPLAY_CONTROL_1, 0x0037); + ili922x_write(spi, REG_DISPLAY_CONTROL_2, 0x0202); + ili922x_write(spi, REG_DISPLAY_CONTROL_3, 0x0000); + ili922x_write(spi, REG_FRAME_CYCLE_CONTROL, 0x0000); + + /* Set RGB interface */ + ili922x_write(spi, REG_EXT_INTF_CONTROL, 0x0110); + + ili922x_poweron(spi); + + ili922x_write(spi, REG_GAMMA_CONTROL_1, 0x0302); + ili922x_write(spi, REG_GAMMA_CONTROL_2, 0x0407); + ili922x_write(spi, REG_GAMMA_CONTROL_3, 0x0304); + ili922x_write(spi, REG_GAMMA_CONTROL_4, 0x0203); + ili922x_write(spi, REG_GAMMA_CONTROL_5, 0x0706); + ili922x_write(spi, REG_GAMMA_CONTROL_6, 0x0407); + ili922x_write(spi, REG_GAMMA_CONTROL_7, 0x0706); + ili922x_write(spi, REG_GAMMA_CONTROL_8, 0x0000); + ili922x_write(spi, REG_GAMMA_CONTROL_9, 0x0C06); + ili922x_write(spi, REG_GAMMA_CONTROL_10, 0x0F00); + ili922x_write(spi, REG_RAM_ADDRESS_SET, 0x0000); + ili922x_write(spi, REG_GATE_SCAN_CONTROL, 0x0000); + ili922x_write(spi, REG_VERT_SCROLL_CONTROL, 0x0000); + ili922x_write(spi, REG_FIRST_SCREEN_DRIVE_POS, 0xDB00); + ili922x_write(spi, REG_SECOND_SCREEN_DRIVE_POS, 0xDB00); + ili922x_write(spi, REG_RAM_ADDR_POS_H, 0xAF00); + ili922x_write(spi, REG_RAM_ADDR_POS_V, 0xDB00); + ili922x_reg_dump(spi); + set_write_to_gram_reg(spi); +} + +static int ili922x_lcd_power(struct ili922x *lcd, int power) +{ + int ret = 0; + + if (POWER_IS_ON(power) && !POWER_IS_ON(lcd->power)) + ret = ili922x_poweron(lcd->spi); + else if (!POWER_IS_ON(power) && POWER_IS_ON(lcd->power)) + ret = ili922x_poweroff(lcd->spi); + + if (!ret) + lcd->power = power; + + return ret; +} + +static int ili922x_set_power(struct lcd_device *ld, int power) +{ + struct ili922x *ili = lcd_get_data(ld); + + return ili922x_lcd_power(ili, power); +} + +static int ili922x_get_power(struct lcd_device *ld) +{ + struct ili922x *ili = lcd_get_data(ld); + + return ili->power; +} + +static struct lcd_ops ili922x_ops = { + .get_power = ili922x_get_power, + .set_power = ili922x_set_power, +}; + +static int ili922x_probe(struct spi_device *spi) +{ + struct ili922x *ili; + struct lcd_device *lcd; + int ret; + u16 reg = 0; + + ili = devm_kzalloc(&spi->dev, sizeof(*ili), GFP_KERNEL); + if (!ili) { + dev_err(&spi->dev, "cannot alloc priv data\n"); + return -ENOMEM; + } + + ili->spi = spi; + dev_set_drvdata(&spi->dev, ili); + + /* check if the device is connected */ + ret = ili922x_read(spi, REG_DRIVER_CODE_READ, ®); + if (ret || ((reg & ILITEK_DEVICE_ID_MASK) != ILITEK_DEVICE_ID)) { + dev_err(&spi->dev, + "no LCD found: Chip ID 0x%x, ret %d\n", + reg, ret); + return -ENODEV; + } else { + dev_info(&spi->dev, "ILI%x found, SPI freq %d, mode %d\n", + reg, spi->max_speed_hz, spi->mode); + } + + ret = ili922x_read_status(spi, ®); + if (ret) { + dev_err(&spi->dev, "reading RS failed...\n"); + return ret; + } else + dev_dbg(&spi->dev, "status: 0x%x\n", reg); + + ili922x_display_init(spi); + + ili->power = FB_BLANK_POWERDOWN; + + lcd = lcd_device_register("ili922xlcd", &spi->dev, ili, + &ili922x_ops); + if (IS_ERR(lcd)) { + dev_err(&spi->dev, "cannot register LCD\n"); + return PTR_ERR(lcd); + } + + ili->ld = lcd; + spi_set_drvdata(spi, ili); + + ili922x_lcd_power(ili, FB_BLANK_UNBLANK); + + return 0; +} + +static int ili922x_remove(struct spi_device *spi) +{ + struct ili922x *ili = spi_get_drvdata(spi); + + ili922x_poweroff(spi); + lcd_device_unregister(ili->ld); + return 0; +} + +static struct spi_driver ili922x_driver = { + .driver = { + .name = "ili922x", + .owner = THIS_MODULE, + }, + .probe = ili922x_probe, + .remove = ili922x_remove, +}; + +module_spi_driver(ili922x_driver); + +MODULE_AUTHOR("Stefano Babic <sbabic@denx.de>"); +MODULE_DESCRIPTION("ILI9221/9222 LCD driver"); +MODULE_LICENSE("GPL"); +MODULE_PARM_DESC(ili922x_id, "set controller identifier (default=1)"); +MODULE_PARM_DESC(tx_invert, "invert bytes before sending"); diff --git a/drivers/video/backlight/jornada720_bl.c b/drivers/video/backlight/jornada720_bl.c index fef6ce4fad71..3ccb89340f22 100644 --- a/drivers/video/backlight/jornada720_bl.c +++ b/drivers/video/backlight/jornada720_bl.c @@ -9,8 +9,6 @@ * */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include <linux/backlight.h> #include <linux/device.h> #include <linux/fb.h> @@ -40,11 +38,13 @@ static int jornada_bl_get_brightness(struct backlight_device *bd) ret = jornada_ssp_byte(GETBRIGHTNESS); if (jornada_ssp_byte(GETBRIGHTNESS) != TXDUMMY) { - pr_err("get brightness timeout\n"); + dev_err(&bd->dev, "get brightness timeout\n"); jornada_ssp_end(); return -ETIMEDOUT; - } else /* exchange txdummy for value */ + } else { + /* exchange txdummy for value */ ret = jornada_ssp_byte(TXDUMMY); + } jornada_ssp_end(); @@ -61,7 +61,7 @@ static int jornada_bl_update_status(struct backlight_device *bd) if ((bd->props.power != FB_BLANK_UNBLANK) || (bd->props.fb_blank != FB_BLANK_UNBLANK)) { ret = jornada_ssp_byte(BRIGHTNESSOFF); if (ret != TXDUMMY) { - pr_info("brightness off timeout\n"); + dev_info(&bd->dev, "brightness off timeout\n"); /* turn off backlight */ PPSR &= ~PPC_LDD1; PPDR |= PPC_LDD1; @@ -72,7 +72,7 @@ static int jornada_bl_update_status(struct backlight_device *bd) /* send command to our mcu */ if (jornada_ssp_byte(SETBRIGHTNESS) != TXDUMMY) { - pr_info("failed to set brightness\n"); + dev_info(&bd->dev, "failed to set brightness\n"); ret = -ETIMEDOUT; goto out; } @@ -86,7 +86,7 @@ static int jornada_bl_update_status(struct backlight_device *bd) */ if (jornada_ssp_byte(BL_MAX_BRIGHT - bd->props.brightness) != TXDUMMY) { - pr_err("set brightness failed\n"); + dev_err(&bd->dev, "set brightness failed\n"); ret = -ETIMEDOUT; } @@ -120,7 +120,7 @@ static int jornada_bl_probe(struct platform_device *pdev) if (IS_ERR(bd)) { ret = PTR_ERR(bd); - pr_err("failed to register device, err=%x\n", ret); + dev_err(&pdev->dev, "failed to register device, err=%x\n", ret); return ret; } @@ -134,7 +134,7 @@ static int jornada_bl_probe(struct platform_device *pdev) jornada_bl_update_status(bd); platform_set_drvdata(pdev, bd); - pr_info("HP Jornada 700 series backlight driver\n"); + dev_info(&pdev->dev, "HP Jornada 700 series backlight driver\n"); return 0; } diff --git a/drivers/video/backlight/jornada720_lcd.c b/drivers/video/backlight/jornada720_lcd.c index 635b30523fd5..b061413f1a65 100644 --- a/drivers/video/backlight/jornada720_lcd.c +++ b/drivers/video/backlight/jornada720_lcd.c @@ -9,8 +9,6 @@ * */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include <linux/device.h> #include <linux/fb.h> #include <linux/kernel.h> @@ -27,7 +25,7 @@ #define LCD_MAX_CONTRAST 0xff #define LCD_DEF_CONTRAST 0x80 -static int jornada_lcd_get_power(struct lcd_device *dev) +static int jornada_lcd_get_power(struct lcd_device *ld) { /* LDD2 in PPC = LCD POWER */ if (PPSR & PPC_LDD2) @@ -36,17 +34,17 @@ static int jornada_lcd_get_power(struct lcd_device *dev) return FB_BLANK_POWERDOWN; /* PW OFF */ } -static int jornada_lcd_get_contrast(struct lcd_device *dev) +static int jornada_lcd_get_contrast(struct lcd_device *ld) { int ret; - if (jornada_lcd_get_power(dev) != FB_BLANK_UNBLANK) + if (jornada_lcd_get_power(ld) != FB_BLANK_UNBLANK) return 0; jornada_ssp_start(); if (jornada_ssp_byte(GETCONTRAST) != TXDUMMY) { - pr_err("get contrast failed\n"); + dev_err(&ld->dev, "get contrast failed\n"); jornada_ssp_end(); return -ETIMEDOUT; } else { @@ -56,7 +54,7 @@ static int jornada_lcd_get_contrast(struct lcd_device *dev) } } -static int jornada_lcd_set_contrast(struct lcd_device *dev, int value) +static int jornada_lcd_set_contrast(struct lcd_device *ld, int value) { int ret; @@ -67,7 +65,7 @@ static int jornada_lcd_set_contrast(struct lcd_device *dev, int value) /* push the new value */ if (jornada_ssp_byte(value) != TXDUMMY) { - pr_err("set contrast failed\n"); + dev_err(&ld->dev, "set contrast failed\n"); jornada_ssp_end(); return -ETIMEDOUT; } @@ -78,13 +76,14 @@ static int jornada_lcd_set_contrast(struct lcd_device *dev, int value) return 0; } -static int jornada_lcd_set_power(struct lcd_device *dev, int power) +static int jornada_lcd_set_power(struct lcd_device *ld, int power) { if (power != FB_BLANK_UNBLANK) { PPSR &= ~PPC_LDD2; PPDR |= PPC_LDD2; - } else + } else { PPSR |= PPC_LDD2; + } return 0; } @@ -105,7 +104,7 @@ static int jornada_lcd_probe(struct platform_device *pdev) if (IS_ERR(lcd_device)) { ret = PTR_ERR(lcd_device); - pr_err("failed to register device\n"); + dev_err(&pdev->dev, "failed to register device\n"); return ret; } diff --git a/drivers/video/backlight/kb3886_bl.c b/drivers/video/backlight/kb3886_bl.c index 6c5ed6b242cc..bca6ccc74dfb 100644 --- a/drivers/video/backlight/kb3886_bl.c +++ b/drivers/video/backlight/kb3886_bl.c @@ -106,29 +106,28 @@ static int kb3886bl_send_intensity(struct backlight_device *bd) return 0; } -#ifdef CONFIG_PM -static int kb3886bl_suspend(struct platform_device *pdev, pm_message_t state) +#ifdef CONFIG_PM_SLEEP +static int kb3886bl_suspend(struct device *dev) { - struct backlight_device *bd = platform_get_drvdata(pdev); + struct backlight_device *bd = dev_get_drvdata(dev); kb3886bl_flags |= KB3886BL_SUSPENDED; backlight_update_status(bd); return 0; } -static int kb3886bl_resume(struct platform_device *pdev) +static int kb3886bl_resume(struct device *dev) { - struct backlight_device *bd = platform_get_drvdata(pdev); + struct backlight_device *bd = dev_get_drvdata(dev); kb3886bl_flags &= ~KB3886BL_SUSPENDED; backlight_update_status(bd); return 0; } -#else -#define kb3886bl_suspend NULL -#define kb3886bl_resume NULL #endif +static SIMPLE_DEV_PM_OPS(kb3886bl_pm_ops, kb3886bl_suspend, kb3886bl_resume); + static int kb3886bl_get_intensity(struct backlight_device *bd) { return kb3886bl_intensity; @@ -179,10 +178,9 @@ static int kb3886bl_remove(struct platform_device *pdev) static struct platform_driver kb3886bl_driver = { .probe = kb3886bl_probe, .remove = kb3886bl_remove, - .suspend = kb3886bl_suspend, - .resume = kb3886bl_resume, .driver = { .name = "kb3886-bl", + .pm = &kb3886bl_pm_ops, }, }; diff --git a/drivers/video/backlight/l4f00242t03.c b/drivers/video/backlight/l4f00242t03.c index fb6155771326..a35a38c709cf 100644 --- a/drivers/video/backlight/l4f00242t03.c +++ b/drivers/video/backlight/l4f00242t03.c @@ -51,14 +51,33 @@ static void l4f00242t03_lcd_init(struct spi_device *spi) struct l4f00242t03_pdata *pdata = spi->dev.platform_data; struct l4f00242t03_priv *priv = spi_get_drvdata(spi); const u16 cmd[] = { 0x36, param(0), 0x3A, param(0x60) }; + int ret; dev_dbg(&spi->dev, "initializing LCD\n"); - regulator_set_voltage(priv->io_reg, 1800000, 1800000); - regulator_enable(priv->io_reg); + ret = regulator_set_voltage(priv->io_reg, 1800000, 1800000); + if (ret) { + dev_err(&spi->dev, "failed to set the IO regulator voltage.\n"); + return; + } + ret = regulator_enable(priv->io_reg); + if (ret) { + dev_err(&spi->dev, "failed to enable the IO regulator.\n"); + return; + } - regulator_set_voltage(priv->core_reg, 2800000, 2800000); - regulator_enable(priv->core_reg); + ret = regulator_set_voltage(priv->core_reg, 2800000, 2800000); + if (ret) { + dev_err(&spi->dev, "failed to set the core regulator voltage.\n"); + regulator_disable(priv->io_reg); + return; + } + ret = regulator_enable(priv->core_reg); + if (ret) { + dev_err(&spi->dev, "failed to enable the core regulator.\n"); + regulator_disable(priv->io_reg); + return; + } l4f00242t03_reset(pdata->reset_gpio); diff --git a/drivers/video/backlight/ld9040.c b/drivers/video/backlight/ld9040.c index 1b642f5f381a..1e0a3093ce50 100644 --- a/drivers/video/backlight/ld9040.c +++ b/drivers/video/backlight/ld9040.c @@ -775,12 +775,12 @@ static int ld9040_remove(struct spi_device *spi) return 0; } -#if defined(CONFIG_PM) -static int ld9040_suspend(struct spi_device *spi, pm_message_t mesg) +#ifdef CONFIG_PM_SLEEP +static int ld9040_suspend(struct device *dev) { - struct ld9040 *lcd = spi_get_drvdata(spi); + struct ld9040 *lcd = dev_get_drvdata(dev); - dev_dbg(&spi->dev, "lcd->power = %d\n", lcd->power); + dev_dbg(dev, "lcd->power = %d\n", lcd->power); /* * when lcd panel is suspend, lcd panel becomes off @@ -789,19 +789,18 @@ static int ld9040_suspend(struct spi_device *spi, pm_message_t mesg) return ld9040_power(lcd, FB_BLANK_POWERDOWN); } -static int ld9040_resume(struct spi_device *spi) +static int ld9040_resume(struct device *dev) { - struct ld9040 *lcd = spi_get_drvdata(spi); + struct ld9040 *lcd = dev_get_drvdata(dev); lcd->power = FB_BLANK_POWERDOWN; return ld9040_power(lcd, FB_BLANK_UNBLANK); } -#else -#define ld9040_suspend NULL -#define ld9040_resume NULL #endif +static SIMPLE_DEV_PM_OPS(ld9040_pm_ops, ld9040_suspend, ld9040_resume); + /* Power down all displays on reboot, poweroff or halt. */ static void ld9040_shutdown(struct spi_device *spi) { @@ -814,12 +813,11 @@ static struct spi_driver ld9040_driver = { .driver = { .name = "ld9040", .owner = THIS_MODULE, + .pm = &ld9040_pm_ops, }, .probe = ld9040_probe, .remove = ld9040_remove, .shutdown = ld9040_shutdown, - .suspend = ld9040_suspend, - .resume = ld9040_resume, }; module_spi_driver(ld9040_driver); diff --git a/drivers/video/backlight/lm3533_bl.c b/drivers/video/backlight/lm3533_bl.c index 5d18d4d7f470..1d1dbfb789e3 100644 --- a/drivers/video/backlight/lm3533_bl.c +++ b/drivers/video/backlight/lm3533_bl.c @@ -368,29 +368,28 @@ static int lm3533_bl_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM -static int lm3533_bl_suspend(struct platform_device *pdev, pm_message_t state) +#ifdef CONFIG_PM_SLEEP +static int lm3533_bl_suspend(struct device *dev) { - struct lm3533_bl *bl = platform_get_drvdata(pdev); + struct lm3533_bl *bl = dev_get_drvdata(dev); - dev_dbg(&pdev->dev, "%s\n", __func__); + dev_dbg(dev, "%s\n", __func__); return lm3533_ctrlbank_disable(&bl->cb); } -static int lm3533_bl_resume(struct platform_device *pdev) +static int lm3533_bl_resume(struct device *dev) { - struct lm3533_bl *bl = platform_get_drvdata(pdev); + struct lm3533_bl *bl = dev_get_drvdata(dev); - dev_dbg(&pdev->dev, "%s\n", __func__); + dev_dbg(dev, "%s\n", __func__); return lm3533_ctrlbank_enable(&bl->cb); } -#else -#define lm3533_bl_suspend NULL -#define lm3533_bl_resume NULL #endif +static SIMPLE_DEV_PM_OPS(lm3533_bl_pm_ops, lm3533_bl_suspend, lm3533_bl_resume); + static void lm3533_bl_shutdown(struct platform_device *pdev) { struct lm3533_bl *bl = platform_get_drvdata(pdev); @@ -404,12 +403,11 @@ static struct platform_driver lm3533_bl_driver = { .driver = { .name = "lm3533-backlight", .owner = THIS_MODULE, + .pm = &lm3533_bl_pm_ops, }, .probe = lm3533_bl_probe, .remove = lm3533_bl_remove, .shutdown = lm3533_bl_shutdown, - .suspend = lm3533_bl_suspend, - .resume = lm3533_bl_resume, }; module_platform_driver(lm3533_bl_driver); diff --git a/drivers/video/backlight/lms501kf03.c b/drivers/video/backlight/lms501kf03.c index b43882abefaf..cf01b9ac8131 100644 --- a/drivers/video/backlight/lms501kf03.c +++ b/drivers/video/backlight/lms501kf03.c @@ -387,13 +387,12 @@ static int lms501kf03_remove(struct spi_device *spi) return 0; } -#if defined(CONFIG_PM) - -static int lms501kf03_suspend(struct spi_device *spi, pm_message_t mesg) +#ifdef CONFIG_PM_SLEEP +static int lms501kf03_suspend(struct device *dev) { - struct lms501kf03 *lcd = spi_get_drvdata(spi); + struct lms501kf03 *lcd = dev_get_drvdata(dev); - dev_dbg(&spi->dev, "lcd->power = %d\n", lcd->power); + dev_dbg(dev, "lcd->power = %d\n", lcd->power); /* * when lcd panel is suspend, lcd panel becomes off @@ -402,19 +401,19 @@ static int lms501kf03_suspend(struct spi_device *spi, pm_message_t mesg) return lms501kf03_power(lcd, FB_BLANK_POWERDOWN); } -static int lms501kf03_resume(struct spi_device *spi) +static int lms501kf03_resume(struct device *dev) { - struct lms501kf03 *lcd = spi_get_drvdata(spi); + struct lms501kf03 *lcd = dev_get_drvdata(dev); lcd->power = FB_BLANK_POWERDOWN; return lms501kf03_power(lcd, FB_BLANK_UNBLANK); } -#else -#define lms501kf03_suspend NULL -#define lms501kf03_resume NULL #endif +static SIMPLE_DEV_PM_OPS(lms501kf03_pm_ops, lms501kf03_suspend, + lms501kf03_resume); + static void lms501kf03_shutdown(struct spi_device *spi) { struct lms501kf03 *lcd = spi_get_drvdata(spi); @@ -426,12 +425,11 @@ static struct spi_driver lms501kf03_driver = { .driver = { .name = "lms501kf03", .owner = THIS_MODULE, + .pm = &lms501kf03_pm_ops, }, .probe = lms501kf03_probe, .remove = lms501kf03_remove, .shutdown = lms501kf03_shutdown, - .suspend = lms501kf03_suspend, - .resume = lms501kf03_resume, }; module_spi_driver(lms501kf03_driver); diff --git a/drivers/video/backlight/locomolcd.c b/drivers/video/backlight/locomolcd.c index 146fea8aa431..6c3ec4259a60 100644 --- a/drivers/video/backlight/locomolcd.c +++ b/drivers/video/backlight/locomolcd.c @@ -157,25 +157,24 @@ static const struct backlight_ops locomobl_data = { .update_status = locomolcd_set_intensity, }; -#ifdef CONFIG_PM -static int locomolcd_suspend(struct locomo_dev *dev, pm_message_t state) +#ifdef CONFIG_PM_SLEEP +static int locomolcd_suspend(struct device *dev) { locomolcd_flags |= LOCOMOLCD_SUSPENDED; locomolcd_set_intensity(locomolcd_bl_device); return 0; } -static int locomolcd_resume(struct locomo_dev *dev) +static int locomolcd_resume(struct device *dev) { locomolcd_flags &= ~LOCOMOLCD_SUSPENDED; locomolcd_set_intensity(locomolcd_bl_device); return 0; } -#else -#define locomolcd_suspend NULL -#define locomolcd_resume NULL #endif +static SIMPLE_DEV_PM_OPS(locomolcd_pm_ops, locomolcd_suspend, locomolcd_resume); + static int locomolcd_probe(struct locomo_dev *ldev) { struct backlight_properties props; @@ -230,13 +229,12 @@ static int locomolcd_remove(struct locomo_dev *dev) static struct locomo_driver poodle_lcd_driver = { .drv = { - .name = "locomo-backlight", + .name = "locomo-backlight", + .pm = &locomolcd_pm_ops, }, .devid = LOCOMO_DEVID_BACKLIGHT, .probe = locomolcd_probe, .remove = locomolcd_remove, - .suspend = locomolcd_suspend, - .resume = locomolcd_resume, }; static int __init locomolcd_init(void) diff --git a/drivers/video/backlight/lp855x_bl.c b/drivers/video/backlight/lp855x_bl.c index 7ae9ae6f4655..c98bdbfdc697 100644 --- a/drivers/video/backlight/lp855x_bl.c +++ b/drivers/video/backlight/lp855x_bl.c @@ -35,7 +35,6 @@ #define LP8557_EPROM_START 0x10 #define LP8557_EPROM_END 0x1E -#define BUF_SIZE 20 #define DEFAULT_BL_NAME "lcd-backlight" #define MAX_BRIGHTNESS 255 @@ -304,7 +303,7 @@ static ssize_t lp855x_get_chip_id(struct device *dev, struct device_attribute *attr, char *buf) { struct lp855x *lp = dev_get_drvdata(dev); - return scnprintf(buf, BUF_SIZE, "%s\n", lp->chipname); + return scnprintf(buf, PAGE_SIZE, "%s\n", lp->chipname); } static ssize_t lp855x_get_bl_ctl_mode(struct device *dev, @@ -319,7 +318,7 @@ static ssize_t lp855x_get_bl_ctl_mode(struct device *dev, else if (mode == REGISTER_BASED) strmode = "register based"; - return scnprintf(buf, BUF_SIZE, "%s\n", strmode); + return scnprintf(buf, PAGE_SIZE, "%s\n", strmode); } static DEVICE_ATTR(chip_id, S_IRUGO, lp855x_get_chip_id, NULL); @@ -339,7 +338,6 @@ static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id) { struct lp855x *lp; struct lp855x_platform_data *pdata = cl->dev.platform_data; - enum lp855x_brightness_ctrl_mode mode; int ret; if (!pdata) { @@ -354,7 +352,6 @@ static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id) if (!lp) return -ENOMEM; - mode = pdata->mode; lp->client = cl; lp->dev = &cl->dev; lp->pdata = pdata; diff --git a/drivers/video/backlight/ltv350qv.c b/drivers/video/backlight/ltv350qv.c index c0b4b8f2de98..ed1b39268131 100644 --- a/drivers/video/backlight/ltv350qv.c +++ b/drivers/video/backlight/ltv350qv.c @@ -271,25 +271,24 @@ static int ltv350qv_remove(struct spi_device *spi) return 0; } -#ifdef CONFIG_PM -static int ltv350qv_suspend(struct spi_device *spi, pm_message_t state) +#ifdef CONFIG_PM_SLEEP +static int ltv350qv_suspend(struct device *dev) { - struct ltv350qv *lcd = spi_get_drvdata(spi); + struct ltv350qv *lcd = dev_get_drvdata(dev); return ltv350qv_power(lcd, FB_BLANK_POWERDOWN); } -static int ltv350qv_resume(struct spi_device *spi) +static int ltv350qv_resume(struct device *dev) { - struct ltv350qv *lcd = spi_get_drvdata(spi); + struct ltv350qv *lcd = dev_get_drvdata(dev); return ltv350qv_power(lcd, FB_BLANK_UNBLANK); } -#else -#define ltv350qv_suspend NULL -#define ltv350qv_resume NULL #endif +static SIMPLE_DEV_PM_OPS(ltv350qv_pm_ops, ltv350qv_suspend, ltv350qv_resume); + /* Power down all displays on reboot, poweroff or halt */ static void ltv350qv_shutdown(struct spi_device *spi) { @@ -302,13 +301,12 @@ static struct spi_driver ltv350qv_driver = { .driver = { .name = "ltv350qv", .owner = THIS_MODULE, + .pm = <v350qv_pm_ops, }, .probe = ltv350qv_probe, .remove = ltv350qv_remove, .shutdown = ltv350qv_shutdown, - .suspend = ltv350qv_suspend, - .resume = ltv350qv_resume, }; module_spi_driver(ltv350qv_driver); diff --git a/drivers/video/backlight/omap1_bl.c b/drivers/video/backlight/omap1_bl.c index 627110163067..0aed176cd6a0 100644 --- a/drivers/video/backlight/omap1_bl.c +++ b/drivers/video/backlight/omap1_bl.c @@ -18,8 +18,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> @@ -170,7 +168,7 @@ static int omapbl_probe(struct platform_device *pdev) dev->props.brightness = pdata->default_intensity; omapbl_update_status(dev); - pr_info("OMAP LCD backlight initialised\n"); + dev_info(&pdev->dev, "OMAP LCD backlight initialised\n"); return 0; } diff --git a/drivers/video/backlight/platform_lcd.c b/drivers/video/backlight/platform_lcd.c index 17a6b83f97af..54d94de652b0 100644 --- a/drivers/video/backlight/platform_lcd.c +++ b/drivers/video/backlight/platform_lcd.c @@ -121,7 +121,7 @@ static int platform_lcd_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int platform_lcd_suspend(struct device *dev) { struct platform_lcd *plcd = dev_get_drvdata(dev); @@ -141,10 +141,10 @@ static int platform_lcd_resume(struct device *dev) return 0; } +#endif static SIMPLE_DEV_PM_OPS(platform_lcd_pm_ops, platform_lcd_suspend, platform_lcd_resume); -#endif #ifdef CONFIG_OF static const struct of_device_id platform_lcd_of_match[] = { @@ -158,9 +158,7 @@ static struct platform_driver platform_lcd_driver = { .driver = { .name = "platform-lcd", .owner = THIS_MODULE, -#ifdef CONFIG_PM .pm = &platform_lcd_pm_ops, -#endif .of_match_table = of_match_ptr(platform_lcd_of_match), }, .probe = platform_lcd_probe, diff --git a/drivers/video/backlight/s6e63m0.c b/drivers/video/backlight/s6e63m0.c index 9c2677f0ef7d..b37bb1854bf4 100644 --- a/drivers/video/backlight/s6e63m0.c +++ b/drivers/video/backlight/s6e63m0.c @@ -817,12 +817,12 @@ static int s6e63m0_remove(struct spi_device *spi) return 0; } -#if defined(CONFIG_PM) -static int s6e63m0_suspend(struct spi_device *spi, pm_message_t mesg) +#ifdef CONFIG_PM_SLEEP +static int s6e63m0_suspend(struct device *dev) { - struct s6e63m0 *lcd = spi_get_drvdata(spi); + struct s6e63m0 *lcd = dev_get_drvdata(dev); - dev_dbg(&spi->dev, "lcd->power = %d\n", lcd->power); + dev_dbg(dev, "lcd->power = %d\n", lcd->power); /* * when lcd panel is suspend, lcd panel becomes off @@ -831,19 +831,18 @@ static int s6e63m0_suspend(struct spi_device *spi, pm_message_t mesg) return s6e63m0_power(lcd, FB_BLANK_POWERDOWN); } -static int s6e63m0_resume(struct spi_device *spi) +static int s6e63m0_resume(struct device *dev) { - struct s6e63m0 *lcd = spi_get_drvdata(spi); + struct s6e63m0 *lcd = dev_get_drvdata(dev); lcd->power = FB_BLANK_POWERDOWN; return s6e63m0_power(lcd, FB_BLANK_UNBLANK); } -#else -#define s6e63m0_suspend NULL -#define s6e63m0_resume NULL #endif +static SIMPLE_DEV_PM_OPS(s6e63m0_pm_ops, s6e63m0_suspend, s6e63m0_resume); + /* Power down all displays on reboot, poweroff or halt. */ static void s6e63m0_shutdown(struct spi_device *spi) { @@ -856,12 +855,11 @@ static struct spi_driver s6e63m0_driver = { .driver = { .name = "s6e63m0", .owner = THIS_MODULE, + .pm = &s6e63m0_pm_ops, }, .probe = s6e63m0_probe, .remove = s6e63m0_remove, .shutdown = s6e63m0_shutdown, - .suspend = s6e63m0_suspend, - .resume = s6e63m0_resume, }; module_spi_driver(s6e63m0_driver); diff --git a/drivers/video/backlight/tdo24m.c b/drivers/video/backlight/tdo24m.c index 00162085eec0..18cdf466d50a 100644 --- a/drivers/video/backlight/tdo24m.c +++ b/drivers/video/backlight/tdo24m.c @@ -412,25 +412,24 @@ static int tdo24m_remove(struct spi_device *spi) return 0; } -#ifdef CONFIG_PM -static int tdo24m_suspend(struct spi_device *spi, pm_message_t state) +#ifdef CONFIG_PM_SLEEP +static int tdo24m_suspend(struct device *dev) { - struct tdo24m *lcd = spi_get_drvdata(spi); + struct tdo24m *lcd = dev_get_drvdata(dev); return tdo24m_power(lcd, FB_BLANK_POWERDOWN); } -static int tdo24m_resume(struct spi_device *spi) +static int tdo24m_resume(struct device *dev) { - struct tdo24m *lcd = spi_get_drvdata(spi); + struct tdo24m *lcd = dev_get_drvdata(dev); return tdo24m_power(lcd, FB_BLANK_UNBLANK); } -#else -#define tdo24m_suspend NULL -#define tdo24m_resume NULL #endif +static SIMPLE_DEV_PM_OPS(tdo24m_pm_ops, tdo24m_suspend, tdo24m_resume); + /* Power down all displays on reboot, poweroff or halt */ static void tdo24m_shutdown(struct spi_device *spi) { @@ -443,12 +442,11 @@ static struct spi_driver tdo24m_driver = { .driver = { .name = "tdo24m", .owner = THIS_MODULE, + .pm = &tdo24m_pm_ops, }, .probe = tdo24m_probe, .remove = tdo24m_remove, .shutdown = tdo24m_shutdown, - .suspend = tdo24m_suspend, - .resume = tdo24m_resume, }; module_spi_driver(tdo24m_driver); diff --git a/drivers/video/console/fbcon_cw.c b/drivers/video/console/fbcon_cw.c index 6a737827beb1..a93670ef7f89 100644 --- a/drivers/video/console/fbcon_cw.c +++ b/drivers/video/console/fbcon_cw.c @@ -27,7 +27,7 @@ static void cw_update_attr(u8 *dst, u8 *src, int attribute, { int i, j, offset = (vc->vc_font.height < 10) ? 1 : 2; int width = (vc->vc_font.height + 7) >> 3; - u8 c, t = 0, msk = ~(0xff >> offset); + u8 c, msk = ~(0xff >> offset); for (i = 0; i < vc->vc_font.width; i++) { for (j = 0; j < width; j++) { @@ -40,7 +40,6 @@ static void cw_update_attr(u8 *dst, u8 *src, int attribute, c = ~c; src++; *dst++ = c; - t = c; } } } diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c index 57886787ead0..e78d9f2233b8 100644 --- a/drivers/video/cyber2000fb.c +++ b/drivers/video/cyber2000fb.c @@ -518,6 +518,9 @@ static void cyber2000fb_set_timing(struct cfb_info *cfb, struct par_info *hw) cyber2000_grphw(0xb9, 0x00, cfb); spin_unlock(&cfb->reg_b0_lock); + /* wait (for the PLL?) to avoid palette corruption at higher clocks */ + msleep(1000); + cfb->ramdac_ctrl = hw->ramdac; cyber2000fb_write_ramdac_ctrl(cfb); diff --git a/drivers/video/exynos/exynos_mipi_dsi.c b/drivers/video/exynos/exynos_mipi_dsi.c index fac7df6d1aba..87cd13b5dee6 100644 --- a/drivers/video/exynos/exynos_mipi_dsi.c +++ b/drivers/video/exynos/exynos_mipi_dsi.c @@ -32,6 +32,7 @@ #include <linux/notifier.h> #include <linux/regulator/consumer.h> #include <linux/pm_runtime.h> +#include <linux/err.h> #include <video/exynos_mipi_dsim.h> @@ -384,10 +385,9 @@ static int exynos_mipi_dsi_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - dsim->reg_base = devm_request_and_ioremap(&pdev->dev, res); - if (!dsim->reg_base) { - dev_err(&pdev->dev, "failed to remap io region\n"); - ret = -ENOMEM; + dsim->reg_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(dsim->reg_base)) { + ret = PTR_ERR(dsim->reg_base); goto error; } diff --git a/drivers/video/hyperv_fb.c b/drivers/video/hyperv_fb.c new file mode 100644 index 000000000000..ceb33b0bbb98 --- /dev/null +++ b/drivers/video/hyperv_fb.c @@ -0,0 +1,829 @@ +/* + * Copyright (c) 2012, Microsoft Corporation. + * + * Author: + * Haiyang Zhang <haiyangz@microsoft.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for more + * details. + */ + +/* + * Hyper-V Synthetic Video Frame Buffer Driver + * + * This is the driver for the Hyper-V Synthetic Video, which supports + * screen resolution up to Full HD 1920x1080 with 32 bit color on Windows + * Server 2012, and 1600x1200 with 16 bit color on Windows Server 2008 R2 + * or earlier. + * + * It also solves the double mouse cursor issue of the emulated video mode. + * + * The default screen resolution is 1152x864, which may be changed by a + * kernel parameter: + * video=hyperv_fb:<width>x<height> + * For example: video=hyperv_fb:1280x1024 + * + * Portrait orientation is also supported: + * For example: video=hyperv_fb:864x1152 + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/completion.h> +#include <linux/fb.h> +#include <linux/pci.h> + +#include <linux/hyperv.h> + + +/* Hyper-V Synthetic Video Protocol definitions and structures */ +#define MAX_VMBUS_PKT_SIZE 0x4000 + +#define SYNTHVID_VERSION(major, minor) ((minor) << 16 | (major)) +#define SYNTHVID_VERSION_WIN7 SYNTHVID_VERSION(3, 0) +#define SYNTHVID_VERSION_WIN8 SYNTHVID_VERSION(3, 2) + +#define SYNTHVID_DEPTH_WIN7 16 +#define SYNTHVID_DEPTH_WIN8 32 + +#define SYNTHVID_FB_SIZE_WIN7 (4 * 1024 * 1024) +#define SYNTHVID_WIDTH_MAX_WIN7 1600 +#define SYNTHVID_HEIGHT_MAX_WIN7 1200 + +#define SYNTHVID_FB_SIZE_WIN8 (8 * 1024 * 1024) + +#define PCI_VENDOR_ID_MICROSOFT 0x1414 +#define PCI_DEVICE_ID_HYPERV_VIDEO 0x5353 + + +enum pipe_msg_type { + PIPE_MSG_INVALID, + PIPE_MSG_DATA, + PIPE_MSG_MAX +}; + +struct pipe_msg_hdr { + u32 type; + u32 size; /* size of message after this field */ +} __packed; + + +enum synthvid_msg_type { + SYNTHVID_ERROR = 0, + SYNTHVID_VERSION_REQUEST = 1, + SYNTHVID_VERSION_RESPONSE = 2, + SYNTHVID_VRAM_LOCATION = 3, + SYNTHVID_VRAM_LOCATION_ACK = 4, + SYNTHVID_SITUATION_UPDATE = 5, + SYNTHVID_SITUATION_UPDATE_ACK = 6, + SYNTHVID_POINTER_POSITION = 7, + SYNTHVID_POINTER_SHAPE = 8, + SYNTHVID_FEATURE_CHANGE = 9, + SYNTHVID_DIRT = 10, + + SYNTHVID_MAX = 11 +}; + +struct synthvid_msg_hdr { + u32 type; + u32 size; /* size of this header + payload after this field*/ +} __packed; + + +struct synthvid_version_req { + u32 version; +} __packed; + +struct synthvid_version_resp { + u32 version; + u8 is_accepted; + u8 max_video_outputs; +} __packed; + +struct synthvid_vram_location { + u64 user_ctx; + u8 is_vram_gpa_specified; + u64 vram_gpa; +} __packed; + +struct synthvid_vram_location_ack { + u64 user_ctx; +} __packed; + +struct video_output_situation { + u8 active; + u32 vram_offset; + u8 depth_bits; + u32 width_pixels; + u32 height_pixels; + u32 pitch_bytes; +} __packed; + +struct synthvid_situation_update { + u64 user_ctx; + u8 video_output_count; + struct video_output_situation video_output[1]; +} __packed; + +struct synthvid_situation_update_ack { + u64 user_ctx; +} __packed; + +struct synthvid_pointer_position { + u8 is_visible; + u8 video_output; + s32 image_x; + s32 image_y; +} __packed; + + +#define CURSOR_MAX_X 96 +#define CURSOR_MAX_Y 96 +#define CURSOR_ARGB_PIXEL_SIZE 4 +#define CURSOR_MAX_SIZE (CURSOR_MAX_X * CURSOR_MAX_Y * CURSOR_ARGB_PIXEL_SIZE) +#define CURSOR_COMPLETE (-1) + +struct synthvid_pointer_shape { + u8 part_idx; + u8 is_argb; + u32 width; /* CURSOR_MAX_X at most */ + u32 height; /* CURSOR_MAX_Y at most */ + u32 hot_x; /* hotspot relative to upper-left of pointer image */ + u32 hot_y; + u8 data[4]; +} __packed; + +struct synthvid_feature_change { + u8 is_dirt_needed; + u8 is_ptr_pos_needed; + u8 is_ptr_shape_needed; + u8 is_situ_needed; +} __packed; + +struct rect { + s32 x1, y1; /* top left corner */ + s32 x2, y2; /* bottom right corner, exclusive */ +} __packed; + +struct synthvid_dirt { + u8 video_output; + u8 dirt_count; + struct rect rect[1]; +} __packed; + +struct synthvid_msg { + struct pipe_msg_hdr pipe_hdr; + struct synthvid_msg_hdr vid_hdr; + union { + struct synthvid_version_req ver_req; + struct synthvid_version_resp ver_resp; + struct synthvid_vram_location vram; + struct synthvid_vram_location_ack vram_ack; + struct synthvid_situation_update situ; + struct synthvid_situation_update_ack situ_ack; + struct synthvid_pointer_position ptr_pos; + struct synthvid_pointer_shape ptr_shape; + struct synthvid_feature_change feature_chg; + struct synthvid_dirt dirt; + }; +} __packed; + + + +/* FB driver definitions and structures */ +#define HVFB_WIDTH 1152 /* default screen width */ +#define HVFB_HEIGHT 864 /* default screen height */ +#define HVFB_WIDTH_MIN 640 +#define HVFB_HEIGHT_MIN 480 + +#define RING_BUFSIZE (256 * 1024) +#define VSP_TIMEOUT (10 * HZ) +#define HVFB_UPDATE_DELAY (HZ / 20) + +struct hvfb_par { + struct fb_info *info; + bool fb_ready; /* fb device is ready */ + struct completion wait; + u32 synthvid_version; + + struct delayed_work dwork; + bool update; + + u32 pseudo_palette[16]; + u8 init_buf[MAX_VMBUS_PKT_SIZE]; + u8 recv_buf[MAX_VMBUS_PKT_SIZE]; +}; + +static uint screen_width = HVFB_WIDTH; +static uint screen_height = HVFB_HEIGHT; +static uint screen_depth; +static uint screen_fb_size; + +/* Send message to Hyper-V host */ +static inline int synthvid_send(struct hv_device *hdev, + struct synthvid_msg *msg) +{ + static atomic64_t request_id = ATOMIC64_INIT(0); + int ret; + + msg->pipe_hdr.type = PIPE_MSG_DATA; + msg->pipe_hdr.size = msg->vid_hdr.size; + + ret = vmbus_sendpacket(hdev->channel, msg, + msg->vid_hdr.size + sizeof(struct pipe_msg_hdr), + atomic64_inc_return(&request_id), + VM_PKT_DATA_INBAND, 0); + + if (ret) + pr_err("Unable to send packet via vmbus\n"); + + return ret; +} + + +/* Send screen resolution info to host */ +static int synthvid_send_situ(struct hv_device *hdev) +{ + struct fb_info *info = hv_get_drvdata(hdev); + struct synthvid_msg msg; + + if (!info) + return -ENODEV; + + memset(&msg, 0, sizeof(struct synthvid_msg)); + + msg.vid_hdr.type = SYNTHVID_SITUATION_UPDATE; + msg.vid_hdr.size = sizeof(struct synthvid_msg_hdr) + + sizeof(struct synthvid_situation_update); + msg.situ.user_ctx = 0; + msg.situ.video_output_count = 1; + msg.situ.video_output[0].active = 1; + msg.situ.video_output[0].vram_offset = 0; + msg.situ.video_output[0].depth_bits = info->var.bits_per_pixel; + msg.situ.video_output[0].width_pixels = info->var.xres; + msg.situ.video_output[0].height_pixels = info->var.yres; + msg.situ.video_output[0].pitch_bytes = info->fix.line_length; + + synthvid_send(hdev, &msg); + + return 0; +} + +/* Send mouse pointer info to host */ +static int synthvid_send_ptr(struct hv_device *hdev) +{ + struct synthvid_msg msg; + + memset(&msg, 0, sizeof(struct synthvid_msg)); + msg.vid_hdr.type = SYNTHVID_POINTER_POSITION; + msg.vid_hdr.size = sizeof(struct synthvid_msg_hdr) + + sizeof(struct synthvid_pointer_position); + msg.ptr_pos.is_visible = 1; + msg.ptr_pos.video_output = 0; + msg.ptr_pos.image_x = 0; + msg.ptr_pos.image_y = 0; + synthvid_send(hdev, &msg); + + memset(&msg, 0, sizeof(struct synthvid_msg)); + msg.vid_hdr.type = SYNTHVID_POINTER_SHAPE; + msg.vid_hdr.size = sizeof(struct synthvid_msg_hdr) + + sizeof(struct synthvid_pointer_shape); + msg.ptr_shape.part_idx = CURSOR_COMPLETE; + msg.ptr_shape.is_argb = 1; + msg.ptr_shape.width = 1; + msg.ptr_shape.height = 1; + msg.ptr_shape.hot_x = 0; + msg.ptr_shape.hot_y = 0; + msg.ptr_shape.data[0] = 0; + msg.ptr_shape.data[1] = 1; + msg.ptr_shape.data[2] = 1; + msg.ptr_shape.data[3] = 1; + synthvid_send(hdev, &msg); + + return 0; +} + +/* Send updated screen area (dirty rectangle) location to host */ +static int synthvid_update(struct fb_info *info) +{ + struct hv_device *hdev = device_to_hv_device(info->device); + struct synthvid_msg msg; + + memset(&msg, 0, sizeof(struct synthvid_msg)); + + msg.vid_hdr.type = SYNTHVID_DIRT; + msg.vid_hdr.size = sizeof(struct synthvid_msg_hdr) + + sizeof(struct synthvid_dirt); + msg.dirt.video_output = 0; + msg.dirt.dirt_count = 1; + msg.dirt.rect[0].x1 = 0; + msg.dirt.rect[0].y1 = 0; + msg.dirt.rect[0].x2 = info->var.xres; + msg.dirt.rect[0].y2 = info->var.yres; + + synthvid_send(hdev, &msg); + + return 0; +} + + +/* + * Actions on received messages from host: + * Complete the wait event. + * Or, reply with screen and cursor info. + */ +static void synthvid_recv_sub(struct hv_device *hdev) +{ + struct fb_info *info = hv_get_drvdata(hdev); + struct hvfb_par *par; + struct synthvid_msg *msg; + + if (!info) + return; + + par = info->par; + msg = (struct synthvid_msg *)par->recv_buf; + + /* Complete the wait event */ + if (msg->vid_hdr.type == SYNTHVID_VERSION_RESPONSE || + msg->vid_hdr.type == SYNTHVID_VRAM_LOCATION_ACK) { + memcpy(par->init_buf, msg, MAX_VMBUS_PKT_SIZE); + complete(&par->wait); + return; + } + + /* Reply with screen and cursor info */ + if (msg->vid_hdr.type == SYNTHVID_FEATURE_CHANGE) { + if (par->fb_ready) { + synthvid_send_ptr(hdev); + synthvid_send_situ(hdev); + } + + par->update = msg->feature_chg.is_dirt_needed; + if (par->update) + schedule_delayed_work(&par->dwork, HVFB_UPDATE_DELAY); + } +} + +/* Receive callback for messages from the host */ +static void synthvid_receive(void *ctx) +{ + struct hv_device *hdev = ctx; + struct fb_info *info = hv_get_drvdata(hdev); + struct hvfb_par *par; + struct synthvid_msg *recv_buf; + u32 bytes_recvd; + u64 req_id; + int ret; + + if (!info) + return; + + par = info->par; + recv_buf = (struct synthvid_msg *)par->recv_buf; + + do { + ret = vmbus_recvpacket(hdev->channel, recv_buf, + MAX_VMBUS_PKT_SIZE, + &bytes_recvd, &req_id); + if (bytes_recvd > 0 && + recv_buf->pipe_hdr.type == PIPE_MSG_DATA) + synthvid_recv_sub(hdev); + } while (bytes_recvd > 0 && ret == 0); +} + +/* Check synthetic video protocol version with the host */ +static int synthvid_negotiate_ver(struct hv_device *hdev, u32 ver) +{ + struct fb_info *info = hv_get_drvdata(hdev); + struct hvfb_par *par = info->par; + struct synthvid_msg *msg = (struct synthvid_msg *)par->init_buf; + int t, ret = 0; + + memset(msg, 0, sizeof(struct synthvid_msg)); + msg->vid_hdr.type = SYNTHVID_VERSION_REQUEST; + msg->vid_hdr.size = sizeof(struct synthvid_msg_hdr) + + sizeof(struct synthvid_version_req); + msg->ver_req.version = ver; + synthvid_send(hdev, msg); + + t = wait_for_completion_timeout(&par->wait, VSP_TIMEOUT); + if (!t) { + pr_err("Time out on waiting version response\n"); + ret = -ETIMEDOUT; + goto out; + } + if (!msg->ver_resp.is_accepted) { + ret = -ENODEV; + goto out; + } + + par->synthvid_version = ver; + +out: + return ret; +} + +/* Connect to VSP (Virtual Service Provider) on host */ +static int synthvid_connect_vsp(struct hv_device *hdev) +{ + struct fb_info *info = hv_get_drvdata(hdev); + struct hvfb_par *par = info->par; + int ret; + + ret = vmbus_open(hdev->channel, RING_BUFSIZE, RING_BUFSIZE, + NULL, 0, synthvid_receive, hdev); + if (ret) { + pr_err("Unable to open vmbus channel\n"); + return ret; + } + + /* Negotiate the protocol version with host */ + if (vmbus_proto_version == VERSION_WS2008 || + vmbus_proto_version == VERSION_WIN7) + ret = synthvid_negotiate_ver(hdev, SYNTHVID_VERSION_WIN7); + else + ret = synthvid_negotiate_ver(hdev, SYNTHVID_VERSION_WIN8); + + if (ret) { + pr_err("Synthetic video device version not accepted\n"); + goto error; + } + + if (par->synthvid_version == SYNTHVID_VERSION_WIN7) { + screen_depth = SYNTHVID_DEPTH_WIN7; + screen_fb_size = SYNTHVID_FB_SIZE_WIN7; + } else { + screen_depth = SYNTHVID_DEPTH_WIN8; + screen_fb_size = SYNTHVID_FB_SIZE_WIN8; + } + + return 0; + +error: + vmbus_close(hdev->channel); + return ret; +} + +/* Send VRAM and Situation messages to the host */ +static int synthvid_send_config(struct hv_device *hdev) +{ + struct fb_info *info = hv_get_drvdata(hdev); + struct hvfb_par *par = info->par; + struct synthvid_msg *msg = (struct synthvid_msg *)par->init_buf; + int t, ret = 0; + + /* Send VRAM location */ + memset(msg, 0, sizeof(struct synthvid_msg)); + msg->vid_hdr.type = SYNTHVID_VRAM_LOCATION; + msg->vid_hdr.size = sizeof(struct synthvid_msg_hdr) + + sizeof(struct synthvid_vram_location); + msg->vram.user_ctx = msg->vram.vram_gpa = info->fix.smem_start; + msg->vram.is_vram_gpa_specified = 1; + synthvid_send(hdev, msg); + + t = wait_for_completion_timeout(&par->wait, VSP_TIMEOUT); + if (!t) { + pr_err("Time out on waiting vram location ack\n"); + ret = -ETIMEDOUT; + goto out; + } + if (msg->vram_ack.user_ctx != info->fix.smem_start) { + pr_err("Unable to set VRAM location\n"); + ret = -ENODEV; + goto out; + } + + /* Send pointer and situation update */ + synthvid_send_ptr(hdev); + synthvid_send_situ(hdev); + +out: + return ret; +} + + +/* + * Delayed work callback: + * It is called at HVFB_UPDATE_DELAY or longer time interval to process + * screen updates. It is re-scheduled if further update is necessary. + */ +static void hvfb_update_work(struct work_struct *w) +{ + struct hvfb_par *par = container_of(w, struct hvfb_par, dwork.work); + struct fb_info *info = par->info; + + if (par->fb_ready) + synthvid_update(info); + + if (par->update) + schedule_delayed_work(&par->dwork, HVFB_UPDATE_DELAY); +} + + +/* Framebuffer operation handlers */ + +static int hvfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) +{ + if (var->xres < HVFB_WIDTH_MIN || var->yres < HVFB_HEIGHT_MIN || + var->xres > screen_width || var->yres > screen_height || + var->bits_per_pixel != screen_depth) + return -EINVAL; + + var->xres_virtual = var->xres; + var->yres_virtual = var->yres; + + return 0; +} + +static int hvfb_set_par(struct fb_info *info) +{ + struct hv_device *hdev = device_to_hv_device(info->device); + + return synthvid_send_situ(hdev); +} + + +static inline u32 chan_to_field(u32 chan, struct fb_bitfield *bf) +{ + return ((chan & 0xffff) >> (16 - bf->length)) << bf->offset; +} + +static int hvfb_setcolreg(unsigned regno, unsigned red, unsigned green, + unsigned blue, unsigned transp, struct fb_info *info) +{ + u32 *pal = info->pseudo_palette; + + if (regno > 15) + return -EINVAL; + + pal[regno] = chan_to_field(red, &info->var.red) + | chan_to_field(green, &info->var.green) + | chan_to_field(blue, &info->var.blue) + | chan_to_field(transp, &info->var.transp); + + return 0; +} + + +static struct fb_ops hvfb_ops = { + .owner = THIS_MODULE, + .fb_check_var = hvfb_check_var, + .fb_set_par = hvfb_set_par, + .fb_setcolreg = hvfb_setcolreg, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, +}; + + +/* Get options from kernel paramenter "video=" */ +static void hvfb_get_option(struct fb_info *info) +{ + struct hvfb_par *par = info->par; + char *opt = NULL, *p; + uint x = 0, y = 0; + + if (fb_get_options(KBUILD_MODNAME, &opt) || !opt || !*opt) + return; + + p = strsep(&opt, "x"); + if (!*p || kstrtouint(p, 0, &x) || + !opt || !*opt || kstrtouint(opt, 0, &y)) { + pr_err("Screen option is invalid: skipped\n"); + return; + } + + if (x < HVFB_WIDTH_MIN || y < HVFB_HEIGHT_MIN || + (par->synthvid_version == SYNTHVID_VERSION_WIN8 && + x * y * screen_depth / 8 > SYNTHVID_FB_SIZE_WIN8) || + (par->synthvid_version == SYNTHVID_VERSION_WIN7 && + (x > SYNTHVID_WIDTH_MAX_WIN7 || y > SYNTHVID_HEIGHT_MAX_WIN7))) { + pr_err("Screen resolution option is out of range: skipped\n"); + return; + } + + screen_width = x; + screen_height = y; + return; +} + + +/* Get framebuffer memory from Hyper-V video pci space */ +static int hvfb_getmem(struct fb_info *info) +{ + struct pci_dev *pdev; + ulong fb_phys; + void *fb_virt; + + pdev = pci_get_device(PCI_VENDOR_ID_MICROSOFT, + PCI_DEVICE_ID_HYPERV_VIDEO, NULL); + if (!pdev) { + pr_err("Unable to find PCI Hyper-V video\n"); + return -ENODEV; + } + + if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM) || + pci_resource_len(pdev, 0) < screen_fb_size) + goto err1; + + fb_phys = pci_resource_end(pdev, 0) - screen_fb_size + 1; + if (!request_mem_region(fb_phys, screen_fb_size, KBUILD_MODNAME)) + goto err1; + + fb_virt = ioremap(fb_phys, screen_fb_size); + if (!fb_virt) + goto err2; + + info->apertures = alloc_apertures(1); + if (!info->apertures) + goto err3; + + info->apertures->ranges[0].base = pci_resource_start(pdev, 0); + info->apertures->ranges[0].size = pci_resource_len(pdev, 0); + info->fix.smem_start = fb_phys; + info->fix.smem_len = screen_fb_size; + info->screen_base = fb_virt; + info->screen_size = screen_fb_size; + + pci_dev_put(pdev); + return 0; + +err3: + iounmap(fb_virt); +err2: + release_mem_region(fb_phys, screen_fb_size); +err1: + pci_dev_put(pdev); + return -ENOMEM; +} + +/* Release the framebuffer */ +static void hvfb_putmem(struct fb_info *info) +{ + iounmap(info->screen_base); + release_mem_region(info->fix.smem_start, screen_fb_size); +} + + +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 const struct hv_vmbus_device_id id_table[] = { + /* Synthetic Video Device GUID */ + {HV_SYNTHVID_GUID}, + {} +}; + +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 __init hvfb_drv_init(void) +{ + return vmbus_driver_register(&hvfb_drv); +} + +static void __exit hvfb_drv_exit(void) +{ + 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"); diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c index 217678e0b983..fd2897455696 100644 --- a/drivers/video/matrox/matroxfb_maven.c +++ b/drivers/video/matrox/matroxfb_maven.c @@ -137,8 +137,20 @@ static int* get_ctrl_ptr(struct maven_data* md, int idx) { static int maven_get_reg(struct i2c_client* c, char reg) { char dst; - struct i2c_msg msgs[] = {{ c->addr, I2C_M_REV_DIR_ADDR, sizeof(reg), ® }, - { c->addr, I2C_M_RD | I2C_M_NOSTART, sizeof(dst), &dst }}; + struct i2c_msg msgs[] = { + { + .addr = c->addr, + .flags = I2C_M_REV_DIR_ADDR, + .len = sizeof(reg), + .buf = ® + }, + { + .addr = c->addr, + .flags = I2C_M_RD | I2C_M_NOSTART, + .len = sizeof(dst), + .buf = &dst + } + }; s32 err; err = i2c_transfer(c->adapter, msgs, 2); diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c index b75db0186488..0d0a43c5de4f 100644 --- a/drivers/video/uvesafb.c +++ b/drivers/video/uvesafb.c @@ -166,7 +166,7 @@ static int uvesafb_exec(struct uvesafb_ktask *task) memcpy(&m->id, &uvesafb_cn_id, sizeof(m->id)); m->seq = seq; m->len = len; - m->ack = random32(); + m->ack = prandom_u32(); /* uvesafb_task structure */ memcpy(m + 1, &task->t, sizeof(task->t)); diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig index 5a32232cf7c1..7b16994aa6e1 100644 --- a/drivers/xen/Kconfig +++ b/drivers/xen/Kconfig @@ -145,9 +145,9 @@ config SWIOTLB_XEN select SWIOTLB config XEN_TMEM - bool + tristate depends on !ARM - default y if (CLEANCACHE || FRONTSWAP) + default m if (CLEANCACHE || FRONTSWAP) help Shim to interface in-kernel Transcendent Memory hooks (e.g. cleancache and frontswap) to Xen tmem hypercalls. diff --git a/drivers/xen/tmem.c b/drivers/xen/tmem.c index 3ee836d42581..e3600be4e7fa 100644 --- a/drivers/xen/tmem.c +++ b/drivers/xen/tmem.c @@ -5,6 +5,7 @@ * Author: Dan Magenheimer */ +#include <linux/module.h> #include <linux/kernel.h> #include <linux/types.h> #include <linux/init.h> @@ -128,6 +129,7 @@ static int xen_tmem_flush_object(u32 pool_id, struct tmem_oid oid) return xen_tmem_op(TMEM_FLUSH_OBJECT, pool_id, oid, 0, 0, 0, 0, 0); } +#ifndef CONFIG_XEN_TMEM_MODULE bool __read_mostly tmem_enabled = false; static int __init enable_tmem(char *s) @@ -136,6 +138,7 @@ static int __init enable_tmem(char *s) return 1; } __setup("tmem", enable_tmem); +#endif #ifdef CONFIG_CLEANCACHE static int xen_tmem_destroy_pool(u32 pool_id) @@ -227,16 +230,21 @@ static int tmem_cleancache_init_shared_fs(char *uuid, size_t pagesize) return xen_tmem_new_pool(shared_uuid, TMEM_POOL_SHARED, pagesize); } -static bool __initdata use_cleancache = true; - +static bool disable_cleancache __read_mostly; +static bool disable_selfballooning __read_mostly; +#ifdef CONFIG_XEN_TMEM_MODULE +module_param(disable_cleancache, bool, S_IRUGO); +module_param(disable_selfballooning, bool, S_IRUGO); +#else static int __init no_cleancache(char *s) { - use_cleancache = false; + disable_cleancache = true; return 1; } __setup("nocleancache", no_cleancache); +#endif -static struct cleancache_ops __initdata tmem_cleancache_ops = { +static struct cleancache_ops tmem_cleancache_ops = { .put_page = tmem_cleancache_put_page, .get_page = tmem_cleancache_get_page, .invalidate_page = tmem_cleancache_flush_page, @@ -353,54 +361,71 @@ static void tmem_frontswap_init(unsigned ignored) xen_tmem_new_pool(private, TMEM_POOL_PERSIST, PAGE_SIZE); } -static bool __initdata use_frontswap = true; - +static bool disable_frontswap __read_mostly; +static bool disable_frontswap_selfshrinking __read_mostly; +#ifdef CONFIG_XEN_TMEM_MODULE +module_param(disable_frontswap, bool, S_IRUGO); +module_param(disable_frontswap_selfshrinking, bool, S_IRUGO); +#else static int __init no_frontswap(char *s) { - use_frontswap = false; + disable_frontswap = true; return 1; } __setup("nofrontswap", no_frontswap); +#endif -static struct frontswap_ops __initdata tmem_frontswap_ops = { +static struct frontswap_ops tmem_frontswap_ops = { .store = tmem_frontswap_store, .load = tmem_frontswap_load, .invalidate_page = tmem_frontswap_flush_page, .invalidate_area = tmem_frontswap_flush_area, .init = tmem_frontswap_init }; +#else /* CONFIG_FRONTSWAP */ +#define disable_frontswap_selfshrinking 1 #endif -static int __init xen_tmem_init(void) +static int xen_tmem_init(void) { if (!xen_domain()) return 0; #ifdef CONFIG_FRONTSWAP - if (tmem_enabled && use_frontswap) { + if (tmem_enabled && !disable_frontswap) { char *s = ""; - struct frontswap_ops old_ops = + struct frontswap_ops *old_ops = frontswap_register_ops(&tmem_frontswap_ops); tmem_frontswap_poolid = -1; - if (old_ops.init != NULL) + if (IS_ERR(old_ops) || old_ops) { + if (IS_ERR(old_ops)) + return PTR_ERR(old_ops); s = " (WARNING: frontswap_ops overridden)"; + } printk(KERN_INFO "frontswap enabled, RAM provided by " "Xen Transcendent Memory%s\n", s); } #endif #ifdef CONFIG_CLEANCACHE BUG_ON(sizeof(struct cleancache_filekey) != sizeof(struct tmem_oid)); - if (tmem_enabled && use_cleancache) { + if (tmem_enabled && !disable_cleancache) { char *s = ""; - struct cleancache_ops old_ops = + struct cleancache_ops *old_ops = cleancache_register_ops(&tmem_cleancache_ops); - if (old_ops.init_fs != NULL) + if (old_ops) s = " (WARNING: cleancache_ops overridden)"; printk(KERN_INFO "cleancache enabled, RAM provided by " "Xen Transcendent Memory%s\n", s); } #endif +#ifdef CONFIG_XEN_SELFBALLOONING + xen_selfballoon_init(!disable_selfballooning, + !disable_frontswap_selfshrinking); +#endif return 0; } module_init(xen_tmem_init) +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Dan Magenheimer <dan.magenheimer@oracle.com>"); +MODULE_DESCRIPTION("Shim to Xen transcendent memory"); diff --git a/drivers/xen/xen-selfballoon.c b/drivers/xen/xen-selfballoon.c index 2552d3e0a70f..f2ef569c7cc1 100644 --- a/drivers/xen/xen-selfballoon.c +++ b/drivers/xen/xen-selfballoon.c @@ -121,7 +121,7 @@ static DECLARE_DELAYED_WORK(selfballoon_worker, selfballoon_process); static bool frontswap_selfshrinking __read_mostly; /* Enable/disable with kernel boot option. */ -static bool use_frontswap_selfshrink __initdata = true; +static bool use_frontswap_selfshrink = true; /* * The default values for the following parameters were deemed reasonable @@ -185,7 +185,7 @@ static int __init xen_nofrontswap_selfshrink_setup(char *s) __setup("noselfshrink", xen_nofrontswap_selfshrink_setup); /* Disable with kernel boot option. */ -static bool use_selfballooning __initdata = true; +static bool use_selfballooning = true; static int __init xen_noselfballooning_setup(char *s) { @@ -196,7 +196,7 @@ static int __init xen_noselfballooning_setup(char *s) __setup("noselfballooning", xen_noselfballooning_setup); #else /* !CONFIG_FRONTSWAP */ /* Enable with kernel boot option. */ -static bool use_selfballooning __initdata = false; +static bool use_selfballooning; static int __init xen_selfballooning_setup(char *s) { @@ -537,7 +537,7 @@ int register_xen_selfballooning(struct device *dev) } EXPORT_SYMBOL(register_xen_selfballooning); -static int __init xen_selfballoon_init(void) +int xen_selfballoon_init(bool use_selfballooning, bool use_frontswap_selfshrink) { bool enable = false; @@ -571,7 +571,4 @@ static int __init xen_selfballoon_init(void) return 0; } - -subsys_initcall(xen_selfballoon_init); - -MODULE_LICENSE("GPL"); +EXPORT_SYMBOL(xen_selfballoon_init); |