From 7b6e04a3edc140a82f5e0e29e59d6dc90a629d34 Mon Sep 17 00:00:00 2001 From: Jag Raman Date: Fri, 23 Jun 2017 14:58:29 -0400 Subject: sparc64: ensure VIO operations are defined while being used It's possible that VIO operations are not defined for some VIO clients. In that case, VIO ops pointer should be checked for NULL before being used Signed-off-by: Jagannathan Raman Reviewed-by: Liam Merwick Reviewed-by: Shannon Nelson Signed-off-by: David S. Miller --- arch/sparc/kernel/viohs.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/sparc/kernel/viohs.c b/arch/sparc/kernel/viohs.c index b30b30ab3ddd..ea28cb7118bd 100644 --- a/arch/sparc/kernel/viohs.c +++ b/arch/sparc/kernel/viohs.c @@ -223,6 +223,9 @@ static int send_rdx(struct vio_driver_state *vio) static int send_attr(struct vio_driver_state *vio) { + if (!vio->ops) + return -EINVAL; + return vio->ops->send_attr(vio); } @@ -374,6 +377,9 @@ static int process_attr(struct vio_driver_state *vio, void *pkt) if (!(vio->hs_state & VIO_HS_GOTVERS)) return handshake_failure(vio); + if (!vio->ops) + return 0; + err = vio->ops->handle_attr(vio, pkt); if (err < 0) { return handshake_failure(vio); @@ -388,6 +394,7 @@ static int process_attr(struct vio_driver_state *vio, void *pkt) vio->hs_state |= VIO_HS_SENT_DREG; } } + return 0; } @@ -647,10 +654,13 @@ int vio_control_pkt_engine(struct vio_driver_state *vio, void *pkt) err = process_unknown(vio, pkt); break; } + if (!err && vio->hs_state != prev_state && - (vio->hs_state & VIO_HS_COMPLETE)) - vio->ops->handshake_complete(vio); + (vio->hs_state & VIO_HS_COMPLETE)) { + if (vio->ops) + vio->ops->handshake_complete(vio); + } return err; } @@ -805,8 +815,7 @@ int vio_driver_init(struct vio_driver_state *vio, struct vio_dev *vdev, return -EINVAL; } - if (!ops->send_attr || - !ops->handle_attr || + if (!ops || !ops->send_attr || !ops->handle_attr || !ops->handshake_complete) return -EINVAL; -- cgit v1.2.3 From ac6bb0255430f701ea3723aac5dd06f528078567 Mon Sep 17 00:00:00 2001 From: Jag Raman Date: Fri, 23 Jun 2017 14:58:30 -0400 Subject: sparc64: specify the device class in VIO version info. packet Specify the class of VIO device in the version info. packet. The device's class identifies the type of VIO device, whether it's DISK, CONSOLE, NETWORK, etc... This packet is used in the handshake between the client and server for this device. Signed-off-by: Jagannathan Raman Reviewed-by: Liam Merwick Reviewed-by: Shannon Nelson Signed-off-by: David S. Miller --- arch/sparc/kernel/viohs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/sparc/kernel/viohs.c b/arch/sparc/kernel/viohs.c index ea28cb7118bd..68e952a7bcdb 100644 --- a/arch/sparc/kernel/viohs.c +++ b/arch/sparc/kernel/viohs.c @@ -286,6 +286,7 @@ static int process_ver_info(struct vio_driver_state *vio, ver.minor = vap->minor; pkt->minor = ver.minor; pkt->tag.stype = VIO_SUBTYPE_ACK; + pkt->dev_class = vio->dev_class; viodbg(HS, "SEND VERSION ACK maj[%u] min[%u]\n", pkt->major, pkt->minor); err = send_ctrl(vio, &pkt->tag, sizeof(*pkt)); -- cgit v1.2.3 From 01b7a471382c529f60f5965ecfed9a14bfccf1ab Mon Sep 17 00:00:00 2001 From: Jag Raman Date: Fri, 23 Jun 2017 14:58:31 -0400 Subject: sparc64: skip handshake for LDC channels in RAW mode LDC channels in RAW mode does not provide any session management. No handshake protocol is defined for LDC channels in RAW mode. It's therefore skipped. Signed-off-by: Jagannathan Raman Reviewed-by: Liam Merwick Reviewed-by: Shannon Nelson Signed-off-by: David S. Miller --- arch/sparc/kernel/ldc.c | 10 ++++++++++ arch/sparc/kernel/viohs.c | 6 +++++- 2 files changed, 15 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/sparc/kernel/ldc.c b/arch/sparc/kernel/ldc.c index 97a5743b04e2..840e0b21bfe3 100644 --- a/arch/sparc/kernel/ldc.c +++ b/arch/sparc/kernel/ldc.c @@ -1347,6 +1347,14 @@ int ldc_bind(struct ldc_channel *lp) lp->hs_state = LDC_HS_OPEN; ldc_set_state(lp, LDC_STATE_BOUND); + if (lp->cfg.mode == LDC_MODE_RAW) { + /* + * There is no handshake in RAW mode, so handshake + * is completed. + */ + lp->hs_state = LDC_HS_COMPLETE; + } + spin_unlock_irqrestore(&lp->lock, flags); return 0; @@ -1460,11 +1468,13 @@ void ldc_set_state(struct ldc_channel *lp, u8 state) lp->state = state; } +EXPORT_SYMBOL(ldc_set_state); int ldc_mode(struct ldc_channel *lp) { return lp->cfg.mode; } +EXPORT_SYMBOL(ldc_mode); int ldc_rx_reset(struct ldc_channel *lp) { diff --git a/arch/sparc/kernel/viohs.c b/arch/sparc/kernel/viohs.c index 68e952a7bcdb..d4f13c037a40 100644 --- a/arch/sparc/kernel/viohs.c +++ b/arch/sparc/kernel/viohs.c @@ -776,7 +776,11 @@ void vio_port_up(struct vio_driver_state *vio) } if (!err) { - err = ldc_connect(vio->lp); + if (ldc_mode(vio->lp) == LDC_MODE_RAW) + ldc_set_state(vio->lp, LDC_STATE_CONNECTED); + else + err = ldc_connect(vio->lp); + if (err) printk(KERN_WARNING "%s: Port %lu connect failed, " "err=%d\n", -- cgit v1.2.3 From 411cb4a0b3b12833731abc71059a7eeb04dc8477 Mon Sep 17 00:00:00 2001 From: Jag Raman Date: Fri, 23 Jun 2017 14:58:32 -0400 Subject: sparc64: expand MDESC interface Add the following two APIs to Machine Description (MDESC) - mdesc_get_node: Searches for a node in the Machine Description tree based on given information about that node. - mdesc_get_node_info: Retrieves information about a given node. Signed-off-by: Jagannathan Raman Reviewed-by: Liam Merwick Reviewed-by: Shannon Nelson Signed-off-by: David S. Miller --- arch/sparc/include/asm/mdesc.h | 17 ++++ arch/sparc/kernel/mdesc.c | 216 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 233 insertions(+) (limited to 'arch') diff --git a/arch/sparc/include/asm/mdesc.h b/arch/sparc/include/asm/mdesc.h index aebeb88f70db..68d19909d1cd 100644 --- a/arch/sparc/include/asm/mdesc.h +++ b/arch/sparc/include/asm/mdesc.h @@ -16,6 +16,7 @@ struct mdesc_handle *mdesc_grab(void); void mdesc_release(struct mdesc_handle *); #define MDESC_NODE_NULL (~(u64)0) +#define MDESC_MAX_STR_LEN 256 u64 mdesc_node_by_name(struct mdesc_handle *handle, u64 from_node, const char *name); @@ -71,6 +72,22 @@ struct mdesc_notifier_client { void mdesc_register_notifier(struct mdesc_notifier_client *client); +union md_node_info { + struct vdev_port { + u64 id; /* id */ + u64 parent_cfg_hdl; /* parent config handle */ + const char *name; /* name (property) */ + } vdev_port; + struct ds_port { + u64 id; /* id */ + } ds_port; +}; + +u64 mdesc_get_node(struct mdesc_handle *hp, const char *node_name, + union md_node_info *node_info); +int mdesc_get_node_info(struct mdesc_handle *hp, u64 node, + const char *node_name, union md_node_info *node_info); + void mdesc_fill_in_cpu_data(cpumask_t *mask); void mdesc_populate_present_mask(cpumask_t *mask); void mdesc_get_page_sizes(cpumask_t *mask, unsigned long *pgsz_mask); diff --git a/arch/sparc/kernel/mdesc.c b/arch/sparc/kernel/mdesc.c index c0765bbf60ea..72aca731657f 100644 --- a/arch/sparc/kernel/mdesc.c +++ b/arch/sparc/kernel/mdesc.c @@ -75,6 +75,74 @@ struct mdesc_handle { struct mdesc_hdr mdesc; }; +typedef int (*mdesc_node_info_get_f)(struct mdesc_handle *, u64, + union md_node_info *); +typedef void (*mdesc_node_info_rel_f)(union md_node_info *); +typedef bool (*mdesc_node_match_f)(union md_node_info *, union md_node_info *); + +struct md_node_ops { + char *name; + mdesc_node_info_get_f get_info; + mdesc_node_info_rel_f rel_info; + mdesc_node_match_f node_match; +}; + +static int get_vdev_port_node_info(struct mdesc_handle *md, u64 node, + union md_node_info *node_info); +static void rel_vdev_port_node_info(union md_node_info *node_info); +static bool vdev_port_node_match(union md_node_info *a_node_info, + union md_node_info *b_node_info); + +static int get_ds_port_node_info(struct mdesc_handle *md, u64 node, + union md_node_info *node_info); +static void rel_ds_port_node_info(union md_node_info *node_info); +static bool ds_port_node_match(union md_node_info *a_node_info, + union md_node_info *b_node_info); + +/* supported node types which can be registered */ +static struct md_node_ops md_node_ops_table[] = { + {"virtual-device-port", get_vdev_port_node_info, + rel_vdev_port_node_info, vdev_port_node_match}, + {"domain-services-port", get_ds_port_node_info, + rel_ds_port_node_info, ds_port_node_match}, + {NULL, NULL, NULL, NULL} +}; + +static void mdesc_get_node_ops(const char *node_name, + mdesc_node_info_get_f *get_info_f, + mdesc_node_info_rel_f *rel_info_f, + mdesc_node_match_f *match_f) +{ + int i; + + if (get_info_f) + *get_info_f = NULL; + + if (rel_info_f) + *rel_info_f = NULL; + + if (match_f) + *match_f = NULL; + + if (!node_name) + return; + + for (i = 0; md_node_ops_table[i].name != NULL; i++) { + if (strcmp(md_node_ops_table[i].name, node_name) == 0) { + if (get_info_f) + *get_info_f = md_node_ops_table[i].get_info; + + if (rel_info_f) + *rel_info_f = md_node_ops_table[i].rel_info; + + if (match_f) + *match_f = md_node_ops_table[i].node_match; + + break; + } + } +} + static void mdesc_handle_init(struct mdesc_handle *hp, unsigned int handle_size, void *base) @@ -249,6 +317,86 @@ static const u64 *parent_cfg_handle(struct mdesc_handle *hp, u64 node) return id; } +static int get_vdev_port_node_info(struct mdesc_handle *md, u64 node, + union md_node_info *node_info) +{ + const u64 *parent_cfg_hdlp; + const char *name; + const u64 *idp; + + /* + * Virtual device nodes are distinguished by: + * 1. "id" property + * 2. "name" property + * 3. parent node "cfg-handle" property + */ + idp = mdesc_get_property(md, node, "id", NULL); + name = mdesc_get_property(md, node, "name", NULL); + parent_cfg_hdlp = parent_cfg_handle(md, node); + + if (!idp || !name || !parent_cfg_hdlp) + return -1; + + node_info->vdev_port.id = *idp; + node_info->vdev_port.name = kstrdup_const(name, GFP_KERNEL); + node_info->vdev_port.parent_cfg_hdl = *parent_cfg_hdlp; + + return 0; +} + +static void rel_vdev_port_node_info(union md_node_info *node_info) +{ + if (node_info && node_info->vdev_port.name) { + kfree_const(node_info->vdev_port.name); + node_info->vdev_port.name = NULL; + } +} + +static bool vdev_port_node_match(union md_node_info *a_node_info, + union md_node_info *b_node_info) +{ + if (a_node_info->vdev_port.id != b_node_info->vdev_port.id) + return false; + + if (a_node_info->vdev_port.parent_cfg_hdl != + b_node_info->vdev_port.parent_cfg_hdl) + return false; + + if (strncmp(a_node_info->vdev_port.name, + b_node_info->vdev_port.name, MDESC_MAX_STR_LEN) != 0) + return false; + + return true; +} + +static int get_ds_port_node_info(struct mdesc_handle *md, u64 node, + union md_node_info *node_info) +{ + const u64 *idp; + + /* DS port nodes use the "id" property to distinguish them */ + idp = mdesc_get_property(md, node, "id", NULL); + if (!idp) + return -1; + + node_info->ds_port.id = *idp; + + return 0; +} + +static void rel_ds_port_node_info(union md_node_info *node_info) +{ +} + +static bool ds_port_node_match(union md_node_info *a_node_info, + union md_node_info *b_node_info) +{ + if (a_node_info->ds_port.id != b_node_info->ds_port.id) + return false; + + return true; +} + /* Run 'func' on nodes which are in A but not in B. */ static void invoke_on_missing(const char *name, struct mdesc_handle *a, @@ -367,6 +515,74 @@ out: mutex_unlock(&mdesc_mutex); } +u64 mdesc_get_node(struct mdesc_handle *hp, const char *node_name, + union md_node_info *node_info) +{ + mdesc_node_info_get_f get_info_func; + mdesc_node_info_rel_f rel_info_func; + mdesc_node_match_f node_match_func; + union md_node_info hp_node_info; + u64 hp_node; + int rv; + + if (hp == NULL || node_name == NULL || node_info == NULL) + return MDESC_NODE_NULL; + + /* Find the ops for the given node name */ + mdesc_get_node_ops(node_name, &get_info_func, &rel_info_func, + &node_match_func); + + /* If we didn't find ops for the given node name, it is not supported */ + if (!get_info_func || !rel_info_func || !node_match_func) { + pr_err("MD: %s node is not supported\n", node_name); + return -EINVAL; + } + + mdesc_for_each_node_by_name(hp, hp_node, node_name) { + rv = get_info_func(hp, hp_node, &hp_node_info); + if (rv != 0) + continue; + + if (node_match_func(node_info, &hp_node_info)) + break; + + rel_info_func(&hp_node_info); + } + + rel_info_func(&hp_node_info); + + return hp_node; +} + +int mdesc_get_node_info(struct mdesc_handle *hp, u64 node, + const char *node_name, union md_node_info *node_info) +{ + mdesc_node_info_get_f get_info_func; + int rv; + + if (hp == NULL || node == MDESC_NODE_NULL || + node_name == NULL || node_info == NULL) + return -EINVAL; + + /* Find the get_info op for the given node name */ + mdesc_get_node_ops(node_name, &get_info_func, NULL, NULL); + + /* If we didn't find a get_info_func, the node name is not supported */ + if (get_info_func == NULL) { + pr_err("MD: %s node is not supported\n", node_name); + return -EINVAL; + } + + rv = get_info_func(hp, node, node_info); + if (rv != 0) { + pr_err("MD: Cannot find 1 or more required match properties for %s node.\n", + node_name); + return -1; + } + + return 0; +} + static struct mdesc_elem *node_block(struct mdesc_hdr *mdesc) { return (struct mdesc_elem *) (mdesc + 1); -- cgit v1.2.3 From 0ab2fcd69dbf1dad27a7cee0f608b48690134ced Mon Sep 17 00:00:00 2001 From: Jag Raman Date: Fri, 23 Jun 2017 14:58:33 -0400 Subject: sparc64: mdesc: use __GFP_REPEAT action modifier for VM allocation During MDESC handle allocation, use the __GFP_REPEAT flag instead of __GFP_NOFAIL. If memory is not available, the caller expects a NULL pointer instead of waiting until memory is allocated. Signed-off-by: Jagannathan Raman Reviewed-by: Liam Merwick Reviewed-by: Shannon Nelson Signed-off-by: David S. Miller --- arch/sparc/kernel/mdesc.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/sparc/kernel/mdesc.c b/arch/sparc/kernel/mdesc.c index 72aca731657f..f0249691d000 100644 --- a/arch/sparc/kernel/mdesc.c +++ b/arch/sparc/kernel/mdesc.c @@ -205,12 +205,10 @@ static struct mdesc_handle *mdesc_kmalloc(unsigned int mdesc_size) handle_size = (sizeof(struct mdesc_handle) - sizeof(struct mdesc_hdr) + mdesc_size); + base = kmalloc(handle_size + 15, GFP_KERNEL | __GFP_REPEAT); + if (!base) + return NULL; - /* - * Allocation has to succeed because mdesc update would be missed - * and such events are not retransmitted. - */ - base = kmalloc(handle_size + 15, GFP_KERNEL | __GFP_NOFAIL); addr = (unsigned long)base; addr = (addr + 15UL) & ~15UL; hp = (struct mdesc_handle *) addr; -- cgit v1.2.3 From 06f3c3ac60111a2ebffdc6f6acf16847153c0589 Mon Sep 17 00:00:00 2001 From: Jag Raman Date: Fri, 23 Jun 2017 14:58:34 -0400 Subject: sparc64: add MDESC node name property to VIO device metadata Add the MDESC node name of MDESC client to VIO device metadata. It is later used to uniquely identify a node in the MDESC. VIO & MDESC APIs are updated to handle this node name. Signed-off-by: Jagannathan Raman Reviewed-by: Liam Merwick Reviewed-by: Shannon Nelson Signed-off-by: David S. Miller --- arch/sparc/include/asm/mdesc.h | 7 ++-- arch/sparc/include/asm/vio.h | 2 + arch/sparc/kernel/mdesc.c | 88 ++++++++++++++++++++++-------------------- arch/sparc/kernel/vio.c | 22 +++++++---- 4 files changed, 68 insertions(+), 51 deletions(-) (limited to 'arch') diff --git a/arch/sparc/include/asm/mdesc.h b/arch/sparc/include/asm/mdesc.h index 68d19909d1cd..e8a4c413a1c7 100644 --- a/arch/sparc/include/asm/mdesc.h +++ b/arch/sparc/include/asm/mdesc.h @@ -63,9 +63,10 @@ u64 mdesc_arc_target(struct mdesc_handle *hp, u64 arc); void mdesc_update(void); struct mdesc_notifier_client { - void (*add)(struct mdesc_handle *handle, u64 node); - void (*remove)(struct mdesc_handle *handle, u64 node); - + void (*add)(struct mdesc_handle *handle, u64 node, + const char *node_name); + void (*remove)(struct mdesc_handle *handle, u64 node, + const char *node_name); const char *node_name; struct mdesc_notifier_client *next; }; diff --git a/arch/sparc/include/asm/vio.h b/arch/sparc/include/asm/vio.h index 9dca7a892978..69cb3a5ff8cf 100644 --- a/arch/sparc/include/asm/vio.h +++ b/arch/sparc/include/asm/vio.h @@ -316,12 +316,14 @@ static inline u32 vio_dring_prev(struct vio_dring_state *dr, u32 index) } #define VIO_MAX_TYPE_LEN 32 +#define VIO_MAX_NAME_LEN 32 #define VIO_MAX_COMPAT_LEN 64 struct vio_dev { u64 mp; struct device_node *dp; + char node_name[VIO_MAX_NAME_LEN]; char type[VIO_MAX_TYPE_LEN]; char compat[VIO_MAX_COMPAT_LEN]; int compat_len; diff --git a/arch/sparc/kernel/mdesc.c b/arch/sparc/kernel/mdesc.c index f0249691d000..04b76267ddfa 100644 --- a/arch/sparc/kernel/mdesc.c +++ b/arch/sparc/kernel/mdesc.c @@ -291,7 +291,7 @@ void mdesc_register_notifier(struct mdesc_notifier_client *client) client_list = client; mdesc_for_each_node_by_name(cur_mdesc, node, client->node_name) - client->add(cur_mdesc, node); + client->add(cur_mdesc, node, client->node_name); mutex_unlock(&mdesc_mutex); } @@ -399,55 +399,61 @@ static bool ds_port_node_match(union md_node_info *a_node_info, static void invoke_on_missing(const char *name, struct mdesc_handle *a, struct mdesc_handle *b, - void (*func)(struct mdesc_handle *, u64)) + void (*func)(struct mdesc_handle *, u64, + const char *node_name)) { - u64 node; + mdesc_node_info_get_f get_info_func; + mdesc_node_info_rel_f rel_info_func; + mdesc_node_match_f node_match_func; + union md_node_info a_node_info; + union md_node_info b_node_info; + bool found; + u64 a_node; + u64 b_node; + int rv; - mdesc_for_each_node_by_name(a, node, name) { - int found = 0, is_vdc_port = 0; - const char *name_prop; - const u64 *id; - u64 fnode; - - name_prop = mdesc_get_property(a, node, "name", NULL); - if (name_prop && !strcmp(name_prop, "vdc-port")) { - is_vdc_port = 1; - id = parent_cfg_handle(a, node); - } else - id = mdesc_get_property(a, node, "id", NULL); - - if (!id) { - printk(KERN_ERR "MD: Cannot find ID for %s node.\n", - (name_prop ? name_prop : name)); + /* + * Find the get_info, rel_info and node_match ops for the given + * node name + */ + mdesc_get_node_ops(name, &get_info_func, &rel_info_func, + &node_match_func); + + /* If we didn't find a match, the node type is not supported */ + if (!get_info_func || !rel_info_func || !node_match_func) { + pr_err("MD: %s node type is not supported\n", name); + return; + } + + mdesc_for_each_node_by_name(a, a_node, name) { + found = false; + + rv = get_info_func(a, a_node, &a_node_info); + if (rv != 0) { + pr_err("MD: Cannot find 1 or more required match properties for %s node.\n", + name); continue; } - mdesc_for_each_node_by_name(b, fnode, name) { - const u64 *fid; - - if (is_vdc_port) { - name_prop = mdesc_get_property(b, fnode, - "name", NULL); - if (!name_prop || - strcmp(name_prop, "vdc-port")) - continue; - fid = parent_cfg_handle(b, fnode); - if (!fid) { - printk(KERN_ERR "MD: Cannot find ID " - "for vdc-port node.\n"); - continue; - } - } else - fid = mdesc_get_property(b, fnode, - "id", NULL); - - if (*id == *fid) { - found = 1; + /* Check each node in B for node matching a_node */ + mdesc_for_each_node_by_name(b, b_node, name) { + rv = get_info_func(b, b_node, &b_node_info); + if (rv != 0) + continue; + + if (node_match_func(&a_node_info, &b_node_info)) { + found = true; + rel_info_func(&b_node_info); break; } + + rel_info_func(&b_node_info); } + + rel_info_func(&a_node_info); + if (!found) - func(a, node); + func(a, a_node, name); } } diff --git a/arch/sparc/kernel/vio.c b/arch/sparc/kernel/vio.c index 075d38980dee..f37937b95dbf 100644 --- a/arch/sparc/kernel/vio.c +++ b/arch/sparc/kernel/vio.c @@ -219,6 +219,7 @@ int vio_set_intr(unsigned long dev_ino, int state) EXPORT_SYMBOL(vio_set_intr); static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, + const char *node_name, struct device *parent) { const char *type, *compat, *bus_id_name; @@ -236,7 +237,7 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, tlen = strlen(type) + 1; } } - if (tlen > VIO_MAX_TYPE_LEN) { + if (tlen > VIO_MAX_TYPE_LEN || strlen(type) >= VIO_MAX_TYPE_LEN) { printk(KERN_ERR "VIO: Type string [%s] is too long.\n", type); return NULL; @@ -335,6 +336,11 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, printk(KERN_INFO "VIO: Adding device %s\n", dev_name(&vdev->dev)); + /* node_name is NULL for the parent/channel-devices node */ + if (node_name != NULL) + (void) snprintf(vdev->node_name, VIO_MAX_NAME_LEN, "%s", + node_name); + err = device_register(&vdev->dev); if (err) { printk(KERN_ERR "VIO: Could not register device %s, err=%d\n", @@ -349,9 +355,10 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, return vdev; } -static void vio_add(struct mdesc_handle *hp, u64 node) +static void vio_add(struct mdesc_handle *hp, u64 node, + const char *node_name) { - (void) vio_create_one(hp, node, &root_vdev->dev); + (void) vio_create_one(hp, node, node_name, &root_vdev->dev); } struct vio_md_node_query { @@ -375,7 +382,7 @@ static int vio_md_node_match(struct device *dev, void *arg) return 1; } -static void vio_remove(struct mdesc_handle *hp, u64 node) +static void vio_remove(struct mdesc_handle *hp, u64 node, const char *node_name) { const char *type; const u64 *id, *cfg_handle; @@ -446,7 +453,8 @@ static struct mdesc_notifier_client vio_device_notifier = { * under "openboot" that we should not mess with as aparently that is * reserved exclusively for OBP use. */ -static void vio_add_ds(struct mdesc_handle *hp, u64 node) +static void vio_add_ds(struct mdesc_handle *hp, u64 node, + const char *node_name) { int found; u64 a; @@ -463,7 +471,7 @@ static void vio_add_ds(struct mdesc_handle *hp, u64 node) } if (found) - (void) vio_create_one(hp, node, &root_vdev->dev); + (void) vio_create_one(hp, node, node_name, &root_vdev->dev); } static struct mdesc_notifier_client vio_ds_notifier = { @@ -530,7 +538,7 @@ static int __init vio_init(void) cdev_cfg_handle = *cfg_handle; - root_vdev = vio_create_one(hp, root, NULL); + root_vdev = vio_create_one(hp, root, NULL, NULL); err = -ENODEV; if (!root_vdev) { printk(KERN_ERR "VIO: Could not create root device.\n"); -- cgit v1.2.3 From e2169a32b4f03b926905be029169a8b9f0750a67 Mon Sep 17 00:00:00 2001 From: Jag Raman Date: Fri, 23 Jun 2017 14:58:35 -0400 Subject: sparc64: refactor code to obtain cfg_handle property from MDESC Refactors code to get the cfg_handle property of a node from Machine Description (MDESC) Signed-off-by: Jagannathan Raman Reviewed-by: Liam Merwick Reviewed-by: Shannon Nelson Signed-off-by: David S. Miller --- arch/sparc/kernel/vio.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) (limited to 'arch') diff --git a/arch/sparc/kernel/vio.c b/arch/sparc/kernel/vio.c index f37937b95dbf..1ac5da12ac2b 100644 --- a/arch/sparc/kernel/vio.c +++ b/arch/sparc/kernel/vio.c @@ -181,6 +181,24 @@ static struct device_node *cdev_node; static struct vio_dev *root_vdev; static u64 cdev_cfg_handle; +static const u64 *vio_cfg_handle(struct mdesc_handle *hp, u64 node) +{ + const u64 *cfg_handle = NULL; + u64 a; + + mdesc_for_each_arc(a, hp, node, MDESC_ARC_TYPE_BACK) { + u64 target; + + target = mdesc_arc_target(hp, a); + cfg_handle = mdesc_get_property(hp, target, + "cfg-handle", NULL); + if (cfg_handle) + break; + } + + return cfg_handle; +} + static void vio_fill_channel_info(struct mdesc_handle *hp, u64 mp, struct vio_dev *vdev) { @@ -227,7 +245,6 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, struct vio_dev *vdev; int err, tlen, clen; const u64 *id, *cfg_handle; - u64 a; type = mdesc_get_property(hp, mp, "device-type", &tlen); if (!type) { @@ -245,16 +262,7 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, id = mdesc_get_property(hp, mp, "id", NULL); - cfg_handle = NULL; - mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_BACK) { - u64 target; - - target = mdesc_arc_target(hp, a); - cfg_handle = mdesc_get_property(hp, target, - "cfg-handle", NULL); - if (cfg_handle) - break; - } + cfg_handle = vio_cfg_handle(hp, mp); bus_id_name = type; if (!strcmp(type, "domain-services-port")) -- cgit v1.2.3 From 0542eb7de7d5244d159f827a0c9bd8c01792bd13 Mon Sep 17 00:00:00 2001 From: Jag Raman Date: Fri, 23 Jun 2017 14:58:36 -0400 Subject: sparc64: remove restriction on VIO device name size Removes restriction on VIO device's size limit. Since KOBJ_NAME_LEN has been dropped from kobject, there doesn't seem to be a restriction on the device name anymore. This limit therefore doesn't make sense. Signed-off-by: Jagannathan Raman Reviewed-by: Liam Merwick Reviewed-by: Shannon Nelson Signed-off-by: David S. Miller --- arch/sparc/kernel/vio.c | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) (limited to 'arch') diff --git a/arch/sparc/kernel/vio.c b/arch/sparc/kernel/vio.c index 1ac5da12ac2b..0890a25b30a4 100644 --- a/arch/sparc/kernel/vio.c +++ b/arch/sparc/kernel/vio.c @@ -240,7 +240,7 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, const char *node_name, struct device *parent) { - const char *type, *compat, *bus_id_name; + const char *type, *compat; struct device_node *dp; struct vio_dev *vdev; int err, tlen, clen; @@ -264,21 +264,6 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, cfg_handle = vio_cfg_handle(hp, mp); - bus_id_name = type; - if (!strcmp(type, "domain-services-port")) - bus_id_name = "ds"; - - /* - * 20 char is the old driver-core name size limit, which is no more. - * This check can probably be removed after review and possible - * adaption of the vio users name length handling. - */ - if (strlen(bus_id_name) >= 20 - 4) { - printk(KERN_ERR "VIO: bus_id_name [%s] is too long.\n", - bus_id_name); - return NULL; - } - compat = mdesc_get_property(hp, mp, "device-type", &clen); if (!compat) { clen = 0; @@ -309,15 +294,15 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, vio_fill_channel_info(hp, mp, vdev); if (!id) { - dev_set_name(&vdev->dev, "%s", bus_id_name); + dev_set_name(&vdev->dev, "%s", type); vdev->dev_no = ~(u64)0; vdev->id = ~(u64)0; } else if (!cfg_handle) { - dev_set_name(&vdev->dev, "%s-%llu", bus_id_name, *id); + dev_set_name(&vdev->dev, "%s-%llu", type, *id); vdev->dev_no = *id; vdev->id = ~(u64)0; } else { - dev_set_name(&vdev->dev, "%s-%llu-%llu", bus_id_name, + dev_set_name(&vdev->dev, "%s-%llu-%llu", type, *cfg_handle, *id); vdev->dev_no = *cfg_handle; vdev->id = *id; -- cgit v1.2.3 From 110f2264b37674e99057acd249a930040fad55b1 Mon Sep 17 00:00:00 2001 From: Jag Raman Date: Fri, 23 Jun 2017 14:58:37 -0400 Subject: sparc64: check if a client is allowed to register for MDESC notifications Check if a client is supported, by comparing against a whitelist, to register for notifications from Machine Description (MDESC) Signed-off-by: Jagannathan Raman Reviewed-by: Liam Merwick Reviewed-by: Shannon Nelson Signed-off-by: David S. Miller --- arch/sparc/kernel/mdesc.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'arch') diff --git a/arch/sparc/kernel/mdesc.c b/arch/sparc/kernel/mdesc.c index 04b76267ddfa..f795ee015738 100644 --- a/arch/sparc/kernel/mdesc.c +++ b/arch/sparc/kernel/mdesc.c @@ -284,9 +284,26 @@ static struct mdesc_notifier_client *client_list; void mdesc_register_notifier(struct mdesc_notifier_client *client) { + bool supported = false; u64 node; + int i; mutex_lock(&mdesc_mutex); + + /* check to see if the node is supported for registration */ + for (i = 0; md_node_ops_table[i].name != NULL; i++) { + if (strcmp(md_node_ops_table[i].name, client->node_name) == 0) { + supported = true; + break; + } + } + + if (!supported) { + pr_err("MD: %s node not supported\n", client->node_name); + mutex_unlock(&mdesc_mutex); + return; + } + client->next = client_list; client_list = client; -- cgit v1.2.3 From aa512d5edeab267d612c6be93eb6a2368ee7a6d6 Mon Sep 17 00:00:00 2001 From: Jag Raman Date: Fri, 23 Jun 2017 14:58:38 -0400 Subject: sparc64: enhance VIO device probing - Allocate IRQs for VIO devices during probing. - Allow clients to specify if IRQs would be allocated for a given VIO device. - Cache the device handle of the root node of channel-devices sub-tree in Machine Description (MDESC). Signed-off-by: Jagannathan Raman Reviewed-by: Liam Merwick Reviewed-by: Shannon Nelson Signed-off-by: David S. Miller --- arch/sparc/include/asm/vio.h | 5 +++++ arch/sparc/kernel/vio.c | 53 +++++++++++++++++++++++++++++++------------- 2 files changed, 42 insertions(+), 16 deletions(-) (limited to 'arch') diff --git a/arch/sparc/include/asm/vio.h b/arch/sparc/include/asm/vio.h index 69cb3a5ff8cf..d8eb195b69e3 100644 --- a/arch/sparc/include/asm/vio.h +++ b/arch/sparc/include/asm/vio.h @@ -336,6 +336,10 @@ struct vio_dev { unsigned int tx_irq; unsigned int rx_irq; u64 rx_ino; + u64 tx_ino; + + /* Handle to the root of "channel-devices" sub-tree in MDESC */ + u64 cdev_handle; struct device dev; }; @@ -349,6 +353,7 @@ struct vio_driver { void (*shutdown)(struct vio_dev *dev); unsigned long driver_data; struct device_driver driver; + bool no_irq; }; struct vio_version { diff --git a/arch/sparc/kernel/vio.c b/arch/sparc/kernel/vio.c index 0890a25b30a4..ea63f02cab3f 100644 --- a/arch/sparc/kernel/vio.c +++ b/arch/sparc/kernel/vio.c @@ -70,15 +70,26 @@ static int vio_device_probe(struct device *dev) struct vio_dev *vdev = to_vio_dev(dev); struct vio_driver *drv = to_vio_driver(dev->driver); const struct vio_device_id *id; - int error = -ENODEV; - if (drv->probe) { - id = vio_match_device(drv->id_table, vdev); - if (id) - error = drv->probe(vdev, id); + if (!drv->probe) + return -ENODEV; + + id = vio_match_device(drv->id_table, vdev); + if (!id) + return -ENODEV; + + /* alloc irqs (unless the driver specified not to) */ + if (!drv->no_irq) { + if (vdev->tx_irq == 0 && vdev->tx_ino != ~0UL) + vdev->tx_irq = sun4v_build_virq(vdev->cdev_handle, + vdev->tx_ino); + + if (vdev->rx_irq == 0 && vdev->rx_ino != ~0UL) + vdev->rx_irq = sun4v_build_virq(vdev->cdev_handle, + vdev->rx_ino); } - return error; + return drv->probe(vdev, id); } static int vio_device_remove(struct device *dev) @@ -86,8 +97,15 @@ static int vio_device_remove(struct device *dev) struct vio_dev *vdev = to_vio_dev(dev); struct vio_driver *drv = to_vio_driver(dev->driver); - if (drv->remove) + if (drv->remove) { + /* + * Ideally, we would remove/deallocate tx/rx virqs + * here - however, there are currently no support + * routines to do so at the moment. TBD + */ + return drv->remove(vdev); + } return 1; } @@ -204,6 +222,9 @@ static void vio_fill_channel_info(struct mdesc_handle *hp, u64 mp, { u64 a; + vdev->tx_ino = ~0UL; + vdev->rx_ino = ~0UL; + vdev->channel_id = ~0UL; mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_FWD) { const u64 *chan_id; const u64 *irq; @@ -213,18 +234,18 @@ static void vio_fill_channel_info(struct mdesc_handle *hp, u64 mp, irq = mdesc_get_property(hp, target, "tx-ino", NULL); if (irq) - vdev->tx_irq = sun4v_build_virq(cdev_cfg_handle, *irq); + vdev->tx_ino = *irq; irq = mdesc_get_property(hp, target, "rx-ino", NULL); - if (irq) { - vdev->rx_irq = sun4v_build_virq(cdev_cfg_handle, *irq); + if (irq) vdev->rx_ino = *irq; - } chan_id = mdesc_get_property(hp, target, "id", NULL); if (chan_id) vdev->channel_id = *chan_id; } + + vdev->cdev_handle = cdev_cfg_handle; } int vio_set_intr(unsigned long dev_ino, int state) @@ -287,9 +308,8 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, memset(vdev->compat, 0, sizeof(vdev->compat)); vdev->compat_len = clen; - vdev->channel_id = ~0UL; - vdev->tx_irq = ~0; - vdev->rx_irq = ~0; + vdev->tx_irq = 0; + vdev->rx_irq = 0; vio_fill_channel_info(hp, mp, vdev); @@ -327,13 +347,14 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, } vdev->dp = dp; - printk(KERN_INFO "VIO: Adding device %s\n", dev_name(&vdev->dev)); - /* node_name is NULL for the parent/channel-devices node */ if (node_name != NULL) (void) snprintf(vdev->node_name, VIO_MAX_NAME_LEN, "%s", node_name); + pr_info("VIO: Adding device %s (tx_ino = %llx, rx_ino = %llx)\n", + dev_name(&vdev->dev), vdev->tx_ino, vdev->rx_ino); + err = device_register(&vdev->dev); if (err) { printk(KERN_ERR "VIO: Could not register device %s, err=%d\n", -- cgit v1.2.3 From f4d29ca7defdec9c8010a20a9ce10a71462a9978 Mon Sep 17 00:00:00 2001 From: Jag Raman Date: Fri, 23 Jun 2017 14:58:39 -0400 Subject: sparc64: Enhance search for VIO device in MDESC Enhances search for VIO device in MDESC by leveraging already existing MDESC APIs. Enhances changes in earlier patch, "sparc: Machine description indices can vary", by using existing MD search functions. It also specifies a match function, thereby enabling device_find_child() to use it for the purpose of matching device nodes in MDESC. An API to find VDEV node in MDESC based on its md_node_info is also added. It is planned to be used by VIO device clients in the future. Signed-off-by: Jagannathan Raman Reviewed-by: Liam Merwick Reviewed-by: Shannon Nelson Signed-off-by: David S. Miller --- arch/sparc/include/asm/vio.h | 5 +- arch/sparc/kernel/mdesc.c | 2 + arch/sparc/kernel/vio.c | 120 +++++++++++++++++++++---------------------- 3 files changed, 64 insertions(+), 63 deletions(-) (limited to 'arch') diff --git a/arch/sparc/include/asm/vio.h b/arch/sparc/include/asm/vio.h index d8eb195b69e3..25ede61c0386 100644 --- a/arch/sparc/include/asm/vio.h +++ b/arch/sparc/include/asm/vio.h @@ -329,7 +329,6 @@ struct vio_dev { int compat_len; u64 dev_no; - u64 id; unsigned long channel_id; @@ -341,6 +340,9 @@ struct vio_dev { /* Handle to the root of "channel-devices" sub-tree in MDESC */ u64 cdev_handle; + /* MD specific data used to identify the vdev in MD */ + union md_node_info md_node_info; + struct device dev; }; @@ -497,5 +499,6 @@ int vio_driver_init(struct vio_driver_state *vio, struct vio_dev *vdev, void vio_port_up(struct vio_driver_state *vio); int vio_set_intr(unsigned long dev_ino, int state); +u64 vio_vdev_node(struct mdesc_handle *hp, struct vio_dev *vdev); #endif /* _SPARC64_VIO_H */ diff --git a/arch/sparc/kernel/mdesc.c b/arch/sparc/kernel/mdesc.c index f795ee015738..e4b4e790bf89 100644 --- a/arch/sparc/kernel/mdesc.c +++ b/arch/sparc/kernel/mdesc.c @@ -574,6 +574,7 @@ u64 mdesc_get_node(struct mdesc_handle *hp, const char *node_name, return hp_node; } +EXPORT_SYMBOL(mdesc_get_node); int mdesc_get_node_info(struct mdesc_handle *hp, u64 node, const char *node_name, union md_node_info *node_info) @@ -603,6 +604,7 @@ int mdesc_get_node_info(struct mdesc_handle *hp, u64 node, return 0; } +EXPORT_SYMBOL(mdesc_get_node_info); static struct mdesc_elem *node_block(struct mdesc_hdr *mdesc) { diff --git a/arch/sparc/kernel/vio.c b/arch/sparc/kernel/vio.c index ea63f02cab3f..624f0a98edfe 100644 --- a/arch/sparc/kernel/vio.c +++ b/arch/sparc/kernel/vio.c @@ -217,6 +217,32 @@ static const u64 *vio_cfg_handle(struct mdesc_handle *hp, u64 node) return cfg_handle; } +/** + * vio_vdev_node() - Find VDEV node in MD + * @hp: Handle to the MD + * @vdev: Pointer to VDEV + * + * Find the node in the current MD which matches the given vio_dev. This + * must be done dynamically since the node value can change if the MD + * is updated. + * + * NOTE: the MD must be locked, using mdesc_grab(), when calling this routine + * + * Return: The VDEV node in MDESC + */ +u64 vio_vdev_node(struct mdesc_handle *hp, struct vio_dev *vdev) +{ + u64 node; + + if (vdev == NULL) + return MDESC_NODE_NULL; + + node = mdesc_get_node(hp, (const char *)vdev->node_name, + &vdev->md_node_info); + + return node; +} + static void vio_fill_channel_info(struct mdesc_handle *hp, u64 mp, struct vio_dev *vdev) { @@ -316,16 +342,13 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, if (!id) { dev_set_name(&vdev->dev, "%s", type); vdev->dev_no = ~(u64)0; - vdev->id = ~(u64)0; } else if (!cfg_handle) { dev_set_name(&vdev->dev, "%s-%llu", type, *id); vdev->dev_no = *id; - vdev->id = ~(u64)0; } else { dev_set_name(&vdev->dev, "%s-%llu-%llu", type, *cfg_handle, *id); vdev->dev_no = *cfg_handle; - vdev->id = *id; } vdev->dev.parent = parent; @@ -347,11 +370,24 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, } vdev->dp = dp; - /* node_name is NULL for the parent/channel-devices node */ - if (node_name != NULL) + /* + * node_name is NULL for the parent/channel-devices node and + * the parent doesn't require the MD node info. + */ + if (node_name != NULL) { (void) snprintf(vdev->node_name, VIO_MAX_NAME_LEN, "%s", node_name); + err = mdesc_get_node_info(hp, mp, node_name, + &vdev->md_node_info); + if (err) { + pr_err("VIO: Could not get MD node info %s, err=%d\n", + dev_name(&vdev->dev), err); + kfree(vdev); + return NULL; + } + } + pr_info("VIO: Adding device %s (tx_ino = %llx, rx_ino = %llx)\n", dev_name(&vdev->dev), vdev->tx_ino, vdev->rx_ino); @@ -375,68 +411,36 @@ static void vio_add(struct mdesc_handle *hp, u64 node, (void) vio_create_one(hp, node, node_name, &root_vdev->dev); } -struct vio_md_node_query { - const char *type; - u64 dev_no; - u64 id; +struct vio_remove_node_data { + struct mdesc_handle *hp; + u64 node; }; static int vio_md_node_match(struct device *dev, void *arg) { - struct vio_md_node_query *query = (struct vio_md_node_query *) arg; struct vio_dev *vdev = to_vio_dev(dev); + struct vio_remove_node_data *node_data; + u64 node; - if (vdev->dev_no != query->dev_no) - return 0; - if (vdev->id != query->id) - return 0; - if (strcmp(vdev->type, query->type)) - return 0; + node_data = (struct vio_remove_node_data *)arg; - return 1; + node = vio_vdev_node(node_data->hp, vdev); + + if (node == node_data->node) + return 1; + else + return 0; } static void vio_remove(struct mdesc_handle *hp, u64 node, const char *node_name) { - const char *type; - const u64 *id, *cfg_handle; - u64 a; - struct vio_md_node_query query; + struct vio_remove_node_data node_data; struct device *dev; - type = mdesc_get_property(hp, node, "device-type", NULL); - if (!type) { - type = mdesc_get_property(hp, node, "name", NULL); - if (!type) - type = mdesc_node_name(hp, node); - } - - query.type = type; - - id = mdesc_get_property(hp, node, "id", NULL); - cfg_handle = NULL; - mdesc_for_each_arc(a, hp, node, MDESC_ARC_TYPE_BACK) { - u64 target; - - target = mdesc_arc_target(hp, a); - cfg_handle = mdesc_get_property(hp, target, - "cfg-handle", NULL); - if (cfg_handle) - break; - } - - if (!id) { - query.dev_no = ~(u64)0; - query.id = ~(u64)0; - } else if (!cfg_handle) { - query.dev_no = *id; - query.id = ~(u64)0; - } else { - query.dev_no = *cfg_handle; - query.id = *id; - } + node_data.hp = hp; + node_data.node = node; - dev = device_find_child(&root_vdev->dev, &query, + dev = device_find_child(&root_vdev->dev, (void *)&node_data, vio_md_node_match); if (dev) { printk(KERN_INFO "VIO: Removing device %s\n", dev_name(dev)); @@ -444,15 +448,7 @@ static void vio_remove(struct mdesc_handle *hp, u64 node, const char *node_name) device_unregister(dev); put_device(dev); } else { - if (!id) - printk(KERN_ERR "VIO: Removed unknown %s node.\n", - type); - else if (!cfg_handle) - printk(KERN_ERR "VIO: Removed unknown %s node %llu.\n", - type, *id); - else - printk(KERN_ERR "VIO: Removed unknown %s node %llu-%llu.\n", - type, *cfg_handle, *id); + pr_err("VIO: %s node not found in MDESC\n", node_name); } } -- cgit v1.2.3 From 15c35e4ebbe16a205856e033627e50936ab7cd99 Mon Sep 17 00:00:00 2001 From: Jag Raman Date: Fri, 23 Jun 2017 14:58:40 -0400 Subject: sparc64: add port_id to VIO device metadata Add port_id field to VIO device metadata to identify the port of VIO device. Signed-off-by: Jagannathan Raman Reviewed-by: Liam Merwick Reviewed-by: Shannon Nelson Signed-off-by: David S. Miller --- arch/sparc/include/asm/vio.h | 1 + arch/sparc/kernel/vio.c | 2 ++ 2 files changed, 3 insertions(+) (limited to 'arch') diff --git a/arch/sparc/include/asm/vio.h b/arch/sparc/include/asm/vio.h index 25ede61c0386..d1c47e9f0090 100644 --- a/arch/sparc/include/asm/vio.h +++ b/arch/sparc/include/asm/vio.h @@ -330,6 +330,7 @@ struct vio_dev { u64 dev_no; + unsigned long port_id; unsigned long channel_id; unsigned int tx_irq; diff --git a/arch/sparc/kernel/vio.c b/arch/sparc/kernel/vio.c index 624f0a98edfe..6715fc36e0e9 100644 --- a/arch/sparc/kernel/vio.c +++ b/arch/sparc/kernel/vio.c @@ -334,6 +334,7 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, memset(vdev->compat, 0, sizeof(vdev->compat)); vdev->compat_len = clen; + vdev->port_id = ~0UL; vdev->tx_irq = 0; vdev->rx_irq = 0; @@ -349,6 +350,7 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, dev_set_name(&vdev->dev, "%s-%llu-%llu", type, *cfg_handle, *id); vdev->dev_no = *cfg_handle; + vdev->port_id = *id; } vdev->dev.parent = parent; -- cgit v1.2.3