[RFC PATCH 2/9] media: request: add generic queue
Add a generic request queue that supports most use-case and should be usable as-is by drivers without special hardware features. The generic queue stores the requests into a FIFO list and executes them sequentially. Signed-off-by: Alexandre Courbot--- drivers/media/Makefile | 2 +- drivers/media/media-request-queue-generic.c | 150 include/media/media-request.h | 8 ++ 3 files changed, 159 insertions(+), 1 deletion(-) create mode 100644 drivers/media/media-request-queue-generic.c diff --git a/drivers/media/Makefile b/drivers/media/Makefile index 985d35ec6b29..90117fff1339 100644 --- a/drivers/media/Makefile +++ b/drivers/media/Makefile @@ -4,7 +4,7 @@ # media-objs := media-device.o media-devnode.o media-entity.o \ - media-request.o + media-request.o media-request-queue-generic.o # # I2C drivers should come before other drivers, otherwise they'll fail diff --git a/drivers/media/media-request-queue-generic.c b/drivers/media/media-request-queue-generic.c new file mode 100644 index ..780414b6d46a --- /dev/null +++ b/drivers/media/media-request-queue-generic.c @@ -0,0 +1,150 @@ +/* + * Generic request queue implementation. + * + * Copyright (C) 2017, The Chromium OS Authors. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include + +#include +#include + +/** + * struct media_request_generic - request enabled for the generic queue + * + * @base: base request member + * @queue: entry in media_request_queue_generic::queued_requests + */ +struct media_request_generic { + struct media_request base; + struct list_head queue; +}; +#define to_generic_request(r) \ + container_of(r, struct media_request_generic, base) + +/** + * struct media_request_queue_generic - generic request queue implementation + * + * Implements a simple request queue, where the next queued request is executed + * as soon as the previous one completes. + * + * @base: base request queue member + * @mutex: protects the queue + * @queued_requests: list of requests to be sequentially executed + */ +struct media_request_queue_generic { + struct media_request_queue base; + + struct list_head queued_requests; +}; +#define to_generic_queue(q) \ + container_of(q, struct media_request_queue_generic, base) + +static struct media_request * +media_request_generic_alloc(struct media_request_queue *queue) +{ + struct media_request_generic *req; + + req = kzalloc(sizeof(*req), GFP_KERNEL); + if (!req) + return ERR_PTR(-ENOMEM); + + return >base; +} + +static void media_request_generic_free(struct media_request_queue *queue, + struct media_request *_req) +{ + struct media_request_generic *req = to_generic_request(_req); + + kfree(req); +} + +static void schedule_next_req(struct media_request_queue_generic *queue) +{ + struct media_request_generic *req; + struct media_request_entity_data *data; + + req = list_first_entry_or_null(>queued_requests, typeof(*req), + queue); + if (!req) + return; + + list_del(>queue); + queue->base.active_request = >base; + + list_for_each_entry(data, >base.data, list) { + int ret; + + ret = data->entity->req_ops->apply_data(data); + } + + list_for_each_entry(data, >base.data, list) { + data->entity->ops->process_request(>base, data); + } +} + +static void media_request_generic_complete(struct media_request_queue *_queue) +{ + struct media_request_queue_generic *queue = to_generic_queue(_queue); + + queue->base.active_request = NULL; + schedule_next_req(queue); +} + +static int media_request_generic_queue(struct media_request_queue *_queue, + struct media_request *_req) +{ + struct media_request_queue_generic *queue = to_generic_queue(_queue); + struct media_request_generic *req = to_generic_request(_req); + + list_add_tail(>queue, >queued_requests); + + if (!queue->base.active_request) + schedule_next_req(queue); + + return 0; +} + +static void +media_request_generic_queue_release(struct media_request_queue *_queue) +{ + struct media_request_queue_generic *queue = to_generic_queue(_queue); + + media_request_queue_release(>base); + kfree(queue);
[RFC PATCH 2/9] media: request: add generic queue
Add a generic request queue that supports most use-case and should be usable as-is by drivers without special hardware features. The generic queue stores the requests into a FIFO list and executes them sequentially. Signed-off-by: Alexandre Courbot --- drivers/media/Makefile | 2 +- drivers/media/media-request-queue-generic.c | 150 include/media/media-request.h | 8 ++ 3 files changed, 159 insertions(+), 1 deletion(-) create mode 100644 drivers/media/media-request-queue-generic.c diff --git a/drivers/media/Makefile b/drivers/media/Makefile index 985d35ec6b29..90117fff1339 100644 --- a/drivers/media/Makefile +++ b/drivers/media/Makefile @@ -4,7 +4,7 @@ # media-objs := media-device.o media-devnode.o media-entity.o \ - media-request.o + media-request.o media-request-queue-generic.o # # I2C drivers should come before other drivers, otherwise they'll fail diff --git a/drivers/media/media-request-queue-generic.c b/drivers/media/media-request-queue-generic.c new file mode 100644 index ..780414b6d46a --- /dev/null +++ b/drivers/media/media-request-queue-generic.c @@ -0,0 +1,150 @@ +/* + * Generic request queue implementation. + * + * Copyright (C) 2017, The Chromium OS Authors. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include + +#include +#include + +/** + * struct media_request_generic - request enabled for the generic queue + * + * @base: base request member + * @queue: entry in media_request_queue_generic::queued_requests + */ +struct media_request_generic { + struct media_request base; + struct list_head queue; +}; +#define to_generic_request(r) \ + container_of(r, struct media_request_generic, base) + +/** + * struct media_request_queue_generic - generic request queue implementation + * + * Implements a simple request queue, where the next queued request is executed + * as soon as the previous one completes. + * + * @base: base request queue member + * @mutex: protects the queue + * @queued_requests: list of requests to be sequentially executed + */ +struct media_request_queue_generic { + struct media_request_queue base; + + struct list_head queued_requests; +}; +#define to_generic_queue(q) \ + container_of(q, struct media_request_queue_generic, base) + +static struct media_request * +media_request_generic_alloc(struct media_request_queue *queue) +{ + struct media_request_generic *req; + + req = kzalloc(sizeof(*req), GFP_KERNEL); + if (!req) + return ERR_PTR(-ENOMEM); + + return >base; +} + +static void media_request_generic_free(struct media_request_queue *queue, + struct media_request *_req) +{ + struct media_request_generic *req = to_generic_request(_req); + + kfree(req); +} + +static void schedule_next_req(struct media_request_queue_generic *queue) +{ + struct media_request_generic *req; + struct media_request_entity_data *data; + + req = list_first_entry_or_null(>queued_requests, typeof(*req), + queue); + if (!req) + return; + + list_del(>queue); + queue->base.active_request = >base; + + list_for_each_entry(data, >base.data, list) { + int ret; + + ret = data->entity->req_ops->apply_data(data); + } + + list_for_each_entry(data, >base.data, list) { + data->entity->ops->process_request(>base, data); + } +} + +static void media_request_generic_complete(struct media_request_queue *_queue) +{ + struct media_request_queue_generic *queue = to_generic_queue(_queue); + + queue->base.active_request = NULL; + schedule_next_req(queue); +} + +static int media_request_generic_queue(struct media_request_queue *_queue, + struct media_request *_req) +{ + struct media_request_queue_generic *queue = to_generic_queue(_queue); + struct media_request_generic *req = to_generic_request(_req); + + list_add_tail(>queue, >queued_requests); + + if (!queue->base.active_request) + schedule_next_req(queue); + + return 0; +} + +static void +media_request_generic_queue_release(struct media_request_queue *_queue) +{ + struct media_request_queue_generic *queue = to_generic_queue(_queue); + + media_request_queue_release(>base); + kfree(queue); +} + +static const
[RFC PATCH 4/9] videodev2.h: Add request field to v4l2_buffer
From: Hans VerkuilWhen queuing buffers allow for passing the request ID that should be associated with this buffer. Signed-off-by: Hans Verkuil [acour...@chromium.org: make request ID 32-bit] Signed-off-by: Alexandre Courbot --- drivers/media/usb/cpia2/cpia2_v4l.c | 2 +- drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 7 --- drivers/media/v4l2-core/v4l2-ioctl.c | 4 ++-- drivers/media/v4l2-core/videobuf2-v4l2.c | 3 ++- include/media/videobuf2-v4l2.h| 2 ++ include/uapi/linux/videodev2.h| 3 ++- 6 files changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/media/usb/cpia2/cpia2_v4l.c b/drivers/media/usb/cpia2/cpia2_v4l.c index 3dedd83f0b19..7217dde95a8a 100644 --- a/drivers/media/usb/cpia2/cpia2_v4l.c +++ b/drivers/media/usb/cpia2/cpia2_v4l.c @@ -948,7 +948,7 @@ static int cpia2_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf) buf->sequence = cam->buffers[buf->index].seq; buf->m.offset = cam->buffers[buf->index].data - cam->frame_buffer; buf->length = cam->frame_size; - buf->reserved2 = 0; + buf->request = 0; buf->reserved = 0; memset(>timecode, 0, sizeof(buf->timecode)); diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c index 821f2aa299ae..94f07c3b0b53 100644 --- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c @@ -370,7 +370,7 @@ struct v4l2_buffer32 { __s32 fd; } m; __u32 length; - __u32 reserved2; + __u32 request; __u32 reserved; }; @@ -438,7 +438,8 @@ static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user get_user(kp->type, >type) || get_user(kp->flags, >flags) || get_user(kp->memory, >memory) || - get_user(kp->length, >length)) + get_user(kp->length, >length) || + get_user(kp->request, >request)) return -EFAULT; if (V4L2_TYPE_IS_OUTPUT(kp->type)) @@ -533,7 +534,7 @@ static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user put_user(kp->timestamp.tv_usec, >timestamp.tv_usec) || copy_to_user(>timecode, >timecode, sizeof(struct v4l2_timecode)) || put_user(kp->sequence, >sequence) || - put_user(kp->reserved2, >reserved2) || + put_user(kp->request, >request) || put_user(kp->reserved, >reserved) || put_user(kp->length, >length)) return -EFAULT; diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index ec4ecd5aa8bf..8d041247e97f 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -437,13 +437,13 @@ static void v4l_print_buffer(const void *arg, bool write_only) const struct v4l2_plane *plane; int i; - pr_cont("%02ld:%02d:%02d.%08ld index=%d, type=%s, flags=0x%08x, field=%s, sequence=%d, memory=%s", + pr_cont("%02ld:%02d:%02d.%08ld index=%d, type=%s, request=%u, flags=0x%08x, field=%s, sequence=%d, memory=%s", p->timestamp.tv_sec / 3600, (int)(p->timestamp.tv_sec / 60) % 60, (int)(p->timestamp.tv_sec % 60), (long)p->timestamp.tv_usec, p->index, - prt_names(p->type, v4l2_type_names), + prt_names(p->type, v4l2_type_names), p->request, p->flags, prt_names(p->field, v4l2_field_names), p->sequence, prt_names(p->memory, v4l2_memory_names)); diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c b/drivers/media/v4l2-core/videobuf2-v4l2.c index 0c0669976bdc..bde7b8a3a303 100644 --- a/drivers/media/v4l2-core/videobuf2-v4l2.c +++ b/drivers/media/v4l2-core/videobuf2-v4l2.c @@ -203,7 +203,7 @@ static void __fill_v4l2_buffer(struct vb2_buffer *vb, void *pb) b->timestamp = ns_to_timeval(vb->timestamp); b->timecode = vbuf->timecode; b->sequence = vbuf->sequence; - b->reserved2 = 0; + b->request = vbuf->request; b->reserved = 0; if (q->is_multiplanar) { @@ -320,6 +320,7 @@ static int __fill_vb2_buffer(struct vb2_buffer *vb, } vb->timestamp = 0; vbuf->sequence = 0; + vbuf->request = b->request; if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) { if (b->memory == VB2_MEMORY_USERPTR) { diff --git a/include/media/videobuf2-v4l2.h b/include/media/videobuf2-v4l2.h index 036127c54bbf..ef2be0ccff14 100644 --- a/include/media/videobuf2-v4l2.h +++
[RFC PATCH 4/9] videodev2.h: Add request field to v4l2_buffer
From: Hans Verkuil When queuing buffers allow for passing the request ID that should be associated with this buffer. Signed-off-by: Hans Verkuil [acour...@chromium.org: make request ID 32-bit] Signed-off-by: Alexandre Courbot --- drivers/media/usb/cpia2/cpia2_v4l.c | 2 +- drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 7 --- drivers/media/v4l2-core/v4l2-ioctl.c | 4 ++-- drivers/media/v4l2-core/videobuf2-v4l2.c | 3 ++- include/media/videobuf2-v4l2.h| 2 ++ include/uapi/linux/videodev2.h| 3 ++- 6 files changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/media/usb/cpia2/cpia2_v4l.c b/drivers/media/usb/cpia2/cpia2_v4l.c index 3dedd83f0b19..7217dde95a8a 100644 --- a/drivers/media/usb/cpia2/cpia2_v4l.c +++ b/drivers/media/usb/cpia2/cpia2_v4l.c @@ -948,7 +948,7 @@ static int cpia2_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf) buf->sequence = cam->buffers[buf->index].seq; buf->m.offset = cam->buffers[buf->index].data - cam->frame_buffer; buf->length = cam->frame_size; - buf->reserved2 = 0; + buf->request = 0; buf->reserved = 0; memset(>timecode, 0, sizeof(buf->timecode)); diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c index 821f2aa299ae..94f07c3b0b53 100644 --- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c @@ -370,7 +370,7 @@ struct v4l2_buffer32 { __s32 fd; } m; __u32 length; - __u32 reserved2; + __u32 request; __u32 reserved; }; @@ -438,7 +438,8 @@ static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user get_user(kp->type, >type) || get_user(kp->flags, >flags) || get_user(kp->memory, >memory) || - get_user(kp->length, >length)) + get_user(kp->length, >length) || + get_user(kp->request, >request)) return -EFAULT; if (V4L2_TYPE_IS_OUTPUT(kp->type)) @@ -533,7 +534,7 @@ static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user put_user(kp->timestamp.tv_usec, >timestamp.tv_usec) || copy_to_user(>timecode, >timecode, sizeof(struct v4l2_timecode)) || put_user(kp->sequence, >sequence) || - put_user(kp->reserved2, >reserved2) || + put_user(kp->request, >request) || put_user(kp->reserved, >reserved) || put_user(kp->length, >length)) return -EFAULT; diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index ec4ecd5aa8bf..8d041247e97f 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -437,13 +437,13 @@ static void v4l_print_buffer(const void *arg, bool write_only) const struct v4l2_plane *plane; int i; - pr_cont("%02ld:%02d:%02d.%08ld index=%d, type=%s, flags=0x%08x, field=%s, sequence=%d, memory=%s", + pr_cont("%02ld:%02d:%02d.%08ld index=%d, type=%s, request=%u, flags=0x%08x, field=%s, sequence=%d, memory=%s", p->timestamp.tv_sec / 3600, (int)(p->timestamp.tv_sec / 60) % 60, (int)(p->timestamp.tv_sec % 60), (long)p->timestamp.tv_usec, p->index, - prt_names(p->type, v4l2_type_names), + prt_names(p->type, v4l2_type_names), p->request, p->flags, prt_names(p->field, v4l2_field_names), p->sequence, prt_names(p->memory, v4l2_memory_names)); diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c b/drivers/media/v4l2-core/videobuf2-v4l2.c index 0c0669976bdc..bde7b8a3a303 100644 --- a/drivers/media/v4l2-core/videobuf2-v4l2.c +++ b/drivers/media/v4l2-core/videobuf2-v4l2.c @@ -203,7 +203,7 @@ static void __fill_v4l2_buffer(struct vb2_buffer *vb, void *pb) b->timestamp = ns_to_timeval(vb->timestamp); b->timecode = vbuf->timecode; b->sequence = vbuf->sequence; - b->reserved2 = 0; + b->request = vbuf->request; b->reserved = 0; if (q->is_multiplanar) { @@ -320,6 +320,7 @@ static int __fill_vb2_buffer(struct vb2_buffer *vb, } vb->timestamp = 0; vbuf->sequence = 0; + vbuf->request = b->request; if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) { if (b->memory == VB2_MEMORY_USERPTR) { diff --git a/include/media/videobuf2-v4l2.h b/include/media/videobuf2-v4l2.h index 036127c54bbf..ef2be0ccff14 100644 --- a/include/media/videobuf2-v4l2.h +++ b/include/media/videobuf2-v4l2.h @@ -31,6 +31,7 @@ * @field: enum
[RFC PATCH 8/9] media: vim2m: add media device
Request API requires a media node. Add one to the vim2m driver so we can use requests with it. Signed-off-by: Alexandre Courbot--- drivers/media/platform/vim2m.c | 24 1 file changed, 24 insertions(+) diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/vim2m.c index b01fba020d5f..a32e8a7950eb 100644 --- a/drivers/media/platform/vim2m.c +++ b/drivers/media/platform/vim2m.c @@ -140,6 +140,9 @@ static struct vim2m_fmt *find_format(struct v4l2_format *f) struct vim2m_dev { struct v4l2_device v4l2_dev; struct video_device vfd; +#ifdef CONFIG_MEDIA_CONTROLLER + struct media_device mdev; +#endif atomic_tnum_inst; struct mutexdev_mutex; @@ -1001,6 +1004,13 @@ static int vim2m_probe(struct platform_device *pdev) spin_lock_init(>irqlock); +#ifdef CONFIG_MEDIA_CONTROLLER + dev->mdev.dev = >dev; + strlcpy(dev->mdev.model, "vim2m", sizeof(dev->mdev.model)); + media_device_init(>mdev); + dev->v4l2_dev.mdev = >mdev; +#endif + ret = v4l2_device_register(>dev, >v4l2_dev); if (ret) return ret; @@ -1034,6 +1044,13 @@ static int vim2m_probe(struct platform_device *pdev) goto err_m2m; } +#ifdef CONFIG_MEDIA_CONTROLLER + /* Register the media device node */ + ret = media_device_register(>mdev); + if (ret) + goto err_m2m; +#endif + return 0; err_m2m: @@ -1050,6 +1067,13 @@ static int vim2m_remove(struct platform_device *pdev) struct vim2m_dev *dev = platform_get_drvdata(pdev); v4l2_info(>v4l2_dev, "Removing " MEM2MEM_NAME); + +#ifdef CONFIG_MEDIA_CONTROLLER + if (media_devnode_is_registered(dev->mdev.devnode)) + media_device_unregister(>mdev); + media_device_cleanup(>mdev); +#endif + v4l2_m2m_release(dev->m2m_dev); del_timer_sync(>timer); video_unregister_device(>vfd); -- 2.15.1.504.g5279b80103-goog
[RFC PATCH 6/9] media: vb2: add support for requests in QBUF ioctl
Support the request argument of the QBUF ioctl. Signed-off-by: Alexandre Courbot--- drivers/media/v4l2-core/v4l2-ioctl.c | 93 +++- 1 file changed, 92 insertions(+), 1 deletion(-) diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 8d041247e97f..28f9c368563e 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -29,6 +29,7 @@ #include #include #include +#include #include @@ -965,6 +966,81 @@ static int check_fmt(struct file *file, enum v4l2_buf_type type) return -EINVAL; } +/* + * Validate that a given request can be used during an ioctl. + * + * When using the request API, request file descriptors must be matched against + * the actual request object. User-space can pass any file descriptor, so we + * need to make sure the call is valid before going further. + * + * This function looks up the request and associated data and performs the + * following sanity checks: + * + * * Make sure that the entity supports requests, + * * Make sure that the entity belongs to the media_device managing the passed + * request, + * * Make sure that the entity data (if any) is associated to the current file + * handler. + * + * This function returns a pointer to the valid request, or and error code in + * case of failure. When successful, a reference to the request is acquired and + * must be properly released. + */ +#ifdef CONFIG_MEDIA_CONTROLLER +static struct media_request * +check_request(int request, struct file *file, void *fh) +{ + struct media_request *req = NULL; + struct video_device *vfd = video_devdata(file); + struct v4l2_fh *vfh = + test_bit(V4L2_FL_USES_V4L2_FH, >flags) ? fh : NULL; + struct media_entity *entity = >entity; + const struct media_entity *ent; + struct media_request_entity_data *data; + bool found = false; + + if (!entity) + return ERR_PTR(-EINVAL); + + /* Check that the entity supports requests */ + if (!entity->req_ops) + return ERR_PTR(-ENOTSUPP); + + req = media_request_get_from_fd(request); + if (!req) + return ERR_PTR(-EINVAL); + + /* Validate that the entity belongs to the media_device managing +* the request queue */ + media_device_for_each_entity(ent, req->queue->mdev) { + if (entity == ent) { + found = true; + break; + } + } + if (!found) { + media_request_put(req); + return ERR_PTR(-EINVAL); + } + + /* Validate that the entity's data belongs to the correct fh */ + data = media_request_get_entity_data(req, entity, vfh); + if (IS_ERR(data)) { + media_request_put(req); + return ERR_PTR(PTR_ERR(data)); + } + + return req; +} +#else /* CONFIG_MEDIA_CONTROLLER */ +static struct media_request * +check_request(int request, struct file *file, void *fh) +{ + return ERR_PTR(-ENOTSUPP); +} + +#endif /* CONFIG_MEDIA_CONTROLLER */ + static void v4l_sanitize_format(struct v4l2_format *fmt) { unsigned int offset; @@ -1902,10 +1978,25 @@ static int v4l_querybuf(const struct v4l2_ioctl_ops *ops, static int v4l_qbuf(const struct v4l2_ioctl_ops *ops, struct file *file, void *fh, void *arg) { + struct media_request *req = NULL; struct v4l2_buffer *p = arg; int ret = check_fmt(file, p->type); - return ret ? ret : ops->vidioc_qbuf(file, fh, p); + if (ret) + return ret; + + if (p->request > 0) { + req = check_request(p->request, file, fh); + if (IS_ERR(req)) + return PTR_ERR(req); + } + + ret = ops->vidioc_qbuf(file, fh, p); + + if (req) + media_request_put(req); + + return ret; } static int v4l_dqbuf(const struct v4l2_ioctl_ops *ops, -- 2.15.1.504.g5279b80103-goog
[RFC PATCH 8/9] media: vim2m: add media device
Request API requires a media node. Add one to the vim2m driver so we can use requests with it. Signed-off-by: Alexandre Courbot --- drivers/media/platform/vim2m.c | 24 1 file changed, 24 insertions(+) diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/vim2m.c index b01fba020d5f..a32e8a7950eb 100644 --- a/drivers/media/platform/vim2m.c +++ b/drivers/media/platform/vim2m.c @@ -140,6 +140,9 @@ static struct vim2m_fmt *find_format(struct v4l2_format *f) struct vim2m_dev { struct v4l2_device v4l2_dev; struct video_device vfd; +#ifdef CONFIG_MEDIA_CONTROLLER + struct media_device mdev; +#endif atomic_tnum_inst; struct mutexdev_mutex; @@ -1001,6 +1004,13 @@ static int vim2m_probe(struct platform_device *pdev) spin_lock_init(>irqlock); +#ifdef CONFIG_MEDIA_CONTROLLER + dev->mdev.dev = >dev; + strlcpy(dev->mdev.model, "vim2m", sizeof(dev->mdev.model)); + media_device_init(>mdev); + dev->v4l2_dev.mdev = >mdev; +#endif + ret = v4l2_device_register(>dev, >v4l2_dev); if (ret) return ret; @@ -1034,6 +1044,13 @@ static int vim2m_probe(struct platform_device *pdev) goto err_m2m; } +#ifdef CONFIG_MEDIA_CONTROLLER + /* Register the media device node */ + ret = media_device_register(>mdev); + if (ret) + goto err_m2m; +#endif + return 0; err_m2m: @@ -1050,6 +1067,13 @@ static int vim2m_remove(struct platform_device *pdev) struct vim2m_dev *dev = platform_get_drvdata(pdev); v4l2_info(>v4l2_dev, "Removing " MEM2MEM_NAME); + +#ifdef CONFIG_MEDIA_CONTROLLER + if (media_devnode_is_registered(dev->mdev.devnode)) + media_device_unregister(>mdev); + media_device_cleanup(>mdev); +#endif + v4l2_m2m_release(dev->m2m_dev); del_timer_sync(>timer); video_unregister_device(>vfd); -- 2.15.1.504.g5279b80103-goog
[RFC PATCH 6/9] media: vb2: add support for requests in QBUF ioctl
Support the request argument of the QBUF ioctl. Signed-off-by: Alexandre Courbot --- drivers/media/v4l2-core/v4l2-ioctl.c | 93 +++- 1 file changed, 92 insertions(+), 1 deletion(-) diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 8d041247e97f..28f9c368563e 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -29,6 +29,7 @@ #include #include #include +#include #include @@ -965,6 +966,81 @@ static int check_fmt(struct file *file, enum v4l2_buf_type type) return -EINVAL; } +/* + * Validate that a given request can be used during an ioctl. + * + * When using the request API, request file descriptors must be matched against + * the actual request object. User-space can pass any file descriptor, so we + * need to make sure the call is valid before going further. + * + * This function looks up the request and associated data and performs the + * following sanity checks: + * + * * Make sure that the entity supports requests, + * * Make sure that the entity belongs to the media_device managing the passed + * request, + * * Make sure that the entity data (if any) is associated to the current file + * handler. + * + * This function returns a pointer to the valid request, or and error code in + * case of failure. When successful, a reference to the request is acquired and + * must be properly released. + */ +#ifdef CONFIG_MEDIA_CONTROLLER +static struct media_request * +check_request(int request, struct file *file, void *fh) +{ + struct media_request *req = NULL; + struct video_device *vfd = video_devdata(file); + struct v4l2_fh *vfh = + test_bit(V4L2_FL_USES_V4L2_FH, >flags) ? fh : NULL; + struct media_entity *entity = >entity; + const struct media_entity *ent; + struct media_request_entity_data *data; + bool found = false; + + if (!entity) + return ERR_PTR(-EINVAL); + + /* Check that the entity supports requests */ + if (!entity->req_ops) + return ERR_PTR(-ENOTSUPP); + + req = media_request_get_from_fd(request); + if (!req) + return ERR_PTR(-EINVAL); + + /* Validate that the entity belongs to the media_device managing +* the request queue */ + media_device_for_each_entity(ent, req->queue->mdev) { + if (entity == ent) { + found = true; + break; + } + } + if (!found) { + media_request_put(req); + return ERR_PTR(-EINVAL); + } + + /* Validate that the entity's data belongs to the correct fh */ + data = media_request_get_entity_data(req, entity, vfh); + if (IS_ERR(data)) { + media_request_put(req); + return ERR_PTR(PTR_ERR(data)); + } + + return req; +} +#else /* CONFIG_MEDIA_CONTROLLER */ +static struct media_request * +check_request(int request, struct file *file, void *fh) +{ + return ERR_PTR(-ENOTSUPP); +} + +#endif /* CONFIG_MEDIA_CONTROLLER */ + static void v4l_sanitize_format(struct v4l2_format *fmt) { unsigned int offset; @@ -1902,10 +1978,25 @@ static int v4l_querybuf(const struct v4l2_ioctl_ops *ops, static int v4l_qbuf(const struct v4l2_ioctl_ops *ops, struct file *file, void *fh, void *arg) { + struct media_request *req = NULL; struct v4l2_buffer *p = arg; int ret = check_fmt(file, p->type); - return ret ? ret : ops->vidioc_qbuf(file, fh, p); + if (ret) + return ret; + + if (p->request > 0) { + req = check_request(p->request, file, fh); + if (IS_ERR(req)) + return PTR_ERR(req); + } + + ret = ops->vidioc_qbuf(file, fh, p); + + if (req) + media_request_put(req); + + return ret; } static int v4l_dqbuf(const struct v4l2_ioctl_ops *ops, -- 2.15.1.504.g5279b80103-goog
[RFC PATCH 5/9] media: vb2: add support for requests
Add throttling support for buffers when requests are in use on a given queue. Buffers associated to a request are kept into the vb2 queue until the request becomes active, at which point all the buffers are passed to the driver. The queue can also signal that is has processed all of a request's buffers. Also add support for the request parameter when handling the QBUF ioctl. Signed-off-by: Alexandre Courbot--- drivers/media/v4l2-core/videobuf2-core.c | 59 drivers/media/v4l2-core/videobuf2-v4l2.c | 29 +++- include/media/videobuf2-core.h | 25 +- 3 files changed, 104 insertions(+), 9 deletions(-) diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index cb115ba6a1d2..c01038b7962a 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c @@ -898,6 +898,8 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state) state != VB2_BUF_STATE_REQUEUEING)) state = VB2_BUF_STATE_ERROR; + WARN_ON(vb->request != q->cur_req); + #ifdef CONFIG_VIDEO_ADV_DEBUG /* * Although this is not a callback, it still does have to balance @@ -920,6 +922,13 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state) /* Add the buffer to the done buffers list */ list_add_tail(>done_entry, >done_list); vb->state = state; + + if (q->cur_req) { + WARN_ON(q->req_buf_cnt < 1); + + if (--q->req_buf_cnt == 0) + q->cur_req = NULL; + } } atomic_dec(>owned_by_drv_count); spin_unlock_irqrestore(>done_lock, flags); @@ -1298,6 +1307,16 @@ int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb) } EXPORT_SYMBOL_GPL(vb2_core_prepare_buf); +static void vb2_queue_enqueue_current_buffers(struct vb2_queue *q) +{ + struct vb2_buffer *vb; + + list_for_each_entry(vb, >queued_list, queued_entry) { + if (vb->request == q->cur_req) + __enqueue_in_driver(vb); + } +} + /** * vb2_start_streaming() - Attempt to start streaming. * @q: videobuf2 queue @@ -1318,8 +1337,7 @@ static int vb2_start_streaming(struct vb2_queue *q) * If any buffers were queued before streamon, * we can now pass them to driver for processing. */ - list_for_each_entry(vb, >queued_list, queued_entry) - __enqueue_in_driver(vb); + vb2_queue_enqueue_current_buffers(q); /* Tell the driver to start streaming */ q->start_streaming_called = 1; @@ -1361,7 +1379,8 @@ static int vb2_start_streaming(struct vb2_queue *q) return ret; } -int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb) +int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, + struct media_request *req, void *pb) { struct vb2_buffer *vb; int ret; @@ -1392,6 +1411,7 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb) q->queued_count++; q->waiting_for_buffers = false; vb->state = VB2_BUF_STATE_QUEUED; + vb->request = req; if (pb) call_void_bufop(q, copy_timestamp, vb, pb); @@ -1401,8 +1421,11 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb) /* * If already streaming, give the buffer to driver for processing. * If not, the buffer will be given to driver on next streamon. +* +* If using the request API, the buffer will be given to the driver +* when the request becomes active. */ - if (q->start_streaming_called) + if (q->start_streaming_called && !req) __enqueue_in_driver(vb); /* Fill buffer information for the userspace */ @@ -1427,6 +1450,28 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb) } EXPORT_SYMBOL_GPL(vb2_core_qbuf); +void vb2_queue_start_request(struct vb2_queue *q, struct media_request *req) +{ + struct vb2_buffer *vb; + + q->req_buf_cnt = 0; + list_for_each_entry(vb, >queued_list, queued_entry) { + if (vb->request == req) + ++q->req_buf_cnt; + } + + /* only consider the request if we actually have buffers for it */ + if (q->req_buf_cnt == 0) + return; + + q->cur_req = req; + + /* If not streaming yet, we will enqueue the buffers later */ + if (q->start_streaming_called) + vb2_queue_enqueue_current_buffers(q); +} +EXPORT_SYMBOL_GPL(vb2_queue_start_request); + /** * __vb2_wait_for_done_vb() - wait for a buffer to become available * for dequeuing @@ -2242,7 +2287,7 @@ static int __vb2_init_fileio(struct vb2_queue *q, int
[RFC PATCH 3/9] media: request: add generic entity ops
Add skeleton ops for generic entities. The intent is to provide a generic mechanism to apply request parameters to entities using regular media/v4l2 functions. Signed-off-by: Alexandre Courbot--- drivers/media/Makefile | 3 +- drivers/media/media-request-entity-generic.c | 56 include/media/media-request.h| 5 +++ 3 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 drivers/media/media-request-entity-generic.c diff --git a/drivers/media/Makefile b/drivers/media/Makefile index 90117fff1339..dea482f6ab72 100644 --- a/drivers/media/Makefile +++ b/drivers/media/Makefile @@ -4,7 +4,8 @@ # media-objs := media-device.o media-devnode.o media-entity.o \ - media-request.o media-request-queue-generic.o + media-request.o media-request-queue-generic.o \ + media-request-entity-generic.o # # I2C drivers should come before other drivers, otherwise they'll fail diff --git a/drivers/media/media-request-entity-generic.c b/drivers/media/media-request-entity-generic.c new file mode 100644 index ..18e53f9ce525 --- /dev/null +++ b/drivers/media/media-request-entity-generic.c @@ -0,0 +1,56 @@ +/* + * Media generic entity ops + * + * Copyright (C) 2017, The Chromium OS Authors. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include + +#include +#include + +struct media_request_entity_data_generic { + struct media_request_entity_data base; +}; + +static struct media_request_entity_data * +alloc_req_data(struct media_request *req, struct media_entity *entity) +{ + struct media_request_entity_data_generic *ret; + + ret = kzalloc(sizeof(*ret), GFP_KERNEL); + if (!ret) + return ERR_PTR(-ENOMEM); + + return >base; +} + +static void release_req_data(struct media_request_entity_data *_data) +{ + struct media_request_entity_data_generic *data; + + data = container_of(_data, typeof(*data), base); + kfree(data); +} + +static int apply_req_data(struct media_request_entity_data *_data) +{ + return 0; +} + +const struct media_request_entity_ops +media_entity_request_generic_ops = { + .alloc_data = alloc_req_data, + .release_data = release_req_data, + .apply_data = apply_req_data, +}; +EXPORT_SYMBOL_GPL(media_entity_request_generic_ops); diff --git a/include/media/media-request.h b/include/media/media-request.h index 583a1116f735..de3d6d824ffd 100644 --- a/include/media/media-request.h +++ b/include/media/media-request.h @@ -240,6 +240,11 @@ struct media_request_entity_ops { int (*apply_data)(struct media_request_entity_data *data); }; +/* + * Generic entity request support, built on top of standard V4L2 functions + */ +extern const struct media_request_entity_ops media_entity_request_generic_ops; + /** * media_device_request_cmd() - perform the REQUEST_CMD ioctl * -- 2.15.1.504.g5279b80103-goog
[RFC PATCH 5/9] media: vb2: add support for requests
Add throttling support for buffers when requests are in use on a given queue. Buffers associated to a request are kept into the vb2 queue until the request becomes active, at which point all the buffers are passed to the driver. The queue can also signal that is has processed all of a request's buffers. Also add support for the request parameter when handling the QBUF ioctl. Signed-off-by: Alexandre Courbot --- drivers/media/v4l2-core/videobuf2-core.c | 59 drivers/media/v4l2-core/videobuf2-v4l2.c | 29 +++- include/media/videobuf2-core.h | 25 +- 3 files changed, 104 insertions(+), 9 deletions(-) diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index cb115ba6a1d2..c01038b7962a 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c @@ -898,6 +898,8 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state) state != VB2_BUF_STATE_REQUEUEING)) state = VB2_BUF_STATE_ERROR; + WARN_ON(vb->request != q->cur_req); + #ifdef CONFIG_VIDEO_ADV_DEBUG /* * Although this is not a callback, it still does have to balance @@ -920,6 +922,13 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state) /* Add the buffer to the done buffers list */ list_add_tail(>done_entry, >done_list); vb->state = state; + + if (q->cur_req) { + WARN_ON(q->req_buf_cnt < 1); + + if (--q->req_buf_cnt == 0) + q->cur_req = NULL; + } } atomic_dec(>owned_by_drv_count); spin_unlock_irqrestore(>done_lock, flags); @@ -1298,6 +1307,16 @@ int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb) } EXPORT_SYMBOL_GPL(vb2_core_prepare_buf); +static void vb2_queue_enqueue_current_buffers(struct vb2_queue *q) +{ + struct vb2_buffer *vb; + + list_for_each_entry(vb, >queued_list, queued_entry) { + if (vb->request == q->cur_req) + __enqueue_in_driver(vb); + } +} + /** * vb2_start_streaming() - Attempt to start streaming. * @q: videobuf2 queue @@ -1318,8 +1337,7 @@ static int vb2_start_streaming(struct vb2_queue *q) * If any buffers were queued before streamon, * we can now pass them to driver for processing. */ - list_for_each_entry(vb, >queued_list, queued_entry) - __enqueue_in_driver(vb); + vb2_queue_enqueue_current_buffers(q); /* Tell the driver to start streaming */ q->start_streaming_called = 1; @@ -1361,7 +1379,8 @@ static int vb2_start_streaming(struct vb2_queue *q) return ret; } -int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb) +int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, + struct media_request *req, void *pb) { struct vb2_buffer *vb; int ret; @@ -1392,6 +1411,7 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb) q->queued_count++; q->waiting_for_buffers = false; vb->state = VB2_BUF_STATE_QUEUED; + vb->request = req; if (pb) call_void_bufop(q, copy_timestamp, vb, pb); @@ -1401,8 +1421,11 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb) /* * If already streaming, give the buffer to driver for processing. * If not, the buffer will be given to driver on next streamon. +* +* If using the request API, the buffer will be given to the driver +* when the request becomes active. */ - if (q->start_streaming_called) + if (q->start_streaming_called && !req) __enqueue_in_driver(vb); /* Fill buffer information for the userspace */ @@ -1427,6 +1450,28 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb) } EXPORT_SYMBOL_GPL(vb2_core_qbuf); +void vb2_queue_start_request(struct vb2_queue *q, struct media_request *req) +{ + struct vb2_buffer *vb; + + q->req_buf_cnt = 0; + list_for_each_entry(vb, >queued_list, queued_entry) { + if (vb->request == req) + ++q->req_buf_cnt; + } + + /* only consider the request if we actually have buffers for it */ + if (q->req_buf_cnt == 0) + return; + + q->cur_req = req; + + /* If not streaming yet, we will enqueue the buffers later */ + if (q->start_streaming_called) + vb2_queue_enqueue_current_buffers(q); +} +EXPORT_SYMBOL_GPL(vb2_queue_start_request); + /** * __vb2_wait_for_done_vb() - wait for a buffer to become available * for dequeuing @@ -2242,7 +2287,7 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read)
[RFC PATCH 3/9] media: request: add generic entity ops
Add skeleton ops for generic entities. The intent is to provide a generic mechanism to apply request parameters to entities using regular media/v4l2 functions. Signed-off-by: Alexandre Courbot --- drivers/media/Makefile | 3 +- drivers/media/media-request-entity-generic.c | 56 include/media/media-request.h| 5 +++ 3 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 drivers/media/media-request-entity-generic.c diff --git a/drivers/media/Makefile b/drivers/media/Makefile index 90117fff1339..dea482f6ab72 100644 --- a/drivers/media/Makefile +++ b/drivers/media/Makefile @@ -4,7 +4,8 @@ # media-objs := media-device.o media-devnode.o media-entity.o \ - media-request.o media-request-queue-generic.o + media-request.o media-request-queue-generic.o \ + media-request-entity-generic.o # # I2C drivers should come before other drivers, otherwise they'll fail diff --git a/drivers/media/media-request-entity-generic.c b/drivers/media/media-request-entity-generic.c new file mode 100644 index ..18e53f9ce525 --- /dev/null +++ b/drivers/media/media-request-entity-generic.c @@ -0,0 +1,56 @@ +/* + * Media generic entity ops + * + * Copyright (C) 2017, The Chromium OS Authors. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include + +#include +#include + +struct media_request_entity_data_generic { + struct media_request_entity_data base; +}; + +static struct media_request_entity_data * +alloc_req_data(struct media_request *req, struct media_entity *entity) +{ + struct media_request_entity_data_generic *ret; + + ret = kzalloc(sizeof(*ret), GFP_KERNEL); + if (!ret) + return ERR_PTR(-ENOMEM); + + return >base; +} + +static void release_req_data(struct media_request_entity_data *_data) +{ + struct media_request_entity_data_generic *data; + + data = container_of(_data, typeof(*data), base); + kfree(data); +} + +static int apply_req_data(struct media_request_entity_data *_data) +{ + return 0; +} + +const struct media_request_entity_ops +media_entity_request_generic_ops = { + .alloc_data = alloc_req_data, + .release_data = release_req_data, + .apply_data = apply_req_data, +}; +EXPORT_SYMBOL_GPL(media_entity_request_generic_ops); diff --git a/include/media/media-request.h b/include/media/media-request.h index 583a1116f735..de3d6d824ffd 100644 --- a/include/media/media-request.h +++ b/include/media/media-request.h @@ -240,6 +240,11 @@ struct media_request_entity_ops { int (*apply_data)(struct media_request_entity_data *data); }; +/* + * Generic entity request support, built on top of standard V4L2 functions + */ +extern const struct media_request_entity_ops media_entity_request_generic_ops; + /** * media_device_request_cmd() - perform the REQUEST_CMD ioctl * -- 2.15.1.504.g5279b80103-goog
[RFC PATCH 9/9] media: vim2m: add request support
Set the necessary ops for supporting requests in vim2m. Signed-off-by: Alexandre Courbot--- drivers/media/platform/vim2m.c | 22 ++ 1 file changed, 22 insertions(+) diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/vim2m.c index a32e8a7950eb..ffe94ef9214d 100644 --- a/drivers/media/platform/vim2m.c +++ b/drivers/media/platform/vim2m.c @@ -30,6 +30,7 @@ #include #include #include +#include MODULE_DESCRIPTION("Virtual device for mem2mem framework testing"); MODULE_AUTHOR("Pawel Osciak, "); @@ -142,6 +143,7 @@ struct vim2m_dev { struct video_device vfd; #ifdef CONFIG_MEDIA_CONTROLLER struct media_device mdev; + struct media_request_queue *req_queue; #endif atomic_tnum_inst; @@ -937,6 +939,11 @@ static int vim2m_open(struct file *file) goto open_unlock; } +#ifdef CONFIG_MEDIA_CONTROLLER + v4l2_mem_ctx_request_init(ctx->fh.m2m_ctx, dev->req_queue, + >vfd.entity); +#endif + v4l2_fh_add(>fh); atomic_inc(>num_inst); @@ -992,6 +999,12 @@ static const struct v4l2_m2m_ops m2m_ops = { .job_abort = job_abort, }; +#ifdef CONFIG_MEDIA_CONTROLLER +static const struct media_entity_operations vim2m_entity_ops = { + .process_request = v4l2_m2m_process_request, +}; +#endif + static int vim2m_probe(struct platform_device *pdev) { struct vim2m_dev *dev; @@ -1006,6 +1019,10 @@ static int vim2m_probe(struct platform_device *pdev) #ifdef CONFIG_MEDIA_CONTROLLER dev->mdev.dev = >dev; + dev->req_queue = media_request_queue_generic_alloc(>mdev); + if (IS_ERR(dev->req_queue)) + return PTR_ERR(dev->req_queue); + dev->mdev.req_queue = dev->req_queue; strlcpy(dev->mdev.model, "vim2m", sizeof(dev->mdev.model)); media_device_init(>mdev); dev->v4l2_dev.mdev = >mdev; @@ -1023,6 +1040,11 @@ static int vim2m_probe(struct platform_device *pdev) vfd->lock = >dev_mutex; vfd->v4l2_dev = >v4l2_dev; +#ifdef CONFIG_MEDIA_CONTROLLER + vfd->entity.ops = _entity_ops; + vfd->entity.req_ops = _entity_request_generic_ops; +#endif + ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0); if (ret) { v4l2_err(>v4l2_dev, "Failed to register video device\n"); -- 2.15.1.504.g5279b80103-goog
[RFC PATCH 9/9] media: vim2m: add request support
Set the necessary ops for supporting requests in vim2m. Signed-off-by: Alexandre Courbot --- drivers/media/platform/vim2m.c | 22 ++ 1 file changed, 22 insertions(+) diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/vim2m.c index a32e8a7950eb..ffe94ef9214d 100644 --- a/drivers/media/platform/vim2m.c +++ b/drivers/media/platform/vim2m.c @@ -30,6 +30,7 @@ #include #include #include +#include MODULE_DESCRIPTION("Virtual device for mem2mem framework testing"); MODULE_AUTHOR("Pawel Osciak, "); @@ -142,6 +143,7 @@ struct vim2m_dev { struct video_device vfd; #ifdef CONFIG_MEDIA_CONTROLLER struct media_device mdev; + struct media_request_queue *req_queue; #endif atomic_tnum_inst; @@ -937,6 +939,11 @@ static int vim2m_open(struct file *file) goto open_unlock; } +#ifdef CONFIG_MEDIA_CONTROLLER + v4l2_mem_ctx_request_init(ctx->fh.m2m_ctx, dev->req_queue, + >vfd.entity); +#endif + v4l2_fh_add(>fh); atomic_inc(>num_inst); @@ -992,6 +999,12 @@ static const struct v4l2_m2m_ops m2m_ops = { .job_abort = job_abort, }; +#ifdef CONFIG_MEDIA_CONTROLLER +static const struct media_entity_operations vim2m_entity_ops = { + .process_request = v4l2_m2m_process_request, +}; +#endif + static int vim2m_probe(struct platform_device *pdev) { struct vim2m_dev *dev; @@ -1006,6 +1019,10 @@ static int vim2m_probe(struct platform_device *pdev) #ifdef CONFIG_MEDIA_CONTROLLER dev->mdev.dev = >dev; + dev->req_queue = media_request_queue_generic_alloc(>mdev); + if (IS_ERR(dev->req_queue)) + return PTR_ERR(dev->req_queue); + dev->mdev.req_queue = dev->req_queue; strlcpy(dev->mdev.model, "vim2m", sizeof(dev->mdev.model)); media_device_init(>mdev); dev->v4l2_dev.mdev = >mdev; @@ -1023,6 +1040,11 @@ static int vim2m_probe(struct platform_device *pdev) vfd->lock = >dev_mutex; vfd->v4l2_dev = >v4l2_dev; +#ifdef CONFIG_MEDIA_CONTROLLER + vfd->entity.ops = _entity_ops; + vfd->entity.req_ops = _entity_request_generic_ops; +#endif + ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0); if (ret) { v4l2_err(>v4l2_dev, "Failed to register video device\n"); -- 2.15.1.504.g5279b80103-goog
[RFC PATCH 7/9] media: v4l2-mem2mem: add request support
Support request API in the mem2mem framework. Drivers that specify ops for the queue and entities can support requests seamlessly. Signed-off-by: Alexandre Courbot--- drivers/media/v4l2-core/v4l2-mem2mem.c | 34 ++ include/media/v4l2-mem2mem.h | 19 +++ 2 files changed, 53 insertions(+) diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c index f62e68aa04c4..eb52bee8e06a 100644 --- a/drivers/media/v4l2-core/v4l2-mem2mem.c +++ b/drivers/media/v4l2-core/v4l2-mem2mem.c @@ -22,6 +22,7 @@ #include #include #include +#include MODULE_DESCRIPTION("Mem to mem device framework for videobuf"); MODULE_AUTHOR("Pawel Osciak, "); @@ -219,6 +220,15 @@ void v4l2_m2m_try_schedule(struct v4l2_m2m_ctx *m2m_ctx) m2m_dev = m2m_ctx->m2m_dev; dprintk("Trying to schedule a job for m2m_ctx: %p\n", m2m_ctx); +#ifdef CONFIG_MEDIA_CONTROLLER + /* request is completed if all queues are done with it */ + if (m2m_ctx->req_queue && m2m_ctx->req_queue->active_request && + m2m_ctx->cap_q_ctx.q.cur_req == NULL && + m2m_ctx->out_q_ctx.q.cur_req == NULL) + media_request_entity_complete(m2m_ctx->req_queue, + m2m_ctx->entity); +#endif + if (!m2m_ctx->out_q_ctx.q.streaming || !m2m_ctx->cap_q_ctx.q.streaming) { dprintk("Streaming needs to be on for both queues\n"); @@ -665,6 +675,15 @@ struct v4l2_m2m_ctx *v4l2_m2m_ctx_init(struct v4l2_m2m_dev *m2m_dev, } EXPORT_SYMBOL_GPL(v4l2_m2m_ctx_init); +void v4l2_mem_ctx_request_init(struct v4l2_m2m_ctx *ctx, + struct media_request_queue *req_queue, + struct media_entity *entity) +{ + ctx->entity = entity; + ctx->req_queue = req_queue; +} +EXPORT_SYMBOL_GPL(v4l2_mem_ctx_request_init); + void v4l2_m2m_ctx_release(struct v4l2_m2m_ctx *m2m_ctx) { /* wait until the current context is dequeued from job_queue */ @@ -810,3 +829,18 @@ unsigned int v4l2_m2m_fop_poll(struct file *file, poll_table *wait) } EXPORT_SYMBOL_GPL(v4l2_m2m_fop_poll); +int v4l2_m2m_process_request(struct media_request *req, +struct media_request_entity_data *data) +{ +#ifdef CONFIG_MEDIA_CONTROLLER + struct v4l2_fh *fh = data->fh; + struct v4l2_m2m_ctx *ctx = fh->m2m_ctx; + + vb2_queue_start_request(>cap_q_ctx.q, req); + vb2_queue_start_request(>out_q_ctx.q, req); + + v4l2_m2m_try_schedule(ctx); +#endif + return 0; +} +EXPORT_SYMBOL_GPL(v4l2_m2m_process_request); diff --git a/include/media/v4l2-mem2mem.h b/include/media/v4l2-mem2mem.h index e157d5c9b224..1c9925c3d4ce 100644 --- a/include/media/v4l2-mem2mem.h +++ b/include/media/v4l2-mem2mem.h @@ -19,6 +19,10 @@ #include +struct media_entity; +struct media_request; +struct media_request_entity_data; + /** * struct v4l2_m2m_ops - mem-to-mem device driver callbacks * @device_run:required. Begin the actual job (transaction) inside this @@ -83,6 +87,7 @@ struct v4l2_m2m_queue_ctx { * * @q_lock: struct lock * @m2m_dev: opaque pointer to the internal data to handle M2M context + * @state: Pointer to state handler for channel support * @cap_q_ctx: Capture (output to memory) queue context * @out_q_ctx: Output (input from memory) queue context * @queue: List of memory to memory contexts @@ -100,6 +105,8 @@ struct v4l2_m2m_ctx { /* internal use only */ struct v4l2_m2m_dev *m2m_dev; + struct media_request_queue *req_queue; + struct media_entity *entity; struct v4l2_m2m_queue_ctx cap_q_ctx; @@ -351,6 +358,16 @@ struct v4l2_m2m_ctx *v4l2_m2m_ctx_init(struct v4l2_m2m_dev *m2m_dev, void *drv_priv, int (*queue_init)(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq)); +/** + * v4l2_mem_ctx_request_init() - enable a context to be used with requests + * + * @ctx: context to potentially use within a channel + * @req_queue: request queue that will be used with this context + */ +void v4l2_mem_ctx_request_init(struct v4l2_m2m_ctx *ctx, + struct media_request_queue *req_queue, + struct media_entity *entity); + static inline void v4l2_m2m_set_src_buffered(struct v4l2_m2m_ctx *m2m_ctx, bool buffered) { @@ -602,6 +619,8 @@ int v4l2_m2m_ioctl_streamoff(struct file *file, void *fh, enum v4l2_buf_type type); int v4l2_m2m_fop_mmap(struct file *file, struct vm_area_struct *vma); unsigned int v4l2_m2m_fop_poll(struct file *file, poll_table *wait); +int v4l2_m2m_process_request(struct media_request *req, +struct media_request_entity_data *data); #endif /*
[RFC PATCH 7/9] media: v4l2-mem2mem: add request support
Support request API in the mem2mem framework. Drivers that specify ops for the queue and entities can support requests seamlessly. Signed-off-by: Alexandre Courbot --- drivers/media/v4l2-core/v4l2-mem2mem.c | 34 ++ include/media/v4l2-mem2mem.h | 19 +++ 2 files changed, 53 insertions(+) diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c index f62e68aa04c4..eb52bee8e06a 100644 --- a/drivers/media/v4l2-core/v4l2-mem2mem.c +++ b/drivers/media/v4l2-core/v4l2-mem2mem.c @@ -22,6 +22,7 @@ #include #include #include +#include MODULE_DESCRIPTION("Mem to mem device framework for videobuf"); MODULE_AUTHOR("Pawel Osciak, "); @@ -219,6 +220,15 @@ void v4l2_m2m_try_schedule(struct v4l2_m2m_ctx *m2m_ctx) m2m_dev = m2m_ctx->m2m_dev; dprintk("Trying to schedule a job for m2m_ctx: %p\n", m2m_ctx); +#ifdef CONFIG_MEDIA_CONTROLLER + /* request is completed if all queues are done with it */ + if (m2m_ctx->req_queue && m2m_ctx->req_queue->active_request && + m2m_ctx->cap_q_ctx.q.cur_req == NULL && + m2m_ctx->out_q_ctx.q.cur_req == NULL) + media_request_entity_complete(m2m_ctx->req_queue, + m2m_ctx->entity); +#endif + if (!m2m_ctx->out_q_ctx.q.streaming || !m2m_ctx->cap_q_ctx.q.streaming) { dprintk("Streaming needs to be on for both queues\n"); @@ -665,6 +675,15 @@ struct v4l2_m2m_ctx *v4l2_m2m_ctx_init(struct v4l2_m2m_dev *m2m_dev, } EXPORT_SYMBOL_GPL(v4l2_m2m_ctx_init); +void v4l2_mem_ctx_request_init(struct v4l2_m2m_ctx *ctx, + struct media_request_queue *req_queue, + struct media_entity *entity) +{ + ctx->entity = entity; + ctx->req_queue = req_queue; +} +EXPORT_SYMBOL_GPL(v4l2_mem_ctx_request_init); + void v4l2_m2m_ctx_release(struct v4l2_m2m_ctx *m2m_ctx) { /* wait until the current context is dequeued from job_queue */ @@ -810,3 +829,18 @@ unsigned int v4l2_m2m_fop_poll(struct file *file, poll_table *wait) } EXPORT_SYMBOL_GPL(v4l2_m2m_fop_poll); +int v4l2_m2m_process_request(struct media_request *req, +struct media_request_entity_data *data) +{ +#ifdef CONFIG_MEDIA_CONTROLLER + struct v4l2_fh *fh = data->fh; + struct v4l2_m2m_ctx *ctx = fh->m2m_ctx; + + vb2_queue_start_request(>cap_q_ctx.q, req); + vb2_queue_start_request(>out_q_ctx.q, req); + + v4l2_m2m_try_schedule(ctx); +#endif + return 0; +} +EXPORT_SYMBOL_GPL(v4l2_m2m_process_request); diff --git a/include/media/v4l2-mem2mem.h b/include/media/v4l2-mem2mem.h index e157d5c9b224..1c9925c3d4ce 100644 --- a/include/media/v4l2-mem2mem.h +++ b/include/media/v4l2-mem2mem.h @@ -19,6 +19,10 @@ #include +struct media_entity; +struct media_request; +struct media_request_entity_data; + /** * struct v4l2_m2m_ops - mem-to-mem device driver callbacks * @device_run:required. Begin the actual job (transaction) inside this @@ -83,6 +87,7 @@ struct v4l2_m2m_queue_ctx { * * @q_lock: struct lock * @m2m_dev: opaque pointer to the internal data to handle M2M context + * @state: Pointer to state handler for channel support * @cap_q_ctx: Capture (output to memory) queue context * @out_q_ctx: Output (input from memory) queue context * @queue: List of memory to memory contexts @@ -100,6 +105,8 @@ struct v4l2_m2m_ctx { /* internal use only */ struct v4l2_m2m_dev *m2m_dev; + struct media_request_queue *req_queue; + struct media_entity *entity; struct v4l2_m2m_queue_ctx cap_q_ctx; @@ -351,6 +358,16 @@ struct v4l2_m2m_ctx *v4l2_m2m_ctx_init(struct v4l2_m2m_dev *m2m_dev, void *drv_priv, int (*queue_init)(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq)); +/** + * v4l2_mem_ctx_request_init() - enable a context to be used with requests + * + * @ctx: context to potentially use within a channel + * @req_queue: request queue that will be used with this context + */ +void v4l2_mem_ctx_request_init(struct v4l2_m2m_ctx *ctx, + struct media_request_queue *req_queue, + struct media_entity *entity); + static inline void v4l2_m2m_set_src_buffered(struct v4l2_m2m_ctx *m2m_ctx, bool buffered) { @@ -602,6 +619,8 @@ int v4l2_m2m_ioctl_streamoff(struct file *file, void *fh, enum v4l2_buf_type type); int v4l2_m2m_fop_mmap(struct file *file, struct vm_area_struct *vma); unsigned int v4l2_m2m_fop_poll(struct file *file, poll_table *wait); +int v4l2_m2m_process_request(struct media_request *req, +struct media_request_entity_data *data); #endif /* _MEDIA_V4L2_MEM2MEM_H */ --
[RFC PATCH 1/9] media: add request API core and UAPI
The request API provides a way to group buffers and device parameters into units of work to be queued and executed. This patch introduces the UAPI and core framework. This patch is based on the previous work by Laurent Pinchart. The core has changed considerably, but the UAPI is mostly untouched. Signed-off-by: Alexandre Courbot--- drivers/media/Makefile | 3 +- drivers/media/media-device.c | 6 + drivers/media/media-request.c| 390 +++ drivers/media/v4l2-core/v4l2-ioctl.c | 2 +- include/media/media-device.h | 3 + include/media/media-entity.h | 6 + include/media/media-request.h| 269 include/uapi/linux/media.h | 11 + 8 files changed, 688 insertions(+), 2 deletions(-) create mode 100644 drivers/media/media-request.c create mode 100644 include/media/media-request.h diff --git a/drivers/media/Makefile b/drivers/media/Makefile index 594b462ddf0e..985d35ec6b29 100644 --- a/drivers/media/Makefile +++ b/drivers/media/Makefile @@ -3,7 +3,8 @@ # Makefile for the kernel multimedia device drivers. # -media-objs := media-device.o media-devnode.o media-entity.o +media-objs := media-device.o media-devnode.o media-entity.o \ + media-request.o # # I2C drivers should come before other drivers, otherwise they'll fail diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c index e79f72b8b858..045cec7d2de9 100644 --- a/drivers/media/media-device.c +++ b/drivers/media/media-device.c @@ -32,6 +32,7 @@ #include #include #include +#include #ifdef CONFIG_MEDIA_CONTROLLER @@ -407,6 +408,7 @@ static const struct media_ioctl_info ioctl_info[] = { MEDIA_IOC(ENUM_LINKS, media_device_enum_links, MEDIA_IOC_FL_GRAPH_MUTEX), MEDIA_IOC(SETUP_LINK, media_device_setup_link, MEDIA_IOC_FL_GRAPH_MUTEX), MEDIA_IOC(G_TOPOLOGY, media_device_get_topology, MEDIA_IOC_FL_GRAPH_MUTEX), + MEDIA_IOC(REQUEST_CMD, media_device_request_cmd, 0), }; static long media_device_ioctl(struct file *filp, unsigned int cmd, @@ -688,6 +690,10 @@ EXPORT_SYMBOL_GPL(media_device_init); void media_device_cleanup(struct media_device *mdev) { + if (mdev->req_queue) { + mdev->req_queue->ops->release(mdev->req_queue); + mdev->req_queue = NULL; + } ida_destroy(>entity_internal_idx); mdev->entity_internal_idx_max = 0; media_graph_walk_cleanup(>pm_count_walk); diff --git a/drivers/media/media-request.c b/drivers/media/media-request.c new file mode 100644 index ..15dc65ddfe41 --- /dev/null +++ b/drivers/media/media-request.c @@ -0,0 +1,390 @@ +/* + * Request and request queue base management + * + * Copyright (C) 2017, The Chromium OS Authors. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +const struct file_operations request_fops; + +void media_request_get(struct media_request *req) +{ + kref_get(>kref); +} +EXPORT_SYMBOL_GPL(media_request_get); + +struct media_request * +media_request_get_from_fd(int fd) +{ + struct file *f; + struct media_request *req; + + f = fget(fd); + if (!f) + return NULL; + + /* Not a request FD? */ + if (f->f_op != _fops) { + fput(f); + return NULL; + } + + req = f->private_data; + media_request_get(req); + fput(f); + + return req; +} +EXPORT_SYMBOL_GPL(media_request_get_from_fd); + +static void media_request_release(struct kref *kref) +{ + struct media_request_entity_data *data, *next; + struct media_request *req = + container_of(kref, typeof(*req), kref); + struct media_device *mdev = req->queue->mdev; + + dev_dbg(mdev->dev, "%s: releasing request %u\n", __func__, req->id); + + list_del(>list); + list_for_each_entry_safe(data, next, >data, list) { + list_del(>list); + data->entity->req_ops->release_data(data); + } + + req->queue->ops->req_free(req->queue, req); +} + +void media_request_put(struct media_request *req) +{ + kref_put(>kref, media_request_release); +} +EXPORT_SYMBOL_GPL(media_request_put); + +struct media_request_entity_data * +media_request_get_entity_data(struct media_request *req, + struct media_entity *entity, void *fh) +{ + struct
[RFC PATCH 1/9] media: add request API core and UAPI
The request API provides a way to group buffers and device parameters into units of work to be queued and executed. This patch introduces the UAPI and core framework. This patch is based on the previous work by Laurent Pinchart. The core has changed considerably, but the UAPI is mostly untouched. Signed-off-by: Alexandre Courbot --- drivers/media/Makefile | 3 +- drivers/media/media-device.c | 6 + drivers/media/media-request.c| 390 +++ drivers/media/v4l2-core/v4l2-ioctl.c | 2 +- include/media/media-device.h | 3 + include/media/media-entity.h | 6 + include/media/media-request.h| 269 include/uapi/linux/media.h | 11 + 8 files changed, 688 insertions(+), 2 deletions(-) create mode 100644 drivers/media/media-request.c create mode 100644 include/media/media-request.h diff --git a/drivers/media/Makefile b/drivers/media/Makefile index 594b462ddf0e..985d35ec6b29 100644 --- a/drivers/media/Makefile +++ b/drivers/media/Makefile @@ -3,7 +3,8 @@ # Makefile for the kernel multimedia device drivers. # -media-objs := media-device.o media-devnode.o media-entity.o +media-objs := media-device.o media-devnode.o media-entity.o \ + media-request.o # # I2C drivers should come before other drivers, otherwise they'll fail diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c index e79f72b8b858..045cec7d2de9 100644 --- a/drivers/media/media-device.c +++ b/drivers/media/media-device.c @@ -32,6 +32,7 @@ #include #include #include +#include #ifdef CONFIG_MEDIA_CONTROLLER @@ -407,6 +408,7 @@ static const struct media_ioctl_info ioctl_info[] = { MEDIA_IOC(ENUM_LINKS, media_device_enum_links, MEDIA_IOC_FL_GRAPH_MUTEX), MEDIA_IOC(SETUP_LINK, media_device_setup_link, MEDIA_IOC_FL_GRAPH_MUTEX), MEDIA_IOC(G_TOPOLOGY, media_device_get_topology, MEDIA_IOC_FL_GRAPH_MUTEX), + MEDIA_IOC(REQUEST_CMD, media_device_request_cmd, 0), }; static long media_device_ioctl(struct file *filp, unsigned int cmd, @@ -688,6 +690,10 @@ EXPORT_SYMBOL_GPL(media_device_init); void media_device_cleanup(struct media_device *mdev) { + if (mdev->req_queue) { + mdev->req_queue->ops->release(mdev->req_queue); + mdev->req_queue = NULL; + } ida_destroy(>entity_internal_idx); mdev->entity_internal_idx_max = 0; media_graph_walk_cleanup(>pm_count_walk); diff --git a/drivers/media/media-request.c b/drivers/media/media-request.c new file mode 100644 index ..15dc65ddfe41 --- /dev/null +++ b/drivers/media/media-request.c @@ -0,0 +1,390 @@ +/* + * Request and request queue base management + * + * Copyright (C) 2017, The Chromium OS Authors. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +const struct file_operations request_fops; + +void media_request_get(struct media_request *req) +{ + kref_get(>kref); +} +EXPORT_SYMBOL_GPL(media_request_get); + +struct media_request * +media_request_get_from_fd(int fd) +{ + struct file *f; + struct media_request *req; + + f = fget(fd); + if (!f) + return NULL; + + /* Not a request FD? */ + if (f->f_op != _fops) { + fput(f); + return NULL; + } + + req = f->private_data; + media_request_get(req); + fput(f); + + return req; +} +EXPORT_SYMBOL_GPL(media_request_get_from_fd); + +static void media_request_release(struct kref *kref) +{ + struct media_request_entity_data *data, *next; + struct media_request *req = + container_of(kref, typeof(*req), kref); + struct media_device *mdev = req->queue->mdev; + + dev_dbg(mdev->dev, "%s: releasing request %u\n", __func__, req->id); + + list_del(>list); + list_for_each_entry_safe(data, next, >data, list) { + list_del(>list); + data->entity->req_ops->release_data(data); + } + + req->queue->ops->req_free(req->queue, req); +} + +void media_request_put(struct media_request *req) +{ + kref_put(>kref, media_request_release); +} +EXPORT_SYMBOL_GPL(media_request_put); + +struct media_request_entity_data * +media_request_get_entity_data(struct media_request *req, + struct media_entity *entity, void *fh) +{ + struct media_request_queue *queue =
[RFC PATCH 0/9] media: base request API support
Here is a new attempt at the request API, following the UAPI we agreed on in Prague. Hopefully this can be used as the basis to move forward. This series only introduces the very basics of how requests work: allocate a request, queue buffers to it, queue the request itself, wait for it to complete, reuse it. It does *not* yet use Hans' work with controls setting. I have preferred to submit it this way for now as it allows us to concentrate on the basic request/buffer flow, which was harder to get properly than I initially thought. I still have a gut feeling that it can be improved, with less back-and- forth into drivers. Plugging in controls support should not be too hard a task (basically just apply the saved controls when the request starts), and I am looking at it now. The resulting vim2m driver can be successfully used with requests, and my tests so far have been successful. There are still some rougher edges: * locking is currently quite coarse-grained * too many #ifdef CONFIG_MEDIA_CONTROLLER in the code, as the request API depends on it - I plan to craft the headers so that it becomes unnecessary. As it is, some of the code will probably not even compile if CONFIG_MEDIA_CONTROLLER is not set But all in all I think the request flow should be clear and easy to review, and the possibility of custom queue and entity support implementations should give us the flexibility we need to support more specific use-cases (I expect the generic implementations to be sufficient most of the time though). A very simple test program exercising this API is available here (don't forget to adapt the /dev/media0 hardcoding): https://gist.github.com/Gnurou/dbc3776ed97ea7d4ce6041ea15eb0438 Looking forward to your feedback and comments! Alexandre Courbot (8): media: add request API core and UAPI media: request: add generic queue media: request: add generic entity ops media: vb2: add support for requests media: vb2: add support for requests in QBUF ioctl media: v4l2-mem2mem: add request support media: vim2m: add media device media: vim2m: add request support Hans Verkuil (1): videodev2.h: Add request field to v4l2_buffer drivers/media/Makefile| 4 +- drivers/media/media-device.c | 6 + drivers/media/media-request-entity-generic.c | 56 drivers/media/media-request-queue-generic.c | 150 ++ drivers/media/media-request.c | 390 ++ drivers/media/platform/vim2m.c| 46 +++ drivers/media/usb/cpia2/cpia2_v4l.c | 2 +- drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 7 +- drivers/media/v4l2-core/v4l2-ioctl.c | 99 ++- drivers/media/v4l2-core/v4l2-mem2mem.c| 34 +++ drivers/media/v4l2-core/videobuf2-core.c | 59 +++- drivers/media/v4l2-core/videobuf2-v4l2.c | 32 ++- include/media/media-device.h | 3 + include/media/media-entity.h | 6 + include/media/media-request.h | 282 +++ include/media/v4l2-mem2mem.h | 19 ++ include/media/videobuf2-core.h| 25 +- include/media/videobuf2-v4l2.h| 2 + include/uapi/linux/media.h| 11 + include/uapi/linux/videodev2.h| 3 +- 20 files changed, 1216 insertions(+), 20 deletions(-) create mode 100644 drivers/media/media-request-entity-generic.c create mode 100644 drivers/media/media-request-queue-generic.c create mode 100644 drivers/media/media-request.c create mode 100644 include/media/media-request.h -- 2.15.1.504.g5279b80103-goog
[RFC PATCH 0/9] media: base request API support
Here is a new attempt at the request API, following the UAPI we agreed on in Prague. Hopefully this can be used as the basis to move forward. This series only introduces the very basics of how requests work: allocate a request, queue buffers to it, queue the request itself, wait for it to complete, reuse it. It does *not* yet use Hans' work with controls setting. I have preferred to submit it this way for now as it allows us to concentrate on the basic request/buffer flow, which was harder to get properly than I initially thought. I still have a gut feeling that it can be improved, with less back-and- forth into drivers. Plugging in controls support should not be too hard a task (basically just apply the saved controls when the request starts), and I am looking at it now. The resulting vim2m driver can be successfully used with requests, and my tests so far have been successful. There are still some rougher edges: * locking is currently quite coarse-grained * too many #ifdef CONFIG_MEDIA_CONTROLLER in the code, as the request API depends on it - I plan to craft the headers so that it becomes unnecessary. As it is, some of the code will probably not even compile if CONFIG_MEDIA_CONTROLLER is not set But all in all I think the request flow should be clear and easy to review, and the possibility of custom queue and entity support implementations should give us the flexibility we need to support more specific use-cases (I expect the generic implementations to be sufficient most of the time though). A very simple test program exercising this API is available here (don't forget to adapt the /dev/media0 hardcoding): https://gist.github.com/Gnurou/dbc3776ed97ea7d4ce6041ea15eb0438 Looking forward to your feedback and comments! Alexandre Courbot (8): media: add request API core and UAPI media: request: add generic queue media: request: add generic entity ops media: vb2: add support for requests media: vb2: add support for requests in QBUF ioctl media: v4l2-mem2mem: add request support media: vim2m: add media device media: vim2m: add request support Hans Verkuil (1): videodev2.h: Add request field to v4l2_buffer drivers/media/Makefile| 4 +- drivers/media/media-device.c | 6 + drivers/media/media-request-entity-generic.c | 56 drivers/media/media-request-queue-generic.c | 150 ++ drivers/media/media-request.c | 390 ++ drivers/media/platform/vim2m.c| 46 +++ drivers/media/usb/cpia2/cpia2_v4l.c | 2 +- drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 7 +- drivers/media/v4l2-core/v4l2-ioctl.c | 99 ++- drivers/media/v4l2-core/v4l2-mem2mem.c| 34 +++ drivers/media/v4l2-core/videobuf2-core.c | 59 +++- drivers/media/v4l2-core/videobuf2-v4l2.c | 32 ++- include/media/media-device.h | 3 + include/media/media-entity.h | 6 + include/media/media-request.h | 282 +++ include/media/v4l2-mem2mem.h | 19 ++ include/media/videobuf2-core.h| 25 +- include/media/videobuf2-v4l2.h| 2 + include/uapi/linux/media.h| 11 + include/uapi/linux/videodev2.h| 3 +- 20 files changed, 1216 insertions(+), 20 deletions(-) create mode 100644 drivers/media/media-request-entity-generic.c create mode 100644 drivers/media/media-request-queue-generic.c create mode 100644 drivers/media/media-request.c create mode 100644 include/media/media-request.h -- 2.15.1.504.g5279b80103-goog
Re: [PATCH v2 01/17] mm/gup: Fixup p*_access_permitted()
On Thu, Dec 14, 2017 at 10:09:24PM -0800, Linus Torvalds wrote: > On Dec 14, 2017 21:04, "Dave Hansen"wrote: > Can we please just undo that broken crap instead of trying to "fix" it? > > It was wrong. We absolutely do not want to complicate the gup path. > > Let's fet rid of those broken p??_access_permited() things. So we actually need the pte_access_permitted() stuff if we want to ensure we're not stepping on !PAGE_USER things.
Re: [PATCH v2 01/17] mm/gup: Fixup p*_access_permitted()
On Thu, Dec 14, 2017 at 10:09:24PM -0800, Linus Torvalds wrote: > On Dec 14, 2017 21:04, "Dave Hansen" wrote: > Can we please just undo that broken crap instead of trying to "fix" it? > > It was wrong. We absolutely do not want to complicate the gup path. > > Let's fet rid of those broken p??_access_permited() things. So we actually need the pte_access_permitted() stuff if we want to ensure we're not stepping on !PAGE_USER things.
[PATCH 04/27] clocksource/arm_arch_timer: Use timecounter_initialize interface
With new interface timecounter_initialize we can initialize timecounter fields and underlying cyclecounter together. Update arch_timer_kvm_info timecounter init with this new function. Signed-off-by: Sagar Arun KambleCc: Richard Cochran Cc: Mark Rutland Cc: Marc Zyngier Cc: Daniel Lezcano Cc: Thomas Gleixner Cc: linux-arm-ker...@lists.infradead.org Cc: linux-kernel@vger.kernel.org --- drivers/clocksource/arm_arch_timer.c | 15 +++ 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 31543e5..d96393f 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -910,10 +910,7 @@ static u64 arch_counter_get_cntvct_mem(void) return ((u64) vct_hi << 32) | vct_lo; } -static struct arch_timer_kvm_info arch_timer_kvm_info = { - .timecounter.cc.read = arch_counter_read_cc, - .timecounter.cc.mask = CLOCKSOURCE_MASK(56), -}; +static struct arch_timer_kvm_info arch_timer_kvm_info; struct arch_timer_kvm_info *arch_timer_get_kvm_info(void) { @@ -923,7 +920,6 @@ struct arch_timer_kvm_info *arch_timer_get_kvm_info(void) static void __init arch_counter_register(unsigned type) { u64 start_count; - struct cyclecounter *cc = _timer_kvm_info.timecounter.cc; /* Register the CP15 based counter if we have one */ if (type & ARCH_TIMER_TYPE_CP15) { @@ -943,9 +939,12 @@ static void __init arch_counter_register(unsigned type) start_count = arch_timer_read_counter(); clocksource_register_hz(_counter, arch_timer_rate); - cc->mult = clocksource_counter.mult; - cc->shift = clocksource_counter.shift; - timecounter_init(_timer_kvm_info.timecounter, start_count); + timecounter_initialize(_timer_kvm_info.timecounter, + arch_counter_read_cc, + CLOCKSOURCE_MASK(56), + clocksource_counter.mult, + clocksource_counter.shift, + start_count); /* 56 bits minimum, so we assume worst case rollover */ sched_clock_register(arch_timer_read_counter, 56, arch_timer_rate); -- 1.9.1
[PATCH 04/27] clocksource/arm_arch_timer: Use timecounter_initialize interface
With new interface timecounter_initialize we can initialize timecounter fields and underlying cyclecounter together. Update arch_timer_kvm_info timecounter init with this new function. Signed-off-by: Sagar Arun Kamble Cc: Richard Cochran Cc: Mark Rutland Cc: Marc Zyngier Cc: Daniel Lezcano Cc: Thomas Gleixner Cc: linux-arm-ker...@lists.infradead.org Cc: linux-kernel@vger.kernel.org --- drivers/clocksource/arm_arch_timer.c | 15 +++ 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 31543e5..d96393f 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -910,10 +910,7 @@ static u64 arch_counter_get_cntvct_mem(void) return ((u64) vct_hi << 32) | vct_lo; } -static struct arch_timer_kvm_info arch_timer_kvm_info = { - .timecounter.cc.read = arch_counter_read_cc, - .timecounter.cc.mask = CLOCKSOURCE_MASK(56), -}; +static struct arch_timer_kvm_info arch_timer_kvm_info; struct arch_timer_kvm_info *arch_timer_get_kvm_info(void) { @@ -923,7 +920,6 @@ struct arch_timer_kvm_info *arch_timer_get_kvm_info(void) static void __init arch_counter_register(unsigned type) { u64 start_count; - struct cyclecounter *cc = _timer_kvm_info.timecounter.cc; /* Register the CP15 based counter if we have one */ if (type & ARCH_TIMER_TYPE_CP15) { @@ -943,9 +939,12 @@ static void __init arch_counter_register(unsigned type) start_count = arch_timer_read_counter(); clocksource_register_hz(_counter, arch_timer_rate); - cc->mult = clocksource_counter.mult; - cc->shift = clocksource_counter.shift; - timecounter_init(_timer_kvm_info.timecounter, start_count); + timecounter_initialize(_timer_kvm_info.timecounter, + arch_counter_read_cc, + CLOCKSOURCE_MASK(56), + clocksource_counter.mult, + clocksource_counter.shift, + start_count); /* 56 bits minimum, so we assume worst case rollover */ sched_clock_register(arch_timer_read_counter, 56, arch_timer_rate); -- 1.9.1
[PATCH 05/27] amd-xgbe: Use timecounter_initialize interface
With new interface timecounter_initialize we can initialize timecounter fields and underlying cyclecounter together. Update xgbe tstamp_tc timecounter init with this new function. Signed-off-by: Sagar Arun KambleCc: Richard Cochran Cc: Tom Lendacky Cc: net...@vger.kernel.org Cc: linux-kernel@vger.kernel.org --- drivers/net/ethernet/amd/xgbe/xgbe-ptp.c | 13 ++--- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c b/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c index 5ea4edf..486437b 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c @@ -228,7 +228,6 @@ void xgbe_ptp_register(struct xgbe_prv_data *pdata) { struct ptp_clock_info *info = >ptp_clock_info; struct ptp_clock *clock; - struct cyclecounter *cc = >tstamp_tc.cc; u64 dividend; snprintf(info->name, sizeof(info->name), "%s", @@ -258,12 +257,12 @@ void xgbe_ptp_register(struct xgbe_prv_data *pdata) pdata->tstamp_addend = div_u64(dividend, pdata->ptpclk_rate); /* Setup the timecounter */ - cc->read = xgbe_cc_read; - cc->mask = CLOCKSOURCE_MASK(64); - cc->mult = 1; - cc->shift = 0; - - timecounter_init(>tstamp_tc, ktime_to_ns(ktime_get_real())); + timecounter_initialize(>tstamp_tc, + xgbe_cc_read, + CLOCKSOURCE_MASK(64), + 1, + 0, + ktime_to_ns(ktime_get_real())); /* Disable all timestamping to start */ XGMAC_IOWRITE(pdata, MAC_TSCR, 0); -- 1.9.1
[PATCH 05/27] amd-xgbe: Use timecounter_initialize interface
With new interface timecounter_initialize we can initialize timecounter fields and underlying cyclecounter together. Update xgbe tstamp_tc timecounter init with this new function. Signed-off-by: Sagar Arun Kamble Cc: Richard Cochran Cc: Tom Lendacky Cc: net...@vger.kernel.org Cc: linux-kernel@vger.kernel.org --- drivers/net/ethernet/amd/xgbe/xgbe-ptp.c | 13 ++--- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c b/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c index 5ea4edf..486437b 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c @@ -228,7 +228,6 @@ void xgbe_ptp_register(struct xgbe_prv_data *pdata) { struct ptp_clock_info *info = >ptp_clock_info; struct ptp_clock *clock; - struct cyclecounter *cc = >tstamp_tc.cc; u64 dividend; snprintf(info->name, sizeof(info->name), "%s", @@ -258,12 +257,12 @@ void xgbe_ptp_register(struct xgbe_prv_data *pdata) pdata->tstamp_addend = div_u64(dividend, pdata->ptpclk_rate); /* Setup the timecounter */ - cc->read = xgbe_cc_read; - cc->mask = CLOCKSOURCE_MASK(64); - cc->mult = 1; - cc->shift = 0; - - timecounter_init(>tstamp_tc, ktime_to_ns(ktime_get_real())); + timecounter_initialize(>tstamp_tc, + xgbe_cc_read, + CLOCKSOURCE_MASK(64), + 1, + 0, + ktime_to_ns(ktime_get_real())); /* Disable all timestamping to start */ XGMAC_IOWRITE(pdata, MAC_TSCR, 0); -- 1.9.1
[PATCH 07/27] fec: Use timecounter_initialize interface
With new interface timecounter_initialize we can initialize timecounter fields and underlying cyclecounter together. Update fec ethernet timecounter init with this new function. Signed-off-by: Sagar Arun KambleCc: Richard Cochran Cc: Fugang Duan Cc: net...@vger.kernel.org Cc: linux-kernel@vger.kernel.org --- drivers/net/ethernet/freescale/fec_ptp.c | 15 +++ 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c index b1261d1..1ba7216 100644 --- a/drivers/net/ethernet/freescale/fec_ptp.c +++ b/drivers/net/ethernet/freescale/fec_ptp.c @@ -278,14 +278,13 @@ void fec_ptp_start_cyclecounter(struct net_device *ndev) writel(FEC_T_CTRL_ENABLE | FEC_T_CTRL_PERIOD_RST, fep->hwp + FEC_ATIME_CTRL); - memset(>tc.cc, 0, sizeof(fep->tc.cc)); - fep->tc.cc.read = fec_ptp_read; - fep->tc.cc.mask = CLOCKSOURCE_MASK(31); - fep->tc.cc.shift = 31; - fep->tc.cc.mult = FEC_CC_MULT; - - /* reset the ns time counter */ - timecounter_init(>tc, ktime_to_ns(ktime_get_real())); + /* Initialize the ns time counter */ + timecounter_initialize(>tc, + fec_ptp_read, + CLOCKSOURCE_MASK(31), + FEC_CC_MULT, + 31, + ktime_to_ns(ktime_get_real())); spin_unlock_irqrestore(>tmreg_lock, flags); } -- 1.9.1
Re: [PATCH] exit: move exit_task_namespaces() after exit_task_work()
On Fri, Dec 15, 2017 at 7:56 AM, Eric W. Biedermanwrote: > Cong Wang writes: > >> syzbot reported we have a use-after-free when mqueue_evict_inode() >> is called on __cleanup_mnt() path, where the ipc ns is already >> freed by the previous exit_task_namespaces(). We can just move >> it after after exit_task_work() to avoid this use-after-free. > > How does that possibly work. (I haven't seen this syzbot report). > > Looking at the code we have get_ns_from_inode. Which takes the mq_lock, > sees if the pointer is NULL and takes a reference if it is non-NULL. > > Meanwhile put_ipc_ns calls mq_clear_sbinfo(ns) with the mq_lock held > when the count drops to zero. > > Where is the race in that? > > The rest of mqueue_evict_inode uses the returned pointer and > tests that the pointer is non-NULL before user it. > > So either szbot is giving you a bad report or there is a subtle race > there I am not seeing. The change below is not at all the proper way to > fix a subtle race. > > Eric Cong, what was that report? Searching by "exit_task_work|exit_task_namespaces" there are too many of them: https://groups.google.com/forum/#!searchin/syzkaller-bugs/%22exit_task_work$7Cexit_task_namespaces%22%7Csort:date I can only say that syzbot does not make up reports. That's something that actually happened and was provoked by userspace. >> Reported-by: syzbot >> Cc: Ingo Molnar >> Cc: Al Viro >> Cc: Andrew Morton >> Cc: Linus Torvalds >> Cc: sta...@vger.kernel.org >> Signed-off-by: Cong Wang >> --- >> kernel/exit.c | 2 +- >> 1 file changed, 1 insertion(+), 1 deletion(-) >> >> diff --git a/kernel/exit.c b/kernel/exit.c >> index 6b4298a41167..909e43c45158 100644 >> --- a/kernel/exit.c >> +++ b/kernel/exit.c >> @@ -861,8 +861,8 @@ void __noreturn do_exit(long code) >> exit_fs(tsk); >> if (group_dead) >> disassociate_ctty(1); >> - exit_task_namespaces(tsk); >> exit_task_work(tsk); >> + exit_task_namespaces(tsk); >> exit_thread(tsk); >> >> /*
[PATCH 07/27] fec: Use timecounter_initialize interface
With new interface timecounter_initialize we can initialize timecounter fields and underlying cyclecounter together. Update fec ethernet timecounter init with this new function. Signed-off-by: Sagar Arun Kamble Cc: Richard Cochran Cc: Fugang Duan Cc: net...@vger.kernel.org Cc: linux-kernel@vger.kernel.org --- drivers/net/ethernet/freescale/fec_ptp.c | 15 +++ 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c index b1261d1..1ba7216 100644 --- a/drivers/net/ethernet/freescale/fec_ptp.c +++ b/drivers/net/ethernet/freescale/fec_ptp.c @@ -278,14 +278,13 @@ void fec_ptp_start_cyclecounter(struct net_device *ndev) writel(FEC_T_CTRL_ENABLE | FEC_T_CTRL_PERIOD_RST, fep->hwp + FEC_ATIME_CTRL); - memset(>tc.cc, 0, sizeof(fep->tc.cc)); - fep->tc.cc.read = fec_ptp_read; - fep->tc.cc.mask = CLOCKSOURCE_MASK(31); - fep->tc.cc.shift = 31; - fep->tc.cc.mult = FEC_CC_MULT; - - /* reset the ns time counter */ - timecounter_init(>tc, ktime_to_ns(ktime_get_real())); + /* Initialize the ns time counter */ + timecounter_initialize(>tc, + fec_ptp_read, + CLOCKSOURCE_MASK(31), + FEC_CC_MULT, + 31, + ktime_to_ns(ktime_get_real())); spin_unlock_irqrestore(>tmreg_lock, flags); } -- 1.9.1
Re: [PATCH] exit: move exit_task_namespaces() after exit_task_work()
On Fri, Dec 15, 2017 at 7:56 AM, Eric W. Biederman wrote: > Cong Wang writes: > >> syzbot reported we have a use-after-free when mqueue_evict_inode() >> is called on __cleanup_mnt() path, where the ipc ns is already >> freed by the previous exit_task_namespaces(). We can just move >> it after after exit_task_work() to avoid this use-after-free. > > How does that possibly work. (I haven't seen this syzbot report). > > Looking at the code we have get_ns_from_inode. Which takes the mq_lock, > sees if the pointer is NULL and takes a reference if it is non-NULL. > > Meanwhile put_ipc_ns calls mq_clear_sbinfo(ns) with the mq_lock held > when the count drops to zero. > > Where is the race in that? > > The rest of mqueue_evict_inode uses the returned pointer and > tests that the pointer is non-NULL before user it. > > So either szbot is giving you a bad report or there is a subtle race > there I am not seeing. The change below is not at all the proper way to > fix a subtle race. > > Eric Cong, what was that report? Searching by "exit_task_work|exit_task_namespaces" there are too many of them: https://groups.google.com/forum/#!searchin/syzkaller-bugs/%22exit_task_work$7Cexit_task_namespaces%22%7Csort:date I can only say that syzbot does not make up reports. That's something that actually happened and was provoked by userspace. >> Reported-by: syzbot >> Cc: Ingo Molnar >> Cc: Al Viro >> Cc: Andrew Morton >> Cc: Linus Torvalds >> Cc: sta...@vger.kernel.org >> Signed-off-by: Cong Wang >> --- >> kernel/exit.c | 2 +- >> 1 file changed, 1 insertion(+), 1 deletion(-) >> >> diff --git a/kernel/exit.c b/kernel/exit.c >> index 6b4298a41167..909e43c45158 100644 >> --- a/kernel/exit.c >> +++ b/kernel/exit.c >> @@ -861,8 +861,8 @@ void __noreturn do_exit(long code) >> exit_fs(tsk); >> if (group_dead) >> disassociate_ctty(1); >> - exit_task_namespaces(tsk); >> exit_task_work(tsk); >> + exit_task_namespaces(tsk); >> exit_thread(tsk); >> >> /*
[PATCH 08/27] e1000e: Use timecounter_initialize interface
With new interface timecounter_initialize we can initialize timecounter fields and underlying cyclecounter together. Update e1000e timecounter init with this new function. Signed-off-by: Sagar Arun KambleCc: Richard Cochran Cc: Jeff Kirsher Cc: intel-wired-...@lists.osuosl.org Cc: net...@vger.kernel.org Cc: linux-kernel@vger.kernel.org --- drivers/net/ethernet/intel/e1000e/e1000.h | 4 drivers/net/ethernet/intel/e1000e/netdev.c | 31 +- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/drivers/net/ethernet/intel/e1000e/e1000.h b/drivers/net/ethernet/intel/e1000e/e1000.h index b59f82a..d6b0e59 100644 --- a/drivers/net/ethernet/intel/e1000e/e1000.h +++ b/drivers/net/ethernet/intel/e1000e/e1000.h @@ -341,6 +341,10 @@ struct e1000_adapter { struct work_struct tx_hwtstamp_work; spinlock_t systim_lock; /* protects SYSTIML/H regsters */ struct timecounter tc; + u64 (*cc_read)(const struct cyclecounter *cc); + u64 cc_mask; + u32 cc_mult; + u32 cc_shift; struct ptp_clock *ptp_clock; struct ptp_clock_info ptp_clock_info; struct pm_qos_request pm_qos_req; diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index c9f7ba3..6be1327 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -3536,7 +3536,7 @@ s32 e1000e_get_base_timinca(struct e1000_adapter *adapter, u32 *timinca) incperiod = INCPERIOD_96MHZ; incvalue = INCVALUE_96MHZ; shift = INCVALUE_SHIFT_96MHZ; - adapter->tc.cc.shift = shift + INCPERIOD_SHIFT_96MHZ; + adapter->cc_shift = shift + INCPERIOD_SHIFT_96MHZ; break; case e1000_pch_lpt: if (er32(TSYNCRXCTL) & E1000_TSYNCRXCTL_SYSCFI) { @@ -3544,13 +3544,13 @@ s32 e1000e_get_base_timinca(struct e1000_adapter *adapter, u32 *timinca) incperiod = INCPERIOD_96MHZ; incvalue = INCVALUE_96MHZ; shift = INCVALUE_SHIFT_96MHZ; - adapter->tc.cc.shift = shift + INCPERIOD_SHIFT_96MHZ; + adapter->cc_shift = shift + INCPERIOD_SHIFT_96MHZ; } else { /* Stable 25MHz frequency */ incperiod = INCPERIOD_25MHZ; incvalue = INCVALUE_25MHZ; shift = INCVALUE_SHIFT_25MHZ; - adapter->tc.cc.shift = shift; + adapter->cc_shift = shift; } break; case e1000_pch_spt: @@ -3559,7 +3559,7 @@ s32 e1000e_get_base_timinca(struct e1000_adapter *adapter, u32 *timinca) incperiod = INCPERIOD_24MHZ; incvalue = INCVALUE_24MHZ; shift = INCVALUE_SHIFT_24MHZ; - adapter->tc.cc.shift = shift; + adapter->cc_shift = shift; break; } return -EINVAL; @@ -3569,13 +3569,13 @@ s32 e1000e_get_base_timinca(struct e1000_adapter *adapter, u32 *timinca) incperiod = INCPERIOD_24MHZ; incvalue = INCVALUE_24MHZ; shift = INCVALUE_SHIFT_24MHZ; - adapter->tc.cc.shift = shift; + adapter->cc_shift = shift; } else { /* Stable 38400KHz frequency */ incperiod = INCPERIOD_38400KHZ; incvalue = INCVALUE_38400KHZ; shift = INCVALUE_SHIFT_38400KHZ; - adapter->tc.cc.shift = shift; + adapter->cc_shift = shift; } break; case e1000_82574: @@ -3584,7 +3584,7 @@ s32 e1000e_get_base_timinca(struct e1000_adapter *adapter, u32 *timinca) incperiod = INCPERIOD_25MHZ; incvalue = INCVALUE_25MHZ; shift = INCVALUE_SHIFT_25MHZ; - adapter->tc.cc.shift = shift; + adapter->cc_shift = shift; break; default: return -EINVAL; @@ -3953,9 +3953,14 @@ static void e1000e_systim_reset(struct e1000_adapter *adapter) return; } - /* reset the systim ns time counter */ + /* reinitialize the systim ns time counter */ spin_lock_irqsave(>systim_lock, flags); - timecounter_init(>tc, ktime_to_ns(ktime_get_real())); + timecounter_initialize(>tc, + adapter->cc_read, + adapter->cc_mask, + adapter->cc_mult, + adapter->cc_shift, +
[PATCH 08/27] e1000e: Use timecounter_initialize interface
With new interface timecounter_initialize we can initialize timecounter fields and underlying cyclecounter together. Update e1000e timecounter init with this new function. Signed-off-by: Sagar Arun Kamble Cc: Richard Cochran Cc: Jeff Kirsher Cc: intel-wired-...@lists.osuosl.org Cc: net...@vger.kernel.org Cc: linux-kernel@vger.kernel.org --- drivers/net/ethernet/intel/e1000e/e1000.h | 4 drivers/net/ethernet/intel/e1000e/netdev.c | 31 +- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/drivers/net/ethernet/intel/e1000e/e1000.h b/drivers/net/ethernet/intel/e1000e/e1000.h index b59f82a..d6b0e59 100644 --- a/drivers/net/ethernet/intel/e1000e/e1000.h +++ b/drivers/net/ethernet/intel/e1000e/e1000.h @@ -341,6 +341,10 @@ struct e1000_adapter { struct work_struct tx_hwtstamp_work; spinlock_t systim_lock; /* protects SYSTIML/H regsters */ struct timecounter tc; + u64 (*cc_read)(const struct cyclecounter *cc); + u64 cc_mask; + u32 cc_mult; + u32 cc_shift; struct ptp_clock *ptp_clock; struct ptp_clock_info ptp_clock_info; struct pm_qos_request pm_qos_req; diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index c9f7ba3..6be1327 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -3536,7 +3536,7 @@ s32 e1000e_get_base_timinca(struct e1000_adapter *adapter, u32 *timinca) incperiod = INCPERIOD_96MHZ; incvalue = INCVALUE_96MHZ; shift = INCVALUE_SHIFT_96MHZ; - adapter->tc.cc.shift = shift + INCPERIOD_SHIFT_96MHZ; + adapter->cc_shift = shift + INCPERIOD_SHIFT_96MHZ; break; case e1000_pch_lpt: if (er32(TSYNCRXCTL) & E1000_TSYNCRXCTL_SYSCFI) { @@ -3544,13 +3544,13 @@ s32 e1000e_get_base_timinca(struct e1000_adapter *adapter, u32 *timinca) incperiod = INCPERIOD_96MHZ; incvalue = INCVALUE_96MHZ; shift = INCVALUE_SHIFT_96MHZ; - adapter->tc.cc.shift = shift + INCPERIOD_SHIFT_96MHZ; + adapter->cc_shift = shift + INCPERIOD_SHIFT_96MHZ; } else { /* Stable 25MHz frequency */ incperiod = INCPERIOD_25MHZ; incvalue = INCVALUE_25MHZ; shift = INCVALUE_SHIFT_25MHZ; - adapter->tc.cc.shift = shift; + adapter->cc_shift = shift; } break; case e1000_pch_spt: @@ -3559,7 +3559,7 @@ s32 e1000e_get_base_timinca(struct e1000_adapter *adapter, u32 *timinca) incperiod = INCPERIOD_24MHZ; incvalue = INCVALUE_24MHZ; shift = INCVALUE_SHIFT_24MHZ; - adapter->tc.cc.shift = shift; + adapter->cc_shift = shift; break; } return -EINVAL; @@ -3569,13 +3569,13 @@ s32 e1000e_get_base_timinca(struct e1000_adapter *adapter, u32 *timinca) incperiod = INCPERIOD_24MHZ; incvalue = INCVALUE_24MHZ; shift = INCVALUE_SHIFT_24MHZ; - adapter->tc.cc.shift = shift; + adapter->cc_shift = shift; } else { /* Stable 38400KHz frequency */ incperiod = INCPERIOD_38400KHZ; incvalue = INCVALUE_38400KHZ; shift = INCVALUE_SHIFT_38400KHZ; - adapter->tc.cc.shift = shift; + adapter->cc_shift = shift; } break; case e1000_82574: @@ -3584,7 +3584,7 @@ s32 e1000e_get_base_timinca(struct e1000_adapter *adapter, u32 *timinca) incperiod = INCPERIOD_25MHZ; incvalue = INCVALUE_25MHZ; shift = INCVALUE_SHIFT_25MHZ; - adapter->tc.cc.shift = shift; + adapter->cc_shift = shift; break; default: return -EINVAL; @@ -3953,9 +3953,14 @@ static void e1000e_systim_reset(struct e1000_adapter *adapter) return; } - /* reset the systim ns time counter */ + /* reinitialize the systim ns time counter */ spin_lock_irqsave(>systim_lock, flags); - timecounter_init(>tc, ktime_to_ns(ktime_get_real())); + timecounter_initialize(>tc, + adapter->cc_read, + adapter->cc_mask, + adapter->cc_mult, + adapter->cc_shift, + ktime_to_ns(ktime_get_real()));
[PATCH 03/27] microblaze: Use timecounter_initialize interface
With new interface timecounter_initialize we can initialize timecounter fields and underlying cyclecounter together. Update xilinx_tc init with this new function. Signed-off-by: Sagar Arun KambleCc: Richard Cochran Cc: Michal Simek Cc: Daniel Lezcano Cc: Neil Armstrong Cc: Nicolai Stange Cc: Arnd Bergmann Cc: Rob Herring Cc: Thomas Gleixner Cc: linux-kernel@vger.kernel.org --- arch/microblaze/kernel/timer.c | 19 ++- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/arch/microblaze/kernel/timer.c b/arch/microblaze/kernel/timer.c index b7f89e9..b32a896 100644 --- a/arch/microblaze/kernel/timer.c +++ b/arch/microblaze/kernel/timer.c @@ -204,20 +204,21 @@ static u64 xilinx_cc_read(const struct cyclecounter *cc) return xilinx_read(NULL); } -static struct timecounter xilinx_tc = { - .cc.read = xilinx_cc_read, - .cc.mask = CLOCKSOURCE_MASK(32), - .cc.mult = 0, - .cc.shift = 8, -}; +static struct timecounter xilinx_tc; static int __init init_xilinx_timecounter(void) { - struct cyclecounter *cc = _tc.cc; + u32 mult = 0; + u32 shift = 8; - cc->mult = div_sc(timer_clock_freq, NSEC_PER_SEC, cc->shift); + mult = div_sc(timer_clock_freq, NSEC_PER_SEC, shift); - timecounter_init(_tc, sched_clock()); + timecounter_initialize(_tc, + xilinx_cc_read, + CLOCKSOURCE_MASK(32), + mult, + shift, + sched_clock()); return 0; } -- 1.9.1
[PATCH 03/27] microblaze: Use timecounter_initialize interface
With new interface timecounter_initialize we can initialize timecounter fields and underlying cyclecounter together. Update xilinx_tc init with this new function. Signed-off-by: Sagar Arun Kamble Cc: Richard Cochran Cc: Michal Simek Cc: Daniel Lezcano Cc: Neil Armstrong Cc: Nicolai Stange Cc: Arnd Bergmann Cc: Rob Herring Cc: Thomas Gleixner Cc: linux-kernel@vger.kernel.org --- arch/microblaze/kernel/timer.c | 19 ++- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/arch/microblaze/kernel/timer.c b/arch/microblaze/kernel/timer.c index b7f89e9..b32a896 100644 --- a/arch/microblaze/kernel/timer.c +++ b/arch/microblaze/kernel/timer.c @@ -204,20 +204,21 @@ static u64 xilinx_cc_read(const struct cyclecounter *cc) return xilinx_read(NULL); } -static struct timecounter xilinx_tc = { - .cc.read = xilinx_cc_read, - .cc.mask = CLOCKSOURCE_MASK(32), - .cc.mult = 0, - .cc.shift = 8, -}; +static struct timecounter xilinx_tc; static int __init init_xilinx_timecounter(void) { - struct cyclecounter *cc = _tc.cc; + u32 mult = 0; + u32 shift = 8; - cc->mult = div_sc(timer_clock_freq, NSEC_PER_SEC, cc->shift); + mult = div_sc(timer_clock_freq, NSEC_PER_SEC, shift); - timecounter_init(_tc, sched_clock()); + timecounter_initialize(_tc, + xilinx_cc_read, + CLOCKSOURCE_MASK(32), + mult, + shift, + sched_clock()); return 0; } -- 1.9.1
[PATCH 11/27] net/mlx4: Use timecounter_initialize interface
With new interface timecounter_initialize we can initialize timecounter fields and underlying cyclecounter together. Update mlx4 timecounter init with this new function. Signed-off-by: Sagar Arun KambleCc: Richard Cochran Cc: Tariq Toukan Cc: net...@vger.kernel.org Cc: linux-r...@vger.kernel.org Cc: linux-kernel@vger.kernel.org --- drivers/net/ethernet/mellanox/mlx4/en_clock.c | 17 + 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/en_clock.c b/drivers/net/ethernet/mellanox/mlx4/en_clock.c index 35987b5..dd736cc 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_clock.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_clock.c @@ -264,6 +264,7 @@ void mlx4_en_init_timestamp(struct mlx4_en_dev *mdev) { struct mlx4_dev *dev = mdev->dev; unsigned long flags; + u32 mult, shift; /* mlx4_en_init_timestamp is called for each netdev. * mdev->ptp_clock is common for all ports, skip initialization if @@ -274,17 +275,17 @@ void mlx4_en_init_timestamp(struct mlx4_en_dev *mdev) seqlock_init(>clock_lock); - memset(>clock.cc, 0, sizeof(mdev->clock.cc)); - mdev->clock.cc.read = mlx4_en_read_clock; - mdev->clock.cc.mask = CLOCKSOURCE_MASK(48); - mdev->clock.cc.shift = freq_to_shift(dev->caps.hca_core_clock); - mdev->clock.cc.mult = - clocksource_khz2mult(1000 * dev->caps.hca_core_clock, -mdev->clock.cc.shift); + shift = freq_to_shift(dev->caps.hca_core_clock); + mult = clocksource_khz2mult(1000 * dev->caps.hca_core_clock, shift); mdev->nominal_c_mult = mdev->clock.cc.mult; write_seqlock_irqsave(>clock_lock, flags); - timecounter_init(>clock, ktime_to_ns(ktime_get_real())); + timecounter_initialize(>clock, + mlx4_en_read_clock, + CLOCKSOURCE_MASK(48), + mult, + shift, + ktime_to_ns(ktime_get_real())); write_sequnlock_irqrestore(>clock_lock, flags); /* Configure the PHC */ -- 1.9.1
[PATCH 11/27] net/mlx4: Use timecounter_initialize interface
With new interface timecounter_initialize we can initialize timecounter fields and underlying cyclecounter together. Update mlx4 timecounter init with this new function. Signed-off-by: Sagar Arun Kamble Cc: Richard Cochran Cc: Tariq Toukan Cc: net...@vger.kernel.org Cc: linux-r...@vger.kernel.org Cc: linux-kernel@vger.kernel.org --- drivers/net/ethernet/mellanox/mlx4/en_clock.c | 17 + 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/en_clock.c b/drivers/net/ethernet/mellanox/mlx4/en_clock.c index 35987b5..dd736cc 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_clock.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_clock.c @@ -264,6 +264,7 @@ void mlx4_en_init_timestamp(struct mlx4_en_dev *mdev) { struct mlx4_dev *dev = mdev->dev; unsigned long flags; + u32 mult, shift; /* mlx4_en_init_timestamp is called for each netdev. * mdev->ptp_clock is common for all ports, skip initialization if @@ -274,17 +275,17 @@ void mlx4_en_init_timestamp(struct mlx4_en_dev *mdev) seqlock_init(>clock_lock); - memset(>clock.cc, 0, sizeof(mdev->clock.cc)); - mdev->clock.cc.read = mlx4_en_read_clock; - mdev->clock.cc.mask = CLOCKSOURCE_MASK(48); - mdev->clock.cc.shift = freq_to_shift(dev->caps.hca_core_clock); - mdev->clock.cc.mult = - clocksource_khz2mult(1000 * dev->caps.hca_core_clock, -mdev->clock.cc.shift); + shift = freq_to_shift(dev->caps.hca_core_clock); + mult = clocksource_khz2mult(1000 * dev->caps.hca_core_clock, shift); mdev->nominal_c_mult = mdev->clock.cc.mult; write_seqlock_irqsave(>clock_lock, flags); - timecounter_init(>clock, ktime_to_ns(ktime_get_real())); + timecounter_initialize(>clock, + mlx4_en_read_clock, + CLOCKSOURCE_MASK(48), + mult, + shift, + ktime_to_ns(ktime_get_real())); write_sequnlock_irqrestore(>clock_lock, flags); /* Configure the PHC */ -- 1.9.1
[PATCH 06/27] bnx2x: Use timecounter_initialize interface
With new interface timecounter_initialize we can initialize timecounter fields and underlying cyclecounter together. Update bnx2x timecounter init with this new function. Signed-off-by: Sagar Arun KambleCc: Richard Cochran Cc: Ariel Elior Cc: everest-linux...@cavium.com Cc: net...@vger.kernel.org Cc: linux-kernel@vger.kernel.org --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 18 ++ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 83624ad..1e10a81 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -15269,15 +15269,6 @@ static u64 bnx2x_cyclecounter_read(const struct cyclecounter *cc) return phc_cycles; } -static void bnx2x_init_cyclecounter(struct cyclecounter *cc) -{ - memset(cc, 0, sizeof(*cc)); - cc->read = bnx2x_cyclecounter_read; - cc->mask = CYCLECOUNTER_MASK(64); - cc->shift = 0; - cc->mult = 1; -} - static int bnx2x_send_reset_timesync_ramrod(struct bnx2x *bp) { struct bnx2x_func_state_params func_params = {NULL}; @@ -15511,9 +15502,12 @@ void bnx2x_init_ptp(struct bnx2x *bp) * unload / load (e.g. MTU change) while it is running. */ if (!bp->timecounter_init_done) { - bnx2x_init_cyclecounter(>timecounter.cc); - timecounter_init(>timecounter, -ktime_to_ns(ktime_get_real())); + timecounter_initialize(>timecounter, + bnx2x_cyclecounter_read, + CYCLECOUNTER_MASK(64), + 1, + 0, + ktime_to_ns(ktime_get_real())); bp->timecounter_init_done = 1; } -- 1.9.1
[PATCH 06/27] bnx2x: Use timecounter_initialize interface
With new interface timecounter_initialize we can initialize timecounter fields and underlying cyclecounter together. Update bnx2x timecounter init with this new function. Signed-off-by: Sagar Arun Kamble Cc: Richard Cochran Cc: Ariel Elior Cc: everest-linux...@cavium.com Cc: net...@vger.kernel.org Cc: linux-kernel@vger.kernel.org --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 18 ++ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 83624ad..1e10a81 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -15269,15 +15269,6 @@ static u64 bnx2x_cyclecounter_read(const struct cyclecounter *cc) return phc_cycles; } -static void bnx2x_init_cyclecounter(struct cyclecounter *cc) -{ - memset(cc, 0, sizeof(*cc)); - cc->read = bnx2x_cyclecounter_read; - cc->mask = CYCLECOUNTER_MASK(64); - cc->shift = 0; - cc->mult = 1; -} - static int bnx2x_send_reset_timesync_ramrod(struct bnx2x *bp) { struct bnx2x_func_state_params func_params = {NULL}; @@ -15511,9 +15502,12 @@ void bnx2x_init_ptp(struct bnx2x *bp) * unload / load (e.g. MTU change) while it is running. */ if (!bp->timecounter_init_done) { - bnx2x_init_cyclecounter(>timecounter.cc); - timecounter_init(>timecounter, -ktime_to_ns(ktime_get_real())); + timecounter_initialize(>timecounter, + bnx2x_cyclecounter_read, + CYCLECOUNTER_MASK(64), + 1, + 0, + ktime_to_ns(ktime_get_real())); bp->timecounter_init_done = 1; } -- 1.9.1
Re: [PATCH v6] mfd: Add support for RTS5250S power saving
Hi, On 14-12-17 23:25, Bjorn Helgaas wrote: [+cc Hans, Dave, linux-pci] I appreciate the Cc but I'm not really involved in this, other then fixing the original commit up so that the T440s can reach idle-state PC7 again, instead of only going to PC3. With that said, for any fixes to this please Cc me so that I can test that the T440s does not regress again. Regards, Hans On Thu, Sep 07, 2017 at 04:26:39PM +0800, rui_f...@realsil.com.cn wrote: From: Rui FengI wish this had been posted to linux-pci before being merged. I'm concerned because some of this appears to overlap and conflict with PCI core management of ASPM. I assume these devices advertise ASPM support in their Link Capabilites registers, right? If so, why isn't the existing PCI core ASPM support sufficient? Enable power saving for RTS5250S as following steps: 1.Set 0xFE58 to enable clock power management. Is this clock power management something specific to RTS5250S, or is it standard PCIe architected stuff? 2.Check cfg space whether support L1SS or not. This sounds like standard PCIe ASPM L1 Substates, right? 3.If support L1SS, set 0xFF03 to free clkreq. 4.When entering idle status, enable aspm and set parameters for L1SS and LTR. 5.Wnen entering run status, disable aspm and set parameters for L1SS and LTR. In general, drivers should not configure ASPM, L1SS, and LTR themselves; the PCI core should do that. If a driver needs to tweak ASPM at run-time, it should use interfaces exported by the PCI core to do so. If entering L1SS mode successfully, electric current will be below 2mA. Signed-off-by: Rui Feng ... +static void rts5249_init_from_cfg(struct rtsx_pcr *pcr) +{ + struct rtsx_cr_option *option = &(pcr->option); + u32 lval; + + if (CHK_PCI_PID(pcr, PID_524A)) + rtsx_pci_read_config_dword(pcr, + PCR_ASPM_SETTING_REG1, ); + else + rtsx_pci_read_config_dword(pcr, + PCR_ASPM_SETTING_REG2, ); This looks like you're reading the ASPM L1 Substates capability, i.e., PCI_L1SS_CAP, using hard-coded offsets based on the Device ID. You should be using pci_find_ext_capability() to locate it. + if (lval & ASPM_L1_1_EN_MASK) + rtsx_set_dev_flag(pcr, ASPM_L1_1_EN); + + if (lval & ASPM_L1_2_EN_MASK) + rtsx_set_dev_flag(pcr, ASPM_L1_2_EN); + + if (lval & PM_L1_1_EN_MASK) + rtsx_set_dev_flag(pcr, PM_L1_1_EN); + + if (lval & PM_L1_2_EN_MASK) + rtsx_set_dev_flag(pcr, PM_L1_2_EN); You're adding these: #define ASPM_L1_1_EN_MASK BIT(3) #define ASPM_L1_2_EN_MASK BIT(2) #define PM_L1_1_EN_MASKBIT(1) #define PM_L1_2_EN_MASKBIT(0) The PCI core already defines these and you should use them instead: #define PCI_L1SS_CAP_PCIPM_L1_20x0001 /* PCI-PM L1.2 Supported */ #define PCI_L1SS_CAP_PCIPM_L1_10x0002 /* PCI-PM L1.1 Supported */ #define PCI_L1SS_CAP_ASPM_L1_2 0x0004 /* ASPM L1.2 Supported */ #define PCI_L1SS_CAP_ASPM_L1_1 0x0008 /* ASPM L1.1 Supported */ + if (option->ltr_en) { + u16 val; + + pcie_capability_read_word(pcr->pci, PCI_EXP_DEVCTL2, ); + if (val & PCI_EXP_DEVCTL2_LTR_EN) { + option->ltr_enabled = true; + option->ltr_active = true; ltr_active is never actually used. + rtsx_set_ltr_latency(pcr, option->ltr_active_latency); + } else { + option->ltr_enabled = false; + } + } +} ... +static void rts5249_set_aspm(struct rtsx_pcr *pcr, bool enable) +{ + struct rtsx_cr_option *option = >option; + u8 val = 0; + + if (pcr->aspm_enabled == enable) + return; + + if (option->dev_aspm_mode == DEV_ASPM_DYNAMIC) { + if (enable) + val = pcr->aspm_en; + rtsx_pci_update_cfg_byte(pcr, + pcr->pcie_cap + PCI_EXP_LNKCTL, + ASPM_MASK_NEG, val); This stomps on whatever ASPM configuration the PCI core did. + } else if (option->dev_aspm_mode == DEV_ASPM_BACKDOOR) { DEV_ASPM_BACKDOOR is never set, so this looks like dead code. + u8 mask = FORCE_ASPM_VAL_MASK | FORCE_ASPM_CTL0; + if (!enable) + val = FORCE_ASPM_CTL0; + rtsx_pci_write_register(pcr, ASPM_FORCE_CTL, mask, val); + } + + pcr->aspm_enabled = enable; +}
[PATCH 12/27] net/mlx5: Use timecounter_initialize interface
With new interface timecounter_initialize we can initialize timecounter fields and underlying cyclecounter together. Update mlx5 timecounter init with this new function. Signed-off-by: Sagar Arun KambleCc: Richard Cochran Cc: Saeed Mahameed Cc: Matan Barak Cc: Leon Romanovsky Cc: Eugenia Emantayev Cc: Eitan Rabin Cc: Feras Daoud Cc: Sagar Arun Kamble Cc: Miroslav Lichvar Cc: net...@vger.kernel.org Cc: linux-r...@vger.kernel.org Cc: linux-kernel@vger.kernel.org --- drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c | 18 +++--- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c index 8cb6838..071f78a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c @@ -458,6 +458,7 @@ void mlx5_init_clock(struct mlx5_core_dev *mdev) u64 ns; u64 frac = 0; u32 dev_freq; + u32 mult, shift; dev_freq = MLX5_CAP_GEN(mdev, device_frequency_khz); if (!dev_freq) { @@ -465,13 +466,16 @@ void mlx5_init_clock(struct mlx5_core_dev *mdev) return; } rwlock_init(>lock); - cc->read = read_internal_timer; - cc->shift = MLX5_CYCLES_SHIFT; - cc->mult = clocksource_khz2mult(dev_freq, cc->shift); - clock->nominal_c_mult = cc->mult; - cc->mask = CLOCKSOURCE_MASK(41); - - timecounter_init(>tc, ktime_to_ns(ktime_get_real())); + shift = MLX5_CYCLES_SHIFT; + mult = clocksource_khz2mult(dev_freq, shift); + clock->nominal_c_mult = mult; + + timecounter_initialize(>tc, + read_internal_timer, + CLOCKSOURCE_MASK(41), + mult, + shift, + ktime_to_ns(ktime_get_real())); /* Calculate period in seconds to call the overflow watchdog - to make * sure counter is checked at least once every wrap around. -- 1.9.1
Re: [PATCH v6] mfd: Add support for RTS5250S power saving
Hi, On 14-12-17 23:25, Bjorn Helgaas wrote: [+cc Hans, Dave, linux-pci] I appreciate the Cc but I'm not really involved in this, other then fixing the original commit up so that the T440s can reach idle-state PC7 again, instead of only going to PC3. With that said, for any fixes to this please Cc me so that I can test that the T440s does not regress again. Regards, Hans On Thu, Sep 07, 2017 at 04:26:39PM +0800, rui_f...@realsil.com.cn wrote: From: Rui Feng I wish this had been posted to linux-pci before being merged. I'm concerned because some of this appears to overlap and conflict with PCI core management of ASPM. I assume these devices advertise ASPM support in their Link Capabilites registers, right? If so, why isn't the existing PCI core ASPM support sufficient? Enable power saving for RTS5250S as following steps: 1.Set 0xFE58 to enable clock power management. Is this clock power management something specific to RTS5250S, or is it standard PCIe architected stuff? 2.Check cfg space whether support L1SS or not. This sounds like standard PCIe ASPM L1 Substates, right? 3.If support L1SS, set 0xFF03 to free clkreq. 4.When entering idle status, enable aspm and set parameters for L1SS and LTR. 5.Wnen entering run status, disable aspm and set parameters for L1SS and LTR. In general, drivers should not configure ASPM, L1SS, and LTR themselves; the PCI core should do that. If a driver needs to tweak ASPM at run-time, it should use interfaces exported by the PCI core to do so. If entering L1SS mode successfully, electric current will be below 2mA. Signed-off-by: Rui Feng ... +static void rts5249_init_from_cfg(struct rtsx_pcr *pcr) +{ + struct rtsx_cr_option *option = &(pcr->option); + u32 lval; + + if (CHK_PCI_PID(pcr, PID_524A)) + rtsx_pci_read_config_dword(pcr, + PCR_ASPM_SETTING_REG1, ); + else + rtsx_pci_read_config_dword(pcr, + PCR_ASPM_SETTING_REG2, ); This looks like you're reading the ASPM L1 Substates capability, i.e., PCI_L1SS_CAP, using hard-coded offsets based on the Device ID. You should be using pci_find_ext_capability() to locate it. + if (lval & ASPM_L1_1_EN_MASK) + rtsx_set_dev_flag(pcr, ASPM_L1_1_EN); + + if (lval & ASPM_L1_2_EN_MASK) + rtsx_set_dev_flag(pcr, ASPM_L1_2_EN); + + if (lval & PM_L1_1_EN_MASK) + rtsx_set_dev_flag(pcr, PM_L1_1_EN); + + if (lval & PM_L1_2_EN_MASK) + rtsx_set_dev_flag(pcr, PM_L1_2_EN); You're adding these: #define ASPM_L1_1_EN_MASK BIT(3) #define ASPM_L1_2_EN_MASK BIT(2) #define PM_L1_1_EN_MASKBIT(1) #define PM_L1_2_EN_MASKBIT(0) The PCI core already defines these and you should use them instead: #define PCI_L1SS_CAP_PCIPM_L1_20x0001 /* PCI-PM L1.2 Supported */ #define PCI_L1SS_CAP_PCIPM_L1_10x0002 /* PCI-PM L1.1 Supported */ #define PCI_L1SS_CAP_ASPM_L1_2 0x0004 /* ASPM L1.2 Supported */ #define PCI_L1SS_CAP_ASPM_L1_1 0x0008 /* ASPM L1.1 Supported */ + if (option->ltr_en) { + u16 val; + + pcie_capability_read_word(pcr->pci, PCI_EXP_DEVCTL2, ); + if (val & PCI_EXP_DEVCTL2_LTR_EN) { + option->ltr_enabled = true; + option->ltr_active = true; ltr_active is never actually used. + rtsx_set_ltr_latency(pcr, option->ltr_active_latency); + } else { + option->ltr_enabled = false; + } + } +} ... +static void rts5249_set_aspm(struct rtsx_pcr *pcr, bool enable) +{ + struct rtsx_cr_option *option = >option; + u8 val = 0; + + if (pcr->aspm_enabled == enable) + return; + + if (option->dev_aspm_mode == DEV_ASPM_DYNAMIC) { + if (enable) + val = pcr->aspm_en; + rtsx_pci_update_cfg_byte(pcr, + pcr->pcie_cap + PCI_EXP_LNKCTL, + ASPM_MASK_NEG, val); This stomps on whatever ASPM configuration the PCI core did. + } else if (option->dev_aspm_mode == DEV_ASPM_BACKDOOR) { DEV_ASPM_BACKDOOR is never set, so this looks like dead code. + u8 mask = FORCE_ASPM_VAL_MASK | FORCE_ASPM_CTL0; + if (!enable) + val = FORCE_ASPM_CTL0; + rtsx_pci_write_register(pcr, ASPM_FORCE_CTL, mask, val); + } + + pcr->aspm_enabled = enable; +}
[PATCH 12/27] net/mlx5: Use timecounter_initialize interface
With new interface timecounter_initialize we can initialize timecounter fields and underlying cyclecounter together. Update mlx5 timecounter init with this new function. Signed-off-by: Sagar Arun Kamble Cc: Richard Cochran Cc: Saeed Mahameed Cc: Matan Barak Cc: Leon Romanovsky Cc: Eugenia Emantayev Cc: Eitan Rabin Cc: Feras Daoud Cc: Sagar Arun Kamble Cc: Miroslav Lichvar Cc: net...@vger.kernel.org Cc: linux-r...@vger.kernel.org Cc: linux-kernel@vger.kernel.org --- drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c | 18 +++--- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c index 8cb6838..071f78a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c @@ -458,6 +458,7 @@ void mlx5_init_clock(struct mlx5_core_dev *mdev) u64 ns; u64 frac = 0; u32 dev_freq; + u32 mult, shift; dev_freq = MLX5_CAP_GEN(mdev, device_frequency_khz); if (!dev_freq) { @@ -465,13 +466,16 @@ void mlx5_init_clock(struct mlx5_core_dev *mdev) return; } rwlock_init(>lock); - cc->read = read_internal_timer; - cc->shift = MLX5_CYCLES_SHIFT; - cc->mult = clocksource_khz2mult(dev_freq, cc->shift); - clock->nominal_c_mult = cc->mult; - cc->mask = CLOCKSOURCE_MASK(41); - - timecounter_init(>tc, ktime_to_ns(ktime_get_real())); + shift = MLX5_CYCLES_SHIFT; + mult = clocksource_khz2mult(dev_freq, shift); + clock->nominal_c_mult = mult; + + timecounter_initialize(>tc, + read_internal_timer, + CLOCKSOURCE_MASK(41), + mult, + shift, + ktime_to_ns(ktime_get_real())); /* Calculate period in seconds to call the overflow watchdog - to make * sure counter is checked at least once every wrap around. -- 1.9.1
[PATCH 15/27] ALSA: hda - Use timecounter_initialize interface
With new interface timecounter_initialize we can initialize timecounter fields and underlying cyclecounter together. Update azx timecounter init with this new function. Signed-off-by: Sagar Arun KambleCc: Richard Cochran Cc: Jaroslav Kysela Cc: Takashi Iwai Cc: Thomas Gleixner Cc: Vinod Koul Cc: alsa-de...@alsa-project.org Cc: linux-kernel@vger.kernel.org --- sound/hda/hdac_stream.c | 14 ++ 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/sound/hda/hdac_stream.c b/sound/hda/hdac_stream.c index 9426c1a..ad91dde 100644 --- a/sound/hda/hdac_stream.c +++ b/sound/hda/hdac_stream.c @@ -477,12 +477,8 @@ static void azx_timecounter_init(struct hdac_stream *azx_dev, bool force, u64 last) { struct timecounter *tc = _dev->tc; - struct cyclecounter *cc = _dev->tc.cc; u64 nsec; - cc->read = azx_cc_read; - cc->mask = CLOCKSOURCE_MASK(32); - /* * Converting from 24 MHz to ns means applying a 125/3 factor. * To avoid any saturation issues in intermediate operations, @@ -493,11 +489,13 @@ static void azx_timecounter_init(struct hdac_stream *azx_dev, * overflows occur after about 4 hours or less, not a option. */ - cc->mult = 125; /* saturation after 195 years */ - cc->shift = 0; - nsec = 0; /* audio time is elapsed time since trigger */ - timecounter_init(tc, nsec); + timecounter_initialize(tc, + azx_cc_read, + CLOCKSOURCE_MASK(32), + 125, /* saturation after 195 years */ + 0, + nsec); if (force) { /* * force timecounter to use predefined value, -- 1.9.1
[PATCH 15/27] ALSA: hda - Use timecounter_initialize interface
With new interface timecounter_initialize we can initialize timecounter fields and underlying cyclecounter together. Update azx timecounter init with this new function. Signed-off-by: Sagar Arun Kamble Cc: Richard Cochran Cc: Jaroslav Kysela Cc: Takashi Iwai Cc: Thomas Gleixner Cc: Vinod Koul Cc: alsa-de...@alsa-project.org Cc: linux-kernel@vger.kernel.org --- sound/hda/hdac_stream.c | 14 ++ 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/sound/hda/hdac_stream.c b/sound/hda/hdac_stream.c index 9426c1a..ad91dde 100644 --- a/sound/hda/hdac_stream.c +++ b/sound/hda/hdac_stream.c @@ -477,12 +477,8 @@ static void azx_timecounter_init(struct hdac_stream *azx_dev, bool force, u64 last) { struct timecounter *tc = _dev->tc; - struct cyclecounter *cc = _dev->tc.cc; u64 nsec; - cc->read = azx_cc_read; - cc->mask = CLOCKSOURCE_MASK(32); - /* * Converting from 24 MHz to ns means applying a 125/3 factor. * To avoid any saturation issues in intermediate operations, @@ -493,11 +489,13 @@ static void azx_timecounter_init(struct hdac_stream *azx_dev, * overflows occur after about 4 hours or less, not a option. */ - cc->mult = 125; /* saturation after 195 years */ - cc->shift = 0; - nsec = 0; /* audio time is elapsed time since trigger */ - timecounter_init(tc, nsec); + timecounter_initialize(tc, + azx_cc_read, + CLOCKSOURCE_MASK(32), + 125, /* saturation after 195 years */ + 0, + nsec); if (force) { /* * force timecounter to use predefined value, -- 1.9.1
[PATCH 14/27] net: cpts: Use timecounter_initialize interface
With new interface timecounter_initialize we can initialize timecounter fields and underlying cyclecounter together. Update cpts timecounter init with this new function. Signed-off-by: Sagar Arun KambleCc: "David S. Miller" Cc: Grygorii Strashko Cc: Richard Cochran Cc: Bhumika Goyal Cc: Thomas Gleixner Cc: Ivan Khoronzhuk Cc: net...@vger.kernel.org Cc: linux-kernel@vger.kernel.org --- drivers/net/ethernet/ti/cpts.c | 29 + drivers/net/ethernet/ti/cpts.h | 3 +++ 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/ti/cpts.c b/drivers/net/ethernet/ti/cpts.c index b8fe843..e6afc94 100644 --- a/drivers/net/ethernet/ti/cpts.c +++ b/drivers/net/ethernet/ti/cpts.c @@ -447,7 +447,12 @@ int cpts_register(struct cpts *cpts) cpts_write32(cpts, CPTS_EN, control); cpts_write32(cpts, TS_PEND_EN, int_enable); - timecounter_init(>tc, ktime_to_ns(ktime_get_real())); + timecounter_initialize(>tc, + cpts_systim_read, + cpts->mask, + cpts->mult, + cpts->shift, + ktime_to_ns(ktime_get_real())); cpts->clock = ptp_clock_register(>info, cpts->dev); if (IS_ERR(cpts->clock)) { @@ -484,7 +489,8 @@ void cpts_unregister(struct cpts *cpts) } EXPORT_SYMBOL_GPL(cpts_unregister); -static void cpts_calc_mult_shift(struct cpts *cpts) +static void cpts_calc_mult_shift(struct cpts *cpts, u64 mask, +u32 *mult, u32 *shift) { struct cyclecounter *cc = >tc.cc; u64 frac, maxsec, ns; @@ -495,7 +501,7 @@ static void cpts_calc_mult_shift(struct cpts *cpts) /* Calc the maximum number of seconds which we can run before * wrapping around. */ - maxsec = cc->mask; + maxsec = mask; do_div(maxsec, freq); /* limit conversation rate to 10 sec as higher values will produce * too small mult factors and so reduce the conversion accuracy @@ -508,18 +514,18 @@ static void cpts_calc_mult_shift(struct cpts *cpts) dev_info(cpts->dev, "cpts: overflow check period %lu (jiffies)\n", cpts->ov_check_period); - if (cc->mult || cc->shift) + if (*mult || *shift) return; - clocks_calc_mult_shift(>mult, >shift, + clocks_calc_mult_shift(mult, shift, freq, NSEC_PER_SEC, maxsec); frac = 0; - ns = cyclecounter_cyc2ns(cc, freq, cc->mask, ); + ns = cyclecounter_cyc2ns(cc, freq, mask, ); dev_info(cpts->dev, "CPTS: ref_clk_freq:%u calc_mult:%u calc_shift:%u error:%lld nsec/sec\n", -freq, cc->mult, cc->shift, +freq, *mult, *shift, (ns - NSEC_PER_SEC)); } @@ -571,15 +577,14 @@ struct cpts *cpts_create(struct device *dev, void __iomem *regs, clk_prepare(cpts->refclk); - cpts->tc.cc.read = cpts_systim_read; - cpts->tc.cc.mask = CLOCKSOURCE_MASK(32); + cpts->mask = CLOCKSOURCE_MASK(32); cpts->info = cpts_info; - cpts_calc_mult_shift(cpts); - /* save tc.cc.mult original value as it can be modified + cpts_calc_mult_shift(cpts, cpts->mask, >mult, >shift); + /* save mult original value as it can be modified * by cpts_ptp_adjfreq(). */ - cpts->cc_mult = cpts->tc.cc.mult; + cpts->cc_mult = cpts->mult; return cpts; } diff --git a/drivers/net/ethernet/ti/cpts.h b/drivers/net/ethernet/ti/cpts.h index a7174eb..da50d34 100644 --- a/drivers/net/ethernet/ti/cpts.h +++ b/drivers/net/ethernet/ti/cpts.h @@ -118,6 +118,9 @@ struct cpts { spinlock_t lock; /* protects time registers */ u32 cc_mult; /* for the nominal frequency */ struct timecounter tc; + u64 mask; + u32 mult; + u32 shift; int phc_index; struct clk *refclk; struct list_head events; -- 1.9.1
[PATCH 14/27] net: cpts: Use timecounter_initialize interface
With new interface timecounter_initialize we can initialize timecounter fields and underlying cyclecounter together. Update cpts timecounter init with this new function. Signed-off-by: Sagar Arun Kamble Cc: "David S. Miller" Cc: Grygorii Strashko Cc: Richard Cochran Cc: Bhumika Goyal Cc: Thomas Gleixner Cc: Ivan Khoronzhuk Cc: net...@vger.kernel.org Cc: linux-kernel@vger.kernel.org --- drivers/net/ethernet/ti/cpts.c | 29 + drivers/net/ethernet/ti/cpts.h | 3 +++ 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/ti/cpts.c b/drivers/net/ethernet/ti/cpts.c index b8fe843..e6afc94 100644 --- a/drivers/net/ethernet/ti/cpts.c +++ b/drivers/net/ethernet/ti/cpts.c @@ -447,7 +447,12 @@ int cpts_register(struct cpts *cpts) cpts_write32(cpts, CPTS_EN, control); cpts_write32(cpts, TS_PEND_EN, int_enable); - timecounter_init(>tc, ktime_to_ns(ktime_get_real())); + timecounter_initialize(>tc, + cpts_systim_read, + cpts->mask, + cpts->mult, + cpts->shift, + ktime_to_ns(ktime_get_real())); cpts->clock = ptp_clock_register(>info, cpts->dev); if (IS_ERR(cpts->clock)) { @@ -484,7 +489,8 @@ void cpts_unregister(struct cpts *cpts) } EXPORT_SYMBOL_GPL(cpts_unregister); -static void cpts_calc_mult_shift(struct cpts *cpts) +static void cpts_calc_mult_shift(struct cpts *cpts, u64 mask, +u32 *mult, u32 *shift) { struct cyclecounter *cc = >tc.cc; u64 frac, maxsec, ns; @@ -495,7 +501,7 @@ static void cpts_calc_mult_shift(struct cpts *cpts) /* Calc the maximum number of seconds which we can run before * wrapping around. */ - maxsec = cc->mask; + maxsec = mask; do_div(maxsec, freq); /* limit conversation rate to 10 sec as higher values will produce * too small mult factors and so reduce the conversion accuracy @@ -508,18 +514,18 @@ static void cpts_calc_mult_shift(struct cpts *cpts) dev_info(cpts->dev, "cpts: overflow check period %lu (jiffies)\n", cpts->ov_check_period); - if (cc->mult || cc->shift) + if (*mult || *shift) return; - clocks_calc_mult_shift(>mult, >shift, + clocks_calc_mult_shift(mult, shift, freq, NSEC_PER_SEC, maxsec); frac = 0; - ns = cyclecounter_cyc2ns(cc, freq, cc->mask, ); + ns = cyclecounter_cyc2ns(cc, freq, mask, ); dev_info(cpts->dev, "CPTS: ref_clk_freq:%u calc_mult:%u calc_shift:%u error:%lld nsec/sec\n", -freq, cc->mult, cc->shift, +freq, *mult, *shift, (ns - NSEC_PER_SEC)); } @@ -571,15 +577,14 @@ struct cpts *cpts_create(struct device *dev, void __iomem *regs, clk_prepare(cpts->refclk); - cpts->tc.cc.read = cpts_systim_read; - cpts->tc.cc.mask = CLOCKSOURCE_MASK(32); + cpts->mask = CLOCKSOURCE_MASK(32); cpts->info = cpts_info; - cpts_calc_mult_shift(cpts); - /* save tc.cc.mult original value as it can be modified + cpts_calc_mult_shift(cpts, cpts->mask, >mult, >shift); + /* save mult original value as it can be modified * by cpts_ptp_adjfreq(). */ - cpts->cc_mult = cpts->tc.cc.mult; + cpts->cc_mult = cpts->mult; return cpts; } diff --git a/drivers/net/ethernet/ti/cpts.h b/drivers/net/ethernet/ti/cpts.h index a7174eb..da50d34 100644 --- a/drivers/net/ethernet/ti/cpts.h +++ b/drivers/net/ethernet/ti/cpts.h @@ -118,6 +118,9 @@ struct cpts { spinlock_t lock; /* protects time registers */ u32 cc_mult; /* for the nominal frequency */ struct timecounter tc; + u64 mask; + u32 mult; + u32 shift; int phc_index; struct clk *refclk; struct list_head events; -- 1.9.1
[PATCH 18/27] bnx2x: Use timecounter_reset interface
With new interface timecounter_reset we can update the start time for timecounter. Update bnx2x_ptp_settime with this new function. Signed-off-by: Sagar Arun KambleCc: Richard Cochran Cc: Ariel Elior Cc: everest-linux...@cavium.com Cc: net...@vger.kernel.org Cc: linux-kernel@vger.kernel.org --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 1e10a81..e30e736 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -13849,8 +13849,8 @@ static int bnx2x_ptp_settime(struct ptp_clock_info *ptp, DP(BNX2X_MSG_PTP, "PTP settime called, ns = %llu\n", ns); - /* Re-init the timecounter */ - timecounter_init(>timecounter, ns); + /* Reset the timecounter */ + timecounter_reset(>timecounter, ns); return 0; } -- 1.9.1
[PATCH 16/27] timecounter: Introduce timecounter_reset
timecounter_init initializes the cyclecounter and sets the start time. Sometimes drivers using timecounter just want to update start time. This patch creates new function timecounter_reset that just resets the timecounter start time and associated state. Suggested-by: Richard CochranSigned-off-by: Sagar Arun Kamble Cc: Richard Cochran Cc: Chris Wilson Cc: John Stultz Cc: Thomas Gleixner Cc: Stephen Boyd Cc: linux-kernel@vger.kernel.org --- include/linux/timecounter.h | 17 +++-- kernel/time/timecounter.c | 9 + 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/include/linux/timecounter.h b/include/linux/timecounter.h index 59d3fd7..e0fd741 100644 --- a/include/linux/timecounter.h +++ b/include/linux/timecounter.h @@ -98,7 +98,7 @@ static inline void timecounter_adjtime(struct timecounter *tc, s64 delta) /** * timecounter_init - initialize a time counter - * @tc:Pointer to time counter which is to be initialized/reset + * @tc:Pointer to time counter which is to be initialized * @start_tstamp: Arbitrary initial time stamp. * * After this call the current cycle register (roughly) corresponds to @@ -131,8 +131,21 @@ extern void timecounter_initialize(struct timecounter *tc, u64 start_tstamp); /** + * timecounter_reset - reset a time counter + * @tc:Pointer to time counter which is to be reset + * @start_tstamp: Arbitrary initial time stamp. + * + * After this call the current cycle register (roughly) corresponds to + * the supplied time stamp. Every call to timecounter_read() increments + * the time stamp counter by the number of elapsed nanoseconds. + */ +extern void timecounter_reset(struct timecounter *tc, + u64 start_tstamp); + +/** * timecounter_read - return nanoseconds elapsed since timecounter_init() or - *timecounter_initialize() plus the initial time stamp + *timecounter_initialize() or timecounter_reset() plus + * the initial time stamp * @tc: Pointer to time counter. * * In other words, keeps track of time since the same epoch as diff --git a/kernel/time/timecounter.c b/kernel/time/timecounter.c index 6d915752..3f62fe0 100644 --- a/kernel/time/timecounter.c +++ b/kernel/time/timecounter.c @@ -47,6 +47,15 @@ void timecounter_initialize(struct timecounter *tc, } EXPORT_SYMBOL_GPL(timecounter_initialize); +void timecounter_reset(struct timecounter *tc, + u64 start_tstamp) +{ + tc->cycle_last = tc->cc.read(>cc); + tc->nsec = start_tstamp; + tc->frac = 0; +} +EXPORT_SYMBOL_GPL(timecounter_reset); + /** * timecounter_read_delta - get nanoseconds since last call of this function * @tc: Pointer to time counter -- 1.9.1
[PATCH 18/27] bnx2x: Use timecounter_reset interface
With new interface timecounter_reset we can update the start time for timecounter. Update bnx2x_ptp_settime with this new function. Signed-off-by: Sagar Arun Kamble Cc: Richard Cochran Cc: Ariel Elior Cc: everest-linux...@cavium.com Cc: net...@vger.kernel.org Cc: linux-kernel@vger.kernel.org --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 1e10a81..e30e736 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -13849,8 +13849,8 @@ static int bnx2x_ptp_settime(struct ptp_clock_info *ptp, DP(BNX2X_MSG_PTP, "PTP settime called, ns = %llu\n", ns); - /* Re-init the timecounter */ - timecounter_init(>timecounter, ns); + /* Reset the timecounter */ + timecounter_reset(>timecounter, ns); return 0; } -- 1.9.1
[PATCH 16/27] timecounter: Introduce timecounter_reset
timecounter_init initializes the cyclecounter and sets the start time. Sometimes drivers using timecounter just want to update start time. This patch creates new function timecounter_reset that just resets the timecounter start time and associated state. Suggested-by: Richard Cochran Signed-off-by: Sagar Arun Kamble Cc: Richard Cochran Cc: Chris Wilson Cc: John Stultz Cc: Thomas Gleixner Cc: Stephen Boyd Cc: linux-kernel@vger.kernel.org --- include/linux/timecounter.h | 17 +++-- kernel/time/timecounter.c | 9 + 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/include/linux/timecounter.h b/include/linux/timecounter.h index 59d3fd7..e0fd741 100644 --- a/include/linux/timecounter.h +++ b/include/linux/timecounter.h @@ -98,7 +98,7 @@ static inline void timecounter_adjtime(struct timecounter *tc, s64 delta) /** * timecounter_init - initialize a time counter - * @tc:Pointer to time counter which is to be initialized/reset + * @tc:Pointer to time counter which is to be initialized * @start_tstamp: Arbitrary initial time stamp. * * After this call the current cycle register (roughly) corresponds to @@ -131,8 +131,21 @@ extern void timecounter_initialize(struct timecounter *tc, u64 start_tstamp); /** + * timecounter_reset - reset a time counter + * @tc:Pointer to time counter which is to be reset + * @start_tstamp: Arbitrary initial time stamp. + * + * After this call the current cycle register (roughly) corresponds to + * the supplied time stamp. Every call to timecounter_read() increments + * the time stamp counter by the number of elapsed nanoseconds. + */ +extern void timecounter_reset(struct timecounter *tc, + u64 start_tstamp); + +/** * timecounter_read - return nanoseconds elapsed since timecounter_init() or - *timecounter_initialize() plus the initial time stamp + *timecounter_initialize() or timecounter_reset() plus + * the initial time stamp * @tc: Pointer to time counter. * * In other words, keeps track of time since the same epoch as diff --git a/kernel/time/timecounter.c b/kernel/time/timecounter.c index 6d915752..3f62fe0 100644 --- a/kernel/time/timecounter.c +++ b/kernel/time/timecounter.c @@ -47,6 +47,15 @@ void timecounter_initialize(struct timecounter *tc, } EXPORT_SYMBOL_GPL(timecounter_initialize); +void timecounter_reset(struct timecounter *tc, + u64 start_tstamp) +{ + tc->cycle_last = tc->cc.read(>cc); + tc->nsec = start_tstamp; + tc->frac = 0; +} +EXPORT_SYMBOL_GPL(timecounter_reset); + /** * timecounter_read_delta - get nanoseconds since last call of this function * @tc: Pointer to time counter -- 1.9.1
Re: [PATCH tip 0/3] Improvements of scheduler related Tracepoints
On Thu, Dec 14, 2017 at 07:16:00PM -0800, Alexei Starovoitov wrote: > On 12/14/17 12:49 PM, Peter Zijlstra wrote: > > On Thu, Dec 14, 2017 at 12:20:41PM -0800, Teng Qin wrote: > > > This set of commits attempts to improve three scheduler related > > > Tracepoints: sched_switch, sched_process_fork, sched_process_exit. > > > > > > Firstly, these commit add additional flag values, namely preempt, > > > clone_flags and group_dead to these Tracepoints, to make information > > > exposed via the Tracepoints more useful and complete. > > > > > > Secondly, these commits exposes task_struct pointers in these > > > Tracepoints. The task_struct pointers are arguments of the Tracepoints > > > and currently only used to compute struct field values. But for BPF > > > programs attached to these Tracepoints, we may want to read additional > > > task information via the task_struct pointers. This is currently either > > > impossible, or we have to make assumption of whether the Tracepoint is > > > running from previous / parent or next / child, and use current pointer > > > instead. Exposing the task_struct pointers explicitly makes such use > > > case easier and more reliable. > > > > > > > NAK > > not sure what is the concern here. > Is it first or second part of the above ? Definitely the second, but also the first. You know I would have ripped out all scheduler tracepoints if I could have. They're a pain in the arse. A lot of people want to add to the tracepoints, with the end result that they'll end up a big bloated pile of useless crap. The first part is just the pieces you want added. As to the second, that's complete crap; that just makes everything slower for bodies benefit. If you register a traceprobe you already get access to these things. I think your problem is that you use perf to get access to the tracepoints, which them means you have to do disgusting things like this.
Re: [PATCH tip 0/3] Improvements of scheduler related Tracepoints
On Thu, Dec 14, 2017 at 07:16:00PM -0800, Alexei Starovoitov wrote: > On 12/14/17 12:49 PM, Peter Zijlstra wrote: > > On Thu, Dec 14, 2017 at 12:20:41PM -0800, Teng Qin wrote: > > > This set of commits attempts to improve three scheduler related > > > Tracepoints: sched_switch, sched_process_fork, sched_process_exit. > > > > > > Firstly, these commit add additional flag values, namely preempt, > > > clone_flags and group_dead to these Tracepoints, to make information > > > exposed via the Tracepoints more useful and complete. > > > > > > Secondly, these commits exposes task_struct pointers in these > > > Tracepoints. The task_struct pointers are arguments of the Tracepoints > > > and currently only used to compute struct field values. But for BPF > > > programs attached to these Tracepoints, we may want to read additional > > > task information via the task_struct pointers. This is currently either > > > impossible, or we have to make assumption of whether the Tracepoint is > > > running from previous / parent or next / child, and use current pointer > > > instead. Exposing the task_struct pointers explicitly makes such use > > > case easier and more reliable. > > > > > > > NAK > > not sure what is the concern here. > Is it first or second part of the above ? Definitely the second, but also the first. You know I would have ripped out all scheduler tracepoints if I could have. They're a pain in the arse. A lot of people want to add to the tracepoints, with the end result that they'll end up a big bloated pile of useless crap. The first part is just the pieces you want added. As to the second, that's complete crap; that just makes everything slower for bodies benefit. If you register a traceprobe you already get access to these things. I think your problem is that you use perf to get access to the tracepoints, which them means you have to do disgusting things like this.
Re: [PATCH] locking/lockdep: Remove the cross-release locking checks
On Fri, Dec 15, 2017 at 3:24 PM, Theodore Ts'owrote: > On Fri, Dec 15, 2017 at 01:05:43PM +0900, Byungchul Park wrote: >> For example, in the case of fs issues, for now we can >> invalidate wait_for_completion() in submit_bio_wait() > > And this will spawn a checkpatch.pl ERROR: > > ERROR("LOCKDEP", > "lockdep_no_validate class is reserved for > device->mutex.\n" . $herecurr); > > This mention in checkpatch.pl is the only documentation I've been able > to find about lockdep_set_novalidate_class(), by the way. > >> ... and re-validate it later, of course, I really want to find more >> fundamental solution though. > > Oh, and I was finally able to find the quote that the *only* people > who are likely to be able to deal with lock annotations are the Right. Using the word, "only", is one that I should not have done and I apologize for. They are just "only" people who solve and classify locks quickly, assuming all of kernel guys are familiar with lockdep annotations. Thus, even this statement is bad as well, since no good document for that exists, as you pointed out. I agree. > subsystem maintainers. But if the ways of dealing with lock > annotations are not documented, such that subsystem maintainers are > going to have a very hard time figuring out *how* to deal with it, it Right. I've agreed with this, since you pointed out it's problem not to be documented well. > seems that lock classification as a solution to cross-release false > positives seems unlikely: > >From: Byungchul Park >Date: Fri, 8 Dec 2017 18:27:45 +0900 >Subject: Re: [PATCH v4 72/73] xfs: Convert mru cache to XArray > >1) Firstly, it's hard to assign lock classes *properly*. By >default, it relies on the caller site of lockdep_init_map(), >but we need to assign another class manually, where ordering >rules are complicated so cannot rely on the caller site. That >*only* can be done by experts of the subsystem. > > - Ted -- Thanks, Byungchul
Re: [PATCH] locking/lockdep: Remove the cross-release locking checks
On Fri, Dec 15, 2017 at 3:24 PM, Theodore Ts'o wrote: > On Fri, Dec 15, 2017 at 01:05:43PM +0900, Byungchul Park wrote: >> For example, in the case of fs issues, for now we can >> invalidate wait_for_completion() in submit_bio_wait() > > And this will spawn a checkpatch.pl ERROR: > > ERROR("LOCKDEP", > "lockdep_no_validate class is reserved for > device->mutex.\n" . $herecurr); > > This mention in checkpatch.pl is the only documentation I've been able > to find about lockdep_set_novalidate_class(), by the way. > >> ... and re-validate it later, of course, I really want to find more >> fundamental solution though. > > Oh, and I was finally able to find the quote that the *only* people > who are likely to be able to deal with lock annotations are the Right. Using the word, "only", is one that I should not have done and I apologize for. They are just "only" people who solve and classify locks quickly, assuming all of kernel guys are familiar with lockdep annotations. Thus, even this statement is bad as well, since no good document for that exists, as you pointed out. I agree. > subsystem maintainers. But if the ways of dealing with lock > annotations are not documented, such that subsystem maintainers are > going to have a very hard time figuring out *how* to deal with it, it Right. I've agreed with this, since you pointed out it's problem not to be documented well. > seems that lock classification as a solution to cross-release false > positives seems unlikely: > >From: Byungchul Park >Date: Fri, 8 Dec 2017 18:27:45 +0900 >Subject: Re: [PATCH v4 72/73] xfs: Convert mru cache to XArray > >1) Firstly, it's hard to assign lock classes *properly*. By >default, it relies on the caller site of lockdep_init_map(), >but we need to assign another class manually, where ordering >rules are complicated so cannot rely on the caller site. That >*only* can be done by experts of the subsystem. > > - Ted -- Thanks, Byungchul
[PATCH 22/27] ixgbe: Use timecounter_reset interface
With new interface timecounter_reset we can update the start time for timecounter. Update ixgbe_ptp_settime with this new function. Signed-off-by: Sagar Arun KambleCc: Richard Cochran Cc: Jeff Kirsher Cc: intel-wired-...@lists.osuosl.org Cc: net...@vger.kernel.org Cc: linux-kernel@vger.kernel.org --- drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c index 073c1ef..35f85ef 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c @@ -508,7 +508,7 @@ static int ixgbe_ptp_settime(struct ptp_clock_info *ptp, /* reset the timecounter */ spin_lock_irqsave(>tmreg_lock, flags); - timecounter_init(>hw_tc, ns); + timecounter_reset(>hw_tc, ns); spin_unlock_irqrestore(>tmreg_lock, flags); if (adapter->ptp_setup_sdp) -- 1.9.1
[PATCH 22/27] ixgbe: Use timecounter_reset interface
With new interface timecounter_reset we can update the start time for timecounter. Update ixgbe_ptp_settime with this new function. Signed-off-by: Sagar Arun Kamble Cc: Richard Cochran Cc: Jeff Kirsher Cc: intel-wired-...@lists.osuosl.org Cc: net...@vger.kernel.org Cc: linux-kernel@vger.kernel.org --- drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c index 073c1ef..35f85ef 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c @@ -508,7 +508,7 @@ static int ixgbe_ptp_settime(struct ptp_clock_info *ptp, /* reset the timecounter */ spin_lock_irqsave(>tmreg_lock, flags); - timecounter_init(>hw_tc, ns); + timecounter_reset(>hw_tc, ns); spin_unlock_irqrestore(>tmreg_lock, flags); if (adapter->ptp_setup_sdp) -- 1.9.1
[PATCH 23/27] net/mlx4: Use timecounter_reset interface
With new interface timecounter_reset we can update the start time for timecounter. Update mlx4_en_phc_settime with this new function. Signed-off-by: Sagar Arun KambleCc: Richard Cochran Cc: Tariq Toukan Cc: net...@vger.kernel.org Cc: linux-r...@vger.kernel.org Cc: linux-kernel@vger.kernel.org --- drivers/net/ethernet/mellanox/mlx4/en_clock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/en_clock.c b/drivers/net/ethernet/mellanox/mlx4/en_clock.c index dd736cc..bfed4ac 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_clock.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_clock.c @@ -207,7 +207,7 @@ static int mlx4_en_phc_settime(struct ptp_clock_info *ptp, /* reset the timecounter */ write_seqlock_irqsave(>clock_lock, flags); - timecounter_init(>clock, ns); + timecounter_reset(>clock, ns); write_sequnlock_irqrestore(>clock_lock, flags); return 0; -- 1.9.1
[PATCH 21/27] igb: Use timecounter_reset interface
With new interface timecounter_reset we can update the start time for timecounter. Update igb_ptp_settime_82576 with this new function. Signed-off-by: Sagar Arun KambleCc: Richard Cochran Cc: Jeff Kirsher Cc: intel-wired-...@lists.osuosl.org Cc: net...@vger.kernel.org Cc: linux-kernel@vger.kernel.org --- drivers/net/ethernet/intel/igb/igb_ptp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/igb/igb_ptp.c b/drivers/net/ethernet/intel/igb/igb_ptp.c index f6c1a8d..90344b2 100644 --- a/drivers/net/ethernet/intel/igb/igb_ptp.c +++ b/drivers/net/ethernet/intel/igb/igb_ptp.c @@ -330,7 +330,7 @@ static int igb_ptp_settime_82576(struct ptp_clock_info *ptp, spin_lock_irqsave(>tmreg_lock, flags); - timecounter_init(>tc, ns); + timecounter_reset(>tc, ns); spin_unlock_irqrestore(>tmreg_lock, flags); -- 1.9.1
[PATCH 21/27] igb: Use timecounter_reset interface
With new interface timecounter_reset we can update the start time for timecounter. Update igb_ptp_settime_82576 with this new function. Signed-off-by: Sagar Arun Kamble Cc: Richard Cochran Cc: Jeff Kirsher Cc: intel-wired-...@lists.osuosl.org Cc: net...@vger.kernel.org Cc: linux-kernel@vger.kernel.org --- drivers/net/ethernet/intel/igb/igb_ptp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/igb/igb_ptp.c b/drivers/net/ethernet/intel/igb/igb_ptp.c index f6c1a8d..90344b2 100644 --- a/drivers/net/ethernet/intel/igb/igb_ptp.c +++ b/drivers/net/ethernet/intel/igb/igb_ptp.c @@ -330,7 +330,7 @@ static int igb_ptp_settime_82576(struct ptp_clock_info *ptp, spin_lock_irqsave(>tmreg_lock, flags); - timecounter_init(>tc, ns); + timecounter_reset(>tc, ns); spin_unlock_irqrestore(>tmreg_lock, flags); -- 1.9.1
[PATCH 23/27] net/mlx4: Use timecounter_reset interface
With new interface timecounter_reset we can update the start time for timecounter. Update mlx4_en_phc_settime with this new function. Signed-off-by: Sagar Arun Kamble Cc: Richard Cochran Cc: Tariq Toukan Cc: net...@vger.kernel.org Cc: linux-r...@vger.kernel.org Cc: linux-kernel@vger.kernel.org --- drivers/net/ethernet/mellanox/mlx4/en_clock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/en_clock.c b/drivers/net/ethernet/mellanox/mlx4/en_clock.c index dd736cc..bfed4ac 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_clock.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_clock.c @@ -207,7 +207,7 @@ static int mlx4_en_phc_settime(struct ptp_clock_info *ptp, /* reset the timecounter */ write_seqlock_irqsave(>clock_lock, flags); - timecounter_init(>clock, ns); + timecounter_reset(>clock, ns); write_sequnlock_irqrestore(>clock_lock, flags); return 0; -- 1.9.1
[PATCH 24/27] net/mlx5: Use timecounter_reset interface
With new interface timecounter_reset we can update the start time for timecounter. Update mlx5_ptp_settime with this new function. Signed-off-by: Sagar Arun KambleCc: Richard Cochran Cc: Saeed Mahameed Cc: Matan Barak Cc: Leon Romanovsky Cc: Eugenia Emantayev Cc: Eitan Rabin Cc: Feras Daoud Cc: Tariq Toukan Cc: Thomas Gleixner Cc: net...@vger.kernel.org Cc: linux-r...@vger.kernel.org Cc: linux-kernel@vger.kernel.org --- drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c index 071f78a..e490522 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c @@ -122,7 +122,7 @@ static int mlx5_ptp_settime(struct ptp_clock_info *ptp, unsigned long flags; write_lock_irqsave(>lock, flags); - timecounter_init(>tc, ns); + timecounter_reset(>tc, ns); write_unlock_irqrestore(>lock, flags); return 0; -- 1.9.1
[PATCH 24/27] net/mlx5: Use timecounter_reset interface
With new interface timecounter_reset we can update the start time for timecounter. Update mlx5_ptp_settime with this new function. Signed-off-by: Sagar Arun Kamble Cc: Richard Cochran Cc: Saeed Mahameed Cc: Matan Barak Cc: Leon Romanovsky Cc: Eugenia Emantayev Cc: Eitan Rabin Cc: Feras Daoud Cc: Tariq Toukan Cc: Thomas Gleixner Cc: net...@vger.kernel.org Cc: linux-r...@vger.kernel.org Cc: linux-kernel@vger.kernel.org --- drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c index 071f78a..e490522 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c @@ -122,7 +122,7 @@ static int mlx5_ptp_settime(struct ptp_clock_info *ptp, unsigned long flags; write_lock_irqsave(>lock, flags); - timecounter_init(>tc, ns); + timecounter_reset(>tc, ns); write_unlock_irqrestore(>lock, flags); return 0; -- 1.9.1
[PATCH 25/27] qede: Use timecounter_reset interface
With new interface timecounter_reset we can update the start time for timecounter. Update qede_ptp_settime with this new function. Signed-off-by: Sagar Arun KambleCc: Richard Cochran Cc: Ariel Elior Cc: everest-linux...@cavium.com Cc: net...@vger.kernel.org Cc: linux-kernel@vger.kernel.org --- drivers/net/ethernet/qlogic/qede/qede_ptp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qede/qede_ptp.c b/drivers/net/ethernet/qlogic/qede/qede_ptp.c index 0d054dc..c2de311 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_ptp.c +++ b/drivers/net/ethernet/qlogic/qede/qede_ptp.c @@ -129,9 +129,9 @@ static int qede_ptp_settime(struct ptp_clock_info *info, DP_VERBOSE(edev, QED_MSG_DEBUG, "PTP settime called, ns = %llu\n", ns); - /* Re-init the timecounter */ + /* Reset the timecounter */ spin_lock_bh(>lock); - timecounter_init(>tc, ns); + timecounter_reset(>tc, ns); spin_unlock_bh(>lock); return 0; -- 1.9.1
[PATCH 26/27] net: cpts: Use timecounter_reset interface
With new interface timecounter_reset we can update the start time for timecounter. Update cpts_ptp_settime with this new function. Signed-off-by: Sagar Arun KambleCc: "David S. Miller" Cc: Grygorii Strashko Cc: Bhumika Goyal Cc: Richard Cochran Cc: Thomas Gleixner Cc: net...@vger.kernel.org Cc: linux-kernel@vger.kernel.org --- drivers/net/ethernet/ti/cpts.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/ti/cpts.c b/drivers/net/ethernet/ti/cpts.c index e6afc94..41bac4d 100644 --- a/drivers/net/ethernet/ti/cpts.c +++ b/drivers/net/ethernet/ti/cpts.c @@ -268,7 +268,7 @@ static int cpts_ptp_settime(struct ptp_clock_info *ptp, ns = timespec64_to_ns(ts); spin_lock_irqsave(>lock, flags); - timecounter_init(>tc, ns); + timecounter_reset(>tc, ns); spin_unlock_irqrestore(>lock, flags); return 0; -- 1.9.1
[PATCH 25/27] qede: Use timecounter_reset interface
With new interface timecounter_reset we can update the start time for timecounter. Update qede_ptp_settime with this new function. Signed-off-by: Sagar Arun Kamble Cc: Richard Cochran Cc: Ariel Elior Cc: everest-linux...@cavium.com Cc: net...@vger.kernel.org Cc: linux-kernel@vger.kernel.org --- drivers/net/ethernet/qlogic/qede/qede_ptp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qede/qede_ptp.c b/drivers/net/ethernet/qlogic/qede/qede_ptp.c index 0d054dc..c2de311 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_ptp.c +++ b/drivers/net/ethernet/qlogic/qede/qede_ptp.c @@ -129,9 +129,9 @@ static int qede_ptp_settime(struct ptp_clock_info *info, DP_VERBOSE(edev, QED_MSG_DEBUG, "PTP settime called, ns = %llu\n", ns); - /* Re-init the timecounter */ + /* Reset the timecounter */ spin_lock_bh(>lock); - timecounter_init(>tc, ns); + timecounter_reset(>tc, ns); spin_unlock_bh(>lock); return 0; -- 1.9.1
[PATCH 26/27] net: cpts: Use timecounter_reset interface
With new interface timecounter_reset we can update the start time for timecounter. Update cpts_ptp_settime with this new function. Signed-off-by: Sagar Arun Kamble Cc: "David S. Miller" Cc: Grygorii Strashko Cc: Bhumika Goyal Cc: Richard Cochran Cc: Thomas Gleixner Cc: net...@vger.kernel.org Cc: linux-kernel@vger.kernel.org --- drivers/net/ethernet/ti/cpts.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/ti/cpts.c b/drivers/net/ethernet/ti/cpts.c index e6afc94..41bac4d 100644 --- a/drivers/net/ethernet/ti/cpts.c +++ b/drivers/net/ethernet/ti/cpts.c @@ -268,7 +268,7 @@ static int cpts_ptp_settime(struct ptp_clock_info *ptp, ns = timespec64_to_ns(ts); spin_lock_irqsave(>lock, flags); - timecounter_init(>tc, ns); + timecounter_reset(>tc, ns); spin_unlock_irqrestore(>lock, flags); return 0; -- 1.9.1
[PATCH 20/27] e1000e: Use timecounter_reset interface
With new interface timecounter_reset we can update the start time for timecounter. Update e1000e_phc_settime with this new function. Signed-off-by: Sagar Arun KambleCc: Richard Cochran Cc: Jeff Kirsher Cc: intel-wired-...@lists.osuosl.org Cc: net...@vger.kernel.org Cc: linux-kernel@vger.kernel.org --- drivers/net/ethernet/intel/e1000e/ptp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/e1000e/ptp.c b/drivers/net/ethernet/intel/e1000e/ptp.c index 03d5f2a..5b368aa 100644 --- a/drivers/net/ethernet/intel/e1000e/ptp.c +++ b/drivers/net/ethernet/intel/e1000e/ptp.c @@ -222,7 +222,7 @@ static int e1000e_phc_settime(struct ptp_clock_info *ptp, /* reset the timecounter */ spin_lock_irqsave(>systim_lock, flags); - timecounter_init(>tc, ns); + timecounter_reset(>tc, ns); spin_unlock_irqrestore(>systim_lock, flags); return 0; -- 1.9.1
[PATCH 20/27] e1000e: Use timecounter_reset interface
With new interface timecounter_reset we can update the start time for timecounter. Update e1000e_phc_settime with this new function. Signed-off-by: Sagar Arun Kamble Cc: Richard Cochran Cc: Jeff Kirsher Cc: intel-wired-...@lists.osuosl.org Cc: net...@vger.kernel.org Cc: linux-kernel@vger.kernel.org --- drivers/net/ethernet/intel/e1000e/ptp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/e1000e/ptp.c b/drivers/net/ethernet/intel/e1000e/ptp.c index 03d5f2a..5b368aa 100644 --- a/drivers/net/ethernet/intel/e1000e/ptp.c +++ b/drivers/net/ethernet/intel/e1000e/ptp.c @@ -222,7 +222,7 @@ static int e1000e_phc_settime(struct ptp_clock_info *ptp, /* reset the timecounter */ spin_lock_irqsave(>systim_lock, flags); - timecounter_init(>tc, ns); + timecounter_reset(>tc, ns); spin_unlock_irqrestore(>systim_lock, flags); return 0; -- 1.9.1
[PATCH 17/27] amd-xgbe: Use timecounter_reset interface
With new interface timecounter_reset we can update the start time for timecounter. Update xgbe_config_tstamp and xgbe_settime with this new function. Signed-off-by: Sagar Arun KambleCc: Richard Cochran Cc: Tom Lendacky Cc: net...@vger.kernel.org Cc: linux-kernel@vger.kernel.org --- drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 4 ++-- drivers/net/ethernet/amd/xgbe/xgbe-ptp.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c index 5005c87..aee99de 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c @@ -1621,8 +1621,8 @@ static int xgbe_config_tstamp(struct xgbe_prv_data *pdata, xgbe_update_tstamp_addend(pdata, pdata->tstamp_addend); xgbe_set_tstamp_time(pdata, 0, 0); - /* Initialize the timecounter */ - timecounter_init(>tstamp_tc, ktime_to_ns(ktime_get_real())); + /* Reset the timecounter */ + timecounter_reset(>tstamp_tc, ktime_to_ns(ktime_get_real())); return 0; } diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c b/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c index 486437b..5fcde50 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c @@ -211,7 +211,7 @@ static int xgbe_settime(struct ptp_clock_info *info, spin_lock_irqsave(>tstamp_lock, flags); - timecounter_init(>tstamp_tc, nsec); + timecounter_reset(>tstamp_tc, nsec); spin_unlock_irqrestore(>tstamp_lock, flags); -- 1.9.1
[PATCH 27/27] timecounter: Remove timecounter_init
With all timecounter users now initializing timecounter using timecounter_initialize remove timecounter_init function. Signed-off-by: Sagar Arun KambleCc: Richard Cochran Cc: John Stultz Cc: Thomas Gleixner Cc: Stephen Boyd Cc: linux-kernel@vger.kernel.org --- include/linux/timecounter.h | 20 +++- kernel/time/timecounter.c | 16 2 files changed, 7 insertions(+), 29 deletions(-) diff --git a/include/linux/timecounter.h b/include/linux/timecounter.h index e0fd741..e3e1d1e 100644 --- a/include/linux/timecounter.h +++ b/include/linux/timecounter.h @@ -46,8 +46,7 @@ struct cyclecounter { /** * struct timecounter - layer above a %struct cyclecounter which counts nanoseconds * Contains the state needed by timecounter_read() to detect - * cycle counter wrap around. Initialize with timecounter_init() when - * underlying cyclecounter is initialized, with timecounter_initialize() to + * cycle counter wrap around. Initialize with timecounter_initialize() to * initialize cyclecounter and timecounter fields. Also used to convert * cycle counts into the corresponding nanosecond counts with * timecounter_cyc2time(). Users of this code are responsible for @@ -97,18 +96,6 @@ static inline void timecounter_adjtime(struct timecounter *tc, s64 delta) } /** - * timecounter_init - initialize a time counter - * @tc:Pointer to time counter which is to be initialized - * @start_tstamp: Arbitrary initial time stamp. - * - * After this call the current cycle register (roughly) corresponds to - * the initial time stamp. Every call to timecounter_read() increments - * the time stamp counter by the number of elapsed nanoseconds. - */ -extern void timecounter_init(struct timecounter *tc, -u64 start_tstamp); - -/** * timecounter_initialize - initialize a time counter and underlying cyclecounter * @tc:Pointer to time counter which is to be initialized @@ -143,9 +130,8 @@ extern void timecounter_reset(struct timecounter *tc, u64 start_tstamp); /** - * timecounter_read - return nanoseconds elapsed since timecounter_init() or - *timecounter_initialize() or timecounter_reset() plus - * the initial time stamp + * timecounter_read - return nanoseconds elapsed since timecounter_initialize() + * or timecounter_reset() plus the initial time stamp * @tc: Pointer to time counter. * * In other words, keeps track of time since the same epoch as diff --git a/kernel/time/timecounter.c b/kernel/time/timecounter.c index 3f62fe0..0a02ef0 100644 --- a/kernel/time/timecounter.c +++ b/kernel/time/timecounter.c @@ -18,17 +18,6 @@ #include #include -void timecounter_init(struct timecounter *tc, u64 start_tstamp) -{ - struct cyclecounter *cc = >cc; - - tc->cycle_last = cc->read(cc); - tc->nsec = start_tstamp; - tc->mask = (1ULL << cc->shift) - 1; - tc->frac = 0; -} -EXPORT_SYMBOL_GPL(timecounter_init); - void timecounter_initialize(struct timecounter *tc, u64 (*read)(const struct cyclecounter *cc), u64 mask, @@ -43,7 +32,10 @@ void timecounter_initialize(struct timecounter *tc, cc->mult = mult; cc->shift = shift; - timecounter_init(tc, start_tstamp); + tc->cycle_last = cc->read(cc); + tc->nsec = start_tstamp; + tc->mask = (1ULL << cc->shift) - 1; + tc->frac = 0; } EXPORT_SYMBOL_GPL(timecounter_initialize); -- 1.9.1
[PATCH 17/27] amd-xgbe: Use timecounter_reset interface
With new interface timecounter_reset we can update the start time for timecounter. Update xgbe_config_tstamp and xgbe_settime with this new function. Signed-off-by: Sagar Arun Kamble Cc: Richard Cochran Cc: Tom Lendacky Cc: net...@vger.kernel.org Cc: linux-kernel@vger.kernel.org --- drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 4 ++-- drivers/net/ethernet/amd/xgbe/xgbe-ptp.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c index 5005c87..aee99de 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c @@ -1621,8 +1621,8 @@ static int xgbe_config_tstamp(struct xgbe_prv_data *pdata, xgbe_update_tstamp_addend(pdata, pdata->tstamp_addend); xgbe_set_tstamp_time(pdata, 0, 0); - /* Initialize the timecounter */ - timecounter_init(>tstamp_tc, ktime_to_ns(ktime_get_real())); + /* Reset the timecounter */ + timecounter_reset(>tstamp_tc, ktime_to_ns(ktime_get_real())); return 0; } diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c b/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c index 486437b..5fcde50 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c @@ -211,7 +211,7 @@ static int xgbe_settime(struct ptp_clock_info *info, spin_lock_irqsave(>tstamp_lock, flags); - timecounter_init(>tstamp_tc, nsec); + timecounter_reset(>tstamp_tc, nsec); spin_unlock_irqrestore(>tstamp_lock, flags); -- 1.9.1
[PATCH 27/27] timecounter: Remove timecounter_init
With all timecounter users now initializing timecounter using timecounter_initialize remove timecounter_init function. Signed-off-by: Sagar Arun Kamble Cc: Richard Cochran Cc: John Stultz Cc: Thomas Gleixner Cc: Stephen Boyd Cc: linux-kernel@vger.kernel.org --- include/linux/timecounter.h | 20 +++- kernel/time/timecounter.c | 16 2 files changed, 7 insertions(+), 29 deletions(-) diff --git a/include/linux/timecounter.h b/include/linux/timecounter.h index e0fd741..e3e1d1e 100644 --- a/include/linux/timecounter.h +++ b/include/linux/timecounter.h @@ -46,8 +46,7 @@ struct cyclecounter { /** * struct timecounter - layer above a %struct cyclecounter which counts nanoseconds * Contains the state needed by timecounter_read() to detect - * cycle counter wrap around. Initialize with timecounter_init() when - * underlying cyclecounter is initialized, with timecounter_initialize() to + * cycle counter wrap around. Initialize with timecounter_initialize() to * initialize cyclecounter and timecounter fields. Also used to convert * cycle counts into the corresponding nanosecond counts with * timecounter_cyc2time(). Users of this code are responsible for @@ -97,18 +96,6 @@ static inline void timecounter_adjtime(struct timecounter *tc, s64 delta) } /** - * timecounter_init - initialize a time counter - * @tc:Pointer to time counter which is to be initialized - * @start_tstamp: Arbitrary initial time stamp. - * - * After this call the current cycle register (roughly) corresponds to - * the initial time stamp. Every call to timecounter_read() increments - * the time stamp counter by the number of elapsed nanoseconds. - */ -extern void timecounter_init(struct timecounter *tc, -u64 start_tstamp); - -/** * timecounter_initialize - initialize a time counter and underlying cyclecounter * @tc:Pointer to time counter which is to be initialized @@ -143,9 +130,8 @@ extern void timecounter_reset(struct timecounter *tc, u64 start_tstamp); /** - * timecounter_read - return nanoseconds elapsed since timecounter_init() or - *timecounter_initialize() or timecounter_reset() plus - * the initial time stamp + * timecounter_read - return nanoseconds elapsed since timecounter_initialize() + * or timecounter_reset() plus the initial time stamp * @tc: Pointer to time counter. * * In other words, keeps track of time since the same epoch as diff --git a/kernel/time/timecounter.c b/kernel/time/timecounter.c index 3f62fe0..0a02ef0 100644 --- a/kernel/time/timecounter.c +++ b/kernel/time/timecounter.c @@ -18,17 +18,6 @@ #include #include -void timecounter_init(struct timecounter *tc, u64 start_tstamp) -{ - struct cyclecounter *cc = >cc; - - tc->cycle_last = cc->read(cc); - tc->nsec = start_tstamp; - tc->mask = (1ULL << cc->shift) - 1; - tc->frac = 0; -} -EXPORT_SYMBOL_GPL(timecounter_init); - void timecounter_initialize(struct timecounter *tc, u64 (*read)(const struct cyclecounter *cc), u64 mask, @@ -43,7 +32,10 @@ void timecounter_initialize(struct timecounter *tc, cc->mult = mult; cc->shift = shift; - timecounter_init(tc, start_tstamp); + tc->cycle_last = cc->read(cc); + tc->nsec = start_tstamp; + tc->mask = (1ULL << cc->shift) - 1; + tc->frac = 0; } EXPORT_SYMBOL_GPL(timecounter_initialize); -- 1.9.1
[PATCH 19/27] net: fec: ptp: Use timecounter_reset interface
With new interface timecounter_reset we can update the start time for timecounter. Update fec_ptp_settime with this new function. Signed-off-by: Sagar Arun KambleCc: Richard Cochran Cc: Fugang Duan Cc: net...@vger.kernel.org Cc: linux-kernel@vger.kernel.org --- drivers/net/ethernet/freescale/fec_ptp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c index 1ba7216..d03ea0e 100644 --- a/drivers/net/ethernet/freescale/fec_ptp.c +++ b/drivers/net/ethernet/freescale/fec_ptp.c @@ -419,7 +419,6 @@ static int fec_ptp_settime(struct ptp_clock_info *ptp, { struct fec_enet_private *fep = container_of(ptp, struct fec_enet_private, ptp_caps); - u64 ns; unsigned long flags; u32 counter; @@ -439,7 +438,7 @@ static int fec_ptp_settime(struct ptp_clock_info *ptp, spin_lock_irqsave(>tmreg_lock, flags); writel(counter, fep->hwp + FEC_ATIME); - timecounter_init(>tc, ns); + timecounter_reset(>tc, ns); spin_unlock_irqrestore(>tmreg_lock, flags); mutex_unlock(>ptp_clk_mutex); return 0; -- 1.9.1
[PATCH 19/27] net: fec: ptp: Use timecounter_reset interface
With new interface timecounter_reset we can update the start time for timecounter. Update fec_ptp_settime with this new function. Signed-off-by: Sagar Arun Kamble Cc: Richard Cochran Cc: Fugang Duan Cc: net...@vger.kernel.org Cc: linux-kernel@vger.kernel.org --- drivers/net/ethernet/freescale/fec_ptp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c index 1ba7216..d03ea0e 100644 --- a/drivers/net/ethernet/freescale/fec_ptp.c +++ b/drivers/net/ethernet/freescale/fec_ptp.c @@ -419,7 +419,6 @@ static int fec_ptp_settime(struct ptp_clock_info *ptp, { struct fec_enet_private *fep = container_of(ptp, struct fec_enet_private, ptp_caps); - u64 ns; unsigned long flags; u32 counter; @@ -439,7 +438,7 @@ static int fec_ptp_settime(struct ptp_clock_info *ptp, spin_lock_irqsave(>tmreg_lock, flags); writel(counter, fep->hwp + FEC_ATIME); - timecounter_init(>tc, ns); + timecounter_reset(>tc, ns); spin_unlock_irqrestore(>tmreg_lock, flags); mutex_unlock(>ptp_clk_mutex); return 0; -- 1.9.1
[PATCH 13/27] qede: Use timecounter_initialize interface
With new interface timecounter_initialize we can initialize timecounter fields and underlying cyclecounter together. Update qede timecounter init with this new function. Signed-off-by: Sagar Arun KambleCc: Richard Cochran Cc: Ariel Elior Cc: everest-linux...@cavium.com Cc: net...@vger.kernel.org Cc: linux-kernel@vger.kernel.org --- drivers/net/ethernet/qlogic/qede/qede_ptp.c | 13 ++--- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qede/qede_ptp.c b/drivers/net/ethernet/qlogic/qede/qede_ptp.c index 95bb8a8..0d054dc 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_ptp.c +++ b/drivers/net/ethernet/qlogic/qede/qede_ptp.c @@ -427,13 +427,12 @@ static int qede_ptp_init(struct qede_dev *edev, bool init_tc) * unload / load (e.g. MTU change) while it is running. */ if (init_tc) { - memset(>tc.cc, 0, sizeof(ptp->tc.cc)); - ptp->tc.cc.read = qede_ptp_read_cc; - ptp->tc.cc.mask = CYCLECOUNTER_MASK(64); - ptp->tc.cc.shift = 0; - ptp->tc.cc.mult = 1; - - timecounter_init(>tc, ktime_to_ns(ktime_get_real())); + timecounter_initialize(>tc, + qede_ptp_read_cc, + CYCLECOUNTER_MASK(64), + 1, + 0, + ktime_to_ns(ktime_get_real())); } return rc; -- 1.9.1
[PATCH 13/27] qede: Use timecounter_initialize interface
With new interface timecounter_initialize we can initialize timecounter fields and underlying cyclecounter together. Update qede timecounter init with this new function. Signed-off-by: Sagar Arun Kamble Cc: Richard Cochran Cc: Ariel Elior Cc: everest-linux...@cavium.com Cc: net...@vger.kernel.org Cc: linux-kernel@vger.kernel.org --- drivers/net/ethernet/qlogic/qede/qede_ptp.c | 13 ++--- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qede/qede_ptp.c b/drivers/net/ethernet/qlogic/qede/qede_ptp.c index 95bb8a8..0d054dc 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_ptp.c +++ b/drivers/net/ethernet/qlogic/qede/qede_ptp.c @@ -427,13 +427,12 @@ static int qede_ptp_init(struct qede_dev *edev, bool init_tc) * unload / load (e.g. MTU change) while it is running. */ if (init_tc) { - memset(>tc.cc, 0, sizeof(ptp->tc.cc)); - ptp->tc.cc.read = qede_ptp_read_cc; - ptp->tc.cc.mask = CYCLECOUNTER_MASK(64); - ptp->tc.cc.shift = 0; - ptp->tc.cc.mult = 1; - - timecounter_init(>tc, ktime_to_ns(ktime_get_real())); + timecounter_initialize(>tc, + qede_ptp_read_cc, + CYCLECOUNTER_MASK(64), + 1, + 0, + ktime_to_ns(ktime_get_real())); } return rc; -- 1.9.1
[PATCH 10/27] ixgbe: Use timecounter_initialize interface
With new interface timecounter_initialize we can initialize timecounter fields and underlying cyclecounter together. Update ixgbe ptp timecounter init with this new function. Signed-off-by: Sagar Arun KambleCc: Richard Cochran Cc: Jeff Kirsher Cc: intel-wired-...@lists.osuosl.org Cc: net...@vger.kernel.org Cc: linux-kernel@vger.kernel.org --- drivers/net/ethernet/intel/ixgbe/ixgbe.h | 6 +++- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 4 +-- drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c | 45 +++ 3 files changed, 32 insertions(+), 23 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h index 5c391a0..67e8b5c 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h @@ -739,6 +739,10 @@ struct ixgbe_adapter { unsigned long last_rx_timestamp; spinlock_t tmreg_lock; struct timecounter hw_tc; + u64 (*cc_read)(const struct cyclecounter *cc); + u64 cc_mask; + u32 cc_mult; + u32 cc_shift; u32 base_incval; u32 tx_hwtstamp_timeouts; u32 tx_hwtstamp_skipped; @@ -994,7 +998,7 @@ static inline void ixgbe_ptp_rx_hwtstamp(struct ixgbe_ring *rx_ring, int ixgbe_ptp_set_ts_config(struct ixgbe_adapter *adapter, struct ifreq *ifr); int ixgbe_ptp_get_ts_config(struct ixgbe_adapter *adapter, struct ifreq *ifr); -void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter); +void ixgbe_ptp_start_timecounter(struct ixgbe_adapter *adapter); void ixgbe_ptp_reset(struct ixgbe_adapter *adapter); void ixgbe_ptp_check_pps_event(struct ixgbe_adapter *adapter); #ifdef CONFIG_PCI_IOV diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 62a1891..86a337b 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -7332,7 +7332,7 @@ static void ixgbe_watchdog_link_is_up(struct ixgbe_adapter *adapter) adapter->last_rx_ptp_check = jiffies; if (test_bit(__IXGBE_PTP_RUNNING, >state)) - ixgbe_ptp_start_cyclecounter(adapter); + ixgbe_ptp_start_timecounter(adapter); switch (link_speed) { case IXGBE_LINK_SPEED_10GB_FULL: @@ -7400,7 +7400,7 @@ static void ixgbe_watchdog_link_is_down(struct ixgbe_adapter *adapter) adapter->flags2 |= IXGBE_FLAG2_SEARCH_FOR_SFP; if (test_bit(__IXGBE_PTP_RUNNING, >state)) - ixgbe_ptp_start_cyclecounter(adapter); + ixgbe_ptp_start_timecounter(adapter); e_info(drv, "NIC Link is Down\n"); netif_carrier_off(netdev); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c index 6e9f2c0..073c1ef 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c @@ -1075,7 +1075,8 @@ static void ixgbe_ptp_link_speed_adjust(struct ixgbe_adapter *adapter, } /** - * ixgbe_ptp_start_cyclecounter - create the cycle counter from hw + * ixgbe_ptp_start_timecounter - create the cycle counter from hw and + * initialize corresponding timecounter. * @adapter: pointer to the adapter structure * * This function should be called to set the proper values for the TIMINCA @@ -1084,10 +1085,9 @@ static void ixgbe_ptp_link_speed_adjust(struct ixgbe_adapter *adapter, * structure. It should be called whenever a new TIMINCA value is necessary, * such as during initialization or when the link speed changes. */ -void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter) +void ixgbe_ptp_start_timecounter(struct ixgbe_adapter *adapter) { struct ixgbe_hw *hw = >hw; - struct cyclecounter cc; unsigned long flags; u32 incval = 0; u32 tsauxc = 0; @@ -1104,9 +1104,9 @@ void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter) * proper fix to this problem would require modification of the * timecounter delta calculations. */ - cc.mask = CLOCKSOURCE_MASK(64); - cc.mult = 1; - cc.shift = 0; + adapter->cc_mask = CLOCKSOURCE_MASK(64); + adapter->cc_mult = 1; + adapter->cc_shift = 0; switch (hw->mac.type) { case ixgbe_mac_X550EM_x: @@ -1118,13 +1118,13 @@ void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter) */ fuse0 = IXGBE_READ_REG(hw, IXGBE_FUSES0_GROUP(0)); if (!(fuse0 & IXGBE_FUSES0_300MHZ)) { - cc.mult = 3; - cc.shift = 2; + adapter->cc_mult = 3; + adapter->cc_shift = 2; } /* fallthrough */ case ixgbe_mac_x550em_a: case ixgbe_mac_X550: -
[PATCH 02/27] timecounter: Introduce timecounter_initialize to update timecounter and cyclecounter
With cyclecounter coupled with timecounter, we should move to use interface that initializes entire timecounter structure. This patch creates function timecounter_initialize that takes cyclecounter parameters and start time and initializes the timecounter and underlying cyclecounter. Function timecounter_init which requires initialized cyclecounter can be removed once all drivers are migrated to this new interface. Suggested-by: Richard CochranSigned-off-by: Sagar Arun Kamble Cc: Richard Cochran Cc: Chris Wilson Cc: John Stultz Cc: Thomas Gleixner Cc: Stephen Boyd Cc: linux-kernel@vger.kernel.org --- include/linux/timecounter.h | 41 - kernel/time/timecounter.c | 18 ++ 2 files changed, 50 insertions(+), 9 deletions(-) diff --git a/include/linux/timecounter.h b/include/linux/timecounter.h index 6daca06..59d3fd7 100644 --- a/include/linux/timecounter.h +++ b/include/linux/timecounter.h @@ -46,13 +46,14 @@ struct cyclecounter { /** * struct timecounter - layer above a %struct cyclecounter which counts nanoseconds * Contains the state needed by timecounter_read() to detect - * cycle counter wrap around. Initialize with - * timecounter_init(). Also used to convert cycle counts into the - * corresponding nanosecond counts with timecounter_cyc2time(). Users - * of this code are responsible for initializing the underlying - * cycle counter hardware, locking issues and reading the time - * more often than the cycle counter wraps around. The nanosecond - * counter will only wrap around after ~585 years. + * cycle counter wrap around. Initialize with timecounter_init() when + * underlying cyclecounter is initialized, with timecounter_initialize() to + * initialize cyclecounter and timecounter fields. Also used to convert + * cycle counts into the corresponding nanosecond counts with + * timecounter_cyc2time(). Users of this code are responsible for + * locking issues and reading the time more often than the cycle counter + * wraps around. The nanosecond counter will only wrap around after ~585 + * years. * * @cc:the cycle counter used by this instance * @cycle_last:most recent cycle counter value seen by @@ -108,8 +109,30 @@ extern void timecounter_init(struct timecounter *tc, u64 start_tstamp); /** - * timecounter_read - return nanoseconds elapsed since timecounter_init() - *plus the initial time stamp + * timecounter_initialize - initialize a time counter and underlying + cyclecounter + * @tc:Pointer to time counter which is to be initialized + * @read: Pointer to function that returns the current cycle value + * @mask: bitmask for two's complement + * subtraction of non 64 bit counters, + * @mult: cycle to nanosecond multiplier + * @shift: cycle to nanosecond divisor (power of two) + * @start_tstamp: Arbitrary initial time stamp. + * + * After this call the current cycle register (roughly) corresponds to + * the initial time stamp. Every call to timecounter_read() increments + * the time stamp counter by the number of elapsed nanoseconds. + */ +extern void timecounter_initialize(struct timecounter *tc, + u64 (*read)(const struct cyclecounter *cc), + u64 mask, + u32 mult, + u32 shift, + u64 start_tstamp); + +/** + * timecounter_read - return nanoseconds elapsed since timecounter_init() or + *timecounter_initialize() plus the initial time stamp * @tc: Pointer to time counter. * * In other words, keeps track of time since the same epoch as diff --git a/kernel/time/timecounter.c b/kernel/time/timecounter.c index 7919acb..6d915752 100644 --- a/kernel/time/timecounter.c +++ b/kernel/time/timecounter.c @@ -29,6 +29,24 @@ void timecounter_init(struct timecounter *tc, u64 start_tstamp) } EXPORT_SYMBOL_GPL(timecounter_init); +void timecounter_initialize(struct timecounter *tc, + u64 (*read)(const struct cyclecounter *cc), + u64 mask, + u32 mult, + u32 shift, + u64 start_tstamp) +{ + struct cyclecounter *cc = >cc; + + cc->read = read; + cc->mask = mask; + cc->mult = mult; + cc->shift = shift; + + timecounter_init(tc, start_tstamp); +} +EXPORT_SYMBOL_GPL(timecounter_initialize); + /** * timecounter_read_delta - get nanoseconds since
[PATCH 10/27] ixgbe: Use timecounter_initialize interface
With new interface timecounter_initialize we can initialize timecounter fields and underlying cyclecounter together. Update ixgbe ptp timecounter init with this new function. Signed-off-by: Sagar Arun Kamble Cc: Richard Cochran Cc: Jeff Kirsher Cc: intel-wired-...@lists.osuosl.org Cc: net...@vger.kernel.org Cc: linux-kernel@vger.kernel.org --- drivers/net/ethernet/intel/ixgbe/ixgbe.h | 6 +++- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 4 +-- drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c | 45 +++ 3 files changed, 32 insertions(+), 23 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h index 5c391a0..67e8b5c 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h @@ -739,6 +739,10 @@ struct ixgbe_adapter { unsigned long last_rx_timestamp; spinlock_t tmreg_lock; struct timecounter hw_tc; + u64 (*cc_read)(const struct cyclecounter *cc); + u64 cc_mask; + u32 cc_mult; + u32 cc_shift; u32 base_incval; u32 tx_hwtstamp_timeouts; u32 tx_hwtstamp_skipped; @@ -994,7 +998,7 @@ static inline void ixgbe_ptp_rx_hwtstamp(struct ixgbe_ring *rx_ring, int ixgbe_ptp_set_ts_config(struct ixgbe_adapter *adapter, struct ifreq *ifr); int ixgbe_ptp_get_ts_config(struct ixgbe_adapter *adapter, struct ifreq *ifr); -void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter); +void ixgbe_ptp_start_timecounter(struct ixgbe_adapter *adapter); void ixgbe_ptp_reset(struct ixgbe_adapter *adapter); void ixgbe_ptp_check_pps_event(struct ixgbe_adapter *adapter); #ifdef CONFIG_PCI_IOV diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 62a1891..86a337b 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -7332,7 +7332,7 @@ static void ixgbe_watchdog_link_is_up(struct ixgbe_adapter *adapter) adapter->last_rx_ptp_check = jiffies; if (test_bit(__IXGBE_PTP_RUNNING, >state)) - ixgbe_ptp_start_cyclecounter(adapter); + ixgbe_ptp_start_timecounter(adapter); switch (link_speed) { case IXGBE_LINK_SPEED_10GB_FULL: @@ -7400,7 +7400,7 @@ static void ixgbe_watchdog_link_is_down(struct ixgbe_adapter *adapter) adapter->flags2 |= IXGBE_FLAG2_SEARCH_FOR_SFP; if (test_bit(__IXGBE_PTP_RUNNING, >state)) - ixgbe_ptp_start_cyclecounter(adapter); + ixgbe_ptp_start_timecounter(adapter); e_info(drv, "NIC Link is Down\n"); netif_carrier_off(netdev); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c index 6e9f2c0..073c1ef 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c @@ -1075,7 +1075,8 @@ static void ixgbe_ptp_link_speed_adjust(struct ixgbe_adapter *adapter, } /** - * ixgbe_ptp_start_cyclecounter - create the cycle counter from hw + * ixgbe_ptp_start_timecounter - create the cycle counter from hw and + * initialize corresponding timecounter. * @adapter: pointer to the adapter structure * * This function should be called to set the proper values for the TIMINCA @@ -1084,10 +1085,9 @@ static void ixgbe_ptp_link_speed_adjust(struct ixgbe_adapter *adapter, * structure. It should be called whenever a new TIMINCA value is necessary, * such as during initialization or when the link speed changes. */ -void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter) +void ixgbe_ptp_start_timecounter(struct ixgbe_adapter *adapter) { struct ixgbe_hw *hw = >hw; - struct cyclecounter cc; unsigned long flags; u32 incval = 0; u32 tsauxc = 0; @@ -1104,9 +1104,9 @@ void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter) * proper fix to this problem would require modification of the * timecounter delta calculations. */ - cc.mask = CLOCKSOURCE_MASK(64); - cc.mult = 1; - cc.shift = 0; + adapter->cc_mask = CLOCKSOURCE_MASK(64); + adapter->cc_mult = 1; + adapter->cc_shift = 0; switch (hw->mac.type) { case ixgbe_mac_X550EM_x: @@ -1118,13 +1118,13 @@ void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter) */ fuse0 = IXGBE_READ_REG(hw, IXGBE_FUSES0_GROUP(0)); if (!(fuse0 & IXGBE_FUSES0_300MHZ)) { - cc.mult = 3; - cc.shift = 2; + adapter->cc_mult = 3; + adapter->cc_shift = 2; } /* fallthrough */ case ixgbe_mac_x550em_a: case ixgbe_mac_X550: - cc.read = ixgbe_ptp_read_X550; + adapter->cc_read =
[PATCH 02/27] timecounter: Introduce timecounter_initialize to update timecounter and cyclecounter
With cyclecounter coupled with timecounter, we should move to use interface that initializes entire timecounter structure. This patch creates function timecounter_initialize that takes cyclecounter parameters and start time and initializes the timecounter and underlying cyclecounter. Function timecounter_init which requires initialized cyclecounter can be removed once all drivers are migrated to this new interface. Suggested-by: Richard Cochran Signed-off-by: Sagar Arun Kamble Cc: Richard Cochran Cc: Chris Wilson Cc: John Stultz Cc: Thomas Gleixner Cc: Stephen Boyd Cc: linux-kernel@vger.kernel.org --- include/linux/timecounter.h | 41 - kernel/time/timecounter.c | 18 ++ 2 files changed, 50 insertions(+), 9 deletions(-) diff --git a/include/linux/timecounter.h b/include/linux/timecounter.h index 6daca06..59d3fd7 100644 --- a/include/linux/timecounter.h +++ b/include/linux/timecounter.h @@ -46,13 +46,14 @@ struct cyclecounter { /** * struct timecounter - layer above a %struct cyclecounter which counts nanoseconds * Contains the state needed by timecounter_read() to detect - * cycle counter wrap around. Initialize with - * timecounter_init(). Also used to convert cycle counts into the - * corresponding nanosecond counts with timecounter_cyc2time(). Users - * of this code are responsible for initializing the underlying - * cycle counter hardware, locking issues and reading the time - * more often than the cycle counter wraps around. The nanosecond - * counter will only wrap around after ~585 years. + * cycle counter wrap around. Initialize with timecounter_init() when + * underlying cyclecounter is initialized, with timecounter_initialize() to + * initialize cyclecounter and timecounter fields. Also used to convert + * cycle counts into the corresponding nanosecond counts with + * timecounter_cyc2time(). Users of this code are responsible for + * locking issues and reading the time more often than the cycle counter + * wraps around. The nanosecond counter will only wrap around after ~585 + * years. * * @cc:the cycle counter used by this instance * @cycle_last:most recent cycle counter value seen by @@ -108,8 +109,30 @@ extern void timecounter_init(struct timecounter *tc, u64 start_tstamp); /** - * timecounter_read - return nanoseconds elapsed since timecounter_init() - *plus the initial time stamp + * timecounter_initialize - initialize a time counter and underlying + cyclecounter + * @tc:Pointer to time counter which is to be initialized + * @read: Pointer to function that returns the current cycle value + * @mask: bitmask for two's complement + * subtraction of non 64 bit counters, + * @mult: cycle to nanosecond multiplier + * @shift: cycle to nanosecond divisor (power of two) + * @start_tstamp: Arbitrary initial time stamp. + * + * After this call the current cycle register (roughly) corresponds to + * the initial time stamp. Every call to timecounter_read() increments + * the time stamp counter by the number of elapsed nanoseconds. + */ +extern void timecounter_initialize(struct timecounter *tc, + u64 (*read)(const struct cyclecounter *cc), + u64 mask, + u32 mult, + u32 shift, + u64 start_tstamp); + +/** + * timecounter_read - return nanoseconds elapsed since timecounter_init() or + *timecounter_initialize() plus the initial time stamp * @tc: Pointer to time counter. * * In other words, keeps track of time since the same epoch as diff --git a/kernel/time/timecounter.c b/kernel/time/timecounter.c index 7919acb..6d915752 100644 --- a/kernel/time/timecounter.c +++ b/kernel/time/timecounter.c @@ -29,6 +29,24 @@ void timecounter_init(struct timecounter *tc, u64 start_tstamp) } EXPORT_SYMBOL_GPL(timecounter_init); +void timecounter_initialize(struct timecounter *tc, + u64 (*read)(const struct cyclecounter *cc), + u64 mask, + u32 mult, + u32 shift, + u64 start_tstamp) +{ + struct cyclecounter *cc = >cc; + + cc->read = read; + cc->mask = mask; + cc->mult = mult; + cc->shift = shift; + + timecounter_init(tc, start_tstamp); +} +EXPORT_SYMBOL_GPL(timecounter_initialize); + /** * timecounter_read_delta - get nanoseconds since last call of this function * @tc: Pointer to time counter -- 1.9.1
[PATCH 09/27] igb: Use timecounter_initialize interface
With new interface timecounter_initialize we can initialize timecounter fields and underlying cyclecounter together. Update igb ptp timecounter init with this new function. Signed-off-by: Sagar Arun KambleCc: Richard Cochran Cc: Jeff Kirsher Cc: intel-wired-...@lists.osuosl.org Cc: net...@vger.kernel.org Cc: linux-kernel@vger.kernel.org --- drivers/net/ethernet/intel/igb/igb.h | 4 drivers/net/ethernet/intel/igb/igb_ptp.c | 23 ++- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h index 4eac4f2..4ef5632 100644 --- a/drivers/net/ethernet/intel/igb/igb.h +++ b/drivers/net/ethernet/intel/igb/igb.h @@ -566,6 +566,10 @@ struct igb_adapter { unsigned int ptp_flags; spinlock_t tmreg_lock; struct timecounter tc; + u64 (*cc_read)(const struct cyclecounter *cc); + u64 cc_mask; + u32 cc_mult; + u32 cc_shift; u32 tx_hwtstamp_timeouts; u32 tx_hwtstamp_skipped; u32 rx_hwtstamp_cleared; diff --git a/drivers/net/ethernet/intel/igb/igb_ptp.c b/drivers/net/ethernet/intel/igb/igb_ptp.c index 0745eff..f6c1a8d 100644 --- a/drivers/net/ethernet/intel/igb/igb_ptp.c +++ b/drivers/net/ethernet/intel/igb/igb_ptp.c @@ -1126,10 +1126,10 @@ void igb_ptp_init(struct igb_adapter *adapter) adapter->ptp_caps.gettime64 = igb_ptp_gettime_82576; adapter->ptp_caps.settime64 = igb_ptp_settime_82576; adapter->ptp_caps.enable = igb_ptp_feature_enable; - adapter->tc.cc.read = igb_ptp_read_82576; - adapter->tc.cc.mask = CYCLECOUNTER_MASK(64); - adapter->tc.cc.mult = 1; - adapter->tc.cc.shift = IGB_82576_TSYNC_SHIFT; + adapter->cc_read = igb_ptp_read_82576; + adapter->cc_mask = CYCLECOUNTER_MASK(64); + adapter->cc_mult = 1; + adapter->cc_shift = IGB_82576_TSYNC_SHIFT; adapter->ptp_flags |= IGB_PTP_OVERFLOW_CHECK; break; case e1000_82580: @@ -1145,10 +1145,10 @@ void igb_ptp_init(struct igb_adapter *adapter) adapter->ptp_caps.gettime64 = igb_ptp_gettime_82576; adapter->ptp_caps.settime64 = igb_ptp_settime_82576; adapter->ptp_caps.enable = igb_ptp_feature_enable; - adapter->tc.cc.read = igb_ptp_read_82580; - adapter->tc.cc.mask = CYCLECOUNTER_MASK(IGB_NBITS_82580); - adapter->tc.cc.mult = 1; - adapter->tc.cc.shift = 0; + adapter->cc_read = igb_ptp_read_82580; + adapter->cc_mask = CYCLECOUNTER_MASK(IGB_NBITS_82580); + adapter->cc_mult = 1; + adapter->cc_shift = 0; adapter->ptp_flags |= IGB_PTP_OVERFLOW_CHECK; break; case e1000_i210: @@ -1289,7 +1289,12 @@ void igb_ptp_reset(struct igb_adapter *adapter) igb_ptp_write_i210(adapter, ); } else { - timecounter_init(>tc, ktime_to_ns(ktime_get_real())); + timecounter_initialize(>tc, + adapter->cc_read, + adapter->cc_mask, + adapter->cc_mult, + adapter->cc_shift, + ktime_to_ns(ktime_get_real())); } out: spin_unlock_irqrestore(>tmreg_lock, flags); -- 1.9.1
[PATCH 01/27] timecounter: Make cyclecounter struct part of timecounter struct
There is no real need for the users of timecounters to define cyclecounter and timecounter variables separately. Since timecounter will always be based on cyclecounter, have cyclecounter struct as member of timecounter struct. v2: Rebase. Suggested-by: Chris WilsonSigned-off-by: Sagar Arun Kamble Cc: Chris Wilson Cc: Richard Cochran Cc: John Stultz Cc: Thomas Gleixner Cc: Stephen Boyd Cc: linux-kernel@vger.kernel.org Cc: linux-arm-ker...@lists.infradead.org Cc: net...@vger.kernel.org Cc: intel-wired-...@lists.osuosl.org Cc: linux-r...@vger.kernel.org Cc: alsa-de...@alsa-project.org Cc: kvm...@lists.cs.columbia.edu Acked-by: Jeff Kirsher (Intel drivers) --- arch/microblaze/kernel/timer.c | 20 ++-- drivers/clocksource/arm_arch_timer.c | 19 ++-- drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 3 +- drivers/net/ethernet/amd/xgbe/xgbe-ptp.c | 9 +++--- drivers/net/ethernet/amd/xgbe/xgbe.h | 1 - drivers/net/ethernet/broadcom/bnx2x/bnx2x.h| 1 - drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 20 ++-- drivers/net/ethernet/freescale/fec.h | 1 - drivers/net/ethernet/freescale/fec_ptp.c | 30 +- drivers/net/ethernet/intel/e1000e/e1000.h | 1 - drivers/net/ethernet/intel/e1000e/netdev.c | 27 drivers/net/ethernet/intel/e1000e/ptp.c| 2 +- drivers/net/ethernet/intel/igb/igb.h | 1 - drivers/net/ethernet/intel/igb/igb_ptp.c | 25 --- drivers/net/ethernet/intel/ixgbe/ixgbe.h | 1 - drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c | 17 +- drivers/net/ethernet/mellanox/mlx4/en_clock.c | 28 - drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 1 - .../net/ethernet/mellanox/mlx5/core/lib/clock.c| 34 ++-- drivers/net/ethernet/qlogic/qede/qede_ptp.c| 20 ++-- drivers/net/ethernet/ti/cpts.c | 36 -- drivers/net/ethernet/ti/cpts.h | 1 - include/linux/mlx5/driver.h| 1 - include/linux/timecounter.h| 4 +-- include/sound/hdaudio.h| 1 - kernel/time/timecounter.c | 28 - sound/hda/hdac_stream.c| 7 +++-- virt/kvm/arm/arch_timer.c | 6 ++-- 28 files changed, 163 insertions(+), 182 deletions(-) diff --git a/arch/microblaze/kernel/timer.c b/arch/microblaze/kernel/timer.c index 7de941c..b7f89e9 100644 --- a/arch/microblaze/kernel/timer.c +++ b/arch/microblaze/kernel/timer.c @@ -199,27 +199,25 @@ static u64 xilinx_read(struct clocksource *cs) return (u64)xilinx_clock_read(); } -static struct timecounter xilinx_tc = { - .cc = NULL, -}; - static u64 xilinx_cc_read(const struct cyclecounter *cc) { return xilinx_read(NULL); } -static struct cyclecounter xilinx_cc = { - .read = xilinx_cc_read, - .mask = CLOCKSOURCE_MASK(32), - .shift = 8, +static struct timecounter xilinx_tc = { + .cc.read = xilinx_cc_read, + .cc.mask = CLOCKSOURCE_MASK(32), + .cc.mult = 0, + .cc.shift = 8, }; static int __init init_xilinx_timecounter(void) { - xilinx_cc.mult = div_sc(timer_clock_freq, NSEC_PER_SEC, - xilinx_cc.shift); + struct cyclecounter *cc = _tc.cc; + + cc->mult = div_sc(timer_clock_freq, NSEC_PER_SEC, cc->shift); - timecounter_init(_tc, _cc, sched_clock()); + timecounter_init(_tc, sched_clock()); return 0; } diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 57cb2f0..31543e5 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -179,11 +179,6 @@ static u64 arch_counter_read_cc(const struct cyclecounter *cc) .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; -static struct cyclecounter cyclecounter __ro_after_init = { - .read = arch_counter_read_cc, - .mask = CLOCKSOURCE_MASK(56), -}; - struct ate_acpi_oem_info { char oem_id[ACPI_OEM_ID_SIZE + 1]; char oem_table_id[ACPI_OEM_TABLE_ID_SIZE + 1]; @@ -915,7 +910,10 @@ static u64 arch_counter_get_cntvct_mem(void) return ((u64) vct_hi << 32) | vct_lo; } -static struct arch_timer_kvm_info arch_timer_kvm_info; +static struct arch_timer_kvm_info arch_timer_kvm_info = { + .timecounter.cc.read = arch_counter_read_cc, + .timecounter.cc.mask = CLOCKSOURCE_MASK(56), +}; struct arch_timer_kvm_info *arch_timer_get_kvm_info(void) { @@ -925,6 +923,7 @@ struct
[PATCH 01/27] timecounter: Make cyclecounter struct part of timecounter struct
There is no real need for the users of timecounters to define cyclecounter and timecounter variables separately. Since timecounter will always be based on cyclecounter, have cyclecounter struct as member of timecounter struct. v2: Rebase. Suggested-by: Chris Wilson Signed-off-by: Sagar Arun Kamble Cc: Chris Wilson Cc: Richard Cochran Cc: John Stultz Cc: Thomas Gleixner Cc: Stephen Boyd Cc: linux-kernel@vger.kernel.org Cc: linux-arm-ker...@lists.infradead.org Cc: net...@vger.kernel.org Cc: intel-wired-...@lists.osuosl.org Cc: linux-r...@vger.kernel.org Cc: alsa-de...@alsa-project.org Cc: kvm...@lists.cs.columbia.edu Acked-by: Jeff Kirsher (Intel drivers) --- arch/microblaze/kernel/timer.c | 20 ++-- drivers/clocksource/arm_arch_timer.c | 19 ++-- drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 3 +- drivers/net/ethernet/amd/xgbe/xgbe-ptp.c | 9 +++--- drivers/net/ethernet/amd/xgbe/xgbe.h | 1 - drivers/net/ethernet/broadcom/bnx2x/bnx2x.h| 1 - drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 20 ++-- drivers/net/ethernet/freescale/fec.h | 1 - drivers/net/ethernet/freescale/fec_ptp.c | 30 +- drivers/net/ethernet/intel/e1000e/e1000.h | 1 - drivers/net/ethernet/intel/e1000e/netdev.c | 27 drivers/net/ethernet/intel/e1000e/ptp.c| 2 +- drivers/net/ethernet/intel/igb/igb.h | 1 - drivers/net/ethernet/intel/igb/igb_ptp.c | 25 --- drivers/net/ethernet/intel/ixgbe/ixgbe.h | 1 - drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c | 17 +- drivers/net/ethernet/mellanox/mlx4/en_clock.c | 28 - drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 1 - .../net/ethernet/mellanox/mlx5/core/lib/clock.c| 34 ++-- drivers/net/ethernet/qlogic/qede/qede_ptp.c| 20 ++-- drivers/net/ethernet/ti/cpts.c | 36 -- drivers/net/ethernet/ti/cpts.h | 1 - include/linux/mlx5/driver.h| 1 - include/linux/timecounter.h| 4 +-- include/sound/hdaudio.h| 1 - kernel/time/timecounter.c | 28 - sound/hda/hdac_stream.c| 7 +++-- virt/kvm/arm/arch_timer.c | 6 ++-- 28 files changed, 163 insertions(+), 182 deletions(-) diff --git a/arch/microblaze/kernel/timer.c b/arch/microblaze/kernel/timer.c index 7de941c..b7f89e9 100644 --- a/arch/microblaze/kernel/timer.c +++ b/arch/microblaze/kernel/timer.c @@ -199,27 +199,25 @@ static u64 xilinx_read(struct clocksource *cs) return (u64)xilinx_clock_read(); } -static struct timecounter xilinx_tc = { - .cc = NULL, -}; - static u64 xilinx_cc_read(const struct cyclecounter *cc) { return xilinx_read(NULL); } -static struct cyclecounter xilinx_cc = { - .read = xilinx_cc_read, - .mask = CLOCKSOURCE_MASK(32), - .shift = 8, +static struct timecounter xilinx_tc = { + .cc.read = xilinx_cc_read, + .cc.mask = CLOCKSOURCE_MASK(32), + .cc.mult = 0, + .cc.shift = 8, }; static int __init init_xilinx_timecounter(void) { - xilinx_cc.mult = div_sc(timer_clock_freq, NSEC_PER_SEC, - xilinx_cc.shift); + struct cyclecounter *cc = _tc.cc; + + cc->mult = div_sc(timer_clock_freq, NSEC_PER_SEC, cc->shift); - timecounter_init(_tc, _cc, sched_clock()); + timecounter_init(_tc, sched_clock()); return 0; } diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 57cb2f0..31543e5 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -179,11 +179,6 @@ static u64 arch_counter_read_cc(const struct cyclecounter *cc) .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; -static struct cyclecounter cyclecounter __ro_after_init = { - .read = arch_counter_read_cc, - .mask = CLOCKSOURCE_MASK(56), -}; - struct ate_acpi_oem_info { char oem_id[ACPI_OEM_ID_SIZE + 1]; char oem_table_id[ACPI_OEM_TABLE_ID_SIZE + 1]; @@ -915,7 +910,10 @@ static u64 arch_counter_get_cntvct_mem(void) return ((u64) vct_hi << 32) | vct_lo; } -static struct arch_timer_kvm_info arch_timer_kvm_info; +static struct arch_timer_kvm_info arch_timer_kvm_info = { + .timecounter.cc.read = arch_counter_read_cc, + .timecounter.cc.mask = CLOCKSOURCE_MASK(56), +}; struct arch_timer_kvm_info *arch_timer_get_kvm_info(void) { @@ -925,6 +923,7 @@ struct arch_timer_kvm_info *arch_timer_get_kvm_info(void) static void __init arch_counter_register(unsigned type) { u64 start_count; + struct cyclecounter *cc = _timer_kvm_info.timecounter.cc;
[PATCH 09/27] igb: Use timecounter_initialize interface
With new interface timecounter_initialize we can initialize timecounter fields and underlying cyclecounter together. Update igb ptp timecounter init with this new function. Signed-off-by: Sagar Arun Kamble Cc: Richard Cochran Cc: Jeff Kirsher Cc: intel-wired-...@lists.osuosl.org Cc: net...@vger.kernel.org Cc: linux-kernel@vger.kernel.org --- drivers/net/ethernet/intel/igb/igb.h | 4 drivers/net/ethernet/intel/igb/igb_ptp.c | 23 ++- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h index 4eac4f2..4ef5632 100644 --- a/drivers/net/ethernet/intel/igb/igb.h +++ b/drivers/net/ethernet/intel/igb/igb.h @@ -566,6 +566,10 @@ struct igb_adapter { unsigned int ptp_flags; spinlock_t tmreg_lock; struct timecounter tc; + u64 (*cc_read)(const struct cyclecounter *cc); + u64 cc_mask; + u32 cc_mult; + u32 cc_shift; u32 tx_hwtstamp_timeouts; u32 tx_hwtstamp_skipped; u32 rx_hwtstamp_cleared; diff --git a/drivers/net/ethernet/intel/igb/igb_ptp.c b/drivers/net/ethernet/intel/igb/igb_ptp.c index 0745eff..f6c1a8d 100644 --- a/drivers/net/ethernet/intel/igb/igb_ptp.c +++ b/drivers/net/ethernet/intel/igb/igb_ptp.c @@ -1126,10 +1126,10 @@ void igb_ptp_init(struct igb_adapter *adapter) adapter->ptp_caps.gettime64 = igb_ptp_gettime_82576; adapter->ptp_caps.settime64 = igb_ptp_settime_82576; adapter->ptp_caps.enable = igb_ptp_feature_enable; - adapter->tc.cc.read = igb_ptp_read_82576; - adapter->tc.cc.mask = CYCLECOUNTER_MASK(64); - adapter->tc.cc.mult = 1; - adapter->tc.cc.shift = IGB_82576_TSYNC_SHIFT; + adapter->cc_read = igb_ptp_read_82576; + adapter->cc_mask = CYCLECOUNTER_MASK(64); + adapter->cc_mult = 1; + adapter->cc_shift = IGB_82576_TSYNC_SHIFT; adapter->ptp_flags |= IGB_PTP_OVERFLOW_CHECK; break; case e1000_82580: @@ -1145,10 +1145,10 @@ void igb_ptp_init(struct igb_adapter *adapter) adapter->ptp_caps.gettime64 = igb_ptp_gettime_82576; adapter->ptp_caps.settime64 = igb_ptp_settime_82576; adapter->ptp_caps.enable = igb_ptp_feature_enable; - adapter->tc.cc.read = igb_ptp_read_82580; - adapter->tc.cc.mask = CYCLECOUNTER_MASK(IGB_NBITS_82580); - adapter->tc.cc.mult = 1; - adapter->tc.cc.shift = 0; + adapter->cc_read = igb_ptp_read_82580; + adapter->cc_mask = CYCLECOUNTER_MASK(IGB_NBITS_82580); + adapter->cc_mult = 1; + adapter->cc_shift = 0; adapter->ptp_flags |= IGB_PTP_OVERFLOW_CHECK; break; case e1000_i210: @@ -1289,7 +1289,12 @@ void igb_ptp_reset(struct igb_adapter *adapter) igb_ptp_write_i210(adapter, ); } else { - timecounter_init(>tc, ktime_to_ns(ktime_get_real())); + timecounter_initialize(>tc, + adapter->cc_read, + adapter->cc_mask, + adapter->cc_mult, + adapter->cc_shift, + ktime_to_ns(ktime_get_real())); } out: spin_unlock_irqrestore(>tmreg_lock, flags); -- 1.9.1
[PATCH 00/27] timecounter/cyclecounter struct/interface update
This series makes cyclecounter part of timecounter and introduces two new interface functions timecounter_initialize() for initializing both timecounter and cyclecounter fields and timecounter_reset() for setting start time of timecounter. Updates all drivers with new functions and removes function timecounter_init(). Cc: Sagar Arun KambleCc: Richard Cochran Cc: John Stultz Cc: Thomas Gleixner Cc: Stephen Boyd Cc: linux-kernel@vger.kernel.org Sagar Arun Kamble (27): timecounter: Make cyclecounter struct part of timecounter struct timecounter: Introduce timecounter_initialize to update timecounter and cyclecounter microblaze: Use timecounter_initialize interface clocksource/arm_arch_timer: Use timecounter_initialize interface amd-xgbe: Use timecounter_initialize interface bnx2x: Use timecounter_initialize interface fec: Use timecounter_initialize interface e1000e: Use timecounter_initialize interface igb: Use timecounter_initialize interface ixgbe: Use timecounter_initialize interface net/mlx4: Use timecounter_initialize interface net/mlx5: Use timecounter_initialize interface qede: Use timecounter_initialize interface net: cpts: Use timecounter_initialize interface ALSA: hda - Use timecounter_initialize interface timecounter: Introduce timecounter_reset amd-xgbe: Use timecounter_reset interface bnx2x: Use timecounter_reset interface net: fec: ptp: Use timecounter_reset interface e1000e: Use timecounter_reset interface igb: Use timecounter_reset interface ixgbe: Use timecounter_reset interface net/mlx4: Use timecounter_reset interface net/mlx5: Use timecounter_reset interface qede: Use timecounter_reset interface net: cpts: Use timecounter_reset interface timecounter: Remove timecounter_init arch/microblaze/kernel/timer.c | 23 - drivers/clocksource/arm_arch_timer.c | 16 +++--- drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 5 +- drivers/net/ethernet/amd/xgbe/xgbe-ptp.c | 18 +++ drivers/net/ethernet/amd/xgbe/xgbe.h | 1 - drivers/net/ethernet/broadcom/bnx2x/bnx2x.h| 1 - drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 24 - drivers/net/ethernet/freescale/fec.h | 1 - drivers/net/ethernet/freescale/fec_ptp.c | 34 ++--- drivers/net/ethernet/intel/e1000e/e1000.h | 5 +- drivers/net/ethernet/intel/e1000e/netdev.c | 34 +++-- drivers/net/ethernet/intel/e1000e/ptp.c| 2 +- drivers/net/ethernet/intel/igb/igb.h | 5 +- drivers/net/ethernet/intel/igb/igb_ptp.c | 30 ++- drivers/net/ethernet/intel/ixgbe/ixgbe.h | 7 ++- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 4 +- drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c | 58 -- drivers/net/ethernet/mellanox/mlx4/en_clock.c | 29 +-- drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 1 - .../net/ethernet/mellanox/mlx5/core/lib/clock.c| 38 +++--- drivers/net/ethernet/qlogic/qede/qede_ptp.c| 21 drivers/net/ethernet/ti/cpts.c | 45 ++--- drivers/net/ethernet/ti/cpts.h | 4 +- include/linux/mlx5/driver.h| 1 - include/linux/timecounter.h| 52 +-- include/sound/hdaudio.h| 1 - kernel/time/timecounter.c | 49 -- sound/hda/hdac_stream.c| 17 +++ virt/kvm/arm/arch_timer.c | 6 +-- 29 files changed, 291 insertions(+), 241 deletions(-) -- 1.9.1
[PATCH 00/27] timecounter/cyclecounter struct/interface update
This series makes cyclecounter part of timecounter and introduces two new interface functions timecounter_initialize() for initializing both timecounter and cyclecounter fields and timecounter_reset() for setting start time of timecounter. Updates all drivers with new functions and removes function timecounter_init(). Cc: Sagar Arun Kamble Cc: Richard Cochran Cc: John Stultz Cc: Thomas Gleixner Cc: Stephen Boyd Cc: linux-kernel@vger.kernel.org Sagar Arun Kamble (27): timecounter: Make cyclecounter struct part of timecounter struct timecounter: Introduce timecounter_initialize to update timecounter and cyclecounter microblaze: Use timecounter_initialize interface clocksource/arm_arch_timer: Use timecounter_initialize interface amd-xgbe: Use timecounter_initialize interface bnx2x: Use timecounter_initialize interface fec: Use timecounter_initialize interface e1000e: Use timecounter_initialize interface igb: Use timecounter_initialize interface ixgbe: Use timecounter_initialize interface net/mlx4: Use timecounter_initialize interface net/mlx5: Use timecounter_initialize interface qede: Use timecounter_initialize interface net: cpts: Use timecounter_initialize interface ALSA: hda - Use timecounter_initialize interface timecounter: Introduce timecounter_reset amd-xgbe: Use timecounter_reset interface bnx2x: Use timecounter_reset interface net: fec: ptp: Use timecounter_reset interface e1000e: Use timecounter_reset interface igb: Use timecounter_reset interface ixgbe: Use timecounter_reset interface net/mlx4: Use timecounter_reset interface net/mlx5: Use timecounter_reset interface qede: Use timecounter_reset interface net: cpts: Use timecounter_reset interface timecounter: Remove timecounter_init arch/microblaze/kernel/timer.c | 23 - drivers/clocksource/arm_arch_timer.c | 16 +++--- drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 5 +- drivers/net/ethernet/amd/xgbe/xgbe-ptp.c | 18 +++ drivers/net/ethernet/amd/xgbe/xgbe.h | 1 - drivers/net/ethernet/broadcom/bnx2x/bnx2x.h| 1 - drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 24 - drivers/net/ethernet/freescale/fec.h | 1 - drivers/net/ethernet/freescale/fec_ptp.c | 34 ++--- drivers/net/ethernet/intel/e1000e/e1000.h | 5 +- drivers/net/ethernet/intel/e1000e/netdev.c | 34 +++-- drivers/net/ethernet/intel/e1000e/ptp.c| 2 +- drivers/net/ethernet/intel/igb/igb.h | 5 +- drivers/net/ethernet/intel/igb/igb_ptp.c | 30 ++- drivers/net/ethernet/intel/ixgbe/ixgbe.h | 7 ++- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 4 +- drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c | 58 -- drivers/net/ethernet/mellanox/mlx4/en_clock.c | 29 +-- drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 1 - .../net/ethernet/mellanox/mlx5/core/lib/clock.c| 38 +++--- drivers/net/ethernet/qlogic/qede/qede_ptp.c| 21 drivers/net/ethernet/ti/cpts.c | 45 ++--- drivers/net/ethernet/ti/cpts.h | 4 +- include/linux/mlx5/driver.h| 1 - include/linux/timecounter.h| 52 +-- include/sound/hdaudio.h| 1 - kernel/time/timecounter.c | 49 -- sound/hda/hdac_stream.c| 17 +++ virt/kvm/arm/arch_timer.c | 6 +-- 29 files changed, 291 insertions(+), 241 deletions(-) -- 1.9.1
Re: [PATCH 2/6] blk-mq: replace timeout synchronization with a RCU and generation based scheme
On Fri, Dec 15, 2017 at 10:12:50AM +0800, jianchao.wang wrote: > > That only makes it a little better: > > > > Task-A Worker > > > > write_seqcount_begin() > > blk_mq_rw_update_state(rq, IN_FLIGHT) > > blk_add_timer(rq) > > > > schedule_work() > > > > > > read_seqcount_begin() > > while(seq & 1) > > cpu_relax(); > > > Hi Peter > > The current seqcount read side is as below: > do { > start = read_seqcount_begin(>gstate_seq); static inline unsigned read_seqcount_begin(const seqcount_t *s) { seqcount_lockdep_reader_access(s); return raw_read_seqcount_begin(s); } static inline unsigned raw_read_seqcount_begin(const seqcount_t *s) { unsigned ret = __read_seqcount_begin(s); smp_rmb(); return ret; } static inline unsigned __read_seqcount_begin(const seqcount_t *s) { unsigned ret; repeat: ret = READ_ONCE(s->sequence); if (unlikely(ret & 1)) { cpu_relax(); goto repeat; } return ret; }
Re: [PATCH 2/6] blk-mq: replace timeout synchronization with a RCU and generation based scheme
On Fri, Dec 15, 2017 at 10:12:50AM +0800, jianchao.wang wrote: > > That only makes it a little better: > > > > Task-A Worker > > > > write_seqcount_begin() > > blk_mq_rw_update_state(rq, IN_FLIGHT) > > blk_add_timer(rq) > > > > schedule_work() > > > > > > read_seqcount_begin() > > while(seq & 1) > > cpu_relax(); > > > Hi Peter > > The current seqcount read side is as below: > do { > start = read_seqcount_begin(>gstate_seq); static inline unsigned read_seqcount_begin(const seqcount_t *s) { seqcount_lockdep_reader_access(s); return raw_read_seqcount_begin(s); } static inline unsigned raw_read_seqcount_begin(const seqcount_t *s) { unsigned ret = __read_seqcount_begin(s); smp_rmb(); return ret; } static inline unsigned __read_seqcount_begin(const seqcount_t *s) { unsigned ret; repeat: ret = READ_ONCE(s->sequence); if (unlikely(ret & 1)) { cpu_relax(); goto repeat; } return ret; }
Re: [PATCH] ASoC: nau8825: fix issue that pop noise when start capture
On 12/12/2017 3:10 AM, abhijeet.ku...@intel.com wrote: From: Abhijeet KumarIn skylake platform, we hear a loud pop noise(0 dB) at start of audio capture power up sequence. This patch removes the pop noise from the recording by adding a delay before enabling ADC. Signed-off-by: Abhijeet Kumar --- sound/soc/codecs/nau8825.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/nau8825.c b/sound/soc/codecs/nau8825.c index 714ce17da717..e853a6dfd33b 100644 --- a/sound/soc/codecs/nau8825.c +++ b/sound/soc/codecs/nau8825.c @@ -905,6 +905,7 @@ static int nau8825_adc_event(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_POST_PMU: + msleep(125); regmap_update_bits(nau8825->regmap, NAU8825_REG_ENA_CTRL, NAU8825_ENABLE_ADC, NAU8825_ENABLE_ADC); break; The solution is fine for me. It's verified in my device and indeed helps to reduce the capture pop noise. I think the little delay is acceptable. === The privileged confidential information contained in this email is intended for use only by the addressees as indicated by the original sender of this email. If you are not the addressee indicated in this email or are not responsible for delivery of the email to such a person, please kindly reply to the sender indicating this fact and delete all copies of it from your computer and network server immediately. Your cooperation is highly appreciated. It is advised that any unauthorized use of confidential information of Nuvoton is strictly prohibited; and any information in this email irrelevant to the official business of Nuvoton shall be deemed as neither given nor endorsed by Nuvoton.
Re: [PATCH] ASoC: nau8825: fix issue that pop noise when start capture
On 12/12/2017 3:10 AM, abhijeet.ku...@intel.com wrote: From: Abhijeet Kumar In skylake platform, we hear a loud pop noise(0 dB) at start of audio capture power up sequence. This patch removes the pop noise from the recording by adding a delay before enabling ADC. Signed-off-by: Abhijeet Kumar --- sound/soc/codecs/nau8825.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/nau8825.c b/sound/soc/codecs/nau8825.c index 714ce17da717..e853a6dfd33b 100644 --- a/sound/soc/codecs/nau8825.c +++ b/sound/soc/codecs/nau8825.c @@ -905,6 +905,7 @@ static int nau8825_adc_event(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_POST_PMU: + msleep(125); regmap_update_bits(nau8825->regmap, NAU8825_REG_ENA_CTRL, NAU8825_ENABLE_ADC, NAU8825_ENABLE_ADC); break; The solution is fine for me. It's verified in my device and indeed helps to reduce the capture pop noise. I think the little delay is acceptable. === The privileged confidential information contained in this email is intended for use only by the addressees as indicated by the original sender of this email. If you are not the addressee indicated in this email or are not responsible for delivery of the email to such a person, please kindly reply to the sender indicating this fact and delete all copies of it from your computer and network server immediately. Your cooperation is highly appreciated. It is advised that any unauthorized use of confidential information of Nuvoton is strictly prohibited; and any information in this email irrelevant to the official business of Nuvoton shall be deemed as neither given nor endorsed by Nuvoton.
Re: [PATCH] iommu/vt-d: Fix shift overflow in qi_flush_dev_iotlb
On Wed, Dec 13, 2017 at 11:31:02AM -0600, Hook, Gary wrote: > On 12/13/2017 11:15 AM, Alex Williamson wrote: > > On Wed, 13 Dec 2017 10:41:47 -0600 > > "Hook, Gary"wrote: > > > > > On 12/13/2017 9:58 AM, Alex Williamson wrote: > > > > On Wed, 13 Dec 2017 15:13:55 +0800 > > > > Peter Xu wrote: > > > > > On Tue, Dec 12, 2017 at 03:43:08PM -0700, Alex Williamson wrote: > > > > > > > > > > [...] > > > > > > diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c > > > > > > index 9a7ffd13c7f0..87888b102057 100644 > > > > > > --- a/drivers/iommu/dmar.c > > > > > > +++ b/drivers/iommu/dmar.c > > > > > > @@ -1345,7 +1345,9 @@ void qi_flush_dev_iotlb(struct intel_iommu > > > > > > *iommu, u16 sid, u16 qdep, > > > > > > struct qi_desc desc; > > > > > > if (mask) { > > > > > > - BUG_ON(addr & ((1 << (VTD_PAGE_SHIFT + mask)) - 1)); > > > > > > + BUG_ON((mask > MAX_AGAW_PFN_WIDTH) || > > > > > > + ((mask == MAX_AGAW_PFN_WIDTH) && addr) || > > > > > > + (addr & ((1 << (VTD_PAGE_SHIFT + mask)) - 1))); > > > > > > > > > > Could it work if we just use 1ULL instead of 1 here? Thanks, > > > > > > > > In either case we're talking about shifting off the end of the > > > > variable, which I understand to be undefined. Right? Thanks, > > > > > > How so? Bits fall off the left (MSB) end, zeroes fill in the right (LSB) > > > end. I believe that behavior is pretty set. > > > > Maybe I'm relying too much on stackoverflow, but: > > > > https://stackoverflow.com/questions/11270492/what-does-the-c-standard-say-about-bitshifting-more-bits-than-the-width-of-type > > No, probably not. I don't have my copy of c99 handy, so can't check it. But > it is beyond me why any compiler implementation would choose to use a rotate > instead of a shift... probably a performance issue. > > So, yeah, when you have silly parameters, you get what you get. > > I'll stick to my suggestion. Which seems unambiguous... but I could be > wrong. Hi, Alex, Hook, I did a quick test: xz-mi:tmp $ cat a.c #include void main(void) { unsigned long long val = 0x8001ULL; int shift; printf("origin: 0x%llx\n", val); shift = 1; printf("shl 1: 0x%llx\n", val << shift); shift = 62; printf("shl 62: 0x%llx\n", val << shift); shift = 63; printf("shl 63: 0x%llx\n", val << shift); shift = 64; printf("shl 64: 0x%llx\n", val << shift); shift = 65; printf("shl 65: 0x%llx\n", val << shift); } xz-mi:tmp $ gcc -std=c99 a.c xz-mi:tmp $ ./a.out origin: 0x8001 shl 1: 0x2 shl 62: 0x4000 shl 63: 0x8000 shl 64: 0x8001 shl 65: 0x2 xz-mi:tmp $ objdump -d a.out | grep -A20 "" 004004d7 : 4004d7: 55 push %rbp 4004d8: 48 89 e5mov%rsp,%rbp 4004db: 48 83 ec 10 sub$0x10,%rsp 4004df: 48 b8 01 00 00 00 00movabs $0x8001,%rax 4004e6: 00 00 80 4004e9: 48 89 45 f8 mov%rax,-0x8(%rbp) 4004ed: 48 8b 45 f8 mov-0x8(%rbp),%rax 4004f1: 48 89 c6mov%rax,%rsi 4004f4: bf 60 06 40 00 mov$0x400660,%edi 4004f9: b8 00 00 00 00 mov$0x0,%eax 4004fe: e8 ed fe ff ff callq 4003f0 400503: c7 45 f4 01 00 00 00movl $0x1,-0xc(%rbp) 40050a: 8b 45 f4mov-0xc(%rbp),%eax 40050d: 48 8b 55 f8 mov-0x8(%rbp),%rdx 400511: 89 c1 mov%eax,%ecx 400513: 48 d3 e2shl%cl,%rdx 400516: 48 89 d0mov%rdx,%rax 400519: 48 89 c6mov%rax,%rsi 40051c: bf 70 06 40 00 mov$0x400670,%edi 400521: b8 00 00 00 00 mov$0x0,%eax So it seems not really a rotation operation, but it looks more like convering a "shifting N" into "shifting N%64" when N>=64. So now I agree with Alex's change. Thanks all. -- Peter Xu
Re: [PATCH] iommu/vt-d: Fix shift overflow in qi_flush_dev_iotlb
On Wed, Dec 13, 2017 at 11:31:02AM -0600, Hook, Gary wrote: > On 12/13/2017 11:15 AM, Alex Williamson wrote: > > On Wed, 13 Dec 2017 10:41:47 -0600 > > "Hook, Gary" wrote: > > > > > On 12/13/2017 9:58 AM, Alex Williamson wrote: > > > > On Wed, 13 Dec 2017 15:13:55 +0800 > > > > Peter Xu wrote: > > > > > On Tue, Dec 12, 2017 at 03:43:08PM -0700, Alex Williamson wrote: > > > > > > > > > > [...] > > > > > > diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c > > > > > > index 9a7ffd13c7f0..87888b102057 100644 > > > > > > --- a/drivers/iommu/dmar.c > > > > > > +++ b/drivers/iommu/dmar.c > > > > > > @@ -1345,7 +1345,9 @@ void qi_flush_dev_iotlb(struct intel_iommu > > > > > > *iommu, u16 sid, u16 qdep, > > > > > > struct qi_desc desc; > > > > > > if (mask) { > > > > > > - BUG_ON(addr & ((1 << (VTD_PAGE_SHIFT + mask)) - 1)); > > > > > > + BUG_ON((mask > MAX_AGAW_PFN_WIDTH) || > > > > > > + ((mask == MAX_AGAW_PFN_WIDTH) && addr) || > > > > > > + (addr & ((1 << (VTD_PAGE_SHIFT + mask)) - 1))); > > > > > > > > > > Could it work if we just use 1ULL instead of 1 here? Thanks, > > > > > > > > In either case we're talking about shifting off the end of the > > > > variable, which I understand to be undefined. Right? Thanks, > > > > > > How so? Bits fall off the left (MSB) end, zeroes fill in the right (LSB) > > > end. I believe that behavior is pretty set. > > > > Maybe I'm relying too much on stackoverflow, but: > > > > https://stackoverflow.com/questions/11270492/what-does-the-c-standard-say-about-bitshifting-more-bits-than-the-width-of-type > > No, probably not. I don't have my copy of c99 handy, so can't check it. But > it is beyond me why any compiler implementation would choose to use a rotate > instead of a shift... probably a performance issue. > > So, yeah, when you have silly parameters, you get what you get. > > I'll stick to my suggestion. Which seems unambiguous... but I could be > wrong. Hi, Alex, Hook, I did a quick test: xz-mi:tmp $ cat a.c #include void main(void) { unsigned long long val = 0x8001ULL; int shift; printf("origin: 0x%llx\n", val); shift = 1; printf("shl 1: 0x%llx\n", val << shift); shift = 62; printf("shl 62: 0x%llx\n", val << shift); shift = 63; printf("shl 63: 0x%llx\n", val << shift); shift = 64; printf("shl 64: 0x%llx\n", val << shift); shift = 65; printf("shl 65: 0x%llx\n", val << shift); } xz-mi:tmp $ gcc -std=c99 a.c xz-mi:tmp $ ./a.out origin: 0x8001 shl 1: 0x2 shl 62: 0x4000 shl 63: 0x8000 shl 64: 0x8001 shl 65: 0x2 xz-mi:tmp $ objdump -d a.out | grep -A20 "" 004004d7 : 4004d7: 55 push %rbp 4004d8: 48 89 e5mov%rsp,%rbp 4004db: 48 83 ec 10 sub$0x10,%rsp 4004df: 48 b8 01 00 00 00 00movabs $0x8001,%rax 4004e6: 00 00 80 4004e9: 48 89 45 f8 mov%rax,-0x8(%rbp) 4004ed: 48 8b 45 f8 mov-0x8(%rbp),%rax 4004f1: 48 89 c6mov%rax,%rsi 4004f4: bf 60 06 40 00 mov$0x400660,%edi 4004f9: b8 00 00 00 00 mov$0x0,%eax 4004fe: e8 ed fe ff ff callq 4003f0 400503: c7 45 f4 01 00 00 00movl $0x1,-0xc(%rbp) 40050a: 8b 45 f4mov-0xc(%rbp),%eax 40050d: 48 8b 55 f8 mov-0x8(%rbp),%rdx 400511: 89 c1 mov%eax,%ecx 400513: 48 d3 e2shl%cl,%rdx 400516: 48 89 d0mov%rdx,%rax 400519: 48 89 c6mov%rax,%rsi 40051c: bf 70 06 40 00 mov$0x400670,%edi 400521: b8 00 00 00 00 mov$0x0,%eax So it seems not really a rotation operation, but it looks more like convering a "shifting N" into "shifting N%64" when N>=64. So now I agree with Alex's change. Thanks all. -- Peter Xu
[PATCH v4 2/2] misc: xlnx_vcu: Add Xilinx ZYNQMP VCU logicoreIP init driver
Xilinx ZYNQMP logicoreIP Init driver is based on the new LogiCoreIP design created. This driver provides the processing system and programmable logic isolation. Set the frequency based on the clock information get from the logicoreIP register set. It is put in drivers/misc as there is no subsystem for this logicoreIP. Signed-off-by: Dhaval Shah--- Changes since v4: * Indent the help text (below) by 2 additional spaces, as documented in coding-style.rst * Spell check are resolved as per the review comment. * inline the read() and write() functions.. * multi-line comment style * Updated subject line prefix Changes since v3: No Changes. Changes since v2: * Removed the "default n" from the Kconfig * More help text added to explain more about the logicoreIP driver * SPDX id is relocated at top of the file with // style comment * Removed the export API and header file and make it a single driver which provides logocoreIP init. * Provide the information in commit message as well for the why driver in drivers/misc. drivers/misc/Kconfig| 15 ++ drivers/misc/Makefile | 1 + drivers/misc/xlnx_vcu.c | 631 3 files changed, 647 insertions(+) create mode 100644 drivers/misc/xlnx_vcu.c diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index f1a5c23..e679936 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -496,6 +496,21 @@ config PCI_ENDPOINT_TEST Enable this configuration option to enable the host side test driver for PCI Endpoint. +config XILINX_VCU + tristate "Xilinx VCU logicoreIP Init" + help + Provides the driver to enable and disable the isolation between the + processing system and programmable logic part by using the logicoreIP + register set. This driver also configures the frequency based on the + clock information from the logicoreIP register set. + + If you say yes here you get support for the logicoreIP. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called xlnx_vcu. + source "drivers/misc/c2port/Kconfig" source "drivers/misc/eeprom/Kconfig" source "drivers/misc/cb710/Kconfig" diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 5ca5f64..a6bd0b1 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -55,6 +55,7 @@ obj-$(CONFIG_CXL_BASE)+= cxl/ obj-$(CONFIG_ASPEED_LPC_CTRL) += aspeed-lpc-ctrl.o obj-$(CONFIG_ASPEED_LPC_SNOOP) += aspeed-lpc-snoop.o obj-$(CONFIG_PCI_ENDPOINT_TEST)+= pci_endpoint_test.o +obj-$(CONFIG_XILINX_VCU) += xlnx_vcu.o lkdtm-$(CONFIG_LKDTM) += lkdtm_core.o lkdtm-$(CONFIG_LKDTM) += lkdtm_bugs.o diff --git a/drivers/misc/xlnx_vcu.c b/drivers/misc/xlnx_vcu.c new file mode 100644 index 000..f489d34 --- /dev/null +++ b/drivers/misc/xlnx_vcu.c @@ -0,0 +1,631 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Xilinx VCU Init + * + * Copyright (C) 2016 - 2017 Xilinx, Inc. + * + * Contacts Dhaval Shah + */ +#include +#include +#include +#include +#include +#include +#include + +/* Address map for different registers implemented in the VCU LogiCORE IP. */ +#define VCU_ECODER_ENABLE 0x00 +#define VCU_DECODER_ENABLE 0x04 +#define VCU_MEMORY_DEPTH 0x08 +#define VCU_ENC_COLOR_DEPTH0x0c +#define VCU_ENC_VERTICAL_RANGE 0x10 +#define VCU_ENC_FRAME_SIZE_X 0x14 +#define VCU_ENC_FRAME_SIZE_Y 0x18 +#define VCU_ENC_COLOR_FORMAT 0x1c +#define VCU_ENC_FPS0x20 +#define VCU_MCU_CLK0x24 +#define VCU_CORE_CLK 0x28 +#define VCU_PLL_BYPASS 0x2c +#define VCU_ENC_CLK0x30 +#define VCU_PLL_CLK0x34 +#define VCU_ENC_VIDEO_STANDARD 0x38 +#define VCU_STATUS 0x3c +#define VCU_AXI_ENC_CLK0x40 +#define VCU_AXI_DEC_CLK0x44 +#define VCU_AXI_MCU_CLK0x48 +#define VCU_DEC_VIDEO_STANDARD 0x4c +#define VCU_DEC_FRAME_SIZE_X 0x50 +#define VCU_DEC_FRAME_SIZE_Y 0x54 +#define VCU_DEC_FPS0x58 +#define VCU_BUFFER_B_FRAME 0x5c +#define VCU_WPP_EN 0x60 +#define VCU_PLL_CLK_DEC0x64 +#define VCU_GASKET_INIT0x74 +#define VCU_GASKET_VALUE 0x03 + +/* vcu slcr registers, bitmask and shift */ +#define VCU_PLL_CTRL 0x24 +#define VCU_PLL_CTRL_RESET_MASK0x01 +#define VCU_PLL_CTRL_RESET_SHIFT 0 +#define VCU_PLL_CTRL_BYPASS_MASK 0x01 +#define VCU_PLL_CTRL_BYPASS_SHIFT 3 +#define VCU_PLL_CTRL_FBDIV_MASK0x7f +#define VCU_PLL_CTRL_FBDIV_SHIFT 8 +#define
[PATCH v4 2/2] misc: xlnx_vcu: Add Xilinx ZYNQMP VCU logicoreIP init driver
Xilinx ZYNQMP logicoreIP Init driver is based on the new LogiCoreIP design created. This driver provides the processing system and programmable logic isolation. Set the frequency based on the clock information get from the logicoreIP register set. It is put in drivers/misc as there is no subsystem for this logicoreIP. Signed-off-by: Dhaval Shah --- Changes since v4: * Indent the help text (below) by 2 additional spaces, as documented in coding-style.rst * Spell check are resolved as per the review comment. * inline the read() and write() functions.. * multi-line comment style * Updated subject line prefix Changes since v3: No Changes. Changes since v2: * Removed the "default n" from the Kconfig * More help text added to explain more about the logicoreIP driver * SPDX id is relocated at top of the file with // style comment * Removed the export API and header file and make it a single driver which provides logocoreIP init. * Provide the information in commit message as well for the why driver in drivers/misc. drivers/misc/Kconfig| 15 ++ drivers/misc/Makefile | 1 + drivers/misc/xlnx_vcu.c | 631 3 files changed, 647 insertions(+) create mode 100644 drivers/misc/xlnx_vcu.c diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index f1a5c23..e679936 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -496,6 +496,21 @@ config PCI_ENDPOINT_TEST Enable this configuration option to enable the host side test driver for PCI Endpoint. +config XILINX_VCU + tristate "Xilinx VCU logicoreIP Init" + help + Provides the driver to enable and disable the isolation between the + processing system and programmable logic part by using the logicoreIP + register set. This driver also configures the frequency based on the + clock information from the logicoreIP register set. + + If you say yes here you get support for the logicoreIP. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called xlnx_vcu. + source "drivers/misc/c2port/Kconfig" source "drivers/misc/eeprom/Kconfig" source "drivers/misc/cb710/Kconfig" diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 5ca5f64..a6bd0b1 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -55,6 +55,7 @@ obj-$(CONFIG_CXL_BASE)+= cxl/ obj-$(CONFIG_ASPEED_LPC_CTRL) += aspeed-lpc-ctrl.o obj-$(CONFIG_ASPEED_LPC_SNOOP) += aspeed-lpc-snoop.o obj-$(CONFIG_PCI_ENDPOINT_TEST)+= pci_endpoint_test.o +obj-$(CONFIG_XILINX_VCU) += xlnx_vcu.o lkdtm-$(CONFIG_LKDTM) += lkdtm_core.o lkdtm-$(CONFIG_LKDTM) += lkdtm_bugs.o diff --git a/drivers/misc/xlnx_vcu.c b/drivers/misc/xlnx_vcu.c new file mode 100644 index 000..f489d34 --- /dev/null +++ b/drivers/misc/xlnx_vcu.c @@ -0,0 +1,631 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Xilinx VCU Init + * + * Copyright (C) 2016 - 2017 Xilinx, Inc. + * + * Contacts Dhaval Shah + */ +#include +#include +#include +#include +#include +#include +#include + +/* Address map for different registers implemented in the VCU LogiCORE IP. */ +#define VCU_ECODER_ENABLE 0x00 +#define VCU_DECODER_ENABLE 0x04 +#define VCU_MEMORY_DEPTH 0x08 +#define VCU_ENC_COLOR_DEPTH0x0c +#define VCU_ENC_VERTICAL_RANGE 0x10 +#define VCU_ENC_FRAME_SIZE_X 0x14 +#define VCU_ENC_FRAME_SIZE_Y 0x18 +#define VCU_ENC_COLOR_FORMAT 0x1c +#define VCU_ENC_FPS0x20 +#define VCU_MCU_CLK0x24 +#define VCU_CORE_CLK 0x28 +#define VCU_PLL_BYPASS 0x2c +#define VCU_ENC_CLK0x30 +#define VCU_PLL_CLK0x34 +#define VCU_ENC_VIDEO_STANDARD 0x38 +#define VCU_STATUS 0x3c +#define VCU_AXI_ENC_CLK0x40 +#define VCU_AXI_DEC_CLK0x44 +#define VCU_AXI_MCU_CLK0x48 +#define VCU_DEC_VIDEO_STANDARD 0x4c +#define VCU_DEC_FRAME_SIZE_X 0x50 +#define VCU_DEC_FRAME_SIZE_Y 0x54 +#define VCU_DEC_FPS0x58 +#define VCU_BUFFER_B_FRAME 0x5c +#define VCU_WPP_EN 0x60 +#define VCU_PLL_CLK_DEC0x64 +#define VCU_GASKET_INIT0x74 +#define VCU_GASKET_VALUE 0x03 + +/* vcu slcr registers, bitmask and shift */ +#define VCU_PLL_CTRL 0x24 +#define VCU_PLL_CTRL_RESET_MASK0x01 +#define VCU_PLL_CTRL_RESET_SHIFT 0 +#define VCU_PLL_CTRL_BYPASS_MASK 0x01 +#define VCU_PLL_CTRL_BYPASS_SHIFT 3 +#define VCU_PLL_CTRL_FBDIV_MASK0x7f +#define VCU_PLL_CTRL_FBDIV_SHIFT 8 +#define VCU_PLL_CTRL_POR_IN_MASK 0x01 +#define
[PATCH v4 1/2] dt-bindings: misc: Add DT bindings to xlnx_vcu driver
From: Dhaval ShahAdd Device Tree binding document for logicoreIP. This logicoreIP provides the isolation between the processing system and programmable logic. Also provides the clock related information. Signed-off-by: Dhaval Shah --- Chnages since v3: No Changes. Chnages since v3: * Use "dt-bindings: misc: ..." for the subject. Changes since v2: * Describe the h/w * compatible string is updated to make it more specific based on the logicoreIP version. * Removed that encoder and decoder child nodes and relatd properties as that will be a separate driver and dts nodes. other team is working on that. * Updated to use as a single driver. .../devicetree/bindings/misc/xlnx,vcu.txt | 31 ++ 1 file changed, 31 insertions(+) create mode 100644 Documentation/devicetree/bindings/misc/xlnx,vcu.txt diff --git a/Documentation/devicetree/bindings/misc/xlnx,vcu.txt b/Documentation/devicetree/bindings/misc/xlnx,vcu.txt new file mode 100644 index 000..6786d67 --- /dev/null +++ b/Documentation/devicetree/bindings/misc/xlnx,vcu.txt @@ -0,0 +1,31 @@ +LogicoreIP designed compatible with Xilinx ZYNQ family. +--- + +General concept +--- + +LogicoreIP design to provide the isolation between processing system +and programmable logic. Also provides the list of register set to configure +the frequency. + +Required properties: +- compatible: shall be one of: + "xlnx,vcu" + "xlnx,vcu-logicoreip-1.0" +- reg, reg-names: There are two sets of registers need to provide. + 1. vcu slcr + 2. Logicore + reg-names should contain name for the each register sequence. +- clocks: phandle for aclk and pll_ref clocksource +- clock-names: The identification string, "aclk", is always required for + the axi clock. "pll_ref" is required for pll. +Example: + + xlnx_vcu: vcu@a004 { + compatible = "xlnx,vcu-logicoreip-1.0"; + reg = <0x0 0xa004 0x0 0x1000>, +<0x0 0xa0041000 0x0 0x1000>; + reg-names = "vcu_slcr", "logicore"; + clocks = <_1>, < 71>; + clock-names = "pll_ref", "aclk"; + }; -- 2.7.4
[PATCH v4 0/2] Documentation and driver of logicoreIP
1st patch provide Device Tree binding document for logicoreIP 2nd patch provide the xlnx_vcu logicoreIP driver, Kconfig changes and Makefile changes for the driver. Dhaval Shah (2): Documentation: devicetree: Add DT bindings to xlnx_vcu driver misc: xlnx_vcu: Add Xilinx ZYNQMP VCU logicoreIP init driver .../devicetree/bindings/misc/xlnx,vcu.txt | 31 + drivers/misc/Kconfig | 15 + drivers/misc/Makefile | 1 + drivers/misc/xlnx_vcu.c| 631 + 4 files changed, 678 insertions(+) create mode 100644 Documentation/devicetree/bindings/misc/xlnx,vcu.txt create mode 100644 drivers/misc/xlnx_vcu.c -- 2.7.4
[PATCH v4 1/2] dt-bindings: misc: Add DT bindings to xlnx_vcu driver
From: Dhaval Shah Add Device Tree binding document for logicoreIP. This logicoreIP provides the isolation between the processing system and programmable logic. Also provides the clock related information. Signed-off-by: Dhaval Shah --- Chnages since v3: No Changes. Chnages since v3: * Use "dt-bindings: misc: ..." for the subject. Changes since v2: * Describe the h/w * compatible string is updated to make it more specific based on the logicoreIP version. * Removed that encoder and decoder child nodes and relatd properties as that will be a separate driver and dts nodes. other team is working on that. * Updated to use as a single driver. .../devicetree/bindings/misc/xlnx,vcu.txt | 31 ++ 1 file changed, 31 insertions(+) create mode 100644 Documentation/devicetree/bindings/misc/xlnx,vcu.txt diff --git a/Documentation/devicetree/bindings/misc/xlnx,vcu.txt b/Documentation/devicetree/bindings/misc/xlnx,vcu.txt new file mode 100644 index 000..6786d67 --- /dev/null +++ b/Documentation/devicetree/bindings/misc/xlnx,vcu.txt @@ -0,0 +1,31 @@ +LogicoreIP designed compatible with Xilinx ZYNQ family. +--- + +General concept +--- + +LogicoreIP design to provide the isolation between processing system +and programmable logic. Also provides the list of register set to configure +the frequency. + +Required properties: +- compatible: shall be one of: + "xlnx,vcu" + "xlnx,vcu-logicoreip-1.0" +- reg, reg-names: There are two sets of registers need to provide. + 1. vcu slcr + 2. Logicore + reg-names should contain name for the each register sequence. +- clocks: phandle for aclk and pll_ref clocksource +- clock-names: The identification string, "aclk", is always required for + the axi clock. "pll_ref" is required for pll. +Example: + + xlnx_vcu: vcu@a004 { + compatible = "xlnx,vcu-logicoreip-1.0"; + reg = <0x0 0xa004 0x0 0x1000>, +<0x0 0xa0041000 0x0 0x1000>; + reg-names = "vcu_slcr", "logicore"; + clocks = <_1>, < 71>; + clock-names = "pll_ref", "aclk"; + }; -- 2.7.4
[PATCH v4 0/2] Documentation and driver of logicoreIP
1st patch provide Device Tree binding document for logicoreIP 2nd patch provide the xlnx_vcu logicoreIP driver, Kconfig changes and Makefile changes for the driver. Dhaval Shah (2): Documentation: devicetree: Add DT bindings to xlnx_vcu driver misc: xlnx_vcu: Add Xilinx ZYNQMP VCU logicoreIP init driver .../devicetree/bindings/misc/xlnx,vcu.txt | 31 + drivers/misc/Kconfig | 15 + drivers/misc/Makefile | 1 + drivers/misc/xlnx_vcu.c| 631 + 4 files changed, 678 insertions(+) create mode 100644 Documentation/devicetree/bindings/misc/xlnx,vcu.txt create mode 100644 drivers/misc/xlnx_vcu.c -- 2.7.4
Re: [PATCH] APEI / ERST: Fix missing error handling in erst_reader()
On Fri, 15 Dec 2017 02:01:20 +0100, Rafael J. Wysocki wrote: > > On Thu, Dec 14, 2017 at 1:31 PM, Takashi Iwaiwrote: > > The commit f6f828513290 ("pstore: pass allocated memory region back to > > caller") changed the check of the return value from erst_read() in > > erst_reader() in the following way: > > > > if (len == -ENOENT) > > goto skip; > > - else if (len < 0) { > > - rc = -1; > > + else if (len < sizeof(*rcd)) { > > + rc = -EIO; > > goto out; > > > > This introduced another bug: since the comparison with sizeof() is > > cast to unsigned, a negative len value doesn't hit any longer. > > As a result, when an error is returned from erst_read(), the code > > falls through, and it may eventually lead to some weird thing like > > memory corruption. > > > > This patch adds the negative error value check more explicitly for > > addressing the issue. > > > > Fixes: f6f828513290 ("pstore: pass allocated memory region back to caller") > > That's ancient. :-) > > > Cc: > > Tested-by: Jerry Tang > > Signed-off-by: Takashi Iwai > > --- > > drivers/acpi/apei/erst.c | 2 +- > > 1 file changed, 1 insertion(+), 1 deletion(-) > > > > diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c > > index 6742f6c68034..9bff853e85f3 100644 > > --- a/drivers/acpi/apei/erst.c > > +++ b/drivers/acpi/apei/erst.c > > @@ -1007,7 +1007,7 @@ static ssize_t erst_reader(struct pstore_record > > *record) > > /* The record may be cleared by others, try read next record */ > > if (len == -ENOENT) > > goto skip; > > - else if (len < sizeof(*rcd)) { > > + else if (len < 0 || len < sizeof(*rcd)) { > > rc = -EIO; > > goto out; > > } > > -- > > OK, I'm going to queue this up unless I see objections from Boris or Tony. I missed Boris in Cc list, sorry. Now added. Takashi
Re: [PATCH] APEI / ERST: Fix missing error handling in erst_reader()
On Fri, 15 Dec 2017 02:01:20 +0100, Rafael J. Wysocki wrote: > > On Thu, Dec 14, 2017 at 1:31 PM, Takashi Iwai wrote: > > The commit f6f828513290 ("pstore: pass allocated memory region back to > > caller") changed the check of the return value from erst_read() in > > erst_reader() in the following way: > > > > if (len == -ENOENT) > > goto skip; > > - else if (len < 0) { > > - rc = -1; > > + else if (len < sizeof(*rcd)) { > > + rc = -EIO; > > goto out; > > > > This introduced another bug: since the comparison with sizeof() is > > cast to unsigned, a negative len value doesn't hit any longer. > > As a result, when an error is returned from erst_read(), the code > > falls through, and it may eventually lead to some weird thing like > > memory corruption. > > > > This patch adds the negative error value check more explicitly for > > addressing the issue. > > > > Fixes: f6f828513290 ("pstore: pass allocated memory region back to caller") > > That's ancient. :-) > > > Cc: > > Tested-by: Jerry Tang > > Signed-off-by: Takashi Iwai > > --- > > drivers/acpi/apei/erst.c | 2 +- > > 1 file changed, 1 insertion(+), 1 deletion(-) > > > > diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c > > index 6742f6c68034..9bff853e85f3 100644 > > --- a/drivers/acpi/apei/erst.c > > +++ b/drivers/acpi/apei/erst.c > > @@ -1007,7 +1007,7 @@ static ssize_t erst_reader(struct pstore_record > > *record) > > /* The record may be cleared by others, try read next record */ > > if (len == -ENOENT) > > goto skip; > > - else if (len < sizeof(*rcd)) { > > + else if (len < 0 || len < sizeof(*rcd)) { > > rc = -EIO; > > goto out; > > } > > -- > > OK, I'm going to queue this up unless I see objections from Boris or Tony. I missed Boris in Cc list, sorry. Now added. Takashi