Re: [PATCH 6/6] usb: typec: Link all ports during connector registration

2021-03-25 Thread kernel test robot
Hi Heikki,

I love your patch! Yet something to improve:

[auto build test ERROR on peter.chen-usb/for-usb-next]
[also build test ERROR on linus/master v5.12-rc4 next-20210325]
[cannot apply to usb/usb-testing chrome-platform-linux/for-next 
balbi-usb/testing/next]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:
https://github.com/0day-ci/linux/commits/Heikki-Krogerus/usb-Linking-ports-to-their-Type-C-connectors/20210325-203239
base:   https://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/usb.git 
for-usb-next
config: i386-randconfig-a015-20210325 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-22) 9.3.0
reproduce (this is a W=1 build):
# 
https://github.com/0day-ci/linux/commit/3f5d8681c4754fba373563812803b8d5eb11639a
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review 
Heikki-Krogerus/usb-Linking-ports-to-their-Type-C-connectors/20210325-203239
git checkout 3f5d8681c4754fba373563812803b8d5eb11639a
# save the attached .config to linux build tree
make W=1 ARCH=i386 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot 

All errors (new ones prefixed by >>):

   ld: drivers/usb/typec/port-mapper.o: in function `typec_link_ports':
>> drivers/usb/typec/port-mapper.c:260: undefined reference to 
>> `usb_for_each_port'


vim +260 drivers/usb/typec/port-mapper.c

   251  
   252  int typec_link_ports(struct typec_port *con)
   253  {
   254  int ret;
   255  
   256  con->pld = get_pld(>dev);
   257  if (!con->pld)
   258  return 0;
   259  
 > 260  ret = usb_for_each_port(>dev, connector_match);
   261  if (ret)
   262  typec_unlink_ports(con);
   263  
   264  return ret;
   265  }
   266  

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-...@lists.01.org


.config.gz
Description: application/gzip


[PATCH 6/6] usb: typec: Link all ports during connector registration

2021-03-25 Thread Heikki Krogerus
The connectors may be registered after the ports, so the
"connector" links need to be created for the ports also when
ever a new connector gets registered.

Signed-off-by: Heikki Krogerus 
---
 drivers/usb/typec/class.c   |  9 +++--
 drivers/usb/typec/class.h   | 10 +++---
 drivers/usb/typec/port-mapper.c | 62 +++--
 3 files changed, 71 insertions(+), 10 deletions(-)

diff --git a/drivers/usb/typec/class.c b/drivers/usb/typec/class.c
index ff199e2d26c7b..f1c2d823c6509 100644
--- a/drivers/usb/typec/class.c
+++ b/drivers/usb/typec/class.c
@@ -1601,7 +1601,6 @@ static void typec_release(struct device *dev)
ida_destroy(>mode_ids);
typec_switch_put(port->sw);
typec_mux_put(port->mux);
-   free_pld(port->pld);
kfree(port->cap);
kfree(port);
 }
@@ -2027,7 +2026,9 @@ struct typec_port *typec_register_port(struct device 
*parent,
return ERR_PTR(ret);
}
 
-   port->pld = get_pld(>dev);
+   ret = typec_link_ports(port);
+   if (ret)
+   dev_warn(>dev, "failed to create symlinks (%d)\n", ret);
 
return port;
 }
@@ -2041,8 +2042,10 @@ EXPORT_SYMBOL_GPL(typec_register_port);
  */
 void typec_unregister_port(struct typec_port *port)
 {
-   if (!IS_ERR_OR_NULL(port))
+   if (!IS_ERR_OR_NULL(port)) {
+   typec_unlink_ports(port);
device_unregister(>dev);
+   }
 }
 EXPORT_SYMBOL_GPL(typec_unregister_port);
 
diff --git a/drivers/usb/typec/class.h b/drivers/usb/typec/class.h
index f3bc4d175d79c..a6a034f49c228 100644
--- a/drivers/usb/typec/class.h
+++ b/drivers/usb/typec/class.h
@@ -80,15 +80,15 @@ extern struct class typec_mux_class;
 extern struct class typec_class;
 
 #ifdef CONFIG_ACPI
-void *get_pld(struct device *dev);
-void free_pld(void *pld);
+int typec_link_ports(struct typec_port *connector);
+void typec_unlink_ports(struct typec_port *connector);
 #else
-static inline void *get_pld(struct device *dev)
+static inline int typec_link_ports(struct typec_port *connector)
 {
-   return NULL;
+   return 0;
 }
 
-static inline void free_pld(void *pld) { }
+static inline void typec_unlink_ports(struct typec_port *connector) { }
 #endif
 
 #endif /* __USB_TYPEC_CLASS__ */
diff --git a/drivers/usb/typec/port-mapper.c b/drivers/usb/typec/port-mapper.c
index 97264a4f11967..98eda37d99117 100644
--- a/drivers/usb/typec/port-mapper.c
+++ b/drivers/usb/typec/port-mapper.c
@@ -34,7 +34,7 @@ static int acpi_pld_match(const struct acpi_pld_info *pld1,
return 0;
 }
 
-void *get_pld(struct device *dev)
+static void *get_pld(struct device *dev)
 {
struct acpi_pld_info *pld;
acpi_status status;
@@ -49,7 +49,7 @@ void *get_pld(struct device *dev)
return pld;
 }
 
-void free_pld(void *pld)
+static void free_pld(void *pld)
 {
ACPI_FREE(pld);
 }
@@ -223,3 +223,61 @@ void typec_unlink_port(struct device *port)
put_device(data.connector);
 }
 EXPORT_SYMBOL_GPL(typec_unlink_port);
+
+static int connector_match(struct device *port, void *connector)
+{
+   struct port_node *node;
+   int ret;
+
+   node = create_port_node(port);
+   if (IS_ERR(node))
+   return PTR_ERR(node);
+
+   if (!node->pld || !connector_pld_match(connector, node->pld)) {
+   remove_port_node(node);
+   return 0;
+   }
+
+   ret = link_port(to_typec_port(connector), node);
+   if (ret) {
+   remove_port_node(node->pld);
+   return ret;
+   }
+
+   get_device(connector);
+
+   return 0;
+}
+
+int typec_link_ports(struct typec_port *con)
+{
+   int ret;
+
+   con->pld = get_pld(>dev);
+   if (!con->pld)
+   return 0;
+
+   ret = usb_for_each_port(>dev, connector_match);
+   if (ret)
+   typec_unlink_ports(con);
+
+   return ret;
+}
+
+void typec_unlink_ports(struct typec_port *con)
+{
+   struct port_node *node;
+   struct port_node *tmp;
+
+   mutex_lock(>port_list_lock);
+
+   list_for_each_entry_safe(node, tmp, >port_list, list) {
+   __unlink_port(con, node);
+   remove_port_node(node);
+   put_device(>dev);
+   }
+
+   mutex_unlock(>port_list_lock);
+
+   free_pld(con->pld);
+}
-- 
2.30.2