Thread (35 messages) 35 messages, 5 authors, 2022-01-13

Re: [PATCH net-next v3 02/12] net: wwan: t7xx: Add core components

From: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Date: 2021-12-16 11:56:03
Also in: linux-wireless

On Mon, 6 Dec 2021, Ricardo Martinez wrote:
From: Haijun Liu <haijun.liu@mediatek.com>

Registers the t7xx device driver with the kernel. Setup all the core
components: PCIe layer, Modem Host Cross Core Interface (MHCCIF),
modem control operations, modem state machine, and build
infrastructure.

* PCIe layer code implements driver probe and removal.
* MHCCIF provides interrupt channels to communicate events
  such as handshake, PM and port enumeration.
* Modem control implements the entry point for modem init,
  reset and exit.
* The modem status monitor is a state machine used by modem control
  to complete initialization and stop. It is used also to propagate
  exception events reported by other components.

Signed-off-by: Haijun Liu <haijun.liu@mediatek.com>
Signed-off-by: Chandrashekar Devegowda <chandrashekar.devegowda@intel.com>
Co-developed-by: Ricardo Martinez <ricardo.martinez@linux.intel.com>
Signed-off-by: Ricardo Martinez <ricardo.martinez@linux.intel.com>
+	switch (reason) {
+	case EXCEPTION_HS_TIMEOUT:
+		dev_err(dev, "BOOT_HS_FAIL\n");
+		break;
+
+	case EXCEPTION_EVENT:
+		t7xx_fsm_broadcast_state(ctl, MD_STATE_EXCEPTION);
+		t7xx_md_exception_handshake(ctl->md);
+
+		cnt = 0;
+		while (cnt < FSM_MD_EX_REC_OK_TIMEOUT_MS / FSM_EVENT_POLL_INTERVAL_MS) {
+			if (kthread_should_stop())
+				return;
+
+			spin_lock_irqsave(&ctl->event_lock, flags);
+			event = list_first_entry_or_null(&ctl->event_queue,
+							 struct t7xx_fsm_event, entry);
+			if (event) {
+				if (event->event_id == FSM_EVENT_MD_EX) {
+					fsm_del_kf_event(event);
+				} else if (event->event_id == FSM_EVENT_MD_EX_REC_OK) {
+					rec_ok = true;
+					fsm_del_kf_event(event);
+				}
+			}
+
+			spin_unlock_irqrestore(&ctl->event_lock, flags);
+			if (rec_ok)
+				break;
+
+			cnt++;
+			/* Try again after 20ms */
+			msleep(FSM_EVENT_POLL_INTERVAL_MS);
+		}
+
+		cnt = 0;
+		while (cnt < FSM_MD_EX_PASS_TIMEOUT_MS / FSM_EVENT_POLL_INTERVAL_MS) {
+			if (kthread_should_stop())
+				return;
+
+			spin_lock_irqsave(&ctl->event_lock, flags);
+			event = list_first_entry_or_null(&ctl->event_queue,
+							 struct t7xx_fsm_event, entry);
+			if (event && event->event_id == FSM_EVENT_MD_EX_PASS) {
+				pass = true;
+				fsm_del_kf_event(event);
+			}
+
+			spin_unlock_irqrestore(&ctl->event_lock, flags);
+
+			if (pass)
+				break;
+			cnt++;
+			/* Try again after 20ms */
+			msleep(FSM_EVENT_POLL_INTERVAL_MS);
+		}
It hurts me a bit to see so much code duplication with only that one 
extra if branch + if condition right-hand sides being different. It would 
seem like something that could be solved with a helper taking those two 
things as parameters.

I hope the ordering of FSM_EVENT_MD_EX, FSM_EVENT_MD_EX_REC_OK, and
FSM_EVENT_MD_EX_PASS is guaranteed by something. Otherwise, the event 
being waited for might not become the first entry in the event_queue and 
the loop just keeps waiting until timeout?

+void t7xx_fsm_clr_event(struct t7xx_fsm_ctl *ctl, enum t7xx_fsm_event_state event_id)
+{
+       struct device *dev = &ctl->md->t7xx_dev->pdev->dev;
+       struct t7xx_fsm_event *event, *evt_next;
+       unsigned long flags;
+
+       spin_lock_irqsave(&ctl->event_lock, flags);
+       list_for_each_entry_safe(event, evt_next, &ctl->event_queue, entry) {
+               dev_err(dev, "Unhandled event %d\n", event->event_id);
+
+               if (event->event_id == event_id)
+                       fsm_del_kf_event(event);
+       }
It seems that only events matching to event_id are removed from the 
event_queue. Can that dev_err print the same event over and over again 
(I'm assuming here multiple calls to t7xx_fsm_clr_event can occur) because 
the other events still remaining in event_queue?

+struct t7xx_fsm_ctl {
+	struct t7xx_modem	*md;
+	enum md_state		md_state;
+	unsigned int		curr_state;
+	unsigned int		last_state;
The value of last_state is never used.


-- 
 i.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help