diff options
Diffstat (limited to 'drivers')
29 files changed, 180 insertions, 124 deletions
diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c index a8c8b56b275e..1b3def1e8591 100644 --- a/drivers/block/viodasd.c +++ b/drivers/block/viodasd.c @@ -28,6 +28,9 @@ * All disk operations are performed by sending messages back and forth to * the OS/400 partition. */ + +#define pr_fmt(fmt) "viod: " fmt + #include <linux/major.h> #include <linux/fs.h> #include <linux/module.h> @@ -63,9 +66,6 @@ MODULE_LICENSE("GPL"); #define VIOD_VERS "1.64" -#define VIOD_KERN_WARNING KERN_WARNING "viod: " -#define VIOD_KERN_INFO KERN_INFO "viod: " - enum { PARTITION_SHIFT = 3, MAX_DISKNO = HVMAXARCHITECTEDVIRTUALDISKS, @@ -156,7 +156,7 @@ static int viodasd_open(struct block_device *bdev, fmode_t mode) ((u64)DEVICE_NO(d) << 48) | ((u64)flags << 32), 0, 0, 0); if (hvrc != 0) { - printk(VIOD_KERN_WARNING "HV open failed %d\n", (int)hvrc); + pr_warning("HV open failed %d\n", (int)hvrc); return -EIO; } @@ -167,9 +167,8 @@ static int viodasd_open(struct block_device *bdev, fmode_t mode) const struct vio_error_entry *err = vio_lookup_rc(viodasd_err_table, we.sub_result); - printk(VIOD_KERN_WARNING - "bad rc opening disk: %d:0x%04x (%s)\n", - (int)we.rc, we.sub_result, err->msg); + pr_warning("bad rc opening disk: %d:0x%04x (%s)\n", + (int)we.rc, we.sub_result, err->msg); return -EIO; } @@ -195,8 +194,7 @@ static int viodasd_release(struct gendisk *disk, fmode_t mode) ((u64)DEVICE_NO(d) << 48) /* | ((u64)flags << 32) */, 0, 0, 0); if (hvrc != 0) - printk(VIOD_KERN_WARNING "HV close call failed %d\n", - (int)hvrc); + pr_warning("HV close call failed %d\n", (int)hvrc); return 0; } @@ -288,8 +286,7 @@ static int send_request(struct request *req) bevent = (struct vioblocklpevent *) vio_get_event_buffer(viomajorsubtype_blockio); if (bevent == NULL) { - printk(VIOD_KERN_WARNING - "error allocating disk event buffer\n"); + pr_warning("error allocating disk event buffer\n"); goto error_ret; } @@ -333,9 +330,8 @@ static int send_request(struct request *req) } if (hvrc != HvLpEvent_Rc_Good) { - printk(VIOD_KERN_WARNING - "error sending disk event to OS/400 (rc %d)\n", - (int)hvrc); + pr_warning("error sending disk event to OS/400 (rc %d)\n", + (int)hvrc); goto error_ret; } spin_unlock_irqrestore(&viodasd_spinlock, flags); @@ -402,7 +398,7 @@ retry: ((u64)dev_no << 48) | ((u64)flags<< 32), 0, 0, 0); if (hvrc != 0) { - printk(VIOD_KERN_WARNING "bad rc on HV open %d\n", (int)hvrc); + pr_warning("bad rc on HV open %d\n", (int)hvrc); return 0; } @@ -416,9 +412,8 @@ retry: goto retry; } if (we.max_disk > (MAX_DISKNO - 1)) { - printk_once(VIOD_KERN_INFO - "Only examining the first %d of %d disks connected\n", - MAX_DISKNO, we.max_disk + 1); + printk_once(KERN_INFO pr_fmt("Only examining the first %d of %d disks connected\n"), + MAX_DISKNO, we.max_disk + 1); } /* Send the close event to OS/400. We DON'T expect a response */ @@ -432,17 +427,15 @@ retry: ((u64)dev_no << 48) | ((u64)flags << 32), 0, 0, 0); if (hvrc != 0) { - printk(VIOD_KERN_WARNING - "bad rc sending event to OS/400 %d\n", (int)hvrc); + pr_warning("bad rc sending event to OS/400 %d\n", (int)hvrc); return 0; } if (d->dev == NULL) { /* this is when we reprobe for new disks */ if (vio_create_viodasd(dev_no) == NULL) { - printk(VIOD_KERN_WARNING - "cannot allocate virtual device for disk %d\n", - dev_no); + pr_warning("cannot allocate virtual device for disk %d\n", + dev_no); return 0; } /* @@ -457,15 +450,13 @@ retry: spin_lock_init(&d->q_lock); q = blk_init_queue(do_viodasd_request, &d->q_lock); if (q == NULL) { - printk(VIOD_KERN_WARNING "cannot allocate queue for disk %d\n", - dev_no); + pr_warning("cannot allocate queue for disk %d\n", dev_no); return 0; } g = alloc_disk(1 << PARTITION_SHIFT); if (g == NULL) { - printk(VIOD_KERN_WARNING - "cannot allocate disk structure for disk %d\n", - dev_no); + pr_warning("cannot allocate disk structure for disk %d\n", + dev_no); blk_cleanup_queue(q); return 0; } @@ -489,13 +480,12 @@ retry: g->driverfs_dev = d->dev; set_capacity(g, d->size >> 9); - printk(VIOD_KERN_INFO "disk %d: %lu sectors (%lu MB) " - "CHS=%d/%d/%d sector size %d%s\n", - dev_no, (unsigned long)(d->size >> 9), - (unsigned long)(d->size >> 20), - (int)d->cylinders, (int)d->tracks, - (int)d->sectors, (int)d->bytes_per_sector, - d->read_only ? " (RO)" : ""); + pr_info("disk %d: %lu sectors (%lu MB) CHS=%d/%d/%d sector size %d%s\n", + dev_no, (unsigned long)(d->size >> 9), + (unsigned long)(d->size >> 20), + (int)d->cylinders, (int)d->tracks, + (int)d->sectors, (int)d->bytes_per_sector, + d->read_only ? " (RO)" : ""); /* register us in the global list */ add_disk(g); @@ -580,8 +570,8 @@ static int viodasd_handle_read_write(struct vioblocklpevent *bevent) if (error) { const struct vio_error_entry *err; err = vio_lookup_rc(viodasd_err_table, bevent->sub_result); - printk(VIOD_KERN_WARNING "read/write error %d:0x%04x (%s)\n", - event->xRc, bevent->sub_result, err->msg); + pr_warning("read/write error %d:0x%04x (%s)\n", + event->xRc, bevent->sub_result, err->msg); num_sect = blk_rq_sectors(req); } qlock = req->q->queue_lock; @@ -606,8 +596,7 @@ static void handle_block_event(struct HvLpEvent *event) return; /* First, we should NEVER get an int here...only acks */ if (hvlpevent_is_int(event)) { - printk(VIOD_KERN_WARNING - "Yikes! got an int in viodasd event handler!\n"); + pr_warning("Yikes! got an int in viodasd event handler!\n"); if (hvlpevent_need_ack(event)) { event->xRc = HvLpEvent_Rc_InvalidSubtype; HvCallEvent_ackLpEvent(event); @@ -650,7 +639,7 @@ static void handle_block_event(struct HvLpEvent *event) break; default: - printk(VIOD_KERN_WARNING "invalid subtype!"); + pr_warning("invalid subtype!"); if (hvlpevent_need_ack(event)) { event->xRc = HvLpEvent_Rc_InvalidSubtype; HvCallEvent_ackLpEvent(event); @@ -739,29 +728,26 @@ static int __init viodasd_init(void) vio_set_hostlp(); if (viopath_hostLp == HvLpIndexInvalid) { - printk(VIOD_KERN_WARNING "invalid hosting partition\n"); + pr_warning("invalid hosting partition\n"); rc = -EIO; goto early_fail; } - printk(VIOD_KERN_INFO "vers " VIOD_VERS ", hosting partition %d\n", - viopath_hostLp); + pr_info("vers " VIOD_VERS ", hosting partition %d\n", viopath_hostLp); /* register the block device */ rc = register_blkdev(VIODASD_MAJOR, VIOD_GENHD_NAME); if (rc) { - printk(VIOD_KERN_WARNING - "Unable to get major number %d for %s\n", - VIODASD_MAJOR, VIOD_GENHD_NAME); + pr_warning("Unable to get major number %d for %s\n", + VIODASD_MAJOR, VIOD_GENHD_NAME); goto early_fail; } /* Actually open the path to the hosting partition */ rc = viopath_open(viopath_hostLp, viomajorsubtype_blockio, VIOMAXREQ + 2); if (rc) { - printk(VIOD_KERN_WARNING - "error opening path to host partition %d\n", - viopath_hostLp); + pr_warning("error opening path to host partition %d\n", + viopath_hostLp); goto unregister_blk; } @@ -770,7 +756,7 @@ static int __init viodasd_init(void) rc = vio_register_driver(&viodasd_driver); if (rc) { - printk(VIOD_KERN_WARNING "vio_register_driver failed\n"); + pr_warning("vio_register_driver failed\n"); goto unset_handler; } diff --git a/drivers/char/hvc_beat.c b/drivers/char/hvc_beat.c index 0afc8b82212e..6913fc33270c 100644 --- a/drivers/char/hvc_beat.c +++ b/drivers/char/hvc_beat.c @@ -84,7 +84,7 @@ static int hvc_beat_put_chars(uint32_t vtermno, const char *buf, int cnt) return cnt; } -static struct hv_ops hvc_beat_get_put_ops = { +static const struct hv_ops hvc_beat_get_put_ops = { .get_chars = hvc_beat_get_chars, .put_chars = hvc_beat_put_chars, }; diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c index 416d3423150d..4c3b59be286a 100644 --- a/drivers/char/hvc_console.c +++ b/drivers/char/hvc_console.c @@ -125,7 +125,7 @@ static struct hvc_struct *hvc_get_by_index(int index) * console interfaces but can still be used as a tty device. This has to be * static because kmalloc will not work during early console init. */ -static struct hv_ops *cons_ops[MAX_NR_HVC_CONSOLES]; +static const struct hv_ops *cons_ops[MAX_NR_HVC_CONSOLES]; static uint32_t vtermnos[MAX_NR_HVC_CONSOLES] = {[0 ... MAX_NR_HVC_CONSOLES - 1] = -1}; @@ -247,7 +247,7 @@ static void destroy_hvc_struct(struct kref *kref) * vty adapters do NOT get an hvc_instantiate() callback since they * appear after early console init. */ -int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops) +int hvc_instantiate(uint32_t vtermno, int index, const struct hv_ops *ops) { struct hvc_struct *hp; @@ -748,8 +748,9 @@ static const struct tty_operations hvc_ops = { .chars_in_buffer = hvc_chars_in_buffer, }; -struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int data, - struct hv_ops *ops, int outbuf_size) +struct hvc_struct *hvc_alloc(uint32_t vtermno, int data, + const struct hv_ops *ops, + int outbuf_size) { struct hvc_struct *hp; int i; diff --git a/drivers/char/hvc_console.h b/drivers/char/hvc_console.h index 10950ca706d8..54381eba4e4a 100644 --- a/drivers/char/hvc_console.h +++ b/drivers/char/hvc_console.h @@ -55,7 +55,7 @@ struct hvc_struct { int outbuf_size; int n_outbuf; uint32_t vtermno; - struct hv_ops *ops; + const struct hv_ops *ops; int irq_requested; int data; struct winsize ws; @@ -76,11 +76,12 @@ struct hv_ops { }; /* Register a vterm and a slot index for use as a console (console_init) */ -extern int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops); +extern int hvc_instantiate(uint32_t vtermno, int index, + const struct hv_ops *ops); /* register a vterm for hvc tty operation (module_init or hotplug add) */ -extern struct hvc_struct * __devinit hvc_alloc(uint32_t vtermno, int data, - struct hv_ops *ops, int outbuf_size); +extern struct hvc_struct * hvc_alloc(uint32_t vtermno, int data, + const struct hv_ops *ops, int outbuf_size); /* remove a vterm from hvc tty operation (module_exit or hotplug remove) */ extern int hvc_remove(struct hvc_struct *hp); diff --git a/drivers/char/hvc_iseries.c b/drivers/char/hvc_iseries.c index 936d05bf37fa..fd0242676a2a 100644 --- a/drivers/char/hvc_iseries.c +++ b/drivers/char/hvc_iseries.c @@ -197,7 +197,7 @@ done: return sent; } -static struct hv_ops hvc_get_put_ops = { +static const struct hv_ops hvc_get_put_ops = { .get_chars = get_chars, .put_chars = put_chars, .notifier_add = notifier_add_irq, diff --git a/drivers/char/hvc_iucv.c b/drivers/char/hvc_iucv.c index fe62bd0e17b7..21681a81cc35 100644 --- a/drivers/char/hvc_iucv.c +++ b/drivers/char/hvc_iucv.c @@ -922,7 +922,7 @@ static int hvc_iucv_pm_restore_thaw(struct device *dev) /* HVC operations */ -static struct hv_ops hvc_iucv_ops = { +static const struct hv_ops hvc_iucv_ops = { .get_chars = hvc_iucv_get_chars, .put_chars = hvc_iucv_put_chars, .notifier_add = hvc_iucv_notifier_add, diff --git a/drivers/char/hvc_rtas.c b/drivers/char/hvc_rtas.c index 88590d040046..61c4a61558d9 100644 --- a/drivers/char/hvc_rtas.c +++ b/drivers/char/hvc_rtas.c @@ -71,7 +71,7 @@ static int hvc_rtas_read_console(uint32_t vtermno, char *buf, int count) return i; } -static struct hv_ops hvc_rtas_get_put_ops = { +static const struct hv_ops hvc_rtas_get_put_ops = { .get_chars = hvc_rtas_read_console, .put_chars = hvc_rtas_write_console, }; diff --git a/drivers/char/hvc_udbg.c b/drivers/char/hvc_udbg.c index bd63ba878a56..b0957e61a7be 100644 --- a/drivers/char/hvc_udbg.c +++ b/drivers/char/hvc_udbg.c @@ -58,7 +58,7 @@ static int hvc_udbg_get(uint32_t vtermno, char *buf, int count) return i; } -static struct hv_ops hvc_udbg_ops = { +static const struct hv_ops hvc_udbg_ops = { .get_chars = hvc_udbg_get, .put_chars = hvc_udbg_put, }; diff --git a/drivers/char/hvc_vio.c b/drivers/char/hvc_vio.c index 10be343d6ae7..27370e99c66f 100644 --- a/drivers/char/hvc_vio.c +++ b/drivers/char/hvc_vio.c @@ -77,7 +77,7 @@ static int filtered_get_chars(uint32_t vtermno, char *buf, int count) return got; } -static struct hv_ops hvc_get_put_ops = { +static const struct hv_ops hvc_get_put_ops = { .get_chars = filtered_get_chars, .put_chars = hvc_put_chars, .notifier_add = notifier_add_irq, diff --git a/drivers/char/hvc_xen.c b/drivers/char/hvc_xen.c index b1a71638c772..60446f82a3fc 100644 --- a/drivers/char/hvc_xen.c +++ b/drivers/char/hvc_xen.c @@ -122,7 +122,7 @@ static int read_console(uint32_t vtermno, char *buf, int len) return recv; } -static struct hv_ops hvc_ops = { +static const struct hv_ops hvc_ops = { .get_chars = read_console, .put_chars = write_console, .notifier_add = notifier_add_irq, diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c index cbaf420c36c5..2d3dc7ded0a9 100644 --- a/drivers/firewire/net.c +++ b/drivers/firewire/net.c @@ -893,20 +893,31 @@ static void fwnet_receive_broadcast(struct fw_iso_context *context, static struct kmem_cache *fwnet_packet_task_cache; +static void fwnet_free_ptask(struct fwnet_packet_task *ptask) +{ + dev_kfree_skb_any(ptask->skb); + kmem_cache_free(fwnet_packet_task_cache, ptask); +} + static int fwnet_send_packet(struct fwnet_packet_task *ptask); static void fwnet_transmit_packet_done(struct fwnet_packet_task *ptask) { - struct fwnet_device *dev; + struct fwnet_device *dev = ptask->dev; unsigned long flags; - - dev = ptask->dev; + bool free; spin_lock_irqsave(&dev->lock, flags); - list_del(&ptask->pt_link); - spin_unlock_irqrestore(&dev->lock, flags); - ptask->outstanding_pkts--; /* FIXME access inside lock */ + ptask->outstanding_pkts--; + + /* Check whether we or the networking TX soft-IRQ is last user. */ + free = (ptask->outstanding_pkts == 0 && !list_empty(&ptask->pt_link)); + + if (ptask->outstanding_pkts == 0) + list_del(&ptask->pt_link); + + spin_unlock_irqrestore(&dev->lock, flags); if (ptask->outstanding_pkts > 0) { u16 dg_size; @@ -951,10 +962,10 @@ static void fwnet_transmit_packet_done(struct fwnet_packet_task *ptask) ptask->max_payload = skb->len + RFC2374_FRAG_HDR_SIZE; } fwnet_send_packet(ptask); - } else { - dev_kfree_skb_any(ptask->skb); - kmem_cache_free(fwnet_packet_task_cache, ptask); } + + if (free) + fwnet_free_ptask(ptask); } static void fwnet_write_complete(struct fw_card *card, int rcode, @@ -977,6 +988,7 @@ static int fwnet_send_packet(struct fwnet_packet_task *ptask) unsigned tx_len; struct rfc2734_header *bufhdr; unsigned long flags; + bool free; dev = ptask->dev; tx_len = ptask->max_payload; @@ -1022,12 +1034,16 @@ static int fwnet_send_packet(struct fwnet_packet_task *ptask) generation, SCODE_100, 0ULL, ptask->skb->data, tx_len + 8, fwnet_write_complete, ptask); - /* FIXME race? */ spin_lock_irqsave(&dev->lock, flags); - list_add_tail(&ptask->pt_link, &dev->broadcasted_list); + + /* If the AT tasklet already ran, we may be last user. */ + free = (ptask->outstanding_pkts == 0 && list_empty(&ptask->pt_link)); + if (!free) + list_add_tail(&ptask->pt_link, &dev->broadcasted_list); + spin_unlock_irqrestore(&dev->lock, flags); - return 0; + goto out; } fw_send_request(dev->card, &ptask->transaction, @@ -1035,12 +1051,19 @@ static int fwnet_send_packet(struct fwnet_packet_task *ptask) ptask->generation, ptask->speed, ptask->fifo_addr, ptask->skb->data, tx_len, fwnet_write_complete, ptask); - /* FIXME race? */ spin_lock_irqsave(&dev->lock, flags); - list_add_tail(&ptask->pt_link, &dev->sent_list); + + /* If the AT tasklet already ran, we may be last user. */ + free = (ptask->outstanding_pkts == 0 && list_empty(&ptask->pt_link)); + if (!free) + list_add_tail(&ptask->pt_link, &dev->sent_list); + spin_unlock_irqrestore(&dev->lock, flags); dev->netdev->trans_start = jiffies; + out: + if (free) + fwnet_free_ptask(ptask); return 0; } @@ -1298,6 +1321,8 @@ static netdev_tx_t fwnet_tx(struct sk_buff *skb, struct net_device *net) spin_unlock_irqrestore(&dev->lock, flags); ptask->max_payload = max_payload; + INIT_LIST_HEAD(&ptask->pt_link); + fwnet_send_packet(ptask); return NETDEV_TX_OK; diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 2345d4103fe6..43ebf337b131 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -2101,11 +2101,6 @@ static int ohci_queue_iso_transmit(struct fw_iso_context *base, u32 payload_index, payload_end_index, next_page_index; int page, end_page, i, length, offset; - /* - * FIXME: Cycle lost behavior should be configurable: lose - * packet, retransmit or terminate.. - */ - p = packet; payload_index = payload; @@ -2135,6 +2130,14 @@ static int ohci_queue_iso_transmit(struct fw_iso_context *base, if (!p->skip) { d[0].control = cpu_to_le16(DESCRIPTOR_KEY_IMMEDIATE); d[0].req_count = cpu_to_le16(8); + /* + * Link the skip address to this descriptor itself. This causes + * a context to skip a cycle whenever lost cycles or FIFO + * overruns occur, without dropping the data. The application + * should then decide whether this is an error condition or not. + * FIXME: Make the context's cycle-lost behaviour configurable? + */ + d[0].branch_address = cpu_to_le32(d_bus | z); header = (__le32 *) &d[1]; header[0] = cpu_to_le32(IT_HEADER_SY(p->sy) | diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index cdec32977129..2ac074c8f5d2 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c @@ -405,7 +405,8 @@ struct drm_mm_node *drm_mm_search_free_in_range(const struct drm_mm *mm, wasted += alignment - tmp; } - if (entry->size >= size + wasted) { + if (entry->size >= size + wasted && + (entry->start + wasted + size) <= end) { if (!best_match) return entry; if (entry->size < best_size) { diff --git a/drivers/gpu/drm/radeon/atom.c b/drivers/gpu/drm/radeon/atom.c index e3b44562d265..2a3df5599ab4 100644 --- a/drivers/gpu/drm/radeon/atom.c +++ b/drivers/gpu/drm/radeon/atom.c @@ -24,6 +24,7 @@ #include <linux/module.h> #include <linux/sched.h> +#include <asm/unaligned.h> #define ATOM_DEBUG @@ -212,7 +213,9 @@ static uint32_t atom_get_src_int(atom_exec_context *ctx, uint8_t attr, case ATOM_ARG_PS: idx = U8(*ptr); (*ptr)++; - val = le32_to_cpu(ctx->ps[idx]); + /* get_unaligned_le32 avoids unaligned accesses from atombios + * tables, noticed on a DEC Alpha. */ + val = get_unaligned_le32((u32 *)&ctx->ps[idx]); if (print) DEBUG("PS[0x%02X,0x%04X]", idx, val); break; diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c index b32eeea5bb8b..99915a682d59 100644 --- a/drivers/gpu/drm/radeon/atombios_dp.c +++ b/drivers/gpu/drm/radeon/atombios_dp.c @@ -350,7 +350,7 @@ retry: atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); if (args.ucReplyStatus && !args.ucDataOutLen) { - if (args.ucReplyStatus == 0x20 && retry_count < 10) + if (args.ucReplyStatus == 0x20 && retry_count++ < 10) goto retry; DRM_DEBUG("failed to get auxch %02x%02x %02x %02x 0x%02x %02x after %d retries\n", req_bytes[1], req_bytes[0], req_bytes[2], req_bytes[3], diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 1a3e909b7bba..c7320ce4567d 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -1020,6 +1020,12 @@ static int ttm_bo_mem_compat(struct ttm_placement *placement, struct ttm_mem_reg *mem) { int i; + struct drm_mm_node *node = mem->mm_node; + + if (node && placement->lpfn != 0 && + (node->start < placement->fpfn || + node->start + node->size > placement->lpfn)) + return -1; for (i = 0; i < placement->num_placement; i++) { if ((placement->placement[i] & mem->placement & diff --git a/drivers/hwmon/ams/ams-core.c b/drivers/hwmon/ams/ams-core.c index 6c9ace1b76f6..2ad62c339cd2 100644 --- a/drivers/hwmon/ams/ams-core.c +++ b/drivers/hwmon/ams/ams-core.c @@ -213,7 +213,7 @@ int __init ams_init(void) return -ENODEV; } -void ams_exit(void) +void ams_sensor_detach(void) { /* Remove input device */ ams_input_exit(); @@ -221,9 +221,6 @@ void ams_exit(void) /* Remove attributes */ device_remove_file(&ams_info.of_dev->dev, &dev_attr_current); - /* Shut down implementation */ - ams_info.exit(); - /* Flush interrupt worker * * We do this after ams_info.exit(), because an interrupt might @@ -239,6 +236,12 @@ void ams_exit(void) pmf_unregister_irq_client(&ams_freefall_client); } +static void __exit ams_exit(void) +{ + /* Shut down implementation */ + ams_info.exit(); +} + MODULE_AUTHOR("Stelian Pop, Michael Hanselmann"); MODULE_DESCRIPTION("Apple Motion Sensor driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/hwmon/ams/ams-i2c.c b/drivers/hwmon/ams/ams-i2c.c index 2cbf8a6506c7..abeecd27b484 100644 --- a/drivers/hwmon/ams/ams-i2c.c +++ b/drivers/hwmon/ams/ams-i2c.c @@ -238,6 +238,8 @@ static int ams_i2c_probe(struct i2c_client *client, static int ams_i2c_remove(struct i2c_client *client) { if (ams_info.has_device) { + ams_sensor_detach(); + /* Disable interrupts */ ams_i2c_set_irq(AMS_IRQ_ALL, 0); diff --git a/drivers/hwmon/ams/ams-pmu.c b/drivers/hwmon/ams/ams-pmu.c index fb18b3d3162b..4f61b3ee1b08 100644 --- a/drivers/hwmon/ams/ams-pmu.c +++ b/drivers/hwmon/ams/ams-pmu.c @@ -133,6 +133,8 @@ static void ams_pmu_get_xyz(s8 *x, s8 *y, s8 *z) static void ams_pmu_exit(void) { + ams_sensor_detach(); + /* Disable interrupts */ ams_pmu_set_irq(AMS_IRQ_ALL, 0); diff --git a/drivers/hwmon/ams/ams.h b/drivers/hwmon/ams/ams.h index 5ed387b0bd9a..b28d7e27a031 100644 --- a/drivers/hwmon/ams/ams.h +++ b/drivers/hwmon/ams/ams.h @@ -61,6 +61,7 @@ extern struct ams ams_info; extern void ams_sensors(s8 *x, s8 *y, s8 *z); extern int ams_sensor_attach(void); +extern void ams_sensor_detach(void); extern int ams_pmu_init(struct device_node *np); extern int ams_i2c_init(struct device_node *np); diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c index 5ff47ba7f2d0..c42eeb43042d 100644 --- a/drivers/macintosh/therm_adt746x.c +++ b/drivers/macintosh/therm_adt746x.c @@ -90,6 +90,8 @@ static struct task_struct *thread_therm = NULL; static void write_both_fan_speed(struct thermostat *th, int speed); static void write_fan_speed(struct thermostat *th, int speed, int fan); +static void thermostat_create_files(void); +static void thermostat_remove_files(void); static int write_reg(struct thermostat* th, int reg, u8 data) @@ -161,6 +163,8 @@ remove_thermostat(struct i2c_client *client) struct thermostat *th = i2c_get_clientdata(client); int i; + thermostat_remove_files(); + if (thread_therm != NULL) { kthread_stop(thread_therm); } @@ -312,7 +316,7 @@ static void update_fans_speed (struct thermostat *th) if (verbose) printk(KERN_DEBUG "adt746x: Setting fans speed to %d " - "(limit exceeded by %d on %s) \n", + "(limit exceeded by %d on %s)\n", new_speed, var, sensor_location[fan_number+1]); write_both_fan_speed(th, new_speed); @@ -449,6 +453,8 @@ static int probe_thermostat(struct i2c_client *client, return -ENOMEM; } + thermostat_create_files(); + return 0; } @@ -566,7 +572,6 @@ thermostat_init(void) struct device_node* np; const u32 *prop; int i = 0, offset = 0; - int err; np = of_find_node_by_name(NULL, "fan"); if (!np) @@ -633,6 +638,17 @@ thermostat_init(void) return -ENODEV; } +#ifndef CONFIG_I2C_POWERMAC + request_module("i2c-powermac"); +#endif + + return i2c_add_driver(&thermostat_driver); +} + +static void thermostat_create_files(void) +{ + int err; + err = device_create_file(&of_dev->dev, &dev_attr_sensor1_temperature); err |= device_create_file(&of_dev->dev, &dev_attr_sensor2_temperature); err |= device_create_file(&of_dev->dev, &dev_attr_sensor1_limit); @@ -647,16 +663,9 @@ thermostat_init(void) if (err) printk(KERN_WARNING "Failed to create tempertaure attribute file(s).\n"); - -#ifndef CONFIG_I2C_POWERMAC - request_module("i2c-powermac"); -#endif - - return i2c_add_driver(&thermostat_driver); } -static void __exit -thermostat_exit(void) +static void thermostat_remove_files(void) { if (of_dev) { device_remove_file(&of_dev->dev, &dev_attr_sensor1_temperature); @@ -673,9 +682,14 @@ thermostat_exit(void) device_remove_file(&of_dev->dev, &dev_attr_sensor2_fan_speed); - of_device_unregister(of_dev); } +} + +static void __exit +thermostat_exit(void) +{ i2c_del_driver(&thermostat_driver); + of_device_unregister(of_dev); } module_init(thermostat_init); diff --git a/drivers/md/dm-log-userspace-transfer.c b/drivers/md/dm-log-userspace-transfer.c index 54abf9e303b7..f1c8cae70b4b 100644 --- a/drivers/md/dm-log-userspace-transfer.c +++ b/drivers/md/dm-log-userspace-transfer.c @@ -172,11 +172,15 @@ int dm_consult_userspace(const char *uuid, uint64_t luid, int request_type, { int r = 0; size_t dummy = 0; - int overhead_size = - sizeof(struct dm_ulog_request *) + sizeof(struct cn_msg); + int overhead_size = sizeof(struct dm_ulog_request) + sizeof(struct cn_msg); struct dm_ulog_request *tfr = prealloced_ulog_tfr; struct receiving_pkg pkg; + /* + * Given the space needed to hold the 'struct cn_msg' and + * 'struct dm_ulog_request' - do we have enough payload + * space remaining? + */ if (data_size > (DM_ULOG_PREALLOCED_SIZE - overhead_size)) { DMINFO("Size of tfr exceeds preallocated size"); return -EINVAL; @@ -191,7 +195,7 @@ resend: */ mutex_lock(&dm_ulog_lock); - memset(tfr, 0, DM_ULOG_PREALLOCED_SIZE - overhead_size); + memset(tfr, 0, DM_ULOG_PREALLOCED_SIZE - sizeof(struct cn_msg)); memcpy(tfr->uuid, uuid, DM_UUID_LEN); tfr->luid = luid; tfr->seq = dm_ulog_seq++; diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index ad779bd13aec..6c1046df81f6 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c @@ -724,7 +724,7 @@ static void do_writes(struct mirror_set *ms, struct bio_list *writes) /* * Dispatch io. */ - if (unlikely(ms->log_failure)) { + if (unlikely(ms->log_failure) && errors_handled(ms)) { spin_lock_irq(&ms->lock); bio_list_merge(&ms->failures, &sync); spin_unlock_irq(&ms->lock); diff --git a/drivers/md/dm-region-hash.c b/drivers/md/dm-region-hash.c index 5f19ceb6fe91..168bd38f5006 100644 --- a/drivers/md/dm-region-hash.c +++ b/drivers/md/dm-region-hash.c @@ -660,10 +660,9 @@ void dm_rh_recovery_end(struct dm_region *reg, int success) spin_lock_irq(&rh->region_lock); if (success) list_add(®->list, ®->rh->recovered_regions); - else { - reg->state = DM_RH_NOSYNC; + else list_add(®->list, ®->rh->failed_recovered_regions); - } + spin_unlock_irq(&rh->region_lock); rh->wakeup_workers(rh->context); diff --git a/drivers/md/dm-snap-persistent.c b/drivers/md/dm-snap-persistent.c index 7d08879689ac..c097d8a4823d 100644 --- a/drivers/md/dm-snap-persistent.c +++ b/drivers/md/dm-snap-persistent.c @@ -254,7 +254,7 @@ static int chunk_io(struct pstore *ps, void *area, chunk_t chunk, int rw, * Issue the synchronous I/O from a different thread * to avoid generic_make_request recursion. */ - INIT_WORK(&req.work, do_metadata); + INIT_WORK_ON_STACK(&req.work, do_metadata); queue_work(ps->metadata_wq, &req.work); flush_workqueue(ps->metadata_wq); diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c index e0efc1adcaff..bd58703ee8f6 100644 --- a/drivers/md/dm-stripe.c +++ b/drivers/md/dm-stripe.c @@ -110,7 +110,7 @@ static int stripe_ctr(struct dm_target *ti, unsigned int argc, char **argv) } stripes = simple_strtoul(argv[0], &end, 10); - if (*end) { + if (!stripes || *end) { ti->error = "Invalid stripe count"; return -EINVAL; } diff --git a/drivers/md/dm-sysfs.c b/drivers/md/dm-sysfs.c index f53392df7b97..f91b40942e07 100644 --- a/drivers/md/dm-sysfs.c +++ b/drivers/md/dm-sysfs.c @@ -80,20 +80,12 @@ static struct sysfs_ops dm_sysfs_ops = { }; /* - * The sysfs structure is embedded in md struct, nothing to do here - */ -static void dm_sysfs_release(struct kobject *kobj) -{ -} - -/* * dm kobject is embedded in mapped_device structure * no need to define release function here */ static struct kobj_type dm_ktype = { .sysfs_ops = &dm_sysfs_ops, .default_attrs = dm_attrs, - .release = dm_sysfs_release }; /* diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 3167480b532c..aa4e2aa86d49 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -1595,10 +1595,15 @@ static int dm_prep_fn(struct request_queue *q, struct request *rq) return BLKPREP_OK; } -static void map_request(struct dm_target *ti, struct request *clone, - struct mapped_device *md) +/* + * Returns: + * 0 : the request has been processed (not requeued) + * !0 : the request has been requeued + */ +static int map_request(struct dm_target *ti, struct request *clone, + struct mapped_device *md) { - int r; + int r, requeued = 0; struct dm_rq_target_io *tio = clone->end_io_data; /* @@ -1625,6 +1630,7 @@ static void map_request(struct dm_target *ti, struct request *clone, case DM_MAPIO_REQUEUE: /* The target wants to requeue the I/O */ dm_requeue_unmapped_request(clone); + requeued = 1; break; default: if (r > 0) { @@ -1636,6 +1642,8 @@ static void map_request(struct dm_target *ti, struct request *clone, dm_kill_unmapped_request(clone, r); break; } + + return requeued; } /* @@ -1677,12 +1685,17 @@ static void dm_request_fn(struct request_queue *q) atomic_inc(&md->pending[rq_data_dir(clone)]); spin_unlock(q->queue_lock); - map_request(ti, clone, md); + if (map_request(ti, clone, md)) + goto requeued; + spin_lock_irq(q->queue_lock); } goto out; +requeued: + spin_lock_irq(q->queue_lock); + plug_and_out: if (!elv_queue_empty(q)) /* Some requests still remain, retry later */ diff --git a/drivers/ps3/ps3av.c b/drivers/ps3/ps3av.c index e82d8c9c6cda..95a689befc84 100644 --- a/drivers/ps3/ps3av.c +++ b/drivers/ps3/ps3av.c @@ -532,7 +532,7 @@ static void ps3av_set_videomode_packet(u32 id) res = ps3av_cmd_avb_param(&avb_param, len); if (res == PS3AV_STATUS_NO_SYNC_HEAD) printk(KERN_WARNING - "%s: Command failed. Please try your request again. \n", + "%s: Command failed. Please try your request again.\n", __func__); else if (res) dev_dbg(&ps3av->dev->core, "ps3av_cmd_avb_param failed\n"); |