Subject: Re: kern/29600: cbb(4) hangs on boot
To: None <kern-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: FUKAUMI Naoki <fun@naobsd.org>
List: netbsd-bugs
Date: 03/12/2005 06:23:02
The following reply was made to PR kern/29600; it has been noted by GNATS.

From: FUKAUMI Naoki <fun@naobsd.org>
To: gnats-bugs@netbsd.org
Cc: yamt@mwd.biglobe.ne.jp
Subject: Re: kern/29600: cbb(4) hangs on boot
Date: Sat, 12 Mar 2005 15:22:20 +0900

 I have a problem on my VAIO TR1 and OpenBlockS266, too.
 
 VAIO TR-1:
   cbb0 at pci1 dev 5 function 0: Ricoh 5C475 PCI-CardBus bridge (rev. 0xb8)
 
 OpenBlockS266:
   cbb0 at pci0 dev 2 function 0: Ricoh 5C475 PCI-CardBus bridge (rev. 0x80)
 
 I made a patch, idea from:
   http://mail-index.netbsd.org/tech-kern/2005/02/26/0016.html
 
 # I don't know pccbb.c rev. 1.111 (and 1.112) changes are correct.
 # At lease, it doesn't work Ricoh controller with 16-bit card!
 
 Index: sys/dev/pci/pccbb.c
 ===================================================================
 RCS file: /home/fun/cvsroot/NetBSD/src/sys/dev/pci/pccbb.c,v
 retrieving revision 1.117
 diff -u -r1.117 pccbb.c
 --- sys/dev/pci/pccbb.c	27 Feb 2005 00:27:33 -0000	1.117
 +++ sys/dev/pci/pccbb.c	27 Feb 2005 13:26:28 -0000
 @@ -751,7 +751,7 @@
   *     3) route PCI interrupt,
   *     4) close all memory and io windows.
   *     5) turn off bus power.
 - *     6) card detect interrupt on.
 + *     6) card detect and power cycle interrupts on.
   *     7) clear interrupt
   */
  static void
 @@ -908,9 +908,9 @@
  	/* turn off power */
  	pccbb_power((cardbus_chipset_tag_t)sc, CARDBUS_VCC_0V | CARDBUS_VPP_0V);
  
 -	/* CSC Interrupt: Card detect interrupt on */
 +	/* CSC Interrupt: Card detect and power cycle interrupts on */
  	reg = bus_space_read_4(bmt, bmh, CB_SOCKET_MASK);
 -	reg |= CB_SOCKET_MASK_CD | CB_SOCKET_MASK_POWER;  /* Card detect intr is turned on. */
 +	reg |= CB_SOCKET_MASK_CD | CB_SOCKET_MASK_POWER;
  	bus_space_write_4(bmt, bmh, CB_SOCKET_MASK, reg);
  	/* reset interrupt */
  	bus_space_write_4(bmt, bmh, CB_SOCKET_EVENT,
 @@ -1091,6 +1091,7 @@
  	}
  
  	if (sockevent & CB_SOCKET_EVENT_POWER) {
 +		/* XXX: Never happened when attaching 16-bit card. */
  		sc->sc_pwrcycle++;
  		wakeup(&sc->sc_pwrcycle);
  	}
 @@ -1285,7 +1286,7 @@
  	u_int32_t status, sock_ctrl, reg_ctrl;
  	bus_space_tag_t memt = sc->sc_base_memt;
  	bus_space_handle_t memh = sc->sc_base_memh;
 -	int on = 0, pwrcycle;
 +	int on = 0;
  
  	DPRINTF(("pccbb_power: %s and %s [0x%x]\n",
  	    (command & CARDBUS_VCCMASK) == CARDBUS_VCC_UC ? "CARDBUS_VCC_UC" :
 @@ -1352,23 +1353,26 @@
  		break;
  	}
  
 -	pwrcycle = sc->sc_pwrcycle;
 -
  #if 0
  	DPRINTF(("sock_ctrl: 0x%x\n", sock_ctrl));
  #endif
  	bus_space_write_4(memt, memh, CB_SOCKET_CTRL, sock_ctrl);
  
  	if (on) {
 -		int s;
 +		int error, s;
  		struct timeval before, after, diff;
  
  		microtime(&before);
  		s = splbio();
 -		while (pwrcycle == sc->sc_pwrcycle)
 -			tsleep(&sc->sc_pwrcycle, PWAIT, "pccpwr", 0);
 +		/* XXX: Set timeout to 200ms because power cycle event will be
 +		   never happened when attaching 16-bit card. */
 +		error = tsleep(&sc->sc_pwrcycle, PWAIT, "pccpwr", hz/5);
  		splx(s);
  		microtime(&after);
 +		if (error == EWOULDBLOCK) {
 +			DPRINTF(("%s: power on timeout exceeded, assuming "
 +			       "powered on\n", sc->sc_dev.dv_xname));
 +		}
  		timersub(&after, &before, &diff);
  		printf("%s: wait took %ld.%06lds\n", sc->sc_dev.dv_xname,
  		    diff.tv_sec, diff.tv_usec);
 @@ -3440,9 +3444,8 @@
  			/* BIOS did not recover this register */
  			pci_conf_write (sc->sc_pc, sc->sc_tag,
  					PCI_BUSNUM, sc->sc_busnum);
 -		/* CSC Interrupt: Card detect interrupt on */
 +		/* CSC Interrupt: Card detect and power cycle interrupts on */
  		reg = bus_space_read_4(base_memt, base_memh, CB_SOCKET_MASK);
 -		/* Card detect intr is turned on. */
  		reg |= CB_SOCKET_MASK_CD | CB_SOCKET_MASK_POWER;
  		bus_space_write_4(base_memt, base_memh, CB_SOCKET_MASK, reg);
  		/* reset interrupt */