* [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'
@ 2019-08-07 22:33 kbuild test robot
0 siblings, 0 replies; 2+ messages in thread
From: kbuild test robot @ 2019-08-07 22:33 UTC (permalink / raw)
To: Andrew Morton
Cc: kbuild-all, Roman Gushchin, Linux Memory Management List,
Lu Shuaibing, Johannes Weiner
[-- Attachment #1: Type: text/plain, Size: 18820 bytes --]
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@intel.com>
All warnings (new ones prefixed by >>):
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: 'register_hpd_handlers' not found
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
include/linux/spi/spi.h:190: warning: Function parameter or member 'driver_override' not described in 'spi_device'
drivers/usb/typec/bus.c:1: warning: 'typec_altmode_register_driver' not found
drivers/usb/typec/bus.c:1: warning: 'typec_altmode_unregister_driver' not found
drivers/usb/typec/class.c:1: warning: 'typec_altmode_register_notifier' not found
drivers/usb/typec/class.c:1: warning: 'typec_altmode_unregister_notifier' not found
include/linux/w1.h:272: warning: Function parameter or member 'of_match_table' not described in 'w1_family'
include/linux/i2c.h:337: warning: Function parameter or member 'init_irq' not described in 'i2c_client'
fs/super.c:1269: warning: Excess function parameter 'keying' description in 'vfs_get_block_super'
fs/direct-io.c:258: warning: Excess function parameter 'offset' description in 'dio_complete'
fs/libfs.c:496: warning: Excess function parameter 'available' description in 'simple_write_end'
fs/posix_acl.c:647: warning: Function parameter or member 'inode' not described in 'posix_acl_update_mode'
fs/posix_acl.c:647: warning: Function parameter or member 'mode_p' not described in 'posix_acl_update_mode'
fs/posix_acl.c:647: warning: Function parameter or member 'acl' not described in 'posix_acl_update_mode'
include/linux/input/sparse-keymap.h:43: warning: Function parameter or member 'sw' not described in 'key_entry'
include/linux/regulator/machine.h:196: warning: Function parameter or member 'max_uV_step' not described in 'regulation_constraints'
include/linux/regulator/driver.h:223: warning: Function parameter or member 'resume' not described in 'regulator_ops'
include/linux/skbuff.h:881: warning: Function parameter or member 'dev_scratch' not described in 'sk_buff'
include/linux/skbuff.h:881: warning: Function parameter or member 'list' not described in 'sk_buff'
include/linux/skbuff.h:881: warning: Function parameter or member 'ip_defrag_offset' not described in 'sk_buff'
include/linux/skbuff.h:881: warning: Function parameter or member 'skb_mstamp_ns' not described in 'sk_buff'
include/linux/skbuff.h:881: warning: Function parameter or member '__cloned_offset' not described in 'sk_buff'
include/linux/skbuff.h:881: warning: Function parameter or member 'head_frag' not described in 'sk_buff'
include/linux/skbuff.h:881: warning: Function parameter or member '__pkt_type_offset' not described in 'sk_buff'
include/linux/skbuff.h:881: warning: Function parameter or member 'encapsulation' not described in 'sk_buff'
include/linux/skbuff.h:881: warning: Function parameter or member 'encap_hdr_csum' not described in 'sk_buff'
include/linux/skbuff.h:881: warning: Function parameter or member 'csum_valid' not described in 'sk_buff'
include/linux/skbuff.h:881: warning: Function parameter or member '__pkt_vlan_present_offset' not described in 'sk_buff'
include/linux/skbuff.h:881: warning: Function parameter or member 'vlan_present' not described in 'sk_buff'
include/linux/skbuff.h:881: warning: Function parameter or member 'csum_complete_sw' not described in 'sk_buff'
include/linux/skbuff.h:881: warning: Function parameter or member 'csum_level' not described in 'sk_buff'
include/linux/skbuff.h:881: warning: Function parameter or member 'inner_protocol_type' not described in 'sk_buff'
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'
lib/genalloc.c:1: warning: 'gen_pool_add_virt' not found
lib/genalloc.c:1: warning: 'gen_pool_alloc' not found
lib/genalloc.c:1: warning: 'gen_pool_free' not found
lib/genalloc.c:1: warning: 'gen_pool_alloc_algo' not found
include/linux/bitmap.h:341: warning: Function parameter or member 'nbits' not described in 'bitmap_or_equal'
mm/util.c:1: warning: 'get_user_pages_fast' not found
mm/slab.c:4215: warning: Function parameter or member 'objp' not described in '__ksize'
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'
drivers/gpu/drm/mcde/mcde_drv.c:1: warning: 'ST-Ericsson MCDE DRM Driver' not found
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/trace/kprobetrace.rst:99: WARNING: Explicit markup ends without a blank line; unexpected unindent.
Documentation/security/keys/core.rst:1181: WARNING: Inline emphasis start-string without end-string.
Documentation/security/keys/core.rst:1181: WARNING: Inline emphasis start-string without end-string.
Documentation/security/keys/core.rst:1178: WARNING: Inline emphasis start-string without end-string.
Documentation/security/keys/core.rst:1178: WARNING: Inline emphasis start-string without end-string.
Documentation/security/keys/core.rst:1178: WARNING: Inline emphasis start-string without end-string.
Documentation/security/keys/core.rst:1178: WARNING: Inline emphasis start-string without end-string.
Documentation/translations/it_IT/process/maintainer-pgp-guide.rst:458: WARNING: Unknown target name: "nitrokey pro".
Documentation/admin-guide/sysctl/kernel.rst:397: WARNING: Title underline too short.
vim +1594 drivers/gpu/drm/drm_dp_mst_topology.c
ad7f8a1f9ced7f Dave Airlie 2014-06-05 1579
3dfd9a885fbb86 Andrew Morton 2019-07-27 1580 /**
3dfd9a885fbb86 Andrew Morton 2019-07-27 1581 * drm_dp_mst_connector_late_register() - Late MST connector registration
3dfd9a885fbb86 Andrew Morton 2019-07-27 1582 * @drm_connector: The MST connector
3dfd9a885fbb86 Andrew Morton 2019-07-27 1583 * @port: The MST port for this connector
3dfd9a885fbb86 Andrew Morton 2019-07-27 1584 *
3dfd9a885fbb86 Andrew Morton 2019-07-27 1585 * Helper to register the remote aux device for this MST port. Drivers should
3dfd9a885fbb86 Andrew Morton 2019-07-27 1586 * call this from their mst connector's late_register hook to enable MST aux
3dfd9a885fbb86 Andrew Morton 2019-07-27 1587 * devices.
3dfd9a885fbb86 Andrew Morton 2019-07-27 1588 *
3dfd9a885fbb86 Andrew Morton 2019-07-27 1589 * Return: 0 on success, negative error code on failure.
3dfd9a885fbb86 Andrew Morton 2019-07-27 1590 */
3dfd9a885fbb86 Andrew Morton 2019-07-27 1591 int drm_dp_mst_connector_late_register(struct drm_connector *connector,
3dfd9a885fbb86 Andrew Morton 2019-07-27 1592 struct drm_dp_mst_port *port)
3dfd9a885fbb86 Andrew Morton 2019-07-27 @1593 {
3dfd9a885fbb86 Andrew Morton 2019-07-27 @1594 DRM_DEBUG_KMS("registering %s remote bus for %s\n",
3dfd9a885fbb86 Andrew Morton 2019-07-27 1595 port->aux.name, connector->kdev->kobj.name);
3dfd9a885fbb86 Andrew Morton 2019-07-27 1596
3dfd9a885fbb86 Andrew Morton 2019-07-27 1597 port->aux.dev = connector->kdev;
3dfd9a885fbb86 Andrew Morton 2019-07-27 1598 return drm_dp_aux_register_devnode(&port->aux);
3dfd9a885fbb86 Andrew Morton 2019-07-27 1599 }
3dfd9a885fbb86 Andrew Morton 2019-07-27 1600 EXPORT_SYMBOL(drm_dp_mst_connector_late_register);
3dfd9a885fbb86 Andrew Morton 2019-07-27 1601
3dfd9a885fbb86 Andrew Morton 2019-07-27 1602 /**
3dfd9a885fbb86 Andrew Morton 2019-07-27 1603 * drm_dp_mst_connector_early_unregister() - Early MST connector unregistration
3dfd9a885fbb86 Andrew Morton 2019-07-27 1604 * @drm_connector: The MST connector
3dfd9a885fbb86 Andrew Morton 2019-07-27 1605 * @port: The MST port for this connector
3dfd9a885fbb86 Andrew Morton 2019-07-27 1606 *
3dfd9a885fbb86 Andrew Morton 2019-07-27 1607 * Helper to unregister the remote aux device for this MST port, registered by
3dfd9a885fbb86 Andrew Morton 2019-07-27 1608 * drm_dp_mst_connector_late_register(). Drivers should call this from their mst
3dfd9a885fbb86 Andrew Morton 2019-07-27 1609 * connector's early_unregister hook.
3dfd9a885fbb86 Andrew Morton 2019-07-27 1610 */
3dfd9a885fbb86 Andrew Morton 2019-07-27 1611 void drm_dp_mst_connector_early_unregister(struct drm_connector *connector,
3dfd9a885fbb86 Andrew Morton 2019-07-27 1612 struct drm_dp_mst_port *port)
3dfd9a885fbb86 Andrew Morton 2019-07-27 1613 {
3dfd9a885fbb86 Andrew Morton 2019-07-27 @1614 DRM_DEBUG_KMS("unregistering %s remote bus for %s\n",
3dfd9a885fbb86 Andrew Morton 2019-07-27 1615 port->aux.name, connector->kdev->kobj.name);
3dfd9a885fbb86 Andrew Morton 2019-07-27 1616 drm_dp_aux_unregister_devnode(&port->aux);
3dfd9a885fbb86 Andrew Morton 2019-07-27 1617 }
3dfd9a885fbb86 Andrew Morton 2019-07-27 1618 EXPORT_SYMBOL(drm_dp_mst_connector_early_unregister);
3dfd9a885fbb86 Andrew Morton 2019-07-27 1619
:::::: The code at line 1594 was first introduced by commit
:::::: 3dfd9a885fbb869e90f34346b9e2c23f07596d8d linux-next
:::::: TO: Andrew Morton <akpm@linux-foundation.org>
:::::: CC: Johannes Weiner <hannes@cmpxchg.org>
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 7300 bytes --]
^ permalink raw reply [flat|nested] 2+ messages in thread
* [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'
@ 2019-08-01 6:08 kbuild test robot
0 siblings, 0 replies; 2+ messages in thread
From: kbuild test robot @ 2019-08-01 6:08 UTC (permalink / raw)
To: Andrew Morton
Cc: kbuild-all, Roman Gushchin, Linux Memory Management List,
Lu Shuaibing, Johannes Weiner
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=unknown-8bit, Size: 226903 bytes --]
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@intel.com>
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@redhat.com 2016-04-22 2426 if (!port) {
263efde31f97c49 cpaul@redhat.com 2016-04-22 2427 mutex_unlock(&mgr->payload_lock);
263efde31f97c49 cpaul@redhat.com 2016-04-22 2428 return -EINVAL;
263efde31f97c49 cpaul@redhat.com 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@redhat.com 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@linux-foundation.org>
:::::: CC: Johannes Weiner <hannes@cmpxchg.org>
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 7300 bytes --]
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2019-08-07 22:34 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-08-07 22:33 [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' kbuild test robot
-- strict thread matches above, loose matches on Subject: below --
2019-08-01 6:08 kbuild test robot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox