NetBSD-Bugs archive

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

Re: port-i386/44581: MacBook1,1 won't resume after suspend



The following reply was made to PR port-i386/44581; it has been noted by GNATS.

From: Taylor R Campbell <campbell+netbsd%mumble.net@localhost>
To: gnats-bugs%NetBSD.org@localhost
Cc: 
Subject: Re: port-i386/44581: MacBook1,1 won't resume after suspend
Date: Wed, 16 Feb 2011 03:19:20 +0000

 Here's a patch to make the lockdebug panic go away when I reattach and
 redetach fwohci0.  This splits fwohci_init into two routines, one that
 won't fail and guarantees that the relevant kernel data structures are
 initialized well enough for fwohci_detach not to barf (fwohci_init),
 and one that is allowed to fail (fwohci_attach).
 
 Next I'll try to find what's wrong with the pmf handlers to make
 fwohci fail to resume and fail to reattach after the rest of the
 system has suspended and resumed while it has been detached.
 
 Index: dev/cardbus/fwohci_cardbus.c
 ===================================================================
 RCS file: /cvsroot/src/sys/dev/cardbus/fwohci_cardbus.c,v
 retrieving revision 1.33
 diff -p -u -r1.33 fwohci_cardbus.c
 --- dev/cardbus/fwohci_cardbus.c       19 Apr 2010 07:05:15 -0000      1.33
 +++ dev/cardbus/fwohci_cardbus.c       16 Feb 2011 03:16:19 -0000
 @@ -98,6 +98,8 @@ fwohci_cardbus_attach(device_t parent, d
               PCI_REVISION(ca->ca_class));
        aprint_naive("\n");
  
 +      fwohci_init(&sc->sc_sc);
 +
        /* Map I/O registers */
        if (Cardbus_mapreg_map(ct, PCI_OHCI_MAP_REGISTER,
              PCI_MAPREG_TYPE_MEM, 0,
 @@ -129,7 +131,7 @@ fwohci_cardbus_attach(device_t parent, d
        }
  
        /* XXX NULL should be replaced by some call to Cardbus coed */
 -      if (fwohci_init(&sc->sc_sc) != 0) {
 +      if (fwohci_attach(&sc->sc_sc) != 0) {
                Cardbus_intr_disestablish(ct, sc->sc_ih);
                sc->sc_ih = NULL;
        }
 Index: dev/ieee1394/firewire.c
 ===================================================================
 RCS file: /cvsroot/src/sys/dev/ieee1394/firewire.c,v
 retrieving revision 1.38
 diff -p -u -r1.38 firewire.c
 --- dev/ieee1394/firewire.c    7 Sep 2010 07:26:54 -0000       1.38
 +++ dev/ieee1394/firewire.c    16 Feb 2011 03:16:23 -0000
 @@ -680,6 +680,15 @@ fw_init(struct firewire_comm *fc)
        fc->crom_src_buf = NULL;
  }
  
 +void
 +fw_destroy(struct firewire_comm *fc)
 +{
 +      mutex_destroy(&fc->arq->q_mtx);
 +      mutex_destroy(&fc->ars->q_mtx);
 +      mutex_destroy(&fc->atq->q_mtx);
 +      mutex_destroy(&fc->ats->q_mtx);
 +}
 +
  #define BIND_CMP(addr, fwb) \
        (((addr) < (fwb)->start) ? -1 : ((fwb)->end < (addr)) ? 1 : 0)
  
 Index: dev/ieee1394/firewirereg.h
 ===================================================================
 RCS file: /cvsroot/src/sys/dev/ieee1394/firewirereg.h,v
 retrieving revision 1.15
 diff -p -u -r1.15 firewirereg.h
 --- dev/ieee1394/firewirereg.h 14 Nov 2010 15:47:20 -0000      1.15
 +++ dev/ieee1394/firewirereg.h 16 Feb 2011 03:16:23 -0000
 @@ -283,6 +283,7 @@ int fw_xferwait(struct fw_xfer *);
  void fw_drain_txq(struct firewire_comm *);
  void fw_busreset(struct firewire_comm *, uint32_t);
  void fw_init(struct firewire_comm *);
 +void fw_destroy(struct firewire_comm *);
  struct fw_bind *fw_bindlookup(struct firewire_comm *, uint16_t, uint32_t);
  int fw_bindadd(struct firewire_comm *, struct fw_bind *);
  int fw_bindremove(struct firewire_comm *, struct fw_bind *);
 Index: dev/ieee1394/fwohci.c
 ===================================================================
 RCS file: /cvsroot/src/sys/dev/ieee1394/fwohci.c,v
 retrieving revision 1.130
 diff -p -u -r1.130 fwohci.c
 --- dev/ieee1394/fwohci.c      7 Sep 2010 07:19:45 -0000       1.130
 +++ dev/ieee1394/fwohci.c      16 Feb 2011 03:16:23 -0000
 @@ -323,38 +323,15 @@ static void fwohci_arcv(struct fwohci_so
  #define IRX_CH        36
  
  
 -int
 +/*
 + * Call fwohci_init before fwohci_attach to initialize the kernel's
 + * data structures well enough that fwohci_detach won't crash, even if
 + * fwohci_attach fails.
 + */
 +
 +void
  fwohci_init(struct fwohci_softc *sc)
  {
 -      uint32_t reg;
 -      uint8_t ui[8];
 -      int i, mver;
 -
 -/* OHCI version */
 -      reg = OREAD(sc, OHCI_VERSION);
 -      mver = (reg >> 16) & 0xff;
 -      aprint_normal_dev(sc->fc.dev, "OHCI version %x.%x (ROM=%d)\n",
 -          mver, reg & 0xff, (reg >> 24) & 1);
 -      if (mver < 1 || mver > 9) {
 -              aprint_error_dev(sc->fc.dev, "invalid OHCI version\n");
 -              return ENXIO;
 -      }
 -
 -/* Available Isochronous DMA channel probe */
 -      OWRITE(sc, OHCI_IT_MASK, 0xffffffff);
 -      OWRITE(sc, OHCI_IR_MASK, 0xffffffff);
 -      reg = OREAD(sc, OHCI_IT_MASK) & OREAD(sc, OHCI_IR_MASK);
 -      OWRITE(sc, OHCI_IT_MASKCLR, 0xffffffff);
 -      OWRITE(sc, OHCI_IR_MASKCLR, 0xffffffff);
 -      for (i = 0; i < 0x20; i++)
 -              if ((reg & (1 << i)) == 0)
 -                      break;
 -      sc->fc.nisodma = i;
 -      aprint_normal_dev(sc->fc.dev, "No. of Isochronous channels is %d.\n",
 -          i);
 -      if (i == 0)
 -              return ENXIO;
 -
        sc->fc.arq = &sc->arrq.xferq;
        sc->fc.ars = &sc->arrs.xferq;
        sc->fc.atq = &sc->atrq.xferq;
 @@ -395,6 +372,68 @@ fwohci_init(struct fwohci_softc *sc)
        sc->atrq.off = OHCI_ATQOFF;
        sc->atrs.off = OHCI_ATSOFF;
  
 +      sc->fc.tcode = tinfo;
 +
 +      sc->fc.cyctimer = fwohci_cyctimer;
 +      sc->fc.ibr = fwohci_ibr;
 +      sc->fc.set_bmr = fwohci_set_bus_manager;
 +      sc->fc.ioctl = fwohci_ioctl;
 +      sc->fc.irx_enable = fwohci_irx_enable;
 +      sc->fc.irx_disable = fwohci_irx_disable;
 +
 +      sc->fc.itx_enable = fwohci_itxbuf_enable;
 +      sc->fc.itx_disable = fwohci_itx_disable;
 +      sc->fc.timeout = fwohci_timeout;
 +      sc->fc.set_intr = fwohci_set_intr;
 +#if BYTE_ORDER == BIG_ENDIAN
 +      sc->fc.irx_post = fwohci_irx_post;
 +#else
 +      sc->fc.irx_post = NULL;
 +#endif
 +      sc->fc.itx_post = NULL;
 +
 +      sc->intmask = sc->irstat = sc->itstat = 0;
 +
 +      fw_init(&sc->fc);
 +}
 +
 +/*
 + * Call fwohci_attach after fwohci_init to initialize the hardware and
 + * attach children.
 + */
 +
 +int
 +fwohci_attach(struct fwohci_softc *sc)
 +{
 +      uint32_t reg;
 +      uint8_t ui[8];
 +      int i, mver;
 +
 +/* OHCI version */
 +      reg = OREAD(sc, OHCI_VERSION);
 +      mver = (reg >> 16) & 0xff;
 +      aprint_normal_dev(sc->fc.dev, "OHCI version %x.%x (ROM=%d)\n",
 +          mver, reg & 0xff, (reg >> 24) & 1);
 +      if (mver < 1 || mver > 9) {
 +              aprint_error_dev(sc->fc.dev, "invalid OHCI version\n");
 +              return ENXIO;
 +      }
 +
 +/* Available Isochronous DMA channel probe */
 +      OWRITE(sc, OHCI_IT_MASK, 0xffffffff);
 +      OWRITE(sc, OHCI_IR_MASK, 0xffffffff);
 +      reg = OREAD(sc, OHCI_IT_MASK) & OREAD(sc, OHCI_IR_MASK);
 +      OWRITE(sc, OHCI_IT_MASKCLR, 0xffffffff);
 +      OWRITE(sc, OHCI_IR_MASKCLR, 0xffffffff);
 +      for (i = 0; i < 0x20; i++)
 +              if ((reg & (1 << i)) == 0)
 +                      break;
 +      sc->fc.nisodma = i;
 +      aprint_normal_dev(sc->fc.dev, "No. of Isochronous channels is %d.\n",
 +          i);
 +      if (i == 0)
 +              return ENXIO;
 +
        for (i = 0; i < sc->fc.nisodma; i++) {
                sc->fc.it[i] = &sc->it[i].xferq;
                sc->fc.ir[i] = &sc->ir[i].xferq;
 @@ -406,8 +445,6 @@ fwohci_init(struct fwohci_softc *sc)
                sc->ir[i].off = OHCI_IROFF(i);
        }
  
 -      sc->fc.tcode = tinfo;
 -
        sc->fc.config_rom = fwdma_alloc_setup(sc->fc.dev, sc->fc.dmat,
            CROMSIZE, &sc->crom_dma, CROMSIZE, BUS_DMA_NOWAIT);
        if (sc->fc.config_rom == NULL) {
 @@ -467,27 +504,6 @@ fwohci_init(struct fwohci_softc *sc)
            "EUI64 %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
            ui[0], ui[1], ui[2], ui[3], ui[4], ui[5], ui[6], ui[7]);
  
 -      sc->fc.cyctimer = fwohci_cyctimer;
 -      sc->fc.ibr = fwohci_ibr;
 -      sc->fc.set_bmr = fwohci_set_bus_manager;
 -      sc->fc.ioctl = fwohci_ioctl;
 -      sc->fc.irx_enable = fwohci_irx_enable;
 -      sc->fc.irx_disable = fwohci_irx_disable;
 -
 -      sc->fc.itx_enable = fwohci_itxbuf_enable;
 -      sc->fc.itx_disable = fwohci_itx_disable;
 -      sc->fc.timeout = fwohci_timeout;
 -      sc->fc.set_intr = fwohci_set_intr;
 -#if BYTE_ORDER == BIG_ENDIAN
 -      sc->fc.irx_post = fwohci_irx_post;
 -#else
 -      sc->fc.irx_post = NULL;
 -#endif
 -      sc->fc.itx_post = NULL;
 -
 -      sc->intmask = sc->irstat = sc->itstat = 0;
 -
 -      fw_init(&sc->fc);
        fwohci_reset(sc);
  
        sc->fc.bdev =
 @@ -499,10 +515,13 @@ fwohci_init(struct fwohci_softc *sc)
  int
  fwohci_detach(struct fwohci_softc *sc, int flags)
  {
 -      int i;
 +      int i, rv;
  
 -      if (sc->fc.bdev != NULL)
 -              config_detach(sc->fc.bdev, flags);
 +      if (sc->fc.bdev != NULL) {
 +              rv = config_detach(sc->fc.bdev, flags);
 +              if (rv)
 +                      return rv;
 +      }
        if (sc->sid_buf != NULL)
                fwdma_free(sc->sid_dma.dma_tag, sc->sid_dma.dma_map,
                    sc->sid_dma.v_addr);
 @@ -519,10 +538,7 @@ fwohci_detach(struct fwohci_softc *sc, i
                fwohci_db_free(sc, &sc->ir[i]);
        }
  
 -      mutex_destroy(&sc->arrq.xferq.q_mtx);
 -      mutex_destroy(&sc->arrs.xferq.q_mtx);
 -      mutex_destroy(&sc->atrq.xferq.q_mtx);
 -      mutex_destroy(&sc->atrs.xferq.q_mtx);
 +      fw_destroy(&sc->fc);
  
        return 0;
  }
 Index: dev/ieee1394/fwohcivar.h
 ===================================================================
 RCS file: /cvsroot/src/sys/dev/ieee1394/fwohcivar.h,v
 retrieving revision 1.32
 diff -p -u -r1.32 fwohcivar.h
 --- dev/ieee1394/fwohcivar.h   23 May 2010 18:56:59 -0000      1.32
 +++ dev/ieee1394/fwohcivar.h   16 Feb 2011 03:16:23 -0000
 @@ -79,7 +79,8 @@ struct fwohci_softc {
  #define OWRITE(sc, r, x) bus_space_write_4((sc)->bst, (sc)->bsh, (r), (x))
  #define OREAD(sc, r)  bus_space_read_4((sc)->bst, (sc)->bsh, (r))
  
 -int fwohci_init(struct fwohci_softc *);
 +void fwohci_init(struct fwohci_softc *);
 +int fwohci_attach(struct fwohci_softc *);
  int fwohci_detach(struct fwohci_softc *, int);
  int fwohci_intr(void *arg);
  int fwohci_resume(struct fwohci_softc *);
 Index: dev/pci/fwohci_pci.c
 ===================================================================
 RCS file: /cvsroot/src/sys/dev/pci/fwohci_pci.c,v
 retrieving revision 1.39
 diff -p -u -r1.39 fwohci_pci.c
 --- dev/pci/fwohci_pci.c       29 Apr 2010 06:41:27 -0000      1.39
 +++ dev/pci/fwohci_pci.c       16 Feb 2011 03:16:44 -0000
 @@ -107,6 +107,8 @@ fwohci_pci_attach(device_t parent, devic
        aprint_normal(": %s (rev. 0x%02x)\n", devinfo,
            PCI_REVISION(pa->pa_class));
  
 +      fwohci_init(&psc->psc_sc);
 +
        psc->psc_sc.fc.dev = self;
        psc->psc_sc.fc.dmat = pa->pa_dmat;
        psc->psc_pc = pa->pa_pc;
 @@ -154,15 +156,12 @@ fwohci_pci_attach(device_t parent, devic
        }
        aprint_normal_dev(self, "interrupting at %s\n", intrstr);
  
 +      if (fwohci_attach(&psc->psc_sc) != 0)
 +              goto fail;
 +
        if (!pmf_device_register(self, fwohci_pci_suspend, fwohci_pci_resume))
                aprint_error_dev(self, "couldn't establish power handler\n");
  
 -      if (fwohci_init(&psc->psc_sc) != 0) {
 -              pci_intr_disestablish(pa->pa_pc, psc->psc_ih);
 -              bus_space_unmap(psc->psc_sc.bst, psc->psc_sc.bsh,
 -                  psc->psc_sc.bssize);
 -      }
 -
        return;
  
  fail:
 


Home | Main Index | Thread Index | Old Index