Skip to contentSkip to conversation

net: wwan: t7xx: fw flashing & coredump support

PATCH In review [email protected] 5 participants 19 messages Jan 21, 2023 – Jan 27, 2023

Subsystems (7)
lore
Share & tools
lore
#0 lore raw

v5 cover net: wwan: t7xx: fw flashing & coredump support

From: M Chetan Kumar <[email protected]>

This patch series brings-in the support for FM350 wwan device firmware flashing & coredump collection using devlink interface.

Below is the high level description of individual patches. Refer to individual patch commit message for details.

PATCH1: Enables AP CLDMA communication for firmware flashing & coredump collection.

PATCH2: Enables the infrastructure & queue configuration required for early ports enumeration.

PATCH3: Implements device reset and rescan logic required to enter or exit fastboot mode.

PATCH4: Implements devlink interface & uses the fastboot protocol for fw flashing and coredump collection.

PATCH5: t7xx devlink commands documentation.

Version History:
================
v5: Address reivew comments given by Jarvinen, Ilpo Johannes.
v4: Address review comments given by Jesse Brandeburg & Bagas Sanjaya.
v3: Repost the series by setting format.thread git-config option to
shallow as suggested by Brandeburg, Jesse.
v2: Address review comments given by Jarvinen, Ilpo Johannes and
Sergey Ryazanov. Refer to Individual patches on v2 changes.
v1: Initial Version.

Haijun Liu (1):
net: wwan: t7xx: Add AP CLDMA

M Chetan Kumar (4):
net: wwan: t7xx: Infrastructure for early port configuration
net: wwan: t7xx: PCIe reset rescan
net: wwan: t7xx: Enable devlink based fw flashing and coredump
collection
net: wwan: t7xx: Devlink documentation

 Documentation/networking/devlink/index.rst |   1 +
 Documentation/networking/devlink/t7xx.rst  | 224 +++++++
 drivers/net/wwan/Kconfig                   |   1 +
 drivers/net/wwan/t7xx/Makefile             |   5 +-
 drivers/net/wwan/t7xx/t7xx_hif_cldma.c     |  64 +-
 drivers/net/wwan/t7xx/t7xx_hif_cldma.h     |  20 +-
 drivers/net/wwan/t7xx/t7xx_mhccif.h        |   1 +
 drivers/net/wwan/t7xx/t7xx_modem_ops.c     |  81 ++-
 drivers/net/wwan/t7xx/t7xx_modem_ops.h     |   2 +
 drivers/net/wwan/t7xx/t7xx_pci.c           |  72 ++-
 drivers/net/wwan/t7xx/t7xx_pci.h           |   2 +
 drivers/net/wwan/t7xx/t7xx_pci_rescan.c    |  96 +++
 drivers/net/wwan/t7xx/t7xx_pci_rescan.h    |  28 +
 drivers/net/wwan/t7xx/t7xx_port.h          |  12 +-
 drivers/net/wwan/t7xx/t7xx_port_ap_msg.c   |  79 +++
 drivers/net/wwan/t7xx/t7xx_port_ap_msg.h   |  11 +
 drivers/net/wwan/t7xx/t7xx_port_ctrl_msg.c |   8 +-
 drivers/net/wwan/t7xx/t7xx_port_devlink.c  | 701 +++++++++++++++++++++
 drivers/net/wwan/t7xx/t7xx_port_devlink.h  |  86 +++
 drivers/net/wwan/t7xx/t7xx_port_proxy.c    | 132 +++-
 drivers/net/wwan/t7xx/t7xx_port_proxy.h    |  14 +
 drivers/net/wwan/t7xx/t7xx_port_wwan.c     |  25 +-
 drivers/net/wwan/t7xx/t7xx_reg.h           |  30 +-
 drivers/net/wwan/t7xx/t7xx_state_monitor.c | 132 +++-
 drivers/net/wwan/t7xx/t7xx_state_monitor.h |   3 +
 25 files changed, 1729 insertions(+), 101 deletions(-)
 create mode 100644 Documentation/networking/devlink/t7xx.rst
 create mode 100644 drivers/net/wwan/t7xx/t7xx_pci_rescan.c
 create mode 100644 drivers/net/wwan/t7xx/t7xx_pci_rescan.h
 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_devlink.c
 create mode 100644 drivers/net/wwan/t7xx/t7xx_port_devlink.h

--
2.34.1

#1 lore raw

PATCH v5 1/5 net: wwan: t7xx: Add AP CLDMA

From: Haijun Liu <[email protected]>

The t7xx device contains two Cross Layer DMA (CLDMA) interfaces to communicate with AP and Modem processors respectively. So far only MD-CLDMA was being used, this patch enables AP-CLDMA.

Rename small Application Processor (sAP) to AP.

--
v5:
* No Change.
v4:
* No Change.
v3:
* No Change.
v2:
* Reuse handshake_wq for AP work.
* Remove AP trace port tx/rx channel id.
* Rename t7xx_md_port_conf to t7xx_port_conf.

---
 drivers/net/wwan/t7xx/t7xx_hif_cldma.c     | 17 +++--
 drivers/net/wwan/t7xx/t7xx_hif_cldma.h     |  2 +-
 drivers/net/wwan/t7xx/t7xx_mhccif.h        |  1 +
 drivers/net/wwan/t7xx/t7xx_modem_ops.c     | 76 +++++++++++++++++-----
 drivers/net/wwan/t7xx/t7xx_modem_ops.h     |  2 +
 drivers/net/wwan/t7xx/t7xx_port.h          |  6 +-
 drivers/net/wwan/t7xx/t7xx_port_ctrl_msg.c |  8 ++-
 drivers/net/wwan/t7xx/t7xx_port_proxy.c    | 18 ++++-
 drivers/net/wwan/t7xx/t7xx_reg.h           |  2 +-
 drivers/net/wwan/t7xx/t7xx_state_monitor.c | 13 +++-
 drivers/net/wwan/t7xx/t7xx_state_monitor.h |  2 +
 11 files changed, 116 insertions(+), 31 deletions(-)
drivers/net/wwan/t7xx/t7xx_hif_cldma.c +11 -6
index aec3a18d44bd..4f56d8cc0aea 100644
@@ -1066,13 +1066,18 @@ static void t7xx_hw_info_init(struct cldma_ctrl *md_ctrl)
 	struct t7xx_cldma_hw *hw_info = &md_ctrl->hw_info;
 	u32 phy_ao_base, phy_pd_base;
 
-	if (md_ctrl->hif_id != CLDMA_ID_MD)
-		return;
-
-	phy_ao_base = CLDMA1_AO_BASE;
-	phy_pd_base = CLDMA1_PD_BASE;
-	hw_info->phy_interrupt_id = CLDMA1_INT;
 	hw_info->hw_mode = MODE_BIT_64;
+
+	if (md_ctrl->hif_id == CLDMA_ID_MD) {
+		phy_ao_base = CLDMA1_AO_BASE;
+		phy_pd_base = CLDMA1_PD_BASE;
+		hw_info->phy_interrupt_id = CLDMA1_INT;
+	} else {
+		phy_ao_base = CLDMA0_AO_BASE;
+		phy_pd_base = CLDMA0_PD_BASE;
+		hw_info->phy_interrupt_id = CLDMA0_INT;
+	}
+
 	hw_info->ap_ao_base = t7xx_pcie_addr_transfer(pbase->pcie_ext_reg_base,
 						      pbase->pcie_dev_reg_trsl_addr, phy_ao_base);
 	hw_info->ap_pdn_base = t7xx_pcie_addr_transfer(pbase->pcie_ext_reg_base,
drivers/net/wwan/t7xx/t7xx_hif_cldma.h +1 -1
index 47a35e552da7..4410bac6993a 100644
@@ -34,7 +34,7 @@
 /**
  * enum cldma_id - Identifiers for CLDMA HW units.
  * @CLDMA_ID_MD: Modem control channel.
- * @CLDMA_ID_AP: Application Processor control channel (not used at the moment).
+ * @CLDMA_ID_AP: Application Processor control channel.
  * @CLDMA_NUM:   Number of CLDMA HW units available.
  */
 enum cldma_id {
drivers/net/wwan/t7xx/t7xx_mhccif.h +1 -0
index 209b386bc088..20c50dce9fc3 100644
@@ -25,6 +25,7 @@
 			 D2H_INT_EXCEPTION_CLEARQ_DONE |	\
 			 D2H_INT_EXCEPTION_ALLQ_RESET |		\
 			 D2H_INT_PORT_ENUM |			\
+			 D2H_INT_ASYNC_AP_HK |			\
 			 D2H_INT_ASYNC_MD_HK)
 
 void t7xx_mhccif_mask_set(struct t7xx_pci_dev *t7xx_dev, u32 val);
drivers/net/wwan/t7xx/t7xx_modem_ops.c +61 -15

175 lines not on this page · raw message

drivers/net/wwan/t7xx/t7xx_modem_ops.h +2 -0
index 7469ed636ae8..abe633cf7adc 100644
@@ -66,10 +66,12 @@ struct t7xx_modem {
 	struct cldma_ctrl		*md_ctrl[CLDMA_NUM];
 	struct t7xx_pci_dev		*t7xx_dev;
 	struct t7xx_sys_info		core_md;
+	struct t7xx_sys_info		core_ap;
 	bool				md_init_finish;
 	bool				rgu_irq_asserted;
 	struct workqueue_struct		*handshake_wq;
 	struct work_struct		handshake_work;
+	struct work_struct		ap_handshake_work;
 	struct t7xx_fsm_ctl		*fsm_ctl;
 	struct port_proxy		*port_prox;
 	unsigned int			exp_id;
drivers/net/wwan/t7xx/t7xx_port.h +5 -1
index 8ea9079af997..4ae8a00a8532 100644
@@ -36,9 +36,13 @@
 /* Channel ID and Message ID definitions.
  * The channel number consists of peer_id(15:12) , channel_id(11:0)
  * peer_id:
- * 0:reserved, 1: to sAP, 2: to MD
+ * 0:reserved, 1: to AP, 2: to MD
  */
 enum port_ch {
+	/* to AP */
+	PORT_CH_AP_CONTROL_RX = 0x1000,
+	PORT_CH_AP_CONTROL_TX = 0x1001,
+
 	/* to MD */
 	PORT_CH_CONTROL_RX = 0x2000,
 	PORT_CH_CONTROL_TX = 0x2001,
drivers/net/wwan/t7xx/t7xx_port_ctrl_msg.c +6 -2
index 68430b130a67..ae632ef96698 100644
@@ -167,8 +167,12 @@ static int control_msg_handler(struct t7xx_port *port, struct sk_buff *skb)
 	case CTL_ID_HS2_MSG:
 		skb_pull(skb, sizeof(*ctrl_msg_h));
 
-		if (port_conf->rx_ch == PORT_CH_CONTROL_RX) {
-			ret = t7xx_fsm_append_event(ctl, FSM_EVENT_MD_HS2, skb->data,
+		if (port_conf->rx_ch == PORT_CH_CONTROL_RX ||
+		    port_conf->rx_ch == PORT_CH_AP_CONTROL_RX) {
+			int event = port_conf->rx_ch == PORT_CH_CONTROL_RX ?
+				    FSM_EVENT_MD_HS2 : FSM_EVENT_AP_HS2;
+
+			ret = t7xx_fsm_append_event(ctl, event, skb->data,
 						    le32_to_cpu(ctrl_msg_h->data_length));
 			if (ret)
 				dev_err(port->dev, "Failed to append Handshake 2 event");
drivers/net/wwan/t7xx/t7xx_port_proxy.c +15 -3
index 894b1d11b2c9..274846d39fbf 100644
@@ -48,7 +48,7 @@
 	     i < (proxy)->port_count;		\
 	     i++, (p) = &(proxy)->ports[i])
 
-static const struct t7xx_port_conf t7xx_md_port_conf[] = {
+static const struct t7xx_port_conf t7xx_port_conf[] = {
 	{
 		.tx_ch = PORT_CH_UART2_TX,
 		.rx_ch = PORT_CH_UART2_RX,
@@ -89,6 +89,14 @@ static const struct t7xx_port_conf t7xx_md_port_conf[] = {
 		.path_id = CLDMA_ID_MD,
 		.ops = &ctl_port_ops,
 		.name = "t7xx_ctrl",
+	}, {
+		.tx_ch = PORT_CH_AP_CONTROL_TX,
+		.rx_ch = PORT_CH_AP_CONTROL_RX,
+		.txq_index = Q_IDX_CTRL,
+		.rxq_index = Q_IDX_CTRL,
+		.path_id = CLDMA_ID_AP,
+		.ops = &ctl_port_ops,
+		.name = "t7xx_ap_ctrl",
 	},
 };
 
@@ -428,6 +436,9 @@ static void t7xx_proxy_init_all_ports(struct t7xx_modem *md)
 		if (port_conf->tx_ch == PORT_CH_CONTROL_TX)
 			md->core_md.ctl_port = port;
 
+		if (port_conf->tx_ch == PORT_CH_AP_CONTROL_TX)
+			md->core_ap.ctl_port = port;
+
 		port->t7xx_dev = md->t7xx_dev;
 		port->dev = &md->t7xx_dev->pdev->dev;
 		spin_lock_init(&port->port_update_lock);
@@ -442,7 +453,7 @@ static void t7xx_proxy_init_all_ports(struct t7xx_modem *md)
 
 static int t7xx_proxy_alloc(struct t7xx_modem *md)
 {
-	unsigned int port_count = ARRAY_SIZE(t7xx_md_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;
@@ -456,7 +467,7 @@ static int t7xx_proxy_alloc(struct t7xx_modem *md)
 	port_prox->dev = dev;
 
 	for (i = 0; i < port_count; i++)
-		port_prox->ports[i].port_conf = &t7xx_md_port_conf[i];
+		port_prox->ports[i].port_conf = &t7xx_port_conf[i];
 
 	port_prox->port_count = port_count;
 	t7xx_proxy_init_all_ports(md);
@@ -481,6 +492,7 @@ 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;
 }
drivers/net/wwan/t7xx/t7xx_reg.h +1 -1
index 7c1b81091a0f..c41d7d094c08 100644
@@ -56,7 +56,7 @@
 #define D2H_INT_RESUME_ACK			BIT(12)
 #define D2H_INT_SUSPEND_ACK_AP			BIT(13)
 #define D2H_INT_RESUME_ACK_AP			BIT(14)
-#define D2H_INT_ASYNC_SAP_HK			BIT(15)
+#define D2H_INT_ASYNC_AP_HK			BIT(15)
 #define D2H_INT_ASYNC_MD_HK			BIT(16)
 
 /* Register base */
drivers/net/wwan/t7xx/t7xx_state_monitor.c +11 -2
index 0bcca08ff2bd..80edb8e75a6a 100644
@@ -285,8 +285,9 @@ static int fsm_routine_starting(struct t7xx_fsm_ctl *ctl)
 	t7xx_fsm_broadcast_state(ctl, MD_STATE_WAITING_FOR_HS1);
 	t7xx_md_event_notify(md, FSM_START);
 
-	wait_event_interruptible_timeout(ctl->async_hk_wq, md->core_md.ready || ctl->exp_flg,
-					 HZ * 60);
+	wait_event_interruptible_timeout(ctl->async_hk_wq,
+					 (md->core_md.ready && md->core_ap.ready) ||
+					  ctl->exp_flg, HZ * 60);
 	dev = &md->t7xx_dev->pdev->dev;
 
 	if (ctl->exp_flg)
@@ -297,6 +298,13 @@ static int fsm_routine_starting(struct t7xx_fsm_ctl *ctl)
 		if (md->core_md.handshake_ongoing)
 			t7xx_fsm_append_event(ctl, FSM_EVENT_MD_HS2_EXIT, NULL, 0);
 
+		fsm_routine_exception(ctl, NULL, EXCEPTION_HS_TIMEOUT);
+		return -ETIMEDOUT;
+	} else if (!md->core_ap.ready) {
+		dev_err(dev, "AP handshake timeout\n");
+		if (md->core_ap.handshake_ongoing)
+			t7xx_fsm_append_event(ctl, FSM_EVENT_AP_HS2_EXIT, NULL, 0);
+
 		fsm_routine_exception(ctl, NULL, EXCEPTION_HS_TIMEOUT);
 		return -ETIMEDOUT;
 	}
@@ -335,6 +343,7 @@ static void fsm_routine_start(struct t7xx_fsm_ctl *ctl, struct t7xx_fsm_command
 		return;
 	}
 
+	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));
 }
drivers/net/wwan/t7xx/t7xx_state_monitor.h +2 -0
index b1af0259d4c5..b6e76f3903c8 100644
@@ -38,10 +38,12 @@ enum t7xx_fsm_state {
 enum t7xx_fsm_event_state {
 	FSM_EVENT_INVALID,
 	FSM_EVENT_MD_HS2,
+	FSM_EVENT_AP_HS2,
 	FSM_EVENT_MD_EX,
 	FSM_EVENT_MD_EX_REC_OK,
 	FSM_EVENT_MD_EX_PASS,
 	FSM_EVENT_MD_HS2_EXIT,
+	FSM_EVENT_AP_HS2_EXIT,
 	FSM_EVENT_MAX
 };
 
Signature · 1 line
2.34.1
#2 lore raw

PATCH v5 2/5 net: wwan: t7xx: Infrastructure for early port configuration

In reply to [email protected]

From: M Chetan Kumar <[email protected]>

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.

--
v5:
* Change WARN_ON to WARN_ON_ONCE in t7xx_port_proxy_recv_skb_from_dedicated_queue().
* Change early_port_count type from u32 to unsigned int.
* Drop opencoding -> struct_size() in t7xx_proxy_alloc().
* Change max_t() to max() in t7xx_proxy_alloc().
* Remove Spurious space in struct port_proxy decl.
* Change "read poll" to "read poll timeout" in fsm_routine_start.
* Drop ret override to -ETIMEDOUT in fsm_routine_start.
* Change dev_info to dev_dbg in fsm_routine_start.
v4:
* Remove "this patch" in commit message.
* MISC_DEV_STATUS_MASK & MISC_DEV_STATUS_INVALID is unused, drop it.
* Drop unnecessary assignement for ret var inside fsm_routine_start.
* cppcheck - reduce variableScope for stage var in fsm_routine_start.
v3:
* No Change.
v2:
* Move recv_skb handler to cldma_queue.
* Drop cldma_queue_type.
* Restore prototype of t7xx_port_send_raw_skb().
* Remove PORT_CFG_ID_INVALID check in t7xx_port_proxy_set_cfg().
* Add space before */.
* Drop unnecessary logs.
* Use WARN_ON on early port.
* Use new MISC_DEV_STATUS_INVALID instead of MISC_DEV_STATUS.
* Use macros instead of const identifiers.
* Change ports member type from pointer to array type.
* Prefix LK_EVENT_XX with MISC prefix.
* Use t7xx prefix for device_stage enums.
* Correct log messages.
* Dont override pkt_size for non-download port under dedicated Queue.
* Drop cldma_txq_rxq_ids.
* Use macro for txq/rxq index.
* Use warn_on for rxq_idx comparison.
* Drop t7xx_port_proxy_get_port_by_name().
* Replace fsm poll with read_poll_timeout().
* Use "\n" consistently across log message.
* Remove local var _dev prefixes in fsm_routine_start().
* Use max_t.

---
 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     |  3 +-
 drivers/net/wwan/t7xx/t7xx_reg.h           | 22 +++++-
 drivers/net/wwan/t7xx/t7xx_state_monitor.c | 84 ++++++++++++++++++---
 drivers/net/wwan/t7xx/t7xx_state_monitor.h |  1 +
 10 files changed, 232 insertions(+), 47 deletions(-)
drivers/net/wwan/t7xx/t7xx_hif_cldma.c +32 -15
index 4f56d8cc0aea..12c9e9cba74a 100644
@@ -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;
@@ -1331,9 +1347,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);
 }
 
drivers/net/wwan/t7xx/t7xx_hif_cldma.h +13 -5
index 4410bac6993a..5453cfecbe19 100644
@@ -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);
drivers/net/wwan/t7xx/t7xx_modem_ops.c +2 -2
index 24e7d491468e..cbd65aa48721 100644
@@ -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);
drivers/net/wwan/t7xx/t7xx_port.h +4 -0
index 4ae8a00a8532..09acb1ef144d 100644
@@ -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,
drivers/net/wwan/t7xx/t7xx_port_proxy.c +76 -10

135 lines not on this page · raw message

drivers/net/wwan/t7xx/t7xx_port_proxy.h +10 -0
index 81d059fbc0fb..7f5706811445 100644
@@ -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__ */
drivers/net/wwan/t7xx/t7xx_port_wwan.c +2 -1
index 24bd21942403..33fa8c22598a 100644
@@ -54,7 +54,7 @@ static void t7xx_port_ctrl_stop(struct wwan_port *port)
 static int t7xx_port_ctrl_tx(struct wwan_port *port, struct sk_buff *skb)
 {
 	struct t7xx_port *port_private = wwan_port_get_drvdata(port);
-	size_t len, offset, chunk_len = 0, txq_mtu = CLDMA_MTU;
+	size_t len, offset, chunk_len = 0, txq_mtu;
 	const struct t7xx_port_conf *port_conf;
 	struct t7xx_fsm_ctl *ctl;
 	enum md_state md_state;
@@ -72,6 +72,7 @@ static int t7xx_port_ctrl_tx(struct wwan_port *port, struct sk_buff *skb)
 		return -ENODEV;
 	}
 
+	txq_mtu = t7xx_get_port_mtu(port_private);
 	for (offset = 0; offset < len; offset += chunk_len) {
 		struct sk_buff *skb_ccci;
 		int ret;
drivers/net/wwan/t7xx/t7xx_reg.h +19 -3
index c41d7d094c08..3b665c6116fe 100644
@@ -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)
drivers/net/wwan/t7xx/t7xx_state_monitor.c +73 -11

115 lines not on this page · raw message

drivers/net/wwan/t7xx/t7xx_state_monitor.h +1 -0
index b6e76f3903c8..5e8012567ba1 100644
@@ -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 {
Signature · 1 line
2.34.1
#3 lore raw

PATCH v5 3/5 net: wwan: t7xx: PCIe reset rescan

In reply to [email protected]

From: M Chetan Kumar <[email protected]>

PCI rescan module implements "rescan work queue". In firmware flashing or coredump collection procedure WWAN device is programmed to boot in fastboot mode and a work item is scheduled for removal & detection.

The WWAN device is reset using APCI call as part driver removal flow. Work queue rescans pci bus at fixed interval for device detection, later when device is detect work queue exits.

--
v5:
* No Change.
v4:
* Change "is still exist" to "still exists".
v3:
* No Change.
v2:
* Drop empty line inside critical sections.
* Correct log message.
* Correct logic inside t7xx_always_match().
* Drop hp_enable changes.
* Drop g_ prefix from t7xx_rescan_ctx.
* Use tab before comment in struct decl.
* Remove extra white space.
* Drop modem exception state check.
* Crit section newlines.
* Remove unnecessary header files inclusion.
* Drop spinlock around reset and rescan flow.

---
 drivers/net/wwan/t7xx/Makefile          |  3 +-
 drivers/net/wwan/t7xx/t7xx_modem_ops.c  |  3 +
 drivers/net/wwan/t7xx/t7xx_pci.c        | 56 ++++++++++++++-
 drivers/net/wwan/t7xx/t7xx_pci_rescan.c | 96 +++++++++++++++++++++++++
 drivers/net/wwan/t7xx/t7xx_pci_rescan.h | 28 ++++++++
 5 files changed, 184 insertions(+), 2 deletions(-)
 create mode 100644 drivers/net/wwan/t7xx/t7xx_pci_rescan.c
 create mode 100644 drivers/net/wwan/t7xx/t7xx_pci_rescan.h
drivers/net/wwan/t7xx/Makefile +2 -1
index 268ff9e87e5b..ba5c607404a4 100644
@@ -17,7 +17,8 @@ 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_pci_rescan.o
 
 mtk_t7xx-$(CONFIG_WWAN_DEBUGFS) += \
 		t7xx_port_trace.o \
drivers/net/wwan/t7xx/t7xx_modem_ops.c +3 -0
index cbd65aa48721..2fcaea4694ba 100644
@@ -37,6 +37,7 @@
 #include "t7xx_modem_ops.h"
 #include "t7xx_netdev.h"
 #include "t7xx_pci.h"
+#include "t7xx_pci_rescan.h"
 #include "t7xx_pcie_mac.h"
 #include "t7xx_port.h"
 #include "t7xx_port_proxy.h"
@@ -194,6 +195,8 @@ static irqreturn_t t7xx_rgu_isr_thread(int irq, void *data)
 
 	msleep(RGU_RESET_DELAY_MS);
 	t7xx_reset_device_via_pmic(t7xx_dev);
+	t7xx_rescan_queue_work(t7xx_dev->pdev);
+
 	return IRQ_HANDLED;
 }
 
drivers/net/wwan/t7xx/t7xx_pci.c +55 -1

74 lines not on this page · raw message

drivers/net/wwan/t7xx/t7xx_pci_rescan.c new file +96 -0

96 lines not on this page · raw message

drivers/net/wwan/t7xx/t7xx_pci_rescan.h new file +28 -0
new file mode 100644
index 000000000000..80b25c44151c
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0-only
+ *
+ * Copyright (c) 2021, MediaTek Inc.
+ * Copyright (c) 2021-2023, Intel Corporation.
+ */
+
+#ifndef __T7XX_PCI_RESCAN_H__
+#define __T7XX_PCI_RESCAN_H__
+
+#define MTK_RESCAN_WQ "mtk_rescan_wq"
+
+#define DELAY_RESCAN_MTIME 1000
+#define RESCAN_RETRIES 35
+
+struct remove_rescan_context {
+	struct work_struct service_task;
+	struct workqueue_struct *pcie_rescan_wq;
+	struct pci_dev *dev;
+	atomic_t rescan_done;
+};
+
+void t7xx_pci_dev_rescan(void);
+void t7xx_rescan_queue_work(struct pci_dev *pdev);
+int t7xx_rescan_init(void);
+void t7xx_rescan_deinit(void);
+void t7xx_rescan_done(void);
+
+#endif	/* __T7XX_PCI_RESCAN_H__ */
Signature · 1 line
2.34.1
#8 lore raw

PATCH v5 4/5 net: wwan: t7xx: Enable devlink based fw flashing and coredump collection

In reply to [email protected]

From: M Chetan Kumar <[email protected]>

Adds support for t7xx wwan device firmware flashing & coredump collection using devlink.

1> Driver Registers with Devlink framework.
2> Implements devlink ops flash_update callback that programs modem fw. 3> Creates region & snapshot required for device coredump log collection.

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. Once firmware flashing is success completion status is reported to user space application.

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.

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

--
v5:
* Change BUILD_BUG_ON to static_assert in t7xx_devlink_uninit()
& t7xx_devlink_create_regions().
* Add ver & part_name NULL check in t7xx_devlink_info_get().
* Add ver_len check inside to t7xx_devlink_info_get() to prevent underflow.
* Drop error override in t7xx_devlink_port_read().
* Drop error override in t7xx_devlink_fb_handle_response().
* Add clen check in t7xx_devlink_fb_get_core().
* Remove clen == strlen(T7XX_FB_CMD_RTS) in t7xx_devlink_fb_get_core().
* Change "kstrtoint error!" to "bad value" in t7xx_devlink_fb_dump_log().
* Change -EPROTO to -EFBIG in t7xx_devlink_fb_dump_log().
* Use %s and !ret ? "success" : "failure" in t7xx_devlink_flash_update().
* Add newline after decl in t7xx_devlink_reload_up.
* Change "kstrtoint error!" to "bad value" in t7xx_devlink_info_get().
* Change "devlink region fail" to "creating devlink region failed" in t7xx_devlink_create_regions()
* Change for to while in t7xx_devlink_create_regions().
* Add helper func to support CTS & FIN command send.
* Use goto inside t7xx_devlink_fb_dump_log to unroll set bit.
* Add comment for component versioning logic.
v4:
* cppcheck - reduce variableScope for
- skb_ccci & ret var in t7xx_port_ap_msg_tx.
- ret in t7xx_devlink_port_read.
- len, skb & ret in t7xx_devlink_port_write.
v3:
* No Change.
v2:
* Remove devlink pointer inside the port state container.
* Rename t7xx_devlink_region_list to t7xx_devlink_region_infos &
use region index in initialization.
* Change t7xx_devlink_region_infos to const.
* Handle remaining packet data if the buffer is less than the skb data.
* Drop t7xx_devlink_fb_send_buffer(), push fragmentation logic to t7xx_devlink_port_write().
* Add "\n" to log message.
* Move mrdump_region allocation to devlink initialization.
* Drop snprintf for CTS command fill.
* Drop intermediate mdata buffer & zipsize.
* For mcmd use strcmp instead of strncmp.
* Drop set_fastboot_dl instead use devlink param for fastboot operational mode.
* Drop unnecessary logs.
* Change t7xx_devlink_create_region to t7xx_devlink_create_regions.
* Use BUILD_BUG_ON on array size checks.
* Use ARRAY_SIZE inside loop.
* Correct indentation.
* Drop odd empty line.
* Push common devlink initialization code to t7xx_devlink_init.
* Use skb_queue_purge instead of running loop to free skbs.
* Change t7xx_regions index to enums.
* Remove dev in devlink container.
* Refactor struct to separate out devlink static and dynamic data structs.
* Use min_t.
* Drop unnecessary var assginment during initialization.
* Change while() to for().
* Correct size check.
* Rename result to ret.
* Clean-up error handling path in t7xx_devlink_fb_get_core & t7xx_devlink_fb_dump_log.
* Drop __func__ in log message.
* Change NOTY to NOTIFY.
* Push channel enable or disable cb to port proxy.
* Use array index in t7xx_devlink_region_list initialization.
* Drop t7xx_port_proxy_get_port_by_name() instead access port name directly via port_prox.
* Drop udev based event reporting logic.
* Drop get_core prefix in goto label.
* Remove unnessary header files.
* Allocate memory for mrdump_region->buf inside get_core.
* Remove 'region->buf' in t7xx_devlink_region_snapshot.
* Destroy workqueue on following error case in 'devlink_init'.
* Remove useless checks(dl->mode) and condition(dl->wq).
* Support devlink component versioning.
* Kconfig changes to select devlink.

---
 drivers/net/wwan/Kconfig                   |   1 +
 drivers/net/wwan/t7xx/Makefile             |   4 +-
 drivers/net/wwan/t7xx/t7xx_pci.c           |  16 +-
 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   |  79 +++
 drivers/net/wwan/t7xx/t7xx_port_ap_msg.h   |  11 +
 drivers/net/wwan/t7xx/t7xx_port_devlink.c  | 701 +++++++++++++++++++++
 drivers/net/wwan/t7xx/t7xx_port_devlink.h  |  86 +++
 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 |  37 +-
 14 files changed, 977 insertions(+), 26 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_devlink.c
 create mode 100644 drivers/net/wwan/t7xx/t7xx_port_devlink.h
drivers/net/wwan/Kconfig +1 -0
index 410b0245114e..dd7a9883c1ff 100644
@@ -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.
drivers/net/wwan/t7xx/Makefile +3 -1
index ba5c607404a4..c3f1520b3c49 100644
@@ -18,7 +18,9 @@ mtk_t7xx-y:=	t7xx_pci.o \
 		t7xx_hif_dpmaif_rx.o  \
 		t7xx_dpmaif.o \
 		t7xx_netdev.o \
-		t7xx_pci_rescan.o
+		t7xx_pci_rescan.o \
+		t7xx_port_devlink.o \
+		t7xx_port_ap_msg.o
 
 mtk_t7xx-$(CONFIG_WWAN_DEBUGFS) += \
 		t7xx_port_trace.o \
drivers/net/wwan/t7xx/t7xx_pci.c +13 -3
index 3f5ebbc11b82..624f96b42775 100644
@@ -40,6 +40,7 @@
 #include "t7xx_pci.h"
 #include "t7xx_pci_rescan.h"
 #include "t7xx_pcie_mac.h"
+#include "t7xx_port_devlink.h"
 #include "t7xx_reg.h"
 #include "t7xx_state_monitor.h"
 
@@ -107,7 +108,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)
@@ -704,16 +705,20 @@ 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_rescan_done();
@@ -721,6 +726,10 @@ static int t7xx_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	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)
@@ -730,6 +739,7 @@ static void t7xx_pci_remove(struct pci_dev *pdev)
 
 	t7xx_dev = pci_get_drvdata(pdev);
 	t7xx_md_exit(t7xx_dev);
+	t7xx_devlink_unregister(t7xx_dev);
 
 	for (i = 0; i < EXT_INT_NUM; i++) {
 		if (!t7xx_dev->intr_handler[i])
drivers/net/wwan/t7xx/t7xx_pci.h +2 -0
index 112efa534eac..44a8a5034696 100644
@@ -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
+ * @dl: devlink struct
  */
 struct t7xx_pci_dev {
 	t7xx_intr_callback	intr_handler[EXT_INT_NUM];
@@ -81,6 +82,7 @@ struct t7xx_pci_dev {
 #ifdef CONFIG_WWAN_DEBUGFS
 	struct dentry		*debugfs_dir;
 #endif
+	struct t7xx_devlink     *dl;
 };
 
 enum t7xx_pm_id {
drivers/net/wwan/t7xx/t7xx_port.h +2 -0
index 09acb1ef144d..dfa7ad2a9796 100644
@@ -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,
drivers/net/wwan/t7xx/t7xx_port_ap_msg.c new file +79 -0

79 lines not on this page · raw message

drivers/net/wwan/t7xx/t7xx_port_ap_msg.h new file +11 -0
new file mode 100644
index 000000000000..4838d87d86cf
@@ -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__ */
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +701 -0

701 lines not on this page · raw message

drivers/net/wwan/t7xx/t7xx_port_devlink.h new file +86 -0

86 lines not on this page · raw message

drivers/net/wwan/t7xx/t7xx_port_proxy.c +32 -0
index bdfeb10e0c51..9e22f751bb2e 100644
@@ -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 = &devlink_port_ops,
+		.name = "devlink",
 	},
 };
 
@@ -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;
drivers/net/wwan/t7xx/t7xx_port_proxy.h +4 -0
index 7f5706811445..030576a55623 100644
@@ -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 devlink_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__ */
drivers/net/wwan/t7xx/t7xx_port_wwan.c +2 -20
index 33fa8c22598a..183dc6e97760 100644
@@ -134,24 +134,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;
@@ -171,7 +153,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,
 };
drivers/net/wwan/t7xx/t7xx_reg.h +6 -0
index 3b665c6116fe..d27ba45b12ec 100644
@@ -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,
drivers/net/wwan/t7xx/t7xx_state_monitor.c +35 -2
index 26c0e813ee52..b36026fa7507 100644
@@ -37,6 +37,7 @@
 #include "t7xx_modem_ops.h"
 #include "t7xx_pci.h"
 #include "t7xx_pcie_mac.h"
+#include "t7xx_port_devlink.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,21 @@ 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->dl->port;
+		if (WARN_ON(!port))
+			return;
+
+		if (lk_event == LK_EVENT_CREATE_PD_PORT)
+			md->t7xx_dev->dl->mode = T7XX_FB_DUMP_MODE;
+		else
+			md->t7xx_dev->dl->mode = T7XX_FB_DL_MODE;
+
+		port->port_conf->ops->enable_chl(port);
 		t7xx_cldma_start(md_ctrl);
 		break;
 
@@ -271,13 +294,23 @@ static void fsm_routine_stopping(struct t7xx_fsm_ctl *ctl, struct t7xx_fsm_comma
 	t7xx_cldma_stop(md_ctrl);
 
 	if (!ctl->md->rgu_irq_asserted) {
+		if (t7xx_devlink_param_get_fastboot(t7xx_dev->dl->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);
 
-		err = t7xx_acpi_fldr_func(t7xx_dev);
-		if (err)
+		if (t7xx_devlink_param_get_fastboot(t7xx_dev->dl->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);
+		}
 	}
 
 	fsm_finish_command(ctl, cmd, fsm_stopped_handler(ctl));
Signature · 1 line
2.34.1
#11 lore raw

PATCH v5 5/5 net: wwan: t7xx: Devlink documentation

In reply to [email protected]

From: M Chetan Kumar <[email protected]>

Document the t7xx devlink commands usage for firmware flashing & coredump collection.

--
v5:
* No Change.
v4:
* Spell out fw as firmware.
* Drop "Refer to t7xx.rst file for details" in commit message.
* Move explanation below commands under flash update.
* Move firmware image type list under flash commands.
* Keyword formatting.
* Trim the unneeded trailing colon.
* Describe region commands.
v3:
* No change.
v2:
* Documentation correction.
* Add param details.

---
 Documentation/networking/devlink/index.rst |   1 +
 Documentation/networking/devlink/t7xx.rst  | 224 +++++++++++++++++++++
 2 files changed, 225 insertions(+)
 create mode 100644 Documentation/networking/devlink/t7xx.rst
Documentation/networking/devlink/index.rst +1 -0
index fee4d3968309..0c4f5961e78f 100644
@@ -66,3 +66,4 @@ parameters, info versions, and other features it supports.
    prestera
    iosm
    octeontx2
+   t7xx
Documentation/networking/devlink/t7xx.rst new file +224 -0

224 lines not on this page · raw message

Signature · 1 line
2.34.1
#12 lore raw

Re: [PATCH v5 net-next 5/5] net: wwan: t7xx: Devlink documentation

Quoted 52 lines · On Sat, Jan 21, 2023 at 07:03:58PM +0530, [email protected] wrote:
Documentation/networking/devlink/t7xx.rst new file +52 -0
+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"
+
+::

Documentation/networking/devlink/t7xx.rst line 115

Quoted 10 lines
Documentation/networking/devlink/t7xx.rst new file +10 -0
+
+  $ 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"

It seems like you didn't describe what ``devlink dev flash`` commands above are doing, as I had requested from v3 review [1].

Quoted 9 lines
Documentation/networking/devlink/t7xx.rst new file +9 -0
+Coredump Collection
+~~~~~~~~~~~~~~~~~~~
+
+::
+
+  $ devlink region new mr_dump
+
+::
+

Documentation/networking/devlink/t7xx.rst line 204

Quoted 10 lines
Documentation/networking/devlink/t7xx.rst new file +10 -0
+  $ 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.

Individual command explanation please?

Quoted 10 lines
Documentation/networking/devlink/t7xx.rst new file +10 -0
+
+Second Stage Bootloader dump
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+  $ devlink region new lk_dump
+
+::
+

Documentation/networking/devlink/t7xx.rst line 224

Quoted 10 lines
Documentation/networking/devlink/t7xx.rst new file +10 -0
+  $ 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.

Individual command explanation please?

Hint: see any manpages to get sense of how to write the explanations.

Thanks.

[1]: https://lore.kernel.org/linux-doc/[email protected]/

Signature · 1 line
An old man doll... just what I always wanted! - Clara
#13 lore raw

Re: [PATCH v5 net-next 5/5] net: wwan: t7xx: Devlink documentation

Quoted 112 lines · Bagas Sanjaya
Quoted 52 lines · On Sat, Jan 21, 2023 at 07:03:58PM +0530, [email protected] wrote:
(quoted diff) +52 -0
+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"
+
+::

Review

Quoted 10 lines
(quoted diff) +10 -0
+
+  $ 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"

It seems like you didn't describe what ``devlink dev flash`` commands above are doing, as I had requested from v3 review [1].

Quoted 9 lines
(quoted diff) +9 -0
+Coredump Collection
+~~~~~~~~~~~~~~~~~~~
+
+::
+
+  $ devlink region new mr_dump
+
+::
+

Review

Quoted 10 lines
(quoted diff) +10 -0
+  $ 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.

Individual command explanation please?

Quoted 10 lines
(quoted diff) +10 -0
+
+Second Stage Bootloader dump
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+  $ devlink region new lk_dump
+
+::
+

Review

Quoted 10 lines
(quoted diff) +10 -0
+  $ 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.

Individual command explanation please?

Quoted 5 lines

Hint: see any manpages to get sense of how to write the explanations.

Thanks.

[1]: https://lore.kernel.org/linux-doc/[email protected]/

I have added the explanation for each of those commands and also have changed the format a bit.

Could you please take a look and suggest on below changes.

Documentation/networking/devlink/t7xx.rst +50 -64
@@ -54,65 +54,52 @@ 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"
+.. code:: shell
 
-::
+    # Update device Preloader image
+    $ devlink dev flash pci/0000:$bdf file preloader_k6880v1_mdot2_datacard.bin component "preloader"
 
-  $ devlink dev flash pci/0000:$bdf file dpm-verified.img component "dpm_1"
+    # Update device Preloader extension image
+    $ devlink dev flash pci/0000:$bdf file loader_ext-verified.img component "loader_ext1"
 
-::
+    # Update device TEE (Trusted Execution Environment) image
+    $ devlink dev flash pci/0000:$bdf file tee-verified.img component "tee1"
 
-  $ devlink dev flash pci/0000:$bdf file boot-verified.img component "boot"
+    # Update device Second stage bootloader image
+    $ devlink dev flash pci/0000:$bdf file lk-verified.img component "lk"
 
-::
+    # Update device PM (Power Management) image
+    $ devlink dev flash pci/0000:$bdf file spmfw-verified.img component "spmfw"
 
-  $ devlink dev flash pci/0000:$bdf file root.squashfs component "rootfs"
-
-::
+    # Update device Secure PM image
+    $ devlink dev flash pci/0000:$bdf file sspm-verified.img component "sspm_1"
 
-  $ devlink dev flash pci/0000:$bdf file modem-verified.img component "md1img"
+    # Update device CPU PM image
+    $ devlink dev flash pci/0000:$bdf file mcupm-verified.img component "mcupm_1"
 
-::
+    # Update device DRAM PM image
+    $ devlink dev flash pci/0000:$bdf file dpm-verified.img component "dpm_1"
 
-  $ devlink dev flash pci/0000:$bdf file dsp-verified.bin component "md1dsp"
+    # Update Kernel image
+    $ devlink dev flash pci/0000:$bdf file boot-verified.img component "boot"
 
-::
+    # Update Root filesystem image
+    $ devlink dev flash pci/0000:$bdf file root.squashfs component "rootfs"
 
-  $ devlink dev flash pci/0000:$bdf file OP_OTA.img component "mcf1"
+    # Update Modem image
+    $ devlink dev flash pci/0000:$bdf file modem-verified.img component "md1img"
 
-::
+    # Update DSP image
+    $ devlink dev flash pci/0000:$bdf file dsp-verified.bin component "md1dsp"
 
-  $ devlink dev flash pci/0000:$bdf file OEM_OTA.img component "mcf2"
+    # Update Modem OTA image (operator specific)
+    $ devlink dev flash pci/0000:$bdf file OP_OTA.img component "mcf1"
 
-::
+    # Update Modem OTA image (vendor specific)
+    $ devlink dev flash pci/0000:$bdf file OEM_OTA.img component "mcf2"
 
-  $ devlink dev flash pci/0000:$bdf file DEV_OTA.img component "mcf3"
+    # Update Modem OTA image (vendor configurtions)
+    $ devlink dev flash pci/0000:$bdf file DEV_OTA.img component "mcf3"
 
 Note: Component selects the partition type to be programmed.
 
@@ -166,12 +153,13 @@ the driver using fastboot commands.
 Region commands
 ---------------
 
-::
+.. code:: shell
 
-  $ devlink region show
+    # Show all the regions supported by driver.
+    $ devlink region show
 
-This command list the regions implemented by driver. These regions are accessed
-for device internal data. Below table describes the regions.
+Regions are used for accessing device internal data for debugging purpose. Below table
+describes the regions.
 
 .. list-table:: Regions
     :widths: 15 85
@@ -186,17 +174,16 @@ for device internal data. Below table describes the regions.
 Coredump Collection
 ~~~~~~~~~~~~~~~~~~~
 
-::
-
-  $ devlink region new mr_dump
+.. code:: shell
 
-::
+    # Create a modem region snapshot using:
+    $ devlink region new mr_dump
 
-  $ devlink region read mr_dump snapshot 0 address 0 length $len
-
-::
+    # Read a specific part of modem region snapshot using:
+    $ devlink region read mr_dump snapshot 0 address 0 length $len
 
-  $ devlink region del mr_dump snapshot 0
+    # Delete a modem region snapshot using:
+    $ devlink region del mr_dump snapshot 0
 
 Note: $len is actual len to be dumped.
 
@@ -206,17 +193,16 @@ logs when device encounters an exception.
 Second Stage Bootloader dump
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-::
-
-  $ devlink region new lk_dump
+.. code:: shell
 
-::
+    # Create a second stage bootloader snapshot using:
+    $ devlink region new lk_dump
 
-  $ devlink region read lk_dump snapshot 0 address 0 length $len
-
-::
+    # Read a specific part of second stage booloader snapshot using:
+    $ devlink region read lk_dump snapshot 0 address 0 length $len
 
-  $ devlink region del lk_dump snapshot 0
+    # Delete a second stage bootloader snapshot using:
+    $ devlink region del lk_dump snapshot 0
 
 Note: $len is actual len to be dumped.
 
Signature · 1 line
Chetan
maintainer
#4 lore raw

Re: [PATCH v5 net-next 3/5] net: wwan: t7xx: PCIe reset rescan

In reply to [email protected]

Hi Bjorn,

any objections to the kind of shenanigans this is playing?

Quoted 299 lines · On Sat, 21 Jan 2023 19:03:23 +0530 [email protected] wrote:

From: M Chetan Kumar <[email protected]>

PCI rescan module implements "rescan work queue". In firmware flashing or coredump collection procedure WWAN device is programmed to boot in fastboot mode and a work item is scheduled for removal & detection.

The WWAN device is reset using APCI call as part driver removal flow. Work queue rescans pci bus at fixed interval for device detection, later when device is detect work queue exits.

--
v5:
* No Change.
v4:
* Change "is still exist" to "still exists".
v3:
* No Change.
v2:
* Drop empty line inside critical sections.
* Correct log message.
* Correct logic inside t7xx_always_match().
* Drop hp_enable changes.
* Drop g_ prefix from t7xx_rescan_ctx.
* Use tab before comment in struct decl.
* Remove extra white space.
* Drop modem exception state check.
* Crit section newlines.
* Remove unnecessary header files inclusion.
* Drop spinlock around reset and rescan flow.

---
 drivers/net/wwan/t7xx/Makefile          |  3 +-
 drivers/net/wwan/t7xx/t7xx_modem_ops.c  |  3 +
 drivers/net/wwan/t7xx/t7xx_pci.c        | 56 ++++++++++++++-
 drivers/net/wwan/t7xx/t7xx_pci_rescan.c | 96 +++++++++++++++++++++++++
 drivers/net/wwan/t7xx/t7xx_pci_rescan.h | 28 ++++++++
 5 files changed, 184 insertions(+), 2 deletions(-)
 create mode 100644 drivers/net/wwan/t7xx/t7xx_pci_rescan.c
 create mode 100644 drivers/net/wwan/t7xx/t7xx_pci_rescan.h
drivers/net/wwan/t7xx/Makefile +2 -1
index 268ff9e87e5b..ba5c607404a4 100644
@@ -17,7 +17,8 @@ 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_pci_rescan.o
 
 mtk_t7xx-$(CONFIG_WWAN_DEBUGFS) += \
 		t7xx_port_trace.o \
drivers/net/wwan/t7xx/t7xx_modem_ops.c +3 -0
index cbd65aa48721..2fcaea4694ba 100644
@@ -37,6 +37,7 @@
 #include "t7xx_modem_ops.h"
 #include "t7xx_netdev.h"
 #include "t7xx_pci.h"
+#include "t7xx_pci_rescan.h"
 #include "t7xx_pcie_mac.h"
 #include "t7xx_port.h"
 #include "t7xx_port_proxy.h"
@@ -194,6 +195,8 @@ static irqreturn_t t7xx_rgu_isr_thread(int irq, void *data)
 
 	msleep(RGU_RESET_DELAY_MS);
 	t7xx_reset_device_via_pmic(t7xx_dev);
+	t7xx_rescan_queue_work(t7xx_dev->pdev);
+
 	return IRQ_HANDLED;
 }
 
drivers/net/wwan/t7xx/t7xx_pci.c +55 -1
index 871f2a27a398..3f5ebbc11b82 100644
@@ -38,6 +38,7 @@
 #include "t7xx_mhccif.h"
 #include "t7xx_modem_ops.h"
 #include "t7xx_pci.h"
+#include "t7xx_pci_rescan.h"
 #include "t7xx_pcie_mac.h"
 #include "t7xx_reg.h"
 #include "t7xx_state_monitor.h"
@@ -715,6 +716,7 @@ static int t7xx_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 		return ret;
 	}
 
+	t7xx_rescan_done();
 	t7xx_pcie_mac_set_int(t7xx_dev, MHCCIF_INT);
 	t7xx_pcie_mac_interrupts_en(t7xx_dev);
 
@@ -754,7 +756,59 @@ static struct pci_driver t7xx_pci_driver = {
 	.shutdown = t7xx_pci_shutdown,
 };
 
-module_pci_driver(t7xx_pci_driver);
+static int __init t7xx_pci_init(void)
+{
+	int ret;
+
+	t7xx_pci_dev_rescan();
+	ret = t7xx_rescan_init();
+	if (ret) {
+		pr_err("Failed to init t7xx rescan work\n");
+		return ret;
+	}
+
+	return pci_register_driver(&t7xx_pci_driver);
+}
+module_init(t7xx_pci_init);
+
+static int t7xx_always_match(struct device *dev, const void *data)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+	const struct pci_device_id *id = data;
+
+	if (pci_match_id(id, pdev))
+		return 1;
+
+	return 0;
+}
+
+static void __exit t7xx_pci_cleanup(void)
+{
+	int remove_flag = 0;
+	struct device *dev;
+
+	dev = driver_find_device(&t7xx_pci_driver.driver, NULL, &t7xx_pci_table[0],
+				 t7xx_always_match);
+	if (dev) {
+		pr_debug("unregister t7xx PCIe driver while device still exists.\n");
+		put_device(dev);
+		remove_flag = 1;
+	} else {
+		pr_debug("no t7xx PCIe driver found.\n");
+	}
+
+	pci_lock_rescan_remove();
+	pci_unregister_driver(&t7xx_pci_driver);
+	pci_unlock_rescan_remove();
+
+	t7xx_rescan_deinit();
+	if (remove_flag) {
+		pr_debug("remove t7xx PCI device\n");
+		pci_stop_and_remove_bus_device_locked(to_pci_dev(dev));
+	}
+}
+
+module_exit(t7xx_pci_cleanup);
 
 MODULE_AUTHOR("MediaTek Inc");
 MODULE_DESCRIPTION("MediaTek PCIe 5G WWAN modem T7xx driver");
drivers/net/wwan/t7xx/t7xx_pci_rescan.c new file +96 -0
new file mode 100644
index 000000000000..67f13c035846
@@ -0,0 +1,96 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2021, MediaTek Inc.
+ * Copyright (c) 2021-2023, Intel Corporation.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ":t7xx:%s: " fmt, __func__
+#define dev_fmt(fmt) "t7xx: " fmt
+
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+
+#include "t7xx_pci.h"
+#include "t7xx_pci_rescan.h"
+
+static struct remove_rescan_context t7xx_rescan_ctx;
+
+void t7xx_pci_dev_rescan(void)
+{
+	struct pci_bus *b = NULL;
+
+	pci_lock_rescan_remove();
+	while ((b = pci_find_next_bus(b)))
+		pci_rescan_bus(b);
+	pci_unlock_rescan_remove();
+}
+
+void t7xx_rescan_done(void)
+{
+	if (!atomic_read(&t7xx_rescan_ctx.rescan_done)) {
+		atomic_set(&t7xx_rescan_ctx.rescan_done, 1);
+		pr_debug("Rescan probe\n");
+	} else {
+		pr_debug("Init probe\n");
+	}
+}
+
+static void t7xx_remove_rescan(struct work_struct *work)
+{
+	int num_retries = RESCAN_RETRIES;
+	struct pci_dev *pdev;
+
+	atomic_set(&t7xx_rescan_ctx.rescan_done, 0);
+	pdev = t7xx_rescan_ctx.dev;
+
+	if (pdev) {
+		pci_stop_and_remove_bus_device_locked(pdev);
+		pr_debug("start remove and rescan flow\n");
+	}
+
+	do {
+		t7xx_pci_dev_rescan();
+
+		if (atomic_read(&t7xx_rescan_ctx.rescan_done))
+			break;
+
+		msleep(DELAY_RESCAN_MTIME);
+	} while (num_retries--);
+}
+
+void t7xx_rescan_queue_work(struct pci_dev *pdev)
+{
+	if (!atomic_read(&t7xx_rescan_ctx.rescan_done)) {
+		dev_err(&pdev->dev, "Rescan failed\n");
+		return;
+	}
+
+	t7xx_rescan_ctx.dev = pdev;
+	queue_work(t7xx_rescan_ctx.pcie_rescan_wq, &t7xx_rescan_ctx.service_task);
+}
+
+int t7xx_rescan_init(void)
+{
+	atomic_set(&t7xx_rescan_ctx.rescan_done, 1);
+	t7xx_rescan_ctx.dev = NULL;
+
+	t7xx_rescan_ctx.pcie_rescan_wq = create_singlethread_workqueue(MTK_RESCAN_WQ);
+	if (!t7xx_rescan_ctx.pcie_rescan_wq) {
+		pr_err("Failed to create workqueue: %s\n", MTK_RESCAN_WQ);
+		return -ENOMEM;
+	}
+
+	INIT_WORK(&t7xx_rescan_ctx.service_task, t7xx_remove_rescan);
+
+	return 0;
+}
+
+void t7xx_rescan_deinit(void)
+{
+	t7xx_rescan_ctx.dev = NULL;
+	atomic_set(&t7xx_rescan_ctx.rescan_done, 0);
+	cancel_work_sync(&t7xx_rescan_ctx.service_task);
+	destroy_workqueue(t7xx_rescan_ctx.pcie_rescan_wq);
+}
drivers/net/wwan/t7xx/t7xx_pci_rescan.h new file +28 -0
new file mode 100644
index 000000000000..80b25c44151c
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0-only
+ *
+ * Copyright (c) 2021, MediaTek Inc.
+ * Copyright (c) 2021-2023, Intel Corporation.
+ */
+
+#ifndef __T7XX_PCI_RESCAN_H__
+#define __T7XX_PCI_RESCAN_H__
+
+#define MTK_RESCAN_WQ "mtk_rescan_wq"
+
+#define DELAY_RESCAN_MTIME 1000
+#define RESCAN_RETRIES 35
+
+struct remove_rescan_context {
+	struct work_struct service_task;
+	struct workqueue_struct *pcie_rescan_wq;
+	struct pci_dev *dev;
+	atomic_t rescan_done;
+};
+
+void t7xx_pci_dev_rescan(void);
+void t7xx_rescan_queue_work(struct pci_dev *pdev);
+int t7xx_rescan_init(void);
+void t7xx_rescan_deinit(void);
+void t7xx_rescan_done(void);
+
+#endif	/* __T7XX_PCI_RESCAN_H__ */
maintainer
#14 lore raw

Re: [PATCH v5 net-next 5/5] net: wwan: t7xx: Devlink documentation

In reply to [email protected]

Documentation/networking/devlink/t7xx.rst line 224

Quoted 2 lines · On Sat, 21 Jan 2023 19:03:58 +0530 [email protected] wrote:
Documentation/networking/devlink/t7xx.rst new file +2 -0
+In fastboot mode the userspace application uses these commands for obtaining the
+current snapshot of second stage bootloader.

I don't know what fastboot is, and reading this doc I see it used in three forms:
- fastboot protocol
- fastboot mode
- fastboot command & response

In the end - I have no idea what the devlink param you're adding does.

maintainer
#9 lore raw

Re: [PATCH v5 net-next 4/5] net: wwan: t7xx: Enable devlink based fw flashing and coredump collection

In reply to [email protected]
Quoted 3 lines · On Sat, 21 Jan 2023 19:03:38 +0530 [email protected] wrote:

1> Driver Registers with Devlink framework.
2> Implements devlink ops flash_update callback that programs modem fw. 3> Creates region & snapshot required for device coredump log collection.

Sounds like these should be 3 patches?

drivers/net/wwan/t7xx/t7xx_port_devlink.c line 607

Quoted 5 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +5 -0
+	devlink_params_register(dl_ctx, t7xx_devlink_params, ARRAY_SIZE(t7xx_devlink_params));
+	value.vbool = false;
+	devlink_param_driverinit_value_set(dl_ctx, T7XX_DEVLINK_PARAM_ID_FASTBOOT, value);
+	devlink_set_features(dl_ctx, DEVLINK_F_RELOAD);
+	devlink_register(dl_ctx);

Please take the devl_lock() explicitly and use the devl_ version of those calls.

#15 lore raw

Re: [PATCH v5 net-next 5/5] net: wwan: t7xx: Devlink documentation

In reply to Jakub Kicinski
Quoted 9 lines · Jakub Kicinski

Documentation/networking/devlink/t7xx.rst line 224

Quoted 2 lines · On Sat, 21 Jan 2023 19:03:58 +0530 [email protected] wrote:
Documentation/networking/devlink/t7xx.rst new file +2 -0
+In fastboot mode the userspace application uses these commands for obtaining the
+current snapshot of second stage bootloader.

I don't know what fastboot is, and reading this doc I see it used in three forms:
- fastboot protocol
- fastboot mode
- fastboot command & response

The fastboot is sort of a tool. It implements the protocol for programming the device flash or getting device information. The device implements the fastboot commands and host issue those commands for programming the firmware to device flash or to obtain device information. Inorder to execute those commands, first the device needs to be put into fastboot mode.

More details on fastboot can be found in links [1].

Quoted 1 line

In the end - I have no idea what the devlink param you're adding does.

"fastboot" devlink param is used to put the device into fastboot mode to program firmware to device flash or to obtain device information.

[1]
https://en.wikipedia.org/wiki/Fastboot
https://android.googlesource.com/platform/system/core/+/refs/heads/master/fastboot/README.md

Signature · 1 line
Chetan
#10 lore raw

Re: [PATCH v5 net-next 4/5] net: wwan: t7xx: Enable devlink based fw flashing and coredump collection

In reply to Jakub Kicinski
Quoted 6 lines · Jakub Kicinski
Quoted 3 lines · On Sat, 21 Jan 2023 19:03:38 +0530 [email protected] wrote:

1> Driver Registers with Devlink framework.
2> Implements devlink ops flash_update callback that programs modem fw. 3> Creates region & snapshot required for device coredump log collection.

Sounds like these should be 3 patches?

Flashing and coredump feature implementation is kept under single patch. I can revist and break it into 2 patches to seperate out flashing and coredump logic. I hope this fine.

Quoted 9 lines

drivers/net/wwan/t7xx/t7xx_port_devlink.c line 607

Quoted 6 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +5 -0
+	devlink_params_register(dl_ctx, t7xx_devlink_params, ARRAY_SIZE(t7xx_devlink_params));
+	value.vbool = false;
+	devlink_param_driverinit_value_set(dl_ctx, T7XX_DEVLINK_PARAM_ID_FASTBOOT, value);
+	devlink_set_features(dl_ctx, DEVLINK_F_RELOAD);
+	devlink_register(dl_ctx);

Please take the devl_lock() explicitly and use the devl_ version of those calls.

Ok. will modify it as per your suggestion.

Signature · 1 line
Chetan
#16 lore raw

Re: [PATCH v5 net-next 5/5] net: wwan: t7xx: Devlink documentation

In reply to Kumar, M Chetan
Quoted 22 lines · M Chetan
Quoted 10 lines · Jakub Kicinski
Quoted 3 lines · On Sat, 21 Jan 2023 19:03:58 +0530 [email protected] wrote:

+In fastboot mode the userspace application uses these commands for obtaining the
+current snapshot of second stage bootloader.

I don't know what fastboot is, and reading this doc I see it used in three forms:
- fastboot protocol
- fastboot mode
- fastboot command & response

The fastboot is sort of a tool. It implements the protocol for programming the device flash or getting device information. The device implements the fastboot commands and host issue those commands for programming the firmware to device flash or to obtain device information. Inorder to execute those commands, first the device needs to be put into fastboot mode.

More details on fastboot can be found in links [1].

Quoted 1 line

In the end - I have no idea what the devlink param you're adding does.

Quoted 7 lines

"fastboot" devlink param is used to put the device into fastboot mode to program firmware to device flash or to obtain device information.

[1]
https://en.wikipedia.org/wiki/Fastboot
https://android.googlesource.com/platform/system/core/+/refs/heads/master/fastboot/README.md

Make sure to improve the documentation too so that the next reader won't have the same problem in understanding. I hope this was obvious but just in case it wasn't, your true audience is the ones reading the doc later and if a reviewer cannot understand your doc, the chances are the person reading the doc understands even less. And they won't have your reply to the reviewer available so enough information should go into the documentation itself.

Signature · 1 line
 i.
maintainer
#17 lore raw

Re: [PATCH v5 net-next 5/5] net: wwan: t7xx: Devlink documentation

In reply to Kumar, M Chetan
Quoted 17 lines · M Chetan
Quoted 5 lines

I don't know what fastboot is, and reading this doc I see it used in three forms:
- fastboot protocol
- fastboot mode
- fastboot command & response

The fastboot is sort of a tool. It implements the protocol for programming the device flash or getting device information. The device implements the fastboot commands and host issue those commands for programming the firmware to device flash or to obtain device information. Inorder to execute those commands, first the device needs to be put into fastboot mode.

More details on fastboot can be found in links [1].

Quoted 1 line

In the end - I have no idea what the devlink param you're adding does.

Quoted 7 lines

"fastboot" devlink param is used to put the device into fastboot mode to program firmware to device flash or to obtain device information.

[1]
https://en.wikipedia.org/wiki/Fastboot
https://android.googlesource.com/platform/system/core/+/refs/heads/master/fastboot/README.md

As Ilpo mentions, please add this info into the doc, including the links.

The most confusing part is that "fastboot" sounds like it's going to boot fast, while IIUC the behavior is the opposite - it's not going to boot at all and just expose an interface to load the FW, is that right?

Please also clarify what the normal operation for the device is. In what scenarios does the fastboot mode get used?

And just to double confirm - that the FW loaded in fastboot mode is persistently stored on the device, and will be used after power cycle. Rather than it being an upload into RAM.

#18 lore raw

Re: [PATCH v5 net-next 5/5] net: wwan: t7xx: Devlink documentation

Quoted 22 lines · Jakub Kicinski
Quoted 21 lines · M Chetan
Quoted 5 lines

I don't know what fastboot is, and reading this doc I see it used in three forms:
- fastboot protocol
- fastboot mode
- fastboot command & response

The fastboot is sort of a tool. It implements the protocol for programming the device flash or getting device information. The device implements the fastboot commands and host issue those commands for programming the firmware to device flash or to obtain device information. Inorder to execute those commands, first the device needs to be put into fastboot mode.

More details on fastboot can be found in links [1].

Quoted 1 line

In the end - I have no idea what the devlink param you're adding does.

"fastboot" devlink param is used to put the device into fastboot mode to program firmware to device flash or to obtain device information.

Quoted 6 lines
Quoted 3 lines

[1]
https://en.wikipedia.org/wiki/Fastboot
https://android.googlesource.com/platform/system/core/+/refs/heads/master/fastboot/README.md

As Ilpo mentions, please add this info into the doc, including the links.

Sure. In the next patch, I will detail out the fastboot and include those links for reference.

Quoted 5 lines

The most confusing part is that "fastboot" sounds like it's going to boot fast, while IIUC the behavior is the opposite - it's not going to boot at all and just expose an interface to load the FW, is that right?

On device side, the fastboot protocol is implemented in bootloader. When the host request the device to enter fastboot mode, the device is reset. Post reset, the host will be able to communicate with device bootloader using fastboot protocol.

Fastboot protocol implements a set of commands for various operations. The "flash" is one such command used for programming firmware.

Quoted 2 lines

Please also clarify what the normal operation for the device is.

It means fully functional mode.
In this mode wwan functionalities like AT, MBIM, modem trace collection & data path are operational.

Quoted 1 line

In what scenarios does the fastboot mode get used?

It is used in 2 scenarios.
1> Firmware update, when user/app wants to update firmware. 2> Core dump collection, when device encounters an exception.

Quoted 4 lines

And just to double confirm - that the FW loaded in fastboot mode is persistently stored on the device, and will be used after power cycle. Rather than it being an upload into RAM.

That's correct.
The firmware is permanently stored on the device & it will be used after power cycle.

Signature · 1 line
Chetan
#5 lore raw

Re: [PATCH v5 net-next 3/5] net: wwan: t7xx: PCIe reset rescan

In reply to Jakub Kicinski
Quoted 3 lines · Jakub Kicinski

Hi Bjorn,

any objections to the kind of shenanigans this is playing?

Yes, thanks for asking. Drivers definitely should not have to do this sort of thing.

Quoted 8 lines · On Sat, 21 Jan 2023 19:03:23 +0530 [email protected] wrote:
Quoted 7 lines

From: M Chetan Kumar <[email protected]>

PCI rescan module implements "rescan work queue". In firmware flashing or coredump collection procedure WWAN device is programmed to boot in fastboot mode and a work item is scheduled for removal & detection.

Quoted 4 lines
Quoted 4 lines

The WWAN device is reset using APCI call as part driver removal flow. Work queue rescans pci bus at fixed interval for device detection, later when device is detect work queue exits.

I'm not sure what's going on here. Do we need to reset the device when the t7xx driver is loaded so the device will load new firmware when it comes out of reset?

There are a few drivers that do that, e.g., with pci_reset_function().

Quoted 1 line
Quoted 1 line

+static struct remove_rescan_context t7xx_rescan_ctx;

Apparently this only supports a single t7xx instance in a system? Not good.

Quoted 7 lines

drivers/net/wwan/t7xx/t7xx_pci_rescan.c line 26

Quoted 7 lines
drivers/net/wwan/t7xx/t7xx_pci_rescan.c new file +7 -0
+void t7xx_pci_dev_rescan(void)
+{
+	struct pci_bus *b = NULL;
+
+	pci_lock_rescan_remove();
+	while ((b = pci_find_next_bus(b)))
+		pci_rescan_bus(b);

No, this driver absolutely cannot rescan and assign unassigned resources for all the PCI buses in the system.

Bjorn

#6 lore raw

Re: [PATCH v5 net-next 3/5] net: wwan: t7xx: PCIe reset rescan

Quoted 16 lines · Bjorn Helgaas
Quoted 3 lines · Jakub Kicinski

Hi Bjorn,

any objections to the kind of shenanigans this is playing?

Yes, thanks for asking. Drivers definitely should not have to do this sort of thing.

Quoted 8 lines · On Sat, 21 Jan 2023 19:03:23 +0530 [email protected] wrote:
Quoted 7 lines

From: M Chetan Kumar <[email protected]>

PCI rescan module implements "rescan work queue". In firmware flashing or coredump collection procedure WWAN device is programmed to boot in fastboot mode and a work item is scheduled for removal & detection.

Quoted 8 lines
Quoted 4 lines
Quoted 4 lines

The WWAN device is reset using APCI call as part driver removal flow. Work queue rescans pci bus at fixed interval for device detection, later when device is detect work queue exits.

I'm not sure what's going on here. Do we need to reset the device when the t7xx driver is loaded so the device will load new firmware when it comes out of reset?

Flow is, Reset the device to get into firmware download mode then update the firmware and later reset it to go back to normal mode.

Quoted 3 lines

There are a few drivers that do that, e.g., with pci_reset_function().

Thanks for the suggestion.
I will explore a bit and also try to use pci_reset_function() interface and see if it serves the purpose.

Quoted 5 lines
Quoted 1 line
Quoted 1 line

+static struct remove_rescan_context t7xx_rescan_ctx;

Apparently this only supports a single t7xx instance in a system? Not good.

Quoted 10 lines
Quoted 7 lines

drivers/net/wwan/t7xx/t7xx_pci_rescan.c line 26

Quoted 7 lines
drivers/net/wwan/t7xx/t7xx_pci_rescan.c new file +7 -0
+void t7xx_pci_dev_rescan(void)
+{
+	struct pci_bus *b = NULL;
+
+	pci_lock_rescan_remove();
+	while ((b = pci_find_next_bus(b)))
+		pci_rescan_bus(b);

No, this driver absolutely cannot rescan and assign unassigned resources for all the PCI buses in the system.

T7xx device falls off the bus due to ACPI reset.
Would you please suggest how we can bring device back on the bus without such changes inside driver ? Will pci_reset_function() help in this regard ?

If there is no alternate option, then we shall try using remove and rescan from user space and drop this patch.

Quoted 2 lines

Bjorn

Signature · 1 line
Chetan
#7 lore raw

Re: [PATCH v5 net-next 3/5] net: wwan: t7xx: PCIe reset rescan

Quoted 15 lines · M Chetan
Quoted 14 lines · Bjorn Helgaas
Quoted 12 lines · Jakub Kicinski
Quoted 11 lines · On Sat, 21 Jan 2023 19:03:23 +0530 [email protected] wrote:

From: M Chetan Kumar <[email protected]>

PCI rescan module implements "rescan work queue". In firmware flashing or coredump collection procedure WWAN device is programmed to boot in fastboot mode and a work item is scheduled for removal & detection.

The WWAN device is reset using APCI call as part driver removal flow. Work queue rescans pci bus at fixed interval for device detection, later when device is detect work queue exits.

Quoted 6 lines
Quoted 3 lines

I'm not sure what's going on here. Do we need to reset the device when the t7xx driver is loaded so the device will load new firmware when it comes out of reset?

Flow is, Reset the device to get into firmware download mode then update the firmware and later reset it to go back to normal mode.

Thanks, that makes sense, and I'm confident that t7xx is not the only driver that needs to do something like this, so we should be able to figure out a nice way to do it.

Quoted 11 lines
Quoted 10 lines
Quoted 7 lines

drivers/net/wwan/t7xx/t7xx_pci_rescan.c line 26

Quoted 7 lines
drivers/net/wwan/t7xx/t7xx_pci_rescan.c new file +7 -0
+void t7xx_pci_dev_rescan(void)
+{
+	struct pci_bus *b = NULL;
+
+	pci_lock_rescan_remove();
+	while ((b = pci_find_next_bus(b)))
+		pci_rescan_bus(b);

No, this driver absolutely cannot rescan and assign unassigned resources for all the PCI buses in the system.

Quoted 4 lines

T7xx device falls off the bus due to ACPI reset.
Would you please suggest how we can bring device back on the bus without such changes inside driver ? Will pci_reset_function() help in this regard ?

"Falling off the bus" is not very precise language, but it usually means the device stops responding to PCI transactions like config, memory, or I/O accesses.

Any kind of reset, whether it's done via ACPI _RST or one of the mechanisms used by pci_reset_function(), causes a PCI device to stop responding temporarily. When the device exits reset, it does some internal initialization and eventually becomes ready to respond to PCI transactions again.

The PCI core doesn't do anything to the device to "bring it back on the bus" other than powering on the device or deasserting whatever signal initiated the reset in the first place.

For example, if we do the reset via pci_reset_secondary_bus(), we set the Secondary Bus Reset (PCI_BRIDGE_CTL_BUS_RESET) bit in a bridge, which triggers a reset for devices below the bridge. When we clear Secondary Bus Reset, those devices reinitialize themselves and start responding to PCI transactions. pci_reset_secondary_bus() contains a ssleep(1) to give the device time for that initialization.

The t7xx_pci_dev_rescan() loop calls pci_rescan_bus(), which does nothing to bring devices back on the bus. It merely issues config reads to all the possible device addresses to see which respond.

If t7xx_pci_dev_rescan() seems to bring the device back on the bus, it is probably simply because it takes time and gives the device time to finish its initialization. It doesn't actually *do* anything to the device other than do a config read to it.

I notice that t7xx_remove_rescan() would actually *remove* the pci_dev, and pci_rescan_bus() would create a new pci_dev if the t7xx device responds to a config read. But this a real mess. When you remove the device, the driver is detached from it, and we should no longer be running any driver code.

If you can use pci_reset_function(), there's no need to remove and re-enumerate the device, so that should let you get rid of the whole t7xx_remove_rescan() workqueue.

Bjorn