From: Jinjian Song <songjinjian@hotmail.com>
To: netdev@vger.kernel.org
Cc: chandrashekar.devegowda@intel.com,
chiranjeevi.rapolu@linux.intel.com, haijun.liu@mediatek.com,
m.chetan.kumar@linux.intel.com, ricardo.martinez@linux.intel.com,
loic.poulain@linaro.org, ryazanov.s.a@gmail.com,
johannes@sipsolutions.net, davem@davemloft.net,
edumazet@google.com, kuba@kernel.org, pabeni@redhat.com,
linux-kernel@vger.kernel.com, vsankar@lenovo.com,
danielwinkler@google.com, nmarupaka@google.com,
joey.zhao@fibocom.com, liuqf@fibocom.com, felix.yan@fibocom.com,
Jinjian Song <jinjian.song@fibocom.com>
Subject: [net-next v4 4/4] net: wwan: t7xx: Add fastboot WWAN port
Date: Fri, 12 Jan 2024 20:00:14 +0800 [thread overview]
Message-ID: <MEYP282MB26975EE162B2A63903FD1C02BB6F2@MEYP282MB2697.AUSP282.PROD.OUTLOOK.COM> (raw)
In-Reply-To: <20240112120014.3917-1-songjinjian@hotmail.com>
From: Jinjian Song <jinjian.song@fibocom.com>
On early detection of wwan device in fastboot mode, driver sets
up CLDMA0 HW tx/rx queues for raw data transfer and then create
fastboot port to userspace.
Application can use this port to flash firmware and collect
core dump by fastboot protocol commands.
Signed-off-by: Jinjian Song <jinjian.song@fibocom.com>
---
v4:
* change function prefix to t7xx_port_fastboot
* change the name 'FASTBOOT' to fastboot in struct t7xx_early_port_conf
v3:
* no change
v2:
* no change
---
.../networking/device_drivers/wwan/t7xx.rst | 14 ++
drivers/net/wwan/t7xx/Makefile | 1 +
drivers/net/wwan/t7xx/t7xx_port_fastboot.c | 155 ++++++++++++++++++
drivers/net/wwan/t7xx/t7xx_port_proxy.c | 3 +
drivers/net/wwan/t7xx/t7xx_port_proxy.h | 2 +
drivers/net/wwan/t7xx/t7xx_state_monitor.c | 4 +
6 files changed, 179 insertions(+)
create mode 100644 drivers/net/wwan/t7xx/t7xx_port_fastboot.c
diff --git a/Documentation/networking/device_drivers/wwan/t7xx.rst b/Documentation/networking/device_drivers/wwan/t7xx.rst
index d13624a52d8b..7257ede90152 100644
--- a/Documentation/networking/device_drivers/wwan/t7xx.rst
+++ b/Documentation/networking/device_drivers/wwan/t7xx.rst
@@ -125,6 +125,20 @@ The driver exposes an AT port by implementing AT WWAN Port.
The userspace end of the control port is a /dev/wwan0at0 character
device. Application shall use this interface to issue AT commands.
+fastboot port userspace ABI
+---------------------------
+
+/dev/wwan0fastboot0 character device
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The driver exposes a fastboot protocol interface by implementing
+fastboot WWAN Port. The userspace end of the fastboot channel pipe is a
+/dev/wwan0fastboot0 character device. Application shall use this interface for
+fastboot protocol communication.
+
+Please note that driver needs to be reloaded to export /dev/wwan0fastboot0
+port, because device needs a cold reset after enter ``FASTBOOT_DL_SWITCHING``
+mode.
+
The MediaTek's T700 modem supports the 3GPP TS 27.007 [4] specification.
References
diff --git a/drivers/net/wwan/t7xx/Makefile b/drivers/net/wwan/t7xx/Makefile
index 2652cd00504e..ddf03efe388a 100644
--- a/drivers/net/wwan/t7xx/Makefile
+++ b/drivers/net/wwan/t7xx/Makefile
@@ -11,6 +11,7 @@ mtk_t7xx-y:= t7xx_pci.o \
t7xx_port_proxy.o \
t7xx_port_ctrl_msg.o \
t7xx_port_wwan.o \
+ t7xx_port_fastboot.o \
t7xx_hif_dpmaif.o \
t7xx_hif_dpmaif_tx.o \
t7xx_hif_dpmaif_rx.o \
diff --git a/drivers/net/wwan/t7xx/t7xx_port_fastboot.c b/drivers/net/wwan/t7xx/t7xx_port_fastboot.c
new file mode 100644
index 000000000000..880931af3433
--- /dev/null
+++ b/drivers/net/wwan/t7xx/t7xx_port_fastboot.c
@@ -0,0 +1,155 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2023, Fibocom Wireless Inc.
+ *
+ * Authors:
+ * Jinjian Song <jinjian.song@fibocom.com>
+ */
+
+#include <linux/atomic.h>
+#include <linux/dev_printk.h>
+#include <linux/err.h>
+#include <linux/minmax.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/wwan.h>
+
+#include "t7xx_port.h"
+#include "t7xx_port_proxy.h"
+#include "t7xx_state_monitor.h"
+
+static int t7xx_port_fastboot_start(struct wwan_port *port)
+{
+ struct t7xx_port *port_mtk = wwan_port_get_drvdata(port);
+
+ if (atomic_read(&port_mtk->usage_cnt))
+ return -EBUSY;
+
+ atomic_inc(&port_mtk->usage_cnt);
+ return 0;
+}
+
+static void t7xx_port_fastboot_stop(struct wwan_port *port)
+{
+ struct t7xx_port *port_mtk = wwan_port_get_drvdata(port);
+
+ atomic_dec(&port_mtk->usage_cnt);
+}
+
+static int t7xx_port_fastboot_tx(struct wwan_port *port, struct sk_buff *skb)
+{
+ struct t7xx_port *port_private = wwan_port_get_drvdata(port);
+ struct sk_buff *cur = skb, *cloned;
+ size_t actual, len, offset = 0;
+ int ret;
+ int txq_mtu;
+
+ if (!port_private->chan_enable)
+ return -EINVAL;
+
+ txq_mtu = t7xx_get_port_mtu(port_private);
+ if (txq_mtu < 0)
+ return -EINVAL;
+
+ actual = cur->len;
+ while (actual) {
+ len = min_t(size_t, actual, txq_mtu);
+ cloned = __dev_alloc_skb(len, GFP_KERNEL);
+ if (!cloned)
+ return -ENOMEM;
+
+ skb_put_data(cloned, cur->data + offset, len);
+
+ ret = t7xx_port_send_raw_skb(port_private, cloned);
+ if (ret) {
+ dev_kfree_skb(cloned);
+ dev_err(port_private->dev, "Write error on fastboot port, %d\n", ret);
+ break;
+ }
+ offset += len;
+ actual -= len;
+ }
+
+ dev_kfree_skb(skb);
+ return 0;
+}
+
+static const struct wwan_port_ops wwan_ops = {
+ .start = t7xx_port_fastboot_start,
+ .stop = t7xx_port_fastboot_stop,
+ .tx = t7xx_port_fastboot_tx,
+};
+
+static int t7xx_port_fastboot_init(struct t7xx_port *port)
+{
+ const struct t7xx_port_conf *port_conf = port->port_conf;
+ unsigned int header_len = sizeof(struct ccci_header), mtu;
+ struct wwan_port_caps caps;
+
+ port->rx_length_th = RX_QUEUE_MAXLEN;
+
+ if (!port->wwan.wwan_port) {
+ 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);
+ if (IS_ERR(port->wwan.wwan_port))
+ dev_err(port->dev, "Unable to create WWWAN port %s", port_conf->name);
+ }
+
+ return 0;
+}
+
+static void t7xx_port_fastboot_uninit(struct t7xx_port *port)
+{
+ if (!port->wwan.wwan_port)
+ return;
+
+ port->rx_length_th = 0;
+ wwan_remove_port(port->wwan.wwan_port);
+ port->wwan.wwan_port = NULL;
+}
+
+static int t7xx_port_fastboot_recv_skb(struct t7xx_port *port, struct sk_buff *skb)
+{
+ if (!atomic_read(&port->usage_cnt) || !port->chan_enable) {
+ const struct t7xx_port_conf *port_conf = port->port_conf;
+
+ dev_kfree_skb_any(skb);
+ dev_err_ratelimited(port->dev, "Port %s is not opened, drop packets\n",
+ port_conf->name);
+ /* Dropping skb, caller should not access skb.*/
+ return 0;
+ }
+
+ wwan_port_rx(port->wwan.wwan_port, skb);
+
+ return 0;
+}
+
+static int t7xx_port_fastboot_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_fastboot_disable_chl(struct t7xx_port *port)
+{
+ spin_lock(&port->port_update_lock);
+ port->chan_enable = false;
+ spin_unlock(&port->port_update_lock);
+
+ return 0;
+}
+
+struct port_ops fastboot_port_ops = {
+ .init = t7xx_port_fastboot_init,
+ .recv_skb = t7xx_port_fastboot_recv_skb,
+ .uninit = t7xx_port_fastboot_uninit,
+ .enable_chl = t7xx_port_fastboot_enable_chl,
+ .disable_chl = t7xx_port_fastboot_disable_chl,
+};
diff --git a/drivers/net/wwan/t7xx/t7xx_port_proxy.c b/drivers/net/wwan/t7xx/t7xx_port_proxy.c
index e53a152faee4..7200d2d210fc 100644
--- a/drivers/net/wwan/t7xx/t7xx_port_proxy.c
+++ b/drivers/net/wwan/t7xx/t7xx_port_proxy.c
@@ -112,6 +112,9 @@ static const 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 = &fastboot_port_ops,
+ .name = "fastboot",
+ .port_type = WWAN_PORT_FASTBOOT,
},
};
diff --git a/drivers/net/wwan/t7xx/t7xx_port_proxy.h b/drivers/net/wwan/t7xx/t7xx_port_proxy.h
index 7f5706811445..0f40b4884dc0 100644
--- a/drivers/net/wwan/t7xx/t7xx_port_proxy.h
+++ b/drivers/net/wwan/t7xx/t7xx_port_proxy.h
@@ -98,6 +98,8 @@ extern struct port_ops ctl_port_ops;
extern struct port_ops t7xx_trace_port_ops;
#endif
+extern struct port_ops fastboot_port_ops;
+
void t7xx_port_proxy_reset(struct port_proxy *port_prox);
void t7xx_port_proxy_uninit(struct port_proxy *port_prox);
int t7xx_port_proxy_init(struct t7xx_modem *md);
diff --git a/drivers/net/wwan/t7xx/t7xx_state_monitor.c b/drivers/net/wwan/t7xx/t7xx_state_monitor.c
index 3f5e8759705c..7cec51666f42 100644
--- a/drivers/net/wwan/t7xx/t7xx_state_monitor.c
+++ b/drivers/net/wwan/t7xx/t7xx_state_monitor.c
@@ -229,6 +229,7 @@ static void t7xx_lk_stage_event_handling(struct t7xx_fsm_ctl *ctl, unsigned int
struct cldma_ctrl *md_ctrl;
enum lk_event_id lk_event;
struct device *dev;
+ struct t7xx_port *port;
dev = &md->t7xx_dev->pdev->dev;
lk_event = FIELD_GET(MISC_LK_EVENT_MASK, status);
@@ -244,6 +245,9 @@ static void t7xx_lk_stage_event_handling(struct t7xx_fsm_ctl *ctl, unsigned int
t7xx_cldma_stop(md_ctrl);
t7xx_cldma_switch_cfg(md_ctrl, CLDMA_DEDICATED_Q_CFG);
+ port = &ctl->md->port_prox->ports[0];
+ port->port_conf->ops->enable_chl(port);
+
t7xx_cldma_start(md_ctrl);
if (lk_event == LK_EVENT_CREATE_POST_DL_PORT)
--
2.34.1
prev parent reply other threads:[~2024-01-12 12:01 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20240112120014.3917-1-songjinjian@hotmail.com>
2024-01-12 12:00 ` [net-next v4 1/4] wwan: core: Add WWAN fastboot port type Jinjian Song
2024-01-12 12:00 ` [net-next v4 2/4] net: wwan: t7xx: Add sysfs attribute for device state machine Jinjian Song
2024-01-12 12:00 ` [net-next v4 3/4] net: wwan: t7xx: Infrastructure for early port configuration Jinjian Song
2024-01-12 12:00 ` Jinjian Song [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=MEYP282MB26975EE162B2A63903FD1C02BB6F2@MEYP282MB2697.AUSP282.PROD.OUTLOOK.COM \
--to=songjinjian@hotmail.com \
--cc=chandrashekar.devegowda@intel.com \
--cc=chiranjeevi.rapolu@linux.intel.com \
--cc=danielwinkler@google.com \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=felix.yan@fibocom.com \
--cc=haijun.liu@mediatek.com \
--cc=jinjian.song@fibocom.com \
--cc=joey.zhao@fibocom.com \
--cc=johannes@sipsolutions.net \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.com \
--cc=liuqf@fibocom.com \
--cc=loic.poulain@linaro.org \
--cc=m.chetan.kumar@linux.intel.com \
--cc=netdev@vger.kernel.org \
--cc=nmarupaka@google.com \
--cc=pabeni@redhat.com \
--cc=ricardo.martinez@linux.intel.com \
--cc=ryazanov.s.a@gmail.com \
--cc=vsankar@lenovo.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).