Loading Documentation/devicetree/bindings/arm/msm/glink_config_qos.txt 0 → 100644 +22 −0 Original line number Diff line number Diff line Qualcomm Technologies, Inc. G-link QoS Configuration Required properties: -compatible : should be "qcom,glink-qos-config" -qcom,flow-info : A table of MTU transmission time specific for a power state. The total number of entries in the table should be equal to the number of supported flows. -qcom,mtu-size : The MTU size for which the qos elements are configured. -qcom,tput-stats-cycle: The number of allowable cycles for a packet to be transmitted without its priority being re-evaluated. Example: qcom,glink-qos-config-adsp { compatible = "qcom,glink-qos-config"; qcom,flow-info = <0x80 0x0>, <0x70 0x1>, <0x60 0x2>, <0x50 0x3>; qcom,mtu-size = <0x800>; qcom,tput-stats-cycle = <0xa>; }; Documentation/devicetree/bindings/arm/msm/glink_smem_native_xprt.txt +31 −0 Original line number Diff line number Diff line Loading @@ -10,6 +10,12 @@ Required properties: -interrupts : the receiving interrupt line -label : the name of the subsystem this link connects to Optional properties: -qcom,qos-config: Reference to the qos configuration elements.It depends on ramp-time. -qcom,ramp-time: Worst case time in microseconds to transition to this power state. Power states are numbered by array index position. Example: qcom,glink-smem-native-xprt-modem@fa00000 { Loading @@ -21,3 +27,28 @@ Example: interrupts = <0 25 1>; label = "mpss"; }; qcom,glink-smem-native-xprt-adsp@fa00000 { compatible = "qcom,glink-smem-native-xprt"; reg = <0xfa00000 0x200000>, <0xfa006008 0x4>; reg-names = "smem", "irq-reg-base"; qcom,irq-mask = <0x1000>; interrupts = <0 25 1>; label = "lpass"; qcom,qos-config = <&glink_qos_adsp>; qcom,ramp-time = <0x10>, <0x20>, <0x30>, <0x40>; }; glink_qos_adsp: qcom,glink-qos-config-adsp { compatible = "qcom,glink-qos-config"; qcom,flow-info = <0x80 0x0>, <0x70 0x1>, <0x60 0x2>, <0x50 0x3>; qcom,mtu-size = <0x800>; qcom,tput-stats-cycle = <0xa>; }; drivers/soc/qcom/glink.c +91 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #include <linux/spinlock.h> #include <linux/module.h> #include <linux/mutex.h> #include <linux/of.h> #include <linux/sched.h> #include <linux/slab.h> #include <linux/types.h> Loading Loading @@ -3331,6 +3332,96 @@ int glink_xprt_name_to_id(const char *name, uint16_t *id) } EXPORT_SYMBOL(glink_xprt_name_to_id); /** * of_get_glink_core_qos_cfg() - Parse the qos related dt entries * @phandle: The handle to the qos related node in DT. * @cfg: The transport configuration to be filled. * * Return: 0 on Success, standard Linux error otherwise. */ int of_get_glink_core_qos_cfg(struct device_node *phandle, struct glink_core_transport_cfg *cfg) { int rc, i; char *key; uint32_t num_flows; uint32_t *arr32; if (!phandle) { GLINK_ERR("%s: phandle is NULL\n", __func__); return -EINVAL; } key = "qcom,mtu-size"; rc = of_property_read_u32(phandle, key, (uint32_t *)&cfg->mtu); if (rc) { GLINK_ERR("%s: missing key %s\n", __func__, key); return -ENODEV; } key = "qcom,tput-stats-cycle"; rc = of_property_read_u32(phandle, key, &cfg->token_count); if (rc) { GLINK_ERR("%s: missing key %s\n", __func__, key); rc = -ENODEV; goto error; } key = "qcom,flow-info"; if (!of_find_property(phandle, key, &num_flows)) { GLINK_ERR("%s: missing key %s\n", __func__, key); rc = -ENODEV; goto error; } num_flows /= sizeof(uint32_t); if (num_flows % 2) { GLINK_ERR("%s: Invalid flow info length\n", __func__); rc = -EINVAL; goto error; } num_flows /= 2; cfg->num_flows = num_flows; cfg->flow_info = kmalloc_array(num_flows, sizeof(cfg->flow_info), GFP_KERNEL); if (!cfg->flow_info) { GLINK_ERR("%s: Memory allocation for flow info failed\n", __func__); rc = -ENOMEM; goto error; } arr32 = kmalloc_array(num_flows, sizeof(uint32_t), GFP_KERNEL); if (!arr32) { GLINK_ERR("%s: Memory allocation for temporary array failed\n", __func__); rc = -ENOMEM; goto temp_mem_alloc_fail; } of_property_read_u32_array(phandle, key, arr32, num_flows * 2); for (i = 0; i < num_flows; i++) { cfg->flow_info[i].mtu_tx_time_us = arr32[2 * i]; cfg->flow_info[i].power_state = arr32[2 * i + 1]; } kfree(arr32); of_node_put(phandle); return 0; temp_mem_alloc_fail: kfree(cfg->flow_info); error: cfg->mtu = 0; cfg->token_count = 0; cfg->num_flows = 0; cfg->flow_info = NULL; return rc; } EXPORT_SYMBOL(of_get_glink_core_qos_cfg); /** * glink_core_init_xprt_qos_cfg() - Initialize a transport's QoS configuration * @xprt_ptr: Transport to be initialized with QoS configuration. Loading drivers/soc/qcom/glink_core_if.h +11 −0 Original line number Diff line number Diff line Loading @@ -12,6 +12,7 @@ #ifndef _SOC_QCOM_GLINK_CORE_IF_H_ #define _SOC_QCOM_GLINK_CORE_IF_H_ #include <linux/of.h> #include <linux/types.h> #include "glink_private.h" Loading Loading @@ -168,6 +169,16 @@ int glink_core_register_transport(struct glink_transport_if *if_ptr, void glink_core_unregister_transport(struct glink_transport_if *if_ptr); /** * of_get_glink_core_qos_cfg() - Parse the qos related dt entries * @phandle: The handle to the qos related node in DT. * @cfg: The transport configuration to be filled. * * Return: 0 on Success, standard Linux error otherwise. */ int of_get_glink_core_qos_cfg(struct device_node *phandle, struct glink_core_transport_cfg *cfg); /** * rx_linear_vbuf_provider() - Virtual Buffer Provider for linear buffers * iovec: Pointer to the beginning of the linear buffer. Loading drivers/soc/qcom/glink_smem_native_xprt.c +113 −0 Original line number Diff line number Diff line Loading @@ -156,6 +156,9 @@ struct channel_desc { * processing. * @deferred_cmds: List of deferred commands that need to be * processed in process context. * @num_pw_states: Size of @ramp_time_us. * @ramp_time_us: Array of ramp times in microseconds where array * index position represents a power state. */ struct edge_info { struct glink_transport_if xprt_if; Loading Loading @@ -187,6 +190,8 @@ struct edge_info { bool in_ssr; spinlock_t rx_lock; struct list_head deferred_cmds; uint32_t num_pw_states; unsigned long *ramp_time_us; }; /** Loading Loading @@ -1924,6 +1929,51 @@ static int tx_cmd_tracer_pkt(struct glink_transport_if *if_ptr, uint32_t lcid, return tx_data(if_ptr, TRACER_PKT_CMD, lcid, pctx); } /** * get_power_vote_ramp_time() - Get the ramp time required for the power * votes to be applied * @if_ptr: The transport interface on which power voting is requested. * @state: The power state for which ramp time is required. * * Return: The ramp time specific to the power state, standard error otherwise. */ static unsigned long get_power_vote_ramp_time( struct glink_transport_if *if_ptr, uint32_t state) { struct edge_info *einfo; einfo = container_of(if_ptr, struct edge_info, xprt_if); if (state >= einfo->num_pw_states || !(einfo->ramp_time_us)) return (unsigned long)ERR_PTR(-EINVAL); return einfo->ramp_time_us[state]; } /** * power_vote() - Update the power votes to meet qos requirement * @if_ptr: The transport interface on which power voting is requested. * @state: The power state for which the voting should be done. * * Return: 0 on Success, standard error otherwise. */ static int power_vote(struct glink_transport_if *if_ptr, uint32_t state) { return 0; } /** * power_unvote() - Remove the all the power votes * @if_ptr: The transport interface on which power voting is requested. * * Return: 0 on Success, standard error otherwise. */ static int power_unvote(struct glink_transport_if *if_ptr) { return 0; } /** * negotiate_features_v1() - determine what features of a version can be used * @if_ptr: The transport for which features are negotiated for. Loading Loading @@ -1966,6 +2016,9 @@ static void init_xprt_if(struct edge_info *einfo) einfo->xprt_if.mask_rx_irq = mask_rx_irq; einfo->xprt_if.wait_link_down = wait_link_down; einfo->xprt_if.tx_cmd_tracer_pkt = tx_cmd_tracer_pkt; einfo->xprt_if.get_power_vote_ramp_time = get_power_vote_ramp_time; einfo->xprt_if.power_vote = power_vote; einfo->xprt_if.power_unvote = power_unvote; } /** Loading @@ -1983,6 +2036,59 @@ static void init_xprt_cfg(struct edge_info *einfo, const char *name) einfo->xprt_cfg.max_iid = SZ_2G; } /** * parse_qos_dt_params() - Parse the power states from DT * @dev: Reference to the platform device for a specific edge. * @einfo: Edge information for the edge probe function is called. * * Return: 0 on success, standard error code otherwise. */ static int parse_qos_dt_params(struct device_node *node, struct edge_info *einfo) { int rc; int i; char *key; uint32_t *arr32; uint32_t num_states; key = "qcom,ramp-time"; if (!of_find_property(node, key, &num_states)) return -ENODEV; num_states /= sizeof(uint32_t); einfo->num_pw_states = num_states; arr32 = kmalloc_array(num_states, sizeof(uint32_t), GFP_KERNEL); if (!arr32) return -ENOMEM; einfo->ramp_time_us = kmalloc_array(num_states, sizeof(unsigned long), GFP_KERNEL); if (!einfo->ramp_time_us) { rc = -ENOMEM; goto mem_alloc_fail; } rc = of_property_read_u32_array(node, key, arr32, num_states); if (rc) { rc = -ENODEV; goto invalid_key; } for (i = 0; i < num_states; i++) einfo->ramp_time_us[i] = arr32[i]; rc = 0; return rc; invalid_key: kfree(einfo->ramp_time_us); mem_alloc_fail: kfree(arr32); return rc; } /** * subsys_name_to_id() - translate a subsystem name to a processor id * @name: The subsystem name to look up. Loading Loading @@ -2012,6 +2118,7 @@ static int subsys_name_to_id(const char *name) static int glink_smem_native_probe(struct platform_device *pdev) { struct device_node *node; struct device_node *phandle_node; struct edge_info *einfo; int rc; char *key; Loading Loading @@ -2133,6 +2240,12 @@ static int glink_smem_native_probe(struct platform_device *pdev) goto smem_alloc_fail; } key = "qcom,qos-config"; phandle_node = of_parse_phandle(node, key, 0); if (phandle_node && !(of_get_glink_core_qos_cfg(phandle_node, &einfo->xprt_cfg))) parse_qos_dt_params(node, einfo); rc = glink_core_register_transport(&einfo->xprt_if, &einfo->xprt_cfg); if (rc == -EPROBE_DEFER) goto reg_xprt_fail; Loading Loading
Documentation/devicetree/bindings/arm/msm/glink_config_qos.txt 0 → 100644 +22 −0 Original line number Diff line number Diff line Qualcomm Technologies, Inc. G-link QoS Configuration Required properties: -compatible : should be "qcom,glink-qos-config" -qcom,flow-info : A table of MTU transmission time specific for a power state. The total number of entries in the table should be equal to the number of supported flows. -qcom,mtu-size : The MTU size for which the qos elements are configured. -qcom,tput-stats-cycle: The number of allowable cycles for a packet to be transmitted without its priority being re-evaluated. Example: qcom,glink-qos-config-adsp { compatible = "qcom,glink-qos-config"; qcom,flow-info = <0x80 0x0>, <0x70 0x1>, <0x60 0x2>, <0x50 0x3>; qcom,mtu-size = <0x800>; qcom,tput-stats-cycle = <0xa>; };
Documentation/devicetree/bindings/arm/msm/glink_smem_native_xprt.txt +31 −0 Original line number Diff line number Diff line Loading @@ -10,6 +10,12 @@ Required properties: -interrupts : the receiving interrupt line -label : the name of the subsystem this link connects to Optional properties: -qcom,qos-config: Reference to the qos configuration elements.It depends on ramp-time. -qcom,ramp-time: Worst case time in microseconds to transition to this power state. Power states are numbered by array index position. Example: qcom,glink-smem-native-xprt-modem@fa00000 { Loading @@ -21,3 +27,28 @@ Example: interrupts = <0 25 1>; label = "mpss"; }; qcom,glink-smem-native-xprt-adsp@fa00000 { compatible = "qcom,glink-smem-native-xprt"; reg = <0xfa00000 0x200000>, <0xfa006008 0x4>; reg-names = "smem", "irq-reg-base"; qcom,irq-mask = <0x1000>; interrupts = <0 25 1>; label = "lpass"; qcom,qos-config = <&glink_qos_adsp>; qcom,ramp-time = <0x10>, <0x20>, <0x30>, <0x40>; }; glink_qos_adsp: qcom,glink-qos-config-adsp { compatible = "qcom,glink-qos-config"; qcom,flow-info = <0x80 0x0>, <0x70 0x1>, <0x60 0x2>, <0x50 0x3>; qcom,mtu-size = <0x800>; qcom,tput-stats-cycle = <0xa>; };
drivers/soc/qcom/glink.c +91 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #include <linux/spinlock.h> #include <linux/module.h> #include <linux/mutex.h> #include <linux/of.h> #include <linux/sched.h> #include <linux/slab.h> #include <linux/types.h> Loading Loading @@ -3331,6 +3332,96 @@ int glink_xprt_name_to_id(const char *name, uint16_t *id) } EXPORT_SYMBOL(glink_xprt_name_to_id); /** * of_get_glink_core_qos_cfg() - Parse the qos related dt entries * @phandle: The handle to the qos related node in DT. * @cfg: The transport configuration to be filled. * * Return: 0 on Success, standard Linux error otherwise. */ int of_get_glink_core_qos_cfg(struct device_node *phandle, struct glink_core_transport_cfg *cfg) { int rc, i; char *key; uint32_t num_flows; uint32_t *arr32; if (!phandle) { GLINK_ERR("%s: phandle is NULL\n", __func__); return -EINVAL; } key = "qcom,mtu-size"; rc = of_property_read_u32(phandle, key, (uint32_t *)&cfg->mtu); if (rc) { GLINK_ERR("%s: missing key %s\n", __func__, key); return -ENODEV; } key = "qcom,tput-stats-cycle"; rc = of_property_read_u32(phandle, key, &cfg->token_count); if (rc) { GLINK_ERR("%s: missing key %s\n", __func__, key); rc = -ENODEV; goto error; } key = "qcom,flow-info"; if (!of_find_property(phandle, key, &num_flows)) { GLINK_ERR("%s: missing key %s\n", __func__, key); rc = -ENODEV; goto error; } num_flows /= sizeof(uint32_t); if (num_flows % 2) { GLINK_ERR("%s: Invalid flow info length\n", __func__); rc = -EINVAL; goto error; } num_flows /= 2; cfg->num_flows = num_flows; cfg->flow_info = kmalloc_array(num_flows, sizeof(cfg->flow_info), GFP_KERNEL); if (!cfg->flow_info) { GLINK_ERR("%s: Memory allocation for flow info failed\n", __func__); rc = -ENOMEM; goto error; } arr32 = kmalloc_array(num_flows, sizeof(uint32_t), GFP_KERNEL); if (!arr32) { GLINK_ERR("%s: Memory allocation for temporary array failed\n", __func__); rc = -ENOMEM; goto temp_mem_alloc_fail; } of_property_read_u32_array(phandle, key, arr32, num_flows * 2); for (i = 0; i < num_flows; i++) { cfg->flow_info[i].mtu_tx_time_us = arr32[2 * i]; cfg->flow_info[i].power_state = arr32[2 * i + 1]; } kfree(arr32); of_node_put(phandle); return 0; temp_mem_alloc_fail: kfree(cfg->flow_info); error: cfg->mtu = 0; cfg->token_count = 0; cfg->num_flows = 0; cfg->flow_info = NULL; return rc; } EXPORT_SYMBOL(of_get_glink_core_qos_cfg); /** * glink_core_init_xprt_qos_cfg() - Initialize a transport's QoS configuration * @xprt_ptr: Transport to be initialized with QoS configuration. Loading
drivers/soc/qcom/glink_core_if.h +11 −0 Original line number Diff line number Diff line Loading @@ -12,6 +12,7 @@ #ifndef _SOC_QCOM_GLINK_CORE_IF_H_ #define _SOC_QCOM_GLINK_CORE_IF_H_ #include <linux/of.h> #include <linux/types.h> #include "glink_private.h" Loading Loading @@ -168,6 +169,16 @@ int glink_core_register_transport(struct glink_transport_if *if_ptr, void glink_core_unregister_transport(struct glink_transport_if *if_ptr); /** * of_get_glink_core_qos_cfg() - Parse the qos related dt entries * @phandle: The handle to the qos related node in DT. * @cfg: The transport configuration to be filled. * * Return: 0 on Success, standard Linux error otherwise. */ int of_get_glink_core_qos_cfg(struct device_node *phandle, struct glink_core_transport_cfg *cfg); /** * rx_linear_vbuf_provider() - Virtual Buffer Provider for linear buffers * iovec: Pointer to the beginning of the linear buffer. Loading
drivers/soc/qcom/glink_smem_native_xprt.c +113 −0 Original line number Diff line number Diff line Loading @@ -156,6 +156,9 @@ struct channel_desc { * processing. * @deferred_cmds: List of deferred commands that need to be * processed in process context. * @num_pw_states: Size of @ramp_time_us. * @ramp_time_us: Array of ramp times in microseconds where array * index position represents a power state. */ struct edge_info { struct glink_transport_if xprt_if; Loading Loading @@ -187,6 +190,8 @@ struct edge_info { bool in_ssr; spinlock_t rx_lock; struct list_head deferred_cmds; uint32_t num_pw_states; unsigned long *ramp_time_us; }; /** Loading Loading @@ -1924,6 +1929,51 @@ static int tx_cmd_tracer_pkt(struct glink_transport_if *if_ptr, uint32_t lcid, return tx_data(if_ptr, TRACER_PKT_CMD, lcid, pctx); } /** * get_power_vote_ramp_time() - Get the ramp time required for the power * votes to be applied * @if_ptr: The transport interface on which power voting is requested. * @state: The power state for which ramp time is required. * * Return: The ramp time specific to the power state, standard error otherwise. */ static unsigned long get_power_vote_ramp_time( struct glink_transport_if *if_ptr, uint32_t state) { struct edge_info *einfo; einfo = container_of(if_ptr, struct edge_info, xprt_if); if (state >= einfo->num_pw_states || !(einfo->ramp_time_us)) return (unsigned long)ERR_PTR(-EINVAL); return einfo->ramp_time_us[state]; } /** * power_vote() - Update the power votes to meet qos requirement * @if_ptr: The transport interface on which power voting is requested. * @state: The power state for which the voting should be done. * * Return: 0 on Success, standard error otherwise. */ static int power_vote(struct glink_transport_if *if_ptr, uint32_t state) { return 0; } /** * power_unvote() - Remove the all the power votes * @if_ptr: The transport interface on which power voting is requested. * * Return: 0 on Success, standard error otherwise. */ static int power_unvote(struct glink_transport_if *if_ptr) { return 0; } /** * negotiate_features_v1() - determine what features of a version can be used * @if_ptr: The transport for which features are negotiated for. Loading Loading @@ -1966,6 +2016,9 @@ static void init_xprt_if(struct edge_info *einfo) einfo->xprt_if.mask_rx_irq = mask_rx_irq; einfo->xprt_if.wait_link_down = wait_link_down; einfo->xprt_if.tx_cmd_tracer_pkt = tx_cmd_tracer_pkt; einfo->xprt_if.get_power_vote_ramp_time = get_power_vote_ramp_time; einfo->xprt_if.power_vote = power_vote; einfo->xprt_if.power_unvote = power_unvote; } /** Loading @@ -1983,6 +2036,59 @@ static void init_xprt_cfg(struct edge_info *einfo, const char *name) einfo->xprt_cfg.max_iid = SZ_2G; } /** * parse_qos_dt_params() - Parse the power states from DT * @dev: Reference to the platform device for a specific edge. * @einfo: Edge information for the edge probe function is called. * * Return: 0 on success, standard error code otherwise. */ static int parse_qos_dt_params(struct device_node *node, struct edge_info *einfo) { int rc; int i; char *key; uint32_t *arr32; uint32_t num_states; key = "qcom,ramp-time"; if (!of_find_property(node, key, &num_states)) return -ENODEV; num_states /= sizeof(uint32_t); einfo->num_pw_states = num_states; arr32 = kmalloc_array(num_states, sizeof(uint32_t), GFP_KERNEL); if (!arr32) return -ENOMEM; einfo->ramp_time_us = kmalloc_array(num_states, sizeof(unsigned long), GFP_KERNEL); if (!einfo->ramp_time_us) { rc = -ENOMEM; goto mem_alloc_fail; } rc = of_property_read_u32_array(node, key, arr32, num_states); if (rc) { rc = -ENODEV; goto invalid_key; } for (i = 0; i < num_states; i++) einfo->ramp_time_us[i] = arr32[i]; rc = 0; return rc; invalid_key: kfree(einfo->ramp_time_us); mem_alloc_fail: kfree(arr32); return rc; } /** * subsys_name_to_id() - translate a subsystem name to a processor id * @name: The subsystem name to look up. Loading Loading @@ -2012,6 +2118,7 @@ static int subsys_name_to_id(const char *name) static int glink_smem_native_probe(struct platform_device *pdev) { struct device_node *node; struct device_node *phandle_node; struct edge_info *einfo; int rc; char *key; Loading Loading @@ -2133,6 +2240,12 @@ static int glink_smem_native_probe(struct platform_device *pdev) goto smem_alloc_fail; } key = "qcom,qos-config"; phandle_node = of_parse_phandle(node, key, 0); if (phandle_node && !(of_get_glink_core_qos_cfg(phandle_node, &einfo->xprt_cfg))) parse_qos_dt_params(node, einfo); rc = glink_core_register_transport(&einfo->xprt_if, &einfo->xprt_cfg); if (rc == -EPROBE_DEFER) goto reg_xprt_fail; Loading