Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'ipa-kill-off-ipa_clock_get'

Alex Elder says:

====================
net: ipa: kill off ipa_clock_get()

This series replaces the remaining uses of ipa_clock_get() with
calls to pm_runtime_get_sync() instead. It replaces all calls to
ipa_clock_put() with calls to pm_runtime_put().

This completes the preparation for enabling automated suspend under
the control of the power management core code. The next patch (in
an upcoming series) enables that. Then the "ipa_clock" files and
symbols will switch to using an "ipa_power" naming convention instead.

Additional info

It is possible for pm_runtime_get_sync() to return an error. There
are really three cases, identified by return value:
- 1, meaning power was already active
- 0, meaning power was not previously active, but is now
- EACCES, meaning runtime PM is disabled
One additional case is EINVAL, meaning a previous suspend or resume
(or idle) call returned an error. But we have always assumed this
won't happen (we previously didn't even check for an error).

But because we use pm_runtime_force_suspend() to implement system
suspend, there's a chance we'd get an EACCES error (the first thing
that function does is disable runtime suspend). Individual patches
explain what happens in that case, but generally we just accept that
it could be an unlikely problem (occurring only at startup time).

Similarly, pm_runtime_put() could return an error. There too, we
ignore EINVAL, assuming the IPA suspend and resume operations won't
produce an error. EBUSY and EPERM are not applicable, EAGAIN is not
expected (and harmless). We should never get EACCES (runtime
suspend disabled), because pm_runtime_put() calls match prior
pm_runtime_get_sync() calls, and a system suspend will not be
started while a runtime suspend or resume is underway. In summary,
the value returned from pm_runtime_put() is not meaningful, so we
explicitly ignore it.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+65 -92
-17
drivers/net/ipa/ipa_clock.c
··· 272 272 return -EAGAIN; 273 273 } 274 274 275 - /* Get an IPA clock reference. If the reference count is non-zero, it is 276 - * incremented and return is immediate. Otherwise the IPA clock is 277 - * enabled. 278 - */ 279 - int ipa_clock_get(struct ipa *ipa) 280 - { 281 - return pm_runtime_get_sync(&ipa->pdev->dev); 282 - } 283 - 284 - /* Attempt to remove an IPA clock reference. If this represents the 285 - * last reference, disable the IPA clock. 286 - */ 287 - int ipa_clock_put(struct ipa *ipa) 288 - { 289 - return pm_runtime_put(&ipa->pdev->dev); 290 - } 291 - 292 275 static int ipa_suspend(struct device *dev) 293 276 { 294 277 struct ipa *ipa = dev_get_drvdata(dev);
-24
drivers/net/ipa/ipa_clock.h
··· 70 70 */ 71 71 void ipa_clock_exit(struct ipa_clock *clock); 72 72 73 - /** 74 - * ipa_clock_get() - Get an IPA clock reference 75 - * @ipa: IPA pointer 76 - * 77 - * Return: 0 if clock started, 1 if clock already running, or a negative 78 - * error code 79 - * 80 - * This call blocks if this is the first reference. A reference is 81 - * taken even if an error occurs starting the IPA clock. 82 - */ 83 - int ipa_clock_get(struct ipa *ipa); 84 - 85 - /** 86 - * ipa_clock_put() - Drop an IPA clock reference 87 - * @ipa: IPA pointer 88 - * 89 - * Return: 0 if successful, or a negative error code 90 - * 91 - * This drops a clock reference. If the last reference is being dropped, 92 - * the clock is stopped and RX endpoints are suspended. This call will 93 - * not block unless the last reference is dropped. 94 - */ 95 - int ipa_clock_put(struct ipa *ipa); 96 - 97 73 #endif /* _IPA_CLOCK_H_ */
+7 -7
drivers/net/ipa/ipa_interrupt.c
··· 21 21 22 22 #include <linux/types.h> 23 23 #include <linux/interrupt.h> 24 + #include <linux/pm_runtime.h> 24 25 25 26 #include "ipa.h" 26 - #include "ipa_clock.h" 27 27 #include "ipa_reg.h" 28 28 #include "ipa_endpoint.h" 29 29 #include "ipa_interrupt.h" ··· 80 80 struct ipa_interrupt *interrupt = dev_id; 81 81 struct ipa *ipa = interrupt->ipa; 82 82 u32 enabled = interrupt->enabled; 83 + struct device *dev; 83 84 u32 pending; 84 85 u32 offset; 85 86 u32 mask; 86 87 int ret; 87 88 88 - ret = ipa_clock_get(ipa); 89 + dev = &ipa->pdev->dev; 90 + ret = pm_runtime_get_sync(dev); 89 91 if (WARN_ON(ret < 0)) 90 - goto out_clock_put; 92 + goto out_power_put; 91 93 92 94 /* The status register indicates which conditions are present, 93 95 * including conditions whose interrupt is not enabled. Handle ··· 110 108 111 109 /* If any disabled interrupts are pending, clear them */ 112 110 if (pending) { 113 - struct device *dev = &ipa->pdev->dev; 114 - 115 111 dev_dbg(dev, "clearing disabled IPA interrupts 0x%08x\n", 116 112 pending); 117 113 offset = ipa_reg_irq_clr_offset(ipa->version); 118 114 iowrite32(pending, ipa->reg_virt + offset); 119 115 } 120 - out_clock_put: 121 - (void)ipa_clock_put(ipa); 116 + out_power_put: 117 + (void)pm_runtime_put(dev); 122 118 123 119 return IRQ_HANDLED; 124 120 }
+11 -10
drivers/net/ipa/ipa_main.c
··· 15 15 #include <linux/of.h> 16 16 #include <linux/of_device.h> 17 17 #include <linux/of_address.h> 18 + #include <linux/pm_runtime.h> 18 19 #include <linux/qcom_scm.h> 19 20 #include <linux/soc/qcom/mdt_loader.h> 20 21 ··· 738 737 goto err_table_exit; 739 738 740 739 /* The clock needs to be active for config and setup */ 741 - ret = ipa_clock_get(ipa); 740 + ret = pm_runtime_get_sync(dev); 742 741 if (WARN_ON(ret < 0)) 743 - goto err_clock_put; 742 + goto err_power_put; 744 743 745 744 ret = ipa_config(ipa, data); 746 745 if (ret) 747 - goto err_clock_put; 746 + goto err_power_put; 748 747 749 748 dev_info(dev, "IPA driver initialized"); 750 749 ··· 766 765 if (ret) 767 766 goto err_deconfig; 768 767 done: 769 - (void)ipa_clock_put(ipa); 768 + (void)pm_runtime_put(dev); 770 769 771 770 return 0; 772 771 773 772 err_deconfig: 774 773 ipa_deconfig(ipa); 775 - err_clock_put: 776 - (void)ipa_clock_put(ipa); 774 + err_power_put: 775 + (void)pm_runtime_put(dev); 777 776 ipa_modem_exit(ipa); 778 777 err_table_exit: 779 778 ipa_table_exit(ipa); ··· 799 798 struct ipa_clock *clock = ipa->clock; 800 799 int ret; 801 800 802 - ret = ipa_clock_get(ipa); 801 + ret = pm_runtime_get_sync(&pdev->dev); 803 802 if (WARN_ON(ret < 0)) 804 - goto out_clock_put; 803 + goto out_power_put; 805 804 806 805 if (ipa->setup_complete) { 807 806 ret = ipa_modem_stop(ipa); ··· 817 816 } 818 817 819 818 ipa_deconfig(ipa); 820 - out_clock_put: 821 - (void)ipa_clock_put(ipa); 819 + out_power_put: 820 + (void)pm_runtime_put(&pdev->dev); 822 821 823 822 ipa_modem_exit(ipa); 824 823 ipa_table_exit(ipa);
+23 -17
drivers/net/ipa/ipa_modem.c
··· 49 49 { 50 50 struct ipa_priv *priv = netdev_priv(netdev); 51 51 struct ipa *ipa = priv->ipa; 52 + struct device *dev; 52 53 int ret; 53 54 54 - ret = ipa_clock_get(ipa); 55 - if (WARN_ON(ret < 0)) 56 - goto err_clock_put; 55 + dev = &ipa->pdev->dev; 56 + ret = pm_runtime_get_sync(dev); 57 + if (ret < 0) 58 + goto err_power_put; 57 59 58 60 ret = ipa_endpoint_enable_one(ipa->name_map[IPA_ENDPOINT_AP_MODEM_TX]); 59 61 if (ret) 60 - goto err_clock_put; 62 + goto err_power_put; 61 63 62 64 ret = ipa_endpoint_enable_one(ipa->name_map[IPA_ENDPOINT_AP_MODEM_RX]); 63 65 if (ret) ··· 67 65 68 66 netif_start_queue(netdev); 69 67 70 - (void)ipa_clock_put(ipa); 68 + (void)pm_runtime_put(dev); 71 69 72 70 return 0; 73 71 74 72 err_disable_tx: 75 73 ipa_endpoint_disable_one(ipa->name_map[IPA_ENDPOINT_AP_MODEM_TX]); 76 - err_clock_put: 77 - (void)ipa_clock_put(ipa); 74 + err_power_put: 75 + (void)pm_runtime_put(dev); 78 76 79 77 return ret; 80 78 } ··· 84 82 { 85 83 struct ipa_priv *priv = netdev_priv(netdev); 86 84 struct ipa *ipa = priv->ipa; 85 + struct device *dev; 87 86 int ret; 88 87 89 - ret = ipa_clock_get(ipa); 90 - if (WARN_ON(ret < 0)) 91 - goto out_clock_put; 88 + dev = &ipa->pdev->dev; 89 + ret = pm_runtime_get_sync(dev); 90 + if (ret < 0) 91 + goto out_power_put; 92 92 93 93 netif_stop_queue(netdev); 94 94 95 95 ipa_endpoint_disable_one(ipa->name_map[IPA_ENDPOINT_AP_MODEM_RX]); 96 96 ipa_endpoint_disable_one(ipa->name_map[IPA_ENDPOINT_AP_MODEM_TX]); 97 - out_clock_put: 98 - (void)ipa_clock_put(ipa); 97 + out_power_put: 98 + (void)pm_runtime_put(dev); 99 99 100 100 return 0; 101 101 } ··· 366 362 struct device *dev = &ipa->pdev->dev; 367 363 int ret; 368 364 369 - ret = ipa_clock_get(ipa); 370 - if (WARN_ON(ret < 0)) 371 - goto out_clock_put; 365 + ret = pm_runtime_get_sync(dev); 366 + if (ret < 0) { 367 + dev_err(dev, "error %d getting power to handle crash\n", ret); 368 + goto out_power_put; 369 + } 372 370 373 371 ipa_endpoint_modem_pause_all(ipa, true); 374 372 ··· 397 391 if (ret) 398 392 dev_err(dev, "error %d zeroing modem memory regions\n", ret); 399 393 400 - out_clock_put: 401 - (void)ipa_clock_put(ipa); 394 + out_power_put: 395 + (void)pm_runtime_put(dev); 402 396 } 403 397 404 398 static int ipa_modem_notify(struct notifier_block *nb, unsigned long action,
+11 -8
drivers/net/ipa/ipa_smp2p.c
··· 16 16 #include "ipa_smp2p.h" 17 17 #include "ipa.h" 18 18 #include "ipa_uc.h" 19 - #include "ipa_clock.h" 20 19 21 20 /** 22 21 * DOC: IPA SMP2P communication with the modem ··· 152 153 static irqreturn_t ipa_smp2p_modem_setup_ready_isr(int irq, void *dev_id) 153 154 { 154 155 struct ipa_smp2p *smp2p = dev_id; 156 + struct device *dev; 155 157 int ret; 156 158 157 159 mutex_lock(&smp2p->mutex); ··· 161 161 goto out_mutex_unlock; 162 162 smp2p->disabled = true; /* If any others arrive, ignore them */ 163 163 164 - /* The clock needs to be active for setup */ 165 - ret = ipa_clock_get(smp2p->ipa); 166 - if (WARN_ON(ret < 0)) 167 - goto out_clock_put; 164 + /* Power needs to be active for setup */ 165 + dev = &smp2p->ipa->pdev->dev; 166 + ret = pm_runtime_get_sync(dev); 167 + if (ret < 0) { 168 + dev_err(dev, "error %d getting power for setup\n", ret); 169 + goto out_power_put; 170 + } 168 171 169 172 /* An error here won't cause driver shutdown, so warn if one occurs */ 170 173 ret = ipa_setup(smp2p->ipa); 171 174 WARN(ret != 0, "error %d from ipa_setup()\n", ret); 172 175 173 - out_clock_put: 174 - (void)ipa_clock_put(smp2p->ipa); 176 + out_power_put: 177 + (void)pm_runtime_put(dev); 175 178 out_mutex_unlock: 176 179 mutex_unlock(&smp2p->mutex); 177 180 ··· 214 211 if (!ipa->smp2p->clock_on) 215 212 return; 216 213 217 - (void)ipa_clock_put(ipa); 214 + (void)pm_runtime_put(&ipa->pdev->dev); 218 215 ipa->smp2p->clock_on = false; 219 216 } 220 217
+13 -9
drivers/net/ipa/ipa_uc.c
··· 7 7 #include <linux/types.h> 8 8 #include <linux/io.h> 9 9 #include <linux/delay.h> 10 + #include <linux/pm_runtime.h> 10 11 11 12 #include "ipa.h" 12 - #include "ipa_clock.h" 13 13 #include "ipa_uc.h" 14 14 15 15 /** ··· 154 154 case IPA_UC_RESPONSE_INIT_COMPLETED: 155 155 if (ipa->uc_clocked) { 156 156 ipa->uc_loaded = true; 157 - (void)ipa_clock_put(ipa); 157 + (void)pm_runtime_put(dev); 158 158 ipa->uc_clocked = false; 159 159 } else { 160 160 dev_warn(dev, "unexpected init_completed response\n"); ··· 182 182 ipa_interrupt_remove(ipa->interrupt, IPA_IRQ_UC_1); 183 183 ipa_interrupt_remove(ipa->interrupt, IPA_IRQ_UC_0); 184 184 if (ipa->uc_clocked) 185 - (void)ipa_clock_put(ipa); 185 + (void)pm_runtime_put(&ipa->pdev->dev); 186 186 } 187 187 188 188 /* Take a proxy clock reference for the microcontroller */ 189 189 void ipa_uc_clock(struct ipa *ipa) 190 190 { 191 191 static bool already; 192 + struct device *dev; 192 193 int ret; 193 194 194 195 if (already) 195 196 return; 196 197 already = true; /* Only do this on first boot */ 197 198 198 - /* This clock reference dropped in ipa_uc_response_hdlr() above */ 199 - ret = ipa_clock_get(ipa); 200 - if (WARN(ret < 0, "error %d getting proxy clock\n", ret)) 201 - (void)ipa_clock_put(ipa); 202 - 203 - ipa->uc_clocked = ret >= 0; 199 + /* This power reference dropped in ipa_uc_response_hdlr() above */ 200 + dev = &ipa->pdev->dev; 201 + ret = pm_runtime_get_sync(dev); 202 + if (ret < 0) { 203 + pm_runtime_put_noidle(dev); 204 + dev_err(dev, "error %d getting proxy power\n", ret); 205 + } else { 206 + ipa->uc_clocked = true; 207 + } 204 208 } 205 209 206 210 /* Send a command to the microcontroller */