Message ID | 20250313-mhi_bw_up-v2-10-869ca32170bf@oss.qualcomm.com (mailing list archive) |
---|---|
State | Handled Elsewhere |
Headers | show |
Series | bus: mhi: host: Add support for mhi bus bw | expand |
On Thu, Mar 13, 2025 at 05:10:17PM +0530, Krishna Chaitanya Chundru wrote: > From: Miaoqing Pan <quic_miaoqing@quicinc.com> > > Add support for MHI bandwidth scaling, which will reduce power consumption > if WLAN operates with lower bandwidth. This feature is only enabled for > QCA6390. What is the event that initiates bandwidth scaling or reduces power consumption? Is there any kind of user interface like a sysfs knob an administrator can use? Does this happen based on ath11k usage? Battery or thermal status? I guess reducing power consumption or reducing heat is probably the driving factor since we would always use max performance if power and heat were not issues? Some hints here would be useful. > Tested-on: WCN6855 hw2.1 PCI WLAN.HSP.1.1-04546-QCAHSPSWPL_V1_V2_SILICONZ_IOE-1 > Signed-off-by: Miaoqing Pan <quic_miaoqing@quicinc.com> > --- > drivers/net/wireless/ath/ath11k/mhi.c | 41 +++++++++++++++++++++++++++++++++++ > 1 file changed, 41 insertions(+) > > diff --git a/drivers/net/wireless/ath/ath11k/mhi.c b/drivers/net/wireless/ath/ath11k/mhi.c > index 6e45f464a429..74769c0993ae 100644 > --- a/drivers/net/wireless/ath/ath11k/mhi.c > +++ b/drivers/net/wireless/ath/ath11k/mhi.c > @@ -20,6 +20,7 @@ > #define MHI_TIMEOUT_DEFAULT_MS 20000 > #define RDDM_DUMP_SIZE 0x420000 > #define MHI_CB_INVALID 0xff > +#define MHI_BW_SCALE_CHAN_DB 126 > > static const struct mhi_channel_config ath11k_mhi_channels_qca6390[] = { > { > @@ -73,6 +74,17 @@ static struct mhi_event_config ath11k_mhi_events_qca6390[] = { > .client_managed = false, > .offload_channel = false, > }, > + { > + .num_elements = 8, > + .irq_moderation_ms = 0, > + .irq = 1, > + .mode = MHI_DB_BRST_DISABLE, > + .data_type = MHI_ER_BW_SCALE, > + .priority = 2, > + .hardware_event = false, > + .client_managed = false, > + .offload_channel = false, > + }, > }; > > static const struct mhi_controller_config ath11k_mhi_config_qca6390 = { > @@ -313,6 +325,33 @@ static void ath11k_mhi_op_write_reg(struct mhi_controller *mhi_cntrl, > writel(val, addr); > } > > +static int ath11k_mhi_op_get_misc_doorbell(struct mhi_controller *mhi_cntrl, > + enum mhi_er_data_type type) > +{ > + if (type == MHI_ER_BW_SCALE) > + return MHI_BW_SCALE_CHAN_DB; > + > + return -EINVAL; > +} > + > +static int ath11k_mhi_op_bw_scale(struct mhi_controller *mhi_cntrl, > + struct mhi_link_info *link_info) > +{ > + enum pci_bus_speed speed = pci_lnkctl2_bus_speed(link_info->target_link_speed); > + struct ath11k_base *ab = dev_get_drvdata(mhi_cntrl->cntrl_dev); > + struct pci_dev *pci_dev = to_pci_dev(ab->dev); > + struct pci_dev *pdev; > + > + if (!pci_dev) > + return -EINVAL; > + > + pdev = pci_upstream_bridge(pci_dev); > + if (!pdev) > + return -ENODEV; > + > + return pcie_set_target_speed(pdev, speed, true); Seems kind of unfortunate that: 1) The endpoint driver needs to be involved here, even though it does nothing that is endpoint-specific, and 2) The endpoint driver twiddles something in *another* device (the upstream bridge). There's a potential locking issue here and potential conflict with any other devices that may be below that bridge. > +} > + > static int ath11k_mhi_read_addr_from_dt(struct mhi_controller *mhi_ctrl) > { > struct device_node *np; > @@ -389,6 +428,8 @@ int ath11k_mhi_register(struct ath11k_pci *ab_pci) > mhi_ctrl->status_cb = ath11k_mhi_op_status_cb; > mhi_ctrl->read_reg = ath11k_mhi_op_read_reg; > mhi_ctrl->write_reg = ath11k_mhi_op_write_reg; > + mhi_ctrl->bw_scale = ath11k_mhi_op_bw_scale; > + mhi_ctrl->get_misc_doorbell = ath11k_mhi_op_get_misc_doorbell; > > switch (ab->hw_rev) { > case ATH11K_HW_QCN9074_HW10: > > -- > 2.34.1 >
On 3/13/2025 4:40 AM, Krishna Chaitanya Chundru wrote: > From: Miaoqing Pan <quic_miaoqing@quicinc.com> > > Add support for MHI bandwidth scaling, which will reduce power consumption > if WLAN operates with lower bandwidth. This feature is only enabled for > QCA6390. > > Tested-on: WCN6855 hw2.1 PCI WLAN.HSP.1.1-04546-QCAHSPSWPL_V1_V2_SILICONZ_IOE-1 Tested-on is not an official tag but an ath.git-specific tag, so it should be separated from the official tags by a blank line > Signed-off-by: Miaoqing Pan <quic_miaoqing@quicinc.com> your S-O-B needs to be added /jeff
diff --git a/drivers/net/wireless/ath/ath11k/mhi.c b/drivers/net/wireless/ath/ath11k/mhi.c index 6e45f464a429..74769c0993ae 100644 --- a/drivers/net/wireless/ath/ath11k/mhi.c +++ b/drivers/net/wireless/ath/ath11k/mhi.c @@ -20,6 +20,7 @@ #define MHI_TIMEOUT_DEFAULT_MS 20000 #define RDDM_DUMP_SIZE 0x420000 #define MHI_CB_INVALID 0xff +#define MHI_BW_SCALE_CHAN_DB 126 static const struct mhi_channel_config ath11k_mhi_channels_qca6390[] = { { @@ -73,6 +74,17 @@ static struct mhi_event_config ath11k_mhi_events_qca6390[] = { .client_managed = false, .offload_channel = false, }, + { + .num_elements = 8, + .irq_moderation_ms = 0, + .irq = 1, + .mode = MHI_DB_BRST_DISABLE, + .data_type = MHI_ER_BW_SCALE, + .priority = 2, + .hardware_event = false, + .client_managed = false, + .offload_channel = false, + }, }; static const struct mhi_controller_config ath11k_mhi_config_qca6390 = { @@ -313,6 +325,33 @@ static void ath11k_mhi_op_write_reg(struct mhi_controller *mhi_cntrl, writel(val, addr); } +static int ath11k_mhi_op_get_misc_doorbell(struct mhi_controller *mhi_cntrl, + enum mhi_er_data_type type) +{ + if (type == MHI_ER_BW_SCALE) + return MHI_BW_SCALE_CHAN_DB; + + return -EINVAL; +} + +static int ath11k_mhi_op_bw_scale(struct mhi_controller *mhi_cntrl, + struct mhi_link_info *link_info) +{ + enum pci_bus_speed speed = pci_lnkctl2_bus_speed(link_info->target_link_speed); + struct ath11k_base *ab = dev_get_drvdata(mhi_cntrl->cntrl_dev); + struct pci_dev *pci_dev = to_pci_dev(ab->dev); + struct pci_dev *pdev; + + if (!pci_dev) + return -EINVAL; + + pdev = pci_upstream_bridge(pci_dev); + if (!pdev) + return -ENODEV; + + return pcie_set_target_speed(pdev, speed, true); +} + static int ath11k_mhi_read_addr_from_dt(struct mhi_controller *mhi_ctrl) { struct device_node *np; @@ -389,6 +428,8 @@ int ath11k_mhi_register(struct ath11k_pci *ab_pci) mhi_ctrl->status_cb = ath11k_mhi_op_status_cb; mhi_ctrl->read_reg = ath11k_mhi_op_read_reg; mhi_ctrl->write_reg = ath11k_mhi_op_write_reg; + mhi_ctrl->bw_scale = ath11k_mhi_op_bw_scale; + mhi_ctrl->get_misc_doorbell = ath11k_mhi_op_get_misc_doorbell; switch (ab->hw_rev) { case ATH11K_HW_QCN9074_HW10: