From patchwork Tue Sep 12 09:48:41 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jinjian Song X-Patchwork-Id: 13381201 X-Patchwork-Delegate: kuba@kernel.org Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4AE6A168B4 for ; Tue, 12 Sep 2023 09:49:36 +0000 (UTC) Received: from AUS01-ME3-obe.outbound.protection.outlook.com (mail-me3aus01olkn2182.outbound.protection.outlook.com [40.92.63.182]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7639C10D1; Tue, 12 Sep 2023 02:49:35 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=Xx9Qypla2I0jBHjCxcT2bTZx+5Lff8Wcw2Zmxao86VJyWMGflYBF47sNmdqWO7oLQL/8vJLxlMvP36uT9P5Q3sTkfSYgjIMKmS7wyOd7j1ONyE5AGqaTPb2s+XGviuy3D7xv57c33hL00RoK46Alu2L3sJhIqyrlozqheOuplVSBzxTR1cwR1lnSdYfsknmRFXx11BtgG7l3x/1g1BJo2jdeaQ7aKRSqjeqVsNqqKRYkM5w2oh+YG54soTTKHCi/16gDvbJINPmjeGFSgvsYPDK3aaFT580ltuGLRdhTz6U+d+pFxXeQwG2ITilZoWrKNdu8oY+i4dOUD1V3gHnW/Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; 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; bh=aUywhITeJaO23VuiGjT/8C7oWO+JQdBpH/GZu/NRFXU=; b=n/MAzxs78b39d/gP+qkw6iFSE/wR5N5L2Cy8Ryapor/p6QTI80Z7Rprc7hNLgnfZtZvJ1/oQZjkmAX8TXRuKFoTD9QAatPVVzyyvUOd3r4qTScI2+vdh12qOEXvKZPV/KD81x7nvemOZ1VJV8mD9v7MdV0OvRt2By9KOZAgbaPyuE93U6bYrtKYsOkAB1fhpeCnvml7KoTbP+1oaK6tOn7pG0shOCeWcIUuQwRj7M6xapiFSp7TdiB08pcgoTu3vkN+HJmF9gUolVRFsAAMFokqxXnzvLfn0Z18BXx/a9zRtrNzOlU8HGMPN0gAmOTTBLN9SVu3wgFlmflCNnrZ9ZA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=none; dmarc=none; dkim=none; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=hotmail.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=aUywhITeJaO23VuiGjT/8C7oWO+JQdBpH/GZu/NRFXU=; b=fB2zVwU7cIY9JdW9DjBTI7eIc2fQjLs6jDUumLqp/xf9vyuqC5woKKBnEraG82uvt9VCuM3aC1IHukWuLtGsZRO72jARWL9gmf28ZH5BGZCkpeYR9bSL7CEhxNaTMpwvZdXTjNPikt7HkKO7P5Q0RoPQC9EXEYOKzEGepUIndKFWc3O8YsGBAk5bfk8gECzRMuN/Y9U9MmXl2a5VWRIKuLj8+PlRhpo0kBxQiGaSv/BE9c3YDwcOwPpC/FDnYoE0GLyzYvttpmdD7iiqKyKFv7ATlGTllOrrMLMzYjwCrhwQKr/raU6NR2PhGuqVBh3Lq/80YAtL8+pD2CLpwMSX2A== Received: from ME3P282MB2703.AUSP282.PROD.OUTLOOK.COM (2603:10c6:220:16b::5) by SY4P282MB2981.AUSP282.PROD.OUTLOOK.COM (2603:10c6:10:15c::13) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6768.35; Tue, 12 Sep 2023 09:49:27 +0000 Received: from ME3P282MB2703.AUSP282.PROD.OUTLOOK.COM ([fe80::68b4:6263:97f:9a45]) by ME3P282MB2703.AUSP282.PROD.OUTLOOK.COM ([fe80::68b4:6263:97f:9a45%3]) with mapi id 15.20.6768.036; Tue, 12 Sep 2023 09:49:27 +0000 From: Jinjian Song To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, corbet@lwn.net, loic.poulain@linaro.org, ryazanov.s.a@gmail.com Cc: jiri@resnulli.us, johannes@sipsolutions.net, chandrashekar.devegowda@intel.com, linuxwwan@intel.com, chiranjeevi.rapolu@linux.intel.com, haijun.liu@mediatek.com, m.chetan.kumar@linux.intel.com, ricardo.martinez@linux.intel.com, netdev@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, nmarupaka@google.com, vsankar@lenovo.com, danielwinkler@google.com, Jinjian Song Subject: [net-next v4 1/5] net: wwan: t7xx: Infrastructure for early port configuration Date: Tue, 12 Sep 2023 17:48:41 +0800 Message-ID: X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230912094845.11233-1-songjinjian@hotmail.com> References: <20230912094845.11233-1-songjinjian@hotmail.com> X-TMN: [J1hkIbHsVqIBsHWwWvFyF5lMFxfK1lhR] X-ClientProxiedBy: SI2PR01CA0048.apcprd01.prod.exchangelabs.com (2603:1096:4:193::17) To ME3P282MB2703.AUSP282.PROD.OUTLOOK.COM (2603:10c6:220:16b::5) X-Microsoft-Original-Message-ID: <20230912094845.11233-2-songjinjian@hotmail.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: ME3P282MB2703:EE_|SY4P282MB2981:EE_ X-MS-Office365-Filtering-Correlation-Id: f08662b9-2ae7-4a3f-ec88-08dbb3758d8c X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: oWjxiJLpkCKzUTcv5Rt3Z/bEfvEKJ8xckXefYt6UesNWZh5wsm3Y02G76YM0dVDgFS0F795P9j1oY/MVsMh5GuvsdjE2oJDUC+YWMpHwdAX+p1dNs04JeP4FqtHp2/fld5L7jYE0DaPP3VyBG9hBIJHSozsVIVn2LVWeD4x2fS8WghQm/uICMmDo3rUX/opyzLqAK1kwFHccJGuwEury84R19wZYnBhGHJ3VndxIcUkAkmC0BRRdLv4FQk+ukgKMD/ARIytdsxhTA3VfSK6JaRKC+H2/DctcNKwLvYUDr2HZhJ5Fk3knLgdM4vAJz6VB0yhTZhA/A13YMmYbjNqchjpFhvnOVirJINYpwtvs92ul3bQ7aio0RAbIPqwebuT2xuSoyZpd6nMoYPJ3VU6B/h24cF/Hc4tkPNcazcw1IRluXFXw9saQzR2nug227Sfh5cF8Vq+BKyHbdpmtLcImLSkAaIJo0nRSxxC58oKGSdFangD4luRivfFwnNdJpFFlvVGBjwK3rgq+v1BAkE4J10eMIjb9t6H/SnllkVaOOtP9MHN/7q6aPJXf6NwOpYU6hRXR0g2Ta0TT3U/KaXbNP0kKOphfSbm4WDztTZj0lsc= X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: N3QFagob5fVqXJ5tXZo3F9g4USbP5YfFsvsuJP38Rx9J0IALFCTHjNuK7C9FuesyM4vfard9bhOACifRS0Wvhkp+MBnD3fhBZPqYjyoXgIQEmvhzv8p/jAsUcWR9QO+jyXfUwyYV/AuzPslGUgXaJJ+Pc/A5ORxsB9rvAAAKBVy9S2aXHTlX64HD/dV3bmSQrm0cNRUvbedVq11el4O0uNwg3z67F1iuAkfm3+gFW33WCMFUS9ymvBaI3C9S9iDukqCbdcTUKq+pJrsjRCB41NUFdNicVUVOdXumvPTa1z814nG/1TTkXjJSAnV40GWIyAbknbPlvHqaUVQjioPDtwv8El7PlwrEUR/74BHTVU+ohfBzYlxfJvUFzuju1MtiaO8T/ps39IOy7/GaGr3BERhMaki4c3XZsTW/cIcw19SKmIgXu2aSXcohyZJWcV42jsXzK7V6Hi+USs/n0NACSrHg3HQana8XSln/z5VTmfhkfxbqsb1sNbonugtaRel0ExJLd9rwHjRsrzSychL9i14P1RqNEnKRjRuKK5OHwAWtqtyWWymCPgfCs2j0DNGXN2VA0FfnLb+XBJ77PATof91P1I+lK7SiMAP8k4VHHDnfw93U7dSoCYExYVtrsOXRoh2kuonfwDezJB2/pPfTzaEf2b44kV2wJTqnm2hrIBUhUHu77KATbjFX82rICcE8A0u1F7yxGd2r7fjrNgLqB4nhCC9znmctBpl3MpIwIunCJVQ2GVks2pRxi30tLror5qsAQLwQDQrHrWyl00EUx/UqJUA6uh0zkI6iIIvChNzESWyoPdUKio3fpPO95SKUCzwlOTGfKK9PxEZm3hL5jvcJYv1chwMoSiikQHQUC2sPqAMCqmJHl//RdD52QOpfTQcM14XW7gNTLXTIsbAaaVaZSOf8T3M/d+3N+EAntQPdBZH/WuqieRU6z6afnKyslUD/17IgJIixMzmA0WfhtQKM1zAcBWM7eJ0doXqdSJP2jRIQmD6zNt61i2AhAD5i5Pr1VPCviVepDq7W5BeP6GqxMw3XT5T1mlCuu45z5yUtbouisANxn8cz0t5in+4BFLttyrAw+M6XU8k6TI2ZI03ilqd3He74M5YBml8HPCRAWv5vdWh2EczLd80ySv9LnPf9sUF5anrKJklBR4xN3KNKTfWptxjxaiHxXBC1DmsyDeoWTH98RB4c0EysZBIpb36CHy/6c5EKFqxucdTqr/ddCa6P5/FXHLvApQod2JM= X-OriginatorOrg: sct-15-20-4755-11-msonline-outlook-746f3.templateTenant X-MS-Exchange-CrossTenant-Network-Message-Id: f08662b9-2ae7-4a3f-ec88-08dbb3758d8c X-MS-Exchange-CrossTenant-AuthSource: ME3P282MB2703.AUSP282.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Sep 2023 09:49:27.6017 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 84df9e7f-e9f6-40af-b435-aaaaaaaaaaaa X-MS-Exchange-CrossTenant-RMS-PersistedConsumerOrg: 00000000-0000-0000-0000-000000000000 X-MS-Exchange-Transport-CrossTenantHeadersStamped: SY4P282MB2981 X-Patchwork-Delegate: kuba@kernel.org From: Jinjian Song To support cases such as FW update or Core dump, the t7xx device is capable of signaling the host that a special port needs to be created before the handshake phase. Adds the infrastructure required to create the early ports which also requires a different configuration of CLDMA queues. Base on the v5 patch version of follow series: 'net: wwan: t7xx: fw flashing & coredump support' (https://patchwork.kernel.org/project/netdevbpf/patch/3777bb382f4b0395cb594a602c5c79dbab86c9e0.1674307425.git.m.chetan.kumar@linux.intel.com/) Signed-off-by: Jinjian Song --- v4: * no change v3: * no change v2: * remove t7xx_port_ap_msg file --- drivers/net/wwan/t7xx/t7xx_hif_cldma.c | 47 ++++++++---- drivers/net/wwan/t7xx/t7xx_hif_cldma.h | 18 +++-- drivers/net/wwan/t7xx/t7xx_modem_ops.c | 4 +- drivers/net/wwan/t7xx/t7xx_port.h | 4 + drivers/net/wwan/t7xx/t7xx_port_proxy.c | 86 +++++++++++++++++++--- drivers/net/wwan/t7xx/t7xx_port_proxy.h | 10 +++ drivers/net/wwan/t7xx/t7xx_port_wwan.c | 5 +- drivers/net/wwan/t7xx/t7xx_reg.h | 22 +++++- drivers/net/wwan/t7xx/t7xx_state_monitor.c | 86 +++++++++++++++++++--- drivers/net/wwan/t7xx/t7xx_state_monitor.h | 1 + 10 files changed, 235 insertions(+), 48 deletions(-) diff --git a/drivers/net/wwan/t7xx/t7xx_hif_cldma.c b/drivers/net/wwan/t7xx/t7xx_hif_cldma.c index cc70360364b7..abc41a7089fa 100644 --- a/drivers/net/wwan/t7xx/t7xx_hif_cldma.c +++ b/drivers/net/wwan/t7xx/t7xx_hif_cldma.c @@ -57,8 +57,6 @@ #define CHECK_Q_STOP_TIMEOUT_US 1000000 #define CHECK_Q_STOP_STEP_US 10000 -#define CLDMA_JUMBO_BUFF_SZ (63 * 1024 + sizeof(struct ccci_header)) - static void md_cd_queue_struct_reset(struct cldma_queue *queue, struct cldma_ctrl *md_ctrl, enum mtk_txrx tx_rx, unsigned int index) { @@ -161,7 +159,7 @@ static int t7xx_cldma_gpd_rx_from_q(struct cldma_queue *queue, int budget, bool skb_reset_tail_pointer(skb); skb_put(skb, le16_to_cpu(gpd->data_buff_len)); - ret = md_ctrl->recv_skb(queue, skb); + ret = queue->recv_skb(queue, skb); /* Break processing, will try again later */ if (ret < 0) return ret; @@ -897,13 +895,13 @@ static void t7xx_cldma_hw_start_send(struct cldma_ctrl *md_ctrl, int qno, /** * t7xx_cldma_set_recv_skb() - Set the callback to handle RX packets. - * @md_ctrl: CLDMA context structure. + * @queue: CLDMA queue. * @recv_skb: Receiving skb callback. */ -void t7xx_cldma_set_recv_skb(struct cldma_ctrl *md_ctrl, +void t7xx_cldma_set_recv_skb(struct cldma_queue *queue, int (*recv_skb)(struct cldma_queue *queue, struct sk_buff *skb)) { - md_ctrl->recv_skb = recv_skb; + queue->recv_skb = recv_skb; } /** @@ -993,6 +991,28 @@ int t7xx_cldma_send_skb(struct cldma_ctrl *md_ctrl, int qno, struct sk_buff *skb return ret; } +static void t7xx_cldma_adjust_config(struct cldma_ctrl *md_ctrl, enum cldma_cfg cfg_id) +{ + int qno; + + for (qno = 0; qno < CLDMA_RXQ_NUM; qno++) { + md_ctrl->rx_ring[qno].pkt_size = CLDMA_SHARED_Q_BUFF_SZ; + t7xx_cldma_set_recv_skb(&md_ctrl->rxq[qno], t7xx_port_proxy_recv_skb); + } + + md_ctrl->rx_ring[CLDMA_RXQ_NUM - 1].pkt_size = CLDMA_JUMBO_BUFF_SZ; + + for (qno = 0; qno < CLDMA_TXQ_NUM; qno++) + md_ctrl->tx_ring[qno].pkt_size = CLDMA_SHARED_Q_BUFF_SZ; + + if (cfg_id == CLDMA_DEDICATED_Q_CFG) { + md_ctrl->tx_ring[CLDMA_Q_IDX_DUMP].pkt_size = CLDMA_DEDICATED_Q_BUFF_SZ; + md_ctrl->rx_ring[CLDMA_Q_IDX_DUMP].pkt_size = CLDMA_DEDICATED_Q_BUFF_SZ; + t7xx_cldma_set_recv_skb(&md_ctrl->rxq[CLDMA_Q_IDX_DUMP], + t7xx_port_proxy_recv_skb_from_dedicated_queue); + } +} + static int t7xx_cldma_late_init(struct cldma_ctrl *md_ctrl) { char dma_pool_name[32]; @@ -1018,16 +1038,9 @@ static int t7xx_cldma_late_init(struct cldma_ctrl *md_ctrl) dev_err(md_ctrl->dev, "control TX ring init fail\n"); goto err_free_tx_ring; } - - md_ctrl->tx_ring[i].pkt_size = CLDMA_MTU; } for (j = 0; j < CLDMA_RXQ_NUM; j++) { - md_ctrl->rx_ring[j].pkt_size = CLDMA_MTU; - - if (j == CLDMA_RXQ_NUM - 1) - md_ctrl->rx_ring[j].pkt_size = CLDMA_JUMBO_BUFF_SZ; - ret = t7xx_cldma_rx_ring_init(md_ctrl, &md_ctrl->rx_ring[j]); if (ret) { dev_err(md_ctrl->dev, "Control RX ring init fail\n"); @@ -1094,6 +1107,7 @@ int t7xx_cldma_alloc(enum cldma_id hif_id, struct t7xx_pci_dev *t7xx_dev) { struct device *dev = &t7xx_dev->pdev->dev; struct cldma_ctrl *md_ctrl; + int qno; md_ctrl = devm_kzalloc(dev, sizeof(*md_ctrl), GFP_KERNEL); if (!md_ctrl) @@ -1102,7 +1116,9 @@ int t7xx_cldma_alloc(enum cldma_id hif_id, struct t7xx_pci_dev *t7xx_dev) md_ctrl->t7xx_dev = t7xx_dev; md_ctrl->dev = dev; md_ctrl->hif_id = hif_id; - md_ctrl->recv_skb = t7xx_cldma_default_recv_skb; + for (qno = 0; qno < CLDMA_RXQ_NUM; qno++) + md_ctrl->rxq[qno].recv_skb = t7xx_cldma_default_recv_skb; + t7xx_hw_info_init(md_ctrl); t7xx_dev->md->md_ctrl[hif_id] = md_ctrl; return 0; @@ -1332,9 +1348,10 @@ int t7xx_cldma_init(struct cldma_ctrl *md_ctrl) return -ENOMEM; } -void t7xx_cldma_switch_cfg(struct cldma_ctrl *md_ctrl) +void t7xx_cldma_switch_cfg(struct cldma_ctrl *md_ctrl, enum cldma_cfg cfg_id) { t7xx_cldma_late_release(md_ctrl); + t7xx_cldma_adjust_config(md_ctrl, cfg_id); t7xx_cldma_late_init(md_ctrl); } diff --git a/drivers/net/wwan/t7xx/t7xx_hif_cldma.h b/drivers/net/wwan/t7xx/t7xx_hif_cldma.h index 4410bac6993a..5453cfecbe19 100644 --- a/drivers/net/wwan/t7xx/t7xx_hif_cldma.h +++ b/drivers/net/wwan/t7xx/t7xx_hif_cldma.h @@ -31,6 +31,10 @@ #include "t7xx_cldma.h" #include "t7xx_pci.h" +#define CLDMA_JUMBO_BUFF_SZ (63 * 1024 + sizeof(struct ccci_header)) +#define CLDMA_SHARED_Q_BUFF_SZ 3584 +#define CLDMA_DEDICATED_Q_BUFF_SZ 2048 + /** * enum cldma_id - Identifiers for CLDMA HW units. * @CLDMA_ID_MD: Modem control channel. @@ -55,6 +59,11 @@ struct cldma_gpd { __le16 not_used2; }; +enum cldma_cfg { + CLDMA_SHARED_Q_CFG, + CLDMA_DEDICATED_Q_CFG, +}; + struct cldma_request { struct cldma_gpd *gpd; /* Virtual address for CPU */ dma_addr_t gpd_addr; /* Physical address for DMA */ @@ -82,6 +91,7 @@ struct cldma_queue { wait_queue_head_t req_wq; /* Only for TX */ struct workqueue_struct *worker; struct work_struct cldma_work; + int (*recv_skb)(struct cldma_queue *queue, struct sk_buff *skb); }; struct cldma_ctrl { @@ -101,24 +111,22 @@ struct cldma_ctrl { struct md_pm_entity *pm_entity; struct t7xx_cldma_hw hw_info; bool is_late_init; - int (*recv_skb)(struct cldma_queue *queue, struct sk_buff *skb); }; +#define CLDMA_Q_IDX_DUMP 1 #define GPD_FLAGS_HWO BIT(0) #define GPD_FLAGS_IOC BIT(7) #define GPD_DMAPOOL_ALIGN 16 -#define CLDMA_MTU 3584 /* 3.5kB */ - int t7xx_cldma_alloc(enum cldma_id hif_id, struct t7xx_pci_dev *t7xx_dev); void t7xx_cldma_hif_hw_init(struct cldma_ctrl *md_ctrl); int t7xx_cldma_init(struct cldma_ctrl *md_ctrl); void t7xx_cldma_exit(struct cldma_ctrl *md_ctrl); -void t7xx_cldma_switch_cfg(struct cldma_ctrl *md_ctrl); +void t7xx_cldma_switch_cfg(struct cldma_ctrl *md_ctrl, enum cldma_cfg cfg_id); void t7xx_cldma_start(struct cldma_ctrl *md_ctrl); int t7xx_cldma_stop(struct cldma_ctrl *md_ctrl); void t7xx_cldma_reset(struct cldma_ctrl *md_ctrl); -void t7xx_cldma_set_recv_skb(struct cldma_ctrl *md_ctrl, +void t7xx_cldma_set_recv_skb(struct cldma_queue *queue, int (*recv_skb)(struct cldma_queue *queue, struct sk_buff *skb)); int t7xx_cldma_send_skb(struct cldma_ctrl *md_ctrl, int qno, struct sk_buff *skb); void t7xx_cldma_stop_all_qs(struct cldma_ctrl *md_ctrl, enum mtk_txrx tx_rx); diff --git a/drivers/net/wwan/t7xx/t7xx_modem_ops.c b/drivers/net/wwan/t7xx/t7xx_modem_ops.c index 24e7d491468e..cbd65aa48721 100644 --- a/drivers/net/wwan/t7xx/t7xx_modem_ops.c +++ b/drivers/net/wwan/t7xx/t7xx_modem_ops.c @@ -529,7 +529,7 @@ static void t7xx_md_hk_wq(struct work_struct *work) /* Clear the HS2 EXIT event appended in core_reset() */ t7xx_fsm_clr_event(ctl, FSM_EVENT_MD_HS2_EXIT); - t7xx_cldma_switch_cfg(md->md_ctrl[CLDMA_ID_MD]); + t7xx_cldma_switch_cfg(md->md_ctrl[CLDMA_ID_MD], CLDMA_SHARED_Q_CFG); t7xx_cldma_start(md->md_ctrl[CLDMA_ID_MD]); t7xx_fsm_broadcast_state(ctl, MD_STATE_WAITING_FOR_HS2); md->core_md.handshake_ongoing = true; @@ -544,7 +544,7 @@ static void t7xx_ap_hk_wq(struct work_struct *work) /* Clear the HS2 EXIT event appended in t7xx_core_reset(). */ t7xx_fsm_clr_event(ctl, FSM_EVENT_AP_HS2_EXIT); t7xx_cldma_stop(md->md_ctrl[CLDMA_ID_AP]); - t7xx_cldma_switch_cfg(md->md_ctrl[CLDMA_ID_AP]); + t7xx_cldma_switch_cfg(md->md_ctrl[CLDMA_ID_AP], CLDMA_SHARED_Q_CFG); t7xx_cldma_start(md->md_ctrl[CLDMA_ID_AP]); md->core_ap.handshake_ongoing = true; t7xx_core_hk_handler(md, &md->core_ap, ctl, FSM_EVENT_AP_HS2, FSM_EVENT_AP_HS2_EXIT); diff --git a/drivers/net/wwan/t7xx/t7xx_port.h b/drivers/net/wwan/t7xx/t7xx_port.h index 4ae8a00a8532..09acb1ef144d 100644 --- a/drivers/net/wwan/t7xx/t7xx_port.h +++ b/drivers/net/wwan/t7xx/t7xx_port.h @@ -75,6 +75,8 @@ enum port_ch { PORT_CH_DSS6_TX = 0x20df, PORT_CH_DSS7_RX = 0x20e0, PORT_CH_DSS7_TX = 0x20e1, + + PORT_CH_ID_UNIMPORTANT = 0xffff, }; struct t7xx_port; @@ -135,9 +137,11 @@ struct t7xx_port { }; }; +int t7xx_get_port_mtu(struct t7xx_port *port); struct sk_buff *t7xx_port_alloc_skb(int payload); struct sk_buff *t7xx_ctrl_alloc_skb(int payload); int t7xx_port_enqueue_skb(struct t7xx_port *port, struct sk_buff *skb); +int t7xx_port_send_raw_skb(struct t7xx_port *port, struct sk_buff *skb); int t7xx_port_send_skb(struct t7xx_port *port, struct sk_buff *skb, unsigned int pkt_header, unsigned int ex_msg); int t7xx_port_send_ctl_skb(struct t7xx_port *port, struct sk_buff *skb, unsigned int msg, diff --git a/drivers/net/wwan/t7xx/t7xx_port_proxy.c b/drivers/net/wwan/t7xx/t7xx_port_proxy.c index 274846d39fbf..bdfeb10e0c51 100644 --- a/drivers/net/wwan/t7xx/t7xx_port_proxy.c +++ b/drivers/net/wwan/t7xx/t7xx_port_proxy.c @@ -100,6 +100,18 @@ static const struct t7xx_port_conf t7xx_port_conf[] = { }, }; +static struct t7xx_port_conf t7xx_early_port_conf[] = { + { + .tx_ch = PORT_CH_ID_UNIMPORTANT, + .rx_ch = PORT_CH_ID_UNIMPORTANT, + .txq_index = CLDMA_Q_IDX_DUMP, + .rxq_index = CLDMA_Q_IDX_DUMP, + .txq_exp_index = CLDMA_Q_IDX_DUMP, + .rxq_exp_index = CLDMA_Q_IDX_DUMP, + .path_id = CLDMA_ID_AP, + }, +}; + static struct t7xx_port *t7xx_proxy_get_port_by_ch(struct port_proxy *port_prox, enum port_ch ch) { const struct t7xx_port_conf *port_conf; @@ -214,7 +226,17 @@ int t7xx_port_enqueue_skb(struct t7xx_port *port, struct sk_buff *skb) return 0; } -static int t7xx_port_send_raw_skb(struct t7xx_port *port, struct sk_buff *skb) +int t7xx_get_port_mtu(struct t7xx_port *port) +{ + enum cldma_id path_id = port->port_conf->path_id; + int tx_qno = t7xx_port_get_queue_no(port); + struct cldma_ctrl *md_ctrl; + + md_ctrl = port->t7xx_dev->md->md_ctrl[path_id]; + return md_ctrl->tx_ring[tx_qno].pkt_size; +} + +int t7xx_port_send_raw_skb(struct t7xx_port *port, struct sk_buff *skb) { enum cldma_id path_id = port->port_conf->path_id; struct cldma_ctrl *md_ctrl; @@ -329,6 +351,30 @@ static void t7xx_proxy_setup_ch_mapping(struct port_proxy *port_prox) } } +int t7xx_port_proxy_recv_skb_from_dedicated_queue(struct cldma_queue *queue, struct sk_buff *skb) +{ + struct t7xx_pci_dev *t7xx_dev = queue->md_ctrl->t7xx_dev; + struct port_proxy *port_prox = t7xx_dev->md->port_prox; + const struct t7xx_port_conf *port_conf; + struct t7xx_port *port; + int ret; + + port = &port_prox->ports[0]; + if (WARN_ON_ONCE(port->port_conf->rxq_index != queue->index)) { + dev_kfree_skb_any(skb); + return -EINVAL; + } + + port_conf = port->port_conf; + ret = port_conf->ops->recv_skb(port, skb); + if (ret < 0 && ret != -ENOBUFS) { + dev_err(port->dev, "drop on RX ch %d, %d\n", port_conf->rx_ch, ret); + dev_kfree_skb_any(skb); + } + + return ret; +} + static struct t7xx_port *t7xx_port_proxy_find_port(struct t7xx_pci_dev *t7xx_dev, struct cldma_queue *queue, u16 channel) { @@ -359,7 +405,7 @@ static struct t7xx_port *t7xx_port_proxy_find_port(struct t7xx_pci_dev *t7xx_dev ** 0 - Packet consumed. ** -ERROR - Failed to process skb. */ -static int t7xx_port_proxy_recv_skb(struct cldma_queue *queue, struct sk_buff *skb) +int t7xx_port_proxy_recv_skb(struct cldma_queue *queue, struct sk_buff *skb) { struct ccci_header *ccci_h = (struct ccci_header *)skb->data; struct t7xx_pci_dev *t7xx_dev = queue->md_ctrl->t7xx_dev; @@ -451,13 +497,39 @@ static void t7xx_proxy_init_all_ports(struct t7xx_modem *md) t7xx_proxy_setup_ch_mapping(port_prox); } +void t7xx_port_proxy_set_cfg(struct t7xx_modem *md, enum port_cfg_id cfg_id) +{ + struct port_proxy *port_prox = md->port_prox; + const struct t7xx_port_conf *port_conf; + u32 port_count; + int i; + + t7xx_port_proxy_uninit(port_prox); + + if (cfg_id == PORT_CFG_ID_EARLY) { + port_conf = t7xx_early_port_conf; + port_count = ARRAY_SIZE(t7xx_early_port_conf); + } else { + port_conf = t7xx_port_conf; + port_count = ARRAY_SIZE(t7xx_port_conf); + } + + for (i = 0; i < port_count; i++) + port_prox->ports[i].port_conf = &port_conf[i]; + + port_prox->cfg_id = cfg_id; + port_prox->port_count = port_count; + t7xx_proxy_init_all_ports(md); +} + static int t7xx_proxy_alloc(struct t7xx_modem *md) { + unsigned int early_port_count = ARRAY_SIZE(t7xx_early_port_conf); unsigned int port_count = ARRAY_SIZE(t7xx_port_conf); struct device *dev = &md->t7xx_dev->pdev->dev; struct port_proxy *port_prox; - int i; + port_count = max(port_count, early_port_count); port_prox = devm_kzalloc(dev, sizeof(*port_prox) + sizeof(struct t7xx_port) * port_count, GFP_KERNEL); if (!port_prox) @@ -465,12 +537,8 @@ static int t7xx_proxy_alloc(struct t7xx_modem *md) md->port_prox = port_prox; port_prox->dev = dev; + t7xx_port_proxy_set_cfg(md, PORT_CFG_ID_EARLY); - for (i = 0; i < port_count; i++) - port_prox->ports[i].port_conf = &t7xx_port_conf[i]; - - port_prox->port_count = port_count; - t7xx_proxy_init_all_ports(md); return 0; } @@ -492,8 +560,6 @@ int t7xx_port_proxy_init(struct t7xx_modem *md) if (ret) return ret; - t7xx_cldma_set_recv_skb(md->md_ctrl[CLDMA_ID_AP], t7xx_port_proxy_recv_skb); - t7xx_cldma_set_recv_skb(md->md_ctrl[CLDMA_ID_MD], t7xx_port_proxy_recv_skb); return 0; } diff --git a/drivers/net/wwan/t7xx/t7xx_port_proxy.h b/drivers/net/wwan/t7xx/t7xx_port_proxy.h index 81d059fbc0fb..7f5706811445 100644 --- a/drivers/net/wwan/t7xx/t7xx_port_proxy.h +++ b/drivers/net/wwan/t7xx/t7xx_port_proxy.h @@ -31,11 +31,18 @@ #define RX_QUEUE_MAXLEN 32 #define CTRL_QUEUE_MAXLEN 16 +enum port_cfg_id { + PORT_CFG_ID_INVALID, + PORT_CFG_ID_NORMAL, + PORT_CFG_ID_EARLY, +}; + struct port_proxy { int port_count; struct list_head rx_ch_ports[PORT_CH_ID_MASK + 1]; struct list_head queue_ports[CLDMA_NUM][MTK_QUEUES]; struct device *dev; + enum port_cfg_id cfg_id; struct t7xx_port ports[]; }; @@ -98,5 +105,8 @@ void t7xx_port_proxy_md_status_notify(struct port_proxy *port_prox, unsigned int int t7xx_port_enum_msg_handler(struct t7xx_modem *md, void *msg); int t7xx_port_proxy_chl_enable_disable(struct port_proxy *port_prox, unsigned int ch_id, bool en_flag); +void t7xx_port_proxy_set_cfg(struct t7xx_modem *md, enum port_cfg_id cfg_id); +int t7xx_port_proxy_recv_skb(struct cldma_queue *queue, struct sk_buff *skb); +int t7xx_port_proxy_recv_skb_from_dedicated_queue(struct cldma_queue *queue, struct sk_buff *skb); #endif /* __T7XX_PORT_PROXY_H__ */ diff --git a/drivers/net/wwan/t7xx/t7xx_port_wwan.c b/drivers/net/wwan/t7xx/t7xx_port_wwan.c index 17389c8f6600..ddc20ddfa734 100644 --- a/drivers/net/wwan/t7xx/t7xx_port_wwan.c +++ b/drivers/net/wwan/t7xx/t7xx_port_wwan.c @@ -152,14 +152,15 @@ static int t7xx_port_wwan_disable_chl(struct t7xx_port *port) static void t7xx_port_wwan_md_state_notify(struct t7xx_port *port, unsigned int state) { const struct t7xx_port_conf *port_conf = port->port_conf; - unsigned int header_len = sizeof(struct ccci_header); + unsigned int header_len = sizeof(struct ccci_header), mtu; struct wwan_port_caps caps; if (state != MD_STATE_READY) return; if (!port->wwan.wwan_port) { - caps.frag_len = CLDMA_MTU - header_len; + mtu = t7xx_get_port_mtu(port); + caps.frag_len = mtu - header_len; caps.headroom_len = header_len; port->wwan.wwan_port = wwan_create_port(port->dev, port_conf->port_type, &wwan_ops, &caps, port); diff --git a/drivers/net/wwan/t7xx/t7xx_reg.h b/drivers/net/wwan/t7xx/t7xx_reg.h index c41d7d094c08..3b665c6116fe 100644 --- a/drivers/net/wwan/t7xx/t7xx_reg.h +++ b/drivers/net/wwan/t7xx/t7xx_reg.h @@ -102,10 +102,26 @@ enum t7xx_pm_resume_state { }; #define T7XX_PCIE_MISC_DEV_STATUS 0x0d1c -#define MISC_STAGE_MASK GENMASK(2, 0) -#define MISC_RESET_TYPE_PLDR BIT(26) #define MISC_RESET_TYPE_FLDR BIT(27) -#define LINUX_STAGE 4 +#define MISC_RESET_TYPE_PLDR BIT(26) +#define MISC_LK_EVENT_MASK GENMASK(11, 8) + +enum lk_event_id { + LK_EVENT_NORMAL = 0, + LK_EVENT_CREATE_PD_PORT = 1, + LK_EVENT_CREATE_POST_DL_PORT = 2, + LK_EVENT_RESET = 7, +}; + +#define MISC_STAGE_MASK GENMASK(2, 0) + +enum t7xx_device_stage { + T7XX_DEV_STAGE_INIT = 0, + T7XX_DEV_STAGE_BROM_PRE = 1, + T7XX_DEV_STAGE_BROM_POST = 2, + T7XX_DEV_STAGE_LK = 3, + T7XX_DEV_STAGE_LINUX = 4, +}; #define T7XX_PCIE_RESOURCE_STATUS 0x0d28 #define T7XX_PCIE_RESOURCE_STS_MSK GENMASK(4, 0) diff --git a/drivers/net/wwan/t7xx/t7xx_state_monitor.c b/drivers/net/wwan/t7xx/t7xx_state_monitor.c index 80edb8e75a6a..9c51e332e7c5 100644 --- a/drivers/net/wwan/t7xx/t7xx_state_monitor.c +++ b/drivers/net/wwan/t7xx/t7xx_state_monitor.c @@ -206,6 +206,34 @@ static void fsm_routine_exception(struct t7xx_fsm_ctl *ctl, struct t7xx_fsm_comm fsm_finish_command(ctl, cmd, 0); } +static void t7xx_lk_stage_event_handling(struct t7xx_fsm_ctl *ctl, unsigned int status) +{ + struct t7xx_modem *md = ctl->md; + struct cldma_ctrl *md_ctrl; + enum lk_event_id lk_event; + struct device *dev; + + dev = &md->t7xx_dev->pdev->dev; + lk_event = FIELD_GET(MISC_LK_EVENT_MASK, status); + switch (lk_event) { + case LK_EVENT_NORMAL: + case LK_EVENT_RESET: + break; + + case LK_EVENT_CREATE_PD_PORT: + md_ctrl = md->md_ctrl[CLDMA_ID_AP]; + t7xx_cldma_hif_hw_init(md_ctrl); + t7xx_cldma_stop(md_ctrl); + t7xx_cldma_switch_cfg(md_ctrl, CLDMA_DEDICATED_Q_CFG); + t7xx_cldma_start(md_ctrl); + break; + + default: + dev_err(dev, "Invalid LK event %d\n", lk_event); + break; + } +} + static int fsm_stopped_handler(struct t7xx_fsm_ctl *ctl) { ctl->curr_state = FSM_STATE_STOPPED; @@ -317,7 +345,8 @@ static int fsm_routine_starting(struct t7xx_fsm_ctl *ctl) static void fsm_routine_start(struct t7xx_fsm_ctl *ctl, struct t7xx_fsm_command *cmd) { struct t7xx_modem *md = ctl->md; - u32 dev_status; + struct device *dev; + u32 status; int ret; if (!md) @@ -329,23 +358,57 @@ static void fsm_routine_start(struct t7xx_fsm_ctl *ctl, struct t7xx_fsm_command return; } + dev = &md->t7xx_dev->pdev->dev; ctl->curr_state = FSM_STATE_PRE_START; t7xx_md_event_notify(md, FSM_PRE_START); - ret = read_poll_timeout(ioread32, dev_status, - (dev_status & MISC_STAGE_MASK) == LINUX_STAGE, 20000, 2000000, - false, IREG_BASE(md->t7xx_dev) + T7XX_PCIE_MISC_DEV_STATUS); + ret = read_poll_timeout(ioread32, status, + ((status & MISC_STAGE_MASK) == T7XX_DEV_STAGE_LINUX) || + ((status & MISC_STAGE_MASK) == T7XX_DEV_STAGE_LK), 100000, + 20000000, false, IREG_BASE(md->t7xx_dev) + + T7XX_PCIE_MISC_DEV_STATUS); + if (ret) { - struct device *dev = &md->t7xx_dev->pdev->dev; + dev_err(dev, "read poll timeout %d\n", ret); + goto finish_command; + } - fsm_finish_command(ctl, cmd, -ETIMEDOUT); - dev_err(dev, "Invalid device status 0x%lx\n", dev_status & MISC_STAGE_MASK); - return; + if (status != ctl->prev_status || cmd->flag != 0) { + u32 stage = FIELD_GET(MISC_STAGE_MASK, status); + + switch (stage) { + case T7XX_DEV_STAGE_INIT: + case T7XX_DEV_STAGE_BROM_PRE: + case T7XX_DEV_STAGE_BROM_POST: + dev_dbg(dev, "BROM_STAGE Entered\n"); + ret = t7xx_fsm_append_cmd(ctl, FSM_CMD_START, 0); + break; + + case T7XX_DEV_STAGE_LK: + dev_dbg(dev, "LK_STAGE Entered\n"); + t7xx_lk_stage_event_handling(ctl, status); + break; + + case T7XX_DEV_STAGE_LINUX: + dev_dbg(dev, "LINUX_STAGE Entered\n"); + t7xx_mhccif_mask_clr(md->t7xx_dev, D2H_INT_PORT_ENUM | + D2H_INT_ASYNC_MD_HK | D2H_INT_ASYNC_AP_HK); + if (cmd->flag == 0) + break; + t7xx_cldma_hif_hw_init(md->md_ctrl[CLDMA_ID_AP]); + t7xx_cldma_hif_hw_init(md->md_ctrl[CLDMA_ID_MD]); + t7xx_port_proxy_set_cfg(md, PORT_CFG_ID_NORMAL); + ret = fsm_routine_starting(ctl); + break; + + default: + break; + } + ctl->prev_status = status; } - t7xx_cldma_hif_hw_init(md->md_ctrl[CLDMA_ID_AP]); - t7xx_cldma_hif_hw_init(md->md_ctrl[CLDMA_ID_MD]); - fsm_finish_command(ctl, cmd, fsm_routine_starting(ctl)); +finish_command: + fsm_finish_command(ctl, cmd, ret); } static int fsm_main_thread(void *data) @@ -516,6 +579,7 @@ void t7xx_fsm_reset(struct t7xx_modem *md) fsm_flush_event_cmd_qs(ctl); ctl->curr_state = FSM_STATE_STOPPED; ctl->exp_flg = false; + ctl->prev_status = 0; } int t7xx_fsm_init(struct t7xx_modem *md) diff --git a/drivers/net/wwan/t7xx/t7xx_state_monitor.h b/drivers/net/wwan/t7xx/t7xx_state_monitor.h index b6e76f3903c8..5e8012567ba1 100644 --- a/drivers/net/wwan/t7xx/t7xx_state_monitor.h +++ b/drivers/net/wwan/t7xx/t7xx_state_monitor.h @@ -96,6 +96,7 @@ struct t7xx_fsm_ctl { bool exp_flg; spinlock_t notifier_lock; /* Protects notifier list */ struct list_head notifier_list; + u32 prev_status; }; struct t7xx_fsm_event { From patchwork Tue Sep 12 09:48:42 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jinjian Song X-Patchwork-Id: 13381202 X-Patchwork-Delegate: kuba@kernel.org Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B70DC23A6 for ; Tue, 12 Sep 2023 09:49:47 +0000 (UTC) Received: from AUS01-ME3-obe.outbound.protection.outlook.com (mail-me3aus01olkn2175.outbound.protection.outlook.com [40.92.63.175]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D97C2E6C; Tue, 12 Sep 2023 02:49:46 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=a2ZMqnrJtXPa5EPv4Ihnr7FuW4cgPZzt7f2fvo7GISN9BJyQuYDTPPXPv+D7rTzVMp0ZLD2ItHD6R4+wvFk74LhEITU3nShck6OQeBZ1+nYyEmbL5rb7TUTSGZAcD3UY36ro9vC1QkF7ou7497RBr8ykR1cuV4z6YOktCJtinp3KwWrg4KQVYhU/sIEf6epvtUmQ93Vby8n7XGTMRtdQHT8pVYd8qDzq+GMn2J66LiObss0Q13peS+X0v2SI/04idncd2bdKH0kf8MhIZPRw/YjRR0dYyn7Sfh6iiBgXGEFJef0cOuc86QBxgXFRuuwgqhp10oCsVB8GobL4ooz6ew== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; 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; bh=F0kHDrQc5x1gLsYC9lu18yg0qGADXmyvgcCdOUQTgEA=; b=S8GgfY9/QNbM8WSENosUwv2BTMlk5mK4A7SXwFcvMP7zyeN4IskDSfRxgULLUUIVrj0Fwi4O0oqP32JrKxue4Q/CnrDBb3triP2Ee8a2LCCFhC6Zkya7r8zrg6eIZ4AiX8SRqgRu3PfS2d90rUDGxXm6uPDM/pesDnJOTTBJDDbPJwcqfwhPxBQtAja2HbxeZwrpHMX/Kf28qrcLBJvPWT5Gg4g2U6QdObL+Cxgz8p24ic/0Eh2pSN3/+5zJ+aSPbh5kgaeQnmOC7hPxEqkNLoLHHHPo0Ywq3h7iVngjeE0bUta9C9fdzV36ZQlqkC7Gm1rqHaYao7XkVTX+KWOIOg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=none; dmarc=none; dkim=none; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=hotmail.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=F0kHDrQc5x1gLsYC9lu18yg0qGADXmyvgcCdOUQTgEA=; b=Z7cqjhkFqTvk+dhHw7IHfiDWznXYRYVM2TuGZUPrPc1yb5yrdsB+G0CA68pP296jlufcfbZnDOEBlVAWuclcDx/M5yO1a4QBmHjCC5fjb9JkvAlOSFUbRs0txl/Oo+ylnYsbvKpaWeMQcCeH8zVCWlU8iGJ9/qWoScIAbFvS3ZcPAC+NoguItVm7dfm0hmjfpDuxCnEJ0QEAi8MqG20CM35LzqmuHAUZGP00EX6pVFA0v9JCOYMX+R9H9/ADZGW4mikp4lXr35l+Fa0znk8PQo9vFAofjSP0Z24ak8xhlE9Dcanqk3nyoaUA8bRmBn9w0ya2C8zEXc2xFwB28A9MKg== Received: from ME3P282MB2703.AUSP282.PROD.OUTLOOK.COM (2603:10c6:220:16b::5) by SY4P282MB2981.AUSP282.PROD.OUTLOOK.COM (2603:10c6:10:15c::13) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6768.35; Tue, 12 Sep 2023 09:49:39 +0000 Received: from ME3P282MB2703.AUSP282.PROD.OUTLOOK.COM ([fe80::68b4:6263:97f:9a45]) by ME3P282MB2703.AUSP282.PROD.OUTLOOK.COM ([fe80::68b4:6263:97f:9a45%3]) with mapi id 15.20.6768.036; Tue, 12 Sep 2023 09:49:39 +0000 From: Jinjian Song To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, corbet@lwn.net, loic.poulain@linaro.org, ryazanov.s.a@gmail.com Cc: jiri@resnulli.us, johannes@sipsolutions.net, chandrashekar.devegowda@intel.com, linuxwwan@intel.com, chiranjeevi.rapolu@linux.intel.com, haijun.liu@mediatek.com, m.chetan.kumar@linux.intel.com, ricardo.martinez@linux.intel.com, netdev@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, nmarupaka@google.com, vsankar@lenovo.com, danielwinkler@google.com, Jinjian Song Subject: [net-next v4 2/5] net: wwan: t7xx: Register with devlink and implement firmware flashing Date: Tue, 12 Sep 2023 17:48:42 +0800 Message-ID: X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230912094845.11233-1-songjinjian@hotmail.com> References: <20230912094845.11233-1-songjinjian@hotmail.com> X-TMN: [yM78TcBkNZGmr4Ntoyn9ZQtYD46Qwmyt] X-ClientProxiedBy: SI2PR01CA0048.apcprd01.prod.exchangelabs.com (2603:1096:4:193::17) To ME3P282MB2703.AUSP282.PROD.OUTLOOK.COM (2603:10c6:220:16b::5) X-Microsoft-Original-Message-ID: <20230912094845.11233-3-songjinjian@hotmail.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: ME3P282MB2703:EE_|SY4P282MB2981:EE_ X-MS-Office365-Filtering-Correlation-Id: ee0fd639-05c7-48b4-8481-08dbb375946e X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: s4OjoZPdeUGNvIeEah+gzZFoLKe3L5YL6Pzmnwh07BWun2ns8hYqgTUdj8r6/7VHqkdRxiArUCUNzmr6ojoPjtp+ldrUPB59oV+NbWiZfb7fZn3YJRKcpbJFsrGxXwsrlqlATwEK2s0NO80OPny6Gj0fxj2J0S8hK/VBRwamOJXE2MLJpVdEmHfZde75JZlwP4O4pjwSBuZUG5tw7rDjBWYkqj/3utfiUQAvcpfscXjCSKNhNsiivg46jncI+Q6cB6snZiHd4ARHC30lQ+Xe1Lzzl9ea3bpWlHesSnZ1CgaBXpXx7BWtW6dA/Npshr58wpZZ4ihUUbsQ2X8Hyqd+mcc1c7aL4NrYOoHfVcOnBq5hbvQibuAWcMieVeF9174jQ73HlAhJrvTK+ysUBROLeV9PAq+Uw46mqYElHU78cpi5SSsSAr23/v0DqDN/X1AO1Vc3XIpwRtW7zuvfUJAOO8uIf7Afwc0nLW24hD7Idr087o5h6QU8sqayp6OL+cZ/R98jBSHgTOulH+0lzshoC6xbb/J5G1sf2okH9sTT3C8lUCk/9uFnVoO9t4aeRD6En+8U7RU696cm/6Ued01TgCwTma5/6buqRchNSwKtl4o= X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: TtVYiaG+rXUhj3QRQWiLOivDVCe8ahcwqFYUV8heU2zJgldOp6meMBt+jXcCRLBxPiiotoGzUz8vC0X3D3/VUcTvsH4IUrZwMCpH8eyVjmKvJI+cjZwaN8AFsMtK0BF2EAPKHnvDS7jI+Y0PRiwgyuC4DjSTeN2TIzHKPhQCilNPcGgxpd8AkJ9PwSmQW+hzll5iZRLoVJTjAf0vrFBZDrhxWR3RL6vWKqCPw6bTEldgFLEDYdiAOn35rt8CZwuFgVnwzACocUemoyjwPAPX8VxpZd4vq870uYOznPmPbyEzEnzqvebzgifqpFzfRFRIef6cABL8zEalDijOPJaW7WOAKMJz3VwpqA6ya610aSlh0KeY9WGU7sdRZk6xNJy/JXvHAmoiIr0VSFUVcBm5IeS0JFz5MNpJbIiy4NzbT0n/jK6obd6bfvFfl1+WEjrLJ6AVSKd/qqv8I00KMIQoraF2OOyInl8komz+mHQo2Ab//azXNPufftUyyiz+euvgEAbF6ClLOxCXBRl1NnYUmsoMwSHhzRrI2LIrJyE/3Oz3PbQ+/nFjvka3/ztQTbhgUf9j2Bq4kNISYKv7xhuNtfP0lZYvgRlIN0DVwwf8f1qM8Hm2Ya+z2NWhhkDSia1P438X2eSkSUAuwaN3Ht/U95jLADOLMX7DXWsvqllgGUDn8J2cACz+zjdtg1A48FFQBxVvQGnYXkQgt6+kp+h8kL9aCxq+nF6Kv6YyUfJPeW0xKavu6wV+VyifpYs32aOiu0Ekv/o3XmojqoaqtHUG8M1sjr2ZiMqEEclWBmHEVezzgqHDa5eE+6BXg4rWE6pLS/rY0ZMJMLlq37RI4HEa5jMrWJ2S4/VXEczKiwgsGGQm476Hx5XuX5E+K4PfNhHjPoFfPHnkxVpMCjG8YUvOiXlCsQ14YPAbNIvthfcO2ZItnoUVhHGyV7xOukEV7q1AmO6xIOZiLV/HHE1ZsTVGDDsQeW6iG1X90wJCSRzvIaIPtUboqoEV3aK0gXU5PlzWWQ8efBAFZNTUrkK98eEcbpSVOR9XuejijelSgcy6pxn1weXljE+E42pEwJ3PVaLCMcobWW38hhaRhEU6p8YSI2KSiwTk7KNkjuL0lCkzB3yC2fAIKkoZ/QmkkRBROkNSvd4Rim8JEXEP9ugph2KI4DCd84qJdTvCFsQFbfTxFCi2aeH3nBZtHW028/OIgUyFOqOERyVdRY04CJ3nH9lOrM4iyi99775MuzaBlgbnGOI= X-OriginatorOrg: sct-15-20-4755-11-msonline-outlook-746f3.templateTenant X-MS-Exchange-CrossTenant-Network-Message-Id: ee0fd639-05c7-48b4-8481-08dbb375946e X-MS-Exchange-CrossTenant-AuthSource: ME3P282MB2703.AUSP282.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Sep 2023 09:49:39.1009 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 84df9e7f-e9f6-40af-b435-aaaaaaaaaaaa X-MS-Exchange-CrossTenant-RMS-PersistedConsumerOrg: 00000000-0000-0000-0000-000000000000 X-MS-Exchange-Transport-CrossTenantHeadersStamped: SY4P282MB2981 X-Patchwork-Delegate: kuba@kernel.org From: Jinjian Song Adds support for t7xx wwan device firmware flashing using devlink. On early detection of wwan device in fastboot mode driver sets up CLDMA0 HW tx/rx queues for raw data transfer and then registers to devlink framework. On user space application issuing command for firmware update the driver sends fastboot flash command & firmware to program NAND. In flashing procedure the fastboot command & response are exchanged between driver and device. Below is the devlink command usage for firmware flashing $devlink dev flash pci/$BDF file ABC.img component ABC Note: ABC.img is the firmware to be programmed to "ABC" partition. Base on the v5 patch version of follow series: 'net: wwan: t7xx: fw flashing & coredump support' (https://patchwork.kernel.org/project/netdevbpf/patch/fc8bbb0b66a5ff3a489ea9857d79b374508090ef.1674307425.git.m.chetan.kumar@linux.intel.com/) Signed-off-by: Jinjian Song --- v4: * no change v3: * no change v2: * modify functions and struct name from devlink to flash_dump * delete stub funtions * delete devlink_flash_update_status_notify * delete devlink_info_get_loopbak --- drivers/net/wwan/Kconfig | 1 + drivers/net/wwan/t7xx/Makefile | 4 +- drivers/net/wwan/t7xx/t7xx_pci.c | 17 +- drivers/net/wwan/t7xx/t7xx_pci.h | 2 + drivers/net/wwan/t7xx/t7xx_port.h | 2 + drivers/net/wwan/t7xx/t7xx_port_ap_msg.c | 78 ++++ drivers/net/wwan/t7xx/t7xx_port_ap_msg.h | 11 + drivers/net/wwan/t7xx/t7xx_port_flash_dump.c | 427 +++++++++++++++++++ drivers/net/wwan/t7xx/t7xx_port_flash_dump.h | 45 ++ drivers/net/wwan/t7xx/t7xx_port_proxy.c | 32 ++ drivers/net/wwan/t7xx/t7xx_port_proxy.h | 4 + drivers/net/wwan/t7xx/t7xx_port_wwan.c | 22 +- drivers/net/wwan/t7xx/t7xx_reg.h | 6 + drivers/net/wwan/t7xx/t7xx_state_monitor.c | 42 +- 14 files changed, 663 insertions(+), 30 deletions(-) create mode 100644 drivers/net/wwan/t7xx/t7xx_port_ap_msg.c create mode 100644 drivers/net/wwan/t7xx/t7xx_port_ap_msg.h create mode 100644 drivers/net/wwan/t7xx/t7xx_port_flash_dump.c create mode 100644 drivers/net/wwan/t7xx/t7xx_port_flash_dump.h diff --git a/drivers/net/wwan/Kconfig b/drivers/net/wwan/Kconfig index 410b0245114e..dd7a9883c1ff 100644 --- a/drivers/net/wwan/Kconfig +++ b/drivers/net/wwan/Kconfig @@ -108,6 +108,7 @@ config IOSM config MTK_T7XX tristate "MediaTek PCIe 5G WWAN modem T7xx device" depends on PCI + select NET_DEVLINK select RELAY if WWAN_DEBUGFS help Enables MediaTek PCIe based 5G WWAN modem (T7xx series) device. diff --git a/drivers/net/wwan/t7xx/Makefile b/drivers/net/wwan/t7xx/Makefile index 2652cd00504e..e5785bae64d5 100644 --- a/drivers/net/wwan/t7xx/Makefile +++ b/drivers/net/wwan/t7xx/Makefile @@ -15,7 +15,9 @@ mtk_t7xx-y:= t7xx_pci.o \ t7xx_hif_dpmaif_tx.o \ t7xx_hif_dpmaif_rx.o \ t7xx_dpmaif.o \ - t7xx_netdev.o + t7xx_netdev.o \ + t7xx_port_flash_dump.o \ + t7xx_port_ap_msg.o mtk_t7xx-$(CONFIG_WWAN_DEBUGFS) += \ t7xx_port_trace.o \ diff --git a/drivers/net/wwan/t7xx/t7xx_pci.c b/drivers/net/wwan/t7xx/t7xx_pci.c index 91256e005b84..845d1555f134 100644 --- a/drivers/net/wwan/t7xx/t7xx_pci.c +++ b/drivers/net/wwan/t7xx/t7xx_pci.c @@ -39,6 +39,7 @@ #include "t7xx_modem_ops.h" #include "t7xx_pci.h" #include "t7xx_pcie_mac.h" +#include "t7xx_port_flash_dump.h" #include "t7xx_reg.h" #include "t7xx_state_monitor.h" @@ -108,7 +109,7 @@ static int t7xx_pci_pm_init(struct t7xx_pci_dev *t7xx_dev) pm_runtime_set_autosuspend_delay(&pdev->dev, PM_AUTOSUSPEND_MS); pm_runtime_use_autosuspend(&pdev->dev); - return t7xx_wait_pm_config(t7xx_dev); + return 0; } void t7xx_pci_pm_init_late(struct t7xx_pci_dev *t7xx_dev) @@ -723,22 +724,30 @@ static int t7xx_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) t7xx_pci_infracfg_ao_calc(t7xx_dev); t7xx_mhccif_init(t7xx_dev); - ret = t7xx_md_init(t7xx_dev); + ret = t7xx_devlink_register(t7xx_dev); if (ret) return ret; + ret = t7xx_md_init(t7xx_dev); + if (ret) + goto err_devlink_unregister; + t7xx_pcie_mac_interrupts_dis(t7xx_dev); ret = t7xx_interrupt_init(t7xx_dev); if (ret) { t7xx_md_exit(t7xx_dev); - return ret; + goto err_devlink_unregister; } t7xx_pcie_mac_set_int(t7xx_dev, MHCCIF_INT); t7xx_pcie_mac_interrupts_en(t7xx_dev); return 0; + +err_devlink_unregister: + t7xx_devlink_unregister(t7xx_dev); + return ret; } static void t7xx_pci_remove(struct pci_dev *pdev) @@ -757,6 +766,8 @@ static void t7xx_pci_remove(struct pci_dev *pdev) } pci_free_irq_vectors(t7xx_dev->pdev); + + t7xx_devlink_unregister(t7xx_dev); } static const struct pci_device_id t7xx_pci_table[] = { diff --git a/drivers/net/wwan/t7xx/t7xx_pci.h b/drivers/net/wwan/t7xx/t7xx_pci.h index f08f1ab74469..28f22a2dc493 100644 --- a/drivers/net/wwan/t7xx/t7xx_pci.h +++ b/drivers/net/wwan/t7xx/t7xx_pci.h @@ -59,6 +59,7 @@ typedef irqreturn_t (*t7xx_intr_callback)(int irq, void *param); * @md_pm_lock: protects PCIe sleep lock * @sleep_disable_count: PCIe L1.2 lock counter * @sleep_lock_acquire: indicates that sleep has been disabled + * @flash_dump: devlink struct */ struct t7xx_pci_dev { t7xx_intr_callback intr_handler[EXT_INT_NUM]; @@ -82,6 +83,7 @@ struct t7xx_pci_dev { #ifdef CONFIG_WWAN_DEBUGFS struct dentry *debugfs_dir; #endif + struct t7xx_flash_dump *flash_dump; }; enum t7xx_pm_id { diff --git a/drivers/net/wwan/t7xx/t7xx_port.h b/drivers/net/wwan/t7xx/t7xx_port.h index 09acb1ef144d..dfa7ad2a9796 100644 --- a/drivers/net/wwan/t7xx/t7xx_port.h +++ b/drivers/net/wwan/t7xx/t7xx_port.h @@ -42,6 +42,8 @@ enum port_ch { /* to AP */ PORT_CH_AP_CONTROL_RX = 0x1000, PORT_CH_AP_CONTROL_TX = 0x1001, + PORT_CH_AP_MSG_RX = 0x101E, + PORT_CH_AP_MSG_TX = 0x101F, /* to MD */ PORT_CH_CONTROL_RX = 0x2000, diff --git a/drivers/net/wwan/t7xx/t7xx_port_ap_msg.c b/drivers/net/wwan/t7xx/t7xx_port_ap_msg.c new file mode 100644 index 000000000000..46f311a38fbb --- /dev/null +++ b/drivers/net/wwan/t7xx/t7xx_port_ap_msg.c @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2022-2023, Intel Corporation. + */ + +#include "t7xx_port.h" +#include "t7xx_port_proxy.h" +#include "t7xx_port_flash_dump.h" +#include "t7xx_state_monitor.h" +#include "t7xx_port_ap_msg.h" + +int t7xx_port_ap_msg_tx(struct t7xx_port *port, char *buff, size_t len) +{ + const struct t7xx_port_conf *port_conf; + size_t offset, chunk_len = 0, txq_mtu; + struct t7xx_fsm_ctl *ctl; + struct sk_buff *skb_ccci; + enum md_state md_state; + int ret; + + if (!len || !port->chan_enable) + return -EINVAL; + + port_conf = port->port_conf; + ctl = port->t7xx_dev->md->fsm_ctl; + md_state = t7xx_fsm_get_md_state(ctl); + if (md_state == MD_STATE_WAITING_FOR_HS1 || md_state == MD_STATE_WAITING_FOR_HS2) { + dev_warn(port->dev, "Cannot write to %s port when md_state=%d\n", + port_conf->name, md_state); + return -ENODEV; + } + + txq_mtu = t7xx_get_port_mtu(port); + for (offset = 0; offset < len; offset += chunk_len) { + chunk_len = min(len - offset, txq_mtu - sizeof(struct ccci_header)); + skb_ccci = t7xx_port_alloc_skb(chunk_len); + if (!skb_ccci) + return -ENOMEM; + + skb_put_data(skb_ccci, buff + offset, chunk_len); + ret = t7xx_port_send_skb(port, skb_ccci, 0, 0); + if (ret) { + dev_kfree_skb_any(skb_ccci); + dev_err(port->dev, "Write error on %s port, %d\n", + port_conf->name, ret); + return ret; + } + } + + return len; +} + +static int t7xx_port_ap_msg_init(struct t7xx_port *port) +{ + struct t7xx_flash_dump *flash_dump = port->t7xx_dev->flash_dump; + + port->rx_length_th = T7XX_MAX_QUEUE_LENGTH; + flash_dump->status = T7XX_DEVLINK_IDLE; + flash_dump->port = port; + + return 0; +} + +static void t7xx_port_ap_msg_uninit(struct t7xx_port *port) +{ + struct t7xx_flash_dump *flash_dump = port->t7xx_dev->flash_dump; + + flash_dump->mode = T7XX_NORMAL_MODE; + skb_queue_purge(&port->rx_skb_list); +} + +struct port_ops ap_msg_port_ops = { + .init = &t7xx_port_ap_msg_init, + .recv_skb = &t7xx_port_enqueue_skb, + .uninit = &t7xx_port_ap_msg_uninit, + .enable_chl = &t7xx_port_enable_chl, + .disable_chl = &t7xx_port_disable_chl, +}; diff --git a/drivers/net/wwan/t7xx/t7xx_port_ap_msg.h b/drivers/net/wwan/t7xx/t7xx_port_ap_msg.h new file mode 100644 index 000000000000..4838d87d86cf --- /dev/null +++ b/drivers/net/wwan/t7xx/t7xx_port_ap_msg.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0-only + * + * Copyright (c) 2022-2023, Intel Corporation. + */ + +#ifndef __T7XX_PORT_AP_MSG_H__ +#define __T7XX_PORT_AP_MSG_H__ + +int t7xx_port_ap_msg_tx(struct t7xx_port *port, char *buff, size_t len); + +#endif /* __T7XX_PORT_AP_MSG_H__ */ diff --git a/drivers/net/wwan/t7xx/t7xx_port_flash_dump.c b/drivers/net/wwan/t7xx/t7xx_port_flash_dump.c new file mode 100644 index 000000000000..1129ef793798 --- /dev/null +++ b/drivers/net/wwan/t7xx/t7xx_port_flash_dump.c @@ -0,0 +1,427 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2022-2023, Intel Corporation. + */ + +#include + +#include "t7xx_port_proxy.h" +#include "t7xx_port_ap_msg.h" +#include "t7xx_port_flash_dump.h" + +static int t7xx_flash_dump_port_read(struct t7xx_port *port, char *buf, size_t count) +{ + struct sk_buff *skb; + int read_len; + + spin_lock_irq(&port->rx_wq.lock); + if (skb_queue_empty(&port->rx_skb_list)) { + int ret = wait_event_interruptible_locked_irq(port->rx_wq, + !skb_queue_empty(&port->rx_skb_list)); + if (ret == -ERESTARTSYS) { + spin_unlock_irq(&port->rx_wq.lock); + return ret; + } + } + skb = skb_dequeue(&port->rx_skb_list); + spin_unlock_irq(&port->rx_wq.lock); + + read_len = min_t(size_t, count, skb->len); + memcpy(buf, skb->data, read_len); + + if (read_len < skb->len) { + skb_pull(skb, read_len); + skb_queue_head(&port->rx_skb_list, skb); + } else { + consume_skb(skb); + } + + return read_len; +} + +static int t7xx_flash_dump_port_write(struct t7xx_port *port, const char *buf, size_t count) +{ + const struct t7xx_port_conf *port_conf = port->port_conf; + size_t actual = count, offset = 0; + int txq_mtu; + + txq_mtu = t7xx_get_port_mtu(port); + if (txq_mtu < 0) + return -EINVAL; + + while (actual) { + int len = min_t(size_t, actual, txq_mtu); + struct sk_buff *skb; + int ret; + + skb = __dev_alloc_skb(len, GFP_KERNEL); + if (!skb) + return -ENOMEM; + + skb_put_data(skb, buf + offset, len); + ret = t7xx_port_send_raw_skb(port, skb); + if (ret) { + dev_err(port->dev, "write error on %s, size: %d, ret: %d\n", + port_conf->name, len, ret); + dev_kfree_skb(skb); + return ret; + } + + offset += len; + actual -= len; + } + + return count; +} + +static int t7xx_flash_dump_fb_handle_response(struct t7xx_port *port, char *data) +{ + char status[T7XX_FB_RESPONSE_SIZE + 1]; + int ret = 0, index; + + for (index = 0; index < T7XX_FB_RESP_COUNT; index++) { + int read_bytes = t7xx_flash_dump_port_read(port, status, T7XX_FB_RESPONSE_SIZE); + + if (read_bytes < 0) { + dev_err(port->dev, "status read interrupted\n"); + ret = read_bytes; + break; + } + + status[read_bytes] = '\0'; + dev_dbg(port->dev, "raw response from device: %s\n", status); + if (!strncmp(status, T7XX_FB_RESP_INFO, strlen(T7XX_FB_RESP_INFO))) { + break; + } else if (!strncmp(status, T7XX_FB_RESP_OKAY, strlen(T7XX_FB_RESP_OKAY))) { + break; + } else if (!strncmp(status, T7XX_FB_RESP_FAIL, strlen(T7XX_FB_RESP_FAIL))) { + ret = -EPROTO; + break; + } else if (!strncmp(status, T7XX_FB_RESP_DATA, strlen(T7XX_FB_RESP_DATA))) { + if (data) + snprintf(data, T7XX_FB_RESPONSE_SIZE, "%s", + status + strlen(T7XX_FB_RESP_DATA)); + break; + } + } + + return ret; +} + +static int t7xx_flash_dump_fb_raw_command(char *cmd, struct t7xx_port *port, char *data) +{ + int ret, cmd_size = strlen(cmd); + + if (cmd_size > T7XX_FB_COMMAND_SIZE) { + dev_err(port->dev, "command length %d is long\n", cmd_size); + return -EINVAL; + } + + if (cmd_size != t7xx_flash_dump_port_write(port, cmd, cmd_size)) { + dev_err(port->dev, "raw command = %s write failed\n", cmd); + return -EIO; + } + + dev_dbg(port->dev, "raw command = %s written to the device\n", cmd); + ret = t7xx_flash_dump_fb_handle_response(port, data); + if (ret) + dev_err(port->dev, "raw command = %s response FAILURE:%d\n", cmd, ret); + + return ret; +} + +static int t7xx_flash_dump_fb_download_command(struct t7xx_port *port, size_t size) +{ + char download_command[T7XX_FB_COMMAND_SIZE]; + + snprintf(download_command, sizeof(download_command), "%s:%08zx", + T7XX_FB_CMD_DOWNLOAD, size); + return t7xx_flash_dump_fb_raw_command(download_command, port, NULL); +} + +static int t7xx_flash_dump_fb_download(struct t7xx_port *port, const u8 *buf, size_t size) +{ + int ret; + + if (!size) + return -EINVAL; + + ret = t7xx_flash_dump_fb_download_command(port, size); + if (ret) + return ret; + + ret = t7xx_flash_dump_port_write(port, buf, size); + if (ret < 0) + return ret; + + return t7xx_flash_dump_fb_handle_response(port, NULL); +} + +static int t7xx_flash_dump_fb_flash(struct t7xx_port *port, const char *cmd) +{ + char flash_command[T7XX_FB_COMMAND_SIZE]; + + snprintf(flash_command, sizeof(flash_command), "%s:%s", T7XX_FB_CMD_FLASH, cmd); + return t7xx_flash_dump_fb_raw_command(flash_command, port, NULL); +} + +static int t7xx_flash_dump_fb_flash_partition(struct t7xx_port *port, const char *partition, + const u8 *buf, size_t size) +{ + int ret; + + ret = t7xx_flash_dump_fb_download(port, buf, size); + if (ret < 0) + return ret; + + return t7xx_flash_dump_fb_flash(port, partition); +} + +static int t7xx_devlink_flash_update(struct devlink *devlink, + struct devlink_flash_update_params *params, + struct netlink_ext_ack *extack) +{ + struct t7xx_flash_dump *flash_dump = devlink_priv(devlink); + const char *component = params->component; + const struct firmware *fw = params->fw; + struct t7xx_port *port; + int ret; + + if (flash_dump->mode != T7XX_FB_DL_MODE) { + dev_err(&flash_dump->t7xx_dev->pdev->dev, "Modem is not in fastboot download mode!\n"); + ret = -EPERM; + goto err_out; + } + + if (flash_dump->status != T7XX_DEVLINK_IDLE) { + dev_err(&flash_dump->t7xx_dev->pdev->dev, "Modem is busy!\n"); + ret = -EBUSY; + goto err_out; + } + + if (!component || !fw->data) { + ret = -EINVAL; + goto err_out; + } + + set_bit(T7XX_FLASH_STATUS, &flash_dump->status); + port = flash_dump->port; + dev_dbg(port->dev, "flash partition name:%s binary size:%zu\n", component, fw->size); + ret = t7xx_flash_dump_fb_flash_partition(port, component, fw->data, fw->size); + clear_bit(T7XX_FLASH_STATUS, &flash_dump->status); + +err_out: + return ret; +} + +enum t7xx_devlink_param_id { + T7XX_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX, + T7XX_DEVLINK_PARAM_ID_FASTBOOT, +}; + +static const struct devlink_param t7xx_devlink_params[] = { + DEVLINK_PARAM_DRIVER(T7XX_DEVLINK_PARAM_ID_FASTBOOT, + "fastboot", DEVLINK_PARAM_TYPE_BOOL, + BIT(DEVLINK_PARAM_CMODE_DRIVERINIT), + NULL, NULL, NULL), +}; + +bool t7xx_devlink_param_get_fastboot(struct devlink *devlink) +{ + union devlink_param_value saved_value; + + devl_param_driverinit_value_get(devlink, T7XX_DEVLINK_PARAM_ID_FASTBOOT, + &saved_value); + return saved_value.vbool; +} + +static int t7xx_devlink_reload_down(struct devlink *devlink, bool netns_change, + enum devlink_reload_action action, + enum devlink_reload_limit limit, + struct netlink_ext_ack *extack) +{ + struct t7xx_flash_dump *flash_dump = devlink_priv(devlink); + + switch (action) { + case DEVLINK_RELOAD_ACTION_DRIVER_REINIT: + return 0; + case DEVLINK_RELOAD_ACTION_FW_ACTIVATE: + if (!flash_dump->mode) + return -EPERM; + return t7xx_flash_dump_fb_raw_command(T7XX_FB_CMD_REBOOT, flash_dump->port, NULL); + default: + /* Unsupported action should not get to this function */ + return -EOPNOTSUPP; + } +} + +static int t7xx_devlink_reload_up(struct devlink *devlink, + enum devlink_reload_action action, + enum devlink_reload_limit limit, + u32 *actions_performed, + struct netlink_ext_ack *extack) +{ + *actions_performed = BIT(action); + switch (action) { + case DEVLINK_RELOAD_ACTION_DRIVER_REINIT: + case DEVLINK_RELOAD_ACTION_FW_ACTIVATE: + return 0; + default: + /* Unsupported action should not get to this function */ + return -EOPNOTSUPP; + } +} + +static int t7xx_flash_dump_get_part_ver_fb_mode(struct t7xx_port *port, const char *cmd, char *data) +{ + char req_command[T7XX_FB_COMMAND_SIZE]; + + snprintf(req_command, sizeof(req_command), "%s:%s", T7XX_FB_CMD_GET_VER, cmd); + return t7xx_flash_dump_fb_raw_command(req_command, port, data); +} + +static int t7xx_flash_dump_get_part_ver_norm_mode(struct t7xx_port *port, const char *cmd, + char *data) +{ + char req_command[T7XX_FB_COMMAND_SIZE]; + int len; + + len = snprintf(req_command, sizeof(req_command), "%s:%s", T7XX_FB_CMD_GET_VER, cmd); + t7xx_port_ap_msg_tx(port, req_command, len); + + return t7xx_flash_dump_fb_handle_response(port, data); +} + +static int t7xx_devlink_info_get(struct devlink *devlink, struct devlink_info_req *req, + struct netlink_ext_ack *extack) +{ + struct t7xx_flash_dump *flash_dump = devlink_priv(devlink); + char *part_name, *ver, *part_no, *data; + int ret, total_part, i, ver_len; + struct t7xx_port *port; + + port = flash_dump->port; + port->port_conf->ops->enable_chl(port); + + if (flash_dump->status != T7XX_DEVLINK_IDLE) { + dev_err(&flash_dump->t7xx_dev->pdev->dev, "Modem is busy!\n"); + return -EBUSY; + } + + data = kzalloc(T7XX_FB_RESPONSE_SIZE, GFP_KERNEL); + if (!data) + return -ENOMEM; + + set_bit(T7XX_GET_INFO, &flash_dump->status); + if (flash_dump->mode == T7XX_FB_DL_MODE) + ret = t7xx_flash_dump_get_part_ver_fb_mode(port, "", data); + else + ret = t7xx_flash_dump_get_part_ver_norm_mode(port, "", data); + + if (ret < 0) + goto err_clear_bit; + + part_no = strsep(&data, ","); + if (kstrtoint(part_no, 16, &total_part)) { + dev_err(&flash_dump->t7xx_dev->pdev->dev, "kstrtoint error!\n"); + ret = -EINVAL; + goto err_clear_bit; + } + + for (i = 0; i < total_part; i++) { + part_name = strsep(&data, ","); + ver = strsep(&data, ","); + ver_len = strlen(ver); + if (ver[ver_len - 2] == 0x5C && ver[ver_len - 1] == 0x6E) + ver[ver_len - 4] = '\0'; + ret = devlink_info_version_running_put_ext(req, part_name, ver, + DEVLINK_INFO_VERSION_TYPE_COMPONENT); + } + +err_clear_bit: + clear_bit(T7XX_GET_INFO, &flash_dump->status); + kfree(data); + return ret; +} + +/* Call back function for devlink ops */ +static const struct devlink_ops devlink_flash_ops = { + .supported_flash_update_params = DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK, + .flash_update = t7xx_devlink_flash_update, + .reload_actions = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT) | + BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE), + .info_get = t7xx_devlink_info_get, + .reload_down = t7xx_devlink_reload_down, + .reload_up = t7xx_devlink_reload_up, +}; + +int t7xx_devlink_register(struct t7xx_pci_dev *t7xx_dev) +{ + union devlink_param_value value; + struct devlink *dl_ctx; + + dl_ctx = devlink_alloc(&devlink_flash_ops, sizeof(struct t7xx_flash_dump), + &t7xx_dev->pdev->dev); + if (!dl_ctx) + return -ENOMEM; + + t7xx_dev->flash_dump = devlink_priv(dl_ctx); + t7xx_dev->flash_dump->ctx = dl_ctx; + t7xx_dev->flash_dump->t7xx_dev = t7xx_dev; + + devl_lock(dl_ctx); + devl_params_register(dl_ctx, t7xx_devlink_params, ARRAY_SIZE(t7xx_devlink_params)); + value.vbool = false; + devl_param_driverinit_value_set(dl_ctx, T7XX_DEVLINK_PARAM_ID_FASTBOOT, value); + devl_register(dl_ctx); + devl_unlock(dl_ctx); + + return 0; +} + +void t7xx_devlink_unregister(struct t7xx_pci_dev *t7xx_dev) +{ + struct devlink *dl_ctx = t7xx_dev->flash_dump->ctx; + + devl_lock(dl_ctx); + devl_unregister(dl_ctx); + devl_params_unregister(dl_ctx, t7xx_devlink_params, ARRAY_SIZE(t7xx_devlink_params)); + devl_unlock(dl_ctx); + devlink_free(dl_ctx); +} + +/** + * t7xx_port_flash_dump_init - Initialize devlink to t7xx driver + * @port: Pointer to port structure + * + * Returns: 0 on success and error values on failure + */ +static int t7xx_port_flash_dump_init(struct t7xx_port *port) +{ + struct t7xx_flash_dump *flash_dump = port->t7xx_dev->flash_dump; + + port->rx_length_th = T7XX_MAX_QUEUE_LENGTH; + + flash_dump->mode = T7XX_NORMAL_MODE; + flash_dump->status = T7XX_DEVLINK_IDLE; + flash_dump->port = port; + + return 0; +} + +static void t7xx_port_flash_dump_uninit(struct t7xx_port *port) +{ + struct t7xx_flash_dump *flash_dump = port->t7xx_dev->flash_dump; + + flash_dump->mode = T7XX_NORMAL_MODE; + + skb_queue_purge(&port->rx_skb_list); +} + +struct port_ops flash_dump_port_ops = { + .init = &t7xx_port_flash_dump_init, + .recv_skb = &t7xx_port_enqueue_skb, + .uninit = &t7xx_port_flash_dump_uninit, + .enable_chl = &t7xx_port_enable_chl, + .disable_chl = &t7xx_port_disable_chl, +}; diff --git a/drivers/net/wwan/t7xx/t7xx_port_flash_dump.h b/drivers/net/wwan/t7xx/t7xx_port_flash_dump.h new file mode 100644 index 000000000000..7614c01dcb2c --- /dev/null +++ b/drivers/net/wwan/t7xx/t7xx_port_flash_dump.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: GPL-2.0-only + * + * Copyright (c) 2022-2023, Intel Corporation. + */ + +#ifndef __T7XX_PORT_FLASH_DUMP_H__ +#define __T7XX_PORT_FLASH_DUMP_H__ + +#include +#include + +#define T7XX_MAX_QUEUE_LENGTH 32 +#define T7XX_FB_COMMAND_SIZE 64 +#define T7XX_FB_RESPONSE_SIZE 512 +#define T7XX_FB_RESP_COUNT 30 + +#define T7XX_FLASH_STATUS 0 +#define T7XX_GET_INFO 3 + +#define T7XX_DEVLINK_IDLE 0 +#define T7XX_NORMAL_MODE 0 +#define T7XX_FB_DL_MODE 1 + +#define T7XX_FB_CMD_DOWNLOAD "download" +#define T7XX_FB_CMD_FLASH "flash" +#define T7XX_FB_CMD_REBOOT "reboot" +#define T7XX_FB_RESP_OKAY "OKAY" +#define T7XX_FB_RESP_FAIL "FAIL" +#define T7XX_FB_RESP_DATA "DATA" +#define T7XX_FB_RESP_INFO "INFO" +#define T7XX_FB_CMD_GET_VER "get_version" + +struct t7xx_flash_dump { + struct t7xx_pci_dev *t7xx_dev; + struct t7xx_port *port; + struct devlink *ctx; + unsigned long status; + u8 mode; +}; + +bool t7xx_devlink_param_get_fastboot(struct devlink *devlink); +int t7xx_devlink_register(struct t7xx_pci_dev *t7xx_dev); +void t7xx_devlink_unregister(struct t7xx_pci_dev *t7xx_dev); + +#endif /*__T7XX_PORT_FLASH_DUMP_H__*/ diff --git a/drivers/net/wwan/t7xx/t7xx_port_proxy.c b/drivers/net/wwan/t7xx/t7xx_port_proxy.c index bdfeb10e0c51..11b88c41fc03 100644 --- a/drivers/net/wwan/t7xx/t7xx_port_proxy.c +++ b/drivers/net/wwan/t7xx/t7xx_port_proxy.c @@ -40,6 +40,7 @@ #define Q_IDX_CTRL 0 #define Q_IDX_MBIM 2 #define Q_IDX_AT_CMD 5 +#define Q_IDX_AP_MSG 2 #define INVALID_SEQ_NUM GENMASK(15, 0) @@ -97,7 +98,18 @@ static const struct t7xx_port_conf t7xx_port_conf[] = { .path_id = CLDMA_ID_AP, .ops = &ctl_port_ops, .name = "t7xx_ap_ctrl", + }, { + .tx_ch = PORT_CH_AP_MSG_TX, + .rx_ch = PORT_CH_AP_MSG_RX, + .txq_index = Q_IDX_AP_MSG, + .rxq_index = Q_IDX_AP_MSG, + .txq_exp_index = Q_IDX_AP_MSG, + .rxq_exp_index = Q_IDX_AP_MSG, + .path_id = CLDMA_ID_AP, + .ops = &ap_msg_port_ops, + .name = "ap_msg", }, + }; static struct t7xx_port_conf t7xx_early_port_conf[] = { @@ -109,6 +121,8 @@ static struct t7xx_port_conf t7xx_early_port_conf[] = { .txq_exp_index = CLDMA_Q_IDX_DUMP, .rxq_exp_index = CLDMA_Q_IDX_DUMP, .path_id = CLDMA_ID_AP, + .ops = &flash_dump_port_ops, + .name = "flash_dump", }, }; @@ -325,6 +339,24 @@ int t7xx_port_send_skb(struct t7xx_port *port, struct sk_buff *skb, unsigned int return t7xx_port_send_ccci_skb(port, skb, pkt_header, ex_msg); } +int t7xx_port_enable_chl(struct t7xx_port *port) +{ + spin_lock(&port->port_update_lock); + port->chan_enable = true; + spin_unlock(&port->port_update_lock); + + return 0; +} + +int t7xx_port_disable_chl(struct t7xx_port *port) +{ + spin_lock(&port->port_update_lock); + port->chan_enable = false; + spin_unlock(&port->port_update_lock); + + return 0; +} + static void t7xx_proxy_setup_ch_mapping(struct port_proxy *port_prox) { struct t7xx_port *port; diff --git a/drivers/net/wwan/t7xx/t7xx_port_proxy.h b/drivers/net/wwan/t7xx/t7xx_port_proxy.h index 7f5706811445..42f1ebf402d8 100644 --- a/drivers/net/wwan/t7xx/t7xx_port_proxy.h +++ b/drivers/net/wwan/t7xx/t7xx_port_proxy.h @@ -93,6 +93,8 @@ struct ctrl_msg_header { /* Port operations mapping */ extern struct port_ops wwan_sub_port_ops; extern struct port_ops ctl_port_ops; +extern struct port_ops flash_dump_port_ops; +extern struct port_ops ap_msg_port_ops; #ifdef CONFIG_WWAN_DEBUGFS extern struct port_ops t7xx_trace_port_ops; @@ -108,5 +110,7 @@ int t7xx_port_proxy_chl_enable_disable(struct port_proxy *port_prox, unsigned in void t7xx_port_proxy_set_cfg(struct t7xx_modem *md, enum port_cfg_id cfg_id); int t7xx_port_proxy_recv_skb(struct cldma_queue *queue, struct sk_buff *skb); int t7xx_port_proxy_recv_skb_from_dedicated_queue(struct cldma_queue *queue, struct sk_buff *skb); +int t7xx_port_enable_chl(struct t7xx_port *port); +int t7xx_port_disable_chl(struct t7xx_port *port); #endif /* __T7XX_PORT_PROXY_H__ */ diff --git a/drivers/net/wwan/t7xx/t7xx_port_wwan.c b/drivers/net/wwan/t7xx/t7xx_port_wwan.c index ddc20ddfa734..b4e2926f33f6 100644 --- a/drivers/net/wwan/t7xx/t7xx_port_wwan.c +++ b/drivers/net/wwan/t7xx/t7xx_port_wwan.c @@ -131,24 +131,6 @@ static int t7xx_port_wwan_recv_skb(struct t7xx_port *port, struct sk_buff *skb) return 0; } -static int t7xx_port_wwan_enable_chl(struct t7xx_port *port) -{ - spin_lock(&port->port_update_lock); - port->chan_enable = true; - spin_unlock(&port->port_update_lock); - - return 0; -} - -static int t7xx_port_wwan_disable_chl(struct t7xx_port *port) -{ - spin_lock(&port->port_update_lock); - port->chan_enable = false; - spin_unlock(&port->port_update_lock); - - return 0; -} - static void t7xx_port_wwan_md_state_notify(struct t7xx_port *port, unsigned int state) { const struct t7xx_port_conf *port_conf = port->port_conf; @@ -173,7 +155,7 @@ struct port_ops wwan_sub_port_ops = { .init = t7xx_port_wwan_init, .recv_skb = t7xx_port_wwan_recv_skb, .uninit = t7xx_port_wwan_uninit, - .enable_chl = t7xx_port_wwan_enable_chl, - .disable_chl = t7xx_port_wwan_disable_chl, + .enable_chl = t7xx_port_enable_chl, + .disable_chl = t7xx_port_disable_chl, .md_state_notify = t7xx_port_wwan_md_state_notify, }; diff --git a/drivers/net/wwan/t7xx/t7xx_reg.h b/drivers/net/wwan/t7xx/t7xx_reg.h index 3b665c6116fe..b106c988321a 100644 --- a/drivers/net/wwan/t7xx/t7xx_reg.h +++ b/drivers/net/wwan/t7xx/t7xx_reg.h @@ -101,10 +101,16 @@ enum t7xx_pm_resume_state { PM_RESUME_REG_STATE_L2_EXP, }; +enum host_event_e { + HOST_EVENT_INIT = 0, + FASTBOOT_DL_NOTIFY = 0x3, +}; + #define T7XX_PCIE_MISC_DEV_STATUS 0x0d1c #define MISC_RESET_TYPE_FLDR BIT(27) #define MISC_RESET_TYPE_PLDR BIT(26) #define MISC_LK_EVENT_MASK GENMASK(11, 8) +#define HOST_EVENT_MASK GENMASK(31, 28) enum lk_event_id { LK_EVENT_NORMAL = 0, diff --git a/drivers/net/wwan/t7xx/t7xx_state_monitor.c b/drivers/net/wwan/t7xx/t7xx_state_monitor.c index 9c51e332e7c5..24f79e981fd9 100644 --- a/drivers/net/wwan/t7xx/t7xx_state_monitor.c +++ b/drivers/net/wwan/t7xx/t7xx_state_monitor.c @@ -37,6 +37,7 @@ #include "t7xx_modem_ops.h" #include "t7xx_pci.h" #include "t7xx_pcie_mac.h" +#include "t7xx_port_flash_dump.h" #include "t7xx_port_proxy.h" #include "t7xx_reg.h" #include "t7xx_state_monitor.h" @@ -206,11 +207,22 @@ static void fsm_routine_exception(struct t7xx_fsm_ctl *ctl, struct t7xx_fsm_comm fsm_finish_command(ctl, cmd, 0); } +static void t7xx_host_event_notify(struct t7xx_modem *md, unsigned int event_id) +{ + u32 value; + + value = ioread32(IREG_BASE(md->t7xx_dev) + T7XX_PCIE_MISC_DEV_STATUS); + value &= ~HOST_EVENT_MASK; + value |= FIELD_PREP(HOST_EVENT_MASK, event_id); + iowrite32(value, IREG_BASE(md->t7xx_dev) + T7XX_PCIE_MISC_DEV_STATUS); +} + static void t7xx_lk_stage_event_handling(struct t7xx_fsm_ctl *ctl, unsigned int status) { struct t7xx_modem *md = ctl->md; struct cldma_ctrl *md_ctrl; enum lk_event_id lk_event; + struct t7xx_port *port; struct device *dev; dev = &md->t7xx_dev->pdev->dev; @@ -221,10 +233,19 @@ static void t7xx_lk_stage_event_handling(struct t7xx_fsm_ctl *ctl, unsigned int break; case LK_EVENT_CREATE_PD_PORT: + case LK_EVENT_CREATE_POST_DL_PORT: md_ctrl = md->md_ctrl[CLDMA_ID_AP]; t7xx_cldma_hif_hw_init(md_ctrl); t7xx_cldma_stop(md_ctrl); t7xx_cldma_switch_cfg(md_ctrl, CLDMA_DEDICATED_Q_CFG); + port = ctl->md->t7xx_dev->flash_dump->port; + if (WARN_ON(!port)) + return; + + if (lk_event == LK_EVENT_CREATE_POST_DL_PORT) + md->t7xx_dev->flash_dump->mode = T7XX_FB_DL_MODE; + + port->port_conf->ops->enable_chl(port); t7xx_cldma_start(md_ctrl); break; @@ -258,7 +279,9 @@ static void fsm_routine_stopping(struct t7xx_fsm_ctl *ctl, struct t7xx_fsm_comma struct cldma_ctrl *md_ctrl; int err; - if (ctl->curr_state == FSM_STATE_STOPPED || ctl->curr_state == FSM_STATE_STOPPING) { + if (ctl->curr_state == FSM_STATE_STOPPED || + ctl->curr_state == FSM_STATE_STOPPING || + ctl->md->rgu_irq_asserted) { fsm_finish_command(ctl, cmd, -EINVAL); return; } @@ -270,11 +293,18 @@ static void fsm_routine_stopping(struct t7xx_fsm_ctl *ctl, struct t7xx_fsm_comma t7xx_fsm_broadcast_state(ctl, MD_STATE_WAITING_TO_STOP); t7xx_cldma_stop(md_ctrl); - if (!ctl->md->rgu_irq_asserted) { - t7xx_mhccif_h2d_swint_trigger(t7xx_dev, H2D_CH_DRM_DISABLE_AP); - /* Wait for the DRM disable to take effect */ - msleep(FSM_DRM_DISABLE_DELAY_MS); - + if (t7xx_devlink_param_get_fastboot(t7xx_dev->flash_dump->ctx)) + t7xx_host_event_notify(ctl->md, FASTBOOT_DL_NOTIFY); + + t7xx_mhccif_h2d_swint_trigger(t7xx_dev, H2D_CH_DRM_DISABLE_AP); + /* Wait for the DRM disable to take effect */ + msleep(FSM_DRM_DISABLE_DELAY_MS); + if (t7xx_devlink_param_get_fastboot(t7xx_dev->flash_dump->ctx)) { + /* Do not try fldr because device will always wait for + * MHCCIF bit 13 in fastboot download flow. + */ + t7xx_mhccif_h2d_swint_trigger(t7xx_dev, H2D_CH_DEVICE_RESET); + } else { err = t7xx_acpi_fldr_func(t7xx_dev); if (err) t7xx_mhccif_h2d_swint_trigger(t7xx_dev, H2D_CH_DEVICE_RESET); From patchwork Tue Sep 12 09:48:43 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jinjian Song X-Patchwork-Id: 13381203 X-Patchwork-Delegate: kuba@kernel.org Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B4DBF171B1 for ; Tue, 12 Sep 2023 09:49:51 +0000 (UTC) Received: from AUS01-SY4-obe.outbound.protection.outlook.com (mail-sy4aus01olkn2155.outbound.protection.outlook.com [40.92.62.155]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CC24BE6C; Tue, 12 Sep 2023 02:49:50 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=VDcs6u6lSIaVML//v+8iCk5/lzfJd5FNbIay3uwWRHjt+MS5YTbgJdKlgmr+cDlLINbzMPjNuMKOxlzlADG3MO8c8e/iy0w2o7IlWXWhHG2SMCxBWB0vH8h0qGbRD7tlMdhFpJGboUKL1burGSOUAVWm8TcsLzer5gM3BFZsVWC3mn8s8IE8I+02qiJyGNFCVCuqHD4EZK7O8nPFOg0Yy9sHaUKwVU+VtHwnvtjrXLJ9flWBRpu0pP6z8Y9l15yb07VDrMKzLpc/+nx9wkhikVL3C6DT41Z9XtDD3WmooN+E+pAmu0b5cADazqlA9PkG/SsJZ0NbIDwFkNvc/f7obQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; 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; bh=x1ON2lIXDXmijZaqWzsXZFy1gNW7vJ4qARHbNm90A0U=; b=Ep8XkdXrS0tFvsRX/hPMBwGe1zSFa3mpclREQsjtTLMgsZPSQo+DtAqB7Ns14z0d+//x3P+urFMD0qGSNBF+Thv5XlmBQ+8gUN+S0VLZ9RDt4yBaLyJ52e35zADVq+q49Net9T5JJwY0a4AloLyLoV6T3JR4aGAbmAcNXpl7k85UBKYpsB/lOy9LWg+ATrpQYcR+w7T6nT8WbR66dgECvv6Nw+ik4HroWZZ0E4T19i+wZafyxeoEKe4YBPXbukyIqi0NzL0pmFy+CKorVC1VsH0Dk39rlMfu86SCYYcq/B/WV3vIBoWoHPTTRsn1bnhg2dJIbmAJjeJkxjWR94wIjg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=none; dmarc=none; dkim=none; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=hotmail.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=x1ON2lIXDXmijZaqWzsXZFy1gNW7vJ4qARHbNm90A0U=; b=eWUqNr9bzw/Rg87hB3y72SzIKTxs9XOhc6B220Xc4qszvhZ40tIWTHY8uW1dt+jxMVf6hjWz6Pqm78IiQQDmC7dQOnhiNHCTxTgiG6Hv5FAwB9SjkTeTjsKc6GifTqCGwg0prTAkcdS4JowPJxAjcQSjs+5tUEdkESWsoy8Q00MhtVf7Whr1XImxOeUWH1JrFJlEjYwMsNGzWYLts8Km0WLaVZLw3EFptJdTwY3rfIpaXoj5KDlDdi6UaqMu0Cnur3iUAacdGyOt6BQQReYwrrrWo8Ap0w7+iYJDNKDCjZZ8Z1hfaFZcASftuVJqPRegGtl4SauxAQ+3YEb3py1Jxg== Received: from ME3P282MB2703.AUSP282.PROD.OUTLOOK.COM (2603:10c6:220:16b::5) by SY4P282MB2981.AUSP282.PROD.OUTLOOK.COM (2603:10c6:10:15c::13) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6768.35; Tue, 12 Sep 2023 09:49:43 +0000 Received: from ME3P282MB2703.AUSP282.PROD.OUTLOOK.COM ([fe80::68b4:6263:97f:9a45]) by ME3P282MB2703.AUSP282.PROD.OUTLOOK.COM ([fe80::68b4:6263:97f:9a45%3]) with mapi id 15.20.6768.036; Tue, 12 Sep 2023 09:49:43 +0000 From: Jinjian Song To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, corbet@lwn.net, loic.poulain@linaro.org, ryazanov.s.a@gmail.com Cc: jiri@resnulli.us, johannes@sipsolutions.net, chandrashekar.devegowda@intel.com, linuxwwan@intel.com, chiranjeevi.rapolu@linux.intel.com, haijun.liu@mediatek.com, m.chetan.kumar@linux.intel.com, ricardo.martinez@linux.intel.com, netdev@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, nmarupaka@google.com, vsankar@lenovo.com, danielwinkler@google.com, Jinjian Song Subject: [net-next v4 3/5] net: wwan: t7xx: Creates region & snapshot for coredump log collection Date: Tue, 12 Sep 2023 17:48:43 +0800 Message-ID: X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230912094845.11233-1-songjinjian@hotmail.com> References: <20230912094845.11233-1-songjinjian@hotmail.com> X-TMN: [yEC8JhMDWlnSUI3jy8vqNQhlIeTwNTdI] X-ClientProxiedBy: SI2PR01CA0048.apcprd01.prod.exchangelabs.com (2603:1096:4:193::17) To ME3P282MB2703.AUSP282.PROD.OUTLOOK.COM (2603:10c6:220:16b::5) X-Microsoft-Original-Message-ID: <20230912094845.11233-4-songjinjian@hotmail.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: ME3P282MB2703:EE_|SY4P282MB2981:EE_ X-MS-Office365-Filtering-Correlation-Id: 30945674-e3ef-45ba-3089-08dbb3759724 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: 9mgSHWf1YMWwvudydukzo5+o4v3MeNimdRCG1yKRJ9UAkraedRp6q9vb4D6doXFC6uuzeVQJzDEjpF36ZH8vvABT0KcVC4m7tUXo/3VbewawZMwgRzeVU5oEJsLv24yRUssR/5aPiXrdaaKhL3Ts1I/GIEDMKHtHaxHNk+QjzHNoW3SL2Rc6KzYR0cKsZ5eDG+m8dcO8n8kzdj7JS4sMQY9rbb36OGvGwgKgLPc4sZjqOa1u9Rpkmm/GQJ6BZy84l2AomiFVf+i39LoPstwtd+QfEaOmhIFaJjJKfcPqmmbkKA2jRBP37ORuFGcMLrzFgDiYz6tjDgbsknc+nMxakfgUMD0Zz15oW99nQiA7MAaXHQTvySJjN9VxuEbqDr0vyOxSH/dZM6jN1UgMZM6Jy4HMHxe1nE1uUxe9S5XlVfHVcrO17ZcvXfdL2qyWWZghsXsEcRBviBknlennaK5KvqzXHHcL1lzYiijzCO0omFM+7o602MadrHNFT3mkNw9riUr4K9yE63J93QCoZeWlNDND09gTxyd0YYc7NnOpAZiCJ8+L1os8GWSx3E9AMoWm1QFImO+Ja0Od7mKG+ePCiajYlwYSF1qH2Jv5qzNABbo= X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: 2REIklQRakn2uxyqHnG1XVzvMHNK1ZCVYZ6ugAFY+5gln4532l1TpJTzQ+V6zUk267ZHQGQgJ+BWdb+oxjhcDUKRWTljwqHuPY0n6Swk+cQgvLdwE24KRqsCkGI7ZLx89mRZ6XvS7lIlNwxcmfcKyxerKbV8z9erzh5trP6oJMoGwRN4n08bq4OG0mlS1I1Qp8WWAZ8p2LqANYEnuFiRyfKuE1aSR+5InoxVC1kLhPWMxVMRmW3PRBYcNeHpLNIW755d+G7dWYRkAySBiIMDqL/1XUr+LvNpuRRhNrdIE4Bc5A+6IIWK74aszs3IXB9H25VxSFL0RTh/toOt6X4mRhXOra/SVM8zSyRQtIllx8O0uctuHpXGqDiH0lV+TvemiM5qo1o7bmxBI6QPexGUzT2BixFVicZi+Dd1Et9N8vRFDRhDIVyEl2uIhsv0Xj+gfUtLYBsBFUKkmO6g/T75mM862GP25c/M2ECG08BthYQRHrq1ABOmGr8OYBpihw2d9crav+WeRmGko0YeOvNKA5ZBrI5xYbmOOAgpF99m4mfxZP59cGqD1MYneVFRbu+GG5Mo9jn3NrUW94TzpfPL6XsX3XHjiZJZHoxDNbFBNNQ5Eufm40tU2LZ0n74QbFG8Vxyn6cDXafpxPF3wRHm54yba65gO9Zna5OhhI0yFFh7BTyqK92wpZLCQbdB8WX0CQHkDtiYQ88VGTGCoDnVc5cANv7DsuF196R5uxswHbybVYzOEZhwV3FBvQAq7puJcLUV/Oemfb/rVhr0HQ4SMBvSBjGa5XnahcOM6HHhWTToTjmI0gokR7lAwiYJNIGztE1nZKFOEj24OLvp9HDb/r/nAiLZwVXZhhUd8HiKZVKgNMovKNGx7/oXRcVyU4qdyEYs/g+YWBHJzAp42jis3AR+a9Nx7CB619gy7IBO9C5rZ2rIoZa7zUYrB7gt5gI8JbSzD1i6gJW1SZzOdirc45/p5Wa6hg0IKlL5SOmMexESiPb/721PqcyMvnfZSDLkICSf7/0A6UE66EtWOto0cdAWcLu+UOWfaPYcAwga9PVotXDx8y41lGFcrMQGF98jHRLOUP6kFpeNS7N5QRJ8Bok27e+Iie6OgaHLWjGxM37PONejK5WAWwzNhiQR1pcFiyWj+/7jp5IIMQhojhoNeqpDzai9brQEmwBPz8dkxTwSzv8xrzTZNqGJXxwlpEvijJ9YdheALAQwbJoX8dh5hEEl+/IRCNG7LrE3eqTdYBm4= X-OriginatorOrg: sct-15-20-4755-11-msonline-outlook-746f3.templateTenant X-MS-Exchange-CrossTenant-Network-Message-Id: 30945674-e3ef-45ba-3089-08dbb3759724 X-MS-Exchange-CrossTenant-AuthSource: ME3P282MB2703.AUSP282.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Sep 2023 09:49:43.3935 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 84df9e7f-e9f6-40af-b435-aaaaaaaaaaaa X-MS-Exchange-CrossTenant-RMS-PersistedConsumerOrg: 00000000-0000-0000-0000-000000000000 X-MS-Exchange-Transport-CrossTenantHeadersStamped: SY4P282MB2981 X-Patchwork-Delegate: kuba@kernel.org From: Jinjian Song Adds support for t7xx wwan device coredump collection using devlink. In case of coredump collection when wwan device encounters an exception it reboots & stays in fastboot mode for coredump collection by host driver. On detecting exception state driver collects the core dump, creates the devlink region & reports an event to user space application for dump collection. The user space application invokes devlink region read command for dump collection. Below are the devlink commands used for coredump collection. devlink region new pci/$BDF/mr_dump devlink region read pci/$BDF/mr_dump snapshot $ID address $ADD length $LEN devlink region del pci/$BDF/mr_dump snapshot $ID Base on the v5 patch version of follown series: 'net: wwan: t7xx: fw flashing & coredump support' (https://patchwork.kernel.org/project/netdevbpf/patch/fc8bbb0b66a5ff3a489ea9857d79b374508090ef.1674307425.git.m.chetan.kumar@linux.intel.com/) Signed-off-by: Jinjian Song --- v4: * no change v3: * no change v2: * rename function name from devlink to flash_dump --- drivers/net/wwan/t7xx/t7xx_port_flash_dump.c | 256 ++++++++++++++++++- drivers/net/wwan/t7xx/t7xx_port_flash_dump.h | 39 +++ drivers/net/wwan/t7xx/t7xx_state_monitor.c | 2 + 3 files changed, 296 insertions(+), 1 deletion(-) diff --git a/drivers/net/wwan/t7xx/t7xx_port_flash_dump.c b/drivers/net/wwan/t7xx/t7xx_port_flash_dump.c index 1129ef793798..b8ef3b7d7430 100644 --- a/drivers/net/wwan/t7xx/t7xx_port_flash_dump.c +++ b/drivers/net/wwan/t7xx/t7xx_port_flash_dump.c @@ -9,6 +9,11 @@ #include "t7xx_port_ap_msg.h" #include "t7xx_port_flash_dump.h" +static struct t7xx_dump_region_info t7xx_dump_region_infos[] = { + [T7XX_MRDUMP_INDEX] = {"mr_dump", T7XX_MRDUMP_SIZE}, + [T7XX_LKDUMP_INDEX] = {"lk_dump", T7XX_LKDUMP_SIZE}, +}; + static int t7xx_flash_dump_port_read(struct t7xx_port *port, char *buf, size_t count) { struct sk_buff *skb; @@ -130,6 +135,151 @@ static int t7xx_flash_dump_fb_raw_command(char *cmd, struct t7xx_port *port, cha return ret; } +static int t7xx_flash_dump_fb_cmd_send(struct t7xx_port *port, char *cmd) +{ + int len = strlen(cmd); + int ret; + + ret = t7xx_flash_dump_port_write(port, cmd, len); + if (ret == len) + return 0; + + return ret; +} + +static int t7xx_flash_dump_fb_get_core(struct t7xx_port *port) +{ + u32 mrd_mb = T7XX_MRDUMP_SIZE / (1024 * 1024); + struct t7xx_flash_dump *flash_dump = port->t7xx_dev->flash_dump; + char mcmd[T7XX_FB_MCMD_SIZE + 1]; + size_t offset_dlen = 0; + int clen, dlen, ret; + + flash_dump->regions[T7XX_MRDUMP_INDEX].buf = + vmalloc(flash_dump->regions[T7XX_MRDUMP_INDEX].info->size); + if (!flash_dump->regions[T7XX_MRDUMP_INDEX].buf) + return -ENOMEM; + + set_bit(T7XX_MRDUMP_STATUS, &flash_dump->status); + ret = t7xx_flash_dump_fb_raw_command(T7XX_FB_CMD_OEM_MRDUMP, port, NULL); + if (ret) { + dev_err(port->dev, "%s command failed\n", T7XX_FB_CMD_OEM_MRDUMP); + goto free_mem; + } + + while (flash_dump->regions[T7XX_MRDUMP_INDEX].info->size > offset_dlen) { + clen = t7xx_flash_dump_port_read(port, mcmd, sizeof(mcmd) - 1); + if (clen <= 0) + goto free_mem; + + mcmd[clen] = '\0'; + if (!strcmp(mcmd, T7XX_FB_CMD_RTS)) { + memset(mcmd, 0, sizeof(mcmd)); + ret = t7xx_flash_dump_fb_cmd_send(port, T7XX_FB_CMD_CTS); + if (ret < 0) { + dev_err(port->dev, "write for _CTS failed:%zu\n", + strlen(T7XX_FB_CMD_CTS)); + goto free_mem; + } + + dlen = t7xx_flash_dump_port_read(port, + flash_dump->regions[T7XX_MRDUMP_INDEX].buf + + offset_dlen, T7XX_FB_MDATA_SIZE); + if (dlen <= 0) { + dev_err(port->dev, "read data error(%d)\n", dlen); + ret = dlen; + goto free_mem; + } + offset_dlen += dlen; + + ret = t7xx_flash_dump_fb_cmd_send(port, T7XX_FB_CMD_FIN); + if (ret < 0) { + dev_err(port->dev, "_FIN failed, (Read %05zu:%05zu)\n", + strlen(T7XX_FB_CMD_FIN), offset_dlen); + goto free_mem; + } + continue; + } else if (!strcmp(mcmd, T7XX_FB_RESP_MRDUMP_DONE)) { + dev_dbg(port->dev, "%s! size:%zd\n", T7XX_FB_RESP_MRDUMP_DONE, offset_dlen); + clear_bit(T7XX_MRDUMP_STATUS, &flash_dump->status); + return 0; + } + dev_err(port->dev, "getcore protocol error (read len %05d, response %s)\n", + clen, mcmd); + ret = -EPROTO; + goto free_mem; + } + + dev_err(port->dev, "mrdump exceeds %uMB size. Discarded!\n", mrd_mb); + +free_mem: + vfree(flash_dump->regions[T7XX_MRDUMP_INDEX].buf); + clear_bit(T7XX_MRDUMP_STATUS, &flash_dump->status); + return ret; +} + +static int t7xx_flash_dump_fb_dump_log(struct t7xx_port *port) +{ + struct t7xx_flash_dump *flash_dump = port->t7xx_dev->flash_dump; + struct t7xx_dump_region *lkdump_region; + char rsp[T7XX_FB_RESPONSE_SIZE]; + int datasize = 0, ret; + size_t offset = 0; + + if (flash_dump->status != T7XX_DEVLINK_IDLE) { + dev_err(&flash_dump->t7xx_dev->pdev->dev, "Modem is busy!\n"); + return -EBUSY; + } + + set_bit(T7XX_LKDUMP_STATUS, &flash_dump->status); + ret = t7xx_flash_dump_fb_raw_command(T7XX_FB_CMD_OEM_LKDUMP, port, rsp); + if (ret) { + dev_err(port->dev, "%s command returns failure\n", T7XX_FB_CMD_OEM_LKDUMP); + goto err_clear_bit; + } + + ret = kstrtoint(rsp, 16, &datasize); + if (ret) { + dev_err(port->dev, "bad value\n"); + goto err_clear_bit; + } + + lkdump_region = &flash_dump->regions[T7XX_LKDUMP_INDEX]; + if (datasize > lkdump_region->info->size) { + dev_err(port->dev, "lkdump size is more than %dKB. Discarded!\n", + T7XX_LKDUMP_SIZE / 1024); + ret = -EFBIG; + goto err_clear_bit; + } + + lkdump_region->buf = vmalloc(lkdump_region->info->size); + if (!lkdump_region->buf) { + ret = -ENOMEM; + goto err_clear_bit; + } + + while (datasize > 0) { + int dlen = t7xx_flash_dump_port_read(port, lkdump_region->buf + offset, datasize); + + if (dlen <= 0) { + dev_err(port->dev, "lkdump read error ret = %d\n", dlen); + ret = dlen; + goto err_clear_bit; + } + + datasize -= dlen; + offset += dlen; + } + + dev_dbg(port->dev, "LKDUMP DONE! size:%zd\n", offset); + clear_bit(T7XX_LKDUMP_STATUS, &flash_dump->status); + return t7xx_flash_dump_fb_handle_response(port, NULL); + +err_clear_bit: + clear_bit(T7XX_LKDUMP_STATUS, &flash_dump->status); + return ret; +} + static int t7xx_flash_dump_fb_download_command(struct t7xx_port *port, size_t size) { char download_command[T7XX_FB_COMMAND_SIZE]; @@ -355,6 +505,67 @@ static const struct devlink_ops devlink_flash_ops = { .reload_up = t7xx_devlink_reload_up, }; +static int t7xx_flash_dump_region_snapshot(struct devlink *dl, const struct devlink_region_ops *ops, + struct netlink_ext_ack *extack, u8 **data) +{ + struct t7xx_flash_dump *flash_dump = devlink_priv(dl); + struct t7xx_dump_region *region = ops->priv; + struct t7xx_port *port = flash_dump->port; + u8 *snapshot_mem; + + if (flash_dump->status != T7XX_DEVLINK_IDLE) + return -EBUSY; + + if (!strncmp(ops->name, "mr_dump", strlen("mr_dump"))) { + snapshot_mem = vmalloc(region->info->size); + memcpy(snapshot_mem, region->buf, region->info->size); + *data = snapshot_mem; + } else if (!strncmp(ops->name, "lk_dump", strlen("lk_dump"))) { + int ret; + + ret = t7xx_flash_dump_fb_dump_log(port); + if (ret) + return ret; + + *data = region->buf; + } + + return 0; +} + +static_assert(ARRAY_SIZE(t7xx_dump_region_infos) == + ARRAY_SIZE(((struct t7xx_flash_dump *)NULL)->regions)); + +/* To create regions for dump files */ +static int t7xx_flash_dump_create_regions(struct t7xx_flash_dump *flash_dump) +{ + int ret, i; + + for (i = 0; i < ARRAY_SIZE(t7xx_dump_region_infos); i++) { + flash_dump->regions[i].info = &t7xx_dump_region_infos[i]; + flash_dump->regions[i].ops.name = flash_dump->regions[i].info->name; + flash_dump->regions[i].ops.snapshot = t7xx_flash_dump_region_snapshot; + flash_dump->regions[i].ops.destructor = vfree; + flash_dump->regions[i].dlreg = devlink_region_create(flash_dump->ctx, + &flash_dump->regions[i].ops, + T7XX_MAX_SNAPSHOTS, + t7xx_dump_region_infos[i].size + ); + if (IS_ERR(flash_dump->regions[i].dlreg)) { + ret = PTR_ERR(flash_dump->regions[i].dlreg); + dev_err(flash_dump->port->dev, "create region failed, err %d\n", ret); + while (i >= 0) + devlink_region_destroy(flash_dump->regions[i--].dlreg); + + return ret; + } + + flash_dump->regions[i].ops.priv = &flash_dump->regions[i]; + } + + return 0; +} + int t7xx_devlink_register(struct t7xx_pci_dev *t7xx_dev) { union devlink_param_value value; @@ -379,6 +590,14 @@ int t7xx_devlink_register(struct t7xx_pci_dev *t7xx_dev) return 0; } +static void t7xx_flash_dump_work(struct work_struct *work) +{ + struct t7xx_flash_dump *flash_dump; + + flash_dump = container_of(work, struct t7xx_flash_dump, ws); + t7xx_flash_dump_fb_get_core(flash_dump->port); +} + void t7xx_devlink_unregister(struct t7xx_pci_dev *t7xx_dev) { struct devlink *dl_ctx = t7xx_dev->flash_dump->ctx; @@ -399,29 +618,64 @@ void t7xx_devlink_unregister(struct t7xx_pci_dev *t7xx_dev) static int t7xx_port_flash_dump_init(struct t7xx_port *port) { struct t7xx_flash_dump *flash_dump = port->t7xx_dev->flash_dump; + struct workqueue_struct *flash_dump_wq; + int rc; + + flash_dump_wq = create_workqueue("t7xx_flash_dump"); + if (!flash_dump_wq) { + dev_err(port->dev, "create_workqueue failed\n"); + return -ENODATA; + } + INIT_WORK(&flash_dump->ws, t7xx_flash_dump_work); port->rx_length_th = T7XX_MAX_QUEUE_LENGTH; flash_dump->mode = T7XX_NORMAL_MODE; flash_dump->status = T7XX_DEVLINK_IDLE; + flash_dump->wq = flash_dump_wq; flash_dump->port = port; + rc = t7xx_flash_dump_create_regions(flash_dump); + if (rc) { + destroy_workqueue(flash_dump->wq); + dev_err(port->dev, "devlink region creation failed, rc %d\n", rc); + return -ENOMEM; + } + return 0; } static void t7xx_port_flash_dump_uninit(struct t7xx_port *port) { struct t7xx_flash_dump *flash_dump = port->t7xx_dev->flash_dump; + int i; + + vfree(flash_dump->regions[T7XX_MRDUMP_INDEX].buf); flash_dump->mode = T7XX_NORMAL_MODE; + destroy_workqueue(flash_dump->wq); + + for (i = 0; i < ARRAY_SIZE(t7xx_dump_region_infos); ++i) + devlink_region_destroy(flash_dump->regions[i].dlreg); skb_queue_purge(&port->rx_skb_list); } +static int t7xx_flash_dump_enable_chl(struct t7xx_port *port) +{ + struct t7xx_flash_dump *flash_dump = port->t7xx_dev->flash_dump; + + t7xx_port_enable_chl(port); + if (flash_dump->mode == T7XX_FB_DUMP_MODE) + queue_work(flash_dump->wq, &flash_dump->ws); + + return 0; +} + struct port_ops flash_dump_port_ops = { .init = &t7xx_port_flash_dump_init, .recv_skb = &t7xx_port_enqueue_skb, .uninit = &t7xx_port_flash_dump_uninit, - .enable_chl = &t7xx_port_enable_chl, + .enable_chl = &t7xx_flash_dump_enable_chl, .disable_chl = &t7xx_port_disable_chl, }; diff --git a/drivers/net/wwan/t7xx/t7xx_port_flash_dump.h b/drivers/net/wwan/t7xx/t7xx_port_flash_dump.h index 7614c01dcb2c..90758baa7854 100644 --- a/drivers/net/wwan/t7xx/t7xx_port_flash_dump.h +++ b/drivers/net/wwan/t7xx/t7xx_port_flash_dump.h @@ -12,28 +12,67 @@ #define T7XX_MAX_QUEUE_LENGTH 32 #define T7XX_FB_COMMAND_SIZE 64 #define T7XX_FB_RESPONSE_SIZE 512 +#define T7XX_FB_MCMD_SIZE 64 +#define T7XX_FB_MDATA_SIZE 1024 #define T7XX_FB_RESP_COUNT 30 +#define T7XX_FB_EVENT_SIZE 50 + +#define T7XX_MAX_SNAPSHOTS 1 +#define T7XX_MRDUMP_SIZE (160 * 1024 * 1024) +#define T7XX_LKDUMP_SIZE (256 * 1024) +#define T7XX_TOTAL_REGIONS 2 + #define T7XX_FLASH_STATUS 0 +#define T7XX_MRDUMP_STATUS 1 +#define T7XX_LKDUMP_STATUS 2 #define T7XX_GET_INFO 3 #define T7XX_DEVLINK_IDLE 0 #define T7XX_NORMAL_MODE 0 #define T7XX_FB_DL_MODE 1 +#define T7XX_FB_DUMP_MODE 2 +#define T7XX_FB_CMD_RTS "_RTS" +#define T7XX_FB_CMD_CTS "_CTS" +#define T7XX_FB_CMD_FIN "_FIN" +#define T7XX_FB_CMD_OEM_MRDUMP "oem mrdump" +#define T7XX_FB_CMD_OEM_LKDUMP "oem dump_pllk_log" #define T7XX_FB_CMD_DOWNLOAD "download" #define T7XX_FB_CMD_FLASH "flash" #define T7XX_FB_CMD_REBOOT "reboot" +#define T7XX_FB_RESP_MRDUMP_DONE "MRDUMP08_DONE" #define T7XX_FB_RESP_OKAY "OKAY" #define T7XX_FB_RESP_FAIL "FAIL" #define T7XX_FB_RESP_DATA "DATA" #define T7XX_FB_RESP_INFO "INFO" #define T7XX_FB_CMD_GET_VER "get_version" +/* Internal region indexes */ +enum t7xx_regions { + T7XX_MRDUMP_INDEX, + T7XX_LKDUMP_INDEX, +}; + +struct t7xx_dump_region_info { + const char *name; + size_t size; +}; + +struct t7xx_dump_region { + struct t7xx_dump_region_info *info; + struct devlink_region_ops ops; + struct devlink_region *dlreg; + void *buf; +}; + struct t7xx_flash_dump { struct t7xx_pci_dev *t7xx_dev; struct t7xx_port *port; struct devlink *ctx; + struct t7xx_dump_region regions[T7XX_TOTAL_REGIONS]; + struct workqueue_struct *wq; + struct work_struct ws; unsigned long status; u8 mode; }; diff --git a/drivers/net/wwan/t7xx/t7xx_state_monitor.c b/drivers/net/wwan/t7xx/t7xx_state_monitor.c index 24f79e981fd9..86cdb0d572d4 100644 --- a/drivers/net/wwan/t7xx/t7xx_state_monitor.c +++ b/drivers/net/wwan/t7xx/t7xx_state_monitor.c @@ -244,6 +244,8 @@ static void t7xx_lk_stage_event_handling(struct t7xx_fsm_ctl *ctl, unsigned int if (lk_event == LK_EVENT_CREATE_POST_DL_PORT) md->t7xx_dev->flash_dump->mode = T7XX_FB_DL_MODE; + else + md->t7xx_dev->flash_dump->mode = T7XX_FB_DUMP_MODE; port->port_conf->ops->enable_chl(port); t7xx_cldma_start(md_ctrl); From patchwork Tue Sep 12 09:48:44 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jinjian Song X-Patchwork-Id: 13381204 X-Patchwork-Delegate: kuba@kernel.org Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BA7BD171B1 for ; Tue, 12 Sep 2023 09:49:55 +0000 (UTC) Received: from AUS01-SY4-obe.outbound.protection.outlook.com (mail-sy4aus01olkn2188.outbound.protection.outlook.com [40.92.62.188]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CA99B10F9; Tue, 12 Sep 2023 02:49:54 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=QFhT9AegLLtiEQDThGhQFkoo2n/5MHazMK7aMf85dSVMLAI1Ut8NxiDuDZbu3Q+eWfnXLNW6ghFyfJQUzdFCERZc/L1pwvY7+XFknHr4miiJf0iTHri8iCxHUb9KnGMf3Nv2Fg/INYKPN5uv58pAjSzoe0Wv3JxUj9YVJD6gq2CWOwqjVty3Y1le8m860XXE9PuaQ9SdhwH7vFSytg4tz7/CghjCaGwJ2YQxZUJHsA/OpAVnFNpu4Qxy6tpjm/I74GvmXrQEsQFouaGjH+9KpHzFWaknGF1AwslYxD+kBIMJHzr8g5KkofX8CIddJ9+/nuMZwpWOMwjqcxxEfECNUg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; 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; bh=p6GM24XSiJWLbY2WDpV0DErZ2kE+zYwpeBDXyZpl4HQ=; b=d0vuSPJNXKWhkG8ObNv3cLkiJvsGCL1LCd8BX+TTci/WOwx9o3xdihbVw1PJ2RTTVQ/aM191YX6D19kEesajIBgpENQatTbytcp5EU5OsepMGkAwl9RNB/NDlbI9F4UiuzF/C/+/Yew/YEPguS4TsV0EB4fuq6+SmRIxZAsXcL1Ufqbt0fLECBeHxAfDtQyrqR94li/MS8G+DFyTOLRaSLYIy8dsRug2hiJThpIkDG62De7pWDnp7uxAlyOel+zqxt7UxJdfjzwAgoWLR0UQzNwvA8CaUE6cFRXPGqJFNlw0QysNkQe7aGT2CZyu2u7H2ueGC77WiABt72Uvufbjaw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=none; dmarc=none; dkim=none; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=hotmail.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=p6GM24XSiJWLbY2WDpV0DErZ2kE+zYwpeBDXyZpl4HQ=; b=d0KskQjW4GDgGzxme/FF3orN5Ia9Sx3bC2CT6BV5uAEnCESNgUaHEGK5/lIfuVmtKUdmZsdSe07gjbQpP95p7f4cnm/K7HvAqFKiqM+yL4Fg334xZrvUMCkq8+I4CJafJxbF0Sj2c2wzOP8bXzKpA4ab97bf0/TbNEev/7A76dci0IncN2MBFSQZa+J6f2vbs3SJRMeIZvUkMzajDJnbI/tKTl6+CI/iGTEjWPRvd+ohfnTQI1byxAphUvGc9dUYlfPd8WVws/1rsdK42zAJ75T8Y6VO/AFo/k6rc19NP2s2N6Gsl70hTLtEeS1mf2dnWgAJ5G8B50dV2cESSx4P3g== Received: from ME3P282MB2703.AUSP282.PROD.OUTLOOK.COM (2603:10c6:220:16b::5) by SY4P282MB2981.AUSP282.PROD.OUTLOOK.COM (2603:10c6:10:15c::13) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6768.35; Tue, 12 Sep 2023 09:49:48 +0000 Received: from ME3P282MB2703.AUSP282.PROD.OUTLOOK.COM ([fe80::68b4:6263:97f:9a45]) by ME3P282MB2703.AUSP282.PROD.OUTLOOK.COM ([fe80::68b4:6263:97f:9a45%3]) with mapi id 15.20.6768.036; Tue, 12 Sep 2023 09:49:48 +0000 From: Jinjian Song To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, corbet@lwn.net, loic.poulain@linaro.org, ryazanov.s.a@gmail.com Cc: jiri@resnulli.us, johannes@sipsolutions.net, chandrashekar.devegowda@intel.com, linuxwwan@intel.com, chiranjeevi.rapolu@linux.intel.com, haijun.liu@mediatek.com, m.chetan.kumar@linux.intel.com, ricardo.martinez@linux.intel.com, netdev@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, nmarupaka@google.com, vsankar@lenovo.com, danielwinkler@google.com, Jinjian Song Subject: [net-next v4 4/5] net: wwan: t7xx: Adds sysfs attribute of modem event Date: Tue, 12 Sep 2023 17:48:44 +0800 Message-ID: X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230912094845.11233-1-songjinjian@hotmail.com> References: <20230912094845.11233-1-songjinjian@hotmail.com> X-TMN: [ggug/LKLf5lizIaW4an3zaN0VwkXRSr+] X-ClientProxiedBy: SI2PR01CA0048.apcprd01.prod.exchangelabs.com (2603:1096:4:193::17) To ME3P282MB2703.AUSP282.PROD.OUTLOOK.COM (2603:10c6:220:16b::5) X-Microsoft-Original-Message-ID: <20230912094845.11233-5-songjinjian@hotmail.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: ME3P282MB2703:EE_|SY4P282MB2981:EE_ X-MS-Office365-Filtering-Correlation-Id: 3e3ea742-ac44-4d32-ee90-08dbb37599ec X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: ThJ3mY8kXEP6IGT92Qzk3IaCaz10oy8kEWCDWkZnPqxyAdxbeDp+Blpdp88D6LPDg01wmlxDkx7o+8yeHeqNvKTANoEkFxCCiKYeQH9Vl2M0QRY8hTyB7ij/wmFvmF7jKCbq3FJmraA1iL++gKSdPBPO/oXJi0tvaiHVbaZ5USI4JvHohUvk8JUtjcCfRhnLBTjxWRByvUuE9u5qmNDRrsXb6dp2Xc2ylqwqLiwKDOASDjg46HxgVMCkISp3TBzcTq++Fp661ZgSjQx6EUtpfavQJylUmPfTZKFbuAczjbtbTYhFLamkQa098qn/Q6Hu6pmmwCzVUvlvo46YLMmjvqcBzo1Ag29nt2jDaeKpt4Ebcx34eRQyht9WCPS21UkGac5R95ihVGgOFaPhsklQYZSf2EA+A/EuZdmTTRMhT6jNC7V6lcUM+2C88m8Thnt7v0Rp4yZFszTPL/MSAXWFfFsZaHyrGfwOxnSmwo3BT3VfURmY5NWyhYzmoDYsh2T3G3qEtapej/skE1NavcdpjNySL5Ju9Wp1DaS5P8BPMH0EIrQTU5Nhq1ButLD26Ba0HZxFYX13ZR2y3I+rvCnrJUQUpmno5JpSGDuaxU2TcfA= X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: +DOOj+rych/Vi1pjTDMTBiQ7fooBhclk7viiCBWPmos9AHcre1avlHY1QkMdTghIcbHKk62orIcl5DmbVILok8ylV1M63+MZXkjuxKO/ry+1lffYeBCnfVYkZXIgTK1nAhSZicC4QoVIgz2EL1SsmusVQFs59IE2OoAgJL9Zgy7BTbhalncFaSpJKyHRoCMtWkFSlhxb5Z8eauarvSKtYl6rlW9t75+C2T7gS4bAC6pV1C9Ut0UYX7fKgjox5GgS2EgqlUhqqRatktF9optxmxpdNXn3QxuMtX+t163RwxmMQpl1E+u3BBJ7U+VHiGhBfSBCiGEgGqeUdOHy/0ukxiwSxVIAdxXPKP3N/b8DlxL9BgfkymRVrYoeeOB2ajXa7cwOrRSg5pSRKmJJUDYTnhJMD8KB6DHB6DKv2twpDytJpXO9zWnfSYFzNQLoJ7S28vlaa/eapxQuuoILc1ienKc/SyqA1+HwdQPWpk3oKYQn4ArfY42qp6qbzddgLByKCAW/2TyaL+JU9I6CMkLSjCj6GGueG9sBr6+gZgw7oZYS+eCYhGDLlRIXiO4Fq5C962cvk7x2K9tqOsBVHFzrdUEmRwLiAmZQmsUBLRvyt1Txqy5lqqMwEmlwBxk2rXMrpisrry09ovAZCaoXECM7HTgZycnCTPeLWX8jNQBgjRaY9vTd6TEjvtKv0ilJkL78FJ4DHHJq+DOuDA8RF2pLu3+YTYTr6opAB3Wuu7UnZ0oyGogTZVdHyH8smoJ18OVPzijAY8NdrlUYTNgOpDaaCw/ZHAe0fEfzuZxng+ncMCVIJy5WgW5Cc8TvwT0q3KvyW65V+3/MEKQJXf1zmaFL6o5oaTG1I6F/bS/A337wXur1SBn4Ud9vktNg95fvmZPHjtp3ySK/7bdRd138PIXvdanIQhP/gNFmHklPhyf9lLxI9/pRWGphjyndXhmqM8AjhGKldyhi+CJ/oUdpGruXqRtIvflp8e//xQnyF+aqXjWY77kINCbixRxuJUe9Xvh5weO3tllRmrXuRsQchhMwH4nNgEGt3jCzEVN/WWtKbKT3sx6rvt08XMm+uBLB8bWuN3erSPdkrMRlDYBvNWk6Z8D5hTYNTD4P471OpgpFYI07DWIMzY0aonJi7cIba2tTYCodD0PL9bvSEhluDtWxbW4huh5xRZvgDgR+JsoHBTPj2itEm9Uv0Ar6OKdwe+NwTkrI+wYunTEFr/PStRKbNRv4K03+hx54ue6fpbVhlIU= X-OriginatorOrg: sct-15-20-4755-11-msonline-outlook-746f3.templateTenant X-MS-Exchange-CrossTenant-Network-Message-Id: 3e3ea742-ac44-4d32-ee90-08dbb37599ec X-MS-Exchange-CrossTenant-AuthSource: ME3P282MB2703.AUSP282.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Sep 2023 09:49:48.1364 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 84df9e7f-e9f6-40af-b435-aaaaaaaaaaaa X-MS-Exchange-CrossTenant-RMS-PersistedConsumerOrg: 00000000-0000-0000-0000-000000000000 X-MS-Exchange-Transport-CrossTenantHeadersStamped: SY4P282MB2981 X-Patchwork-Delegate: kuba@kernel.org From: Jinjian Song Adds support for t7xx wwan device firmware flashing & coredump collection using devlink. Provides sysfs attribute on user space to query the event from modem about flashing/coredump/reset. Base on the v5 patch version of follow series: 'net: wwan: t7xx: fw flashing & coredump support' (https://patchwork.kernel.org/project/netdevbpf/patch/fc8bbb0b66a5ff3a489ea9857d79b374508090ef.1674307425.git.m.chetan.kumar@linux.intel.com/) Signed-off-by: Jinjian Song --- v4: * no change v3: * no change v2: * rename struct name from devlink to flash_dump --- drivers/net/wwan/t7xx/t7xx_modem_ops.c | 1 + drivers/net/wwan/t7xx/t7xx_pci.c | 62 ++++++++++++++++++++ drivers/net/wwan/t7xx/t7xx_pci.h | 17 ++++++ drivers/net/wwan/t7xx/t7xx_port_flash_dump.c | 14 +++++ drivers/net/wwan/t7xx/t7xx_port_flash_dump.h | 1 + drivers/net/wwan/t7xx/t7xx_state_monitor.c | 7 +++ 6 files changed, 102 insertions(+) diff --git a/drivers/net/wwan/t7xx/t7xx_modem_ops.c b/drivers/net/wwan/t7xx/t7xx_modem_ops.c index cbd65aa48721..4de75874f1b5 100644 --- a/drivers/net/wwan/t7xx/t7xx_modem_ops.c +++ b/drivers/net/wwan/t7xx/t7xx_modem_ops.c @@ -192,6 +192,7 @@ static irqreturn_t t7xx_rgu_isr_thread(int irq, void *data) { struct t7xx_pci_dev *t7xx_dev = data; + atomic_set(&t7xx_dev->event, T7XX_RESET); msleep(RGU_RESET_DELAY_MS); t7xx_reset_device_via_pmic(t7xx_dev); return IRQ_HANDLED; diff --git a/drivers/net/wwan/t7xx/t7xx_pci.c b/drivers/net/wwan/t7xx/t7xx_pci.c index 845d1555f134..e5579e04f82d 100644 --- a/drivers/net/wwan/t7xx/t7xx_pci.c +++ b/drivers/net/wwan/t7xx/t7xx_pci.c @@ -2,6 +2,7 @@ /* * Copyright (c) 2021, MediaTek Inc. * Copyright (c) 2021-2022, Intel Corporation. + * Copyright (c) 2023, Fibocom Wireless Inc. * * Authors: * Haijun Liu @@ -14,6 +15,7 @@ * Chiranjeevi Rapolu * Eliot Lee * Moises Veleta + * Jinjian Song */ #include @@ -60,6 +62,57 @@ enum t7xx_pm_state { MTK_PM_RESUMED, }; +static ssize_t t7xx_event_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + enum t7xx_event event = T7XX_UNKNOWN; + struct pci_dev *pdev; + struct t7xx_pci_dev *t7xx_dev; + + pdev = to_pci_dev(dev); + t7xx_dev = pci_get_drvdata(pdev); + if (!t7xx_dev) + return -ENODEV; + + event = atomic_read(&t7xx_dev->event); + if (event == T7XX_READY) { + return sprintf(buf, "T7XX_MODEM_READY\n"); + } else if (event == T7XX_RESET) { + return sprintf(buf, "T7XX_RESET\n"); + } else if (event == T7XX_FASTBOOT_DL_MODE) { + return sprintf(buf, "T7XX_MODEM_FASTBOOT_DL_MODE\n"); + } else if (event == T7XX_FLASH_SUCCESS) { + return sprintf(buf, "T7XX_FLASHING_SUCCESS\n"); + } else if (event == T7XX_FLASH_FAILURE) { + return sprintf(buf, "T7XX_FLASHING_FAILURE\n"); + } else if (event == T7XX_FASTBOOT_DUMP_MODE) { + return sprintf(buf, "T7XX_MODEM_FASTBOOT_DUMP_MODE\n"); + } else if (event == T7XX_MRDUMP_READY) { + return sprintf(buf, "T7XX_MRDUMP_READY size:%zu\n", + t7xx_dev->flash_dump->regions[T7XX_MRDUMP_INDEX].info->dump_size); + } else if (event == T7XX_LKDUMP_READY) { + return sprintf(buf, "T7XX_LKDUMP_READY size:%zu\n", + t7xx_dev->flash_dump->regions[T7XX_LKDUMP_INDEX].info->dump_size); + } else if (event == T7XX_MRDUMP_DISCARD) { + return sprintf(buf, "T7XX_MRDUMP_DISCARDED\n"); + } else if (event == T7XX_LKDUMP_DISCARD) { + return sprintf(buf, "T7XX_LKDUMP_DISCARDED\n"); + } + + return sprintf(buf, "T7XX_UNKNOWN\n"); +} + +static DEVICE_ATTR_RO(t7xx_event); + +static struct attribute *t7xx_event_attr[] = { + &dev_attr_t7xx_event.attr, + NULL +}; + +static const struct attribute_group t7xx_event_attribute_group = { + .attrs = t7xx_event_attr, +}; + static void t7xx_dev_set_sleep_capability(struct t7xx_pci_dev *t7xx_dev, bool enable) { void __iomem *ctrl_reg = IREG_BASE(t7xx_dev) + T7XX_PCIE_MISC_CTRL; @@ -734,8 +787,17 @@ static int t7xx_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) t7xx_pcie_mac_interrupts_dis(t7xx_dev); + ret = sysfs_create_group(&t7xx_dev->pdev->dev.kobj, + &t7xx_event_attribute_group); + if (ret) { + t7xx_md_exit(t7xx_dev); + goto err_devlink_unregister; + } + ret = t7xx_interrupt_init(t7xx_dev); if (ret) { + sysfs_remove_group(&t7xx_dev->pdev->dev.kobj, + &t7xx_event_attribute_group); t7xx_md_exit(t7xx_dev); goto err_devlink_unregister; } diff --git a/drivers/net/wwan/t7xx/t7xx_pci.h b/drivers/net/wwan/t7xx/t7xx_pci.h index 28f22a2dc493..b7c78a9530f3 100644 --- a/drivers/net/wwan/t7xx/t7xx_pci.h +++ b/drivers/net/wwan/t7xx/t7xx_pci.h @@ -2,6 +2,7 @@ * * Copyright (c) 2021, MediaTek Inc. * Copyright (c) 2021-2022, Intel Corporation. + * Copyright (c) 2023, Fibocom Wireless Inc. * * Authors: * Haijun Liu @@ -12,6 +13,7 @@ * Amir Hanania * Chiranjeevi Rapolu * Moises Veleta + * Jinjian Song */ #ifndef __T7XX_PCI_H__ @@ -84,6 +86,7 @@ struct t7xx_pci_dev { struct dentry *debugfs_dir; #endif struct t7xx_flash_dump *flash_dump; + atomic_t event; }; enum t7xx_pm_id { @@ -115,6 +118,20 @@ struct md_pm_entity { void *entity_param; }; +enum t7xx_event { + T7XX_UNKNOWN, + T7XX_READY, + T7XX_RESET, + T7XX_FASTBOOT_DL_MODE, + T7XX_FLASH_SUCCESS, + T7XX_FLASH_FAILURE, + T7XX_FASTBOOT_DUMP_MODE, + T7XX_MRDUMP_READY, + T7XX_LKDUMP_READY, + T7XX_MRDUMP_DISCARD, + T7XX_LKDUMP_DISCARD, +}; + void t7xx_pci_disable_sleep(struct t7xx_pci_dev *t7xx_dev); void t7xx_pci_enable_sleep(struct t7xx_pci_dev *t7xx_dev); int t7xx_pci_sleep_disable_complete(struct t7xx_pci_dev *t7xx_dev); diff --git a/drivers/net/wwan/t7xx/t7xx_port_flash_dump.c b/drivers/net/wwan/t7xx/t7xx_port_flash_dump.c index b8ef3b7d7430..0a0f2847aa3f 100644 --- a/drivers/net/wwan/t7xx/t7xx_port_flash_dump.c +++ b/drivers/net/wwan/t7xx/t7xx_port_flash_dump.c @@ -201,11 +201,14 @@ static int t7xx_flash_dump_fb_get_core(struct t7xx_port *port) continue; } else if (!strcmp(mcmd, T7XX_FB_RESP_MRDUMP_DONE)) { dev_dbg(port->dev, "%s! size:%zd\n", T7XX_FB_RESP_MRDUMP_DONE, offset_dlen); + flash_dump->regions[T7XX_MRDUMP_INDEX].info->dump_size = offset_dlen; + atomic_set(&port->t7xx_dev->event, T7XX_MRDUMP_READY); clear_bit(T7XX_MRDUMP_STATUS, &flash_dump->status); return 0; } dev_err(port->dev, "getcore protocol error (read len %05d, response %s)\n", clen, mcmd); + atomic_set(&port->t7xx_dev->event, T7XX_MRDUMP_DISCARD); ret = -EPROTO; goto free_mem; } @@ -248,6 +251,7 @@ static int t7xx_flash_dump_fb_dump_log(struct t7xx_port *port) if (datasize > lkdump_region->info->size) { dev_err(port->dev, "lkdump size is more than %dKB. Discarded!\n", T7XX_LKDUMP_SIZE / 1024); + atomic_set(&port->t7xx_dev->event, T7XX_LKDUMP_DISCARD); ret = -EFBIG; goto err_clear_bit; } @@ -272,6 +276,8 @@ static int t7xx_flash_dump_fb_dump_log(struct t7xx_port *port) } dev_dbg(port->dev, "LKDUMP DONE! size:%zd\n", offset); + lkdump_region->info->dump_size = offset; + atomic_set(&port->t7xx_dev->event, T7XX_LKDUMP_READY); clear_bit(T7XX_LKDUMP_STATUS, &flash_dump->status); return t7xx_flash_dump_fb_handle_response(port, NULL); @@ -361,6 +367,10 @@ static int t7xx_devlink_flash_update(struct devlink *devlink, clear_bit(T7XX_FLASH_STATUS, &flash_dump->status); err_out: + if (ret) + atomic_set(&port->t7xx_dev->event, T7XX_FLASH_FAILURE); + else + atomic_set(&port->t7xx_dev->event, T7XX_FLASH_SUCCESS); return ret; } @@ -411,9 +421,13 @@ static int t7xx_devlink_reload_up(struct devlink *devlink, u32 *actions_performed, struct netlink_ext_ack *extack) { + struct t7xx_flash_dump *flash_dump = devlink_priv(devlink); + *actions_performed = BIT(action); switch (action) { case DEVLINK_RELOAD_ACTION_DRIVER_REINIT: + atomic_set(&flash_dump->t7xx_dev->event, T7XX_RESET); + return 0; case DEVLINK_RELOAD_ACTION_FW_ACTIVATE: return 0; default: diff --git a/drivers/net/wwan/t7xx/t7xx_port_flash_dump.h b/drivers/net/wwan/t7xx/t7xx_port_flash_dump.h index 90758baa7854..057bb36216ca 100644 --- a/drivers/net/wwan/t7xx/t7xx_port_flash_dump.h +++ b/drivers/net/wwan/t7xx/t7xx_port_flash_dump.h @@ -57,6 +57,7 @@ enum t7xx_regions { struct t7xx_dump_region_info { const char *name; size_t size; + size_t dump_size; }; struct t7xx_dump_region { diff --git a/drivers/net/wwan/t7xx/t7xx_state_monitor.c b/drivers/net/wwan/t7xx/t7xx_state_monitor.c index 86cdb0d572d4..ab35342a2d16 100644 --- a/drivers/net/wwan/t7xx/t7xx_state_monitor.c +++ b/drivers/net/wwan/t7xx/t7xx_state_monitor.c @@ -249,6 +249,12 @@ static void t7xx_lk_stage_event_handling(struct t7xx_fsm_ctl *ctl, unsigned int port->port_conf->ops->enable_chl(port); t7xx_cldma_start(md_ctrl); + + if (lk_event == LK_EVENT_CREATE_POST_DL_PORT) + atomic_set(&md->t7xx_dev->event, T7XX_FASTBOOT_DL_MODE); + else + atomic_set(&md->t7xx_dev->event, T7XX_FASTBOOT_DUMP_MODE); + break; default: @@ -332,6 +338,7 @@ static void fsm_routine_ready(struct t7xx_fsm_ctl *ctl) ctl->curr_state = FSM_STATE_READY; t7xx_fsm_broadcast_ready_state(ctl); + atomic_set(&md->t7xx_dev->event, T7XX_READY); t7xx_md_event_notify(md, FSM_READY); } From patchwork Tue Sep 12 09:48:45 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jinjian Song X-Patchwork-Id: 13381205 X-Patchwork-Delegate: kuba@kernel.org Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 660ED17737 for ; Tue, 12 Sep 2023 09:50:01 +0000 (UTC) Received: from AUS01-SY4-obe.outbound.protection.outlook.com (mail-sy4aus01olkn2178.outbound.protection.outlook.com [40.92.62.178]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D19E0E6B; Tue, 12 Sep 2023 02:50:00 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=lTd2H2FilmVbvA2rd1f2/KmvmGu7inD6/KHQEtCAhERPATS/WxL5UEPbM7dKPddY7GcmAkwAiPFCg2+OI1KRJT40cMK1+cGhhys0d5mYu0YFj45U1CsuPGfdZH3cSul1PGSJp5d7Z2NlgPrHw7QILrP1nVEtsaiQ9TxvtPI2Kl3Vnb8tqCdVXt5BIpGCWoNBWflSbttLmRnt5sJcTuULZ1OTY1gzkm7j0sTTipQr1WFKG4YnWz3n2jiPEhtYYR8x+dQUeu11PTyNco4D5WxeYnuOQnbQ1emhnXxdew6NkgUNk3Kkz3lLWxP2aMcy+mbWX3hG7B3CXNCQqg8uPHs3zQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; 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; bh=11PJmNmcYjmj5VVgJ7K0q+adbrpE0xocLu9jecU+ClE=; b=UssN1aGIpprEQH3IlKZguXJ7Gzlr9ok2Mqx7qyuC57P0at1RyvNLrFno7fmVUJ0yASL2vCgu/2a57qgo31RYfOIrZHNOBx2JgoVeyDB99kNeD92aHs+Og9xHKrC4ZZPr76RsJkMSriNEmZewDQ7f8Ytr0VeVj2YRTo2L8RIUJPqO9TMMmG77jg+5HMsKW/F41bhBkDY0+a8jtk2KVpJ3laqysUr7ek4KUDoWZF9XCaMzk0xH0T4e1AOGwamLtc5tKZYL2pmB2oW9jqun7c+36T9//KiqjgQt19YPSY4W3Gvc9WyuNhdzi5zHggk/3qECcl7wfcmKK99WsVkQ5SZiDg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=none; dmarc=none; dkim=none; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=hotmail.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=11PJmNmcYjmj5VVgJ7K0q+adbrpE0xocLu9jecU+ClE=; b=DmhjbxhDwFmxEcSRRetIMfuePjRjiADfp+V3ohRu7Lu6z4+CKorrJtHeOn5WZsefPpXmEyQu07PHheCRd3yU6D/UE5T6dHX6LcUPYGFTVdPcaXd1jWEI+BbfobCOZGs8RptlsjNbPZVZeMqiD+0khij0lQWeeEU+8fa+tamFFvGO+CoqaHmWC/D5lczBVhDQz7KStvh2t7nsE5olhLKeZmywD+yeief+VaMEJHL5r6U7lAGWn1XHcltrKPPUgo+6gvCkE+h1jyIhAsjBDCr1Susvb998YLUAd8k/Gv+zuLwIjtA7XZuq6YWEvouG24ba9Jd0DfZev7PKB5+ab+NCkg== Received: from ME3P282MB2703.AUSP282.PROD.OUTLOOK.COM (2603:10c6:220:16b::5) by SY4P282MB2981.AUSP282.PROD.OUTLOOK.COM (2603:10c6:10:15c::13) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6768.35; Tue, 12 Sep 2023 09:49:53 +0000 Received: from ME3P282MB2703.AUSP282.PROD.OUTLOOK.COM ([fe80::68b4:6263:97f:9a45]) by ME3P282MB2703.AUSP282.PROD.OUTLOOK.COM ([fe80::68b4:6263:97f:9a45%3]) with mapi id 15.20.6768.036; Tue, 12 Sep 2023 09:49:53 +0000 From: Jinjian Song To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, corbet@lwn.net, loic.poulain@linaro.org, ryazanov.s.a@gmail.com Cc: jiri@resnulli.us, johannes@sipsolutions.net, chandrashekar.devegowda@intel.com, linuxwwan@intel.com, chiranjeevi.rapolu@linux.intel.com, haijun.liu@mediatek.com, m.chetan.kumar@linux.intel.com, ricardo.martinez@linux.intel.com, netdev@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, nmarupaka@google.com, vsankar@lenovo.com, danielwinkler@google.com, Jinjian Song Subject: [net-next v4 5/5] net: wwan: t7xx: Devlink documentation Date: Tue, 12 Sep 2023 17:48:45 +0800 Message-ID: X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230912094845.11233-1-songjinjian@hotmail.com> References: <20230912094845.11233-1-songjinjian@hotmail.com> X-TMN: [0tyZKwlvml3QWeml2v5sWNFNmeExt5Z6] X-ClientProxiedBy: SI2PR01CA0048.apcprd01.prod.exchangelabs.com (2603:1096:4:193::17) To ME3P282MB2703.AUSP282.PROD.OUTLOOK.COM (2603:10c6:220:16b::5) X-Microsoft-Original-Message-ID: <20230912094845.11233-6-songjinjian@hotmail.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: ME3P282MB2703:EE_|SY4P282MB2981:EE_ X-MS-Office365-Filtering-Correlation-Id: 45576c39-06a7-4af6-2ce8-08dbb3759d1c X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: Zs7oW/5CfsiKFabRl24+0Mi/CGOJ4ksvAjNX09hdzBF2txwEZ7zH3Zkp0HJeSOMRGvds8VXGKvE5J9K6mw3zYOEWVsMa2Rw6wSfBKyL7S7YyKXeO2/DpEUKQfT9ho/HsODpnyWoeTknJmUmY59+oHG9gqMTqJ0Bgy84K9rN6t39ZEDCtFubdb3QlkekCnkcEVtaUc/V7Qte/ZjPa23OXRrCPzzDPmuZqcZ+3p0RbjMxeme4jTwNFxNXHNIagfr3T3aVEfvUYCGSiCGLPDJbh9TjKQpdVuuVbKECdGXHbc1Qc+MjIqwHVPw/oUb90IzEXgHiNaAOolYacSN31fxUxEblVEm4kaptsniwR2+ypbTk5p3V7MPGqWCIuQVEThlY+vxkkEwJL3jffeXtBLWwaHIlTn3EYaEdi4OUr6jHWgUaosB9mT3cRSXlX+IaWLl9UEdnZG+i+vzVLoZN930GNHLsuh5XZqBw4FwQSt5ZwxBTKPSL+HaycjBkl4Xiup/QBuNOrnEDEETz3MhrIFj2kQolqUZgBjQGNBoJ/FL+pROhFUSeSwmGLfjtCajPgJ8zbCTNy/rKPjxZupyDesxMVPi8wTGzckm924sGn4ll+VyQ= X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: /e/BXWVkX3l6xpYIsxjYLimsrssC+hmIVJMqmMrzhsmlVTbA5EApM50eM8Pqikby6HoDRrjcFXCCTEiniGVMDL1LUWUUoiQr/Kr05C8rHufIFHNL4Rh+IA8UCtCgh64Utk0fNYaUDMusfl4H72vD9Cr3T4VISDpoZz5XfPdbc14MphNUvoybC8g3iBSW//hMjnnThZ3AKNe+X3aUq2tNFpZzC+cjeS749Y50XrZ7lG+P5IQPwBDPNMXjt9EGTrtK07jGc4f69REEDBVozXq4om5dp3HfthNv5IhB7Zl0dSZd6+wKOX3IxmGHUNJuYTcX8cBzPfBFpaKPuz6VLPHGQrX9gZmtVxORfPph/8z8viQtrLE6ytAVNDMsqCpdaXOzwAMd7C8PZMDMst3R77RqyxejWeCkwjKxATQ5BJZoTxScPreiw1vbkwc1YmKOwnuHRTLliu29vq4M9oO6tlXTqAdgIpnuqioOjrNLTksVwyYr2BjrWHPDjQlSh8nwWC/KSfulL32uI+ebtt+tFak3fW865e80UYgbWJKHACQQ76QTEGNoLLiqon0li4lXTquMHy9KJd3DvwzQVO8KnmwxEj8iBfM3lHUarsGXt5bbaKCjmHjpxJkwjhUmY4+NO1mVXL/Le6KkjKeCtMRtNPwvu9oIP/BsFi9sK+OJNHdRtKEqgeT4c0xDWeGt/0GpDhH//SaewEMFRfVHcEVIBU2qjcRNfAIIwS0XEdbn52Oq3PFURA5wEFxq5SKJDUJIiGuLQ7rnMG4oJ89kO3lCeN9YnrcP0AwZdyK3omwcSLUbtwaqEQrbR0MTh13cJe2f3D7z4jsPADHUWW2HK+VV6fwoUByIUZMKOG3EtbLON8XAE32p3CTPgXkAshmxJL/ktOEeUrSJ+VgII3TNF78J9vJMFdcG4CUKachmn9UmWJI6oZINQ7ehvEoDMQzPFqpRdrssIr1iVkUC4yPnNbpWYo/J1XDM7m4xIUdFXDshrmI8OghPwbRHAQJnMf+qwXph2GuQhEQ3OsPJlTCrTocAnwWJU8ffvqu3PlOxx5n72/Nfc11mFWtHu6El2bGn+a3xu4RhS1FfG9BPDrTq2aC+R3Zl9vqXkZ+cToE0QN4wEi6cN7ly33rZc9wo87FxuVyQR+6ZWSBBNe9xqbjx/Bd/LLf4Q0tVioJqieGl2sgFEbkK4PfGf+pSy9OVnSSYP+5qQrSuvvRc/tcGYsGorPSuzym+REud1iNhv34H2Ul1YITxrD8= X-OriginatorOrg: sct-15-20-4755-11-msonline-outlook-746f3.templateTenant X-MS-Exchange-CrossTenant-Network-Message-Id: 45576c39-06a7-4af6-2ce8-08dbb3759d1c X-MS-Exchange-CrossTenant-AuthSource: ME3P282MB2703.AUSP282.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Sep 2023 09:49:53.4538 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 84df9e7f-e9f6-40af-b435-aaaaaaaaaaaa X-MS-Exchange-CrossTenant-RMS-PersistedConsumerOrg: 00000000-0000-0000-0000-000000000000 X-MS-Exchange-Transport-CrossTenantHeadersStamped: SY4P282MB2981 X-Patchwork-Delegate: kuba@kernel.org From: Jinjian Song Document the t7xx devlink commands usage for firmware flashing & coredump collection. Base on the v5 patch version of follow series: 'net: wwan: t7xx: fw flashing & coredump support' (https://patchwork.kernel.org/project/netdevbpf/patch/f902d4a0cb807a205687f7e693079fba72ca7341.1674307425.git.m.chetan.kumar@linux.intel.com/) Signed-off-by: Jinjian Song --- v4: * no change v3: * supplementary separator '~' v2: * no change --- Documentation/networking/devlink/index.rst | 1 + Documentation/networking/devlink/t7xx.rst | 232 +++++++++++++++++++++ 2 files changed, 233 insertions(+) create mode 100644 Documentation/networking/devlink/t7xx.rst diff --git a/Documentation/networking/devlink/index.rst b/Documentation/networking/devlink/index.rst index b49749e2b9a6..f101781105ca 100644 --- a/Documentation/networking/devlink/index.rst +++ b/Documentation/networking/devlink/index.rst @@ -67,3 +67,4 @@ parameters, info versions, and other features it supports. iosm octeontx2 sfc + mtk_t7xx diff --git a/Documentation/networking/devlink/t7xx.rst b/Documentation/networking/devlink/t7xx.rst new file mode 100644 index 000000000000..20057bda3923 --- /dev/null +++ b/Documentation/networking/devlink/t7xx.rst @@ -0,0 +1,232 @@ +.. SPDX-License-Identifier: GPL-2.0 + +==================== +t7xx devlink support +==================== + +This document describes the devlink features implemented by the ``t7xx`` +device driver. + +Parameters +========== +The ``t7xx`` driver implements the following driver-specific parameters. + +.. list-table:: Driver-specific parameters + :widths: 5 5 5 85 + + * - Name + - Type + - Mode + - Description + * - ``fastboot`` + - boolean + - driverinit + - Set this param to enter fastboot mode. + +Flash Update +============ + +The ``t7xx`` driver implements the flash update using the ``devlink-flash`` +interface. + +The driver uses ``DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK`` to identify the type of +firmware image that need to be programmed upon the request by user space application. + +``t7xx`` driver uses fastboot protocol for firmware flashing. In the firmware +flashing procedure, fastboot command & response are exchanged between driver +and wwan device. + +:: + + $ devlink dev param set pci/0000:bdf name fastboot value 1 cmode driverinit + +The devlink param fastboot is set to true via devlink param command, by +passing name ``fastboot``, value ``1`` and cmode ``driverinit``. + +:: + + $ devlink dev reload pci/0000:$bdf action driver_reinit + +The wwan device is put into fastboot mode via devlink reload command, by +passing ``driver_reinit`` action. + +:: + + $ devlink dev reload pci/0000:$bdf action fw_activate + +Upon completion of firmware flashing or coredump collection the wwan device is +reset to normal mode using devlink reload command, by passing ``fw_activate`` +action. + +Flash Commands +-------------- + +:: + + $ devlink dev flash pci/0000:$bdf file preloader_k6880v1_mdot2_datacard.bin component "preloader" + +:: + + $ devlink dev flash pci/0000:$bdf file loader_ext-verified.img component "loader_ext1" + +:: + + $ devlink dev flash pci/0000:$bdf file tee-verified.img component "tee1" + +:: + + $ devlink dev flash pci/0000:$bdf file lk-verified.img component "lk" + +:: + + $ devlink dev flash pci/0000:$bdf file spmfw-verified.img component "spmfw" + +:: + + $ devlink dev flash pci/0000:$bdf file sspm-verified.img component "sspm_1" + +:: + + $ devlink dev flash pci/0000:$bdf file mcupm-verified.img component "mcupm_1" + +:: + + $ devlink dev flash pci/0000:$bdf file dpm-verified.img component "dpm_1" + +:: + + $ devlink dev flash pci/0000:$bdf file boot-verified.img component "boot" + +:: + + $ devlink dev flash pci/0000:$bdf file root.squashfs component "rootfs" + +:: + + $ devlink dev flash pci/0000:$bdf file modem-verified.img component "md1img" + +:: + + $ devlink dev flash pci/0000:$bdf file dsp-verified.bin component "md1dsp" + +:: + + $ devlink dev flash pci/0000:$bdf file OP_OTA.img component "mcf1" + +:: + + $ devlink dev flash pci/0000:$bdf file OEM_OTA.img component "mcf2" + +:: + + $ devlink dev flash pci/0000:$bdf file DEV_OTA.img component "mcf3" + +Note: Component selects the partition type to be programmed. + + +The supported list of firmware image types is described below. + +.. list-table:: Firmware Image types + :widths: 15 85 + + * - Name + - Description + * - ``preloader`` + - The first-stage bootloader image + * - ``loader_ext1`` + - Preloader extension image + * - ``tee1`` + - ARM trusted firmware and TEE (Trusted Execution Environment) image + * - ``lk`` + - The second-stage bootloader image + * - ``spmfw`` + - MediaTek in-house ASIC for power management image + * - ``sspm_1`` + - MediaTek in-house ASIC for power management under secure world image + * - ``mcupm_1`` + - MediaTek in-house ASIC for cpu power management image + * - ``dpm_1`` + - MediaTek in-house ASIC for dram power management image + * - ``boot`` + - The kernel and dtb image + * - ``rootfs`` + - Root filesystem image + * - ``md1img`` + - Modem image + * - ``md1dsp`` + - Modem DSP image + * - ``mcf1`` + - Modem OTA image (Modem Configuration Framework) for operators + * - ``mcf2`` + - Modem OTA image (Modem Configuration Framework) for OEM vendors + * - ``mcf3`` + - Modem OTA image (other usage) for OEM configurations + + +Regions +======= + +The ``t7xx`` driver supports core dump collection in exception state and second +stage bootloader log collection in fastboot mode. The log snapshot is taken by +the driver using fastboot commands. + +Region commands +--------------- + +:: + + $ devlink region show + +This command list the regions implemented by driver. These regions are accessed +for device internal data. Below table describes the regions. + +.. list-table:: Regions + :widths: 15 85 + + * - Name + - Description + * - ``mr_dump`` + - The detailed modem component logs are captured in this region + * - ``lk_dump`` + - This region dumps the current snapshot of lk + +Coredump Collection +~~~~~~~~~~~~~~~~~~~ + +:: + + $ devlink region new mr_dump + +:: + + $ devlink region read mr_dump snapshot 0 address 0 length $len + +:: + + $ devlink region del mr_dump snapshot 0 + +Note: $len is actual len to be dumped. + +The userspace application uses these commands for obtaining the modem component +logs when device encounters an exception. + +Second Stage Bootloader dump +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + $ devlink region new lk_dump + +:: + + $ devlink region read lk_dump snapshot 0 address 0 length $len + +:: + + $ devlink region del lk_dump snapshot 0 + +Note: $len is actual len to be dumped. + +In fastboot mode the userspace application uses these commands for obtaining the +current snapshot of second stage bootloader. +