kern/101274: SysKonnect Yukon initialization bug on K8M800 motherboards

Kirill Stepanchuk kirillstp at hotmail.com
Wed Aug 2 18:00:33 UTC 2006


>Number:         101274
>Category:       kern
>Synopsis:       SysKonnect Yukon initialization bug on K8M800 motherboards
>Confidential:   no
>Severity:       critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Aug 02 18:00:31 GMT 2006
>Closed-Date:
>Last-Modified:
>Originator:     Kirill Stepanchuk
>Release:        FreeBSD 5.4
>Organization:
Sandvine Inc
>Environment:
FreeBSD 5.4-STABLE FreeBSD 5.4-STABLE #3: Wed Oct 12 09:08:41 EDT 2005 i386

>Description:
The SysKonnect Yukon NICs have a problem with K8M800 motherboards. On reboots and power cycles, the NIC will come up in a bad state, which prevents the driver from being attached. The error message "sk0: unknown media type 0x0" identifies that the NIC is in a bad state.
>How-To-Repeat:
A D-Link DGE-530T Gigabit Ethernet Adapter will exibit this behaviour on K8M800 motherboards
>Fix:
--- if_sk.c@@/main/RELENG_5/sandvine_bsd_5_main/0	2006-07-25 10:59:39.000000000 -0400
+++ if_sk.c	2006-08-01 10:40:47.000000000 -0400
@@ -1564,12 +1564,82 @@
 	int			unit, error = 0, rid, *port;
 	uint8_t			skrs;
 	char			*pname, *revstr;
+        u_int32_t		iobase, membase, irq;
+        u_int32_t               command;
 
 	sc = device_get_softc(dev);
 	unit = device_get_unit(dev);
 
 	mtx_init(&sc->sk_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
 	    MTX_DEF | MTX_RECURSE);
+
+
+
+	/*
+	 * Handle power management nonsense.
+	 */
+	command = pci_read_config(dev, SK_PCI_CAPID, 4) & 0x000000FF;
+	if (command == 0x01) {
+		command = pci_read_config(dev, SK_PCI_PWRMGMTCTRL, 4);
+		if (command & SK_PSTATE_MASK) {
+
+
+			/* Save important PCI config data. */
+			iobase = pci_read_config(dev, SK_PCI_LOIO, 4);
+			membase = pci_read_config(dev, SK_PCI_LOMEM, 4);
+			irq = pci_read_config(dev, SK_PCI_INTLINE, 4);
+
+			/* Reset the power state. */
+			printf("skc%d: chip is in D%d power mode "
+			"-- setting to D0\n", unit, command & SK_PSTATE_MASK);
+			command &= 0xFFFFFFFC;
+			pci_write_config(dev, SK_PCI_PWRMGMTCTRL, command, 4);
+
+			/* Restore PCI config data. */
+			pci_write_config(dev, SK_PCI_LOIO, iobase, 4);
+			pci_write_config(dev, SK_PCI_LOMEM, membase, 4);
+			pci_write_config(dev, SK_PCI_INTLINE, irq, 4);
+		}
+	}
+
+	/* Perform a PCI Reset using the chip's own power management functions:
+	1. Save Config
+	2. Set to D3 power mode
+	3. Set to D0 power mode
+	4. Restore Config
+	*/
+
+	/* Save important PCI config data. */
+	iobase = pci_read_config(dev, SK_PCI_LOIO, 4);
+	membase = pci_read_config(dev, SK_PCI_LOMEM, 4);
+	irq = pci_read_config(dev, SK_PCI_INTLINE, 4);
+
+	if(bootverbose){
+		command = pci_read_config(dev, SK_PCI_PWRMGMTCTRL, 4);
+		printf("skc%d: chip is in D%d power mode "
+		"-- setting to D3\n", unit, command & SK_PSTATE_MASK);
+	}
+	command =SK_PSTATE_D3;
+	pci_write_config(dev, SK_PCI_PWRMGMTCTRL, command, 4);
+	if(bootverbose) {
+		command = pci_read_config(dev, SK_PCI_PWRMGMTCTRL, 4);
+		printf("skc%d: chip is in D%d power mode "
+		"-- setting to D0\n", unit, command & SK_PSTATE_MASK);
+	}
+	command =SK_PSTATE_D0;
+	pci_write_config(dev, SK_PCI_PWRMGMTCTRL, command, 4);
+	if(bootverbose){
+		command = pci_read_config(dev, SK_PCI_PWRMGMTCTRL, 4);
+		printf("skc%d: chip is in D%d power mode ", unit, command & SK_PSTATE_MASK);
+	}
+
+	/* Restore PCI config data. */
+	pci_write_config(dev, SK_PCI_LOIO, iobase, 4);
+	pci_write_config(dev, SK_PCI_LOMEM, membase, 4);
+	pci_write_config(dev, SK_PCI_INTLINE, irq, 4);
+
+
+
 	/*
 	 * Map control/status registers.
 	 */

>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list