Skip to content

Commit 920c3ed

Browse files
author
David S. Miller
committed
[SPARC64]: Add basic infrastructure for MD add/remove notification.
And add dummy handlers for the VIO device layer. These will be filled in with real code after the vdc, vnet, and ds drivers are reworked to have simpler dependencies on the VIO device tree. Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent cb32da0 commit 920c3ed

File tree

3 files changed

+118
-3
lines changed

3 files changed

+118
-3
lines changed

arch/sparc64/kernel/mdesc.c

Lines changed: 75 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ static struct mdesc_handle *mdesc_kmalloc(unsigned int mdesc_size)
137137
sizeof(struct mdesc_hdr) +
138138
mdesc_size);
139139

140-
base = kmalloc(handle_size + 15, GFP_KERNEL);
140+
base = kmalloc(handle_size + 15, GFP_KERNEL | __GFP_NOFAIL);
141141
if (base) {
142142
struct mdesc_handle *hp;
143143
unsigned long addr;
@@ -214,18 +214,83 @@ void mdesc_release(struct mdesc_handle *hp)
214214
}
215215
EXPORT_SYMBOL(mdesc_release);
216216

217+
static DEFINE_MUTEX(mdesc_mutex);
218+
static struct mdesc_notifier_client *client_list;
219+
220+
void mdesc_register_notifier(struct mdesc_notifier_client *client)
221+
{
222+
u64 node;
223+
224+
mutex_lock(&mdesc_mutex);
225+
client->next = client_list;
226+
client_list = client;
227+
228+
mdesc_for_each_node_by_name(cur_mdesc, node, client->node_name)
229+
client->add(cur_mdesc, node);
230+
231+
mutex_unlock(&mdesc_mutex);
232+
}
233+
234+
/* Run 'func' on nodes which are in A but not in B. */
235+
static void invoke_on_missing(const char *name,
236+
struct mdesc_handle *a,
237+
struct mdesc_handle *b,
238+
void (*func)(struct mdesc_handle *, u64))
239+
{
240+
u64 node;
241+
242+
mdesc_for_each_node_by_name(a, node, name) {
243+
const u64 *id = mdesc_get_property(a, node, "id", NULL);
244+
int found = 0;
245+
u64 fnode;
246+
247+
mdesc_for_each_node_by_name(b, fnode, name) {
248+
const u64 *fid = mdesc_get_property(b, fnode,
249+
"id", NULL);
250+
251+
if (*id == *fid) {
252+
found = 1;
253+
break;
254+
}
255+
}
256+
if (!found)
257+
func(a, node);
258+
}
259+
}
260+
261+
static void notify_one(struct mdesc_notifier_client *p,
262+
struct mdesc_handle *old_hp,
263+
struct mdesc_handle *new_hp)
264+
{
265+
invoke_on_missing(p->node_name, old_hp, new_hp, p->remove);
266+
invoke_on_missing(p->node_name, new_hp, old_hp, p->add);
267+
}
268+
269+
static void mdesc_notify_clients(struct mdesc_handle *old_hp,
270+
struct mdesc_handle *new_hp)
271+
{
272+
struct mdesc_notifier_client *p = client_list;
273+
274+
while (p) {
275+
notify_one(p, old_hp, new_hp);
276+
p = p->next;
277+
}
278+
}
279+
217280
void mdesc_update(void)
218281
{
219282
unsigned long len, real_len, status;
220283
struct mdesc_handle *hp, *orig_hp;
221284
unsigned long flags;
222285

286+
mutex_lock(&mdesc_mutex);
287+
223288
(void) sun4v_mach_desc(0UL, 0UL, &len);
224289

225290
hp = mdesc_alloc(len, &kmalloc_mdesc_memops);
226291
if (!hp) {
227292
printk(KERN_ERR "MD: mdesc alloc fails\n");
228-
return;
293+
goto out;
229294
}
230295

231296
status = sun4v_mach_desc(__pa(&hp->mdesc), len, &real_len);
@@ -234,18 +299,25 @@ void mdesc_update(void)
234299
status);
235300
atomic_dec(&hp->refcnt);
236301
mdesc_free(hp);
237-
return;
302+
goto out;
238303
}
239304

240305
spin_lock_irqsave(&mdesc_lock, flags);
241306
orig_hp = cur_mdesc;
242307
cur_mdesc = hp;
308+
spin_unlock_irqrestore(&mdesc_lock, flags);
243309

310+
mdesc_notify_clients(orig_hp, hp);
311+
312+
spin_lock_irqsave(&mdesc_lock, flags);
244313
if (atomic_dec_and_test(&orig_hp->refcnt))
245314
mdesc_free(orig_hp);
246315
else
247316
list_add(&orig_hp->list, &mdesc_zombie_list);
248317
spin_unlock_irqrestore(&mdesc_lock, flags);
318+
319+
out:
320+
mutex_unlock(&mdesc_mutex);
249321
}
250322

251323
static struct mdesc_elem *node_block(struct mdesc_hdr *mdesc)

arch/sparc64/kernel/vio.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,36 @@ struct device_node *cdev_node;
172172
static struct vio_dev *root_vdev;
173173
static u64 cdev_cfg_handle;
174174

175+
static void vio_add(struct mdesc_handle *hp, u64 node)
176+
{
177+
const char *name = mdesc_get_property(hp, node, "name", NULL);
178+
const u64 *id = mdesc_get_property(hp, node, "id", NULL);
179+
180+
printk(KERN_ERR "VIO: Device add (%s) ID[%lx]\n",
181+
name, *id);
182+
}
183+
184+
static void vio_remove(struct mdesc_handle *hp, u64 node)
185+
{
186+
const char *name = mdesc_get_property(hp, node, "name", NULL);
187+
const u64 *id = mdesc_get_property(hp, node, "id", NULL);
188+
189+
printk(KERN_ERR "VIO: Device remove (%s) ID[%lx]\n",
190+
name, *id);
191+
}
192+
193+
static struct mdesc_notifier_client vio_device_notifier = {
194+
.add = vio_add,
195+
.remove = vio_remove,
196+
.node_name = "virtual-device-port",
197+
};
198+
199+
static struct mdesc_notifier_client vio_ds_notifier = {
200+
.add = vio_add,
201+
.remove = vio_remove,
202+
.node_name = "domain-services-port",
203+
};
204+
175205
static void vio_fill_channel_info(struct mdesc_handle *hp, u64 mp,
176206
struct vio_dev *vdev)
177207
{
@@ -381,6 +411,9 @@ static int __init vio_init(void)
381411

382412
cdev_cfg_handle = *cfg_handle;
383413

414+
mdesc_register_notifier(&vio_device_notifier);
415+
mdesc_register_notifier(&vio_ds_notifier);
416+
384417
create_devices(hp, root);
385418

386419
mdesc_release(hp);

include/asm-sparc64/mdesc.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,16 @@ extern u64 mdesc_arc_target(struct mdesc_handle *hp, u64 arc);
6161

6262
extern void mdesc_update(void);
6363

64+
struct mdesc_notifier_client {
65+
void (*add)(struct mdesc_handle *handle, u64 node);
66+
void (*remove)(struct mdesc_handle *handle, u64 node);
67+
68+
const char *node_name;
69+
struct mdesc_notifier_client *next;
70+
};
71+
72+
extern void mdesc_register_notifier(struct mdesc_notifier_client *client);
73+
6474
extern void mdesc_fill_in_cpu_data(cpumask_t mask);
6575

6676
extern void sun4v_mdesc_init(void);

0 commit comments

Comments
 (0)