[rgushchin:fix_stock_sync 128/139] htmldocs: drivers/gpu/drm/drm_dp_mst_topology.c:1594: warning: Function parameter or member 'connector' not described in 'drm_dp_mst_connector_late_register'

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Andrew,

First bad commit (maybe != root cause):

tree:   https://github.com/rgushchin/linux.git fix_stock_sync
head:   77c1d66e244190589ac167eacbd3df0d4a15d53f
commit: 32c23264144055cd71160d785f9f04a7236451e8 [128/139] linux-next-git-rejects
reproduce: make htmldocs

If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <lkp@xxxxxxxxx>

All warnings (new ones prefixed by >>):

   include/linux/skbuff.h:881: warning: Function parameter or member 'remcsum_offload' not described in 'sk_buff'
   include/linux/skbuff.h:881: warning: Function parameter or member 'sender_cpu' not described in 'sk_buff'
   include/linux/skbuff.h:881: warning: Function parameter or member 'reserved_tailroom' not described in 'sk_buff'
   include/linux/skbuff.h:881: warning: Function parameter or member 'inner_ipproto' not described in 'sk_buff'
   include/net/sock.h:233: warning: Function parameter or member 'skc_addrpair' not described in 'sock_common'
   include/net/sock.h:233: warning: Function parameter or member 'skc_portpair' not described in 'sock_common'
   include/net/sock.h:233: warning: Function parameter or member 'skc_ipv6only' not described in 'sock_common'
   include/net/sock.h:233: warning: Function parameter or member 'skc_net_refcnt' not described in 'sock_common'
   include/net/sock.h:233: warning: Function parameter or member 'skc_v6_daddr' not described in 'sock_common'
   include/net/sock.h:233: warning: Function parameter or member 'skc_v6_rcv_saddr' not described in 'sock_common'
   include/net/sock.h:233: warning: Function parameter or member 'skc_cookie' not described in 'sock_common'
   include/net/sock.h:233: warning: Function parameter or member 'skc_listener' not described in 'sock_common'
   include/net/sock.h:233: warning: Function parameter or member 'skc_tw_dr' not described in 'sock_common'
   include/net/sock.h:233: warning: Function parameter or member 'skc_rcv_wnd' not described in 'sock_common'
   include/net/sock.h:233: warning: Function parameter or member 'skc_tw_rcv_nxt' not described in 'sock_common'
   include/net/sock.h:515: warning: Function parameter or member 'sk_rx_skb_cache' not described in 'sock'
   include/net/sock.h:515: warning: Function parameter or member 'sk_wq_raw' not described in 'sock'
   include/net/sock.h:515: warning: Function parameter or member 'tcp_rtx_queue' not described in 'sock'
   include/net/sock.h:515: warning: Function parameter or member 'sk_tx_skb_cache' not described in 'sock'
   include/net/sock.h:515: warning: Function parameter or member 'sk_route_forced_caps' not described in 'sock'
   include/net/sock.h:515: warning: Function parameter or member 'sk_txtime_report_errors' not described in 'sock'
   include/net/sock.h:515: warning: Function parameter or member 'sk_validate_xmit_skb' not described in 'sock'
   include/net/sock.h:515: warning: Function parameter or member 'sk_bpf_storage' not described in 'sock'
   include/net/sock.h:2439: warning: Function parameter or member 'tcp_rx_skb_cache_key' not described in 'DECLARE_STATIC_KEY_FALSE'
   include/net/sock.h:2439: warning: Excess function parameter 'sk' description in 'DECLARE_STATIC_KEY_FALSE'
   include/net/sock.h:2439: warning: Excess function parameter 'skb' description in 'DECLARE_STATIC_KEY_FALSE'
   include/linux/netdevice.h:2040: warning: Function parameter or member 'gso_partial_features' not described in 'net_device'
   include/linux/netdevice.h:2040: warning: Function parameter or member 'l3mdev_ops' not described in 'net_device'
   include/linux/netdevice.h:2040: warning: Function parameter or member 'xfrmdev_ops' not described in 'net_device'
   include/linux/netdevice.h:2040: warning: Function parameter or member 'tlsdev_ops' not described in 'net_device'
   include/linux/netdevice.h:2040: warning: Function parameter or member 'name_assign_type' not described in 'net_device'
   include/linux/netdevice.h:2040: warning: Function parameter or member 'ieee802154_ptr' not described in 'net_device'
   include/linux/netdevice.h:2040: warning: Function parameter or member 'mpls_ptr' not described in 'net_device'
   include/linux/netdevice.h:2040: warning: Function parameter or member 'xdp_prog' not described in 'net_device'
   include/linux/netdevice.h:2040: warning: Function parameter or member 'gro_flush_timeout' not described in 'net_device'
   include/linux/netdevice.h:2040: warning: Function parameter or member 'nf_hooks_ingress' not described in 'net_device'
   include/linux/netdevice.h:2040: warning: Function parameter or member '____cacheline_aligned_in_smp' not described in 'net_device'
   include/linux/netdevice.h:2040: warning: Function parameter or member 'qdisc_hash' not described in 'net_device'
   include/linux/netdevice.h:2040: warning: Function parameter or member 'xps_cpus_map' not described in 'net_device'
   include/linux/netdevice.h:2040: warning: Function parameter or member 'xps_rxqs_map' not described in 'net_device'
   include/linux/phylink.h:56: warning: Function parameter or member '__ETHTOOL_DECLARE_LINK_MODE_MASK(advertising' not described in 'phylink_link_state'
   include/linux/phylink.h:56: warning: Function parameter or member '__ETHTOOL_DECLARE_LINK_MODE_MASK(lp_advertising' not described in 'phylink_link_state'
   drivers/net/phy/phylink.c:593: warning: Function parameter or member 'config' not described in 'phylink_create'
   drivers/net/phy/phylink.c:593: warning: Excess function parameter 'ndev' description in 'phylink_create'
   include/linux/lsm_hooks.h:1811: warning: Function parameter or member 'quotactl' not described in 'security_list_options'
   include/linux/lsm_hooks.h:1811: warning: Function parameter or member 'quota_on' not described in 'security_list_options'
   include/linux/lsm_hooks.h:1811: warning: Function parameter or member 'sb_free_mnt_opts' not described in 'security_list_options'
   include/linux/lsm_hooks.h:1811: warning: Function parameter or member 'sb_eat_lsm_opts' not described in 'security_list_options'
   include/linux/lsm_hooks.h:1811: warning: Function parameter or member 'sb_kern_mount' not described in 'security_list_options'
   include/linux/lsm_hooks.h:1811: warning: Function parameter or member 'sb_show_options' not described in 'security_list_options'
   include/linux/lsm_hooks.h:1811: warning: Function parameter or member 'sb_add_mnt_opt' not described in 'security_list_options'
   include/linux/lsm_hooks.h:1811: warning: Function parameter or member 'd_instantiate' not described in 'security_list_options'
   include/linux/lsm_hooks.h:1811: warning: Function parameter or member 'getprocattr' not described in 'security_list_options'
   include/linux/lsm_hooks.h:1811: warning: Function parameter or member 'setprocattr' not described in 'security_list_options'
   drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c:350: warning: Excess function parameter 'dev' description in 'amdgpu_gem_prime_export'
   drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c:351: warning: Excess function parameter 'dev' description in 'amdgpu_gem_prime_export'
   drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c:142: warning: Function parameter or member 'blockable' not described in 'amdgpu_mn_read_lock'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:347: warning: cannot understand function prototype: 'struct amdgpu_vm_pt_cursor '
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:348: warning: cannot understand function prototype: 'struct amdgpu_vm_pt_cursor '
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:494: warning: Function parameter or member 'start' not described in 'amdgpu_vm_pt_first_dfs'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:546: warning: Function parameter or member 'adev' not described in 'for_each_amdgpu_vm_pt_dfs_safe'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:546: warning: Function parameter or member 'vm' not described in 'for_each_amdgpu_vm_pt_dfs_safe'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:546: warning: Function parameter or member 'start' not described in 'for_each_amdgpu_vm_pt_dfs_safe'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:546: warning: Function parameter or member 'cursor' not described in 'for_each_amdgpu_vm_pt_dfs_safe'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:546: warning: Function parameter or member 'entry' not described in 'for_each_amdgpu_vm_pt_dfs_safe'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:823: warning: Function parameter or member 'level' not described in 'amdgpu_vm_bo_param'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1285: warning: Function parameter or member 'params' not described in 'amdgpu_vm_update_flags'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1285: warning: Function parameter or member 'bo' not described in 'amdgpu_vm_update_flags'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1285: warning: Function parameter or member 'level' not described in 'amdgpu_vm_update_flags'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1285: warning: Function parameter or member 'pe' not described in 'amdgpu_vm_update_flags'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1285: warning: Function parameter or member 'addr' not described in 'amdgpu_vm_update_flags'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1285: warning: Function parameter or member 'count' not described in 'amdgpu_vm_update_flags'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1285: warning: Function parameter or member 'incr' not described in 'amdgpu_vm_update_flags'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1285: warning: Function parameter or member 'flags' not described in 'amdgpu_vm_update_flags'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:2822: warning: Function parameter or member 'pasid' not described in 'amdgpu_vm_make_compute'
   drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c:378: warning: Excess function parameter 'entry' description in 'amdgpu_irq_dispatch'
   drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c:379: warning: Function parameter or member 'ih' not described in 'amdgpu_irq_dispatch'
   drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c:379: warning: Excess function parameter 'entry' description in 'amdgpu_irq_dispatch'
   drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c:1: warning: no structured comments found
   drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c:1: warning: no structured comments found
   drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c:1: warning: 'pp_dpm_sclk pp_dpm_mclk pp_dpm_pcie' not found
   drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h:132: warning: Incorrect use of kernel-doc format: Documentation Makefile include scripts source @atomic_obj
   drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h:238: warning: Incorrect use of kernel-doc format: Documentation Makefile include scripts source gpu_info FW provided soc bounding box struct or 0 if not
   drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h:243: warning: Function parameter or member 'atomic_obj' not described in 'amdgpu_display_manager'
   drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h:243: warning: Function parameter or member 'backlight_link' not described in 'amdgpu_display_manager'
   drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h:243: warning: Function parameter or member 'backlight_caps' not described in 'amdgpu_display_manager'
   drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h:243: warning: Function parameter or member 'freesync_module' not described in 'amdgpu_display_manager'
   drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h:243: warning: Function parameter or member 'fw_dmcu' not described in 'amdgpu_display_manager'
   drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h:243: warning: Function parameter or member 'dmcu_fw_version' not described in 'amdgpu_display_manager'
   drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h:243: warning: Function parameter or member 'soc_bounding_box' not described in 'amdgpu_display_manager'
   drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c:1: warning: 'dm_crtc_high_irq' not found
   drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c:1: warning: 'dm_pflip_high_irq' not found
   drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c:1: warning: 'register_hpd_handlers' not found
   include/drm/drm_modeset_helper_vtables.h:1053: warning: Function parameter or member 'prepare_writeback_job' not described in 'drm_connector_helper_funcs'
   include/drm/drm_modeset_helper_vtables.h:1053: warning: Function parameter or member 'cleanup_writeback_job' not described in 'drm_connector_helper_funcs'
   include/drm/drm_atomic_state_helper.h:1: warning: no structured comments found
   drivers/gpu/drm/drm_dp_mst_topology.c:1593: warning: Excess function parameter 'drm_connector' description in 'drm_dp_mst_connector_late_register'
   drivers/gpu/drm/drm_dp_mst_topology.c:1613: warning: Excess function parameter 'drm_connector' description in 'drm_dp_mst_connector_early_unregister'
   drivers/gpu/drm/drm_dp_mst_topology.c:1593: warning: Excess function parameter 'drm_connector' description in 'drm_dp_mst_connector_late_register'
   drivers/gpu/drm/drm_dp_mst_topology.c:1613: warning: Excess function parameter 'drm_connector' description in 'drm_dp_mst_connector_early_unregister'
>> drivers/gpu/drm/drm_dp_mst_topology.c:1594: warning: Function parameter or member 'connector' not described in 'drm_dp_mst_connector_late_register'
   drivers/gpu/drm/drm_dp_mst_topology.c:1594: warning: Excess function parameter 'drm_connector' description in 'drm_dp_mst_connector_late_register'
>> drivers/gpu/drm/drm_dp_mst_topology.c:1614: warning: Function parameter or member 'connector' not described in 'drm_dp_mst_connector_early_unregister'
   drivers/gpu/drm/drm_dp_mst_topology.c:1614: warning: Excess function parameter 'drm_connector' description in 'drm_dp_mst_connector_early_unregister'
   drivers/gpu/drm/drm_dp_mst_topology.c:1593: warning: Excess function parameter 'drm_connector' description in 'drm_dp_mst_connector_late_register'
   drivers/gpu/drm/drm_dp_mst_topology.c:1613: warning: Excess function parameter 'drm_connector' description in 'drm_dp_mst_connector_early_unregister'
   drivers/gpu/drm/i915/display/intel_dpll_mgr.h:158: warning: Enum value 'DPLL_ID_TGL_MGPLL5' not described in enum 'intel_dpll_id'
   drivers/gpu/drm/i915/display/intel_dpll_mgr.h:158: warning: Enum value 'DPLL_ID_TGL_MGPLL6' not described in enum 'intel_dpll_id'
   drivers/gpu/drm/i915/display/intel_dpll_mgr.h:158: warning: Excess enum value 'DPLL_ID_TGL_TCPLL6' description in 'intel_dpll_id'
   drivers/gpu/drm/i915/display/intel_dpll_mgr.h:158: warning: Excess enum value 'DPLL_ID_TGL_TCPLL5' description in 'intel_dpll_id'
   drivers/gpu/drm/i915/display/intel_dpll_mgr.h:342: warning: Function parameter or member 'wakeref' not described in 'intel_shared_dpll'
   include/net/cfg80211.h:1092: warning: Function parameter or member 'txpwr' not described in 'station_parameters'
   include/net/mac80211.h:4043: warning: Function parameter or member 'sta_set_txpwr' not described in 'ieee80211_ops'
   include/net/mac80211.h:2006: warning: Function parameter or member 'txpwr' not described in 'ieee80211_sta'
   Documentation/admin-guide/xfs.rst:257: WARNING: Block quote ends without a blank line; unexpected unindent.
   Documentation/admin-guide/sysctl/kernel.rst:397: WARNING: Title underline too short.

vim +1594 drivers/gpu/drm/drm_dp_mst_topology.c

ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1579  
3dfd9a885fbb869 Andrew Morton        2019-07-27  1580  /**
3dfd9a885fbb869 Andrew Morton        2019-07-27  1581   * drm_dp_mst_connector_late_register() - Late MST connector registration
3dfd9a885fbb869 Andrew Morton        2019-07-27  1582   * @drm_connector: The MST connector
3dfd9a885fbb869 Andrew Morton        2019-07-27  1583   * @port: The MST port for this connector
3dfd9a885fbb869 Andrew Morton        2019-07-27  1584   *
3dfd9a885fbb869 Andrew Morton        2019-07-27  1585   * Helper to register the remote aux device for this MST port. Drivers should
3dfd9a885fbb869 Andrew Morton        2019-07-27  1586   * call this from their mst connector's late_register hook to enable MST aux
3dfd9a885fbb869 Andrew Morton        2019-07-27  1587   * devices.
3dfd9a885fbb869 Andrew Morton        2019-07-27  1588   *
3dfd9a885fbb869 Andrew Morton        2019-07-27  1589   * Return: 0 on success, negative error code on failure.
3dfd9a885fbb869 Andrew Morton        2019-07-27  1590   */
3dfd9a885fbb869 Andrew Morton        2019-07-27  1591  int drm_dp_mst_connector_late_register(struct drm_connector *connector,
3dfd9a885fbb869 Andrew Morton        2019-07-27  1592  				       struct drm_dp_mst_port *port)
3dfd9a885fbb869 Andrew Morton        2019-07-27 @1593  {
3dfd9a885fbb869 Andrew Morton        2019-07-27 @1594  	DRM_DEBUG_KMS("registering %s remote bus for %s\n",
3dfd9a885fbb869 Andrew Morton        2019-07-27  1595  		      port->aux.name, connector->kdev->kobj.name);
3dfd9a885fbb869 Andrew Morton        2019-07-27  1596  
3dfd9a885fbb869 Andrew Morton        2019-07-27  1597  	port->aux.dev = connector->kdev;
3dfd9a885fbb869 Andrew Morton        2019-07-27  1598  	return drm_dp_aux_register_devnode(&port->aux);
3dfd9a885fbb869 Andrew Morton        2019-07-27  1599  }
3dfd9a885fbb869 Andrew Morton        2019-07-27  1600  EXPORT_SYMBOL(drm_dp_mst_connector_late_register);
3dfd9a885fbb869 Andrew Morton        2019-07-27  1601  
3dfd9a885fbb869 Andrew Morton        2019-07-27  1602  /**
3dfd9a885fbb869 Andrew Morton        2019-07-27  1603   * drm_dp_mst_connector_early_unregister() - Early MST connector unregistration
3dfd9a885fbb869 Andrew Morton        2019-07-27  1604   * @drm_connector: The MST connector
3dfd9a885fbb869 Andrew Morton        2019-07-27  1605   * @port: The MST port for this connector
3dfd9a885fbb869 Andrew Morton        2019-07-27  1606   *
3dfd9a885fbb869 Andrew Morton        2019-07-27  1607   * Helper to unregister the remote aux device for this MST port, registered by
3dfd9a885fbb869 Andrew Morton        2019-07-27  1608   * drm_dp_mst_connector_late_register(). Drivers should call this from their mst
3dfd9a885fbb869 Andrew Morton        2019-07-27  1609   * connector's early_unregister hook.
3dfd9a885fbb869 Andrew Morton        2019-07-27  1610   */
3dfd9a885fbb869 Andrew Morton        2019-07-27  1611  void drm_dp_mst_connector_early_unregister(struct drm_connector *connector,
3dfd9a885fbb869 Andrew Morton        2019-07-27  1612  					   struct drm_dp_mst_port *port)
3dfd9a885fbb869 Andrew Morton        2019-07-27  1613  {
3dfd9a885fbb869 Andrew Morton        2019-07-27 @1614  	DRM_DEBUG_KMS("unregistering %s remote bus for %s\n",
3dfd9a885fbb869 Andrew Morton        2019-07-27  1615  		      port->aux.name, connector->kdev->kobj.name);
3dfd9a885fbb869 Andrew Morton        2019-07-27  1616  	drm_dp_aux_unregister_devnode(&port->aux);
3dfd9a885fbb869 Andrew Morton        2019-07-27  1617  }
3dfd9a885fbb869 Andrew Morton        2019-07-27  1618  EXPORT_SYMBOL(drm_dp_mst_connector_early_unregister);
3dfd9a885fbb869 Andrew Morton        2019-07-27  1619  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1620  static void drm_dp_add_port(struct drm_dp_mst_branch *mstb,
7b0a89a6db9a591 Dhinakaran Pandiyan  2017-01-24  1621  			    struct drm_device *dev,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1622  			    struct drm_dp_link_addr_reply_port *port_msg)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1623  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1624  	struct drm_dp_mst_port *port;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1625  	bool ret;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1626  	bool created = false;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1627  	int old_pdt = 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1628  	int old_ddps = 0;
ebcc0e6b509108b Lyude Paul           2019-01-10  1629  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1630  	port = drm_dp_get_port(mstb, port_msg->port_number);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1631  	if (!port) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1632  		port = kzalloc(sizeof(*port), GFP_KERNEL);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1633  		if (!port)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1634  			return;
ebcc0e6b509108b Lyude Paul           2019-01-10  1635  		kref_init(&port->topology_kref);
ebcc0e6b509108b Lyude Paul           2019-01-10  1636  		kref_init(&port->malloc_kref);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1637  		port->parent = mstb;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1638  		port->port_num = port_msg->port_number;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1639  		port->mgr = mstb->mgr;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1640  		port->aux.name = "DPMST";
7b0a89a6db9a591 Dhinakaran Pandiyan  2017-01-24  1641  		port->aux.dev = dev->dev;
3dfd9a885fbb869 Andrew Morton        2019-07-27  1642  		port->aux.is_remote = true;
ebcc0e6b509108b Lyude Paul           2019-01-10  1643  
ebcc0e6b509108b Lyude Paul           2019-01-10  1644  		/*
ebcc0e6b509108b Lyude Paul           2019-01-10  1645  		 * Make sure the memory allocation for our parent branch stays
ebcc0e6b509108b Lyude Paul           2019-01-10  1646  		 * around until our own memory allocation is released
ebcc0e6b509108b Lyude Paul           2019-01-10  1647  		 */
ebcc0e6b509108b Lyude Paul           2019-01-10  1648  		drm_dp_mst_get_mstb_malloc(mstb);
ebcc0e6b509108b Lyude Paul           2019-01-10  1649  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1650  		created = true;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1651  	} else {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1652  		old_pdt = port->pdt;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1653  		old_ddps = port->ddps;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1654  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1655  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1656  	port->pdt = port_msg->peer_device_type;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1657  	port->input = port_msg->input_port;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1658  	port->mcs = port_msg->mcs;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1659  	port->ddps = port_msg->ddps;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1660  	port->ldps = port_msg->legacy_device_plug_status;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1661  	port->dpcd_rev = port_msg->dpcd_revision;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1662  	port->num_sdp_streams = port_msg->num_sdp_streams;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1663  	port->num_sdp_stream_sinks = port_msg->num_sdp_stream_sinks;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1664  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1665  	/* manage mstb port lists with mgr lock - take a reference
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1666  	   for this list */
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1667  	if (created) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1668  		mutex_lock(&mstb->mgr->lock);
ebcc0e6b509108b Lyude Paul           2019-01-10  1669  		drm_dp_mst_topology_get_port(port);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1670  		list_add(&port->next, &mstb->ports);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1671  		mutex_unlock(&mstb->mgr->lock);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1672  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1673  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1674  	if (old_ddps != port->ddps) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1675  		if (port->ddps) {
3d76df632d7f4eb Lyude Paul           2019-01-10  1676  			if (!port->input) {
3d76df632d7f4eb Lyude Paul           2019-01-10  1677  				drm_dp_send_enum_path_resources(mstb->mgr,
3d76df632d7f4eb Lyude Paul           2019-01-10  1678  								mstb, port);
3d76df632d7f4eb Lyude Paul           2019-01-10  1679  			}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1680  		} else {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1681  			port->available_pbn = 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1682  		}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1683  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1684  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1685  	if (old_pdt != port->pdt && !port->input) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1686  		drm_dp_port_teardown_pdt(port, old_pdt);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1687  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1688  		ret = drm_dp_port_setup_pdt(port);
68d8c9fc91a0f63 Dave Airlie          2015-09-06  1689  		if (ret == true)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1690  			drm_dp_send_link_address(mstb->mgr, port->mstb);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1691  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1692  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1693  	if (created && !port->input) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1694  		char proppath[255];
1c960876be7cffd Dave Airlie          2015-09-16  1695  
3d76df632d7f4eb Lyude Paul           2019-01-10  1696  		build_mst_prop_path(mstb, port->port_num, proppath,
3d76df632d7f4eb Lyude Paul           2019-01-10  1697  				    sizeof(proppath));
3d76df632d7f4eb Lyude Paul           2019-01-10  1698  		port->connector = (*mstb->mgr->cbs->add_connector)(mstb->mgr,
3d76df632d7f4eb Lyude Paul           2019-01-10  1699  								   port,
3d76df632d7f4eb Lyude Paul           2019-01-10  1700  								   proppath);
df4839fdc9b3c92 Dave Airlie          2015-09-16  1701  		if (!port->connector) {
df4839fdc9b3c92 Dave Airlie          2015-09-16  1702  			/* remove it from the port list */
df4839fdc9b3c92 Dave Airlie          2015-09-16  1703  			mutex_lock(&mstb->mgr->lock);
df4839fdc9b3c92 Dave Airlie          2015-09-16  1704  			list_del(&port->next);
df4839fdc9b3c92 Dave Airlie          2015-09-16  1705  			mutex_unlock(&mstb->mgr->lock);
df4839fdc9b3c92 Dave Airlie          2015-09-16  1706  			/* drop port list reference */
d0757afd00d71dc Lyude Paul           2019-01-10  1707  			drm_dp_mst_topology_put_port(port);
df4839fdc9b3c92 Dave Airlie          2015-09-16  1708  			goto out;
df4839fdc9b3c92 Dave Airlie          2015-09-16  1709  		}
4da5caa6a6f82cd Ville Syrjälä        2016-10-26  1710  		if ((port->pdt == DP_PEER_DEVICE_DP_LEGACY_CONV ||
4da5caa6a6f82cd Ville Syrjälä        2016-10-26  1711  		     port->pdt == DP_PEER_DEVICE_SST_SINK) &&
4da5caa6a6f82cd Ville Syrjälä        2016-10-26  1712  		    port->port_num >= DP_MST_LOGICAL_PORT_0) {
3d76df632d7f4eb Lyude Paul           2019-01-10  1713  			port->cached_edid = drm_get_edid(port->connector,
3d76df632d7f4eb Lyude Paul           2019-01-10  1714  							 &port->aux.ddc);
97e14fbeb53fe06 Daniel Vetter        2018-07-09  1715  			drm_connector_set_tile_property(port->connector);
8ae22cb419ad0ba Dave Airlie          2016-02-17  1716  		}
d9515c5ec1a20c7 Dave Airlie          2015-09-16  1717  		(*mstb->mgr->cbs->register_connector)(port->connector);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1718  	}
8ae22cb419ad0ba Dave Airlie          2016-02-17  1719  
df4839fdc9b3c92 Dave Airlie          2015-09-16  1720  out:
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1721  	/* put reference to this port */
d0757afd00d71dc Lyude Paul           2019-01-10  1722  	drm_dp_mst_topology_put_port(port);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1723  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1724  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1725  static void drm_dp_update_port(struct drm_dp_mst_branch *mstb,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1726  			       struct drm_dp_connection_status_notify *conn_stat)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1727  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1728  	struct drm_dp_mst_port *port;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1729  	int old_pdt;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1730  	int old_ddps;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1731  	bool dowork = false;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1732  	port = drm_dp_get_port(mstb, conn_stat->port_number);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1733  	if (!port)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1734  		return;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1735  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1736  	old_ddps = port->ddps;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1737  	old_pdt = port->pdt;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1738  	port->pdt = conn_stat->peer_device_type;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1739  	port->mcs = conn_stat->message_capability_status;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1740  	port->ldps = conn_stat->legacy_device_plug_status;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1741  	port->ddps = conn_stat->displayport_device_plug_status;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1742  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1743  	if (old_ddps != port->ddps) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1744  		if (port->ddps) {
8ae22cb419ad0ba Dave Airlie          2016-02-17  1745  			dowork = true;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1746  		} else {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1747  			port->available_pbn = 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1748  		}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1749  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1750  	if (old_pdt != port->pdt && !port->input) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1751  		drm_dp_port_teardown_pdt(port, old_pdt);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1752  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1753  		if (drm_dp_port_setup_pdt(port))
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1754  			dowork = true;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1755  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1756  
d0757afd00d71dc Lyude Paul           2019-01-10  1757  	drm_dp_mst_topology_put_port(port);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1758  	if (dowork)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1759  		queue_work(system_long_wq, &mstb->mgr->work);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1760  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1761  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1762  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1763  static struct drm_dp_mst_branch *drm_dp_get_mst_branch_device(struct drm_dp_mst_topology_mgr *mgr,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1764  							       u8 lct, u8 *rad)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1765  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1766  	struct drm_dp_mst_branch *mstb;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1767  	struct drm_dp_mst_port *port;
ebcc0e6b509108b Lyude Paul           2019-01-10  1768  	int i, ret;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1769  	/* find the port by iterating down */
9eb1e57f564d4e6 Dave Airlie          2015-06-22  1770  
9eb1e57f564d4e6 Dave Airlie          2015-06-22  1771  	mutex_lock(&mgr->lock);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1772  	mstb = mgr->mst_primary;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1773  
23d8003907d094f Stanislav Lisovskiy  2018-11-09  1774  	if (!mstb)
23d8003907d094f Stanislav Lisovskiy  2018-11-09  1775  		goto out;
23d8003907d094f Stanislav Lisovskiy  2018-11-09  1776  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1777  	for (i = 0; i < lct - 1; i++) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1778  		int shift = (i % 2) ? 0 : 4;
7a11a334aa6af4c Mykola Lysenko       2015-12-25  1779  		int port_num = (rad[i / 2] >> shift) & 0xf;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1780  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1781  		list_for_each_entry(port, &mstb->ports, next) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1782  			if (port->port_num == port_num) {
30730c7f5943b3b Adam Richter         2015-10-16  1783  				mstb = port->mstb;
30730c7f5943b3b Adam Richter         2015-10-16  1784  				if (!mstb) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1785  					DRM_ERROR("failed to lookup MSTB with lct %d, rad %02x\n", lct, rad[0]);
30730c7f5943b3b Adam Richter         2015-10-16  1786  					goto out;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1787  				}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1788  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1789  				break;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1790  			}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1791  		}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1792  	}
ebcc0e6b509108b Lyude Paul           2019-01-10  1793  	ret = drm_dp_mst_topology_try_get_mstb(mstb);
ebcc0e6b509108b Lyude Paul           2019-01-10  1794  	if (!ret)
ebcc0e6b509108b Lyude Paul           2019-01-10  1795  		mstb = NULL;
30730c7f5943b3b Adam Richter         2015-10-16  1796  out:
9eb1e57f564d4e6 Dave Airlie          2015-06-22  1797  	mutex_unlock(&mgr->lock);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1798  	return mstb;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1799  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1800  
bd9343208704fcc Mykola Lysenko       2015-12-18  1801  static struct drm_dp_mst_branch *get_mst_branch_device_by_guid_helper(
bd9343208704fcc Mykola Lysenko       2015-12-18  1802  	struct drm_dp_mst_branch *mstb,
bd9343208704fcc Mykola Lysenko       2015-12-18  1803  	uint8_t *guid)
bd9343208704fcc Mykola Lysenko       2015-12-18  1804  {
bd9343208704fcc Mykola Lysenko       2015-12-18  1805  	struct drm_dp_mst_branch *found_mstb;
bd9343208704fcc Mykola Lysenko       2015-12-18  1806  	struct drm_dp_mst_port *port;
bd9343208704fcc Mykola Lysenko       2015-12-18  1807  
5e93b8208d3c419 Hersen Wu            2016-01-22  1808  	if (memcmp(mstb->guid, guid, 16) == 0)
5e93b8208d3c419 Hersen Wu            2016-01-22  1809  		return mstb;
5e93b8208d3c419 Hersen Wu            2016-01-22  1810  
5e93b8208d3c419 Hersen Wu            2016-01-22  1811  
bd9343208704fcc Mykola Lysenko       2015-12-18  1812  	list_for_each_entry(port, &mstb->ports, next) {
bd9343208704fcc Mykola Lysenko       2015-12-18  1813  		if (!port->mstb)
bd9343208704fcc Mykola Lysenko       2015-12-18  1814  			continue;
bd9343208704fcc Mykola Lysenko       2015-12-18  1815  
bd9343208704fcc Mykola Lysenko       2015-12-18  1816  		found_mstb = get_mst_branch_device_by_guid_helper(port->mstb, guid);
bd9343208704fcc Mykola Lysenko       2015-12-18  1817  
bd9343208704fcc Mykola Lysenko       2015-12-18  1818  		if (found_mstb)
bd9343208704fcc Mykola Lysenko       2015-12-18  1819  			return found_mstb;
bd9343208704fcc Mykola Lysenko       2015-12-18  1820  	}
bd9343208704fcc Mykola Lysenko       2015-12-18  1821  
bd9343208704fcc Mykola Lysenko       2015-12-18  1822  	return NULL;
bd9343208704fcc Mykola Lysenko       2015-12-18  1823  }
bd9343208704fcc Mykola Lysenko       2015-12-18  1824  
de6d68182f22c67 Lyude Paul           2019-01-10  1825  static struct drm_dp_mst_branch *
de6d68182f22c67 Lyude Paul           2019-01-10  1826  drm_dp_get_mst_branch_device_by_guid(struct drm_dp_mst_topology_mgr *mgr,
bd9343208704fcc Mykola Lysenko       2015-12-18  1827  				     uint8_t *guid)
bd9343208704fcc Mykola Lysenko       2015-12-18  1828  {
bd9343208704fcc Mykola Lysenko       2015-12-18  1829  	struct drm_dp_mst_branch *mstb;
ebcc0e6b509108b Lyude Paul           2019-01-10  1830  	int ret;
bd9343208704fcc Mykola Lysenko       2015-12-18  1831  
bd9343208704fcc Mykola Lysenko       2015-12-18  1832  	/* find the port by iterating down */
bd9343208704fcc Mykola Lysenko       2015-12-18  1833  	mutex_lock(&mgr->lock);
bd9343208704fcc Mykola Lysenko       2015-12-18  1834  
bd9343208704fcc Mykola Lysenko       2015-12-18  1835  	mstb = get_mst_branch_device_by_guid_helper(mgr->mst_primary, guid);
ebcc0e6b509108b Lyude Paul           2019-01-10  1836  	if (mstb) {
ebcc0e6b509108b Lyude Paul           2019-01-10  1837  		ret = drm_dp_mst_topology_try_get_mstb(mstb);
ebcc0e6b509108b Lyude Paul           2019-01-10  1838  		if (!ret)
ebcc0e6b509108b Lyude Paul           2019-01-10  1839  			mstb = NULL;
ebcc0e6b509108b Lyude Paul           2019-01-10  1840  	}
bd9343208704fcc Mykola Lysenko       2015-12-18  1841  
bd9343208704fcc Mykola Lysenko       2015-12-18  1842  	mutex_unlock(&mgr->lock);
bd9343208704fcc Mykola Lysenko       2015-12-18  1843  	return mstb;
bd9343208704fcc Mykola Lysenko       2015-12-18  1844  }
bd9343208704fcc Mykola Lysenko       2015-12-18  1845  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1846  static void drm_dp_check_and_send_link_address(struct drm_dp_mst_topology_mgr *mgr,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1847  					       struct drm_dp_mst_branch *mstb)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1848  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1849  	struct drm_dp_mst_port *port;
9254ec496a1dbdd Daniel Vetter        2015-06-22  1850  	struct drm_dp_mst_branch *mstb_child;
68d8c9fc91a0f63 Dave Airlie          2015-09-06  1851  	if (!mstb->link_address_sent)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1852  		drm_dp_send_link_address(mgr, mstb);
68d8c9fc91a0f63 Dave Airlie          2015-09-06  1853  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1854  	list_for_each_entry(port, &mstb->ports, next) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1855  		if (port->input)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1856  			continue;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1857  
8ae22cb419ad0ba Dave Airlie          2016-02-17  1858  		if (!port->ddps)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1859  			continue;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1860  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1861  		if (!port->available_pbn)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1862  			drm_dp_send_enum_path_resources(mgr, mstb, port);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1863  
9254ec496a1dbdd Daniel Vetter        2015-06-22  1864  		if (port->mstb) {
d0757afd00d71dc Lyude Paul           2019-01-10  1865  			mstb_child = drm_dp_mst_topology_get_mstb_validated(
d0757afd00d71dc Lyude Paul           2019-01-10  1866  			    mgr, port->mstb);
9254ec496a1dbdd Daniel Vetter        2015-06-22  1867  			if (mstb_child) {
9254ec496a1dbdd Daniel Vetter        2015-06-22  1868  				drm_dp_check_and_send_link_address(mgr, mstb_child);
d0757afd00d71dc Lyude Paul           2019-01-10  1869  				drm_dp_mst_topology_put_mstb(mstb_child);
9254ec496a1dbdd Daniel Vetter        2015-06-22  1870  			}
9254ec496a1dbdd Daniel Vetter        2015-06-22  1871  		}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1872  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1873  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1874  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1875  static void drm_dp_mst_link_probe_work(struct work_struct *work)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1876  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1877  	struct drm_dp_mst_topology_mgr *mgr = container_of(work, struct drm_dp_mst_topology_mgr, work);
9254ec496a1dbdd Daniel Vetter        2015-06-22  1878  	struct drm_dp_mst_branch *mstb;
ebcc0e6b509108b Lyude Paul           2019-01-10  1879  	int ret;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1880  
9254ec496a1dbdd Daniel Vetter        2015-06-22  1881  	mutex_lock(&mgr->lock);
9254ec496a1dbdd Daniel Vetter        2015-06-22  1882  	mstb = mgr->mst_primary;
9254ec496a1dbdd Daniel Vetter        2015-06-22  1883  	if (mstb) {
ebcc0e6b509108b Lyude Paul           2019-01-10  1884  		ret = drm_dp_mst_topology_try_get_mstb(mstb);
ebcc0e6b509108b Lyude Paul           2019-01-10  1885  		if (!ret)
ebcc0e6b509108b Lyude Paul           2019-01-10  1886  			mstb = NULL;
9254ec496a1dbdd Daniel Vetter        2015-06-22  1887  	}
9254ec496a1dbdd Daniel Vetter        2015-06-22  1888  	mutex_unlock(&mgr->lock);
9254ec496a1dbdd Daniel Vetter        2015-06-22  1889  	if (mstb) {
9254ec496a1dbdd Daniel Vetter        2015-06-22  1890  		drm_dp_check_and_send_link_address(mgr, mstb);
d0757afd00d71dc Lyude Paul           2019-01-10  1891  		drm_dp_mst_topology_put_mstb(mstb);
9254ec496a1dbdd Daniel Vetter        2015-06-22  1892  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1893  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1894  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1895  static bool drm_dp_validate_guid(struct drm_dp_mst_topology_mgr *mgr,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1896  				 u8 *guid)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1897  {
e38e12895022d71 Ville Syrjälä        2017-07-12  1898  	u64 salt;
e38e12895022d71 Ville Syrjälä        2017-07-12  1899  
e38e12895022d71 Ville Syrjälä        2017-07-12  1900  	if (memchr_inv(guid, 0, 16))
e38e12895022d71 Ville Syrjälä        2017-07-12  1901  		return true;
e38e12895022d71 Ville Syrjälä        2017-07-12  1902  
e38e12895022d71 Ville Syrjälä        2017-07-12  1903  	salt = get_jiffies_64();
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1904  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1905  	memcpy(&guid[0], &salt, sizeof(u64));
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1906  	memcpy(&guid[8], &salt, sizeof(u64));
e38e12895022d71 Ville Syrjälä        2017-07-12  1907  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1908  	return false;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1909  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1910  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1911  static int build_dpcd_read(struct drm_dp_sideband_msg_tx *msg, u8 port_num, u32 offset, u8 num_bytes)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1912  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1913  	struct drm_dp_sideband_msg_req_body req;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1914  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1915  	req.req_type = DP_REMOTE_DPCD_READ;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1916  	req.u.dpcd_read.port_number = port_num;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1917  	req.u.dpcd_read.dpcd_address = offset;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1918  	req.u.dpcd_read.num_bytes = num_bytes;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1919  	drm_dp_encode_sideband_req(&req, msg);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1920  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1921  	return 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1922  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1923  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1924  static int drm_dp_send_sideband_msg(struct drm_dp_mst_topology_mgr *mgr,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1925  				    bool up, u8 *msg, int len)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1926  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1927  	int ret;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1928  	int regbase = up ? DP_SIDEBAND_MSG_UP_REP_BASE : DP_SIDEBAND_MSG_DOWN_REQ_BASE;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1929  	int tosend, total, offset;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1930  	int retries = 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1931  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1932  retry:
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1933  	total = len;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1934  	offset = 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1935  	do {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1936  		tosend = min3(mgr->max_dpcd_transaction_bytes, 16, total);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1937  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1938  		ret = drm_dp_dpcd_write(mgr->aux, regbase + offset,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1939  					&msg[offset],
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1940  					tosend);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1941  		if (ret != tosend) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1942  			if (ret == -EIO && retries < 5) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1943  				retries++;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1944  				goto retry;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1945  			}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1946  			DRM_DEBUG_KMS("failed to dpcd write %d %d\n", tosend, ret);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1947  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1948  			return -EIO;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1949  		}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1950  		offset += tosend;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1951  		total -= tosend;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1952  	} while (total > 0);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1953  	return 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1954  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1955  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1956  static int set_hdr_from_dst_qlock(struct drm_dp_sideband_msg_hdr *hdr,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1957  				  struct drm_dp_sideband_msg_tx *txmsg)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1958  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1959  	struct drm_dp_mst_branch *mstb = txmsg->dst;
bd9343208704fcc Mykola Lysenko       2015-12-18  1960  	u8 req_type;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1961  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1962  	/* both msg slots are full */
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1963  	if (txmsg->seqno == -1) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1964  		if (mstb->tx_slots[0] && mstb->tx_slots[1]) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1965  			DRM_DEBUG_KMS("%s: failed to find slot\n", __func__);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1966  			return -EAGAIN;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1967  		}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1968  		if (mstb->tx_slots[0] == NULL && mstb->tx_slots[1] == NULL) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1969  			txmsg->seqno = mstb->last_seqno;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1970  			mstb->last_seqno ^= 1;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1971  		} else if (mstb->tx_slots[0] == NULL)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1972  			txmsg->seqno = 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1973  		else
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1974  			txmsg->seqno = 1;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1975  		mstb->tx_slots[txmsg->seqno] = txmsg;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1976  	}
bd9343208704fcc Mykola Lysenko       2015-12-18  1977  
bd9343208704fcc Mykola Lysenko       2015-12-18  1978  	req_type = txmsg->msg[0] & 0x7f;
bd9343208704fcc Mykola Lysenko       2015-12-18  1979  	if (req_type == DP_CONNECTION_STATUS_NOTIFY ||
bd9343208704fcc Mykola Lysenko       2015-12-18  1980  		req_type == DP_RESOURCE_STATUS_NOTIFY)
bd9343208704fcc Mykola Lysenko       2015-12-18  1981  		hdr->broadcast = 1;
bd9343208704fcc Mykola Lysenko       2015-12-18  1982  	else
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1983  		hdr->broadcast = 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1984  	hdr->path_msg = txmsg->path_msg;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1985  	hdr->lct = mstb->lct;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1986  	hdr->lcr = mstb->lct - 1;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1987  	if (mstb->lct > 1)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1988  		memcpy(hdr->rad, mstb->rad, mstb->lct / 2);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1989  	hdr->seqno = txmsg->seqno;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1990  	return 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1991  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1992  /*
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1993   * process a single block of the next message in the sideband queue
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1994   */
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1995  static int process_single_tx_qlock(struct drm_dp_mst_topology_mgr *mgr,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1996  				   struct drm_dp_sideband_msg_tx *txmsg,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1997  				   bool up)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1998  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  1999  	u8 chunk[48];
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2000  	struct drm_dp_sideband_msg_hdr hdr;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2001  	int len, space, idx, tosend;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2002  	int ret;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2003  
bf3719c04ee3322 Damien Lespiau       2014-07-14  2004  	memset(&hdr, 0, sizeof(struct drm_dp_sideband_msg_hdr));
bf3719c04ee3322 Damien Lespiau       2014-07-14  2005  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2006  	if (txmsg->state == DRM_DP_SIDEBAND_TX_QUEUED) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2007  		txmsg->seqno = -1;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2008  		txmsg->state = DRM_DP_SIDEBAND_TX_START_SEND;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2009  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2010  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2011  	/* make hdr from dst mst - for replies use seqno
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2012  	   otherwise assign one */
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2013  	ret = set_hdr_from_dst_qlock(&hdr, txmsg);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2014  	if (ret < 0)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2015  		return ret;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2016  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2017  	/* amount left to send in this message */
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2018  	len = txmsg->cur_len - txmsg->cur_offset;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2019  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2020  	/* 48 - sideband msg size - 1 byte for data CRC, x header bytes */
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2021  	space = 48 - 1 - drm_dp_calc_sb_hdr_size(&hdr);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2022  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2023  	tosend = min(len, space);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2024  	if (len == txmsg->cur_len)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2025  		hdr.somt = 1;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2026  	if (space >= len)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2027  		hdr.eomt = 1;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2028  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2029  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2030  	hdr.msg_len = tosend + 1;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2031  	drm_dp_encode_sideband_msg_hdr(&hdr, chunk, &idx);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2032  	memcpy(&chunk[idx], &txmsg->msg[txmsg->cur_offset], tosend);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2033  	/* add crc at end */
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2034  	drm_dp_crc_sideband_chunk_req(&chunk[idx], tosend);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2035  	idx += tosend + 1;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2036  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2037  	ret = drm_dp_send_sideband_msg(mgr, up, chunk, idx);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2038  	if (ret) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2039  		DRM_DEBUG_KMS("sideband msg failed to send\n");
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2040  		return ret;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2041  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2042  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2043  	txmsg->cur_offset += tosend;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2044  	if (txmsg->cur_offset == txmsg->cur_len) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2045  		txmsg->state = DRM_DP_SIDEBAND_TX_SENT;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2046  		return 1;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2047  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2048  	return 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2049  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2050  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2051  static void process_single_down_tx_qlock(struct drm_dp_mst_topology_mgr *mgr)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2052  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2053  	struct drm_dp_sideband_msg_tx *txmsg;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2054  	int ret;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2055  
cd961bb9eebb630 Daniel Vetter        2015-01-28  2056  	WARN_ON(!mutex_is_locked(&mgr->qlock));
cd961bb9eebb630 Daniel Vetter        2015-01-28  2057  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2058  	/* construct a chunk from the first msg in the tx_msg queue */
cb021a3eb6e9870 Daniel Vetter        2016-07-15  2059  	if (list_empty(&mgr->tx_msg_downq))
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2060  		return;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2061  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2062  	txmsg = list_first_entry(&mgr->tx_msg_downq, struct drm_dp_sideband_msg_tx, next);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2063  	ret = process_single_tx_qlock(mgr, txmsg, false);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2064  	if (ret == 1) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2065  		/* txmsg is sent it should be in the slots now */
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2066  		list_del(&txmsg->next);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2067  	} else if (ret) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2068  		DRM_DEBUG_KMS("failed to send msg in q %d\n", ret);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2069  		list_del(&txmsg->next);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2070  		if (txmsg->seqno != -1)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2071  			txmsg->dst->tx_slots[txmsg->seqno] = NULL;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2072  		txmsg->state = DRM_DP_SIDEBAND_TX_TIMEOUT;
68e989dc044346a Chris Wilson         2017-05-13  2073  		wake_up_all(&mgr->tx_waitq);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2074  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2075  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2076  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2077  /* called holding qlock */
1f16ee7fa13649f Mykola Lysenko       2015-12-18  2078  static void process_single_up_tx_qlock(struct drm_dp_mst_topology_mgr *mgr,
1f16ee7fa13649f Mykola Lysenko       2015-12-18  2079  				       struct drm_dp_sideband_msg_tx *txmsg)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2080  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2081  	int ret;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2082  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2083  	/* construct a chunk from the first msg in the tx_msg queue */
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2084  	ret = process_single_tx_qlock(mgr, txmsg, true);
1f16ee7fa13649f Mykola Lysenko       2015-12-18  2085  
1f16ee7fa13649f Mykola Lysenko       2015-12-18  2086  	if (ret != 1)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2087  		DRM_DEBUG_KMS("failed to send msg in q %d\n", ret);
1f16ee7fa13649f Mykola Lysenko       2015-12-18  2088  
d8fd3722207f154 Imre Deak            2019-05-24  2089  	if (txmsg->seqno != -1) {
d8fd3722207f154 Imre Deak            2019-05-24  2090  		WARN_ON((unsigned int)txmsg->seqno >
d8fd3722207f154 Imre Deak            2019-05-24  2091  			ARRAY_SIZE(txmsg->dst->tx_slots));
1f16ee7fa13649f Mykola Lysenko       2015-12-18  2092  		txmsg->dst->tx_slots[txmsg->seqno] = NULL;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2093  	}
d8fd3722207f154 Imre Deak            2019-05-24  2094  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2095  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2096  static void drm_dp_queue_down_tx(struct drm_dp_mst_topology_mgr *mgr,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2097  				 struct drm_dp_sideband_msg_tx *txmsg)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2098  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2099  	mutex_lock(&mgr->qlock);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2100  	list_add_tail(&txmsg->next, &mgr->tx_msg_downq);
cb021a3eb6e9870 Daniel Vetter        2016-07-15  2101  	if (list_is_singular(&mgr->tx_msg_downq))
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2102  		process_single_down_tx_qlock(mgr);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2103  	mutex_unlock(&mgr->qlock);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2104  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2105  
68d8c9fc91a0f63 Dave Airlie          2015-09-06  2106  static void drm_dp_send_link_address(struct drm_dp_mst_topology_mgr *mgr,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2107  				     struct drm_dp_mst_branch *mstb)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2108  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2109  	int len;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2110  	struct drm_dp_sideband_msg_tx *txmsg;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2111  	int ret;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2112  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2113  	txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2114  	if (!txmsg)
68d8c9fc91a0f63 Dave Airlie          2015-09-06  2115  		return;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2116  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2117  	txmsg->dst = mstb;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2118  	len = build_link_address(txmsg);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2119  
68d8c9fc91a0f63 Dave Airlie          2015-09-06  2120  	mstb->link_address_sent = true;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2121  	drm_dp_queue_down_tx(mgr, txmsg);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2122  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2123  	ret = drm_dp_mst_wait_tx_reply(mstb, txmsg);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2124  	if (ret > 0) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2125  		int i;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2126  
45bbda1e35f4943 Ville Syrjälä        2019-01-22  2127  		if (txmsg->reply.reply_type == DP_SIDEBAND_REPLY_NAK) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2128  			DRM_DEBUG_KMS("link address nak received\n");
45bbda1e35f4943 Ville Syrjälä        2019-01-22  2129  		} else {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2130  			DRM_DEBUG_KMS("link address reply: %d\n", txmsg->reply.u.link_addr.nports);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2131  			for (i = 0; i < txmsg->reply.u.link_addr.nports; i++) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2132  				DRM_DEBUG_KMS("port %d: input %d, pdt: %d, pn: %d, dpcd_rev: %02x, mcs: %d, ddps: %d, ldps %d, sdp %d/%d\n", i,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2133  				       txmsg->reply.u.link_addr.ports[i].input_port,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2134  				       txmsg->reply.u.link_addr.ports[i].peer_device_type,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2135  				       txmsg->reply.u.link_addr.ports[i].port_number,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2136  				       txmsg->reply.u.link_addr.ports[i].dpcd_revision,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2137  				       txmsg->reply.u.link_addr.ports[i].mcs,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2138  				       txmsg->reply.u.link_addr.ports[i].ddps,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2139  				       txmsg->reply.u.link_addr.ports[i].legacy_device_plug_status,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2140  				       txmsg->reply.u.link_addr.ports[i].num_sdp_streams,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2141  				       txmsg->reply.u.link_addr.ports[i].num_sdp_stream_sinks);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2142  			}
5e93b8208d3c419 Hersen Wu            2016-01-22  2143  
5e93b8208d3c419 Hersen Wu            2016-01-22  2144  			drm_dp_check_mstb_guid(mstb, txmsg->reply.u.link_addr.guid);
5e93b8208d3c419 Hersen Wu            2016-01-22  2145  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2146  			for (i = 0; i < txmsg->reply.u.link_addr.nports; i++) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2147  				drm_dp_add_port(mstb, mgr->dev, &txmsg->reply.u.link_addr.ports[i]);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2148  			}
16bff572cc660f1 Daniel Vetter        2018-11-28  2149  			drm_kms_helper_hotplug_event(mgr->dev);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2150  		}
68d8c9fc91a0f63 Dave Airlie          2015-09-06  2151  	} else {
68d8c9fc91a0f63 Dave Airlie          2015-09-06  2152  		mstb->link_address_sent = false;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2153  		DRM_DEBUG_KMS("link address failed %d\n", ret);
68d8c9fc91a0f63 Dave Airlie          2015-09-06  2154  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2155  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2156  	kfree(txmsg);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2157  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2158  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2159  static int drm_dp_send_enum_path_resources(struct drm_dp_mst_topology_mgr *mgr,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2160  					   struct drm_dp_mst_branch *mstb,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2161  					   struct drm_dp_mst_port *port)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2162  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2163  	int len;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2164  	struct drm_dp_sideband_msg_tx *txmsg;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2165  	int ret;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2166  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2167  	txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2168  	if (!txmsg)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2169  		return -ENOMEM;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2170  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2171  	txmsg->dst = mstb;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2172  	len = build_enum_path_resources(txmsg, port->port_num);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2173  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2174  	drm_dp_queue_down_tx(mgr, txmsg);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2175  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2176  	ret = drm_dp_mst_wait_tx_reply(mstb, txmsg);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2177  	if (ret > 0) {
45bbda1e35f4943 Ville Syrjälä        2019-01-22  2178  		if (txmsg->reply.reply_type == DP_SIDEBAND_REPLY_NAK) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2179  			DRM_DEBUG_KMS("enum path resources nak received\n");
45bbda1e35f4943 Ville Syrjälä        2019-01-22  2180  		} else {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2181  			if (port->port_num != txmsg->reply.u.path_resources.port_number)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2182  				DRM_ERROR("got incorrect port in response\n");
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2183  			DRM_DEBUG_KMS("enum path resources %d: %d %d\n", txmsg->reply.u.path_resources.port_number, txmsg->reply.u.path_resources.full_payload_bw_number,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2184  			       txmsg->reply.u.path_resources.avail_payload_bw_number);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2185  			port->available_pbn = txmsg->reply.u.path_resources.avail_payload_bw_number;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2186  		}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2187  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2188  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2189  	kfree(txmsg);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2190  	return 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2191  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2192  
91a25e463130c8e Mykola Lysenko       2016-01-27  2193  static struct drm_dp_mst_port *drm_dp_get_last_connected_port_to_mstb(struct drm_dp_mst_branch *mstb)
91a25e463130c8e Mykola Lysenko       2016-01-27  2194  {
91a25e463130c8e Mykola Lysenko       2016-01-27  2195  	if (!mstb->port_parent)
91a25e463130c8e Mykola Lysenko       2016-01-27  2196  		return NULL;
91a25e463130c8e Mykola Lysenko       2016-01-27  2197  
91a25e463130c8e Mykola Lysenko       2016-01-27  2198  	if (mstb->port_parent->mstb != mstb)
91a25e463130c8e Mykola Lysenko       2016-01-27  2199  		return mstb->port_parent;
91a25e463130c8e Mykola Lysenko       2016-01-27  2200  
91a25e463130c8e Mykola Lysenko       2016-01-27  2201  	return drm_dp_get_last_connected_port_to_mstb(mstb->port_parent->parent);
91a25e463130c8e Mykola Lysenko       2016-01-27  2202  }
91a25e463130c8e Mykola Lysenko       2016-01-27  2203  
56d1c14ecfe81d5 Lyude Paul           2019-01-10  2204  /*
56d1c14ecfe81d5 Lyude Paul           2019-01-10  2205   * Searches upwards in the topology starting from mstb to try to find the
56d1c14ecfe81d5 Lyude Paul           2019-01-10  2206   * closest available parent of mstb that's still connected to the rest of the
56d1c14ecfe81d5 Lyude Paul           2019-01-10  2207   * topology. This can be used in order to perform operations like releasing
56d1c14ecfe81d5 Lyude Paul           2019-01-10  2208   * payloads, where the branch device which owned the payload may no longer be
56d1c14ecfe81d5 Lyude Paul           2019-01-10  2209   * around and thus would require that the payload on the last living relative
56d1c14ecfe81d5 Lyude Paul           2019-01-10  2210   * be freed instead.
56d1c14ecfe81d5 Lyude Paul           2019-01-10  2211   */
56d1c14ecfe81d5 Lyude Paul           2019-01-10  2212  static struct drm_dp_mst_branch *
56d1c14ecfe81d5 Lyude Paul           2019-01-10  2213  drm_dp_get_last_connected_port_and_mstb(struct drm_dp_mst_topology_mgr *mgr,
91a25e463130c8e Mykola Lysenko       2016-01-27  2214  					struct drm_dp_mst_branch *mstb,
91a25e463130c8e Mykola Lysenko       2016-01-27  2215  					int *port_num)
91a25e463130c8e Mykola Lysenko       2016-01-27  2216  {
91a25e463130c8e Mykola Lysenko       2016-01-27  2217  	struct drm_dp_mst_branch *rmstb = NULL;
91a25e463130c8e Mykola Lysenko       2016-01-27  2218  	struct drm_dp_mst_port *found_port;
56d1c14ecfe81d5 Lyude Paul           2019-01-10  2219  
91a25e463130c8e Mykola Lysenko       2016-01-27  2220  	mutex_lock(&mgr->lock);
56d1c14ecfe81d5 Lyude Paul           2019-01-10  2221  	if (!mgr->mst_primary)
56d1c14ecfe81d5 Lyude Paul           2019-01-10  2222  		goto out;
56d1c14ecfe81d5 Lyude Paul           2019-01-10  2223  
56d1c14ecfe81d5 Lyude Paul           2019-01-10  2224  	do {
91a25e463130c8e Mykola Lysenko       2016-01-27  2225  		found_port = drm_dp_get_last_connected_port_to_mstb(mstb);
56d1c14ecfe81d5 Lyude Paul           2019-01-10  2226  		if (!found_port)
56d1c14ecfe81d5 Lyude Paul           2019-01-10  2227  			break;
91a25e463130c8e Mykola Lysenko       2016-01-27  2228  
56d1c14ecfe81d5 Lyude Paul           2019-01-10  2229  		if (drm_dp_mst_topology_try_get_mstb(found_port->parent)) {
91a25e463130c8e Mykola Lysenko       2016-01-27  2230  			rmstb = found_port->parent;
91a25e463130c8e Mykola Lysenko       2016-01-27  2231  			*port_num = found_port->port_num;
56d1c14ecfe81d5 Lyude Paul           2019-01-10  2232  		} else {
56d1c14ecfe81d5 Lyude Paul           2019-01-10  2233  			/* Search again, starting from this parent */
56d1c14ecfe81d5 Lyude Paul           2019-01-10  2234  			mstb = found_port->parent;
91a25e463130c8e Mykola Lysenko       2016-01-27  2235  		}
56d1c14ecfe81d5 Lyude Paul           2019-01-10  2236  	} while (!rmstb);
56d1c14ecfe81d5 Lyude Paul           2019-01-10  2237  out:
91a25e463130c8e Mykola Lysenko       2016-01-27  2238  	mutex_unlock(&mgr->lock);
91a25e463130c8e Mykola Lysenko       2016-01-27  2239  	return rmstb;
91a25e463130c8e Mykola Lysenko       2016-01-27  2240  }
91a25e463130c8e Mykola Lysenko       2016-01-27  2241  
8fa6a4255e80537 Thierry Reding       2014-07-21  2242  static int drm_dp_payload_send_msg(struct drm_dp_mst_topology_mgr *mgr,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2243  				   struct drm_dp_mst_port *port,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2244  				   int id,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2245  				   int pbn)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2246  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2247  	struct drm_dp_sideband_msg_tx *txmsg;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2248  	struct drm_dp_mst_branch *mstb;
91a25e463130c8e Mykola Lysenko       2016-01-27  2249  	int len, ret, port_num;
ef8f9bea1368b89 Libin Yang           2015-12-02  2250  	u8 sinks[DRM_DP_MAX_SDP_STREAMS];
ef8f9bea1368b89 Libin Yang           2015-12-02  2251  	int i;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2252  
91a25e463130c8e Mykola Lysenko       2016-01-27  2253  	port_num = port->port_num;
d0757afd00d71dc Lyude Paul           2019-01-10  2254  	mstb = drm_dp_mst_topology_get_mstb_validated(mgr, port->parent);
91a25e463130c8e Mykola Lysenko       2016-01-27  2255  	if (!mstb) {
de6d68182f22c67 Lyude Paul           2019-01-10  2256  		mstb = drm_dp_get_last_connected_port_and_mstb(mgr,
de6d68182f22c67 Lyude Paul           2019-01-10  2257  							       port->parent,
de6d68182f22c67 Lyude Paul           2019-01-10  2258  							       &port_num);
91a25e463130c8e Mykola Lysenko       2016-01-27  2259  
cfe9f90358d97a8 Lyude Paul           2019-01-10  2260  		if (!mstb)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2261  			return -EINVAL;
91a25e463130c8e Mykola Lysenko       2016-01-27  2262  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2263  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2264  	txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2265  	if (!txmsg) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2266  		ret = -ENOMEM;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2267  		goto fail_put;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2268  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2269  
ef8f9bea1368b89 Libin Yang           2015-12-02  2270  	for (i = 0; i < port->num_sdp_streams; i++)
ef8f9bea1368b89 Libin Yang           2015-12-02  2271  		sinks[i] = i;
ef8f9bea1368b89 Libin Yang           2015-12-02  2272  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2273  	txmsg->dst = mstb;
91a25e463130c8e Mykola Lysenko       2016-01-27  2274  	len = build_allocate_payload(txmsg, port_num,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2275  				     id,
ef8f9bea1368b89 Libin Yang           2015-12-02  2276  				     pbn, port->num_sdp_streams, sinks);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2277  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2278  	drm_dp_queue_down_tx(mgr, txmsg);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2279  
56d1c14ecfe81d5 Lyude Paul           2019-01-10  2280  	/*
56d1c14ecfe81d5 Lyude Paul           2019-01-10  2281  	 * FIXME: there is a small chance that between getting the last
56d1c14ecfe81d5 Lyude Paul           2019-01-10  2282  	 * connected mstb and sending the payload message, the last connected
56d1c14ecfe81d5 Lyude Paul           2019-01-10  2283  	 * mstb could also be removed from the topology. In the future, this
56d1c14ecfe81d5 Lyude Paul           2019-01-10  2284  	 * needs to be fixed by restarting the
56d1c14ecfe81d5 Lyude Paul           2019-01-10  2285  	 * drm_dp_get_last_connected_port_and_mstb() search in the event of a
56d1c14ecfe81d5 Lyude Paul           2019-01-10  2286  	 * timeout if the topology is still connected to the system.
56d1c14ecfe81d5 Lyude Paul           2019-01-10  2287  	 */
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2288  	ret = drm_dp_mst_wait_tx_reply(mstb, txmsg);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2289  	if (ret > 0) {
45bbda1e35f4943 Ville Syrjälä        2019-01-22  2290  		if (txmsg->reply.reply_type == DP_SIDEBAND_REPLY_NAK)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2291  			ret = -EINVAL;
de6d68182f22c67 Lyude Paul           2019-01-10  2292  		else
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2293  			ret = 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2294  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2295  	kfree(txmsg);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2296  fail_put:
d0757afd00d71dc Lyude Paul           2019-01-10  2297  	drm_dp_mst_topology_put_mstb(mstb);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2298  	return ret;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2299  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2300  
0bb9c2b27f5e503 Dhinakaran Pandiyan  2017-09-06  2301  int drm_dp_send_power_updown_phy(struct drm_dp_mst_topology_mgr *mgr,
0bb9c2b27f5e503 Dhinakaran Pandiyan  2017-09-06  2302  				 struct drm_dp_mst_port *port, bool power_up)
0bb9c2b27f5e503 Dhinakaran Pandiyan  2017-09-06  2303  {
0bb9c2b27f5e503 Dhinakaran Pandiyan  2017-09-06  2304  	struct drm_dp_sideband_msg_tx *txmsg;
0bb9c2b27f5e503 Dhinakaran Pandiyan  2017-09-06  2305  	int len, ret;
0bb9c2b27f5e503 Dhinakaran Pandiyan  2017-09-06  2306  
d0757afd00d71dc Lyude Paul           2019-01-10  2307  	port = drm_dp_mst_topology_get_port_validated(mgr, port);
0bb9c2b27f5e503 Dhinakaran Pandiyan  2017-09-06  2308  	if (!port)
0bb9c2b27f5e503 Dhinakaran Pandiyan  2017-09-06  2309  		return -EINVAL;
0bb9c2b27f5e503 Dhinakaran Pandiyan  2017-09-06  2310  
0bb9c2b27f5e503 Dhinakaran Pandiyan  2017-09-06  2311  	txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);
0bb9c2b27f5e503 Dhinakaran Pandiyan  2017-09-06  2312  	if (!txmsg) {
d0757afd00d71dc Lyude Paul           2019-01-10  2313  		drm_dp_mst_topology_put_port(port);
0bb9c2b27f5e503 Dhinakaran Pandiyan  2017-09-06  2314  		return -ENOMEM;
0bb9c2b27f5e503 Dhinakaran Pandiyan  2017-09-06  2315  	}
0bb9c2b27f5e503 Dhinakaran Pandiyan  2017-09-06  2316  
0bb9c2b27f5e503 Dhinakaran Pandiyan  2017-09-06  2317  	txmsg->dst = port->parent;
0bb9c2b27f5e503 Dhinakaran Pandiyan  2017-09-06  2318  	len = build_power_updown_phy(txmsg, port->port_num, power_up);
0bb9c2b27f5e503 Dhinakaran Pandiyan  2017-09-06  2319  	drm_dp_queue_down_tx(mgr, txmsg);
0bb9c2b27f5e503 Dhinakaran Pandiyan  2017-09-06  2320  
0bb9c2b27f5e503 Dhinakaran Pandiyan  2017-09-06  2321  	ret = drm_dp_mst_wait_tx_reply(port->parent, txmsg);
0bb9c2b27f5e503 Dhinakaran Pandiyan  2017-09-06  2322  	if (ret > 0) {
45bbda1e35f4943 Ville Syrjälä        2019-01-22  2323  		if (txmsg->reply.reply_type == DP_SIDEBAND_REPLY_NAK)
0bb9c2b27f5e503 Dhinakaran Pandiyan  2017-09-06  2324  			ret = -EINVAL;
0bb9c2b27f5e503 Dhinakaran Pandiyan  2017-09-06  2325  		else
0bb9c2b27f5e503 Dhinakaran Pandiyan  2017-09-06  2326  			ret = 0;
0bb9c2b27f5e503 Dhinakaran Pandiyan  2017-09-06  2327  	}
0bb9c2b27f5e503 Dhinakaran Pandiyan  2017-09-06  2328  	kfree(txmsg);
d0757afd00d71dc Lyude Paul           2019-01-10  2329  	drm_dp_mst_topology_put_port(port);
0bb9c2b27f5e503 Dhinakaran Pandiyan  2017-09-06  2330  
0bb9c2b27f5e503 Dhinakaran Pandiyan  2017-09-06  2331  	return ret;
0bb9c2b27f5e503 Dhinakaran Pandiyan  2017-09-06  2332  }
0bb9c2b27f5e503 Dhinakaran Pandiyan  2017-09-06  2333  EXPORT_SYMBOL(drm_dp_send_power_updown_phy);
0bb9c2b27f5e503 Dhinakaran Pandiyan  2017-09-06  2334  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2335  static int drm_dp_create_payload_step1(struct drm_dp_mst_topology_mgr *mgr,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2336  				       int id,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2337  				       struct drm_dp_payload *payload)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2338  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2339  	int ret;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2340  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2341  	ret = drm_dp_dpcd_write_payload(mgr, id, payload);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2342  	if (ret < 0) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2343  		payload->payload_state = 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2344  		return ret;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2345  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2346  	payload->payload_state = DP_PAYLOAD_LOCAL;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2347  	return 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2348  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2349  
8fa6a4255e80537 Thierry Reding       2014-07-21  2350  static int drm_dp_create_payload_step2(struct drm_dp_mst_topology_mgr *mgr,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2351  				       struct drm_dp_mst_port *port,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2352  				       int id,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2353  				       struct drm_dp_payload *payload)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2354  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2355  	int ret;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2356  	ret = drm_dp_payload_send_msg(mgr, port, id, port->vcpi.pbn);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2357  	if (ret < 0)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2358  		return ret;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2359  	payload->payload_state = DP_PAYLOAD_REMOTE;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2360  	return ret;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2361  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2362  
8fa6a4255e80537 Thierry Reding       2014-07-21  2363  static int drm_dp_destroy_payload_step1(struct drm_dp_mst_topology_mgr *mgr,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2364  					struct drm_dp_mst_port *port,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2365  					int id,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2366  					struct drm_dp_payload *payload)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2367  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2368  	DRM_DEBUG_KMS("\n");
1e55a53a28d3e52 Matt Roper           2019-02-01  2369  	/* it's okay for these to fail */
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2370  	if (port) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2371  		drm_dp_payload_send_msg(mgr, port, id, 0);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2372  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2373  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2374  	drm_dp_dpcd_write_payload(mgr, id, payload);
dfda0df3426483c Dave Airlie          2014-08-06  2375  	payload->payload_state = DP_PAYLOAD_DELETE_LOCAL;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2376  	return 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2377  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2378  
8fa6a4255e80537 Thierry Reding       2014-07-21  2379  static int drm_dp_destroy_payload_step2(struct drm_dp_mst_topology_mgr *mgr,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2380  					int id,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2381  					struct drm_dp_payload *payload)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2382  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2383  	payload->payload_state = 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2384  	return 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2385  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2386  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2387  /**
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2388   * drm_dp_update_payload_part1() - Execute payload update part 1
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2389   * @mgr: manager to use.
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2390   *
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2391   * This iterates over all proposed virtual channels, and tries to
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2392   * allocate space in the link for them. For 0->slots transitions,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2393   * this step just writes the VCPI to the MST device. For slots->0
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2394   * transitions, this writes the updated VCPIs and removes the
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2395   * remote VC payloads.
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2396   *
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2397   * after calling this the driver should generate ACT and payload
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2398   * packets.
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2399   */
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2400  int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2401  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2402  	struct drm_dp_payload req_payload;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2403  	struct drm_dp_mst_port *port;
cfe9f90358d97a8 Lyude Paul           2019-01-10  2404  	int i, j;
cfe9f90358d97a8 Lyude Paul           2019-01-10  2405  	int cur_slots = 1;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2406  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2407  	mutex_lock(&mgr->payload_lock);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2408  	for (i = 0; i < mgr->max_payloads; i++) {
706246c761ddd39 Lyude Paul           2018-12-13  2409  		struct drm_dp_vcpi *vcpi = mgr->proposed_vcpis[i];
706246c761ddd39 Lyude Paul           2018-12-13  2410  		struct drm_dp_payload *payload = &mgr->payloads[i];
cfe9f90358d97a8 Lyude Paul           2019-01-10  2411  		bool put_port = false;
706246c761ddd39 Lyude Paul           2018-12-13  2412  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2413  		/* solve the current payloads - compare to the hw ones
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2414  		   - update the hw view */
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2415  		req_payload.start_slot = cur_slots;
706246c761ddd39 Lyude Paul           2018-12-13  2416  		if (vcpi) {
706246c761ddd39 Lyude Paul           2018-12-13  2417  			port = container_of(vcpi, struct drm_dp_mst_port,
706246c761ddd39 Lyude Paul           2018-12-13  2418  					    vcpi);
cfe9f90358d97a8 Lyude Paul           2019-01-10  2419  
cfe9f90358d97a8 Lyude Paul           2019-01-10  2420  			/* Validated ports don't matter if we're releasing
cfe9f90358d97a8 Lyude Paul           2019-01-10  2421  			 * VCPI
cfe9f90358d97a8 Lyude Paul           2019-01-10  2422  			 */
cfe9f90358d97a8 Lyude Paul           2019-01-10  2423  			if (vcpi->num_slots) {
cfe9f90358d97a8 Lyude Paul           2019-01-10  2424  				port = drm_dp_mst_topology_get_port_validated(
cfe9f90358d97a8 Lyude Paul           2019-01-10  2425  				    mgr, port);
263efde31f97c49 cpaul@xxxxxxxxxx     2016-04-22  2426  				if (!port) {
263efde31f97c49 cpaul@xxxxxxxxxx     2016-04-22  2427  					mutex_unlock(&mgr->payload_lock);
263efde31f97c49 cpaul@xxxxxxxxxx     2016-04-22  2428  					return -EINVAL;
263efde31f97c49 cpaul@xxxxxxxxxx     2016-04-22  2429  				}
cfe9f90358d97a8 Lyude Paul           2019-01-10  2430  				put_port = true;
cfe9f90358d97a8 Lyude Paul           2019-01-10  2431  			}
cfe9f90358d97a8 Lyude Paul           2019-01-10  2432  
706246c761ddd39 Lyude Paul           2018-12-13  2433  			req_payload.num_slots = vcpi->num_slots;
706246c761ddd39 Lyude Paul           2018-12-13  2434  			req_payload.vcpi = vcpi->vcpi;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2435  		} else {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2436  			port = NULL;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2437  			req_payload.num_slots = 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2438  		}
dfda0df3426483c Dave Airlie          2014-08-06  2439  
706246c761ddd39 Lyude Paul           2018-12-13  2440  		payload->start_slot = req_payload.start_slot;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2441  		/* work out what is required to happen with this payload */
706246c761ddd39 Lyude Paul           2018-12-13  2442  		if (payload->num_slots != req_payload.num_slots) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2443  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2444  			/* need to push an update for this payload */
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2445  			if (req_payload.num_slots) {
706246c761ddd39 Lyude Paul           2018-12-13  2446  				drm_dp_create_payload_step1(mgr, vcpi->vcpi,
706246c761ddd39 Lyude Paul           2018-12-13  2447  							    &req_payload);
706246c761ddd39 Lyude Paul           2018-12-13  2448  				payload->num_slots = req_payload.num_slots;
706246c761ddd39 Lyude Paul           2018-12-13  2449  				payload->vcpi = req_payload.vcpi;
706246c761ddd39 Lyude Paul           2018-12-13  2450  
706246c761ddd39 Lyude Paul           2018-12-13  2451  			} else if (payload->num_slots) {
706246c761ddd39 Lyude Paul           2018-12-13  2452  				payload->num_slots = 0;
706246c761ddd39 Lyude Paul           2018-12-13  2453  				drm_dp_destroy_payload_step1(mgr, port,
706246c761ddd39 Lyude Paul           2018-12-13  2454  							     payload->vcpi,
706246c761ddd39 Lyude Paul           2018-12-13  2455  							     payload);
706246c761ddd39 Lyude Paul           2018-12-13  2456  				req_payload.payload_state =
706246c761ddd39 Lyude Paul           2018-12-13  2457  					payload->payload_state;
706246c761ddd39 Lyude Paul           2018-12-13  2458  				payload->start_slot = 0;
706246c761ddd39 Lyude Paul           2018-12-13  2459  			}
706246c761ddd39 Lyude Paul           2018-12-13  2460  			payload->payload_state = req_payload.payload_state;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2461  		}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2462  		cur_slots += req_payload.num_slots;
263efde31f97c49 cpaul@xxxxxxxxxx     2016-04-22  2463  
cfe9f90358d97a8 Lyude Paul           2019-01-10  2464  		if (put_port)
d0757afd00d71dc Lyude Paul           2019-01-10  2465  			drm_dp_mst_topology_put_port(port);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2466  	}
dfda0df3426483c Dave Airlie          2014-08-06  2467  
dfda0df3426483c Dave Airlie          2014-08-06  2468  	for (i = 0; i < mgr->max_payloads; i++) {
706246c761ddd39 Lyude Paul           2018-12-13  2469  		if (mgr->payloads[i].payload_state != DP_PAYLOAD_DELETE_LOCAL)
706246c761ddd39 Lyude Paul           2018-12-13  2470  			continue;
706246c761ddd39 Lyude Paul           2018-12-13  2471  
dfda0df3426483c Dave Airlie          2014-08-06  2472  		DRM_DEBUG_KMS("removing payload %d\n", i);
dfda0df3426483c Dave Airlie          2014-08-06  2473  		for (j = i; j < mgr->max_payloads - 1; j++) {
706246c761ddd39 Lyude Paul           2018-12-13  2474  			mgr->payloads[j] = mgr->payloads[j + 1];
dfda0df3426483c Dave Airlie          2014-08-06  2475  			mgr->proposed_vcpis[j] = mgr->proposed_vcpis[j + 1];
706246c761ddd39 Lyude Paul           2018-12-13  2476  
706246c761ddd39 Lyude Paul           2018-12-13  2477  			if (mgr->proposed_vcpis[j] &&
706246c761ddd39 Lyude Paul           2018-12-13  2478  			    mgr->proposed_vcpis[j]->num_slots) {
dfda0df3426483c Dave Airlie          2014-08-06  2479  				set_bit(j + 1, &mgr->payload_mask);
dfda0df3426483c Dave Airlie          2014-08-06  2480  			} else {
dfda0df3426483c Dave Airlie          2014-08-06  2481  				clear_bit(j + 1, &mgr->payload_mask);
dfda0df3426483c Dave Airlie          2014-08-06  2482  			}
dfda0df3426483c Dave Airlie          2014-08-06  2483  		}
706246c761ddd39 Lyude Paul           2018-12-13  2484  
706246c761ddd39 Lyude Paul           2018-12-13  2485  		memset(&mgr->payloads[mgr->max_payloads - 1], 0,
706246c761ddd39 Lyude Paul           2018-12-13  2486  		       sizeof(struct drm_dp_payload));
dfda0df3426483c Dave Airlie          2014-08-06  2487  		mgr->proposed_vcpis[mgr->max_payloads - 1] = NULL;
dfda0df3426483c Dave Airlie          2014-08-06  2488  		clear_bit(mgr->max_payloads, &mgr->payload_mask);
dfda0df3426483c Dave Airlie          2014-08-06  2489  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2490  	mutex_unlock(&mgr->payload_lock);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2491  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2492  	return 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2493  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2494  EXPORT_SYMBOL(drm_dp_update_payload_part1);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2495  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2496  /**
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2497   * drm_dp_update_payload_part2() - Execute payload update part 2
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2498   * @mgr: manager to use.
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2499   *
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2500   * This iterates over all proposed virtual channels, and tries to
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2501   * allocate space in the link for them. For 0->slots transitions,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2502   * this step writes the remote VC payload commands. For slots->0
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2503   * this just resets some internal state.
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2504   */
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2505  int drm_dp_update_payload_part2(struct drm_dp_mst_topology_mgr *mgr)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2506  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2507  	struct drm_dp_mst_port *port;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2508  	int i;
7389ad4b6515c2d Damien Lespiau       2014-07-14  2509  	int ret = 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2510  	mutex_lock(&mgr->payload_lock);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2511  	for (i = 0; i < mgr->max_payloads; i++) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2512  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2513  		if (!mgr->proposed_vcpis[i])
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2514  			continue;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2515  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2516  		port = container_of(mgr->proposed_vcpis[i], struct drm_dp_mst_port, vcpi);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2517  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2518  		DRM_DEBUG_KMS("payload %d %d\n", i, mgr->payloads[i].payload_state);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2519  		if (mgr->payloads[i].payload_state == DP_PAYLOAD_LOCAL) {
dfda0df3426483c Dave Airlie          2014-08-06  2520  			ret = drm_dp_create_payload_step2(mgr, port, mgr->proposed_vcpis[i]->vcpi, &mgr->payloads[i]);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2521  		} else if (mgr->payloads[i].payload_state == DP_PAYLOAD_DELETE_LOCAL) {
dfda0df3426483c Dave Airlie          2014-08-06  2522  			ret = drm_dp_destroy_payload_step2(mgr, mgr->proposed_vcpis[i]->vcpi, &mgr->payloads[i]);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2523  		}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2524  		if (ret) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2525  			mutex_unlock(&mgr->payload_lock);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2526  			return ret;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2527  		}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2528  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2529  	mutex_unlock(&mgr->payload_lock);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2530  	return 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2531  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2532  EXPORT_SYMBOL(drm_dp_update_payload_part2);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2533  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2534  static int drm_dp_send_dpcd_read(struct drm_dp_mst_topology_mgr *mgr,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2535  				 struct drm_dp_mst_port *port,
3dfd9a885fbb869 Andrew Morton        2019-07-27  2536  				 int offset, int size, u8 *bytes)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2537  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2538  	int len;
3dfd9a885fbb869 Andrew Morton        2019-07-27  2539  	int ret = 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2540  	struct drm_dp_sideband_msg_tx *txmsg;
3dfd9a885fbb869 Andrew Morton        2019-07-27  2541  	struct drm_dp_mst_branch *mstb;
3dfd9a885fbb869 Andrew Morton        2019-07-27  2542  
3dfd9a885fbb869 Andrew Morton        2019-07-27  2543  	mstb = drm_dp_mst_topology_get_mstb_validated(mgr, port->parent);
3dfd9a885fbb869 Andrew Morton        2019-07-27  2544  	if (!mstb)
3dfd9a885fbb869 Andrew Morton        2019-07-27  2545  		return -EINVAL;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2546  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2547  	txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);
3dfd9a885fbb869 Andrew Morton        2019-07-27  2548  	if (!txmsg) {
3dfd9a885fbb869 Andrew Morton        2019-07-27  2549  		ret = -ENOMEM;
3dfd9a885fbb869 Andrew Morton        2019-07-27  2550  		goto fail_put;
3dfd9a885fbb869 Andrew Morton        2019-07-27  2551  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2552  
3dfd9a885fbb869 Andrew Morton        2019-07-27  2553  	len = build_dpcd_read(txmsg, port->port_num, offset, size);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2554  	txmsg->dst = port->parent;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2555  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2556  	drm_dp_queue_down_tx(mgr, txmsg);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2557  
3dfd9a885fbb869 Andrew Morton        2019-07-27  2558  	ret = drm_dp_mst_wait_tx_reply(mstb, txmsg);
3dfd9a885fbb869 Andrew Morton        2019-07-27  2559  	if (ret < 0)
3dfd9a885fbb869 Andrew Morton        2019-07-27  2560  		goto fail_free;
3dfd9a885fbb869 Andrew Morton        2019-07-27  2561  
3dfd9a885fbb869 Andrew Morton        2019-07-27  2562  	/* DPCD read should never be NACKed */
3dfd9a885fbb869 Andrew Morton        2019-07-27  2563  	if (txmsg->reply.reply_type == 1) {
3dfd9a885fbb869 Andrew Morton        2019-07-27  2564  		DRM_ERROR("mstb %p port %d: DPCD read on addr 0x%x for %d bytes NAKed\n",
3dfd9a885fbb869 Andrew Morton        2019-07-27  2565  			  mstb, port->port_num, offset, size);
3dfd9a885fbb869 Andrew Morton        2019-07-27  2566  		ret = -EIO;
3dfd9a885fbb869 Andrew Morton        2019-07-27  2567  		goto fail_free;
3dfd9a885fbb869 Andrew Morton        2019-07-27  2568  	}
3dfd9a885fbb869 Andrew Morton        2019-07-27  2569  
3dfd9a885fbb869 Andrew Morton        2019-07-27  2570  	if (txmsg->reply.u.remote_dpcd_read_ack.num_bytes != size) {
3dfd9a885fbb869 Andrew Morton        2019-07-27  2571  		ret = -EPROTO;
3dfd9a885fbb869 Andrew Morton        2019-07-27  2572  		goto fail_free;
3dfd9a885fbb869 Andrew Morton        2019-07-27  2573  	}
3dfd9a885fbb869 Andrew Morton        2019-07-27  2574  
3dfd9a885fbb869 Andrew Morton        2019-07-27  2575  	ret = min_t(size_t, txmsg->reply.u.remote_dpcd_read_ack.num_bytes,
3dfd9a885fbb869 Andrew Morton        2019-07-27  2576  		    size);
3dfd9a885fbb869 Andrew Morton        2019-07-27  2577  	memcpy(bytes, txmsg->reply.u.remote_dpcd_read_ack.bytes, ret);
3dfd9a885fbb869 Andrew Morton        2019-07-27  2578  
3dfd9a885fbb869 Andrew Morton        2019-07-27  2579  fail_free:
3dfd9a885fbb869 Andrew Morton        2019-07-27  2580  	kfree(txmsg);
3dfd9a885fbb869 Andrew Morton        2019-07-27  2581  fail_put:
3dfd9a885fbb869 Andrew Morton        2019-07-27  2582  	drm_dp_mst_topology_put_mstb(mstb);
3dfd9a885fbb869 Andrew Morton        2019-07-27  2583  
3dfd9a885fbb869 Andrew Morton        2019-07-27  2584  	return ret;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2585  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2586  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2587  static int drm_dp_send_dpcd_write(struct drm_dp_mst_topology_mgr *mgr,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2588  				  struct drm_dp_mst_port *port,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2589  				  int offset, int size, u8 *bytes)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2590  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2591  	int len;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2592  	int ret;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2593  	struct drm_dp_sideband_msg_tx *txmsg;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2594  	struct drm_dp_mst_branch *mstb;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2595  
d0757afd00d71dc Lyude Paul           2019-01-10  2596  	mstb = drm_dp_mst_topology_get_mstb_validated(mgr, port->parent);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2597  	if (!mstb)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2598  		return -EINVAL;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2599  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2600  	txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2601  	if (!txmsg) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2602  		ret = -ENOMEM;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2603  		goto fail_put;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2604  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2605  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2606  	len = build_dpcd_write(txmsg, port->port_num, offset, size, bytes);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2607  	txmsg->dst = mstb;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2608  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2609  	drm_dp_queue_down_tx(mgr, txmsg);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2610  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2611  	ret = drm_dp_mst_wait_tx_reply(mstb, txmsg);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2612  	if (ret > 0) {
45bbda1e35f4943 Ville Syrjälä        2019-01-22  2613  		if (txmsg->reply.reply_type == DP_SIDEBAND_REPLY_NAK)
3dfd9a885fbb869 Andrew Morton        2019-07-27  2614  			ret = -EIO;
45bbda1e35f4943 Ville Syrjälä        2019-01-22  2615  		else
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2616  			ret = 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2617  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2618  	kfree(txmsg);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2619  fail_put:
d0757afd00d71dc Lyude Paul           2019-01-10  2620  	drm_dp_mst_topology_put_mstb(mstb);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2621  	return ret;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2622  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2623  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2624  static int drm_dp_encode_up_ack_reply(struct drm_dp_sideband_msg_tx *msg, u8 req_type)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2625  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2626  	struct drm_dp_sideband_msg_reply_body reply;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2627  
45bbda1e35f4943 Ville Syrjälä        2019-01-22  2628  	reply.reply_type = DP_SIDEBAND_REPLY_ACK;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2629  	reply.req_type = req_type;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2630  	drm_dp_encode_sideband_reply(&reply, msg);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2631  	return 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2632  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2633  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2634  static int drm_dp_send_up_ack_reply(struct drm_dp_mst_topology_mgr *mgr,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2635  				    struct drm_dp_mst_branch *mstb,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2636  				    int req_type, int seqno, bool broadcast)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2637  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2638  	struct drm_dp_sideband_msg_tx *txmsg;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2639  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2640  	txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2641  	if (!txmsg)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2642  		return -ENOMEM;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2643  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2644  	txmsg->dst = mstb;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2645  	txmsg->seqno = seqno;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2646  	drm_dp_encode_up_ack_reply(txmsg, req_type);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2647  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2648  	mutex_lock(&mgr->qlock);
1f16ee7fa13649f Mykola Lysenko       2015-12-18  2649  
1f16ee7fa13649f Mykola Lysenko       2015-12-18  2650  	process_single_up_tx_qlock(mgr, txmsg);
1f16ee7fa13649f Mykola Lysenko       2015-12-18  2651  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2652  	mutex_unlock(&mgr->qlock);
1f16ee7fa13649f Mykola Lysenko       2015-12-18  2653  
1f16ee7fa13649f Mykola Lysenko       2015-12-18  2654  	kfree(txmsg);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2655  	return 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2656  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2657  
b853fdb3c0e7122 Chris Wilson         2014-11-12  2658  static bool drm_dp_get_vc_payload_bw(int dp_link_bw,
b853fdb3c0e7122 Chris Wilson         2014-11-12  2659  				     int dp_link_count,
b853fdb3c0e7122 Chris Wilson         2014-11-12  2660  				     int *out)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2661  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2662  	switch (dp_link_bw) {
b853fdb3c0e7122 Chris Wilson         2014-11-12  2663  	default:
b853fdb3c0e7122 Chris Wilson         2014-11-12  2664  		DRM_DEBUG_KMS("invalid link bandwidth in DPCD: %x (link count: %d)\n",
b853fdb3c0e7122 Chris Wilson         2014-11-12  2665  			      dp_link_bw, dp_link_count);
b853fdb3c0e7122 Chris Wilson         2014-11-12  2666  		return false;
b853fdb3c0e7122 Chris Wilson         2014-11-12  2667  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2668  	case DP_LINK_BW_1_62:
b853fdb3c0e7122 Chris Wilson         2014-11-12  2669  		*out = 3 * dp_link_count;
b853fdb3c0e7122 Chris Wilson         2014-11-12  2670  		break;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2671  	case DP_LINK_BW_2_7:
b853fdb3c0e7122 Chris Wilson         2014-11-12  2672  		*out = 5 * dp_link_count;
b853fdb3c0e7122 Chris Wilson         2014-11-12  2673  		break;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2674  	case DP_LINK_BW_5_4:
b853fdb3c0e7122 Chris Wilson         2014-11-12  2675  		*out = 10 * dp_link_count;
b853fdb3c0e7122 Chris Wilson         2014-11-12  2676  		break;
e0bd878a959008f Manasi Navare        2018-01-22  2677  	case DP_LINK_BW_8_1:
e0bd878a959008f Manasi Navare        2018-01-22  2678  		*out = 15 * dp_link_count;
e0bd878a959008f Manasi Navare        2018-01-22  2679  		break;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2680  	}
b853fdb3c0e7122 Chris Wilson         2014-11-12  2681  	return true;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2682  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2683  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2684  /**
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2685   * drm_dp_mst_topology_mgr_set_mst() - Set the MST state for a topology manager
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2686   * @mgr: manager to set state for
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2687   * @mst_state: true to enable MST on this connector - false to disable.
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2688   *
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2689   * This is called by the driver when it detects an MST capable device plugged
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2690   * into a DP MST capable port, or when a DP MST capable device is unplugged.
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2691   */
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2692  int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool mst_state)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2693  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2694  	int ret = 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2695  	struct drm_dp_mst_branch *mstb = NULL;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2696  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2697  	mutex_lock(&mgr->lock);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2698  	if (mst_state == mgr->mst_state)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2699  		goto out_unlock;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2700  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2701  	mgr->mst_state = mst_state;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2702  	/* set the device into MST mode */
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2703  	if (mst_state) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2704  		WARN_ON(mgr->mst_primary);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2705  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2706  		/* get dpcd info */
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2707  		ret = drm_dp_dpcd_read(mgr->aux, DP_DPCD_REV, mgr->dpcd, DP_RECEIVER_CAP_SIZE);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2708  		if (ret != DP_RECEIVER_CAP_SIZE) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2709  			DRM_DEBUG_KMS("failed to read DPCD\n");
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2710  			goto out_unlock;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2711  		}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2712  
b853fdb3c0e7122 Chris Wilson         2014-11-12  2713  		if (!drm_dp_get_vc_payload_bw(mgr->dpcd[1],
b853fdb3c0e7122 Chris Wilson         2014-11-12  2714  					      mgr->dpcd[2] & DP_MAX_LANE_COUNT_MASK,
b853fdb3c0e7122 Chris Wilson         2014-11-12  2715  					      &mgr->pbn_div)) {
b853fdb3c0e7122 Chris Wilson         2014-11-12  2716  			ret = -EINVAL;
b853fdb3c0e7122 Chris Wilson         2014-11-12  2717  			goto out_unlock;
b853fdb3c0e7122 Chris Wilson         2014-11-12  2718  		}
b853fdb3c0e7122 Chris Wilson         2014-11-12  2719  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2720  		/* add initial branch device at LCT 1 */
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2721  		mstb = drm_dp_add_mst_branch_device(1, NULL);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2722  		if (mstb == NULL) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2723  			ret = -ENOMEM;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2724  			goto out_unlock;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2725  		}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2726  		mstb->mgr = mgr;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2727  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2728  		/* give this the main reference */
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2729  		mgr->mst_primary = mstb;
ebcc0e6b509108b Lyude Paul           2019-01-10  2730  		drm_dp_mst_topology_get_mstb(mgr->mst_primary);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2731  
c175cd16df27211 Andrey Grodzovsky    2016-01-22  2732  		ret = drm_dp_dpcd_writeb(mgr->aux, DP_MSTM_CTRL,
c175cd16df27211 Andrey Grodzovsky    2016-01-22  2733  							 DP_MST_EN | DP_UP_REQ_EN | DP_UPSTREAM_IS_SRC);
c175cd16df27211 Andrey Grodzovsky    2016-01-22  2734  		if (ret < 0) {
c175cd16df27211 Andrey Grodzovsky    2016-01-22  2735  			goto out_unlock;
c175cd16df27211 Andrey Grodzovsky    2016-01-22  2736  		}
c175cd16df27211 Andrey Grodzovsky    2016-01-22  2737  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2738  		{
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2739  			struct drm_dp_payload reset_pay;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2740  			reset_pay.start_slot = 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2741  			reset_pay.num_slots = 0x3f;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2742  			drm_dp_dpcd_write_payload(mgr, 0, &reset_pay);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2743  		}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2744  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2745  		queue_work(system_long_wq, &mgr->work);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2746  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2747  		ret = 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2748  	} else {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2749  		/* disable MST on the device */
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2750  		mstb = mgr->mst_primary;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2751  		mgr->mst_primary = NULL;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2752  		/* this can fail if the device is gone */
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2753  		drm_dp_dpcd_writeb(mgr->aux, DP_MSTM_CTRL, 0);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2754  		ret = 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2755  		memset(mgr->payloads, 0, mgr->max_payloads * sizeof(struct drm_dp_payload));
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2756  		mgr->payload_mask = 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2757  		set_bit(0, &mgr->payload_mask);
dfda0df3426483c Dave Airlie          2014-08-06  2758  		mgr->vcpi_mask = 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2759  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2760  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2761  out_unlock:
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2762  	mutex_unlock(&mgr->lock);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2763  	if (mstb)
d0757afd00d71dc Lyude Paul           2019-01-10  2764  		drm_dp_mst_topology_put_mstb(mstb);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2765  	return ret;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2766  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2767  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2768  EXPORT_SYMBOL(drm_dp_mst_topology_mgr_set_mst);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2769  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2770  /**
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2771   * drm_dp_mst_topology_mgr_suspend() - suspend the MST manager
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2772   * @mgr: manager to suspend
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2773   *
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2774   * This function tells the MST device that we can't handle UP messages
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2775   * anymore. This should stop it from sending any since we are suspended.
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2776   */
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2777  void drm_dp_mst_topology_mgr_suspend(struct drm_dp_mst_topology_mgr *mgr)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2778  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2779  	mutex_lock(&mgr->lock);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2780  	drm_dp_dpcd_writeb(mgr->aux, DP_MSTM_CTRL,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2781  			   DP_MST_EN | DP_UPSTREAM_IS_SRC);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2782  	mutex_unlock(&mgr->lock);
274d83524895fe4 Dave Airlie          2015-09-30  2783  	flush_work(&mgr->work);
274d83524895fe4 Dave Airlie          2015-09-30  2784  	flush_work(&mgr->destroy_connector_work);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2785  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2786  EXPORT_SYMBOL(drm_dp_mst_topology_mgr_suspend);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2787  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2788  /**
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2789   * drm_dp_mst_topology_mgr_resume() - resume the MST manager
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2790   * @mgr: manager to resume
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2791   *
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2792   * This will fetch DPCD and see if the device is still there,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2793   * if it is, it will rewrite the MSTM control bits, and return.
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2794   *
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2795   * if the device fails this returns -1, and the driver should do
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2796   * a full MST reprobe, in case we were undocked.
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2797   */
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2798  int drm_dp_mst_topology_mgr_resume(struct drm_dp_mst_topology_mgr *mgr)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2799  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2800  	int ret = 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2801  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2802  	mutex_lock(&mgr->lock);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2803  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2804  	if (mgr->mst_primary) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2805  		int sret;
1652fce65f70f10 Lyude                2016-04-13  2806  		u8 guid[16];
1652fce65f70f10 Lyude                2016-04-13  2807  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2808  		sret = drm_dp_dpcd_read(mgr->aux, DP_DPCD_REV, mgr->dpcd, DP_RECEIVER_CAP_SIZE);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2809  		if (sret != DP_RECEIVER_CAP_SIZE) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2810  			DRM_DEBUG_KMS("dpcd read failed - undocked during suspend?\n");
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2811  			ret = -1;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2812  			goto out_unlock;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2813  		}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2814  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2815  		ret = drm_dp_dpcd_writeb(mgr->aux, DP_MSTM_CTRL,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2816  					 DP_MST_EN | DP_UP_REQ_EN | DP_UPSTREAM_IS_SRC);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2817  		if (ret < 0) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2818  			DRM_DEBUG_KMS("mst write failed - undocked during suspend?\n");
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2819  			ret = -1;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2820  			goto out_unlock;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2821  		}
1652fce65f70f10 Lyude                2016-04-13  2822  
1652fce65f70f10 Lyude                2016-04-13  2823  		/* Some hubs forget their guids after they resume */
1652fce65f70f10 Lyude                2016-04-13  2824  		sret = drm_dp_dpcd_read(mgr->aux, DP_GUID, guid, 16);
1652fce65f70f10 Lyude                2016-04-13  2825  		if (sret != 16) {
1652fce65f70f10 Lyude                2016-04-13  2826  			DRM_DEBUG_KMS("dpcd read failed - undocked during suspend?\n");
1652fce65f70f10 Lyude                2016-04-13  2827  			ret = -1;
1652fce65f70f10 Lyude                2016-04-13  2828  			goto out_unlock;
1652fce65f70f10 Lyude                2016-04-13  2829  		}
1652fce65f70f10 Lyude                2016-04-13  2830  		drm_dp_check_mstb_guid(mgr->mst_primary, guid);
1652fce65f70f10 Lyude                2016-04-13  2831  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2832  		ret = 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2833  	} else
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2834  		ret = -1;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2835  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2836  out_unlock:
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2837  	mutex_unlock(&mgr->lock);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2838  	return ret;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2839  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2840  EXPORT_SYMBOL(drm_dp_mst_topology_mgr_resume);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2841  
636c4c3e762b62a Imre Deak            2017-07-19  2842  static bool drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2843  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2844  	int len;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2845  	u8 replyblock[32];
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2846  	int replylen, origlen, curreply;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2847  	int ret;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2848  	struct drm_dp_sideband_msg_rx *msg;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2849  	int basereg = up ? DP_SIDEBAND_MSG_UP_REQ_BASE : DP_SIDEBAND_MSG_DOWN_REP_BASE;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2850  	msg = up ? &mgr->up_req_recv : &mgr->down_rep_recv;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2851  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2852  	len = min(mgr->max_dpcd_transaction_bytes, 16);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2853  	ret = drm_dp_dpcd_read(mgr->aux, basereg,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2854  			       replyblock, len);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2855  	if (ret != len) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2856  		DRM_DEBUG_KMS("failed to read DPCD down rep %d %d\n", len, ret);
636c4c3e762b62a Imre Deak            2017-07-19  2857  		return false;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2858  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2859  	ret = drm_dp_sideband_msg_build(msg, replyblock, len, true);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2860  	if (!ret) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2861  		DRM_DEBUG_KMS("sideband msg build failed %d\n", replyblock[0]);
636c4c3e762b62a Imre Deak            2017-07-19  2862  		return false;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2863  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2864  	replylen = msg->curchunk_len + msg->curchunk_hdrlen;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2865  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2866  	origlen = replylen;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2867  	replylen -= len;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2868  	curreply = len;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2869  	while (replylen > 0) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2870  		len = min3(replylen, mgr->max_dpcd_transaction_bytes, 16);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2871  		ret = drm_dp_dpcd_read(mgr->aux, basereg + curreply,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2872  				    replyblock, len);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2873  		if (ret != len) {
448421b5e93b917 Imre Deak            2017-07-19  2874  			DRM_DEBUG_KMS("failed to read a chunk (len %d, ret %d)\n",
448421b5e93b917 Imre Deak            2017-07-19  2875  				      len, ret);
636c4c3e762b62a Imre Deak            2017-07-19  2876  			return false;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2877  		}
448421b5e93b917 Imre Deak            2017-07-19  2878  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2879  		ret = drm_dp_sideband_msg_build(msg, replyblock, len, false);
448421b5e93b917 Imre Deak            2017-07-19  2880  		if (!ret) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2881  			DRM_DEBUG_KMS("failed to build sideband msg\n");
636c4c3e762b62a Imre Deak            2017-07-19  2882  			return false;
448421b5e93b917 Imre Deak            2017-07-19  2883  		}
448421b5e93b917 Imre Deak            2017-07-19  2884  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2885  		curreply += len;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2886  		replylen -= len;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2887  	}
636c4c3e762b62a Imre Deak            2017-07-19  2888  	return true;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2889  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2890  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2891  static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2892  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2893  	int ret = 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2894  
636c4c3e762b62a Imre Deak            2017-07-19  2895  	if (!drm_dp_get_one_sb_msg(mgr, false)) {
636c4c3e762b62a Imre Deak            2017-07-19  2896  		memset(&mgr->down_rep_recv, 0,
636c4c3e762b62a Imre Deak            2017-07-19  2897  		       sizeof(struct drm_dp_sideband_msg_rx));
636c4c3e762b62a Imre Deak            2017-07-19  2898  		return 0;
636c4c3e762b62a Imre Deak            2017-07-19  2899  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2900  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2901  	if (mgr->down_rep_recv.have_eomt) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2902  		struct drm_dp_sideband_msg_tx *txmsg;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2903  		struct drm_dp_mst_branch *mstb;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2904  		int slot = -1;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2905  		mstb = drm_dp_get_mst_branch_device(mgr,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2906  						    mgr->down_rep_recv.initial_hdr.lct,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2907  						    mgr->down_rep_recv.initial_hdr.rad);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2908  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2909  		if (!mstb) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2910  			DRM_DEBUG_KMS("Got MST reply from unknown device %d\n", mgr->down_rep_recv.initial_hdr.lct);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2911  			memset(&mgr->down_rep_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2912  			return 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2913  		}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2914  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2915  		/* find the message */
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2916  		slot = mgr->down_rep_recv.initial_hdr.seqno;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2917  		mutex_lock(&mgr->qlock);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2918  		txmsg = mstb->tx_slots[slot];
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2919  		/* remove from slots */
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2920  		mutex_unlock(&mgr->qlock);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2921  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2922  		if (!txmsg) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2923  			DRM_DEBUG_KMS("Got MST reply with no msg %p %d %d %02x %02x\n",
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2924  			       mstb,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2925  			       mgr->down_rep_recv.initial_hdr.seqno,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2926  			       mgr->down_rep_recv.initial_hdr.lct,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2927  				      mgr->down_rep_recv.initial_hdr.rad[0],
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2928  				      mgr->down_rep_recv.msg[0]);
d0757afd00d71dc Lyude Paul           2019-01-10  2929  			drm_dp_mst_topology_put_mstb(mstb);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2930  			memset(&mgr->down_rep_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2931  			return 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2932  		}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2933  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2934  		drm_dp_sideband_parse_reply(&mgr->down_rep_recv, &txmsg->reply);
45bbda1e35f4943 Ville Syrjälä        2019-01-22  2935  
45bbda1e35f4943 Ville Syrjälä        2019-01-22  2936  		if (txmsg->reply.reply_type == DP_SIDEBAND_REPLY_NAK)
3dadbd2957eb8da Ville Syrjälä        2019-01-22  2937  			DRM_DEBUG_KMS("Got NAK reply: req 0x%02x (%s), reason 0x%02x (%s), nak data 0x%02x\n",
3dadbd2957eb8da Ville Syrjälä        2019-01-22  2938  				      txmsg->reply.req_type,
3dadbd2957eb8da Ville Syrjälä        2019-01-22  2939  				      drm_dp_mst_req_type_str(txmsg->reply.req_type),
3dadbd2957eb8da Ville Syrjälä        2019-01-22  2940  				      txmsg->reply.u.nak.reason,
3dadbd2957eb8da Ville Syrjälä        2019-01-22  2941  				      drm_dp_mst_nak_reason_str(txmsg->reply.u.nak.reason),
3dadbd2957eb8da Ville Syrjälä        2019-01-22  2942  				      txmsg->reply.u.nak.nak_data);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2943  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2944  		memset(&mgr->down_rep_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
d0757afd00d71dc Lyude Paul           2019-01-10  2945  		drm_dp_mst_topology_put_mstb(mstb);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2946  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2947  		mutex_lock(&mgr->qlock);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2948  		txmsg->state = DRM_DP_SIDEBAND_TX_RX;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2949  		mstb->tx_slots[slot] = NULL;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2950  		mutex_unlock(&mgr->qlock);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2951  
68e989dc044346a Chris Wilson         2017-05-13  2952  		wake_up_all(&mgr->tx_waitq);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2953  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2954  	return ret;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2955  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2956  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2957  static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2958  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2959  	int ret = 0;
636c4c3e762b62a Imre Deak            2017-07-19  2960  
636c4c3e762b62a Imre Deak            2017-07-19  2961  	if (!drm_dp_get_one_sb_msg(mgr, true)) {
636c4c3e762b62a Imre Deak            2017-07-19  2962  		memset(&mgr->up_req_recv, 0,
636c4c3e762b62a Imre Deak            2017-07-19  2963  		       sizeof(struct drm_dp_sideband_msg_rx));
636c4c3e762b62a Imre Deak            2017-07-19  2964  		return 0;
636c4c3e762b62a Imre Deak            2017-07-19  2965  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2966  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2967  	if (mgr->up_req_recv.have_eomt) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2968  		struct drm_dp_sideband_msg_req_body msg;
bd9343208704fcc Mykola Lysenko       2015-12-18  2969  		struct drm_dp_mst_branch *mstb = NULL;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2970  		bool seqno;
bd9343208704fcc Mykola Lysenko       2015-12-18  2971  
bd9343208704fcc Mykola Lysenko       2015-12-18  2972  		if (!mgr->up_req_recv.initial_hdr.broadcast) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2973  			mstb = drm_dp_get_mst_branch_device(mgr,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2974  							    mgr->up_req_recv.initial_hdr.lct,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2975  							    mgr->up_req_recv.initial_hdr.rad);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2976  			if (!mstb) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2977  				DRM_DEBUG_KMS("Got MST reply from unknown device %d\n", mgr->up_req_recv.initial_hdr.lct);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2978  				memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2979  				return 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2980  			}
bd9343208704fcc Mykola Lysenko       2015-12-18  2981  		}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2982  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2983  		seqno = mgr->up_req_recv.initial_hdr.seqno;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2984  		drm_dp_sideband_parse_req(&mgr->up_req_recv, &msg);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2985  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2986  		if (msg.req_type == DP_CONNECTION_STATUS_NOTIFY) {
bd9343208704fcc Mykola Lysenko       2015-12-18  2987  			drm_dp_send_up_ack_reply(mgr, mgr->mst_primary, msg.req_type, seqno, false);
bd9343208704fcc Mykola Lysenko       2015-12-18  2988  
bd9343208704fcc Mykola Lysenko       2015-12-18  2989  			if (!mstb)
bd9343208704fcc Mykola Lysenko       2015-12-18  2990  				mstb = drm_dp_get_mst_branch_device_by_guid(mgr, msg.u.conn_stat.guid);
bd9343208704fcc Mykola Lysenko       2015-12-18  2991  
bd9343208704fcc Mykola Lysenko       2015-12-18  2992  			if (!mstb) {
bd9343208704fcc Mykola Lysenko       2015-12-18  2993  				DRM_DEBUG_KMS("Got MST reply from unknown device %d\n", mgr->up_req_recv.initial_hdr.lct);
bd9343208704fcc Mykola Lysenko       2015-12-18  2994  				memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
bd9343208704fcc Mykola Lysenko       2015-12-18  2995  				return 0;
bd9343208704fcc Mykola Lysenko       2015-12-18  2996  			}
bd9343208704fcc Mykola Lysenko       2015-12-18  2997  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  2998  			drm_dp_update_port(mstb, &msg.u.conn_stat);
5e93b8208d3c419 Hersen Wu            2016-01-22  2999  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3000  			DRM_DEBUG_KMS("Got CSN: pn: %d ldps:%d ddps: %d mcs: %d ip: %d pdt: %d\n", msg.u.conn_stat.port_number, msg.u.conn_stat.legacy_device_plug_status, msg.u.conn_stat.displayport_device_plug_status, msg.u.conn_stat.message_capability_status, msg.u.conn_stat.input_port, msg.u.conn_stat.peer_device_type);
16bff572cc660f1 Daniel Vetter        2018-11-28  3001  			drm_kms_helper_hotplug_event(mgr->dev);
8ae22cb419ad0ba Dave Airlie          2016-02-17  3002  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3003  		} else if (msg.req_type == DP_RESOURCE_STATUS_NOTIFY) {
bd9343208704fcc Mykola Lysenko       2015-12-18  3004  			drm_dp_send_up_ack_reply(mgr, mgr->mst_primary, msg.req_type, seqno, false);
bd9343208704fcc Mykola Lysenko       2015-12-18  3005  			if (!mstb)
bd9343208704fcc Mykola Lysenko       2015-12-18  3006  				mstb = drm_dp_get_mst_branch_device_by_guid(mgr, msg.u.resource_stat.guid);
bd9343208704fcc Mykola Lysenko       2015-12-18  3007  
bd9343208704fcc Mykola Lysenko       2015-12-18  3008  			if (!mstb) {
bd9343208704fcc Mykola Lysenko       2015-12-18  3009  				DRM_DEBUG_KMS("Got MST reply from unknown device %d\n", mgr->up_req_recv.initial_hdr.lct);
bd9343208704fcc Mykola Lysenko       2015-12-18  3010  				memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
bd9343208704fcc Mykola Lysenko       2015-12-18  3011  				return 0;
bd9343208704fcc Mykola Lysenko       2015-12-18  3012  			}
bd9343208704fcc Mykola Lysenko       2015-12-18  3013  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3014  			DRM_DEBUG_KMS("Got RSN: pn: %d avail_pbn %d\n", msg.u.resource_stat.port_number, msg.u.resource_stat.available_pbn);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3015  		}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3016  
7f8b3987da54cb4 Imre Deak            2017-07-19  3017  		if (mstb)
d0757afd00d71dc Lyude Paul           2019-01-10  3018  			drm_dp_mst_topology_put_mstb(mstb);
7f8b3987da54cb4 Imre Deak            2017-07-19  3019  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3020  		memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3021  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3022  	return ret;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3023  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3024  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3025  /**
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3026   * drm_dp_mst_hpd_irq() - MST hotplug IRQ notify
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3027   * @mgr: manager to notify irq for.
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3028   * @esi: 4 bytes from SINK_COUNT_ESI
295ee85316aedfe Daniel Vetter        2014-07-30  3029   * @handled: whether the hpd interrupt was consumed or not
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3030   *
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3031   * This should be called from the driver when it detects a short IRQ,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3032   * along with the value of the DEVICE_SERVICE_IRQ_VECTOR_ESI0. The
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3033   * topology manager will process the sideband messages received as a result
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3034   * of this.
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3035   */
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3036  int drm_dp_mst_hpd_irq(struct drm_dp_mst_topology_mgr *mgr, u8 *esi, bool *handled)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3037  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3038  	int ret = 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3039  	int sc;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3040  	*handled = false;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3041  	sc = esi[0] & 0x3f;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3042  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3043  	if (sc != mgr->sink_count) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3044  		mgr->sink_count = sc;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3045  		*handled = true;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3046  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3047  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3048  	if (esi[1] & DP_DOWN_REP_MSG_RDY) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3049  		ret = drm_dp_mst_handle_down_rep(mgr);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3050  		*handled = true;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3051  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3052  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3053  	if (esi[1] & DP_UP_REQ_MSG_RDY) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3054  		ret |= drm_dp_mst_handle_up_req(mgr);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3055  		*handled = true;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3056  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3057  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3058  	drm_dp_mst_kick_tx(mgr);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3059  	return ret;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3060  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3061  EXPORT_SYMBOL(drm_dp_mst_hpd_irq);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3062  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3063  /**
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3064   * drm_dp_mst_detect_port() - get connection status for an MST port
132d49d728f3af6 Daniel Vetter        2016-07-15  3065   * @connector: DRM connector for this port
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3066   * @mgr: manager for this port
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3067   * @port: unverified pointer to a port
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3068   *
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3069   * This returns the current connection state for a port. It validates the
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3070   * port pointer still exists so the caller doesn't require a reference
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3071   */
c6a0aed4d493936 Dave Airlie          2014-10-20  3072  enum drm_connector_status drm_dp_mst_detect_port(struct drm_connector *connector,
c6a0aed4d493936 Dave Airlie          2014-10-20  3073  						 struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3074  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3075  	enum drm_connector_status status = connector_status_disconnected;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3076  
1e55a53a28d3e52 Matt Roper           2019-02-01  3077  	/* we need to search for the port in the mgr in case it's gone */
d0757afd00d71dc Lyude Paul           2019-01-10  3078  	port = drm_dp_mst_topology_get_port_validated(mgr, port);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3079  	if (!port)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3080  		return connector_status_disconnected;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3081  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3082  	if (!port->ddps)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3083  		goto out;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3084  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3085  	switch (port->pdt) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3086  	case DP_PEER_DEVICE_NONE:
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3087  	case DP_PEER_DEVICE_MST_BRANCHING:
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3088  		break;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3089  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3090  	case DP_PEER_DEVICE_SST_SINK:
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3091  		status = connector_status_connected;
8ae22cb419ad0ba Dave Airlie          2016-02-17  3092  		/* for logical ports - cache the EDID */
8ae22cb419ad0ba Dave Airlie          2016-02-17  3093  		if (port->port_num >= 8 && !port->cached_edid) {
8ae22cb419ad0ba Dave Airlie          2016-02-17  3094  			port->cached_edid = drm_get_edid(connector, &port->aux.ddc);
8ae22cb419ad0ba Dave Airlie          2016-02-17  3095  		}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3096  		break;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3097  	case DP_PEER_DEVICE_DP_LEGACY_CONV:
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3098  		if (port->ldps)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3099  			status = connector_status_connected;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3100  		break;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3101  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3102  out:
d0757afd00d71dc Lyude Paul           2019-01-10  3103  	drm_dp_mst_topology_put_port(port);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3104  	return status;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3105  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3106  EXPORT_SYMBOL(drm_dp_mst_detect_port);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3107  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3108  /**
ef8f9bea1368b89 Libin Yang           2015-12-02  3109   * drm_dp_mst_port_has_audio() - Check whether port has audio capability or not
ef8f9bea1368b89 Libin Yang           2015-12-02  3110   * @mgr: manager for this port
ef8f9bea1368b89 Libin Yang           2015-12-02  3111   * @port: unverified pointer to a port.
ef8f9bea1368b89 Libin Yang           2015-12-02  3112   *
ef8f9bea1368b89 Libin Yang           2015-12-02  3113   * This returns whether the port supports audio or not.
ef8f9bea1368b89 Libin Yang           2015-12-02  3114   */
ef8f9bea1368b89 Libin Yang           2015-12-02  3115  bool drm_dp_mst_port_has_audio(struct drm_dp_mst_topology_mgr *mgr,
ef8f9bea1368b89 Libin Yang           2015-12-02  3116  					struct drm_dp_mst_port *port)
ef8f9bea1368b89 Libin Yang           2015-12-02  3117  {
ef8f9bea1368b89 Libin Yang           2015-12-02  3118  	bool ret = false;
ef8f9bea1368b89 Libin Yang           2015-12-02  3119  
d0757afd00d71dc Lyude Paul           2019-01-10  3120  	port = drm_dp_mst_topology_get_port_validated(mgr, port);
ef8f9bea1368b89 Libin Yang           2015-12-02  3121  	if (!port)
ef8f9bea1368b89 Libin Yang           2015-12-02  3122  		return ret;
ef8f9bea1368b89 Libin Yang           2015-12-02  3123  	ret = port->has_audio;
d0757afd00d71dc Lyude Paul           2019-01-10  3124  	drm_dp_mst_topology_put_port(port);
ef8f9bea1368b89 Libin Yang           2015-12-02  3125  	return ret;
ef8f9bea1368b89 Libin Yang           2015-12-02  3126  }
ef8f9bea1368b89 Libin Yang           2015-12-02  3127  EXPORT_SYMBOL(drm_dp_mst_port_has_audio);
ef8f9bea1368b89 Libin Yang           2015-12-02  3128  
ef8f9bea1368b89 Libin Yang           2015-12-02  3129  /**
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3130   * drm_dp_mst_get_edid() - get EDID for an MST port
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3131   * @connector: toplevel connector to get EDID for
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3132   * @mgr: manager for this port
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3133   * @port: unverified pointer to a port.
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3134   *
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3135   * This returns an EDID for the port connected to a connector,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3136   * It validates the pointer still exists so the caller doesn't require a
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3137   * reference.
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3138   */
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3139  struct edid *drm_dp_mst_get_edid(struct drm_connector *connector, struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3140  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3141  	struct edid *edid = NULL;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3142  
1e55a53a28d3e52 Matt Roper           2019-02-01  3143  	/* we need to search for the port in the mgr in case it's gone */
d0757afd00d71dc Lyude Paul           2019-01-10  3144  	port = drm_dp_mst_topology_get_port_validated(mgr, port);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3145  	if (!port)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3146  		return NULL;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3147  
c6a0aed4d493936 Dave Airlie          2014-10-20  3148  	if (port->cached_edid)
c6a0aed4d493936 Dave Airlie          2014-10-20  3149  		edid = drm_edid_duplicate(port->cached_edid);
8ae22cb419ad0ba Dave Airlie          2016-02-17  3150  	else {
8ae22cb419ad0ba Dave Airlie          2016-02-17  3151  		edid = drm_get_edid(connector, &port->aux.ddc);
8ae22cb419ad0ba Dave Airlie          2016-02-17  3152  	}
ef8f9bea1368b89 Libin Yang           2015-12-02  3153  	port->has_audio = drm_detect_monitor_audio(edid);
d0757afd00d71dc Lyude Paul           2019-01-10  3154  	drm_dp_mst_topology_put_port(port);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3155  	return edid;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3156  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3157  EXPORT_SYMBOL(drm_dp_mst_get_edid);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3158  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3159  /**
e4b0c868106d7ef Lyude Paul           2018-10-23  3160   * drm_dp_find_vcpi_slots() - Find VCPI slots for this PBN value
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3161   * @mgr: manager to use
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3162   * @pbn: payload bandwidth to convert into slots.
e4b0c868106d7ef Lyude Paul           2018-10-23  3163   *
e4b0c868106d7ef Lyude Paul           2018-10-23  3164   * Calculate the number of VCPI slots that will be required for the given PBN
e4b0c868106d7ef Lyude Paul           2018-10-23  3165   * value. This function is deprecated, and should not be used in atomic
e4b0c868106d7ef Lyude Paul           2018-10-23  3166   * drivers.
e4b0c868106d7ef Lyude Paul           2018-10-23  3167   *
e4b0c868106d7ef Lyude Paul           2018-10-23  3168   * RETURNS:
e4b0c868106d7ef Lyude Paul           2018-10-23  3169   * The total slots required for this port, or error.
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3170   */
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3171  int drm_dp_find_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3172  			   int pbn)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3173  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3174  	int num_slots;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3175  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3176  	num_slots = DIV_ROUND_UP(pbn, mgr->pbn_div);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3177  
feb2c3bc331576e Pandiyan, Dhinakaran 2017-03-16  3178  	/* max. time slots - one slot for MTP header */
feb2c3bc331576e Pandiyan, Dhinakaran 2017-03-16  3179  	if (num_slots > 63)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3180  		return -ENOSPC;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3181  	return num_slots;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3182  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3183  EXPORT_SYMBOL(drm_dp_find_vcpi_slots);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3184  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3185  static int drm_dp_init_vcpi(struct drm_dp_mst_topology_mgr *mgr,
1e797f556c616a4 Pandiyan, Dhinakaran 2017-03-16  3186  			    struct drm_dp_vcpi *vcpi, int pbn, int slots)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3187  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3188  	int ret;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3189  
feb2c3bc331576e Pandiyan, Dhinakaran 2017-03-16  3190  	/* max. time slots - one slot for MTP header */
1e797f556c616a4 Pandiyan, Dhinakaran 2017-03-16  3191  	if (slots > 63)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3192  		return -ENOSPC;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3193  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3194  	vcpi->pbn = pbn;
1e797f556c616a4 Pandiyan, Dhinakaran 2017-03-16  3195  	vcpi->aligned_pbn = slots * mgr->pbn_div;
1e797f556c616a4 Pandiyan, Dhinakaran 2017-03-16  3196  	vcpi->num_slots = slots;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3197  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3198  	ret = drm_dp_mst_assign_payload_id(mgr, vcpi);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3199  	if (ret < 0)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3200  		return ret;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3201  	return 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3202  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3203  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3204  /**
eceae147246749c Lyude Paul           2019-01-10  3205   * drm_dp_atomic_find_vcpi_slots() - Find and add VCPI slots to the state
edb1ed1ab7d314e Pandiyan, Dhinakaran 2017-04-20  3206   * @state: global atomic state
edb1ed1ab7d314e Pandiyan, Dhinakaran 2017-04-20  3207   * @mgr: MST topology manager for the port
edb1ed1ab7d314e Pandiyan, Dhinakaran 2017-04-20  3208   * @port: port to find vcpi slots for
edb1ed1ab7d314e Pandiyan, Dhinakaran 2017-04-20  3209   * @pbn: bandwidth required for the mode in PBN
edb1ed1ab7d314e Pandiyan, Dhinakaran 2017-04-20  3210   *
eceae147246749c Lyude Paul           2019-01-10  3211   * Allocates VCPI slots to @port, replacing any previous VCPI allocations it
eceae147246749c Lyude Paul           2019-01-10  3212   * may have had. Any atomic drivers which support MST must call this function
eceae147246749c Lyude Paul           2019-01-10  3213   * in their &drm_encoder_helper_funcs.atomic_check() callback to change the
eceae147246749c Lyude Paul           2019-01-10  3214   * current VCPI allocation for the new state, but only when
eceae147246749c Lyude Paul           2019-01-10  3215   * &drm_crtc_state.mode_changed or &drm_crtc_state.connectors_changed is set
eceae147246749c Lyude Paul           2019-01-10  3216   * to ensure compatibility with userspace applications that still use the
eceae147246749c Lyude Paul           2019-01-10  3217   * legacy modesetting UAPI.
eceae147246749c Lyude Paul           2019-01-10  3218   *
eceae147246749c Lyude Paul           2019-01-10  3219   * Allocations set by this function are not checked against the bandwidth
eceae147246749c Lyude Paul           2019-01-10  3220   * restraints of @mgr until the driver calls drm_dp_mst_atomic_check().
eceae147246749c Lyude Paul           2019-01-10  3221   *
eceae147246749c Lyude Paul           2019-01-10  3222   * Additionally, it is OK to call this function multiple times on the same
eceae147246749c Lyude Paul           2019-01-10  3223   * @port as needed. It is not OK however, to call this function and
eceae147246749c Lyude Paul           2019-01-10  3224   * drm_dp_atomic_release_vcpi_slots() in the same atomic check phase.
eceae147246749c Lyude Paul           2019-01-10  3225   *
eceae147246749c Lyude Paul           2019-01-10  3226   * See also:
eceae147246749c Lyude Paul           2019-01-10  3227   * drm_dp_atomic_release_vcpi_slots()
eceae147246749c Lyude Paul           2019-01-10  3228   * drm_dp_mst_atomic_check()
eceae147246749c Lyude Paul           2019-01-10  3229   *
eceae147246749c Lyude Paul           2019-01-10  3230   * Returns:
eceae147246749c Lyude Paul           2019-01-10  3231   * Total slots in the atomic state assigned for this port, or a negative error
eceae147246749c Lyude Paul           2019-01-10  3232   * code if the port no longer exists
edb1ed1ab7d314e Pandiyan, Dhinakaran 2017-04-20  3233   */
edb1ed1ab7d314e Pandiyan, Dhinakaran 2017-04-20  3234  int drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state,
edb1ed1ab7d314e Pandiyan, Dhinakaran 2017-04-20  3235  				  struct drm_dp_mst_topology_mgr *mgr,
edb1ed1ab7d314e Pandiyan, Dhinakaran 2017-04-20  3236  				  struct drm_dp_mst_port *port, int pbn)
edb1ed1ab7d314e Pandiyan, Dhinakaran 2017-04-20  3237  {
edb1ed1ab7d314e Pandiyan, Dhinakaran 2017-04-20  3238  	struct drm_dp_mst_topology_state *topology_state;
eceae147246749c Lyude Paul           2019-01-10  3239  	struct drm_dp_vcpi_allocation *pos, *vcpi = NULL;
eceae147246749c Lyude Paul           2019-01-10  3240  	int prev_slots, req_slots, ret;
edb1ed1ab7d314e Pandiyan, Dhinakaran 2017-04-20  3241  
edb1ed1ab7d314e Pandiyan, Dhinakaran 2017-04-20  3242  	topology_state = drm_atomic_get_mst_topology_state(state, mgr);
56a91c4932bd038 Ville Syrjälä        2017-07-12  3243  	if (IS_ERR(topology_state))
56a91c4932bd038 Ville Syrjälä        2017-07-12  3244  		return PTR_ERR(topology_state);
edb1ed1ab7d314e Pandiyan, Dhinakaran 2017-04-20  3245  
eceae147246749c Lyude Paul           2019-01-10  3246  	/* Find the current allocation for this port, if any */
eceae147246749c Lyude Paul           2019-01-10  3247  	list_for_each_entry(pos, &topology_state->vcpis, next) {
eceae147246749c Lyude Paul           2019-01-10  3248  		if (pos->port == port) {
eceae147246749c Lyude Paul           2019-01-10  3249  			vcpi = pos;
eceae147246749c Lyude Paul           2019-01-10  3250  			prev_slots = vcpi->vcpi;
eceae147246749c Lyude Paul           2019-01-10  3251  
eceae147246749c Lyude Paul           2019-01-10  3252  			/*
eceae147246749c Lyude Paul           2019-01-10  3253  			 * This should never happen, unless the driver tries
eceae147246749c Lyude Paul           2019-01-10  3254  			 * releasing and allocating the same VCPI allocation,
eceae147246749c Lyude Paul           2019-01-10  3255  			 * which is an error
eceae147246749c Lyude Paul           2019-01-10  3256  			 */
eceae147246749c Lyude Paul           2019-01-10  3257  			if (WARN_ON(!prev_slots)) {
eceae147246749c Lyude Paul           2019-01-10  3258  				DRM_ERROR("cannot allocate and release VCPI on [MST PORT:%p] in the same state\n",
eceae147246749c Lyude Paul           2019-01-10  3259  					  port);
eceae147246749c Lyude Paul           2019-01-10  3260  				return -EINVAL;
eceae147246749c Lyude Paul           2019-01-10  3261  			}
eceae147246749c Lyude Paul           2019-01-10  3262  
eceae147246749c Lyude Paul           2019-01-10  3263  			break;
eceae147246749c Lyude Paul           2019-01-10  3264  		}
eceae147246749c Lyude Paul           2019-01-10  3265  	}
eceae147246749c Lyude Paul           2019-01-10  3266  	if (!vcpi)
eceae147246749c Lyude Paul           2019-01-10  3267  		prev_slots = 0;
eceae147246749c Lyude Paul           2019-01-10  3268  
edb1ed1ab7d314e Pandiyan, Dhinakaran 2017-04-20  3269  	req_slots = DIV_ROUND_UP(pbn, mgr->pbn_div);
edb1ed1ab7d314e Pandiyan, Dhinakaran 2017-04-20  3270  
eceae147246749c Lyude Paul           2019-01-10  3271  	DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] [MST PORT:%p] VCPI %d -> %d\n",
eceae147246749c Lyude Paul           2019-01-10  3272  			 port->connector->base.id, port->connector->name,
eceae147246749c Lyude Paul           2019-01-10  3273  			 port, prev_slots, req_slots);
eceae147246749c Lyude Paul           2019-01-10  3274  
eceae147246749c Lyude Paul           2019-01-10  3275  	/* Add the new allocation to the state */
eceae147246749c Lyude Paul           2019-01-10  3276  	if (!vcpi) {
eceae147246749c Lyude Paul           2019-01-10  3277  		vcpi = kzalloc(sizeof(*vcpi), GFP_KERNEL);
a3d15c4b0ecd169 Lyude Paul           2019-02-01  3278  		if (!vcpi)
a3d15c4b0ecd169 Lyude Paul           2019-02-01  3279  			return -ENOMEM;
edb1ed1ab7d314e Pandiyan, Dhinakaran 2017-04-20  3280  
eceae147246749c Lyude Paul           2019-01-10  3281  		drm_dp_mst_get_port_malloc(port);
eceae147246749c Lyude Paul           2019-01-10  3282  		vcpi->port = port;
eceae147246749c Lyude Paul           2019-01-10  3283  		list_add(&vcpi->next, &topology_state->vcpis);
eceae147246749c Lyude Paul           2019-01-10  3284  	}
eceae147246749c Lyude Paul           2019-01-10  3285  	vcpi->vcpi = req_slots;
edb1ed1ab7d314e Pandiyan, Dhinakaran 2017-04-20  3286  
eceae147246749c Lyude Paul           2019-01-10  3287  	ret = req_slots;
eceae147246749c Lyude Paul           2019-01-10  3288  	return ret;
edb1ed1ab7d314e Pandiyan, Dhinakaran 2017-04-20  3289  }
edb1ed1ab7d314e Pandiyan, Dhinakaran 2017-04-20  3290  EXPORT_SYMBOL(drm_dp_atomic_find_vcpi_slots);
edb1ed1ab7d314e Pandiyan, Dhinakaran 2017-04-20  3291  
edb1ed1ab7d314e Pandiyan, Dhinakaran 2017-04-20  3292  /**
edb1ed1ab7d314e Pandiyan, Dhinakaran 2017-04-20  3293   * drm_dp_atomic_release_vcpi_slots() - Release allocated vcpi slots
edb1ed1ab7d314e Pandiyan, Dhinakaran 2017-04-20  3294   * @state: global atomic state
edb1ed1ab7d314e Pandiyan, Dhinakaran 2017-04-20  3295   * @mgr: MST topology manager for the port
eceae147246749c Lyude Paul           2019-01-10  3296   * @port: The port to release the VCPI slots from
edb1ed1ab7d314e Pandiyan, Dhinakaran 2017-04-20  3297   *
eceae147246749c Lyude Paul           2019-01-10  3298   * Releases any VCPI slots that have been allocated to a port in the atomic
eceae147246749c Lyude Paul           2019-01-10  3299   * state. Any atomic drivers which support MST must call this function in
eceae147246749c Lyude Paul           2019-01-10  3300   * their &drm_connector_helper_funcs.atomic_check() callback when the
1e55a53a28d3e52 Matt Roper           2019-02-01  3301   * connector will no longer have VCPI allocated (e.g. because its CRTC was
eceae147246749c Lyude Paul           2019-01-10  3302   * removed) when it had VCPI allocated in the previous atomic state.
eceae147246749c Lyude Paul           2019-01-10  3303   *
eceae147246749c Lyude Paul           2019-01-10  3304   * It is OK to call this even if @port has been removed from the system.
eceae147246749c Lyude Paul           2019-01-10  3305   * Additionally, it is OK to call this function multiple times on the same
eceae147246749c Lyude Paul           2019-01-10  3306   * @port as needed. It is not OK however, to call this function and
eceae147246749c Lyude Paul           2019-01-10  3307   * drm_dp_atomic_find_vcpi_slots() on the same @port in a single atomic check
eceae147246749c Lyude Paul           2019-01-10  3308   * phase.
eceae147246749c Lyude Paul           2019-01-10  3309   *
eceae147246749c Lyude Paul           2019-01-10  3310   * See also:
eceae147246749c Lyude Paul           2019-01-10  3311   * drm_dp_atomic_find_vcpi_slots()
eceae147246749c Lyude Paul           2019-01-10  3312   * drm_dp_mst_atomic_check()
eceae147246749c Lyude Paul           2019-01-10  3313   *
eceae147246749c Lyude Paul           2019-01-10  3314   * Returns:
eceae147246749c Lyude Paul           2019-01-10  3315   * 0 if all slots for this port were added back to
eceae147246749c Lyude Paul           2019-01-10  3316   * &drm_dp_mst_topology_state.avail_slots or negative error code
edb1ed1ab7d314e Pandiyan, Dhinakaran 2017-04-20  3317   */
edb1ed1ab7d314e Pandiyan, Dhinakaran 2017-04-20  3318  int drm_dp_atomic_release_vcpi_slots(struct drm_atomic_state *state,
edb1ed1ab7d314e Pandiyan, Dhinakaran 2017-04-20  3319  				     struct drm_dp_mst_topology_mgr *mgr,
eceae147246749c Lyude Paul           2019-01-10  3320  				     struct drm_dp_mst_port *port)
edb1ed1ab7d314e Pandiyan, Dhinakaran 2017-04-20  3321  {
edb1ed1ab7d314e Pandiyan, Dhinakaran 2017-04-20  3322  	struct drm_dp_mst_topology_state *topology_state;
eceae147246749c Lyude Paul           2019-01-10  3323  	struct drm_dp_vcpi_allocation *pos;
eceae147246749c Lyude Paul           2019-01-10  3324  	bool found = false;
edb1ed1ab7d314e Pandiyan, Dhinakaran 2017-04-20  3325  
edb1ed1ab7d314e Pandiyan, Dhinakaran 2017-04-20  3326  	topology_state = drm_atomic_get_mst_topology_state(state, mgr);
56a91c4932bd038 Ville Syrjälä        2017-07-12  3327  	if (IS_ERR(topology_state))
56a91c4932bd038 Ville Syrjälä        2017-07-12  3328  		return PTR_ERR(topology_state);
edb1ed1ab7d314e Pandiyan, Dhinakaran 2017-04-20  3329  
eceae147246749c Lyude Paul           2019-01-10  3330  	list_for_each_entry(pos, &topology_state->vcpis, next) {
eceae147246749c Lyude Paul           2019-01-10  3331  		if (pos->port == port) {
eceae147246749c Lyude Paul           2019-01-10  3332  			found = true;
eceae147246749c Lyude Paul           2019-01-10  3333  			break;
eceae147246749c Lyude Paul           2019-01-10  3334  		}
eceae147246749c Lyude Paul           2019-01-10  3335  	}
eceae147246749c Lyude Paul           2019-01-10  3336  	if (WARN_ON(!found)) {
eceae147246749c Lyude Paul           2019-01-10  3337  		DRM_ERROR("no VCPI for [MST PORT:%p] found in mst state %p\n",
eceae147246749c Lyude Paul           2019-01-10  3338  			  port, &topology_state->base);
eceae147246749c Lyude Paul           2019-01-10  3339  		return -EINVAL;
eceae147246749c Lyude Paul           2019-01-10  3340  	}
eceae147246749c Lyude Paul           2019-01-10  3341  
eceae147246749c Lyude Paul           2019-01-10  3342  	DRM_DEBUG_ATOMIC("[MST PORT:%p] VCPI %d -> 0\n", port, pos->vcpi);
eceae147246749c Lyude Paul           2019-01-10  3343  	if (pos->vcpi) {
eceae147246749c Lyude Paul           2019-01-10  3344  		drm_dp_mst_put_port_malloc(port);
eceae147246749c Lyude Paul           2019-01-10  3345  		pos->vcpi = 0;
eceae147246749c Lyude Paul           2019-01-10  3346  	}
edb1ed1ab7d314e Pandiyan, Dhinakaran 2017-04-20  3347  
edb1ed1ab7d314e Pandiyan, Dhinakaran 2017-04-20  3348  	return 0;
edb1ed1ab7d314e Pandiyan, Dhinakaran 2017-04-20  3349  }
edb1ed1ab7d314e Pandiyan, Dhinakaran 2017-04-20  3350  EXPORT_SYMBOL(drm_dp_atomic_release_vcpi_slots);
edb1ed1ab7d314e Pandiyan, Dhinakaran 2017-04-20  3351  
edb1ed1ab7d314e Pandiyan, Dhinakaran 2017-04-20  3352  /**
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3353   * drm_dp_mst_allocate_vcpi() - Allocate a virtual channel
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3354   * @mgr: manager for this port
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3355   * @port: port to allocate a virtual channel for.
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3356   * @pbn: payload bandwidth number to request
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3357   * @slots: returned number of slots for this PBN.
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3358   */
1e797f556c616a4 Pandiyan, Dhinakaran 2017-03-16  3359  bool drm_dp_mst_allocate_vcpi(struct drm_dp_mst_topology_mgr *mgr,
1e797f556c616a4 Pandiyan, Dhinakaran 2017-03-16  3360  			      struct drm_dp_mst_port *port, int pbn, int slots)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3361  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3362  	int ret;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3363  
d0757afd00d71dc Lyude Paul           2019-01-10  3364  	port = drm_dp_mst_topology_get_port_validated(mgr, port);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3365  	if (!port)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3366  		return false;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3367  
1e797f556c616a4 Pandiyan, Dhinakaran 2017-03-16  3368  	if (slots < 0)
1e797f556c616a4 Pandiyan, Dhinakaran 2017-03-16  3369  		return false;
1e797f556c616a4 Pandiyan, Dhinakaran 2017-03-16  3370  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3371  	if (port->vcpi.vcpi > 0) {
e0ac7113fb23519 Lyude Paul           2019-01-10  3372  		DRM_DEBUG_KMS("payload: vcpi %d already allocated for pbn %d - requested pbn %d\n",
e0ac7113fb23519 Lyude Paul           2019-01-10  3373  			      port->vcpi.vcpi, port->vcpi.pbn, pbn);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3374  		if (pbn == port->vcpi.pbn) {
d0757afd00d71dc Lyude Paul           2019-01-10  3375  			drm_dp_mst_topology_put_port(port);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3376  			return true;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3377  		}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3378  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3379  
1e797f556c616a4 Pandiyan, Dhinakaran 2017-03-16  3380  	ret = drm_dp_init_vcpi(mgr, &port->vcpi, pbn, slots);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3381  	if (ret) {
feb2c3bc331576e Pandiyan, Dhinakaran 2017-03-16  3382  		DRM_DEBUG_KMS("failed to init vcpi slots=%d max=63 ret=%d\n",
feb2c3bc331576e Pandiyan, Dhinakaran 2017-03-16  3383  			      DIV_ROUND_UP(pbn, mgr->pbn_div), ret);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3384  		goto out;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3385  	}
feb2c3bc331576e Pandiyan, Dhinakaran 2017-03-16  3386  	DRM_DEBUG_KMS("initing vcpi for pbn=%d slots=%d\n",
feb2c3bc331576e Pandiyan, Dhinakaran 2017-03-16  3387  		      pbn, port->vcpi.num_slots);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3388  
1e55a53a28d3e52 Matt Roper           2019-02-01  3389  	/* Keep port allocated until its payload has been removed */
cfe9f90358d97a8 Lyude Paul           2019-01-10  3390  	drm_dp_mst_get_port_malloc(port);
d0757afd00d71dc Lyude Paul           2019-01-10  3391  	drm_dp_mst_topology_put_port(port);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3392  	return true;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3393  out:
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3394  	return false;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3395  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3396  EXPORT_SYMBOL(drm_dp_mst_allocate_vcpi);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3397  
87f5942d1f7bc32 Dave Airlie          2015-02-24  3398  int drm_dp_mst_get_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port)
87f5942d1f7bc32 Dave Airlie          2015-02-24  3399  {
87f5942d1f7bc32 Dave Airlie          2015-02-24  3400  	int slots = 0;
d0757afd00d71dc Lyude Paul           2019-01-10  3401  	port = drm_dp_mst_topology_get_port_validated(mgr, port);
87f5942d1f7bc32 Dave Airlie          2015-02-24  3402  	if (!port)
87f5942d1f7bc32 Dave Airlie          2015-02-24  3403  		return slots;
87f5942d1f7bc32 Dave Airlie          2015-02-24  3404  
87f5942d1f7bc32 Dave Airlie          2015-02-24  3405  	slots = port->vcpi.num_slots;
d0757afd00d71dc Lyude Paul           2019-01-10  3406  	drm_dp_mst_topology_put_port(port);
87f5942d1f7bc32 Dave Airlie          2015-02-24  3407  	return slots;
87f5942d1f7bc32 Dave Airlie          2015-02-24  3408  }
87f5942d1f7bc32 Dave Airlie          2015-02-24  3409  EXPORT_SYMBOL(drm_dp_mst_get_vcpi_slots);
87f5942d1f7bc32 Dave Airlie          2015-02-24  3410  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3411  /**
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3412   * drm_dp_mst_reset_vcpi_slots() - Reset number of slots to 0 for VCPI
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3413   * @mgr: manager for this port
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3414   * @port: unverified pointer to a port.
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3415   *
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3416   * This just resets the number of slots for the ports VCPI for later programming.
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3417   */
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3418  void drm_dp_mst_reset_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3419  {
cfe9f90358d97a8 Lyude Paul           2019-01-10  3420  	/*
1e55a53a28d3e52 Matt Roper           2019-02-01  3421  	 * A port with VCPI will remain allocated until its VCPI is
cfe9f90358d97a8 Lyude Paul           2019-01-10  3422  	 * released, no verified ref needed
cfe9f90358d97a8 Lyude Paul           2019-01-10  3423  	 */
cfe9f90358d97a8 Lyude Paul           2019-01-10  3424  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3425  	port->vcpi.num_slots = 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3426  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3427  EXPORT_SYMBOL(drm_dp_mst_reset_vcpi_slots);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3428  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3429  /**
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3430   * drm_dp_mst_deallocate_vcpi() - deallocate a VCPI
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3431   * @mgr: manager for this port
3a8844c298522fa Lyude Paul           2019-02-01  3432   * @port: port to deallocate vcpi for
3a8844c298522fa Lyude Paul           2019-02-01  3433   *
3a8844c298522fa Lyude Paul           2019-02-01  3434   * This can be called unconditionally, regardless of whether
3a8844c298522fa Lyude Paul           2019-02-01  3435   * drm_dp_mst_allocate_vcpi() succeeded or not.
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3436   */
4afb8a26b53a6d9 Lyude Paul           2019-01-10  3437  void drm_dp_mst_deallocate_vcpi(struct drm_dp_mst_topology_mgr *mgr,
4afb8a26b53a6d9 Lyude Paul           2019-01-10  3438  				struct drm_dp_mst_port *port)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3439  {
3a8844c298522fa Lyude Paul           2019-02-01  3440  	if (!port->vcpi.vcpi)
3a8844c298522fa Lyude Paul           2019-02-01  3441  		return;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3442  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3443  	drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3444  	port->vcpi.num_slots = 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3445  	port->vcpi.pbn = 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3446  	port->vcpi.aligned_pbn = 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3447  	port->vcpi.vcpi = 0;
cfe9f90358d97a8 Lyude Paul           2019-01-10  3448  	drm_dp_mst_put_port_malloc(port);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3449  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3450  EXPORT_SYMBOL(drm_dp_mst_deallocate_vcpi);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3451  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3452  static int drm_dp_dpcd_write_payload(struct drm_dp_mst_topology_mgr *mgr,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3453  				     int id, struct drm_dp_payload *payload)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3454  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3455  	u8 payload_alloc[3], status;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3456  	int ret;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3457  	int retries = 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3458  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3459  	drm_dp_dpcd_writeb(mgr->aux, DP_PAYLOAD_TABLE_UPDATE_STATUS,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3460  			   DP_PAYLOAD_TABLE_UPDATED);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3461  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3462  	payload_alloc[0] = id;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3463  	payload_alloc[1] = payload->start_slot;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3464  	payload_alloc[2] = payload->num_slots;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3465  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3466  	ret = drm_dp_dpcd_write(mgr->aux, DP_PAYLOAD_ALLOCATE_SET, payload_alloc, 3);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3467  	if (ret != 3) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3468  		DRM_DEBUG_KMS("failed to write payload allocation %d\n", ret);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3469  		goto fail;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3470  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3471  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3472  retry:
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3473  	ret = drm_dp_dpcd_readb(mgr->aux, DP_PAYLOAD_TABLE_UPDATE_STATUS, &status);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3474  	if (ret < 0) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3475  		DRM_DEBUG_KMS("failed to read payload table status %d\n", ret);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3476  		goto fail;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3477  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3478  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3479  	if (!(status & DP_PAYLOAD_TABLE_UPDATED)) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3480  		retries++;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3481  		if (retries < 20) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3482  			usleep_range(10000, 20000);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3483  			goto retry;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3484  		}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3485  		DRM_DEBUG_KMS("status not set after read payload table status %d\n", status);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3486  		ret = -EINVAL;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3487  		goto fail;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3488  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3489  	ret = 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3490  fail:
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3491  	return ret;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3492  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3493  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3494  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3495  /**
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3496   * drm_dp_check_act_status() - Check ACT handled status.
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3497   * @mgr: manager to use
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3498   *
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3499   * Check the payload status bits in the DPCD for ACT handled completion.
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3500   */
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3501  int drm_dp_check_act_status(struct drm_dp_mst_topology_mgr *mgr)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3502  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3503  	u8 status;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3504  	int ret;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3505  	int count = 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3506  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3507  	do {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3508  		ret = drm_dp_dpcd_readb(mgr->aux, DP_PAYLOAD_TABLE_UPDATE_STATUS, &status);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3509  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3510  		if (ret < 0) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3511  			DRM_DEBUG_KMS("failed to read payload table status %d\n", ret);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3512  			goto fail;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3513  		}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3514  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3515  		if (status & DP_PAYLOAD_ACT_HANDLED)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3516  			break;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3517  		count++;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3518  		udelay(100);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3519  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3520  	} while (count < 30);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3521  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3522  	if (!(status & DP_PAYLOAD_ACT_HANDLED)) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3523  		DRM_DEBUG_KMS("failed to get ACT bit %d after %d retries\n", status, count);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3524  		ret = -EINVAL;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3525  		goto fail;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3526  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3527  	return 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3528  fail:
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3529  	return ret;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3530  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3531  EXPORT_SYMBOL(drm_dp_check_act_status);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3532  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3533  /**
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3534   * drm_dp_calc_pbn_mode() - Calculate the PBN for a mode.
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3535   * @clock: dot clock for the mode
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3536   * @bpp: bpp for the mode.
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3537   *
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3538   * This uses the formula in the spec to calculate the PBN value for a mode.
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3539   */
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3540  int drm_dp_calc_pbn_mode(int clock, int bpp)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3541  {
a9ebb3e46c7ef61 Harry Wentland       2016-01-22  3542  	u64 kbps;
a9ebb3e46c7ef61 Harry Wentland       2016-01-22  3543  	s64 peak_kbps;
a9ebb3e46c7ef61 Harry Wentland       2016-01-22  3544  	u32 numerator;
a9ebb3e46c7ef61 Harry Wentland       2016-01-22  3545  	u32 denominator;
a9ebb3e46c7ef61 Harry Wentland       2016-01-22  3546  
a9ebb3e46c7ef61 Harry Wentland       2016-01-22  3547  	kbps = clock * bpp;
a9ebb3e46c7ef61 Harry Wentland       2016-01-22  3548  
a9ebb3e46c7ef61 Harry Wentland       2016-01-22  3549  	/*
a9ebb3e46c7ef61 Harry Wentland       2016-01-22  3550  	 * margin 5300ppm + 300ppm ~ 0.6% as per spec, factor is 1.006
a9ebb3e46c7ef61 Harry Wentland       2016-01-22  3551  	 * The unit of 54/64Mbytes/sec is an arbitrary unit chosen based on
a9ebb3e46c7ef61 Harry Wentland       2016-01-22  3552  	 * common multiplier to render an integer PBN for all link rate/lane
a9ebb3e46c7ef61 Harry Wentland       2016-01-22  3553  	 * counts combinations
a9ebb3e46c7ef61 Harry Wentland       2016-01-22  3554  	 * calculate
a9ebb3e46c7ef61 Harry Wentland       2016-01-22  3555  	 * peak_kbps *= (1006/1000)
a9ebb3e46c7ef61 Harry Wentland       2016-01-22  3556  	 * peak_kbps *= (64/54)
a9ebb3e46c7ef61 Harry Wentland       2016-01-22  3557  	 * peak_kbps *= 8    convert to bytes
a9ebb3e46c7ef61 Harry Wentland       2016-01-22  3558  	 */
a9ebb3e46c7ef61 Harry Wentland       2016-01-22  3559  
a9ebb3e46c7ef61 Harry Wentland       2016-01-22  3560  	numerator = 64 * 1006;
a9ebb3e46c7ef61 Harry Wentland       2016-01-22  3561  	denominator = 54 * 8 * 1000 * 1000;
a9ebb3e46c7ef61 Harry Wentland       2016-01-22  3562  
a9ebb3e46c7ef61 Harry Wentland       2016-01-22  3563  	kbps *= numerator;
a9ebb3e46c7ef61 Harry Wentland       2016-01-22  3564  	peak_kbps = drm_fixp_from_fraction(kbps, denominator);
a9ebb3e46c7ef61 Harry Wentland       2016-01-22  3565  
a9ebb3e46c7ef61 Harry Wentland       2016-01-22  3566  	return drm_fixp2int_ceil(peak_kbps);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3567  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3568  EXPORT_SYMBOL(drm_dp_calc_pbn_mode);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3569  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3570  static int test_calc_pbn_mode(void)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3571  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3572  	int ret;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3573  	ret = drm_dp_calc_pbn_mode(154000, 30);
a9ebb3e46c7ef61 Harry Wentland       2016-01-22  3574  	if (ret != 689) {
a9ebb3e46c7ef61 Harry Wentland       2016-01-22  3575  		DRM_ERROR("PBN calculation test failed - clock %d, bpp %d, expected PBN %d, actual PBN %d.\n",
a9ebb3e46c7ef61 Harry Wentland       2016-01-22  3576  				154000, 30, 689, ret);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3577  		return -EINVAL;
a9ebb3e46c7ef61 Harry Wentland       2016-01-22  3578  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3579  	ret = drm_dp_calc_pbn_mode(234000, 30);
a9ebb3e46c7ef61 Harry Wentland       2016-01-22  3580  	if (ret != 1047) {
a9ebb3e46c7ef61 Harry Wentland       2016-01-22  3581  		DRM_ERROR("PBN calculation test failed - clock %d, bpp %d, expected PBN %d, actual PBN %d.\n",
a9ebb3e46c7ef61 Harry Wentland       2016-01-22  3582  				234000, 30, 1047, ret);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3583  		return -EINVAL;
a9ebb3e46c7ef61 Harry Wentland       2016-01-22  3584  	}
a9ebb3e46c7ef61 Harry Wentland       2016-01-22  3585  	ret = drm_dp_calc_pbn_mode(297000, 24);
a9ebb3e46c7ef61 Harry Wentland       2016-01-22  3586  	if (ret != 1063) {
a9ebb3e46c7ef61 Harry Wentland       2016-01-22  3587  		DRM_ERROR("PBN calculation test failed - clock %d, bpp %d, expected PBN %d, actual PBN %d.\n",
a9ebb3e46c7ef61 Harry Wentland       2016-01-22  3588  				297000, 24, 1063, ret);
a9ebb3e46c7ef61 Harry Wentland       2016-01-22  3589  		return -EINVAL;
a9ebb3e46c7ef61 Harry Wentland       2016-01-22  3590  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3591  	return 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3592  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3593  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3594  /* we want to kick the TX after we've ack the up/down IRQs. */
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3595  static void drm_dp_mst_kick_tx(struct drm_dp_mst_topology_mgr *mgr)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3596  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3597  	queue_work(system_long_wq, &mgr->tx_work);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3598  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3599  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3600  static void drm_dp_mst_dump_mstb(struct seq_file *m,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3601  				 struct drm_dp_mst_branch *mstb)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3602  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3603  	struct drm_dp_mst_port *port;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3604  	int tabs = mstb->lct;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3605  	char prefix[10];
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3606  	int i;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3607  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3608  	for (i = 0; i < tabs; i++)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3609  		prefix[i] = '\t';
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3610  	prefix[i] = '\0';
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3611  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3612  	seq_printf(m, "%smst: %p, %d\n", prefix, mstb, mstb->num_ports);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3613  	list_for_each_entry(port, &mstb->ports, next) {
51108f252b02d3b Jim Bride            2016-04-14  3614  		seq_printf(m, "%sport: %d: input: %d: pdt: %d, ddps: %d ldps: %d, sdp: %d/%d, %p, conn: %p\n", prefix, port->port_num, port->input, port->pdt, port->ddps, port->ldps, port->num_sdp_streams, port->num_sdp_stream_sinks, port, port->connector);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3615  		if (port->mstb)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3616  			drm_dp_mst_dump_mstb(m, port->mstb);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3617  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3618  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3619  
7056a2bccc3b5af Andy Shevchenko      2018-03-19  3620  #define DP_PAYLOAD_TABLE_SIZE		64
7056a2bccc3b5af Andy Shevchenko      2018-03-19  3621  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3622  static bool dump_dp_payload_table(struct drm_dp_mst_topology_mgr *mgr,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3623  				  char *buf)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3624  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3625  	int i;
46466b0dac3f6be Joe Perches          2017-05-30  3626  
7056a2bccc3b5af Andy Shevchenko      2018-03-19  3627  	for (i = 0; i < DP_PAYLOAD_TABLE_SIZE; i += 16) {
46466b0dac3f6be Joe Perches          2017-05-30  3628  		if (drm_dp_dpcd_read(mgr->aux,
46466b0dac3f6be Joe Perches          2017-05-30  3629  				     DP_PAYLOAD_TABLE_UPDATE_STATUS + i,
46466b0dac3f6be Joe Perches          2017-05-30  3630  				     &buf[i], 16) != 16)
46466b0dac3f6be Joe Perches          2017-05-30  3631  			return false;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3632  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3633  	return true;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3634  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3635  
51108f252b02d3b Jim Bride            2016-04-14  3636  static void fetch_monitor_name(struct drm_dp_mst_topology_mgr *mgr,
51108f252b02d3b Jim Bride            2016-04-14  3637  			       struct drm_dp_mst_port *port, char *name,
51108f252b02d3b Jim Bride            2016-04-14  3638  			       int namelen)
51108f252b02d3b Jim Bride            2016-04-14  3639  {
51108f252b02d3b Jim Bride            2016-04-14  3640  	struct edid *mst_edid;
51108f252b02d3b Jim Bride            2016-04-14  3641  
51108f252b02d3b Jim Bride            2016-04-14  3642  	mst_edid = drm_dp_mst_get_edid(port->connector, mgr, port);
51108f252b02d3b Jim Bride            2016-04-14  3643  	drm_edid_get_monitor_name(mst_edid, name, namelen);
51108f252b02d3b Jim Bride            2016-04-14  3644  }
51108f252b02d3b Jim Bride            2016-04-14  3645  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3646  /**
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3647   * drm_dp_mst_dump_topology(): dump topology to seq file.
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3648   * @m: seq_file to dump output to
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3649   * @mgr: manager to dump current topology for.
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3650   *
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3651   * helper to dump MST topology to a seq file for debugfs.
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3652   */
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3653  void drm_dp_mst_dump_topology(struct seq_file *m,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3654  			      struct drm_dp_mst_topology_mgr *mgr)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3655  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3656  	int i;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3657  	struct drm_dp_mst_port *port;
51108f252b02d3b Jim Bride            2016-04-14  3658  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3659  	mutex_lock(&mgr->lock);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3660  	if (mgr->mst_primary)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3661  		drm_dp_mst_dump_mstb(m, mgr->mst_primary);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3662  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3663  	/* dump VCPIs */
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3664  	mutex_unlock(&mgr->lock);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3665  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3666  	mutex_lock(&mgr->payload_lock);
51108f252b02d3b Jim Bride            2016-04-14  3667  	seq_printf(m, "vcpi: %lx %lx %d\n", mgr->payload_mask, mgr->vcpi_mask,
51108f252b02d3b Jim Bride            2016-04-14  3668  		mgr->max_payloads);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3669  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3670  	for (i = 0; i < mgr->max_payloads; i++) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3671  		if (mgr->proposed_vcpis[i]) {
51108f252b02d3b Jim Bride            2016-04-14  3672  			char name[14];
51108f252b02d3b Jim Bride            2016-04-14  3673  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3674  			port = container_of(mgr->proposed_vcpis[i], struct drm_dp_mst_port, vcpi);
51108f252b02d3b Jim Bride            2016-04-14  3675  			fetch_monitor_name(mgr, port, name, sizeof(name));
51108f252b02d3b Jim Bride            2016-04-14  3676  			seq_printf(m, "vcpi %d: %d %d %d sink name: %s\n", i,
51108f252b02d3b Jim Bride            2016-04-14  3677  				   port->port_num, port->vcpi.vcpi,
51108f252b02d3b Jim Bride            2016-04-14  3678  				   port->vcpi.num_slots,
51108f252b02d3b Jim Bride            2016-04-14  3679  				   (*name != 0) ? name :  "Unknown");
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3680  		} else
51108f252b02d3b Jim Bride            2016-04-14  3681  			seq_printf(m, "vcpi %d:unused\n", i);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3682  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3683  	for (i = 0; i < mgr->max_payloads; i++) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3684  		seq_printf(m, "payload %d: %d, %d, %d\n",
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3685  			   i,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3686  			   mgr->payloads[i].payload_state,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3687  			   mgr->payloads[i].start_slot,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3688  			   mgr->payloads[i].num_slots);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3689  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3690  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3691  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3692  	mutex_unlock(&mgr->payload_lock);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3693  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3694  	mutex_lock(&mgr->lock);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3695  	if (mgr->mst_primary) {
7056a2bccc3b5af Andy Shevchenko      2018-03-19  3696  		u8 buf[DP_PAYLOAD_TABLE_SIZE];
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3697  		int ret;
46466b0dac3f6be Joe Perches          2017-05-30  3698  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3699  		ret = drm_dp_dpcd_read(mgr->aux, DP_DPCD_REV, buf, DP_RECEIVER_CAP_SIZE);
46466b0dac3f6be Joe Perches          2017-05-30  3700  		seq_printf(m, "dpcd: %*ph\n", DP_RECEIVER_CAP_SIZE, buf);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3701  		ret = drm_dp_dpcd_read(mgr->aux, DP_FAUX_CAP, buf, 2);
46466b0dac3f6be Joe Perches          2017-05-30  3702  		seq_printf(m, "faux/mst: %*ph\n", 2, buf);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3703  		ret = drm_dp_dpcd_read(mgr->aux, DP_MSTM_CTRL, buf, 1);
46466b0dac3f6be Joe Perches          2017-05-30  3704  		seq_printf(m, "mst ctrl: %*ph\n", 1, buf);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3705  
44790462d041d30 Dave Airlie          2015-07-14  3706  		/* dump the standard OUI branch header */
44790462d041d30 Dave Airlie          2015-07-14  3707  		ret = drm_dp_dpcd_read(mgr->aux, DP_BRANCH_OUI, buf, DP_BRANCH_OUI_HEADER_SIZE);
46466b0dac3f6be Joe Perches          2017-05-30  3708  		seq_printf(m, "branch oui: %*phN devid: ", 3, buf);
51108f252b02d3b Jim Bride            2016-04-14  3709  		for (i = 0x3; i < 0x8 && buf[i]; i++)
44790462d041d30 Dave Airlie          2015-07-14  3710  			seq_printf(m, "%c", buf[i]);
46466b0dac3f6be Joe Perches          2017-05-30  3711  		seq_printf(m, " revision: hw: %x.%x sw: %x.%x\n",
46466b0dac3f6be Joe Perches          2017-05-30  3712  			   buf[0x9] >> 4, buf[0x9] & 0xf, buf[0xa], buf[0xb]);
46466b0dac3f6be Joe Perches          2017-05-30  3713  		if (dump_dp_payload_table(mgr, buf))
7056a2bccc3b5af Andy Shevchenko      2018-03-19  3714  			seq_printf(m, "payload table: %*ph\n", DP_PAYLOAD_TABLE_SIZE, buf);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3715  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3716  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3717  	mutex_unlock(&mgr->lock);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3718  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3719  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3720  EXPORT_SYMBOL(drm_dp_mst_dump_topology);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3721  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3722  static void drm_dp_tx_work(struct work_struct *work)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3723  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3724  	struct drm_dp_mst_topology_mgr *mgr = container_of(work, struct drm_dp_mst_topology_mgr, tx_work);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3725  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3726  	mutex_lock(&mgr->qlock);
cb021a3eb6e9870 Daniel Vetter        2016-07-15  3727  	if (!list_empty(&mgr->tx_msg_downq))
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3728  		process_single_down_tx_qlock(mgr);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3729  	mutex_unlock(&mgr->qlock);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3730  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3731  
6b8eeca65b18ae7 Dave Airlie          2015-06-15  3732  static void drm_dp_destroy_connector_work(struct work_struct *work)
6b8eeca65b18ae7 Dave Airlie          2015-06-15  3733  {
6b8eeca65b18ae7 Dave Airlie          2015-06-15  3734  	struct drm_dp_mst_topology_mgr *mgr = container_of(work, struct drm_dp_mst_topology_mgr, destroy_connector_work);
4772ff03df8094f Maarten Lankhorst    2015-08-11  3735  	struct drm_dp_mst_port *port;
df4839fdc9b3c92 Dave Airlie          2015-09-16  3736  	bool send_hotplug = false;
6b8eeca65b18ae7 Dave Airlie          2015-06-15  3737  	/*
6b8eeca65b18ae7 Dave Airlie          2015-06-15  3738  	 * Not a regular list traverse as we have to drop the destroy
6b8eeca65b18ae7 Dave Airlie          2015-06-15  3739  	 * connector lock before destroying the connector, to avoid AB->BA
6b8eeca65b18ae7 Dave Airlie          2015-06-15  3740  	 * ordering between this lock and the config mutex.
6b8eeca65b18ae7 Dave Airlie          2015-06-15  3741  	 */
6b8eeca65b18ae7 Dave Airlie          2015-06-15  3742  	for (;;) {
6b8eeca65b18ae7 Dave Airlie          2015-06-15  3743  		mutex_lock(&mgr->destroy_connector_lock);
4772ff03df8094f Maarten Lankhorst    2015-08-11  3744  		port = list_first_entry_or_null(&mgr->destroy_connector_list, struct drm_dp_mst_port, next);
4772ff03df8094f Maarten Lankhorst    2015-08-11  3745  		if (!port) {
6b8eeca65b18ae7 Dave Airlie          2015-06-15  3746  			mutex_unlock(&mgr->destroy_connector_lock);
6b8eeca65b18ae7 Dave Airlie          2015-06-15  3747  			break;
6b8eeca65b18ae7 Dave Airlie          2015-06-15  3748  		}
4772ff03df8094f Maarten Lankhorst    2015-08-11  3749  		list_del(&port->next);
6b8eeca65b18ae7 Dave Airlie          2015-06-15  3750  		mutex_unlock(&mgr->destroy_connector_lock);
6b8eeca65b18ae7 Dave Airlie          2015-06-15  3751  
91a25e463130c8e Mykola Lysenko       2016-01-27  3752  		INIT_LIST_HEAD(&port->next);
91a25e463130c8e Mykola Lysenko       2016-01-27  3753  
4772ff03df8094f Maarten Lankhorst    2015-08-11  3754  		mgr->cbs->destroy_connector(mgr, port->connector);
4772ff03df8094f Maarten Lankhorst    2015-08-11  3755  
4772ff03df8094f Maarten Lankhorst    2015-08-11  3756  		drm_dp_port_teardown_pdt(port, port->pdt);
36e3fa6a38e135e Ville Syrjälä        2016-10-26  3757  		port->pdt = DP_PEER_DEVICE_NONE;
4772ff03df8094f Maarten Lankhorst    2015-08-11  3758  
ebcc0e6b509108b Lyude Paul           2019-01-10  3759  		drm_dp_mst_put_port_malloc(port);
df4839fdc9b3c92 Dave Airlie          2015-09-16  3760  		send_hotplug = true;
6b8eeca65b18ae7 Dave Airlie          2015-06-15  3761  	}
df4839fdc9b3c92 Dave Airlie          2015-09-16  3762  	if (send_hotplug)
16bff572cc660f1 Daniel Vetter        2018-11-28  3763  		drm_kms_helper_hotplug_event(mgr->dev);
6b8eeca65b18ae7 Dave Airlie          2015-06-15  3764  }
6b8eeca65b18ae7 Dave Airlie          2015-06-15  3765  
a4370c777406c28 Ville Syrjälä        2017-07-12  3766  static struct drm_private_state *
a4370c777406c28 Ville Syrjälä        2017-07-12  3767  drm_dp_mst_duplicate_state(struct drm_private_obj *obj)
3f3353b7e1218d2 Pandiyan, Dhinakaran 2017-04-20  3768  {
eceae147246749c Lyude Paul           2019-01-10  3769  	struct drm_dp_mst_topology_state *state, *old_state =
eceae147246749c Lyude Paul           2019-01-10  3770  		to_dp_mst_topology_state(obj->state);
eceae147246749c Lyude Paul           2019-01-10  3771  	struct drm_dp_vcpi_allocation *pos, *vcpi;
3f3353b7e1218d2 Pandiyan, Dhinakaran 2017-04-20  3772  
eceae147246749c Lyude Paul           2019-01-10  3773  	state = kmemdup(old_state, sizeof(*state), GFP_KERNEL);
a4370c777406c28 Ville Syrjälä        2017-07-12  3774  	if (!state)
3f3353b7e1218d2 Pandiyan, Dhinakaran 2017-04-20  3775  		return NULL;
3f3353b7e1218d2 Pandiyan, Dhinakaran 2017-04-20  3776  
a4370c777406c28 Ville Syrjälä        2017-07-12  3777  	__drm_atomic_helper_private_obj_duplicate_state(obj, &state->base);
3f3353b7e1218d2 Pandiyan, Dhinakaran 2017-04-20  3778  
eceae147246749c Lyude Paul           2019-01-10  3779  	INIT_LIST_HEAD(&state->vcpis);
eceae147246749c Lyude Paul           2019-01-10  3780  
eceae147246749c Lyude Paul           2019-01-10  3781  	list_for_each_entry(pos, &old_state->vcpis, next) {
eceae147246749c Lyude Paul           2019-01-10  3782  		/* Prune leftover freed VCPI allocations */
eceae147246749c Lyude Paul           2019-01-10  3783  		if (!pos->vcpi)
eceae147246749c Lyude Paul           2019-01-10  3784  			continue;
eceae147246749c Lyude Paul           2019-01-10  3785  
eceae147246749c Lyude Paul           2019-01-10  3786  		vcpi = kmemdup(pos, sizeof(*vcpi), GFP_KERNEL);
eceae147246749c Lyude Paul           2019-01-10  3787  		if (!vcpi)
eceae147246749c Lyude Paul           2019-01-10  3788  			goto fail;
eceae147246749c Lyude Paul           2019-01-10  3789  
eceae147246749c Lyude Paul           2019-01-10  3790  		drm_dp_mst_get_port_malloc(vcpi->port);
eceae147246749c Lyude Paul           2019-01-10  3791  		list_add(&vcpi->next, &state->vcpis);
eceae147246749c Lyude Paul           2019-01-10  3792  	}
eceae147246749c Lyude Paul           2019-01-10  3793  
a4370c777406c28 Ville Syrjälä        2017-07-12  3794  	return &state->base;
eceae147246749c Lyude Paul           2019-01-10  3795  
eceae147246749c Lyude Paul           2019-01-10  3796  fail:
eceae147246749c Lyude Paul           2019-01-10  3797  	list_for_each_entry_safe(pos, vcpi, &state->vcpis, next) {
eceae147246749c Lyude Paul           2019-01-10  3798  		drm_dp_mst_put_port_malloc(pos->port);
eceae147246749c Lyude Paul           2019-01-10  3799  		kfree(pos);
eceae147246749c Lyude Paul           2019-01-10  3800  	}
eceae147246749c Lyude Paul           2019-01-10  3801  	kfree(state);
eceae147246749c Lyude Paul           2019-01-10  3802  
eceae147246749c Lyude Paul           2019-01-10  3803  	return NULL;
3f3353b7e1218d2 Pandiyan, Dhinakaran 2017-04-20  3804  }
3f3353b7e1218d2 Pandiyan, Dhinakaran 2017-04-20  3805  
a4370c777406c28 Ville Syrjälä        2017-07-12  3806  static void drm_dp_mst_destroy_state(struct drm_private_obj *obj,
a4370c777406c28 Ville Syrjälä        2017-07-12  3807  				     struct drm_private_state *state)
3f3353b7e1218d2 Pandiyan, Dhinakaran 2017-04-20  3808  {
a4370c777406c28 Ville Syrjälä        2017-07-12  3809  	struct drm_dp_mst_topology_state *mst_state =
a4370c777406c28 Ville Syrjälä        2017-07-12  3810  		to_dp_mst_topology_state(state);
eceae147246749c Lyude Paul           2019-01-10  3811  	struct drm_dp_vcpi_allocation *pos, *tmp;
eceae147246749c Lyude Paul           2019-01-10  3812  
eceae147246749c Lyude Paul           2019-01-10  3813  	list_for_each_entry_safe(pos, tmp, &mst_state->vcpis, next) {
eceae147246749c Lyude Paul           2019-01-10  3814  		/* We only keep references to ports with non-zero VCPIs */
eceae147246749c Lyude Paul           2019-01-10  3815  		if (pos->vcpi)
eceae147246749c Lyude Paul           2019-01-10  3816  			drm_dp_mst_put_port_malloc(pos->port);
eceae147246749c Lyude Paul           2019-01-10  3817  		kfree(pos);
eceae147246749c Lyude Paul           2019-01-10  3818  	}
a4370c777406c28 Ville Syrjälä        2017-07-12  3819  
a4370c777406c28 Ville Syrjälä        2017-07-12  3820  	kfree(mst_state);
3f3353b7e1218d2 Pandiyan, Dhinakaran 2017-04-20  3821  }
3f3353b7e1218d2 Pandiyan, Dhinakaran 2017-04-20  3822  
eceae147246749c Lyude Paul           2019-01-10  3823  static inline int
eceae147246749c Lyude Paul           2019-01-10  3824  drm_dp_mst_atomic_check_topology_state(struct drm_dp_mst_topology_mgr *mgr,
eceae147246749c Lyude Paul           2019-01-10  3825  				       struct drm_dp_mst_topology_state *mst_state)
eceae147246749c Lyude Paul           2019-01-10  3826  {
eceae147246749c Lyude Paul           2019-01-10  3827  	struct drm_dp_vcpi_allocation *vcpi;
5e187a01426d220 Lyude Paul           2019-01-10  3828  	int avail_slots = 63, payload_count = 0;
eceae147246749c Lyude Paul           2019-01-10  3829  
eceae147246749c Lyude Paul           2019-01-10  3830  	list_for_each_entry(vcpi, &mst_state->vcpis, next) {
eceae147246749c Lyude Paul           2019-01-10  3831  		/* Releasing VCPI is always OK-even if the port is gone */
eceae147246749c Lyude Paul           2019-01-10  3832  		if (!vcpi->vcpi) {
eceae147246749c Lyude Paul           2019-01-10  3833  			DRM_DEBUG_ATOMIC("[MST PORT:%p] releases all VCPI slots\n",
eceae147246749c Lyude Paul           2019-01-10  3834  					 vcpi->port);
eceae147246749c Lyude Paul           2019-01-10  3835  			continue;
eceae147246749c Lyude Paul           2019-01-10  3836  		}
eceae147246749c Lyude Paul           2019-01-10  3837  
eceae147246749c Lyude Paul           2019-01-10  3838  		DRM_DEBUG_ATOMIC("[MST PORT:%p] requires %d vcpi slots\n",
eceae147246749c Lyude Paul           2019-01-10  3839  				 vcpi->port, vcpi->vcpi);
eceae147246749c Lyude Paul           2019-01-10  3840  
eceae147246749c Lyude Paul           2019-01-10  3841  		avail_slots -= vcpi->vcpi;
eceae147246749c Lyude Paul           2019-01-10  3842  		if (avail_slots < 0) {
eceae147246749c Lyude Paul           2019-01-10  3843  			DRM_DEBUG_ATOMIC("[MST PORT:%p] not enough VCPI slots in mst state %p (avail=%d)\n",
eceae147246749c Lyude Paul           2019-01-10  3844  					 vcpi->port, mst_state,
eceae147246749c Lyude Paul           2019-01-10  3845  					 avail_slots + vcpi->vcpi);
eceae147246749c Lyude Paul           2019-01-10  3846  			return -ENOSPC;
eceae147246749c Lyude Paul           2019-01-10  3847  		}
5e187a01426d220 Lyude Paul           2019-01-10  3848  
5e187a01426d220 Lyude Paul           2019-01-10  3849  		if (++payload_count > mgr->max_payloads) {
5e187a01426d220 Lyude Paul           2019-01-10  3850  			DRM_DEBUG_ATOMIC("[MST MGR:%p] state %p has too many payloads (max=%d)\n",
5e187a01426d220 Lyude Paul           2019-01-10  3851  					 mgr, mst_state, mgr->max_payloads);
5e187a01426d220 Lyude Paul           2019-01-10  3852  			return -EINVAL;
5e187a01426d220 Lyude Paul           2019-01-10  3853  		}
eceae147246749c Lyude Paul           2019-01-10  3854  	}
eceae147246749c Lyude Paul           2019-01-10  3855  	DRM_DEBUG_ATOMIC("[MST MGR:%p] mst state %p VCPI avail=%d used=%d\n",
eceae147246749c Lyude Paul           2019-01-10  3856  			 mgr, mst_state, avail_slots,
eceae147246749c Lyude Paul           2019-01-10  3857  			 63 - avail_slots);
eceae147246749c Lyude Paul           2019-01-10  3858  
eceae147246749c Lyude Paul           2019-01-10  3859  	return 0;
eceae147246749c Lyude Paul           2019-01-10  3860  }
eceae147246749c Lyude Paul           2019-01-10  3861  
eceae147246749c Lyude Paul           2019-01-10  3862  /**
eceae147246749c Lyude Paul           2019-01-10  3863   * drm_dp_mst_atomic_check - Check that the new state of an MST topology in an
eceae147246749c Lyude Paul           2019-01-10  3864   * atomic update is valid
eceae147246749c Lyude Paul           2019-01-10  3865   * @state: Pointer to the new &struct drm_dp_mst_topology_state
eceae147246749c Lyude Paul           2019-01-10  3866   *
eceae147246749c Lyude Paul           2019-01-10  3867   * Checks the given topology state for an atomic update to ensure that it's
eceae147246749c Lyude Paul           2019-01-10  3868   * valid. This includes checking whether there's enough bandwidth to support
eceae147246749c Lyude Paul           2019-01-10  3869   * the new VCPI allocations in the atomic update.
eceae147246749c Lyude Paul           2019-01-10  3870   *
eceae147246749c Lyude Paul           2019-01-10  3871   * Any atomic drivers supporting DP MST must make sure to call this after
eceae147246749c Lyude Paul           2019-01-10  3872   * checking the rest of their state in their
eceae147246749c Lyude Paul           2019-01-10  3873   * &drm_mode_config_funcs.atomic_check() callback.
eceae147246749c Lyude Paul           2019-01-10  3874   *
eceae147246749c Lyude Paul           2019-01-10  3875   * See also:
eceae147246749c Lyude Paul           2019-01-10  3876   * drm_dp_atomic_find_vcpi_slots()
eceae147246749c Lyude Paul           2019-01-10  3877   * drm_dp_atomic_release_vcpi_slots()
eceae147246749c Lyude Paul           2019-01-10  3878   *
eceae147246749c Lyude Paul           2019-01-10  3879   * Returns:
eceae147246749c Lyude Paul           2019-01-10  3880   *
eceae147246749c Lyude Paul           2019-01-10  3881   * 0 if the new state is valid, negative error code otherwise.
eceae147246749c Lyude Paul           2019-01-10  3882   */
eceae147246749c Lyude Paul           2019-01-10  3883  int drm_dp_mst_atomic_check(struct drm_atomic_state *state)
eceae147246749c Lyude Paul           2019-01-10  3884  {
eceae147246749c Lyude Paul           2019-01-10  3885  	struct drm_dp_mst_topology_mgr *mgr;
eceae147246749c Lyude Paul           2019-01-10  3886  	struct drm_dp_mst_topology_state *mst_state;
eceae147246749c Lyude Paul           2019-01-10  3887  	int i, ret = 0;
eceae147246749c Lyude Paul           2019-01-10  3888  
eceae147246749c Lyude Paul           2019-01-10  3889  	for_each_new_mst_mgr_in_state(state, mgr, mst_state, i) {
eceae147246749c Lyude Paul           2019-01-10  3890  		ret = drm_dp_mst_atomic_check_topology_state(mgr, mst_state);
eceae147246749c Lyude Paul           2019-01-10  3891  		if (ret)
eceae147246749c Lyude Paul           2019-01-10  3892  			break;
eceae147246749c Lyude Paul           2019-01-10  3893  	}
eceae147246749c Lyude Paul           2019-01-10  3894  
eceae147246749c Lyude Paul           2019-01-10  3895  	return ret;
eceae147246749c Lyude Paul           2019-01-10  3896  }
eceae147246749c Lyude Paul           2019-01-10  3897  EXPORT_SYMBOL(drm_dp_mst_atomic_check);
eceae147246749c Lyude Paul           2019-01-10  3898  
bea5c38f1eb6698 Lyude Paul           2019-01-10  3899  const struct drm_private_state_funcs drm_dp_mst_topology_state_funcs = {
a4370c777406c28 Ville Syrjälä        2017-07-12  3900  	.atomic_duplicate_state = drm_dp_mst_duplicate_state,
a4370c777406c28 Ville Syrjälä        2017-07-12  3901  	.atomic_destroy_state = drm_dp_mst_destroy_state,
3f3353b7e1218d2 Pandiyan, Dhinakaran 2017-04-20  3902  };
bea5c38f1eb6698 Lyude Paul           2019-01-10  3903  EXPORT_SYMBOL(drm_dp_mst_topology_state_funcs);
3f3353b7e1218d2 Pandiyan, Dhinakaran 2017-04-20  3904  
3f3353b7e1218d2 Pandiyan, Dhinakaran 2017-04-20  3905  /**
3f3353b7e1218d2 Pandiyan, Dhinakaran 2017-04-20  3906   * drm_atomic_get_mst_topology_state: get MST topology state
3f3353b7e1218d2 Pandiyan, Dhinakaran 2017-04-20  3907   *
3f3353b7e1218d2 Pandiyan, Dhinakaran 2017-04-20  3908   * @state: global atomic state
3f3353b7e1218d2 Pandiyan, Dhinakaran 2017-04-20  3909   * @mgr: MST topology manager, also the private object in this case
3f3353b7e1218d2 Pandiyan, Dhinakaran 2017-04-20  3910   *
3f3353b7e1218d2 Pandiyan, Dhinakaran 2017-04-20  3911   * This function wraps drm_atomic_get_priv_obj_state() passing in the MST atomic
3f3353b7e1218d2 Pandiyan, Dhinakaran 2017-04-20  3912   * state vtable so that the private object state returned is that of a MST
3f3353b7e1218d2 Pandiyan, Dhinakaran 2017-04-20  3913   * topology object. Also, drm_atomic_get_private_obj_state() expects the caller
3f3353b7e1218d2 Pandiyan, Dhinakaran 2017-04-20  3914   * to care of the locking, so warn if don't hold the connection_mutex.
3f3353b7e1218d2 Pandiyan, Dhinakaran 2017-04-20  3915   *
3f3353b7e1218d2 Pandiyan, Dhinakaran 2017-04-20  3916   * RETURNS:
3f3353b7e1218d2 Pandiyan, Dhinakaran 2017-04-20  3917   *
3f3353b7e1218d2 Pandiyan, Dhinakaran 2017-04-20  3918   * The MST topology state or error pointer.
3f3353b7e1218d2 Pandiyan, Dhinakaran 2017-04-20  3919   */
3f3353b7e1218d2 Pandiyan, Dhinakaran 2017-04-20  3920  struct drm_dp_mst_topology_state *drm_atomic_get_mst_topology_state(struct drm_atomic_state *state,
3f3353b7e1218d2 Pandiyan, Dhinakaran 2017-04-20  3921  								    struct drm_dp_mst_topology_mgr *mgr)
3f3353b7e1218d2 Pandiyan, Dhinakaran 2017-04-20  3922  {
3f3353b7e1218d2 Pandiyan, Dhinakaran 2017-04-20  3923  	struct drm_device *dev = mgr->dev;
3f3353b7e1218d2 Pandiyan, Dhinakaran 2017-04-20  3924  
3f3353b7e1218d2 Pandiyan, Dhinakaran 2017-04-20  3925  	WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
a4370c777406c28 Ville Syrjälä        2017-07-12  3926  	return to_dp_mst_topology_state(drm_atomic_get_private_obj_state(state, &mgr->base));
3f3353b7e1218d2 Pandiyan, Dhinakaran 2017-04-20  3927  }
3f3353b7e1218d2 Pandiyan, Dhinakaran 2017-04-20  3928  EXPORT_SYMBOL(drm_atomic_get_mst_topology_state);
3f3353b7e1218d2 Pandiyan, Dhinakaran 2017-04-20  3929  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3930  /**
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3931   * drm_dp_mst_topology_mgr_init - initialise a topology manager
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3932   * @mgr: manager struct to initialise
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3933   * @dev: device providing this structure - for i2c addition.
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3934   * @aux: DP helper aux channel to talk to this device
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3935   * @max_dpcd_transaction_bytes: hw specific DPCD transaction limit
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3936   * @max_payloads: maximum number of payloads this GPU can source
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3937   * @conn_base_id: the connector object ID the MST device is connected to.
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3938   *
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3939   * Return 0 for success, or negative error code on failure
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3940   */
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3941  int drm_dp_mst_topology_mgr_init(struct drm_dp_mst_topology_mgr *mgr,
7b0a89a6db9a591 Dhinakaran Pandiyan  2017-01-24  3942  				 struct drm_device *dev, struct drm_dp_aux *aux,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3943  				 int max_dpcd_transaction_bytes,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3944  				 int max_payloads, int conn_base_id)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3945  {
a4370c777406c28 Ville Syrjälä        2017-07-12  3946  	struct drm_dp_mst_topology_state *mst_state;
a4370c777406c28 Ville Syrjälä        2017-07-12  3947  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3948  	mutex_init(&mgr->lock);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3949  	mutex_init(&mgr->qlock);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3950  	mutex_init(&mgr->payload_lock);
6b8eeca65b18ae7 Dave Airlie          2015-06-15  3951  	mutex_init(&mgr->destroy_connector_lock);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3952  	INIT_LIST_HEAD(&mgr->tx_msg_downq);
6b8eeca65b18ae7 Dave Airlie          2015-06-15  3953  	INIT_LIST_HEAD(&mgr->destroy_connector_list);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3954  	INIT_WORK(&mgr->work, drm_dp_mst_link_probe_work);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3955  	INIT_WORK(&mgr->tx_work, drm_dp_tx_work);
6b8eeca65b18ae7 Dave Airlie          2015-06-15  3956  	INIT_WORK(&mgr->destroy_connector_work, drm_dp_destroy_connector_work);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3957  	init_waitqueue_head(&mgr->tx_waitq);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3958  	mgr->dev = dev;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3959  	mgr->aux = aux;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3960  	mgr->max_dpcd_transaction_bytes = max_dpcd_transaction_bytes;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3961  	mgr->max_payloads = max_payloads;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3962  	mgr->conn_base_id = conn_base_id;
4d6a10da79fddcf Imre Deak            2016-01-29  3963  	if (max_payloads + 1 > sizeof(mgr->payload_mask) * 8 ||
4d6a10da79fddcf Imre Deak            2016-01-29  3964  	    max_payloads + 1 > sizeof(mgr->vcpi_mask) * 8)
4d6a10da79fddcf Imre Deak            2016-01-29  3965  		return -EINVAL;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3966  	mgr->payloads = kcalloc(max_payloads, sizeof(struct drm_dp_payload), GFP_KERNEL);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3967  	if (!mgr->payloads)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3968  		return -ENOMEM;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3969  	mgr->proposed_vcpis = kcalloc(max_payloads, sizeof(struct drm_dp_vcpi *), GFP_KERNEL);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3970  	if (!mgr->proposed_vcpis)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3971  		return -ENOMEM;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3972  	set_bit(0, &mgr->payload_mask);
441388a8a73f905 Imre Deak            2016-01-29  3973  	if (test_calc_pbn_mode() < 0)
441388a8a73f905 Imre Deak            2016-01-29  3974  		DRM_ERROR("MST PBN self-test failed\n");
441388a8a73f905 Imre Deak            2016-01-29  3975  
a4370c777406c28 Ville Syrjälä        2017-07-12  3976  	mst_state = kzalloc(sizeof(*mst_state), GFP_KERNEL);
a4370c777406c28 Ville Syrjälä        2017-07-12  3977  	if (mst_state == NULL)
3f3353b7e1218d2 Pandiyan, Dhinakaran 2017-04-20  3978  		return -ENOMEM;
a4370c777406c28 Ville Syrjälä        2017-07-12  3979  
a4370c777406c28 Ville Syrjälä        2017-07-12  3980  	mst_state->mgr = mgr;
eceae147246749c Lyude Paul           2019-01-10  3981  	INIT_LIST_HEAD(&mst_state->vcpis);
a4370c777406c28 Ville Syrjälä        2017-07-12  3982  
b962a12050a387e Rob Clark            2018-10-22  3983  	drm_atomic_private_obj_init(dev, &mgr->base,
a4370c777406c28 Ville Syrjälä        2017-07-12  3984  				    &mst_state->base,
bea5c38f1eb6698 Lyude Paul           2019-01-10  3985  				    &drm_dp_mst_topology_state_funcs);
3f3353b7e1218d2 Pandiyan, Dhinakaran 2017-04-20  3986  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3987  	return 0;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3988  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3989  EXPORT_SYMBOL(drm_dp_mst_topology_mgr_init);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3990  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3991  /**
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3992   * drm_dp_mst_topology_mgr_destroy() - destroy topology manager.
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3993   * @mgr: manager to destroy
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3994   */
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3995  void drm_dp_mst_topology_mgr_destroy(struct drm_dp_mst_topology_mgr *mgr)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  3996  {
f536e00c46d22cc Lyude Paul           2018-12-11  3997  	drm_dp_mst_topology_mgr_set_mst(mgr, false);
274d83524895fe4 Dave Airlie          2015-09-30  3998  	flush_work(&mgr->work);
6b8eeca65b18ae7 Dave Airlie          2015-06-15  3999  	flush_work(&mgr->destroy_connector_work);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4000  	mutex_lock(&mgr->payload_lock);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4001  	kfree(mgr->payloads);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4002  	mgr->payloads = NULL;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4003  	kfree(mgr->proposed_vcpis);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4004  	mgr->proposed_vcpis = NULL;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4005  	mutex_unlock(&mgr->payload_lock);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4006  	mgr->dev = NULL;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4007  	mgr->aux = NULL;
a4370c777406c28 Ville Syrjälä        2017-07-12  4008  	drm_atomic_private_obj_fini(&mgr->base);
3f3353b7e1218d2 Pandiyan, Dhinakaran 2017-04-20  4009  	mgr->funcs = NULL;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4010  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4011  EXPORT_SYMBOL(drm_dp_mst_topology_mgr_destroy);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4012  
cb8ce7111117e16 Ville Syrjälä        2018-09-28  4013  static bool remote_i2c_read_ok(const struct i2c_msg msgs[], int num)
cb8ce7111117e16 Ville Syrjälä        2018-09-28  4014  {
cb8ce7111117e16 Ville Syrjälä        2018-09-28  4015  	int i;
cb8ce7111117e16 Ville Syrjälä        2018-09-28  4016  
cb8ce7111117e16 Ville Syrjälä        2018-09-28  4017  	if (num - 1 > DP_REMOTE_I2C_READ_MAX_TRANSACTIONS)
cb8ce7111117e16 Ville Syrjälä        2018-09-28  4018  		return false;
cb8ce7111117e16 Ville Syrjälä        2018-09-28  4019  
cb8ce7111117e16 Ville Syrjälä        2018-09-28  4020  	for (i = 0; i < num - 1; i++) {
cb8ce7111117e16 Ville Syrjälä        2018-09-28  4021  		if (msgs[i].flags & I2C_M_RD ||
cb8ce7111117e16 Ville Syrjälä        2018-09-28  4022  		    msgs[i].len > 0xff)
cb8ce7111117e16 Ville Syrjälä        2018-09-28  4023  			return false;
cb8ce7111117e16 Ville Syrjälä        2018-09-28  4024  	}
cb8ce7111117e16 Ville Syrjälä        2018-09-28  4025  
cb8ce7111117e16 Ville Syrjälä        2018-09-28  4026  	return msgs[num - 1].flags & I2C_M_RD &&
cb8ce7111117e16 Ville Syrjälä        2018-09-28  4027  		msgs[num - 1].len <= 0xff;
cb8ce7111117e16 Ville Syrjälä        2018-09-28  4028  }
cb8ce7111117e16 Ville Syrjälä        2018-09-28  4029  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4030  /* I2C device */
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4031  static int drm_dp_mst_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4032  			       int num)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4033  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4034  	struct drm_dp_aux *aux = adapter->algo_data;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4035  	struct drm_dp_mst_port *port = container_of(aux, struct drm_dp_mst_port, aux);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4036  	struct drm_dp_mst_branch *mstb;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4037  	struct drm_dp_mst_topology_mgr *mgr = port->mgr;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4038  	unsigned int i;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4039  	struct drm_dp_sideband_msg_req_body msg;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4040  	struct drm_dp_sideband_msg_tx *txmsg = NULL;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4041  	int ret;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4042  
d0757afd00d71dc Lyude Paul           2019-01-10  4043  	mstb = drm_dp_mst_topology_get_mstb_validated(mgr, port->parent);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4044  	if (!mstb)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4045  		return -EREMOTEIO;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4046  
cb8ce7111117e16 Ville Syrjälä        2018-09-28  4047  	if (!remote_i2c_read_ok(msgs, num)) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4048  		DRM_DEBUG_KMS("Unsupported I2C transaction for MST device\n");
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4049  		ret = -EIO;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4050  		goto out;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4051  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4052  
ae491542cbbbcca Dave Airlie          2015-10-14  4053  	memset(&msg, 0, sizeof(msg));
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4054  	msg.req_type = DP_REMOTE_I2C_READ;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4055  	msg.u.i2c_read.num_transactions = num - 1;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4056  	msg.u.i2c_read.port_number = port->port_num;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4057  	for (i = 0; i < num - 1; i++) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4058  		msg.u.i2c_read.transactions[i].i2c_dev_id = msgs[i].addr;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4059  		msg.u.i2c_read.transactions[i].num_bytes = msgs[i].len;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4060  		msg.u.i2c_read.transactions[i].bytes = msgs[i].buf;
c978ae9bde582e8 Ville Syrjälä        2018-09-28  4061  		msg.u.i2c_read.transactions[i].no_stop_bit = !(msgs[i].flags & I2C_M_STOP);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4062  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4063  	msg.u.i2c_read.read_i2c_device_id = msgs[num - 1].addr;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4064  	msg.u.i2c_read.num_bytes_read = msgs[num - 1].len;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4065  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4066  	txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4067  	if (!txmsg) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4068  		ret = -ENOMEM;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4069  		goto out;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4070  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4071  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4072  	txmsg->dst = mstb;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4073  	drm_dp_encode_sideband_req(&msg, txmsg);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4074  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4075  	drm_dp_queue_down_tx(mgr, txmsg);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4076  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4077  	ret = drm_dp_mst_wait_tx_reply(mstb, txmsg);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4078  	if (ret > 0) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4079  
45bbda1e35f4943 Ville Syrjälä        2019-01-22  4080  		if (txmsg->reply.reply_type == DP_SIDEBAND_REPLY_NAK) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4081  			ret = -EREMOTEIO;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4082  			goto out;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4083  		}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4084  		if (txmsg->reply.u.remote_i2c_read_ack.num_bytes != msgs[num - 1].len) {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4085  			ret = -EIO;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4086  			goto out;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4087  		}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4088  		memcpy(msgs[num - 1].buf, txmsg->reply.u.remote_i2c_read_ack.bytes, msgs[num - 1].len);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4089  		ret = num;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4090  	}
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4091  out:
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4092  	kfree(txmsg);
d0757afd00d71dc Lyude Paul           2019-01-10  4093  	drm_dp_mst_topology_put_mstb(mstb);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4094  	return ret;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4095  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4096  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4097  static u32 drm_dp_mst_i2c_functionality(struct i2c_adapter *adapter)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4098  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4099  	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4100  	       I2C_FUNC_SMBUS_READ_BLOCK_DATA |
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4101  	       I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4102  	       I2C_FUNC_10BIT_ADDR;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4103  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4104  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4105  static const struct i2c_algorithm drm_dp_mst_i2c_algo = {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4106  	.functionality = drm_dp_mst_i2c_functionality,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4107  	.master_xfer = drm_dp_mst_i2c_xfer,
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4108  };
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4109  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4110  /**
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4111   * drm_dp_mst_register_i2c_bus() - register an I2C adapter for I2C-over-AUX
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4112   * @aux: DisplayPort AUX channel
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4113   *
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4114   * Returns 0 on success or a negative error code on failure.
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4115   */
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4116  static int drm_dp_mst_register_i2c_bus(struct drm_dp_aux *aux)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4117  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4118  	aux->ddc.algo = &drm_dp_mst_i2c_algo;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4119  	aux->ddc.algo_data = aux;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4120  	aux->ddc.retries = 3;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4121  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4122  	aux->ddc.class = I2C_CLASS_DDC;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4123  	aux->ddc.owner = THIS_MODULE;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4124  	aux->ddc.dev.parent = aux->dev;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4125  	aux->ddc.dev.of_node = aux->dev->of_node;
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4126  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4127  	strlcpy(aux->ddc.name, aux->name ? aux->name : dev_name(aux->dev),
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4128  		sizeof(aux->ddc.name));
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4129  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4130  	return i2c_add_adapter(&aux->ddc);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4131  }
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4132  
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4133  /**
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4134   * drm_dp_mst_unregister_i2c_bus() - unregister an I2C-over-AUX adapter
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4135   * @aux: DisplayPort AUX channel
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4136   */
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4137  static void drm_dp_mst_unregister_i2c_bus(struct drm_dp_aux *aux)
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4138  {
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4139  	i2c_del_adapter(&aux->ddc);
ad7f8a1f9ced7f0 Dave Airlie          2014-06-05  4140  }

:::::: The code at line 1594 was first introduced by commit
:::::: 3dfd9a885fbb869e90f34346b9e2c23f07596d8d linux-next

:::::: TO: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx>
:::::: CC: Johannes Weiner <hannes@xxxxxxxxxxx>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

Attachment: .config.gz
Description: application/gzip


[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux