Commit 498d319b authored by Stefani Seibold's avatar Stefani Seibold Committed by Linus Torvalds

kfifo API type safety

This patch enhances the type safety for the kfifo API.  It is now safe
to put const data into a non const FIFO and the API will now generate a
compiler warning when reading from the fifo where the destination
address is pointing to a const variable.

As a side effect the kfifo_put() does now expect the value of an element
instead a pointer to the element.  This was suggested Russell King.  It
make the handling of the kfifo_put easier since there is no need to
create a helper variable for getting the address of a pointer or to pass
integers of different sizes.

IMHO the API break is okay, since there are currently only six users of
kfifo_put().

The code is also cleaner by kicking out the "if (0)" expressions.

[akpm@linux-foundation.org: coding-style fixes]
Signed-off-by: default avatarStefani Seibold <stefani@seibold.net>
Cc: Russell King <rmk@arm.linux.org.uk>
Cc: Hauke Mehrtens <hauke@hauke-m.de>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent a019e48c
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
*/ */
void drm_flip_work_queue(struct drm_flip_work *work, void *val) void drm_flip_work_queue(struct drm_flip_work *work, void *val)
{ {
if (kfifo_put(&work->fifo, (const void **)&val)) { if (kfifo_put(&work->fifo, val)) {
atomic_inc(&work->pending); atomic_inc(&work->pending);
} else { } else {
DRM_ERROR("%s fifo full!\n", work->name); DRM_ERROR("%s fifo full!\n", work->name);
......
...@@ -56,7 +56,7 @@ int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp) ...@@ -56,7 +56,7 @@ int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp)
ev.id = ev_code; ev.id = ev_code;
ev.timestamp = timestamp; ev.timestamp = timestamp;
copied = kfifo_put(&ev_int->det_events, &ev); copied = kfifo_put(&ev_int->det_events, ev);
if (copied != 0) if (copied != 0)
wake_up_locked_poll(&ev_int->wait, POLLIN); wake_up_locked_poll(&ev_int->wait, POLLIN);
} }
......
...@@ -446,7 +446,7 @@ static void rt2800mmio_txstatus_interrupt(struct rt2x00_dev *rt2x00dev) ...@@ -446,7 +446,7 @@ static void rt2800mmio_txstatus_interrupt(struct rt2x00_dev *rt2x00dev)
if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID)) if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID))
break; break;
if (!kfifo_put(&rt2x00dev->txstatus_fifo, &status)) { if (!kfifo_put(&rt2x00dev->txstatus_fifo, status)) {
rt2x00_warn(rt2x00dev, "TX status FIFO overrun, drop tx status report\n"); rt2x00_warn(rt2x00dev, "TX status FIFO overrun, drop tx status report\n");
break; break;
} }
......
...@@ -164,7 +164,7 @@ static bool rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev, ...@@ -164,7 +164,7 @@ static bool rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev,
valid = rt2x00_get_field32(tx_status, TX_STA_FIFO_VALID); valid = rt2x00_get_field32(tx_status, TX_STA_FIFO_VALID);
if (valid) { if (valid) {
if (!kfifo_put(&rt2x00dev->txstatus_fifo, &tx_status)) if (!kfifo_put(&rt2x00dev->txstatus_fifo, tx_status))
rt2x00_warn(rt2x00dev, "TX status FIFO overrun\n"); rt2x00_warn(rt2x00dev, "TX status FIFO overrun\n");
queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work); queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
......
...@@ -574,7 +574,7 @@ void aer_recover_queue(int domain, unsigned int bus, unsigned int devfn, ...@@ -574,7 +574,7 @@ void aer_recover_queue(int domain, unsigned int bus, unsigned int devfn,
}; };
spin_lock_irqsave(&aer_recover_ring_lock, flags); spin_lock_irqsave(&aer_recover_ring_lock, flags);
if (kfifo_put(&aer_recover_ring, &entry)) if (kfifo_put(&aer_recover_ring, entry))
schedule_work(&aer_recover_work); schedule_work(&aer_recover_work);
else else
pr_err("AER recover: Buffer overflow when recovering AER for %04x:%02x:%02x:%x\n", pr_err("AER recover: Buffer overflow when recovering AER for %04x:%02x:%02x:%x\n",
......
/* /*
* A generic kernel FIFO implementation * A generic kernel FIFO implementation
* *
* Copyright (C) 2009/2010 Stefani Seibold <stefani@seibold.net> * Copyright (C) 2013 Stefani Seibold <stefani@seibold.net>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -67,9 +67,10 @@ struct __kfifo { ...@@ -67,9 +67,10 @@ struct __kfifo {
union { \ union { \
struct __kfifo kfifo; \ struct __kfifo kfifo; \
datatype *type; \ datatype *type; \
const datatype *const_type; \
char (*rectype)[recsize]; \ char (*rectype)[recsize]; \
ptrtype *ptr; \ ptrtype *ptr; \
const ptrtype *ptr_const; \ ptrtype const *ptr_const; \
} }
#define __STRUCT_KFIFO(type, size, recsize, ptrtype) \ #define __STRUCT_KFIFO(type, size, recsize, ptrtype) \
...@@ -386,16 +387,12 @@ __kfifo_int_must_check_helper( \ ...@@ -386,16 +387,12 @@ __kfifo_int_must_check_helper( \
#define kfifo_put(fifo, val) \ #define kfifo_put(fifo, val) \
({ \ ({ \
typeof((fifo) + 1) __tmp = (fifo); \ typeof((fifo) + 1) __tmp = (fifo); \
typeof((val) + 1) __val = (val); \ typeof(*__tmp->const_type) __val = (val); \
unsigned int __ret; \ unsigned int __ret; \
const size_t __recsize = sizeof(*__tmp->rectype); \ size_t __recsize = sizeof(*__tmp->rectype); \
struct __kfifo *__kfifo = &__tmp->kfifo; \ struct __kfifo *__kfifo = &__tmp->kfifo; \
if (0) { \
typeof(__tmp->ptr_const) __dummy __attribute__ ((unused)); \
__dummy = (typeof(__val))NULL; \
} \
if (__recsize) \ if (__recsize) \
__ret = __kfifo_in_r(__kfifo, __val, sizeof(*__val), \ __ret = __kfifo_in_r(__kfifo, &__val, sizeof(__val), \
__recsize); \ __recsize); \
else { \ else { \
__ret = !kfifo_is_full(__tmp); \ __ret = !kfifo_is_full(__tmp); \
...@@ -404,7 +401,7 @@ __kfifo_int_must_check_helper( \ ...@@ -404,7 +401,7 @@ __kfifo_int_must_check_helper( \
((typeof(__tmp->type))__kfifo->data) : \ ((typeof(__tmp->type))__kfifo->data) : \
(__tmp->buf) \ (__tmp->buf) \
)[__kfifo->in & __tmp->kfifo.mask] = \ )[__kfifo->in & __tmp->kfifo.mask] = \
*(typeof(__tmp->type))__val; \ (typeof(*__tmp->type))__val; \
smp_wmb(); \ smp_wmb(); \
__kfifo->in++; \ __kfifo->in++; \
} \ } \
...@@ -415,7 +412,7 @@ __kfifo_int_must_check_helper( \ ...@@ -415,7 +412,7 @@ __kfifo_int_must_check_helper( \
/** /**
* kfifo_get - get data from the fifo * kfifo_get - get data from the fifo
* @fifo: address of the fifo to be used * @fifo: address of the fifo to be used
* @val: the var where to store the data to be added * @val: address where to store the data
* *
* This macro reads the data from the fifo. * This macro reads the data from the fifo.
* It returns 0 if the fifo was empty. Otherwise it returns the number * It returns 0 if the fifo was empty. Otherwise it returns the number
...@@ -428,12 +425,10 @@ __kfifo_int_must_check_helper( \ ...@@ -428,12 +425,10 @@ __kfifo_int_must_check_helper( \
__kfifo_uint_must_check_helper( \ __kfifo_uint_must_check_helper( \
({ \ ({ \
typeof((fifo) + 1) __tmp = (fifo); \ typeof((fifo) + 1) __tmp = (fifo); \
typeof((val) + 1) __val = (val); \ typeof(__tmp->ptr) __val = (val); \
unsigned int __ret; \ unsigned int __ret; \
const size_t __recsize = sizeof(*__tmp->rectype); \ const size_t __recsize = sizeof(*__tmp->rectype); \
struct __kfifo *__kfifo = &__tmp->kfifo; \ struct __kfifo *__kfifo = &__tmp->kfifo; \
if (0) \
__val = (typeof(__tmp->ptr))0; \
if (__recsize) \ if (__recsize) \
__ret = __kfifo_out_r(__kfifo, __val, sizeof(*__val), \ __ret = __kfifo_out_r(__kfifo, __val, sizeof(*__val), \
__recsize); \ __recsize); \
...@@ -456,7 +451,7 @@ __kfifo_uint_must_check_helper( \ ...@@ -456,7 +451,7 @@ __kfifo_uint_must_check_helper( \
/** /**
* kfifo_peek - get data from the fifo without removing * kfifo_peek - get data from the fifo without removing
* @fifo: address of the fifo to be used * @fifo: address of the fifo to be used
* @val: the var where to store the data to be added * @val: address where to store the data
* *
* This reads the data from the fifo without removing it from the fifo. * This reads the data from the fifo without removing it from the fifo.
* It returns 0 if the fifo was empty. Otherwise it returns the number * It returns 0 if the fifo was empty. Otherwise it returns the number
...@@ -469,12 +464,10 @@ __kfifo_uint_must_check_helper( \ ...@@ -469,12 +464,10 @@ __kfifo_uint_must_check_helper( \
__kfifo_uint_must_check_helper( \ __kfifo_uint_must_check_helper( \
({ \ ({ \
typeof((fifo) + 1) __tmp = (fifo); \ typeof((fifo) + 1) __tmp = (fifo); \
typeof((val) + 1) __val = (val); \ typeof(__tmp->ptr) __val = (val); \
unsigned int __ret; \ unsigned int __ret; \
const size_t __recsize = sizeof(*__tmp->rectype); \ const size_t __recsize = sizeof(*__tmp->rectype); \
struct __kfifo *__kfifo = &__tmp->kfifo; \ struct __kfifo *__kfifo = &__tmp->kfifo; \
if (0) \
__val = (typeof(__tmp->ptr))NULL; \
if (__recsize) \ if (__recsize) \
__ret = __kfifo_out_peek_r(__kfifo, __val, sizeof(*__val), \ __ret = __kfifo_out_peek_r(__kfifo, __val, sizeof(*__val), \
__recsize); \ __recsize); \
...@@ -508,14 +501,10 @@ __kfifo_uint_must_check_helper( \ ...@@ -508,14 +501,10 @@ __kfifo_uint_must_check_helper( \
#define kfifo_in(fifo, buf, n) \ #define kfifo_in(fifo, buf, n) \
({ \ ({ \
typeof((fifo) + 1) __tmp = (fifo); \ typeof((fifo) + 1) __tmp = (fifo); \
typeof((buf) + 1) __buf = (buf); \ typeof(__tmp->ptr_const) __buf = (buf); \
unsigned long __n = (n); \ unsigned long __n = (n); \
const size_t __recsize = sizeof(*__tmp->rectype); \ const size_t __recsize = sizeof(*__tmp->rectype); \
struct __kfifo *__kfifo = &__tmp->kfifo; \ struct __kfifo *__kfifo = &__tmp->kfifo; \
if (0) { \
typeof(__tmp->ptr_const) __dummy __attribute__ ((unused)); \
__dummy = (typeof(__buf))NULL; \
} \
(__recsize) ?\ (__recsize) ?\
__kfifo_in_r(__kfifo, __buf, __n, __recsize) : \ __kfifo_in_r(__kfifo, __buf, __n, __recsize) : \
__kfifo_in(__kfifo, __buf, __n); \ __kfifo_in(__kfifo, __buf, __n); \
...@@ -561,14 +550,10 @@ __kfifo_uint_must_check_helper( \ ...@@ -561,14 +550,10 @@ __kfifo_uint_must_check_helper( \
__kfifo_uint_must_check_helper( \ __kfifo_uint_must_check_helper( \
({ \ ({ \
typeof((fifo) + 1) __tmp = (fifo); \ typeof((fifo) + 1) __tmp = (fifo); \
typeof((buf) + 1) __buf = (buf); \ typeof(__tmp->ptr) __buf = (buf); \
unsigned long __n = (n); \ unsigned long __n = (n); \
const size_t __recsize = sizeof(*__tmp->rectype); \ const size_t __recsize = sizeof(*__tmp->rectype); \
struct __kfifo *__kfifo = &__tmp->kfifo; \ struct __kfifo *__kfifo = &__tmp->kfifo; \
if (0) { \
typeof(__tmp->ptr) __dummy = NULL; \
__buf = __dummy; \
} \
(__recsize) ?\ (__recsize) ?\
__kfifo_out_r(__kfifo, __buf, __n, __recsize) : \ __kfifo_out_r(__kfifo, __buf, __n, __recsize) : \
__kfifo_out(__kfifo, __buf, __n); \ __kfifo_out(__kfifo, __buf, __n); \
...@@ -773,14 +758,10 @@ __kfifo_uint_must_check_helper( \ ...@@ -773,14 +758,10 @@ __kfifo_uint_must_check_helper( \
__kfifo_uint_must_check_helper( \ __kfifo_uint_must_check_helper( \
({ \ ({ \
typeof((fifo) + 1) __tmp = (fifo); \ typeof((fifo) + 1) __tmp = (fifo); \
typeof((buf) + 1) __buf = (buf); \ typeof(__tmp->ptr) __buf = (buf); \
unsigned long __n = (n); \ unsigned long __n = (n); \
const size_t __recsize = sizeof(*__tmp->rectype); \ const size_t __recsize = sizeof(*__tmp->rectype); \
struct __kfifo *__kfifo = &__tmp->kfifo; \ struct __kfifo *__kfifo = &__tmp->kfifo; \
if (0) { \
typeof(__tmp->ptr) __dummy __attribute__ ((unused)) = NULL; \
__buf = __dummy; \
} \
(__recsize) ? \ (__recsize) ? \
__kfifo_out_peek_r(__kfifo, __buf, __n, __recsize) : \ __kfifo_out_peek_r(__kfifo, __buf, __n, __recsize) : \
__kfifo_out_peek(__kfifo, __buf, __n); \ __kfifo_out_peek(__kfifo, __buf, __n); \
......
...@@ -1269,7 +1269,7 @@ void memory_failure_queue(unsigned long pfn, int trapno, int flags) ...@@ -1269,7 +1269,7 @@ void memory_failure_queue(unsigned long pfn, int trapno, int flags)
mf_cpu = &get_cpu_var(memory_failure_cpu); mf_cpu = &get_cpu_var(memory_failure_cpu);
spin_lock_irqsave(&mf_cpu->lock, proc_flags); spin_lock_irqsave(&mf_cpu->lock, proc_flags);
if (kfifo_put(&mf_cpu->fifo, &entry)) if (kfifo_put(&mf_cpu->fifo, entry))
schedule_work_on(smp_processor_id(), &mf_cpu->work); schedule_work_on(smp_processor_id(), &mf_cpu->work);
else else
pr_err("Memory failure: buffer overflow when queuing memory failure at %#lx\n", pr_err("Memory failure: buffer overflow when queuing memory failure at %#lx\n",
......
...@@ -64,7 +64,7 @@ static int __init testfunc(void) ...@@ -64,7 +64,7 @@ static int __init testfunc(void)
/* put values into the fifo */ /* put values into the fifo */
for (i = 0; i != 10; i++) for (i = 0; i != 10; i++)
kfifo_put(&test, &i); kfifo_put(&test, i);
/* show the number of used elements */ /* show the number of used elements */
printk(KERN_INFO "fifo len: %u\n", kfifo_len(&test)); printk(KERN_INFO "fifo len: %u\n", kfifo_len(&test));
...@@ -85,7 +85,7 @@ static int __init testfunc(void) ...@@ -85,7 +85,7 @@ static int __init testfunc(void)
kfifo_skip(&test); kfifo_skip(&test);
/* put values into the fifo until is full */ /* put values into the fifo until is full */
for (i = 20; kfifo_put(&test, &i); i++) for (i = 20; kfifo_put(&test, i); i++)
; ;
printk(KERN_INFO "queue len: %u\n", kfifo_len(&test)); printk(KERN_INFO "queue len: %u\n", kfifo_len(&test));
......
...@@ -39,7 +39,7 @@ static int __init example_init(void) ...@@ -39,7 +39,7 @@ static int __init example_init(void)
kfifo_in(&fifo, "test", 4); kfifo_in(&fifo, "test", 4);
for (i = 0; i != 9; i++) for (i = 0; i != 9; i++)
kfifo_put(&fifo, &i); kfifo_put(&fifo, i);
/* kick away first byte */ /* kick away first byte */
kfifo_skip(&fifo); kfifo_skip(&fifo);
......
...@@ -61,7 +61,7 @@ static int __init testfunc(void) ...@@ -61,7 +61,7 @@ static int __init testfunc(void)
/* put values into the fifo */ /* put values into the fifo */
for (i = 0; i != 10; i++) for (i = 0; i != 10; i++)
kfifo_put(&test, &i); kfifo_put(&test, i);
/* show the number of used elements */ /* show the number of used elements */
printk(KERN_INFO "fifo len: %u\n", kfifo_len(&test)); printk(KERN_INFO "fifo len: %u\n", kfifo_len(&test));
...@@ -78,7 +78,7 @@ static int __init testfunc(void) ...@@ -78,7 +78,7 @@ static int __init testfunc(void)
kfifo_skip(&test); kfifo_skip(&test);
/* put values into the fifo until is full */ /* put values into the fifo until is full */
for (i = 20; kfifo_put(&test, &i); i++) for (i = 20; kfifo_put(&test, i); i++)
; ;
printk(KERN_INFO "queue len: %u\n", kfifo_len(&test)); printk(KERN_INFO "queue len: %u\n", kfifo_len(&test));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment