バッファリング関係の修正 など

driver:
ringbuffer: メモリの再確保を出来るだけ避けるように変更
ringbuffer: メモリ確保時のパラーメータを変更
px4: ringbufferの変更に合わせた変更
px4: ringbufferのサイズの算出方法を変更
px4: atomicなcontext内でアクセスする動的なメモリ領域はGFP_ATOMICを使用して割り当てられたもののみとするように変更
px4: すでに使用されているtsdevのopenが成功してしまうことがある不具合を修正
This commit is contained in:
nns779
2018-07-10 23:27:18 +09:00
parent 7760c09786
commit f3645e30fd
4 changed files with 132 additions and 39 deletions

View File

@@ -1,7 +1,7 @@
KVER = $(shell uname -r)
KVER := $(shell uname -r)
KBUILD_DIR := /lib/modules/$(KVER)/build
INSTALL_DIR := /lib/modules/$(KVER)/misc
CURRENT_DIR = $(shell pwd)
CURRENT_DIR := $(shell pwd)
VERBOSE := 0
DEBUG := 0
TARGET := px4_drv.ko
@@ -17,7 +17,9 @@ endif
obj-m := px4_drv.o
px4_drv-objs := px4.o it930x-bus.o it930x.o tc90522.o rt710.o r850_lite.o r850_channel.o ringbuffer.o
all:
all: module
module:
$(MAKE) -C $(KBUILD_DIR) M=$(CURRENT_DIR) KBUILD_VERBOSE=$(VERBOSE) modules
clean:

View File

@@ -62,7 +62,7 @@ struct px4_tsdev {
struct rt710_tuner rt710; // for ISDB-S
} t;
atomic_t streaming; // 0: not streaming, !0: streaming
struct ringbuffer rgbuf;
struct ringbuffer *rgbuf;
};
struct px4_device {
@@ -78,6 +78,7 @@ struct px4_device {
struct cdev cdev;
unsigned int streaming_count;
struct px4_tsdev tsdev[TSDEV_NUM];
struct ringbuffer **rgbuf;
};
MODULE_AUTHOR("nns779");
@@ -93,6 +94,7 @@ static struct px4_device *devs[MAX_DEVICE];
static bool devs_reserve[MAX_DEVICE];
static unsigned int xfer_packets = 816;
static unsigned int max_urbs = 6;
static unsigned int tsdev_max_packets = 1024;
static bool no_dma = false;
module_param(xfer_packets, uint, S_IRUSR | S_IWUSR);
@@ -101,6 +103,9 @@ MODULE_PARM_DESC(xfer_packets, "Number of transfer packets from the device. (def
module_param(max_urbs, uint, S_IRUSR | S_IWUSR);
MODULE_PARM_DESC(max_urbs, "Maximum number of URBs. (default: 6)");
module_param(tsdev_max_packets, uint, S_IRUSR | S_IWUSR);
MODULE_PARM_DESC(tsdev_max_packets, "Maximum number of packets buffering in tsdev. (default: 1024)");
module_param(no_dma, bool, S_IRUSR | S_IWUSR);
static const struct usb_device_id px4_usb_ids[] = {
@@ -115,6 +120,7 @@ MODULE_DEVICE_TABLE(usb, px4_usb_ids);
static int px4_init(struct px4_device *px4)
{
int ret = 0;
int i;
atomic_set(&px4->ref, 1);
@@ -132,10 +138,16 @@ static int px4_init(struct px4_device *px4)
tsdev->lnb_power = false;
tsdev->px4 = px4;
atomic_set(&tsdev->streaming, 0);
ringbuffer_init(&tsdev->rgbuf);
ret = ringbuffer_create(&tsdev->rgbuf);
if (ret)
break;
ringbuffer_alloc(tsdev->rgbuf, 188 * tsdev_max_packets);
px4->rgbuf[i] = tsdev->rgbuf;
}
return 0;
return ret;
}
static int px4_term(struct px4_device *px4)
@@ -145,7 +157,7 @@ static int px4_term(struct px4_device *px4)
for (i = 0; i < TSDEV_NUM; i++) {
struct px4_tsdev *tsdev = &px4->tsdev[i];
ringbuffer_term(&tsdev->rgbuf);
ringbuffer_destroy(tsdev->rgbuf);
}
return 0;
@@ -345,7 +357,7 @@ static bool px4_ts_sync(u8 **buf, u32 *len, bool *sync_remain)
return ret;
}
static void px4_ts_write(struct px4_device *px4, u8 **buf, u32 *len)
static void px4_ts_write(struct ringbuffer **rgbuf, u8 **buf, u32 *len)
{
u8 *p = *buf;
u32 remain = *len;
@@ -355,7 +367,7 @@ static void px4_ts_write(struct px4_device *px4, u8 **buf, u32 *len)
if (id && id < 5) {
p[0] = 0x47;
ringbuffer_write(&px4->tsdev[id - 1].rgbuf, p, 188);
ringbuffer_write_atomic(rgbuf[id - 1], p, 188);
} else {
pr_debug("px4_ts_write: unknown id %d\n", id);
}
@@ -372,7 +384,7 @@ static void px4_ts_write(struct px4_device *px4, u8 **buf, u32 *len)
static int px4_on_stream(void *context, void *buf, u32 len)
{
struct px4_device *px4 = context;
struct ringbuffer **rgbuf = context;
u8 *p = buf;
u32 remain = len;
bool sync_remain = false;
@@ -381,7 +393,7 @@ static int px4_on_stream(void *context, void *buf, u32 len)
if (!px4_ts_sync(&p, &remain, &sync_remain))
break;
px4_ts_write(px4, &p, &remain);
px4_ts_write(rgbuf, &p, &remain);
}
if (sync_remain)
@@ -739,7 +751,6 @@ static int px4_tsdev_set_channel(struct px4_tsdev *tsdev, struct ptx_freq *freq)
static int px4_tsdev_start_streaming(struct px4_tsdev *tsdev)
{
int ret = 0;
size_t buf_size;
struct px4_device *px4 = tsdev->px4;
struct it930x_bus *bus = &px4->it930x.bus;
struct tc90522_demod *tc90522 = &tsdev->tc90522;
@@ -759,8 +770,6 @@ static int px4_tsdev_start_streaming(struct px4_tsdev *tsdev)
it930x_purge_psb(&px4->it930x);
}
buf_size = bus->usb.streaming_xfer_size + bus->usb.streaming_urb_num;
switch (tsdev->isdb) {
case ISDB_S:
// enable ts pins
@@ -786,13 +795,17 @@ static int px4_tsdev_start_streaming(struct px4_tsdev *tsdev)
if (ret)
goto fail;
ret = ringbuffer_alloc(&tsdev->rgbuf, buf_size);
ret = ringbuffer_alloc(tsdev->rgbuf, 188 * tsdev_max_packets);
if (ret)
goto fail;
ret = ringbuffer_start(tsdev->rgbuf);
if (ret)
goto fail;
if (!px4->streaming_count) {
pr_debug("px4_tsdev_start_streaming %d:%u: starting...\n", px4->dev_idx, tsdev->id);
ret = it930x_bus_start_streaming(bus, px4_on_stream, px4);
ret = it930x_bus_start_streaming(bus, px4_on_stream, px4->rgbuf);
if (ret) {
pr_debug("px4_tsdev_start_streaming %d:%u: it930x_bus_start_streaming() failed.\n", px4->dev_idx, tsdev->id);
goto fail_after_ringbuffer;
@@ -806,7 +819,7 @@ static int px4_tsdev_start_streaming(struct px4_tsdev *tsdev)
return ret;
fail_after_ringbuffer:
ringbuffer_free(&tsdev->rgbuf);
ringbuffer_stop(tsdev->rgbuf);
fail:
atomic_set(&tsdev->streaming, 0);
@@ -833,7 +846,7 @@ static int px4_tsdev_stop_streaming(struct px4_tsdev *tsdev, bool avail)
it930x_bus_stop_streaming(&px4->it930x.bus);
}
ringbuffer_free(&tsdev->rgbuf);
ringbuffer_stop(tsdev->rgbuf);
if (!avail)
return 0;
@@ -926,7 +939,7 @@ static int px4_tsdev_open(struct inode *inode, struct file *file)
if (tsdev->open) {
// already used by another
ret = -EIO;
goto fail;
goto fail_already_used;
}
tsdev->open = true;
@@ -974,6 +987,7 @@ fail_after_power:
px4_set_power(px4, false);
fail:
tsdev->open = false;
fail_already_used:
mutex_unlock(&px4->lock);
px4_unref(px4);
@@ -1001,7 +1015,7 @@ static ssize_t px4_tsdev_read(struct file *file, char __user *buf, size_t count,
return -EIO;
rd = count;
ret = ringbuffer_read_to_user(&tsdev->rgbuf, buf, &rd);
ret = ringbuffer_read_to_user(tsdev->rgbuf, buf, &rd);
return (ret) ? (ret) : (rd);
}
@@ -1220,9 +1234,16 @@ static int px4_probe(struct usb_interface *intf, const struct usb_device_id *id)
px4 = kzalloc(sizeof(*px4), GFP_KERNEL);
if (!px4) {
pr_err("px4_probe: kzalloc returns NULL.\n");
pr_err("px4_probe: kzalloc() returns NULL.\n");
ret = -ENOMEM;
goto fail;
goto fail_before_bus;
}
px4->rgbuf = (struct ringbuffer **)kzalloc(sizeof(*px4->rgbuf) * TSDEV_NUM, GFP_ATOMIC);
if (!px4->rgbuf) {
pr_err("px4_probe: kzalloc() returns NULL (2).\n");
ret = -ENOMEM;
goto fail_before_bus;
}
px4->dev_idx = dev_idx;
@@ -1245,7 +1266,7 @@ static int px4_probe(struct usb_interface *intf, const struct usb_device_id *id)
ret = px4_init(px4);
if (ret)
goto fail;
goto fail_before_bus;
// Initialize bus operator
@@ -1256,7 +1277,7 @@ static int px4_probe(struct usb_interface *intf, const struct usb_device_id *id)
ret = it930x_bus_init(bus);
if (ret)
goto fail;
goto fail_before_bus;
// Load config from eeprom
@@ -1325,13 +1346,20 @@ static int px4_probe(struct usb_interface *intf, const struct usb_device_id *id)
usb_set_intfdata(intf, px4);
return 0;
fail:
it930x_bus_term(&px4->it930x.bus);
fail_before_bus:
if (px4) {
it930x_bus_term(&px4->it930x.bus);
if (px4->rgbuf)
kfree(px4->rgbuf);
kfree(px4);
}
mutex_lock(&glock);
devs_reserve[dev_idx] = false;
mutex_unlock(&glock);
return ret;
}
@@ -1374,6 +1402,7 @@ static void px4_disconnect(struct usb_interface *intf)
// uninitialize
px4_term(px4);
it930x_bus_term(&px4->it930x.bus);
kfree(px4->rgbuf);
kfree(px4);
return;

View File

@@ -11,7 +11,7 @@
#include "ringbuffer.h"
int ringbuffer_init(struct ringbuffer *ringbuffer)
static int _ringbuffer_init(struct ringbuffer *ringbuffer)
{
spin_lock_init(&ringbuffer->lock);
atomic_set(&ringbuffer->avail, 0);
@@ -28,9 +28,35 @@ int ringbuffer_init(struct ringbuffer *ringbuffer)
return 0;
}
int ringbuffer_term(struct ringbuffer *ringbuffer)
int ringbuffer_create(struct ringbuffer **ringbuffer)
{
return ringbuffer_free(ringbuffer);
int ret = 0;
struct ringbuffer *p;
*ringbuffer = NULL;
p = kzalloc(sizeof(struct ringbuffer), GFP_ATOMIC);
if (!p)
return -ENOMEM;
ret = _ringbuffer_init(p);
if (!ret)
*ringbuffer = p;
else
kfree(p);
return ret;
}
int ringbuffer_destroy(struct ringbuffer *ringbuffer)
{
int ret = 0;
ret = ringbuffer_free(ringbuffer);
if (!ret)
kfree(ringbuffer);
return ret;
}
static void _ringbuffer_free(struct ringbuffer *ringbuffer)
@@ -58,12 +84,16 @@ int ringbuffer_alloc(struct ringbuffer *ringbuffer, size_t size)
wake_up(&ringbuffer->data_wait);
wait_event(ringbuffer->wait, !atomic_read(&ringbuffer->rw_cnt));
if (ringbuffer->buf)
if (ringbuffer->buf) {
if (ringbuffer->buf_size == size)
goto exit;
_ringbuffer_free(ringbuffer);
}
// Allocate
ringbuffer->buf = (u8 *)__get_free_pages(GFP_KERNEL, get_order(size));
ringbuffer->buf = (u8 *)__get_free_pages(GFP_ATOMIC, get_order(size));
if (!ringbuffer->buf) {
ret = -ENOMEM;
goto exit;
@@ -74,8 +104,6 @@ int ringbuffer_alloc(struct ringbuffer *ringbuffer, size_t size)
ringbuffer->tail_pos = 0;
ringbuffer->head_pos = 0;
atomic_set(&ringbuffer->avail, 1);
exit:
// Release lock
atomic_sub(1, &ringbuffer->wait_cnt);
@@ -87,9 +115,6 @@ int ringbuffer_free(struct ringbuffer *ringbuffer)
{
int ret = 0;
if (!ringbuffer->buf)
return 0;
// Acquire lock
if (atomic_add_return(1, &ringbuffer->wait_cnt) != 1) {
// Someone is waiting
@@ -100,6 +125,9 @@ int ringbuffer_free(struct ringbuffer *ringbuffer)
wake_up(&ringbuffer->data_wait);
wait_event(ringbuffer->wait, !atomic_read(&ringbuffer->rw_cnt));
if (!ringbuffer->buf)
goto exit;
_ringbuffer_free(ringbuffer);
exit:
@@ -109,7 +137,39 @@ exit:
return 0;
}
int ringbuffer_write(struct ringbuffer *ringbuffer, const void *data, size_t len)
int ringbuffer_start(struct ringbuffer *ringbuffer)
{
int ret = 0;
if (atomic_read(&ringbuffer->avail))
return 0;
// Acquire lock for read buffer pointer
if (atomic_add_return(1, &ringbuffer->wait_cnt) != 1) {
// Someone is waiting
ret = -EAGAIN;
goto exit;
}
if (ringbuffer->buf && ringbuffer->buf_size)
atomic_set(&ringbuffer->avail, 1);
exit:
// Release lock
atomic_sub(1, &ringbuffer->wait_cnt);
return 0;
}
int ringbuffer_stop(struct ringbuffer *ringbuffer)
{
atomic_set(&ringbuffer->avail, 0);
wake_up(&ringbuffer->data_wait);
return 0;
}
int ringbuffer_write_atomic(struct ringbuffer *ringbuffer, const void *data, size_t len)
{
unsigned long flags;
const u8 *p = data;

View File

@@ -22,11 +22,13 @@ struct ringbuffer {
size_t head_pos; // read
};
int ringbuffer_init(struct ringbuffer *ringbuffer);
int ringbuffer_term(struct ringbuffer *ringbuffer);
int ringbuffer_create(struct ringbuffer **ringbuffer);
int ringbuffer_destroy(struct ringbuffer *ringbuffer);
int ringbuffer_alloc(struct ringbuffer *ringbuffer, size_t size);
int ringbuffer_free(struct ringbuffer *ringbuffer);
int ringbuffer_write(struct ringbuffer *ringbuffer, const void *data, size_t len);
int ringbuffer_start(struct ringbuffer *ringbuffer);
int ringbuffer_stop(struct ringbuffer *ringbuffer);
int ringbuffer_write_atomic(struct ringbuffer *ringbuffer, const void *data, size_t len);
int ringbuffer_read_to_user(struct ringbuffer *ringbuffer, void __user *buf, size_t *len);
#endif