Commit 99d0701a authored by Ben Skeggs's avatar Ben Skeggs

drm/nouveau/nvkm: rip out old notify

Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
Reviewed-by: default avatarLyude Paul <lyude@redhat.com>
parent 6c9705f6
......@@ -33,31 +33,4 @@ nvif_event_ctor(struct nvif_object *parent, const char *name, u32 handle, nvif_e
void nvif_event_dtor(struct nvif_event *);
int nvif_event_allow(struct nvif_event *);
int nvif_event_block(struct nvif_event *);
struct nvif_notify_req_v0 {
__u8 version;
__u8 reply;
__u8 pad02[5];
#define NVIF_NOTIFY_V0_ROUTE_NVIF 0x00
__u8 route;
__u64 token; /* must be unique */
__u8 data[]; /* request data (below) */
};
struct nvif_notify_rep_v0 {
__u8 version;
__u8 pad01[6];
__u8 route;
__u64 token;
__u8 data[]; /* reply data (below) */
};
struct nvif_notify_uevent_req {
/* nvif_notify_req ... */
};
struct nvif_notify_uevent_rep {
/* nvif_notify_rep ... */
};
#endif
......@@ -15,10 +15,6 @@ struct nvif_ioctl_v0 {
#define NVIF_IOCTL_V0_WR 0x06
#define NVIF_IOCTL_V0_MAP 0x07
#define NVIF_IOCTL_V0_UNMAP 0x08
#define NVIF_IOCTL_V0_NTFY_NEW 0x09
#define NVIF_IOCTL_V0_NTFY_DEL 0x0a
#define NVIF_IOCTL_V0_NTFY_GET 0x0b
#define NVIF_IOCTL_V0_NTFY_PUT 0x0c
__u8 type;
__u8 pad02[4];
#define NVIF_IOCTL_V0_OWNER_NVIF 0x00
......@@ -63,6 +59,14 @@ struct nvif_ioctl_new_v0 {
struct nvif_ioctl_del {
};
struct nvif_ioctl_mthd_v0 {
/* nvif_ioctl ... */
__u8 version;
__u8 method;
__u8 pad02[6];
__u8 data[]; /* method data (class.h) */
};
struct nvif_ioctl_rd_v0 {
/* nvif_ioctl ... */
__u8 version;
......@@ -95,43 +99,4 @@ struct nvif_ioctl_map_v0 {
struct nvif_ioctl_unmap {
};
struct nvif_ioctl_ntfy_new_v0 {
/* nvif_ioctl ... */
__u8 version;
__u8 event;
__u8 index;
__u8 pad03[5];
__u8 data[]; /* event request data (event.h) */
};
struct nvif_ioctl_ntfy_del_v0 {
/* nvif_ioctl ... */
__u8 version;
__u8 index;
__u8 pad02[6];
};
struct nvif_ioctl_ntfy_get_v0 {
/* nvif_ioctl ... */
__u8 version;
__u8 index;
__u8 pad02[6];
};
struct nvif_ioctl_ntfy_put_v0 {
/* nvif_ioctl ... */
__u8 version;
__u8 index;
__u8 pad02[6];
};
struct nvif_ioctl_mthd_v0 {
/* nvif_ioctl ... */
__u8 version;
__u8 method;
__u8 pad02[6];
__u8 data[]; /* method data (class.h) */
};
#endif
/* SPDX-License-Identifier: MIT */
#ifndef __NVIF_NOTIFY_H__
#define __NVIF_NOTIFY_H__
struct nvif_notify {
struct nvif_object *object;
const char *name;
int index;
#define NVIF_NOTIFY_USER 0
#define NVIF_NOTIFY_WORK 1
unsigned long flags;
atomic_t putcnt;
void (*dtor)(struct nvif_notify *);
#define NVIF_NOTIFY_DROP 0
#define NVIF_NOTIFY_KEEP 1
int (*func)(struct nvif_notify *);
/* this is const for a *very* good reason - the data might be on the
* stack from an irq handler. if you're not nvif/notify.c then you
* should probably think twice before casting it away...
*/
const void *data;
u32 size;
struct work_struct work;
};
int nvif_notify_ctor(struct nvif_object *, const char *name,
int (*func)(struct nvif_notify *), bool work, u8 type,
void *data, u32 size, u32 reply, struct nvif_notify *);
int nvif_notify_dtor(struct nvif_notify *);
int nvif_notify_get(struct nvif_notify *);
int nvif_notify_put(struct nvif_notify *);
int nvif_notify(const void *, u32, const void *, u32);
#endif
......@@ -10,30 +10,19 @@ struct nvkm_client {
u64 device;
u32 debug;
struct nvkm_client_notify *notify[32];
struct rb_root objroot;
void *data;
int (*ntfy)(const void *, u32, const void *, u32);
int (*event)(u64 token, void *argv, u32 argc);
struct list_head umem;
spinlock_t lock;
};
int nvkm_client_new(const char *name, u64 device, const char *cfg,
const char *dbg,
int (*)(const void *, u32, const void *, u32),
int (*)(u64, void *, u32),
struct nvkm_client **);
int nvkm_client_new(const char *name, u64 device, const char *cfg, const char *dbg,
int (*)(u64, void *, u32), struct nvkm_client **);
struct nvkm_client *nvkm_client_search(struct nvkm_client *, u64 handle);
int nvkm_client_notify_new(struct nvkm_object *, struct nvkm_event *,
void *data, u32 size);
int nvkm_client_notify_del(struct nvkm_client *, int index);
int nvkm_client_notify_get(struct nvkm_client *, int index);
int nvkm_client_notify_put(struct nvkm_client *, int index);
/* logging for client-facing objects */
#define nvif_printk(o,l,p,f,a...) do { \
const struct nvkm_object *_object = (o); \
......
......@@ -2,7 +2,6 @@
#ifndef __NVKM_EVENT_H__
#define __NVKM_EVENT_H__
#include <core/os.h>
struct nvkm_notify;
struct nvkm_object;
struct nvkm_oclass;
struct nvkm_uevent;
......@@ -16,16 +15,12 @@ struct nvkm_event {
spinlock_t refs_lock;
spinlock_t list_lock;
struct list_head list;
int *refs;
struct list_head ntfy;
};
struct nvkm_event_func {
int (*ctor)(struct nvkm_object *, void *data, u32 size,
struct nvkm_notify *);
void (*send)(void *data, u32 size, struct nvkm_notify *);
void (*init)(struct nvkm_event *, int type, int index);
void (*fini)(struct nvkm_event *, int type, int index);
};
......@@ -33,10 +28,6 @@ struct nvkm_event_func {
int nvkm_event_init(const struct nvkm_event_func *func, struct nvkm_subdev *, int types_nr,
int index_nr, struct nvkm_event *);
void nvkm_event_fini(struct nvkm_event *);
void nvkm_event_get(struct nvkm_event *, u32 types, int index);
void nvkm_event_put(struct nvkm_event *, u32 types, int index);
void nvkm_event_send(struct nvkm_event *, u32 types, int index,
void *data, u32 size);
#define NVKM_EVENT_KEEP 0
#define NVKM_EVENT_DROP 1
......
/* SPDX-License-Identifier: MIT */
#ifndef __NVKM_NOTIFY_H__
#define __NVKM_NOTIFY_H__
#include <core/os.h>
struct nvkm_object;
struct nvkm_notify {
struct nvkm_event *event;
struct list_head head;
#define NVKM_NOTIFY_USER 0
#define NVKM_NOTIFY_WORK 1
unsigned long flags;
int block;
#define NVKM_NOTIFY_DROP 0
#define NVKM_NOTIFY_KEEP 1
int (*func)(struct nvkm_notify *);
/* set by nvkm_event ctor */
u32 types;
int index;
u32 size;
struct work_struct work;
/* this is const for a *very* good reason - the data might be on the
* stack from an irq handler. if you're not core/notify.c then you
* should probably think twice before casting it away...
*/
const void *data;
};
int nvkm_notify_init(struct nvkm_object *, struct nvkm_event *,
int (*func)(struct nvkm_notify *), bool work,
void *data, u32 size, u32 reply,
struct nvkm_notify *);
void nvkm_notify_fini(struct nvkm_notify *);
void nvkm_notify_get(struct nvkm_notify *);
void nvkm_notify_put(struct nvkm_notify *);
void nvkm_notify_send(struct nvkm_notify *, void *data, u32 size);
#endif
......@@ -78,11 +78,6 @@ enum nouveau_drm_object_route {
NVDRM_OBJECT_ANY = NVIF_IOCTL_V0_OWNER_ANY,
};
enum nouveau_drm_notify_route {
NVDRM_NOTIFY_NVIF = 0,
NVDRM_NOTIFY_USIF
};
enum nouveau_drm_handle {
NVDRM_CHAN = 0xcccc0000, /* |= client chid */
NVDRM_NVSW = 0x55550000,
......
......@@ -27,12 +27,10 @@
******************************************************************************/
#include <core/client.h>
#include <core/notify.h>
#include <core/ioctl.h>
#include <nvif/client.h>
#include <nvif/driver.h>
#include <nvif/notify.h>
#include <nvif/event.h>
#include <nvif/ioctl.h>
......@@ -87,7 +85,7 @@ static int
nvkm_client_driver_init(const char *name, u64 device, const char *cfg,
const char *dbg, void **ppriv)
{
return nvkm_client_new(name, device, cfg, dbg, nvif_notify, nvkm_client_event,
return nvkm_client_new(name, device, cfg, dbg, nvkm_client_event,
(struct nvkm_client **)ppriv);
}
......
......@@ -151,12 +151,6 @@ usif_ioctl(struct drm_file *filp, void __user *user, u32 argc)
case NVIF_IOCTL_V0_NEW:
ret = usif_object_new(filp, data, size, argv, argc, abi16);
break;
case NVIF_IOCTL_V0_NTFY_NEW:
case NVIF_IOCTL_V0_NTFY_DEL:
case NVIF_IOCTL_V0_NTFY_GET:
case NVIF_IOCTL_V0_NTFY_PUT:
ret = -ENOSYS;
break;
default:
ret = nvif_client_ioctl(client, argv, argc);
break;
......
......@@ -10,7 +10,6 @@ nvif-y += nvif/fifo.o
nvif-y += nvif/head.o
nvif-y += nvif/mem.o
nvif-y += nvif/mmu.o
nvif-y += nvif/notify.o
nvif-y += nvif/outp.o
nvif-y += nvif/timer.o
nvif-y += nvif/vmm.o
......
/*
* Copyright 2014 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs <bskeggs@redhat.com>
*/
#include <nvif/client.h>
#include <nvif/driver.h>
#include <nvif/notify.h>
#include <nvif/object.h>
#include <nvif/ioctl.h>
#include <nvif/event.h>
static inline int
nvif_notify_put_(struct nvif_notify *notify)
{
struct nvif_object *object = notify->object;
struct {
struct nvif_ioctl_v0 ioctl;
struct nvif_ioctl_ntfy_put_v0 ntfy;
} args = {
.ioctl.type = NVIF_IOCTL_V0_NTFY_PUT,
.ntfy.index = notify->index,
};
if (atomic_inc_return(&notify->putcnt) != 1)
return 0;
return nvif_object_ioctl(object, &args, sizeof(args), NULL);
}
int
nvif_notify_put(struct nvif_notify *notify)
{
if (likely(notify->object) &&
test_and_clear_bit(NVIF_NOTIFY_USER, &notify->flags)) {
int ret = nvif_notify_put_(notify);
if (test_bit(NVIF_NOTIFY_WORK, &notify->flags))
flush_work(&notify->work);
return ret;
}
return 0;
}
static inline int
nvif_notify_get_(struct nvif_notify *notify)
{
struct nvif_object *object = notify->object;
struct {
struct nvif_ioctl_v0 ioctl;
struct nvif_ioctl_ntfy_get_v0 ntfy;
} args = {
.ioctl.type = NVIF_IOCTL_V0_NTFY_GET,
.ntfy.index = notify->index,
};
if (atomic_dec_return(&notify->putcnt) != 0)
return 0;
return nvif_object_ioctl(object, &args, sizeof(args), NULL);
}
int
nvif_notify_get(struct nvif_notify *notify)
{
if (likely(notify->object) &&
!test_and_set_bit(NVIF_NOTIFY_USER, &notify->flags))
return nvif_notify_get_(notify);
return 0;
}
static inline int
nvif_notify_func(struct nvif_notify *notify, bool keep)
{
int ret = notify->func(notify);
if (ret == NVIF_NOTIFY_KEEP ||
!test_and_clear_bit(NVIF_NOTIFY_USER, &notify->flags)) {
if (!keep)
atomic_dec(&notify->putcnt);
else
nvif_notify_get_(notify);
}
return ret;
}
static void
nvif_notify_work(struct work_struct *work)
{
struct nvif_notify *notify = container_of(work, typeof(*notify), work);
nvif_notify_func(notify, true);
}
int
nvif_notify(const void *header, u32 length, const void *data, u32 size)
{
struct nvif_notify *notify = NULL;
const union {
struct nvif_notify_rep_v0 v0;
} *args = header;
int ret = NVIF_NOTIFY_DROP;
if (length == sizeof(args->v0) && args->v0.version == 0) {
if (WARN_ON(args->v0.route))
return NVIF_NOTIFY_DROP;
notify = (void *)(unsigned long)args->v0.token;
}
if (!WARN_ON(notify == NULL)) {
struct nvif_client *client = notify->object->client;
if (!WARN_ON(notify->size != size)) {
atomic_inc(&notify->putcnt);
if (test_bit(NVIF_NOTIFY_WORK, &notify->flags)) {
memcpy((void *)notify->data, data, size);
schedule_work(&notify->work);
return NVIF_NOTIFY_DROP;
}
notify->data = data;
ret = nvif_notify_func(notify, client->driver->keep);
notify->data = NULL;
}
}
return ret;
}
int
nvif_notify_dtor(struct nvif_notify *notify)
{
struct nvif_object *object = notify->object;
struct {
struct nvif_ioctl_v0 ioctl;
struct nvif_ioctl_ntfy_del_v0 ntfy;
} args = {
.ioctl.type = NVIF_IOCTL_V0_NTFY_DEL,
.ntfy.index = notify->index,
};
int ret = nvif_notify_put(notify);
if (ret >= 0 && object) {
ret = nvif_object_ioctl(object, &args, sizeof(args), NULL);
notify->object = NULL;
kfree((void *)notify->data);
}
return ret;
}
int
nvif_notify_ctor(struct nvif_object *object, const char *name,
int (*func)(struct nvif_notify *), bool work, u8 event,
void *data, u32 size, u32 reply, struct nvif_notify *notify)
{
struct {
struct nvif_ioctl_v0 ioctl;
struct nvif_ioctl_ntfy_new_v0 ntfy;
struct nvif_notify_req_v0 req;
} *args;
int ret = -ENOMEM;
notify->object = object;
notify->name = name ? name : "nvifNotify";
notify->flags = 0;
atomic_set(&notify->putcnt, 1);
notify->func = func;
notify->data = NULL;
notify->size = reply;
if (work) {
INIT_WORK(&notify->work, nvif_notify_work);
set_bit(NVIF_NOTIFY_WORK, &notify->flags);
notify->data = kmalloc(notify->size, GFP_KERNEL);
if (!notify->data)
goto done;
}
if (!(args = kmalloc(sizeof(*args) + size, GFP_KERNEL)))
goto done;
args->ioctl.version = 0;
args->ioctl.type = NVIF_IOCTL_V0_NTFY_NEW;
args->ntfy.version = 0;
args->ntfy.event = event;
args->req.version = 0;
args->req.reply = notify->size;
args->req.route = 0;
args->req.token = (unsigned long)(void *)notify;
memcpy(args->req.data, data, size);
ret = nvif_object_ioctl(object, args, sizeof(*args) + size, NULL);
notify->index = args->ntfy.index;
kfree(args);
done:
if (ret)
nvif_notify_dtor(notify);
return ret;
}
......@@ -8,7 +8,6 @@ nvkm-y += nvkm/core/gpuobj.o
nvkm-y += nvkm/core/ioctl.o
nvkm-y += nvkm/core/memory.o
nvkm-y += nvkm/core/mm.o
nvkm-y += nvkm/core/notify.o
nvkm-y += nvkm/core/object.o
nvkm-y += nvkm/core/oproxy.o
nvkm-y += nvkm/core/option.o
......
......@@ -23,7 +23,6 @@
*/
#include <core/client.h>
#include <core/device.h>
#include <core/notify.h>
#include <core/option.h>
#include <nvif/class.h>
......@@ -44,7 +43,7 @@ nvkm_uclient_new(const struct nvkm_oclass *oclass, void *argv, u32 argc,
if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))){
args->v0.name[sizeof(args->v0.name) - 1] = 0;
ret = nvkm_client_new(args->v0.name, args->v0.device, NULL,
NULL, oclass->client->ntfy, oclass->client->event, &client);
NULL, oclass->client->event, &client);
if (ret)
return ret;
} else
......@@ -68,113 +67,6 @@ nvkm_uclient_sclass = {
.ctor = nvkm_uclient_new,
};
struct nvkm_client_notify {
struct nvkm_client *client;
struct nvkm_notify n;
u8 version;
u8 size;
union {
struct nvif_notify_rep_v0 v0;
} rep;
};
static int
nvkm_client_notify(struct nvkm_notify *n)
{
struct nvkm_client_notify *notify = container_of(n, typeof(*notify), n);
struct nvkm_client *client = notify->client;
return client->ntfy(&notify->rep, notify->size, n->data, n->size);
}
int
nvkm_client_notify_put(struct nvkm_client *client, int index)
{
if (index < ARRAY_SIZE(client->notify)) {
if (client->notify[index]) {
nvkm_notify_put(&client->notify[index]->n);
return 0;
}
}
return -ENOENT;
}
int
nvkm_client_notify_get(struct nvkm_client *client, int index)
{
if (index < ARRAY_SIZE(client->notify)) {
if (client->notify[index]) {
nvkm_notify_get(&client->notify[index]->n);
return 0;
}
}
return -ENOENT;
}
int
nvkm_client_notify_del(struct nvkm_client *client, int index)
{
if (index < ARRAY_SIZE(client->notify)) {
if (client->notify[index]) {
nvkm_notify_fini(&client->notify[index]->n);
kfree(client->notify[index]);
client->notify[index] = NULL;
return 0;
}
}
return -ENOENT;
}
int
nvkm_client_notify_new(struct nvkm_object *object,
struct nvkm_event *event, void *data, u32 size)
{
struct nvkm_client *client = object->client;
struct nvkm_client_notify *notify;
union {
struct nvif_notify_req_v0 v0;
} *req = data;
u8 index, reply;
int ret = -ENOSYS;
for (index = 0; index < ARRAY_SIZE(client->notify); index++) {
if (!client->notify[index])
break;
}
if (index == ARRAY_SIZE(client->notify))
return -ENOSPC;
notify = kzalloc(sizeof(*notify), GFP_KERNEL);
if (!notify)
return -ENOMEM;
nvif_ioctl(object, "notify new size %d\n", size);
if (!(ret = nvif_unpack(ret, &data, &size, req->v0, 0, 0, true))) {
nvif_ioctl(object, "notify new vers %d reply %d route %02x "
"token %llx\n", req->v0.version,
req->v0.reply, req->v0.route, req->v0.token);
notify->version = req->v0.version;
notify->size = sizeof(notify->rep.v0);
notify->rep.v0.version = req->v0.version;
notify->rep.v0.route = req->v0.route;
notify->rep.v0.token = req->v0.token;
reply = req->v0.reply;
}
if (ret == 0) {
ret = nvkm_notify_init(object, event, nvkm_client_notify,
false, data, size, reply, &notify->n);
if (ret == 0) {
client->notify[index] = notify;
notify->client = client;
return index;
}
}
kfree(notify);
return ret;
}
static const struct nvkm_object_func nvkm_client;
struct nvkm_client *
nvkm_client_search(struct nvkm_client *client, u64 handle)
......@@ -255,23 +147,13 @@ nvkm_client_child_get(struct nvkm_object *object, int index,
static int
nvkm_client_fini(struct nvkm_object *object, bool suspend)
{
struct nvkm_client *client = nvkm_client(object);
const char *name[2] = { "fini", "suspend" };
int i;
nvif_debug(object, "%s notify\n", name[suspend]);
for (i = 0; i < ARRAY_SIZE(client->notify); i++)
nvkm_client_notify_put(client, i);
return 0;
}
static void *
nvkm_client_dtor(struct nvkm_object *object)
{
struct nvkm_client *client = nvkm_client(object);
int i;
for (i = 0; i < ARRAY_SIZE(client->notify); i++)
nvkm_client_notify_del(client, i);
return client;
return nvkm_client(object);
}
static const struct nvkm_object_func
......@@ -283,9 +165,7 @@ nvkm_client = {
};
int
nvkm_client_new(const char *name, u64 device, const char *cfg,
const char *dbg,
int (*ntfy)(const void *, u32, const void *, u32),
nvkm_client_new(const char *name, u64 device, const char *cfg, const char *dbg,
int (*event)(u64, void *, u32), struct nvkm_client **pclient)
{
struct nvkm_oclass oclass = { .base = nvkm_uclient_sclass };
......@@ -300,7 +180,6 @@ nvkm_client_new(const char *name, u64 device, const char *cfg,
client->device = device;
client->debug = nvkm_dbgopt(dbg, "CLIENT");
client->objroot = RB_ROOT;
client->ntfy = ntfy;
client->event = event;
INIT_LIST_HEAD(&client->umem);
spin_lock_init(&client->lock);
......
......@@ -20,10 +20,9 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include <core/event.h>
#include <core/notify.h>
#include <core/subdev.h>
void
static void
nvkm_event_put(struct nvkm_event *event, u32 types, int index)
{
assert_spin_locked(&event->refs_lock);
......@@ -40,7 +39,7 @@ nvkm_event_put(struct nvkm_event *event, u32 types, int index)
}
}
void
static void
nvkm_event_get(struct nvkm_event *event, u32 types, int index)
{
assert_spin_locked(&event->refs_lock);
......@@ -171,8 +170,13 @@ void
nvkm_event_ntfy(struct nvkm_event *event, int id, u32 bits)
{
struct nvkm_event_ntfy *ntfy, *ntmp;
unsigned long flags;
if (!event->refs || WARN_ON(id >= event->index_nr))
return;
nvkm_trace(event->subdev, "event: ntfy %08x on %d\n", bits, id);
spin_lock_irqsave(&event->list_lock, flags);
list_for_each_entry_safe(ntfy, ntmp, &event->ntfy, head) {
if (ntfy->id == id && ntfy->bits & bits) {
......@@ -180,29 +184,7 @@ nvkm_event_ntfy(struct nvkm_event *event, int id, u32 bits)
ntfy->func(ntfy, ntfy->bits & bits);
}
}
}
void
nvkm_event_send(struct nvkm_event *event, u32 types, int index, void *data, u32 size)
{
struct nvkm_notify *notify;
unsigned long flags;
if (!event->refs || WARN_ON(index >= event->index_nr))
return;
spin_lock_irqsave(&event->list_lock, flags);
nvkm_event_ntfy(event, index, types);
list_for_each_entry(notify, &event->list, head) {
if (notify->index == index && (notify->types & types)) {
if (event->func->send) {
event->func->send(data, size, notify);
continue;
}
nvkm_notify_send(notify, data, size);
}
}
spin_unlock_irqrestore(&event->list_lock, flags);
}
......@@ -229,7 +211,6 @@ nvkm_event_init(const struct nvkm_event_func *func, struct nvkm_subdev *subdev,
event->index_nr = index_nr;
spin_lock_init(&event->refs_lock);
spin_lock_init(&event->list_lock);
INIT_LIST_HEAD(&event->list);
INIT_LIST_HEAD(&event->ntfy);
return 0;
}
......@@ -313,90 +313,6 @@ nvkm_ioctl_unmap(struct nvkm_client *client,
return ret;
}
static int
nvkm_ioctl_ntfy_new(struct nvkm_client *client,
struct nvkm_object *object, void *data, u32 size)
{
union {
struct nvif_ioctl_ntfy_new_v0 v0;
} *args = data;
struct nvkm_event *event;
int ret = -ENOSYS;
nvif_ioctl(object, "ntfy new size %d\n", size);
if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) {
nvif_ioctl(object, "ntfy new vers %d event %02x\n",
args->v0.version, args->v0.event);
ret = nvkm_object_ntfy(object, args->v0.event, &event);
if (ret == 0) {
ret = nvkm_client_notify_new(object, event, data, size);
if (ret >= 0) {
args->v0.index = ret;
ret = 0;
}
}
}
return ret;
}
static int
nvkm_ioctl_ntfy_del(struct nvkm_client *client,
struct nvkm_object *object, void *data, u32 size)
{
union {
struct nvif_ioctl_ntfy_del_v0 v0;
} *args = data;
int ret = -ENOSYS;
nvif_ioctl(object, "ntfy del size %d\n", size);
if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
nvif_ioctl(object, "ntfy del vers %d index %d\n",
args->v0.version, args->v0.index);
ret = nvkm_client_notify_del(client, args->v0.index);
}
return ret;
}
static int
nvkm_ioctl_ntfy_get(struct nvkm_client *client,
struct nvkm_object *object, void *data, u32 size)
{
union {
struct nvif_ioctl_ntfy_get_v0 v0;
} *args = data;
int ret = -ENOSYS;
nvif_ioctl(object, "ntfy get size %d\n", size);
if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
nvif_ioctl(object, "ntfy get vers %d index %d\n",
args->v0.version, args->v0.index);
ret = nvkm_client_notify_get(client, args->v0.index);
}
return ret;
}
static int
nvkm_ioctl_ntfy_put(struct nvkm_client *client,
struct nvkm_object *object, void *data, u32 size)
{
union {
struct nvif_ioctl_ntfy_put_v0 v0;
} *args = data;
int ret = -ENOSYS;
nvif_ioctl(object, "ntfy put size %d\n", size);
if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
nvif_ioctl(object, "ntfy put vers %d index %d\n",
args->v0.version, args->v0.index);
ret = nvkm_client_notify_put(client, args->v0.index);
}
return ret;
}
static struct {
int version;
int (*func)(struct nvkm_client *, struct nvkm_object *, void *, u32);
......@@ -411,10 +327,6 @@ nvkm_ioctl_v0[] = {
{ 0x00, nvkm_ioctl_wr },
{ 0x00, nvkm_ioctl_map },
{ 0x00, nvkm_ioctl_unmap },
{ 0x00, nvkm_ioctl_ntfy_new },
{ 0x00, nvkm_ioctl_ntfy_del },
{ 0x00, nvkm_ioctl_ntfy_get },
{ 0x00, nvkm_ioctl_ntfy_put },
};
static int
......
/*
* Copyright 2014 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs <bskeggs@redhat.com>
*/
#include <core/notify.h>
#include <core/event.h>
static inline void
nvkm_notify_put_locked(struct nvkm_notify *notify)
{
if (notify->block++ == 0)
nvkm_event_put(notify->event, notify->types, notify->index);
}
void
nvkm_notify_put(struct nvkm_notify *notify)
{
struct nvkm_event *event = notify->event;
unsigned long flags;
if (likely(event) &&
test_and_clear_bit(NVKM_NOTIFY_USER, &notify->flags)) {
spin_lock_irqsave(&event->refs_lock, flags);
nvkm_notify_put_locked(notify);
spin_unlock_irqrestore(&event->refs_lock, flags);
if (test_bit(NVKM_NOTIFY_WORK, &notify->flags))
flush_work(&notify->work);
}
}
static inline void
nvkm_notify_get_locked(struct nvkm_notify *notify)
{
if (--notify->block == 0)
nvkm_event_get(notify->event, notify->types, notify->index);
}
void
nvkm_notify_get(struct nvkm_notify *notify)
{
struct nvkm_event *event = notify->event;
unsigned long flags;
if (likely(event) &&
!test_and_set_bit(NVKM_NOTIFY_USER, &notify->flags)) {
spin_lock_irqsave(&event->refs_lock, flags);
nvkm_notify_get_locked(notify);
spin_unlock_irqrestore(&event->refs_lock, flags);
}
}
static inline void
nvkm_notify_func(struct nvkm_notify *notify)
{
struct nvkm_event *event = notify->event;
int ret = notify->func(notify);
unsigned long flags;
if ((ret == NVKM_NOTIFY_KEEP) ||
!test_and_clear_bit(NVKM_NOTIFY_USER, &notify->flags)) {
spin_lock_irqsave(&event->refs_lock, flags);
nvkm_notify_get_locked(notify);
spin_unlock_irqrestore(&event->refs_lock, flags);
}
}
static void
nvkm_notify_work(struct work_struct *work)
{
struct nvkm_notify *notify = container_of(work, typeof(*notify), work);
nvkm_notify_func(notify);
}
void
nvkm_notify_send(struct nvkm_notify *notify, void *data, u32 size)
{
struct nvkm_event *event = notify->event;
unsigned long flags;
assert_spin_locked(&event->list_lock);
BUG_ON(size != notify->size);
spin_lock_irqsave(&event->refs_lock, flags);
if (notify->block) {
spin_unlock_irqrestore(&event->refs_lock, flags);
return;
}
nvkm_notify_put_locked(notify);
spin_unlock_irqrestore(&event->refs_lock, flags);
if (test_bit(NVKM_NOTIFY_WORK, &notify->flags)) {
memcpy((void *)notify->data, data, size);
schedule_work(&notify->work);
} else {
notify->data = data;
nvkm_notify_func(notify);
notify->data = NULL;
}
}
void
nvkm_notify_fini(struct nvkm_notify *notify)
{
unsigned long flags;
if (notify->event) {
nvkm_notify_put(notify);
spin_lock_irqsave(&notify->event->list_lock, flags);
list_del(&notify->head);
spin_unlock_irqrestore(&notify->event->list_lock, flags);
kfree((void *)notify->data);
notify->event = NULL;
}
}
int
nvkm_notify_init(struct nvkm_object *object, struct nvkm_event *event,
int (*func)(struct nvkm_notify *), bool work,
void *data, u32 size, u32 reply,
struct nvkm_notify *notify)
{
unsigned long flags;
int ret = -ENODEV;
if ((notify->event = event), event->refs) {
ret = event->func->ctor(object, data, size, notify);
if (ret == 0 && (ret = -EINVAL, notify->size == reply)) {
notify->flags = 0;
notify->block = 1;
notify->func = func;
notify->data = NULL;
if (ret = 0, work) {
INIT_WORK(&notify->work, nvkm_notify_work);
set_bit(NVKM_NOTIFY_WORK, &notify->flags);
notify->data = kmalloc(reply, GFP_KERNEL);
if (!notify->data)
ret = -ENOMEM;
}
}
if (ret == 0) {
spin_lock_irqsave(&event->list_lock, flags);
list_add_tail(&notify->head, &event->list);
spin_unlock_irqrestore(&event->list_lock, flags);
}
}
if (ret)
notify->event = NULL;
return ret;
}
......@@ -65,7 +65,7 @@ nvkm_disp_vblank_func = {
void
nvkm_disp_vblank(struct nvkm_disp *disp, int head)
{
nvkm_event_send(&disp->vblank, NVKM_DISP_HEAD_EVENT_VBLANK, head, NULL, 0);
nvkm_event_ntfy(&disp->vblank, head, NVKM_DISP_HEAD_EVENT_VBLANK);
}
static int
......
......@@ -503,7 +503,7 @@ nv50_disp_chan_uevent_init(struct nvkm_event *event, int types, int index)
void
nv50_disp_chan_uevent_send(struct nvkm_disp *disp, int chid)
{
nvkm_event_send(&disp->uevent, NVKM_DISP_EVENT_CHAN_AWAKEN, chid, NULL, 0);
nvkm_event_ntfy(&disp->uevent, chid, NVKM_DISP_EVENT_CHAN_AWAKEN);
}
const struct nvkm_event_func
......
......@@ -121,7 +121,7 @@ nvkm_fifo_chan_chid(struct nvkm_fifo *fifo, int chid, unsigned long *rflags)
void
nvkm_fifo_kevent(struct nvkm_fifo *fifo, int chid)
{
nvkm_event_send(&fifo->kevent, NVKM_FIFO_EVENT_KILLED, chid, NULL, 0);
nvkm_event_ntfy(&fifo->kevent, chid, NVKM_FIFO_EVENT_KILLED);
}
static const struct nvkm_event_func
......@@ -151,7 +151,7 @@ nvkm_fifo_uevent_func = {
void
nvkm_fifo_uevent(struct nvkm_fifo *fifo)
{
nvkm_event_send(&fifo->uevent, NVKM_FIFO_EVENT_NON_STALL_INTR, 0, NULL, 0);
nvkm_event_ntfy(&fifo->uevent, 0, NVKM_FIFO_EVENT_NON_STALL_INTR);
}
static int
......
......@@ -35,7 +35,7 @@ nvkm_sw_chan_mthd(struct nvkm_sw_chan *chan, int subc, u32 mthd, u32 data)
case 0x0000:
return true;
case 0x0500:
nvkm_event_send(&chan->event, NVKM_SW_CHAN_EVENT_PAGE_FLIP, 0, NULL, 0);
nvkm_event_ntfy(&chan->event, 0, NVKM_SW_CHAN_EVENT_PAGE_FLIP);
return true;
default:
if (chan->func->mthd)
......
......@@ -65,7 +65,7 @@ gp100_fault_buffer_info(struct nvkm_fault_buffer *buffer)
void
gp100_fault_intr(struct nvkm_fault *fault)
{
nvkm_event_send(&fault->event, NVKM_FAULT_BUFFER_EVENT_PENDING, 0, NULL, 0);
nvkm_event_ntfy(&fault->event, 0, NVKM_FAULT_BUFFER_EVENT_PENDING);
}
static const struct nvkm_fault_func
......
......@@ -166,14 +166,14 @@ gv100_fault_intr(struct nvkm_fault *fault)
if (stat & 0x20000000) {
if (fault->buffer[0]) {
nvkm_event_send(&fault->event, NVKM_FAULT_BUFFER_EVENT_PENDING, 0, NULL, 0);
nvkm_event_ntfy(&fault->event, 0, NVKM_FAULT_BUFFER_EVENT_PENDING);
stat &= ~0x20000000;
}
}
if (stat & 0x08000000) {
if (fault->buffer[1]) {
nvkm_event_send(&fault->event, NVKM_FAULT_BUFFER_EVENT_PENDING, 1, NULL, 0);
nvkm_event_ntfy(&fault->event, 1, NVKM_FAULT_BUFFER_EVENT_PENDING);
stat &= ~0x08000000;
}
}
......
......@@ -126,7 +126,7 @@ tu102_fault_intr(struct nvkm_fault *fault)
nvkm_wr32(device, 0xb81010, 0x10);
if (fault->buffer[0]) {
nvkm_event_send(&fault->event, NVKM_FAULT_BUFFER_EVENT_PENDING, 0, NULL, 0);
nvkm_event_ntfy(&fault->event, 0, NVKM_FAULT_BUFFER_EVENT_PENDING);
stat &= ~0x00000200;
}
}
......@@ -137,7 +137,7 @@ tu102_fault_intr(struct nvkm_fault *fault)
nvkm_wr32(device, 0xb81008, 0x1);
if (fault->buffer[1]) {
nvkm_event_send(&fault->event, NVKM_FAULT_BUFFER_EVENT_PENDING, 1, NULL, 0);
nvkm_event_ntfy(&fault->event, 1, NVKM_FAULT_BUFFER_EVENT_PENDING);
stat &= ~0x00000100;
}
}
......
......@@ -139,7 +139,7 @@ nvkm_gpio_intr(struct nvkm_subdev *subdev)
for (i = 0; (hi | lo) && i < gpio->func->lines; i++) {
u32 mask = (NVKM_GPIO_HI * !!(hi & (1 << i))) |
(NVKM_GPIO_LO * !!(lo & (1 << i)));
nvkm_event_send(&gpio->event, mask, i, NULL, 0);
nvkm_event_ntfy(&gpio->event, i, mask);
}
}
......
......@@ -130,7 +130,7 @@ nvkm_i2c_intr(struct nvkm_subdev *subdev)
if (rq & aux->intr) mask |= NVKM_I2C_IRQ;
if (tx & aux->intr) mask |= NVKM_I2C_DONE;
if (mask)
nvkm_event_send(&i2c->event, mask, aux->id, NULL, 0);
nvkm_event_ntfy(&i2c->event, aux->id, mask);
}
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment