Highspeed device and below has different state names than superspeed and
higher. Add proper checks and printouts of link states for highspeed and
below.

Signed-off-by: Thinh Nguyen <thi...@synopsys.com>
---
Change in v2:
 - New patch, no previous change

 drivers/usb/dwc3/debug.h   | 29 +++++++++++++++++++++++++++++
 drivers/usb/dwc3/debugfs.c | 19 +++++++++++++++++--
 2 files changed, 46 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/dwc3/debug.h b/drivers/usb/dwc3/debug.h
index c66d216dcc30..4f75ab3505b7 100644
--- a/drivers/usb/dwc3/debug.h
+++ b/drivers/usb/dwc3/debug.h
@@ -116,6 +116,35 @@ dwc3_gadget_link_string(enum dwc3_link_state link_state)
        }
 }
 
+/**
+ * dwc3_gadget_hs_link_string - returns highspeed and below link name
+ * @link_state: link state code
+ */
+static inline const char *
+dwc3_gadget_hs_link_string(enum dwc3_link_state link_state)
+{
+       switch (link_state) {
+       case DWC3_LINK_STATE_U0:
+               return "On";
+       case DWC3_LINK_STATE_U2:
+               return "Sleep";
+       case DWC3_LINK_STATE_U3:
+               return "Suspend";
+       case DWC3_LINK_STATE_SS_DIS:
+               return "Disconnected";
+       case DWC3_LINK_STATE_RX_DET:
+               return "Early Suspend";
+       case DWC3_LINK_STATE_RECOV:
+               return "Recovery";
+       case DWC3_LINK_STATE_RESET:
+               return "Reset";
+       case DWC3_LINK_STATE_RESUME:
+               return "Resume";
+       default:
+               return "UNKNOWN link state\n";
+       }
+}
+
 /**
  * dwc3_trb_type_string - returns TRB type as a string
  * @type: the type of the TRB
diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c
index 1da012f105d7..e613a61ae58a 100644
--- a/drivers/usb/dwc3/debugfs.c
+++ b/drivers/usb/dwc3/debugfs.c
@@ -539,13 +539,17 @@ static int dwc3_link_state_show(struct seq_file *s, void 
*unused)
        unsigned long           flags;
        enum dwc3_link_state    state;
        u32                     reg;
+       u8                      speed;
 
        spin_lock_irqsave(&dwc->lock, flags);
        reg = dwc3_readl(dwc->regs, DWC3_DSTS);
        state = DWC3_DSTS_USBLNKST(reg);
-       spin_unlock_irqrestore(&dwc->lock, flags);
+       speed = reg & DWC3_DSTS_CONNECTSPD;
 
-       seq_printf(s, "%s\n", dwc3_gadget_link_string(state));
+       seq_printf(s, "%s\n", (speed >= DWC3_DSTS_SUPERSPEED) ?
+                  dwc3_gadget_link_string(state) :
+                  dwc3_gadget_hs_link_string(state));
+       spin_unlock_irqrestore(&dwc->lock, flags);
 
        return 0;
 }
@@ -563,6 +567,8 @@ static ssize_t dwc3_link_state_write(struct file *file,
        unsigned long           flags;
        enum dwc3_link_state    state = 0;
        char                    buf[32];
+       u32                     reg;
+       u8                      speed;
 
        if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
                return -EFAULT;
@@ -583,6 +589,15 @@ static ssize_t dwc3_link_state_write(struct file *file,
                return -EINVAL;
 
        spin_lock_irqsave(&dwc->lock, flags);
+       reg = dwc3_readl(dwc->regs, DWC3_DSTS);
+       speed = reg & DWC3_DSTS_CONNECTSPD;
+
+       if (speed < DWC3_DSTS_SUPERSPEED &&
+           state != DWC3_LINK_STATE_RECOV) {
+               spin_unlock_irqrestore(&dwc->lock, flags);
+               return -EINVAL;
+       }
+
        dwc3_gadget_set_link_state(dwc, state);
        spin_unlock_irqrestore(&dwc->lock, flags);
 
-- 
2.11.0

Reply via email to