xref: /openbsd-src/sys/dev/pci/drm/drm_managed.c (revision ad8b1aafbcc34f7eb86e4ebfd874be286017954b)
1*ad8b1aafSjsg /* Public domain. */
2*ad8b1aafSjsg 
3*ad8b1aafSjsg #include <linux/kernel.h>
4*ad8b1aafSjsg #include <linux/slab.h>
5*ad8b1aafSjsg #include <linux/string.h>
6*ad8b1aafSjsg #include <linux/list.h>
7*ad8b1aafSjsg 
8*ad8b1aafSjsg #include <drm/drm_device.h>
9*ad8b1aafSjsg #include <drm/drm_managed.h>
10*ad8b1aafSjsg 
11*ad8b1aafSjsg struct drmm_node {
12*ad8b1aafSjsg 	void *p;
13*ad8b1aafSjsg 	size_t size;
14*ad8b1aafSjsg 	drmm_func_t func;
15*ad8b1aafSjsg 	struct list_head list;
16*ad8b1aafSjsg };
17*ad8b1aafSjsg 
18*ad8b1aafSjsg void *
drmm_kzalloc(struct drm_device * dev,size_t size,int flags)19*ad8b1aafSjsg drmm_kzalloc(struct drm_device *dev, size_t size, int flags)
20*ad8b1aafSjsg {
21*ad8b1aafSjsg 	void *p;
22*ad8b1aafSjsg 	struct drmm_node *node = malloc(sizeof(*node), M_DRM, flags | M_ZERO);
23*ad8b1aafSjsg 	if (node == NULL)
24*ad8b1aafSjsg 		return NULL;
25*ad8b1aafSjsg 	p = kzalloc(size, flags);
26*ad8b1aafSjsg 	if (p == NULL) {
27*ad8b1aafSjsg 		free(node, M_DRM, sizeof(*node));
28*ad8b1aafSjsg 		return NULL;
29*ad8b1aafSjsg 	}
30*ad8b1aafSjsg 	INIT_LIST_HEAD(&node->list);
31*ad8b1aafSjsg 	node->p = p;
32*ad8b1aafSjsg 	node->size = size;
33*ad8b1aafSjsg 	mtx_enter(&dev->managed.lock);
34*ad8b1aafSjsg 	list_add(&node->list, &dev->managed.resources);
35*ad8b1aafSjsg 	mtx_leave(&dev->managed.lock);
36*ad8b1aafSjsg 	return p;
37*ad8b1aafSjsg }
38*ad8b1aafSjsg 
39*ad8b1aafSjsg void *
drmm_kcalloc(struct drm_device * dev,size_t n,size_t size,int flags)40*ad8b1aafSjsg drmm_kcalloc(struct drm_device *dev, size_t n, size_t size, int flags)
41*ad8b1aafSjsg {
42*ad8b1aafSjsg 	void *p;
43*ad8b1aafSjsg 	struct drmm_node *node = malloc(sizeof(*node), M_DRM, flags | M_ZERO);
44*ad8b1aafSjsg 	if (node == NULL)
45*ad8b1aafSjsg 		return NULL;
46*ad8b1aafSjsg 	p = kcalloc(n, size, flags);
47*ad8b1aafSjsg 	if (p == NULL) {
48*ad8b1aafSjsg 		free(node, M_DRM, sizeof(*node));
49*ad8b1aafSjsg 		return NULL;
50*ad8b1aafSjsg 	}
51*ad8b1aafSjsg 	INIT_LIST_HEAD(&node->list);
52*ad8b1aafSjsg 	node->p = p;
53*ad8b1aafSjsg 	node->size = n * size;
54*ad8b1aafSjsg 	mtx_enter(&dev->managed.lock);
55*ad8b1aafSjsg 	list_add(&node->list, &dev->managed.resources);
56*ad8b1aafSjsg 	mtx_leave(&dev->managed.lock);
57*ad8b1aafSjsg 	return p;
58*ad8b1aafSjsg }
59*ad8b1aafSjsg 
60*ad8b1aafSjsg char *
drmm_kstrdup(struct drm_device * dev,const char * s,int flags)61*ad8b1aafSjsg drmm_kstrdup(struct drm_device *dev, const char *s, int flags)
62*ad8b1aafSjsg {
63*ad8b1aafSjsg 	char *p;
64*ad8b1aafSjsg 	struct drmm_node *node = malloc(sizeof(*node), M_DRM, flags | M_ZERO);
65*ad8b1aafSjsg 	if (node == NULL)
66*ad8b1aafSjsg 		return NULL;
67*ad8b1aafSjsg 	p = kstrdup(s, flags);
68*ad8b1aafSjsg 	if (p == NULL) {
69*ad8b1aafSjsg 		free(node, M_DRM, sizeof(*node));
70*ad8b1aafSjsg 		return NULL;
71*ad8b1aafSjsg 	}
72*ad8b1aafSjsg 	INIT_LIST_HEAD(&node->list);
73*ad8b1aafSjsg 	node->p = p;
74*ad8b1aafSjsg 	node->size = strlen(s) + 1;
75*ad8b1aafSjsg 	mtx_enter(&dev->managed.lock);
76*ad8b1aafSjsg 	list_add(&node->list, &dev->managed.resources);
77*ad8b1aafSjsg 	mtx_leave(&dev->managed.lock);
78*ad8b1aafSjsg 	return p;
79*ad8b1aafSjsg }
80*ad8b1aafSjsg 
81*ad8b1aafSjsg void
drmm_kfree(struct drm_device * dev,void * p)82*ad8b1aafSjsg drmm_kfree(struct drm_device *dev, void *p)
83*ad8b1aafSjsg {
84*ad8b1aafSjsg 	struct drmm_node *n, *m = NULL;
85*ad8b1aafSjsg 
86*ad8b1aafSjsg 	if (p == NULL)
87*ad8b1aafSjsg 		return;
88*ad8b1aafSjsg 
89*ad8b1aafSjsg 	mtx_enter(&dev->managed.lock);
90*ad8b1aafSjsg 	list_for_each_entry(n, &dev->managed.resources, list) {
91*ad8b1aafSjsg 		if (n->p == p) {
92*ad8b1aafSjsg 			list_del(&n->list);
93*ad8b1aafSjsg 			m = n;
94*ad8b1aafSjsg 			break;
95*ad8b1aafSjsg 		}
96*ad8b1aafSjsg 	}
97*ad8b1aafSjsg 	mtx_leave(&dev->managed.lock);
98*ad8b1aafSjsg 
99*ad8b1aafSjsg 	if (m != NULL) {
100*ad8b1aafSjsg 		free(m->p, M_DRM, m->size);
101*ad8b1aafSjsg 		free(m, M_DRM, sizeof(*m));
102*ad8b1aafSjsg 	}
103*ad8b1aafSjsg }
104*ad8b1aafSjsg 
105*ad8b1aafSjsg int
drmm_add_action(struct drm_device * dev,drmm_func_t f,void * cookie)106*ad8b1aafSjsg drmm_add_action(struct drm_device *dev, drmm_func_t f, void *cookie)
107*ad8b1aafSjsg {
108*ad8b1aafSjsg 	struct drmm_node *node = malloc(sizeof(*node), M_DRM, M_WAITOK | M_ZERO);
109*ad8b1aafSjsg 	if (node == NULL)
110*ad8b1aafSjsg 		return -ENOMEM;
111*ad8b1aafSjsg 	INIT_LIST_HEAD(&node->list);
112*ad8b1aafSjsg 	node->func = f;
113*ad8b1aafSjsg 	node->p = cookie;
114*ad8b1aafSjsg 	mtx_enter(&dev->managed.lock);
115*ad8b1aafSjsg 	list_add(&node->list, &dev->managed.resources);
116*ad8b1aafSjsg 	mtx_leave(&dev->managed.lock);
117*ad8b1aafSjsg 
118*ad8b1aafSjsg 	return 0;
119*ad8b1aafSjsg }
120*ad8b1aafSjsg 
121*ad8b1aafSjsg int
drmm_add_action_or_reset(struct drm_device * dev,drmm_func_t f,void * cookie)122*ad8b1aafSjsg drmm_add_action_or_reset(struct drm_device *dev, drmm_func_t f, void *cookie)
123*ad8b1aafSjsg {
124*ad8b1aafSjsg 	struct drmm_node *node = malloc(sizeof(*node), M_DRM, M_WAITOK | M_ZERO);
125*ad8b1aafSjsg 	if (node == NULL) {
126*ad8b1aafSjsg 		f(dev, cookie);
127*ad8b1aafSjsg 		return -ENOMEM;
128*ad8b1aafSjsg 	}
129*ad8b1aafSjsg 	INIT_LIST_HEAD(&node->list);
130*ad8b1aafSjsg 	node->func = f;
131*ad8b1aafSjsg 	node->p = cookie;
132*ad8b1aafSjsg 	mtx_enter(&dev->managed.lock);
133*ad8b1aafSjsg 	list_add(&node->list, &dev->managed.resources);
134*ad8b1aafSjsg 	mtx_leave(&dev->managed.lock);
135*ad8b1aafSjsg 
136*ad8b1aafSjsg 	return 0;
137*ad8b1aafSjsg }
138*ad8b1aafSjsg 
139*ad8b1aafSjsg void
drm_managed_release(struct drm_device * dev)140*ad8b1aafSjsg drm_managed_release(struct drm_device *dev)
141*ad8b1aafSjsg {
142*ad8b1aafSjsg 	struct drmm_node *n, *t;
143*ad8b1aafSjsg 	list_for_each_entry_safe(n, t, &dev->managed.resources, list) {
144*ad8b1aafSjsg 		list_del(&n->list);
145*ad8b1aafSjsg 		if (n->func)
146*ad8b1aafSjsg 			n->func(dev, n->p);
147*ad8b1aafSjsg 		else
148*ad8b1aafSjsg 			free(n->p, M_DRM, n->size);
149*ad8b1aafSjsg 		free(n, M_DRM, sizeof(*n));
150*ad8b1aafSjsg 	}
151*ad8b1aafSjsg }
152*ad8b1aafSjsg 
153*ad8b1aafSjsg void
drmm_add_final_kfree(struct drm_device * dev,void * p)154*ad8b1aafSjsg drmm_add_final_kfree(struct drm_device *dev, void *p)
155*ad8b1aafSjsg {
156*ad8b1aafSjsg 	dev->managed.final_kfree = p;
157*ad8b1aafSjsg }
158