2013-01-08 14:57:26

by Yuanhan Liu

[permalink] [raw]
Subject: [PATCH 5/5] kfifo: log based kfifo API

The current kfifo API take the kfifo size as input, while it rounds
_down_ the size to power of 2 at __kfifo_alloc. This may introduce
potential issue.

Take the code at drivers/hid/hid-logitech-dj.c as example:

if (kfifo_alloc(&djrcv_dev->notif_fifo,
DJ_MAX_NUMBER_NOTIFICATIONS * sizeof(struct dj_report),
GFP_KERNEL)) {

Where, DJ_MAX_NUMBER_NOTIFICATIONS is 8, and sizeo of(struct dj_report)
is 15.

Which means it wants to allocate a kfifo buffer which can store 8
dj_report entries at once. The expected kfifo buffer size would be
8 * 15 = 120 then. While, in the end, __kfifo_alloc will turn the
size to rounddown_power_of_2(120) = 64, and then allocate a buf
with 64 bytes, which I don't think this is the original author want.

With the new log API, we can do like following:

int kfifo_size_order = order_base_2(DJ_MAX_NUMBER_NOTIFICATIONS *
sizeof(struct dj_report));

if (kfifo_alloc(&djrcv_dev->notif_fifo, kfifo_size_order, GFP_KERNEL)) {

This make sure we will allocate enough kfifo buffer for holding
DJ_MAX_NUMBER_NOTIFICATIONS dj_report entries.

Cc: Stefani Seibold <[email protected]>
Cc: Andrew Morton <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Signed-off-by: Yuanhan Liu <[email protected]>
---
arch/arm/plat-omap/Kconfig | 2 +-
arch/arm/plat-omap/mailbox.c | 6 +++-
arch/powerpc/sysdev/fsl_rmu.c | 2 +-
drivers/char/sonypi.c | 9 ++++---
drivers/hid/hid-logitech-dj.c | 7 +++--
drivers/iio/industrialio-event.c | 2 +-
drivers/iio/kfifo_buf.c | 3 +-
drivers/infiniband/hw/cxgb3/cxio_resource.c | 8 ++++--
drivers/media/i2c/cx25840/cx25840-ir.c | 9 +++++--
drivers/media/pci/cx23885/cx23888-ir.c | 9 +++++--
drivers/media/pci/meye/meye.c | 6 +---
drivers/media/pci/meye/meye.h | 2 +
drivers/media/rc/ir-raw.c | 7 +++--
drivers/memstick/host/r592.h | 2 +-
drivers/mmc/card/sdio_uart.c | 4 ++-
drivers/mtd/sm_ftl.c | 5 +++-
drivers/net/wireless/libertas/main.c | 4 ++-
drivers/net/wireless/rt2x00/rt2x00dev.c | 5 +--
drivers/pci/pcie/aer/aerdrv_core.c | 3 +-
drivers/platform/x86/fujitsu-laptop.c | 5 ++-
drivers/platform/x86/sony-laptop.c | 6 ++--
drivers/rapidio/devices/tsi721.c | 5 ++-
drivers/scsi/libiscsi_tcp.c | 6 +++-
drivers/staging/omapdrm/omap_plane.c | 5 +++-
drivers/tty/n_gsm.c | 4 ++-
drivers/tty/nozomi.c | 5 +--
drivers/tty/serial/ifx6x60.c | 2 +-
drivers/tty/serial/ifx6x60.h | 3 +-
drivers/tty/serial/kgdb_nmi.c | 7 +++--
drivers/usb/host/fhci.h | 4 ++-
drivers/usb/serial/cypress_m8.c | 4 +-
drivers/usb/serial/io_ti.c | 4 +-
drivers/usb/serial/ti_usb_3410_5052.c | 7 +++--
drivers/usb/serial/usb-serial.c | 2 +-
include/linux/kfifo.h | 31 +++++++++++++--------------
include/linux/rio.h | 1 +
include/media/lirc_dev.h | 4 ++-
kernel/kfifo.c | 9 +------
mm/memory-failure.c | 3 +-
net/dccp/probe.c | 6 +++-
net/sctp/probe.c | 6 +++-
samples/kfifo/bytestream-example.c | 8 +++---
samples/kfifo/dma-example.c | 5 ++-
samples/kfifo/inttype-example.c | 7 +++--
samples/kfifo/record-example.c | 6 ++--
45 files changed, 142 insertions(+), 108 deletions(-)

diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index 665870d..7eda02c 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -124,7 +124,7 @@ config OMAP_MBOX_FWK
DSP, IVA1.0 and IVA2 in OMAP1/2/3.

config OMAP_MBOX_KFIFO_SIZE
- int "Mailbox kfifo default buffer size (bytes)"
+ int "Mailbox kfifo default buffer size (bytes, should be power of 2. If not, will roundup to power of 2"
depends on OMAP_MBOX_FWK
default 256
help
diff --git a/arch/arm/plat-omap/mailbox.c b/arch/arm/plat-omap/mailbox.c
index 42377ef..848fa0b 100644
--- a/arch/arm/plat-omap/mailbox.c
+++ b/arch/arm/plat-omap/mailbox.c
@@ -30,6 +30,7 @@
#include <linux/err.h>
#include <linux/notifier.h>
#include <linux/module.h>
+#include <linux/log2.h>

#include <plat/mailbox.h>

@@ -40,7 +41,7 @@ static DEFINE_MUTEX(mbox_configured_lock);

static unsigned int mbox_kfifo_size = CONFIG_OMAP_MBOX_KFIFO_SIZE;
module_param(mbox_kfifo_size, uint, S_IRUGO);
-MODULE_PARM_DESC(mbox_kfifo_size, "Size of omap's mailbox kfifo (bytes)");
+MODULE_PARM_DESC(mbox_kfifo_size, "Size of omap's mailbox kfifo (bytes, should be power of 2. If not, will roundup to power of 2)");

/* Mailbox FIFO handle functions */
static inline mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox)
@@ -218,6 +219,7 @@ static struct omap_mbox_queue *mbox_queue_alloc(struct omap_mbox *mbox,
void (*tasklet)(unsigned long))
{
struct omap_mbox_queue *mq;
+ int mbox_kfifo_size_order = order_base_2(mbox_kfifo_size);

mq = kzalloc(sizeof(struct omap_mbox_queue), GFP_KERNEL);
if (!mq)
@@ -225,7 +227,7 @@ static struct omap_mbox_queue *mbox_queue_alloc(struct omap_mbox *mbox,

spin_lock_init(&mq->lock);

- if (kfifo_alloc(&mq->fifo, mbox_kfifo_size, GFP_KERNEL))
+ if (kfifo_alloc(&mq->fifo, mbox_kfifo_size_order, GFP_KERNEL))
goto error;

if (work)
diff --git a/arch/powerpc/sysdev/fsl_rmu.c b/arch/powerpc/sysdev/fsl_rmu.c
index 14bd522..84d2b8c 100644
--- a/arch/powerpc/sysdev/fsl_rmu.c
+++ b/arch/powerpc/sysdev/fsl_rmu.c
@@ -587,7 +587,7 @@ int fsl_rio_port_write_init(struct fsl_rio_pw *pw)

INIT_WORK(&pw->pw_work, fsl_pw_dpc);
spin_lock_init(&pw->pw_fifo_lock);
- if (kfifo_alloc(&pw->pw_fifo, RIO_PW_MSG_SIZE * 32, GFP_KERNEL)) {
+ if (kfifo_alloc(&pw->pw_fifo, RIO_KFIFO_SIZE_ORDER, GFP_KERNEL)) {
pr_err("FIFO allocation failed\n");
rc = -ENOMEM;
goto err_out_irq;
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
index d780295..39d8dd7 100644
--- a/drivers/char/sonypi.c
+++ b/drivers/char/sonypi.c
@@ -429,7 +429,7 @@ static struct sonypi_eventtypes {
{ 0 }
};

-#define SONYPI_BUF_SIZE 128
+#define SONYPI_KFIFO_SIZE_ORDER 7

/* Correspondance table between sonypi events and input layer events */
static struct {
@@ -1316,7 +1316,8 @@ static int sonypi_probe(struct platform_device *dev)
"http://www.linux.it/~malattia/wiki/index.php/Sony_drivers\n");

spin_lock_init(&sonypi_device.fifo_lock);
- error = kfifo_alloc(&sonypi_device.fifo, SONYPI_BUF_SIZE, GFP_KERNEL);
+ error = kfifo_alloc(&sonypi_device.fifo, SONYPI_KFIFO_SIZE_ORDER,
+ GFP_KERNEL);
if (error) {
printk(KERN_ERR "sonypi: kfifo_alloc failed\n");
return error;
@@ -1395,8 +1396,8 @@ static int sonypi_probe(struct platform_device *dev)
}

spin_lock_init(&sonypi_device.input_fifo_lock);
- error = kfifo_alloc(&sonypi_device.input_fifo, SONYPI_BUF_SIZE,
- GFP_KERNEL);
+ error = kfifo_alloc(&sonypi_device.input_fifo,
+ SONYPI_KFIFO_SIZE_ORDER, GFP_KERNEL);
if (error) {
printk(KERN_ERR "sonypi: kfifo_alloc failed\n");
goto err_inpdev_unregister;
diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c
index 9500f2f..031be77 100644
--- a/drivers/hid/hid-logitech-dj.c
+++ b/drivers/hid/hid-logitech-dj.c
@@ -26,6 +26,7 @@
#include <linux/hid.h>
#include <linux/module.h>
#include <linux/usb.h>
+#include <linux/log2.h>
#include <asm/unaligned.h>
#include "usbhid/usbhid.h"
#include "hid-ids.h"
@@ -730,6 +731,8 @@ static int logi_dj_probe(struct hid_device *hdev,
struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
struct dj_receiver_dev *djrcv_dev;
int retval;
+ int kfifo_size_order = order_base_2(DJ_MAX_NUMBER_NOTIFICATIONS *
+ sizeof(struct dj_report));

if (is_dj_device((struct dj_device *)hdev->driver_data))
return -ENODEV;
@@ -757,9 +760,7 @@ static int logi_dj_probe(struct hid_device *hdev,
djrcv_dev->hdev = hdev;
INIT_WORK(&djrcv_dev->work, delayedwork_callback);
spin_lock_init(&djrcv_dev->lock);
- if (kfifo_alloc(&djrcv_dev->notif_fifo,
- DJ_MAX_NUMBER_NOTIFICATIONS * sizeof(struct dj_report),
- GFP_KERNEL)) {
+ if (kfifo_alloc(&djrcv_dev->notif_fifo, kfifo_size_order, GFP_KERNEL)) {
dev_err(&hdev->dev,
"%s:failed allocating notif_fifo\n", __func__);
kfree(djrcv_dev);
diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-event.c
index 261cae0..9b73680 100644
--- a/drivers/iio/industrialio-event.c
+++ b/drivers/iio/industrialio-event.c
@@ -35,7 +35,7 @@
*/
struct iio_event_interface {
wait_queue_head_t wait;
- DECLARE_KFIFO(det_events, struct iio_event_data, 16);
+ DECLARE_KFIFO(det_events, struct iio_event_data, 4);

struct list_head dev_attr_list;
unsigned long flags;
diff --git a/drivers/iio/kfifo_buf.c b/drivers/iio/kfifo_buf.c
index 5bc5c86..d8ba52ff 100644
--- a/drivers/iio/kfifo_buf.c
+++ b/drivers/iio/kfifo_buf.c
@@ -7,6 +7,7 @@
#include <linux/mutex.h>
#include <linux/iio/kfifo_buf.h>
#include <linux/sched.h>
+#include <linux/log2.h>

struct iio_kfifo {
struct iio_buffer buffer;
@@ -23,7 +24,7 @@ static inline int __iio_allocate_kfifo(struct iio_kfifo *buf,
return -EINVAL;

__iio_update_buffer(&buf->buffer, bytes_per_datum, length);
- return __kfifo_alloc((struct __kfifo *)&buf->kf, length,
+ return __kfifo_alloc((struct __kfifo *)&buf->kf, order_base_2(length),
bytes_per_datum, GFP_KERNEL);
}

diff --git a/drivers/infiniband/hw/cxgb3/cxio_resource.c b/drivers/infiniband/hw/cxgb3/cxio_resource.c
index 31f9201..186d05e 100644
--- a/drivers/infiniband/hw/cxgb3/cxio_resource.c
+++ b/drivers/infiniband/hw/cxgb3/cxio_resource.c
@@ -36,6 +36,7 @@
#include <linux/kfifo.h>
#include <linux/spinlock.h>
#include <linux/errno.h>
+#include <linux/log2.h>
#include "cxio_resource.h"
#include "cxio_hal.h"

@@ -54,8 +55,9 @@ static int __cxio_init_resource_fifo(struct kfifo *fifo,
u32 random_bytes;
u32 rarray[16];
spin_lock_init(fifo_lock);
+ int kfifo_size_order = order_base_2(nr * sizeof(u32));

- if (kfifo_alloc(fifo, nr * sizeof(u32), GFP_KERNEL))
+ if (kfifo_alloc(fifo, kfifo_size_order, GFP_KERNEL))
return -ENOMEM;

for (i = 0; i < skip_low + skip_high; i++)
@@ -111,11 +113,11 @@ static int cxio_init_resource_fifo_random(struct kfifo *fifo,
static int cxio_init_qpid_fifo(struct cxio_rdev *rdev_p)
{
u32 i;
+ int kfifo_size_order = order_base_2(T3_MAX_NUM_QP * sizeof(u32));

spin_lock_init(&rdev_p->rscp->qpid_fifo_lock);

- if (kfifo_alloc(&rdev_p->rscp->qpid_fifo, T3_MAX_NUM_QP * sizeof(u32),
- GFP_KERNEL))
+ if (kfifo_alloc(&rdev_p->rscp->qpid_fifo, kfifo_size_order, GFP_KERNEL))
return -ENOMEM;

for (i = 16; i < T3_MAX_NUM_QP; i++)
diff --git a/drivers/media/i2c/cx25840/cx25840-ir.c b/drivers/media/i2c/cx25840/cx25840-ir.c
index 38ce76e..1da0b6c 100644
--- a/drivers/media/i2c/cx25840/cx25840-ir.c
+++ b/drivers/media/i2c/cx25840/cx25840-ir.c
@@ -24,6 +24,7 @@
#include <linux/slab.h>
#include <linux/kfifo.h>
#include <linux/module.h>
+#include <linux/log2.h>
#include <media/cx25840.h>
#include <media/rc-core.h>

@@ -106,8 +107,10 @@ union cx25840_ir_fifo_rec {
struct ir_raw_event ir_core_data;
};

-#define CX25840_IR_RX_KFIFO_SIZE (256 * sizeof(union cx25840_ir_fifo_rec))
-#define CX25840_IR_TX_KFIFO_SIZE (256 * sizeof(union cx25840_ir_fifo_rec))
+#define CX25840_IR_RX_KFIFO_SIZE_ORDER (order_base_2(256 * sizeof(union cx25840_ir_fifo_rec)))
+#define CX25840_IR_RX_KFIFO_SIZE (1<<CX25840_IR_RX_KFIFO_SIZE_ORDER)
+#define CX25840_IR_TX_KFIFO_SIZE_ORDER (order_base_2(256 * sizeof(union cx25840_ir_fifo_rec)))
+#define CX25840_IR_TX_KFIFO_SIZE (CX25840_IR_TX_KFIFO_SIZE_ORDER)

struct cx25840_ir_state {
struct i2c_client *c;
@@ -1236,7 +1239,7 @@ int cx25840_ir_probe(struct v4l2_subdev *sd)

spin_lock_init(&ir_state->rx_kfifo_lock);
if (kfifo_alloc(&ir_state->rx_kfifo,
- CX25840_IR_RX_KFIFO_SIZE, GFP_KERNEL)) {
+ CX25840_IR_RX_KFIFO_SIZE_ORDER, GFP_KERNEL)) {
kfree(ir_state);
return -ENOMEM;
}
diff --git a/drivers/media/pci/cx23885/cx23888-ir.c b/drivers/media/pci/cx23885/cx23888-ir.c
index c4bd1e9..4c6e24b 100644
--- a/drivers/media/pci/cx23885/cx23888-ir.c
+++ b/drivers/media/pci/cx23885/cx23888-ir.c
@@ -23,6 +23,7 @@

#include <linux/kfifo.h>
#include <linux/slab.h>
+#include <linux/log2.h>

#include <media/v4l2-device.h>
#include <media/v4l2-chip-ident.h>
@@ -125,8 +126,10 @@ union cx23888_ir_fifo_rec {
struct ir_raw_event ir_core_data;
};

-#define CX23888_IR_RX_KFIFO_SIZE (256 * sizeof(union cx23888_ir_fifo_rec))
-#define CX23888_IR_TX_KFIFO_SIZE (256 * sizeof(union cx23888_ir_fifo_rec))
+#define CX23888_IR_RX_KFIFO_SIZE_ORDER (order_base_2(256 * sizeof(union cx23888_ir_fifo_rec)))
+#define CX23888_IR_RX_KFIFO_SIZE (1<<CX23888_IR_RX_KFIFO_SIZE_ORDER)
+#define CX23888_IR_TX_KFIFO_SIZE_ORDER (order_base_2(256 * sizeof(union cx23888_ir_fifo_rec)))
+#define CX23888_IR_TX_KFIFO_SIZE (1<<CX23888_IR_TX_KFIFO_SIZE_ORDER)

struct cx23888_ir_state {
struct v4l2_subdev sd;
@@ -1213,7 +1216,7 @@ int cx23888_ir_probe(struct cx23885_dev *dev)
return -ENOMEM;

spin_lock_init(&state->rx_kfifo_lock);
- if (kfifo_alloc(&state->rx_kfifo, CX23888_IR_RX_KFIFO_SIZE, GFP_KERNEL))
+ if (kfifo_alloc(&state->rx_kfifo, CX23888_IR_RX_KFIFO_SIZE_ORDER, GFP_KERNEL))
return -ENOMEM;

state->dev = dev;
diff --git a/drivers/media/pci/meye/meye.c b/drivers/media/pci/meye/meye.c
index 049e186..3bcde0c 100644
--- a/drivers/media/pci/meye/meye.c
+++ b/drivers/media/pci/meye/meye.c
@@ -1759,14 +1759,12 @@ static int meye_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
}

spin_lock_init(&meye.grabq_lock);
- if (kfifo_alloc(&meye.grabq, sizeof(int) * MEYE_MAX_BUFNBRS,
- GFP_KERNEL)) {
+ if (kfifo_alloc(&meye.grabq, MEYE_KFIFO_SIZE_ORDER, GFP_KERNEL)) {
v4l2_err(v4l2_dev, "fifo allocation failed\n");
goto outkfifoalloc1;
}
spin_lock_init(&meye.doneq_lock);
- if (kfifo_alloc(&meye.doneq, sizeof(int) * MEYE_MAX_BUFNBRS,
- GFP_KERNEL)) {
+ if (kfifo_alloc(&meye.doneq, MEYE_KFIFO_SIZE_ORDER, GFP_KERNEL)) {
v4l2_err(v4l2_dev, "fifo allocation failed\n");
goto outkfifoalloc2;
}
diff --git a/drivers/media/pci/meye/meye.h b/drivers/media/pci/meye/meye.h
index 4bdeb03..5d3ab4f 100644
--- a/drivers/media/pci/meye/meye.h
+++ b/drivers/media/pci/meye/meye.h
@@ -260,6 +260,7 @@
/* private API definitions */
#include <linux/meye.h>
#include <linux/mutex.h>
+#include <linux/log2.h>


/* Enable jpg software correction */
@@ -270,6 +271,7 @@

/* Maximum number of buffers */
#define MEYE_MAX_BUFNBRS 32
+#define MEYE_KFIFO_SIZE_ORDER (order_base_2(MEYE_MAX_BUFNBRS * sizeof(int)))

/* State of a buffer */
#define MEYE_BUF_UNUSED 0 /* not used */
diff --git a/drivers/media/rc/ir-raw.c b/drivers/media/rc/ir-raw.c
index 97dc8d1..e4d1ec8 100644
--- a/drivers/media/rc/ir-raw.c
+++ b/drivers/media/rc/ir-raw.c
@@ -18,6 +18,7 @@
#include <linux/kmod.h>
#include <linux/sched.h>
#include <linux/freezer.h>
+#include <linux/log2.h>
#include "rc-core-priv.h"

/* Define the max number of pulse/space transitions to buffer */
@@ -252,6 +253,8 @@ int ir_raw_event_register(struct rc_dev *dev)
{
int rc;
struct ir_raw_handler *handler;
+ int kfifo_size_order = order_base_2(sizeof(struct ir_raw_event) *
+ MAX_IR_EVENT_SIZE);

if (!dev)
return -EINVAL;
@@ -262,9 +265,7 @@ int ir_raw_event_register(struct rc_dev *dev)

dev->raw->dev = dev;
dev->raw->enabled_protocols = ~0;
- rc = kfifo_alloc(&dev->raw->kfifo,
- sizeof(struct ir_raw_event) * MAX_IR_EVENT_SIZE,
- GFP_KERNEL);
+ rc = kfifo_alloc(&dev->raw->kfifo, kfifo_size_order, GFP_KERNEL);
if (rc < 0)
goto out;

diff --git a/drivers/memstick/host/r592.h b/drivers/memstick/host/r592.h
index c5726c1..6fc19f4 100644
--- a/drivers/memstick/host/r592.h
+++ b/drivers/memstick/host/r592.h
@@ -143,7 +143,7 @@ struct r592_device {
struct task_struct *io_thread;
bool parallel_mode;

- DECLARE_KFIFO(pio_fifo, u8, sizeof(u32));
+ DECLARE_KFIFO(pio_fifo, u8, 2);

/* DMA area */
int dma_capable;
diff --git a/drivers/mmc/card/sdio_uart.c b/drivers/mmc/card/sdio_uart.c
index bd57a11..c54a7c5 100644
--- a/drivers/mmc/card/sdio_uart.c
+++ b/drivers/mmc/card/sdio_uart.c
@@ -43,12 +43,14 @@
#include <linux/mmc/card.h>
#include <linux/mmc/sdio_func.h>
#include <linux/mmc/sdio_ids.h>
+#include <linux/log2.h>


#define UART_NR 8 /* Number of UARTs this driver can handle */


#define FIFO_SIZE PAGE_SIZE
+#define FIFO_SIZE_ORDER PAGE_SHIFT
#define WAKEUP_CHARS 256

struct uart_icount {
@@ -93,7 +95,7 @@ static int sdio_uart_add_port(struct sdio_uart_port *port)

mutex_init(&port->func_lock);
spin_lock_init(&port->write_lock);
- if (kfifo_alloc(&port->xmit_fifo, FIFO_SIZE, GFP_KERNEL))
+ if (kfifo_alloc(&port->xmit_fifo, FIFO_SIZE_ORDER, GFP_KERNEL))
return -ENOMEM;

spin_lock(&sdio_uart_table_lock);
diff --git a/drivers/mtd/sm_ftl.c b/drivers/mtd/sm_ftl.c
index 8dd6ba5..672ef47 100644
--- a/drivers/mtd/sm_ftl.c
+++ b/drivers/mtd/sm_ftl.c
@@ -17,6 +17,7 @@
#include <linux/bitops.h>
#include <linux/slab.h>
#include <linux/mtd/nand_ecc.h>
+#include <linux/log2.h>
#include "nand/sm_common.h"
#include "sm_ftl.h"

@@ -766,6 +767,7 @@ static int sm_init_zone(struct sm_ftl *ftl, int zone_num)
int lba;
int i = 0;
int len;
+ int kfifo_size_order;

dbg("initializing zone %d", zone_num);

@@ -778,7 +780,8 @@ static int sm_init_zone(struct sm_ftl *ftl, int zone_num)


/* Allocate memory for free sectors FIFO */
- if (kfifo_alloc(&zone->free_sectors, ftl->zone_size * 2, GFP_KERNEL)) {
+ kfifo_size_order = order_base_2(ftl->zone_size * 2);
+ if (kfifo_alloc(&zone->free_sectors, kfifo_size_order, GFP_KERNEL)) {
kfree(zone->lba_to_phys_table);
return -ENOMEM;
}
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index 0c02f04..ea5ddf4 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -25,6 +25,8 @@
#include "cmd.h"
#include "mesh.h"

+#define KFIFO_SIZE_ORDER 6
+
#define DRIVER_RELEASE_VERSION "323.p0"
const char lbs_driver_version[] = "COMM-USB8388-" DRIVER_RELEASE_VERSION
#ifdef DEBUG
@@ -914,7 +916,7 @@ static int lbs_init_adapter(struct lbs_private *priv)
priv->resp_len[0] = priv->resp_len[1] = 0;

/* Create the event FIFO */
- ret = kfifo_alloc(&priv->event_fifo, sizeof(u32) * 16, GFP_KERNEL);
+ ret = kfifo_alloc(&priv->event_fifo, KFIFO_SIZE_ORDER, GFP_KERNEL);
if (ret) {
pr_err("Out of memory allocating event FIFO buffer\n");
goto out;
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 44f8b3f..c8f68485 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -979,12 +979,11 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev)
* tx_queues * entry_num and round up to the nearest
* power of 2.
*/
- int kfifo_size =
- roundup_pow_of_two(rt2x00dev->ops->tx_queues *
+ int kfifo_size_order = order_base_2(rt2x00dev->ops->tx_queues *
rt2x00dev->ops->tx->entry_num *
sizeof(u32));

- status = kfifo_alloc(&rt2x00dev->txstatus_fifo, kfifo_size,
+ status = kfifo_alloc(&rt2x00dev->txstatus_fifo, kfifo_size_order,
GFP_KERNEL);
if (status)
return status;
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c
index 421bbc5..ec9284a 100644
--- a/drivers/pci/pcie/aer/aerdrv_core.c
+++ b/drivers/pci/pcie/aer/aerdrv_core.c
@@ -574,7 +574,6 @@ static void handle_error_source(struct pcie_device *aerdev,
static void aer_recover_work_func(struct work_struct *work);

#define AER_RECOVER_RING_ORDER 4
-#define AER_RECOVER_RING_SIZE (1 << AER_RECOVER_RING_ORDER)

struct aer_recover_entry
{
@@ -585,7 +584,7 @@ struct aer_recover_entry
};

static DEFINE_KFIFO(aer_recover_ring, struct aer_recover_entry,
- AER_RECOVER_RING_SIZE);
+ AER_RECOVER_RING_ORDER);
/*
* Mutual exclusion for writers of aer_recover_ring, reader side don't
* need lock, because there is only one reader and lock is not needed
diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c
index c4c1a54..185bd55 100644
--- a/drivers/platform/x86/fujitsu-laptop.c
+++ b/drivers/platform/x86/fujitsu-laptop.c
@@ -66,6 +66,7 @@
#include <linux/backlight.h>
#include <linux/input.h>
#include <linux/kfifo.h>
+#include <linux/log2.h>
#include <linux/video_output.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
@@ -116,6 +117,7 @@

#define MAX_HOTKEY_RINGBUFFER_SIZE 100
#define RINGBUFFERSIZE 40
+#define KFIFO_SIZE_ORDER (order_base_2(RINGBUFFERSIZE * sizeof(int)))

/* Debugging */
#define FUJLAPTOP_LOG ACPI_FUJITSU_HID ": "
@@ -825,8 +827,7 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device)

/* kfifo */
spin_lock_init(&fujitsu_hotkey->fifo_lock);
- error = kfifo_alloc(&fujitsu_hotkey->fifo, RINGBUFFERSIZE * sizeof(int),
- GFP_KERNEL);
+ error = kfifo_alloc(&fujitsu_hotkey->fifo, KFIFO_SIZE_ORDER, GFP_KERNEL);
if (error) {
pr_err("kfifo_alloc failed\n");
goto err_stop;
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c
index daaddec..ee57eac 100644
--- a/drivers/platform/x86/sony-laptop.c
+++ b/drivers/platform/x86/sony-laptop.c
@@ -183,7 +183,7 @@ static void sony_nc_rfkill_update(void);

/*********** Input Devices ***********/

-#define SONY_LAPTOP_BUF_SIZE 128
+#define SONY_LAPTOP_KFIFO_SIZE_ORDER 7
struct sony_laptop_input_s {
atomic_t users;
struct input_dev *jog_dev;
@@ -447,7 +447,7 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device)
/* kfifo */
spin_lock_init(&sony_laptop_input.fifo_lock);
error = kfifo_alloc(&sony_laptop_input.fifo,
- SONY_LAPTOP_BUF_SIZE, GFP_KERNEL);
+ SONY_LAPTOP_KFIFO_SIZE_ORDER, GFP_KERNEL);
if (error) {
pr_err("kfifo_alloc failed\n");
goto err_dec_users;
@@ -3752,7 +3752,7 @@ static int sonypi_compat_init(void)

spin_lock_init(&sonypi_compat.fifo_lock);
error =
- kfifo_alloc(&sonypi_compat.fifo, SONY_LAPTOP_BUF_SIZE, GFP_KERNEL);
+ kfifo_alloc(&sonypi_compat.fifo, SONY_LAPTOP_KFIFO_SIZE_ORDER, GFP_KERNEL);
if (error) {
pr_err("kfifo_alloc failed\n");
return error;
diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c
index 6faba40..a731e87 100644
--- a/drivers/rapidio/devices/tsi721.c
+++ b/drivers/rapidio/devices/tsi721.c
@@ -32,6 +32,7 @@
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
#include <linux/kfifo.h>
+#include <linux/log2.h>
#include <linux/delay.h>

#include "tsi721.h"
@@ -970,11 +971,11 @@ static void tsi721_init_sr2pc_mapping(struct tsi721_device *priv)
*/
static int tsi721_port_write_init(struct tsi721_device *priv)
{
+ int kfifo_size_order = order_base_2(TSI721_RIO_PW_MSG_SIZE * 32);
priv->pw_discard_count = 0;
INIT_WORK(&priv->pw_work, tsi721_pw_dpc);
spin_lock_init(&priv->pw_fifo_lock);
- if (kfifo_alloc(&priv->pw_fifo,
- TSI721_RIO_PW_MSG_SIZE * 32, GFP_KERNEL)) {
+ if (kfifo_alloc(&priv->pw_fifo, kfifo_size_order, GFP_KERNEL)) {
dev_err(&priv->pdev->dev, "PW FIFO allocation failed\n");
return -ENOMEM;
}
diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c
index 552e8a2..bdb09bf 100644
--- a/drivers/scsi/libiscsi_tcp.c
+++ b/drivers/scsi/libiscsi_tcp.c
@@ -35,6 +35,7 @@
#include <linux/crypto.h>
#include <linux/delay.h>
#include <linux/kfifo.h>
+#include <linux/log2.h>
#include <linux/scatterlist.h>
#include <linux/module.h>
#include <net/tcp.h>
@@ -1113,6 +1114,7 @@ int iscsi_tcp_r2tpool_alloc(struct iscsi_session *session)
{
int i;
int cmd_i;
+ int kfifo_size_order;

/*
* initialize per-task: R2T pool and xmit queue
@@ -1135,8 +1137,8 @@ int iscsi_tcp_r2tpool_alloc(struct iscsi_session *session)
}

/* R2T xmit queue */
- if (kfifo_alloc(&tcp_task->r2tqueue,
- session->max_r2t * 4 * sizeof(void*), GFP_KERNEL)) {
+ kfifo_size_order = order_base_2(session->max_r2t * 4 * sizeof(void *));
+ if (kfifo_alloc(&tcp_task->r2tqueue, kfifo_size_order, GFP_KERNEL)) {
iscsi_pool_free(&tcp_task->r2tpool);
goto r2t_alloc_fail;
}
diff --git a/drivers/staging/omapdrm/omap_plane.c b/drivers/staging/omapdrm/omap_plane.c
index 2a8e5ba..40f057f 100644
--- a/drivers/staging/omapdrm/omap_plane.c
+++ b/drivers/staging/omapdrm/omap_plane.c
@@ -28,6 +28,8 @@
*/
#define omap_plane _omap_plane

+#define OMAP_KFIFO_SIZE_ORDER 4
+
/*
* plane funcs
*/
@@ -508,7 +510,8 @@ struct drm_plane *omap_plane_init(struct drm_device *dev,

mutex_init(&omap_plane->unpin_mutex);

- ret = kfifo_alloc(&omap_plane->unpin_fifo, 16, GFP_KERNEL);
+ ret = kfifo_alloc(&omap_plane->unpin_fifo, OMAP_KFIFO_SIZE_ORDER,
+ GFP_KERNEL);
if (ret) {
dev_err(dev->dev, "could not allocate unpin FIFO\n");
goto fail;
diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c
index dcc0430..b3b1b1c 100644
--- a/drivers/tty/n_gsm.c
+++ b/drivers/tty/n_gsm.c
@@ -66,6 +66,8 @@
static int debug;
module_param(debug, int, 0600);

+#define KFIFO_SIZE_ORDER 12
+
/* Defaults: these are from the specification */

#define T1 10 /* 100mS */
@@ -1636,7 +1638,7 @@ static struct gsm_dlci *gsm_dlci_alloc(struct gsm_mux *gsm, int addr)
spin_lock_init(&dlci->lock);
mutex_init(&dlci->mutex);
dlci->fifo = &dlci->_fifo;
- if (kfifo_alloc(&dlci->_fifo, 4096, GFP_KERNEL) < 0) {
+ if (kfifo_alloc(&dlci->_fifo, KFIFO_SIZE_ORDER, GFP_KERNEL) < 0) {
kfree(dlci);
return NULL;
}
diff --git a/drivers/tty/nozomi.c b/drivers/tty/nozomi.c
index a0c69ab..8b54da3 100644
--- a/drivers/tty/nozomi.c
+++ b/drivers/tty/nozomi.c
@@ -128,8 +128,7 @@ static int debug;
#define NTTY_TTY_MAXMINORS 256
#define NTTY_FIFO_BUFFER_SIZE 8192

-/* Must be power of 2 */
-#define FIFO_BUFFER_SIZE_UL 8192
+#define FIFO_BUFFER_SIZE_ORDER 13

/* Size of tmp send buffer to card */
#define SEND_BUF_MAX 1024
@@ -1428,7 +1427,7 @@ static int nozomi_card_init(struct pci_dev *pdev,
}

for (i = PORT_MDM; i < MAX_PORT; i++) {
- if (kfifo_alloc(&dc->port[i].fifo_ul, FIFO_BUFFER_SIZE_UL,
+ if (kfifo_alloc(&dc->port[i].fifo_ul, FIFO_BUFFER_SIZE_ORDER,
GFP_KERNEL)) {
dev_err(&pdev->dev,
"Could not allocate kfifo buffer\n");
diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c
index 675d94a..f80dc2c 100644
--- a/drivers/tty/serial/ifx6x60.c
+++ b/drivers/tty/serial/ifx6x60.c
@@ -880,7 +880,7 @@ static int ifx_spi_create_port(struct ifx_spi_device *ifx_dev)
lockdep_set_class_and_subclass(&ifx_dev->fifo_lock,
&ifx_spi_key, 0);

- if (kfifo_alloc(&ifx_dev->tx_fifo, IFX_SPI_FIFO_SIZE, GFP_KERNEL)) {
+ if (kfifo_alloc(&ifx_dev->tx_fifo, IFX_SPI_FIFO_SIZE_ORDER, GFP_KERNEL)) {
ret = -ENOMEM;
goto error_ret;
}
diff --git a/drivers/tty/serial/ifx6x60.h b/drivers/tty/serial/ifx6x60.h
index 4fbddc2..da4fd1c 100644
--- a/drivers/tty/serial/ifx6x60.h
+++ b/drivers/tty/serial/ifx6x60.h
@@ -31,7 +31,8 @@

#define IFX_SPI_MAX_MINORS 1
#define IFX_SPI_TRANSFER_SIZE 2048
-#define IFX_SPI_FIFO_SIZE 4096
+#define IFX_SPI_FIFO_SIZE_ORDER 12
+#define IFX_SPI_FIFO_SIZE (1 << IFX_SPI_FIFO_SIZE_ORDER)

#define IFX_SPI_HEADER_OVERHEAD 4
#define IFX_RESET_TIMEOUT msecs_to_jiffies(50)
diff --git a/drivers/tty/serial/kgdb_nmi.c b/drivers/tty/serial/kgdb_nmi.c
index 6ac2b79..947dd72 100644
--- a/drivers/tty/serial/kgdb_nmi.c
+++ b/drivers/tty/serial/kgdb_nmi.c
@@ -26,6 +26,7 @@
#include <linux/interrupt.h>
#include <linux/hrtimer.h>
#include <linux/tick.h>
+#include <linux/log2.h>
#include <linux/kfifo.h>
#include <linux/kgdb.h>
#include <linux/kdb.h>
@@ -75,13 +76,13 @@ static struct console kgdb_nmi_console = {
* This is usually the maximum rate on debug ports. We make fifo large enough
* to make copy-pasting to the terminal usable.
*/
-#define KGDB_NMI_BAUD 115200
-#define KGDB_NMI_FIFO_SIZE roundup_pow_of_two(KGDB_NMI_BAUD / 8 / HZ)
+#define KGDB_NMI_BAUD 115200
+#define KGDB_NMI_FIFO_SIZE_ORDER order_base_2(KGDB_NMI_BAUD / 8 / HZ)

struct kgdb_nmi_tty_priv {
struct tty_port port;
struct tasklet_struct tlet;
- STRUCT_KFIFO(char, KGDB_NMI_FIFO_SIZE) fifo;
+ STRUCT_KFIFO(char, KGDB_NMI_FIFO_SIZE_ORDER) fifo;
};

static struct kgdb_nmi_tty_priv *kgdb_nmi_port_to_priv(struct tty_port *port)
diff --git a/drivers/usb/host/fhci.h b/drivers/usb/host/fhci.h
index 7cc1c32..e4a0ac6 100644
--- a/drivers/usb/host/fhci.h
+++ b/drivers/usb/host/fhci.h
@@ -24,6 +24,7 @@
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/kfifo.h>
+#include <linux/log2.h>
#include <linux/io.h>
#include <linux/usb.h>
#include <linux/usb/hcd.h>
@@ -478,7 +479,8 @@ static inline struct usb_hcd *fhci_to_hcd(struct fhci_hcd *fhci)
/* fifo of pointers */
static inline int cq_new(struct kfifo *fifo, int size)
{
- return kfifo_alloc(fifo, size * sizeof(void *), GFP_KERNEL);
+ int kfifo_size_order = order_base_2(size * sizeof(void *));
+ return kfifo_alloc(fifo, kfifo_size_order, GFP_KERNEL);
}

static inline void cq_delete(struct kfifo *kfifo)
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index fd8c35f..a4d7cd1 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -54,7 +54,7 @@ static bool unstable_bauds;
#define DRIVER_DESC "Cypress USB to Serial Driver"

/* write buffer size defines */
-#define CYPRESS_BUF_SIZE 1024
+#define CYPRESS_KFIFO_SIZE_ORDER 10

static const struct usb_device_id id_table_earthmate[] = {
{ USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB) },
@@ -445,7 +445,7 @@ static int cypress_generic_port_probe(struct usb_serial_port *port)

priv->comm_is_ok = !0;
spin_lock_init(&priv->lock);
- if (kfifo_alloc(&priv->write_fifo, CYPRESS_BUF_SIZE, GFP_KERNEL)) {
+ if (kfifo_alloc(&priv->write_fifo, CYPRESS_KFIFO_SIZE_ORDER, GFP_KERNEL)) {
kfree(priv);
return -ENOMEM;
}
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index 58184f3..a19018b 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -64,7 +64,7 @@

#define EDGE_CLOSING_WAIT 4000 /* in .01 sec */

-#define EDGE_OUT_BUF_SIZE 1024
+#define EDGE_KFIFO_SIZE_ORDER 10


/* Product information read from the Edgeport */
@@ -2567,7 +2567,7 @@ static int edge_port_probe(struct usb_serial_port *port)
if (!edge_port)
return -ENOMEM;

- ret = kfifo_alloc(&edge_port->write_fifo, EDGE_OUT_BUF_SIZE,
+ ret = kfifo_alloc(&edge_port->write_fifo, EDGE_KFIFO_SIZE_ORDER,
GFP_KERNEL);
if (ret) {
kfree(edge_port);
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index f2530d2..777e90a 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -45,7 +45,8 @@

#define TI_FIRMWARE_BUF_SIZE 16284

-#define TI_WRITE_BUF_SIZE 1024
+#define TI_KFIFO_SIZE_ORDER 10
+#define TI_KFIFO_SIZE (1 << TI_KFIFO_SIZE_ORDER)

#define TI_TRANSFER_TIMEOUT 2

@@ -434,7 +435,7 @@ static int ti_port_probe(struct usb_serial_port *port)
tport->tp_closing_wait = closing_wait;
init_waitqueue_head(&tport->tp_msr_wait);
init_waitqueue_head(&tport->tp_write_wait);
- if (kfifo_alloc(&tport->write_fifo, TI_WRITE_BUF_SIZE, GFP_KERNEL)) {
+ if (kfifo_alloc(&tport->write_fifo, TI_KFIFO_SIZE_ORDER, GFP_KERNEL)) {
kfree(tport);
return -ENOMEM;
}
@@ -1355,7 +1356,7 @@ static int ti_get_serial_info(struct ti_port *tport,
ret_serial.line = port->serial->minor;
ret_serial.port = port->number - port->serial->minor;
ret_serial.flags = tport->tp_flags;
- ret_serial.xmit_fifo_size = TI_WRITE_BUF_SIZE;
+ ret_serial.xmit_fifo_size = TI_KFIFO_SIZE;
ret_serial.baud_base = tport->tp_tdev->td_is_3410 ? 921600 : 460800;
ret_serial.closing_wait = tport->tp_closing_wait;

diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 64bda13..11ca271 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -934,7 +934,7 @@ static int usb_serial_probe(struct usb_interface *interface,
for (i = 0; i < num_bulk_out; ++i) {
endpoint = bulk_out_endpoint[i];
port = serial->port[i];
- if (kfifo_alloc(&port->write_fifo, PAGE_SIZE, GFP_KERNEL))
+ if (kfifo_alloc(&port->write_fifo, PAGE_SHIFT, GFP_KERNEL))
goto probe_error;
buffer_size = serial->type->bulk_out_size;
if (!buffer_size)
diff --git a/include/linux/kfifo.h b/include/linux/kfifo.h
index 4bf984e..28dfe98 100644
--- a/include/linux/kfifo.h
+++ b/include/linux/kfifo.h
@@ -76,8 +76,8 @@ struct __kfifo {
type buf[((size < 2) || (size & (size - 1))) ? -1 : size]; \
}

-#define STRUCT_KFIFO(type, size) \
- struct __STRUCT_KFIFO(type, size, 0)
+#define STRUCT_KFIFO(type, size_order) \
+ struct __STRUCT_KFIFO(type, (1<<(size_order)), 0)

#define __STRUCT_KFIFO_PTR(type, recsize) \
{ \
@@ -93,11 +93,11 @@ struct __kfifo {
*/
struct kfifo __STRUCT_KFIFO_PTR(unsigned char, 0);

-#define STRUCT_KFIFO_REC_1(size) \
- struct __STRUCT_KFIFO(unsigned char, size, 1)
+#define STRUCT_KFIFO_REC_1(size_order) \
+ struct __STRUCT_KFIFO(unsigned char, (1<<(size_order)), 1)

-#define STRUCT_KFIFO_REC_2(size) \
- struct __STRUCT_KFIFO(unsigned char, size, 2)
+#define STRUCT_KFIFO_REC_2(size_order) \
+ struct __STRUCT_KFIFO(unsigned char, (1<<(size_order)), 2)

/*
* define kfifo_rec types
@@ -123,9 +123,9 @@ struct kfifo_rec_ptr_2 __STRUCT_KFIFO_PTR(unsigned char, 2);
* DECLARE_KFIFO - macro to declare a fifo object
* @fifo: name of the declared fifo
* @type: type of the fifo elements
- * @size: the number of elements in the fifo, this must be a power of 2
+ * @size_order: request 2^size_order fifo elements
*/
-#define DECLARE_KFIFO(fifo, type, size) STRUCT_KFIFO(type, size) fifo
+#define DECLARE_KFIFO(fifo, type, size_order) STRUCT_KFIFO(type, size_order) fifo

/**
* INIT_KFIFO - Initialize a fifo declared by DECLARE_KFIFO
@@ -146,12 +146,12 @@ struct kfifo_rec_ptr_2 __STRUCT_KFIFO_PTR(unsigned char, 2);
* DEFINE_KFIFO - macro to define and initialize a fifo
* @fifo: name of the declared fifo datatype
* @type: type of the fifo elements
- * @size: the number of elements in the fifo, this must be a power of 2
+ * @size_order: request 2^size_order fifo elements
*
* Note: the macro can be used for global and local fifo data type variables.
*/
-#define DEFINE_KFIFO(fifo, type, size) \
- DECLARE_KFIFO(fifo, type, size) = \
+#define DEFINE_KFIFO(fifo, type, size_order) \
+ DECLARE_KFIFO(fifo, type, size_order) = \
(typeof(fifo)) { \
{ \
{ \
@@ -317,22 +317,21 @@ __kfifo_uint_must_check_helper( \
/**
* kfifo_alloc - dynamically allocates a new fifo buffer
* @fifo: pointer to the fifo
- * @size: the number of elements in the fifo, this must be a power of 2
+ * @size_order: request 2^size_order fifo elements
* @gfp_mask: get_free_pages mask, passed to kmalloc()
*
* This macro dynamically allocates a new fifo buffer.
*
- * The numer of elements will be rounded-up to a power of 2.
* The fifo will be release with kfifo_free().
* Return 0 if no error, otherwise an error code.
*/
-#define kfifo_alloc(fifo, size, gfp_mask) \
+#define kfifo_alloc(fifo, size_order, gfp_mask) \
__kfifo_int_must_check_helper( \
({ \
typeof((fifo) + 1) __tmp = (fifo); \
struct __kfifo *__kfifo = &__tmp->kfifo; \
__is_kfifo_ptr(__tmp) ? \
- __kfifo_alloc(__kfifo, size, sizeof(*__tmp->type), gfp_mask) : \
+ __kfifo_alloc(__kfifo, size_order, sizeof(*__tmp->type), gfp_mask) : \
-EINVAL; \
}) \
)
@@ -745,7 +744,7 @@ __kfifo_uint_must_check_helper( \
}) \
)

-extern int __kfifo_alloc(struct __kfifo *fifo, unsigned int size,
+extern int __kfifo_alloc(struct __kfifo *fifo, int size_order,
size_t esize, gfp_t gfp_mask);

extern void __kfifo_free(struct __kfifo *fifo);
diff --git a/include/linux/rio.h b/include/linux/rio.h
index a3e7842..05ff6bb 100644
--- a/include/linux/rio.h
+++ b/include/linux/rio.h
@@ -70,6 +70,7 @@
#define RIO_OUTB_MBOX_RESOURCE 2

#define RIO_PW_MSG_SIZE 64
+#define RIO_KFIFO_SIZE_ORDER 11 /* 64 * 32 */

/*
* A component tag value (stored in the component tag CSR) is used as device's
diff --git a/include/media/lirc_dev.h b/include/media/lirc_dev.h
index 168dd0b..7816d39 100644
--- a/include/media/lirc_dev.h
+++ b/include/media/lirc_dev.h
@@ -19,6 +19,7 @@
#include <linux/ioctl.h>
#include <linux/poll.h>
#include <linux/kfifo.h>
+#include <linux/log2.h>
#include <media/lirc.h>

struct lirc_buffer {
@@ -50,12 +51,13 @@ static inline int lirc_buffer_init(struct lirc_buffer *buf,
unsigned int size)
{
int ret;
+ int kfifo_size_order = order_base_2(size * chunk_size);

init_waitqueue_head(&buf->wait_poll);
spin_lock_init(&buf->fifo_lock);
buf->chunk_size = chunk_size;
buf->size = size;
- ret = kfifo_alloc(&buf->fifo, size * chunk_size, GFP_KERNEL);
+ ret = kfifo_alloc(&buf->fifo, kfifo_size_order, GFP_KERNEL);
if (ret == 0)
buf->fifo_initialized = 1;

diff --git a/kernel/kfifo.c b/kernel/kfifo.c
index d07f480..be1c2a0 100644
--- a/kernel/kfifo.c
+++ b/kernel/kfifo.c
@@ -35,15 +35,10 @@ static inline unsigned int kfifo_unused(struct __kfifo *fifo)
return (fifo->mask + 1) - (fifo->in - fifo->out);
}

-int __kfifo_alloc(struct __kfifo *fifo, unsigned int size,
+int __kfifo_alloc(struct __kfifo *fifo, int size_order,
size_t esize, gfp_t gfp_mask)
{
- /*
- * round down to the next power of 2, since our 'let the indices
- * wrap' technique works only in this case.
- */
- if (!is_power_of_2(size))
- size = rounddown_pow_of_two(size);
+ unsigned int size = 1 << size_order;

fifo->in = 0;
fifo->out = 0;
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index c6e4dd3..827bbf3 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -1189,7 +1189,6 @@ out:
EXPORT_SYMBOL_GPL(memory_failure);

#define MEMORY_FAILURE_FIFO_ORDER 4
-#define MEMORY_FAILURE_FIFO_SIZE (1 << MEMORY_FAILURE_FIFO_ORDER)

struct memory_failure_entry {
unsigned long pfn;
@@ -1199,7 +1198,7 @@ struct memory_failure_entry {

struct memory_failure_cpu {
DECLARE_KFIFO(fifo, struct memory_failure_entry,
- MEMORY_FAILURE_FIFO_SIZE);
+ MEMORY_FAILURE_FIFO_ORDER);
spinlock_t lock;
struct work_struct work;
};
diff --git a/net/dccp/probe.c b/net/dccp/probe.c
index 0a8d6eb..0a12fd5 100644
--- a/net/dccp/probe.c
+++ b/net/dccp/probe.c
@@ -31,6 +31,7 @@
#include <linux/kfifo.h>
#include <linux/vmalloc.h>
#include <linux/gfp.h>
+#include <linux/log2.h>
#include <net/net_namespace.h>

#include "dccp.h"
@@ -166,10 +167,11 @@ static __init int setup_jprobe(void)
static __init int dccpprobe_init(void)
{
int ret = -ENOMEM;
+ int kfifo_size_order = order_base_2(bufsize);

init_waitqueue_head(&dccpw.wait);
spin_lock_init(&dccpw.lock);
- if (kfifo_alloc(&dccpw.fifo, bufsize, GFP_KERNEL))
+ if (kfifo_alloc(&dccpw.fifo, kfifo_size_order, GFP_KERNEL))
return ret;
if (!proc_net_fops_create(&init_net, procname, S_IRUSR, &dccpprobe_fops))
goto err0;
@@ -200,7 +202,7 @@ module_exit(dccpprobe_exit);
MODULE_PARM_DESC(port, "Port to match (0=all)");
module_param(port, int, 0);

-MODULE_PARM_DESC(bufsize, "Log buffer size (default 64k)");
+MODULE_PARM_DESC(bufsize, "Log buffer size (default 64k , should be power of 2. If not, will roundup to power of 2)");
module_param(bufsize, int, 0);

MODULE_AUTHOR("Ian McDonald <[email protected]>");
diff --git a/net/sctp/probe.c b/net/sctp/probe.c
index 5f7518d..1736ef4 100644
--- a/net/sctp/probe.c
+++ b/net/sctp/probe.c
@@ -33,6 +33,7 @@
#include <linux/module.h>
#include <linux/kfifo.h>
#include <linux/time.h>
+#include <linux/log2.h>
#include <net/net_namespace.h>

#include <net/sctp/sctp.h>
@@ -47,7 +48,7 @@ MODULE_PARM_DESC(port, "Port to match (0=all)");
module_param(port, int, 0);

static int bufsize __read_mostly = 64 * 1024;
-MODULE_PARM_DESC(bufsize, "Log buffer size (default 64k)");
+MODULE_PARM_DESC(bufsize, "Log buffer size (default 64k, should be power of 2. If not, will roundup to power of 2)");
module_param(bufsize, int, 0);

static int full __read_mostly = 1;
@@ -182,10 +183,11 @@ static struct jprobe sctp_recv_probe = {
static __init int sctpprobe_init(void)
{
int ret = -ENOMEM;
+ int kfifo_size_order = order_base_2(bufsize);

init_waitqueue_head(&sctpw.wait);
spin_lock_init(&sctpw.lock);
- if (kfifo_alloc(&sctpw.fifo, bufsize, GFP_KERNEL))
+ if (kfifo_alloc(&sctpw.fifo, kfifo_size_order, GFP_KERNEL))
return ret;

if (!proc_net_fops_create(&init_net, procname, S_IRUSR,
diff --git a/samples/kfifo/bytestream-example.c b/samples/kfifo/bytestream-example.c
index cfe40ad..eb3a46e 100644
--- a/samples/kfifo/bytestream-example.c
+++ b/samples/kfifo/bytestream-example.c
@@ -18,7 +18,7 @@
*/

/* fifo size in elements (bytes) */
-#define FIFO_SIZE 32
+#define FIFO_SIZE_ORDER 5

/* name of the proc entry */
#define PROC_FIFO "bytestream-fifo"
@@ -41,10 +41,10 @@ static DEFINE_MUTEX(write_lock);
#ifdef DYNAMIC
static struct kfifo test;
#else
-static DECLARE_KFIFO(test, unsigned char, FIFO_SIZE);
+static DECLARE_KFIFO(test, unsigned char, FIFO_SIZE_ORDER);
#endif

-static const unsigned char expected_result[FIFO_SIZE] = {
+static const unsigned char expected_result[1<<FIFO_SIZE_ORDER] = {
3, 4, 5, 6, 7, 8, 9, 0,
1, 20, 21, 22, 23, 24, 25, 26,
27, 28, 29, 30, 31, 32, 33, 34,
@@ -156,7 +156,7 @@ static int __init example_init(void)
#ifdef DYNAMIC
int ret;

- ret = kfifo_alloc(&test, FIFO_SIZE, GFP_KERNEL);
+ ret = kfifo_alloc(&test, FIFO_SIZE_ORDER, GFP_KERNEL);
if (ret) {
printk(KERN_ERR "error kfifo_alloc\n");
return ret;
diff --git a/samples/kfifo/dma-example.c b/samples/kfifo/dma-example.c
index 0647379..bbc0787 100644
--- a/samples/kfifo/dma-example.c
+++ b/samples/kfifo/dma-example.c
@@ -16,7 +16,8 @@
*/

/* fifo size in elements (bytes) */
-#define FIFO_SIZE 32
+#define FIFO_SIZE_ORDER 5
+#define FIFO_SIZE (1<< FIFO_SIZE_ORDER)

static struct kfifo fifo;

@@ -29,7 +30,7 @@ static int __init example_init(void)

printk(KERN_INFO "DMA fifo test start\n");

- if (kfifo_alloc(&fifo, FIFO_SIZE, GFP_KERNEL)) {
+ if (kfifo_alloc(&fifo, FIFO_SIZE_ORDER, GFP_KERNEL)) {
printk(KERN_WARNING "error kfifo_alloc\n");
return -ENOMEM;
}
diff --git a/samples/kfifo/inttype-example.c b/samples/kfifo/inttype-example.c
index 6f8e79e..bed3229 100644
--- a/samples/kfifo/inttype-example.c
+++ b/samples/kfifo/inttype-example.c
@@ -18,7 +18,8 @@
*/

/* fifo size in elements (ints) */
-#define FIFO_SIZE 32
+#define FIFO_SIZE_ORDER 5
+#define FIFO_SIZE (1<< FIFO_SIZE_ORDER)

/* name of the proc entry */
#define PROC_FIFO "int-fifo"
@@ -41,7 +42,7 @@ static DEFINE_MUTEX(write_lock);
#ifdef DYNAMIC
static DECLARE_KFIFO_PTR(test, int);
#else
-static DEFINE_KFIFO(test, int, FIFO_SIZE);
+static DEFINE_KFIFO(test, int, FIFO_SIZE_ORDER);
#endif

static const int expected_result[FIFO_SIZE] = {
@@ -149,7 +150,7 @@ static int __init example_init(void)
#ifdef DYNAMIC
int ret;

- ret = kfifo_alloc(&test, FIFO_SIZE, GFP_KERNEL);
+ ret = kfifo_alloc(&test, FIFO_SIZE_ORDER, GFP_KERNEL);
if (ret) {
printk(KERN_ERR "error kfifo_alloc\n");
return ret;
diff --git a/samples/kfifo/record-example.c b/samples/kfifo/record-example.c
index 2d7529e..2902eae 100644
--- a/samples/kfifo/record-example.c
+++ b/samples/kfifo/record-example.c
@@ -18,7 +18,7 @@
*/

/* fifo size in elements (bytes) */
-#define FIFO_SIZE 128
+#define FIFO_SIZE_ORDER 7

/* name of the proc entry */
#define PROC_FIFO "record-fifo"
@@ -50,7 +50,7 @@ static DEFINE_MUTEX(write_lock);
struct kfifo_rec_ptr_1 test;

#else
-typedef STRUCT_KFIFO_REC_1(FIFO_SIZE) mytest;
+typedef STRUCT_KFIFO_REC_1(FIFO_SIZE_ORDER) mytest;

static mytest test;
#endif
@@ -163,7 +163,7 @@ static int __init example_init(void)
#ifdef DYNAMIC
int ret;

- ret = kfifo_alloc(&test, FIFO_SIZE, GFP_KERNEL);
+ ret = kfifo_alloc(&test, FIFO_SIZE_ORDER, GFP_KERNEL);
if (ret) {
printk(KERN_ERR "error kfifo_alloc\n");
return ret;
--
1.7.7.6



2013-01-09 02:41:48

by Yuanhan Liu

[permalink] [raw]
Subject: Re: [PATCH 5/5] kfifo: log based kfifo API

On Tue, Jan 08, 2013 at 10:16:46AM -0800, Dmitry Torokhov wrote:
> Hi Yuanhan,
>
> On Tue, Jan 08, 2013 at 10:57:53PM +0800, Yuanhan Liu wrote:
> > The current kfifo API take the kfifo size as input, while it rounds
> > _down_ the size to power of 2 at __kfifo_alloc. This may introduce
> > potential issue.
> >
> > Take the code at drivers/hid/hid-logitech-dj.c as example:
> >
> > if (kfifo_alloc(&djrcv_dev->notif_fifo,
> > DJ_MAX_NUMBER_NOTIFICATIONS * sizeof(struct dj_report),
> > GFP_KERNEL)) {
> >
> > Where, DJ_MAX_NUMBER_NOTIFICATIONS is 8, and sizeo of(struct dj_report)
> > is 15.
> >
> > Which means it wants to allocate a kfifo buffer which can store 8
> > dj_report entries at once. The expected kfifo buffer size would be
> > 8 * 15 = 120 then. While, in the end, __kfifo_alloc will turn the
> > size to rounddown_power_of_2(120) = 64, and then allocate a buf
> > with 64 bytes, which I don't think this is the original author want.
> >
> > With the new log API, we can do like following:
> >
> > int kfifo_size_order = order_base_2(DJ_MAX_NUMBER_NOTIFICATIONS *
> > sizeof(struct dj_report));
> >
> > if (kfifo_alloc(&djrcv_dev->notif_fifo, kfifo_size_order, GFP_KERNEL)) {
> >
> > This make sure we will allocate enough kfifo buffer for holding
> > DJ_MAX_NUMBER_NOTIFICATIONS dj_report entries.
>
> Why don't you simply change __kfifo_alloc to round the allocation up
> instead of down?

Hi Dmitry,

Yes, it would be neat and that was my first reaction as well. I then
sent out a patch, but it was NACKed by Stefani(the original kfifo
author). Here is the link:

https://lkml.org/lkml/2012/10/26/144

Then Stefani proposed to change the API to take log of size as input to
root fix this kind of issues. And here it is.

Thanks.

--yliu

2013-01-08 21:19:21

by Andy Walls

[permalink] [raw]
Subject: Re: [PATCH 5/5] kfifo: log based kfifo API

Dmitry Torokhov <[email protected]> wrote:

>Hi Yuanhan,
>
>On Tue, Jan 08, 2013 at 10:57:53PM +0800, Yuanhan Liu wrote:
>> The current kfifo API take the kfifo size as input, while it rounds
>> _down_ the size to power of 2 at __kfifo_alloc. This may introduce
>> potential issue.
>>
>> Take the code at drivers/hid/hid-logitech-dj.c as example:
>>
>> if (kfifo_alloc(&djrcv_dev->notif_fifo,
>> DJ_MAX_NUMBER_NOTIFICATIONS * sizeof(struct
>dj_report),
>> GFP_KERNEL)) {
>>
>> Where, DJ_MAX_NUMBER_NOTIFICATIONS is 8, and sizeo of(struct
>dj_report)
>> is 15.
>>
>> Which means it wants to allocate a kfifo buffer which can store 8
>> dj_report entries at once. The expected kfifo buffer size would be
>> 8 * 15 = 120 then. While, in the end, __kfifo_alloc will turn the
>> size to rounddown_power_of_2(120) = 64, and then allocate a buf
>> with 64 bytes, which I don't think this is the original author want.
>>
>> With the new log API, we can do like following:
>>
>> int kfifo_size_order = order_base_2(DJ_MAX_NUMBER_NOTIFICATIONS *
>> sizeof(struct dj_report));
>>
>> if (kfifo_alloc(&djrcv_dev->notif_fifo, kfifo_size_order,
>GFP_KERNEL)) {
>>
>> This make sure we will allocate enough kfifo buffer for holding
>> DJ_MAX_NUMBER_NOTIFICATIONS dj_report entries.
>
>Why don't you simply change __kfifo_alloc to round the allocation up
>instead of down?
>
>Thanks.
>
>--
>Dmitry
>--
>To unsubscribe from this list: send the line "unsubscribe linux-media"
>in
>the body of a message to [email protected]
>More majordomo info at http://vger.kernel.org/majordomo-info.html

Hi Dmitry,

I agree. I don't see the benefit in pushing up the change to a kfifo internal decision/problem to many different places in the kernel.

Regards,
Andy



2013-01-08 18:16:51

by Dmitry Torokhov

[permalink] [raw]
Subject: Re: [PATCH 5/5] kfifo: log based kfifo API

Hi Yuanhan,

On Tue, Jan 08, 2013 at 10:57:53PM +0800, Yuanhan Liu wrote:
> The current kfifo API take the kfifo size as input, while it rounds
> _down_ the size to power of 2 at __kfifo_alloc. This may introduce
> potential issue.
>
> Take the code at drivers/hid/hid-logitech-dj.c as example:
>
> if (kfifo_alloc(&djrcv_dev->notif_fifo,
> DJ_MAX_NUMBER_NOTIFICATIONS * sizeof(struct dj_report),
> GFP_KERNEL)) {
>
> Where, DJ_MAX_NUMBER_NOTIFICATIONS is 8, and sizeo of(struct dj_report)
> is 15.
>
> Which means it wants to allocate a kfifo buffer which can store 8
> dj_report entries at once. The expected kfifo buffer size would be
> 8 * 15 = 120 then. While, in the end, __kfifo_alloc will turn the
> size to rounddown_power_of_2(120) = 64, and then allocate a buf
> with 64 bytes, which I don't think this is the original author want.
>
> With the new log API, we can do like following:
>
> int kfifo_size_order = order_base_2(DJ_MAX_NUMBER_NOTIFICATIONS *
> sizeof(struct dj_report));
>
> if (kfifo_alloc(&djrcv_dev->notif_fifo, kfifo_size_order, GFP_KERNEL)) {
>
> This make sure we will allocate enough kfifo buffer for holding
> DJ_MAX_NUMBER_NOTIFICATIONS dj_report entries.

Why don't you simply change __kfifo_alloc to round the allocation up
instead of down?

Thanks.

--
Dmitry