Skip to content

Commit

Permalink
[SPARC64]: Add basic infrastructure for MD add/remove notification.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
David S. Miller committed Jul 18, 2007
1 parent cb32da0 commit 920c3ed
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 3 deletions.
78 changes: 75 additions & 3 deletions arch/sparc64/kernel/mdesc.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ static struct mdesc_handle *mdesc_kmalloc(unsigned int mdesc_size)
sizeof(struct mdesc_hdr) +
mdesc_size);

base = kmalloc(handle_size + 15, GFP_KERNEL);
base = kmalloc(handle_size + 15, GFP_KERNEL | __GFP_NOFAIL);
if (base) {
struct mdesc_handle *hp;
unsigned long addr;
Expand Down Expand Up @@ -214,18 +214,83 @@ void mdesc_release(struct mdesc_handle *hp)
}
EXPORT_SYMBOL(mdesc_release);

static DEFINE_MUTEX(mdesc_mutex);
static struct mdesc_notifier_client *client_list;

void mdesc_register_notifier(struct mdesc_notifier_client *client)
{
u64 node;

mutex_lock(&mdesc_mutex);
client->next = client_list;
client_list = client;

mdesc_for_each_node_by_name(cur_mdesc, node, client->node_name)
client->add(cur_mdesc, node);

mutex_unlock(&mdesc_mutex);
}

/* Run 'func' on nodes which are in A but not in B. */
static void invoke_on_missing(const char *name,
struct mdesc_handle *a,
struct mdesc_handle *b,
void (*func)(struct mdesc_handle *, u64))
{
u64 node;

mdesc_for_each_node_by_name(a, node, name) {
const u64 *id = mdesc_get_property(a, node, "id", NULL);
int found = 0;
u64 fnode;

mdesc_for_each_node_by_name(b, fnode, name) {
const u64 *fid = mdesc_get_property(b, fnode,
"id", NULL);

if (*id == *fid) {
found = 1;
break;
}
}
if (!found)
func(a, node);
}
}

static void notify_one(struct mdesc_notifier_client *p,
struct mdesc_handle *old_hp,
struct mdesc_handle *new_hp)
{
invoke_on_missing(p->node_name, old_hp, new_hp, p->remove);
invoke_on_missing(p->node_name, new_hp, old_hp, p->add);
}

static void mdesc_notify_clients(struct mdesc_handle *old_hp,
struct mdesc_handle *new_hp)
{
struct mdesc_notifier_client *p = client_list;

while (p) {
notify_one(p, old_hp, new_hp);
p = p->next;
}
}

void mdesc_update(void)
{
unsigned long len, real_len, status;
struct mdesc_handle *hp, *orig_hp;
unsigned long flags;

mutex_lock(&mdesc_mutex);

(void) sun4v_mach_desc(0UL, 0UL, &len);

hp = mdesc_alloc(len, &kmalloc_mdesc_memops);
if (!hp) {
printk(KERN_ERR "MD: mdesc alloc fails\n");
return;
goto out;
}

status = sun4v_mach_desc(__pa(&hp->mdesc), len, &real_len);
Expand All @@ -234,18 +299,25 @@ void mdesc_update(void)
status);
atomic_dec(&hp->refcnt);
mdesc_free(hp);
return;
goto out;
}

spin_lock_irqsave(&mdesc_lock, flags);
orig_hp = cur_mdesc;
cur_mdesc = hp;
spin_unlock_irqrestore(&mdesc_lock, flags);

mdesc_notify_clients(orig_hp, hp);

spin_lock_irqsave(&mdesc_lock, flags);
if (atomic_dec_and_test(&orig_hp->refcnt))
mdesc_free(orig_hp);
else
list_add(&orig_hp->list, &mdesc_zombie_list);
spin_unlock_irqrestore(&mdesc_lock, flags);

out:
mutex_unlock(&mdesc_mutex);
}

static struct mdesc_elem *node_block(struct mdesc_hdr *mdesc)
Expand Down
33 changes: 33 additions & 0 deletions arch/sparc64/kernel/vio.c
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,36 @@ struct device_node *cdev_node;
static struct vio_dev *root_vdev;
static u64 cdev_cfg_handle;

static void vio_add(struct mdesc_handle *hp, u64 node)
{
const char *name = mdesc_get_property(hp, node, "name", NULL);
const u64 *id = mdesc_get_property(hp, node, "id", NULL);

printk(KERN_ERR "VIO: Device add (%s) ID[%lx]\n",
name, *id);
}

static void vio_remove(struct mdesc_handle *hp, u64 node)
{
const char *name = mdesc_get_property(hp, node, "name", NULL);
const u64 *id = mdesc_get_property(hp, node, "id", NULL);

printk(KERN_ERR "VIO: Device remove (%s) ID[%lx]\n",
name, *id);
}

static struct mdesc_notifier_client vio_device_notifier = {
.add = vio_add,
.remove = vio_remove,
.node_name = "virtual-device-port",
};

static struct mdesc_notifier_client vio_ds_notifier = {
.add = vio_add,
.remove = vio_remove,
.node_name = "domain-services-port",
};

static void vio_fill_channel_info(struct mdesc_handle *hp, u64 mp,
struct vio_dev *vdev)
{
Expand Down Expand Up @@ -381,6 +411,9 @@ static int __init vio_init(void)

cdev_cfg_handle = *cfg_handle;

mdesc_register_notifier(&vio_device_notifier);
mdesc_register_notifier(&vio_ds_notifier);

create_devices(hp, root);

mdesc_release(hp);
Expand Down
10 changes: 10 additions & 0 deletions include/asm-sparc64/mdesc.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,16 @@ extern u64 mdesc_arc_target(struct mdesc_handle *hp, u64 arc);

extern void mdesc_update(void);

struct mdesc_notifier_client {
void (*add)(struct mdesc_handle *handle, u64 node);
void (*remove)(struct mdesc_handle *handle, u64 node);

const char *node_name;
struct mdesc_notifier_client *next;
};

extern void mdesc_register_notifier(struct mdesc_notifier_client *client);

extern void mdesc_fill_in_cpu_data(cpumask_t mask);

extern void sun4v_mdesc_init(void);
Expand Down

0 comments on commit 920c3ed

Please sign in to comment.