drm/nouveau/nvkm: rip out old notify
Signed-off-by: Ben Skeggs <bskeggs@redhat.com> Reviewed-by: Lyude Paul <lyude@redhat.com>
This commit is contained in:
parent
6c9705f684
commit
99d0701afd
|
@ -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 *);
|
void nvif_event_dtor(struct nvif_event *);
|
||||||
int nvif_event_allow(struct nvif_event *);
|
int nvif_event_allow(struct nvif_event *);
|
||||||
int nvif_event_block(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
|
#endif
|
||||||
|
|
|
@ -15,10 +15,6 @@ struct nvif_ioctl_v0 {
|
||||||
#define NVIF_IOCTL_V0_WR 0x06
|
#define NVIF_IOCTL_V0_WR 0x06
|
||||||
#define NVIF_IOCTL_V0_MAP 0x07
|
#define NVIF_IOCTL_V0_MAP 0x07
|
||||||
#define NVIF_IOCTL_V0_UNMAP 0x08
|
#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 type;
|
||||||
__u8 pad02[4];
|
__u8 pad02[4];
|
||||||
#define NVIF_IOCTL_V0_OWNER_NVIF 0x00
|
#define NVIF_IOCTL_V0_OWNER_NVIF 0x00
|
||||||
|
@ -63,6 +59,14 @@ struct nvif_ioctl_new_v0 {
|
||||||
struct nvif_ioctl_del {
|
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 {
|
struct nvif_ioctl_rd_v0 {
|
||||||
/* nvif_ioctl ... */
|
/* nvif_ioctl ... */
|
||||||
__u8 version;
|
__u8 version;
|
||||||
|
@ -95,43 +99,4 @@ struct nvif_ioctl_map_v0 {
|
||||||
|
|
||||||
struct nvif_ioctl_unmap {
|
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
|
#endif
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
/* 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;
|
u64 device;
|
||||||
u32 debug;
|
u32 debug;
|
||||||
|
|
||||||
struct nvkm_client_notify *notify[32];
|
|
||||||
struct rb_root objroot;
|
struct rb_root objroot;
|
||||||
|
|
||||||
void *data;
|
void *data;
|
||||||
int (*ntfy)(const void *, u32, const void *, u32);
|
|
||||||
int (*event)(u64 token, void *argv, u32 argc);
|
int (*event)(u64 token, void *argv, u32 argc);
|
||||||
|
|
||||||
struct list_head umem;
|
struct list_head umem;
|
||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
int nvkm_client_new(const char *name, u64 device, const char *cfg,
|
int nvkm_client_new(const char *name, u64 device, const char *cfg, const char *dbg,
|
||||||
const char *dbg,
|
int (*)(u64, void *, u32), struct nvkm_client **);
|
||||||
int (*)(const void *, u32, const void *, u32),
|
|
||||||
int (*)(u64, void *, u32),
|
|
||||||
struct nvkm_client **);
|
|
||||||
struct nvkm_client *nvkm_client_search(struct nvkm_client *, u64 handle);
|
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 */
|
/* logging for client-facing objects */
|
||||||
#define nvif_printk(o,l,p,f,a...) do { \
|
#define nvif_printk(o,l,p,f,a...) do { \
|
||||||
const struct nvkm_object *_object = (o); \
|
const struct nvkm_object *_object = (o); \
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
#ifndef __NVKM_EVENT_H__
|
#ifndef __NVKM_EVENT_H__
|
||||||
#define __NVKM_EVENT_H__
|
#define __NVKM_EVENT_H__
|
||||||
#include <core/os.h>
|
#include <core/os.h>
|
||||||
struct nvkm_notify;
|
|
||||||
struct nvkm_object;
|
struct nvkm_object;
|
||||||
struct nvkm_oclass;
|
struct nvkm_oclass;
|
||||||
struct nvkm_uevent;
|
struct nvkm_uevent;
|
||||||
|
@ -16,16 +15,12 @@ struct nvkm_event {
|
||||||
|
|
||||||
spinlock_t refs_lock;
|
spinlock_t refs_lock;
|
||||||
spinlock_t list_lock;
|
spinlock_t list_lock;
|
||||||
struct list_head list;
|
|
||||||
int *refs;
|
int *refs;
|
||||||
|
|
||||||
struct list_head ntfy;
|
struct list_head ntfy;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct nvkm_event_func {
|
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 (*init)(struct nvkm_event *, int type, int index);
|
||||||
void (*fini)(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 nvkm_event_init(const struct nvkm_event_func *func, struct nvkm_subdev *, int types_nr,
|
||||||
int index_nr, struct nvkm_event *);
|
int index_nr, struct nvkm_event *);
|
||||||
void nvkm_event_fini(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_KEEP 0
|
||||||
#define NVKM_EVENT_DROP 1
|
#define NVKM_EVENT_DROP 1
|
||||||
|
|
|
@ -1,39 +0,0 @@
|
||||||
/* 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,
|
NVDRM_OBJECT_ANY = NVIF_IOCTL_V0_OWNER_ANY,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum nouveau_drm_notify_route {
|
|
||||||
NVDRM_NOTIFY_NVIF = 0,
|
|
||||||
NVDRM_NOTIFY_USIF
|
|
||||||
};
|
|
||||||
|
|
||||||
enum nouveau_drm_handle {
|
enum nouveau_drm_handle {
|
||||||
NVDRM_CHAN = 0xcccc0000, /* |= client chid */
|
NVDRM_CHAN = 0xcccc0000, /* |= client chid */
|
||||||
NVDRM_NVSW = 0x55550000,
|
NVDRM_NVSW = 0x55550000,
|
||||||
|
|
|
@ -27,12 +27,10 @@
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#include <core/client.h>
|
#include <core/client.h>
|
||||||
#include <core/notify.h>
|
|
||||||
#include <core/ioctl.h>
|
#include <core/ioctl.h>
|
||||||
|
|
||||||
#include <nvif/client.h>
|
#include <nvif/client.h>
|
||||||
#include <nvif/driver.h>
|
#include <nvif/driver.h>
|
||||||
#include <nvif/notify.h>
|
|
||||||
#include <nvif/event.h>
|
#include <nvif/event.h>
|
||||||
#include <nvif/ioctl.h>
|
#include <nvif/ioctl.h>
|
||||||
|
|
||||||
|
@ -87,7 +85,7 @@ static int
|
||||||
nvkm_client_driver_init(const char *name, u64 device, const char *cfg,
|
nvkm_client_driver_init(const char *name, u64 device, const char *cfg,
|
||||||
const char *dbg, void **ppriv)
|
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);
|
(struct nvkm_client **)ppriv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -151,12 +151,6 @@ usif_ioctl(struct drm_file *filp, void __user *user, u32 argc)
|
||||||
case NVIF_IOCTL_V0_NEW:
|
case NVIF_IOCTL_V0_NEW:
|
||||||
ret = usif_object_new(filp, data, size, argv, argc, abi16);
|
ret = usif_object_new(filp, data, size, argv, argc, abi16);
|
||||||
break;
|
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:
|
default:
|
||||||
ret = nvif_client_ioctl(client, argv, argc);
|
ret = nvif_client_ioctl(client, argv, argc);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -10,7 +10,6 @@ nvif-y += nvif/fifo.o
|
||||||
nvif-y += nvif/head.o
|
nvif-y += nvif/head.o
|
||||||
nvif-y += nvif/mem.o
|
nvif-y += nvif/mem.o
|
||||||
nvif-y += nvif/mmu.o
|
nvif-y += nvif/mmu.o
|
||||||
nvif-y += nvif/notify.o
|
|
||||||
nvif-y += nvif/outp.o
|
nvif-y += nvif/outp.o
|
||||||
nvif-y += nvif/timer.o
|
nvif-y += nvif/timer.o
|
||||||
nvif-y += nvif/vmm.o
|
nvif-y += nvif/vmm.o
|
||||||
|
|
|
@ -1,210 +0,0 @@
|
||||||
/*
|
|
||||||
* 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(¬ify->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, ¬ify->flags)) {
|
|
||||||
int ret = nvif_notify_put_(notify);
|
|
||||||
if (test_bit(NVIF_NOTIFY_WORK, ¬ify->flags))
|
|
||||||
flush_work(¬ify->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(¬ify->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, ¬ify->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, ¬ify->flags)) {
|
|
||||||
if (!keep)
|
|
||||||
atomic_dec(¬ify->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(¬ify->putcnt);
|
|
||||||
if (test_bit(NVIF_NOTIFY_WORK, ¬ify->flags)) {
|
|
||||||
memcpy((void *)notify->data, data, size);
|
|
||||||
schedule_work(¬ify->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(¬ify->putcnt, 1);
|
|
||||||
notify->func = func;
|
|
||||||
notify->data = NULL;
|
|
||||||
notify->size = reply;
|
|
||||||
if (work) {
|
|
||||||
INIT_WORK(¬ify->work, nvif_notify_work);
|
|
||||||
set_bit(NVIF_NOTIFY_WORK, ¬ify->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/ioctl.o
|
||||||
nvkm-y += nvkm/core/memory.o
|
nvkm-y += nvkm/core/memory.o
|
||||||
nvkm-y += nvkm/core/mm.o
|
nvkm-y += nvkm/core/mm.o
|
||||||
nvkm-y += nvkm/core/notify.o
|
|
||||||
nvkm-y += nvkm/core/object.o
|
nvkm-y += nvkm/core/object.o
|
||||||
nvkm-y += nvkm/core/oproxy.o
|
nvkm-y += nvkm/core/oproxy.o
|
||||||
nvkm-y += nvkm/core/option.o
|
nvkm-y += nvkm/core/option.o
|
||||||
|
|
|
@ -23,7 +23,6 @@
|
||||||
*/
|
*/
|
||||||
#include <core/client.h>
|
#include <core/client.h>
|
||||||
#include <core/device.h>
|
#include <core/device.h>
|
||||||
#include <core/notify.h>
|
|
||||||
#include <core/option.h>
|
#include <core/option.h>
|
||||||
|
|
||||||
#include <nvif/class.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))){
|
if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))){
|
||||||
args->v0.name[sizeof(args->v0.name) - 1] = 0;
|
args->v0.name[sizeof(args->v0.name) - 1] = 0;
|
||||||
ret = nvkm_client_new(args->v0.name, args->v0.device, NULL,
|
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)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
} else
|
} else
|
||||||
|
@ -68,113 +67,6 @@ nvkm_uclient_sclass = {
|
||||||
.ctor = nvkm_uclient_new,
|
.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(¬ify->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, ¬ify->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;
|
static const struct nvkm_object_func nvkm_client;
|
||||||
struct nvkm_client *
|
struct nvkm_client *
|
||||||
nvkm_client_search(struct nvkm_client *client, u64 handle)
|
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
|
static int
|
||||||
nvkm_client_fini(struct nvkm_object *object, bool suspend)
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
nvkm_client_dtor(struct nvkm_object *object)
|
nvkm_client_dtor(struct nvkm_object *object)
|
||||||
{
|
{
|
||||||
struct nvkm_client *client = nvkm_client(object);
|
return nvkm_client(object);
|
||||||
int i;
|
|
||||||
for (i = 0; i < ARRAY_SIZE(client->notify); i++)
|
|
||||||
nvkm_client_notify_del(client, i);
|
|
||||||
return client;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct nvkm_object_func
|
static const struct nvkm_object_func
|
||||||
|
@ -283,9 +165,7 @@ nvkm_client = {
|
||||||
};
|
};
|
||||||
|
|
||||||
int
|
int
|
||||||
nvkm_client_new(const char *name, u64 device, const char *cfg,
|
nvkm_client_new(const char *name, u64 device, const char *cfg, const char *dbg,
|
||||||
const char *dbg,
|
|
||||||
int (*ntfy)(const void *, u32, const void *, u32),
|
|
||||||
int (*event)(u64, void *, u32), struct nvkm_client **pclient)
|
int (*event)(u64, void *, u32), struct nvkm_client **pclient)
|
||||||
{
|
{
|
||||||
struct nvkm_oclass oclass = { .base = nvkm_uclient_sclass };
|
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->device = device;
|
||||||
client->debug = nvkm_dbgopt(dbg, "CLIENT");
|
client->debug = nvkm_dbgopt(dbg, "CLIENT");
|
||||||
client->objroot = RB_ROOT;
|
client->objroot = RB_ROOT;
|
||||||
client->ntfy = ntfy;
|
|
||||||
client->event = event;
|
client->event = event;
|
||||||
INIT_LIST_HEAD(&client->umem);
|
INIT_LIST_HEAD(&client->umem);
|
||||||
spin_lock_init(&client->lock);
|
spin_lock_init(&client->lock);
|
||||||
|
|
|
@ -20,10 +20,9 @@
|
||||||
* OTHER DEALINGS IN THE SOFTWARE.
|
* OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
#include <core/event.h>
|
#include <core/event.h>
|
||||||
#include <core/notify.h>
|
|
||||||
#include <core/subdev.h>
|
#include <core/subdev.h>
|
||||||
|
|
||||||
void
|
static void
|
||||||
nvkm_event_put(struct nvkm_event *event, u32 types, int index)
|
nvkm_event_put(struct nvkm_event *event, u32 types, int index)
|
||||||
{
|
{
|
||||||
assert_spin_locked(&event->refs_lock);
|
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)
|
nvkm_event_get(struct nvkm_event *event, u32 types, int index)
|
||||||
{
|
{
|
||||||
assert_spin_locked(&event->refs_lock);
|
assert_spin_locked(&event->refs_lock);
|
||||||
|
@ -171,8 +170,13 @@ void
|
||||||
nvkm_event_ntfy(struct nvkm_event *event, int id, u32 bits)
|
nvkm_event_ntfy(struct nvkm_event *event, int id, u32 bits)
|
||||||
{
|
{
|
||||||
struct nvkm_event_ntfy *ntfy, *ntmp;
|
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);
|
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) {
|
list_for_each_entry_safe(ntfy, ntmp, &event->ntfy, head) {
|
||||||
if (ntfy->id == id && ntfy->bits & bits) {
|
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);
|
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);
|
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;
|
event->index_nr = index_nr;
|
||||||
spin_lock_init(&event->refs_lock);
|
spin_lock_init(&event->refs_lock);
|
||||||
spin_lock_init(&event->list_lock);
|
spin_lock_init(&event->list_lock);
|
||||||
INIT_LIST_HEAD(&event->list);
|
|
||||||
INIT_LIST_HEAD(&event->ntfy);
|
INIT_LIST_HEAD(&event->ntfy);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -313,90 +313,6 @@ nvkm_ioctl_unmap(struct nvkm_client *client,
|
||||||
return ret;
|
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 {
|
static struct {
|
||||||
int version;
|
int version;
|
||||||
int (*func)(struct nvkm_client *, struct nvkm_object *, void *, u32);
|
int (*func)(struct nvkm_client *, struct nvkm_object *, void *, u32);
|
||||||
|
@ -411,10 +327,6 @@ nvkm_ioctl_v0[] = {
|
||||||
{ 0x00, nvkm_ioctl_wr },
|
{ 0x00, nvkm_ioctl_wr },
|
||||||
{ 0x00, nvkm_ioctl_map },
|
{ 0x00, nvkm_ioctl_map },
|
||||||
{ 0x00, nvkm_ioctl_unmap },
|
{ 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
|
static int
|
||||||
|
|
|
@ -1,163 +0,0 @@
|
||||||
/*
|
|
||||||
* 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, ¬ify->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, ¬ify->flags))
|
|
||||||
flush_work(¬ify->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, ¬ify->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, ¬ify->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, ¬ify->flags)) {
|
|
||||||
memcpy((void *)notify->data, data, size);
|
|
||||||
schedule_work(¬ify->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(¬ify->event->list_lock, flags);
|
|
||||||
list_del(¬ify->head);
|
|
||||||
spin_unlock_irqrestore(¬ify->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(¬ify->work, nvkm_notify_work);
|
|
||||||
set_bit(NVKM_NOTIFY_WORK, ¬ify->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(¬ify->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
|
void
|
||||||
nvkm_disp_vblank(struct nvkm_disp *disp, int head)
|
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
|
static int
|
||||||
|
|
|
@ -503,7 +503,7 @@ nv50_disp_chan_uevent_init(struct nvkm_event *event, int types, int index)
|
||||||
void
|
void
|
||||||
nv50_disp_chan_uevent_send(struct nvkm_disp *disp, int chid)
|
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
|
const struct nvkm_event_func
|
||||||
|
|
|
@ -121,7 +121,7 @@ nvkm_fifo_chan_chid(struct nvkm_fifo *fifo, int chid, unsigned long *rflags)
|
||||||
void
|
void
|
||||||
nvkm_fifo_kevent(struct nvkm_fifo *fifo, int chid)
|
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
|
static const struct nvkm_event_func
|
||||||
|
@ -151,7 +151,7 @@ nvkm_fifo_uevent_func = {
|
||||||
void
|
void
|
||||||
nvkm_fifo_uevent(struct nvkm_fifo *fifo)
|
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
|
static int
|
||||||
|
|
|
@ -35,7 +35,7 @@ nvkm_sw_chan_mthd(struct nvkm_sw_chan *chan, int subc, u32 mthd, u32 data)
|
||||||
case 0x0000:
|
case 0x0000:
|
||||||
return true;
|
return true;
|
||||||
case 0x0500:
|
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;
|
return true;
|
||||||
default:
|
default:
|
||||||
if (chan->func->mthd)
|
if (chan->func->mthd)
|
||||||
|
|
|
@ -65,7 +65,7 @@ gp100_fault_buffer_info(struct nvkm_fault_buffer *buffer)
|
||||||
void
|
void
|
||||||
gp100_fault_intr(struct nvkm_fault *fault)
|
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
|
static const struct nvkm_fault_func
|
||||||
|
|
|
@ -166,14 +166,14 @@ gv100_fault_intr(struct nvkm_fault *fault)
|
||||||
|
|
||||||
if (stat & 0x20000000) {
|
if (stat & 0x20000000) {
|
||||||
if (fault->buffer[0]) {
|
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;
|
stat &= ~0x20000000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stat & 0x08000000) {
|
if (stat & 0x08000000) {
|
||||||
if (fault->buffer[1]) {
|
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;
|
stat &= ~0x08000000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,7 +126,7 @@ tu102_fault_intr(struct nvkm_fault *fault)
|
||||||
nvkm_wr32(device, 0xb81010, 0x10);
|
nvkm_wr32(device, 0xb81010, 0x10);
|
||||||
|
|
||||||
if (fault->buffer[0]) {
|
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;
|
stat &= ~0x00000200;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -137,7 +137,7 @@ tu102_fault_intr(struct nvkm_fault *fault)
|
||||||
nvkm_wr32(device, 0xb81008, 0x1);
|
nvkm_wr32(device, 0xb81008, 0x1);
|
||||||
|
|
||||||
if (fault->buffer[1]) {
|
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;
|
stat &= ~0x00000100;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -139,7 +139,7 @@ nvkm_gpio_intr(struct nvkm_subdev *subdev)
|
||||||
for (i = 0; (hi | lo) && i < gpio->func->lines; i++) {
|
for (i = 0; (hi | lo) && i < gpio->func->lines; i++) {
|
||||||
u32 mask = (NVKM_GPIO_HI * !!(hi & (1 << i))) |
|
u32 mask = (NVKM_GPIO_HI * !!(hi & (1 << i))) |
|
||||||
(NVKM_GPIO_LO * !!(lo & (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 (rq & aux->intr) mask |= NVKM_I2C_IRQ;
|
||||||
if (tx & aux->intr) mask |= NVKM_I2C_DONE;
|
if (tx & aux->intr) mask |= NVKM_I2C_DONE;
|
||||||
if (mask)
|
if (mask)
|
||||||
nvkm_event_send(&i2c->event, mask, aux->id, NULL, 0);
|
nvkm_event_ntfy(&i2c->event, aux->id, mask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue