From 4ec0e02a89c790a967d6b9632019776c72e4d160 Mon Sep 17 00:00:00 2001 From: NAKAMURA Gou Date: Fri, 26 Feb 2016 18:30:03 +0900 Subject: [PATCH] sysfs: add snooping ops --- executer/kernel/mcctrl/sysfs.c | 432 ++++++++++++++++++++++++++++- executer/kernel/mcctrl/sysfs.h | 23 ++ executer/kernel/mcctrl/sysfs_msg.h | 12 + kernel/include/sysfs.h | 23 ++ kernel/include/sysfs_msg.h | 12 + kernel/sysfs.c | 40 +++ 6 files changed, 539 insertions(+), 3 deletions(-) diff --git a/executer/kernel/mcctrl/sysfs.c b/executer/kernel/mcctrl/sysfs.c index 8c083e96..b446864a 100644 --- a/executer/kernel/mcctrl/sysfs.c +++ b/executer/kernel/mcctrl/sysfs.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "mcctrl.h" #include "sysfs_msg.h" @@ -65,6 +66,20 @@ static struct kobj_type the_ktype; static struct sysfsm_ops remote_ops; static struct sysfsm_ops local_ops; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,0,0) +static inline int +bitmap_scnprintf(char *buf, unsigned buflen, const unsigned long *maskp, int nmaskbits) +{ + return scnprintf(buf, buflen, "%*pb\n", nmaskbits, maskp); +} /* bitmap_scnprintf() */ + +static inline int +bitmap_scnlistprintf(char *buf, unsigned buflen, const unsigned long *maskp, int nmaskbits) +{ + return scnprintf(buf, buflen, "%*pbl\n", nmaskbits, maskp); +} /* bitmap_scnlistprintf() */ +#endif + static ssize_t remote_show(struct sysfsm_ops *ops, void *instance, void *buf, size_t bufsize) { @@ -1318,6 +1333,247 @@ out: return error; } /* sysfsm_setup() */ +/*********************************************************************** + * remote snooping + */ +struct remote_snooping_param { + ihk_device_t dev; + int nbits; + int size; + long phys; + void *ptr; +}; + +static void cleanup_special_remote_create(struct sysfsm_ops *ops, void *instance) +{ + struct sysfsm_node *np = instance; + struct remote_snooping_param *param = (void *)np->client_instance; + + ihk_device_unmap_virtual(param->dev, param->ptr, param->size); + ihk_device_unmap_memory(param->dev, param->phys, param->size); + kfree(param); + return; +} /* cleanup_special_remote_create() */ + +/**** remote int ****/ +static ssize_t snooping_remote_show_d32(struct sysfsm_ops *ops, void *instance, void *buf, size_t bufsize) +{ + struct sysfsm_node *np = instance; + struct remote_snooping_param *p = (void *)np->client_instance; + + return sprintf(buf, "%d\n", *(int *)p->ptr); +} /* snooping_remote_show_d32() */ + +static struct sysfsm_ops snooping_remote_ops_d32 = { + .show = &snooping_remote_show_d32, + .release = &cleanup_special_remote_create, +}; + +/**** remote long ****/ +static ssize_t snooping_remote_show_d64(struct sysfsm_ops *ops, void *instance, void *buf, size_t bufsize) +{ + struct sysfsm_node *np = instance; + struct remote_snooping_param *p = (void *)np->client_instance; + + return sprintf(buf, "%ld\n", *(long *)p->ptr); +} /* snooping_remote_show_d64() */ + +static struct sysfsm_ops snooping_remote_ops_d64 = { + .show = &snooping_remote_show_d64, + .release = &cleanup_special_remote_create, +}; + +/**** remote unsigned int ****/ +static ssize_t snooping_remote_show_u32(struct sysfsm_ops *ops, void *instance, void *buf, size_t bufsize) +{ + struct sysfsm_node *np = instance; + struct remote_snooping_param *p = (void *)np->client_instance; + + return sprintf(buf, "%u\n", *(unsigned *)p->ptr); +} /* snooping_remote_show_u32() */ + +static struct sysfsm_ops snooping_remote_ops_u32 = { + .show = &snooping_remote_show_u32, + .release = &cleanup_special_remote_create, +}; + +/**** remote unsigned long ****/ +static ssize_t snooping_remote_show_u64(struct sysfsm_ops *ops, void *instance, void *buf, size_t bufsize) +{ + struct sysfsm_node *np = instance; + struct remote_snooping_param *p = (void *)np->client_instance; + + return sprintf(buf, "%lu\n", *(unsigned long *)p->ptr); +} /* snooping_remote_show_u64() */ + +static struct sysfsm_ops snooping_remote_ops_u64 = { + .show = &snooping_remote_show_u64, + .release = &cleanup_special_remote_create, +}; + +/**** remote string ****/ +static ssize_t snooping_remote_show_s(struct sysfsm_ops *ops, void *instance, void *buf, size_t bufsize) +{ + struct sysfsm_node *np = instance; + struct remote_snooping_param *p = (void *)np->client_instance; + + return sprintf(buf, "%.*s\n", (int)p->size, (char *)p->ptr); +} /* snooping_remote_show_s() */ + +static struct sysfsm_ops snooping_remote_ops_s = { + .show = &snooping_remote_show_s, + .release = &cleanup_special_remote_create, +}; + +/**** remote list ****/ +static ssize_t snooping_remote_show_pbl(struct sysfsm_ops *ops, void *instance, void *buf, size_t bufsize) +{ + struct sysfsm_node *np = instance; + struct remote_snooping_param *p = (void *)np->client_instance; + + return bitmap_scnlistprintf(buf, bufsize, p->ptr, p->nbits); +} /* snooping_remote_show_pbl() */ + +static struct sysfsm_ops snooping_remote_ops_pbl = { + .show = &snooping_remote_show_pbl, + .release = &cleanup_special_remote_create, +}; + +/**** remote map ****/ +static ssize_t snooping_remote_show_pb(struct sysfsm_ops *ops, void *instance, void *buf, size_t bufsize) +{ + struct sysfsm_node *np = instance; + struct remote_snooping_param *p = (void *)np->client_instance; + + return bitmap_scnprintf(buf, bufsize, p->ptr, p->nbits); +} /* snooping_remote_show_pb() */ + +static struct sysfsm_ops snooping_remote_ops_pb = { + .show = &snooping_remote_show_pb, + .release = &cleanup_special_remote_create, +}; + +/**** remote K unsigned int ****/ +static ssize_t snooping_remote_show_u32K(struct sysfsm_ops *ops, void *instance, void *buf, size_t bufsize) +{ + struct sysfsm_node *np = instance; + struct remote_snooping_param *p = (void *)np->client_instance; + + return sprintf(buf, "%uK\n", (*(unsigned *)p->ptr >> 10)); +} /* snooping_remote_show_u32K() */ + +static struct sysfsm_ops snooping_remote_ops_u32K = { + .show = &snooping_remote_show_u32K, + .release = &cleanup_special_remote_create, +}; + +struct sysfsm_ops * const remote_snooping_ops_table[] = { + [(long)SYSFS_SNOOPING_OPS_d32] = &snooping_remote_ops_d32, + [(long)SYSFS_SNOOPING_OPS_d64] = &snooping_remote_ops_d64, + [(long)SYSFS_SNOOPING_OPS_u32] = &snooping_remote_ops_u32, + [(long)SYSFS_SNOOPING_OPS_u64] = &snooping_remote_ops_u64, + [(long)SYSFS_SNOOPING_OPS_s] = &snooping_remote_ops_s, + [(long)SYSFS_SNOOPING_OPS_pbl] = &snooping_remote_ops_pbl, + [(long)SYSFS_SNOOPING_OPS_pb] = &snooping_remote_ops_pb, + [(long)SYSFS_SNOOPING_OPS_u32K] = &snooping_remote_ops_u32K, +}; + +static int setup_special_remote_create(ihk_device_t dev, const struct sysfs_req_create_param *param, struct sysfsm_ops **mopsp, long *cinstancep) +{ + int error; + struct remote_snooping_param *rsp = NULL; + long phys = -1; + struct sysfsm_bitmap_param *pbp = NULL; + long rpa; + + switch (param->client_ops) { + case (long)SYSFS_SNOOPING_OPS_d32: + case (long)SYSFS_SNOOPING_OPS_d64: + case (long)SYSFS_SNOOPING_OPS_u32: + case (long)SYSFS_SNOOPING_OPS_u64: + case (long)SYSFS_SNOOPING_OPS_s: + case (long)SYSFS_SNOOPING_OPS_pbl: + case (long)SYSFS_SNOOPING_OPS_pb: + case (long)SYSFS_SNOOPING_OPS_u32K: + break; + + default: + eprintk("mcctrl:setup_special_remote_create:unknown ops %#lx\n", param->client_ops); + return -EINVAL; + } + + rsp = kmalloc(sizeof(*rsp), GFP_KERNEL); + if (!rsp) { + eprintk("mcctrl:setup_special_remote_create:kmalloc failed.\n"); + return -ENOMEM; + } + + switch (param->client_ops) { + case (long)SYSFS_SNOOPING_OPS_s: + case (long)SYSFS_SNOOPING_OPS_pbl: + case (long)SYSFS_SNOOPING_OPS_pb: + phys = ihk_device_map_memory(dev, *cinstancep, sizeof(*pbp)); + pbp = ihk_device_map_virtual(dev, phys, sizeof(*pbp), NULL, 0); + break; + } + + rsp->dev = dev; + + switch (param->client_ops) { + case (long)SYSFS_SNOOPING_OPS_d32: + rsp->size = sizeof(int); + rpa = *cinstancep; + break; + + case (long)SYSFS_SNOOPING_OPS_d64: + rsp->size = sizeof(long); + rpa = *cinstancep; + break; + + case (long)SYSFS_SNOOPING_OPS_u32: + case (long)SYSFS_SNOOPING_OPS_u32K: + rsp->size = sizeof(unsigned); + rpa = *cinstancep; + break; + + case (long)SYSFS_SNOOPING_OPS_u64: + rsp->size = sizeof(unsigned long); + rpa = *cinstancep; + break; + + case (long)SYSFS_SNOOPING_OPS_s: + case (long)SYSFS_SNOOPING_OPS_pbl: + case (long)SYSFS_SNOOPING_OPS_pb: + rsp->nbits = pbp->nbits; + rsp->size = (rsp->nbits + 7) / 8; /* how many bytes */ + rpa = (long)pbp->ptr; + break; + + default: + BUG(); + } + + rsp->phys = ihk_device_map_memory(dev, rpa, rsp->size); + rsp->ptr = ihk_device_map_virtual(dev, rsp->phys, rsp->size, NULL, 0); + + error = 0; + *mopsp = remote_snooping_ops_table[param->client_ops]; + *cinstancep = (long)rsp; + rsp = NULL; + +#if 0 +out: +#endif + if (pbp) { + ihk_device_unmap_virtual(dev, pbp, sizeof(*pbp)); + ihk_device_unmap_memory(dev, phys, sizeof(*pbp)); + } + if (rsp) { + kfree(rsp); + } + return error; +} /* setup_special_remote_create() */ + static void sysfsm_req_setup(void *os, long param_rpa) { @@ -1358,14 +1614,28 @@ sysfsm_req_create(void *os, long param_rpa) struct sysfs_req_create_param *param; struct sysfsm_node *np; struct mcctrl_usrdata *udp = ihk_host_os_get_usrdata(os); + struct sysfsm_ops *ops; + long cinstance; param_pa = ihk_device_map_memory(dev, param_rpa, sizeof(*param)); param = ihk_device_map_virtual(dev, param_pa, sizeof(*param), NULL, 0); + ops = &remote_ops; + cinstance = param->client_instance; + if (is_special_sysfs_ops((void *)param->client_ops)) { + error = setup_special_remote_create(dev, param, &ops, &cinstance); + if (error) { + goto out; + } + } + np = sysfsm_create(&udp->sysfsm_data, param->path, param->mode, - &remote_ops, param->client_ops, param->client_instance); + ops, param->client_ops, cinstance); if (IS_ERR(np)) { error = PTR_ERR(np); + if (is_special_sysfs_ops((void *)param->client_ops)) { + cleanup_special_remote_create(ops, (void *)cinstance); + } goto out; } @@ -1761,6 +2031,145 @@ static struct sysfsm_ops local_ops = { .release = &local_release, }; +/*********************************************************************** + * local snooping + */ +static void cleanup_special_local_create(struct sysfsm_ops *ops, void *instance) +{ + kfree(instance); + return; +} /* cleanup_special_local_create() */ + + +/**** local int ****/ +static ssize_t snooping_local_show_d32(struct sysfsm_ops *ops, void *instance, void *buf, size_t bufsize) +{ + return sprintf(buf, "%d\n", *(int *)instance); +} /* snooping_local_show_d32() */ + +struct sysfsm_ops snooping_local_ops_d32 = { + .show = &snooping_local_show_d32, +}; + +/**** local long ****/ +static ssize_t snooping_local_show_d64(struct sysfsm_ops *ops, void *instance, void *buf, size_t bufsize) +{ + return sprintf(buf, "%ld\n", *(long *)instance); +} /* snooping_local_show_d64() */ + +struct sysfsm_ops snooping_local_ops_d64 = { + .show = &snooping_local_show_d64, +}; + +/**** local unsigned ****/ +static ssize_t snooping_local_show_u32(struct sysfsm_ops *ops, void *instance, void *buf, size_t bufsize) +{ + return sprintf(buf, "%u\n", *(unsigned *)instance); +} /* snooping_local_show_u32() */ + +struct sysfsm_ops snooping_local_ops_u32 = { + .show = &snooping_local_show_u32, +}; + +/**** local unsigned long ****/ +static ssize_t snooping_local_show_u64(struct sysfsm_ops *ops, void *instance, void *buf, size_t bufsize) +{ + return sprintf(buf, "%lu\n", *(unsigned long *)instance); +} /* snooping_local_show_u64() */ + +struct sysfsm_ops snooping_local_ops_u64 = { + .show = &snooping_local_show_u64, +}; + +/**** local string ****/ +static ssize_t snooping_local_show_s(struct sysfsm_ops *ops, void *instance, void *buf, size_t bufsize) +{ + return sprintf(buf, "%s\n", (char *)instance); +} /* snooping_local_show_s() */ + +struct sysfsm_ops snooping_local_ops_s = { + .show = &snooping_local_show_s, +}; + +/**** local list ****/ +static ssize_t snooping_local_show_pbl(struct sysfsm_ops *ops, void *instance, void *buf, size_t bufsize) +{ + const struct sysfsm_bitmap_param *p = instance; + + return bitmap_scnlistprintf(buf, bufsize, p->ptr, p->nbits); +} /* snooping_local_show_pbl() */ + +struct sysfsm_ops snooping_local_ops_pbl = { + .show = &snooping_local_show_pbl, + .release = &cleanup_special_local_create, +}; + +/**** local map ****/ +static ssize_t snooping_local_show_pb(struct sysfsm_ops *ops, void *instance, void *buf, size_t bufsize) +{ + const struct sysfsm_bitmap_param *p = instance; + + return bitmap_scnprintf(buf, bufsize, p->ptr, p->nbits); +} /* snooping_local_show_pb() */ + +struct sysfsm_ops snooping_local_ops_pb = { + .show = &snooping_local_show_pb, + .release = &cleanup_special_local_create, +}; + +/**** local K unsigned ****/ +static ssize_t snooping_local_show_u32K(struct sysfsm_ops *ops, void *instance, void *buf, size_t bufsize) +{ + return sprintf(buf, "%uK\n", (*(unsigned *)instance >> 10)); +} /* snooping_local_show_u32K() */ + +struct sysfsm_ops snooping_local_ops_u32K = { + .show = &snooping_local_show_u32K, +}; + +struct sysfsm_ops * const local_snooping_ops_table[] = { + [(long)SYSFS_SNOOPING_OPS_d32] = &snooping_local_ops_d32, + [(long)SYSFS_SNOOPING_OPS_d64] = &snooping_local_ops_d64, + [(long)SYSFS_SNOOPING_OPS_u32] = &snooping_local_ops_u32, + [(long)SYSFS_SNOOPING_OPS_u64] = &snooping_local_ops_u64, + [(long)SYSFS_SNOOPING_OPS_s] = &snooping_local_ops_s, + [(long)SYSFS_SNOOPING_OPS_pbl] = &snooping_local_ops_pbl, + [(long)SYSFS_SNOOPING_OPS_pb] = &snooping_local_ops_pb, + [(long)SYSFS_SNOOPING_OPS_u32K] = &snooping_local_ops_u32K, +}; + +static int setup_special_local_create(struct sysfs_req_create_param *param) +{ + struct sysfsm_bitmap_param *p = NULL; + + switch (param->client_ops) { + case (long)SYSFS_SNOOPING_OPS_d32: + case (long)SYSFS_SNOOPING_OPS_d64: + case (long)SYSFS_SNOOPING_OPS_u32: + case (long)SYSFS_SNOOPING_OPS_u64: + case (long)SYSFS_SNOOPING_OPS_s: + case (long)SYSFS_SNOOPING_OPS_u32K: + param->client_ops = (long)local_snooping_ops_table[param->client_ops]; + return 0; + + case (long)SYSFS_SNOOPING_OPS_pbl: + case (long)SYSFS_SNOOPING_OPS_pb: + p = kmalloc(sizeof(*p), GFP_KERNEL); + if (!p) { + return -ENOMEM; + } + + memcpy(p, (void *)param->client_instance, sizeof(*p)); + + param->client_ops = (long)local_snooping_ops_table[param->client_ops]; + param->client_instance = (long)p; + return 0; + } + + eprintk("mcctrl:setup_special_local_create:unknown ops %#lx\n", param->client_ops); + return -EINVAL; +} /* setup_special_local_create() */ + int sysfsm_createf(ihk_os_t os, struct sysfsm_ops *ops, void *instance, int mode, const char *fmt, ...) @@ -1771,6 +2180,7 @@ sysfsm_createf(ihk_os_t os, struct sysfsm_ops *ops, void *instance, int mode, ssize_t n; struct sysfs_req_create_param *param = NULL; struct sysfsm_node *np; + char special = 0; dprintk("mcctrl:sysfsm_createf(%p,%p,%p,%#o,%s,...)\n", os, ops, instance, mode, fmt); @@ -1783,6 +2193,10 @@ sysfsm_createf(ihk_os_t os, struct sysfsm_ops *ops, void *instance, int mode, goto out; } + param->client_ops = (long)ops; + param->client_instance = (long)instance; + param->mode = mode; + va_start(ap, fmt); n = vsnprintf(param->path, sizeof(param->path), fmt, ap); va_end(ap); @@ -1799,8 +2213,17 @@ sysfsm_createf(ihk_os_t os, struct sysfsm_ops *ops, void *instance, int mode, goto out; } - np = sysfsm_create(&udp->sysfsm_data, param->path, mode, &local_ops, - (long)ops, (long)instance); + if (is_special_sysfs_ops((void *)param->client_ops)) { + error = setup_special_local_create(param); + if (error) { + eprintk("mcctrl:sysfsm_createf:setup_special_local_create failed. %d\n", error); + goto out; + } + special = 1; + } + + np = sysfsm_create(&udp->sysfsm_data, param->path, param->mode, &local_ops, + param->client_ops, param->client_instance); if (IS_ERR(np)) { error = PTR_ERR(np); eprintk("mcctrl:sysfsm_createf:sysfsm_create failed. %d\n", error); @@ -1809,6 +2232,9 @@ sysfsm_createf(ihk_os_t os, struct sysfsm_ops *ops, void *instance, int mode, error = 0; out: + if (error && special) { + cleanup_special_local_create((void *)param->client_ops, (void *)param->client_instance); + } free_page((uintptr_t)param); if (error) { eprintk("mcctrl:sysfsm_createf(%p,%p,%p,%#o,%s,...): %d\n", diff --git a/executer/kernel/mcctrl/sysfs.h b/executer/kernel/mcctrl/sysfs.h index 18a90bcd..9df1de85 100644 --- a/executer/kernel/mcctrl/sysfs.h +++ b/executer/kernel/mcctrl/sysfs.h @@ -32,6 +32,29 @@ struct sysfs_handle { }; typedef struct sysfs_handle sysfs_handle_t; +struct sysfsm_bitmap_param { + int nbits; + int padding; + void *ptr; +}; + +#define SYSFS_SPECIAL_OPS_MIN ((void *)1) +#define SYSFS_SPECIAL_OPS_MAX ((void *)1000) + +#define SYSFS_SNOOPING_OPS_d32 ((void *)1) +#define SYSFS_SNOOPING_OPS_d64 ((void *)2) +#define SYSFS_SNOOPING_OPS_u32 ((void *)3) +#define SYSFS_SNOOPING_OPS_u64 ((void *)4) +#define SYSFS_SNOOPING_OPS_s ((void *)5) +#define SYSFS_SNOOPING_OPS_pbl ((void *)6) +#define SYSFS_SNOOPING_OPS_pb ((void *)7) +#define SYSFS_SNOOPING_OPS_u32K ((void *)8) + +static inline int is_special_sysfs_ops(void *ops) +{ + return (((long)SYSFS_SPECIAL_OPS_MIN <= (long)ops) + && ((long)ops <= (long)SYSFS_SPECIAL_OPS_MAX)); +} extern int sysfsm_createf(ihk_os_t os, struct sysfsm_ops *ops, void *instance, int mode, const char *fmt, ...); diff --git a/executer/kernel/mcctrl/sysfs_msg.h b/executer/kernel/mcctrl/sysfs_msg.h index 22761585..a67cdfea 100644 --- a/executer/kernel/mcctrl/sysfs_msg.h +++ b/executer/kernel/mcctrl/sysfs_msg.h @@ -25,6 +25,18 @@ struct sysfs_req_create_param { int busy; }; /* struct sysfs_req_create_param */ +#define SYSFS_SPECIAL_OPS_MIN ((void *)1) +#define SYSFS_SPECIAL_OPS_MAX ((void *)1000) + +#define SYSFS_SNOOPING_OPS_d32 ((void *)1) +#define SYSFS_SNOOPING_OPS_d64 ((void *)2) +#define SYSFS_SNOOPING_OPS_u32 ((void *)3) +#define SYSFS_SNOOPING_OPS_u64 ((void *)4) +#define SYSFS_SNOOPING_OPS_s ((void *)5) +#define SYSFS_SNOOPING_OPS_pbl ((void *)6) +#define SYSFS_SNOOPING_OPS_pb ((void *)7) +#define SYSFS_SNOOPING_OPS_u32K ((void *)8) + struct sysfs_req_mkdir_param { int error; int padding; diff --git a/kernel/include/sysfs.h b/kernel/include/sysfs.h index cf4e39a3..52debc1c 100644 --- a/kernel/include/sysfs.h +++ b/kernel/include/sysfs.h @@ -32,6 +32,29 @@ struct sysfs_handle { }; typedef struct sysfs_handle sysfs_handle_t; +struct sysfs_bitmap_param { + int nbits; + int padding; + void *ptr; +}; + +#define SYSFS_SPECIAL_OPS_MIN ((void *)1) +#define SYSFS_SPECIAL_OPS_MAX ((void *)1000) + +#define SYSFS_SNOOPING_OPS_d32 ((void *)1) +#define SYSFS_SNOOPING_OPS_d64 ((void *)2) +#define SYSFS_SNOOPING_OPS_u32 ((void *)3) +#define SYSFS_SNOOPING_OPS_u64 ((void *)4) +#define SYSFS_SNOOPING_OPS_s ((void *)5) +#define SYSFS_SNOOPING_OPS_pbl ((void *)6) +#define SYSFS_SNOOPING_OPS_pb ((void *)7) +#define SYSFS_SNOOPING_OPS_u32K ((void *)8) + +static inline int is_special_sysfs_ops(void *ops) +{ + return (((long)SYSFS_SPECIAL_OPS_MIN <= (long)ops) + && ((long)ops <= (long)SYSFS_SPECIAL_OPS_MAX)); +} extern int sysfs_createf(struct sysfs_ops *ops, void *instance, int mode, const char *fmt, ...); diff --git a/kernel/include/sysfs_msg.h b/kernel/include/sysfs_msg.h index 22761585..a67cdfea 100644 --- a/kernel/include/sysfs_msg.h +++ b/kernel/include/sysfs_msg.h @@ -25,6 +25,18 @@ struct sysfs_req_create_param { int busy; }; /* struct sysfs_req_create_param */ +#define SYSFS_SPECIAL_OPS_MIN ((void *)1) +#define SYSFS_SPECIAL_OPS_MAX ((void *)1000) + +#define SYSFS_SNOOPING_OPS_d32 ((void *)1) +#define SYSFS_SNOOPING_OPS_d64 ((void *)2) +#define SYSFS_SNOOPING_OPS_u32 ((void *)3) +#define SYSFS_SNOOPING_OPS_u64 ((void *)4) +#define SYSFS_SNOOPING_OPS_s ((void *)5) +#define SYSFS_SNOOPING_OPS_pbl ((void *)6) +#define SYSFS_SNOOPING_OPS_pb ((void *)7) +#define SYSFS_SNOOPING_OPS_u32K ((void *)8) + struct sysfs_req_mkdir_param { int error; int padding; diff --git a/kernel/sysfs.c b/kernel/sysfs.c index 6a352f72..a924e531 100644 --- a/kernel/sysfs.c +++ b/kernel/sysfs.c @@ -30,6 +30,37 @@ static size_t sysfs_data_bufsize; static void *sysfs_data_buf; +static int setup_special_create(struct sysfs_req_create_param *param, struct sysfs_bitmap_param *pbp) +{ + void *cinstance = (void *)param->client_instance; + + switch (param->client_ops) { + case (long)SYSFS_SNOOPING_OPS_d32: + case (long)SYSFS_SNOOPING_OPS_d64: + case (long)SYSFS_SNOOPING_OPS_u32: + case (long)SYSFS_SNOOPING_OPS_u64: + case (long)SYSFS_SNOOPING_OPS_u32K: + param->client_instance = virt_to_phys(cinstance); + return 0; + + case (long)SYSFS_SNOOPING_OPS_s: + pbp->nbits = 8 * (strlen(cinstance) + 1); + pbp->ptr = (void *)virt_to_phys(cinstance); + param->client_instance = virt_to_phys(pbp); + return 0; + + case (long)SYSFS_SNOOPING_OPS_pbl: + case (long)SYSFS_SNOOPING_OPS_pb: + *pbp = *(struct sysfs_bitmap_param *)cinstance; + pbp->ptr = (void *)virt_to_phys(pbp->ptr); + param->client_instance = virt_to_phys(pbp); + return 0; + } + + ekprintf("setup_special_create:unknown ops %#lx\n", param->client_ops); + return -EINVAL; +} /* setup_special_create() */ + int sysfs_createf(struct sysfs_ops *ops, void *instance, int mode, const char *fmt, ...) @@ -39,6 +70,7 @@ sysfs_createf(struct sysfs_ops *ops, void *instance, int mode, ssize_t n; struct sysfs_req_create_param *param = NULL; struct ikc_scd_packet packet; + struct sysfs_bitmap_param asbp; dkprintf("sysfs_createf(%p,%p,%#o,%s,...)\n", ops, instance, mode, fmt); @@ -70,6 +102,14 @@ sysfs_createf(struct sysfs_ops *ops, void *instance, int mode, goto out; } + if (is_special_sysfs_ops(ops)) { + error = setup_special_create(param, &asbp); + if (error) { + ekprintf("sysfs_createf:setup_special_create failed. %d\n", error); + goto out; + } + } + packet.msg = SCD_MSG_SYSFS_REQ_CREATE; packet.sysfs_arg1 = virt_to_phys(param);