tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

com(4) and LSI bug workaround



Hi!


I mistook commit the other day.

  http://mail-index.NetBSD.org/source-changes/2013/09/01/msg047120.html

Although the processing for this ARMADAXP was moved to com_mv.c, IIR of
com is reset by reading.  That is, since IIR was read by mvuart_intr(),
IIR was not able to be correctly read by comintr().
I would like to add the next member to com_softc, in order to solve this
problem.

  /* XXXX: vendor workaround functions */
  int (*sc_vendor_workaround)(struct com_softc *);


Processing which avoids BUSY of ARMADAXP is performed by calling this
from comintr() at the time of COM_TYPE_ARMADAXP.  Probably addition of
this member will consume many several bytes of memories by almost all
your machines.
However, no machines other than ARMADAXP call this.  I would like to
merge this correction.


Please let me know your opinion.

Probably, it will be more desirable for this member to add reasoncode
and value of int to an argument for other LSI with fault.

  int (*sc_vendor_workaround)(struct com_softc *, int reasoncode, int val);

Thanks,
--
kiyohara
Index: ic/com.c
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/com.c,v
retrieving revision 1.314
diff -u -r1.314 com.c
--- ic/com.c    1 Sep 2013 04:58:15 -0000       1.314
+++ ic/com.c    24 Sep 2013 11:00:02 -0000
@@ -1938,6 +1938,18 @@
        mutex_spin_enter(&sc->sc_lock);
        iir = CSR_READ_1(regsp, COM_REG_IIR);
 
+       if (sc->sc_type == COM_TYPE_ARMADAXP) {
+               if ((iir & IIR_BUSY) == IIR_BUSY) {
+                       if (sc->sc_vendor_workaround != NULL &&
+                           sc->sc_vendor_workaround(sc) != 0) {
+                               mutex_spin_exit(&sc->sc_lock);
+                               return (0);
+                       }
+                       CSR_WRITE_1(regsp, COM_REG_LCR, sc->sc_lcr);
+                       iir = CSR_READ_1(regsp, COM_REG_IIR);
+               }
+       }
+
        if (ISSET(iir, IIR_NOPEND)) {
                mutex_spin_exit(&sc->sc_lock);
                return (0);
Index: ic/comvar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/comvar.h,v
retrieving revision 1.76
diff -u -r1.76 comvar.h
--- ic/comvar.h 1 Sep 2013 04:51:24 -0000       1.76
+++ ic/comvar.h 24 Sep 2013 11:00:02 -0000
@@ -226,6 +226,9 @@
        void (*disable)(struct com_softc *);
        int enabled;
 
+       /* XXXX: vendor workaround functions */
+       int (*sc_vendor_workaround)(struct com_softc *);
+
        struct pps_state sc_pps_state;  /* pps state */
 
 #ifdef RND_COM
Index: marvell/com_mv.c
===================================================================
RCS file: /cvsroot/src/sys/dev/marvell/com_mv.c,v
retrieving revision 1.6
diff -u -r1.6 com_mv.c
--- marvell/com_mv.c    1 Sep 2013 04:51:24 -0000       1.6
+++ marvell/com_mv.c    24 Sep 2013 11:00:04 -0000
@@ -53,7 +53,7 @@
 static int mvuart_match(device_t, struct cfdata *, void *);
 static void mvuart_attach(device_t, device_t, void *);
 
-static int mvuart_intr(void *);
+static int mvuart_armadaxp_workaround(struct com_softc *);
 
 CFATTACH_DECL_NEW(mvuart_gt, sizeof(struct com_softc),
     mvuart_match, mvuart_attach, NULL, NULL);
@@ -88,12 +88,14 @@
 struct {
        int model;
        int type;
+       int (*workaround)(struct com_softc *);
 } mvuart_extensions[] = {
-       { MARVELL_ARMADAXP_MV78130,     COM_TYPE_ARMADAXP },
-       { MARVELL_ARMADAXP_MV78160,     COM_TYPE_ARMADAXP },
-       { MARVELL_ARMADAXP_MV78230,     COM_TYPE_ARMADAXP },
-       { MARVELL_ARMADAXP_MV78260,     COM_TYPE_ARMADAXP },
-       { MARVELL_ARMADAXP_MV78460,     COM_TYPE_ARMADAXP },
+#define MV(x)  MARVELL_ ## x
+       { MV(ARMADAXP_MV78130), COM_TYPE_ARMADAXP, mvuart_armadaxp_workaround },
+       { MV(ARMADAXP_MV78160), COM_TYPE_ARMADAXP, mvuart_armadaxp_workaround },
+       { MV(ARMADAXP_MV78230), COM_TYPE_ARMADAXP, mvuart_armadaxp_workaround },
+       { MV(ARMADAXP_MV78260), COM_TYPE_ARMADAXP, mvuart_armadaxp_workaround },
+       { MV(ARMADAXP_MV78460), COM_TYPE_ARMADAXP, mvuart_armadaxp_workaround },
 };
 
 /* ARGSUSED */
@@ -157,56 +159,40 @@
        for (i = 0; i < __arraycount(mvuart_extensions); i++)
                if (mva->mva_model == mvuart_extensions[i].model) {
                        sc->sc_type = mvuart_extensions[i].type;
+                       sc->sc_vendor_workaround =
+                           mvuart_extensions[i].workaround;
                        break;
                }
 
        com_attach_subr(sc);
 
-       if (sc->sc_type == COM_TYPE_ARMADAXP)
-               marvell_intr_establish(mva->mva_irq, IPL_SERIAL,
-                   mvuart_intr, sc);
-       else
-               marvell_intr_establish(mva->mva_irq, IPL_SERIAL, comintr, sc);
+       marvell_intr_establish(mva->mva_irq, IPL_SERIAL, comintr, sc);
 }
 
 static int
-mvuart_intr(void *arg)
+mvuart_armadaxp_workaround(struct com_softc *sc)
 {
-       struct com_softc *sc = arg;
        struct com_regs *regsp = &sc->sc_regs;
        int timeout;
-       uint8_t iir, v;
+       uint8_t v;
 
-       if (!device_is_active(sc->sc_dev))
-               return 0;
-
-       KASSERT(regsp != NULL);
-
-       mutex_spin_enter(&sc->sc_lock);
-       iir = CSR_READ_1(regsp, COM_REG_IIR);
-       if ((iir & IIR_BUSY) == IIR_BUSY) {
-               /*
-                * XXXXX: What is this?  I don't found in Marvell datasheet.
-                *        Maybe workaround for BUG in UART.
-                */
+       /*
+        * XXXXX: What is this?  I don't found in Marvell datasheet.
+        *        Maybe workaround for BUG in UART.
+        */
+       v = bus_space_read_1(regsp->cr_iot, regsp->cr_ioh, MVUART_REG_USR);
+       for (timeout = 10000; (v & 0x1) != 0; timeout--) {
+               if (timeout <= 0) {
+                       aprint_error_dev(sc->sc_dev,
+                           "timeout while waiting for BUSY interrupt "
+                           "acknowledge\n");
+                       return -1;
+               }
                v = bus_space_read_1(regsp->cr_iot, regsp->cr_ioh,
                    MVUART_REG_USR);
-               for (timeout = 10000; (v & 0x1) != 0; timeout--) {
-                       if (timeout <= 0) {
-                               aprint_error_dev(sc->sc_dev,
-                                   "timeout while waiting for BUSY interrupt "
-                                   "acknowledge\n");
-                               mutex_spin_exit(&sc->sc_lock);
-                               return 0;
-                       }
-                       v = bus_space_read_1(regsp->cr_iot, regsp->cr_ioh,
-                           MVUART_REG_USR);
-               }
-               CSR_WRITE_1(regsp, COM_REG_LCR, sc->sc_lcr);
        }
-       mutex_spin_exit(&sc->sc_lock);
 
-       return comintr(arg);
+       return 0;
 }
 
 #ifdef COM_REGMAP


Home | Main Index | Thread Index | Old Index