get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/1.2/patches/2232895/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 2232895,
    "url": "http://patchwork.ozlabs.org/api/1.2/patches/2232895/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/linux-ide/patch/20260505100523.1922388-11-vladimir.oltean@nxp.com/",
    "project": {
        "id": 13,
        "url": "http://patchwork.ozlabs.org/api/1.2/projects/13/?format=api",
        "name": "Linux IDE development",
        "link_name": "linux-ide",
        "list_id": "linux-ide.vger.kernel.org",
        "list_email": "linux-ide@vger.kernel.org",
        "web_url": null,
        "scm_url": null,
        "webscm_url": null,
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<20260505100523.1922388-11-vladimir.oltean@nxp.com>",
    "list_archive_url": null,
    "date": "2026-05-05T10:05:02",
    "name": "[v8,phy-next,10/31] scsi: ufs: exynos: use dedicated API for updating PHY bus width",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "a4722dbc7bdd28e62acc31110a082d8a68c6c8a4",
    "submitter": {
        "id": 75582,
        "url": "http://patchwork.ozlabs.org/api/1.2/people/75582/?format=api",
        "name": "Vladimir Oltean",
        "email": "vladimir.oltean@nxp.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/linux-ide/patch/20260505100523.1922388-11-vladimir.oltean@nxp.com/mbox/",
    "series": [
        {
            "id": 502804,
            "url": "http://patchwork.ozlabs.org/api/1.2/series/502804/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/linux-ide/list/?series=502804",
            "date": "2026-05-05T10:04:53",
            "name": "Split Generic PHY consumer and provider API",
            "version": 8,
            "mbox": "http://patchwork.ozlabs.org/series/502804/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2232895/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2232895/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "\n <linux-ide+bounces-5644-incoming=patchwork.ozlabs.org@vger.kernel.org>",
        "X-Original-To": [
            "incoming@patchwork.ozlabs.org",
            "linux-ide@vger.kernel.org"
        ],
        "Delivered-To": "patchwork-incoming@legolas.ozlabs.org",
        "Authentication-Results": [
            "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=nxp.com header.i=@nxp.com header.a=rsa-sha256\n header.s=selector1 header.b=Xy81EUke;\n\tdkim-atps=neutral",
            "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=172.105.105.114; helo=tor.lore.kernel.org;\n envelope-from=linux-ide+bounces-5644-incoming=patchwork.ozlabs.org@vger.kernel.org;\n receiver=patchwork.ozlabs.org)",
            "smtp.subspace.kernel.org;\n\tdkim=pass (2048-bit key) header.d=nxp.com header.i=@nxp.com\n header.b=\"Xy81EUke\"",
            "smtp.subspace.kernel.org;\n arc=fail smtp.client-ip=52.101.72.37",
            "smtp.subspace.kernel.org;\n dmarc=pass (p=none dis=none) header.from=nxp.com",
            "smtp.subspace.kernel.org;\n spf=pass smtp.mailfrom=nxp.com",
            "dkim=none (message not signed)\n header.d=none;dmarc=none action=none header.from=nxp.com;"
        ],
        "Received": [
            "from tor.lore.kernel.org (tor.lore.kernel.org [172.105.105.114])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g8vnX4Zmyz1yJV\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 05 May 2026 20:26:40 +1000 (AEST)",
            "from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby tor.lore.kernel.org (Postfix) with ESMTP id E826B309A1E7\n\tfor <incoming@patchwork.ozlabs.org>; Tue,  5 May 2026 10:10:51 +0000 (UTC)",
            "from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id AFB2533A9EB;\n\tTue,  5 May 2026 10:06:08 +0000 (UTC)",
            "from AM0PR02CU008.outbound.protection.outlook.com\n (mail-westeuropeazon11013037.outbound.protection.outlook.com [52.101.72.37])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby smtp.subspace.kernel.org (Postfix) with ESMTPS id 60F693F23B7;\n\tTue,  5 May 2026 10:06:04 +0000 (UTC)",
            "from AM9PR04MB8585.eurprd04.prod.outlook.com (2603:10a6:20b:438::13)\n by DB9PR04MB8363.eurprd04.prod.outlook.com (2603:10a6:10:24b::11) with\n Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9846.26; Tue, 5 May\n 2026 10:05:56 +0000",
            "from AM9PR04MB8585.eurprd04.prod.outlook.com\n ([fe80::f010:fca8:7ef:62f4]) by AM9PR04MB8585.eurprd04.prod.outlook.com\n ([fe80::f010:fca8:7ef:62f4%4]) with mapi id 15.20.9870.023; Tue, 5 May 2026\n 10:05:56 +0000"
        ],
        "ARC-Seal": [
            "i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1777975567; cv=fail;\n b=qPBjR7M1vRM4VV8hP/aeEN1ij6aWKAyto2BGN1RHRjYjrzTsLeJ/UCyrx/tuH5pWktENMtJATgarmWo7DafvRPyuhvp/sPBQCggh4Zwx6QhJ1NElacUw8RlNqpHqOdOF9kXxrUOtq7e6ovUGNZWBZ4hpUFefdkJtHqsNCYE6QmE=",
            "i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none;\n b=e94PMQYPhHi00IMVT8SMEYyIeRGLLKf0R+ujgE66F60vU64z0z/OYyQqWQARUu0iFT5tiPewLXVlGGUdck6PkvNx0oCd1CiQ235xTVHe2ixRAKpUUkTHgU2ZfuDVDgNzPVzDP13+Nq/i+hVs+8XrSzV9g0u0RhpTpx/Bu8kxETTI+zvkAHElOrMwVY4HBiprBw0aEgm+mjDOm4r2C33RBOIgxN53XSg6uQkGs7jwZtXf4zjH2wIOcxaJvPimghZQyCOWUw/UWbTxDhqdgDG/lOrgCP6k+pBXoNB7M4KN5UKW93ONuqVyoMpYov30aE/SGt9DuugEhP4OZR+OhHjhdA=="
        ],
        "ARC-Message-Signature": [
            "i=2; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1777975567; c=relaxed/simple;\n\tbh=EuyYu4j2h/hs45g8aUk91fBW985c0hIc40GVq60dTfg=;\n\th=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References:\n\t Content-Type:MIME-Version;\n b=fntv9mFE0dh7FusiFYvctQf3t3yw6EQtTWjmQtjrRmlztctZBcomDgM+yKUFcBQGhSOnHaavlNGTPdJmF5g/tBLIvhOcriHQlcH2rkhrFswd4Hr82eBP0VsLVEtj+zMyTkMvzOJSxyw7kcDR16qlbxxaDP5mU8lwQZf1Jr7txgU=",
            "i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com;\n s=arcselector10001;\n h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1;\n bh=cSRCaU/T/RHpwudJD39b132C2AOlZdafTfBCJ5GHb7o=;\n b=LIYJwy/2D8Rwm9OnL7+oFsyMbrMNLEuc3Q1Xv5dy0ZC3nbd+tKfVUM1pyqxOs3p+Cn1wZNqjZuj7t99JP5gc0XIJL7vTBpTA8et9Q8kCGyvOgofPILD/bhS/JRp/V3vpIOX7WocUwgMeB8NcljH1wZeOqSXNBbMNLzeqLuRSNS5wzoYfD90ECmB8ZDLJinz3EOlwckm3eY8bxVSgDZfLjLMVzPSyAd+VHFMlp/p6XakbjyV65s70R352y9A73sQccl+IRw4frJVvUL1dZeUe0soNDvXb/LNVSzHAn1/ikn3L6Lg00lH7SSHsl2pk9GNMQ8oyw1CFdCupQ875JMVg5A=="
        ],
        "ARC-Authentication-Results": [
            "i=2; smtp.subspace.kernel.org;\n dmarc=pass (p=none dis=none) header.from=nxp.com;\n spf=pass smtp.mailfrom=nxp.com;\n dkim=pass (2048-bit key) header.d=nxp.com header.i=@nxp.com\n header.b=Xy81EUke; arc=fail smtp.client-ip=52.101.72.37",
            "i=1; mx.microsoft.com 1; spf=pass\n smtp.mailfrom=nxp.com; dmarc=pass action=none header.from=nxp.com; dkim=pass\n header.d=nxp.com; arc=none"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=nxp.com; s=selector1;\n h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;\n bh=cSRCaU/T/RHpwudJD39b132C2AOlZdafTfBCJ5GHb7o=;\n b=Xy81EUkea+ev6aXZQ3kig6eB6QFfeaxFmYMADmQLIjKEaJtc6GTk9XBnM5ntLJfQdUfHVdGJn8EPguqszt2SPuc2jfexfSwRgKBX0BDkzjXuA/tmF2l6WLZ1FayHqVL1HXLl2daM5N9k2CV8R51JmkwiBJer45tnpw67gpZUci3SJaNVVZrRFx43QrOzV8xzNJOBwZOM4GZ04GfIG8QPbhZVdK+HlMW3MWOB4SMOP+YGw9cWQFVfD80lNCX7nIodUWal8ri2U/9zVM7q7PqapBGz8x/WCLjDu8FPBOJ6hDxp1xc/qBDrWF3LVrjWbb49bu/EvKA8MY/rZ6Qnc6qLxg==",
        "From": "Vladimir Oltean <vladimir.oltean@nxp.com>",
        "To": "linux-phy@lists.infradead.org",
        "Cc": "Vinod Koul <vkoul@kernel.org>,\n\tNeil Armstrong <neil.armstrong@linaro.org>,\n\tdri-devel@lists.freedesktop.org,\n\tfreedreno@lists.freedesktop.org,\n\tlinux-arm-kernel@lists.infradead.org,\n\tlinux-arm-msm@vger.kernel.org,\n\tlinux-can@vger.kernel.org,\n\tlinux-gpio@vger.kernel.org,\n\tlinux-ide@vger.kernel.org,\n\tlinux-kernel@vger.kernel.org,\n\tlinux-media@vger.kernel.org,\n\tlinux-pci@vger.kernel.org,\n\tlinux-renesas-soc@vger.kernel.org,\n\tlinux-riscv@lists.infradead.org,\n\tlinux-rockchip@lists.infradead.org,\n\tlinux-samsung-soc@vger.kernel.org,\n\tlinux-scsi@vger.kernel.org,\n\tlinux-sunxi@lists.linux.dev,\n\tlinux-tegra@vger.kernel.org,\n\tlinux-usb@vger.kernel.org,\n\tnetdev@vger.kernel.org,\n\tspacemit@lists.linux.dev,\n\tUNGLinuxDriver@microchip.com,\n\tAlim Akhtar <alim.akhtar@samsung.com>,\n\tBart Van Assche <bvanassche@acm.org>,\n\tPeter Griffin <peter.griffin@linaro.org>,\n\t\"James E.J. Bottomley\" <James.Bottomley@HansenPartnership.com>,\n\t\"Martin K. Petersen\" <martin.petersen@oracle.com>,\n\tKrzysztof Kozlowski <krzk@kernel.org>,\n\tChanho Park <chanho61.park@samsung.com>",
        "Subject": "[PATCH v8 phy-next 10/31] scsi: ufs: exynos: use dedicated API for\n updating PHY bus width",
        "Date": "Tue,  5 May 2026 13:05:02 +0300",
        "Message-Id": "<20260505100523.1922388-11-vladimir.oltean@nxp.com>",
        "X-Mailer": "git-send-email 2.34.1",
        "In-Reply-To": "<20260505100523.1922388-1-vladimir.oltean@nxp.com>",
        "References": "<20260505100523.1922388-1-vladimir.oltean@nxp.com>",
        "Content-Transfer-Encoding": "8bit",
        "Content-Type": "text/plain",
        "X-ClientProxiedBy": "FR4P281CA0226.DEUP281.PROD.OUTLOOK.COM\n (2603:10a6:d10:e9::14) To AM9PR04MB8585.eurprd04.prod.outlook.com\n (2603:10a6:20b:438::13)",
        "Precedence": "bulk",
        "X-Mailing-List": "linux-ide@vger.kernel.org",
        "List-Id": "<linux-ide.vger.kernel.org>",
        "List-Subscribe": "<mailto:linux-ide+subscribe@vger.kernel.org>",
        "List-Unsubscribe": "<mailto:linux-ide+unsubscribe@vger.kernel.org>",
        "MIME-Version": "1.0",
        "X-MS-PublicTrafficType": "Email",
        "X-MS-TrafficTypeDiagnostic": "AM9PR04MB8585:EE_|DB9PR04MB8363:EE_",
        "X-MS-Office365-Filtering-Correlation-Id": "0fd1a2e4-5c9c-47ea-1f93-08deaa8de615",
        "X-LD-Processed": "686ea1d3-bc2b-4c6f-a92c-d99c5c301635,ExtAddr",
        "X-MS-Exchange-SenderADCheck": "1",
        "X-MS-Exchange-AntiSpam-Relay": "0",
        "X-Microsoft-Antispam": "\n BCL:0;ARA:13230040|376014|1800799024|19092799006|7416014|366016|22082099003|18002099003|56012099003;",
        "X-Microsoft-Antispam-Message-Info": "\n y5JvMxunJ8txVoYYgW9oeeWpwH6jTW79Ae2Z5uOaRb5SrixMXaD46A9tSMCzq9pnDUpnAw5AT4izCzbeQ5xZjFhcKBNu8x93aWGNqBljCFErsZYg2cquL44XgemR7r7JAGIAEe9cLc8uYLnedSDJL9xqqMXxrTqcXSEsG4vreNuMSp263nrwSxSXeeKldLK6hvskq7zQS8YZ8Nlq98L+fUUXE0rmxcESRRXzWYCfxeTbQkaE7KD57a/aMFyLK7PuhM6TvZmmFRl+WOv5YN71tXprg1USh3qw2cJZUQwQj9/cMohqmuqsc0k8/MBZrn9qvHWnSOqOB/wnlc/lpiL6UaxjYDhHWOegVco6p8IS72ekDVEOgiye4vAYoo5JB4IU13DleGqSdhk1t/c6o839ztu5VZXhu4Z+dpWou5+EVcJ0LAEtmTEq/+4Q303Ea/Hda3z+5AtRiXB6RPKz8V5lA6UrHEhI6FY2xEYmYQJeknY7ngDW8cG0Bfx5j+OycPgJzBwOFjHIq80yZmi23/C5uoj1R73XYzGOhVi9h3zPzacJmbAcwLINTNwtJzQTHs1LeWWEC1A+5Rus92su0l4QWoM7IVa0Oo0bb/kzQJxVXoWyIDoNCJNq6ek9TFaoeQwVBWkmOsH0HzjVFJhRegcKGA==",
        "X-Forefront-Antispam-Report": "\n CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:AM9PR04MB8585.eurprd04.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230040)(376014)(1800799024)(19092799006)(7416014)(366016)(22082099003)(18002099003)(56012099003);DIR:OUT;SFP:1101;",
        "X-MS-Exchange-AntiSpam-MessageData-ChunkCount": "1",
        "X-MS-Exchange-AntiSpam-MessageData-0": "\n Xa2B1pH6ppdSVcK+2eNSe06fW/myPWKtK9mJyaLNQwcTr7cRhUrVs7BhPoFMYpKbg6MqNAuBgqLUQTaLFUG7QY/cfBwZhBy1/7OfORZMq8EK8s6WPooSpK/sK8YnHj95aYPPg5mfYzlvT/+hiTO/1w2m18woZhOUKZ9SLy8qCQQyKR7ZHhQ8FUW3GU4UcqvcNFKNofrKyri+xEXboMt1e/MAy1MkYnTdhSxx4KX/HUDLs050V6CnuHr8y+etpOSEF0IkDsOpMf07bnw44Vvd+af4hVl6wB34AMPK71ZARx35fdFQYV5m3KUcCKz7S3bqynrfqWRMCMWxhL9JbtkxLpZHLBuGDQeJokVnABRJNqSwImQPwK3XaRuRAN11b/K2fEsaOvZUUnYLmIW580ZkjWNJWdROkd/kcL6ChTDjoqtbOoqokW7iyaX0C4LO8bkxZnSmBHXJ3l5HHUnIcPr82k3Coaq1agAq+dJ8LK4mtNEUxpHhgRvkm9t/W7o7Ks57k7gx3CQvN4ldCt5pgoMTiDif1FrmKq7Gj9jMM8aWgLU4jpnY+5A5P/aT8V4Er9vaV1lHgr/poZ8SWqME5MvKV7VtJrBrqRz74TPunkTPUUvQlo2ZCoLtdBlca+Oh6wT2Ic/XNbO4TdZUoXGHHvwTqNCLvsAIjdXNw/sg5INGtEC9fovnhXxU978prHMdD5uSDP335XSyhnAMWCp3is5FTRGjZvv5mmCAa4LqZqh9vsN9O7qxWzUw7RbUFxdW1VklW+v4DTAsvg1BJhabrMJ+8z4YTjOlfX1OWNU6cfDBf1aMHNE1WiyP1zjJKM8AZ4r7PAAkq2zuda+2pTMmt6LN3goE3/gxcAD6USMesh2K0K/wJimysca8XRENBHCZRg7OimTFMh+m8kzOqwffYWb6j3eGD3XKgQMqGmBD3yPvbb3Z+63/JZMuc2O4l9oQOmhIPxnEHtBaG7c6PEH/hM2JxDxS1ZSH6wCsR52iyEUfNBUxcZBXmreNpjswcO0tx3opTl2I5Rb9+z0HYOTw0YPIZmcwbJcifEMLBPeP3FSkcj3cW7b9HRkc9cqRz5AUCgTcWnI9+MfIKsy2ZMMHTENwEYrOlI9LUIH7CeiO+ItE+X2Xbu/fmPrk2gNY3wDj/Uav8XgrmTKDrFG/kGcoX50kF0BRA9OxOqNbnnPyqVWUMM/HPrOEJKcm4RZvpVcSCmZV9POyKHCNBmv8opktrCWF+V0wT9e8coFFokeZTYFiNVkQDB2xL7Pt69zlRb5KywkJ2pRHEPGttZ2XYHFQWf0Be6TrOddpNC7NZ7rN6i13ONd0hVMbkVAKByLCC12h3ODNbINsz5yU4y4CoolWWk+i8xlO36oN8hGlcaGGtHMiHMP9gTCKZcWEVY2nCW/0pRbe91y6J+qCYJ1DCj0fUAGsQNECSE1JlDUVZmi4RO5xtQDf1eHSjgN7FDlM/UD+MqfTsqtGwIQMrv8rj3WLDHEBuLCCToyjoVbQ3+5047pXZGJLkMvuI5iHzLLXuJ30im6Vq3trBj6YQ/H2wXOjnYfJVUfbNBVxtpeXARGKs1cCdsng/hLIqMLgjXTvxB4gZXU+co8AySSZbbtU5LEZ69Cbice4ldLssTU0wuyim80sM3tano4qnU4ljFtemuplp+4LeCyzyqFaeuMQ0gKuQhYq/ruvW/hUxsEdfCTLjqbt3VTXYggYtARNu34rNYvBTu7q6KwkaqhnKiIf0vPMRbVgTw==",
        "X-OriginatorOrg": "nxp.com",
        "X-MS-Exchange-CrossTenant-Network-Message-Id": "\n 0fd1a2e4-5c9c-47ea-1f93-08deaa8de615",
        "X-MS-Exchange-CrossTenant-AuthSource": "AM9PR04MB8585.eurprd04.prod.outlook.com",
        "X-MS-Exchange-CrossTenant-AuthAs": "Internal",
        "X-MS-Exchange-CrossTenant-OriginalArrivalTime": "05 May 2026 10:05:56.4082\n (UTC)",
        "X-MS-Exchange-CrossTenant-FromEntityHeader": "Hosted",
        "X-MS-Exchange-CrossTenant-Id": "686ea1d3-bc2b-4c6f-a92c-d99c5c301635",
        "X-MS-Exchange-CrossTenant-MailboxType": "HOSTED",
        "X-MS-Exchange-CrossTenant-UserPrincipalName": "\n vkHMvoPaohs5q6ZoRq9I17MSTz7EWznPzirXt/mWLGmuVGAtG/9Eki37GOga3Oh8t0r0/b5J4UCl3o0Q8xy72A==",
        "X-MS-Exchange-Transport-CrossTenantHeadersStamped": "DB9PR04MB8363"
    },
    "content": "I am trying to get rid of code instances where PHY consumers (like the\nExynos UFS HCD) poke inside struct phy fields, in order to further turn\nstruct phy into an opaque data structure.\n\nThe ufs-exynos.c driver interacts with phy-samsung-ufs.c in order to\npower it on and to update the lane count. For the later purpose, it\n(ab)uses phy_set_bus_width().\n\nThe phy_set_bus_width() function is a PHY provider function, not a\nconsumer one, and I am calling its use from ufs-exynos.c an abuse\nbecause\n(1) commit 8feed347d33b (\"phy: add phy_get_bus_width()/phy_set_bus_width()\n    calls\") clearly states the intended use.\n(2) phy_set_bus_width() only alters phy->attrs.bus_width, and does not\n    call into phy_ops at all. So a consumer that makes a call to\n    phy_set_bus_width() can not possibly produce any hardware change in\n    the provider at all.\n\nThis is where the Exynos UFS HCD driver decided to be creative and\nhijacked phy_init() to pick up the change of the bus_width attribute.\n\nThis requires a very careful dance where the PHY consumer needs to\nsimultaneously juggle multiple requirements:\n- the UFS PHY needs to pick up the updated lane count in its\n  samsung_ufs_phy_init() handler for the phy_init() call\n- phy_init() calls need to be balanced with phy_exit(), otherwise\n  subsequent phy_init() calls don't make it into samsung_ufs_phy_init()\n  and just leave the PHY with an elevated init_count\n- phy_power_on() can't be called without phy_init()\n\nThe difficulty to observe all requirements is why the following bug fix\ncommits exist:\n3d73b200f989 (\"scsi: ufs: ufs-exynos: Change ufs phy control sequence\")\n7f05fd9a3b6f (\"scsi: ufs: exynos: Ensure consistent phy reference counts\")\n\nCurrently the UFS HCD driver tries to keep the PHY init_count and\npower_count in tight lockstep, but even this is error-prone. For\nexample, if exynos_ufs_suspend() runs and then exynos_ufs_exit(),\nthe PHY power_count will underflow.\n\nIf we address the root issue first (phy_init() abused to pick up new\nlane count) by introducing a new PHY consumer method which actually does\ncall into the PHY provider driver, then we are able to absorb the entire\nUFS HCD dance and update the lane count without altering the PHY\ninit_count or power_count.\n\nThis allows more consumer flexibility to call phy_init() from other\nplaces, and same goes for phy_power_on().\n\nIt is common practice to call phy_init() only once, right after\nphy_get(), and doing so will naturally balance it with phy_exit().\n\nWe can also leave the phy_power_on() call to be on demand, placed inside\nexynos_ufs_pre_link(). But the UFS core (specifically ufshcd_link_startup())\nmay call the variant operation exynos_ufs_pre_link() -> exynos_ufs_phy_init()\nmultiple times if the link startup fails and needs to be retried.\n\nFor this reason we need a consumer-specific \"bool phy_powered_on\" which\nensures that we call phy_power_on() at most once, and that\nexynos_ufs_exit() only calls phy_power_off() if phy_power_on() was\npreviously called. Using the phy->power_count for this purpose is\nundesirable because it is going away, and the PHY API is not offering a\nhelper for it (would be a foot gun, because multiple consumers of the\nsame provider shouldn't interfere with each other; each should only undo\nthe effects of what it did itself)\n\nInside the new samsung_ufs_phy_request_bus_width(), I've sanity checked\nthat the bus width is either 1 or 2 lanes. This coincides with\nsamsung_ufs_phy_config() which only configures LANE_0 and LANE_1.\n\nSigned-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>\n---\nCc: Alim Akhtar <alim.akhtar@samsung.com>\nCc: Bart Van Assche <bvanassche@acm.org>\nCc: Peter Griffin <peter.griffin@linaro.org>\nCc: \"James E.J. Bottomley\" <James.Bottomley@HansenPartnership.com>\nCc: \"Martin K. Petersen\" <martin.petersen@oracle.com>\nCc: Krzysztof Kozlowski <krzk@kernel.org>\nCc: Chanho Park <chanho61.park@samsung.com>\n\nv7->v8:\n- rewrote commit after Sashiko pointed out the new handling is still\n  not correct:\n  https://sashiko.dev/#/patchset/20260430110652.558622-1-vladimir.oltean@nxp.com\n- removed Reviewed-by, Tested-by and Acked-by tags from Alim, Bart and\n  Peter\nv6->v7: collect tags from Martin and Peter\nv5->v6: collect tags from Alim Akhtar\nv4->v5: collect tag, add \"scsi: \" prefix to commit title\nv3->v4: none\nv2->v3:\n- add Cc Chanho Park, author of commit 3d73b200f989 (\"scsi: ufs:\n  ufs-exynos: Change ufs phy control sequence\")\nv1->v2:\n- add better ufs->phy_powered_on handling in exynos_ufs_exit(),\n  exynos_ufs_suspend() and exynos_ufs_resume() which ensures we won't\n  enter a phy->power_count underrun condition\n---\n drivers/phy/phy-core.c                |  35 ++++++++\n drivers/phy/samsung/phy-samsung-ufs.c |  27 +++++-\n drivers/ufs/host/ufs-exynos.c         | 114 ++++++++++++++++++--------\n drivers/ufs/host/ufs-exynos.h         |   1 +\n include/linux/phy/phy.h               |  11 +++\n 5 files changed, 151 insertions(+), 37 deletions(-)",
    "diff": "diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c\nindex 21aaf2f76e53..634ac07fd1f3 100644\n--- a/drivers/phy/phy-core.c\n+++ b/drivers/phy/phy-core.c\n@@ -606,6 +606,41 @@ int phy_validate(struct phy *phy, enum phy_mode mode, int submode,\n }\n EXPORT_SYMBOL_GPL(phy_validate);\n \n+/**\n+ * phy_request_bus_width() - request PHY to change its bus width\n+ * @phy: the phy returned by phy_get()\n+ * @bus_width: new bus width\n+ *\n+ * Consumers can use this method to request the PHY to update itself to a new\n+ * bus width (typically meaning lane count). Can be called from any init state\n+ * and power state. PHY is expected to use the new lane count as soon as this\n+ * method returns.\n+ *\n+ * Returns: 0 if successful or if operating on an optional and absent PHY,\n+ *\t-EOPNOTSUPP if the operation is not implemented, -EINVAL if the\n+ *\trequested bus width is not supported, other negative error codes for\n+ *\tdriver-specific failures.\n+ */\n+int phy_request_bus_width(struct phy *phy, int bus_width)\n+{\n+\tint ret;\n+\n+\tif (!phy)\n+\t\treturn 0;\n+\n+\tif (!phy->ops->request_bus_width)\n+\t\treturn -EOPNOTSUPP;\n+\n+\tmutex_lock(&phy->mutex);\n+\tret = phy->ops->request_bus_width(phy, bus_width);\n+\tif (!ret)\n+\t\tphy_set_bus_width(phy, bus_width);\n+\tmutex_unlock(&phy->mutex);\n+\n+\treturn ret;\n+}\n+EXPORT_SYMBOL_GPL(phy_request_bus_width);\n+\n /**\n  * _of_phy_get() - lookup and obtain a reference to a phy by phandle\n  * @np: device_node for which to get the phy\ndiff --git a/drivers/phy/samsung/phy-samsung-ufs.c b/drivers/phy/samsung/phy-samsung-ufs.c\nindex ee665f26c236..b09a35ab6acd 100644\n--- a/drivers/phy/samsung/phy-samsung-ufs.c\n+++ b/drivers/phy/samsung/phy-samsung-ufs.c\n@@ -165,7 +165,6 @@ static int samsung_ufs_phy_init(struct phy *phy)\n {\n \tstruct samsung_ufs_phy *ss_phy = get_samsung_ufs_phy(phy);\n \n-\tss_phy->lane_cnt = phy->attrs.bus_width;\n \tss_phy->ufs_phy_state = CFG_PRE_INIT;\n \n \treturn 0;\n@@ -204,6 +203,31 @@ static int samsung_ufs_phy_power_off(struct phy *phy)\n \treturn 0;\n }\n \n+static int samsung_ufs_phy_request_bus_width(struct phy *phy, int bus_width)\n+{\n+\tstruct samsung_ufs_phy *ss_phy = get_samsung_ufs_phy(phy);\n+\tu8 old_lane_cnt = ss_phy->lane_cnt;\n+\tint err = 0;\n+\n+\tif (bus_width != 1 && bus_width != 2)\n+\t\treturn -EINVAL;\n+\n+\tss_phy->lane_cnt = bus_width;\n+\n+\tif (phy->init_count)\n+\t\tsamsung_ufs_phy_init(phy);\n+\n+\t/* If the init_count is 0, the power_count should also be 0 */\n+\tif (phy->power_count) {\n+\t\tsamsung_ufs_phy_power_off(phy);\n+\t\terr = samsung_ufs_phy_power_on(phy);\n+\t\tif (err)\n+\t\t\tss_phy->lane_cnt = old_lane_cnt;\n+\t}\n+\n+\treturn err;\n+}\n+\n static int samsung_ufs_phy_set_mode(struct phy *generic_phy,\n \t\t\t\t    enum phy_mode mode, int submode)\n {\n@@ -272,6 +296,7 @@ static const struct phy_ops samsung_ufs_phy_ops = {\n \t.calibrate\t= samsung_ufs_phy_calibrate,\n \t.set_mode\t= samsung_ufs_phy_set_mode,\n \t.notify_phystate = samsung_ufs_phy_notify_state,\n+\t.request_bus_width = samsung_ufs_phy_request_bus_width,\n \t.owner          = THIS_MODULE,\n };\n \ndiff --git a/drivers/ufs/host/ufs-exynos.c b/drivers/ufs/host/ufs-exynos.c\nindex 77a6c8e44485..b90876b268db 100644\n--- a/drivers/ufs/host/ufs-exynos.c\n+++ b/drivers/ufs/host/ufs-exynos.c\n@@ -931,11 +931,73 @@ static void exynos_ufs_specify_nexus_t_tm_req(struct ufs_hba *hba,\n \t}\n }\n \n-static int exynos_ufs_phy_init(struct exynos_ufs *ufs)\n+static int exynos_ufs_phy_init(struct device *dev, struct exynos_ufs *ufs)\n+{\n+\tstruct phy *generic_phy;\n+\tint ret;\n+\n+\tgeneric_phy = devm_phy_get(dev, \"ufs-phy\");\n+\tif (IS_ERR(generic_phy)) {\n+\t\tret = PTR_ERR(generic_phy);\n+\t\tdev_err(dev, \"failed to get ufs-phy: %pe\\n\", ERR_PTR(ret));\n+\t\treturn ret;\n+\t}\n+\n+\tret = phy_init(generic_phy);\n+\tif (ret) {\n+\t\tdev_err(dev, \"phy init failed: %pe\\n\", ERR_PTR(ret));\n+\t\treturn ret;\n+\t}\n+\n+\tufs->phy = generic_phy;\n+\n+\treturn ret;\n+}\n+\n+static void exynos_ufs_phy_exit(struct exynos_ufs *ufs)\n+{\n+\tphy_exit(ufs->phy);\n+}\n+\n+static int exynos_ufs_phy_power_on(struct exynos_ufs *ufs)\n+{\n+\tint ret;\n+\n+\tif (ufs->phy_powered_on)\n+\t\treturn 0;\n+\n+\tret = phy_power_on(ufs->phy);\n+\tif (ret) {\n+\t\tdev_err(ufs->hba->dev, \"Failed to power on PHY: %pe\\n\",\n+\t\t\tERR_PTR(ret));\n+\t\treturn ret;\n+\t}\n+\n+\tufs->phy_powered_on = true;\n+\n+\treturn 0;\n+}\n+\n+static void exynos_ufs_phy_power_off(struct exynos_ufs *ufs)\n+{\n+\tint ret;\n+\n+\tif (!ufs->phy_powered_on)\n+\t\treturn;\n+\n+\tret = phy_power_off(ufs->phy);\n+\tif (ret)\n+\t\tdev_warn(ufs->hba->dev, \"Failed to power off PHY: %pe\\n\",\n+\t\t\t ERR_PTR(ret));\n+\n+\tufs->phy_powered_on = false;\n+}\n+\n+static int exynos_ufs_phy_update_bus_width(struct exynos_ufs *ufs)\n {\n \tstruct ufs_hba *hba = ufs->hba;\n \tstruct phy *generic_phy = ufs->phy;\n-\tint ret = 0;\n+\tint ret;\n \n \tif (ufs->avail_ln_rx == 0 || ufs->avail_ln_tx == 0) {\n \t\tufshcd_dme_get(hba, UIC_ARG_MIB(PA_AVAILRXDATALANES),\n@@ -947,30 +1009,11 @@ static int exynos_ufs_phy_init(struct exynos_ufs *ufs)\n \t\t\tufs->avail_ln_rx, ufs->avail_ln_tx);\n \t}\n \n-\tphy_set_bus_width(generic_phy, ufs->avail_ln_rx);\n-\n-\tif (generic_phy->power_count) {\n-\t\tphy_power_off(generic_phy);\n-\t\tphy_exit(generic_phy);\n-\t}\n-\n-\tret = phy_init(generic_phy);\n-\tif (ret) {\n-\t\tdev_err(hba->dev, \"%s: phy init failed, ret = %d\\n\",\n-\t\t\t__func__, ret);\n-\t\treturn ret;\n-\t}\n-\n-\tret = phy_power_on(generic_phy);\n+\tret = phy_request_bus_width(generic_phy, ufs->avail_ln_rx);\n \tif (ret)\n-\t\tgoto out_exit_phy;\n-\n-\treturn 0;\n-\n-out_exit_phy:\n-\tphy_exit(generic_phy);\n+\t\treturn ret;\n \n-\treturn ret;\n+\treturn exynos_ufs_phy_power_on(ufs);\n }\n \n static void exynos_ufs_config_unipro(struct exynos_ufs *ufs)\n@@ -1055,7 +1098,7 @@ static int exynos_ufs_pre_link(struct ufs_hba *hba)\n \t\tufs->drv_data->pre_link(ufs);\n \n \t/* m-phy */\n-\texynos_ufs_phy_init(ufs);\n+\texynos_ufs_phy_update_bus_width(ufs);\n \tif (!(ufs->opts & EXYNOS_UFS_OPT_SKIP_CONFIG_PHY_ATTR)) {\n \t\texynos_ufs_config_phy_time_attr(ufs);\n \t\texynos_ufs_config_phy_cap_attr(ufs);\n@@ -1475,12 +1518,9 @@ static int exynos_ufs_init(struct ufs_hba *hba)\n \t\tgoto out;\n \t}\n \n-\tufs->phy = devm_phy_get(dev, \"ufs-phy\");\n-\tif (IS_ERR(ufs->phy)) {\n-\t\tret = PTR_ERR(ufs->phy);\n-\t\tdev_err(dev, \"failed to get ufs-phy\\n\");\n+\tret = exynos_ufs_phy_init(dev, ufs);\n+\tif (ret)\n \t\tgoto out;\n-\t}\n \n \texynos_ufs_priv_init(hba, ufs);\n \n@@ -1490,13 +1530,13 @@ static int exynos_ufs_init(struct ufs_hba *hba)\n \t\tret = ufs->drv_data->drv_init(ufs);\n \t\tif (ret) {\n \t\t\tdev_err(dev, \"failed to init drv-data\\n\");\n-\t\t\tgoto out;\n+\t\t\tgoto out_phy_exit;\n \t\t}\n \t}\n \n \tret = exynos_ufs_get_clk_info(ufs);\n \tif (ret)\n-\t\tgoto out;\n+\t\tgoto out_phy_exit;\n \texynos_ufs_specify_phy_time_attr(ufs);\n \n \texynos_ufs_config_smu(ufs);\n@@ -1504,6 +1544,8 @@ static int exynos_ufs_init(struct ufs_hba *hba)\n \thba->host->dma_alignment = DATA_UNIT_SIZE - 1;\n \treturn 0;\n \n+out_phy_exit:\n+\texynos_ufs_phy_exit(ufs);\n out:\n \thba->priv = NULL;\n \treturn ret;\n@@ -1513,8 +1555,8 @@ static void exynos_ufs_exit(struct ufs_hba *hba)\n {\n \tstruct exynos_ufs *ufs = ufshcd_get_variant(hba);\n \n-\tphy_power_off(ufs->phy);\n-\tphy_exit(ufs->phy);\n+\texynos_ufs_phy_power_off(ufs);\n+\texynos_ufs_phy_exit(ufs);\n }\n \n static int exynos_ufs_host_reset(struct ufs_hba *hba)\n@@ -1728,7 +1770,7 @@ static int exynos_ufs_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op,\n \t\tufs->drv_data->suspend(ufs);\n \n \tif (!ufshcd_is_link_active(hba))\n-\t\tphy_power_off(ufs->phy);\n+\t\texynos_ufs_phy_power_off(ufs);\n \n \treturn 0;\n }\n@@ -1738,7 +1780,7 @@ static int exynos_ufs_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)\n \tstruct exynos_ufs *ufs = ufshcd_get_variant(hba);\n \n \tif (!ufshcd_is_link_active(hba))\n-\t\tphy_power_on(ufs->phy);\n+\t\texynos_ufs_phy_power_on(ufs);\n \n \texynos_ufs_config_smu(ufs);\n \texynos_ufs_fmp_resume(hba);\ndiff --git a/drivers/ufs/host/ufs-exynos.h b/drivers/ufs/host/ufs-exynos.h\nindex abe7e472759e..683b9150e2ba 100644\n--- a/drivers/ufs/host/ufs-exynos.h\n+++ b/drivers/ufs/host/ufs-exynos.h\n@@ -227,6 +227,7 @@ struct exynos_ufs {\n \tint avail_ln_rx;\n \tint avail_ln_tx;\n \tint rx_sel_idx;\n+\tbool phy_powered_on;\n \tstruct ufs_pa_layer_attr dev_req_params;\n \tstruct ufs_phy_time_cfg t_cfg;\n \tktime_t entry_hibern8_t;\ndiff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h\nindex ea47975e288a..01af84f97608 100644\n--- a/include/linux/phy/phy.h\n+++ b/include/linux/phy/phy.h\n@@ -93,6 +93,7 @@ union phy_configure_opts {\n  * @reset: resetting the phy\n  * @calibrate: calibrate the phy\n  * @notify_phystate: notify and configure the phy for a particular state\n+ * @request_bus_width: request a different bus width for the phy\n  * @release: ops to be performed while the consumer relinquishes the PHY\n  * @owner: the module owner containing the ops\n  */\n@@ -143,6 +144,7 @@ struct phy_ops {\n \tint\t(*disconnect)(struct phy *phy, int port);\n \n \tint\t(*notify_phystate)(struct phy *phy, union phy_notify state);\n+\tint\t(*request_bus_width)(struct phy *phy, int bus_width);\n \tvoid\t(*release)(struct phy *phy);\n \tstruct module *owner;\n };\n@@ -275,6 +277,7 @@ static inline void phy_set_bus_width(struct phy *phy, int bus_width)\n {\n \tphy->attrs.bus_width = bus_width;\n }\n+int phy_request_bus_width(struct phy *phy, int bus_width);\n struct phy *phy_get(struct device *dev, const char *string);\n struct phy *devm_phy_get(struct device *dev, const char *string);\n struct phy *devm_phy_optional_get(struct device *dev, const char *string);\n@@ -456,6 +459,14 @@ static inline void phy_set_bus_width(struct phy *phy, int bus_width)\n \treturn;\n }\n \n+static inline int phy_request_bus_width(struct phy *phy, int bus_width)\n+{\n+\tif (!phy)\n+\t\treturn 0;\n+\n+\treturn -ENOSYS;\n+}\n+\n static inline struct phy *phy_get(struct device *dev, const char *string)\n {\n \treturn ERR_PTR(-ENOSYS);\n",
    "prefixes": [
        "v8",
        "phy-next",
        "10/31"
    ]
}