Date: Mon, 8 Jul 2024 12:25:19 +0200 From: Krzysztof Kozlowski To: Linus Walleij Cc: Peng Fan , linux-arm-kernel@lists.infradead.org, linux-samsung-soc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org, Krzysztof Kozlowski Subject: [PATCH PULL] pinctrl: samsung: Use scope based of_node_put() cleanups From: Peng Fan Use scope based of_node_put() cleanup to simplify code. Signed-off-by: Peng Fan Link: https://lore.kernel.org/r/20240504-pinctrl-cleanup-v2-20-26c5f2dc1181@nxp.com Signed-off-by: Krzysztof Kozlowski --- Hi Linus, I got only this one in the queue, so sending directly. Best regards, Krzysztof drivers/pinctrl/samsung/pinctrl-exynos.c | 16 ++++------------ drivers/pinctrl/samsung/pinctrl-samsung.c | 19 +++++-------------- 2 files changed, 9 insertions(+), 26 deletions(-) diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.c b/drivers/pinctrl/samsung/pinctrl-exynos.c index ce5e6783b5b9..b79c211c0374 100644 --- a/drivers/pinctrl/samsung/pinctrl-exynos.c +++ b/drivers/pinctrl/samsung/pinctrl-exynos.c @@ -662,7 +662,7 @@ static void exynos_irq_demux_eint16_31(struct irq_desc *desc) __init int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d) { struct device *dev = d->dev; - struct device_node *wkup_np = NULL; + struct device_node *wkup_np __free(device_node) = NULL; struct device_node *np; struct samsung_pin_bank *bank; struct exynos_weint_data *weint_data; @@ -692,17 +692,14 @@ __init int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d) bank->irq_chip = devm_kmemdup(dev, irq_chip, sizeof(*irq_chip), GFP_KERNEL); - if (!bank->irq_chip) { - of_node_put(wkup_np); + if (!bank->irq_chip) return -ENOMEM; - } bank->irq_chip->chip.name = bank->name; bank->irq_domain = irq_domain_create_linear(bank->fwnode, bank->nr_pins, &exynos_eint_irqd_ops, bank); if (!bank->irq_domain) { dev_err(dev, "wkup irq domain add failed\n"); - of_node_put(wkup_np); return -ENXIO; } @@ -715,10 +712,8 @@ __init int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d) weint_data = devm_kcalloc(dev, bank->nr_pins, sizeof(*weint_data), GFP_KERNEL); - if (!weint_data) { - of_node_put(wkup_np); + if (!weint_data) return -ENOMEM; - } for (idx = 0; idx < bank->nr_pins; ++idx) { irq = irq_of_parse_and_map(to_of_node(bank->fwnode), idx); @@ -735,13 +730,10 @@ __init int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d) } } - if (!muxed_banks) { - of_node_put(wkup_np); + if (!muxed_banks) return 0; - } irq = irq_of_parse_and_map(wkup_np, 0); - of_node_put(wkup_np); if (!irq) { dev_err(dev, "irq number for muxed EINTs not found\n"); return 0; diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c index 623df65a5d6f..a7deae4afdcc 100644 --- a/drivers/pinctrl/samsung/pinctrl-samsung.c +++ b/drivers/pinctrl/samsung/pinctrl-samsung.c @@ -251,7 +251,6 @@ static int samsung_dt_node_to_map(struct pinctrl_dev *pctldev, { struct samsung_pinctrl_drv_data *drvdata; unsigned reserved_maps; - struct device_node *np; int ret; drvdata = pinctrl_dev_get_drvdata(pctldev); @@ -266,12 +265,11 @@ static int samsung_dt_node_to_map(struct pinctrl_dev *pctldev, &reserved_maps, num_maps); - for_each_child_of_node(np_config, np) { + for_each_child_of_node_scoped(np_config, np) { ret = samsung_dt_subnode_to_map(drvdata, pctldev->dev, np, map, &reserved_maps, num_maps); if (ret < 0) { samsung_dt_free_map(pctldev, *map, *num_maps); - of_node_put(np); return ret; } } @@ -849,16 +847,12 @@ static struct samsung_pmx_func *samsung_pinctrl_create_functions( * and create pin groups and pin function lists. */ func_cnt = 0; - for_each_child_of_node(dev_np, cfg_np) { - struct device_node *func_np; - + for_each_child_of_node_scoped(dev_np, cfg_np) { if (!of_get_child_count(cfg_np)) { ret = samsung_pinctrl_create_function(dev, drvdata, cfg_np, func); - if (ret < 0) { - of_node_put(cfg_np); + if (ret < 0) return ERR_PTR(ret); - } if (ret > 0) { ++func; ++func_cnt; @@ -866,14 +860,11 @@ static struct samsung_pmx_func *samsung_pinctrl_create_functions( continue; } - for_each_child_of_node(cfg_np, func_np) { + for_each_child_of_node_scoped(cfg_np, func_np) { ret = samsung_pinctrl_create_function(dev, drvdata, func_np, func); - if (ret < 0) { - of_node_put(func_np); - of_node_put(cfg_np); + if (ret < 0) return ERR_PTR(ret); - } if (ret > 0) { ++func; ++func_cnt; -- 2.43.0 . Date: Mon, 8 Jul 2024 08:08:20 -0700 From: Namhyung Kim To: Linus Torvalds Cc: Arnaldo Carvalho de Melo , Namhyung Kim , Ian Rogers , Kan Liang , Adrian Hunter , Peter Zijlstra , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org Subject: [GIT PULL] perf-tools-fixes for v6.10 Hi Linus, Please consider pulling the following changes in perf tools for v6.10. Thanks, Namhyung The following changes since commit 83a7eefedc9b56fe7bfeff13b6c7356688ffa670: Linux 6.10-rc3 (2024-06-09 14:19:43 -0700) are available in the Git repository at: git://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools.git tags/perf-tools-fixes-for-v6.10-2024-07-08 for you to fetch changes up to 7b2450bb40275802b73593331b0db2fc147ae2b7: perf dsos: When adding a dso into sorted dsos maintain the sort order (2024-07-07 22:26:29 -0700) ---------------------------------------------------------------- perf tools: Fix the performance issue for v6.10 These addresses the performance issues reported by Matt, Namhyung and Linus. Recently it changed processing comm string and DSO with sorted arrays but it required to sort the array whenever it adds a new entry. This caused a performance issue and fix is to enhance the sorting by finding the insertion point in the sorted array and to shift righthand side using memmove(). Signed-off-by: Namhyung Kim ---------------------------------------------------------------- Ian Rogers (2): perf comm str: Avoid sort during insert perf dsos: When adding a dso into sorted dsos maintain the sort order tools/perf/util/comm.c | 29 ++++++++++++++++++----------- tools/perf/util/dsos.c | 26 +++++++++++++++++++++----- 2 files changed, 39 insertions(+), 16 deletions(-) . Date: Mon, 8 Jul 2024 16:42:13 -0600 From: Shuah Khan To: Linus Torvalds Cc: Shuah Khan , shuah , linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, John Hubbard , "Jason A. Donenfeld" Subject: [GIT PULL] Kselftest fixes for Linux 6.10 This is a multi-part message in MIME format. --------------zvEHuaPS38NLDGr1NkzGpYeN Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit Hi Linus, Please pull this kselftest fixes update for Linux 6.10. This kselftest fixes update for Linux 6.10 consists of fixes to clang build failures to timerns, vDSO tests and fixes to vDSO makefile. Note: makefile fixes are included to avoid conflicts during 6.11 merge window. diff is attached. thanks, -- Shuah ---------------------------------------------------------------- The following changes since commit 48236960c06d32370bfa6f2cc408e786873262c8: selftests/resctrl: Fix non-contiguous CBM for AMD (2024-06-26 13:22:34 -0600) are available in the Git repository at: git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest tags/linux_kselftest-fixes-6.10 for you to fetch changes up to 66cde337fa1b7c6cf31f856fa015bd91a4d383e7: selftests/vDSO: remove duplicate compiler invocations from Makefile (2024-07-05 14:12:34 -0600) ---------------------------------------------------------------- linux_kselftest-fixes-6.10 This kselftest fixes update for Linux 6.10 consists of fixes to clang build failures to timerns, vDSO tests and fixes to vDSO makefile. ---------------------------------------------------------------- John Hubbard (4): selftest/timerns: fix clang build failures for abs() calls selftests/vDSO: fix clang build errors and warnings selftests/vDSO: remove partially duplicated "all:" target in Makefile selftests/vDSO: remove duplicate compiler invocations from Makefile tools/testing/selftests/timens/exec.c | 6 ++--- tools/testing/selftests/timens/timer.c | 2 +- tools/testing/selftests/timens/timerfd.c | 2 +- tools/testing/selftests/timens/vfork_exec.c | 4 +-- tools/testing/selftests/vDSO/Makefile | 29 +++++++++------------- tools/testing/selftests/vDSO/parse_vdso.c | 16 ++++++++---- .../selftests/vDSO/vdso_standalone_test_x86.c | 18 ++++++++++++-- 7 files changed, 46 insertions(+), 31 deletions(-) ---------------------------------------------------------------- --------------zvEHuaPS38NLDGr1NkzGpYeN Content-Type: text/x-patch; charset=UTF-8; name="linux_kselftest-fixes-6.10.diff" Content-Disposition: attachment; filename="linux_kselftest-fixes-6.10.diff" Content-Transfer-Encoding: base64 ZGlmZiAtLWdpdCBhL3Rvb2xzL3Rlc3Rpbmcvc2VsZnRlc3RzL3RpbWVucy9leGVjLmMgYi90 b29scy90ZXN0aW5nL3NlbGZ0ZXN0cy90aW1lbnMvZXhlYy5jCmluZGV4IGU0MGRjNWJlMmY2 Ni4uZDEyZmY5NTVkZTBkIDEwMDY0NAotLS0gYS90b29scy90ZXN0aW5nL3NlbGZ0ZXN0cy90 aW1lbnMvZXhlYy5jCisrKyBiL3Rvb2xzL3Rlc3Rpbmcvc2VsZnRlc3RzL3RpbWVucy9leGVj LmMKQEAgLTMwLDcgKzMwLDcgQEAgaW50IG1haW4oaW50IGFyZ2MsIGNoYXIgKmFyZ3ZbXSkK IAogCQlmb3IgKGkgPSAwOyBpIDwgMjsgaSsrKSB7CiAJCQlfZ2V0dGltZShDTE9DS19NT05P VE9OSUMsICZ0c3QsIGkpOwotCQkJaWYgKGFicyh0c3QudHZfc2VjIC0gbm93LnR2X3NlYykg PiA1KQorCQkJaWYgKGxhYnModHN0LnR2X3NlYyAtIG5vdy50dl9zZWMpID4gNSkKIAkJCQly ZXR1cm4gcHJfZmFpbCgiJWxkICVsZFxuIiwgbm93LnR2X3NlYywgdHN0LnR2X3NlYyk7CiAJ CX0KIAkJcmV0dXJuIDA7CkBAIC01MCw3ICs1MCw3IEBAIGludCBtYWluKGludCBhcmdjLCBj aGFyICphcmd2W10pCiAKIAlmb3IgKGkgPSAwOyBpIDwgMjsgaSsrKSB7CiAJCV9nZXR0aW1l KENMT0NLX01PTk9UT05JQywgJnRzdCwgaSk7Ci0JCWlmIChhYnModHN0LnR2X3NlYyAtIG5v dy50dl9zZWMpID4gNSkKKwkJaWYgKGxhYnModHN0LnR2X3NlYyAtIG5vdy50dl9zZWMpID4g NSkKIAkJCXJldHVybiBwcl9mYWlsKCIlbGQgJWxkXG4iLAogCQkJCQlub3cudHZfc2VjLCB0 c3QudHZfc2VjKTsKIAl9CkBAIC03MCw3ICs3MCw3IEBAIGludCBtYWluKGludCBhcmdjLCBj aGFyICphcmd2W10pCiAJCS8qIENoZWNrIHRoYXQgYSBjaGlsZCBwcm9jZXNzIGlzIGluIHRo ZSBuZXcgdGltZW5zLiAqLwogCQlmb3IgKGkgPSAwOyBpIDwgMjsgaSsrKSB7CiAJCQlfZ2V0 dGltZShDTE9DS19NT05PVE9OSUMsICZ0c3QsIGkpOwotCQkJaWYgKGFicyh0c3QudHZfc2Vj IC0gbm93LnR2X3NlYyAtIE9GRlNFVCkgPiA1KQorCQkJaWYgKGxhYnModHN0LnR2X3NlYyAt IG5vdy50dl9zZWMgLSBPRkZTRVQpID4gNSkKIAkJCQlyZXR1cm4gcHJfZmFpbCgiJWxkICVs ZFxuIiwKIAkJCQkJCW5vdy50dl9zZWMgKyBPRkZTRVQsIHRzdC50dl9zZWMpOwogCQl9CmRp ZmYgLS1naXQgYS90b29scy90ZXN0aW5nL3NlbGZ0ZXN0cy90aW1lbnMvdGltZXIuYyBiL3Rv b2xzL3Rlc3Rpbmcvc2VsZnRlc3RzL3RpbWVucy90aW1lci5jCmluZGV4IDVlN2YwMDUxYmQ3 Yi4uNWI5MzlmNTlkZmE0IDEwMDY0NAotLS0gYS90b29scy90ZXN0aW5nL3NlbGZ0ZXN0cy90 aW1lbnMvdGltZXIuYworKysgYi90b29scy90ZXN0aW5nL3NlbGZ0ZXN0cy90aW1lbnMvdGlt ZXIuYwpAQCAtNTYsNyArNTYsNyBAQCBpbnQgcnVuX3Rlc3QoaW50IGNsb2NraWQsIHN0cnVj dCB0aW1lc3BlYyBub3cpCiAJCQlyZXR1cm4gcHJfcGVycm9yKCJ0aW1lcmZkX2dldHRpbWUi KTsKIAogCQllbGFwc2VkID0gbmV3X3ZhbHVlLml0X3ZhbHVlLnR2X3NlYzsKLQkJaWYgKGFi cyhlbGFwc2VkIC0gMzYwMCkgPiA2MCkgeworCQlpZiAobGxhYnMoZWxhcHNlZCAtIDM2MDAp ID4gNjApIHsKIAkJCWtzZnRfdGVzdF9yZXN1bHRfZmFpbCgiY2xvY2tpZDogJWQgZWxhcHNl ZDogJWxsZFxuIiwKIAkJCQkJICAgICAgY2xvY2tpZCwgZWxhcHNlZCk7CiAJCQlyZXR1cm4g MTsKZGlmZiAtLWdpdCBhL3Rvb2xzL3Rlc3Rpbmcvc2VsZnRlc3RzL3RpbWVucy90aW1lcmZk LmMgYi90b29scy90ZXN0aW5nL3NlbGZ0ZXN0cy90aW1lbnMvdGltZXJmZC5jCmluZGV4IDll ZGQ0M2Q2YjJjMS4uYTQxOTZiYmQ2ZTMzIDEwMDY0NAotLS0gYS90b29scy90ZXN0aW5nL3Nl bGZ0ZXN0cy90aW1lbnMvdGltZXJmZC5jCisrKyBiL3Rvb2xzL3Rlc3Rpbmcvc2VsZnRlc3Rz L3RpbWVucy90aW1lcmZkLmMKQEAgLTYxLDcgKzYxLDcgQEAgaW50IHJ1bl90ZXN0KGludCBj bG9ja2lkLCBzdHJ1Y3QgdGltZXNwZWMgbm93KQogCQkJcmV0dXJuIHByX3BlcnJvcigidGlt ZXJmZF9nZXR0aW1lKCVkKSIsIGNsb2NraWQpOwogCiAJCWVsYXBzZWQgPSBuZXdfdmFsdWUu aXRfdmFsdWUudHZfc2VjOwotCQlpZiAoYWJzKGVsYXBzZWQgLSAzNjAwKSA+IDYwKSB7CisJ CWlmIChsbGFicyhlbGFwc2VkIC0gMzYwMCkgPiA2MCkgewogCQkJa3NmdF90ZXN0X3Jlc3Vs dF9mYWlsKCJjbG9ja2lkOiAlZCBlbGFwc2VkOiAlbGxkXG4iLAogCQkJCQkgICAgICBjbG9j a2lkLCBlbGFwc2VkKTsKIAkJCXJldHVybiAxOwpkaWZmIC0tZ2l0IGEvdG9vbHMvdGVzdGlu Zy9zZWxmdGVzdHMvdGltZW5zL3Zmb3JrX2V4ZWMuYyBiL3Rvb2xzL3Rlc3Rpbmcvc2VsZnRl c3RzL3RpbWVucy92Zm9ya19leGVjLmMKaW5kZXggYmViNzYxNDk0MWZiLi41Yjg5MDdiZjQ1 MWQgMTAwNjQ0Ci0tLSBhL3Rvb2xzL3Rlc3Rpbmcvc2VsZnRlc3RzL3RpbWVucy92Zm9ya19l eGVjLmMKKysrIGIvdG9vbHMvdGVzdGluZy9zZWxmdGVzdHMvdGltZW5zL3Zmb3JrX2V4ZWMu YwpAQCAtMzIsNyArMzIsNyBAQCBzdGF0aWMgdm9pZCAqdGNoZWNrKHZvaWQgKl9hcmdzKQog CiAJZm9yIChpID0gMDsgaSA8IDI7IGkrKykgewogCQlfZ2V0dGltZShDTE9DS19NT05PVE9O SUMsICZ0c3QsIGkpOwotCQlpZiAoYWJzKHRzdC50dl9zZWMgLSBub3ctPnR2X3NlYykgPiA1 KSB7CisJCWlmIChsYWJzKHRzdC50dl9zZWMgLSBub3ctPnR2X3NlYykgPiA1KSB7CiAJCQlw cl9mYWlsKCIlczogaW4tdGhyZWFkOiB1bmV4cGVjdGVkIHZhbHVlOiAlbGQgKCVsZClcbiIs CiAJCQkJYXJncy0+dHN0X25hbWUsIHRzdC50dl9zZWMsIG5vdy0+dHZfc2VjKTsKIAkJCXJl dHVybiAodm9pZCAqKTFVTDsKQEAgLTY0LDcgKzY0LDcgQEAgc3RhdGljIGludCBjaGVjayhj aGFyICp0c3RfbmFtZSwgc3RydWN0IHRpbWVzcGVjICpub3cpCiAKIAlmb3IgKGkgPSAwOyBp IDwgMjsgaSsrKSB7CiAJCV9nZXR0aW1lKENMT0NLX01PTk9UT05JQywgJnRzdCwgaSk7Ci0J CWlmIChhYnModHN0LnR2X3NlYyAtIG5vdy0+dHZfc2VjKSA+IDUpCisJCWlmIChsYWJzKHRz dC50dl9zZWMgLSBub3ctPnR2X3NlYykgPiA1KQogCQkJcmV0dXJuIHByX2ZhaWwoIiVzOiB1 bmV4cGVjdGVkIHZhbHVlOiAlbGQgKCVsZClcbiIsCiAJCQkJCXRzdF9uYW1lLCB0c3QudHZf c2VjLCBub3ctPnR2X3NlYyk7CiAJfQpkaWZmIC0tZ2l0IGEvdG9vbHMvdGVzdGluZy9zZWxm dGVzdHMvdkRTTy9NYWtlZmlsZSBiL3Rvb2xzL3Rlc3Rpbmcvc2VsZnRlc3RzL3ZEU08vTWFr ZWZpbGUKaW5kZXggZDUzYTRkODAwOGY5Li45OGQ4YmEyYWZhMDAgMTAwNjQ0Ci0tLSBhL3Rv b2xzL3Rlc3Rpbmcvc2VsZnRlc3RzL3ZEU08vTWFrZWZpbGUKKysrIGIvdG9vbHMvdGVzdGlu Zy9zZWxmdGVzdHMvdkRTTy9NYWtlZmlsZQpAQCAtMSwzNSArMSwzMCBAQAogIyBTUERYLUxp Y2Vuc2UtSWRlbnRpZmllcjogR1BMLTIuMAotaW5jbHVkZSAuLi9saWIubWsKLQogdW5hbWVf TSA6PSAkKHNoZWxsIHVuYW1lIC1tIDI+L2Rldi9udWxsIHx8IGVjaG8gbm90KQogQVJDSCA/ PSAkKHNoZWxsIGVjaG8gJCh1bmFtZV9NKSB8IHNlZCAtZSBzL2kuODYveDg2LyAtZSBzL3g4 Nl82NC94ODYvKQogCi1URVNUX0dFTl9QUk9HUyA6PSAkKE9VVFBVVCkvdmRzb190ZXN0X2dl dHRpbWVvZmRheSAkKE9VVFBVVCkvdmRzb190ZXN0X2dldGNwdQotVEVTVF9HRU5fUFJPR1Mg Kz0gJChPVVRQVVQpL3Zkc29fdGVzdF9hYmkKLVRFU1RfR0VOX1BST0dTICs9ICQoT1VUUFVU KS92ZHNvX3Rlc3RfY2xvY2tfZ2V0cmVzCitURVNUX0dFTl9QUk9HUyA6PSB2ZHNvX3Rlc3Rf Z2V0dGltZW9mZGF5CitURVNUX0dFTl9QUk9HUyArPSB2ZHNvX3Rlc3RfZ2V0Y3B1CitURVNU X0dFTl9QUk9HUyArPSB2ZHNvX3Rlc3RfYWJpCitURVNUX0dFTl9QUk9HUyArPSB2ZHNvX3Rl c3RfY2xvY2tfZ2V0cmVzCiBpZmVxICgkKEFSQ0gpLCQoZmlsdGVyICQoQVJDSCkseDg2IHg4 Nl82NCkpCi1URVNUX0dFTl9QUk9HUyArPSAkKE9VVFBVVCkvdmRzb19zdGFuZGFsb25lX3Rl c3RfeDg2CitURVNUX0dFTl9QUk9HUyArPSB2ZHNvX3N0YW5kYWxvbmVfdGVzdF94ODYKIGVu ZGlmCi1URVNUX0dFTl9QUk9HUyArPSAkKE9VVFBVVCkvdmRzb190ZXN0X2NvcnJlY3RuZXNz CitURVNUX0dFTl9QUk9HUyArPSB2ZHNvX3Rlc3RfY29ycmVjdG5lc3MKIAogQ0ZMQUdTIDo9 IC1zdGQ9Z251OTkKLUNGTEFHU192ZHNvX3N0YW5kYWxvbmVfdGVzdF94ODYgOj0gLW5vc3Rk bGliIC1mbm8tYXN5bmNocm9ub3VzLXVud2luZC10YWJsZXMgLWZuby1zdGFjay1wcm90ZWN0 b3IKLUxERkxBR1NfdmRzb190ZXN0X2NvcnJlY3RuZXNzIDo9IC1sZGwKKwogaWZlcSAoJChD T05GSUdfWDg2XzMyKSx5KQogTERMSUJTICs9IC1sZ2NjX3MKIGVuZGlmCiAKLWFsbDogJChU RVNUX0dFTl9QUk9HUykKK2luY2x1ZGUgLi4vbGliLm1rCiAkKE9VVFBVVCkvdmRzb190ZXN0 X2dldHRpbWVvZmRheTogcGFyc2VfdmRzby5jIHZkc29fdGVzdF9nZXR0aW1lb2ZkYXkuYwog JChPVVRQVVQpL3Zkc29fdGVzdF9nZXRjcHU6IHBhcnNlX3Zkc28uYyB2ZHNvX3Rlc3RfZ2V0 Y3B1LmMKICQoT1VUUFVUKS92ZHNvX3Rlc3RfYWJpOiBwYXJzZV92ZHNvLmMgdmRzb190ZXN0 X2FiaS5jCiAkKE9VVFBVVCkvdmRzb190ZXN0X2Nsb2NrX2dldHJlczogdmRzb190ZXN0X2Ns b2NrX2dldHJlcy5jCisKICQoT1VUUFVUKS92ZHNvX3N0YW5kYWxvbmVfdGVzdF94ODY6IHZk c29fc3RhbmRhbG9uZV90ZXN0X3g4Ni5jIHBhcnNlX3Zkc28uYwotCSQoQ0MpICQoQ0ZMQUdT KSAkKENGTEFHU192ZHNvX3N0YW5kYWxvbmVfdGVzdF94ODYpIFwKLQkJdmRzb19zdGFuZGFs b25lX3Rlc3RfeDg2LmMgcGFyc2VfdmRzby5jIFwKLQkJLW8gJEAKKyQoT1VUUFVUKS92ZHNv X3N0YW5kYWxvbmVfdGVzdF94ODY6IENGTEFHUyArPS1ub3N0ZGxpYiAtZm5vLWFzeW5jaHJv bm91cy11bndpbmQtdGFibGVzIC1mbm8tc3RhY2stcHJvdGVjdG9yCisKICQoT1VUUFVUKS92 ZHNvX3Rlc3RfY29ycmVjdG5lc3M6IHZkc29fdGVzdF9jb3JyZWN0bmVzcy5jCi0JJChDQykg JChDRkxBR1MpIFwKLQkJdmRzb190ZXN0X2NvcnJlY3RuZXNzLmMgXAotCQktbyAkQCBcCi0J CSQoTERGTEFHU192ZHNvX3Rlc3RfY29ycmVjdG5lc3MpCiskKE9VVFBVVCkvdmRzb190ZXN0 X2NvcnJlY3RuZXNzOiBMREZMQUdTICs9IC1sZGwKZGlmZiAtLWdpdCBhL3Rvb2xzL3Rlc3Rp bmcvc2VsZnRlc3RzL3ZEU08vcGFyc2VfdmRzby5jIGIvdG9vbHMvdGVzdGluZy9zZWxmdGVz dHMvdkRTTy9wYXJzZV92ZHNvLmMKaW5kZXggNDEzZjc1NjIwYTM1Li40YWU0MTczNzJlOWUg MTAwNjQ0Ci0tLSBhL3Rvb2xzL3Rlc3Rpbmcvc2VsZnRlc3RzL3ZEU08vcGFyc2VfdmRzby5j CisrKyBiL3Rvb2xzL3Rlc3Rpbmcvc2VsZnRlc3RzL3ZEU08vcGFyc2VfdmRzby5jCkBAIC01 NSwxNCArNTUsMjAgQEAgc3RhdGljIHN0cnVjdCB2ZHNvX2luZm8KIAlFTEYoVmVyZGVmKSAq dmVyZGVmOwogfSB2ZHNvX2luZm87CiAKLS8qIFN0cmFpZ2h0IGZyb20gdGhlIEVMRiBzcGVj aWZpY2F0aW9uLiAqLwotc3RhdGljIHVuc2lnbmVkIGxvbmcgZWxmX2hhc2goY29uc3QgdW5z aWduZWQgY2hhciAqbmFtZSkKKy8qCisgKiBTdHJhaWdodCBmcm9tIHRoZSBFTEYgc3BlY2lm aWNhdGlvbi4uLmFuZCB0aGVuIHR3ZWFrZWQgc2xpZ2h0bHksIGluIG9yZGVyIHRvCisgKiBh dm9pZCBhIGZldyBjbGFuZyB3YXJuaW5ncy4KKyAqLworc3RhdGljIHVuc2lnbmVkIGxvbmcg ZWxmX2hhc2goY29uc3QgY2hhciAqbmFtZSkKIHsKIAl1bnNpZ25lZCBsb25nIGggPSAwLCBn OwotCXdoaWxlICgqbmFtZSkKKwljb25zdCB1bnNpZ25lZCBjaGFyICp1Y2hfbmFtZSA9IChj b25zdCB1bnNpZ25lZCBjaGFyICopbmFtZTsKKworCXdoaWxlICgqdWNoX25hbWUpCiAJewot CQloID0gKGggPDwgNCkgKyAqbmFtZSsrOwotCQlpZiAoZyA9IGggJiAweGYwMDAwMDAwKQor CQloID0gKGggPDwgNCkgKyAqdWNoX25hbWUrKzsKKwkJZyA9IGggJiAweGYwMDAwMDAwOwor CQlpZiAoZykKIAkJCWggXj0gZyA+PiAyNDsKIAkJaCAmPSB+ZzsKIAl9CmRpZmYgLS1naXQg YS90b29scy90ZXN0aW5nL3NlbGZ0ZXN0cy92RFNPL3Zkc29fc3RhbmRhbG9uZV90ZXN0X3g4 Ni5jIGIvdG9vbHMvdGVzdGluZy9zZWxmdGVzdHMvdkRTTy92ZHNvX3N0YW5kYWxvbmVfdGVz dF94ODYuYwppbmRleCA4YTQ0ZmY5NzNlZTEuLjI3ZjZmZGYxMTk2OSAxMDA2NDQKLS0tIGEv dG9vbHMvdGVzdGluZy9zZWxmdGVzdHMvdkRTTy92ZHNvX3N0YW5kYWxvbmVfdGVzdF94ODYu YworKysgYi90b29scy90ZXN0aW5nL3NlbGZ0ZXN0cy92RFNPL3Zkc29fc3RhbmRhbG9uZV90 ZXN0X3g4Ni5jCkBAIC0xOCw3ICsxOCw3IEBACiAKICNpbmNsdWRlICJwYXJzZV92ZHNvLmgi CiAKLS8qIFdlIG5lZWQgYSBsaWJjIGZ1bmN0aW9ucy4uLiAqLworLyogV2UgbmVlZCBzb21l IGxpYmMgZnVuY3Rpb25zLi4uICovCiBpbnQgc3RyY21wKGNvbnN0IGNoYXIgKmEsIGNvbnN0 IGNoYXIgKmIpCiB7CiAJLyogVGhpcyBpbXBsZW1lbnRhdGlvbiBpcyBidWdneTogaXQgbmV2 ZXIgcmV0dXJucyAtMS4gKi8KQEAgLTM0LDYgKzM0LDIwIEBAIGludCBzdHJjbXAoY29uc3Qg Y2hhciAqYSwgY29uc3QgY2hhciAqYikKIAlyZXR1cm4gMDsKIH0KIAorLyoKKyAqIFRoZSBj bGFuZyBidWlsZCBuZWVkcyB0aGlzLCBhbHRob3VnaCBnY2MgZG9lcyBub3QuCisgKiBTdG9s ZW4gZnJvbSBsaWIvc3RyaW5nLmMuCisgKi8KK3ZvaWQgKm1lbWNweSh2b2lkICpkZXN0LCBj b25zdCB2b2lkICpzcmMsIHNpemVfdCBjb3VudCkKK3sKKwljaGFyICp0bXAgPSBkZXN0Owor CWNvbnN0IGNoYXIgKnMgPSBzcmM7CisKKwl3aGlsZSAoY291bnQtLSkKKwkJKnRtcCsrID0g KnMrKzsKKwlyZXR1cm4gZGVzdDsKK30KKwogLyogLi4uYW5kIHR3byBzeXNjYWxscy4gIFRo aXMgaXMgeDg2LXNwZWNpZmljLiAqLwogc3RhdGljIGlubGluZSBsb25nIHg4Nl9zeXNjYWxs Myhsb25nIG5yLCBsb25nIGEwLCBsb25nIGExLCBsb25nIGEyKQogewpAQCAtNzAsNyArODQs NyBAQCB2b2lkIHRvX2Jhc2UxMChjaGFyICpsYXN0ZGlnLCB0aW1lX3QgbikKIAl9CiB9CiAK LV9fYXR0cmlidXRlX18oKGV4dGVybmFsbHlfdmlzaWJsZSkpIHZvaWQgY19tYWluKHZvaWQg KipzdGFjaykKK3ZvaWQgY19tYWluKHZvaWQgKipzdGFjaykKIHsKIAkvKiBQYXJzZSB0aGUg c3RhY2sgKi8KIAlsb25nIGFyZ2MgPSAobG9uZykqc3RhY2s7Cg== --------------zvEHuaPS38NLDGr1NkzGpYeN-- . Date: Tue, 9 Jul 2024 14:21:34 +0300 From: Georgi Djakov To: gregkh@linuxfoundation.org Cc: linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org, djakov@kernel.org Subject: [GIT PULL] interconnect changes for 6.11 Hello Greg, This is the pull request with interconnect changes for the v6.11-rc1 merge window. It contains some new drivers and bugfixes. As always, the summary is in the signed tag. The patches have been in linux-next for a while. There are no reported issues currently. Please pull into char-misc-next when possible. Thanks, Georgi The following changes since commit 1613e604df0cd359cf2a7fbd9be7a0bcfacfabd0: Linux 6.10-rc1 (2024-05-26 15:20:12 -0700) are available in the Git repository at: git://git.kernel.org/pub/scm/linux/kernel/git/djakov/icc.git tags/icc-6.11-rc1 for you to fetch changes up to 226e58b20975000960cb40b7488f55f173007489: Merge branch 'icc-rpmh-qos' into icc-next (2024-07-04 22:45:20 +0300) ---------------------------------------------------------------- interconnect changes for 6.11 This pull request contains the interconnect changes for the 6.11-rc1 merge window. It contains just driver changes with the following highlights: Driver changes: - New driver for MediaTek MT8183/8195 platforms - New driver for MSM8953 platforms - New QoS support for RPMh-based platforms with SC7280 being the first one to benefit from it. - Fix incorrect master-id value in qcm2290 driver - Add missing MODULE_DESCRIPTION in a few drivers Signed-off-by: Georgi Djakov ---------------------------------------------------------------- AngeloGioacchino Del Regno (2): dt-bindings: interconnect: Add MediaTek EMI Interconnect bindings interconnect: mediatek: Add MediaTek MT8183/8195 EMI Interconnect driver Georgi Djakov (4): Merge branch 'icc-mtk' into icc-next Merge branch 'icc-fixes' into icc-next Merge branch 'icc-msm8953' into icc-next Merge branch 'icc-rpmh-qos' into icc-next Jeff Johnson (2): interconnect: imx: add missing MODULE_DESCRIPTION() macros interconnect: qcom: add missing MODULE_DESCRIPTION() macros Jiapeng Chong (1): interconnect: mediatek: remove unneeded semicolon Konrad Dybcio (1): interconnect: qcom: qcm2290: Fix mas_snoc_bimc RPM master ID Odelu Kukatla (4): dt-bindings: interconnect: add clock property to enable QOS on SC7280 interconnect: qcom: icc-rpmh: Add QoS configuration support interconnect: qcom: sc7280: enable QoS configuration interconnect: qcom: Fix DT backwards compatibility for QoS Vladimir Lypak (2): dt-bindings: interconnect: qcom: Add Qualcomm MSM8953 NoC interconnect: qcom: Add MSM8953 driver .../devicetree/bindings/interconnect/mediatek,mt8183-emi.yaml | 51 + .../devicetree/bindings/interconnect/qcom,msm8953.yaml | 101 + .../devicetree/bindings/interconnect/qcom,sc7280-rpmh.yaml | 53 + drivers/interconnect/Kconfig | 1 + drivers/interconnect/Makefile | 1 + drivers/interconnect/imx/imx.c | 1 + drivers/interconnect/imx/imx8mm.c | 1 + drivers/interconnect/imx/imx8mn.c | 1 + drivers/interconnect/imx/imx8mp.c | 1 + drivers/interconnect/imx/imx8mq.c | 1 + drivers/interconnect/mediatek/Kconfig | 29 + drivers/interconnect/mediatek/Makefile | 5 + drivers/interconnect/mediatek/icc-emi.c | 153 + drivers/interconnect/mediatek/icc-emi.h | 40 + drivers/interconnect/mediatek/mt8183.c | 143 + drivers/interconnect/mediatek/mt8195.c | 339 ++ drivers/interconnect/qcom/Kconfig | 9 + drivers/interconnect/qcom/Makefile | 2 + drivers/interconnect/qcom/icc-common.c | 1 + drivers/interconnect/qcom/icc-rpmh.c | 94 + drivers/interconnect/qcom/icc-rpmh.h | 36 + drivers/interconnect/qcom/msm8953.c | 1321 ++++++++ drivers/interconnect/qcom/qcm2290.c | 2 +- drivers/interconnect/qcom/sc7280.c | 276 ++ include/dt-bindings/interconnect/mediatek,mt8183.h | 23 + include/dt-bindings/interconnect/mediatek,mt8195.h | 44 + include/dt-bindings/interconnect/qcom,msm8953.h | 93 + 27 files changed, 2821 insertions(+), 1 deletion(-) create mode 100644 Documentation/devicetree/bindings/interconnect/mediatek,mt8183-emi.yaml create mode 100644 Documentation/devicetree/bindings/interconnect/qcom,msm8953.yaml create mode 100644 drivers/interconnect/mediatek/Kconfig create mode 100644 drivers/interconnect/mediatek/Makefile create mode 100644 drivers/interconnect/mediatek/icc-emi.c create mode 100644 drivers/interconnect/mediatek/icc-emi.h create mode 100644 drivers/interconnect/mediatek/mt8183.c create mode 100644 drivers/interconnect/mediatek/mt8195.c create mode 100644 drivers/interconnect/qcom/msm8953.c create mode 100644 include/dt-bindings/interconnect/mediatek,mt8183.h create mode 100644 include/dt-bindings/interconnect/mediatek,mt8195.h create mode 100644 include/dt-bindings/interconnect/qcom,msm8953.h . Date: Tue, 9 Jul 2024 09:57:59 -0500 From: Steve French To: Linus Torvalds Cc: CIFS , LKML , Namjae Jeon Subject: [GIT PULL] ksmbd server fixes Please pull the following changes since commit 22a40d14b572deb80c0648557f4bd502d7e83826: Linux 6.10-rc6 (2024-06-30 14:40:44 -0700) are available in the Git repository at: git://git.samba.org/ksmbd.git tags/6.10-rc6-smb3-server-fixes for you to fetch changes up to e2e33caa5dc2eae7bddf88b22ce11ec3d760e5cd: ksmbd: discard write access to the directory open (2024-07-05 09:56:13 -0500) ---------------------------------------------------------------- Two ksmbd server fixes - fix access flags to address fuse incompatibility - fix device type returned by get filesystem info ---------------------------------------------------------------- Hobin Woo (1): ksmbd: discard write access to the directory open Namjae Jeon (1): ksmbd: return FILE_DEVICE_DISK instead of super magic fs/smb/common/smb2pdu.h | 34 ++++++++++++++++++++++++++++++++++ fs/smb/server/smb2pdu.c | 22 ++++++++++++++++++---- 2 files changed, 52 insertions(+), 4 deletions(-) -- Thanks, Steve . Date: Tue, 9 Jul 2024 16:36:53 -0600 From: Rob Herring To: Linus Torvalds Cc: Saravana Kannan , Krzysztof Kozlowski , Conor Dooley , linux-kernel@vger.kernel.org, devicetree@vger.kernel.org Subject: [GIT PULL] Devicetree fixes for v6.10, part 2 Hi Linus, Please pull this 1 fix. Rob The following changes since commit e7985f43609c782132f8f5794ee6cc4cdb66ca75: of: property: Fix fw_devlink handling of interrupt-map (2024-05-30 19:43:47 -0500) are available in the Git repository at: ssh://git@gitolite.kernel.org/pub/scm/linux/kernel/git/robh/linux.git tags/devicetree-fixes-for-6.10-2 for you to fetch changes up to 2cf6b7d15a28640117bf9f75dc050892cf78a6e8: of/irq: Disable "interrupt-map" parsing for PASEMI Nemo (2024-07-08 15:42:20 -0600) ---------------------------------------------------------------- Devicetree fix for 6.10, part 2: - One fix for PASemi Nemo board interrupts ---------------------------------------------------------------- Marc Zyngier (1): of/irq: Disable "interrupt-map" parsing for PASEMI Nemo drivers/of/irq.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) . Date: Wed, 10 Jul 2024 16:46:30 +0800 From: Huacai Chen To: Paolo Bonzini , Huacai Chen , Tianrui Zhao , Bibo Mao Cc: kvm@vger.kernel.org, loongarch@lists.linux.dev, linux-kernel@vger.kernel.org, Xuerui Wang , Jiaxun Yang , Huacai Chen Subject: [GIT PULL] LoongArch KVM changes for v6.11 The following changes since commit 256abd8e550ce977b728be79a74e1729438b4948: Linux 6.10-rc7 (2024-07-07 14:23:46 -0700) are available in the Git repository at: git://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson.git tags/loongarch-kvm-6.11 for you to fetch changes up to b3403f8d3c3fd8398bb5f23fe4f69faa738f1399: perf kvm: Add kvm-stat for loongarch64 (2024-07-09 16:25:51 +0800) ---------------------------------------------------------------- LoongArch KVM changes for v6.11 1. Add ParaVirt steal time support. 2. Add some VM migration enhancement. 3. Add perf kvm-stat support for loongarch. ---------------------------------------------------------------- Bibo Mao (10): LoongArch: KVM: Sync pending interrupt when getting ESTAT from user mode LoongArch: KVM: Delay secondary mmu tlb flush until guest entry LoongArch: KVM: Select huge page only if secondary mmu supports it LoongArch: KVM: Discard dirty page tracking on readonly memslot LoongArch: KVM: Add memory barrier before update pmd entry LoongArch: KVM: Add dirty bitmap initially all set support LoongArch: KVM: Mark page accessed and dirty with page ref added LoongArch: KVM: Add PV steal time support in host side LoongArch: KVM: Add PV steal time support in guest side perf kvm: Add kvm-stat for loongarch64 Jia Qingtong (1): LoongArch: KVM: always make pte young in page map's fast path Documentation/admin-guide/kernel-parameters.txt | 6 +- arch/loongarch/Kconfig | 11 ++ arch/loongarch/include/asm/kvm_host.h | 13 ++ arch/loongarch/include/asm/kvm_para.h | 11 ++ arch/loongarch/include/asm/kvm_vcpu.h | 5 + arch/loongarch/include/asm/loongarch.h | 1 + arch/loongarch/include/asm/paravirt.h | 5 + arch/loongarch/include/uapi/asm/kvm.h | 4 + arch/loongarch/kernel/paravirt.c | 145 ++++++++++++++++++++++ arch/loongarch/kernel/time.c | 2 + arch/loongarch/kvm/Kconfig | 1 + arch/loongarch/kvm/exit.c | 38 +++++- arch/loongarch/kvm/main.c | 1 + arch/loongarch/kvm/mmu.c | 72 +++++++---- arch/loongarch/kvm/tlb.c | 5 +- arch/loongarch/kvm/vcpu.c | 154 +++++++++++++++++++++++- tools/perf/arch/loongarch/Makefile | 1 + tools/perf/arch/loongarch/util/Build | 2 + tools/perf/arch/loongarch/util/header.c | 96 +++++++++++++++ tools/perf/arch/loongarch/util/kvm-stat.c | 139 +++++++++++++++++++++ 20 files changed, 680 insertions(+), 32 deletions(-) create mode 100644 tools/perf/arch/loongarch/util/header.c create mode 100644 tools/perf/arch/loongarch/util/kvm-stat.c . Date: Wed, 10 Jul 2024 18:49:23 +0800 From: Huacai Chen To: Paolo Bonzini , Huacai Chen , Tianrui Zhao , Bibo Mao Cc: kvm@vger.kernel.org, loongarch@lists.linux.dev, linux-kernel@vger.kernel.org, Xuerui Wang , Jiaxun Yang , Huacai Chen Subject: [GIT PULL] LoongArch KVM changes for v6.11 The following changes since commit 256abd8e550ce977b728be79a74e1729438b4948: Linux 6.10-rc7 (2024-07-07 14:23:46 -0700) are available in the Git repository at: git://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson.git tags/loongarch-kvm-6.11 for you to fetch changes up to 492ac37fa38faf520b5beae44c930063265ee183: perf kvm: Add kvm-stat for loongarch64 (2024-07-10 16:50:27 +0800) ---------------------------------------------------------------- LoongArch KVM changes for v6.11 1. Add ParaVirt steal time support. 2. Add some VM migration enhancement. 3. Add perf kvm-stat support for loongarch. ---------------------------------------------------------------- Bibo Mao (10): LoongArch: KVM: Sync pending interrupt when getting ESTAT from user mode LoongArch: KVM: Delay secondary mmu tlb flush until guest entry LoongArch: KVM: Select huge page only if secondary mmu supports it LoongArch: KVM: Discard dirty page tracking on readonly memslot LoongArch: KVM: Add memory barrier before update pmd entry LoongArch: KVM: Add dirty bitmap initially all set support LoongArch: KVM: Mark page accessed and dirty with page ref added LoongArch: KVM: Add PV steal time support in host side LoongArch: KVM: Add PV steal time support in guest side perf kvm: Add kvm-stat for loongarch64 Jia Qingtong (1): LoongArch: KVM: always make pte young in page map's fast path Documentation/admin-guide/kernel-parameters.txt | 6 +- arch/loongarch/Kconfig | 11 ++ arch/loongarch/include/asm/kvm_host.h | 13 ++ arch/loongarch/include/asm/kvm_para.h | 11 ++ arch/loongarch/include/asm/kvm_vcpu.h | 5 + arch/loongarch/include/asm/loongarch.h | 1 + arch/loongarch/include/asm/paravirt.h | 5 + arch/loongarch/include/uapi/asm/kvm.h | 4 + arch/loongarch/kernel/paravirt.c | 145 ++++++++++++++++++++++ arch/loongarch/kernel/time.c | 2 + arch/loongarch/kvm/Kconfig | 1 + arch/loongarch/kvm/exit.c | 38 +++++- arch/loongarch/kvm/main.c | 1 + arch/loongarch/kvm/mmu.c | 72 +++++++---- arch/loongarch/kvm/tlb.c | 5 +- arch/loongarch/kvm/vcpu.c | 154 +++++++++++++++++++++++- tools/perf/arch/loongarch/Makefile | 1 + tools/perf/arch/loongarch/util/Build | 2 + tools/perf/arch/loongarch/util/header.c | 96 +++++++++++++++ tools/perf/arch/loongarch/util/kvm-stat.c | 139 +++++++++++++++++++++ 20 files changed, 680 insertions(+), 32 deletions(-) create mode 100644 tools/perf/arch/loongarch/util/header.c create mode 100644 tools/perf/arch/loongarch/util/kvm-stat.c . Date: Wed, 10 Jul 2024 12:57:16 +0200 From: "Rafael J. Wysocki" To: Linus Torvalds Cc: Linux PM , Linux Kernel Mailing List , Daniel Lezcano Subject: [GIT PULL] Thermal control fixes for v6.10-rc8 Hi Linus, Please pull from the tag git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git \ thermal-6.10-rc8 with top-most commit 94eacc1c583dd2ba51a2158fb13285f5dc42714b thermal: core: Fix list sorting in __thermal_zone_device_update() on top of commit 22a40d14b572deb80c0648557f4bd502d7e83826 Linux 6.10-rc6 to receive thermal control fixes for final 6.10. These fix a possible NULL pointer dereference in a thermal governor, fix up the handling of thermal zones enabled before their temperature can be determined and fix list sorting during thermal zone temperature updates. Specifics: - Prevent the Power Allocator thermal governor from dereferencing a NULL pointer if it is bound to a tripless thermal zone (N=C3=ADcolas Prado). - Prevent thermal zones enabled too early from staying effectively dormant forever because their temperature cannot be determined initially (Rafael Wysocki). - Fix list sorting during thermal zone temperature updates to ensure the proper ordering of trip crossing notifications (Rafael Wysocki). Thanks! --------------- N=C3=ADcolas F. R. A. Prado (1): thermal: gov_power_allocator: Return early in manage if trip_max is N= ULL Rafael J. Wysocki (2): thermal: core: Call monitor_thermal_zone() if zone temperature is inv= alid thermal: core: Fix list sorting in __thermal_zone_device_update() --------------- drivers/thermal/gov_power_allocator.c | 3 +++ drivers/thermal/thermal_core.c | 15 ++++++++------- drivers/thermal/thermal_core.h | 6 ++++++ 3 files changed, 17 insertions(+), 7 deletions(-) . Date: Wed, 10 Jul 2024 12:58:50 +0200 From: "Rafael J. Wysocki" To: Linus Torvalds Cc: Linux PM , Linux Kernel Mailing List , ACPI Devel Maling List Subject: [GIT PULL] Power management fixes for v6.10-rc8 Hi Linus, Please pull from the tag git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git \ pm-6.10-rc8 with top-most commit d92467ad9d9ee63a700934b9228a989ef671d511 cpufreq: ACPI: Mark boost policy as enabled when setting boost on top of commit 22a40d14b572deb80c0648557f4bd502d7e83826 Linux 6.10-rc6 to receive power management fixes for final 6.10. These fix two issues related to boost frequencies handling, one in the cpufreq core and one in the ACPI cpufreq driver (Mario Limonciello). Thanks! --------------- Mario Limonciello (2): cpufreq: Allow drivers to advertise boost enabled cpufreq: ACPI: Mark boost policy as enabled when setting boost --------------- drivers/cpufreq/acpi-cpufreq.c | 4 +++- drivers/cpufreq/cpufreq.c | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) . Date: Wed, 10 Jul 2024 13:00:05 +0200 From: "Rafael J. Wysocki" To: Linus Torvalds Cc: ACPI Devel Maling List , Linux PM , Linux Kernel Mailing List Subject: [GIT PULL] ACPI fix for v6.10-rc8 Hi Linus, Please pull from the tag git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git \ acpi-6.10-rc8 with top-most commit 233323f9b9f828cd7cd5145ad811c1990b692542 ACPI: processor_idle: Fix invalid comparison with insertion sort for latency on top of commit 22a40d14b572deb80c0648557f4bd502d7e83826 Linux 6.10-rc6 to receive an ACPI fix for final 6.10. This fixes the sorting of _CST output data in the ACPI processor idle driver (Kuan-Wei Chiu). Thanks! --------------- Kuan-Wei Chiu (1): ACPI: processor_idle: Fix invalid comparison with insertion sort for latency --------------- drivers/acpi/processor_idle.c | 37 ++++++++++++++++--------------------- 1 file changed, 16 insertions(+), 21 deletions(-) . Date: Wed, 10 Jul 2024 16:22:55 +0200 From: Hans de Goede To: Linus Torvalds Cc: Linux Kernel Mailing List , platform-driver-x86@vger.kernel.org, =?UTF-8?Q?Ilpo_J=C3=A4rvinen?= , Armin Wolf Subject: [GIT PULL] platform-drivers-x86 for 6.10-6 Hi Linus, Obviously I should not have jinxed things by saying that my previous pull- request would be the last one for 6.10. So here is one more 6.10 fixes pull-request with a 1 liner fix for a dmi_system_id array in the toshiba_acpi driver not being terminated properly. Something which somehow has escaped detection since being introduced in 2022 until now. Regards, Hans The following changes since commit e527a6127223b644e0a27b44f4b16e16eb6c7f0a: platform/x86: toshiba_acpi: Fix quickstart quirk handling (2024-07-02 16:01:45 +0200) are available in the Git repository at: git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86.git tags/platform-drivers-x86-v6.10-6 for you to fetch changes up to b6e02c6b0377d4339986e07aeb696c632cd392aa: platform/x86: toshiba_acpi: Fix array out-of-bounds access (2024-07-10 16:12:12 +0200) ---------------------------------------------------------------- platform-drivers-x86 for v6.10-6 Highlights: - Fix missing dmi_system_id array termination in toshiba_acpi introduced in 2022 The following is an automated git shortlog grouped by driver: toshiba_acpi: - Fix array out-of-bounds access ---------------------------------------------------------------- Armin Wolf (1): platform/x86: toshiba_acpi: Fix array out-of-bounds access drivers/platform/x86/toshiba_acpi.c | 1 + 1 file changed, 1 insertion(+) . Date: Wed, 10 Jul 2024 18:12:05 +0200 From: Johan Hovold To: Greg Kroah-Hartman Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [GIT PULL] USB-serial fixes for 6.10-rc8 Hi Greg, I noticed that you still have some fixes queued for 6.10-rc8/final so figured I'd send this now even if this addresses a really old bug. I've verified that the issue is real and have tested the fix here myself. Feel free to queue it up for 6.11-rc1 if you prefer. Johan The following changes since commit 4298e400dbdbf259549d69c349e060652ad53611: USB: serial: option: add Telit generic core-dump composition (2024-06-27 12:04:33 +0200) are available in the Git repository at: https://git.kernel.org/pub/scm/linux/kernel/git/johan/usb-serial.git tags/usb-serial-6.10-rc8 for you to fetch changes up to c15a688e49987385baa8804bf65d570e362f8576: USB: serial: mos7840: fix crash on resume (2024-07-09 18:10:04 +0200) ---------------------------------------------------------------- USB-serial fixes for 6.10-rc8 Here's a fix for a long-standing issue in the mos7840 driver that can trigger a crash when resuming from system suspend. Included are also some new modem device ids. All have been in linux-next with no reported issues. ---------------------------------------------------------------- Dmitry Smirnov (1): USB: serial: mos7840: fix crash on resume Mank Wang (1): USB: serial: option: add Netprisma LCUK54 series modules Slark Xiao (1): USB: serial: option: add support for Foxconn T99W651 Vanillan Wang (1): USB: serial: option: add Rolling RW350-GL variants drivers/usb/serial/mos7840.c | 45 ++++++++++++++++++++++++++++++++++++++++++++ drivers/usb/serial/option.c | 28 +++++++++++++++++++++++++++ 2 files changed, 73 insertions(+) . Date: Wed, 10 Jul 2024 12:44:31 -0400 From: Kent Overstreet To: Linus Torvalds Cc: linux-bcachefs@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [GIT PULL] bcachefs fixes for 6.10-rc8 Hi Linus, fresh batch of bcachefs fixes for you. Cheers, Kent The following changes since commit 64cd7de998f393e73981e2aa4ee13e4e887f01ea: bcachefs: Fix kmalloc bug in __snapshot_t_mut (2024-06-25 20:51:14 -0400) are available in the Git repository at: https://evilpiepirate.org/git/bcachefs.git tags/bcachefs-2024-07-10 for you to fetch changes up to 7d7f71cd8763a296d02dff9514447aa3de199c47: bcachefs: Add missing bch2_trans_begin() (2024-07-10 09:53:39 -0400) ---------------------------------------------------------------- bcachefs fixes for 6.10-rc8 - Switch some asserts to WARN() - Fix a few "transaction not locked" asserts in the data read retry paths and backpointers gc - Fix a race that would cause the journal to get stuck on a flush commit - Add missing fsck checks for the fragmentation LRU - The usual assorted ssorted syzbot fixes ---------------------------------------------------------------- Kent Overstreet (21): bcachefs: Switch online_reserved shutdown assert to WARN() bcachefs: Delete old faulty bch2_trans_unlock() call bcachefs: Change bch2_fs_journal_stop() BUG_ON() to warning bcachefs: Fix shift greater than integer size bcachefs: Don't use the new_fs() bucket alloc path on an initialized fs bcachefs: Fix bch2_read_retry_nodecode() bcachefs: Fix loop restart in bch2_btree_transactions_read() bcachefs: Add missing printbuf_tabstops_reset() calls bcachefs: bch2_btree_write_buffer_maybe_flush() bcachefs: add check for missing fragmentation in check_alloc_to_lru_ref() bcachefs: Repair fragmentation_lru in alloc_write_key() bcachefs: io clock: run timer fns under clock lock bcachefs: Fix journal getting stuck on a flush commit closures: fix closure_sync + closure debugging bcachefs: Fix bch2_inode_insert() race path for tmpfiles bcachefs: Fix undefined behaviour in eytzinger1_first() bcachefs: Log mount failure error code bcachefs: bch2_data_update_to_text() bcachefs: Warn on attempting a move with no replicas bcachefs: Fix missing error check in journal_entry_btree_keys_validate() bcachefs: Add missing bch2_trans_begin() Youling Tang (1): bcachefs: Mark bch_inode_info as SLAB_ACCOUNT fs/bcachefs/alloc_background.c | 48 +++++++++++++-------------- fs/bcachefs/alloc_foreground.c | 2 ++ fs/bcachefs/backpointers.c | 70 +++++++++++++++------------------------- fs/bcachefs/bkey.c | 5 +-- fs/bcachefs/bkey.h | 7 ++++ fs/bcachefs/btree_gc.c | 24 +++++++------- fs/bcachefs/btree_write_buffer.c | 37 +++++++++++++++++++++ fs/bcachefs/btree_write_buffer.h | 3 ++ fs/bcachefs/clock.c | 7 ++-- fs/bcachefs/data_update.c | 44 +++++++++++++++++++++++++ fs/bcachefs/data_update.h | 5 +++ fs/bcachefs/debug.c | 12 +++---- fs/bcachefs/eytzinger.h | 6 ++-- fs/bcachefs/fs.c | 11 ++++++- fs/bcachefs/io_read.c | 4 ++- fs/bcachefs/journal.c | 18 ++++++----- fs/bcachefs/journal.h | 2 +- fs/bcachefs/journal_io.c | 12 ++++--- fs/bcachefs/lru.c | 39 ++++++++++++++++++++++ fs/bcachefs/lru.h | 3 ++ fs/bcachefs/move.c | 25 -------------- fs/bcachefs/sb-errors_format.h | 3 +- fs/bcachefs/super.c | 11 ++++--- include/linux/closure.h | 7 ++++ lib/closure.c | 3 ++ 25 files changed, 266 insertions(+), 142 deletions(-) . Date: Wed, 10 Jul 2024 11:27:51 -0600 From: Alex Williamson To: Linus Torvalds Cc: "Liu, Yi L" , "kvm@vger.kernel.org" , Subject: [GIT PULL] VFIO fix for v6.10 Hi Linus, This fixes a late breaking regression introduced in the v6.10 cycle and appearing in recent stable backports. Thanks, Alex The following changes since commit 256abd8e550ce977b728be79a74e1729438b4948: Linux 6.10-rc7 (2024-07-07 14:23:46 -0700) are available in the Git repository at: https://github.com/awilliam/linux-vfio.git tags/vfio-v6.10 for you to fetch changes up to 5a88a3f67e37e39f933b38ebb4985ba5822e9eca: vfio/pci: Init the count variable in collecting hot-reset devices (2024-07-10 08:47:46 -0600) ---------------------------------------------------------------- VFIO fix for v6.10 - Recent stable backports are exposing a bug introduced in the v6.10 development cycle where a counter value is uninitialized. This leads to regressions in userspace drivers like QEMU where where the kernel might ask for an arbitrary buffer size or return out of memory itself based on a bogus value. Zero initialize the counter. (Yi Liu) ---------------------------------------------------------------- Yi Liu (1): vfio/pci: Init the count variable in collecting hot-reset devices drivers/vfio/pci/vfio_pci_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) . Date: Wed, 10 Jul 2024 10:48:56 -0700 From: James Bottomley To: Andrew Morton , Linus Torvalds Cc: linux-scsi , linux-kernel Subject: [GIT PULL] SCSI fixes for 6.10-rc7 One core change that moves a disk start message to a location where it will only be printed once instead of twice plus a couple of error handling race fixes in the ufs driver. The patch is available here: git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git scsi-fixes The short changelog is: Damien Le Moal (1): scsi: sd: Do not repeat the starting disk message Peter Wang (2): scsi: ufs: core: Fix ufshcd_abort_one racing issue scsi: ufs: core: Fix ufshcd_clear_cmd racing issue And the diffstat: drivers/scsi/sd.c | 5 ++--- drivers/ufs/core/ufs-mcq.c | 11 ++++++----- drivers/ufs/core/ufshcd.c | 2 ++ 3 files changed, 10 insertions(+), 8 deletions(-) With full diff below James --- diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index fe82baa924f8..6203915945a4 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -4117,8 +4117,6 @@ static int sd_resume(struct device *dev) { struct scsi_disk *sdkp = dev_get_drvdata(dev); - sd_printk(KERN_NOTICE, sdkp, "Starting disk\n"); - if (opal_unlock_from_suspend(sdkp->opal_dev)) { sd_printk(KERN_NOTICE, sdkp, "OPAL unlock failed\n"); return -EIO; @@ -4135,12 +4133,13 @@ static int sd_resume_common(struct device *dev, bool runtime) if (!sdkp) /* E.g.: runtime resume at the start of sd_probe() */ return 0; + sd_printk(KERN_NOTICE, sdkp, "Starting disk\n"); + if (!sd_do_start_stop(sdkp->device, runtime)) { sdkp->suspended = false; return 0; } - sd_printk(KERN_NOTICE, sdkp, "Starting disk\n"); ret = sd_start_stop_device(sdkp, 1); if (!ret) { sd_resume(dev); diff --git a/drivers/ufs/core/ufs-mcq.c b/drivers/ufs/core/ufs-mcq.c index 8944548c30fa..c532416aec22 100644 --- a/drivers/ufs/core/ufs-mcq.c +++ b/drivers/ufs/core/ufs-mcq.c @@ -105,16 +105,15 @@ EXPORT_SYMBOL_GPL(ufshcd_mcq_config_mac); * @hba: per adapter instance * @req: pointer to the request to be issued * - * Return: the hardware queue instance on which the request would - * be queued. + * Return: the hardware queue instance on which the request will be or has + * been queued. %NULL if the request has already been freed. */ struct ufs_hw_queue *ufshcd_mcq_req_to_hwq(struct ufs_hba *hba, struct request *req) { - u32 utag = blk_mq_unique_tag(req); - u32 hwq = blk_mq_unique_tag_to_hwq(utag); + struct blk_mq_hw_ctx *hctx = READ_ONCE(req->mq_hctx); - return &hba->uhq[hwq]; + return hctx ? &hba->uhq[hctx->queue_num] : NULL; } /** @@ -515,6 +514,8 @@ int ufshcd_mcq_sq_cleanup(struct ufs_hba *hba, int task_tag) if (!cmd) return -EINVAL; hwq = ufshcd_mcq_req_to_hwq(hba, scsi_cmd_to_rq(cmd)); + if (!hwq) + return 0; } else { hwq = hba->dev_cmd_queue; } diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index 1b65e6ae4137..46433ecf0c4d 100644 --- a/drivers/ufs/core/ufshcd.c +++ b/drivers/ufs/core/ufshcd.c @@ -6456,6 +6456,8 @@ static bool ufshcd_abort_one(struct request *rq, void *priv) /* Release cmd in MCQ mode if abort succeeds */ if (is_mcq_enabled(hba) && (*ret == 0)) { hwq = ufshcd_mcq_req_to_hwq(hba, scsi_cmd_to_rq(lrbp->cmd)); + if (!hwq) + return 0; spin_lock_irqsave(&hwq->cq_lock, flags); if (ufshcd_cmd_inflight(lrbp->cmd)) ufshcd_release_scsi_cmd(hba, lrbp); . Date: Wed, 10 Jul 2024 13:23:33 -0700 From: Andrew Morton To: Linus Torvalds Cc: linux-kernel@vger.kernel.org, linux-mm@kvack.org, mm-commits@vger.kernel.org Subject: [GIT PULL] hotfixes against 6.10-rc7 Linus, please merge this batch of hotfixes, thanks. The following changes since commit 93aef9eda1cea9e84ab2453fcceb8addad0e46f1: nilfs2: fix incorrect inode allocation from reserved inodes (2024-07-03 12:29:25 -0700) are available in the Git repository at: git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm tags/mm-hotfixes-stable-2024-07-10-13-19 for you to fetch changes up to f708f6970cc9d6bac71da45c129482092e710537: mm/hugetlb: fix kernel NULL pointer dereference when migrating hugetlb folio (2024-07-09 15:41:11 -0700) ---------------------------------------------------------------- 21 hotfixes, 15 of which are cc:stable. No identifiable theme here - all are singleton patches, 19 are for MM. ---------------------------------------------------------------- Audra Mitchell (1): Fix userfaultfd_api to return EINVAL as expected Gavin Shan (4): mm/filemap: make MAX_PAGECACHE_ORDER acceptable to xarray mm/readahead: limit page cache size in page_cache_ra_order() mm/filemap: skip to create PMD-sized page cache if needed mm/shmem: disable PMD-sized page cache if needed Hugh Dickins (1): mm: fix crashes from deferred split racing folio migration Lorenzo Stoakes (1): MAINTAINERS: mailmap: update Lorenzo Stoakes's email address Miaohe Lin (2): mm/hugetlb: fix potential race in __update_and_free_hugetlb_folio() mm/hugetlb: fix kernel NULL pointer dereference when migrating hugetlb folio Nhat Pham (1): cachestat: do not flush stats in recency check Paul Menzel (1): lib/build_OID_registry: avoid non-destructive substitution for Perl < 5.13.2 compat Ryusuke Konishi (1): nilfs2: fix kernel bug on rename operation of broken directory SeongJae Park (1): mm/damon/core: merge regions aggressively when max_nr_regions is unmet Suren Baghdasaryan (2): sched.h: always_inline alloc_tag_{save|restore} to fix modpost warnings arch/xtensa: always_inline get_current() and current_thread_info() Uladzislau Rezki (Sony) (1): mm: vmalloc: check if a hash-index is in cpu_possible_mask Waiman Long (1): mm: prevent derefencing NULL ptr in pfn_section_valid() Yang Shi (2): mm: page_ref: remove folio_try_get_rcu() mm: gup: stop abusing try_grab_folio Yu Zhao (1): mm/hugetlb_vmemmap: fix race with speculative PFN walkers ZhangPeng (1): filemap: replace pte_offset_map() with pte_offset_map_nolock() .mailmap | 1 + MAINTAINERS | 2 +- arch/xtensa/include/asm/current.h | 2 +- arch/xtensa/include/asm/thread_info.h | 2 +- fs/nilfs2/dir.c | 32 +++- fs/userfaultfd.c | 7 +- include/linux/mmzone.h | 3 +- include/linux/page_ref.h | 57 ++----- include/linux/pagemap.h | 11 +- include/linux/sched.h | 4 +- include/linux/swap.h | 3 +- lib/build_OID_registry | 4 +- mm/damon/core.c | 23 ++- mm/filemap.c | 20 ++- mm/gup.c | 291 ++++++++++++++++++---------------- mm/huge_memory.c | 2 +- mm/hugetlb.c | 70 ++------ mm/hugetlb_vmemmap.c | 16 ++ mm/internal.h | 4 +- mm/memcontrol.c | 11 -- mm/migrate.c | 13 ++ mm/readahead.c | 8 +- mm/shmem.c | 15 +- mm/vmalloc.c | 10 +- mm/workingset.c | 14 +- 25 files changed, 339 insertions(+), 286 deletions(-) . Date: Thu, 11 Jul 2024 07:09:27 +0200 From: Christian Brauner To: Linus Torvalds Cc: Christian Brauner , linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [GIT PULL] vfs fixes /* Summary */ This contains fixes for this merge window: cachefiles: - Export an existing and add a new cachefile helper to be used in filesystems to fix reference count bugs. - Use the newly added fscache_ty_get_volume() helper to get a reference count on an fscache_volume to handle volumes that are about to be removed cleanly. - After withdrawing a fscache_cache via FSCACHE_CACHE_IS_WITHDRAWN wait for all ongoing cookie lookups to complete and for the object count to reach zero. - Propagate errors from vfs_getxattr() to avoid an infinite loop in cachefiles_check_volume_xattr() because it keeps seeing ESTALE. - Don't send new requests when an object is dropped by raising CACHEFILES_ONDEMAND_OJBSTATE_DROPPING. - Cancel all requests for an object that is about to be dropped. - Wait for the ondemand_boject_worker to finish before dropping a cachefiles object to prevent use-after-free. - Use cyclic allocation for message ids to better handle id recycling. - Add missing lock protection when iterating through the xarray when polling. netfs: - Use standard logging helpers for debug logging. VFS: - Fix potential use-after-free in file locks during trace_posix_lock_inode(). The tracepoint could fire while another task raced it and freed the lock that was requested to be traced. - Only increment the nr_dentry_negative counter for dentries that are present on the superblock LRU. Currently, DCACHE_LRU_LIST list is used to detect this case. However, the flag is also raised in combination with DCACHE_SHRINK_LIST to indicate that dentry->d_lru is used. So checking only DCACHE_LRU_LIST will lead to wrong nr_dentry_negative count. Fix the check to not count dentries that are on a shrink related list. Misc: - hfsplus: fix an uninitialized value issue in copy_name. - minix: fix minixfs_rename with HIGHMEM. It still uses kunmap() even though we switched it to kmap_local_page() a while ago. /* Testing */ clang: Debian clang version 16.0.6 (27) gcc: (Debian 13.2.0-25) 13.2.0 All patches are based on v6.10-rc6. No build failures or warnings were observed. /* Conflicts */ No known conflicts. The following changes since commit 22a40d14b572deb80c0648557f4bd502d7e83826: Linux 6.10-rc6 (2024-06-30 14:40:44 -0700) are available in the Git repository at: git@gitolite.kernel.org:pub/scm/linux/kernel/git/vfs/vfs tags/vfs-6.10-rc8.fixes for you to fetch changes up to 3d1bec293378700dddc087d4d862306702276c23: minixfs: Fix minixfs_rename with HIGHMEM (2024-07-10 07:15:36 +0200) Please consider pulling these changes from the signed vfs-6.10-rc8.fixes tag. Thanks! Christian ---------------------------------------------------------------- vfs-6.10-rc8.fixes ---------------------------------------------------------------- Baokun Li (7): netfs, fscache: export fscache_put_volume() and add fscache_try_get_volume() cachefiles: fix slab-use-after-free in fscache_withdraw_volume() cachefiles: fix slab-use-after-free in cachefiles_withdraw_cookie() cachefiles: propagate errors from vfs_getxattr() to avoid infinite loop cachefiles: stop sending new request when dropping object cachefiles: cancel all requests for the object that is being dropped cachefiles: cyclic allocation of msg_id to avoid reuse Brian Foster (1): vfs: don't mod negative dentry count when on shrinker list Christian Brauner (1): Merge patch series "cachefiles: random bugfixes" Edward Adam Davis (1): hfsplus: fix uninit-value in copy_name Hou Tao (1): cachefiles: wait for ondemand_object_worker to finish when dropping object Jeff Layton (1): filelock: fix potential use-after-free in posix_lock_inode Jingbo Xu (1): cachefiles: add missing lock protection when polling Matthew Wilcox (Oracle) (1): minixfs: Fix minixfs_rename with HIGHMEM Uwe Kleine-König (1): netfs: Switch debug logging to pr_debug() fs/cachefiles/cache.c | 45 +++++++++++++++++++++++++++++++++++- fs/cachefiles/daemon.c | 4 ++-- fs/cachefiles/internal.h | 3 +++ fs/cachefiles/ondemand.c | 52 +++++++++++++++++++++++++++++++++++++----- fs/cachefiles/volume.c | 1 - fs/cachefiles/xattr.c | 5 +++- fs/dcache.c | 12 +++++++--- fs/hfsplus/xattr.c | 2 +- fs/locks.c | 2 +- fs/minix/namei.c | 3 +-- fs/netfs/buffered_read.c | 14 ++++++------ fs/netfs/buffered_write.c | 12 +++++----- fs/netfs/direct_read.c | 2 +- fs/netfs/direct_write.c | 8 +++---- fs/netfs/fscache_cache.c | 4 ++-- fs/netfs/fscache_cookie.c | 28 +++++++++++------------ fs/netfs/fscache_io.c | 12 +++++----- fs/netfs/fscache_main.c | 2 +- fs/netfs/fscache_volume.c | 18 +++++++++++++-- fs/netfs/internal.h | 35 +--------------------------- fs/netfs/io.c | 12 +++++----- fs/netfs/main.c | 4 ---- fs/netfs/misc.c | 4 ++-- fs/netfs/write_collect.c | 16 ++++++------- fs/netfs/write_issue.c | 36 ++++++++++++++--------------- include/linux/fscache-cache.h | 6 +++++ include/trace/events/fscache.h | 4 ++++ 27 files changed, 213 insertions(+), 133 deletions(-) . Date: Thu, 11 Jul 2024 15:47:10 +0100 From: Mark Brown To: Linus Torvalds Cc: linux-spi@vger.kernel.org, linux-kernel@vger.kernel.org, Mark Brown Subject: [GIT PULL] SPI fixes for v6.10-rc7 The following changes since commit f2661062f16b2de5d7b6a5c42a9a5c96326b8454: Linux 6.10-rc5 (2024-06-23 17:08:54 -0400) are available in the Git repository at: https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git tags/spi-fix-v6.10-rc7 for you to fetch changes up to c8bd922d924bb4ab6c6c488310157d1a27996f31: spi: mux: set ctlr->bits_per_word_mask (2024-07-09 17:42:33 +0100) ---------------------------------------------------------------- spi: Fixes for v6.10 This pull request fixes two regressions that have been bubbling along for a large part of this release. One is a revert of the multi mode support for the OMAP SPI controller, this introduced regressions on a number of systems and while there has been progress on fixing those we've not got something that works for everyone yet so let's just drop the change for now. The other is a series of fixes from David Lechner for his recent message optimisation work, this interacted badly with spi-mux which is altogether too clever with recursive use of the bus and creates situations that hadn't been considered. There are also a couple of small driver specific fixes, including one more patch from David for sleep duration calculations in the AXI driver. ---------------------------------------------------------------- Bastien Curutchet (1): spi: davinci: Unset POWERDOWN bit when releasing resources David Lechner (4): spi: axi-spi-engine: fix sleep calculation spi: don't unoptimize message in spi_async() spi: add defer_optimize_message controller flag spi: mux: set ctlr->bits_per_word_mask Mark Brown (1): spi: omap2-mcspi: Revert multi mode support Uwe Kleine-König (1): spi: imx: Don't expect DMA for i.MX{25,35,50,51,53} cspi devices drivers/spi/spi-axi-spi-engine.c | 26 ++++++++++++++++++-------- drivers/spi/spi-davinci.c | 6 ++++++ drivers/spi/spi-imx.c | 2 +- drivers/spi/spi-mux.c | 2 ++ drivers/spi/spi-omap2-mcspi.c | 15 +-------------- drivers/spi/spi.c | 20 +++++++++++++++++--- include/linux/spi/spi.h | 4 ++++ 7 files changed, 49 insertions(+), 26 deletions(-) . Date: Thu, 11 Jul 2024 20:11:55 +0200 From: Daniel Lezcano To: Thomas Gleixner Cc: Linux Kernel Mailing List , Chris Packham , Geert Uytterhoeven , Jiaxun Yang , Li kunyu , =?UTF-8?Q?Niklas_S=C3=B6derlund?= , Thomas Bonnefille Subject: [GIT PULL] timer drivers for v6.11-rc1 Hi Thomas, please consider pulling the following changes since commit 746770499be55cf375a108a321a818b238182446: timers/migration: Fix grammar in comment (2024-07-04 20:24:57 +0200) which are available in the Git repository at: https://git.linaro.org/people/daniel.lezcano/linux.git tags/timers-v6.11-rc1 for you to fetch changes up to 8b77f4b8dc81aeb73107b169cb9c6e06c15d297e: clocksource/drivers/realtek: Add timer driver for rtl-otto platforms (2024-07-10 09:41:20 +0200) Thanks -- Daniel ---------------------------------------------------------------- - Remove unnecessary local variables initialization as they will be initialized in the code path anyway right after on the ARM arch timer and the ARM global timer (Li kunyu) - Fix a race condition in the interrupt leading to a deadlock on the SH CMT driver. Note that this fix was not tested on the platform using this timer but the fix seems reasonable enough to be picked confidently (Niklas Söderlund) - Increase the rating of the gic-timer and use the configured width clocksource register on the MIPS architecture (Jiaxun Yang) - Add the DT bindings for the TMU on the Renesas platforms (Geert Uytterhoeven) - Add the DT bindings for the SOPHGO SG2002 clint on RiscV (Thomas Bonnefille) - Add the rtl-otto timer driver along with the DT bindings for the Realtek platform (Chris Packham) ---------------------------------------------------------------- Chris Packham (2): dt-bindings: timer: Add schema for realtek,otto-timer clocksource/drivers/realtek: Add timer driver for rtl-otto platforms Geert Uytterhoeven (3): dt-bindings: timer: renesas,tmu: Add R-Mobile APE6 support dt-bindings: timer: renesas,tmu: Add RZ/G1 support dt-bindings: timer: renesas,tmu: Add R-Car Gen2 support Jiaxun Yang (2): clocksource/drivers/mips-gic-timer: Refine rating computation clocksource/drivers/mips-gic-timer: Correct sched_clock width Li kunyu (2): clocksource/drivers/arm_arch_timer: Remove unnecessary ‘0’ values from irq clocksource/driver/arm_global_timer: Remove unnecessary ‘0’ values from err Niklas Söderlund (1): clocksource/drivers/sh_cmt: Address race condition for clock events Thomas Bonnefille (1): dt-bindings: timer: Add SOPHGO SG2002 clint .../bindings/timer/realtek,otto-timer.yaml | 63 +++++ .../devicetree/bindings/timer/renesas,tmu.yaml | 12 + .../devicetree/bindings/timer/sifive,clint.yaml | 1 + drivers/clocksource/Kconfig | 10 + drivers/clocksource/Makefile | 1 + drivers/clocksource/arm_arch_timer.c | 2 +- drivers/clocksource/arm_global_timer.c | 2 +- drivers/clocksource/mips-gic-timer.c | 20 +- drivers/clocksource/sh_cmt.c | 13 +- drivers/clocksource/timer-rtl-otto.c | 291 +++++++++++++++++++++ include/linux/cpuhotplug.h | 1 + 11 files changed, 405 insertions(+), 11 deletions(-) create mode 100644 Documentation/devicetree/bindings/timer/realtek,otto-timer.yaml create mode 100644 drivers/clocksource/timer-rtl-otto.c -- Linaro.org │ Open source software for ARM SoCs Follow Linaro: Facebook | Twitter | Blog . Date: Thu, 11 Jul 2024 20:03:53 +0100 From: Catalin Marinas To: Linus Torvalds Cc: Will Deacon , Marc Zyngier , Oliver Upton , Thomas Gleixner , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [GIT PULL] arm64 updates for 6.11 Hi Linus, I'm about to go on holiday for two weeks, so here's an early pull request for 6.11. The biggest part is the virtual CPU hotplug that touches ACPI, irqchip. We also have some GICv3 optimisation for pseudo-NMIs that has been queued via the arm64 tree. Otherwise the usual perf updates, kselftest, various small cleanups. There's a minor conflict currently in -next with the kvmarm tree but it's trivial (in arch/arm64/include/asm/esr.h). I'll check emails occasionally during the merging window but if there's anything urgent, Will can take over. Thanks. The following changes since commit 83a7eefedc9b56fe7bfeff13b6c7356688ffa670: Linux 6.10-rc3 (2024-06-09 14:19:43 -0700) are available in the Git repository at: git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux tags/arm64-upstream for you to fetch changes up to 4f3a6c4de7d932be94cde2c52ae58feeec9c9dbf: Merge branch 'for-next/vcpu-hotplug' into for-next/core (2024-07-11 19:10:02 +0100) ---------------------------------------------------------------- arm64 updates for 6.11: * Virtual CPU hotplug support for arm64 ACPI systems * cpufeature infrastructure cleanups and making the FEAT_ECBHB ID bits visible to guests * CPU errata: expand the speculative SSBS workaround to more CPUs * arm64 ACPI: - acpi=nospcr option to disable SPCR as default console for arm64 - Move some ACPI code (cpuidle, FFH) to drivers/acpi/arm64/ * GICv3, use compile-time PMR values: optimise the way regular IRQs are masked/unmasked when GICv3 pseudo-NMIs are used, removing the need for a static key in fast paths by using a priority value chosen dynamically at boot time * arm64 perf updates: - Rework of the IMX PMU driver to enable support for I.MX95 - Enable support for tertiary match groups in the CMN PMU driver - Initial refactoring of the CPU PMU code to prepare for the fixed instruction counter introduced by Arm v9.4 - Add missing PMU driver MODULE_DESCRIPTION() strings - Hook up DT compatibles for recent CPU PMUs * arm64 kselftest updates: - Kernel mode NEON fp-stress - Cleanups, spelling mistakes * arm64 Documentation update with a minor clarification on TBI * Miscellaneous: - Fix missing IPI statistics - Implement raw_smp_processor_id() using thread_info rather than a per-CPU variable (better code generation) - Make MTE checking of in-kernel asynchronous tag faults conditional on KASAN being enabled - Minor cleanups, typos ---------------------------------------------------------------- Andre Przywara (2): dt-bindings: arm: pmu: Add new Cortex and Neoverse cores perf: pmuv3: Add new Cortex and Neoverse PMUs Anshuman Khandual (3): arm64/mm: Stop using ESR_ELx_FSC_TYPE during fault KVM: arm64: Replace custom macros with fields from ID_AA64PFR0_EL1 arm64/cpufeature: Replace custom macros with fields from ID_AA64PFR0_EL1 Catalin Marinas (3): irqchip/gic-v3: Fix 'broken_rdists' unused warning when !SMP and !ACPI Merge branches 'for-next/cpufeature', 'for-next/misc', 'for-next/kselftest', 'for-next/mte', 'for-next/errata', 'for-next/acpi', 'for-next/gic-v3-pmr' and 'for-next/doc', remote-tracking branch 'arm64/for-next/perf' into for-next/core Merge branch 'for-next/vcpu-hotplug' into for-next/core Colin Ian King (1): kselftest/arm64: Fix a couple of spelling mistakes Dev Jain (1): kselftest/arm64: Fix redundancy of a testcase Gavin Shan (1): arm64: Kconfig: Fix dependencies to enable ACPI_HOTPLUG_CPU Ilkka Koskinen (2): perf/arm-cmn: Decouple wp_config registers from filter group number perf/arm-cmn: Enable support for tertiary match group James Morse (7): ACPI: processor: Register deferred CPUs from acpi_processor_get_info() ACPI: Add post_eject to struct acpi_scan_handler for cpu hotplug arm64: acpi: Move get_cpu_for_acpi_id() to a header irqchip/gic-v3: Don't return errors from gic_acpi_match_gicc() irqchip/gic-v3: Add support for ACPI's disabled but 'online capable' CPUs arm64: document virtual CPU hotplug's expectations cpumask: Add enabled cpumask for present CPUs that can be brought online Jean-Philippe Brucker (1): arm64: psci: Ignore DENIED CPUs Jeff Johnson (2): ARM64: reloc_test: add missing MODULE_DESCRIPTION() macro perf: add missing MODULE_DESCRIPTION() macros Jinjie Ruan (1): arm64: smp: Fix missing IPI statistics Jonathan Cameron (11): ACPI: processor: Simplify initial onlining to use same path for cold and hotplug cpu: Do not warn on arch_register_cpu() returning -EPROBE_DEFER ACPI: processor: Drop duplicated check on _STA (enabled + present) ACPI: processor: Return an error if acpi_processor_get_info() fails in processor_add() ACPI: processor: Fix memory leaks in error paths of processor_add() ACPI: processor: Move checks and availability of acpi_processor earlier ACPI: processor: Add acpi_get_processor_handle() helper ACPI: scan: switch to flags for acpi_scan_check_and_detach() arm64: acpi: Harden get_cpu_for_acpi_id() against missing CPU entry arm64: arch_register_cpu() variant to check if an ACPI handle is now available. arm64: Kconfig: Enable hotplug CPU on arm64 if ACPI_PROCESSOR is enabled. Kevin Brodsky (1): Documentation: arm64: Update memory.rst for TBI Liu Wei (1): ACPI: Add acpi=nospcr to disable ACPI SPCR as default console on ARM64 Mark Brown (1): kselftest/arm64: Include kernel mode NEON in fp-stress Mark Rutland (10): arm64: cputype: Add Cortex-X3 definitions arm64: cputype: Add Cortex-A720 definitions arm64: cputype: Add Cortex-X925 definitions arm64: errata: Unify speculative SSBS errata logic arm64: errata: Expand speculative SSBS workaround wordpart.h: Add REPEAT_BYTE_U32() irqchip/gic-common: Remove sync_access callback irqchip/gic-v3: Make distributor priorities variables irqchip/gic-v3: Detect GICD_CTRL.DS and SCR_EL3.FIQ earlier arm64: irqchip/gic-v3: Select priorities at boot time Mike Rapoport (IBM) (1): arm64: Kconfig: fix typo in __builtin_return_adddress Muhammad Usama Anjum (2): selftests: arm64: tags_test: conform test to TAP output selftests: arm64: tags: remove the result script Nianyao Tang (1): arm64/cpufeatures/kvm: Add ARMv8.9 FEAT_ECBHB bits in ID_AA64MMFR1 register Peter Collingbourne (1): arm64: mte: Make mte_check_tfsr_*() conditional on KASAN instead of MTE Puranjay Mohan (2): arm64/arch_timer: include arm64: implement raw_smp_processor_id() using thread_info Rob Herring (Arm) (5): perf: arm_pmuv3: Avoid assigning fixed cycle counter with threshold perf: arm_pmuv3: Drop unnecessary IS_ENABLED(CONFIG_ARM64) check perf/arm: Move 32-bit PMU drivers to drivers/perf/ perf: arm_v6/7_pmu: Drop non-DT probe support perf: arm_pmuv3: Include asm/arm_pmuv3.h from linux/perf/arm_pmuv3.h Seongsu Park (1): arm64: Cleanup __cpu_set_tcr_t0sz() Sudeep Holla (3): ACPI: arm64: Sort entries alphabetically arm64: cpuidle: Move ACPI specific code into drivers/acpi/arm64/ arm64: FFH: Move ACPI specific code into drivers/acpi/arm64/ Xu Yang (6): dt-bindings: perf: fsl-imx-ddr: Add i.MX95 compatible perf: imx_perf: add macro definitions for parsing config attr perf: imx_perf: let the driver manage the counter usage rather the user perf: imx_perf: refactor driver for imx93 perf: imx_perf: fix counter start and config sequence perf: imx_perf: add support for i.MX95 platform Youwan Wang (1): ACPI / amba: Drop unnecessary check for registered amba_dummy_clk Documentation/ABI/testing/sysfs-devices-system-cpu | 6 + Documentation/admin-guide/kernel-parameters.txt | 10 +- Documentation/arch/arm64/cpu-hotplug.rst | 79 +++++ Documentation/arch/arm64/index.rst | 1 + Documentation/arch/arm64/memory.rst | 42 ++- Documentation/arch/arm64/silicon-errata.rst | 16 +- Documentation/devicetree/bindings/arm/pmu.yaml | 6 + .../devicetree/bindings/perf/fsl-imx-ddr.yaml | 3 + arch/arm/kernel/Makefile | 2 - arch/arm64/Kconfig | 41 +-- arch/arm64/include/asm/acpi.h | 12 + arch/arm64/include/asm/arch_gicv3.h | 15 - arch/arm64/include/asm/arch_timer.h | 2 +- arch/arm64/include/asm/arm_pmuv3.h | 2 +- arch/arm64/include/asm/cpucaps.h | 2 +- arch/arm64/include/asm/cpufeature.h | 4 +- arch/arm64/include/asm/cputype.h | 6 + arch/arm64/include/asm/esr.h | 33 +- arch/arm64/include/asm/mmu_context.h | 4 +- arch/arm64/include/asm/mte.h | 4 +- arch/arm64/include/asm/ptrace.h | 33 +- arch/arm64/include/asm/smp.h | 13 +- arch/arm64/include/asm/sysreg.h | 4 - arch/arm64/kernel/Makefile | 1 - arch/arm64/kernel/acpi.c | 129 ++------ arch/arm64/kernel/acpi_numa.c | 11 - arch/arm64/kernel/cpu_errata.c | 17 +- arch/arm64/kernel/cpufeature.c | 5 +- arch/arm64/kernel/image-vars.h | 5 - arch/arm64/kernel/proton-pack.c | 2 +- arch/arm64/kernel/psci.c | 2 +- arch/arm64/kernel/reloc_test_core.c | 1 + arch/arm64/kernel/smp.c | 74 ++++- arch/arm64/kvm/hyp/include/nvhe/fixed_config.h | 10 +- arch/arm64/kvm/hyp/nvhe/pkvm.c | 4 +- arch/arm64/kvm/hyp/nvhe/sys_regs.c | 2 +- arch/arm64/kvm/pmu-emul.c | 1 - drivers/acpi/acpi_processor.c | 145 +++++---- drivers/acpi/arm64/Makefile | 6 +- drivers/acpi/arm64/amba.c | 6 +- .../arm64/kernel => drivers/acpi/arm64}/cpuidle.c | 4 - drivers/acpi/arm64/ffh.c | 107 +++++++ drivers/acpi/processor_core.c | 3 +- drivers/acpi/processor_driver.c | 43 +-- drivers/acpi/scan.c | 47 ++- drivers/base/cpu.c | 12 +- drivers/irqchip/irq-gic-common.c | 22 +- drivers/irqchip/irq-gic-common.h | 7 +- drivers/irqchip/irq-gic-v3-its.c | 11 +- drivers/irqchip/irq-gic-v3.c | 282 ++++++++-------- drivers/irqchip/irq-gic.c | 10 +- drivers/irqchip/irq-hip04.c | 6 +- drivers/perf/Kconfig | 12 + drivers/perf/Makefile | 3 + drivers/perf/arm-ccn.c | 1 + drivers/perf/arm-cmn.c | 116 +++++-- drivers/perf/arm_cspmu/ampere_cspmu.c | 1 + drivers/perf/arm_cspmu/arm_cspmu.c | 1 + drivers/perf/arm_cspmu/nvidia_cspmu.c | 1 + drivers/perf/arm_pmuv3.c | 26 +- .../perf_event_v6.c => drivers/perf/arm_v6_pmu.c | 20 +- .../perf_event_v7.c => drivers/perf/arm_v7_pmu.c | 13 +- .../perf/arm_xscale_pmu.c | 3 - drivers/perf/cxl_pmu.c | 1 + drivers/perf/fsl_imx8_ddr_perf.c | 1 + drivers/perf/fsl_imx9_ddr_perf.c | 354 +++++++++++++++------ drivers/perf/hisilicon/hisi_uncore_pmu.c | 1 + drivers/perf/marvell_cn10k_ddr_pmu.c | 1 + include/acpi/acpi_bus.h | 1 + include/acpi/processor.h | 2 +- include/linux/acpi.h | 12 +- include/linux/cpumask.h | 25 ++ include/linux/irqchip/arm-gic-common.h | 4 - include/linux/irqchip/arm-gic-v3-prio.h | 52 +++ include/linux/irqchip/arm-gic-v3.h | 2 +- include/linux/perf/arm_pmuv3.h | 2 + include/linux/wordpart.h | 8 + kernel/cpu.c | 3 + tools/testing/selftests/arm64/abi/ptrace.c | 2 +- tools/testing/selftests/arm64/fp/.gitignore | 1 + tools/testing/selftests/arm64/fp/Makefile | 1 + tools/testing/selftests/arm64/fp/fp-stress.c | 26 +- tools/testing/selftests/arm64/fp/kernel-test.c | 324 +++++++++++++++++++ tools/testing/selftests/arm64/tags/Makefile | 1 - .../testing/selftests/arm64/tags/run_tags_test.sh | 12 - tools/testing/selftests/arm64/tags/tags_test.c | 10 +- 86 files changed, 1606 insertions(+), 752 deletions(-) create mode 100644 Documentation/arch/arm64/cpu-hotplug.rst rename {arch/arm64/kernel => drivers/acpi/arm64}/cpuidle.c (97%) create mode 100644 drivers/acpi/arm64/ffh.c rename arch/arm/kernel/perf_event_v6.c => drivers/perf/arm_v6_pmu.c (95%) rename arch/arm/kernel/perf_event_v7.c => drivers/perf/arm_v7_pmu.c (99%) rename arch/arm/kernel/perf_event_xscale.c => drivers/perf/arm_xscale_pmu.c (99%) create mode 100644 include/linux/irqchip/arm-gic-v3-prio.h create mode 100644 tools/testing/selftests/arm64/fp/kernel-test.c delete mode 100755 tools/testing/selftests/arm64/tags/run_tags_test.sh . Date: Fri, 12 Jul 2024 14:46:56 +1000 From: Dave Airlie To: LKML , Daniel Vetter Cc: dri-devel Subject: [git pull] drm fixes for 6.10-rc8 Hi Linus, Back to work, thanks to Sima for last week, not too many fixes as expected getting close to release, amdgpu and xe have a couple each, and then some other misc ones. Dave. drm-fixes-2024-07-12: drm fixes for 6.10-rc8 amdgpu: - PSR-SU fix - Reseved VMID fix xe: - Use write-back caching mode for system memory on DGFX - Do not leak object when finalizing hdcp gsc bridge: - adv7511 EDID irq fix gma500: - NULL mode fixes. meson: - fix resource leak The following changes since commit 256abd8e550ce977b728be79a74e1729438b4948= : Linux 6.10-rc7 (2024-07-07 14:23:46 -0700) are available in the Git repository at: https://gitlab.freedesktop.org/drm/kernel.git tags/drm-fixes-2024-07-12 for you to fetch changes up to 8b68788bebd3f697ae62aa9af3dac35ed112ebd7: Merge tag 'amd-drm-fixes-6.10-2024-07-11' of https://gitlab.freedesktop.org/agd5f/linux into drm-fixes (2024-07-12 13:32:36 +1000) ---------------------------------------------------------------- drm fixes for 6.10-rc8 amdgpu: - PSR-SU fix - Reseved VMID fix xe: - Use write-back caching mode for system memory on DGFX - Do not leak object when finalizing hdcp gsc bridge: - adv7511 EDID irq fix gma500: - NULL mode fixes. meson: - fix resource leak ---------------------------------------------------------------- Adam Ford (1): drm/bridge: adv7511: Fix Intermittent EDID failures Christian K=C3=B6nig (1): drm/amdgpu: reject gang submit on reserved VMIDs Dave Airlie (3): Merge tag 'drm-misc-fixes-2024-07-11' of https://gitlab.freedesktop.org/drm/misc/kernel into drm-fixes Merge tag 'drm-xe-fixes-2024-07-11' of https://gitlab.freedesktop.org/drm/xe/kernel into drm-fixes Merge tag 'amd-drm-fixes-6.10-2024-07-11' of https://gitlab.freedesktop.org/agd5f/linux into drm-fixes Leo Li (1): Revert "drm/amd/display: Reset freesync config before update new stat= e" Ma Ke (2): drm/gma500: fix null pointer dereference in psb_intel_lvds_get_modes drm/gma500: fix null pointer dereference in cdv_intel_lvds_get_modes Nirmoy Das (1): drm/xe/display/xe_hdcp_gsc: Free arbiter on driver removal Thomas Hellstr=C3=B6m (1): drm/xe: Use write-back caching mode for system memory on DGFX Yao Zi (1): drm/meson: fix canvas release in bind function drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 15 ++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c | 15 +++++++- drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h | 1 + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 1 - drivers/gpu/drm/bridge/adv7511/adv7511.h | 2 +- drivers/gpu/drm/bridge/adv7511/adv7511_cec.c | 13 +++++-- drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 22 ++++++----- drivers/gpu/drm/gma500/cdv_intel_lvds.c | 3 ++ drivers/gpu/drm/gma500/psb_intel_lvds.c | 3 ++ drivers/gpu/drm/meson/meson_drv.c | 37 +++++++++--------- drivers/gpu/drm/xe/display/xe_hdcp_gsc.c | 12 ++++-- drivers/gpu/drm/xe/xe_bo.c | 47 ++++++++++++++-----= ---- drivers/gpu/drm/xe/xe_bo_types.h | 3 +- include/uapi/drm/xe_drm.h | 8 +++- 14 files changed, 122 insertions(+), 60 deletions(-) . Date: Fri, 12 Jul 2024 09:46:44 +0200 From: Takashi Iwai To: Linus Torvalds Cc: Mark Brown , Liam Girdwood , Linux Sound Mailing List , Linux Kernel Mailing List Subject: [GIT PULL] sound fixes for 6.10 Linus, please pull sound fixes for v6.10 from: git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git tags/sound-6.10 The topmost commit is f19e1027f6c0f5fae18b2f2ed88b55a6a637f76e ---------------------------------------------------------------- sound fixes for 6.10-final Majority of changes here are small device-specific fixes for ASoC SOF / Intel and usual HD-audio quirks. The only significant high LOC is found in the Cirrus firmware driver, but all those are for hardening against malicious firmware blobs, and they look fine for taking as a last minute fix, too. ---------------------------------------------------------------- Bard Liao (1): ASoC: rt711-sdw: add missing readable registers Dmitry Savin (1): ALSA: hda: cs35l41: Fix swapped l/r audio channels for Lenovo ThinBook 13x Gen4 Edson Juliano Drosdeck (1): ALSA: hda/realtek: Limit mic boost on VAIO PRO PX Kai Vehmanen (1): ASoC: SOF: Intel: hda: fix null deref on system suspend entry Micha³ Kopeæ (1): ALSA: hda/realtek: add quirk for Clevo V5[46]0TU Nazar Bilinskyi (1): ALSA: hda/realtek: Enable Mute LED on HP 250 G7 Peter Ujfalusi (1): ASoC: SOF: Intel: hda-pcm: Limit the maximum number of periods by MAX_BDL_ENTRIES Richard Fitzgerald (5): firmware: cs_dsp: Fix overflow checking of wmfw header firmware: cs_dsp: Return error if block header overflows file firmware: cs_dsp: Validate payload length before processing block firmware: cs_dsp: Prevent buffer overrun when processing V2 alg headers firmware: cs_dsp: Use strnlen() on name fields in V1 wmfw files --- drivers/firmware/cirrus/cs_dsp.c | 231 +++++++++++++++++++++++++---------- sound/pci/hda/cs35l41_hda_property.c | 4 +- sound/pci/hda/patch_realtek.c | 4 + sound/soc/codecs/rt711-sdw.c | 2 + sound/soc/sof/intel/hda-dai.c | 12 +- sound/soc/sof/intel/hda-pcm.c | 6 + 6 files changed, 184 insertions(+), 75 deletions(-) . Date: Fri, 12 Jul 2024 11:10:08 +0200 From: Bartosz Golaszewski To: Linus Torvalds Cc: Greg Kroah-Hartman , Krzysztof Kozlowski , Bjorn Andersson , Bjorn Helgaas , Arnd Bergmann , Mark Brown , Rob Herring , Luiz Augusto von Dentz , Srini Kandagatla , linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, Bartosz Golaszewski Subject: [GIT PULL] power sequencing updates for v6.11-rc1 From: Bartosz Golaszewski Linus, I'm sending this early as this is the initial pull-request for a new driver subsystem living under drivers/power/sequencing/. I'll try to be brief here and allow myself to link the cover letter from the last time the series was sent in its entirety[1] (as opposed to smaller chunks targetting specific maintainers) for a very detailed description of the problem and the solution. I'll just stick to the key points below. This has been in development since last year's Linux Plumbers Conference and was inspired by the need to enable support upstream for Bluetooth/WLAN chips on Qualcomm platforms. The main problem we're fixing is powering up devices which are represented as separate objects in the kernel (binding to different drivers) but which share parts of the power-up sequence and thus need some kind of a mediator who knows the possible interactions and can assure they don't interfere with neither device's bring up. An example of such an inter-driver interaction is the WCN family of BT/WLAN chips from Qualcomm of which some models require the user to observe a certain delay between driving the bt-enable and wlan-enable GPIOs. This is not a new problem but up to this point all attempts at addressing it ended up hitting one wall or another and being dropped. The main obstacle was the fact that most these attempts tried to introduce the concept of a "power sequence" into the device-tree bindings which breaks the main DT rule: describe the hardware, not its behavior. The solution I proposed focuses on making the power sequencer drivers interpret the actual HW description flexibly. More details on that are in the linked cover letter. The second problem fixed here is powering up PCI devices before they are detected on the bus. This is achieved by creating special platform devices for device-tree nodes describing hard-wired PCI devices which bind to the so-called PCI power control drivers which enable required resources and trigger a bus rescan once the controlled device is up then setup the correct devlink hierarchy for power-management. By combining the two new frameworks we implemented the power sequencing PCI power control driver which is capable of powering up the WLAN modules of the QCom WCN family of chipsets. All this has spent a significant amount of time in linux-next and enabled WLAN/BT support on several Qualcomm platforms. To further prove that this is useful and needed: right after this was picked up into next, I was sent a series using the subsystem for a similar use-case on Amlogic platforms[2]. This PR contains the core power sequencing framework, the first driver, PCI changes using the pwrseq library (blessed by Bjorn Helgaas) and some fixes that came later. You'll also see the pwrseq core pulled into the Bluetooth tree to satisfy the build-time dependency on power sequencing in the hci_qca driver which uses the same power sequence provider as the PCI pwrctl driver added in this PR. More changes that don't have build-time dependencies on pwrseq are scattered across three other maintainer trees: there will be DT bindings in the regulator and wireless trees and DTS changes in the arm64 tree. Please consider pulling for v6.11. Best Regards, Bartosz Golaszewski [1] https://lore.kernel.org/all/20240528-pwrseq-v8-0-d354d52b763c@linaro.org/ [2] https://lore.kernel.org/lkml/20240705-pwrseq-v1-0-31829b47fc72@amlogic.com/ The following changes since commit 83a7eefedc9b56fe7bfeff13b6c7356688ffa670: Linux 6.10-rc3 (2024-06-09 14:19:43 -0700) are available in the Git repository at: git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux.git tags/pwrseq-updates-for-v6.11-rc1 for you to fetch changes up to 50b040ef373293b4ae2ecdc5873daa4656724868: PCI/pwrctl: only call of_platform_populate() if CONFIG_OF is enabled (2024-07-08 21:15:26 +0200) ---------------------------------------------------------------- pwrseq updates for v6.11-rc1 - add the pwrseq core framework - add the first power sequencing driver: pwrseq-qcom-wcn - add power control (pwrctl) changes to PCI core - add the first PCI pwrctl power sequencing driver ---------------------------------------------------------------- Bartosz Golaszewski (7): power: sequencing: implement the pwrseq core power: pwrseq: add a driver for the PMU module on the QCom WCN chipsets PCI: Hold the rescan mutex when scanning for the first time PCI/pwrctl: Reuse the OF node for power controlled devices PCI/pwrctl: Create platform devices for child OF nodes of the port node PCI/pwrctl: Add PCI power control core code PCI/pwrctl: Add a PCI power control driver for power sequenced devices Bert Karwatzki (1): PCI/pwrctl: only call of_platform_populate() if CONFIG_OF is enabled Krzysztof Kozlowski (1): power: sequencing: simplify returning pointer without cleanup MAINTAINERS | 16 + drivers/pci/Kconfig | 1 + drivers/pci/Makefile | 1 + drivers/pci/bus.c | 9 + drivers/pci/of.c | 14 +- drivers/pci/probe.c | 2 + drivers/pci/pwrctl/Kconfig | 17 + drivers/pci/pwrctl/Makefile | 6 + drivers/pci/pwrctl/core.c | 137 ++++ drivers/pci/pwrctl/pci-pwrctl-pwrseq.c | 89 +++ drivers/pci/remove.c | 3 +- drivers/power/Kconfig | 1 + drivers/power/Makefile | 1 + drivers/power/sequencing/Kconfig | 29 + drivers/power/sequencing/Makefile | 6 + drivers/power/sequencing/core.c | 1105 ++++++++++++++++++++++++++++ drivers/power/sequencing/pwrseq-qcom-wcn.c | 336 +++++++++ include/linux/pci-pwrctl.h | 51 ++ include/linux/pwrseq/consumer.h | 56 ++ include/linux/pwrseq/provider.h | 75 ++ 20 files changed, 1950 insertions(+), 5 deletions(-) create mode 100644 drivers/pci/pwrctl/Kconfig create mode 100644 drivers/pci/pwrctl/Makefile create mode 100644 drivers/pci/pwrctl/core.c create mode 100644 drivers/pci/pwrctl/pci-pwrctl-pwrseq.c create mode 100644 drivers/power/sequencing/Kconfig create mode 100644 drivers/power/sequencing/Makefile create mode 100644 drivers/power/sequencing/core.c create mode 100644 drivers/power/sequencing/pwrseq-qcom-wcn.c create mode 100644 include/linux/pci-pwrctl.h create mode 100644 include/linux/pwrseq/consumer.h create mode 100644 include/linux/pwrseq/provider.h . Date: Fri, 12 Jul 2024 12:40:43 +0200 From: Greg KH To: Linus Torvalds Cc: Andrew Morton , linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org Subject: [GIT PULL] USB driver fixes for 6.10-final The following changes since commit 22a40d14b572deb80c0648557f4bd502d7e83826: Linux 6.10-rc6 (2024-06-30 14:40:44 -0700) are available in the Git repository at: git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git tags/usb-6.10-final for you to fetch changes up to 70c8e3944063a83b7fae1996db7971e9b858c635: Merge tag 'usb-serial-6.10-rc8' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/johan/usb-serial into usb-linus (2024-07-10 19:55:07 +0200) ---------------------------------------------------------------- USB fixes for 6.10-final Here are some small USB driver fixes and new device ids for 6.10-final. Included in here are: - new usb-serial device ids for reported devices - syzbot-triggered duplicate endpoint bugfix - gadget bugfix for configfs memory overwrite - xhci resume bugfix - new device quirk added - usb core error path bugfix All of these have been in linux-next (most for a while) with no reported issues. Signed-off-by: Greg Kroah-Hartman ---------------------------------------------------------------- Alan Stern (1): USB: core: Fix duplicate endpoint bug by clearing reserved bits in the descriptor Bjørn Mork (1): USB: serial: option: add Fibocom FM350-GL Daniele Palmas (2): USB: serial: option: add Telit FN912 rmnet compositions USB: serial: option: add Telit generic core-dump composition Dmitry Smirnov (1): USB: serial: mos7840: fix crash on resume Greg Kroah-Hartman (2): Merge tag 'usb-serial-6.10-rc6' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/johan/usb-serial into usb-linus Merge tag 'usb-serial-6.10-rc8' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/johan/usb-serial into usb-linus Heikki Krogerus (1): usb: dwc3: pci: add support for the Intel Panther Lake Javier Carrasco (1): usb: core: add missing of_node_put() in usb_of_has_devices_or_graph Lee Jones (1): usb: gadget: configfs: Prevent OOB read/write in usb_string_copy() Mank Wang (1): USB: serial: option: add Netprisma LCUK54 series modules Mathias Nyman (1): xhci: always resume roothubs if xHC was reset during resume Slark Xiao (1): USB: serial: option: add support for Foxconn T99W651 Vanillan Wang (1): USB: serial: option: add Rolling RW350-GL variants WangYuli (1): USB: Add USB_QUIRK_NO_SET_INTF quirk for START BP-850k drivers/usb/core/config.c | 18 ++++++++++++++--- drivers/usb/core/of.c | 7 +++++-- drivers/usb/core/quirks.c | 3 +++ drivers/usb/dwc3/dwc3-pci.c | 8 ++++++++ drivers/usb/gadget/configfs.c | 3 +++ drivers/usb/host/xhci.c | 16 ++++++++++++--- drivers/usb/serial/mos7840.c | 45 +++++++++++++++++++++++++++++++++++++++++++ drivers/usb/serial/option.c | 38 ++++++++++++++++++++++++++++++++++++ 8 files changed, 130 insertions(+), 8 deletions(-) . Date: Fri, 12 Jul 2024 12:41:01 +0200 From: Greg KH To: Linus Torvalds Cc: Jiri Slaby , Stephen Rothwell , Andrew Morton , linux-kernel@vger.kernel.org, linux-serial@vger.kernel.org Subject: [GIT PULL] TTY / Serial driver fixes for 6.10-final The following changes since commit 22a40d14b572deb80c0648557f4bd502d7e83826: Linux 6.10-rc6 (2024-06-30 14:40:44 -0700) are available in the Git repository at: git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git tags/tty-6.10-final for you to fetch changes up to 2ac33975abda6921896e52372aec2be2cf51ab37: serial: qcom-geni: do not kill the machine on fifo underrun (2024-07-04 12:30:30 +0200) ---------------------------------------------------------------- TTY/Serial fixes for 6.10-final Here are some small serial driver fixes for 6.10-final. Included in here are: - qcom-geni fixes for a much much much discussed issue and everyone now seems to be agreed that this is the proper way forward to resolve the reported lockups - imx serial driver bugfixes - 8250_omap errata fix - ma35d1 serial driver bugfix All of these have been in linux-next for over a week with no reported issues. Signed-off-by: Greg Kroah-Hartman ---------------------------------------------------------------- Jacky Huang (1): tty: serial: ma35d1: Add a NULL check for of_node Johan Hovold (3): serial: qcom-geni: fix soft lockup on sw flow control and suspend serial: qcom-geni: fix hard lockup on buffer flush serial: qcom-geni: do not kill the machine on fifo underrun Rasmus Villemoes (1): serial: imx: ensure RTS signal is not left active after shutdown Stefan Eichenberger (1): serial: imx: only set receiver level if it is zero Udit Kumar (1): serial: 8250_omap: Fix Errata i2310 with RX FIFO level check drivers/tty/serial/8250/8250_omap.c | 3 +- drivers/tty/serial/imx.c | 59 +++++++++++++++++++++++++++++++++-- drivers/tty/serial/ma35d1_serial.c | 13 ++++---- drivers/tty/serial/qcom_geni_serial.c | 51 ++++++++++++++++++++++-------- 4 files changed, 104 insertions(+), 22 deletions(-) . Date: Fri, 12 Jul 2024 12:41:17 +0200 From: Greg KH To: Linus Torvalds Cc: Andrew Morton , Arnd Bergmann , linux-kernel@vger.kernel.org Subject: [GIT PULL] Char/Misc driver fixes for 6.10-final The following changes since commit 22a40d14b572deb80c0648557f4bd502d7e83826: Linux 6.10-rc6 (2024-06-30 14:40:44 -0700) are available in the Git repository at: git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git tags/char-misc-6.10-final for you to fetch changes up to 389637d4fb5fee40e8a0f2bfd31583f6768ef792: mei: vsc: Fix spelling error (2024-07-04 12:21:39 +0200) ---------------------------------------------------------------- Char/Misc driver fixes for 6.10-final Here are some small remaining driver fixes for 6.10-final that have all been in linux-next for a while and resolve reported issues. Included in here are: - mei driver fixes (and a spelling fix at the end just to be clean) - iio driver fixes for reported problems - fastrpc bugfixes - nvmem small fixes Again, all have been in linux-next for a while with no reported issues. Signed-off-by: Greg Kroah-Hartman ---------------------------------------------------------------- Ekansh Gupta (6): misc: fastrpc: Fix DSP capabilities request misc: fastrpc: Copy the complete capability structure to user misc: fastrpc: Avoid updating PD type for capability request misc: fastrpc: Fix memory leak in audio daemon attach operation misc: fastrpc: Fix ownership reassignment of remote heap misc: fastrpc: Restrict untrusted app to attach to privileged PD Greg Kroah-Hartman (1): Merge tag 'iio-fixes-for-6.10c' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/jic23/iio into char-misc-linus He Zhe (1): hpet: Support 32-bit userspace Joy Chakraborty (3): misc: microchip: pci1xxxx: Fix return value of nvmem callbacks nvmem: rmem: Fix return value of rmem_read() nvmem: meson-efuse: Fix return value of nvmem callbacks João Paulo Gonçalves (1): iio: trigger: Fix condition for own trigger Mudit Sharma (1): iio: light: apds9306: Fix error handing Thomas Weißschuh (2): nvmem: core: only change name to fram for current attribute nvmem: core: limit cell sysfs permissions to main attribute ones Wentong Wu (5): mei: vsc: Enhance IVSC chipset stability during warm reboot mei: vsc: Prevent timeout error with added delay post-firmware download mei: vsc: Utilize the appropriate byte order swap function mei: vsc: Enhance SPI transfer of IVSC ROM mei: vsc: Fix spelling error drivers/char/hpet.c | 34 ++++++++++++++++--- drivers/iio/industrialio-trigger.c | 2 +- drivers/iio/light/apds9306.c | 4 +-- drivers/misc/fastrpc.c | 41 ++++++++++++++++++----- drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_otpe2p.c | 4 --- drivers/misc/mei/platform-vsc.c | 4 +-- drivers/misc/mei/vsc-fw-loader.c | 2 +- drivers/misc/mei/vsc-tp.c | 18 ++++++++-- drivers/nvmem/core.c | 7 ++-- drivers/nvmem/meson-efuse.c | 14 +++++--- drivers/nvmem/rmem.c | 5 ++- include/uapi/misc/fastrpc.h | 3 ++ 12 files changed, 103 insertions(+), 35 deletions(-) . Date: Fri, 12 Jul 2024 14:39:56 +0200 From: "Arnd Bergmann" To: "Linus Torvalds" Cc: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, soc@kernel.org, linux-arm-msm@vger.kernel.org, "Chunyan Zhang" , "Christophe Leroy" Subject: [GIT PULL] ARM: SoC fixes for 6.10, part 3 The following changes since commit 256abd8e550ce977b728be79a74e1729438b4948: Linux 6.10-rc7 (2024-07-07 14:23:46 -0700) are available in the Git repository at: https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git tags/arm-fixes-6.10-3 for you to fetch changes up to 6fba5cbd323e013079b304489629a6b814110512: MAINTAINERS: Update FREESCALE SOC DRIVERS and QUICC ENGINE LIBRARY (2024-07-12 13:16:09 +0200) ---------------------------------------------------------------- ARM: SoC fixes for 6.10, part 3 Most of these changes are Qualcomm SoC specific and came in after I sent out the last set of fixes. This includes two regression fixes for SoC drivers, a defconfig change to ensure the Lenovo X13s is usable and 11 changes to DT files to fix regressions and minor platform specific issues. Tony and Chunyan step back from their respective maintainership roles on the omap and unisoc platforms, and Christophe in turn takes over maintaining some of the Freescale SoC drivers that he has been taking care of in practice already. Lastly, there are two trivial fixes for the davinci and sunxi platforms. ---------------------------------------------------------------- Abel Vesa (1): arm64: dts: qcom: x1e80100: Fix PCIe 6a reg offsets and add MHI Andre Przywara (1): arm64: dts: allwinner: Fix PMIC interrupt number Arnd Bergmann (4): Merge tag 'qcom-arm64-fixes-for-6.10' of https://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux into arm/fixes Merge tag 'qcom-arm64-defconfig-fixes-for-6.10' of https://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux into arm/fixes Merge tag 'qcom-drivers-fixes-for-6.10' of https://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux into arm/fixes Merge tag 'sunxi-fixes-for-6.10' of https://git.kernel.org/pub/scm/linux/kernel/git/sunxi/linux into arm/fixes Bjorn Andersson (1): arm64: dts: qcom: sc8180x: Fix LLCC reg property again Caleb Connolly (1): arm64: dts: qcom: sm6115: add iommu for sdhc_1 Chen Ni (1): ARM: davinci: Convert comma to semicolon Christophe Leroy (1): MAINTAINERS: Update FREESCALE SOC DRIVERS and QUICC ENGINE LIBRARY Chunyan Zhang (1): MAINTAINERS: Move myself from SPRD Maintainer to Reviewer Cong Zhang (1): arm64: dts: qcom: sa8775p: Correct IRQ number of EL2 non-secure physical timer Johan Hovold (4): arm64: dts: qcom: sc8280xp-x13s: fix touchscreen power on arm64: dts: qcom: sc8280xp-crd: use external pull up for touch reset arm64: defconfig: enable Elan i2c-hid driver soc: qcom: pmic_glink: disable UCSI on sc8280xp Komal Bajaj (2): arm64: dts: qcom: qdu1000: Fix LLCC reg property Revert "dt-bindings: cache: qcom,llcc: correct QDU1000 reg entries" Konrad Dybcio (2): arm64: dts: qcom: x1e80100-*: Allocate some CMA buffers arm64: dts: qcom: sc8280xp: Set status = "reserved" on PSHOLD Krzysztof Kozlowski (2): arm64: dts: qcom: x1e80100-crd: fix WCD audio codec TX port mapping arm64: dts: qcom: x1e80100-crd: fix DAI used for headset recording Tony Lindgren (1): MAINTAINERS: Add more maintainers for omaps Documentation/devicetree/bindings/cache/qcom,llcc.yaml | 2 +- MAINTAINERS | 13 +++++++++---- arch/arm/mach-davinci/pm.c | 2 +- .../boot/dts/allwinner/sun50i-h64-remix-mini-pc.dts | 2 +- arch/arm64/boot/dts/qcom/qdu1000.dtsi | 16 +++++++++++++++- arch/arm64/boot/dts/qcom/sa8775p.dtsi | 2 +- arch/arm64/boot/dts/qcom/sc8180x.dtsi | 11 +++++++---- arch/arm64/boot/dts/qcom/sc8280xp-crd.dts | 3 +-- .../boot/dts/qcom/sc8280xp-lenovo-thinkpad-x13s.dts | 15 ++++++++------- arch/arm64/boot/dts/qcom/sc8280xp.dtsi | 2 ++ arch/arm64/boot/dts/qcom/sm6115.dtsi | 1 + arch/arm64/boot/dts/qcom/x1e80100-crd.dts | 13 +++++++++++-- arch/arm64/boot/dts/qcom/x1e80100-qcp.dts | 9 +++++++++ arch/arm64/boot/dts/qcom/x1e80100.dtsi | 10 ++++++---- arch/arm64/configs/defconfig | 1 + drivers/soc/qcom/pmic_glink.c | 4 ++++ 16 files changed, 78 insertions(+), 28 deletions(-) . Date: Fri, 12 Jul 2024 15:50:34 +0200 From: Christian Brauner To: Linus Torvalds Cc: Christian Brauner , linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [GIT PULL for v6.11] vfs misc Hey Linus, /* Summary */ Features: - Support passing NULL along AT_EMPTY_PATH for statx(). NULL paths with any flag value other than AT_EMPTY_PATH go the usual route and end up with -EFAULT to retain compatibility (Rust is abusing calls of the sort to detect availability of statx). This avoids path lookup code, lockref management, memory allocation and in case of NULL path userspace memory access (which can be quite expensive with SMAP on x86_64). - Don't block i_writecount during exec. Remove the deny_write_access() mechanism for executables. - Relax open_by_handle_at() permissions in specific cases where we can prove that the caller had sufficient privileges to open a file. - Switch timespec64 fields in struct inode to discrete integers freeing up 4 bytes. Fixes: - Fix false positive circular locking warning in hfsplus. - Initialize hfs_inode_info after hfs_alloc_inode() in hfs. - Avoid accidental overflows in vfs_fallocate(). - Don't interrupt fallocate with EINTR in tmpfs to avoid constantly restarting shmem_fallocate(). - Add missing quote in comment in fs/readdir. Cleanups: - Don't assign and test in an if statement in mqueue. Move the assignment out of the if statement. - Reflow the logic in may_create_in_sticky(). - Remove the usage of the deprecated ida_simple_xx() API from procfs. - Reject FSCONFIG_CMD_CREATE_EXCL requets that depend on the new mount api early. - Rename variables in copy_tree() to make it easier to understand. - Replace WARN(down_read_trylock, ...) abuse with proper asserts in various places in the VFS. - Get rid of user_path_at_empty() and drop the empty argument from getname_flags(). - Check for error while copying and no path in one branch in getname_flags(). - Avoid redundant smp_mb() for THP handling in do_dentry_open(). - Rename parent_ino to d_parent_ino and make it use RCU. - Remove unused header include in fs/readdir. - Export in_group_capable() helper and switch f2fs and fuse over to it instead of open-coding the logic in both places. /* Testing */ clang: Debian clang version 16.0.6 (26) gcc: (Debian 13.2.0-24) All patches are based on v6.10-rc1 and have been sitting in linux-next. No build failures or warnings were observed. /* Conflicts */ Merge conflicts with other trees ================================ [1]: linux-next: manual merge of the block tree with the vfs-brauner tree https://lore.kernel.org/linux-next/Zn76C70F9QB_Z0bw@sirena.org.uk [2]: linux-next: manual merge of the block tree with the vfs-brauner tree https://lore.kernel.org/linux-next/Zn76HPyBbHbnmGmw@sirena.org.uk The following changes since commit 1613e604df0cd359cf2a7fbd9be7a0bcfacfabd0: Linux 6.10-rc1 (2024-05-26 15:20:12 -0700) are available in the Git repository at: git@gitolite.kernel.org:pub/scm/linux/kernel/git/vfs/vfs tags/vfs-6.11.misc for you to fetch changes up to b80cc4df1124702c600fd43b784e423a30919204: ipc: mqueue: remove assignment from IS_ERR argument (2024-07-09 06:47:40 +0200) Please consider pulling these changes from the signed vfs-6.11.misc tag. Thanks! Christian ---------------------------------------------------------------- vfs-6.11.misc ---------------------------------------------------------------- Chao Yu (2): hfsplus: fix to avoid false alarm of circular locking hfs: fix to initialize fields of hfs_inode_info after hfs_alloc_inode() Chen Ni (1): ipc: mqueue: remove assignment from IS_ERR argument Christian Brauner (5): fhandle: relax open_by_handle_at() permission checks fs: don't block i_writecount during exec fs: reflow may_create_in_sticky() fs: new helper vfs_empty_path() stat: use vfs_empty_path() helper Christophe JAILLET (1): proc: Remove usage of the deprecated ida_simple_xx() API Hongbo Li (1): fs: fsconfig: intercept non-new mount API in advance for FSCONFIG_CMD_CREATE_EXCL command Jeff Layton (1): fs: switch timespec64 fields in inode to discrete integers Jemmy (1): Improve readability of copy_tree Justin Stitt (1): fs: remove accidental overflow during wraparound check Mateusz Guzik (8): vfs: replace WARN(down_read_trylock, ...) abuse with proper asserts vfs: stop using user_path_at_empty in do_readlinkat vfs: retire user_path_at_empty and drop empty arg from getname_flags vfs: shave a branch in getname_flags vfs: reorder checks in may_create_in_sticky vfs: remove redundant smp_mb for thp handling in do_dentry_open vfs: support statx(..., NULL, AT_EMPTY_PATH, ...) vfs: rename parent_ino to d_parent_ino and make it use RCU Mikulas Patocka (1): tmpfs: don't interrupt fallocate with EINTR Thorsten Blum (2): readdir: Remove unused header include readdir: Add missing quote in macro comment Youling Tang (3): fs: Export in_group_or_capable() f2fs: Use in_group_or_capable() helper fuse: Use in_group_or_capable() helper fs/attr.c | 2 - fs/binfmt_elf.c | 2 - fs/binfmt_elf_fdpic.c | 5 +- fs/binfmt_misc.c | 7 +- fs/dcache.c | 30 +++++++- fs/exec.c | 14 +--- fs/exportfs/expfs.c | 9 ++- fs/f2fs/acl.c | 3 +- fs/f2fs/file.c | 6 +- fs/fhandle.c | 178 +++++++++++++++++++++++++++++++++++++---------- fs/fsopen.c | 7 +- fs/fuse/acl.c | 4 +- fs/hfs/inode.c | 3 + fs/hfsplus/bfind.c | 15 +--- fs/hfsplus/extents.c | 9 ++- fs/hfsplus/hfsplus_fs.h | 21 ++++++ fs/hfsplus/ioctl.c | 4 +- fs/inode.c | 1 + fs/internal.h | 14 ++++ fs/mount.h | 1 + fs/namei.c | 98 ++++++++++++++++---------- fs/namespace.c | 74 +++++++++----------- fs/nfsd/nfsfh.c | 2 +- fs/open.c | 17 +++-- fs/proc/generic.c | 6 +- fs/quota/dquot.c | 8 +-- fs/readdir.c | 4 +- fs/stat.c | 172 +++++++++++++++++++++++++++++---------------- include/linux/dcache.h | 2 + include/linux/exportfs.h | 2 + include/linux/fs.h | 85 +++++++++++++--------- include/linux/namei.h | 8 +-- io_uring/statx.c | 3 +- io_uring/xattr.c | 4 +- ipc/mqueue.c | 3 +- kernel/fork.c | 26 +------ mm/khugepaged.c | 10 +-- mm/shmem.c | 9 ++- 38 files changed, 539 insertions(+), 329 deletions(-) . Date: Fri, 12 Jul 2024 15:54:15 +0200 From: Christian Brauner To: Linus Torvalds Cc: Christian Brauner , linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [GIT PULL for v6.11] vfs module descriptions Hey Linus, /* Summary */ This contains patches to add module descriptions to all modules under fs/ currently lacking them. /* Testing */ clang: Debian clang version 16.0.6 (26) gcc: (Debian 13.2.0-24) All patches are based on v6.10-rc1 and have been sitting in linux-next. No build failures or warnings were observed. /* Conflicts */ No known conflicts. The following changes since commit 1613e604df0cd359cf2a7fbd9be7a0bcfacfabd0: Linux 6.10-rc1 (2024-05-26 15:20:12 -0700) are available in the Git repository at: git@gitolite.kernel.org:pub/scm/linux/kernel/git/vfs/vfs tags/vfs-6.11.module.description for you to fetch changes up to 807221c54db6bc696b65106b4ee76286e435944d: openpromfs: add missing MODULE_DESCRIPTION() macro (2024-06-20 09:46:01 +0200) Please consider pulling these changes from the signed vfs-6.11.module.description tag. Thanks! Christian ---------------------------------------------------------------- vfs-6.11.module.description ---------------------------------------------------------------- Jeff Johnson (13): fs: minix: add MODULE_DESCRIPTION() fs: efs: add MODULE_DESCRIPTION() fs: sysv: add MODULE_DESCRIPTION() qnx6: add MODULE_DESCRIPTION() qnx4: add MODULE_DESCRIPTION() fs: hpfs: add MODULE_DESCRIPTION() fs: hfs: add MODULE_DESCRIPTION() fs: cramfs: add MODULE_DESCRIPTION() fs: binfmt: add missing MODULE_DESCRIPTION() macros fs: fat: add missing MODULE_DESCRIPTION() macros fs: autofs: add MODULE_DESCRIPTION() fs: nls: add missing MODULE_DESCRIPTION() macros openpromfs: add missing MODULE_DESCRIPTION() macro fs/autofs/init.c | 1 + fs/binfmt_misc.c | 1 + fs/binfmt_script.c | 1 + fs/cramfs/inode.c | 1 + fs/efs/inode.c | 1 + fs/fat/fat_test.c | 1 + fs/fat/inode.c | 1 + fs/hfs/super.c | 1 + fs/hpfs/super.c | 1 + fs/minix/inode.c | 1 + fs/nls/mac-celtic.c | 1 + fs/nls/mac-centeuro.c | 1 + fs/nls/mac-croatian.c | 1 + fs/nls/mac-cyrillic.c | 1 + fs/nls/mac-gaelic.c | 1 + fs/nls/mac-greek.c | 1 + fs/nls/mac-iceland.c | 1 + fs/nls/mac-inuit.c | 1 + fs/nls/mac-roman.c | 1 + fs/nls/mac-romanian.c | 1 + fs/nls/mac-turkish.c | 1 + fs/nls/nls_ascii.c | 1 + fs/nls/nls_base.c | 1 + fs/nls/nls_cp1250.c | 1 + fs/nls/nls_cp1251.c | 1 + fs/nls/nls_cp1255.c | 1 + fs/nls/nls_cp437.c | 1 + fs/nls/nls_cp737.c | 1 + fs/nls/nls_cp775.c | 1 + fs/nls/nls_cp850.c | 1 + fs/nls/nls_cp852.c | 1 + fs/nls/nls_cp855.c | 1 + fs/nls/nls_cp857.c | 1 + fs/nls/nls_cp860.c | 1 + fs/nls/nls_cp861.c | 1 + fs/nls/nls_cp862.c | 1 + fs/nls/nls_cp863.c | 1 + fs/nls/nls_cp864.c | 1 + fs/nls/nls_cp865.c | 1 + fs/nls/nls_cp866.c | 1 + fs/nls/nls_cp869.c | 1 + fs/nls/nls_cp874.c | 1 + fs/nls/nls_cp932.c | 1 + fs/nls/nls_cp936.c | 1 + fs/nls/nls_cp949.c | 1 + fs/nls/nls_cp950.c | 1 + fs/nls/nls_euc-jp.c | 1 + fs/nls/nls_iso8859-1.c | 1 + fs/nls/nls_iso8859-13.c | 1 + fs/nls/nls_iso8859-14.c | 1 + fs/nls/nls_iso8859-15.c | 1 + fs/nls/nls_iso8859-2.c | 1 + fs/nls/nls_iso8859-3.c | 1 + fs/nls/nls_iso8859-4.c | 1 + fs/nls/nls_iso8859-5.c | 1 + fs/nls/nls_iso8859-6.c | 1 + fs/nls/nls_iso8859-7.c | 1 + fs/nls/nls_iso8859-9.c | 1 + fs/nls/nls_koi8-r.c | 1 + fs/nls/nls_koi8-ru.c | 1 + fs/nls/nls_koi8-u.c | 1 + fs/nls/nls_ucs2_utils.c | 1 + fs/nls/nls_utf8.c | 1 + fs/openpromfs/inode.c | 1 + fs/qnx4/inode.c | 1 + fs/qnx6/inode.c | 1 + fs/sysv/super.c | 1 + 67 files changed, 67 insertions(+) . Date: Fri, 12 Jul 2024 15:54:57 +0200 From: Christian Brauner To: Linus Torvalds Cc: Christian Brauner , linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [GIT PULL for v6.11] vfs pg_error Hey Linus, /* Summary */ This contains work to remove almost all remaining users of PG_error from filesystems and filesystem helper libraries. An additional patch will be coming in via the jfs tree which tests the PG_error bit. Afterwards nothing will be testing it anymore and it's safe to remove all places which set or clear the PG_error bit. The goal is to fully remove PG_error by the next merge window. /* Testing */ clang: Debian clang version 16.0.6 (26) gcc: (Debian 13.2.0-24) All patches are based on v6.10-rc1 and have been sitting in linux-next. No build failures or warnings were observed. /* Conflicts */ Merge conflicts with mainline ============================= There's one merge conflict in fs/nsfs/symlink.c After conflict resolution the function should look like this: static int nfs_symlink_filler(struct file *file, struct folio *folio) { struct inode *inode = folio->mapping->host; int error; error = NFS_PROTO(inode)->readlink(inode, &folio->page, 0, PAGE_SIZE); folio_end_read(folio, error == 0); return error; } The following changes since commit 1613e604df0cd359cf2a7fbd9be7a0bcfacfabd0: Linux 6.10-rc1 (2024-05-26 15:20:12 -0700) are available in the Git repository at: git@gitolite.kernel.org:pub/scm/linux/kernel/git/vfs/vfs tags/vfs-6.11.pg_error for you to fetch changes up to 7ad635ea82704a64c40aba67a7d04293d4780f0f: buffer: Remove calls to set and clear the folio error flag (2024-05-31 12:31:43 +0200) Please consider pulling these changes from the signed vfs-6.11.pg_error tag. Thanks! Christian ---------------------------------------------------------------- vfs-6.11.pg_error ---------------------------------------------------------------- Matthew Wilcox (Oracle) (16): befs: Convert befs_symlink_read_folio() to use folio_end_read() coda: Convert coda_symlink_filler() to use folio_end_read() cramfs: Convert cramfs_read_folio to use a folio efs: Convert efs_symlink_read_folio to use a folio hpfs: Convert hpfs_symlink_read_folio to use a folio isofs: Convert rock_ridge_symlink_read_folio to use a folio hostfs: Convert hostfs_read_folio() to use a folio jffs2: Remove calls to set/clear the folio error flag nfs: Remove calls to folio_set_error orangefs: Remove calls to set/clear the error flag reiserfs: Remove call to folio_set_error() romfs: Convert romfs_read_folio() to use a folio ufs: Remove call to set the folio error flag vboxsf: Convert vboxsf_read_folio() to use a folio iomap: Remove calls to set and clear folio error flag buffer: Remove calls to set and clear the folio error flag fs/befs/linuxvfs.c | 10 ++++------ fs/buffer.c | 7 +------ fs/coda/symlink.c | 10 +--------- fs/cramfs/inode.c | 25 ++++++++++--------------- fs/efs/symlink.c | 14 +++++--------- fs/hostfs/hostfs_kern.c | 23 ++++++----------------- fs/hpfs/namei.c | 15 +++------------ fs/iomap/buffered-io.c | 8 -------- fs/isofs/rock.c | 17 ++++++++--------- fs/jffs2/file.c | 14 +++----------- fs/mpage.c | 13 +++---------- fs/nfs/read.c | 2 -- fs/nfs/symlink.c | 12 ++---------- fs/nfs/write.c | 1 - fs/orangefs/inode.c | 13 +++---------- fs/orangefs/orangefs-bufmap.c | 4 +--- fs/reiserfs/inode.c | 1 - fs/romfs/super.c | 22 ++++++---------------- fs/ufs/dir.c | 1 - fs/vboxsf/file.c | 18 +++++------------- 20 files changed, 61 insertions(+), 169 deletions(-) . Date: Fri, 12 Jul 2024 15:55:41 +0200 From: Christian Brauner To: Linus Torvalds Cc: Christian Brauner , linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [GIT PULL for v6.11] vfs mount api Hey Linus, /* Summary */ This contains work for the mount api: - Add a generic helper to parse uid and gid mount options. Currently we open-code the same logic in various filesystems which is error prone. Especially since the verification of uid and gid mount options is a sensitive operation in the face of idmappings. Add a generic helper and convert all filesystems over to it. Make sure that filesystems that are mountable in unprivileged containers verify that the specified uid and gid can be represented in the owning namespace of the filesystem. - Convert hostfs to the new mount api. /* Testing */ clang: Debian clang version 16.0.6 (26) gcc: (Debian 13.2.0-24) All patches are based on v6.10-rc1 and have been sitting in linux-next. No build failures or warnings were observed. /* Conflicts */ No known conflicts. The following changes since commit 1613e604df0cd359cf2a7fbd9be7a0bcfacfabd0: Linux 6.10-rc1 (2024-05-26 15:20:12 -0700) are available in the Git repository at: git@gitolite.kernel.org:pub/scm/linux/kernel/git/vfs/vfs tags/vfs-6.11.mount.api for you to fetch changes up to eea6a8322efd3982e59c41a5b61948a0b043ca58: fuse: Convert to new uid/gid option parsing helpers (2024-07-03 16:55:11 +0200) Please consider pulling these changes from the signed vfs-6.11.mount.api tag. Thanks! Christian ---------------------------------------------------------------- vfs-6.11.mount.api ---------------------------------------------------------------- Eric Sandeen (18): fs_parse: add uid & gid option option parsing helpers autofs: Convert to new uid/gid option parsing helpers debugfs: Convert to new uid/gid option parsing helpers efivarfs: Convert to new uid/gid option parsing helpers exfat: Convert to new uid/gid option parsing helpers ext4: Convert to new uid/gid option parsing helpers hugetlbfs: Convert to new uid/gid option parsing helpers isofs: Convert to new uid/gid option parsing helpers ntfs3: Convert to new uid/gid option parsing helpers tmpfs: Convert to new uid/gid option parsing helpers smb: client: Convert to new uid/gid option parsing helpers tracefs: Convert to new uid/gid option parsing helpers vboxsf: Convert to new uid/gid option parsing helpers fat: move debug into fat_mount_options fat: Convert to new mount api fat: Convert to new uid/gid option parsing helpers fuse: verify {g,u}id mount options correctly fuse: Convert to new uid/gid option parsing helpers Hongbo Li (1): hostfs: convert hostfs to use the new mount API Nathan Chancellor (1): hostfs: Add const qualifier to host_root in hostfs_fill_super() Documentation/filesystems/mount_api.rst | 9 +- fs/autofs/inode.c | 16 +- fs/debugfs/inode.c | 16 +- fs/efivarfs/super.c | 12 +- fs/exfat/super.c | 8 +- fs/ext4/super.c | 22 +- fs/fat/fat.h | 18 +- fs/fat/inode.c | 674 ++++++++++++++++---------------- fs/fat/namei_msdos.c | 38 +- fs/fat/namei_vfat.c | 38 +- fs/fs_parser.c | 34 ++ fs/fuse/inode.c | 24 +- fs/hostfs/hostfs_kern.c | 83 +++- fs/hugetlbfs/inode.c | 12 +- fs/isofs/inode.c | 16 +- fs/ntfs3/super.c | 12 +- fs/smb/client/fs_context.c | 39 +- fs/tracefs/inode.c | 16 +- fs/vboxsf/super.c | 16 +- include/linux/fs_parser.h | 6 +- mm/shmem.c | 12 +- 21 files changed, 594 insertions(+), 527 deletions(-) . Date: Fri, 12 Jul 2024 15:57:15 +0200 From: Christian Brauner To: Linus Torvalds Cc: Christian Brauner , linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [GIT PULL for v6.11] vfs casefold Hey Linus, /* Summary */ This contains some work to simplify the handling of casefolded names: - Simplify the handling of casefolded names in f2fs and ext4 by keeping the names as a qstr to avoiding unnecessary conversions. - Introduce a new generic_ci_match() libfs case-insensitive lookup helper and use it in both f2fs and ext4 allowing to remove the filesystem specific implementations. - Remove a bunch of ifdefs by making the unicode built checks part of the code flow. /* Testing */ clang: Debian clang version 16.0.6 (26) gcc: (Debian 13.2.0-24) All patches are based on v6.10-rc1 and have been sitting in linux-next. No build failures or warnings were observed. /* Conflicts */ No known conflicts. The following changes since commit 1613e604df0cd359cf2a7fbd9be7a0bcfacfabd0: Linux 6.10-rc1 (2024-05-26 15:20:12 -0700) are available in the Git repository at: git@gitolite.kernel.org:pub/scm/linux/kernel/git/vfs/vfs tags/vfs-6.11.casefold for you to fetch changes up to 28add38d545f445f01eec844b85eed4593c31733: f2fs: Move CONFIG_UNICODE defguards into the code flow (2024-06-07 17:00:45 +0200) Please consider pulling these changes from the signed vfs-6.11.casefold tag. Thanks! Christian ---------------------------------------------------------------- vfs-6.11.casefold ---------------------------------------------------------------- Gabriel Krisman Bertazi (7): ext4: Simplify the handling of cached casefolded names f2fs: Simplify the handling of cached casefolded names libfs: Introduce case-insensitive string comparison helper ext4: Reuse generic_ci_match for ci comparisons f2fs: Reuse generic_ci_match for ci comparisons ext4: Move CONFIG_UNICODE defguards into the code flow f2fs: Move CONFIG_UNICODE defguards into the code flow fs/ext4/crypto.c | 10 +---- fs/ext4/ext4.h | 35 +++++++++------ fs/ext4/namei.c | 122 ++++++++++++++++------------------------------------- fs/ext4/super.c | 4 +- fs/f2fs/dir.c | 105 ++++++++++++++------------------------------- fs/f2fs/f2fs.h | 16 ++++++- fs/f2fs/namei.c | 10 ++--- fs/f2fs/recovery.c | 9 +--- fs/f2fs/super.c | 8 ++-- fs/libfs.c | 74 ++++++++++++++++++++++++++++++++ include/linux/fs.h | 4 ++ 11 files changed, 195 insertions(+), 202 deletions(-) . Date: Fri, 12 Jul 2024 15:58:04 +0200 From: Christian Brauner To: Linus Torvalds Cc: Christian Brauner , linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [GIT PULL for v6.11] vfs inode Hey Linus, /* Summary */ This contains smaller performance improvements to inodes and dentries: # inode: - Add rcu based inode lookup variants. They avoid one inode hash lock acquire in the common case thereby significantly reducing contention. We already support RCU-based operations but didn't take advantage of them during inode insertion. Callers of iget_locked() get the improvement without any code changes. Callers that need a custom callback can switch to iget5_locked_rcu() as e.g., did btrfs. With 20 threads each walking a dedicated 1000 dirs * 1000 files directory tree to stat(2) on a 32 core + 24GB ram vm: before: 3.54s user 892.30s system 1966% cpu 45.549 total after: 3.28s user 738.66s system 1955% cpu 37.932 total (-16.7%) Long-term we should pick up the effort to introduce more fine-grained locking and possibly improve on the currently used hash implementation. - Start zeroing i_state in inode_init_always() instead of doing it in individual filesystems. This allows us to remove an unneeded lock acquire in new_inode() and not burden individual filesystems with this. dcache: - Move d_lockref out of the area used by RCU lookup to avoid cacheline ping poing because the embedded name is sharing a cacheline with d_lockref. - Fix dentry size on 32bit with CONFIG_SMP=y so it does actually end up with 128 bytes in total. /* Testing */ clang: Debian clang version 16.0.6 (26) gcc: (Debian 13.2.0-24) All patches are based on v6.10-rc1 and have been sitting in linux-next. No build failures or warnings were observed. /* Conflicts */ Merge conflicts with other trees ================================ [1]: linux-next: manual merge of the vfs-brauner tree with the btrfs tree https://lore.kernel.org/linux-next/ZnFyeNLLrEcX5_g0@sirena.org.uk Merge conflicts with mainline ============================= This causes a merge conflict with fs/bcachefs/fs.c. The gist is that inode->i_state initialization in __bch2_new_inode() isn't needed anymore after this is merged and that line needs to be deleted from that function. The following changes since commit 1613e604df0cd359cf2a7fbd9be7a0bcfacfabd0: Linux 6.10-rc1 (2024-05-26 15:20:12 -0700) are available in the Git repository at: git@gitolite.kernel.org:pub/scm/linux/kernel/git/vfs/vfs tags/vfs-6.11.inode for you to fetch changes up to dc99c0ff53f588bb210b1e8b3314c7581cde68a2: fs: fix dentry size (2024-07-03 10:34:11 +0200) Please consider pulling these changes from the signed vfs-6.11.inode tag. Thanks! Christian ---------------------------------------------------------------- vfs-6.11.inode ---------------------------------------------------------------- Christian Brauner (1): fs: fix dentry size Mateusz Guzik (7): vfs: add rcu-based find_inode variants for iget ops btrfs: use iget5_locked_rcu xfs: preserve i_state around inode_init_always in xfs_reinit_inode vfs: partially sanitize i_state zeroing on inode creation xfs: remove now spurious i_state initialization in xfs_inode_alloc bcachefs: remove now spurious i_state initialization vfs: move d_lockref out of the area used by RCU lookup fs/bcachefs/fs.c | 1 - fs/btrfs/inode.c | 2 +- fs/inode.c | 108 +++++++++++++++++++++++++++++++++++++------------ fs/xfs/xfs_icache.c | 5 ++- include/linux/dcache.h | 9 ++++- include/linux/fs.h | 7 +++- 6 files changed, 99 insertions(+), 33 deletions(-) . Date: Fri, 12 Jul 2024 15:58:52 +0200 From: Christian Brauner To: Linus Torvalds Cc: Christian Brauner , linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [GIT PULL for v6.11] vfs procfs Hey Linus, /* Summary */ This contains work to allow restricting access to /proc//mem. Over the years various exploits started abusing /proc//mem (cf. [1] and [2]). Specifically [2] is interesting as it installed an arbitrary payload from noexec storage into a running process and then executed it. That payload itself included an ELF loader to run arbitrary code off of noexec storage. The biggest problem is that /proc//mem ignores page permissions by using FOLL_FORCE which was discussed several times on- and off-list. Unfortunately there are various use-cases using /proc//mem making it impossible to just turn it off. They at least include PTRACE_POKEDATA and the seccomp notifier which is used to emulate system calls. So give userspace a way to restrict access to /proc//mem via kernel command line options. Setting them to "all" restricts access for all processes while "ptracer" will allow access to ptracers: (1) Restrict the use of FOLL_FORCE via proc_mem.restrict_foll_force (2) Restrict opening /proc//mem for reading. (3) Restrict opening /proc//mem for writing. (4) Restrict writing to /proc//mem. --- The level of fine-grained management isn't my favorite as it requires distributions to have some level of knowledge around the implications of FOLL_FORCE and /proc//mem access in general. But the use-cases where /proc//mem access is needed do already imply a sophisticated knowledge around its implications. Especially when it comes to the seccomp notifier and gdb to inspect or emulate process state. So that ultimately swayed me to accept this. If we need something simpler I'm all ears. /* Testing */ clang: Debian clang version 16.0.6 (26) gcc: (Debian 13.2.0-24) All patches are based on v6.10-rc1 and have been sitting in linux-next. No build failures or warnings were observed. /* Conflicts */ No known conflicts. The following changes since commit 1613e604df0cd359cf2a7fbd9be7a0bcfacfabd0: Linux 6.10-rc1 (2024-05-26 15:20:12 -0700) are available in the Git repository at: git@gitolite.kernel.org:pub/scm/linux/kernel/git/vfs/vfs tags/vfs-6.11.procfs for you to fetch changes up to 39efa92f9e5fceb44edef5536c58e3750b9d638d: proc: restrict /proc/pid/mem (2024-06-18 12:26:54 +0200) Please consider pulling these changes from the signed vfs-6.11.procfs tag. Thanks! Christian ---------------------------------------------------------------- vfs-6.11.procfs ---------------------------------------------------------------- Adrian Ratiu (2): proc: pass file instead of inode to proc_mem_open proc: restrict /proc/pid/mem Documentation/admin-guide/kernel-parameters.txt | 38 +++++ fs/proc/base.c | 203 +++++++++++++++++++++++- fs/proc/internal.h | 2 +- fs/proc/task_mmu.c | 6 +- fs/proc/task_nommu.c | 2 +- security/Kconfig | 121 ++++++++++++++ 6 files changed, 363 insertions(+), 9 deletions(-) . Date: Fri, 12 Jul 2024 15:59:50 +0200 From: Christian Brauner To: Linus Torvalds Cc: Christian Brauner , linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [GIT PULL for v6.11] vfs mount Hey Linus, /* Summary */ This contains work to extend the abilities of listmount() and statmount() and various fixes and cleanups. Features: - Allow iterating through mounts via listmount() from newest to oldest. This makes it possible for mount(8) to keep iterating the mount table in reverse order so it gets newest mounts first. - Relax permissions on listmount() and statmount(). It's not necessary to have capabilities in the initial namespace. It's sufficient to have capabilities in the owning namespace of the mount namespace we're located in to list unreachable mounts in that namespace. - Extend both listmount() and statmount() to list and stat mounts in foreign mount namespaces. Currently the only way to iterate over mount entries in mount namespaces that aren't in the caller's mount namespace is by crawling through /proc in order to find /proc//mountinfo for the relevant mount namespace. This is both very clumsy and hugely inefficient. So extend struct mnt_id_req with a new member that allows to specify the mount namespace id of the mount namespace we want to look at. Luckily internally we already have most of the infrastructure for this so we just need to expose it to userspace. Give userspace a way to retrieve the id of a mount namespace via statmount() and through a new nsfs ioctl() on mount namespace file descriptor. This comes with appropriate selftests. - Expose mount options through statmount(). Currently if userspace wants to get mount options for a mount and with statmount(), they still have to open /proc//mountinfo to parse mount options. Simply the information through statmount() directly. Afterwards it's possible to only rely on statmount() and listmount() to retrieve all and more information than /proc//mountinfo provides. This comes with appropriate selftests. Fixes: - Avoid copying to userspace under the namespace semaphore in listmount. Cleanups: - Simplify the error handling in listmount by relying on our newly added cleanup infrastructure. - Refuse invalid mount ids early for both listmount and statmount. /* Testing */ clang: Debian clang version 16.0.6 (26) gcc: (Debian 13.2.0-24) All patches are based on v6.10-rc1 and have been sitting in linux-next. No build failures or warnings were observed. /* Conflicts */ No known conflicts. The following changes since commit 1613e604df0cd359cf2a7fbd9be7a0bcfacfabd0: Linux 6.10-rc1 (2024-05-26 15:20:12 -0700) are available in the Git repository at: git@gitolite.kernel.org:pub/scm/linux/kernel/git/vfs/vfs tags/vfs-6.11.mount for you to fetch changes up to 4bed843b10004d9101b49ac7270131051c39a92b: fs: reject invalid last mount id early (2024-07-08 06:32:18 +0200) Please consider pulling these changes from the signed vfs-6.11.mount tag. Thanks! Christian ---------------------------------------------------------------- vfs-6.11.mount ---------------------------------------------------------------- Christian Brauner (15): path: add cleanup helper fs: don't copy to userspace under namespace semaphore fs: simplify error handling fs: relax permissions for listmount() listmount: allow listing in reverse order fs: relax permissions for statmount() fs: Allow listmount() in foreign mount namespace fs: Allow statmount() in foreign mount namespace Merge patch series "Support foreign mount namespace with statmount/listmount" fs: use guard for namespace_sem in statmount() Merge patch series "Add the ability to query mount options in statmount" fs: only copy to userspace on success in listmount() fs: find rootfs mount of the mount namespace fs: refuse mnt id requests with invalid ids early fs: reject invalid last mount id early Josef Bacik (7): fs: keep an index of current mount namespaces fs: export the mount ns id via statmount fs: add an ioctl to get the mnt ns id from nsfs selftests: add a test for the foreign mnt ns extensions fs: rename show_mnt_opts -> show_vfsmnt_opts fs: export mount options via statmount() sefltests: extend the statmount test for mount options fs/mount.h | 2 + fs/namespace.c | 450 +++++++++++++++++---- fs/nsfs.c | 14 + fs/proc_namespace.c | 6 +- include/linux/path.h | 9 + include/uapi/linux/mount.h | 10 +- include/uapi/linux/nsfs.h | 2 + .../selftests/filesystems/statmount/Makefile | 2 +- .../selftests/filesystems/statmount/statmount.h | 46 +++ .../filesystems/statmount/statmount_test.c | 144 +++++-- .../filesystems/statmount/statmount_test_ns.c | 364 +++++++++++++++++ 11 files changed, 926 insertions(+), 123 deletions(-) create mode 100644 tools/testing/selftests/filesystems/statmount/statmount.h create mode 100644 tools/testing/selftests/filesystems/statmount/statmount_test_ns.c . Date: Fri, 12 Jul 2024 16:00:48 +0200 From: Christian Brauner To: Linus Torvalds Cc: Christian Brauner , linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [GIT PULL for v6.11] vfs nsfs Hey Linus, /* Summary */ This adds ioctls allowing to translate PIDs between PID namespaces. The motivating use-case comes from LXCFS which is a tiny fuse filesystem used to virtualize various aspects of procfs. LXCFS is run on the host. The files and directories it creates can be bind-mounted by e.g. a container at startup and mounted over the various procfs files the container wishes to have virtualized. When e.g. a read request for uptime is received, LXCFS will receive the pid of the reader. In order to virtualize the corresponding read, LXCFS needs to know the pid of the init process of the reader's pid namespace. In order to do this, LXCFS first needs to fork() two helper processes. The first helper process setns() to the readers pid namespace. The second helper process is needed to create a process that is a proper member of the pid namespace. The second helper process then creates a ucred message with ucred.pid set to 1 and sends it back to LXCFS. The kernel will translate the ucred.pid field to the corresponding pid number in LXCFS's pid namespace. This way LXCFS can learn the init pid number of the reader's pid namespace and can go on to virtualize. Since these two forks() are costly LXCFS maintains an init pid cache that caches a given pid for a fixed amount of time. The cache is pruned during new read requests. However, even with the cache the hit of the two forks() is singificant when a very large number of containers are running. So this adds a simple set of ioctls that let's a caller translate PIDs from and into a given PID namespace. This significantly improves performance with a very simple change. To protect against races pidfds can be used to check whether the process is still valid. /* Testing */ clang: Debian clang version 16.0.6 (26) gcc: (Debian 13.2.0-24) All patches are based on v6.10-rc1 and have been sitting in linux-next. No build failures or warnings were observed. /* Conflicts */ [1]: This contains a merge conflict with the vfs-6.11.mount pull request https://lore.kernel.org/r/20240712-vfs-mount-8fd93381a87f@brauner After conflict resolution the merge diff looks like this: diff --cc fs/nsfs.c index af352dadffe1,a23c827a0299..ad6bb91a3e23 --- a/fs/nsfs.c +++ b/fs/nsfs.c @@@ -144,22 -147,56 +148,69 @@@ static long ns_ioctl(struct file *filp argp = (uid_t __user *) arg; uid = from_kuid_munged(current_user_ns(), user_ns->owner); return put_user(uid, argp); + case NS_GET_MNTNS_ID: { + struct mnt_namespace *mnt_ns; + __u64 __user *idp; + __u64 id; + + if (ns->ops->type != CLONE_NEWNS) + return -EINVAL; + + mnt_ns = container_of(ns, struct mnt_namespace, ns); + idp = (__u64 __user *)arg; + id = mnt_ns->seq; + return put_user(id, idp); + } + case NS_GET_PID_FROM_PIDNS: + fallthrough; + case NS_GET_TGID_FROM_PIDNS: + fallthrough; + case NS_GET_PID_IN_PIDNS: + fallthrough; + case NS_GET_TGID_IN_PIDNS: + if (ns->ops->type != CLONE_NEWPID) + return -EINVAL; + + ret = -ESRCH; + pid_ns = container_of(ns, struct pid_namespace, ns); + + rcu_read_lock(); + + if (ioctl == NS_GET_PID_IN_PIDNS || + ioctl == NS_GET_TGID_IN_PIDNS) + tsk = find_task_by_vpid(arg); + else + tsk = find_task_by_pid_ns(arg, pid_ns); + if (!tsk) + break; + + switch (ioctl) { + case NS_GET_PID_FROM_PIDNS: + ret = task_pid_vnr(tsk); + break; + case NS_GET_TGID_FROM_PIDNS: + ret = task_tgid_vnr(tsk); + break; + case NS_GET_PID_IN_PIDNS: + ret = task_pid_nr_ns(tsk, pid_ns); + break; + case NS_GET_TGID_IN_PIDNS: + ret = task_tgid_nr_ns(tsk, pid_ns); + break; + default: + ret = 0; + break; + } + rcu_read_unlock(); + + if (!ret) + ret = -ESRCH; + break; default: - return -ENOTTY; + ret = -ENOTTY; } + + return ret; } int ns_get_name(char *buf, size_t size, struct task_struct *task, diff --cc include/uapi/linux/nsfs.h index 56e8b1639b98,faeb9195da08..b133211331f6 --- a/include/uapi/linux/nsfs.h +++ b/include/uapi/linux/nsfs.h @@@ -15,7 -15,13 +15,15 @@@ #define NS_GET_NSTYPE _IO(NSIO, 0x3) /* Get owner UID (in the caller's user namespace) for a user namespace */ #define NS_GET_OWNER_UID _IO(NSIO, 0x4) +/* Get the id for a mount namespace */ +#define NS_GET_MNTNS_ID _IO(NSIO, 0x5) + /* Translate pid from target pid namespace into the caller's pid namespace. */ -#define NS_GET_PID_FROM_PIDNS _IOR(NSIO, 0x5, int) ++#define NS_GET_PID_FROM_PIDNS _IOR(NSIO, 0x6, int) + /* Return thread-group leader id of pid in the callers pid namespace. */ + #define NS_GET_TGID_FROM_PIDNS _IOR(NSIO, 0x7, int) + /* Translate pid from caller's pid namespace into a target pid namespace. */ -#define NS_GET_PID_IN_PIDNS _IOR(NSIO, 0x6, int) ++#define NS_GET_PID_IN_PIDNS _IOR(NSIO, 0x8, int) + /* Return thread-group leader id of pid in the target pid namespace. */ -#define NS_GET_TGID_IN_PIDNS _IOR(NSIO, 0x8, int) ++#define NS_GET_TGID_IN_PIDNS _IOR(NSIO, 0x9, int) #endif /* __LINUX_NSFS_H */ The following changes since commit 1613e604df0cd359cf2a7fbd9be7a0bcfacfabd0: Linux 6.10-rc1 (2024-05-26 15:20:12 -0700) are available in the Git repository at: git@gitolite.kernel.org:pub/scm/linux/kernel/git/vfs/vfs tags/vfs-6.11.nsfs for you to fetch changes up to ca567df74a28a9fb368c6b2d93e864113f73f5c2: nsfs: add pid translation ioctls (2024-06-25 23:00:41 +0200) Please consider pulling these changes from the signed vfs-6.11.nsfs tag. Thanks! Christian ---------------------------------------------------------------- vfs-6.11.nsfs ---------------------------------------------------------------- Christian Brauner (1): nsfs: add pid translation ioctls fs/nsfs.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++- include/uapi/linux/nsfs.h | 8 +++++++ 2 files changed, 60 insertions(+), 1 deletion(-) . Date: Fri, 12 Jul 2024 16:01:45 +0200 From: Christian Brauner To: Linus Torvalds Cc: Christian Brauner , linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [GIT PULL for v6.11] vfs pidfs Hey Linus, /* Summary */ This contains work to make it possible to derive namespace file descriptors from pidfd file descriptors. Right now it is already possible to use a pidfd with setns() to atomically change multiple namespaces at the same time. In other words, it is possible to switch to the namespace context of a process using a pidfd. There is no need to first open namespace file descriptors via procfs. The work included here is an extension of these abilities by allowing to open namespace file descriptors using a pidfd. This means it is now possible to interact with namespaces without ever touching procfs. To this end a new set of ioctls() on pidfds is introduced covering all supported namespace types. /* Testing */ clang: Debian clang version 16.0.6 (26) gcc: (Debian 13.2.0-24) All patches are based on v6.10-rc1 and have been sitting in linux-next. No build failures or warnings were observed. /* Conflicts */ [1]: This contains a merge conflict with the vfs-6.11.misc pull request https://lore.kernel.org/r/20240712-vfs-misc-c1dbbc5eaf82@brauner After conflict resolution the merge diff looks like this: diff --cc fs/internal.h index f26454c60a98,24346cf765dd..a5e9a2f5b30d --- a/fs/internal.h +++ b/fs/internal.h @@@ -323,15 -322,4 +324,16 @@@ struct stashed_operations int path_from_stashed(struct dentry **stashed, struct vfsmount *mnt, void *data, struct path *path); void stashed_dentry_prune(struct dentry *dentry); +/** + * path_mounted - check whether path is mounted + * @path: path to check + * + * Determine whether @path refers to the root of a mount. + * + * Return: true if @path is the root of a mount, false if not. + */ +static inline bool path_mounted(const struct path *path) +{ + return path->mnt->mnt_root == path->dentry; +} + int open_namespace(struct ns_common *ns); The following changes since commit 1613e604df0cd359cf2a7fbd9be7a0bcfacfabd0: Linux 6.10-rc1 (2024-05-26 15:20:12 -0700) are available in the Git repository at: git@gitolite.kernel.org:pub/scm/linux/kernel/git/vfs/vfs tags/vfs-6.11.pidfs for you to fetch changes up to 5b08bd408534bfb3a7cf5778da5b27d4e4fffe12: pidfs: allow retrieval of namespace file descriptors (2024-06-28 10:37:29 +0200) Please consider pulling these changes from the signed vfs-6.11.pidfs tag. Thanks! Christian ---------------------------------------------------------------- vfs-6.11.pidfs ---------------------------------------------------------------- Christian Brauner (6): path: add cleanup helper file: add take_fd() cleanup helper nsproxy: add a cleanup helper for nsproxy nsproxy: add helper to go from arbitrary namespace to ns_common nsfs: add open_namespace() pidfs: allow retrieval of namespace file descriptors fs/internal.h | 2 ++ fs/nsfs.c | 55 +++++++++++++++------------- fs/pidfs.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++ include/linux/cleanup.h | 13 ++++--- include/linux/file.h | 20 +++++++++++ include/linux/nsproxy.h | 13 +++++++ include/linux/path.h | 9 +++++ include/uapi/linux/pidfd.h | 14 ++++++++ 8 files changed, 187 insertions(+), 29 deletions(-) . Date: Fri, 12 Jul 2024 16:03:24 +0200 From: Christian Brauner To: Linus Torvalds Cc: Christian Brauner , linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [GIT PULL for v6.11] vfs iomap Hey Linus, /* Summary */ This contains some minor work for the iomap subsystem: - Add documentaiton on the design of iomap and how to port to it. - Optimize iomap_read_folio(). - Bring back the change to iomap_write_end() to no increase i_size. This is accompanied by a change to xfs to reserve blocks for truncating large realtime inodes to avoid exposing stale data when iomap_write_end() stops increasing i_size. /* Testing */ clang: Debian clang version 16.0.6 (26) gcc: (Debian 13.2.0-24) All patches are based on v6.10-rc4 and have been sitting in linux-next. No build failures or warnings were observed. /* Conflicts */ No known conflicts. The following changes since commit 6ba59ff4227927d3a8530fc2973b80e94b54d58f: Linux 6.10-rc4 (2024-06-16 13:40:16 -0700) are available in the Git repository at: git@gitolite.kernel.org:pub/scm/linux/kernel/git/vfs/vfs tags/vfs-6.11.iomap for you to fetch changes up to 602f09f4029c7b5e1a2f44a7651ac8922a904a1b: iomap: don't increase i_size in iomap_write_end() (2024-06-19 15:58:28 +0200) Please consider pulling these changes from the signed vfs-6.11.iomap tag. Thanks! Christian ---------------------------------------------------------------- vfs-6.11.iomap ---------------------------------------------------------------- Darrick J. Wong (1): Documentation: the design of iomap and how to port Ritesh Harjani (IBM) (1): iomap: Optimize iomap_read_folio Zhang Yi (2): xfs: reserve blocks for truncating large realtime inode iomap: don't increase i_size in iomap_write_end() Documentation/filesystems/index.rst | 1 + Documentation/filesystems/iomap/design.rst | 441 +++++++++++++++ Documentation/filesystems/iomap/index.rst | 13 + Documentation/filesystems/iomap/operations.rst | 713 +++++++++++++++++++++++++ Documentation/filesystems/iomap/porting.rst | 120 +++++ MAINTAINERS | 1 + fs/iomap/buffered-io.c | 73 ++- fs/xfs/xfs_iops.c | 15 +- 8 files changed, 1351 insertions(+), 26 deletions(-) create mode 100644 Documentation/filesystems/iomap/design.rst create mode 100644 Documentation/filesystems/iomap/index.rst create mode 100644 Documentation/filesystems/iomap/operations.rst create mode 100644 Documentation/filesystems/iomap/porting.rst . Date: Fri, 12 Jul 2024 16:44:57 +0200 From: Ulf Hansson To: Linus , linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Ulf Hansson Subject: [GIT PULL] MMC fixes for v6.10-rc8 Hi Linus, Here's a PR with a couple of MMC fixes intended for v6.10-rc8. Details about the highlights are as usual found in the signed tag. Please pull this in! Kind regards Ulf Hansson The following changes since commit ab069ce125965a5e282f7b53b86aee76ab32975c: mmc: sdhci: Do not lock spinlock around mmc_gpio_get_ro() (2024-06-20 16:42:30 +0200) are available in the Git repository at: git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc.git tags/mmc-v6.10-rc4-2 for you to fetch changes up to 16198eef11c1929374381d7f6271b4bf6aa44615: mmc: davinci_mmc: Prevent transmitted data size from exceeding sgm's length (2024-07-11 17:48:54 +0200) ---------------------------------------------------------------- MMC host: - davinci_mmc: Prevent transmitted data size from exceeding sgm's length - sdhci: Fix max_seg_size for 64KiB PAGE_SIZE ---------------------------------------------------------------- Adrian Hunter (1): mmc: sdhci: Fix max_seg_size for 64KiB PAGE_SIZE Bastien Curutchet (1): mmc: davinci_mmc: Prevent transmitted data size from exceeding sgm's length drivers/mmc/host/davinci_mmc.c | 3 +++ drivers/mmc/host/sdhci.c | 15 +++++++++++++++ 2 files changed, 18 insertions(+) . Date: Fri, 12 Jul 2024 16:51:06 +0200 From: Daniel Lezcano To: Thomas Gleixner Cc: Linux Kernel Mailing List , Chris Packham , Geert Uytterhoeven , Jiaxun Yang , Li kunyu , =?UTF-8?Q?Niklas_S=C3=B6derlund?= , Thomas Bonnefille Subject: [GIT PULL][resend] timer drivers for v6.11-rc1 Hi Thomas, please consider pulling the following changes since commit 256abd8e550ce977b728be79a74e1729438b4948: Linux 6.10-rc7 (2024-07-07 14:23:46 -0700) which are available in the Git repository at: https://git.linaro.org/people/daniel.lezcano/linux.git tags/timers-v6.11-rc1 for you to fetch changes up to 4bdc3eaa102b6bedb0800f76f53eca516d5cf20c: clocksource/drivers/realtek: Add timer driver for rtl-otto platforms (2024-07-12 16:07:06 +0200) Thanks -- Daniel ---------------------------------------------------------------- - Remove unnecessary local variables initialization as they will be initialized in the code path anyway right after on the ARM arch timer and the ARM global timer (Li kunyu) - Fix a race condition in the interrupt leading to a deadlock on the SH CMT driver. Note that this fix was not tested on the platform using this timer but the fix seems reasonable enough to be picked confidently (Niklas Söderlund) - Increase the rating of the gic-timer and use the configured width clocksource register on the MIPS architecture (Jiaxun Yang) - Add the DT bindings for the TMU on the Renesas platforms (Geert Uytterhoeven) - Add the DT bindings for the SOPHGO SG2002 clint on RiscV (Thomas Bonnefille) - Add the rtl-otto timer driver along with the DT bindings for the Realtek platform (Chris Packham) ---------------------------------------------------------------- Chris Packham (2): dt-bindings: timer: Add schema for realtek,otto-timer clocksource/drivers/realtek: Add timer driver for rtl-otto platforms Geert Uytterhoeven (3): dt-bindings: timer: renesas,tmu: Add R-Mobile APE6 support dt-bindings: timer: renesas,tmu: Add RZ/G1 support dt-bindings: timer: renesas,tmu: Add R-Car Gen2 support Jiaxun Yang (2): clocksource/drivers/mips-gic-timer: Refine rating computation clocksource/drivers/mips-gic-timer: Correct sched_clock width Li kunyu (2): clocksource/drivers/arm_arch_timer: Remove unnecessary ‘0’ values from irq clocksource/driver/arm_global_timer: Remove unnecessary ‘0’ values from err Niklas Söderlund (1): clocksource/drivers/sh_cmt: Address race condition for clock events Thomas Bonnefille (1): dt-bindings: timer: Add SOPHGO SG2002 clint .../bindings/timer/realtek,otto-timer.yaml | 63 +++++ .../devicetree/bindings/timer/renesas,tmu.yaml | 12 + .../devicetree/bindings/timer/sifive,clint.yaml | 1 + drivers/clocksource/Kconfig | 10 + drivers/clocksource/Makefile | 1 + drivers/clocksource/arm_arch_timer.c | 2 +- drivers/clocksource/arm_global_timer.c | 2 +- drivers/clocksource/mips-gic-timer.c | 20 +- drivers/clocksource/sh_cmt.c | 13 +- drivers/clocksource/timer-rtl-otto.c | 291 +++++++++++++++++++++ include/linux/cpuhotplug.h | 1 + 11 files changed, 405 insertions(+), 11 deletions(-) create mode 100644 Documentation/devicetree/bindings/timer/realtek,otto-timer.yaml create mode 100644 drivers/clocksource/timer-rtl-otto.c -- Linaro.org │ Open source software for ARM SoCs Follow Linaro: Facebook | Twitter | Blog . Date: Fri, 12 Jul 2024 16:51:31 +0200 From: Ulf Hansson To: Linus , linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Ulf Hansson , linux-arm-kernel@lists.infradead.org Subject: [GIT PULL] pmdomain fixes for v6.10-rc8 Hi Linus, Here's a PR with a pmdomain fixe intended for v6.10-rc8. Details about the highlights are as usual found in the signed tag. Please pull this in! Kind regards Ulf Hansson The following changes since commit c3f38fa61af77b49866b006939479069cd451173: Linux 6.10-rc2 (2024-06-02 15:44:56 -0700) are available in the Git repository at: git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/linux-pm.git tags/pmdomain-v6.10-rc2 for you to fetch changes up to ddab91f4b2de5c5b46e312a90107d9353087d8ea: pmdomain: qcom: rpmhpd: Skip retention level for Power Domains (2024-07-09 12:47:46 +0200) ---------------------------------------------------------------- pmdomain providers: - qcom: Skip retention level for rpmhpd's ---------------------------------------------------------------- Taniya Das (1): pmdomain: qcom: rpmhpd: Skip retention level for Power Domains drivers/pmdomain/qcom/rpmhpd.c | 7 +++++++ 1 file changed, 7 insertions(+) . Date: Fri, 12 Jul 2024 11:11:54 -0400 From: Kent Overstreet To: Linus Torvalds Cc: linux-bcachefs@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [GIT PULL] bcachefs fixes for 6.10-rc8, more Hi Linus, just a few stragglers left. The revert should've had a Reported-By: Gabriel de Perthuis noting it here since I just tagged the pull, but he did the work of bisecting it for us :) Cheers, Kent The following changes since commit 7d7f71cd8763a296d02dff9514447aa3de199c47: bcachefs: Add missing bch2_trans_begin() (2024-07-10 09:53:39 -0400) are available in the Git repository at: https://evilpiepirate.org/git/bcachefs.git tags/bcachefs-2024-07-12 for you to fetch changes up to 1841027c7de47527ed819a935b7aa340b9171eb5: bcachefs: bch2_gc_btree() should not use btree_root_lock (2024-07-11 20:10:55 -0400) ---------------------------------------------------------------- bcachefs fixes for 6.10-rc8, more - revert the SLAB_ACCOUNT patch, something crazy is going on in memcg and someone forgot to test - minor fixes: missing rcu_read_lock(), scheduling while atomic (in an emergency shutdown path) - two lockdep fixes; these could have gone earlier, but were left to bake awhile ---------------------------------------------------------------- Kent Overstreet (6): bcachefs: Fix RCU splat bcachefs: fix scheduling while atomic in break_cycle() Revert "bcachefs: Mark bch_inode_info as SLAB_ACCOUNT" bcachefs; Use trans_unlock_long() when waiting on allocator bcachefs: Set PF_MEMALLOC_NOFS when trans->locked bcachefs: bch2_gc_btree() should not use btree_root_lock fs/bcachefs/btree_gc.c | 30 ++++++++++++++++++++++-------- fs/bcachefs/btree_iter.c | 7 ++++--- fs/bcachefs/btree_locking.c | 10 ++++------ fs/bcachefs/btree_locking.h | 22 ++++++++++++++++++++++ fs/bcachefs/btree_types.h | 1 + fs/bcachefs/buckets.c | 2 +- fs/bcachefs/buckets.h | 8 ++++++++ fs/bcachefs/fs.c | 3 +-- fs/bcachefs/io_misc.c | 2 +- fs/bcachefs/util.c | 25 ++++++++++++++++++++++--- fs/bcachefs/util.h | 1 + 11 files changed, 87 insertions(+), 24 deletions(-) . Date: Fri, 12 Jul 2024 18:47:43 +0200 From: Ilya Dryomov To: Linus Torvalds Cc: ceph-devel@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [GIT PULL] Ceph fixes for 6.10-rc8 Hi Linus, The following changes since commit 256abd8e550ce977b728be79a74e1729438b4948: Linux 6.10-rc7 (2024-07-07 14:23:46 -0700) are available in the Git repository at: https://github.com/ceph/ceph-client.git tags/ceph-for-6.10-rc8 for you to fetch changes up to 359bc01d2ecc9093216d21cfa03a545c44413cb6: libceph: fix crush_choose_firstn() kernel-doc warnings (2024-07-11 16:33:07 +0200) ---------------------------------------------------------------- A fix for a possible use-after-free following "rbd unmap" or "umount" marked for stable and two kernel-doc fixups. ---------------------------------------------------------------- Ilya Dryomov (1): libceph: fix race between delayed_work() and ceph_monc_stop() Jeff Johnson (2): libceph: suppress crush_choose_indep() kernel-doc warnings libceph: fix crush_choose_firstn() kernel-doc warnings net/ceph/crush/mapper.c | 7 +++++-- net/ceph/mon_client.c | 14 ++++++++++++-- 2 files changed, 17 insertions(+), 4 deletions(-) . Date: Fri, 12 Jul 2024 20:48:27 +0200 From: David Sterba To: torvalds@linux-foundation.org Cc: David Sterba , linux-btrfs@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [GIT PULL] Btrfs fixes for 6.10-rc8 Hi, please pull the following branch that fixes a regression in extent map shrinker behaviour. In the past weeks we got reports from users that there are huge latency spikes or freezes. This was bisected to newly added shrinker of extent maps (it was added to fix a build up of the structures in memory). I'm assuming that the freezes would happen to many users after release so I'd like to get it merged now so it's in 6.10. Although the diff size is not small the changes are relatively straightforward, the reporters verified the fixes and we did testing on our side. Please pull, thanks. The fixes: - adjust behaviour under memory pressure and check lock or scheduling conditions, bail out if needed - synchronize tracking of the scanning progress so inode ranges are not skipped or work duplicated - do a delayed iput when scanning a root so evicting an inode does not slow things down in case of lots of dirty data, also fix lockdep warning, a deadlock could happen when writing the dirty data would need to start a transaction ---------------------------------------------------------------- The following changes since commit a56c85fa2d59ab0780514741550edf87989a66e9: btrfs: fix folio refcount in __alloc_dummy_extent_buffer() (2024-07-04 02:19:10 +0200) are available in the Git repository at: git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux.git tags/for-6.10-rc7-tag for you to fetch changes up to 4484940514295b75389f94787f8e179ba6255353: btrfs: avoid races when tracking progress for extent map shrinking (2024-07-11 16:50:54 +0200) ---------------------------------------------------------------- Filipe Manana (3): btrfs: use delayed iput during extent map shrinking btrfs: stop extent map shrinker if reschedule is needed btrfs: avoid races when tracking progress for extent map shrinking fs/btrfs/disk-io.c | 2 + fs/btrfs/extent_map.c | 123 +++++++++++++++++++++++++++++++++---------- fs/btrfs/fs.h | 1 + include/trace/events/btrfs.h | 18 ++++--- 4 files changed, 107 insertions(+), 37 deletions(-) . Date: Fri, 12 Jul 2024 16:56:50 -0700 From: Sean Christopherson To: Paolo Bonzini Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Sean Christopherson Subject: [GIT PULL] KVM: x86 pull requests for 6.11 There's a trivial conflict between "misc" and "vmx" in kvm-x86-ops.h, they both delete ops that happen to be _right_ next to each other. Otherwise, should apply cleanly. . Date: Sat, 13 Jul 2024 09:38:42 +0200 From: Andi Shyti To: Wolfram Sang Cc: linux-i2c , lkml Subject: [GIT PULL] i2c-host-fixes for v6.10-rc8 Hi Wolfram, Three fixes from you in this pull request, you definitely don't need an introduction to them :-) Thanks, Andi The following changes since commit 256abd8e550ce977b728be79a74e1729438b4948: Linux 6.10-rc7 (2024-07-07 14:23:46 -0700) are available in the Git repository at: git://git.kernel.org/pub/scm/linux/kernel/git/andi.shyti/linux.git tags/i2c-host-fixes-6.10-rc8 for you to fetch changes up to ea5ea84c9d3570dc06e8fc5ee2273eaa584aa3ac: i2c: rcar: ensure Gen3+ reset does not disturb local targets (2024-07-12 01:45:08 +0200) ---------------------------------------------------------------- This tag includes three fixes for the Renesas R-Car driver: 1. Ensures the device is in a known state after probing. 2. Allows clearing the NO_RXDMA flag after a reset. 3. Forces a reset before any transfer on Gen3+ platforms to prevent disruption of the configuration during parallel transfers. ---------------------------------------------------------------- Wolfram Sang (3): i2c: rcar: bring hardware to known state when probing i2c: rcar: clear NO_RXDMA flag after resetting i2c: rcar: ensure Gen3+ reset does not disturb local targets drivers/i2c/busses/i2c-rcar.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) . Date: Sat, 13 Jul 2024 10:57:45 +0200 From: Andi Shyti To: Wolfram Sang Cc: linux-i2c , lkml , Andi Shyti Subject: [GIT PULL] i2c-host for v6.11 Hi Wolfram, Not a massive pull request. The majority of changes relate to the naming convention updates. Other than that, the holiday period has given us some slack in the number of patches queued for this pull request. There is still one pending documentation fix required for an issue reported by Stephen that I haven't noticed. I need to add the documentation check to my workflow. If you don't have the bandwidth, I can take care of it. I also have a pending patch for a v2 pull request from Hans de Goede ("i2c: i801: Use a different adapter name for IDF adapters") that is waiting for precedence. I wish you a great rest of the weekend, Andi The following changes since commit 256abd8e550ce977b728be79a74e1729438b4948: Linux 6.10-rc7 (2024-07-07 14:23:46 -0700) are available in the Git repository at: git://git.kernel.org/pub/scm/linux/kernel/git/andi.shyti/linux.git tags/i2c-host-6.11 for you to fetch changes up to ab1c7ea48f6e225aa40eff3be45a47c7d93cb3b8: dt-bindings: i2c: amlogic,meson6-i2c: add optional power-domains (2024-07-12 01:57:57 +0200) ---------------------------------------------------------------- This release includes significant updates, with the primary change being the renaming from "master/slave" to "controller/target" to adhere to I2C v7 and SMBus 3.2 standards. New Support: - Added support for Intel Arrow Lake-H. - Added I2C support in the Arioha SoC by linking the Mediatek I2C controller. Cleanups: - Added the MODULE_DESCRIPTION() macro, resolving a modpost warning in the ALi 1563 Southbridge driver. - Constified the regmap_config declaration in the i2c-designware driver. - Improved the coding style in the Renesas R-Car driver by removing unnecessary semicolons after brackets. General improvements: - In the OMAP device, replaced NOIRQ_SYSTEM_SLEEP_PM_OPS with RUNTIME_PM_OPS to enable waking up the controller during suspend() before suspend_noirq() kicks in. - Improved logging in the Xilinx driver. - Added a warning (WARN()) in the Renesas R-Car driver for spurious interrupts. DTS Changes: - Removed address-cell and size-cell from the Atmel at91sam, nVidia Tegra 20, and Samsung S3c2410 devices. - Fixed Texas Instruments OMAP4 I2C controller to comply with the i2c-controller.yaml schema. - Improved indentation in DTS examples for several I2C devices. - Converted the NXP LPC1788 binding to the dt-schema. - Added documentation for the compatible string thead,th1520-i2c. - Added the "power-domains" property for the Meson I2C driver. ---------------------------------------------------------------- George Stark (1): dt-bindings: i2c: amlogic,meson6-i2c: add optional power-domains Jarkko Nikula (1): i2c: i801: Add support for Intel Arrow Lake-H Javier Carrasco (1): i2c: designware: Constify read-only struct regmap_config Jeff Johnson (1): i2c: add missing MODULE_DESCRIPTION() macros Kanak Shilledar (1): dt-bindings: i2c: nxp,lpc1788-i2c: convert to dt schema Krzysztof Kozlowski (5): dt-bindings: i2c: atmel,at91sam: drop unneeded address/size-cells dt-bindings: i2c: nvidia,tegra20: drop unneeded address/size-cells dt-bindings: i2c: samsung,s3c2410: drop unneeded address/size-cells dt-bindings: i2c: ti,omap4: reference i2c-controller.yaml schema dt-bindings: i2c: adjust indentation in DTS example to coding style Lorenzo Bianconi (1): i2c: mt7621: Add Airoha EN7581 i2c support Marc Ferland (1): i2c: xiic: improve error message when transfer fails to start Nicolas Ferre (1): dt-bindings: i2c: at91: Add sama7d65 compatible string Thomas Bonnefille (1): dt-bindings: i2c: dw: Document compatible thead,th1520-i2c Thomas Richard (2): i2c: omap: switch to NOIRQ_SYSTEM_SLEEP_PM_OPS() and RUNTIME_PM_OPS() i2c: omap: wakeup the controller during suspend() callback Wolfram Sang (62): i2c: rcar: WARN about spurious irqs i2c: rcar: minor changes to adhere to coding style i2c: reword i2c_algorithm according to newest specification i2c: ali15x3: reword according to newest specification i2c: altera: reword according to newest specification i2c: au1550: reword according to newest specification i2c: bcm-kona: reword according to newest specification i2c: bcm2835: reword according to newest specification i2c: brcmstb: reword according to newest specification i2c: cht-wc: reword according to newest specification i2c: cp2615: reword according to newest specification i2c: cros-ec-tunnel: reword according to newest specification i2c: davinci: reword according to newest specification i2c: digicolor: reword according to newest specification i2c: diolan-u2c: reword according to newest specification i2c: dln2: reword according to newest specification i2c: fsi: reword according to newest specification i2c: gpio: reword according to newest specification i2c: highlander: reword according to newest specification i2c: hisi: reword according to newest specification i2c: hix5hd2: reword according to newest specification i2c: i801: reword according to newest specification i2c: ibm_iic: reword according to newest specification i2c: iop3xx: reword according to newest specification i2c: isch: reword according to newest specification i2c: jz4780: reword according to newest specification i2c: kempld: reword according to newest specification i2c: ljca: reword according to newest specification i2c: lpc2k: reword according to newest specification i2c: ls2x: reword according to newest specification i2c: mlxcpld: reword according to newest specification i2c: mpc: reword according to newest specification i2c: mt7621: reword according to newest specification i2c: mv64xxx: reword according to newest specification i2c: ocores: reword according to newest specification i2c: octeon: reword according to newest specification i2c: opal: reword according to newest specification i2c: owl: reword according to newest specification i2c: pasemi: reword according to newest specification i2c: piix4: reword according to newest specification i2c: powermac: reword according to newest specification i2c: pxa-pci: reword according to newest specification i2c: riic: reword according to newest specification i2c: rk3x: reword according to newest specification i2c: robotfuzz-osif: reword according to newest specification i2c: rzv2m: reword according to newest specification i2c: sis5595: reword according to newest specification i2c: sprd: reword according to newest specification i2c: stm32f4: reword according to newest specification i2c: sun6i-p2wi: reword according to newest specification i2c: taos-evm: reword according to newest specification i2c: tegra-bpmp: reword according to newest specification i2c: thunderx-pcidrv: reword according to newest specification i2c: tiny-usb: reword according to newest specification i2c: uniphier-f: reword according to newest specification i2c: uniphier: reword according to newest specification i2c: viperboard: reword according to newest specification i2c: viai2c: reword according to newest specification i2c: nvidia-gpu: reword according to newest specification i2c: virtio: reword according to newest specification i2c: cpm: reword according to newest specification i2c: st: reword according to newest specification .../bindings/i2c/amlogic,meson6-i2c.yaml | 3 + .../devicetree/bindings/i2c/atmel,at91sam-i2c.yaml | 10 +- .../devicetree/bindings/i2c/brcm,brcmstb-i2c.yaml | 28 +++--- .../devicetree/bindings/i2c/i2c-demux-pinctrl.yaml | 112 ++++++++++----------- .../devicetree/bindings/i2c/i2c-lpc2k.txt | 33 ------ .../bindings/i2c/nvidia,tegra20-i2c.yaml | 6 -- .../devicetree/bindings/i2c/nxp,lpc1788-i2c.yaml | 54 ++++++++++ .../devicetree/bindings/i2c/renesas,iic-emev2.yaml | 14 +-- .../devicetree/bindings/i2c/renesas,rcar-i2c.yaml | 20 ++-- .../devicetree/bindings/i2c/renesas,riic.yaml | 34 +++---- .../bindings/i2c/renesas,rmobile-iic.yaml | 24 ++--- .../bindings/i2c/samsung,s3c2410-i2c.yaml | 6 -- .../bindings/i2c/snps,designware-i2c.yaml | 4 + .../devicetree/bindings/i2c/st,stm32-i2c.yaml | 66 ++++++------ .../devicetree/bindings/i2c/ti,omap4-i2c.yaml | 64 +++++------- Documentation/i2c/busses/i2c-i801.rst | 1 + MAINTAINERS | 2 +- drivers/i2c/busses/Kconfig | 3 +- drivers/i2c/busses/i2c-ali1563.c | 1 + drivers/i2c/busses/i2c-ali15x3.c | 2 +- drivers/i2c/busses/i2c-altera.c | 4 +- drivers/i2c/busses/i2c-au1550.c | 15 ++- drivers/i2c/busses/i2c-bcm-kona.c | 13 ++- drivers/i2c/busses/i2c-bcm2835.c | 10 +- drivers/i2c/busses/i2c-brcmstb.c | 11 +- drivers/i2c/busses/i2c-ccgx-ucsi.c | 1 + drivers/i2c/busses/i2c-cht-wc.c | 8 +- drivers/i2c/busses/i2c-cp2615.c | 10 +- drivers/i2c/busses/i2c-cpm.c | 4 +- drivers/i2c/busses/i2c-cros-ec-tunnel.c | 4 +- drivers/i2c/busses/i2c-davinci.c | 17 ++-- drivers/i2c/busses/i2c-designware-platdrv.c | 2 +- drivers/i2c/busses/i2c-digicolor.c | 6 +- drivers/i2c/busses/i2c-diolan-u2c.c | 2 +- drivers/i2c/busses/i2c-dln2.c | 4 +- drivers/i2c/busses/i2c-fsi.c | 56 +++++------ drivers/i2c/busses/i2c-gpio.c | 8 +- drivers/i2c/busses/i2c-highlander.c | 2 +- drivers/i2c/busses/i2c-hisi.c | 8 +- drivers/i2c/busses/i2c-hix5hd2.c | 6 +- drivers/i2c/busses/i2c-i801.c | 15 +-- drivers/i2c/busses/i2c-ibm_iic.c | 27 ++--- drivers/i2c/busses/i2c-iop3xx.c | 15 ++- drivers/i2c/busses/i2c-isch.c | 2 +- drivers/i2c/busses/i2c-jz4780.c | 4 +- drivers/i2c/busses/i2c-kempld.c | 4 +- drivers/i2c/busses/i2c-ljca.c | 20 ++-- drivers/i2c/busses/i2c-lpc2k.c | 10 +- drivers/i2c/busses/i2c-ls2x.c | 11 +- drivers/i2c/busses/i2c-mlxcpld.c | 14 +-- drivers/i2c/busses/i2c-mpc.c | 4 +- drivers/i2c/busses/i2c-mt7621.c | 26 ++--- drivers/i2c/busses/i2c-mv64xxx.c | 12 +-- drivers/i2c/busses/i2c-nvidia-gpu.c | 7 +- drivers/i2c/busses/i2c-ocores.c | 8 +- drivers/i2c/busses/i2c-octeon-core.c | 6 +- drivers/i2c/busses/i2c-octeon-core.h | 4 +- drivers/i2c/busses/i2c-octeon-platdrv.c | 2 +- drivers/i2c/busses/i2c-omap.c | 36 +++++-- drivers/i2c/busses/i2c-opal.c | 10 +- drivers/i2c/busses/i2c-owl.c | 12 +-- drivers/i2c/busses/i2c-pasemi-core.c | 6 +- drivers/i2c/busses/i2c-piix4.c | 2 +- drivers/i2c/busses/i2c-powermac.c | 14 +-- drivers/i2c/busses/i2c-pxa-pci.c | 2 +- drivers/i2c/busses/i2c-pxa.c | 1 + drivers/i2c/busses/i2c-qup.c | 1 + drivers/i2c/busses/i2c-rcar.c | 13 ++- drivers/i2c/busses/i2c-riic.c | 8 +- drivers/i2c/busses/i2c-rk3x.c | 20 ++-- drivers/i2c/busses/i2c-robotfuzz-osif.c | 4 +- drivers/i2c/busses/i2c-rzv2m.c | 12 +-- drivers/i2c/busses/i2c-sis5595.c | 2 +- drivers/i2c/busses/i2c-sprd.c | 16 +-- drivers/i2c/busses/i2c-st.c | 8 +- drivers/i2c/busses/i2c-stm32f4.c | 8 +- drivers/i2c/busses/i2c-sun6i-p2wi.c | 20 ++-- drivers/i2c/busses/i2c-taos-evm.c | 2 +- drivers/i2c/busses/i2c-tegra-bpmp.c | 4 +- drivers/i2c/busses/i2c-thunderx-pcidrv.c | 2 +- drivers/i2c/busses/i2c-tiny-usb.c | 6 +- drivers/i2c/busses/i2c-uniphier-f.c | 26 +++-- drivers/i2c/busses/i2c-uniphier.c | 15 ++- drivers/i2c/busses/i2c-viai2c-common.c | 2 +- drivers/i2c/busses/i2c-viai2c-wmt.c | 8 +- drivers/i2c/busses/i2c-viai2c-zhaoxin.c | 12 +-- drivers/i2c/busses/i2c-viperboard.c | 10 +- drivers/i2c/busses/i2c-virtio.c | 2 +- drivers/i2c/busses/i2c-xiic.c | 9 +- include/linux/i2c.h | 24 ++++- 90 files changed, 604 insertions(+), 582 deletions(-) delete mode 100644 Documentation/devicetree/bindings/i2c/i2c-lpc2k.txt create mode 100644 Documentation/devicetree/bindings/i2c/nxp,lpc1788-i2c.yaml . Date: Sat, 13 Jul 2024 13:53:39 -0500 From: Steve French To: Linus Torvalds Cc: CIFS , LKML Subject: [GIT PULL] smb3 client fix Please pull the following changes since commit 34afb82a3c67f869267a26f593b6f8fc6bf35905: Merge tag '6.10-rc6-smb3-server-fixes' of git://git.samba.org/ksmbd (2024-07-09 08:16:18 -0700) are available in the Git repository at: git://git.samba.org/sfrench/cifs-2.6.git tags/6.10-rc7-smb3-client-fix for you to fetch changes up to d2346e2836318a227057ed41061114cbebee5d2a: cifs: fix setting SecurityFlags to true (2024-07-13 09:24:27 -0500) ---------------------------------------------------------------- small cifs SecurityFlags fix, also for stable ---------------------------------------------------------------- Steve French (1): cifs: fix setting SecurityFlags to true Documentation/admin-guide/cifs/usage.rst | 36 +++++++++++------------------------- fs/smb/client/cifsglob.h | 4 ++-- 2 files changed, 13 insertions(+), 27 deletions(-) -- Thanks, Steve . Date: Sun, 14 Jul 2024 00:43:10 +0200 From: Wolfram Sang To: Linus Torvalds Cc: linux-i2c@vger.kernel.org, linux-kernel@vger.kernel.org, Peter Rosin , Bartosz Golaszewski , Andi Shyti Subject: [PULL REQUEST] i2c-for-6.10-rc8 --zJEu+bkQi7iU23s1 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline The following changes since commit 256abd8e550ce977b728be79a74e1729438b4948: Linux 6.10-rc7 (2024-07-07 14:23:46 -0700) are available in the Git repository at: git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux.git tags/i2c-for-6.10-rc8 for you to fetch changes up to 3fdd2d21f1c7f0203575b46d2b3fba81292992b6: Merge tag 'i2c-host-fixes-6.10-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/andi.shyti/linux into i2c/for-current (2024-07-13 10:50:55 +0200) ---------------------------------------------------------------- Fixes for the I2C testunit, the Renesas R-Car driver and some MAINTAINERS corrections. ---------------------------------------------------------------- Wolfram Sang (9): i2c: rcar: bring hardware to known state when probing i2c: rcar: clear NO_RXDMA flag after resetting MAINTAINERS: delete entries for Thor Thayer MAINTAINERS: VIRTIO I2C loses a maintainer, gains a reviewer i2c: testunit: correct Kconfig description i2c: mark HostNotify target address as used i2c: rcar: ensure Gen3+ reset does not disturb local targets i2c: testunit: avoid re-issued work after read message Merge tag 'i2c-host-fixes-6.10-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/andi.shyti/linux into i2c/for-current with much appreciated quality assurance from ---------------------------------------------------------------- Andi Shyti (1): (Rev.) i2c: testunit: avoid re-issued work after read message MAINTAINERS | 23 +---------------------- drivers/i2c/Kconfig | 2 +- drivers/i2c/busses/i2c-rcar.c | 27 +++++++++++++++++++++------ drivers/i2c/i2c-core-base.c | 1 + drivers/i2c/i2c-slave-testunit.c | 7 +++++++ 5 files changed, 31 insertions(+), 29 deletions(-) --zJEu+bkQi7iU23s1 Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEOZGx6rniZ1Gk92RdFA3kzBSgKbYFAmaTAv4ACgkQFA3kzBSg Kbah8xAAmZtWH8xe4kx0P3VSP/5kv6RrGXWFL43FJRWV/f886VhnOHqmeAwffBsQ TVcegfMk6LP6X3lKv2DhNaowVA0xyeIrVfYbqEgrjUGaRJvjokDLXSBpiB6+tbMJ 1izhs4quXSD0GgnMDD7ito2UZKSMzU4/YNDFVCUIx/bvf+C6u3kJSfrBJz2AvUNR t7gm7k6Il7Fm+s12Hlrg7oNASI1jtIyaH1ughg+a7sgwfyzxCsQXFgH4EQCO0HPW C1q1P/bDmMko75Ig4yQuVfJJkizDXb/QcPHAjclaLP48TnHaPdi8eTkBPdJWm+jC 1Cy1CxZRbqqaO0G6ahmkdghRLgdV6EcNJvyGoX1skjE+YddMrpTXkKTxTPJOQM1x 91YF6jr9gfq8+g76mWM+Yht/vd9Jjajf0f5ZvWvJgdXuP7FyWDg0jAp6Nqbt9Fjd EdX8hLkx/E6g8NbXioSmdQ7TgJRE2vxo/74eExNp09ThHwFsWm9w/gjoruExPRGx MeE93AyTwAM5Bg9oA7EDVrXEdGmKIX/hVbHHKQf9QC62aJzCKjwNO1zsDxaN+YGc FLzuMhyl3YSK4LJpeX7xjavfIwnOs/vU2yI7IYxwe5EP+5YLzWOz6mv70O4Rj4wJ zsyjVtWmrEJpCsWPu58nhGf4UAZ4a0YJMwPia1JZ5enz8t8/CPw= =wLHB -----END PGP SIGNATURE----- --zJEu+bkQi7iU23s1-- . Date: Sun, 14 Jul 2024 11:17:06 +0200 From: Borislav Petkov To: Linus Torvalds Cc: x86-ml , lkml Subject: [GIT PULL] x86/urgent for v6.10 Hi Linus, please pull one final urgent x86 fix for v6.10. AFAIK, nothing weird stands out in x86-land - I think we're ready to go. Thx. --- The following changes since commit 22a40d14b572deb80c0648557f4bd502d7e83826: Linux 6.10-rc6 (2024-06-30 14:40:44 -0700) are available in the Git repository at: git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip tags/x86_urgent_for_v6.10 for you to fetch changes up to ac8b270b61d48fcc61f052097777e3b5e11591e0: x86/bhi: Avoid warning in #DB handler due to BHI mitigation (2024-07-03 13:26:30 +0200) ---------------------------------------------------------------- - Make sure TF is cleared before calling other functions (BHI mitigation in this case) in the SYSENTER compat handler, as otherwise it will warn about being in single-step mode ---------------------------------------------------------------- Alexandre Chartre (1): x86/bhi: Avoid warning in #DB handler due to BHI mitigation arch/x86/entry/entry_64_compat.S | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) -- Regards/Gruss, Boris. https://people.kernel.org/tglx/notes-about-netiquette . Date: Sun, 14 Jul 2024 11:31:30 +0200 From: Borislav Petkov To: Linus Torvalds Cc: x86-ml , lkml Subject: [GIT PULL] sched/urgent for v6.10 Hi Linus, please pull the last three sched urgent fixes for v6.10. Thx. --- The following changes since commit f2661062f16b2de5d7b6a5c42a9a5c96326b8454: Linux 6.10-rc5 (2024-06-23 17:08:54 -0400) are available in the Git repository at: git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip tags/sched_urgent_for_v6.10 for you to fetch changes up to ddae0ca2a8fe12d0e24ab10ba759c3fbd755ada8: sched: Move psi_account_irqtime() out of update_rq_clock_task() hotpath (2024-07-01 13:01:44 +0200) ---------------------------------------------------------------- - Fix a performance regression when measuring the CPU time of a thread (clock_gettime(CLOCK_THREAD_CPUTIME_ID,...)) due to the addition of PSI IRQ time accounting in the hotpath - Fix a task_struct leak due to missing to decrement the refcount when the task is enqueued before the timer which is supposed to do that, expires - Revert an attempt to expedite detaching of movable tasks, as finding those could become very costly. Turns out the original issue wasn't even hit by anyone ---------------------------------------------------------------- John Stultz (1): sched: Move psi_account_irqtime() out of update_rq_clock_task() hotpath Josh Don (1): Revert "sched/fair: Make sure to try to detach at least one movable task" Wander Lairson Costa (1): sched/deadline: Fix task_struct reference leak kernel/sched/core.c | 7 +++++-- kernel/sched/deadline.c | 7 ++++++- kernel/sched/fair.c | 12 +++--------- kernel/sched/psi.c | 21 ++++++++++++++++----- kernel/sched/sched.h | 1 + kernel/sched/stats.h | 11 ++++++++--- 6 files changed, 39 insertions(+), 20 deletions(-) -- Regards/Gruss, Boris. https://people.kernel.org/tglx/notes-about-netiquette . Date: Sun, 14 Jul 2024 09:21:45 -0700 From: "Paul E. McKenney" To: torvalds@linux-foundation.org Cc: linux-kernel@vger.kernel.org, linux-arch@vger.kernel.org, linux-arm-kernel@lists.infradead.org, kernel-team@meta.com, elver@google.com, akpm@linux-foundation.org, tglx@linutronix.de, peterz@infradead.org, arnd@arndb.de, broonie@kernel.org, naresh.kamboju@linaro.org, nathan@kernel.org, linus.walleij@linaro.org, rmk+kernel@armlinux.org.uk, afd@ti.com, eric.devolder@oracle.com, robh@kernel.org, mark.rutland@arm.com Subject: [GIT PULL] Emulated one-byte cmpxchg() for ARM Hello, Linux, Please pull the following cmpxchg()-related changes: git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu.git tags/cmpxchg.2024.07.12a # HEAD: f1b5644862c5b594f48ad01d7880a96b95d83a2f: ARM: Emulate one-byte cmpxchg (2024-07-04 13:32:41 -0700) ---------------------------------------------------------------- ARM: Provide one-byte cmpxchg emulation This series provides emulated one-byte cmpxchg() support for ARM using the cmpxchg_emu_u8() function that uses a four-byte cmpxchg() to emulate the one-byte variant. Similar patches for emulation of one-byte cmpxchg() for arc, sh, and xtensa have not yet received maintainer acks, so they are slated for the v6.12 merge window. ---------------------------------------------------------------- Paul E. McKenney (1): ARM: Emulate one-byte cmpxchg arch/arm/Kconfig | 1 + arch/arm/include/asm/cmpxchg.h | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) . Date: Sun, 14 Jul 2024 09:28:43 -0700 From: "Paul E. McKenney" To: torvalds@linux-foundation.org Cc: linux-kernel@vger.kernel.org, linux-arch@vger.kernel.org, lkmm@lists.linux.dev, stern@rowland.harvard.edu, parri.andrea@gmail.com, will@kernel.org, peterz@infradead.org, boqun.feng@gmail.com, npiggin@gmail.com, dhowells@redhat.com, j.alglave@ucl.ac.uk, luc.maranget@inria.fr, akiyks@gmail.com, dlustig@nvidia.com, joel@joelfernandes.org Subject: [GIT PULL] LKMM changes for v6.11 Hello, Linux, When the merge window opens, please pull this LKMM update from: git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu.git tags/lkmm.2024.07.12a # HEAD: ea6ee1bac6034cb4e91bcc229ed1354ca1a024d5: tools/memory-model: Code reorganization in lock.cat (2024-06-06 11:24:58 -0700) ---------------------------------------------------------------- lkmm: Fix corner-case locking bug and improve documentation A simple but odd single-process litmus test acquires and immediately releases a lock, then calls spin_is_locked(). LKMM acts if it was a deadlock due to an assumption that spin_is_locked() will follow a spin_lock() or some other process's spin_unlock(). This litmus test manages to violate this assumption because the spin_is_locked() follows the same process's spin_unlock(). This series fixes this bug, reorganizes and optimizes the lock.cat model, and updates documentation. ---------------------------------------------------------------- Alan Stern (2): tools/memory-model: Fix bug in lock.cat tools/memory-model: Code reorganization in lock.cat Paul E. McKenney (2): tools/memory-model: Add KCSAN LF mentorship session citation tools/memory-model: Add access-marking.txt to README tools/memory-model/Documentation/README | 4 ++ .../memory-model/Documentation/access-marking.txt | 10 ++-- tools/memory-model/lock.cat | 62 +++++++++++++--------- 3 files changed, 49 insertions(+), 27 deletions(-) . Date: Sun, 14 Jul 2024 09:37:08 -0700 From: "Paul E. McKenney" To: torvalds@linux-foundation.org Cc: linux-kernel@vger.kernel.org, rcu@vger.kernel.org, kernel-team@meta.com Subject: [GIT PULL] Generic torture-test changes for v6.11 Hello, Linus, When the merge window opens, please pull this generic torture-test update from: git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu.git tags/torture.2024.07.12a # HEAD: d4641fa67d3dcc24d108cbfc4e47d0312ef49947: scftorture: Make torture_type static (2024-05-30 15:31:51 -0700) ---------------------------------------------------------------- Torture-test updates for v6.11 This pull request adds MODULE_DESCRIPTION() to torture.c, locktorture.c, and scftorture.c, and also adds static to a global variable that is used only in scftorture.c. ---------------------------------------------------------------- Jeff Johnson (4): torture: Add MODULE_DESCRIPTION() locktorture: Add MODULE_DESCRIPTION() scftorture: Add MODULE_DESCRIPTION() scftorture: Make torture_type static kernel/locking/locktorture.c | 1 + kernel/scftorture.c | 3 ++- kernel/torture.c | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) . Date: Sun, 14 Jul 2024 09:43:44 -0700 From: "Paul E. McKenney" To: torvalds@linux-foundation.org Cc: linux-kernel@vger.kernel.org, kernel-team@meta.com, mingo@kernel.org, tglx@linutronix.de, rcu@vger.kernel.org, joel@joelfernandes.org, oleg@redhat.com, frederic@kernel.org, qiang.zhang1211@gmail.com, quic_jjohnson@quicinc.com Subject: [GIT PULL] RCU changes for v6.11 Hello, Linus, When the merge window opens, please pull this RCU update from: git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu.git tags/rcu.2024.07.12a # HEAD: 02219caa92b5b0ed97f8d8b9cf580f6f34a9be31: Merge branches 'doc.2024.06.06a', 'fixes.2024.07.04a', 'mb.2024.06.28a', 'nocb.2024.06.03a', 'rcu-tasks.2024.06.06a', 'rcutorture.2024.06.06a' and 'srcu.2024.06.18a' into HEAD (2024-07-04 13:54:17 -0700) ---------------------------------------------------------------- RCU pull request for v6.11 doc.2024.06.06a: Update Tasks RCU and Tasks Rude RCU description in Requirements.rst and clarify rcu_assign_pointer() and rcu_dereference() ordering properties. fixes.2024.07.04a: Add lockdep assertions for RCU readers, limit inline wakeups for callback-bypass synchronize_rcu(), add an rcutree.nohz_full_patience_delay to reduce nohz_full OS jitter, add Uladzislau Rezki as RCU maintainer, and fix a subtle callback-migration memory-ordering issue. mb.2024.06.28a: Remove a number of redundant memory barriers. nocb.2024.06.03a: Remove unnecessary bypass-list lock-contention mitigation, use parking API instead of open-coded ad-hoc equivalent, and upgrade obsolete comments. rcu-tasks.2024.06.06a: Revert avoidance of a deadlock that can no longer occur and properly synchronize Tasks Trace RCU checking of runqueues. rcutorture.2024.06.06a: Add tests for handling of double-call_rcu() bug, add missing MODULE_DESCRIPTION, and add a script that histograms the number of calls to RCU updaters. srcu.2024.06.18a: Fill out SRCU polled-grace-period API. ---------------------------------------------------------------- Frederic Weisbecker (13): rcu/nocb: Fix segcblist state machine comments about bypass rcu/nocb: Fix segcblist state machine stale comments about timers rcu/nocb: Use kthread parking instead of ad-hoc implementation rcu/nocb: Remove buggy bypass lock contention mitigation Revert "rcu-tasks: Fix synchronize_rcu_tasks() VS zap_pid_ns_processes()" rcu/tasks: Fix stale task snaphot for Tasks Trace rcu: Remove full ordering on second EQS snapshot rcu: Remove superfluous full memory barrier upon first EQS snapshot rcu/exp: Remove superfluous full memory barrier upon first EQS snapshot rcu: Remove full memory barrier on boot time eqs sanity check rcu: Remove full memory barrier on RCU stall printout rcu/exp: Remove redundant full memory barrier at the end of GP rcu: Fix rcu_barrier() VS post CPUHP_TEARDOWN_CPU invocation Jeff Johnson (1): rcutorture: Add missing MODULE_DESCRIPTION() macros Joel Fernandes (Google) (1): rcu/tree: Reduce wake up for synchronize_rcu() common case Oleg Nesterov (1): rcu: Eliminate lockless accesses to rcu_sync->gp_count Paul E. McKenney (13): rcu: Add lockdep_assert_in_rcu_read_lock() and friends doc: Update Tasks RCU and Tasks Rude RCU description in Requirements.rst doc: Clarify rcu_assign_pointer() and rcu_dereference() ordering rcutorture: Fix rcu_torture_fwd_cb_cr() data race tools/rcu: Add rcu-updaters.sh script rcu: Disable interrupts directly in rcu_gp_init() srcu: Disable interrupts directly in srcu_gp_end() srcu: Add NUM_ACTIVE_SRCU_POLL_OLDSTATE srcu: Update cleanup_srcu_struct() comment srcu: Fill out polled grace-period APIs rcu: Add rcutree.nohz_full_patience_delay to reduce nohz_full OS jitter MAINTAINERS: Add Uladzislau Rezki as RCU maintainer Merge branches 'doc.2024.06.06a', 'fixes.2024.07.04a', 'mb.2024.06.28a', 'nocb.2024.06.03a', 'rcu-tasks.2024.06.06a', 'rcutorture.2024.06.06a' and 'srcu.2024.06.18a' into HEAD Zqiang (1): rcutorture: Make rcutorture support srcu double call test .../Memory-Ordering/Tree-RCU-Memory-Ordering.rst | 6 +- .../RCU/Design/Requirements/Requirements.rst | 16 +++ Documentation/RCU/whatisRCU.rst | 30 +++-- Documentation/admin-guide/kernel-parameters.txt | 8 ++ MAINTAINERS | 1 + include/linux/rcu_segcblist.h | 88 ++++++------ include/linux/rcupdate.h | 62 ++++++++- include/linux/srcu.h | 35 +++++ kernel/pid_namespace.c | 17 --- kernel/rcu/rcuscale.c | 1 + kernel/rcu/rcutorture.c | 49 ++++--- kernel/rcu/refscale.c | 1 + kernel/rcu/srcutiny.c | 3 +- kernel/rcu/srcutree.c | 13 +- kernel/rcu/sync.c | 12 +- kernel/rcu/tasks.h | 26 ++-- kernel/rcu/tree.c | 92 +++++++++---- kernel/rcu/tree.h | 2 +- kernel/rcu/tree_exp.h | 24 +++- kernel/rcu/tree_nocb.h | 147 ++++++--------------- kernel/rcu/tree_plugin.h | 14 +- kernel/rcu/tree_stall.h | 4 +- kernel/sched/core.c | 14 +- tools/rcu/rcu-updaters.sh | 52 ++++++++ 24 files changed, 439 insertions(+), 278 deletions(-) create mode 100755 tools/rcu/rcu-updaters.sh . Date: Sun, 14 Jul 2024 22:00:50 +0200 From: "Jason A. Donenfeld" To: Linus Torvalds Cc: linux-kernel@vger.kernel.org Subject: [GIT PULL] random number generator updates for 6.11-rc1 Hi Linus, Here's the vDSO getrandom() work we've been discussing for the last few weeks. Thank you very much for your input on this and for working with me to get this where it is. I'm happy with the set of compromises, and I think this wound up in a decent place. A blurb for the merge message: This is a short series adding getrandom() support to the vDSO. First, it adds a new kind of mapping to mmap(2), MAP_DROPPABLE, which lets the kernel zero out pages anytime under memory pressure, which enables allocating memory that never gets swapped to disk but also doesn't count as being mlocked. Then, the vDSO implementation of getrandom() is introduced in a generic manner and hooked into random.c. Next, this is implemented on x86. (Also, though it's not ready for this pull, somebody has begun an arm64 implementation already.) Finally, two vDSO selftests are added. Each version of this series has been in linux-next for a little bit, and there are no major reported issues, though there may be a trivial merge conflict. Please pull, and thanks again for your input on this. Thanks, Jason The following changes since commit 8a18fda0febb7790de20ec1c3b4522ce026be1c6: Merge tag 'spi-fix-v6.10-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi (2024-07-11 12:07:50 -0700) are available in the Git repository at: https://git.kernel.org/pub/scm/linux/kernel/git/crng/random.git tags/random-6.11-rc1-for-linus for you to fetch changes up to 41c32169260827f81a55f5c832c4b334ad4c3586: selftests/vDSO: add tests for vgetrandom (2024-07-12 03:31:01 +0200) ---------------------------------------------------------------- Random number generator updates for Linux 6.11-rc1. ---------------------------------------------------------------- Jason A. Donenfeld (4): mm: add MAP_DROPPABLE for designating always lazily freeable mappings random: introduce generic vDSO getrandom() implementation x86: vdso: Wire up getrandom() vDSO implementation selftests/vDSO: add tests for vgetrandom MAINTAINERS | 4 + arch/x86/Kconfig | 1 + arch/x86/entry/vdso/Makefile | 3 +- arch/x86/entry/vdso/vdso.lds.S | 2 + arch/x86/entry/vdso/vgetrandom-chacha.S | 178 +++++++++++++ arch/x86/entry/vdso/vgetrandom.c | 17 ++ arch/x86/include/asm/vdso/getrandom.h | 55 ++++ arch/x86/include/asm/vdso/vsyscall.h | 2 + arch/x86/include/asm/vvar.h | 16 ++ drivers/char/random.c | 18 +- fs/proc/task_mmu.c | 1 + include/linux/mm.h | 7 + include/linux/userfaultfd_k.h | 3 + include/trace/events/mmflags.h | 7 + include/uapi/linux/mman.h | 1 + include/uapi/linux/random.h | 15 ++ include/vdso/datapage.h | 11 + include/vdso/getrandom.h | 46 ++++ lib/vdso/Kconfig | 5 + lib/vdso/getrandom.c | 251 ++++++++++++++++++ mm/ksm.c | 2 +- mm/madvise.c | 5 +- mm/memory.c | 4 + mm/mempolicy.c | 3 + mm/mlock.c | 2 +- mm/mmap.c | 30 +++ mm/rmap.c | 22 +- mm/vmscan.c | 9 - tools/include/asm/rwonce.h | 0 tools/include/uapi/linux/mman.h | 1 + tools/testing/selftests/mm/.gitignore | 1 + tools/testing/selftests/mm/Makefile | 1 + tools/testing/selftests/mm/droppable.c | 53 ++++ tools/testing/selftests/vDSO/.gitignore | 2 + tools/testing/selftests/vDSO/Makefile | 18 ++ tools/testing/selftests/vDSO/vdso_test_chacha.c | 43 +++ tools/testing/selftests/vDSO/vdso_test_getrandom.c | 288 +++++++++++++++++++++ 37 files changed, 1110 insertions(+), 17 deletions(-) create mode 100644 arch/x86/entry/vdso/vgetrandom-chacha.S create mode 100644 arch/x86/entry/vdso/vgetrandom.c create mode 100644 arch/x86/include/asm/vdso/getrandom.h create mode 100644 include/vdso/getrandom.h create mode 100644 lib/vdso/getrandom.c create mode 100644 tools/include/asm/rwonce.h create mode 100644 tools/testing/selftests/mm/droppable.c create mode 100644 tools/testing/selftests/vDSO/vdso_test_chacha.c create mode 100644 tools/testing/selftests/vDSO/vdso_test_getrandom.c . Date: Mon, 15 Jul 2024 05:30:42 +0900 From: Masahiro Yamada To: Linus Torvalds Cc: Linux Kernel Mailing List , Linux Kbuild mailing list Subject: [GIT PULL] Kbuild fixes for v6.10(-rc8) Hello Linus, Please pull Kbuild fixes for v6.10. Thanks. The following changes since commit 22a40d14b572deb80c0648557f4bd502d7e83826: Linux 6.10-rc6 (2024-06-30 14:40:44 -0700) are available in the Git repository at: git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-kbuild.git tags/kbuild-fixes-v6.10-4 for you to fetch changes up to 84679f04ceafd58d9b35f790203520b2930f1a03: fortify: fix warnings in fortify tests with KASAN (2024-07-15 04:53:49 +0900) ---------------------------------------------------------------- Kbuild fixes for v6.10 (fourth) - Make scripts/ld-version.sh robust against the latest LLD - Fix warnings in rpm-pkg with device tree support - Fix warnings in fortify tests with KASAN ---------------------------------------------------------------- Jose Ignacio Tornos Martinez (1): kbuild: rpm-pkg: avoid the warnings with dtb's listed twice Masahiro Yamada (1): fortify: fix warnings in fortify tests with KASAN Nathan Chancellor (1): kbuild: Make ld-version.sh more robust against version string changes lib/Makefile | 4 ++++ scripts/ld-version.sh | 8 +++++--- scripts/package/kernel.spec | 1 - 3 files changed, 9 insertions(+), 4 deletions(-) -- Best Regards Masahiro Yamada . Date: Sun, 14 Jul 2024 22:50:05 +0200 (CEST) From: Thomas Gleixner To: Linus Torvalds Cc: linux-kernel@vger.kernel.org, x86@kernel.org Subject: [GIT pull] core/debugobjects for v6.11-rc1 Linus, please pull the latest core/debugobjects branch from: git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git core-debugobject= s-2024-07-14 up to: 5b5baba62222: debugobjects: Annotate racy debug variables A single update for debugobjects to annotate all intentionally racy global debug variables so that KCSAN ignores them. Thanks, tglx ------------------> Breno Leitao (1): debugobjects: Annotate racy debug variables lib/debugobjects.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/lib/debugobjects.c b/lib/debugobjects.c index fb12a9bacd2f..7cea91e193a8 100644 --- a/lib/debugobjects.c +++ b/lib/debugobjects.c @@ -78,16 +78,17 @@ static bool obj_freeing; /* The number of objs on the global free list */ static int obj_nr_tofree; =20 -static int debug_objects_maxchain __read_mostly; -static int __maybe_unused debug_objects_maxchecked __read_mostly; -static int debug_objects_fixups __read_mostly; -static int debug_objects_warnings __read_mostly; -static int debug_objects_enabled __read_mostly - =3D CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT; -static int debug_objects_pool_size __read_mostly - =3D ODEBUG_POOL_SIZE; -static int debug_objects_pool_min_level __read_mostly - =3D ODEBUG_POOL_MIN_LEVEL; +static int __data_racy debug_objects_maxchain __read_mostly; +static int __data_racy __maybe_unused debug_objects_maxchecked __read_mostly; +static int __data_racy debug_objects_fixups __read_mostly; +static int __data_racy debug_objects_warnings __read_mostly; +static int __data_racy debug_objects_enabled __read_mostly + =3D CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT; +static int __data_racy debug_objects_pool_size __read_mostly + =3D ODEBUG_POOL_SIZE; +static int __data_racy debug_objects_pool_min_level __read_mostly + =3D ODEBUG_POOL_MIN_LEVEL; + static const struct debug_obj_descr *descr_test __read_mostly; static struct kmem_cache *obj_cache __ro_after_init; =20 . Date: Sun, 14 Jul 2024 22:50:08 +0200 (CEST) From: Thomas Gleixner To: Linus Torvalds Cc: linux-kernel@vger.kernel.org, x86@kernel.org Subject: [GIT pull] smp/core for v6.11-rc1 Linus, please pull the latest smp/core branch from: git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git smp-core-2024-07= -14 up to: 77aeb1b685f9: smp: Add missing destroy_work_on_stack() call in smp_ca= ll_on_cpu() A small set of SMP/CPU hotplug updates: - Reverse the order of iteration when freezing secondary CPUs for hibernation. This avoids that drivers like the Intel uncore performance counter have to transfer the assignement of handling the per package uncore events for every CPU in a package, which is a considerable speedup on larger systems. - Add a missing destroy_work_on_stack() invocation in smp_call_on_cpu() to prevent debug objects to emit a false positive warning when the stack is freed. - Small cleanups in comments and a str_plural() conversion Thanks, tglx ------------------> Costa Shulyupin (1): cpu/hotplug: Fix typo in comment Stanislav Spassov (1): cpu/hotplug: Reverse order of iteration in freeze_secondary_cpus() Thorsten Blum (1): smp: Use str_plural() to fix Coccinelle warnings Zqiang (1): smp: Add missing destroy_work_on_stack() call in smp_call_on_cpu() include/linux/cpuhotplug.h | 2 +- kernel/cpu.c | 4 ++-- kernel/smp.c | 5 +++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h index 7a5785f405b6..7f6c820c12eb 100644 --- a/include/linux/cpuhotplug.h +++ b/include/linux/cpuhotplug.h @@ -27,7 +27,7 @@ * startup callbacks sequentially from CPUHP_OFFLINE + 1 to CPUHP_ONLINE * during a CPU online operation. During a CPU offline operation the * installed teardown callbacks are invoked in the reverse order from - * CPU_ONLINE - 1 down to CPUHP_OFFLINE. + * CPUHP_ONLINE - 1 down to CPUHP_OFFLINE. * * The state space has three sections: PREPARE, STARTING and ONLINE. * diff --git a/kernel/cpu.c b/kernel/cpu.c index 563877d6c28b..1979a9935719 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -1891,8 +1891,8 @@ int freeze_secondary_cpus(int primary) cpumask_clear(frozen_cpus); =20 pr_info("Disabling non-boot CPUs ...\n"); - for_each_online_cpu(cpu) { - if (cpu =3D=3D primary) + for (cpu =3D nr_cpu_ids - 1; cpu >=3D 0; cpu--) { + if (!cpu_online(cpu) || cpu =3D=3D primary) continue; =20 if (pm_wakeup_pending()) { diff --git a/kernel/smp.c b/kernel/smp.c index f085ebcdf9e7..aaffecdad319 100644 --- a/kernel/smp.c +++ b/kernel/smp.c @@ -25,6 +25,7 @@ #include #include #include +#include =20 #include #define CREATE_TRACE_POINTS @@ -982,8 +983,7 @@ void __init smp_init(void) num_nodes =3D num_online_nodes(); num_cpus =3D num_online_cpus(); pr_info("Brought up %d node%s, %d CPU%s\n", - num_nodes, (num_nodes > 1 ? "s" : ""), - num_cpus, (num_cpus > 1 ? "s" : "")); + num_nodes, str_plural(num_nodes), num_cpus, str_plural(num_cpus)); =20 /* Any cleanup work */ smp_cpus_done(setup_max_cpus); @@ -1119,6 +1119,7 @@ int smp_call_on_cpu(unsigned int cpu, int (*func)(void = *), void *par, bool phys) =20 queue_work_on(cpu, system_wq, &sscs.work); wait_for_completion(&sscs.done); + destroy_work_on_stack(&sscs.work); =20 return sscs.ret; } . Date: Sun, 14 Jul 2024 22:50:10 +0200 (CEST) From: Thomas Gleixner To: Linus Torvalds Cc: linux-kernel@vger.kernel.org, x86@kernel.org Subject: [GIT pull] timers/core for v6.11-rc1 Linus, please pull the latest timers/core branch from: git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git timers-core-2024= -07-14 up to: b7625d67eb1a: Merge tag 'timers-v6.11-rc1' of https://git.linaro.org/= people/daniel.lezcano/linux into timers/core Updates for timers, timekeeping and related functionality: - Core: - Make the takeover of a hrtimer based broadcast timer reliable during CPU hot-unplug. The current implementation suffers from a race which can lead to broadcast timer starvation in the worst case. - VDSO related cleanups and simplifications - Small cleanups and enhancements all over the place =20 - PTP: - Replace the architecture specific base clock to clocksource, e.g. ART to TSC, conversion function with generic functionality to avoid exposing such internals to drivers and convert all existing drivers over. This also allows to provide functionality which converts the other way round in the core code based on the same parameter set. - Provide a function to convert CLOCK_REALTIME to the base clock to support the upcoming PPS output driver on Intel platforms. - Drivers: - A set of Device Tree bindings for new hardware - Cleanups and enhancements all over the place Thanks, tglx ------------------> Anna-Maria Behnsen (6): vdso/gettimeofday: Clarify comment about open coded function vdso: Add comment about reason for vdso struct ordering x86/vdso: Fix function reference in comment x86/vgtod: Remove unused typedef gtod_long_t x86/vdso: Remove unused include tick/sched: Combine WARN_ON_ONCE and print_once Chris Packham (2): dt-bindings: timer: Add schema for realtek,otto-timer clocksource/drivers/realtek: Add timer driver for rtl-otto platforms Christian Loehle (1): tick: Remove unnused tick_nohz_get_idle_calls() Geert Uytterhoeven (3): dt-bindings: timer: renesas,tmu: Add R-Mobile APE6 support dt-bindings: timer: renesas,tmu: Add RZ/G1 support dt-bindings: timer: renesas,tmu: Add R-Car Gen2 support Jeff Johnson (1): time: Add MODULE_DESCRIPTION() to time test modules Jiaxun Yang (2): clocksource/drivers/mips-gic-timer: Refine rating computation clocksource/drivers/mips-gic-timer: Correct sched_clock width Lakshmi Sowjanya D (4): timekeeping: Provide infrastructure for converting to/from a base clock x86/tsc: Provide ART base clock information for TSC x86/tsc: Remove obsolete ART to TSC conversion functions timekeeping: Add function to convert realtime to base clock Li kunyu (2): clocksource/drivers/arm_arch_timer: Remove unnecessary =E2=80=980=E2=80= =99 values from irq clocksource/driver/arm_global_timer: Remove unnecessary =E2=80=980=E2= =80=99 values from err Niklas S=C3=B6derlund (1): clocksource/drivers/sh_cmt: Address race condition for clock events Thomas Bonnefille (1): dt-bindings: timer: Add SOPHGO SG2002 clint Thomas Gleixner (5): e1000e: Replace convert_art_to_tsc() igc: Remove convert_art_ns_to_tsc() stmmac: intel: Remove convert_art_to_tsc() ALSA: hda: Remove convert_art_to_tsc() ice/ptp: Remove convert_art_to_tsc() Yang Li (1): timekeeping: Add missing kernel-doc function comments Yu Liao (1): tick/broadcast: Make takeover of broadcast hrtimer reliable .../bindings/timer/realtek,otto-timer.yaml | 63 +++++ .../devicetree/bindings/timer/renesas,tmu.yaml | 12 + .../devicetree/bindings/timer/sifive,clint.yaml | 1 + arch/x86/include/asm/tsc.h | 3 - arch/x86/include/asm/vdso/gettimeofday.h | 5 +- arch/x86/include/asm/vdso/vsyscall.h | 1 - arch/x86/include/asm/vgtod.h | 5 - arch/x86/kernel/tsc.c | 92 ++----- drivers/clocksource/Kconfig | 10 + drivers/clocksource/Makefile | 1 + drivers/clocksource/arm_arch_timer.c | 2 +- drivers/clocksource/arm_global_timer.c | 2 +- drivers/clocksource/mips-gic-timer.c | 20 +- drivers/clocksource/sh_cmt.c | 13 +- drivers/clocksource/timer-rtl-otto.c | 291 +++++++++++++++++++= ++ drivers/net/ethernet/intel/e1000e/ptp.c | 3 +- drivers/net/ethernet/intel/ice/ice_ptp.c | 3 +- drivers/net/ethernet/intel/igc/igc_ptp.c | 6 +- drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c | 3 +- include/linux/clocksource.h | 27 ++ include/linux/clocksource_ids.h | 1 + include/linux/cpuhotplug.h | 1 + include/linux/tick.h | 1 - include/linux/timekeeping.h | 6 + include/vdso/datapage.h | 4 + kernel/time/clocksource-wdtest.c | 1 + kernel/time/test_udelay.c | 1 + kernel/time/tick-broadcast.c | 23 ++ kernel/time/tick-sched.c | 22 +- kernel/time/time_test.c | 1 + kernel/time/timekeeping.c | 131 +++++++++- lib/vdso/gettimeofday.c | 20 +- sound/pci/hda/hda_controller.c | 3 +- 33 files changed, 647 insertions(+), 131 deletions(-) create mode 100644 Documentation/devicetree/bindings/timer/realtek,otto-time= r.yaml create mode 100644 drivers/clocksource/timer-rtl-otto.c diff --git a/Documentation/devicetree/bindings/timer/realtek,otto-timer.yaml = b/Documentation/devicetree/bindings/timer/realtek,otto-timer.yaml new file mode 100644 index 000000000000..7b6ec2c69484 --- /dev/null +++ b/Documentation/devicetree/bindings/timer/realtek,otto-timer.yaml @@ -0,0 +1,63 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/timer/realtek,otto-timer.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Realtek Otto SoCs Timer/Counter + +description: + Realtek SoCs support a number of timers/counters. These are used + as a per CPU clock event generator and an overall CPU clocksource. + +maintainers: + - Chris Packham + +properties: + $nodename: + pattern: "^timer@[0-9a-f]+$" + + compatible: + items: + - enum: + - realtek,rtl9302-timer + - const: realtek,otto-timer + + reg: + items: + - description: timer0 registers + - description: timer1 registers + - description: timer2 registers + - description: timer3 registers + - description: timer4 registers + + clocks: + maxItems: 1 + + interrupts: + items: + - description: timer0 interrupt + - description: timer1 interrupt + - description: timer2 interrupt + - description: timer3 interrupt + - description: timer4 interrupt + +required: + - compatible + - reg + - clocks + - interrupts + +additionalProperties: false + +examples: + - | + timer@3200 { + compatible =3D "realtek,rtl9302-timer", "realtek,otto-timer"; + reg =3D <0x3200 0x10>, <0x3210 0x10>, <0x3220 0x10>, + <0x3230 0x10>, <0x3240 0x10>; + + interrupt-parent =3D <&intc>; + interrupts =3D <7>, <8>, <9>, <10>, <11>; + clocks =3D <&lx_clk>; + }; diff --git a/Documentation/devicetree/bindings/timer/renesas,tmu.yaml b/Docum= entation/devicetree/bindings/timer/renesas,tmu.yaml index 360a5cf1ae9c..b6dd98d956f3 100644 --- a/Documentation/devicetree/bindings/timer/renesas,tmu.yaml +++ b/Documentation/devicetree/bindings/timer/renesas,tmu.yaml @@ -21,13 +21,24 @@ properties: compatible: items: - enum: + - renesas,tmu-r8a73a4 # R-Mobile APE6 - renesas,tmu-r8a7740 # R-Mobile A1 + - renesas,tmu-r8a7742 # RZ/G1H + - renesas,tmu-r8a7743 # RZ/G1M + - renesas,tmu-r8a7744 # RZ/G1N + - renesas,tmu-r8a7745 # RZ/G1E + - renesas,tmu-r8a77470 # RZ/G1C - renesas,tmu-r8a774a1 # RZ/G2M - renesas,tmu-r8a774b1 # RZ/G2N - renesas,tmu-r8a774c0 # RZ/G2E - renesas,tmu-r8a774e1 # RZ/G2H - renesas,tmu-r8a7778 # R-Car M1A - renesas,tmu-r8a7779 # R-Car H1 + - renesas,tmu-r8a7790 # R-Car H2 + - renesas,tmu-r8a7791 # R-Car M2-W + - renesas,tmu-r8a7792 # R-Car V2H + - renesas,tmu-r8a7793 # R-Car M2-N + - renesas,tmu-r8a7794 # R-Car E2 - renesas,tmu-r8a7795 # R-Car H3 - renesas,tmu-r8a7796 # R-Car M3-W - renesas,tmu-r8a77961 # R-Car M3-W+ @@ -94,6 +105,7 @@ if: compatible: contains: enum: + - renesas,tmu-r8a73a4 - renesas,tmu-r8a7740 - renesas,tmu-r8a7778 - renesas,tmu-r8a7779 diff --git a/Documentation/devicetree/bindings/timer/sifive,clint.yaml b/Docu= mentation/devicetree/bindings/timer/sifive,clint.yaml index fced6f2d8ecb..b42d43d2de48 100644 --- a/Documentation/devicetree/bindings/timer/sifive,clint.yaml +++ b/Documentation/devicetree/bindings/timer/sifive,clint.yaml @@ -40,6 +40,7 @@ properties: - allwinner,sun20i-d1-clint - sophgo,cv1800b-clint - sophgo,cv1812h-clint + - sophgo,sg2002-clint - thead,th1520-clint - const: thead,c900-clint - items: diff --git a/arch/x86/include/asm/tsc.h b/arch/x86/include/asm/tsc.h index 405efb3e4996..94408a784c8e 100644 --- a/arch/x86/include/asm/tsc.h +++ b/arch/x86/include/asm/tsc.h @@ -28,9 +28,6 @@ static inline cycles_t get_cycles(void) } #define get_cycles get_cycles =20 -extern struct system_counterval_t convert_art_to_tsc(u64 art); -extern struct system_counterval_t convert_art_ns_to_tsc(u64 art_ns); - extern void tsc_early_init(void); extern void tsc_init(void); extern void mark_tsc_unstable(char *reason); diff --git a/arch/x86/include/asm/vdso/gettimeofday.h b/arch/x86/include/asm/= vdso/gettimeofday.h index 0ef36190abe6..b2d2df026f6e 100644 --- a/arch/x86/include/asm/vdso/gettimeofday.h +++ b/arch/x86/include/asm/vdso/gettimeofday.h @@ -328,9 +328,8 @@ static __always_inline u64 vdso_calc_ns(const struct vdso= _data *vd, u64 cycles, * due to unsigned comparison. * * Due to the MSB/Sign-bit being used as invalid marker (see - * arch_vdso_cycles_valid() above), the effective mask is S64_MAX, - * but that case is also unlikely and will also take the unlikely path - * here. + * arch_vdso_cycles_ok() above), the effective mask is S64_MAX, but that + * case is also unlikely and will also take the unlikely path here. */ if (unlikely(delta > vd->max_cycles)) { /* diff --git a/arch/x86/include/asm/vdso/vsyscall.h b/arch/x86/include/asm/vdso= /vsyscall.h index be199a9b2676..93226281b450 100644 --- a/arch/x86/include/asm/vdso/vsyscall.h +++ b/arch/x86/include/asm/vdso/vsyscall.h @@ -4,7 +4,6 @@ =20 #ifndef __ASSEMBLY__ =20 -#include #include #include #include diff --git a/arch/x86/include/asm/vgtod.h b/arch/x86/include/asm/vgtod.h index 7aa38b2ad8a9..a0ce291abcae 100644 --- a/arch/x86/include/asm/vgtod.h +++ b/arch/x86/include/asm/vgtod.h @@ -14,11 +14,6 @@ =20 #include =20 -#ifdef BUILD_VDSO32_64 -typedef u64 gtod_long_t; -#else -typedef unsigned long gtod_long_t; -#endif #endif /* CONFIG_GENERIC_GETTIMEOFDAY */ =20 #endif /* _ASM_X86_VGTOD_H */ diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index 06b170759e5b..d4462fb26299 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -50,9 +50,9 @@ int tsc_clocksource_reliable; =20 static int __read_mostly tsc_force_recalibrate; =20 -static u32 art_to_tsc_numerator; -static u32 art_to_tsc_denominator; -static u64 art_to_tsc_offset; +static struct clocksource_base art_base_clk =3D { + .id =3D CSID_X86_ART, +}; static bool have_art; =20 struct cyc2ns { @@ -1074,7 +1074,7 @@ core_initcall(cpufreq_register_tsc_scaling); */ static void __init detect_art(void) { - unsigned int unused[2]; + unsigned int unused; =20 if (boot_cpu_data.cpuid_level < ART_CPUID_LEAF) return; @@ -1089,13 +1089,14 @@ static void __init detect_art(void) tsc_async_resets) return; =20 - cpuid(ART_CPUID_LEAF, &art_to_tsc_denominator, - &art_to_tsc_numerator, unused, unused+1); + cpuid(ART_CPUID_LEAF, &art_base_clk.denominator, + &art_base_clk.numerator, &art_base_clk.freq_khz, &unused); =20 - if (art_to_tsc_denominator < ART_MIN_DENOMINATOR) + art_base_clk.freq_khz /=3D KHZ; + if (art_base_clk.denominator < ART_MIN_DENOMINATOR) return; =20 - rdmsrl(MSR_IA32_TSC_ADJUST, art_to_tsc_offset); + rdmsrl(MSR_IA32_TSC_ADJUST, art_base_clk.offset); =20 /* Make this sticky over multiple CPU init calls */ setup_force_cpu_cap(X86_FEATURE_ART); @@ -1296,67 +1297,6 @@ int unsynchronized_tsc(void) return 0; } =20 -/* - * Convert ART to TSC given numerator/denominator found in detect_art() - */ -struct system_counterval_t convert_art_to_tsc(u64 art) -{ - u64 tmp, res, rem; - - rem =3D do_div(art, art_to_tsc_denominator); - - res =3D art * art_to_tsc_numerator; - tmp =3D rem * art_to_tsc_numerator; - - do_div(tmp, art_to_tsc_denominator); - res +=3D tmp + art_to_tsc_offset; - - return (struct system_counterval_t) { - .cs_id =3D have_art ? CSID_X86_TSC : CSID_GENERIC, - .cycles =3D res, - }; -} -EXPORT_SYMBOL(convert_art_to_tsc); - -/** - * convert_art_ns_to_tsc() - Convert ART in nanoseconds to TSC. - * @art_ns: ART (Always Running Timer) in unit of nanoseconds - * - * PTM requires all timestamps to be in units of nanoseconds. When user - * software requests a cross-timestamp, this function converts system timest= amp - * to TSC. - * - * This is valid when CPU feature flag X86_FEATURE_TSC_KNOWN_FREQ is set - * indicating the tsc_khz is derived from CPUID[15H]. Drivers should check - * that this flag is set before conversion to TSC is attempted. - * - * Return: - * struct system_counterval_t - system counter value with the ID of the - * corresponding clocksource: - * cycles: System counter value - * cs_id: The clocksource ID for validating comparability - */ - -struct system_counterval_t convert_art_ns_to_tsc(u64 art_ns) -{ - u64 tmp, res, rem; - - rem =3D do_div(art_ns, USEC_PER_SEC); - - res =3D art_ns * tsc_khz; - tmp =3D rem * tsc_khz; - - do_div(tmp, USEC_PER_SEC); - res +=3D tmp; - - return (struct system_counterval_t) { - .cs_id =3D have_art ? CSID_X86_TSC : CSID_GENERIC, - .cycles =3D res, - }; -} -EXPORT_SYMBOL(convert_art_ns_to_tsc); - - static void tsc_refine_calibration_work(struct work_struct *work); static DECLARE_DELAYED_WORK(tsc_irqwork, tsc_refine_calibration_work); /** @@ -1458,8 +1398,10 @@ static void tsc_refine_calibration_work(struct work_st= ruct *work) if (tsc_unstable) goto unreg; =20 - if (boot_cpu_has(X86_FEATURE_ART)) + if (boot_cpu_has(X86_FEATURE_ART)) { have_art =3D true; + clocksource_tsc.base =3D &art_base_clk; + } clocksource_register_khz(&clocksource_tsc, tsc_khz); unreg: clocksource_unregister(&clocksource_tsc_early); @@ -1484,8 +1426,10 @@ static int __init init_tsc_clocksource(void) * the refined calibration and directly register it as a clocksource. */ if (boot_cpu_has(X86_FEATURE_TSC_KNOWN_FREQ)) { - if (boot_cpu_has(X86_FEATURE_ART)) + if (boot_cpu_has(X86_FEATURE_ART)) { have_art =3D true; + clocksource_tsc.base =3D &art_base_clk; + } clocksource_register_khz(&clocksource_tsc, tsc_khz); clocksource_unregister(&clocksource_tsc_early); =20 @@ -1509,10 +1453,12 @@ static bool __init determine_cpu_tsc_frequencies(bool= early) =20 if (early) { cpu_khz =3D x86_platform.calibrate_cpu(); - if (tsc_early_khz) + if (tsc_early_khz) { tsc_khz =3D tsc_early_khz; - else + } else { tsc_khz =3D x86_platform.calibrate_tsc(); + clocksource_tsc.freq_khz =3D tsc_khz; + } } else { /* We should not be here with non-native cpu calibration */ WARN_ON(x86_platform.calibrate_cpu !=3D native_calibrate_cpu); diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 34faa0320ece..95dd4660b5b6 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -134,6 +134,16 @@ config RDA_TIMER help Enables the support for the RDA Micro timer driver. =20 +config REALTEK_OTTO_TIMER + bool "Clocksource/timer for the Realtek Otto platform" if COMPILE_TEST + select TIMER_OF + help + This driver adds support for the timers found in the Realtek RTL83xx + and RTL93xx SoCs series. This includes chips such as RTL8380, RTL8381 + and RTL832, as well as chips from the RTL839x series, such as RTL8390 + RT8391, RTL8392, RTL8393 and RTL8396 and chips of the RTL930x series + such as RTL9301, RTL9302 or RTL9303. + config SUN4I_TIMER bool "Sun4i timer driver" if COMPILE_TEST depends on HAS_IOMEM diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index 4bb856e4df55..22743785299e 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -59,6 +59,7 @@ obj-$(CONFIG_MILBEAUT_TIMER) +=3D timer-milbeaut.o obj-$(CONFIG_SPRD_TIMER) +=3D timer-sprd.o obj-$(CONFIG_NPCM7XX_TIMER) +=3D timer-npcm7xx.o obj-$(CONFIG_RDA_TIMER) +=3D timer-rda.o +obj-$(CONFIG_REALTEK_OTTO_TIMER) +=3D timer-rtl-otto.o =20 obj-$(CONFIG_ARC_TIMERS) +=3D arc_timer.o obj-$(CONFIG_ARM_ARCH_TIMER) +=3D arm_arch_timer.o diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_a= rch_timer.c index 5bb43cc1a8df..aeafc74181f0 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -1556,7 +1556,7 @@ static int __init arch_timer_mem_frame_register(struct arch_timer_mem_frame *frame) { void __iomem *base; - int ret, irq =3D 0; + int ret, irq; =20 if (arch_timer_mem_use_virtual) irq =3D frame->virt_irq; diff --git a/drivers/clocksource/arm_global_timer.c b/drivers/clocksource/arm= _global_timer.c index ab1c8c2b66b8..a05cfaab5f84 100644 --- a/drivers/clocksource/arm_global_timer.c +++ b/drivers/clocksource/arm_global_timer.c @@ -343,7 +343,7 @@ static int __init global_timer_of_register(struct device_= node *np) { struct clk *gt_clk; static unsigned long gt_clk_rate; - int err =3D 0; + int err; =20 /* * In A9 r2p0 the comparators for each processor with the global timer diff --git a/drivers/clocksource/mips-gic-timer.c b/drivers/clocksource/mips-= gic-timer.c index b3ae38f36720..110347707ff9 100644 --- a/drivers/clocksource/mips-gic-timer.c +++ b/drivers/clocksource/mips-gic-timer.c @@ -19,6 +19,7 @@ static DEFINE_PER_CPU(struct clock_event_device, gic_clockevent_device); static int gic_timer_irq; static unsigned int gic_frequency; +static unsigned int gic_count_width; static bool __read_mostly gic_clock_unstable; =20 static void gic_clocksource_unstable(char *reason); @@ -186,18 +187,21 @@ static void gic_clocksource_unstable(char *reason) =20 static int __init __gic_clocksource_init(void) { - unsigned int count_width; int ret; =20 /* Set clocksource mask. */ - count_width =3D read_gic_config() & GIC_CONFIG_COUNTBITS; - count_width >>=3D __ffs(GIC_CONFIG_COUNTBITS); - count_width *=3D 4; - count_width +=3D 32; - gic_clocksource.mask =3D CLOCKSOURCE_MASK(count_width); + gic_count_width =3D read_gic_config() & GIC_CONFIG_COUNTBITS; + gic_count_width >>=3D __ffs(GIC_CONFIG_COUNTBITS); + gic_count_width *=3D 4; + gic_count_width +=3D 32; + gic_clocksource.mask =3D CLOCKSOURCE_MASK(gic_count_width); =20 /* Calculate a somewhat reasonable rating value. */ - gic_clocksource.rating =3D 200 + gic_frequency / 10000000; + if (mips_cm_revision() >=3D CM_REV_CM3 || !IS_ENABLED(CONFIG_CPU_FREQ)) + gic_clocksource.rating =3D 300; /* Good when frequecy is stable */ + else + gic_clocksource.rating =3D 200; + gic_clocksource.rating +=3D clamp(gic_frequency / 10000000, 0, 99); =20 ret =3D clocksource_register_hz(&gic_clocksource, gic_frequency); if (ret < 0) @@ -260,7 +264,7 @@ static int __init gic_clocksource_of_init(struct device_n= ode *node) if (mips_cm_revision() >=3D CM_REV_CM3 || !IS_ENABLED(CONFIG_CPU_FREQ)) { sched_clock_register(mips_cm_is64 ? gic_read_count_64 : gic_read_count_2x32, - 64, gic_frequency); + gic_count_width, gic_frequency); } =20 return 0; diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c index 26919556ef5f..b72b36e0abed 100644 --- a/drivers/clocksource/sh_cmt.c +++ b/drivers/clocksource/sh_cmt.c @@ -528,6 +528,7 @@ static void sh_cmt_set_next(struct sh_cmt_channel *ch, un= signed long delta) static irqreturn_t sh_cmt_interrupt(int irq, void *dev_id) { struct sh_cmt_channel *ch =3D dev_id; + unsigned long flags; =20 /* clear flags */ sh_cmt_write_cmcsr(ch, sh_cmt_read_cmcsr(ch) & @@ -558,6 +559,8 @@ static irqreturn_t sh_cmt_interrupt(int irq, void *dev_id) =20 ch->flags &=3D ~FLAG_SKIPEVENT; =20 + raw_spin_lock_irqsave(&ch->lock, flags); + if (ch->flags & FLAG_REPROGRAM) { ch->flags &=3D ~FLAG_REPROGRAM; sh_cmt_clock_event_program_verify(ch, 1); @@ -570,6 +573,8 @@ static irqreturn_t sh_cmt_interrupt(int irq, void *dev_id) =20 ch->flags &=3D ~FLAG_IRQCONTEXT; =20 + raw_spin_unlock_irqrestore(&ch->lock, flags); + return IRQ_HANDLED; } =20 @@ -780,12 +785,18 @@ static int sh_cmt_clock_event_next(unsigned long delta, struct clock_event_device *ced) { struct sh_cmt_channel *ch =3D ced_to_sh_cmt(ced); + unsigned long flags; =20 BUG_ON(!clockevent_state_oneshot(ced)); + + raw_spin_lock_irqsave(&ch->lock, flags); + if (likely(ch->flags & FLAG_IRQCONTEXT)) ch->next_match_value =3D delta - 1; else - sh_cmt_set_next(ch, delta - 1); + __sh_cmt_set_next(ch, delta - 1); + + raw_spin_unlock_irqrestore(&ch->lock, flags); =20 return 0; } diff --git a/drivers/clocksource/timer-rtl-otto.c b/drivers/clocksource/timer= -rtl-otto.c new file mode 100644 index 000000000000..8a3068b36e75 --- /dev/null +++ b/drivers/clocksource/timer-rtl-otto.c @@ -0,0 +1,291 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "timer-of.h" + +#define RTTM_DATA 0x0 +#define RTTM_CNT 0x4 +#define RTTM_CTRL 0x8 +#define RTTM_INT 0xc + +#define RTTM_CTRL_ENABLE BIT(28) +#define RTTM_INT_PENDING BIT(16) +#define RTTM_INT_ENABLE BIT(20) + +/* + * The Otto platform provides multiple 28 bit timers/counters with the follo= wing + * operating logic. If enabled the timer counts up. Per timer one can set a + * maximum counter value as an end marker. If end marker is reached the timer + * fires an interrupt. If the timer "overflows" by reaching the end marker or + * by adding 1 to 0x0fffffff the counter is reset to 0. When this happens and + * the timer is in operating mode COUNTER it stops. In mode TIMER it will + * continue to count up. + */ +#define RTTM_CTRL_COUNTER 0 +#define RTTM_CTRL_TIMER BIT(24) + +#define RTTM_BIT_COUNT 28 +#define RTTM_MIN_DELTA 8 +#define RTTM_MAX_DELTA CLOCKSOURCE_MASK(28) + +/* + * Timers are derived from the LXB clock frequency. Usually this is a fixed + * multiple of the 25 MHz oscillator. The 930X SOC is an exception from that. + * Its LXB clock has only dividers and uses the switch PLL of 2.45 GHz as its + * base. The only meaningful frequencies we can achieve from that are 175.000 + * MHz and 153.125 MHz. The greatest common divisor of all explained possible + * speeds is 3125000. Pin the timers to this 3.125 MHz reference frequency. + */ +#define RTTM_TICKS_PER_SEC 3125000 + +struct rttm_cs { + struct timer_of to; + struct clocksource cs; +}; + +/* Simple internal register functions */ +static inline void rttm_set_counter(void __iomem *base, unsigned int counter) +{ + iowrite32(counter, base + RTTM_CNT); +} + +static inline unsigned int rttm_get_counter(void __iomem *base) +{ + return ioread32(base + RTTM_CNT); +} + +static inline void rttm_set_period(void __iomem *base, unsigned int period) +{ + iowrite32(period, base + RTTM_DATA); +} + +static inline void rttm_disable_timer(void __iomem *base) +{ + iowrite32(0, base + RTTM_CTRL); +} + +static inline void rttm_enable_timer(void __iomem *base, u32 mode, u32 divis= or) +{ + iowrite32(RTTM_CTRL_ENABLE | mode | divisor, base + RTTM_CTRL); +} + +static inline void rttm_ack_irq(void __iomem *base) +{ + iowrite32(ioread32(base + RTTM_INT) | RTTM_INT_PENDING, base + RTTM_INT); +} + +static inline void rttm_enable_irq(void __iomem *base) +{ + iowrite32(RTTM_INT_ENABLE, base + RTTM_INT); +} + +static inline void rttm_disable_irq(void __iomem *base) +{ + iowrite32(0, base + RTTM_INT); +} + +/* Aggregated control functions for kernel clock framework */ +#define RTTM_DEBUG(base) \ + pr_debug("------------- %d %p\n", \ + smp_processor_id(), base) + +static irqreturn_t rttm_timer_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *clkevt =3D dev_id; + struct timer_of *to =3D to_timer_of(clkevt); + + rttm_ack_irq(to->of_base.base); + RTTM_DEBUG(to->of_base.base); + clkevt->event_handler(clkevt); + + return IRQ_HANDLED; +} + +static void rttm_stop_timer(void __iomem *base) +{ + rttm_disable_timer(base); + rttm_ack_irq(base); +} + +static void rttm_start_timer(struct timer_of *to, u32 mode) +{ + rttm_set_counter(to->of_base.base, 0); + rttm_enable_timer(to->of_base.base, mode, to->of_clk.rate / RTTM_TICKS_PER_= SEC); +} + +static int rttm_next_event(unsigned long delta, struct clock_event_device *c= lkevt) +{ + struct timer_of *to =3D to_timer_of(clkevt); + + RTTM_DEBUG(to->of_base.base); + rttm_stop_timer(to->of_base.base); + rttm_set_period(to->of_base.base, delta); + rttm_start_timer(to, RTTM_CTRL_COUNTER); + + return 0; +} + +static int rttm_state_oneshot(struct clock_event_device *clkevt) +{ + struct timer_of *to =3D to_timer_of(clkevt); + + RTTM_DEBUG(to->of_base.base); + rttm_stop_timer(to->of_base.base); + rttm_set_period(to->of_base.base, RTTM_TICKS_PER_SEC / HZ); + rttm_start_timer(to, RTTM_CTRL_COUNTER); + + return 0; +} + +static int rttm_state_periodic(struct clock_event_device *clkevt) +{ + struct timer_of *to =3D to_timer_of(clkevt); + + RTTM_DEBUG(to->of_base.base); + rttm_stop_timer(to->of_base.base); + rttm_set_period(to->of_base.base, RTTM_TICKS_PER_SEC / HZ); + rttm_start_timer(to, RTTM_CTRL_TIMER); + + return 0; +} + +static int rttm_state_shutdown(struct clock_event_device *clkevt) +{ + struct timer_of *to =3D to_timer_of(clkevt); + + RTTM_DEBUG(to->of_base.base); + rttm_stop_timer(to->of_base.base); + + return 0; +} + +static void rttm_setup_timer(void __iomem *base) +{ + RTTM_DEBUG(base); + rttm_stop_timer(base); + rttm_set_period(base, 0); +} + +static u64 rttm_read_clocksource(struct clocksource *cs) +{ + struct rttm_cs *rcs =3D container_of(cs, struct rttm_cs, cs); + + return rttm_get_counter(rcs->to.of_base.base); +} + +/* Module initialization part. */ +static DEFINE_PER_CPU(struct timer_of, rttm_to) =3D { + .flags =3D TIMER_OF_BASE | TIMER_OF_CLOCK | TIMER_OF_IRQ, + .of_irq =3D { + .flags =3D IRQF_PERCPU | IRQF_TIMER, + .handler =3D rttm_timer_interrupt, + }, + .clkevt =3D { + .rating =3D 400, + .features =3D CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, + .set_state_periodic =3D rttm_state_periodic, + .set_state_shutdown =3D rttm_state_shutdown, + .set_state_oneshot =3D rttm_state_oneshot, + .set_next_event =3D rttm_next_event + }, +}; + +static int rttm_enable_clocksource(struct clocksource *cs) +{ + struct rttm_cs *rcs =3D container_of(cs, struct rttm_cs, cs); + + rttm_disable_irq(rcs->to.of_base.base); + rttm_setup_timer(rcs->to.of_base.base); + rttm_enable_timer(rcs->to.of_base.base, RTTM_CTRL_TIMER, + rcs->to.of_clk.rate / RTTM_TICKS_PER_SEC); + + return 0; +} + +struct rttm_cs rttm_cs =3D { + .to =3D { + .flags =3D TIMER_OF_BASE | TIMER_OF_CLOCK, + }, + .cs =3D { + .name =3D "realtek_otto_timer", + .rating =3D 400, + .mask =3D CLOCKSOURCE_MASK(RTTM_BIT_COUNT), + .flags =3D CLOCK_SOURCE_IS_CONTINUOUS, + .read =3D rttm_read_clocksource, + } +}; + +static u64 notrace rttm_read_clock(void) +{ + return rttm_get_counter(rttm_cs.to.of_base.base); +} + +static int rttm_cpu_starting(unsigned int cpu) +{ + struct timer_of *to =3D per_cpu_ptr(&rttm_to, cpu); + + RTTM_DEBUG(to->of_base.base); + to->clkevt.cpumask =3D cpumask_of(cpu); + irq_force_affinity(to->of_irq.irq, to->clkevt.cpumask); + clockevents_config_and_register(&to->clkevt, RTTM_TICKS_PER_SEC, + RTTM_MIN_DELTA, RTTM_MAX_DELTA); + rttm_enable_irq(to->of_base.base); + + return 0; +} + +static int __init rttm_probe(struct device_node *np) +{ + unsigned int cpu, cpu_rollback; + struct timer_of *to; + unsigned int clkidx =3D num_possible_cpus(); + + /* Use the first n timers as per CPU clock event generators */ + for_each_possible_cpu(cpu) { + to =3D per_cpu_ptr(&rttm_to, cpu); + to->of_irq.index =3D to->of_base.index =3D cpu; + if (timer_of_init(np, to)) { + pr_err("setup of timer %d failed\n", cpu); + goto rollback; + } + rttm_setup_timer(to->of_base.base); + } + + /* Activate the n'th + 1 timer as a stable CPU clocksource. */ + to =3D &rttm_cs.to; + to->of_base.index =3D clkidx; + timer_of_init(np, to); + if (rttm_cs.to.of_base.base && rttm_cs.to.of_clk.rate) { + rttm_enable_clocksource(&rttm_cs.cs); + clocksource_register_hz(&rttm_cs.cs, RTTM_TICKS_PER_SEC); + sched_clock_register(rttm_read_clock, RTTM_BIT_COUNT, RTTM_TICKS_PER_SEC); + } else + pr_err(" setup of timer %d as clocksource failed", clkidx); + + return cpuhp_setup_state(CPUHP_AP_REALTEK_TIMER_STARTING, + "timer/realtek:online", + rttm_cpu_starting, NULL); +rollback: + pr_err("timer registration failed\n"); + for_each_possible_cpu(cpu_rollback) { + if (cpu_rollback =3D=3D cpu) + break; + to =3D per_cpu_ptr(&rttm_to, cpu_rollback); + timer_of_cleanup(to); + } + + return -EINVAL; +} + +TIMER_OF_DECLARE(otto_timer, "realtek,otto-timer", rttm_probe); diff --git a/drivers/net/ethernet/intel/e1000e/ptp.c b/drivers/net/ethernet/i= ntel/e1000e/ptp.c index bbcfd529399b..89d57dd911dc 100644 --- a/drivers/net/ethernet/intel/e1000e/ptp.c +++ b/drivers/net/ethernet/intel/e1000e/ptp.c @@ -124,7 +124,8 @@ static int e1000e_phc_get_syncdevicetime(ktime_t *device, sys_cycles =3D er32(PLTSTMPH); sys_cycles <<=3D 32; sys_cycles |=3D er32(PLTSTMPL); - *system =3D convert_art_to_tsc(sys_cycles); + system->cycles =3D sys_cycles; + system->cs_id =3D CSID_X86_ART; =20 return 0; } diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/= intel/ice/ice_ptp.c index fefaf52fd677..927b623cedd5 100644 --- a/drivers/net/ethernet/intel/ice/ice_ptp.c +++ b/drivers/net/ethernet/intel/ice/ice_ptp.c @@ -2156,7 +2156,8 @@ ice_ptp_get_syncdevicetime(ktime_t *device, hh_ts_lo =3D rd32(hw, GLHH_ART_TIME_L); hh_ts_hi =3D rd32(hw, GLHH_ART_TIME_H); hh_ts =3D ((u64)hh_ts_hi << 32) | hh_ts_lo; - *system =3D convert_art_ns_to_tsc(hh_ts); + system->cycles =3D hh_ts; + system->cs_id =3D CSID_X86_ART; /* Read Device source clock time */ hh_ts_lo =3D rd32(hw, GLTSYN_HHTIME_L(tmr_idx)); hh_ts_hi =3D rd32(hw, GLTSYN_HHTIME_H(tmr_idx)); diff --git a/drivers/net/ethernet/intel/igc/igc_ptp.c b/drivers/net/ethernet/= intel/igc/igc_ptp.c index 1bb026232efc..946edbad4302 100644 --- a/drivers/net/ethernet/intel/igc/igc_ptp.c +++ b/drivers/net/ethernet/intel/igc/igc_ptp.c @@ -938,7 +938,11 @@ static bool igc_is_crosststamp_supported(struct igc_adap= ter *adapter) static struct system_counterval_t igc_device_tstamp_to_system(u64 tstamp) { #if IS_ENABLED(CONFIG_X86_TSC) && !defined(CONFIG_UML) - return convert_art_ns_to_tsc(tstamp); + return (struct system_counterval_t) { + .cs_id =3D CSID_X86_ART, + .cycles =3D tstamp, + .use_nsecs =3D true, + }; #else return (struct system_counterval_t) { }; #endif diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c b/drivers/net/= ethernet/stmicro/stmmac/dwmac-intel.c index 60283543ffc8..e73fa34237d3 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c @@ -390,10 +390,11 @@ static int intel_crosststamp(ktime_t *device, *device =3D ns_to_ktime(ptp_time); read_unlock_irqrestore(&priv->ptp_lock, flags); get_arttime(priv->mii, intel_priv->mdio_adhoc_addr, &art_time); - *system =3D convert_art_to_tsc(art_time); + system->cycles =3D art_time; } =20 system->cycles *=3D intel_priv->crossts_adj; + system->cs_id =3D CSID_X86_ART; priv->plat->flags &=3D ~STMMAC_FLAG_INT_SNAPSHOT_EN; =20 return 0; diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h index 0ad8b550bb4b..d35b677b08fe 100644 --- a/include/linux/clocksource.h +++ b/include/linux/clocksource.h @@ -21,6 +21,7 @@ #include #include =20 +struct clocksource_base; struct clocksource; struct module; =20 @@ -50,6 +51,7 @@ struct module; * multiplication * @name: Pointer to clocksource name * @list: List head for registration (internal) + * @freq_khz: Clocksource frequency in khz. * @rating: Rating value for selection (higher is better) * To avoid rating inflation the following * list should give you a guide as to how @@ -70,6 +72,8 @@ struct module; * validate the clocksource from which the snapshot was * taken. * @flags: Flags describing special properties + * @base: Hardware abstraction for clock on which a clocksource + * is based * @enable: Optional function to enable the clocksource * @disable: Optional function to disable the clocksource * @suspend: Optional suspend function for the clocksource @@ -107,10 +111,12 @@ struct clocksource { u64 max_cycles; const char *name; struct list_head list; + u32 freq_khz; int rating; enum clocksource_ids id; enum vdso_clock_mode vdso_clock_mode; unsigned long flags; + struct clocksource_base *base; =20 int (*enable)(struct clocksource *cs); void (*disable)(struct clocksource *cs); @@ -306,4 +312,25 @@ static inline unsigned int clocksource_get_max_watchdog_= retry(void) =20 void clocksource_verify_percpu(struct clocksource *cs); =20 +/** + * struct clocksource_base - hardware abstraction for clock on which a clock= source + * is based + * @id: Defaults to CSID_GENERIC. The id value is used for conversion + * functions which require that the current clocksource is based + * on a clocksource_base with a particular ID in certain snapshot + * functions to allow callers to validate the clocksource from + * which the snapshot was taken. + * @freq_khz: Nominal frequency of the base clock in kHz + * @offset: Offset between the base clock and the clocksource + * @numerator: Numerator of the clock ratio between base clock and the cloc= ksource + * @denominator: Denominator of the clock ratio between base clock and the c= locksource + */ +struct clocksource_base { + enum clocksource_ids id; + u32 freq_khz; + u64 offset; + u32 numerator; + u32 denominator; +}; + #endif /* _LINUX_CLOCKSOURCE_H */ diff --git a/include/linux/clocksource_ids.h b/include/linux/clocksource_ids.h index a4fa3436940c..2bb4d8c2f1b0 100644 --- a/include/linux/clocksource_ids.h +++ b/include/linux/clocksource_ids.h @@ -9,6 +9,7 @@ enum clocksource_ids { CSID_X86_TSC_EARLY, CSID_X86_TSC, CSID_X86_KVM_CLK, + CSID_X86_ART, CSID_MAX, }; =20 diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h index 7a5785f405b6..56b744dc1317 100644 --- a/include/linux/cpuhotplug.h +++ b/include/linux/cpuhotplug.h @@ -171,6 +171,7 @@ enum cpuhp_state { CPUHP_AP_ARMADA_TIMER_STARTING, CPUHP_AP_MIPS_GIC_TIMER_STARTING, CPUHP_AP_ARC_TIMER_STARTING, + CPUHP_AP_REALTEK_TIMER_STARTING, CPUHP_AP_RISCV_TIMER_STARTING, CPUHP_AP_CLINT_TIMER_STARTING, CPUHP_AP_CSKY_TIMER_STARTING, diff --git a/include/linux/tick.h b/include/linux/tick.h index 4924a33700b7..72744638c5b0 100644 --- a/include/linux/tick.h +++ b/include/linux/tick.h @@ -139,7 +139,6 @@ extern void tick_nohz_irq_exit(void); extern bool tick_nohz_idle_got_tick(void); extern ktime_t tick_nohz_get_next_hrtimer(void); extern ktime_t tick_nohz_get_sleep_length(ktime_t *delta_next); -extern unsigned long tick_nohz_get_idle_calls(void); extern unsigned long tick_nohz_get_idle_calls_cpu(int cpu); extern u64 get_cpu_idle_time_us(int cpu, u64 *last_update_time); extern u64 get_cpu_iowait_time_us(int cpu, u64 *last_update_time); diff --git a/include/linux/timekeeping.h b/include/linux/timekeeping.h index 0ea7823b7f31..fc12a9ba2c88 100644 --- a/include/linux/timekeeping.h +++ b/include/linux/timekeeping.h @@ -310,12 +310,18 @@ struct system_device_crosststamp { * timekeeping code to verify comparability of two cycle values. * The default ID, CSID_GENERIC, does not identify a specific * clocksource. + * @use_nsecs: @cycles is in nanoseconds. */ struct system_counterval_t { u64 cycles; enum clocksource_ids cs_id; + bool use_nsecs; }; =20 +extern bool ktime_real_to_base_clock(ktime_t treal, + enum clocksource_ids base_id, u64 *cycles); +extern bool timekeeping_clocksource_has_base(enum clocksource_ids id); + /* * Get cross timestamp between system clock and device clock */ diff --git a/include/vdso/datapage.h b/include/vdso/datapage.h index d04d394db064..7647e0946f50 100644 --- a/include/vdso/datapage.h +++ b/include/vdso/datapage.h @@ -77,6 +77,10 @@ struct vdso_timestamp { * vdso_data will be accessed by 64 bit and compat code at the same time * so we should be careful before modifying this structure. * + * The ordering of the struct members is optimized to have fast access to the + * often required struct members which are related to CLOCK_REALTIME and + * CLOCK_MONOTONIC. This information is stored in the first cache lines. + * * @basetime is used to store the base time for the system wide time getter * VVAR page. * diff --git a/kernel/time/clocksource-wdtest.c b/kernel/time/clocksource-wdtes= t.c index d06185e054ea..62e73444ffe4 100644 --- a/kernel/time/clocksource-wdtest.c +++ b/kernel/time/clocksource-wdtest.c @@ -22,6 +22,7 @@ #include "tick-internal.h" =20 MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Clocksource watchdog unit test"); MODULE_AUTHOR("Paul E. McKenney "); =20 static int holdoff =3D IS_BUILTIN(CONFIG_TEST_CLOCKSOURCE_WATCHDOG) ? 10 : 0; diff --git a/kernel/time/test_udelay.c b/kernel/time/test_udelay.c index 20d5df631570..783f2297111b 100644 --- a/kernel/time/test_udelay.c +++ b/kernel/time/test_udelay.c @@ -155,5 +155,6 @@ static void __exit udelay_test_exit(void) =20 module_exit(udelay_test_exit); =20 +MODULE_DESCRIPTION("udelay test module"); MODULE_AUTHOR("David Riley "); MODULE_LICENSE("GPL"); diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c index 771d1e040303..b4843099a8da 100644 --- a/kernel/time/tick-broadcast.c +++ b/kernel/time/tick-broadcast.c @@ -1141,6 +1141,7 @@ void tick_broadcast_switch_to_oneshot(void) #ifdef CONFIG_HOTPLUG_CPU void hotplug_cpu__broadcast_tick_pull(int deadcpu) { + struct tick_device *td =3D this_cpu_ptr(&tick_cpu_device); struct clock_event_device *bc; unsigned long flags; =20 @@ -1148,6 +1149,28 @@ void hotplug_cpu__broadcast_tick_pull(int deadcpu) bc =3D tick_broadcast_device.evtdev; =20 if (bc && broadcast_needs_cpu(bc, deadcpu)) { + /* + * If the broadcast force bit of the current CPU is set, + * then the current CPU has not yet reprogrammed the local + * timer device to avoid a ping-pong race. See + * ___tick_broadcast_oneshot_control(). + * + * If the broadcast device is hrtimer based then + * programming the broadcast event below does not have any + * effect because the local clockevent device is not + * running and not programmed because the broadcast event + * is not earlier than the pending event of the local clock + * event device. As a consequence all CPUs waiting for a + * broadcast event are stuck forever. + * + * Detect this condition and reprogram the cpu local timer + * device to avoid the starvation. + */ + if (tick_check_broadcast_expired()) { + cpumask_clear_cpu(smp_processor_id(), tick_broadcast_force_mask); + tick_program_event(td->evtdev->next_event, 1); + } + /* This moves the broadcast assignment to this CPU: */ clockevents_program_event(bc, bc->next_event, 1); } diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 71a792cd8936..753a184c7090 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -1026,10 +1026,10 @@ static void tick_nohz_stop_tick(struct tick_sched *ts= , int cpu) if (expires =3D=3D KTIME_MAX || ts->next_tick =3D=3D hrtimer_get_expires(&= ts->sched_timer)) return; =20 - WARN_ON_ONCE(1); - printk_once("basemono: %llu ts->next_tick: %llu dev->next_event: %llu time= r->active: %d timer->expires: %llu\n", - basemono, ts->next_tick, dev->next_event, - hrtimer_active(&ts->sched_timer), hrtimer_get_expires(&ts->sched_time= r)); + WARN_ONCE(1, "basemono: %llu ts->next_tick: %llu dev->next_event: %llu " + "timer->active: %d timer->expires: %llu\n", basemono, ts->next_tick, + dev->next_event, hrtimer_active(&ts->sched_timer), + hrtimer_get_expires(&ts->sched_timer)); } =20 /* @@ -1385,20 +1385,6 @@ unsigned long tick_nohz_get_idle_calls_cpu(int cpu) return ts->idle_calls; } =20 -/** - * tick_nohz_get_idle_calls - return the current idle calls counter value - * - * Called from the schedutil frequency scaling governor in scheduler context. - * - * Return: the current idle calls counter value for the current CPU - */ -unsigned long tick_nohz_get_idle_calls(void) -{ - struct tick_sched *ts =3D this_cpu_ptr(&tick_cpu_sched); - - return ts->idle_calls; -} - static void tick_nohz_account_idle_time(struct tick_sched *ts, ktime_t now) { diff --git a/kernel/time/time_test.c b/kernel/time/time_test.c index 3e5d422dd15c..2889763165e5 100644 --- a/kernel/time/time_test.c +++ b/kernel/time/time_test.c @@ -96,4 +96,5 @@ static struct kunit_suite time_test_suite =3D { }; =20 kunit_test_suite(time_test_suite); +MODULE_DESCRIPTION("time unit test suite"); MODULE_LICENSE("GPL"); diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 4e18db1819f8..2fa87dcfeda9 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -1195,6 +1195,108 @@ static bool timestamp_in_interval(u64 start, u64 end,= u64 ts) return false; } =20 +static bool convert_clock(u64 *val, u32 numerator, u32 denominator) +{ + u64 rem, res; + + if (!numerator || !denominator) + return false; + + res =3D div64_u64_rem(*val, denominator, &rem) * numerator; + *val =3D res + div_u64(rem * numerator, denominator); + return true; +} + +static bool convert_base_to_cs(struct system_counterval_t *scv) +{ + struct clocksource *cs =3D tk_core.timekeeper.tkr_mono.clock; + struct clocksource_base *base; + u32 num, den; + + /* The timestamp was taken from the time keeper clock source */ + if (cs->id =3D=3D scv->cs_id) + return true; + + /* + * Check whether cs_id matches the base clock. Prevent the compiler from + * re-evaluating @base as the clocksource might change concurrently. + */ + base =3D READ_ONCE(cs->base); + if (!base || base->id !=3D scv->cs_id) + return false; + + num =3D scv->use_nsecs ? cs->freq_khz : base->numerator; + den =3D scv->use_nsecs ? USEC_PER_SEC : base->denominator; + + if (!convert_clock(&scv->cycles, num, den)) + return false; + + scv->cycles +=3D base->offset; + return true; +} + +static bool convert_cs_to_base(u64 *cycles, enum clocksource_ids base_id) +{ + struct clocksource *cs =3D tk_core.timekeeper.tkr_mono.clock; + struct clocksource_base *base; + + /* + * Check whether base_id matches the base clock. Prevent the compiler from + * re-evaluating @base as the clocksource might change concurrently. + */ + base =3D READ_ONCE(cs->base); + if (!base || base->id !=3D base_id) + return false; + + *cycles -=3D base->offset; + if (!convert_clock(cycles, base->denominator, base->numerator)) + return false; + return true; +} + +static bool convert_ns_to_cs(u64 *delta) +{ + struct tk_read_base *tkr =3D &tk_core.timekeeper.tkr_mono; + + if (BITS_TO_BYTES(fls64(*delta) + tkr->shift) >=3D sizeof(*delta)) + return false; + + *delta =3D div_u64((*delta << tkr->shift) - tkr->xtime_nsec, tkr->mult); + return true; +} + +/** + * ktime_real_to_base_clock() - Convert CLOCK_REALTIME timestamp to a base c= lock timestamp + * @treal: CLOCK_REALTIME timestamp to convert + * @base_id: base clocksource id + * @cycles: pointer to store the converted base clock timestamp + * + * Converts a supplied, future realtime clock value to the corresponding bas= e clock value. + * + * Return: true if the conversion is successful, false otherwise. + */ +bool ktime_real_to_base_clock(ktime_t treal, enum clocksource_ids base_id, u= 64 *cycles) +{ + struct timekeeper *tk =3D &tk_core.timekeeper; + unsigned int seq; + u64 delta; + + do { + seq =3D read_seqcount_begin(&tk_core.seq); + if ((u64)treal < tk->tkr_mono.base_real) + return false; + delta =3D (u64)treal - tk->tkr_mono.base_real; + if (!convert_ns_to_cs(&delta)) + return false; + *cycles =3D tk->tkr_mono.cycle_last + delta; + if (!convert_cs_to_base(cycles, base_id)) + return false; + } while (read_seqcount_retry(&tk_core.seq, seq)); + + return true; +} +EXPORT_SYMBOL_GPL(ktime_real_to_base_clock); + /** * get_device_system_crosststamp - Synchronously capture system/device times= tamp * @get_time_fn: Callback to get simultaneous device time and @@ -1241,7 +1343,7 @@ int get_device_system_crosststamp(int (*get_time_fn) * installed timekeeper clocksource */ if (system_counterval.cs_id =3D=3D CSID_GENERIC || - tk->tkr_mono.clock->id !=3D system_counterval.cs_id) + !convert_base_to_cs(&system_counterval)) return -ENODEV; cycles =3D system_counterval.cycles; =20 @@ -1306,6 +1408,30 @@ int get_device_system_crosststamp(int (*get_time_fn) } EXPORT_SYMBOL_GPL(get_device_system_crosststamp); =20 +/** + * timekeeping_clocksource_has_base - Check whether the current clocksource + * is based on given a base clock + * @id: base clocksource ID + * + * Note: The return value is a snapshot which can become invalid right + * after the function returns. + * + * Return: true if the timekeeper clocksource has a base clock with @id, + * false otherwise + */ +bool timekeeping_clocksource_has_base(enum clocksource_ids id) +{ + /* + * This is a snapshot, so no point in using the sequence + * count. Just prevent the compiler from re-evaluating @base as the + * clocksource might change concurrently. + */ + struct clocksource_base *base =3D READ_ONCE(tk_core.timekeeper.tkr_mono.clo= ck->base); + + return base ? base->id =3D=3D id : false; +} +EXPORT_SYMBOL_GPL(timekeeping_clocksource_has_base); + /** * do_settimeofday64 - Sets the time of day. * @ts: pointer to the timespec64 variable containing the new time @@ -2421,6 +2547,7 @@ EXPORT_SYMBOL_GPL(random_get_entropy_fallback); =20 /** * do_adjtimex() - Accessor function to NTP __do_adjtimex function + * @txc: Pointer to kernel_timex structure containing NTP parameters */ int do_adjtimex(struct __kernel_timex *txc) { @@ -2489,6 +2616,8 @@ int do_adjtimex(struct __kernel_timex *txc) #ifdef CONFIG_NTP_PPS /** * hardpps() - Accessor function to NTP __hardpps function + * @phase_ts: Pointer to timespec64 structure representing phase timestamp + * @raw_ts: Pointer to timespec64 structure representing raw timestamp */ void hardpps(const struct timespec64 *phase_ts, const struct timespec64 *raw= _ts) { diff --git a/lib/vdso/gettimeofday.c b/lib/vdso/gettimeofday.c index 899850bd6f0b..c01eaafd8041 100644 --- a/lib/vdso/gettimeofday.c +++ b/lib/vdso/gettimeofday.c @@ -140,14 +140,14 @@ static __always_inline int do_hres(const struct vdso_da= ta *vd, clockid_t clk, =20 do { /* - * Open coded to handle VDSO_CLOCKMODE_TIMENS. Time namespace - * enabled tasks have a special VVAR page installed which - * has vd->seq set to 1 and vd->clock_mode set to - * VDSO_CLOCKMODE_TIMENS. For non time namespace affected tasks - * this does not affect performance because if vd->seq is - * odd, i.e. a concurrent update is in progress the extra - * check for vd->clock_mode is just a few extra - * instructions while spin waiting for vd->seq to become + * Open coded function vdso_read_begin() to handle + * VDSO_CLOCKMODE_TIMENS. Time namespace enabled tasks have a + * special VVAR page installed which has vd->seq set to 1 and + * vd->clock_mode set to VDSO_CLOCKMODE_TIMENS. For non time + * namespace affected tasks this does not affect performance + * because if vd->seq is odd, i.e. a concurrent update is in + * progress the extra check for vd->clock_mode is just a few + * extra instructions while spin waiting for vd->seq to become * even again. */ while (unlikely((seq =3D READ_ONCE(vd->seq)) & 1)) { @@ -223,8 +223,8 @@ static __always_inline int do_coarse(const struct vdso_da= ta *vd, clockid_t clk, =20 do { /* - * Open coded to handle VDSO_CLOCK_TIMENS. See comment in - * do_hres(). + * Open coded function vdso_read_begin() to handle + * VDSO_CLOCK_TIMENS. See comment in do_hres(). */ while ((seq =3D READ_ONCE(vd->seq)) & 1) { if (IS_ENABLED(CONFIG_TIME_NS) && diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c index 766734dc5be2..5d86e5a9c814 100644 --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c @@ -463,7 +463,8 @@ static int azx_get_sync_time(ktime_t *device, *device =3D ktime_add_ns(*device, (wallclk_cycles * NSEC_PER_SEC) / ((HDA_MAX_CYCLE_VALUE + 1) * runtime->rate)); =20 - *system =3D convert_art_to_tsc(tsc_counter); + system->cycles =3D tsc_counter; + system->cs_id =3D CSID_X86_ART; =20 return 0; } . Date: Sun, 14 Jul 2024 22:50:06 +0200 (CEST) From: Thomas Gleixner To: Linus Torvalds Cc: linux-kernel@vger.kernel.org, x86@kernel.org Subject: [GIT pull] irq/core for v6.11-rc1 Linus, please pull the latest irq/core branch from: git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git irq-core-2024-07= -14 up to: faf243d11659: Merge branch 'irq/msi' into irq/core Updates for the interrupt subsystem: - Core: - Provide a new mechanism to create interrupt domains. The existing interfaces have already too many parameters and it's a pain to expand any of this for new required functionality. The new function takes a pointer to a data structure as argument. The data structure combines all existing parameters and allows for easy extension. The first extension for this is to handle the instantiation of generic interrupt chips at the core level and to allow drivers to provide extra init/exit callbacks. This is necessary to do the full interrupt chip initialization before the new domain is published, so that concurrent usage sites won't see a half initialized interrupt domain. Similar problems exist on teardown. This has turned out to be a real problem due to the deferred and parallel probing which was added in recent years. Handling this at the core level allows to remove quite some accrued boilerplate code in existing drivers and avoids horrible workarounds at the driver level. - The usual small improvements all over the place - MSI - Switch ARM/ARM64 over to the modern per device MSI domains. This simplifies the handling of platform MSI and wire to MSI controllers and removes about 500 lines of legacy code. Aside of that it paves the way for ARM/ARM64 to utilize the dynamic allocation of PCI/MSI interrupts and to support the upcoming non standard IMS (Interrupt Message Store) mechanism on PCIe devices - Drivers - Add support for LAN966x OIC and RZ/Five SoC - Split the STM ExtI driver into a microcontroller and a SMP version to allow building the latter as a module for multi-platform kernels. - Enable MSI support for Armada 370XP on platforms which do not support IPIs. - The usual small fixes and enhancements all over the place. Thanks, tglx ------------------> Adrian Huang (1): genirq/proc: Simplify irqdesc::kstat_irqs handling further Anna-Maria Behnsen (2): irqchip/imx-mu-msi: Fix codingstyle in imx_mu_msi_domains_init() irqdomain: Fix formatting irq_find_matching_fwspec() kerneldoc comment Antonio Borneo (8): irqchip/stm32-exti: Add CONFIG_STM32MP_EXTI ARM: stm32: Use different EXTI driver on ARMv7m and ARMv7a arm64: Kconfig: Select STM32MP_EXTI on STM32 platforms irqchip/stm32-exti: Split MCU and MPU code irqchip/stm32mp-exti: Rename internal symbols irqchip/stm32mp-exti: Allow building as module ARM: stm32: Allow build irq-stm32mp-exti driver as module arm64: Kconfig: Allow build irq-stm32mp-exti driver as module Geert Uytterhoeven (1): irqchip/gic-v3: Pass #redistributor-regions to gic_of_setup_kvm_info() Herve Codina (24): irqdomain: Add missing parameter descriptions in kernel-doc comments irqdomain: Fixed unbalanced fwnode get and put irqdomain: Introduce irq_domain_free() irqdomain: Introduce irq_domain_instantiate() irqdomain: Constify parameter in is_fwnode_irqchip() irqdomain: Use a dedicated function to set the domain name irqdomain: Convert __irq_domain_create() to use struct irq_domain_info irqdomain: Handle additional domain flags in irq_domain_instantiate() irqdomain: Handle domain hierarchy parent in irq_domain_instantiate() irqdomain: Use irq_domain_instantiate() for hierarchy domain creation irqdomain: Make __irq_domain_create() return an error code irqdomain: Handle domain bus token in irq_domain_create() irqdomain: Introduce init() and exit() hooks genirq/generic_chip: Introduce irq_domain_{alloc,remove}_generic_chips() genirq/generic_chip: Introduce init() and exit() hooks irqdomain: Add support for generic irq chips creation before publishing= a domain irqdomain: Add a resource managed version of irq_domain_instantiate() irqdomain: Convert __irq_domain_add() wrappers to irq_domain_instantiat= e() irqdomain: Convert domain creation functions to irq_domain_instantiate() _PATCH_19_23_um_virt_pci_Use_irq_domain_instantiate_ irqdomain: Remove __irq_domain_add() dt-bindings: interrupt-controller: Add support for Microchip LAN966x OIC irqchip: Add support for LAN966x OIC MAINTAINERS: Add the Microchip LAN966x OIC driver entry Jeff Johnson (1): irqchip: Add missing MODULE_DESCRIPTION() macros Jinjie Ruan (2): genirq/debugfs: Print irqdomain flags as human-readable strings irqchip/riscv-aplic: Simplify the initialization code Jiri Slaby (SUSE) (1): irqdomain: Fix the kernel-doc and plug it into Documentation Jisheng Zhang (2): irqchip/riscv-intc: Remove asmlinkage irqchip/dw-apb-ictl: Support building as module Lad Prabhakar (3): dt-bindings: interrupt-controller: renesas,rzg2l-irqc: Document RZ/Five= SoC irqchip/renesas-rzg2l: Add support for RZ/Five SoC irqchip/renesas-rzg2l: Reorder function calls in rzg2l_irqc_irq_disable= () Lorenzo Pieralisi (1): irqchip/gic-v3: Enable non-coherent redistributors/ITSes ACPI probing Marc Zyngier (3): irqchip/gic-v4: Always configure affinity on VPE activation irqchip/gic-v4: Substitute vmovp_lock for a per-VM lock irqchip/gic-v4: Make sure a VPE is locked when VMAPP is issued Marek Beh=C3=BAn (1): irqchip/armada-370-xp: Use atomic_io_modify() instead of another spinlo= ck Pali Roh=C3=A1r (4): irqchip/armada-370-xp: Do not allow mapping IRQ 0 and 1 irqchip/armada-370-xp: Only call ipi_resume() if IPI is available irqchip/armada-370-xp: Do not touch IPI registers on platforms without = IPI irqchip/armada-370-xp: Add support for 32 MSI interrupts on non-IPI pla= tforms Rafael J. Wysocki (1): genirq: Set IRQF_COND_ONESHOT in request_irq() Shenwei Wang (1): irqchip/imx-irqsteer: Handle runtime power management correctly Shivamurthy Shastri (1): PCI/MSI: Provide MSI_FLAG_PCI_MSI_MASK_PARENT Stefan Wahren (1): irqchip/bcm2835: Enable SKIP_SET_WAKE and MASK_ON_SUSPEND Thomas Gleixner (23): irqdomain: Make build work for CONFIG_GENERIC_IRQ_CHIP=3Dn Revert "Loongarch: Support loongarch avec" Revert "irqchip/dw-apb-ictl: Support building as module" irqchip: Provide irq-msi-lib irqchip/gic-v3-its: Provide MSI parent infrastructure irqchip/irq-msi-lib: Prepare for PCI MSI/MSIX irqchip/gic-v3-its: Provide MSI parent for PCI/MSI[-X] irqchip/irq-msi-lib: Prepare for DEVICE MSI to replace platform MSI irqchip/mbigen: Prepare for real per device MSI irqchip/irq-msi-lib: Prepare for DOMAIN_BUS_WIRED_TO_MSI irqchip/gic-v3-its: Switch platform MSI to MSI parent irqchip/mbigen: Remove platform_msi_create_device_domain() fallback genirq/msi: Remove platform_msi_create_device_domain() irqchip/gic_v3_mbi: Switch over to parent domain irqchip/gic-v2m: Switch to device MSI irqchip/imx-mu-msi: Switch to MSI parent irqchip/irq-mvebu-icu: Prepare for real per device MSI irqchip/mvebu-gicp: Switch to MSI parent irqchip/mvebu-odmi: Switch to parent MSI irqchip/irq-mvebu-sei: Switch to MSI parent irqchip/irq-mvebu-icu: Remove platform MSI leftovers genirq/msi: Remove platform MSI leftovers genirq/msi: Move msi_device_data to core Tianyang Zhang (1): Loongarch: Support loongarch avec Documentation/core-api/genericirq.rst | 2 + .../microchip,lan966x-oic.yaml | 55 ++ .../interrupt-controller/renesas,rzg2l-irqc.yaml | 17 +- MAINTAINERS | 6 + arch/arm/mach-stm32/Kconfig | 2 +- arch/arm64/Kconfig.platforms | 1 - arch/um/drivers/virt-pci.c | 16 +- drivers/acpi/processor_core.c | 15 + drivers/base/platform-msi.c | 350 +--------- drivers/irqchip/Kconfig | 29 + drivers/irqchip/Makefile | 6 +- drivers/irqchip/irq-armada-370-xp.c | 121 +++- drivers/irqchip/irq-bcm2835.c | 4 +- drivers/irqchip/irq-gic-common.h | 3 + drivers/irqchip/irq-gic-v2m.c | 81 +-- drivers/irqchip/irq-gic-v3-its-msi-parent.c | 210 ++++++ drivers/irqchip/irq-gic-v3-its-pci-msi.c | 202 ------ drivers/irqchip/irq-gic-v3-its-platform-msi.c | 163 ----- drivers/irqchip/irq-gic-v3-its.c | 57 +- drivers/irqchip/irq-gic-v3-mbi.c | 130 ++-- drivers/irqchip/irq-gic-v3.c | 22 +- drivers/irqchip/irq-imx-irqsteer.c | 24 +- drivers/irqchip/irq-imx-mu-msi.c | 54 +- drivers/irqchip/irq-lan966x-oic.c | 278 ++++++++ drivers/irqchip/irq-mbigen.c | 96 +-- drivers/irqchip/irq-meson-gpio.c | 1 + drivers/irqchip/irq-msi-lib.c | 140 ++++ drivers/irqchip/irq-msi-lib.h | 27 + drivers/irqchip/irq-mvebu-gicp.c | 44 +- drivers/irqchip/irq-mvebu-icu.c | 275 ++++---- drivers/irqchip/irq-mvebu-odmi.c | 37 +- drivers/irqchip/irq-mvebu-pic.c | 1 + drivers/irqchip/irq-mvebu-sei.c | 52 +- drivers/irqchip/irq-renesas-rzg2l.c | 150 ++++- drivers/irqchip/irq-riscv-aplic-main.c | 13 +- drivers/irqchip/irq-riscv-intc.c | 4 +- drivers/irqchip/irq-stm32-exti.c | 670 +------------------ drivers/irqchip/irq-stm32mp-exti.c | 729 +++++++++++++++++++= ++ drivers/irqchip/irq-ts4800.c | 1 + drivers/pci/msi/irqdomain.c | 20 + include/linux/acpi.h | 3 + include/linux/interrupt.h | 2 +- include/linux/irq.h | 43 ++ include/linux/irqchip/arm-gic-v4.h | 8 + include/linux/irqdomain.h | 136 +++- include/linux/msi.h | 52 +- kernel/irq/debugfs.c | 10 +- kernel/irq/devres.c | 41 ++ kernel/irq/generic-chip.c | 111 +++- kernel/irq/internals.h | 10 + kernel/irq/irqdomain.c | 290 +++++--- kernel/irq/msi.c | 95 +-- kernel/irq/proc.c | 7 +- 53 files changed, 2712 insertions(+), 2204 deletions(-) create mode 100644 Documentation/devicetree/bindings/interrupt-controller/mi= crochip,lan966x-oic.yaml create mode 100644 drivers/irqchip/irq-gic-v3-its-msi-parent.c delete mode 100644 drivers/irqchip/irq-gic-v3-its-pci-msi.c delete mode 100644 drivers/irqchip/irq-gic-v3-its-platform-msi.c create mode 100644 drivers/irqchip/irq-lan966x-oic.c create mode 100644 drivers/irqchip/irq-msi-lib.c create mode 100644 drivers/irqchip/irq-msi-lib.h create mode 100644 drivers/irqchip/irq-stm32mp-exti.c diff --git a/Documentation/core-api/genericirq.rst b/Documentation/core-api/g= enericirq.rst index 4a460639ab1c..7a27663f309f 100644 --- a/Documentation/core-api/genericirq.rst +++ b/Documentation/core-api/genericirq.rst @@ -410,6 +410,8 @@ which are used in the generic IRQ layer. .. kernel-doc:: include/linux/interrupt.h :internal: =20 +.. kernel-doc:: include/linux/irqdomain.h + Public Functions Provided =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =20 diff --git a/Documentation/devicetree/bindings/interrupt-controller/microchip= ,lan966x-oic.yaml b/Documentation/devicetree/bindings/interrupt-controller/mi= crochip,lan966x-oic.yaml new file mode 100644 index 000000000000..b2adc7174177 --- /dev/null +++ b/Documentation/devicetree/bindings/interrupt-controller/microchip,lan966= x-oic.yaml @@ -0,0 +1,55 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/interrupt-controller/microchip,lan966x-oi= c.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Microchip LAN966x outband interrupt controller + +maintainers: + - Herve Codina + +allOf: + - $ref: /schemas/interrupt-controller.yaml# + +description: | + The Microchip LAN966x outband interrupt controller (OIC) maps the internal + interrupt sources of the LAN966x device to an external interrupt. + When the LAN966x device is used as a PCI device, the external interrupt is + routed to the PCI interrupt. + +properties: + compatible: + const: microchip,lan966x-oic + + '#interrupt-cells': + const: 2 + + interrupt-controller: true + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + +required: + - compatible + - '#interrupt-cells' + - interrupt-controller + - interrupts + - reg + +additionalProperties: false + +examples: + - | + interrupt-controller@e00c0120 { + compatible =3D "microchip,lan966x-oic"; + reg =3D <0xe00c0120 0x190>; + #interrupt-cells =3D <2>; + interrupt-controller; + interrupts =3D <0>; + interrupt-parent =3D <&intc>; + }; +... diff --git a/Documentation/devicetree/bindings/interrupt-controller/renesas,r= zg2l-irqc.yaml b/Documentation/devicetree/bindings/interrupt-controller/renes= as,rzg2l-irqc.yaml index daef4ee06f4e..44b6ae5fc802 100644 --- a/Documentation/devicetree/bindings/interrupt-controller/renesas,rzg2l-ir= qc.yaml +++ b/Documentation/devicetree/bindings/interrupt-controller/renesas,rzg2l-ir= qc.yaml @@ -21,13 +21,16 @@ description: | =20 properties: compatible: - items: - - enum: - - renesas,r9a07g043u-irqc # RZ/G2UL - - renesas,r9a07g044-irqc # RZ/G2{L,LC} - - renesas,r9a07g054-irqc # RZ/V2L - - renesas,r9a08g045-irqc # RZ/G3S - - const: renesas,rzg2l-irqc + oneOf: + - items: + - enum: + - renesas,r9a07g043u-irqc # RZ/G2UL + - renesas,r9a07g044-irqc # RZ/G2{L,LC} + - renesas,r9a07g054-irqc # RZ/V2L + - renesas,r9a08g045-irqc # RZ/G3S + - const: renesas,rzg2l-irqc + + - const: renesas,r9a07g043f-irqc # RZ/Five =20 '#interrupt-cells': description: The first cell should contain a macro RZG2L_{NMI,IRQX} incl= uded in the diff --git a/MAINTAINERS b/MAINTAINERS index aacccb376c28..57a29adc7a44 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14726,6 +14726,12 @@ L: netdev@vger.kernel.org S: Maintained F: drivers/net/ethernet/microchip/lan966x/* =20 +MICROCHIP LAN966X OIC DRIVER +M: Herve Codina +S: Maintained +F: Documentation/devicetree/bindings/interrupt-controller/microchip,lan966x-= oic.yaml +F: drivers/irqchip/irq-lan966x-oic.c + MICROCHIP LCDFB DRIVER M: Nicolas Ferre L: linux-fbdev@vger.kernel.org diff --git a/arch/arm/mach-stm32/Kconfig b/arch/arm/mach-stm32/Kconfig index ae21a9f78f9c..630b992f32b1 100644 --- a/arch/arm/mach-stm32/Kconfig +++ b/arch/arm/mach-stm32/Kconfig @@ -11,7 +11,7 @@ menuconfig ARCH_STM32 select CLKSRC_STM32 select PINCTRL select RESET_CONTROLLER - select STM32_EXTI + select STM32_EXTI if ARM_SINGLE_ARMV7M select STM32_FIREWALL help Support for STMicroelectronics STM32 processors. diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms index a52618073de2..a028ea312378 100644 --- a/arch/arm64/Kconfig.platforms +++ b/arch/arm64/Kconfig.platforms @@ -309,7 +309,6 @@ config ARCH_STM32 select GPIOLIB select PINCTRL select PINCTRL_STM32MP257 - select STM32_EXTI select ARM_SMC_MBOX select ARM_SCMI_PROTOCOL select COMMON_CLK_SCMI diff --git a/arch/um/drivers/virt-pci.c b/arch/um/drivers/virt-pci.c index 7cb503469bbd..a0883d5445b5 100644 --- a/arch/um/drivers/virt-pci.c +++ b/arch/um/drivers/virt-pci.c @@ -986,6 +986,11 @@ static struct resource virt_platform_resource =3D { =20 static int __init um_pci_init(void) { + struct irq_domain_info inner_domain_info =3D { + .size =3D MAX_MSI_VECTORS, + .hwirq_max =3D MAX_MSI_VECTORS, + .ops =3D &um_pci_inner_domain_ops, + }; int err, i; =20 WARN_ON(logic_iomem_add_region(&virt_cfgspace_resource, @@ -1015,11 +1020,10 @@ static int __init um_pci_init(void) goto free; } =20 - um_pci_inner_domain =3D __irq_domain_add(um_pci_fwnode, MAX_MSI_VECTORS, - MAX_MSI_VECTORS, 0, - &um_pci_inner_domain_ops, NULL); - if (!um_pci_inner_domain) { - err =3D -ENOMEM; + inner_domain_info.fwnode =3D um_pci_fwnode; + um_pci_inner_domain =3D irq_domain_instantiate(&inner_domain_info); + if (IS_ERR(um_pci_inner_domain)) { + err =3D PTR_ERR(um_pci_inner_domain); goto free; } =20 @@ -1056,7 +1060,7 @@ static int __init um_pci_init(void) goto free; return 0; free: - if (um_pci_inner_domain) + if (!IS_ERR_OR_NULL(um_pci_inner_domain)) irq_domain_remove(um_pci_inner_domain); if (um_pci_fwnode) irq_domain_free_fwnode(um_pci_fwnode); diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index b203cfe28550..915713c0e9b7 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -215,6 +215,21 @@ phys_cpuid_t __init acpi_map_madt_entry(u32 acpi_id) return rv; } =20 +int __init acpi_get_madt_revision(void) +{ + struct acpi_table_header *madt =3D NULL; + int revision; + + if (ACPI_FAILURE(acpi_get_table(ACPI_SIG_MADT, 0, &madt))) + return -EINVAL; + + revision =3D madt->revision; + + acpi_put_table(madt); + + return revision; +} + static phys_cpuid_t map_mat_entry(acpi_handle handle, int type, u32 acpi_id) { struct acpi_buffer buffer =3D { ACPI_ALLOCATE_BUFFER, NULL }; diff --git a/drivers/base/platform-msi.c b/drivers/base/platform-msi.c index 11f5fdf65b9e..0e60dd650b5e 100644 --- a/drivers/base/platform-msi.c +++ b/drivers/base/platform-msi.c @@ -4,346 +4,12 @@ * * Copyright (C) 2015 ARM Limited, All Rights Reserved. * Author: Marc Zyngier + * Copyright (C) 2022 Linutronix GmbH */ =20 #include -#include -#include #include #include -#include - -/* Begin of removal area. Once everything is converted over. Cleanup the inc= ludes too! */ - -#define DEV_ID_SHIFT 21 -#define MAX_DEV_MSIS (1 << (32 - DEV_ID_SHIFT)) - -/* - * Internal data structure containing a (made up, but unique) devid - * and the callback to write the MSI message. - */ -struct platform_msi_priv_data { - struct device *dev; - void *host_data; - msi_alloc_info_t arg; - irq_write_msi_msg_t write_msg; - int devid; -}; - -/* The devid allocator */ -static DEFINE_IDA(platform_msi_devid_ida); - -#ifdef GENERIC_MSI_DOMAIN_OPS -/* - * Convert an msi_desc to a globaly unique identifier (per-device - * devid + msi_desc position in the msi_list). - */ -static irq_hw_number_t platform_msi_calc_hwirq(struct msi_desc *desc) -{ - u32 devid =3D desc->dev->msi.data->platform_data->devid; - - return (devid << (32 - DEV_ID_SHIFT)) | desc->msi_index; -} - -static void platform_msi_set_desc(msi_alloc_info_t *arg, struct msi_desc *de= sc) -{ - arg->desc =3D desc; - arg->hwirq =3D platform_msi_calc_hwirq(desc); -} - -static int platform_msi_init(struct irq_domain *domain, - struct msi_domain_info *info, - unsigned int virq, irq_hw_number_t hwirq, - msi_alloc_info_t *arg) -{ - return irq_domain_set_hwirq_and_chip(domain, virq, hwirq, - info->chip, info->chip_data); -} - -static void platform_msi_set_proxy_dev(msi_alloc_info_t *arg) -{ - arg->flags |=3D MSI_ALLOC_FLAGS_PROXY_DEVICE; -} -#else -#define platform_msi_set_desc NULL -#define platform_msi_init NULL -#define platform_msi_set_proxy_dev(x) do {} while(0) -#endif - -static void platform_msi_update_dom_ops(struct msi_domain_info *info) -{ - struct msi_domain_ops *ops =3D info->ops; - - BUG_ON(!ops); - - if (ops->msi_init =3D=3D NULL) - ops->msi_init =3D platform_msi_init; - if (ops->set_desc =3D=3D NULL) - ops->set_desc =3D platform_msi_set_desc; -} - -static void platform_msi_write_msg(struct irq_data *data, struct msi_msg *ms= g) -{ - struct msi_desc *desc =3D irq_data_get_msi_desc(data); - - desc->dev->msi.data->platform_data->write_msg(desc, msg); -} - -static void platform_msi_update_chip_ops(struct msi_domain_info *info) -{ - struct irq_chip *chip =3D info->chip; - - BUG_ON(!chip); - if (!chip->irq_mask) - chip->irq_mask =3D irq_chip_mask_parent; - if (!chip->irq_unmask) - chip->irq_unmask =3D irq_chip_unmask_parent; - if (!chip->irq_eoi) - chip->irq_eoi =3D irq_chip_eoi_parent; - if (!chip->irq_set_affinity) - chip->irq_set_affinity =3D msi_domain_set_affinity; - if (!chip->irq_write_msi_msg) - chip->irq_write_msi_msg =3D platform_msi_write_msg; - if (WARN_ON((info->flags & MSI_FLAG_LEVEL_CAPABLE) && - !(chip->flags & IRQCHIP_SUPPORTS_LEVEL_MSI))) - info->flags &=3D ~MSI_FLAG_LEVEL_CAPABLE; -} - -/** - * platform_msi_create_irq_domain - Create a platform MSI interrupt domain - * @fwnode: Optional fwnode of the interrupt controller - * @info: MSI domain info - * @parent: Parent irq domain - * - * Updates the domain and chip ops and creates a platform MSI - * interrupt domain. - * - * Returns: - * A domain pointer or NULL in case of failure. - */ -struct irq_domain *platform_msi_create_irq_domain(struct fwnode_handle *fwno= de, - struct msi_domain_info *info, - struct irq_domain *parent) -{ - struct irq_domain *domain; - - if (info->flags & MSI_FLAG_USE_DEF_DOM_OPS) - platform_msi_update_dom_ops(info); - if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS) - platform_msi_update_chip_ops(info); - info->flags |=3D MSI_FLAG_DEV_SYSFS | MSI_FLAG_ALLOC_SIMPLE_MSI_DESCS | - MSI_FLAG_FREE_MSI_DESCS; - - domain =3D msi_create_irq_domain(fwnode, info, parent); - if (domain) - irq_domain_update_bus_token(domain, DOMAIN_BUS_PLATFORM_MSI); - - return domain; -} -EXPORT_SYMBOL_GPL(platform_msi_create_irq_domain); - -static int platform_msi_alloc_priv_data(struct device *dev, unsigned int nve= c, - irq_write_msi_msg_t write_msi_msg) -{ - struct platform_msi_priv_data *datap; - int err; - - /* - * Limit the number of interrupts to 2048 per device. Should we - * need to bump this up, DEV_ID_SHIFT should be adjusted - * accordingly (which would impact the max number of MSI - * capable devices). - */ - if (!dev->msi.domain || !write_msi_msg || !nvec || nvec > MAX_DEV_MSIS) - return -EINVAL; - - if (dev->msi.domain->bus_token !=3D DOMAIN_BUS_PLATFORM_MSI) { - dev_err(dev, "Incompatible msi_domain, giving up\n"); - return -EINVAL; - } - - err =3D msi_setup_device_data(dev); - if (err) - return err; - - /* Already initialized? */ - if (dev->msi.data->platform_data) - return -EBUSY; - - datap =3D kzalloc(sizeof(*datap), GFP_KERNEL); - if (!datap) - return -ENOMEM; - - datap->devid =3D ida_alloc_max(&platform_msi_devid_ida, - (1 << DEV_ID_SHIFT) - 1, GFP_KERNEL); - if (datap->devid < 0) { - err =3D datap->devid; - kfree(datap); - return err; - } - - datap->write_msg =3D write_msi_msg; - datap->dev =3D dev; - dev->msi.data->platform_data =3D datap; - return 0; -} - -static void platform_msi_free_priv_data(struct device *dev) -{ - struct platform_msi_priv_data *data =3D dev->msi.data->platform_data; - - dev->msi.data->platform_data =3D NULL; - ida_free(&platform_msi_devid_ida, data->devid); - kfree(data); -} - -/** - * platform_msi_domain_alloc_irqs - Allocate MSI interrupts for @dev - * @dev: The device for which to allocate interrupts - * @nvec: The number of interrupts to allocate - * @write_msi_msg: Callback to write an interrupt message for @dev - * - * Returns: - * Zero for success, or an error code in case of failure - */ -static int platform_msi_domain_alloc_irqs(struct device *dev, unsigned int n= vec, - irq_write_msi_msg_t write_msi_msg) -{ - int err; - - err =3D platform_msi_alloc_priv_data(dev, nvec, write_msi_msg); - if (err) - return err; - - err =3D msi_domain_alloc_irqs_range(dev, MSI_DEFAULT_DOMAIN, 0, nvec - 1); - if (err) - platform_msi_free_priv_data(dev); - - return err; -} - -/** - * platform_msi_get_host_data - Query the private data associated with - * a platform-msi domain - * @domain: The platform-msi domain - * - * Return: The private data provided when calling - * platform_msi_create_device_domain(). - */ -void *platform_msi_get_host_data(struct irq_domain *domain) -{ - struct platform_msi_priv_data *data =3D domain->host_data; - - return data->host_data; -} - -static struct lock_class_key platform_device_msi_lock_class; - -/** - * __platform_msi_create_device_domain - Create a platform-msi device domain - * - * @dev: The device generating the MSIs - * @nvec: The number of MSIs that need to be allocated - * @is_tree: flag to indicate tree hierarchy - * @write_msi_msg: Callback to write an interrupt message for @dev - * @ops: The hierarchy domain operations to use - * @host_data: Private data associated to this domain - * - * Return: An irqdomain for @nvec interrupts on success, NULL in case of err= or. - * - * This is for interrupt domains which stack on a platform-msi domain - * created by platform_msi_create_irq_domain(). @dev->msi.domain points to - * that platform-msi domain which is the parent for the new domain. - */ -struct irq_domain * -__platform_msi_create_device_domain(struct device *dev, - unsigned int nvec, - bool is_tree, - irq_write_msi_msg_t write_msi_msg, - const struct irq_domain_ops *ops, - void *host_data) -{ - struct platform_msi_priv_data *data; - struct irq_domain *domain; - int err; - - err =3D platform_msi_alloc_priv_data(dev, nvec, write_msi_msg); - if (err) - return NULL; - - /* - * Use a separate lock class for the MSI descriptor mutex on - * platform MSI device domains because the descriptor mutex nests - * into the domain mutex. See alloc/free below. - */ - lockdep_set_class(&dev->msi.data->mutex, &platform_device_msi_lock_class); - - data =3D dev->msi.data->platform_data; - data->host_data =3D host_data; - domain =3D irq_domain_create_hierarchy(dev->msi.domain, 0, - is_tree ? 0 : nvec, - dev->fwnode, ops, data); - if (!domain) - goto free_priv; - - platform_msi_set_proxy_dev(&data->arg); - err =3D msi_domain_prepare_irqs(domain->parent, dev, nvec, &data->arg); - if (err) - goto free_domain; - - return domain; - -free_domain: - irq_domain_remove(domain); -free_priv: - platform_msi_free_priv_data(dev); - return NULL; -} - -/** - * platform_msi_device_domain_free - Free interrupts associated with a platf= orm-msi - * device domain - * - * @domain: The platform-msi device domain - * @virq: The base irq from which to perform the free operation - * @nr_irqs: How many interrupts to free from @virq - */ -void platform_msi_device_domain_free(struct irq_domain *domain, unsigned int= virq, - unsigned int nr_irqs) -{ - struct platform_msi_priv_data *data =3D domain->host_data; - - msi_lock_descs(data->dev); - msi_domain_depopulate_descs(data->dev, virq, nr_irqs); - irq_domain_free_irqs_common(domain, virq, nr_irqs); - msi_free_msi_descs_range(data->dev, virq, virq + nr_irqs - 1); - msi_unlock_descs(data->dev); -} - -/** - * platform_msi_device_domain_alloc - Allocate interrupts associated with - * a platform-msi device domain - * - * @domain: The platform-msi device domain - * @virq: The base irq from which to perform the allocate operation - * @nr_irqs: How many interrupts to allocate from @virq - * - * Return 0 on success, or an error code on failure. Must be called - * with irq_domain_mutex held (which can only be done as part of a - * top-level interrupt allocation). - */ -int platform_msi_device_domain_alloc(struct irq_domain *domain, unsigned int= virq, - unsigned int nr_irqs) -{ - struct platform_msi_priv_data *data =3D domain->host_data; - struct device *dev =3D data->dev; - - return msi_domain_populate_irqs(domain->parent, dev, virq, nr_irqs, &data->= arg); -} - -/* End of removal area */ - -/* Real per device domain interfaces */ =20 /* * This indirection can go when platform_device_msi_init_and_alloc_irqs() @@ -357,7 +23,7 @@ static void platform_msi_write_msi_msg(struct irq_data *d,= struct msi_msg *msg) cb(irq_data_get_msi_desc(d), msg); } =20 -static void platform_msi_set_desc_byindex(msi_alloc_info_t *arg, struct msi_= desc *desc) +static void platform_msi_set_desc(msi_alloc_info_t *arg, struct msi_desc *de= sc) { arg->desc =3D desc; arg->hwirq =3D desc->msi_index; @@ -373,7 +39,7 @@ static const struct msi_domain_template platform_msi_templ= ate =3D { }, =20 .ops =3D { - .set_desc =3D platform_msi_set_desc_byindex, + .set_desc =3D platform_msi_set_desc, }, =20 .info =3D { @@ -408,10 +74,6 @@ int platform_device_msi_init_and_alloc_irqs(struct device= *dev, unsigned int nve if (!domain || !write_msi_msg) return -EINVAL; =20 - /* Migration support. Will go away once everything is converted */ - if (!irq_domain_is_msi_parent(domain)) - return platform_msi_domain_alloc_irqs(dev, nvec, write_msi_msg); - /* * @write_msi_msg is stored in the resulting msi_domain_info::data. * The underlying domain creation mechanism will assign that @@ -432,12 +94,6 @@ EXPORT_SYMBOL_GPL(platform_device_msi_init_and_alloc_irqs= ); */ void platform_device_msi_free_irqs_all(struct device *dev) { - struct irq_domain *domain =3D dev->msi.domain; - msi_domain_free_irqs_all(dev, MSI_DEFAULT_DOMAIN); - - /* Migration support. Will go away once everything is converted */ - if (!irq_domain_is_msi_parent(domain)) - platform_msi_free_priv_data(dev); } EXPORT_SYMBOL_GPL(platform_device_msi_free_irqs_all); diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index 14464716bacb..d078bdc48c38 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -26,6 +26,7 @@ config ARM_GIC_V2M bool depends on PCI select ARM_GIC + select IRQ_MSI_LIB select PCI_MSI =20 config GIC_NON_BANKED @@ -41,6 +42,7 @@ config ARM_GIC_V3 config ARM_GIC_V3_ITS bool select GENERIC_MSI_IRQ + select IRQ_MSI_LIB default ARM_GIC_V3 =20 config ARM_GIC_V3_ITS_PCI @@ -74,6 +76,9 @@ config ARM_VIC_NR The maximum number of VICs available in the system, for power management. =20 +config IRQ_MSI_LIB + bool + config ARMADA_370_XP_IRQ bool select GENERIC_IRQ_CHIP @@ -169,6 +174,18 @@ config IXP4XX_IRQ select IRQ_DOMAIN select SPARSE_IRQ =20 +config LAN966X_OIC + tristate "Microchip LAN966x OIC Support" + select GENERIC_IRQ_CHIP + select IRQ_DOMAIN + help + Enable support for the LAN966x Outbound Interrupt Controller. + This controller is present on the Microchip LAN966x PCI device and + maps the internal interrupts sources to PCIe interrupt. + + To compile this driver as a module, choose M here: the module + will be called irq-lan966x-oic. + config MADERA_IRQ tristate =20 @@ -366,6 +383,7 @@ config MSCC_OCELOT_IRQ select GENERIC_IRQ_CHIP =20 config MVEBU_GICP + select IRQ_MSI_LIB bool =20 config MVEBU_ICU @@ -373,6 +391,7 @@ config MVEBU_ICU =20 config MVEBU_ODMI bool + select IRQ_MSI_LIB select GENERIC_MSI_IRQ =20 config MVEBU_PIC @@ -392,6 +411,15 @@ config LS_SCFG_MSI config PARTITION_PERCPU bool =20 +config STM32MP_EXTI + tristate "STM32MP extended interrupts and event controller" + depends on (ARCH_STM32 && !ARM_SINGLE_ARMV7M) || COMPILE_TEST + default y + select IRQ_DOMAIN_HIERARCHY + select GENERIC_IRQ_CHIP + help + Support STM32MP EXTI (extended interrupts and event) controller. + config STM32_EXTI bool select IRQ_DOMAIN @@ -487,6 +515,7 @@ config IMX_MU_MSI select IRQ_DOMAIN select IRQ_DOMAIN_HIERARCHY select GENERIC_MSI_IRQ + select IRQ_MSI_LIB help Provide a driver for the i.MX Messaging Unit block used as a CPU-to-CPU MSI controller. This requires a specially crafted DT diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index d9dc3d99aaa8..15635812b2d6 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -29,10 +29,10 @@ obj-$(CONFIG_ARCH_SPEAR3XX) +=3D spear-shirq.o obj-$(CONFIG_ARM_GIC) +=3D irq-gic.o irq-gic-common.o obj-$(CONFIG_ARM_GIC_PM) +=3D irq-gic-pm.o obj-$(CONFIG_ARCH_REALVIEW) +=3D irq-gic-realview.o +obj-$(CONFIG_IRQ_MSI_LIB) +=3D irq-msi-lib.o obj-$(CONFIG_ARM_GIC_V2M) +=3D irq-gic-v2m.o obj-$(CONFIG_ARM_GIC_V3) +=3D irq-gic-v3.o irq-gic-v3-mbi.o irq-gic-common.o -obj-$(CONFIG_ARM_GIC_V3_ITS) +=3D irq-gic-v3-its.o irq-gic-v3-its-platform-= msi.o irq-gic-v4.o -obj-$(CONFIG_ARM_GIC_V3_ITS_PCI) +=3D irq-gic-v3-its-pci-msi.o +obj-$(CONFIG_ARM_GIC_V3_ITS) +=3D irq-gic-v3-its.o irq-gic-v4.o irq-gic-v3-= its-msi-parent.o obj-$(CONFIG_ARM_GIC_V3_ITS_FSL_MC) +=3D irq-gic-v3-its-fsl-mc-msi.o obj-$(CONFIG_PARTITION_PERCPU) +=3D irq-partition-percpu.o obj-$(CONFIG_HISILICON_IRQ_MBIGEN) +=3D irq-mbigen.o @@ -84,6 +84,7 @@ obj-$(CONFIG_MVEBU_SEI) +=3D irq-mvebu-sei.o obj-$(CONFIG_LS_EXTIRQ) +=3D irq-ls-extirq.o obj-$(CONFIG_LS_SCFG_MSI) +=3D irq-ls-scfg-msi.o obj-$(CONFIG_ARCH_ASPEED) +=3D irq-aspeed-vic.o irq-aspeed-i2c-ic.o irq-asp= eed-scu-ic.o +obj-$(CONFIG_STM32MP_EXTI) +=3D irq-stm32mp-exti.o obj-$(CONFIG_STM32_EXTI) +=3D irq-stm32-exti.o obj-$(CONFIG_QCOM_IRQ_COMBINER) +=3D qcom-irq-combiner.o obj-$(CONFIG_IRQ_UNIPHIER_AIDET) +=3D irq-uniphier-aidet.o @@ -104,6 +105,7 @@ obj-$(CONFIG_IMX_IRQSTEER) +=3D irq-imx-irqsteer.o obj-$(CONFIG_IMX_INTMUX) +=3D irq-imx-intmux.o obj-$(CONFIG_IMX_MU_MSI) +=3D irq-imx-mu-msi.o obj-$(CONFIG_MADERA_IRQ) +=3D irq-madera.o +obj-$(CONFIG_LAN966X_OIC) +=3D irq-lan966x-oic.o obj-$(CONFIG_LS1X_IRQ) +=3D irq-ls1x.o obj-$(CONFIG_TI_SCI_INTR_IRQCHIP) +=3D irq-ti-sci-intr.o obj-$(CONFIG_TI_SCI_INTA_IRQCHIP) +=3D irq-ti-sci-inta.o diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada= -370-xp.c index 4b021a67bdfe..dce2b80bf439 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c @@ -13,6 +13,7 @@ * warranty of any kind, whether express or implied. */ =20 +#include #include #include #include @@ -29,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -135,6 +137,7 @@ =20 #define ARMADA_370_XP_MAX_PER_CPU_IRQS (28) =20 +/* IPI and MSI interrupt definitions for IPI platforms */ #define IPI_DOORBELL_START (0) #define IPI_DOORBELL_END (8) #define IPI_DOORBELL_MASK 0xFF @@ -143,6 +146,14 @@ #define PCI_MSI_DOORBELL_END (32) #define PCI_MSI_DOORBELL_MASK 0xFFFF0000 =20 +/* MSI interrupt definitions for non-IPI platforms */ +#define PCI_MSI_FULL_DOORBELL_START 0 +#define PCI_MSI_FULL_DOORBELL_NR 32 +#define PCI_MSI_FULL_DOORBELL_END 32 +#define PCI_MSI_FULL_DOORBELL_MASK GENMASK(31, 0) +#define PCI_MSI_FULL_DOORBELL_SRC0_MASK GENMASK(15, 0) +#define PCI_MSI_FULL_DOORBELL_SRC1_MASK GENMASK(31, 16) + static void __iomem *per_cpu_int_base; static void __iomem *main_int_base; static struct irq_domain *armada_370_xp_mpic_domain; @@ -151,11 +162,46 @@ static int parent_irq; #ifdef CONFIG_PCI_MSI static struct irq_domain *armada_370_xp_msi_domain; static struct irq_domain *armada_370_xp_msi_inner_domain; -static DECLARE_BITMAP(msi_used, PCI_MSI_DOORBELL_NR); +static DECLARE_BITMAP(msi_used, PCI_MSI_FULL_DOORBELL_NR); static DEFINE_MUTEX(msi_used_lock); static phys_addr_t msi_doorbell_addr; #endif =20 +static inline bool is_ipi_available(void) +{ + /* + * We distinguish IPI availability in the IC by the IC not having a + * parent irq defined. If a parent irq is defined, there is a parent + * interrupt controller (e.g. GIC) that takes care of inter-processor + * interrupts. + */ + return parent_irq <=3D 0; +} + +static inline u32 msi_doorbell_mask(void) +{ + return is_ipi_available() ? PCI_MSI_DOORBELL_MASK : + PCI_MSI_FULL_DOORBELL_MASK; +} + +static inline unsigned int msi_doorbell_start(void) +{ + return is_ipi_available() ? PCI_MSI_DOORBELL_START : + PCI_MSI_FULL_DOORBELL_START; +} + +static inline unsigned int msi_doorbell_size(void) +{ + return is_ipi_available() ? PCI_MSI_DOORBELL_NR : + PCI_MSI_FULL_DOORBELL_NR; +} + +static inline unsigned int msi_doorbell_end(void) +{ + return is_ipi_available() ? PCI_MSI_DOORBELL_END : + PCI_MSI_FULL_DOORBELL_END; +} + static inline bool is_percpu_irq(irq_hw_number_t irq) { if (irq <=3D ARMADA_370_XP_MAX_PER_CPU_IRQS) @@ -213,7 +259,7 @@ static void armada_370_xp_compose_msi_msg(struct irq_data= *data, struct msi_msg =20 msg->address_lo =3D lower_32_bits(msi_doorbell_addr); msg->address_hi =3D upper_32_bits(msi_doorbell_addr); - msg->data =3D BIT(cpu + 8) | (data->hwirq + PCI_MSI_DOORBELL_START); + msg->data =3D BIT(cpu + 8) | (data->hwirq + msi_doorbell_start()); } =20 static int armada_370_xp_msi_set_affinity(struct irq_data *irq_data, @@ -246,7 +292,7 @@ static int armada_370_xp_msi_alloc(struct irq_domain *dom= ain, unsigned int virq, int hwirq, i; =20 mutex_lock(&msi_used_lock); - hwirq =3D bitmap_find_free_region(msi_used, PCI_MSI_DOORBELL_NR, + hwirq =3D bitmap_find_free_region(msi_used, msi_doorbell_size(), order_base_2(nr_irqs)); mutex_unlock(&msi_used_lock); =20 @@ -283,9 +329,10 @@ static void armada_370_xp_msi_reenable_percpu(void) u32 reg; =20 /* Enable MSI doorbell mask and combined cpu local interrupt */ - reg =3D readl(per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK_OFFS) - | PCI_MSI_DOORBELL_MASK; + reg =3D readl(per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK_OFFS); + reg |=3D msi_doorbell_mask(); writel(reg, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK_OFFS); + /* Unmask local doorbell interrupt */ writel(1, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS); } @@ -297,7 +344,7 @@ static int armada_370_xp_msi_init(struct device_node *nod= e, ARMADA_370_XP_SW_TRIG_INT_OFFS; =20 armada_370_xp_msi_inner_domain =3D - irq_domain_add_linear(NULL, PCI_MSI_DOORBELL_NR, + irq_domain_add_linear(NULL, msi_doorbell_size(), &armada_370_xp_msi_domain_ops, NULL); if (!armada_370_xp_msi_inner_domain) return -ENOMEM; @@ -313,6 +360,10 @@ static int armada_370_xp_msi_init(struct device_node *no= de, =20 armada_370_xp_msi_reenable_percpu(); =20 + /* Unmask low 16 MSI irqs on non-IPI platforms */ + if (!is_ipi_available()) + writel(0, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS); + return 0; } #else @@ -461,24 +512,18 @@ static __init void armada_xp_ipi_init(struct device_nod= e *node) set_smp_ipi_range(base_ipi, IPI_DOORBELL_END); } =20 -static DEFINE_RAW_SPINLOCK(irq_controller_lock); - static int armada_xp_set_affinity(struct irq_data *d, const struct cpumask *mask_val, bool force) { irq_hw_number_t hwirq =3D irqd_to_hwirq(d); - unsigned long reg, mask; int cpu; =20 /* Select a single core from the affinity mask which is online */ cpu =3D cpumask_any_and(mask_val, cpu_online_mask); - mask =3D 1UL << cpu_logical_map(cpu); =20 - raw_spin_lock(&irq_controller_lock); - reg =3D readl(main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq)); - reg =3D (reg & (~ARMADA_370_XP_INT_SOURCE_CPU_MASK)) | mask; - writel(reg, main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq)); - raw_spin_unlock(&irq_controller_lock); + atomic_io_modify(main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq), + ARMADA_370_XP_INT_SOURCE_CPU_MASK, + BIT(cpu_logical_map(cpu))); =20 irq_data_update_effective_affinity(d, cpumask_of(cpu)); =20 @@ -496,6 +541,9 @@ static void armada_xp_mpic_smp_cpu_init(void) for (i =3D 0; i < nr_irqs; i++) writel(i, per_cpu_int_base + ARMADA_370_XP_INT_SET_MASK_OFFS); =20 + if (!is_ipi_available()) + return; + /* Disable all IPIs */ writel(0, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK_OFFS); =20 @@ -527,7 +575,8 @@ static void armada_xp_mpic_reenable_percpu(void) armada_370_xp_irq_unmask(data); } =20 - ipi_resume(); + if (is_ipi_available()) + ipi_resume(); =20 armada_370_xp_msi_reenable_percpu(); } @@ -566,6 +615,10 @@ static struct irq_chip armada_370_xp_irq_chip =3D { static int armada_370_xp_mpic_irq_map(struct irq_domain *h, unsigned int virq, irq_hw_number_t hw) { + /* IRQs 0 and 1 cannot be mapped, they are handled internally */ + if (hw <=3D 1) + return -EINVAL; + armada_370_xp_irq_mask(irq_get_irq_data(virq)); if (!is_percpu_irq(hw)) writel(hw, per_cpu_int_base + @@ -599,20 +652,20 @@ static void armada_370_xp_handle_msi_irq(struct pt_regs= *regs, bool is_chained) u32 msimask, msinr; =20 msimask =3D readl_relaxed(per_cpu_int_base + - ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS) - & PCI_MSI_DOORBELL_MASK; + ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS); + msimask &=3D msi_doorbell_mask(); =20 writel(~msimask, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS); =20 - for (msinr =3D PCI_MSI_DOORBELL_START; - msinr < PCI_MSI_DOORBELL_END; msinr++) { + for (msinr =3D msi_doorbell_start(); + msinr < msi_doorbell_end(); msinr++) { unsigned int irq; =20 if (!(msimask & BIT(msinr))) continue; =20 - irq =3D msinr - PCI_MSI_DOORBELL_START; + irq =3D msinr - msi_doorbell_start(); =20 generic_handle_domain_irq(armada_370_xp_msi_inner_domain, irq); } @@ -641,7 +694,7 @@ static void armada_370_xp_mpic_handle_cascade_irq(struct = irq_desc *desc) if (!(irqsrc & ARMADA_370_XP_INT_IRQ_FIQ_MASK(cpuid))) continue; =20 - if (irqn =3D=3D 1) { + if (irqn =3D=3D 0 || irqn =3D=3D 1) { armada_370_xp_handle_msi_irq(NULL, true); continue; } @@ -702,6 +755,7 @@ static int armada_370_xp_mpic_suspend(void) =20 static void armada_370_xp_mpic_resume(void) { + bool src0, src1; int nirqs; irq_hw_number_t irq; =20 @@ -741,12 +795,22 @@ static void armada_370_xp_mpic_resume(void) /* Reconfigure doorbells for IPIs and MSIs */ writel(doorbell_mask_reg, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK_OFFS); - if (doorbell_mask_reg & IPI_DOORBELL_MASK) + + if (is_ipi_available()) { + src0 =3D doorbell_mask_reg & IPI_DOORBELL_MASK; + src1 =3D doorbell_mask_reg & PCI_MSI_DOORBELL_MASK; + } else { + src0 =3D doorbell_mask_reg & PCI_MSI_FULL_DOORBELL_SRC0_MASK; + src1 =3D doorbell_mask_reg & PCI_MSI_FULL_DOORBELL_SRC1_MASK; + } + + if (src0) writel(0, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS); - if (doorbell_mask_reg & PCI_MSI_DOORBELL_MASK) + if (src1) writel(1, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS); =20 - ipi_resume(); + if (is_ipi_available()) + ipi_resume(); } =20 static struct syscore_ops armada_370_xp_mpic_syscore_ops =3D { @@ -791,13 +855,18 @@ static int __init armada_370_xp_mpic_of_init(struct dev= ice_node *node, BUG_ON(!armada_370_xp_mpic_domain); irq_domain_update_bus_token(armada_370_xp_mpic_domain, DOMAIN_BUS_WIRED); =20 + /* + * Initialize parent_irq before calling any other functions, since it is + * used to distinguish between IPI and non-IPI platforms. + */ + parent_irq =3D irq_of_parse_and_map(node, 0); + /* Setup for the boot CPU */ armada_xp_mpic_perf_init(); armada_xp_mpic_smp_cpu_init(); =20 armada_370_xp_msi_init(node, main_int_res.start); =20 - parent_irq =3D irq_of_parse_and_map(node, 0); if (parent_irq <=3D 0) { irq_set_default_host(armada_370_xp_mpic_domain); set_handle_irq(armada_370_xp_handle_irq); diff --git a/drivers/irqchip/irq-bcm2835.c b/drivers/irqchip/irq-bcm2835.c index e94e2882286c..6c20604c2242 100644 --- a/drivers/irqchip/irq-bcm2835.c +++ b/drivers/irqchip/irq-bcm2835.c @@ -102,7 +102,9 @@ static void armctrl_unmask_irq(struct irq_data *d) static struct irq_chip armctrl_chip =3D { .name =3D "ARMCTRL-level", .irq_mask =3D armctrl_mask_irq, - .irq_unmask =3D armctrl_unmask_irq + .irq_unmask =3D armctrl_unmask_irq, + .flags =3D IRQCHIP_MASK_ON_SUSPEND | + IRQCHIP_SKIP_SET_WAKE, }; =20 static int armctrl_xlate(struct irq_domain *d, struct device_node *ctrlr, diff --git a/drivers/irqchip/irq-gic-common.h b/drivers/irqchip/irq-gic-commo= n.h index f407cce9ecaa..eb4a220dd6ad 100644 --- a/drivers/irqchip/irq-gic-common.h +++ b/drivers/irqchip/irq-gic-common.h @@ -8,6 +8,7 @@ =20 #include #include +#include #include =20 struct gic_quirk { @@ -29,6 +30,8 @@ void gic_enable_quirks(u32 iidr, const struct gic_quirk *qu= irks, void gic_enable_of_quirks(const struct device_node *np, const struct gic_quirk *quirks, void *data); =20 +extern const struct msi_parent_ops gic_v3_its_msi_parent_ops; + #define RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING (1 << 0) #define RDIST_FLAGS_RD_TABLES_PREALLOCATED (1 << 1) #define RDIST_FLAGS_FORCE_NON_SHAREABLE (1 << 2) diff --git a/drivers/irqchip/irq-gic-v2m.c b/drivers/irqchip/irq-gic-v2m.c index f2ff4387870d..51af63c046ed 100644 --- a/drivers/irqchip/irq-gic-v2m.c +++ b/drivers/irqchip/irq-gic-v2m.c @@ -26,6 +26,8 @@ #include #include =20 +#include "irq-msi-lib.h" + /* * MSI_TYPER: * [31:26] Reserved @@ -72,31 +74,6 @@ struct v2m_data { u32 flags; /* v2m flags for specific implementation */ }; =20 -static void gicv2m_mask_msi_irq(struct irq_data *d) -{ - pci_msi_mask_irq(d); - irq_chip_mask_parent(d); -} - -static void gicv2m_unmask_msi_irq(struct irq_data *d) -{ - pci_msi_unmask_irq(d); - irq_chip_unmask_parent(d); -} - -static struct irq_chip gicv2m_msi_irq_chip =3D { - .name =3D "MSI", - .irq_mask =3D gicv2m_mask_msi_irq, - .irq_unmask =3D gicv2m_unmask_msi_irq, - .irq_eoi =3D irq_chip_eoi_parent, -}; - -static struct msi_domain_info gicv2m_msi_domain_info =3D { - .flags =3D (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | - MSI_FLAG_PCI_MSIX | MSI_FLAG_MULTI_PCI_MSI), - .chip =3D &gicv2m_msi_irq_chip, -}; - static phys_addr_t gicv2m_get_msi_addr(struct v2m_data *v2m, int hwirq) { if (v2m->flags & GICV2M_GRAVITON_ADDRESS_ONLY) @@ -230,6 +207,7 @@ static void gicv2m_irq_domain_free(struct irq_domain *dom= ain, } =20 static const struct irq_domain_ops gicv2m_domain_ops =3D { + .select =3D msi_lib_irq_domain_select, .alloc =3D gicv2m_irq_domain_alloc, .free =3D gicv2m_irq_domain_free, }; @@ -250,19 +228,6 @@ static bool is_msi_spi_valid(u32 base, u32 num) return true; } =20 -static struct irq_chip gicv2m_pmsi_irq_chip =3D { - .name =3D "pMSI", -}; - -static struct msi_domain_ops gicv2m_pmsi_ops =3D { -}; - -static struct msi_domain_info gicv2m_pmsi_domain_info =3D { - .flags =3D (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS), - .ops =3D &gicv2m_pmsi_ops, - .chip =3D &gicv2m_pmsi_irq_chip, -}; - static void __init gicv2m_teardown(void) { struct v2m_data *v2m, *tmp; @@ -278,9 +243,27 @@ static void __init gicv2m_teardown(void) } } =20 + +#define GICV2M_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | \ + MSI_FLAG_USE_DEF_CHIP_OPS | \ + MSI_FLAG_PCI_MSI_MASK_PARENT) + +#define GICV2M_MSI_FLAGS_SUPPORTED (MSI_GENERIC_FLAGS_MASK | \ + MSI_FLAG_PCI_MSIX | \ + MSI_FLAG_MULTI_PCI_MSI) + +static struct msi_parent_ops gicv2m_msi_parent_ops =3D { + .supported_flags =3D GICV2M_MSI_FLAGS_SUPPORTED, + .required_flags =3D GICV2M_MSI_FLAGS_REQUIRED, + .bus_select_token =3D DOMAIN_BUS_NEXUS, + .bus_select_mask =3D MATCH_PCI_MSI | MATCH_PLATFORM_MSI, + .prefix =3D "GICv2m-", + .init_dev_msi_info =3D msi_lib_init_dev_msi_info, +}; + static __init int gicv2m_allocate_domains(struct irq_domain *parent) { - struct irq_domain *inner_domain, *pci_domain, *plat_domain; + struct irq_domain *inner_domain; struct v2m_data *v2m; =20 v2m =3D list_first_entry_or_null(&v2m_nodes, struct v2m_data, entry); @@ -295,22 +278,8 @@ static __init int gicv2m_allocate_domains(struct irq_dom= ain *parent) } =20 irq_domain_update_bus_token(inner_domain, DOMAIN_BUS_NEXUS); - pci_domain =3D pci_msi_create_irq_domain(v2m->fwnode, - &gicv2m_msi_domain_info, - inner_domain); - plat_domain =3D platform_msi_create_irq_domain(v2m->fwnode, - &gicv2m_pmsi_domain_info, - inner_domain); - if (!pci_domain || !plat_domain) { - pr_err("Failed to create MSI domains\n"); - if (plat_domain) - irq_domain_remove(plat_domain); - if (pci_domain) - irq_domain_remove(pci_domain); - irq_domain_remove(inner_domain); - return -ENOMEM; - } - + inner_domain->flags |=3D IRQ_DOMAIN_FLAG_MSI_PARENT; + inner_domain->msi_parent_ops =3D &gicv2m_msi_parent_ops; return 0; } =20 @@ -511,7 +480,7 @@ acpi_parse_madt_msi(union acpi_subtable_headers *header, pr_info("applying Amazon Graviton quirk\n"); res.end =3D res.start + SZ_8K - 1; flags |=3D GICV2M_GRAVITON_ADDRESS_ONLY; - gicv2m_msi_domain_info.flags &=3D ~MSI_FLAG_MULTI_PCI_MSI; + gicv2m_msi_parent_ops.supported_flags &=3D ~MSI_FLAG_MULTI_PCI_MSI; } =20 if (m->flags & ACPI_MADT_OVERRIDE_SPI_VALUES) { diff --git a/drivers/irqchip/irq-gic-v3-its-msi-parent.c b/drivers/irqchip/ir= q-gic-v3-its-msi-parent.c new file mode 100644 index 000000000000..780e1bc9df54 --- /dev/null +++ b/drivers/irqchip/irq-gic-v3-its-msi-parent.c @@ -0,0 +1,210 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (C) 2013-2015 ARM Limited, All Rights Reserved. +// Author: Marc Zyngier +// Copyright (C) 2022 Linutronix GmbH +// Copyright (C) 2022 Intel + +#include +#include + +#include "irq-gic-common.h" +#include "irq-msi-lib.h" + +#define ITS_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | \ + MSI_FLAG_USE_DEF_CHIP_OPS | \ + MSI_FLAG_PCI_MSI_MASK_PARENT) + +#define ITS_MSI_FLAGS_SUPPORTED (MSI_GENERIC_FLAGS_MASK | \ + MSI_FLAG_PCI_MSIX | \ + MSI_FLAG_MULTI_PCI_MSI) + +#ifdef CONFIG_PCI_MSI +static int its_pci_msi_vec_count(struct pci_dev *pdev, void *data) +{ + int msi, msix, *count =3D data; + + msi =3D max(pci_msi_vec_count(pdev), 0); + msix =3D max(pci_msix_vec_count(pdev), 0); + *count +=3D max(msi, msix); + + return 0; +} + +static int its_get_pci_alias(struct pci_dev *pdev, u16 alias, void *data) +{ + struct pci_dev **alias_dev =3D data; + + *alias_dev =3D pdev; + + return 0; +} + +static int its_pci_msi_prepare(struct irq_domain *domain, struct device *dev, + int nvec, msi_alloc_info_t *info) +{ + struct pci_dev *pdev, *alias_dev; + struct msi_domain_info *msi_info; + int alias_count =3D 0, minnvec =3D 1; + + if (!dev_is_pci(dev)) + return -EINVAL; + + pdev =3D to_pci_dev(dev); + /* + * If pdev is downstream of any aliasing bridges, take an upper + * bound of how many other vectors could map to the same DevID. + * Also tell the ITS that the signalling will come from a proxy + * device, and that special allocation rules apply. + */ + pci_for_each_dma_alias(pdev, its_get_pci_alias, &alias_dev); + if (alias_dev !=3D pdev) { + if (alias_dev->subordinate) + pci_walk_bus(alias_dev->subordinate, + its_pci_msi_vec_count, &alias_count); + info->flags |=3D MSI_ALLOC_FLAGS_PROXY_DEVICE; + } + + /* ITS specific DeviceID, as the core ITS ignores dev. */ + info->scratchpad[0].ul =3D pci_msi_domain_get_msi_rid(domain, pdev); + + /* + * @domain->msi_domain_info->hwsize contains the size of the + * MSI[-X] domain, but vector allocation happens one by one. This + * needs some thought when MSI comes into play as the size of MSI + * might be unknown at domain creation time and therefore set to + * MSI_MAX_INDEX. + */ + msi_info =3D msi_get_domain_info(domain); + if (msi_info->hwsize > nvec) + nvec =3D msi_info->hwsize; + + /* + * Always allocate a power of 2, and special case device 0 for + * broken systems where the DevID is not wired (and all devices + * appear as DevID 0). For that reason, we generously allocate a + * minimum of 32 MSIs for DevID 0. If you want more because all + * your devices are aliasing to DevID 0, consider fixing your HW. + */ + nvec =3D max(nvec, alias_count); + if (!info->scratchpad[0].ul) + minnvec =3D 32; + nvec =3D max_t(int, minnvec, roundup_pow_of_two(nvec)); + + msi_info =3D msi_get_domain_info(domain->parent); + return msi_info->ops->msi_prepare(domain->parent, dev, nvec, info); +} +#else /* CONFIG_PCI_MSI */ +#define its_pci_msi_prepare NULL +#endif /* !CONFIG_PCI_MSI */ + +static int of_pmsi_get_dev_id(struct irq_domain *domain, struct device *dev, + u32 *dev_id) +{ + int ret, index =3D 0; + + /* Suck the DeviceID out of the msi-parent property */ + do { + struct of_phandle_args args; + + ret =3D of_parse_phandle_with_args(dev->of_node, + "msi-parent", "#msi-cells", + index, &args); + if (args.np =3D=3D irq_domain_get_of_node(domain)) { + if (WARN_ON(args.args_count !=3D 1)) + return -EINVAL; + *dev_id =3D args.args[0]; + break; + } + index++; + } while (!ret); + + return ret; +} + +int __weak iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id) +{ + return -1; +} + +static int its_pmsi_prepare(struct irq_domain *domain, struct device *dev, + int nvec, msi_alloc_info_t *info) +{ + struct msi_domain_info *msi_info; + u32 dev_id; + int ret; + + if (dev->of_node) + ret =3D of_pmsi_get_dev_id(domain, dev, &dev_id); + else + ret =3D iort_pmsi_get_dev_id(dev, &dev_id); + if (ret) + return ret; + + /* ITS specific DeviceID, as the core ITS ignores dev. */ + info->scratchpad[0].ul =3D dev_id; + + /* + * @domain->msi_domain_info->hwsize contains the size of the device + * domain, but vector allocation happens one by one. + */ + msi_info =3D msi_get_domain_info(domain); + if (msi_info->hwsize > nvec) + nvec =3D msi_info->hwsize; + + /* Allocate at least 32 MSIs, and always as a power of 2 */ + nvec =3D max_t(int, 32, roundup_pow_of_two(nvec)); + + msi_info =3D msi_get_domain_info(domain->parent); + return msi_info->ops->msi_prepare(domain->parent, + dev, nvec, info); +} + +static bool its_init_dev_msi_info(struct device *dev, struct irq_domain *dom= ain, + struct irq_domain *real_parent, struct msi_domain_info *info) +{ + if (!msi_lib_init_dev_msi_info(dev, domain, real_parent, info)) + return false; + + switch(info->bus_token) { + case DOMAIN_BUS_PCI_DEVICE_MSI: + case DOMAIN_BUS_PCI_DEVICE_MSIX: + /* + * FIXME: This probably should be done after a (not yet + * existing) post domain creation callback once to make + * support for dynamic post-enable MSI-X allocations + * work without having to reevaluate the domain size + * over and over. It is known already at allocation + * time via info->hwsize. + * + * That should work perfectly fine for MSI/MSI-X but needs + * some thoughts for purely software managed MSI domains + * where the index space is only limited artificially via + * %MSI_MAX_INDEX. + */ + info->ops->msi_prepare =3D its_pci_msi_prepare; + break; + case DOMAIN_BUS_DEVICE_MSI: + case DOMAIN_BUS_WIRED_TO_MSI: + /* + * FIXME: See the above PCI prepare comment. The domain + * size is also known at domain creation time. + */ + info->ops->msi_prepare =3D its_pmsi_prepare; + break; + default: + /* Confused. How did the lib return true? */ + WARN_ON_ONCE(1); + return false; + } + + return true; +} + +const struct msi_parent_ops gic_v3_its_msi_parent_ops =3D { + .supported_flags =3D ITS_MSI_FLAGS_SUPPORTED, + .required_flags =3D ITS_MSI_FLAGS_REQUIRED, + .bus_select_token =3D DOMAIN_BUS_NEXUS, + .bus_select_mask =3D MATCH_PCI_MSI | MATCH_PLATFORM_MSI, + .prefix =3D "ITS-", + .init_dev_msi_info =3D its_init_dev_msi_info, +}; diff --git a/drivers/irqchip/irq-gic-v3-its-pci-msi.c b/drivers/irqchip/irq-g= ic-v3-its-pci-msi.c deleted file mode 100644 index 93f77a8196da..000000000000 --- a/drivers/irqchip/irq-gic-v3-its-pci-msi.c +++ /dev/null @@ -1,202 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) 2013-2015 ARM Limited, All Rights Reserved. - * Author: Marc Zyngier - */ - -#include -#include -#include -#include -#include -#include - -static void its_mask_msi_irq(struct irq_data *d) -{ - pci_msi_mask_irq(d); - irq_chip_mask_parent(d); -} - -static void its_unmask_msi_irq(struct irq_data *d) -{ - pci_msi_unmask_irq(d); - irq_chip_unmask_parent(d); -} - -static struct irq_chip its_msi_irq_chip =3D { - .name =3D "ITS-MSI", - .irq_unmask =3D its_unmask_msi_irq, - .irq_mask =3D its_mask_msi_irq, - .irq_eoi =3D irq_chip_eoi_parent, -}; - -static int its_pci_msi_vec_count(struct pci_dev *pdev, void *data) -{ - int msi, msix, *count =3D data; - - msi =3D max(pci_msi_vec_count(pdev), 0); - msix =3D max(pci_msix_vec_count(pdev), 0); - *count +=3D max(msi, msix); - - return 0; -} - -static int its_get_pci_alias(struct pci_dev *pdev, u16 alias, void *data) -{ - struct pci_dev **alias_dev =3D data; - - *alias_dev =3D pdev; - - return 0; -} - -static int its_pci_msi_prepare(struct irq_domain *domain, struct device *dev, - int nvec, msi_alloc_info_t *info) -{ - struct pci_dev *pdev, *alias_dev; - struct msi_domain_info *msi_info; - int alias_count =3D 0, minnvec =3D 1; - - if (!dev_is_pci(dev)) - return -EINVAL; - - msi_info =3D msi_get_domain_info(domain->parent); - - pdev =3D to_pci_dev(dev); - /* - * If pdev is downstream of any aliasing bridges, take an upper - * bound of how many other vectors could map to the same DevID. - * Also tell the ITS that the signalling will come from a proxy - * device, and that special allocation rules apply. - */ - pci_for_each_dma_alias(pdev, its_get_pci_alias, &alias_dev); - if (alias_dev !=3D pdev) { - if (alias_dev->subordinate) - pci_walk_bus(alias_dev->subordinate, - its_pci_msi_vec_count, &alias_count); - info->flags |=3D MSI_ALLOC_FLAGS_PROXY_DEVICE; - } - - /* ITS specific DeviceID, as the core ITS ignores dev. */ - info->scratchpad[0].ul =3D pci_msi_domain_get_msi_rid(domain, pdev); - - /* - * Always allocate a power of 2, and special case device 0 for - * broken systems where the DevID is not wired (and all devices - * appear as DevID 0). For that reason, we generously allocate a - * minimum of 32 MSIs for DevID 0. If you want more because all - * your devices are aliasing to DevID 0, consider fixing your HW. - */ - nvec =3D max(nvec, alias_count); - if (!info->scratchpad[0].ul) - minnvec =3D 32; - nvec =3D max_t(int, minnvec, roundup_pow_of_two(nvec)); - return msi_info->ops->msi_prepare(domain->parent, dev, nvec, info); -} - -static struct msi_domain_ops its_pci_msi_ops =3D { - .msi_prepare =3D its_pci_msi_prepare, -}; - -static struct msi_domain_info its_pci_msi_domain_info =3D { - .flags =3D (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | - MSI_FLAG_MULTI_PCI_MSI | MSI_FLAG_PCI_MSIX), - .ops =3D &its_pci_msi_ops, - .chip =3D &its_msi_irq_chip, -}; - -static struct of_device_id its_device_id[] =3D { - { .compatible =3D "arm,gic-v3-its", }, - {}, -}; - -static int __init its_pci_msi_init_one(struct fwnode_handle *handle, - const char *name) -{ - struct irq_domain *parent; - - parent =3D irq_find_matching_fwnode(handle, DOMAIN_BUS_NEXUS); - if (!parent || !msi_get_domain_info(parent)) { - pr_err("%s: Unable to locate ITS domain\n", name); - return -ENXIO; - } - - if (!pci_msi_create_irq_domain(handle, &its_pci_msi_domain_info, - parent)) { - pr_err("%s: Unable to create PCI domain\n", name); - return -ENOMEM; - } - - return 0; -} - -static int __init its_pci_of_msi_init(void) -{ - struct device_node *np; - - for (np =3D of_find_matching_node(NULL, its_device_id); np; - np =3D of_find_matching_node(np, its_device_id)) { - if (!of_device_is_available(np)) - continue; - if (!of_property_read_bool(np, "msi-controller")) - continue; - - if (its_pci_msi_init_one(of_node_to_fwnode(np), np->full_name)) - continue; - - pr_info("PCI/MSI: %pOF domain created\n", np); - } - - return 0; -} - -#ifdef CONFIG_ACPI - -static int __init -its_pci_msi_parse_madt(union acpi_subtable_headers *header, - const unsigned long end) -{ - struct acpi_madt_generic_translator *its_entry; - struct fwnode_handle *dom_handle; - const char *node_name; - int err =3D -ENXIO; - - its_entry =3D (struct acpi_madt_generic_translator *)header; - node_name =3D kasprintf(GFP_KERNEL, "ITS@0x%lx", - (long)its_entry->base_address); - dom_handle =3D iort_find_domain_token(its_entry->translation_id); - if (!dom_handle) { - pr_err("%s: Unable to locate ITS domain handle\n", node_name); - goto out; - } - - err =3D its_pci_msi_init_one(dom_handle, node_name); - if (!err) - pr_info("PCI/MSI: %s domain created\n", node_name); - -out: - kfree(node_name); - return err; -} - -static int __init its_pci_acpi_msi_init(void) -{ - acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_TRANSLATOR, - its_pci_msi_parse_madt, 0); - return 0; -} -#else -static int __init its_pci_acpi_msi_init(void) -{ - return 0; -} -#endif - -static int __init its_pci_msi_init(void) -{ - its_pci_of_msi_init(); - its_pci_acpi_msi_init(); - - return 0; -} -early_initcall(its_pci_msi_init); diff --git a/drivers/irqchip/irq-gic-v3-its-platform-msi.c b/drivers/irqchip/= irq-gic-v3-its-platform-msi.c deleted file mode 100644 index daa6d5053bc3..000000000000 --- a/drivers/irqchip/irq-gic-v3-its-platform-msi.c +++ /dev/null @@ -1,163 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) 2013-2015 ARM Limited, All Rights Reserved. - * Author: Marc Zyngier - */ - -#include -#include -#include -#include -#include - -static struct irq_chip its_pmsi_irq_chip =3D { - .name =3D "ITS-pMSI", -}; - -static int of_pmsi_get_dev_id(struct irq_domain *domain, struct device *dev, - u32 *dev_id) -{ - int ret, index =3D 0; - - /* Suck the DeviceID out of the msi-parent property */ - do { - struct of_phandle_args args; - - ret =3D of_parse_phandle_with_args(dev->of_node, - "msi-parent", "#msi-cells", - index, &args); - if (args.np =3D=3D irq_domain_get_of_node(domain)) { - if (WARN_ON(args.args_count !=3D 1)) - return -EINVAL; - *dev_id =3D args.args[0]; - break; - } - index++; - } while (!ret); - - return ret; -} - -int __weak iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id) -{ - return -1; -} - -static int its_pmsi_prepare(struct irq_domain *domain, struct device *dev, - int nvec, msi_alloc_info_t *info) -{ - struct msi_domain_info *msi_info; - u32 dev_id; - int ret; - - msi_info =3D msi_get_domain_info(domain->parent); - - if (dev->of_node) - ret =3D of_pmsi_get_dev_id(domain, dev, &dev_id); - else - ret =3D iort_pmsi_get_dev_id(dev, &dev_id); - if (ret) - return ret; - - /* ITS specific DeviceID, as the core ITS ignores dev. */ - info->scratchpad[0].ul =3D dev_id; - - /* Allocate at least 32 MSIs, and always as a power of 2 */ - nvec =3D max_t(int, 32, roundup_pow_of_two(nvec)); - return msi_info->ops->msi_prepare(domain->parent, - dev, nvec, info); -} - -static struct msi_domain_ops its_pmsi_ops =3D { - .msi_prepare =3D its_pmsi_prepare, -}; - -static struct msi_domain_info its_pmsi_domain_info =3D { - .flags =3D (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS), - .ops =3D &its_pmsi_ops, - .chip =3D &its_pmsi_irq_chip, -}; - -static const struct of_device_id its_device_id[] =3D { - { .compatible =3D "arm,gic-v3-its", }, - {}, -}; - -static int __init its_pmsi_init_one(struct fwnode_handle *fwnode, - const char *name) -{ - struct irq_domain *parent; - - parent =3D irq_find_matching_fwnode(fwnode, DOMAIN_BUS_NEXUS); - if (!parent || !msi_get_domain_info(parent)) { - pr_err("%s: unable to locate ITS domain\n", name); - return -ENXIO; - } - - if (!platform_msi_create_irq_domain(fwnode, &its_pmsi_domain_info, - parent)) { - pr_err("%s: unable to create platform domain\n", name); - return -ENXIO; - } - - pr_info("Platform MSI: %s domain created\n", name); - return 0; -} - -#ifdef CONFIG_ACPI -static int __init -its_pmsi_parse_madt(union acpi_subtable_headers *header, - const unsigned long end) -{ - struct acpi_madt_generic_translator *its_entry; - struct fwnode_handle *domain_handle; - const char *node_name; - int err =3D -ENXIO; - - its_entry =3D (struct acpi_madt_generic_translator *)header; - node_name =3D kasprintf(GFP_KERNEL, "ITS@0x%lx", - (long)its_entry->base_address); - domain_handle =3D iort_find_domain_token(its_entry->translation_id); - if (!domain_handle) { - pr_err("%s: Unable to locate ITS domain handle\n", node_name); - goto out; - } - - err =3D its_pmsi_init_one(domain_handle, node_name); - -out: - kfree(node_name); - return err; -} - -static void __init its_pmsi_acpi_init(void) -{ - acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_TRANSLATOR, - its_pmsi_parse_madt, 0); -} -#else -static inline void its_pmsi_acpi_init(void) { } -#endif - -static void __init its_pmsi_of_init(void) -{ - struct device_node *np; - - for (np =3D of_find_matching_node(NULL, its_device_id); np; - np =3D of_find_matching_node(np, its_device_id)) { - if (!of_device_is_available(np)) - continue; - if (!of_property_read_bool(np, "msi-controller")) - continue; - - its_pmsi_init_one(of_node_to_fwnode(np), np->full_name); - } -} - -static int __init its_pmsi_init(void) -{ - its_pmsi_of_init(); - its_pmsi_acpi_init(); - return 0; -} -early_initcall(its_pmsi_init); diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-it= s.c index 3c755d5dad6e..18cb551889e9 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -38,6 +38,7 @@ #include =20 #include "irq-gic-common.h" +#include "irq-msi-lib.h" =20 #define ITS_FLAGS_CMDQ_NEEDS_FLUSHING (1ULL << 0) #define ITS_FLAGS_WORKAROUND_CAVIUM_22375 (1ULL << 1) @@ -1317,7 +1318,6 @@ static void its_send_vmovp(struct its_vpe *vpe) { struct its_cmd_desc desc =3D {}; struct its_node *its; - unsigned long flags; int col_id =3D vpe->col_idx; =20 desc.its_vmovp_cmd.vpe =3D vpe; @@ -1329,6 +1329,12 @@ static void its_send_vmovp(struct its_vpe *vpe) return; } =20 + /* + * Protect against concurrent updates of the mapping state on + * individual VMs. + */ + guard(raw_spinlock_irqsave)(&vpe->its_vm->vmapp_lock); + /* * Yet another marvel of the architecture. If using the * its_list "feature", we need to make sure that all ITSs @@ -1337,8 +1343,7 @@ static void its_send_vmovp(struct its_vpe *vpe) * * Wall <-- Head. */ - raw_spin_lock_irqsave(&vmovp_lock, flags); - + guard(raw_spinlock)(&vmovp_lock); desc.its_vmovp_cmd.seq_num =3D vmovp_seq_num++; desc.its_vmovp_cmd.its_list =3D get_its_list(vpe->its_vm); =20 @@ -1353,8 +1358,6 @@ static void its_send_vmovp(struct its_vpe *vpe) desc.its_vmovp_cmd.col =3D &its->collections[col_id]; its_send_single_vcommand(its, its_build_vmovp_cmd, &desc); } - - raw_spin_unlock_irqrestore(&vmovp_lock, flags); } =20 static void its_send_vinvall(struct its_node *its, struct its_vpe *vpe) @@ -1791,12 +1794,10 @@ static bool gic_requires_eager_mapping(void) =20 static void its_map_vm(struct its_node *its, struct its_vm *vm) { - unsigned long flags; - if (gic_requires_eager_mapping()) return; =20 - raw_spin_lock_irqsave(&vmovp_lock, flags); + guard(raw_spinlock_irqsave)(&vm->vmapp_lock); =20 /* * If the VM wasn't mapped yet, iterate over the vpes and get @@ -1809,37 +1810,31 @@ static void its_map_vm(struct its_node *its, struct i= ts_vm *vm) =20 for (i =3D 0; i < vm->nr_vpes; i++) { struct its_vpe *vpe =3D vm->vpes[i]; - struct irq_data *d =3D irq_get_irq_data(vpe->irq); =20 - /* Map the VPE to the first possible CPU */ - vpe->col_idx =3D cpumask_first(cpu_online_mask); - its_send_vmapp(its, vpe, true); + scoped_guard(raw_spinlock, &vpe->vpe_lock) + its_send_vmapp(its, vpe, true); + its_send_vinvall(its, vpe); - irq_data_update_effective_affinity(d, cpumask_of(vpe->col_idx)); } } - - raw_spin_unlock_irqrestore(&vmovp_lock, flags); } =20 static void its_unmap_vm(struct its_node *its, struct its_vm *vm) { - unsigned long flags; - /* Not using the ITS list? Everything is always mapped. */ if (gic_requires_eager_mapping()) return; =20 - raw_spin_lock_irqsave(&vmovp_lock, flags); + guard(raw_spinlock_irqsave)(&vm->vmapp_lock); =20 if (!--vm->vlpi_count[its->list_nr]) { int i; =20 - for (i =3D 0; i < vm->nr_vpes; i++) + for (i =3D 0; i < vm->nr_vpes; i++) { + guard(raw_spinlock)(&vm->vpes[i]->vpe_lock); its_send_vmapp(its, vm->vpes[i], false); + } } - - raw_spin_unlock_irqrestore(&vmovp_lock, flags); } =20 static int its_vlpi_map(struct irq_data *d, struct its_cmd_info *info) @@ -3688,6 +3683,7 @@ static void its_irq_domain_free(struct irq_domain *doma= in, unsigned int virq, } =20 static const struct irq_domain_ops its_domain_ops =3D { + .select =3D msi_lib_irq_domain_select, .alloc =3D its_irq_domain_alloc, .free =3D its_irq_domain_free, .activate =3D its_irq_domain_activate, @@ -3926,6 +3922,8 @@ static void its_vpe_invall(struct its_vpe *vpe) { struct its_node *its; =20 + guard(raw_spinlock_irqsave)(&vpe->its_vm->vmapp_lock); + list_for_each_entry(its, &its_nodes, entry) { if (!is_v4(its)) continue; @@ -4531,6 +4529,7 @@ static int its_vpe_irq_domain_alloc(struct irq_domain *= domain, unsigned int virq vm->db_lpi_base =3D base; vm->nr_db_lpis =3D nr_ids; vm->vprop_page =3D vprop_page; + raw_spin_lock_init(&vm->vmapp_lock); =20 if (gic_rdists->has_rvpeid) irqchip =3D &its_vpe_4_1_irq_chip; @@ -4562,6 +4561,10 @@ static int its_vpe_irq_domain_activate(struct irq_doma= in *domain, struct its_vpe *vpe =3D irq_data_get_irq_chip_data(d); struct its_node *its; =20 + /* Map the VPE to the first possible CPU */ + vpe->col_idx =3D cpumask_first(cpu_online_mask); + irq_data_update_effective_affinity(d, cpumask_of(vpe->col_idx)); + /* * If we use the list map, we issue VMAPP on demand... Unless * we're on a GICv4.1 and we eagerly map the VPE on all ITSs @@ -4570,9 +4573,6 @@ static int its_vpe_irq_domain_activate(struct irq_domai= n *domain, if (!gic_requires_eager_mapping()) return 0; =20 - /* Map the VPE to the first possible CPU */ - vpe->col_idx =3D cpumask_first(cpu_online_mask); - list_for_each_entry(its, &its_nodes, entry) { if (!is_v4(its)) continue; @@ -4581,8 +4581,6 @@ static int its_vpe_irq_domain_activate(struct irq_domai= n *domain, its_send_vinvall(its, vpe); } =20 - irq_data_update_effective_affinity(d, cpumask_of(vpe->col_idx)); - return 0; } =20 @@ -4993,6 +4991,9 @@ static int its_init_domain(struct its_node *its) =20 irq_domain_update_bus_token(inner_domain, DOMAIN_BUS_NEXUS); =20 + inner_domain->msi_parent_ops =3D &gic_v3_its_msi_parent_ops; + inner_domain->flags |=3D IRQ_DOMAIN_FLAG_MSI_PARENT; + return 0; } =20 @@ -5580,6 +5581,10 @@ static int __init gic_acpi_parse_madt_its(union acpi_s= ubtable_headers *header, goto node_err; } =20 + if (acpi_get_madt_revision() >=3D 7 && + (its_entry->flags & ACPI_MADT_ITS_NON_COHERENT)) + its->flags |=3D ITS_FLAGS_FORCE_NON_SHAREABLE; + err =3D its_probe_one(its); if (!err) return 0; diff --git a/drivers/irqchip/irq-gic-v3-mbi.c b/drivers/irqchip/irq-gic-v3-mb= i.c index dbb8b1efda44..3fe870f8ee17 100644 --- a/drivers/irqchip/irq-gic-v3-mbi.c +++ b/drivers/irqchip/irq-gic-v3-mbi.c @@ -18,6 +18,8 @@ =20 #include =20 +#include "irq-msi-lib.h" + struct mbi_range { u32 spi_start; u32 nr_spis; @@ -138,6 +140,7 @@ static void mbi_irq_domain_free(struct irq_domain *domain, } =20 static const struct irq_domain_ops mbi_domain_ops =3D { + .select =3D msi_lib_irq_domain_select, .alloc =3D mbi_irq_domain_alloc, .free =3D mbi_irq_domain_free, }; @@ -151,54 +154,6 @@ static void mbi_compose_msi_msg(struct irq_data *data, s= truct msi_msg *msg) iommu_dma_compose_msi_msg(irq_data_get_msi_desc(data), msg); } =20 -#ifdef CONFIG_PCI_MSI -/* PCI-specific irqchip */ -static void mbi_mask_msi_irq(struct irq_data *d) -{ - pci_msi_mask_irq(d); - irq_chip_mask_parent(d); -} - -static void mbi_unmask_msi_irq(struct irq_data *d) -{ - pci_msi_unmask_irq(d); - irq_chip_unmask_parent(d); -} - -static struct irq_chip mbi_msi_irq_chip =3D { - .name =3D "MSI", - .irq_mask =3D mbi_mask_msi_irq, - .irq_unmask =3D mbi_unmask_msi_irq, - .irq_eoi =3D irq_chip_eoi_parent, - .irq_compose_msi_msg =3D mbi_compose_msi_msg, -}; - -static struct msi_domain_info mbi_msi_domain_info =3D { - .flags =3D (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | - MSI_FLAG_PCI_MSIX | MSI_FLAG_MULTI_PCI_MSI), - .chip =3D &mbi_msi_irq_chip, -}; - -static int mbi_allocate_pci_domain(struct irq_domain *nexus_domain, - struct irq_domain **pci_domain) -{ - *pci_domain =3D pci_msi_create_irq_domain(nexus_domain->parent->fwnode, - &mbi_msi_domain_info, - nexus_domain); - if (!*pci_domain) - return -ENOMEM; - - return 0; -} -#else -static int mbi_allocate_pci_domain(struct irq_domain *nexus_domain, - struct irq_domain **pci_domain) -{ - *pci_domain =3D NULL; - return 0; -} -#endif - static void mbi_compose_mbi_msg(struct irq_data *data, struct msi_msg *msg) { mbi_compose_msi_msg(data, msg); @@ -210,28 +165,51 @@ static void mbi_compose_mbi_msg(struct irq_data *data, = struct msi_msg *msg) iommu_dma_compose_msi_msg(irq_data_get_msi_desc(data), &msg[1]); } =20 -/* Platform-MSI specific irqchip */ -static struct irq_chip mbi_pmsi_irq_chip =3D { - .name =3D "pMSI", - .irq_set_type =3D irq_chip_set_type_parent, - .irq_compose_msi_msg =3D mbi_compose_mbi_msg, - .flags =3D IRQCHIP_SUPPORTS_LEVEL_MSI, -}; - -static struct msi_domain_ops mbi_pmsi_ops =3D { -}; +static bool mbi_init_dev_msi_info(struct device *dev, struct irq_domain *dom= ain, + struct irq_domain *real_parent, struct msi_domain_info *info) +{ + if (!msi_lib_init_dev_msi_info(dev, domain, real_parent, info)) + return false; + + switch (info->bus_token) { + case DOMAIN_BUS_PCI_DEVICE_MSI: + case DOMAIN_BUS_PCI_DEVICE_MSIX: + info->chip->irq_compose_msi_msg =3D mbi_compose_msi_msg; + return true; + + case DOMAIN_BUS_DEVICE_MSI: + info->chip->irq_compose_msi_msg =3D mbi_compose_mbi_msg; + info->chip->irq_set_type =3D irq_chip_set_type_parent; + info->chip->flags |=3D IRQCHIP_SUPPORTS_LEVEL_MSI; + info->flags |=3D MSI_FLAG_LEVEL_CAPABLE; + return true; + + default: + WARN_ON_ONCE(1); + return false; + } +} =20 -static struct msi_domain_info mbi_pmsi_domain_info =3D { - .flags =3D (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | - MSI_FLAG_LEVEL_CAPABLE), - .ops =3D &mbi_pmsi_ops, - .chip =3D &mbi_pmsi_irq_chip, +#define MBI_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | \ + MSI_FLAG_USE_DEF_CHIP_OPS | \ + MSI_FLAG_PCI_MSI_MASK_PARENT) + +#define MBI_MSI_FLAGS_SUPPORTED (MSI_GENERIC_FLAGS_MASK | \ + MSI_FLAG_PCI_MSIX | \ + MSI_FLAG_MULTI_PCI_MSI) + +static const struct msi_parent_ops gic_v3_mbi_msi_parent_ops =3D { + .supported_flags =3D MBI_MSI_FLAGS_SUPPORTED, + .required_flags =3D MBI_MSI_FLAGS_REQUIRED, + .bus_select_token =3D DOMAIN_BUS_NEXUS, + .bus_select_mask =3D MATCH_PCI_MSI | MATCH_PLATFORM_MSI, + .prefix =3D "MBI-", + .init_dev_msi_info =3D mbi_init_dev_msi_info, }; =20 -static int mbi_allocate_domains(struct irq_domain *parent) +static int mbi_allocate_domain(struct irq_domain *parent) { - struct irq_domain *nexus_domain, *pci_domain, *plat_domain; - int err; + struct irq_domain *nexus_domain; =20 nexus_domain =3D irq_domain_create_hierarchy(parent, 0, 0, parent->fwnode, &mbi_domain_ops, NULL); @@ -239,22 +217,8 @@ static int mbi_allocate_domains(struct irq_domain *paren= t) return -ENOMEM; =20 irq_domain_update_bus_token(nexus_domain, DOMAIN_BUS_NEXUS); - - err =3D mbi_allocate_pci_domain(nexus_domain, &pci_domain); - - plat_domain =3D platform_msi_create_irq_domain(parent->fwnode, - &mbi_pmsi_domain_info, - nexus_domain); - - if (err || !plat_domain) { - if (plat_domain) - irq_domain_remove(plat_domain); - if (pci_domain) - irq_domain_remove(pci_domain); - irq_domain_remove(nexus_domain); - return -ENOMEM; - } - + nexus_domain->flags |=3D IRQ_DOMAIN_FLAG_MSI_PARENT; + nexus_domain->msi_parent_ops =3D &gic_v3_mbi_msi_parent_ops; return 0; } =20 @@ -317,7 +281,7 @@ int __init mbi_init(struct fwnode_handle *fwnode, struct = irq_domain *parent) =20 pr_info("Using MBI frame %pa\n", &mbi_phys_base); =20 - ret =3D mbi_allocate_domains(parent); + ret =3D mbi_allocate_domain(parent); if (ret) goto err_free_mbi; =20 diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index 6fb276504bcc..7c12d11513c6 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -2190,11 +2190,10 @@ static void __init gic_populate_ppi_partitions(struct= device_node *gic_node) of_node_put(parts_node); } =20 -static void __init gic_of_setup_kvm_info(struct device_node *node) +static void __init gic_of_setup_kvm_info(struct device_node *node, u32 nr_re= dist_regions) { int ret; struct resource r; - u32 gicv_idx; =20 gic_v3_kvm_info.type =3D GIC_V3; =20 @@ -2202,12 +2201,8 @@ static void __init gic_of_setup_kvm_info(struct device= _node *node) if (!gic_v3_kvm_info.maint_irq) return; =20 - if (of_property_read_u32(node, "#redistributor-regions", - &gicv_idx)) - gicv_idx =3D 1; - - gicv_idx +=3D 3; /* Also skip GICD, GICC, GICH */ - ret =3D of_address_to_resource(node, gicv_idx, &r); + /* Also skip GICD, GICC, GICH */ + ret =3D of_address_to_resource(node, nr_redist_regions + 3, &r); if (!ret) gic_v3_kvm_info.vcpu =3D r; =20 @@ -2297,7 +2292,7 @@ static int __init gic_of_init(struct device_node *node,= struct device_node *pare gic_populate_ppi_partitions(node); =20 if (static_branch_likely(&supports_deactivate_key)) - gic_of_setup_kvm_info(node); + gic_of_setup_kvm_info(node, nr_redist_regions); return 0; =20 out_unmap_rdist: @@ -2349,6 +2344,11 @@ gic_acpi_parse_madt_redist(union acpi_subtable_headers= *header, pr_err("Couldn't map GICR region @%llx\n", redist->base_address); return -ENOMEM; } + + if (acpi_get_madt_revision() >=3D 7 && + (redist->flags & ACPI_MADT_GICR_NON_COHERENT)) + gic_data.rdists.flags |=3D RDIST_FLAGS_FORCE_NON_SHAREABLE; + gic_request_region(redist->base_address, redist->length, "GICR"); =20 gic_acpi_register_redist(redist->base_address, redist_base); @@ -2373,6 +2373,10 @@ gic_acpi_parse_madt_gicc(union acpi_subtable_headers *= header, return -ENOMEM; gic_request_region(gicc->gicr_base_address, size, "GICR"); =20 + if (acpi_get_madt_revision() >=3D 7 && + (gicc->flags & ACPI_MADT_GICC_NON_COHERENT)) + gic_data.rdists.flags |=3D RDIST_FLAGS_FORCE_NON_SHAREABLE; + gic_acpi_register_redist(gicc->gicr_base_address, redist_base); return 0; } diff --git a/drivers/irqchip/irq-imx-irqsteer.c b/drivers/irqchip/irq-imx-irq= steer.c index 20cf7a9e9ece..75a0e980ff35 100644 --- a/drivers/irqchip/irq-imx-irqsteer.c +++ b/drivers/irqchip/irq-imx-irqsteer.c @@ -36,6 +36,7 @@ struct irqsteer_data { int channel; struct irq_domain *domain; u32 *saved_reg; + struct device *dev; }; =20 static int imx_irqsteer_get_reg_index(struct irqsteer_data *data, @@ -72,10 +73,26 @@ static void imx_irqsteer_irq_mask(struct irq_data *d) raw_spin_unlock_irqrestore(&data->lock, flags); } =20 +static void imx_irqsteer_irq_bus_lock(struct irq_data *d) +{ + struct irqsteer_data *data =3D d->chip_data; + + pm_runtime_get_sync(data->dev); +} + +static void imx_irqsteer_irq_bus_sync_unlock(struct irq_data *d) +{ + struct irqsteer_data *data =3D d->chip_data; + + pm_runtime_put_autosuspend(data->dev); +} + static const struct irq_chip imx_irqsteer_irq_chip =3D { - .name =3D "irqsteer", - .irq_mask =3D imx_irqsteer_irq_mask, - .irq_unmask =3D imx_irqsteer_irq_unmask, + .name =3D "irqsteer", + .irq_mask =3D imx_irqsteer_irq_mask, + .irq_unmask =3D imx_irqsteer_irq_unmask, + .irq_bus_lock =3D imx_irqsteer_irq_bus_lock, + .irq_bus_sync_unlock =3D imx_irqsteer_irq_bus_sync_unlock, }; =20 static int imx_irqsteer_irq_map(struct irq_domain *h, unsigned int irq, @@ -150,6 +167,7 @@ static int imx_irqsteer_probe(struct platform_device *pde= v) if (!data) return -ENOMEM; =20 + data->dev =3D &pdev->dev; data->regs =3D devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(data->regs)) { dev_err(&pdev->dev, "failed to initialize reg\n"); diff --git a/drivers/irqchip/irq-imx-mu-msi.c b/drivers/irqchip/irq-imx-mu-ms= i.c index 90d41c1407ac..4342a21de1eb 100644 --- a/drivers/irqchip/irq-imx-mu-msi.c +++ b/drivers/irqchip/irq-imx-mu-msi.c @@ -24,6 +24,8 @@ #include #include =20 +#include "irq-msi-lib.h" + #define IMX_MU_CHANS 4 =20 enum imx_mu_xcr { @@ -114,20 +116,6 @@ static void imx_mu_msi_parent_ack_irq(struct irq_data *d= ata) imx_mu_read(msi_data, msi_data->cfg->xRR + data->hwirq * 4); } =20 -static struct irq_chip imx_mu_msi_irq_chip =3D { - .name =3D "MU-MSI", - .irq_ack =3D irq_chip_ack_parent, -}; - -static struct msi_domain_ops imx_mu_msi_irq_ops =3D { -}; - -static struct msi_domain_info imx_mu_msi_domain_info =3D { - .flags =3D (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS), - .ops =3D &imx_mu_msi_irq_ops, - .chip =3D &imx_mu_msi_irq_chip, -}; - static void imx_mu_msi_parent_compose_msg(struct irq_data *data, struct msi_msg *msg) { @@ -195,6 +183,7 @@ static void imx_mu_msi_domain_irq_free(struct irq_domain = *domain, } =20 static const struct irq_domain_ops imx_mu_msi_domain_ops =3D { + .select =3D msi_lib_irq_domain_select, .alloc =3D imx_mu_msi_domain_irq_alloc, .free =3D imx_mu_msi_domain_irq_free, }; @@ -216,35 +205,38 @@ static void imx_mu_msi_irq_handler(struct irq_desc *des= c) chained_irq_exit(chip, desc); } =20 +#define IMX_MU_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | \ + MSI_FLAG_USE_DEF_CHIP_OPS | \ + MSI_FLAG_PARENT_PM_DEV) + +#define IMX_MU_MSI_FLAGS_SUPPORTED (MSI_GENERIC_FLAGS_MASK) + +static const struct msi_parent_ops imx_mu_msi_parent_ops =3D { + .supported_flags =3D IMX_MU_MSI_FLAGS_SUPPORTED, + .required_flags =3D IMX_MU_MSI_FLAGS_REQUIRED, + .bus_select_token =3D DOMAIN_BUS_NEXUS, + .bus_select_mask =3D MATCH_PLATFORM_MSI, + .prefix =3D "MU-MSI-", + .init_dev_msi_info =3D msi_lib_init_dev_msi_info, +}; + static int imx_mu_msi_domains_init(struct imx_mu_msi *msi_data, struct devic= e *dev) { struct fwnode_handle *fwnodes =3D dev_fwnode(dev); struct irq_domain *parent; =20 /* Initialize MSI domain parent */ - parent =3D irq_domain_create_linear(fwnodes, - IMX_MU_CHANS, - &imx_mu_msi_domain_ops, - msi_data); + parent =3D irq_domain_create_linear(fwnodes, IMX_MU_CHANS, + &imx_mu_msi_domain_ops, msi_data); if (!parent) { dev_err(dev, "failed to create IRQ domain\n"); return -ENOMEM; } =20 irq_domain_update_bus_token(parent, DOMAIN_BUS_NEXUS); - - msi_data->msi_domain =3D platform_msi_create_irq_domain(fwnodes, - &imx_mu_msi_domain_info, - parent); - - if (!msi_data->msi_domain) { - dev_err(dev, "failed to create MSI domain\n"); - irq_domain_remove(parent); - return -ENOMEM; - } - - irq_domain_set_pm_device(msi_data->msi_domain, dev); - + parent->dev =3D parent->pm_dev =3D dev; + parent->flags |=3D IRQ_DOMAIN_FLAG_MSI_PARENT; + parent->msi_parent_ops =3D &imx_mu_msi_parent_ops; return 0; } =20 diff --git a/drivers/irqchip/irq-lan966x-oic.c b/drivers/irqchip/irq-lan966x-= oic.c new file mode 100644 index 000000000000..41ac880e3b87 --- /dev/null +++ b/drivers/irqchip/irq-lan966x-oic.c @@ -0,0 +1,278 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Driver for the Microchip LAN966x outbound interrupt controller + * + * Copyright (c) 2024 Technology Inc. and its subsidiaries. + * + * Authors: + * Horatiu Vultur + * Cl=C3=A9ment L=C3=A9ger + * Herve Codina + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct lan966x_oic_chip_regs { + int reg_off_ena_set; + int reg_off_ena_clr; + int reg_off_sticky; + int reg_off_ident; + int reg_off_map; +}; + +struct lan966x_oic_data { + void __iomem *regs; + int irq; +}; + +#define LAN966X_OIC_NR_IRQ 86 + +/* Interrupt sticky status */ +#define LAN966X_OIC_INTR_STICKY 0x30 +#define LAN966X_OIC_INTR_STICKY1 0x34 +#define LAN966X_OIC_INTR_STICKY2 0x38 + +/* Interrupt enable */ +#define LAN966X_OIC_INTR_ENA 0x48 +#define LAN966X_OIC_INTR_ENA1 0x4c +#define LAN966X_OIC_INTR_ENA2 0x50 + +/* Atomic clear of interrupt enable */ +#define LAN966X_OIC_INTR_ENA_CLR 0x54 +#define LAN966X_OIC_INTR_ENA_CLR1 0x58 +#define LAN966X_OIC_INTR_ENA_CLR2 0x5c + +/* Atomic set of interrupt */ +#define LAN966X_OIC_INTR_ENA_SET 0x60 +#define LAN966X_OIC_INTR_ENA_SET1 0x64 +#define LAN966X_OIC_INTR_ENA_SET2 0x68 + +/* Mapping of source to destination interrupts (_n =3D 0..8) */ +#define LAN966X_OIC_DST_INTR_MAP(_n) (0x78 + (_n) * 4) +#define LAN966X_OIC_DST_INTR_MAP1(_n) (0x9c + (_n) * 4) +#define LAN966X_OIC_DST_INTR_MAP2(_n) (0xc0 + (_n) * 4) + +/* Currently active interrupt sources per destination (_n =3D 0..8) */ +#define LAN966X_OIC_DST_INTR_IDENT(_n) (0xe4 + (_n) * 4) +#define LAN966X_OIC_DST_INTR_IDENT1(_n) (0x108 + (_n) * 4) +#define LAN966X_OIC_DST_INTR_IDENT2(_n) (0x12c + (_n) * 4) + +static unsigned int lan966x_oic_irq_startup(struct irq_data *data) +{ + struct irq_chip_generic *gc =3D irq_data_get_irq_chip_data(data); + struct irq_chip_type *ct =3D irq_data_get_chip_type(data); + struct lan966x_oic_chip_regs *chip_regs =3D gc->private; + u32 map; + + irq_gc_lock(gc); + + /* Map the source interrupt to the destination */ + map =3D irq_reg_readl(gc, chip_regs->reg_off_map); + map |=3D data->mask; + irq_reg_writel(gc, map, chip_regs->reg_off_map); + + irq_gc_unlock(gc); + + ct->chip.irq_ack(data); + ct->chip.irq_unmask(data); + + return 0; +} + +static void lan966x_oic_irq_shutdown(struct irq_data *data) +{ + struct irq_chip_generic *gc =3D irq_data_get_irq_chip_data(data); + struct irq_chip_type *ct =3D irq_data_get_chip_type(data); + struct lan966x_oic_chip_regs *chip_regs =3D gc->private; + u32 map; + + ct->chip.irq_mask(data); + + irq_gc_lock(gc); + + /* Unmap the interrupt */ + map =3D irq_reg_readl(gc, chip_regs->reg_off_map); + map &=3D ~data->mask; + irq_reg_writel(gc, map, chip_regs->reg_off_map); + + irq_gc_unlock(gc); +} + +static int lan966x_oic_irq_set_type(struct irq_data *data, + unsigned int flow_type) +{ + if (flow_type !=3D IRQ_TYPE_LEVEL_HIGH) { + pr_err("lan966x oic doesn't support flow type %d\n", flow_type); + return -EINVAL; + } + + return 0; +} + +static void lan966x_oic_irq_handler_domain(struct irq_domain *d, u32 first_i= rq) +{ + struct irq_chip_generic *gc =3D irq_get_domain_generic_chip(d, first_irq); + struct lan966x_oic_chip_regs *chip_regs =3D gc->private; + unsigned long ident; + unsigned int hwirq; + + ident =3D irq_reg_readl(gc, chip_regs->reg_off_ident); + if (!ident) + return; + + for_each_set_bit(hwirq, &ident, 32) + generic_handle_domain_irq(d, hwirq + first_irq); +} + +static void lan966x_oic_irq_handler(struct irq_desc *desc) +{ + struct irq_domain *d =3D irq_desc_get_handler_data(desc); + struct irq_chip *chip =3D irq_desc_get_chip(desc); + + chained_irq_enter(chip, desc); + lan966x_oic_irq_handler_domain(d, 0); + lan966x_oic_irq_handler_domain(d, 32); + lan966x_oic_irq_handler_domain(d, 64); + chained_irq_exit(chip, desc); +} + +static struct lan966x_oic_chip_regs lan966x_oic_chip_regs[3] =3D { + { + .reg_off_ena_set =3D LAN966X_OIC_INTR_ENA_SET, + .reg_off_ena_clr =3D LAN966X_OIC_INTR_ENA_CLR, + .reg_off_sticky =3D LAN966X_OIC_INTR_STICKY, + .reg_off_ident =3D LAN966X_OIC_DST_INTR_IDENT(0), + .reg_off_map =3D LAN966X_OIC_DST_INTR_MAP(0), + }, { + .reg_off_ena_set =3D LAN966X_OIC_INTR_ENA_SET1, + .reg_off_ena_clr =3D LAN966X_OIC_INTR_ENA_CLR1, + .reg_off_sticky =3D LAN966X_OIC_INTR_STICKY1, + .reg_off_ident =3D LAN966X_OIC_DST_INTR_IDENT1(0), + .reg_off_map =3D LAN966X_OIC_DST_INTR_MAP1(0), + }, { + .reg_off_ena_set =3D LAN966X_OIC_INTR_ENA_SET2, + .reg_off_ena_clr =3D LAN966X_OIC_INTR_ENA_CLR2, + .reg_off_sticky =3D LAN966X_OIC_INTR_STICKY2, + .reg_off_ident =3D LAN966X_OIC_DST_INTR_IDENT2(0), + .reg_off_map =3D LAN966X_OIC_DST_INTR_MAP2(0), + } +}; + +static int lan966x_oic_chip_init(struct irq_chip_generic *gc) +{ + struct lan966x_oic_data *lan966x_oic =3D gc->domain->host_data; + struct lan966x_oic_chip_regs *chip_regs; + + chip_regs =3D &lan966x_oic_chip_regs[gc->irq_base / 32]; + + gc->reg_base =3D lan966x_oic->regs; + gc->chip_types[0].regs.enable =3D chip_regs->reg_off_ena_set; + gc->chip_types[0].regs.disable =3D chip_regs->reg_off_ena_clr; + gc->chip_types[0].regs.ack =3D chip_regs->reg_off_sticky; + gc->chip_types[0].chip.irq_startup =3D lan966x_oic_irq_startup; + gc->chip_types[0].chip.irq_shutdown =3D lan966x_oic_irq_shutdown; + gc->chip_types[0].chip.irq_set_type =3D lan966x_oic_irq_set_type; + gc->chip_types[0].chip.irq_mask =3D irq_gc_mask_disable_reg; + gc->chip_types[0].chip.irq_unmask =3D irq_gc_unmask_enable_reg; + gc->chip_types[0].chip.irq_ack =3D irq_gc_ack_set_bit; + gc->private =3D chip_regs; + + /* Disable all interrupts handled by this chip */ + irq_reg_writel(gc, ~0U, chip_regs->reg_off_ena_clr); + + return 0; +} + +static void lan966x_oic_chip_exit(struct irq_chip_generic *gc) +{ + /* Disable and ack all interrupts handled by this chip */ + irq_reg_writel(gc, ~0U, gc->chip_types[0].regs.disable); + irq_reg_writel(gc, ~0U, gc->chip_types[0].regs.ack); +} + +static int lan966x_oic_domain_init(struct irq_domain *d) +{ + struct lan966x_oic_data *lan966x_oic =3D d->host_data; + + irq_set_chained_handler_and_data(lan966x_oic->irq, lan966x_oic_irq_handler,= d); + + return 0; +} + +static void lan966x_oic_domain_exit(struct irq_domain *d) +{ + struct lan966x_oic_data *lan966x_oic =3D d->host_data; + + irq_set_chained_handler_and_data(lan966x_oic->irq, NULL, NULL); +} + +static int lan966x_oic_probe(struct platform_device *pdev) +{ + struct irq_domain_chip_generic_info dgc_info =3D { + .name =3D "lan966x-oic", + .handler =3D handle_level_irq, + .irqs_per_chip =3D 32, + .num_ct =3D 1, + .init =3D lan966x_oic_chip_init, + .exit =3D lan966x_oic_chip_exit, + }; + struct irq_domain_info d_info =3D { + .fwnode =3D of_node_to_fwnode(pdev->dev.of_node), + .domain_flags =3D IRQ_DOMAIN_FLAG_DESTROY_GC, + .size =3D LAN966X_OIC_NR_IRQ, + .hwirq_max =3D LAN966X_OIC_NR_IRQ, + .ops =3D &irq_generic_chip_ops, + .dgc_info =3D &dgc_info, + .init =3D lan966x_oic_domain_init, + .exit =3D lan966x_oic_domain_exit, + }; + struct lan966x_oic_data *lan966x_oic; + struct device *dev =3D &pdev->dev; + struct irq_domain *domain; + + lan966x_oic =3D devm_kmalloc(dev, sizeof(*lan966x_oic), GFP_KERNEL); + if (!lan966x_oic) + return -ENOMEM; + + lan966x_oic->regs =3D devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(lan966x_oic->regs)) + return dev_err_probe(dev, PTR_ERR(lan966x_oic->regs), + "failed to map resource\n"); + + lan966x_oic->irq =3D platform_get_irq(pdev, 0); + if (lan966x_oic->irq < 0) + return dev_err_probe(dev, lan966x_oic->irq, "failed to get the IRQ\n"); + + d_info.host_data =3D lan966x_oic; + domain =3D devm_irq_domain_instantiate(dev, &d_info); + if (IS_ERR(domain)) + return dev_err_probe(dev, PTR_ERR(domain), + "failed to instantiate the IRQ domain\n"); + return 0; +} + +static const struct of_device_id lan966x_oic_of_match[] =3D { + { .compatible =3D "microchip,lan966x-oic" }, + {} /* sentinel */ +}; +MODULE_DEVICE_TABLE(of, lan966x_oic_of_match); + +static struct platform_driver lan966x_oic_driver =3D { + .probe =3D lan966x_oic_probe, + .driver =3D { + .name =3D "lan966x-oic", + .of_match_table =3D lan966x_oic_of_match, + }, +}; +module_platform_driver(lan966x_oic_driver); + +MODULE_AUTHOR("Herve Codina "); +MODULE_DESCRIPTION("Microchip LAN966x OIC driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/irqchip/irq-mbigen.c b/drivers/irqchip/irq-mbigen.c index 58881d313979..093fd42893a7 100644 --- a/drivers/irqchip/irq-mbigen.c +++ b/drivers/irqchip/irq-mbigen.c @@ -135,24 +135,14 @@ static int mbigen_set_type(struct irq_data *data, unsig= ned int type) return 0; } =20 -static struct irq_chip mbigen_irq_chip =3D { - .name =3D "mbigen-v2", - .irq_mask =3D irq_chip_mask_parent, - .irq_unmask =3D irq_chip_unmask_parent, - .irq_eoi =3D mbigen_eoi_irq, - .irq_set_type =3D mbigen_set_type, - .irq_set_affinity =3D irq_chip_set_affinity_parent, -}; - -static void mbigen_write_msg(struct msi_desc *desc, struct msi_msg *msg) +static void mbigen_write_msi_msg(struct irq_data *d, struct msi_msg *msg) { - struct irq_data *d =3D irq_get_irq_data(desc->irq); void __iomem *base =3D d->chip_data; u32 val; =20 if (!msg->address_lo && !msg->address_hi) return; -=20 + base +=3D get_mbigen_vec_reg(d->hwirq); val =3D readl_relaxed(base); =20 @@ -165,10 +155,8 @@ static void mbigen_write_msg(struct msi_desc *desc, stru= ct msi_msg *msg) writel_relaxed(val, base); } =20 -static int mbigen_domain_translate(struct irq_domain *d, - struct irq_fwspec *fwspec, - unsigned long *hwirq, - unsigned int *type) +static int mbigen_domain_translate(struct irq_domain *d, struct irq_fwspec *= fwspec, + unsigned long *hwirq, unsigned int *type) { if (is_of_node(fwspec->fwnode) || is_acpi_device_node(fwspec->fwnode)) { if (fwspec->param_count !=3D 2) @@ -192,51 +180,48 @@ static int mbigen_domain_translate(struct irq_domain *d, return -EINVAL; } =20 -static int mbigen_irq_domain_alloc(struct irq_domain *domain, - unsigned int virq, - unsigned int nr_irqs, - void *args) +static void mbigen_domain_set_desc(msi_alloc_info_t *arg, struct msi_desc *d= esc) { - struct irq_fwspec *fwspec =3D args; - irq_hw_number_t hwirq; - unsigned int type; - struct mbigen_device *mgn_chip; - int i, err; - - err =3D mbigen_domain_translate(domain, fwspec, &hwirq, &type); - if (err) - return err; - - err =3D platform_msi_device_domain_alloc(domain, virq, nr_irqs); - if (err) - return err; + arg->desc =3D desc; + arg->hwirq =3D (u32)desc->data.icookie.value; +} =20 - mgn_chip =3D platform_msi_get_host_data(domain); +static const struct msi_domain_template mbigen_msi_template =3D { + .chip =3D { + .name =3D "mbigen-v2", + .irq_mask =3D irq_chip_mask_parent, + .irq_unmask =3D irq_chip_unmask_parent, + .irq_eoi =3D mbigen_eoi_irq, + .irq_set_type =3D mbigen_set_type, + .irq_write_msi_msg =3D mbigen_write_msi_msg, + }, =20 - for (i =3D 0; i < nr_irqs; i++) - irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i, - &mbigen_irq_chip, mgn_chip->base); + .ops =3D { + .set_desc =3D mbigen_domain_set_desc, + .msi_translate =3D mbigen_domain_translate, + }, =20 - return 0; -} + .info =3D { + .bus_token =3D DOMAIN_BUS_WIRED_TO_MSI, + .flags =3D MSI_FLAG_USE_DEV_FWNODE, + }, +}; =20 -static void mbigen_irq_domain_free(struct irq_domain *domain, unsigned int v= irq, - unsigned int nr_irqs) +static bool mbigen_create_device_domain(struct device *dev, unsigned int siz= e, + struct mbigen_device *mgn_chip) { - platform_msi_device_domain_free(domain, virq, nr_irqs); -} + if (WARN_ON_ONCE(!dev->msi.domain)) + return false; =20 -static const struct irq_domain_ops mbigen_domain_ops =3D { - .translate =3D mbigen_domain_translate, - .alloc =3D mbigen_irq_domain_alloc, - .free =3D mbigen_irq_domain_free, -}; + return msi_create_device_irq_domain(dev, MSI_DEFAULT_DOMAIN, + &mbigen_msi_template, size, + NULL, mgn_chip->base); +} =20 static int mbigen_of_create_domain(struct platform_device *pdev, struct mbigen_device *mgn_chip) { struct platform_device *child; - struct irq_domain *domain; struct device_node *np; u32 num_pins; int ret =3D 0; @@ -258,11 +243,7 @@ static int mbigen_of_create_domain(struct platform_devic= e *pdev, break; } =20 - domain =3D platform_msi_create_device_domain(&child->dev, num_pins, - mbigen_write_msg, - &mbigen_domain_ops, - mgn_chip); - if (!domain) { + if (!mbigen_create_device_domain(&child->dev, num_pins, mgn_chip)) { ret =3D -ENOMEM; break; } @@ -284,7 +265,6 @@ MODULE_DEVICE_TABLE(acpi, mbigen_acpi_match); static int mbigen_acpi_create_domain(struct platform_device *pdev, struct mbigen_device *mgn_chip) { - struct irq_domain *domain; u32 num_pins =3D 0; int ret; =20 @@ -315,11 +295,7 @@ static int mbigen_acpi_create_domain(struct platform_dev= ice *pdev, if (ret || num_pins =3D=3D 0) return -EINVAL; =20 - domain =3D platform_msi_create_device_domain(&pdev->dev, num_pins, - mbigen_write_msg, - &mbigen_domain_ops, - mgn_chip); - if (!domain) + if (!mbigen_create_device_domain(&pdev->dev, num_pins, mgn_chip)) return -ENOMEM; =20 return 0; diff --git a/drivers/irqchip/irq-meson-gpio.c b/drivers/irqchip/irq-meson-gpi= o.c index 9a1791908598..27e30ce41db3 100644 --- a/drivers/irqchip/irq-meson-gpio.c +++ b/drivers/irqchip/irq-meson-gpio.c @@ -608,5 +608,6 @@ IRQCHIP_MATCH("amlogic,meson-gpio-intc", meson_gpio_irq_o= f_init) IRQCHIP_PLATFORM_DRIVER_END(meson_gpio_intc) =20 MODULE_AUTHOR("Jerome Brunet "); +MODULE_DESCRIPTION("Meson GPIO Interrupt Multiplexer driver"); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:meson-gpio-intc"); diff --git a/drivers/irqchip/irq-msi-lib.c b/drivers/irqchip/irq-msi-lib.c new file mode 100644 index 000000000000..b5b90003311a --- /dev/null +++ b/drivers/irqchip/irq-msi-lib.c @@ -0,0 +1,140 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (C) 2022 Linutronix GmbH +// Copyright (C) 2022 Intel + +#include + +#include "irq-msi-lib.h" + +/** + * msi_lib_init_dev_msi_info - Domain info setup for MSI domains + * @dev: The device for which the domain is created for + * @domain: The domain providing this callback + * @real_parent: The real parent domain of the domain to be initialized + * which might be a domain built on top of @domain or + * @domain itself + * @info: The domain info for the domain to be initialize + * + * This function is to be used for all types of MSI domains above the root + * parent domain and any intermediates. The topmost parent domain specific + * functionality is determined via @real_parent. + * + * All intermediate domains between the root and the device domain must + * have either msi_parent_ops.init_dev_msi_info =3D msi_parent_init_dev_msi_= info + * or invoke it down the line. + */ +bool msi_lib_init_dev_msi_info(struct device *dev, struct irq_domain *domain, + struct irq_domain *real_parent, + struct msi_domain_info *info) +{ + const struct msi_parent_ops *pops =3D real_parent->msi_parent_ops; + u32 required_flags; + + /* Parent ops available? */ + if (WARN_ON_ONCE(!pops)) + return false; + + /* + * MSI parent domain specific settings. For now there is only the + * root parent domain, e.g. NEXUS, acting as a MSI parent, but it is + * possible to stack MSI parents. See x86 vector -> irq remapping + */ + if (domain->bus_token =3D=3D pops->bus_select_token) { + if (WARN_ON_ONCE(domain !=3D real_parent)) + return false; + } else { + WARN_ON_ONCE(1); + return false; + } + + required_flags =3D pops->required_flags; + + /* Is the target domain bus token supported? */ + switch(info->bus_token) { + case DOMAIN_BUS_PCI_DEVICE_MSI: + case DOMAIN_BUS_PCI_DEVICE_MSIX: + if (WARN_ON_ONCE(!IS_ENABLED(CONFIG_PCI_MSI))) + return false; + + break; + case DOMAIN_BUS_DEVICE_MSI: + /* + * Per device MSI should never have any MSI feature bits + * set. It's sole purpose is to create a dumb interrupt + * chip which has a device specific irq_write_msi_msg() + * callback. + */ + if (WARN_ON_ONCE(info->flags)) + return false; + + /* Core managed MSI descriptors */ + info->flags =3D MSI_FLAG_ALLOC_SIMPLE_MSI_DESCS | MSI_FLAG_FREE_MSI_DESCS; + fallthrough; + case DOMAIN_BUS_WIRED_TO_MSI: + /* Remove PCI specific flags */ + required_flags &=3D ~MSI_FLAG_PCI_MSI_MASK_PARENT; + break; + default: + /* + * This should never be reached. See + * msi_lib_irq_domain_select() + */ + WARN_ON_ONCE(1); + return false; + } + + /* + * Mask out the domain specific MSI feature flags which are not + * supported by the real parent. + */ + info->flags &=3D pops->supported_flags; + /* Enforce the required flags */ + info->flags |=3D required_flags; + + /* Chip updates for all child bus types */ + if (!info->chip->irq_eoi) + info->chip->irq_eoi =3D irq_chip_eoi_parent; + if (!info->chip->irq_ack) + info->chip->irq_ack =3D irq_chip_ack_parent; + + /* + * The device MSI domain can never have a set affinity callback. It + * always has to rely on the parent domain to handle affinity + * settings. The device MSI domain just has to write the resulting + * MSI message into the hardware which is the whole purpose of the + * device MSI domain aside of mask/unmask which is provided e.g. by + * PCI/MSI device domains. + */ + info->chip->irq_set_affinity =3D msi_domain_set_affinity; + return true; +} +EXPORT_SYMBOL_GPL(msi_lib_init_dev_msi_info); + +/** + * msi_lib_irq_domain_select - Shared select function for NEXUS domains + * @d: Pointer to the irq domain on which select is invoked + * @fwspec: Firmware spec describing what is searched + * @bus_token: The bus token for which a matching irq domain is looked up + * + * Returns: %0 if @d is not what is being looked for + * + * %1 if @d is either the domain which is directly searched for or + * if @d is providing the parent MSI domain for the functionality + * requested with @bus_token. + */ +int msi_lib_irq_domain_select(struct irq_domain *d, struct irq_fwspec *fwspe= c, + enum irq_domain_bus_token bus_token) +{ + const struct msi_parent_ops *ops =3D d->msi_parent_ops; + u32 busmask =3D BIT(bus_token); + + if (fwspec->fwnode !=3D d->fwnode || fwspec->param_count !=3D 0) + return 0; + + /* Handle pure domain searches */ + if (bus_token =3D=3D ops->bus_select_token) + return 1; + + return ops && !!(ops->bus_select_mask & busmask); +} +EXPORT_SYMBOL_GPL(msi_lib_irq_domain_select); diff --git a/drivers/irqchip/irq-msi-lib.h b/drivers/irqchip/irq-msi-lib.h new file mode 100644 index 000000000000..681ceabb7bc7 --- /dev/null +++ b/drivers/irqchip/irq-msi-lib.h @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (C) 2022 Linutronix GmbH +// Copyright (C) 2022 Intel + +#ifndef _DRIVERS_IRQCHIP_IRQ_MSI_LIB_H +#define _DRIVERS_IRQCHIP_IRQ_MSI_LIB_H + +#include +#include +#include + +#ifdef CONFIG_PCI_MSI +#define MATCH_PCI_MSI BIT(DOMAIN_BUS_PCI_MSI) +#else +#define MATCH_PCI_MSI (0) +#endif + +#define MATCH_PLATFORM_MSI BIT(DOMAIN_BUS_PLATFORM_MSI) + +int msi_lib_irq_domain_select(struct irq_domain *d, struct irq_fwspec *fwspe= c, + enum irq_domain_bus_token bus_token); + +bool msi_lib_init_dev_msi_info(struct device *dev, struct irq_domain *domain, + struct irq_domain *real_parent, + struct msi_domain_info *info); + +#endif /* _DRIVERS_IRQCHIP_IRQ_MSI_LIB_H */ diff --git a/drivers/irqchip/irq-mvebu-gicp.c b/drivers/irqchip/irq-mvebu-gic= p.c index c43a345061d5..2b6183919ea4 100644 --- a/drivers/irqchip/irq-mvebu-gicp.c +++ b/drivers/irqchip/irq-mvebu-gicp.c @@ -17,6 +17,8 @@ #include #include =20 +#include "irq-msi-lib.h" + #include =20 #define GICP_SETSPI_NSR_OFFSET 0x0 @@ -145,32 +147,32 @@ static void gicp_irq_domain_free(struct irq_domain *dom= ain, } =20 static const struct irq_domain_ops gicp_domain_ops =3D { + .select =3D msi_lib_irq_domain_select, .alloc =3D gicp_irq_domain_alloc, .free =3D gicp_irq_domain_free, }; =20 -static struct irq_chip gicp_msi_irq_chip =3D { - .name =3D "GICP", - .irq_set_type =3D irq_chip_set_type_parent, - .flags =3D IRQCHIP_SUPPORTS_LEVEL_MSI, -}; +#define GICP_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | \ + MSI_FLAG_USE_DEF_CHIP_OPS) =20 -static struct msi_domain_ops gicp_msi_ops =3D { -}; +#define GICP_MSI_FLAGS_SUPPORTED (MSI_GENERIC_FLAGS_MASK | \ + MSI_FLAG_LEVEL_CAPABLE) =20 -static struct msi_domain_info gicp_msi_domain_info =3D { - .flags =3D (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | - MSI_FLAG_LEVEL_CAPABLE), - .ops =3D &gicp_msi_ops, - .chip =3D &gicp_msi_irq_chip, +static const struct msi_parent_ops gicp_msi_parent_ops =3D { + .supported_flags =3D GICP_MSI_FLAGS_SUPPORTED, + .required_flags =3D GICP_MSI_FLAGS_REQUIRED, + .bus_select_token =3D DOMAIN_BUS_GENERIC_MSI, + .bus_select_mask =3D MATCH_PLATFORM_MSI, + .prefix =3D "GICP-", + .init_dev_msi_info =3D msi_lib_init_dev_msi_info, }; =20 static int mvebu_gicp_probe(struct platform_device *pdev) { - struct mvebu_gicp *gicp; - struct irq_domain *inner_domain, *plat_domain, *parent_domain; + struct irq_domain *inner_domain, *parent_domain; struct device_node *node =3D pdev->dev.of_node; struct device_node *irq_parent_dn; + struct mvebu_gicp *gicp; int ret, i; =20 gicp =3D devm_kzalloc(&pdev->dev, sizeof(*gicp), GFP_KERNEL); @@ -234,17 +236,9 @@ static int mvebu_gicp_probe(struct platform_device *pdev) if (!inner_domain) return -ENOMEM; =20 - - plat_domain =3D platform_msi_create_irq_domain(of_node_to_fwnode(node), - &gicp_msi_domain_info, - inner_domain); - if (!plat_domain) { - irq_domain_remove(inner_domain); - return -ENOMEM; - } - - platform_set_drvdata(pdev, gicp); - + irq_domain_update_bus_token(inner_domain, DOMAIN_BUS_GENERIC_MSI); + inner_domain->flags |=3D IRQ_DOMAIN_FLAG_MSI_PARENT; + inner_domain->msi_parent_ops =3D &gicp_msi_parent_ops; return 0; } =20 diff --git a/drivers/irqchip/irq-mvebu-icu.c b/drivers/irqchip/irq-mvebu-icu.c index 3c77acc7ec6a..b337f6c05f18 100644 --- a/drivers/irqchip/irq-mvebu-icu.c +++ b/drivers/irqchip/irq-mvebu-icu.c @@ -20,6 +20,8 @@ #include #include =20 +#include "irq-msi-lib.h" + #include =20 /* ICU registers */ @@ -60,99 +62,13 @@ struct mvebu_icu_msi_data { const struct mvebu_icu_subset_data *subset_data; }; =20 -struct mvebu_icu_irq_data { - struct mvebu_icu *icu; - unsigned int icu_group; - unsigned int type; -}; - static DEFINE_STATIC_KEY_FALSE(legacy_bindings); =20 -static void mvebu_icu_init(struct mvebu_icu *icu, - struct mvebu_icu_msi_data *msi_data, - struct msi_msg *msg) -{ - const struct mvebu_icu_subset_data *subset =3D msi_data->subset_data; - - if (atomic_cmpxchg(&msi_data->initialized, false, true)) - return; - - /* Set 'SET' ICU SPI message address in AP */ - writel_relaxed(msg[0].address_hi, icu->base + subset->offset_set_ah); - writel_relaxed(msg[0].address_lo, icu->base + subset->offset_set_al); - - if (subset->icu_group !=3D ICU_GRP_NSR) - return; - - /* Set 'CLEAR' ICU SPI message address in AP (level-MSI only) */ - writel_relaxed(msg[1].address_hi, icu->base + subset->offset_clr_ah); - writel_relaxed(msg[1].address_lo, icu->base + subset->offset_clr_al); -} - -static void mvebu_icu_write_msg(struct msi_desc *desc, struct msi_msg *msg) -{ - struct irq_data *d =3D irq_get_irq_data(desc->irq); - struct mvebu_icu_msi_data *msi_data =3D platform_msi_get_host_data(d->domai= n); - struct mvebu_icu_irq_data *icu_irqd =3D d->chip_data; - struct mvebu_icu *icu =3D icu_irqd->icu; - unsigned int icu_int; - - if (msg->address_lo || msg->address_hi) { - /* One off initialization per domain */ - mvebu_icu_init(icu, msi_data, msg); - /* Configure the ICU with irq number & type */ - icu_int =3D msg->data | ICU_INT_ENABLE; - if (icu_irqd->type & IRQ_TYPE_EDGE_RISING) - icu_int |=3D ICU_IS_EDGE; - icu_int |=3D icu_irqd->icu_group << ICU_GROUP_SHIFT; - } else { - /* De-configure the ICU */ - icu_int =3D 0; - } - - writel_relaxed(icu_int, icu->base + ICU_INT_CFG(d->hwirq)); - - /* - * The SATA unit has 2 ports, and a dedicated ICU entry per - * port. The ahci sata driver supports only one irq interrupt - * per SATA unit. To solve this conflict, we configure the 2 - * SATA wired interrupts in the south bridge into 1 GIC - * interrupt in the north bridge. Even if only a single port - * is enabled, if sata node is enabled, both interrupts are - * configured (regardless of which port is actually in use). - */ - if (d->hwirq =3D=3D ICU_SATA0_ICU_ID || d->hwirq =3D=3D ICU_SATA1_ICU_ID) { - writel_relaxed(icu_int, - icu->base + ICU_INT_CFG(ICU_SATA0_ICU_ID)); - writel_relaxed(icu_int, - icu->base + ICU_INT_CFG(ICU_SATA1_ICU_ID)); - } -} - -static struct irq_chip mvebu_icu_nsr_chip =3D { - .name =3D "ICU-NSR", - .irq_mask =3D irq_chip_mask_parent, - .irq_unmask =3D irq_chip_unmask_parent, - .irq_eoi =3D irq_chip_eoi_parent, - .irq_set_type =3D irq_chip_set_type_parent, - .irq_set_affinity =3D irq_chip_set_affinity_parent, -}; - -static struct irq_chip mvebu_icu_sei_chip =3D { - .name =3D "ICU-SEI", - .irq_ack =3D irq_chip_ack_parent, - .irq_mask =3D irq_chip_mask_parent, - .irq_unmask =3D irq_chip_unmask_parent, - .irq_set_type =3D irq_chip_set_type_parent, - .irq_set_affinity =3D irq_chip_set_affinity_parent, -}; - -static int -mvebu_icu_irq_domain_translate(struct irq_domain *d, struct irq_fwspec *fwsp= ec, +static int mvebu_icu_translate(struct irq_domain *d, struct irq_fwspec *fwsp= ec, unsigned long *hwirq, unsigned int *type) { unsigned int param_count =3D static_branch_unlikely(&legacy_bindings) ? 3 := 2; - struct mvebu_icu_msi_data *msi_data =3D platform_msi_get_host_data(d); + struct mvebu_icu_msi_data *msi_data =3D d->host_data; struct mvebu_icu *icu =3D msi_data->icu; =20 /* Check the count of the parameters in dt */ @@ -192,81 +108,126 @@ mvebu_icu_irq_domain_translate(struct irq_domain *d, s= truct irq_fwspec *fwspec, return 0; } =20 -static int -mvebu_icu_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, - unsigned int nr_irqs, void *args) +static void mvebu_icu_init(struct mvebu_icu *icu, + struct mvebu_icu_msi_data *msi_data, + struct msi_msg *msg) { - int err; - unsigned long hwirq; - struct irq_fwspec *fwspec =3D args; - struct mvebu_icu_msi_data *msi_data =3D platform_msi_get_host_data(domain); - struct mvebu_icu *icu =3D msi_data->icu; - struct mvebu_icu_irq_data *icu_irqd; - struct irq_chip *chip =3D &mvebu_icu_nsr_chip; + const struct mvebu_icu_subset_data *subset =3D msi_data->subset_data; =20 - icu_irqd =3D kmalloc(sizeof(*icu_irqd), GFP_KERNEL); - if (!icu_irqd) - return -ENOMEM; + if (atomic_cmpxchg(&msi_data->initialized, false, true)) + return; =20 - err =3D mvebu_icu_irq_domain_translate(domain, fwspec, &hwirq, - &icu_irqd->type); - if (err) { - dev_err(icu->dev, "failed to translate ICU parameters\n"); - goto free_irqd; - } + /* Set 'SET' ICU SPI message address in AP */ + writel_relaxed(msg[0].address_hi, icu->base + subset->offset_set_ah); + writel_relaxed(msg[0].address_lo, icu->base + subset->offset_set_al); =20 - if (static_branch_unlikely(&legacy_bindings)) - icu_irqd->icu_group =3D fwspec->param[0]; - else - icu_irqd->icu_group =3D msi_data->subset_data->icu_group; - icu_irqd->icu =3D icu; + if (subset->icu_group !=3D ICU_GRP_NSR) + return; =20 - err =3D platform_msi_device_domain_alloc(domain, virq, nr_irqs); - if (err) { - dev_err(icu->dev, "failed to allocate ICU interrupt in parent domain\n"); - goto free_irqd; - } + /* Set 'CLEAR' ICU SPI message address in AP (level-MSI only) */ + writel_relaxed(msg[1].address_hi, icu->base + subset->offset_clr_ah); + writel_relaxed(msg[1].address_lo, icu->base + subset->offset_clr_al); +} =20 - /* Make sure there is no interrupt left pending by the firmware */ - err =3D irq_set_irqchip_state(virq, IRQCHIP_STATE_PENDING, false); - if (err) - goto free_msi; +static int mvebu_icu_msi_init(struct irq_domain *domain, struct msi_domain_i= nfo *info, + unsigned int virq, irq_hw_number_t hwirq, msi_alloc_info_t *arg) +{ + irq_domain_set_hwirq_and_chip(domain, virq, hwirq, info->chip, info->chip_d= ata); + return irq_set_irqchip_state(virq, IRQCHIP_STATE_PENDING, false); +} =20 - if (icu_irqd->icu_group =3D=3D ICU_GRP_SEI) - chip =3D &mvebu_icu_sei_chip; +static void mvebu_icu_set_desc(msi_alloc_info_t *arg, struct msi_desc *desc) +{ + arg->desc =3D desc; + arg->hwirq =3D (u32)desc->data.icookie.value; +} =20 - err =3D irq_domain_set_hwirq_and_chip(domain, virq, hwirq, - chip, icu_irqd); - if (err) { - dev_err(icu->dev, "failed to set the data to IRQ domain\n"); - goto free_msi; +static void mvebu_icu_write_msi_msg(struct irq_data *d, struct msi_msg *msg) +{ + struct mvebu_icu_msi_data *msi_data =3D d->chip_data; + unsigned int icu_group =3D msi_data->subset_data->icu_group; + struct msi_desc *desc =3D irq_data_get_msi_desc(d); + struct mvebu_icu *icu =3D msi_data->icu; + unsigned int type; + u32 icu_int; + + if (msg->address_lo || msg->address_hi) { + /* One off initialization per domain */ + mvebu_icu_init(icu, msi_data, msg); + /* Configure the ICU with irq number & type */ + icu_int =3D msg->data | ICU_INT_ENABLE; + type =3D (unsigned int)(desc->data.icookie.value >> 32); + if (type & IRQ_TYPE_EDGE_RISING) + icu_int |=3D ICU_IS_EDGE; + icu_int |=3D icu_group << ICU_GROUP_SHIFT; + } else { + /* De-configure the ICU */ + icu_int =3D 0; } =20 - return 0; + writel_relaxed(icu_int, icu->base + ICU_INT_CFG(d->hwirq)); =20 -free_msi: - platform_msi_device_domain_free(domain, virq, nr_irqs); -free_irqd: - kfree(icu_irqd); - return err; + /* + * The SATA unit has 2 ports, and a dedicated ICU entry per + * port. The ahci sata driver supports only one irq interrupt + * per SATA unit. To solve this conflict, we configure the 2 + * SATA wired interrupts in the south bridge into 1 GIC + * interrupt in the north bridge. Even if only a single port + * is enabled, if sata node is enabled, both interrupts are + * configured (regardless of which port is actually in use). + */ + if (d->hwirq =3D=3D ICU_SATA0_ICU_ID || d->hwirq =3D=3D ICU_SATA1_ICU_ID) { + writel_relaxed(icu_int, icu->base + ICU_INT_CFG(ICU_SATA0_ICU_ID)); + writel_relaxed(icu_int, icu->base + ICU_INT_CFG(ICU_SATA1_ICU_ID)); + } } =20 -static void -mvebu_icu_irq_domain_free(struct irq_domain *domain, unsigned int virq, - unsigned int nr_irqs) -{ - struct irq_data *d =3D irq_get_irq_data(virq); - struct mvebu_icu_irq_data *icu_irqd =3D d->chip_data; +static const struct msi_domain_template mvebu_icu_nsr_msi_template =3D { + .chip =3D { + .name =3D "ICU-NSR", + .irq_mask =3D irq_chip_mask_parent, + .irq_unmask =3D irq_chip_unmask_parent, + .irq_eoi =3D irq_chip_eoi_parent, + .irq_set_type =3D irq_chip_set_type_parent, + .irq_write_msi_msg =3D mvebu_icu_write_msi_msg, + .flags =3D IRQCHIP_SUPPORTS_LEVEL_MSI, + }, =20 - kfree(icu_irqd); + .ops =3D { + .msi_translate =3D mvebu_icu_translate, + .msi_init =3D mvebu_icu_msi_init, + .set_desc =3D mvebu_icu_set_desc, + }, =20 - platform_msi_device_domain_free(domain, virq, nr_irqs); -} + .info =3D { + .bus_token =3D DOMAIN_BUS_WIRED_TO_MSI, + .flags =3D MSI_FLAG_LEVEL_CAPABLE | + MSI_FLAG_USE_DEV_FWNODE, + }, +}; + +static const struct msi_domain_template mvebu_icu_sei_msi_template =3D { + .chip =3D { + .name =3D "ICU-SEI", + .irq_mask =3D irq_chip_mask_parent, + .irq_unmask =3D irq_chip_unmask_parent, + .irq_ack =3D irq_chip_ack_parent, + .irq_set_type =3D irq_chip_set_type_parent, + .irq_write_msi_msg =3D mvebu_icu_write_msi_msg, + .flags =3D IRQCHIP_SUPPORTS_LEVEL_MSI, + }, =20 -static const struct irq_domain_ops mvebu_icu_domain_ops =3D { - .translate =3D mvebu_icu_irq_domain_translate, - .alloc =3D mvebu_icu_irq_domain_alloc, - .free =3D mvebu_icu_irq_domain_free, + .ops =3D { + .msi_translate =3D mvebu_icu_translate, + .msi_init =3D mvebu_icu_msi_init, + .set_desc =3D mvebu_icu_set_desc, + }, + + .info =3D { + .bus_token =3D DOMAIN_BUS_WIRED_TO_MSI, + .flags =3D MSI_FLAG_LEVEL_CAPABLE | + MSI_FLAG_USE_DEV_FWNODE, + }, }; =20 static const struct mvebu_icu_subset_data mvebu_icu_nsr_subset_data =3D { @@ -297,10 +258,10 @@ static const struct of_device_id mvebu_icu_subset_of_ma= tch[] =3D { =20 static int mvebu_icu_subset_probe(struct platform_device *pdev) { + const struct msi_domain_template *tmpl; struct mvebu_icu_msi_data *msi_data; - struct device_node *msi_parent_dn; struct device *dev =3D &pdev->dev; - struct irq_domain *irq_domain; + bool sei; =20 msi_data =3D devm_kzalloc(dev, sizeof(*msi_data), GFP_KERNEL); if (!msi_data) @@ -314,20 +275,18 @@ static int mvebu_icu_subset_probe(struct platform_devic= e *pdev) msi_data->subset_data =3D of_device_get_match_data(dev); } =20 - dev->msi.domain =3D of_msi_get_domain(dev, dev->of_node, - DOMAIN_BUS_PLATFORM_MSI); + dev->msi.domain =3D of_msi_get_domain(dev, dev->of_node, DOMAIN_BUS_PLATFOR= M_MSI); if (!dev->msi.domain) return -EPROBE_DEFER; =20 - msi_parent_dn =3D irq_domain_get_of_node(dev->msi.domain); - if (!msi_parent_dn) + if (!irq_domain_get_of_node(dev->msi.domain)) return -ENODEV; =20 - irq_domain =3D platform_msi_create_device_tree_domain(dev, ICU_MAX_IRQS, - mvebu_icu_write_msg, - &mvebu_icu_domain_ops, - msi_data); - if (!irq_domain) { + sei =3D msi_data->subset_data->icu_group =3D=3D ICU_GRP_SEI; + tmpl =3D sei ? &mvebu_icu_sei_msi_template : &mvebu_icu_nsr_msi_template; + + if (!msi_create_device_irq_domain(dev, MSI_DEFAULT_DOMAIN, tmpl, + ICU_MAX_IRQS, NULL, msi_data)) { dev_err(dev, "Failed to create ICU MSI domain\n"); return -ENOMEM; } diff --git a/drivers/irqchip/irq-mvebu-odmi.c b/drivers/irqchip/irq-mvebu-odm= i.c index 108091533e10..ff19bfd258dc 100644 --- a/drivers/irqchip/irq-mvebu-odmi.c +++ b/drivers/irqchip/irq-mvebu-odmi.c @@ -17,6 +17,9 @@ #include #include #include + +#include "irq-msi-lib.h" + #include =20 #define GICP_ODMIN_SET 0x40 @@ -141,27 +144,29 @@ static void odmi_irq_domain_free(struct irq_domain *dom= ain, } =20 static const struct irq_domain_ops odmi_domain_ops =3D { + .select =3D msi_lib_irq_domain_select, .alloc =3D odmi_irq_domain_alloc, .free =3D odmi_irq_domain_free, }; =20 -static struct irq_chip odmi_msi_irq_chip =3D { - .name =3D "ODMI", -}; +#define ODMI_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | \ + MSI_FLAG_USE_DEF_CHIP_OPS) =20 -static struct msi_domain_ops odmi_msi_ops =3D { -}; +#define ODMI_MSI_FLAGS_SUPPORTED (MSI_GENERIC_FLAGS_MASK) =20 -static struct msi_domain_info odmi_msi_domain_info =3D { - .flags =3D (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS), - .ops =3D &odmi_msi_ops, - .chip =3D &odmi_msi_irq_chip, +static const struct msi_parent_ops odmi_msi_parent_ops =3D { + .supported_flags =3D ODMI_MSI_FLAGS_SUPPORTED, + .required_flags =3D ODMI_MSI_FLAGS_REQUIRED, + .bus_select_token =3D DOMAIN_BUS_GENERIC_MSI, + .bus_select_mask =3D MATCH_PLATFORM_MSI, + .prefix =3D "ODMI-", + .init_dev_msi_info =3D msi_lib_init_dev_msi_info, }; =20 static int __init mvebu_odmi_init(struct device_node *node, struct device_node *parent) { - struct irq_domain *parent_domain, *inner_domain, *plat_domain; + struct irq_domain *parent_domain, *inner_domain; int ret, i; =20 if (of_property_read_u32(node, "marvell,odmi-frames", &odmis_count)) @@ -208,18 +213,12 @@ static int __init mvebu_odmi_init(struct device_node *n= ode, goto err_unmap; } =20 - plat_domain =3D platform_msi_create_irq_domain(of_node_to_fwnode(node), - &odmi_msi_domain_info, - inner_domain); - if (!plat_domain) { - ret =3D -ENOMEM; - goto err_remove_inner; - } + irq_domain_update_bus_token(inner_domain, DOMAIN_BUS_GENERIC_MSI); + inner_domain->flags |=3D IRQ_DOMAIN_FLAG_MSI_PARENT; + inner_domain->msi_parent_ops =3D &odmi_msi_parent_ops; =20 return 0; =20 -err_remove_inner: - irq_domain_remove(inner_domain); err_unmap: for (i =3D 0; i < odmis_count; i++) { struct odmi_data *odmi =3D &odmis[i]; diff --git a/drivers/irqchip/irq-mvebu-pic.c b/drivers/irqchip/irq-mvebu-pic.c index d17d9c0e2880..08b0cc862adf 100644 --- a/drivers/irqchip/irq-mvebu-pic.c +++ b/drivers/irqchip/irq-mvebu-pic.c @@ -193,6 +193,7 @@ module_platform_driver(mvebu_pic_driver); =20 MODULE_AUTHOR("Yehuda Yitschak "); MODULE_AUTHOR("Thomas Petazzoni "); +MODULE_DESCRIPTION("Marvell Armada 7K/8K PIC driver"); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:mvebu_pic"); =20 diff --git a/drivers/irqchip/irq-mvebu-sei.c b/drivers/irqchip/irq-mvebu-sei.c index a48dbe91b036..f8c70f2d100a 100644 --- a/drivers/irqchip/irq-mvebu-sei.c +++ b/drivers/irqchip/irq-mvebu-sei.c @@ -14,6 +14,8 @@ #include #include =20 +#include "irq-msi-lib.h" + /* Cause register */ #define GICP_SECR(idx) (0x0 + ((idx) * 0x4)) /* Mask register */ @@ -190,6 +192,7 @@ static void mvebu_sei_domain_free(struct irq_domain *doma= in, unsigned int virq, } =20 static const struct irq_domain_ops mvebu_sei_domain_ops =3D { + .select =3D msi_lib_irq_domain_select, .alloc =3D mvebu_sei_domain_alloc, .free =3D mvebu_sei_domain_free, }; @@ -307,21 +310,6 @@ static const struct irq_domain_ops mvebu_sei_cp_domain_o= ps =3D { .free =3D mvebu_sei_cp_domain_free, }; =20 -static struct irq_chip mvebu_sei_msi_irq_chip =3D { - .name =3D "SEI pMSI", - .irq_ack =3D irq_chip_ack_parent, - .irq_set_type =3D irq_chip_set_type_parent, -}; - -static struct msi_domain_ops mvebu_sei_msi_ops =3D { -}; - -static struct msi_domain_info mvebu_sei_msi_domain_info =3D { - .flags =3D MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS, - .ops =3D &mvebu_sei_msi_ops, - .chip =3D &mvebu_sei_msi_irq_chip, -}; - static void mvebu_sei_handle_cascade_irq(struct irq_desc *desc) { struct mvebu_sei *sei =3D irq_desc_get_handler_data(desc); @@ -360,10 +348,23 @@ static void mvebu_sei_reset(struct mvebu_sei *sei) } } =20 +#define SEI_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | \ + MSI_FLAG_USE_DEF_CHIP_OPS) + +#define SEI_MSI_FLAGS_SUPPORTED (MSI_GENERIC_FLAGS_MASK) + +static const struct msi_parent_ops sei_msi_parent_ops =3D { + .supported_flags =3D SEI_MSI_FLAGS_SUPPORTED, + .required_flags =3D SEI_MSI_FLAGS_REQUIRED, + .bus_select_mask =3D MATCH_PLATFORM_MSI, + .bus_select_token =3D DOMAIN_BUS_GENERIC_MSI, + .prefix =3D "SEI-", + .init_dev_msi_info =3D msi_lib_init_dev_msi_info, +}; + static int mvebu_sei_probe(struct platform_device *pdev) { struct device_node *node =3D pdev->dev.of_node; - struct irq_domain *plat_domain; struct mvebu_sei *sei; u32 parent_irq; int ret; @@ -440,33 +441,20 @@ static int mvebu_sei_probe(struct platform_device *pdev) } =20 irq_domain_update_bus_token(sei->cp_domain, DOMAIN_BUS_GENERIC_MSI); - - plat_domain =3D platform_msi_create_irq_domain(of_node_to_fwnode(node), - &mvebu_sei_msi_domain_info, - sei->cp_domain); - if (!plat_domain) { - pr_err("Failed to create CPs MSI domain\n"); - ret =3D -ENOMEM; - goto remove_cp_domain; - } + sei->cp_domain->flags |=3D IRQ_DOMAIN_FLAG_MSI_PARENT; + sei->cp_domain->msi_parent_ops =3D &sei_msi_parent_ops; =20 mvebu_sei_reset(sei); =20 - irq_set_chained_handler_and_data(parent_irq, - mvebu_sei_handle_cascade_irq, - sei); - + irq_set_chained_handler_and_data(parent_irq, mvebu_sei_handle_cascade_irq, = sei); return 0; =20 -remove_cp_domain: - irq_domain_remove(sei->cp_domain); remove_ap_domain: irq_domain_remove(sei->ap_domain); remove_sei_domain: irq_domain_remove(sei->sei_domain); dispose_irq: irq_dispose_mapping(parent_irq); - return ret; } =20 diff --git a/drivers/irqchip/irq-renesas-rzg2l.c b/drivers/irqchip/irq-renesa= s-rzg2l.c index f6484bf15e0b..693ff285ca2c 100644 --- a/drivers/irqchip/irq-renesas-rzg2l.c +++ b/drivers/irqchip/irq-renesas-rzg2l.c @@ -37,6 +37,8 @@ #define TSSEL_SHIFT(n) (8 * (n)) #define TSSEL_MASK GENMASK(7, 0) #define IRQ_MASK 0x3 +#define IMSK 0x10010 +#define TMSK 0x10020 =20 #define TSSR_OFFSET(n) ((n) % 4) #define TSSR_INDEX(n) ((n) / 4) @@ -69,12 +71,14 @@ struct rzg2l_irqc_reg_cache { /** * struct rzg2l_irqc_priv - IRQ controller private data structure * @base: Controller's base address + * @irqchip: Pointer to struct irq_chip * @fwspec: IRQ firmware specific data * @lock: Lock to serialize access to hardware registers * @cache: Registers cache for suspend/resume */ static struct rzg2l_irqc_priv { void __iomem *base; + const struct irq_chip *irqchip; struct irq_fwspec fwspec[IRQC_NUM_IRQ]; raw_spinlock_t lock; struct rzg2l_irqc_reg_cache cache; @@ -138,6 +142,111 @@ static void rzg2l_irqc_eoi(struct irq_data *d) irq_chip_eoi_parent(d); } =20 +static void rzfive_irqc_mask_irq_interrupt(struct rzg2l_irqc_priv *priv, + unsigned int hwirq) +{ + u32 bit =3D BIT(hwirq - IRQC_IRQ_START); + + writel_relaxed(readl_relaxed(priv->base + IMSK) | bit, priv->base + IMSK); +} + +static void rzfive_irqc_unmask_irq_interrupt(struct rzg2l_irqc_priv *priv, + unsigned int hwirq) +{ + u32 bit =3D BIT(hwirq - IRQC_IRQ_START); + + writel_relaxed(readl_relaxed(priv->base + IMSK) & ~bit, priv->base + IMSK); +} + +static void rzfive_irqc_mask_tint_interrupt(struct rzg2l_irqc_priv *priv, + unsigned int hwirq) +{ + u32 bit =3D BIT(hwirq - IRQC_TINT_START); + + writel_relaxed(readl_relaxed(priv->base + TMSK) | bit, priv->base + TMSK); +} + +static void rzfive_irqc_unmask_tint_interrupt(struct rzg2l_irqc_priv *priv, + unsigned int hwirq) +{ + u32 bit =3D BIT(hwirq - IRQC_TINT_START); + + writel_relaxed(readl_relaxed(priv->base + TMSK) & ~bit, priv->base + TMSK); +} + +static void rzfive_irqc_mask(struct irq_data *d) +{ + struct rzg2l_irqc_priv *priv =3D irq_data_to_priv(d); + unsigned int hwirq =3D irqd_to_hwirq(d); + + raw_spin_lock(&priv->lock); + if (hwirq >=3D IRQC_IRQ_START && hwirq <=3D IRQC_IRQ_COUNT) + rzfive_irqc_mask_irq_interrupt(priv, hwirq); + else if (hwirq >=3D IRQC_TINT_START && hwirq < IRQC_NUM_IRQ) + rzfive_irqc_mask_tint_interrupt(priv, hwirq); + raw_spin_unlock(&priv->lock); + irq_chip_mask_parent(d); +} + +static void rzfive_irqc_unmask(struct irq_data *d) +{ + struct rzg2l_irqc_priv *priv =3D irq_data_to_priv(d); + unsigned int hwirq =3D irqd_to_hwirq(d); + + raw_spin_lock(&priv->lock); + if (hwirq >=3D IRQC_IRQ_START && hwirq <=3D IRQC_IRQ_COUNT) + rzfive_irqc_unmask_irq_interrupt(priv, hwirq); + else if (hwirq >=3D IRQC_TINT_START && hwirq < IRQC_NUM_IRQ) + rzfive_irqc_unmask_tint_interrupt(priv, hwirq); + raw_spin_unlock(&priv->lock); + irq_chip_unmask_parent(d); +} + +static void rzfive_tint_irq_endisable(struct irq_data *d, bool enable) +{ + struct rzg2l_irqc_priv *priv =3D irq_data_to_priv(d); + unsigned int hwirq =3D irqd_to_hwirq(d); + + if (hwirq >=3D IRQC_TINT_START && hwirq < IRQC_NUM_IRQ) { + u32 offset =3D hwirq - IRQC_TINT_START; + u32 tssr_offset =3D TSSR_OFFSET(offset); + u8 tssr_index =3D TSSR_INDEX(offset); + u32 reg; + + raw_spin_lock(&priv->lock); + if (enable) + rzfive_irqc_unmask_tint_interrupt(priv, hwirq); + else + rzfive_irqc_mask_tint_interrupt(priv, hwirq); + reg =3D readl_relaxed(priv->base + TSSR(tssr_index)); + if (enable) + reg |=3D TIEN << TSSEL_SHIFT(tssr_offset); + else + reg &=3D ~(TIEN << TSSEL_SHIFT(tssr_offset)); + writel_relaxed(reg, priv->base + TSSR(tssr_index)); + raw_spin_unlock(&priv->lock); + } else { + raw_spin_lock(&priv->lock); + if (enable) + rzfive_irqc_unmask_irq_interrupt(priv, hwirq); + else + rzfive_irqc_mask_irq_interrupt(priv, hwirq); + raw_spin_unlock(&priv->lock); + } +} + +static void rzfive_irqc_irq_disable(struct irq_data *d) +{ + irq_chip_disable_parent(d); + rzfive_tint_irq_endisable(d, false); +} + +static void rzfive_irqc_irq_enable(struct irq_data *d) +{ + rzfive_tint_irq_endisable(d, true); + irq_chip_enable_parent(d); +} + static void rzg2l_tint_irq_endisable(struct irq_data *d, bool enable) { unsigned int hw_irq =3D irqd_to_hwirq(d); @@ -162,8 +271,8 @@ static void rzg2l_tint_irq_endisable(struct irq_data *d, = bool enable) =20 static void rzg2l_irqc_irq_disable(struct irq_data *d) { - rzg2l_tint_irq_endisable(d, false); irq_chip_disable_parent(d); + rzg2l_tint_irq_endisable(d, false); } =20 static void rzg2l_irqc_irq_enable(struct irq_data *d) @@ -321,7 +430,7 @@ static struct syscore_ops rzg2l_irqc_syscore_ops =3D { .resume =3D rzg2l_irqc_irq_resume, }; =20 -static const struct irq_chip irqc_chip =3D { +static const struct irq_chip rzg2l_irqc_chip =3D { .name =3D "rzg2l-irqc", .irq_eoi =3D rzg2l_irqc_eoi, .irq_mask =3D irq_chip_mask_parent, @@ -338,6 +447,23 @@ static const struct irq_chip irqc_chip =3D { IRQCHIP_SKIP_SET_WAKE, }; =20 +static const struct irq_chip rzfive_irqc_chip =3D { + .name =3D "rzfive-irqc", + .irq_eoi =3D rzg2l_irqc_eoi, + .irq_mask =3D rzfive_irqc_mask, + .irq_unmask =3D rzfive_irqc_unmask, + .irq_disable =3D rzfive_irqc_irq_disable, + .irq_enable =3D rzfive_irqc_irq_enable, + .irq_get_irqchip_state =3D irq_chip_get_parent_state, + .irq_set_irqchip_state =3D irq_chip_set_parent_state, + .irq_retrigger =3D irq_chip_retrigger_hierarchy, + .irq_set_type =3D rzg2l_irqc_set_type, + .irq_set_affinity =3D irq_chip_set_affinity_parent, + .flags =3D IRQCHIP_MASK_ON_SUSPEND | + IRQCHIP_SET_TYPE_MASKED | + IRQCHIP_SKIP_SET_WAKE, +}; + static int rzg2l_irqc_alloc(struct irq_domain *domain, unsigned int virq, unsigned int nr_irqs, void *arg) { @@ -369,7 +495,7 @@ static int rzg2l_irqc_alloc(struct irq_domain *domain, un= signed int virq, if (hwirq > (IRQC_NUM_IRQ - 1)) return -EINVAL; =20 - ret =3D irq_domain_set_hwirq_and_chip(domain, virq, hwirq, &irqc_chip, + ret =3D irq_domain_set_hwirq_and_chip(domain, virq, hwirq, priv->irqchip, (void *)(uintptr_t)tint); if (ret) return ret; @@ -401,7 +527,8 @@ static int rzg2l_irqc_parse_interrupts(struct rzg2l_irqc_= priv *priv, return 0; } =20 -static int rzg2l_irqc_init(struct device_node *node, struct device_node *par= ent) +static int rzg2l_irqc_common_init(struct device_node *node, struct device_no= de *parent, + const struct irq_chip *irq_chip) { struct irq_domain *irq_domain, *parent_domain; struct platform_device *pdev; @@ -422,6 +549,8 @@ static int rzg2l_irqc_init(struct device_node *node, stru= ct device_node *parent) if (!rzg2l_irqc_data) return -ENOMEM; =20 + rzg2l_irqc_data->irqchip =3D irq_chip; + rzg2l_irqc_data->base =3D devm_of_iomap(&pdev->dev, pdev->dev.of_node, 0, N= ULL); if (IS_ERR(rzg2l_irqc_data->base)) return PTR_ERR(rzg2l_irqc_data->base); @@ -472,8 +601,21 @@ static int rzg2l_irqc_init(struct device_node *node, str= uct device_node *parent) return ret; } =20 +static int __init rzg2l_irqc_init(struct device_node *node, + struct device_node *parent) +{ + return rzg2l_irqc_common_init(node, parent, &rzg2l_irqc_chip); +} + +static int __init rzfive_irqc_init(struct device_node *node, + struct device_node *parent) +{ + return rzg2l_irqc_common_init(node, parent, &rzfive_irqc_chip); +} + IRQCHIP_PLATFORM_DRIVER_BEGIN(rzg2l_irqc) IRQCHIP_MATCH("renesas,rzg2l-irqc", rzg2l_irqc_init) +IRQCHIP_MATCH("renesas,r9a07g043f-irqc", rzfive_irqc_init) IRQCHIP_PLATFORM_DRIVER_END(rzg2l_irqc) MODULE_AUTHOR("Lad Prabhakar "); MODULE_DESCRIPTION("Renesas RZ/G2L IRQC Driver"); diff --git a/drivers/irqchip/irq-riscv-aplic-main.c b/drivers/irqchip/irq-ris= cv-aplic-main.c index 774a0c97fdab..28dd175b5764 100644 --- a/drivers/irqchip/irq-riscv-aplic-main.c +++ b/drivers/irqchip/irq-riscv-aplic-main.c @@ -127,6 +127,7 @@ static void aplic_init_hw_irqs(struct aplic_priv *priv) =20 int aplic_setup_priv(struct aplic_priv *priv, struct device *dev, void __iom= em *regs) { + struct device_node *np =3D to_of_node(dev->fwnode); struct of_phandle_args parent; int rc; =20 @@ -134,7 +135,7 @@ int aplic_setup_priv(struct aplic_priv *priv, struct devi= ce *dev, void __iomem * * Currently, only OF fwnode is supported so extend this * function for ACPI support. */ - if (!is_of_node(dev->fwnode)) + if (!np) return -EINVAL; =20 /* Save device pointer and register base */ @@ -142,8 +143,7 @@ int aplic_setup_priv(struct aplic_priv *priv, struct devi= ce *dev, void __iomem * priv->regs =3D regs; =20 /* Find out number of interrupt sources */ - rc =3D of_property_read_u32(to_of_node(dev->fwnode), "riscv,num-sources", - &priv->nr_irqs); + rc =3D of_property_read_u32(np, "riscv,num-sources", &priv->nr_irqs); if (rc) { dev_err(dev, "failed to get number of interrupt sources\n"); return rc; @@ -155,8 +155,8 @@ int aplic_setup_priv(struct aplic_priv *priv, struct devi= ce *dev, void __iomem * * If "msi-parent" property is present then we ignore the * APLIC IDCs which forces the APLIC driver to use MSI mode. */ - if (!of_property_present(to_of_node(dev->fwnode), "msi-parent")) { - while (!of_irq_parse_one(to_of_node(dev->fwnode), priv->nr_idcs, &parent)) + if (!of_property_present(np, "msi-parent")) { + while (!of_irq_parse_one(np, priv->nr_idcs, &parent)) priv->nr_idcs++; } =20 @@ -184,8 +184,7 @@ static int aplic_probe(struct platform_device *pdev) * If msi-parent property is present then setup APLIC MSI * mode otherwise setup APLIC direct mode. */ - if (is_of_node(dev->fwnode)) - msi_mode =3D of_property_present(to_of_node(dev->fwnode), "msi-parent"); + msi_mode =3D of_property_present(to_of_node(dev->fwnode), "msi-parent"); if (msi_mode) rc =3D aplic_msi_setup(dev, regs); else diff --git a/drivers/irqchip/irq-riscv-intc.c b/drivers/irqchip/irq-riscv-int= c.c index 4f3a12383a1e..47f3200476da 100644 --- a/drivers/irqchip/irq-riscv-intc.c +++ b/drivers/irqchip/irq-riscv-intc.c @@ -26,7 +26,7 @@ static unsigned int riscv_intc_nr_irqs __ro_after_init =3D = BITS_PER_LONG; static unsigned int riscv_intc_custom_base __ro_after_init =3D BITS_PER_LONG; static unsigned int riscv_intc_custom_nr_irqs __ro_after_init; =20 -static asmlinkage void riscv_intc_irq(struct pt_regs *regs) +static void riscv_intc_irq(struct pt_regs *regs) { unsigned long cause =3D regs->cause & ~CAUSE_IRQ_FLAG; =20 @@ -34,7 +34,7 @@ static asmlinkage void riscv_intc_irq(struct pt_regs *regs) pr_warn_ratelimited("Failed to handle interrupt (cause: %ld)\n", cause); } =20 -static asmlinkage void riscv_intc_aia_irq(struct pt_regs *regs) +static void riscv_intc_aia_irq(struct pt_regs *regs) { unsigned long topi; =20 diff --git a/drivers/irqchip/irq-stm32-exti.c b/drivers/irqchip/irq-stm32-ext= i.c index 2cc9f3b7d669..7c6a0080c330 100644 --- a/drivers/irqchip/irq-stm32-exti.c +++ b/drivers/irqchip/irq-stm32-exti.c @@ -1,45 +1,22 @@ // SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) Maxime Coquelin 2015 - * Copyright (C) STMicroelectronics 2017 + * Copyright (C) STMicroelectronics 2017-2024 * Author: Maxime Coquelin */ =20 #include -#include -#include #include #include #include #include #include #include -#include -#include #include #include -#include -#include - -#include =20 #define IRQS_PER_BANK 32 =20 -#define HWSPNLCK_TIMEOUT 1000 /* usec */ - -#define EXTI_EnCIDCFGR(n) (0x180 + (n) * 4) -#define EXTI_HWCFGR1 0x3f0 - -/* Register: EXTI_EnCIDCFGR(n) */ -#define EXTI_CIDCFGR_CFEN_MASK BIT(0) -#define EXTI_CIDCFGR_CID_MASK GENMASK(6, 4) -#define EXTI_CIDCFGR_CID_SHIFT 4 - -/* Register: EXTI_HWCFGR1 */ -#define EXTI_HWCFGR1_CIDWIDTH_MASK GENMASK(27, 24) - -#define EXTI_CID1 1 - struct stm32_exti_bank { u32 imr_ofst; u32 emr_ofst; @@ -47,13 +24,8 @@ struct stm32_exti_bank { u32 ftsr_ofst; u32 swier_ofst; u32 rpr_ofst; - u32 fpr_ofst; - u32 trg_ofst; - u32 seccfgr_ofst; }; =20 -#define UNDEF_REG ~0 - struct stm32_exti_drv_data { const struct stm32_exti_bank **exti_banks; const u8 *desc_irqs; @@ -63,7 +35,6 @@ struct stm32_exti_drv_data { struct stm32_exti_chip_data { struct stm32_exti_host_data *host_data; const struct stm32_exti_bank *reg_bank; - struct raw_spinlock rlock; u32 wake_active; u32 mask_cache; u32 rtsr_cache; @@ -76,8 +47,6 @@ struct stm32_exti_host_data { struct device *dev; struct stm32_exti_chip_data *chips_data; const struct stm32_exti_drv_data *drv_data; - struct hwspinlock *hwlock; - bool dt_has_irqs_desc; /* skip internal desc_irqs array and get it from DT = */ }; =20 static const struct stm32_exti_bank stm32f4xx_exti_b1 =3D { @@ -87,9 +56,6 @@ static const struct stm32_exti_bank stm32f4xx_exti_b1 =3D { .ftsr_ofst =3D 0x0C, .swier_ofst =3D 0x10, .rpr_ofst =3D 0x14, - .fpr_ofst =3D UNDEF_REG, - .trg_ofst =3D UNDEF_REG, - .seccfgr_ofst =3D UNDEF_REG, }; =20 static const struct stm32_exti_bank *stm32f4xx_exti_banks[] =3D { @@ -108,9 +74,6 @@ static const struct stm32_exti_bank stm32h7xx_exti_b1 =3D { .ftsr_ofst =3D 0x04, .swier_ofst =3D 0x08, .rpr_ofst =3D 0x88, - .fpr_ofst =3D UNDEF_REG, - .trg_ofst =3D UNDEF_REG, - .seccfgr_ofst =3D UNDEF_REG, }; =20 static const struct stm32_exti_bank stm32h7xx_exti_b2 =3D { @@ -120,9 +83,6 @@ static const struct stm32_exti_bank stm32h7xx_exti_b2 =3D { .ftsr_ofst =3D 0x24, .swier_ofst =3D 0x28, .rpr_ofst =3D 0x98, - .fpr_ofst =3D UNDEF_REG, - .trg_ofst =3D UNDEF_REG, - .seccfgr_ofst =3D UNDEF_REG, }; =20 static const struct stm32_exti_bank stm32h7xx_exti_b3 =3D { @@ -132,9 +92,6 @@ static const struct stm32_exti_bank stm32h7xx_exti_b3 =3D { .ftsr_ofst =3D 0x44, .swier_ofst =3D 0x48, .rpr_ofst =3D 0xA8, - .fpr_ofst =3D UNDEF_REG, - .trg_ofst =3D UNDEF_REG, - .seccfgr_ofst =3D UNDEF_REG, }; =20 static const struct stm32_exti_bank *stm32h7xx_exti_banks[] =3D { @@ -148,183 +105,12 @@ static const struct stm32_exti_drv_data stm32h7xx_drv_= data =3D { .bank_nr =3D ARRAY_SIZE(stm32h7xx_exti_banks), }; =20 -static const struct stm32_exti_bank stm32mp1_exti_b1 =3D { - .imr_ofst =3D 0x80, - .emr_ofst =3D UNDEF_REG, - .rtsr_ofst =3D 0x00, - .ftsr_ofst =3D 0x04, - .swier_ofst =3D 0x08, - .rpr_ofst =3D 0x0C, - .fpr_ofst =3D 0x10, - .trg_ofst =3D 0x3EC, - .seccfgr_ofst =3D 0x14, -}; - -static const struct stm32_exti_bank stm32mp1_exti_b2 =3D { - .imr_ofst =3D 0x90, - .emr_ofst =3D UNDEF_REG, - .rtsr_ofst =3D 0x20, - .ftsr_ofst =3D 0x24, - .swier_ofst =3D 0x28, - .rpr_ofst =3D 0x2C, - .fpr_ofst =3D 0x30, - .trg_ofst =3D 0x3E8, - .seccfgr_ofst =3D 0x34, -}; - -static const struct stm32_exti_bank stm32mp1_exti_b3 =3D { - .imr_ofst =3D 0xA0, - .emr_ofst =3D UNDEF_REG, - .rtsr_ofst =3D 0x40, - .ftsr_ofst =3D 0x44, - .swier_ofst =3D 0x48, - .rpr_ofst =3D 0x4C, - .fpr_ofst =3D 0x50, - .trg_ofst =3D 0x3E4, - .seccfgr_ofst =3D 0x54, -}; - -static const struct stm32_exti_bank *stm32mp1_exti_banks[] =3D { - &stm32mp1_exti_b1, - &stm32mp1_exti_b2, - &stm32mp1_exti_b3, -}; - -static struct irq_chip stm32_exti_h_chip; -static struct irq_chip stm32_exti_h_chip_direct; - -#define EXTI_INVALID_IRQ U8_MAX -#define STM32MP1_DESC_IRQ_SIZE (ARRAY_SIZE(stm32mp1_exti_banks) * IRQS_PER_B= ANK) - -/* - * Use some intentionally tricky logic here to initialize the whole array to - * EXTI_INVALID_IRQ, but then override certain fields, requiring us to indic= ate - * that we "know" that there are overrides in this structure, and we'll need= to - * disable that warning from W=3D1 builds. - */ -__diag_push(); -__diag_ignore_all("-Woverride-init", - "logic to initialize all and then override some is OK"); - -static const u8 stm32mp1_desc_irq[] =3D { - /* default value */ - [0 ... (STM32MP1_DESC_IRQ_SIZE - 1)] =3D EXTI_INVALID_IRQ, - - [0] =3D 6, - [1] =3D 7, - [2] =3D 8, - [3] =3D 9, - [4] =3D 10, - [5] =3D 23, - [6] =3D 64, - [7] =3D 65, - [8] =3D 66, - [9] =3D 67, - [10] =3D 40, - [11] =3D 42, - [12] =3D 76, - [13] =3D 77, - [14] =3D 121, - [15] =3D 127, - [16] =3D 1, - [19] =3D 3, - [21] =3D 31, - [22] =3D 33, - [23] =3D 72, - [24] =3D 95, - [25] =3D 107, - [26] =3D 37, - [27] =3D 38, - [28] =3D 39, - [29] =3D 71, - [30] =3D 52, - [31] =3D 53, - [32] =3D 82, - [33] =3D 83, - [46] =3D 151, - [47] =3D 93, - [48] =3D 138, - [50] =3D 139, - [52] =3D 140, - [53] =3D 141, - [54] =3D 135, - [61] =3D 100, - [65] =3D 144, - [68] =3D 143, - [70] =3D 62, - [73] =3D 129, -}; - -static const u8 stm32mp13_desc_irq[] =3D { - /* default value */ - [0 ... (STM32MP1_DESC_IRQ_SIZE - 1)] =3D EXTI_INVALID_IRQ, - - [0] =3D 6, - [1] =3D 7, - [2] =3D 8, - [3] =3D 9, - [4] =3D 10, - [5] =3D 24, - [6] =3D 65, - [7] =3D 66, - [8] =3D 67, - [9] =3D 68, - [10] =3D 41, - [11] =3D 43, - [12] =3D 77, - [13] =3D 78, - [14] =3D 106, - [15] =3D 109, - [16] =3D 1, - [19] =3D 3, - [21] =3D 32, - [22] =3D 34, - [23] =3D 73, - [24] =3D 93, - [25] =3D 114, - [26] =3D 38, - [27] =3D 39, - [28] =3D 40, - [29] =3D 72, - [30] =3D 53, - [31] =3D 54, - [32] =3D 83, - [33] =3D 84, - [44] =3D 96, - [47] =3D 92, - [48] =3D 116, - [50] =3D 117, - [52] =3D 118, - [53] =3D 119, - [68] =3D 63, - [70] =3D 98, -}; - -__diag_pop(); - -static const struct stm32_exti_drv_data stm32mp1_drv_data =3D { - .exti_banks =3D stm32mp1_exti_banks, - .bank_nr =3D ARRAY_SIZE(stm32mp1_exti_banks), - .desc_irqs =3D stm32mp1_desc_irq, -}; - -static const struct stm32_exti_drv_data stm32mp13_drv_data =3D { - .exti_banks =3D stm32mp1_exti_banks, - .bank_nr =3D ARRAY_SIZE(stm32mp1_exti_banks), - .desc_irqs =3D stm32mp13_desc_irq, -}; - static unsigned long stm32_exti_pending(struct irq_chip_generic *gc) { struct stm32_exti_chip_data *chip_data =3D gc->private; const struct stm32_exti_bank *stm32_bank =3D chip_data->reg_bank; - unsigned long pending; =20 - pending =3D irq_reg_readl(gc, stm32_bank->rpr_ofst); - if (stm32_bank->fpr_ofst !=3D UNDEF_REG) - pending |=3D irq_reg_readl(gc, stm32_bank->fpr_ofst); - - return pending; + return irq_reg_readl(gc, stm32_bank->rpr_ofst); } =20 static void stm32_irq_handler(struct irq_desc *desc) @@ -380,33 +166,21 @@ static int stm32_irq_set_type(struct irq_data *d, unsig= ned int type) struct irq_chip_generic *gc =3D irq_data_get_irq_chip_data(d); struct stm32_exti_chip_data *chip_data =3D gc->private; const struct stm32_exti_bank *stm32_bank =3D chip_data->reg_bank; - struct hwspinlock *hwlock =3D chip_data->host_data->hwlock; u32 rtsr, ftsr; int err; =20 irq_gc_lock(gc); =20 - if (hwlock) { - err =3D hwspin_lock_timeout_in_atomic(hwlock, HWSPNLCK_TIMEOUT); - if (err) { - pr_err("%s can't get hwspinlock (%d)\n", __func__, err); - goto unlock; - } - } - rtsr =3D irq_reg_readl(gc, stm32_bank->rtsr_ofst); ftsr =3D irq_reg_readl(gc, stm32_bank->ftsr_ofst); =20 err =3D stm32_exti_set_type(d, type, &rtsr, &ftsr); if (err) - goto unspinlock; + goto unlock; =20 irq_reg_writel(gc, rtsr, stm32_bank->rtsr_ofst); irq_reg_writel(gc, ftsr, stm32_bank->ftsr_ofst); =20 -unspinlock: - if (hwlock) - hwspin_unlock_in_atomic(hwlock); unlock: irq_gc_unlock(gc); =20 @@ -494,287 +268,10 @@ static void stm32_irq_ack(struct irq_data *d) irq_gc_lock(gc); =20 irq_reg_writel(gc, d->mask, stm32_bank->rpr_ofst); - if (stm32_bank->fpr_ofst !=3D UNDEF_REG) - irq_reg_writel(gc, d->mask, stm32_bank->fpr_ofst); =20 irq_gc_unlock(gc); } =20 -/* directly set the target bit without reading first. */ -static inline void stm32_exti_write_bit(struct irq_data *d, u32 reg) -{ - struct stm32_exti_chip_data *chip_data =3D irq_data_get_irq_chip_data(d); - void __iomem *base =3D chip_data->host_data->base; - u32 val =3D BIT(d->hwirq % IRQS_PER_BANK); - - writel_relaxed(val, base + reg); -} - -static inline u32 stm32_exti_set_bit(struct irq_data *d, u32 reg) -{ - struct stm32_exti_chip_data *chip_data =3D irq_data_get_irq_chip_data(d); - void __iomem *base =3D chip_data->host_data->base; - u32 val; - - val =3D readl_relaxed(base + reg); - val |=3D BIT(d->hwirq % IRQS_PER_BANK); - writel_relaxed(val, base + reg); - - return val; -} - -static inline u32 stm32_exti_clr_bit(struct irq_data *d, u32 reg) -{ - struct stm32_exti_chip_data *chip_data =3D irq_data_get_irq_chip_data(d); - void __iomem *base =3D chip_data->host_data->base; - u32 val; - - val =3D readl_relaxed(base + reg); - val &=3D ~BIT(d->hwirq % IRQS_PER_BANK); - writel_relaxed(val, base + reg); - - return val; -} - -static void stm32_exti_h_eoi(struct irq_data *d) -{ - struct stm32_exti_chip_data *chip_data =3D irq_data_get_irq_chip_data(d); - const struct stm32_exti_bank *stm32_bank =3D chip_data->reg_bank; - - raw_spin_lock(&chip_data->rlock); - - stm32_exti_write_bit(d, stm32_bank->rpr_ofst); - if (stm32_bank->fpr_ofst !=3D UNDEF_REG) - stm32_exti_write_bit(d, stm32_bank->fpr_ofst); - - raw_spin_unlock(&chip_data->rlock); - - if (d->parent_data->chip) - irq_chip_eoi_parent(d); -} - -static void stm32_exti_h_mask(struct irq_data *d) -{ - struct stm32_exti_chip_data *chip_data =3D irq_data_get_irq_chip_data(d); - const struct stm32_exti_bank *stm32_bank =3D chip_data->reg_bank; - - raw_spin_lock(&chip_data->rlock); - chip_data->mask_cache =3D stm32_exti_clr_bit(d, stm32_bank->imr_ofst); - raw_spin_unlock(&chip_data->rlock); - - if (d->parent_data->chip) - irq_chip_mask_parent(d); -} - -static void stm32_exti_h_unmask(struct irq_data *d) -{ - struct stm32_exti_chip_data *chip_data =3D irq_data_get_irq_chip_data(d); - const struct stm32_exti_bank *stm32_bank =3D chip_data->reg_bank; - - raw_spin_lock(&chip_data->rlock); - chip_data->mask_cache =3D stm32_exti_set_bit(d, stm32_bank->imr_ofst); - raw_spin_unlock(&chip_data->rlock); - - if (d->parent_data->chip) - irq_chip_unmask_parent(d); -} - -static int stm32_exti_h_set_type(struct irq_data *d, unsigned int type) -{ - struct stm32_exti_chip_data *chip_data =3D irq_data_get_irq_chip_data(d); - const struct stm32_exti_bank *stm32_bank =3D chip_data->reg_bank; - struct hwspinlock *hwlock =3D chip_data->host_data->hwlock; - void __iomem *base =3D chip_data->host_data->base; - u32 rtsr, ftsr; - int err; - - raw_spin_lock(&chip_data->rlock); - - if (hwlock) { - err =3D hwspin_lock_timeout_in_atomic(hwlock, HWSPNLCK_TIMEOUT); - if (err) { - pr_err("%s can't get hwspinlock (%d)\n", __func__, err); - goto unlock; - } - } - - rtsr =3D readl_relaxed(base + stm32_bank->rtsr_ofst); - ftsr =3D readl_relaxed(base + stm32_bank->ftsr_ofst); - - err =3D stm32_exti_set_type(d, type, &rtsr, &ftsr); - if (err) - goto unspinlock; - - writel_relaxed(rtsr, base + stm32_bank->rtsr_ofst); - writel_relaxed(ftsr, base + stm32_bank->ftsr_ofst); - -unspinlock: - if (hwlock) - hwspin_unlock_in_atomic(hwlock); -unlock: - raw_spin_unlock(&chip_data->rlock); - - return err; -} - -static int stm32_exti_h_set_wake(struct irq_data *d, unsigned int on) -{ - struct stm32_exti_chip_data *chip_data =3D irq_data_get_irq_chip_data(d); - u32 mask =3D BIT(d->hwirq % IRQS_PER_BANK); - - raw_spin_lock(&chip_data->rlock); - - if (on) - chip_data->wake_active |=3D mask; - else - chip_data->wake_active &=3D ~mask; - - raw_spin_unlock(&chip_data->rlock); - - return 0; -} - -static int stm32_exti_h_set_affinity(struct irq_data *d, - const struct cpumask *dest, bool force) -{ - if (d->parent_data->chip) - return irq_chip_set_affinity_parent(d, dest, force); - - return IRQ_SET_MASK_OK_DONE; -} - -static int stm32_exti_h_suspend(struct device *dev) -{ - struct stm32_exti_host_data *host_data =3D dev_get_drvdata(dev); - struct stm32_exti_chip_data *chip_data; - int i; - - for (i =3D 0; i < host_data->drv_data->bank_nr; i++) { - chip_data =3D &host_data->chips_data[i]; - stm32_chip_suspend(chip_data, chip_data->wake_active); - } - - return 0; -} - -static int stm32_exti_h_resume(struct device *dev) -{ - struct stm32_exti_host_data *host_data =3D dev_get_drvdata(dev); - struct stm32_exti_chip_data *chip_data; - int i; - - for (i =3D 0; i < host_data->drv_data->bank_nr; i++) { - chip_data =3D &host_data->chips_data[i]; - stm32_chip_resume(chip_data, chip_data->mask_cache); - } - - return 0; -} - -static int stm32_exti_h_retrigger(struct irq_data *d) -{ - struct stm32_exti_chip_data *chip_data =3D irq_data_get_irq_chip_data(d); - const struct stm32_exti_bank *stm32_bank =3D chip_data->reg_bank; - void __iomem *base =3D chip_data->host_data->base; - u32 mask =3D BIT(d->hwirq % IRQS_PER_BANK); - - writel_relaxed(mask, base + stm32_bank->swier_ofst); - - return 0; -} - -static struct irq_chip stm32_exti_h_chip =3D { - .name =3D "stm32-exti-h", - .irq_eoi =3D stm32_exti_h_eoi, - .irq_mask =3D stm32_exti_h_mask, - .irq_unmask =3D stm32_exti_h_unmask, - .irq_retrigger =3D stm32_exti_h_retrigger, - .irq_set_type =3D stm32_exti_h_set_type, - .irq_set_wake =3D stm32_exti_h_set_wake, - .flags =3D IRQCHIP_MASK_ON_SUSPEND, - .irq_set_affinity =3D IS_ENABLED(CONFIG_SMP) ? stm32_exti_h_set_affinity : = NULL, -}; - -static struct irq_chip stm32_exti_h_chip_direct =3D { - .name =3D "stm32-exti-h-direct", - .irq_eoi =3D irq_chip_eoi_parent, - .irq_ack =3D irq_chip_ack_parent, - .irq_mask =3D stm32_exti_h_mask, - .irq_unmask =3D stm32_exti_h_unmask, - .irq_retrigger =3D irq_chip_retrigger_hierarchy, - .irq_set_type =3D irq_chip_set_type_parent, - .irq_set_wake =3D stm32_exti_h_set_wake, - .flags =3D IRQCHIP_MASK_ON_SUSPEND, - .irq_set_affinity =3D IS_ENABLED(CONFIG_SMP) ? irq_chip_set_affinity_parent= : NULL, -}; - -static int stm32_exti_h_domain_alloc(struct irq_domain *dm, - unsigned int virq, - unsigned int nr_irqs, void *data) -{ - struct stm32_exti_host_data *host_data =3D dm->host_data; - struct stm32_exti_chip_data *chip_data; - u8 desc_irq; - struct irq_fwspec *fwspec =3D data; - struct irq_fwspec p_fwspec; - irq_hw_number_t hwirq; - int bank; - u32 event_trg; - struct irq_chip *chip; - - hwirq =3D fwspec->param[0]; - if (hwirq >=3D host_data->drv_data->bank_nr * IRQS_PER_BANK) - return -EINVAL; - - bank =3D hwirq / IRQS_PER_BANK; - chip_data =3D &host_data->chips_data[bank]; - - /* Check if event is reserved (Secure) */ - if (chip_data->event_reserved & BIT(hwirq % IRQS_PER_BANK)) { - dev_err(host_data->dev, "event %lu is reserved, secure\n", hwirq); - return -EPERM; - } - - event_trg =3D readl_relaxed(host_data->base + chip_data->reg_bank->trg_ofst= ); - chip =3D (event_trg & BIT(hwirq % IRQS_PER_BANK)) ? - &stm32_exti_h_chip : &stm32_exti_h_chip_direct; - - irq_domain_set_hwirq_and_chip(dm, virq, hwirq, chip, chip_data); - - if (host_data->dt_has_irqs_desc) { - struct of_phandle_args out_irq; - int ret; - - ret =3D of_irq_parse_one(host_data->dev->of_node, hwirq, &out_irq); - if (ret) - return ret; - /* we only support one parent, so far */ - if (of_node_to_fwnode(out_irq.np) !=3D dm->parent->fwnode) - return -EINVAL; - - of_phandle_args_to_fwspec(out_irq.np, out_irq.args, - out_irq.args_count, &p_fwspec); - - return irq_domain_alloc_irqs_parent(dm, virq, 1, &p_fwspec); - } - - if (!host_data->drv_data->desc_irqs) - return -EINVAL; - - desc_irq =3D host_data->drv_data->desc_irqs[hwirq]; - if (desc_irq !=3D EXTI_INVALID_IRQ) { - p_fwspec.fwnode =3D dm->parent->fwnode; - p_fwspec.param_count =3D 3; - p_fwspec.param[0] =3D GIC_SPI; - p_fwspec.param[1] =3D desc_irq; - p_fwspec.param[2] =3D IRQ_TYPE_LEVEL_HIGH; - - return irq_domain_alloc_irqs_parent(dm, virq, 1, &p_fwspec); - } - - return 0; -} - static struct stm32_exti_host_data *stm32_exti_host_init(const struct stm32_exti_drv_data = *dd, struct device_node *node) @@ -822,19 +319,12 @@ stm32_exti_chip_data *stm32_exti_chip_init(struct stm32= _exti_host_data *h_data, chip_data->host_data =3D h_data; chip_data->reg_bank =3D stm32_bank; =20 - raw_spin_lock_init(&chip_data->rlock); - /* * This IP has no reset, so after hot reboot we should * clear registers to avoid residue */ writel_relaxed(0, base + stm32_bank->imr_ofst); - if (stm32_bank->emr_ofst !=3D UNDEF_REG) - writel_relaxed(0, base + stm32_bank->emr_ofst); - - /* reserve Secure events */ - if (stm32_bank->seccfgr_ofst !=3D UNDEF_REG) - chip_data->event_reserved =3D readl_relaxed(base + stm32_bank->seccfgr_ofs= t); + writel_relaxed(0, base + stm32_bank->emr_ofst); =20 pr_info("%pOF: bank%d\n", node, bank_idx); =20 @@ -914,158 +404,6 @@ static int __init stm32_exti_init(const struct stm32_ex= ti_drv_data *drv_data, return ret; } =20 -static const struct irq_domain_ops stm32_exti_h_domain_ops =3D { - .alloc =3D stm32_exti_h_domain_alloc, - .free =3D irq_domain_free_irqs_common, - .xlate =3D irq_domain_xlate_twocell, -}; - -static void stm32_exti_check_rif(struct stm32_exti_host_data *host_data) -{ - unsigned int bank, i, event; - u32 cid, cidcfgr, hwcfgr1; - - /* quit on CID not supported */ - hwcfgr1 =3D readl_relaxed(host_data->base + EXTI_HWCFGR1); - if ((hwcfgr1 & EXTI_HWCFGR1_CIDWIDTH_MASK) =3D=3D 0) - return; - - for (bank =3D 0; bank < host_data->drv_data->bank_nr; bank++) { - for (i =3D 0; i < IRQS_PER_BANK; i++) { - event =3D bank * IRQS_PER_BANK + i; - cidcfgr =3D readl_relaxed(host_data->base + EXTI_EnCIDCFGR(event)); - cid =3D (cidcfgr & EXTI_CIDCFGR_CID_MASK) >> EXTI_CIDCFGR_CID_SHIFT; - if ((cidcfgr & EXTI_CIDCFGR_CFEN_MASK) && cid !=3D EXTI_CID1) - host_data->chips_data[bank].event_reserved |=3D BIT(i); - } - } -} - -static void stm32_exti_remove_irq(void *data) -{ - struct irq_domain *domain =3D data; - - irq_domain_remove(domain); -} - -static int stm32_exti_probe(struct platform_device *pdev) -{ - int ret, i; - struct device *dev =3D &pdev->dev; - struct device_node *np =3D dev->of_node; - struct irq_domain *parent_domain, *domain; - struct stm32_exti_host_data *host_data; - const struct stm32_exti_drv_data *drv_data; - - host_data =3D devm_kzalloc(dev, sizeof(*host_data), GFP_KERNEL); - if (!host_data) - return -ENOMEM; - - dev_set_drvdata(dev, host_data); - host_data->dev =3D dev; - - /* check for optional hwspinlock which may be not available yet */ - ret =3D of_hwspin_lock_get_id(np, 0); - if (ret =3D=3D -EPROBE_DEFER) - /* hwspinlock framework not yet ready */ - return ret; - - if (ret >=3D 0) { - host_data->hwlock =3D devm_hwspin_lock_request_specific(dev, ret); - if (!host_data->hwlock) { - dev_err(dev, "Failed to request hwspinlock\n"); - return -EINVAL; - } - } else if (ret !=3D -ENOENT) { - /* note: ENOENT is a valid case (means 'no hwspinlock') */ - dev_err(dev, "Failed to get hwspinlock\n"); - return ret; - } - - /* initialize host_data */ - drv_data =3D of_device_get_match_data(dev); - if (!drv_data) { - dev_err(dev, "no of match data\n"); - return -ENODEV; - } - host_data->drv_data =3D drv_data; - - host_data->chips_data =3D devm_kcalloc(dev, drv_data->bank_nr, - sizeof(*host_data->chips_data), - GFP_KERNEL); - if (!host_data->chips_data) - return -ENOMEM; - - host_data->base =3D devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(host_data->base)) - return PTR_ERR(host_data->base); - - for (i =3D 0; i < drv_data->bank_nr; i++) - stm32_exti_chip_init(host_data, i, np); - - stm32_exti_check_rif(host_data); - - parent_domain =3D irq_find_host(of_irq_find_parent(np)); - if (!parent_domain) { - dev_err(dev, "GIC interrupt-parent not found\n"); - return -EINVAL; - } - - domain =3D irq_domain_add_hierarchy(parent_domain, 0, - drv_data->bank_nr * IRQS_PER_BANK, - np, &stm32_exti_h_domain_ops, - host_data); - - if (!domain) { - dev_err(dev, "Could not register exti domain\n"); - return -ENOMEM; - } - - ret =3D devm_add_action_or_reset(dev, stm32_exti_remove_irq, domain); - if (ret) - return ret; - - if (of_property_read_bool(np, "interrupts-extended")) - host_data->dt_has_irqs_desc =3D true; - - return 0; -} - -/* platform driver only for MP1 */ -static const struct of_device_id stm32_exti_ids[] =3D { - { .compatible =3D "st,stm32mp1-exti", .data =3D &stm32mp1_drv_data}, - { .compatible =3D "st,stm32mp13-exti", .data =3D &stm32mp13_drv_data}, - {}, -}; -MODULE_DEVICE_TABLE(of, stm32_exti_ids); - -static const struct dev_pm_ops stm32_exti_dev_pm_ops =3D { - NOIRQ_SYSTEM_SLEEP_PM_OPS(stm32_exti_h_suspend, stm32_exti_h_resume) -}; - -static struct platform_driver stm32_exti_driver =3D { - .probe =3D stm32_exti_probe, - .driver =3D { - .name =3D "stm32_exti", - .of_match_table =3D stm32_exti_ids, - .pm =3D &stm32_exti_dev_pm_ops, - }, -}; - -static int __init stm32_exti_arch_init(void) -{ - return platform_driver_register(&stm32_exti_driver); -} - -static void __exit stm32_exti_arch_exit(void) -{ - return platform_driver_unregister(&stm32_exti_driver); -} - -arch_initcall(stm32_exti_arch_init); -module_exit(stm32_exti_arch_exit); - -/* no platform driver for F4 and H7 */ static int __init stm32f4_exti_of_init(struct device_node *np, struct device_node *parent) { diff --git a/drivers/irqchip/irq-stm32mp-exti.c b/drivers/irqchip/irq-stm32mp= -exti.c new file mode 100644 index 000000000000..33e0cfdea654 --- /dev/null +++ b/drivers/irqchip/irq-stm32mp-exti.c @@ -0,0 +1,729 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) Maxime Coquelin 2015 + * Copyright (C) STMicroelectronics 2017-2024 + * Author: Maxime Coquelin + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define IRQS_PER_BANK 32 + +#define HWSPNLCK_TIMEOUT 1000 /* usec */ + +#define EXTI_EnCIDCFGR(n) (0x180 + (n) * 4) +#define EXTI_HWCFGR1 0x3f0 + +/* Register: EXTI_EnCIDCFGR(n) */ +#define EXTI_CIDCFGR_CFEN_MASK BIT(0) +#define EXTI_CIDCFGR_CID_MASK GENMASK(6, 4) +#define EXTI_CIDCFGR_CID_SHIFT 4 + +/* Register: EXTI_HWCFGR1 */ +#define EXTI_HWCFGR1_CIDWIDTH_MASK GENMASK(27, 24) + +#define EXTI_CID1 1 + +struct stm32mp_exti_bank { + u32 imr_ofst; + u32 rtsr_ofst; + u32 ftsr_ofst; + u32 swier_ofst; + u32 rpr_ofst; + u32 fpr_ofst; + u32 trg_ofst; + u32 seccfgr_ofst; +}; + +struct stm32mp_exti_drv_data { + const struct stm32mp_exti_bank **exti_banks; + const u8 *desc_irqs; + u32 bank_nr; +}; + +struct stm32mp_exti_chip_data { + struct stm32mp_exti_host_data *host_data; + const struct stm32mp_exti_bank *reg_bank; + struct raw_spinlock rlock; + u32 wake_active; + u32 mask_cache; + u32 rtsr_cache; + u32 ftsr_cache; + u32 event_reserved; +}; + +struct stm32mp_exti_host_data { + void __iomem *base; + struct device *dev; + struct stm32mp_exti_chip_data *chips_data; + const struct stm32mp_exti_drv_data *drv_data; + struct hwspinlock *hwlock; + /* skip internal desc_irqs array and get it from DT */ + bool dt_has_irqs_desc; +}; + +static const struct stm32mp_exti_bank stm32mp_exti_b1 =3D { + .imr_ofst =3D 0x80, + .rtsr_ofst =3D 0x00, + .ftsr_ofst =3D 0x04, + .swier_ofst =3D 0x08, + .rpr_ofst =3D 0x0C, + .fpr_ofst =3D 0x10, + .trg_ofst =3D 0x3EC, + .seccfgr_ofst =3D 0x14, +}; + +static const struct stm32mp_exti_bank stm32mp_exti_b2 =3D { + .imr_ofst =3D 0x90, + .rtsr_ofst =3D 0x20, + .ftsr_ofst =3D 0x24, + .swier_ofst =3D 0x28, + .rpr_ofst =3D 0x2C, + .fpr_ofst =3D 0x30, + .trg_ofst =3D 0x3E8, + .seccfgr_ofst =3D 0x34, +}; + +static const struct stm32mp_exti_bank stm32mp_exti_b3 =3D { + .imr_ofst =3D 0xA0, + .rtsr_ofst =3D 0x40, + .ftsr_ofst =3D 0x44, + .swier_ofst =3D 0x48, + .rpr_ofst =3D 0x4C, + .fpr_ofst =3D 0x50, + .trg_ofst =3D 0x3E4, + .seccfgr_ofst =3D 0x54, +}; + +static const struct stm32mp_exti_bank *stm32mp_exti_banks[] =3D { + &stm32mp_exti_b1, + &stm32mp_exti_b2, + &stm32mp_exti_b3, +}; + +static struct irq_chip stm32mp_exti_chip; +static struct irq_chip stm32mp_exti_chip_direct; + +#define EXTI_INVALID_IRQ U8_MAX +#define STM32MP_DESC_IRQ_SIZE (ARRAY_SIZE(stm32mp_exti_banks) * IRQS_PER_BA= NK) + +/* + * Use some intentionally tricky logic here to initialize the whole array to + * EXTI_INVALID_IRQ, but then override certain fields, requiring us to indic= ate + * that we "know" that there are overrides in this structure, and we'll need= to + * disable that warning from W=3D1 builds. + */ +__diag_push(); +__diag_ignore_all("-Woverride-init", + "logic to initialize all and then override some is OK"); + +static const u8 stm32mp1_desc_irq[] =3D { + /* default value */ + [0 ... (STM32MP_DESC_IRQ_SIZE - 1)] =3D EXTI_INVALID_IRQ, + + [0] =3D 6, + [1] =3D 7, + [2] =3D 8, + [3] =3D 9, + [4] =3D 10, + [5] =3D 23, + [6] =3D 64, + [7] =3D 65, + [8] =3D 66, + [9] =3D 67, + [10] =3D 40, + [11] =3D 42, + [12] =3D 76, + [13] =3D 77, + [14] =3D 121, + [15] =3D 127, + [16] =3D 1, + [19] =3D 3, + [21] =3D 31, + [22] =3D 33, + [23] =3D 72, + [24] =3D 95, + [25] =3D 107, + [26] =3D 37, + [27] =3D 38, + [28] =3D 39, + [29] =3D 71, + [30] =3D 52, + [31] =3D 53, + [32] =3D 82, + [33] =3D 83, + [46] =3D 151, + [47] =3D 93, + [48] =3D 138, + [50] =3D 139, + [52] =3D 140, + [53] =3D 141, + [54] =3D 135, + [61] =3D 100, + [65] =3D 144, + [68] =3D 143, + [70] =3D 62, + [73] =3D 129, +}; + +static const u8 stm32mp13_desc_irq[] =3D { + /* default value */ + [0 ... (STM32MP_DESC_IRQ_SIZE - 1)] =3D EXTI_INVALID_IRQ, + + [0] =3D 6, + [1] =3D 7, + [2] =3D 8, + [3] =3D 9, + [4] =3D 10, + [5] =3D 24, + [6] =3D 65, + [7] =3D 66, + [8] =3D 67, + [9] =3D 68, + [10] =3D 41, + [11] =3D 43, + [12] =3D 77, + [13] =3D 78, + [14] =3D 106, + [15] =3D 109, + [16] =3D 1, + [19] =3D 3, + [21] =3D 32, + [22] =3D 34, + [23] =3D 73, + [24] =3D 93, + [25] =3D 114, + [26] =3D 38, + [27] =3D 39, + [28] =3D 40, + [29] =3D 72, + [30] =3D 53, + [31] =3D 54, + [32] =3D 83, + [33] =3D 84, + [44] =3D 96, + [47] =3D 92, + [48] =3D 116, + [50] =3D 117, + [52] =3D 118, + [53] =3D 119, + [68] =3D 63, + [70] =3D 98, +}; + +__diag_pop(); + +static const struct stm32mp_exti_drv_data stm32mp1_drv_data =3D { + .exti_banks =3D stm32mp_exti_banks, + .bank_nr =3D ARRAY_SIZE(stm32mp_exti_banks), + .desc_irqs =3D stm32mp1_desc_irq, +}; + +static const struct stm32mp_exti_drv_data stm32mp13_drv_data =3D { + .exti_banks =3D stm32mp_exti_banks, + .bank_nr =3D ARRAY_SIZE(stm32mp_exti_banks), + .desc_irqs =3D stm32mp13_desc_irq, +}; + +static int stm32mp_exti_convert_type(struct irq_data *d, unsigned int type, = u32 *rtsr, u32 *ftsr) +{ + u32 mask =3D BIT(d->hwirq % IRQS_PER_BANK); + + switch (type) { + case IRQ_TYPE_EDGE_RISING: + *rtsr |=3D mask; + *ftsr &=3D ~mask; + break; + case IRQ_TYPE_EDGE_FALLING: + *rtsr &=3D ~mask; + *ftsr |=3D mask; + break; + case IRQ_TYPE_EDGE_BOTH: + *rtsr |=3D mask; + *ftsr |=3D mask; + break; + default: + return -EINVAL; + } + + return 0; +} + +static void stm32mp_chip_suspend(struct stm32mp_exti_chip_data *chip_data, u= 32 wake_active) +{ + const struct stm32mp_exti_bank *bank =3D chip_data->reg_bank; + void __iomem *base =3D chip_data->host_data->base; + + /* save rtsr, ftsr registers */ + chip_data->rtsr_cache =3D readl_relaxed(base + bank->rtsr_ofst); + chip_data->ftsr_cache =3D readl_relaxed(base + bank->ftsr_ofst); + + writel_relaxed(wake_active, base + bank->imr_ofst); +} + +static void stm32mp_chip_resume(struct stm32mp_exti_chip_data *chip_data, u3= 2 mask_cache) +{ + const struct stm32mp_exti_bank *bank =3D chip_data->reg_bank; + void __iomem *base =3D chip_data->host_data->base; + + /* restore rtsr, ftsr, registers */ + writel_relaxed(chip_data->rtsr_cache, base + bank->rtsr_ofst); + writel_relaxed(chip_data->ftsr_cache, base + bank->ftsr_ofst); + + writel_relaxed(mask_cache, base + bank->imr_ofst); +} + +/* directly set the target bit without reading first. */ +static inline void stm32mp_exti_write_bit(struct irq_data *d, u32 reg) +{ + struct stm32mp_exti_chip_data *chip_data =3D irq_data_get_irq_chip_data(d); + void __iomem *base =3D chip_data->host_data->base; + u32 val =3D BIT(d->hwirq % IRQS_PER_BANK); + + writel_relaxed(val, base + reg); +} + +static inline u32 stm32mp_exti_set_bit(struct irq_data *d, u32 reg) +{ + struct stm32mp_exti_chip_data *chip_data =3D irq_data_get_irq_chip_data(d); + void __iomem *base =3D chip_data->host_data->base; + u32 val; + + val =3D readl_relaxed(base + reg); + val |=3D BIT(d->hwirq % IRQS_PER_BANK); + writel_relaxed(val, base + reg); + + return val; +} + +static inline u32 stm32mp_exti_clr_bit(struct irq_data *d, u32 reg) +{ + struct stm32mp_exti_chip_data *chip_data =3D irq_data_get_irq_chip_data(d); + void __iomem *base =3D chip_data->host_data->base; + u32 val; + + val =3D readl_relaxed(base + reg); + val &=3D ~BIT(d->hwirq % IRQS_PER_BANK); + writel_relaxed(val, base + reg); + + return val; +} + +static void stm32mp_exti_eoi(struct irq_data *d) +{ + struct stm32mp_exti_chip_data *chip_data =3D irq_data_get_irq_chip_data(d); + const struct stm32mp_exti_bank *bank =3D chip_data->reg_bank; + + raw_spin_lock(&chip_data->rlock); + + stm32mp_exti_write_bit(d, bank->rpr_ofst); + stm32mp_exti_write_bit(d, bank->fpr_ofst); + + raw_spin_unlock(&chip_data->rlock); + + if (d->parent_data->chip) + irq_chip_eoi_parent(d); +} + +static void stm32mp_exti_mask(struct irq_data *d) +{ + struct stm32mp_exti_chip_data *chip_data =3D irq_data_get_irq_chip_data(d); + const struct stm32mp_exti_bank *bank =3D chip_data->reg_bank; + + raw_spin_lock(&chip_data->rlock); + chip_data->mask_cache =3D stm32mp_exti_clr_bit(d, bank->imr_ofst); + raw_spin_unlock(&chip_data->rlock); + + if (d->parent_data->chip) + irq_chip_mask_parent(d); +} + +static void stm32mp_exti_unmask(struct irq_data *d) +{ + struct stm32mp_exti_chip_data *chip_data =3D irq_data_get_irq_chip_data(d); + const struct stm32mp_exti_bank *bank =3D chip_data->reg_bank; + + raw_spin_lock(&chip_data->rlock); + chip_data->mask_cache =3D stm32mp_exti_set_bit(d, bank->imr_ofst); + raw_spin_unlock(&chip_data->rlock); + + if (d->parent_data->chip) + irq_chip_unmask_parent(d); +} + +static int stm32mp_exti_set_type(struct irq_data *d, unsigned int type) +{ + struct stm32mp_exti_chip_data *chip_data =3D irq_data_get_irq_chip_data(d); + const struct stm32mp_exti_bank *bank =3D chip_data->reg_bank; + struct hwspinlock *hwlock =3D chip_data->host_data->hwlock; + void __iomem *base =3D chip_data->host_data->base; + u32 rtsr, ftsr; + int err; + + raw_spin_lock(&chip_data->rlock); + + if (hwlock) { + err =3D hwspin_lock_timeout_in_atomic(hwlock, HWSPNLCK_TIMEOUT); + if (err) { + pr_err("%s can't get hwspinlock (%d)\n", __func__, err); + goto unlock; + } + } + + rtsr =3D readl_relaxed(base + bank->rtsr_ofst); + ftsr =3D readl_relaxed(base + bank->ftsr_ofst); + + err =3D stm32mp_exti_convert_type(d, type, &rtsr, &ftsr); + if (!err) { + writel_relaxed(rtsr, base + bank->rtsr_ofst); + writel_relaxed(ftsr, base + bank->ftsr_ofst); + } + + if (hwlock) + hwspin_unlock_in_atomic(hwlock); +unlock: + raw_spin_unlock(&chip_data->rlock); + return err; +} + +static int stm32mp_exti_set_wake(struct irq_data *d, unsigned int on) +{ + struct stm32mp_exti_chip_data *chip_data =3D irq_data_get_irq_chip_data(d); + u32 mask =3D BIT(d->hwirq % IRQS_PER_BANK); + + raw_spin_lock(&chip_data->rlock); + + if (on) + chip_data->wake_active |=3D mask; + else + chip_data->wake_active &=3D ~mask; + + raw_spin_unlock(&chip_data->rlock); + + return 0; +} + +static int stm32mp_exti_set_affinity(struct irq_data *d, const struct cpumas= k *dest, bool force) +{ + if (d->parent_data->chip) + return irq_chip_set_affinity_parent(d, dest, force); + + return IRQ_SET_MASK_OK_DONE; +} + +static int stm32mp_exti_suspend(struct device *dev) +{ + struct stm32mp_exti_host_data *host_data =3D dev_get_drvdata(dev); + struct stm32mp_exti_chip_data *chip_data; + int i; + + for (i =3D 0; i < host_data->drv_data->bank_nr; i++) { + chip_data =3D &host_data->chips_data[i]; + stm32mp_chip_suspend(chip_data, chip_data->wake_active); + } + + return 0; +} + +static int stm32mp_exti_resume(struct device *dev) +{ + struct stm32mp_exti_host_data *host_data =3D dev_get_drvdata(dev); + struct stm32mp_exti_chip_data *chip_data; + int i; + + for (i =3D 0; i < host_data->drv_data->bank_nr; i++) { + chip_data =3D &host_data->chips_data[i]; + stm32mp_chip_resume(chip_data, chip_data->mask_cache); + } + + return 0; +} + +static int stm32mp_exti_retrigger(struct irq_data *d) +{ + struct stm32mp_exti_chip_data *chip_data =3D irq_data_get_irq_chip_data(d); + const struct stm32mp_exti_bank *bank =3D chip_data->reg_bank; + void __iomem *base =3D chip_data->host_data->base; + u32 mask =3D BIT(d->hwirq % IRQS_PER_BANK); + + writel_relaxed(mask, base + bank->swier_ofst); + + return 0; +} + +static struct irq_chip stm32mp_exti_chip =3D { + .name =3D "stm32mp-exti", + .irq_eoi =3D stm32mp_exti_eoi, + .irq_mask =3D stm32mp_exti_mask, + .irq_unmask =3D stm32mp_exti_unmask, + .irq_retrigger =3D stm32mp_exti_retrigger, + .irq_set_type =3D stm32mp_exti_set_type, + .irq_set_wake =3D stm32mp_exti_set_wake, + .flags =3D IRQCHIP_MASK_ON_SUSPEND, + .irq_set_affinity =3D IS_ENABLED(CONFIG_SMP) ? stm32mp_exti_set_affinity : = NULL, +}; + +static struct irq_chip stm32mp_exti_chip_direct =3D { + .name =3D "stm32mp-exti-direct", + .irq_eoi =3D irq_chip_eoi_parent, + .irq_ack =3D irq_chip_ack_parent, + .irq_mask =3D stm32mp_exti_mask, + .irq_unmask =3D stm32mp_exti_unmask, + .irq_retrigger =3D irq_chip_retrigger_hierarchy, + .irq_set_type =3D irq_chip_set_type_parent, + .irq_set_wake =3D stm32mp_exti_set_wake, + .flags =3D IRQCHIP_MASK_ON_SUSPEND, + .irq_set_affinity =3D IS_ENABLED(CONFIG_SMP) ? irq_chip_set_affinity_parent= : NULL, +}; + +static int stm32mp_exti_domain_alloc(struct irq_domain *dm, + unsigned int virq, + unsigned int nr_irqs, void *data) +{ + struct stm32mp_exti_host_data *host_data =3D dm->host_data; + struct stm32mp_exti_chip_data *chip_data; + struct irq_fwspec *fwspec =3D data; + struct irq_fwspec p_fwspec; + irq_hw_number_t hwirq; + struct irq_chip *chip; + u32 event_trg; + u8 desc_irq; + int bank; + + hwirq =3D fwspec->param[0]; + if (hwirq >=3D host_data->drv_data->bank_nr * IRQS_PER_BANK) + return -EINVAL; + + bank =3D hwirq / IRQS_PER_BANK; + chip_data =3D &host_data->chips_data[bank]; + + /* Check if event is reserved (Secure) */ + if (chip_data->event_reserved & BIT(hwirq % IRQS_PER_BANK)) { + dev_err(host_data->dev, "event %lu is reserved, secure\n", hwirq); + return -EPERM; + } + + event_trg =3D readl_relaxed(host_data->base + chip_data->reg_bank->trg_ofst= ); + chip =3D (event_trg & BIT(hwirq % IRQS_PER_BANK)) ? + &stm32mp_exti_chip : &stm32mp_exti_chip_direct; + + irq_domain_set_hwirq_and_chip(dm, virq, hwirq, chip, chip_data); + + if (host_data->dt_has_irqs_desc) { + struct of_phandle_args out_irq; + int ret; + + ret =3D of_irq_parse_one(host_data->dev->of_node, hwirq, &out_irq); + if (ret) + return ret; + /* we only support one parent, so far */ + if (of_node_to_fwnode(out_irq.np) !=3D dm->parent->fwnode) + return -EINVAL; + + of_phandle_args_to_fwspec(out_irq.np, out_irq.args, + out_irq.args_count, &p_fwspec); + + return irq_domain_alloc_irqs_parent(dm, virq, 1, &p_fwspec); + } + + if (!host_data->drv_data->desc_irqs) + return -EINVAL; + + desc_irq =3D host_data->drv_data->desc_irqs[hwirq]; + if (desc_irq !=3D EXTI_INVALID_IRQ) { + p_fwspec.fwnode =3D dm->parent->fwnode; + p_fwspec.param_count =3D 3; + p_fwspec.param[0] =3D GIC_SPI; + p_fwspec.param[1] =3D desc_irq; + p_fwspec.param[2] =3D IRQ_TYPE_LEVEL_HIGH; + + return irq_domain_alloc_irqs_parent(dm, virq, 1, &p_fwspec); + } + + return 0; +} + +static struct stm32mp_exti_chip_data *stm32mp_exti_chip_init(struct stm32mp_= exti_host_data *h_data, + u32 bank_idx, struct device_node *node) +{ + struct stm32mp_exti_chip_data *chip_data; + const struct stm32mp_exti_bank *bank; + void __iomem *base =3D h_data->base; + + bank =3D h_data->drv_data->exti_banks[bank_idx]; + chip_data =3D &h_data->chips_data[bank_idx]; + chip_data->host_data =3D h_data; + chip_data->reg_bank =3D bank; + + raw_spin_lock_init(&chip_data->rlock); + + /* + * This IP has no reset, so after hot reboot we should + * clear registers to avoid residue + */ + writel_relaxed(0, base + bank->imr_ofst); + + /* reserve Secure events */ + chip_data->event_reserved =3D readl_relaxed(base + bank->seccfgr_ofst); + + pr_info("%pOF: bank%d\n", node, bank_idx); + + return chip_data; +} + +static const struct irq_domain_ops stm32mp_exti_domain_ops =3D { + .alloc =3D stm32mp_exti_domain_alloc, + .free =3D irq_domain_free_irqs_common, + .xlate =3D irq_domain_xlate_twocell, +}; + +static void stm32mp_exti_check_rif(struct stm32mp_exti_host_data *host_data) +{ + unsigned int bank, i, event; + u32 cid, cidcfgr, hwcfgr1; + + /* quit on CID not supported */ + hwcfgr1 =3D readl_relaxed(host_data->base + EXTI_HWCFGR1); + if ((hwcfgr1 & EXTI_HWCFGR1_CIDWIDTH_MASK) =3D=3D 0) + return; + + for (bank =3D 0; bank < host_data->drv_data->bank_nr; bank++) { + for (i =3D 0; i < IRQS_PER_BANK; i++) { + event =3D bank * IRQS_PER_BANK + i; + cidcfgr =3D readl_relaxed(host_data->base + EXTI_EnCIDCFGR(event)); + cid =3D (cidcfgr & EXTI_CIDCFGR_CID_MASK) >> EXTI_CIDCFGR_CID_SHIFT; + if ((cidcfgr & EXTI_CIDCFGR_CFEN_MASK) && cid !=3D EXTI_CID1) + host_data->chips_data[bank].event_reserved |=3D BIT(i); + } + } +} + +static void stm32mp_exti_remove_irq(void *data) +{ + struct irq_domain *domain =3D data; + + irq_domain_remove(domain); +} + +static int stm32mp_exti_probe(struct platform_device *pdev) +{ + const struct stm32mp_exti_drv_data *drv_data; + struct irq_domain *parent_domain, *domain; + struct stm32mp_exti_host_data *host_data; + struct device *dev =3D &pdev->dev; + struct device_node *np =3D dev->of_node; + int ret, i; + + host_data =3D devm_kzalloc(dev, sizeof(*host_data), GFP_KERNEL); + if (!host_data) + return -ENOMEM; + + dev_set_drvdata(dev, host_data); + host_data->dev =3D dev; + + /* check for optional hwspinlock which may be not available yet */ + ret =3D of_hwspin_lock_get_id(np, 0); + if (ret =3D=3D -EPROBE_DEFER) + /* hwspinlock framework not yet ready */ + return ret; + + if (ret >=3D 0) { + host_data->hwlock =3D devm_hwspin_lock_request_specific(dev, ret); + if (!host_data->hwlock) { + dev_err(dev, "Failed to request hwspinlock\n"); + return -EINVAL; + } + } else if (ret !=3D -ENOENT) { + /* note: ENOENT is a valid case (means 'no hwspinlock') */ + dev_err(dev, "Failed to get hwspinlock\n"); + return ret; + } + + /* initialize host_data */ + drv_data =3D of_device_get_match_data(dev); + if (!drv_data) { + dev_err(dev, "no of match data\n"); + return -ENODEV; + } + host_data->drv_data =3D drv_data; + + host_data->chips_data =3D devm_kcalloc(dev, drv_data->bank_nr, + sizeof(*host_data->chips_data), + GFP_KERNEL); + if (!host_data->chips_data) + return -ENOMEM; + + host_data->base =3D devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(host_data->base)) + return PTR_ERR(host_data->base); + + for (i =3D 0; i < drv_data->bank_nr; i++) + stm32mp_exti_chip_init(host_data, i, np); + + stm32mp_exti_check_rif(host_data); + + parent_domain =3D irq_find_host(of_irq_find_parent(np)); + if (!parent_domain) { + dev_err(dev, "GIC interrupt-parent not found\n"); + return -EINVAL; + } + + domain =3D irq_domain_add_hierarchy(parent_domain, 0, + drv_data->bank_nr * IRQS_PER_BANK, + np, &stm32mp_exti_domain_ops, + host_data); + + if (!domain) { + dev_err(dev, "Could not register exti domain\n"); + return -ENOMEM; + } + + ret =3D devm_add_action_or_reset(dev, stm32mp_exti_remove_irq, domain); + if (ret) + return ret; + + if (of_property_read_bool(np, "interrupts-extended")) + host_data->dt_has_irqs_desc =3D true; + + return 0; +} + +static const struct of_device_id stm32mp_exti_ids[] =3D { + { .compatible =3D "st,stm32mp1-exti", .data =3D &stm32mp1_drv_data}, + { .compatible =3D "st,stm32mp13-exti", .data =3D &stm32mp13_drv_data}, + {}, +}; +MODULE_DEVICE_TABLE(of, stm32mp_exti_ids); + +static const struct dev_pm_ops stm32mp_exti_dev_pm_ops =3D { + NOIRQ_SYSTEM_SLEEP_PM_OPS(stm32mp_exti_suspend, stm32mp_exti_resume) +}; + +static struct platform_driver stm32mp_exti_driver =3D { + .probe =3D stm32mp_exti_probe, + .driver =3D { + .name =3D "stm32mp_exti", + .of_match_table =3D stm32mp_exti_ids, + .pm =3D &stm32mp_exti_dev_pm_ops, + }, +}; + +module_platform_driver(stm32mp_exti_driver); + +MODULE_AUTHOR("Maxime Coquelin "); +MODULE_DESCRIPTION("STM32MP EXTI driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/irqchip/irq-ts4800.c b/drivers/irqchip/irq-ts4800.c index 57f610dab6b8..b5dddb3c1568 100644 --- a/drivers/irqchip/irq-ts4800.c +++ b/drivers/irqchip/irq-ts4800.c @@ -163,5 +163,6 @@ static struct platform_driver ts4800_ic_driver =3D { module_platform_driver(ts4800_ic_driver); =20 MODULE_AUTHOR("Damien Riegel "); +MODULE_DESCRIPTION("Multiplexed-IRQs driver for TS-4800's FPGA"); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:ts4800_irqc"); diff --git a/drivers/pci/msi/irqdomain.c b/drivers/pci/msi/irqdomain.c index 03d2dd25790d..569125726b3e 100644 --- a/drivers/pci/msi/irqdomain.c +++ b/drivers/pci/msi/irqdomain.c @@ -148,17 +148,35 @@ static void pci_device_domain_set_desc(msi_alloc_info_t= *arg, struct msi_desc *d arg->hwirq =3D desc->msi_index; } =20 +static __always_inline void cond_mask_parent(struct irq_data *data) +{ + struct msi_domain_info *info =3D data->domain->host_data; + + if (unlikely(info->flags & MSI_FLAG_PCI_MSI_MASK_PARENT)) + irq_chip_mask_parent(data); +} + +static __always_inline void cond_unmask_parent(struct irq_data *data) +{ + struct msi_domain_info *info =3D data->domain->host_data; + + if (unlikely(info->flags & MSI_FLAG_PCI_MSI_MASK_PARENT)) + irq_chip_unmask_parent(data); +} + static void pci_irq_mask_msi(struct irq_data *data) { struct msi_desc *desc =3D irq_data_get_msi_desc(data); =20 pci_msi_mask(desc, BIT(data->irq - desc->irq)); + cond_mask_parent(data); } =20 static void pci_irq_unmask_msi(struct irq_data *data) { struct msi_desc *desc =3D irq_data_get_msi_desc(data); =20 + cond_unmask_parent(data); pci_msi_unmask(desc, BIT(data->irq - desc->irq)); } =20 @@ -195,10 +213,12 @@ static const struct msi_domain_template pci_msi_templat= e =3D { static void pci_irq_mask_msix(struct irq_data *data) { pci_msix_mask(irq_data_get_msi_desc(data)); + cond_mask_parent(data); } =20 static void pci_irq_unmask_msix(struct irq_data *data) { + cond_unmask_parent(data); pci_msix_unmask(irq_data_get_msi_desc(data)); } =20 diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 28c3fb2bef0d..000d339e1596 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -279,6 +279,9 @@ static inline bool invalid_phys_cpuid(phys_cpuid_t phys_i= d) return phys_id =3D=3D PHYS_CPUID_INVALID; } =20 + +int __init acpi_get_madt_revision(void); + /* Validate the processor object's proc_id */ bool acpi_duplicate_processor_id(int proc_id); /* Processor _CTS control */ diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index 5c9bdd3ffccc..dac7466de5f3 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h @@ -168,7 +168,7 @@ static inline int __must_check request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char *name, void *dev) { - return request_threaded_irq(irq, handler, NULL, flags, name, dev); + return request_threaded_irq(irq, handler, NULL, flags | IRQF_COND_ONESHOT, = name, dev); } =20 extern int __must_check diff --git a/include/linux/irq.h b/include/linux/irq.h index a217e1029c1d..1f5dbf1f92c9 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -1106,6 +1106,7 @@ enum irq_gc_flags { * @irq_flags_to_set: IRQ* flags to set on irq setup * @irq_flags_to_clear: IRQ* flags to clear on irq setup * @gc_flags: Generic chip specific setup flags + * @exit: Function called on each chip when they are destroyed. * @gc: Array of pointers to generic interrupt chips */ struct irq_domain_chip_generic { @@ -1114,9 +1115,37 @@ struct irq_domain_chip_generic { unsigned int irq_flags_to_clear; unsigned int irq_flags_to_set; enum irq_gc_flags gc_flags; + void (*exit)(struct irq_chip_generic *gc); struct irq_chip_generic *gc[]; }; =20 +/** + * struct irq_domain_chip_generic_info - Generic chip information structure + * @name: Name of the generic interrupt chip + * @handler: Interrupt handler used by the generic interrupt chip + * @irqs_per_chip: Number of interrupts each chip handles (max 32) + * @num_ct: Number of irq_chip_type instances associated with each + * chip + * @irq_flags_to_clear: IRQ_* bits to clear in the mapping function + * @irq_flags_to_set: IRQ_* bits to set in the mapping function + * @gc_flags: Generic chip specific setup flags + * @init: Function called on each chip when they are created. + * Allow to do some additional chip initialisation. + * @exit: Function called on each chip when they are destroyed. + * Allow to do some chip cleanup operation. + */ +struct irq_domain_chip_generic_info { + const char *name; + irq_flow_handler_t handler; + unsigned int irqs_per_chip; + unsigned int num_ct; + unsigned int irq_flags_to_clear; + unsigned int irq_flags_to_set; + enum irq_gc_flags gc_flags; + int (*init)(struct irq_chip_generic *gc); + void (*exit)(struct irq_chip_generic *gc); +}; + /* Generic chip callback functions */ void irq_gc_noop(struct irq_data *d); void irq_gc_mask_disable_reg(struct irq_data *d); @@ -1153,6 +1182,20 @@ int devm_irq_setup_generic_chip(struct device *dev, st= ruct irq_chip_generic *gc, =20 struct irq_chip_generic *irq_get_domain_generic_chip(struct irq_domain *d, u= nsigned int hw_irq); =20 +#ifdef CONFIG_GENERIC_IRQ_CHIP +int irq_domain_alloc_generic_chips(struct irq_domain *d, + const struct irq_domain_chip_generic_info *info); +void irq_domain_remove_generic_chips(struct irq_domain *d); +#else +static inline int +irq_domain_alloc_generic_chips(struct irq_domain *d, + const struct irq_domain_chip_generic_info *info) +{ + return -EINVAL; +} +static inline void irq_domain_remove_generic_chips(struct irq_domain *d) { } +#endif /* CONFIG_GENERIC_IRQ_CHIP */ + int __irq_alloc_domain_generic_chips(struct irq_domain *d, int irqs_per_chip, int num_ct, const char *name, irq_flow_handler_t handler, diff --git a/include/linux/irqchip/arm-gic-v4.h b/include/linux/irqchip/arm-g= ic-v4.h index 2c63375bbd43..ecabed6d3307 100644 --- a/include/linux/irqchip/arm-gic-v4.h +++ b/include/linux/irqchip/arm-gic-v4.h @@ -25,6 +25,14 @@ struct its_vm { irq_hw_number_t db_lpi_base; unsigned long *db_bitmap; int nr_db_lpis; + /* + * Ensures mutual exclusion between updates to vlpi_count[] + * and map/unmap when using the ITSList mechanism. + * + * The lock order for any sequence involving the ITSList is + * vmapp_lock -> vpe_lock ->vmovp_lock. + */ + raw_spinlock_t vmapp_lock; u32 vlpi_count[GICv4_ITS_LIST_MAX]; }; =20 diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h index 21ecf582a0fe..de6105f68fec 100644 --- a/include/linux/irqdomain.h +++ b/include/linux/irqdomain.h @@ -74,11 +74,24 @@ void of_phandle_args_to_fwspec(struct device_node *np, co= nst u32 *args, * struct irq_domain_ops - Methods for irq_domain objects * @match: Match an interrupt controller device node to a host, returns * 1 on a match + * @select: Match an interrupt controller fw specification. It is more gener= ic + * than @match as it receives a complete struct irq_fwspec. Therefore, + * @select is preferred if provided. Returns 1 on a match. * @map: Create or update a mapping between a virtual irq number and a hw * irq number. This is called only once for a given mapping. * @unmap: Dispose of such a mapping * @xlate: Given a device tree node and interrupt specifier, decode * the hardware irq number and linux irq type value. + * @alloc: Allocate @nr_irqs interrupts starting from @virq. + * @free: Free @nr_irqs interrupts starting from @virq. + * @activate: Activate one interrupt in HW (@irqd). If @reserve is set, only + * reserve the vector. If unset, assign the vector (called from + * request_irq()). + * @deactivate: Disarm one interrupt (@irqd). + * @translate: Given @fwspec, decode the hardware irq number (@out_hwirq) and + * linux irq type value (@out_type). This is a generalised @xlate + * (over struct irq_fwspec) and is preferred if provided. + * @debug_show: For domains to show specific data for an interrupt in debugf= s. * * Functions below are provided by the driver and called whenever a new mapp= ing * is created or an old mapping is disposed. The driver can then proceed to @@ -131,6 +144,9 @@ struct irq_domain_chip_generic; * Optional elements: * @fwnode: Pointer to firmware node associated with the irq_domain. Pretty = easy * to swap it for the of_node via the irq_domain_get_of_node accessor + * @bus_token: @fwnode's device_node might be used for several irq domains. = But + * in connection with @bus_token, the pair shall be unique in a + * system. * @gc: Pointer to a list of generic chips. There is a helper function for * setting up one or more generic chips for interrupt controllers * drivers using the generic chip library which uses this pointer. @@ -141,9 +157,12 @@ struct irq_domain_chip_generic; * purposes related to the irq domain. * @parent: Pointer to parent irq_domain to support hierarchy irq_domains * @msi_parent_ops: Pointer to MSI parent domain methods for per device doma= in init + * @exit: Function called when the domain is destroyed * * Revmap data, used internally by the irq domain code: - * @revmap_size: Size of the linear map table @revmap[] + * @hwirq_max: Top limit for the HW irq number. Especially to avoid + * conflicts/failures with reserved HW irqs. Can be ~0. + * @revmap_size: Size of the linear map table @revmap * @revmap_tree: Radix map tree for hwirqs that don't fit in the linear map * @revmap: Linear table of irq_data pointers */ @@ -169,6 +188,7 @@ struct irq_domain { #ifdef CONFIG_GENERIC_MSI_IRQ const struct msi_parent_ops *msi_parent_ops; #endif + void (*exit)(struct irq_domain *d); =20 /* reverse map data. The linear map gets appended to the irq_domain */ irq_hw_number_t hwirq_max; @@ -182,7 +202,7 @@ enum { /* Irq domain is hierarchical */ IRQ_DOMAIN_FLAG_HIERARCHY =3D (1 << 0), =20 - /* Irq domain name was allocated in __irq_domain_add() */ + /* Irq domain name was allocated internally */ IRQ_DOMAIN_NAME_ALLOCATED =3D (1 << 1), =20 /* Irq domain is an IPI domain with virq per cpu */ @@ -208,6 +228,9 @@ enum { /* Irq domain is a MSI device domain */ IRQ_DOMAIN_FLAG_MSI_DEVICE =3D (1 << 9), =20 + /* Irq domain must destroy generic chips when removed */ + IRQ_DOMAIN_FLAG_DESTROY_GC =3D (1 << 10), + /* * Flags starting from IRQ_DOMAIN_FLAG_NONCORE are reserved * for implementation specific purposes and ignored by the @@ -257,10 +280,51 @@ static inline struct fwnode_handle *irq_domain_alloc_fw= node(phys_addr_t *pa) } =20 void irq_domain_free_fwnode(struct fwnode_handle *fwnode); -struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, unsigned i= nt size, - irq_hw_number_t hwirq_max, int direct_max, - const struct irq_domain_ops *ops, - void *host_data); + +struct irq_domain_chip_generic_info; + +/** + * struct irq_domain_info - Domain information structure + * @fwnode: firmware node for the interrupt controller + * @domain_flags: Additional flags to add to the domain flags + * @size: Size of linear map; 0 for radix mapping only + * @hwirq_max: Maximum number of interrupts supported by controller + * @direct_max: Maximum value of direct maps; + * Use ~0 for no limit; 0 for no direct mapping + * @bus_token: Domain bus token + * @ops: Domain operation callbacks + * @host_data: Controller private data pointer + * @dgc_info: Geneneric chip information structure pointer used to + * create generic chips for the domain if not NULL. + * @init: Function called when the domain is created. + * Allow to do some additional domain initialisation. + * @exit: Function called when the domain is destroyed. + * Allow to do some additional cleanup operation. + */ +struct irq_domain_info { + struct fwnode_handle *fwnode; + unsigned int domain_flags; + unsigned int size; + irq_hw_number_t hwirq_max; + int direct_max; + enum irq_domain_bus_token bus_token; + const struct irq_domain_ops *ops; + void *host_data; +#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY + /** + * @parent: Pointer to the parent irq domain used in a hierarchy domain + */ + struct irq_domain *parent; +#endif + struct irq_domain_chip_generic_info *dgc_info; + int (*init)(struct irq_domain *d); + void (*exit)(struct irq_domain *d); +}; + +struct irq_domain *irq_domain_instantiate(const struct irq_domain_info *info= ); +struct irq_domain *devm_irq_domain_instantiate(struct device *dev, + const struct irq_domain_info *info); + struct irq_domain *irq_domain_create_simple(struct fwnode_handle *fwnode, unsigned int size, unsigned int first_irq, @@ -293,7 +357,7 @@ static inline struct fwnode_handle *of_node_to_fwnode(str= uct device_node *node) =20 extern const struct fwnode_operations irqchip_fwnode_ops; =20 -static inline bool is_fwnode_irqchip(struct fwnode_handle *fwnode) +static inline bool is_fwnode_irqchip(const struct fwnode_handle *fwnode) { return fwnode && fwnode->ops =3D=3D &irqchip_fwnode_ops; } @@ -350,7 +414,17 @@ static inline struct irq_domain *irq_domain_add_linear(s= truct device_node *of_no const struct irq_domain_ops *ops, void *host_data) { - return __irq_domain_add(of_node_to_fwnode(of_node), size, size, 0, ops, hos= t_data); + struct irq_domain_info info =3D { + .fwnode =3D of_node_to_fwnode(of_node), + .size =3D size, + .hwirq_max =3D size, + .ops =3D ops, + .host_data =3D host_data, + }; + struct irq_domain *d; + + d =3D irq_domain_instantiate(&info); + return IS_ERR(d) ? NULL : d; } =20 #ifdef CONFIG_IRQ_DOMAIN_NOMAP @@ -359,7 +433,17 @@ static inline struct irq_domain *irq_domain_add_nomap(st= ruct device_node *of_nod const struct irq_domain_ops *ops, void *host_data) { - return __irq_domain_add(of_node_to_fwnode(of_node), 0, max_irq, max_irq, op= s, host_data); + struct irq_domain_info info =3D { + .fwnode =3D of_node_to_fwnode(of_node), + .hwirq_max =3D max_irq, + .direct_max =3D max_irq, + .ops =3D ops, + .host_data =3D host_data, + }; + struct irq_domain *d; + + d =3D irq_domain_instantiate(&info); + return IS_ERR(d) ? NULL : d; } =20 extern unsigned int irq_create_direct_mapping(struct irq_domain *host); @@ -369,7 +453,16 @@ static inline struct irq_domain *irq_domain_add_tree(str= uct device_node *of_node const struct irq_domain_ops *ops, void *host_data) { - return __irq_domain_add(of_node_to_fwnode(of_node), 0, ~0, 0, ops, host_dat= a); + struct irq_domain_info info =3D { + .fwnode =3D of_node_to_fwnode(of_node), + .hwirq_max =3D ~0U, + .ops =3D ops, + .host_data =3D host_data, + }; + struct irq_domain *d; + + d =3D irq_domain_instantiate(&info); + return IS_ERR(d) ? NULL : d; } =20 static inline struct irq_domain *irq_domain_create_linear(struct fwnode_hand= le *fwnode, @@ -377,14 +470,33 @@ static inline struct irq_domain *irq_domain_create_line= ar(struct fwnode_handle * const struct irq_domain_ops *ops, void *host_data) { - return __irq_domain_add(fwnode, size, size, 0, ops, host_data); + struct irq_domain_info info =3D { + .fwnode =3D fwnode, + .size =3D size, + .hwirq_max =3D size, + .ops =3D ops, + .host_data =3D host_data, + }; + struct irq_domain *d; + + d =3D irq_domain_instantiate(&info); + return IS_ERR(d) ? NULL : d; } =20 static inline struct irq_domain *irq_domain_create_tree(struct fwnode_handle= *fwnode, const struct irq_domain_ops *ops, void *host_data) { - return __irq_domain_add(fwnode, 0, ~0, 0, ops, host_data); + struct irq_domain_info info =3D { + .fwnode =3D fwnode, + .hwirq_max =3D ~0, + .ops =3D ops, + .host_data =3D host_data, + }; + struct irq_domain *d; + + d =3D irq_domain_instantiate(&info); + return IS_ERR(d) ? NULL : d; } =20 extern void irq_domain_remove(struct irq_domain *host); diff --git a/include/linux/msi.h b/include/linux/msi.h index dc27cf3903d5..369367ecae5e 100644 --- a/include/linux/msi.h +++ b/include/linux/msi.h @@ -21,11 +21,7 @@ #include #include #include -#include -#include -#include #include -#include =20 #include =20 @@ -81,7 +77,6 @@ extern int pci_msi_ignore_mask; /* Helper functions */ struct msi_desc; struct pci_dev; -struct platform_msi_priv_data; struct device_attribute; struct irq_domain; struct irq_affinity_desc; @@ -228,22 +223,6 @@ struct msi_dev_domain { struct irq_domain *domain; }; =20 -/** - * msi_device_data - MSI per device data - * @properties: MSI properties which are interesting to drivers - * @platform_data: Platform-MSI specific data - * @mutex: Mutex protecting the MSI descriptor store - * @__domains: Internal data for per device MSI domains - * @__iter_idx: Index to search the next entry for iterators - */ -struct msi_device_data { - unsigned long properties; - struct platform_msi_priv_data *platform_data; - struct mutex mutex; - struct msi_dev_domain __domains[MSI_MAX_DEVICE_IRQDOMAINS]; - unsigned long __iter_idx; -}; - int msi_setup_device_data(struct device *dev); =20 void msi_lock_descs(struct device *dev); @@ -556,6 +535,8 @@ enum { MSI_FLAG_USE_DEV_FWNODE =3D (1 << 7), /* Set parent->dev into domain->pm_dev on device domain creation */ MSI_FLAG_PARENT_PM_DEV =3D (1 << 8), + /* Support for parent mask/unmask */ + MSI_FLAG_PCI_MSI_MASK_PARENT =3D (1 << 9), =20 /* Mask for the generic functionality */ MSI_GENERIC_FLAGS_MASK =3D GENMASK(15, 0), @@ -639,35 +620,6 @@ void msi_domain_free_irqs_all(struct device *dev, unsign= ed int domid); =20 struct msi_domain_info *msi_get_domain_info(struct irq_domain *domain); =20 -struct irq_domain *platform_msi_create_irq_domain(struct fwnode_handle *fwno= de, - struct msi_domain_info *info, - struct irq_domain *parent); - -/* When an MSI domain is used as an intermediate domain */ -int msi_domain_prepare_irqs(struct irq_domain *domain, struct device *dev, - int nvec, msi_alloc_info_t *args); -int msi_domain_populate_irqs(struct irq_domain *domain, struct device *dev, - int virq, int nvec, msi_alloc_info_t *args); -void msi_domain_depopulate_descs(struct device *dev, int virq, int nvec); - -struct irq_domain * -__platform_msi_create_device_domain(struct device *dev, - unsigned int nvec, - bool is_tree, - irq_write_msi_msg_t write_msi_msg, - const struct irq_domain_ops *ops, - void *host_data); - -#define platform_msi_create_device_domain(dev, nvec, write, ops, data) \ - __platform_msi_create_device_domain(dev, nvec, false, write, ops, data) -#define platform_msi_create_device_tree_domain(dev, nvec, write, ops, data) \ - __platform_msi_create_device_domain(dev, nvec, true, write, ops, data) - -int platform_msi_device_domain_alloc(struct irq_domain *domain, unsigned int= virq, - unsigned int nr_irqs); -void platform_msi_device_domain_free(struct irq_domain *domain, unsigned int= virq, - unsigned int nvec); -void *platform_msi_get_host_data(struct irq_domain *domain); /* Per device platform MSI */ int platform_device_msi_init_and_alloc_irqs(struct device *dev, unsigned int= nvec, irq_write_msi_msg_t write_msi_msg); diff --git a/kernel/irq/debugfs.c b/kernel/irq/debugfs.c index aae0402507ed..c6ffb97966be 100644 --- a/kernel/irq/debugfs.c +++ b/kernel/irq/debugfs.c @@ -9,14 +9,8 @@ =20 static struct dentry *irq_dir; =20 -struct irq_bit_descr { - unsigned int mask; - char *name; -}; -#define BIT_MASK_DESCR(m) { .mask =3D m, .name =3D #m } - -static void irq_debug_show_bits(struct seq_file *m, int ind, unsigned int st= ate, - const struct irq_bit_descr *sd, int size) +void irq_debug_show_bits(struct seq_file *m, int ind, unsigned int state, + const struct irq_bit_descr *sd, int size) { int i; =20 diff --git a/kernel/irq/devres.c b/kernel/irq/devres.c index f6e5515ee077..b3e98668f4dd 100644 --- a/kernel/irq/devres.c +++ b/kernel/irq/devres.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 #include #include +#include #include #include #include @@ -282,3 +283,43 @@ int devm_irq_setup_generic_chip(struct device *dev, stru= ct irq_chip_generic *gc, } EXPORT_SYMBOL_GPL(devm_irq_setup_generic_chip); #endif /* CONFIG_GENERIC_IRQ_CHIP */ + +#ifdef CONFIG_IRQ_DOMAIN +static void devm_irq_domain_remove(struct device *dev, void *res) +{ + struct irq_domain **domain =3D res; + + irq_domain_remove(*domain); +} + +/** + * devm_irq_domain_instantiate() - Instantiate a new irq domain data for a + * managed device. + * @dev: Device to instantiate the domain for + * @info: Domain information pointer pointing to the information for this + * domain + * + * Return: A pointer to the instantiated irq domain or an ERR_PTR value. + */ +struct irq_domain *devm_irq_domain_instantiate(struct device *dev, + const struct irq_domain_info *info) +{ + struct irq_domain *domain; + struct irq_domain **dr; + + dr =3D devres_alloc(devm_irq_domain_remove, sizeof(*dr), GFP_KERNEL); + if (!dr) + return ERR_PTR(-ENOMEM); + + domain =3D irq_domain_instantiate(info); + if (!IS_ERR(domain)) { + *dr =3D domain; + devres_add(dev, dr); + } else { + devres_free(dr); + } + + return domain; +} +EXPORT_SYMBOL_GPL(devm_irq_domain_instantiate); +#endif /* CONFIG_IRQ_DOMAIN */ diff --git a/kernel/irq/generic-chip.c b/kernel/irq/generic-chip.c index d39a40bc542b..32ffcbb87fa1 100644 --- a/kernel/irq/generic-chip.c +++ b/kernel/irq/generic-chip.c @@ -276,21 +276,14 @@ irq_gc_init_mask_cache(struct irq_chip_generic *gc, enu= m irq_gc_flags flags) } =20 /** - * __irq_alloc_domain_generic_chips - Allocate generic chips for an irq doma= in - * @d: irq domain for which to allocate chips - * @irqs_per_chip: Number of interrupts each chip handles (max 32) - * @num_ct: Number of irq_chip_type instances associated with this - * @name: Name of the irq chip - * @handler: Default flow handler associated with these chips - * @clr: IRQ_* bits to clear in the mapping function - * @set: IRQ_* bits to set in the mapping function - * @gcflags: Generic chip specific setup flags + * irq_domain_alloc_generic_chips - Allocate generic chips for an irq domain + * @d: irq domain for which to allocate chips + * @info: Generic chip information + * + * Return: 0 on success, negative error code on failure */ -int __irq_alloc_domain_generic_chips(struct irq_domain *d, int irqs_per_chip, - int num_ct, const char *name, - irq_flow_handler_t handler, - unsigned int clr, unsigned int set, - enum irq_gc_flags gcflags) +int irq_domain_alloc_generic_chips(struct irq_domain *d, + const struct irq_domain_chip_generic_info *info) { struct irq_domain_chip_generic *dgc; struct irq_chip_generic *gc; @@ -300,27 +293,29 @@ int __irq_alloc_domain_generic_chips(struct irq_domain = *d, int irqs_per_chip, size_t gc_sz; size_t sz; void *tmp; + int ret; =20 if (d->gc) return -EBUSY; =20 - numchips =3D DIV_ROUND_UP(d->revmap_size, irqs_per_chip); + numchips =3D DIV_ROUND_UP(d->revmap_size, info->irqs_per_chip); if (!numchips) return -EINVAL; =20 /* Allocate a pointer, generic chip and chiptypes for each chip */ - gc_sz =3D struct_size(gc, chip_types, num_ct); + gc_sz =3D struct_size(gc, chip_types, info->num_ct); dgc_sz =3D struct_size(dgc, gc, numchips); sz =3D dgc_sz + numchips * gc_sz; =20 tmp =3D dgc =3D kzalloc(sz, GFP_KERNEL); if (!dgc) return -ENOMEM; - dgc->irqs_per_chip =3D irqs_per_chip; + dgc->irqs_per_chip =3D info->irqs_per_chip; dgc->num_chips =3D numchips; - dgc->irq_flags_to_set =3D set; - dgc->irq_flags_to_clear =3D clr; - dgc->gc_flags =3D gcflags; + dgc->irq_flags_to_set =3D info->irq_flags_to_set; + dgc->irq_flags_to_clear =3D info->irq_flags_to_clear; + dgc->gc_flags =3D info->gc_flags; + dgc->exit =3D info->exit; d->gc =3D dgc; =20 /* Calc pointer to the first generic chip */ @@ -328,15 +323,22 @@ int __irq_alloc_domain_generic_chips(struct irq_domain = *d, int irqs_per_chip, for (i =3D 0; i < numchips; i++) { /* Store the pointer to the generic chip */ dgc->gc[i] =3D gc =3D tmp; - irq_init_generic_chip(gc, name, num_ct, i * irqs_per_chip, - NULL, handler); + irq_init_generic_chip(gc, info->name, info->num_ct, + i * dgc->irqs_per_chip, NULL, + info->handler); =20 gc->domain =3D d; - if (gcflags & IRQ_GC_BE_IO) { + if (dgc->gc_flags & IRQ_GC_BE_IO) { gc->reg_readl =3D &irq_readl_be; gc->reg_writel =3D &irq_writel_be; } =20 + if (info->init) { + ret =3D info->init(gc); + if (ret) + goto err; + } + raw_spin_lock_irqsave(&gc_lock, flags); list_add_tail(&gc->list, &gc_list); raw_spin_unlock_irqrestore(&gc_lock, flags); @@ -344,6 +346,69 @@ int __irq_alloc_domain_generic_chips(struct irq_domain *= d, int irqs_per_chip, tmp +=3D gc_sz; } return 0; + +err: + while (i--) { + if (dgc->exit) + dgc->exit(dgc->gc[i]); + irq_remove_generic_chip(dgc->gc[i], ~0U, 0, 0); + } + d->gc =3D NULL; + kfree(dgc); + return ret; +} +EXPORT_SYMBOL_GPL(irq_domain_alloc_generic_chips); + +/** + * irq_domain_remove_generic_chips - Remove generic chips from an irq domain + * @d: irq domain for which generic chips are to be removed + */ +void irq_domain_remove_generic_chips(struct irq_domain *d) +{ + struct irq_domain_chip_generic *dgc =3D d->gc; + unsigned int i; + + if (!dgc) + return; + + for (i =3D 0; i < dgc->num_chips; i++) { + if (dgc->exit) + dgc->exit(dgc->gc[i]); + irq_remove_generic_chip(dgc->gc[i], ~0U, 0, 0); + } + d->gc =3D NULL; + kfree(dgc); +} +EXPORT_SYMBOL_GPL(irq_domain_remove_generic_chips); + +/** + * __irq_alloc_domain_generic_chips - Allocate generic chips for an irq doma= in + * @d: irq domain for which to allocate chips + * @irqs_per_chip: Number of interrupts each chip handles (max 32) + * @num_ct: Number of irq_chip_type instances associated with this + * @name: Name of the irq chip + * @handler: Default flow handler associated with these chips + * @clr: IRQ_* bits to clear in the mapping function + * @set: IRQ_* bits to set in the mapping function + * @gcflags: Generic chip specific setup flags + */ +int __irq_alloc_domain_generic_chips(struct irq_domain *d, int irqs_per_chip, + int num_ct, const char *name, + irq_flow_handler_t handler, + unsigned int clr, unsigned int set, + enum irq_gc_flags gcflags) +{ + struct irq_domain_chip_generic_info info =3D { + .irqs_per_chip =3D irqs_per_chip, + .num_ct =3D num_ct, + .name =3D name, + .handler =3D handler, + .irq_flags_to_clear =3D clr, + .irq_flags_to_set =3D set, + .gc_flags =3D gcflags, + }; + + return irq_domain_alloc_generic_chips(d, &info); } EXPORT_SYMBOL_GPL(__irq_alloc_domain_generic_chips); =20 diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h index ed28059e9849..fe0272cd84a5 100644 --- a/kernel/irq/internals.h +++ b/kernel/irq/internals.h @@ -501,6 +501,16 @@ static inline struct irq_data *irqd_get_parent_data(stru= ct irq_data *irqd) #ifdef CONFIG_GENERIC_IRQ_DEBUGFS #include =20 +struct irq_bit_descr { + unsigned int mask; + char *name; +}; + +#define BIT_MASK_DESCR(m) { .mask =3D m, .name =3D #m } + +void irq_debug_show_bits(struct seq_file *m, int ind, unsigned int state, + const struct irq_bit_descr *sd, int size); + void irq_add_debugfs_entry(unsigned int irq, struct irq_desc *desc); static inline void irq_remove_debugfs_entry(struct irq_desc *desc) { diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index aadc8891cc16..cea8f6874b1f 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -111,6 +111,7 @@ EXPORT_SYMBOL_GPL(__irq_domain_alloc_fwnode); =20 /** * irq_domain_free_fwnode - Free a non-OF-backed fwnode_handle + * @fwnode: fwnode_handle to free * * Free a fwnode_handle allocated with irq_domain_alloc_fwnode. */ @@ -127,27 +128,12 @@ void irq_domain_free_fwnode(struct fwnode_handle *fwnod= e) } EXPORT_SYMBOL_GPL(irq_domain_free_fwnode); =20 -static struct irq_domain *__irq_domain_create(struct fwnode_handle *fwnode, - unsigned int size, - irq_hw_number_t hwirq_max, - int direct_max, - const struct irq_domain_ops *ops, - void *host_data) +static int irq_domain_set_name(struct irq_domain *domain, + const struct fwnode_handle *fwnode, + enum irq_domain_bus_token bus_token) { - struct irqchip_fwid *fwid; - struct irq_domain *domain; - static atomic_t unknown_domains; - - if (WARN_ON((size && direct_max) || - (!IS_ENABLED(CONFIG_IRQ_DOMAIN_NOMAP) && direct_max) || - (direct_max && (direct_max !=3D hwirq_max)))) - return NULL; - - domain =3D kzalloc_node(struct_size(domain, revmap, size), - GFP_KERNEL, of_node_to_nid(to_of_node(fwnode))); - if (!domain) - return NULL; + struct irqchip_fwid *fwid; =20 if (is_fwnode_irqchip(fwnode)) { fwid =3D container_of(fwnode, struct irqchip_fwid, fwnode); @@ -155,17 +141,23 @@ static struct irq_domain *__irq_domain_create(struct fw= node_handle *fwnode, switch (fwid->type) { case IRQCHIP_FWNODE_NAMED: case IRQCHIP_FWNODE_NAMED_ID: - domain->fwnode =3D fwnode; - domain->name =3D kstrdup(fwid->name, GFP_KERNEL); - if (!domain->name) { - kfree(domain); - return NULL; - } + domain->name =3D bus_token ? + kasprintf(GFP_KERNEL, "%s-%d", + fwid->name, bus_token) : + kstrdup(fwid->name, GFP_KERNEL); + if (!domain->name) + return -ENOMEM; domain->flags |=3D IRQ_DOMAIN_NAME_ALLOCATED; break; default: - domain->fwnode =3D fwnode; domain->name =3D fwid->name; + if (bus_token) { + domain->name =3D kasprintf(GFP_KERNEL, "%s-%d", + fwid->name, bus_token); + if (!domain->name) + return -ENOMEM; + domain->flags |=3D IRQ_DOMAIN_NAME_ALLOCATED; + } break; } } else if (is_of_node(fwnode) || is_acpi_device_node(fwnode) || @@ -177,42 +169,68 @@ static struct irq_domain *__irq_domain_create(struct fw= node_handle *fwnode, * unhappy about. Replace them with ':', which does * the trick and is not as offensive as '\'... */ - name =3D kasprintf(GFP_KERNEL, "%pfw", fwnode); - if (!name) { - kfree(domain); - return NULL; - } + name =3D bus_token ? + kasprintf(GFP_KERNEL, "%pfw-%d", fwnode, bus_token) : + kasprintf(GFP_KERNEL, "%pfw", fwnode); + if (!name) + return -ENOMEM; =20 domain->name =3D strreplace(name, '/', ':'); - domain->fwnode =3D fwnode; domain->flags |=3D IRQ_DOMAIN_NAME_ALLOCATED; } =20 if (!domain->name) { if (fwnode) pr_err("Invalid fwnode type for irqdomain\n"); - domain->name =3D kasprintf(GFP_KERNEL, "unknown-%d", - atomic_inc_return(&unknown_domains)); - if (!domain->name) { - kfree(domain); - return NULL; - } + domain->name =3D bus_token ? + kasprintf(GFP_KERNEL, "unknown-%d-%d", + atomic_inc_return(&unknown_domains), + bus_token) : + kasprintf(GFP_KERNEL, "unknown-%d", + atomic_inc_return(&unknown_domains)); + if (!domain->name) + return -ENOMEM; domain->flags |=3D IRQ_DOMAIN_NAME_ALLOCATED; } =20 - fwnode_handle_get(fwnode); - fwnode_dev_initialized(fwnode, true); + return 0; +} + +static struct irq_domain *__irq_domain_create(const struct irq_domain_info *= info) +{ + struct irq_domain *domain; + int err; + + if (WARN_ON((info->size && info->direct_max) || + (!IS_ENABLED(CONFIG_IRQ_DOMAIN_NOMAP) && info->direct_max) || + (info->direct_max && info->direct_max !=3D info->hwirq_max))) + return ERR_PTR(-EINVAL); + + domain =3D kzalloc_node(struct_size(domain, revmap, info->size), + GFP_KERNEL, of_node_to_nid(to_of_node(info->fwnode))); + if (!domain) + return ERR_PTR(-ENOMEM); + + err =3D irq_domain_set_name(domain, info->fwnode, info->bus_token); + if (err) { + kfree(domain); + return ERR_PTR(err); + } + + domain->fwnode =3D fwnode_handle_get(info->fwnode); + fwnode_dev_initialized(domain->fwnode, true); =20 /* Fill structure */ INIT_RADIX_TREE(&domain->revmap_tree, GFP_KERNEL); - domain->ops =3D ops; - domain->host_data =3D host_data; - domain->hwirq_max =3D hwirq_max; + domain->ops =3D info->ops; + domain->host_data =3D info->host_data; + domain->bus_token =3D info->bus_token; + domain->hwirq_max =3D info->hwirq_max; =20 - if (direct_max) + if (info->direct_max) domain->flags |=3D IRQ_DOMAIN_FLAG_NO_MAP; =20 - domain->revmap_size =3D size; + domain->revmap_size =3D info->size; =20 /* * Hierarchical domains use the domain lock of the root domain @@ -240,34 +258,64 @@ static void __irq_domain_publish(struct irq_domain *dom= ain) pr_debug("Added domain %s\n", domain->name); } =20 +static void irq_domain_free(struct irq_domain *domain) +{ + fwnode_dev_initialized(domain->fwnode, false); + fwnode_handle_put(domain->fwnode); + if (domain->flags & IRQ_DOMAIN_NAME_ALLOCATED) + kfree(domain->name); + kfree(domain); +} + /** - * __irq_domain_add() - Allocate a new irq_domain data structure - * @fwnode: firmware node for the interrupt controller - * @size: Size of linear map; 0 for radix mapping only - * @hwirq_max: Maximum number of interrupts supported by controller - * @direct_max: Maximum value of direct maps; Use ~0 for no limit; 0 for no - * direct mapping - * @ops: domain callbacks - * @host_data: Controller private data pointer + * irq_domain_instantiate() - Instantiate a new irq domain data structure + * @info: Domain information pointer pointing to the information for this do= main * - * Allocates and initializes an irq_domain structure. - * Returns pointer to IRQ domain, or NULL on failure. + * Return: A pointer to the instantiated irq domain or an ERR_PTR value. */ -struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, unsigned i= nt size, - irq_hw_number_t hwirq_max, int direct_max, - const struct irq_domain_ops *ops, - void *host_data) +struct irq_domain *irq_domain_instantiate(const struct irq_domain_info *info) { struct irq_domain *domain; + int err; + + domain =3D __irq_domain_create(info); + if (IS_ERR(domain)) + return domain; =20 - domain =3D __irq_domain_create(fwnode, size, hwirq_max, direct_max, - ops, host_data); - if (domain) - __irq_domain_publish(domain); + domain->flags |=3D info->domain_flags; + domain->exit =3D info->exit; + +#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY + if (info->parent) { + domain->root =3D info->parent->root; + domain->parent =3D info->parent; + } +#endif + + if (info->dgc_info) { + err =3D irq_domain_alloc_generic_chips(domain, info->dgc_info); + if (err) + goto err_domain_free; + } + + if (info->init) { + err =3D info->init(domain); + if (err) + goto err_domain_gc_remove; + } + + __irq_domain_publish(domain); =20 return domain; + +err_domain_gc_remove: + if (info->dgc_info) + irq_domain_remove_generic_chips(domain); +err_domain_free: + irq_domain_free(domain); + return ERR_PTR(err); } -EXPORT_SYMBOL_GPL(__irq_domain_add); +EXPORT_SYMBOL_GPL(irq_domain_instantiate); =20 /** * irq_domain_remove() - Remove an irq domain. @@ -279,6 +327,9 @@ EXPORT_SYMBOL_GPL(__irq_domain_add); */ void irq_domain_remove(struct irq_domain *domain) { + if (domain->exit) + domain->exit(domain); + mutex_lock(&irq_domain_mutex); debugfs_remove_domain_dir(domain); =20 @@ -294,13 +345,11 @@ void irq_domain_remove(struct irq_domain *domain) =20 mutex_unlock(&irq_domain_mutex); =20 - pr_debug("Removed domain %s\n", domain->name); + if (domain->flags & IRQ_DOMAIN_FLAG_DESTROY_GC) + irq_domain_remove_generic_chips(domain); =20 - fwnode_dev_initialized(domain->fwnode, false); - fwnode_handle_put(domain->fwnode); - if (domain->flags & IRQ_DOMAIN_NAME_ALLOCATED) - kfree(domain->name); - kfree(domain); + pr_debug("Removed domain %s\n", domain->name); + irq_domain_free(domain); } EXPORT_SYMBOL_GPL(irq_domain_remove); =20 @@ -360,10 +409,17 @@ struct irq_domain *irq_domain_create_simple(struct fwno= de_handle *fwnode, const struct irq_domain_ops *ops, void *host_data) { + struct irq_domain_info info =3D { + .fwnode =3D fwnode, + .size =3D size, + .hwirq_max =3D size, + .ops =3D ops, + .host_data =3D host_data, + }; struct irq_domain *domain; =20 - domain =3D __irq_domain_add(fwnode, size, size, 0, ops, host_data); - if (!domain) + domain =3D irq_domain_instantiate(&info); + if (IS_ERR(domain)) return NULL; =20 if (first_irq > 0) { @@ -416,11 +472,20 @@ struct irq_domain *irq_domain_create_legacy(struct fwno= de_handle *fwnode, const struct irq_domain_ops *ops, void *host_data) { + struct irq_domain_info info =3D { + .fwnode =3D fwnode, + .size =3D first_hwirq + size, + .hwirq_max =3D first_hwirq + size, + .ops =3D ops, + .host_data =3D host_data, + }; struct irq_domain *domain; =20 - domain =3D __irq_domain_add(fwnode, first_hwirq + size, first_hwirq + size,= 0, ops, host_data); - if (domain) - irq_domain_associate_many(domain, first_irq, first_hwirq, size); + domain =3D irq_domain_instantiate(&info); + if (IS_ERR(domain)) + return NULL; + + irq_domain_associate_many(domain, first_irq, first_hwirq, size); =20 return domain; } @@ -438,7 +503,8 @@ struct irq_domain *irq_find_matching_fwspec(struct irq_fw= spec *fwspec, struct fwnode_handle *fwnode =3D fwspec->fwnode; int rc; =20 - /* We might want to match the legacy controller last since + /* + * We might want to match the legacy controller last since * it might potentially be set to match all interrupts in * the absence of a device node. This isn't a problem so far * yet though... @@ -982,6 +1048,12 @@ EXPORT_SYMBOL_GPL(__irq_resolve_mapping); =20 /** * irq_domain_xlate_onecell() - Generic xlate for direct one cell bindings + * @d: Interrupt domain involved in the translation + * @ctrlr: The device tree node for the device whose interrupt is translated + * @intspec: The interrupt specifier data from the device tree + * @intsize: The number of entries in @intspec + * @out_hwirq: Pointer to storage for the hardware interrupt number + * @out_type: Pointer to storage for the interrupt type * * Device Tree IRQ specifier translation function which works with one cell * bindings where the cell value maps directly to the hwirq number. @@ -1000,6 +1072,12 @@ EXPORT_SYMBOL_GPL(irq_domain_xlate_onecell); =20 /** * irq_domain_xlate_twocell() - Generic xlate for direct two cell bindings + * @d: Interrupt domain involved in the translation + * @ctrlr: The device tree node for the device whose interrupt is translated + * @intspec: The interrupt specifier data from the device tree + * @intsize: The number of entries in @intspec + * @out_hwirq: Pointer to storage for the hardware interrupt number + * @out_type: Pointer to storage for the interrupt type * * Device Tree IRQ specifier translation function which works with two cell * bindings where the cell values map directly to the hwirq number @@ -1018,6 +1096,12 @@ EXPORT_SYMBOL_GPL(irq_domain_xlate_twocell); =20 /** * irq_domain_xlate_onetwocell() - Generic xlate for one or two cell bindings + * @d: Interrupt domain involved in the translation + * @ctrlr: The device tree node for the device whose interrupt is translated + * @intspec: The interrupt specifier data from the device tree + * @intsize: The number of entries in @intspec + * @out_hwirq: Pointer to storage for the hardware interrupt number + * @out_type: Pointer to storage for the interrupt type * * Device Tree IRQ specifier translation function which works with either one * or two cell bindings where the cell values map directly to the hwirq numb= er @@ -1051,6 +1135,10 @@ EXPORT_SYMBOL_GPL(irq_domain_simple_ops); /** * irq_domain_translate_onecell() - Generic translate for direct one cell * bindings + * @d: Interrupt domain involved in the translation + * @fwspec: The firmware interrupt specifier to translate + * @out_hwirq: Pointer to storage for the hardware interrupt number + * @out_type: Pointer to storage for the interrupt type */ int irq_domain_translate_onecell(struct irq_domain *d, struct irq_fwspec *fwspec, @@ -1068,6 +1156,10 @@ EXPORT_SYMBOL_GPL(irq_domain_translate_onecell); /** * irq_domain_translate_twocell() - Generic translate for direct two cell * bindings + * @d: Interrupt domain involved in the translation + * @fwspec: The firmware interrupt specifier to translate + * @out_hwirq: Pointer to storage for the hardware interrupt number + * @out_type: Pointer to storage for the interrupt type * * Device Tree IRQ specifier translation function which works with two cell * bindings where the cell values map directly to the hwirq number @@ -1144,23 +1236,22 @@ struct irq_domain *irq_domain_create_hierarchy(struct= irq_domain *parent, const struct irq_domain_ops *ops, void *host_data) { - struct irq_domain *domain; - - if (size) - domain =3D __irq_domain_create(fwnode, size, size, 0, ops, host_data); - else - domain =3D __irq_domain_create(fwnode, 0, ~0, 0, ops, host_data); - - if (domain) { - if (parent) - domain->root =3D parent->root; - domain->parent =3D parent; - domain->flags |=3D flags; + struct irq_domain_info info =3D { + .fwnode =3D fwnode, + .size =3D size, + .hwirq_max =3D size, + .ops =3D ops, + .host_data =3D host_data, + .domain_flags =3D flags, + .parent =3D parent, + }; + struct irq_domain *d; =20 - __irq_domain_publish(domain); - } + if (!info.size) + info.hwirq_max =3D ~0U; =20 - return domain; + d =3D irq_domain_instantiate(&info); + return IS_ERR(d) ? NULL : d; } EXPORT_SYMBOL_GPL(irq_domain_create_hierarchy); =20 @@ -1932,13 +2023,26 @@ static void irq_domain_free_one_irq(struct irq_domain= *domain, unsigned int virq =20 static struct dentry *domain_dir; =20 -static void -irq_domain_debug_show_one(struct seq_file *m, struct irq_domain *d, int ind) +static const struct irq_bit_descr irqdomain_flags[] =3D { + BIT_MASK_DESCR(IRQ_DOMAIN_FLAG_HIERARCHY), + BIT_MASK_DESCR(IRQ_DOMAIN_NAME_ALLOCATED), + BIT_MASK_DESCR(IRQ_DOMAIN_FLAG_IPI_PER_CPU), + BIT_MASK_DESCR(IRQ_DOMAIN_FLAG_IPI_SINGLE), + BIT_MASK_DESCR(IRQ_DOMAIN_FLAG_MSI), + BIT_MASK_DESCR(IRQ_DOMAIN_FLAG_ISOLATED_MSI), + BIT_MASK_DESCR(IRQ_DOMAIN_FLAG_NO_MAP), + BIT_MASK_DESCR(IRQ_DOMAIN_FLAG_MSI_PARENT), + BIT_MASK_DESCR(IRQ_DOMAIN_FLAG_MSI_DEVICE), + BIT_MASK_DESCR(IRQ_DOMAIN_FLAG_NONCORE), +}; + +static void irq_domain_debug_show_one(struct seq_file *m, struct irq_domain = *d, int ind) { seq_printf(m, "%*sname: %s\n", ind, "", d->name); seq_printf(m, "%*ssize: %u\n", ind + 1, "", d->revmap_size); seq_printf(m, "%*smapped: %u\n", ind + 1, "", d->mapcount); seq_printf(m, "%*sflags: 0x%08x\n", ind +1 , "", d->flags); + irq_debug_show_bits(m, ind, d->flags, irqdomain_flags, ARRAY_SIZE(irqdomain= _flags)); if (d->ops && d->ops->debug_show) d->ops->debug_show(m, d, NULL, ind + 1); #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c index 2024f89baea4..5fa0547ece0c 100644 --- a/kernel/irq/msi.c +++ b/kernel/irq/msi.c @@ -8,17 +8,33 @@ * This file contains common code to support Message Signaled Interrupts for * PCI compatible and non PCI compatible devices. */ -#include #include #include #include #include +#include +#include #include #include -#include +#include +#include =20 #include "internals.h" =20 +/** + * struct msi_device_data - MSI per device data + * @properties: MSI properties which are interesting to drivers + * @mutex: Mutex protecting the MSI descriptor store + * @__domains: Internal data for per device MSI domains + * @__iter_idx: Index to search the next entry for iterators + */ +struct msi_device_data { + unsigned long properties; + struct mutex mutex; + struct msi_dev_domain __domains[MSI_MAX_DEVICE_IRQDOMAINS]; + unsigned long __iter_idx; +}; + /** * struct msi_ctrl - MSI internal management control structure * @domid: ID of the domain on which management operations should be done @@ -1088,8 +1104,8 @@ bool msi_match_device_irq_domain(struct device *dev, un= signed int domid, return ret; } =20 -int msi_domain_prepare_irqs(struct irq_domain *domain, struct device *dev, - int nvec, msi_alloc_info_t *arg) +static int msi_domain_prepare_irqs(struct irq_domain *domain, struct device = *dev, + int nvec, msi_alloc_info_t *arg) { struct msi_domain_info *info =3D domain->host_data; struct msi_domain_ops *ops =3D info->ops; @@ -1097,77 +1113,6 @@ int msi_domain_prepare_irqs(struct irq_domain *domain,= struct device *dev, return ops->msi_prepare(domain, dev, nvec, arg); } =20 -int msi_domain_populate_irqs(struct irq_domain *domain, struct device *dev, - int virq_base, int nvec, msi_alloc_info_t *arg) -{ - struct msi_domain_info *info =3D domain->host_data; - struct msi_domain_ops *ops =3D info->ops; - struct msi_ctrl ctrl =3D { - .domid =3D MSI_DEFAULT_DOMAIN, - .first =3D virq_base, - .last =3D virq_base + nvec - 1, - }; - struct msi_desc *desc; - struct xarray *xa; - int ret, virq; - - msi_lock_descs(dev); - - if (!msi_ctrl_valid(dev, &ctrl)) { - ret =3D -EINVAL; - goto unlock; - } - - ret =3D msi_domain_add_simple_msi_descs(dev, &ctrl); - if (ret) - goto unlock; - - xa =3D &dev->msi.data->__domains[ctrl.domid].store; - - for (virq =3D virq_base; virq < virq_base + nvec; virq++) { - desc =3D xa_load(xa, virq); - desc->irq =3D virq; - - ops->set_desc(arg, desc); - ret =3D irq_domain_alloc_irqs_hierarchy(domain, virq, 1, arg); - if (ret) - goto fail; - - irq_set_msi_desc(virq, desc); - } - msi_unlock_descs(dev); - return 0; - -fail: - for (--virq; virq >=3D virq_base; virq--) { - msi_domain_depopulate_descs(dev, virq, 1); - irq_domain_free_irqs_common(domain, virq, 1); - } - msi_domain_free_descs(dev, &ctrl); -unlock: - msi_unlock_descs(dev); - return ret; -} - -void msi_domain_depopulate_descs(struct device *dev, int virq_base, int nvec) -{ - struct msi_ctrl ctrl =3D { - .domid =3D MSI_DEFAULT_DOMAIN, - .first =3D virq_base, - .last =3D virq_base + nvec - 1, - }; - struct msi_desc *desc; - struct xarray *xa; - unsigned long idx; - - if (!msi_ctrl_valid(dev, &ctrl)) - return; - - xa =3D &dev->msi.data->__domains[ctrl.domid].store; - xa_for_each_range(xa, idx, desc, ctrl.first, ctrl.last) - desc->irq =3D 0; -} - /* * Carefully check whether the device can use reservation mode. If * reservation mode is enabled then the early activation will assign a diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c index 5c320c3f10a7..8cccdf40725a 100644 --- a/kernel/irq/proc.c +++ b/kernel/irq/proc.c @@ -461,10 +461,10 @@ int show_interrupts(struct seq_file *p, void *v) { static int prec; =20 - unsigned long flags, any_count =3D 0; int i =3D *(loff_t *) v, j; struct irqaction *action; struct irq_desc *desc; + unsigned long flags; =20 if (i > ACTUAL_NR_IRQS) return 0; @@ -488,10 +488,7 @@ int show_interrupts(struct seq_file *p, void *v) if (!desc || irq_settings_is_hidden(desc)) goto outsparse; =20 - if (desc->kstat_irqs) - any_count =3D kstat_irqs_desc(desc, cpu_online_mask); - - if ((!desc->action || irq_desc_is_chained(desc)) && !any_count) + if (!desc->action || irq_desc_is_chained(desc) || !desc->kstat_irqs) goto outsparse; =20 seq_printf(p, "%*d: ", prec, i); .