From owner-svn-src-head@FreeBSD.ORG Wed Feb 18 06:26:55 2015 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id F3A8F306; Wed, 18 Feb 2015 06:26:54 +0000 (UTC) Received: from mail-ie0-f182.google.com (mail-ie0-f182.google.com [209.85.223.182]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (Client CN "smtp.gmail.com", Issuer "Google Internet Authority G2" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id C0E8B385; Wed, 18 Feb 2015 06:26:54 +0000 (UTC) Received: by iecar1 with SMTP id ar1so46561328iec.11; Tue, 17 Feb 2015 22:26:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:sender:in-reply-to:references:date:message-id:subject :from:to:cc:content-type; bh=sQ4dSar0YKICHCYXBp1Rztk2dnsqbSQevJMk/gJ0eEQ=; b=qMypDQpaZC8U7fKhcqlN47trMkwLcz/AT/ZIsLjhaEv+9gnOzurtgdx8pa4CXxQolF rAy0uudfObrHNDpbv5KIpeo+i8juBuSavMFb29i9Ztr1/t4yNtGqW0uY4CAgtu8+iJqq TRO3of47z99/Od8rzjsEPa3NUdyb6g/Cgjk4UVBiH3uvyXWai9D6LJ5GiyPUtnHvu6KC wOb7bIvkhSbsvBInpOiyW0sTniHjJ9kqxNJGPA52jemFL/I34DVyspHcVK0Qcdcp3gcT mcV03EC9sY32lUyQdlpWqS7Ff819F/tqh1acLoP/7z0P6xMPcbDWiec+pzrTcsxmxW1/ RW+A== MIME-Version: 1.0 X-Received: by 10.42.188.133 with SMTP id da5mr38568446icb.37.1424240808560; Tue, 17 Feb 2015 22:26:48 -0800 (PST) Sender: adrian.chadd@gmail.com Received: by 10.36.17.66 with HTTP; Tue, 17 Feb 2015 22:26:48 -0800 (PST) In-Reply-To: <201502180553.t1I5r5CF063356@svn.freebsd.org> References: <201502180553.t1I5r5CF063356@svn.freebsd.org> Date: Tue, 17 Feb 2015 22:26:48 -0800 X-Google-Sender-Auth: c0akGuDqFhLNAE9W67JndZRO6DA Message-ID: Subject: Re: svn commit: r278936 - in head/sys/dev: cardbus pccbb From: Adrian Chadd To: Warner Losh Content-Type: text/plain; charset=UTF-8 Cc: "svn-src-head@freebsd.org" , "svn-src-all@freebsd.org" , "src-committers@freebsd.org" X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 18 Feb 2015 06:26:55 -0000 Hm! Can you dump the config space when this happens, just locally? I'd like to see what the device id and sub ids are. (That'll tell me if the thing hit a power-on bug, which there has actually been a reset power-on "bug" in atheros hardware since.. well, forever.) -adrian On 17 February 2015 at 21:53, Warner Losh wrote: > Author: imp > Date: Wed Feb 18 05:53:04 2015 > New Revision: 278936 > URL: https://svnweb.freebsd.org/changeset/base/278936 > > Log: > On my Lenovo T400, a Atheros 2413 has a problem powering up > sometimes. It will power up wrong and identify itself badly: > > cardbus0: at device 0.0 (no driver attached) > cardbus0: at device 0.1 (no driver attached) > cardbus0: at device 0.2 (no driver attached) > cardbus0: at device 0.3 (no driver attached) > cardbus0: at device 0.4 (no driver attached) > cardbus0: at device 0.5 (no driver attached) > cardbus0: at device 0.6 (no driver attached) > cardbus0: at device 0.7 (no driver attached) > > All the higher numbered functions (.2 and above) have a config space > of all 0's. This smells a bit like a special debug mode, but the > current atheros driver doesn't cope. It is unclear if this card is > just a flake, or if we're doing something wrong in the power-up > sequence. > > Put a work around into the code that tests for this rather unusual > condition. If we power a CardBus device up, and the device says it is > multi-function, and any of the functions have a 0 device ID, try the > power-up sequence again. > > Modified: > head/sys/dev/cardbus/cardbus.c > head/sys/dev/pccbb/pccbb.c > > Modified: head/sys/dev/cardbus/cardbus.c > ============================================================================== > --- head/sys/dev/cardbus/cardbus.c Wed Feb 18 05:20:52 2015 (r278935) > +++ head/sys/dev/cardbus/cardbus.c Wed Feb 18 05:53:04 2015 (r278936) > @@ -122,6 +122,7 @@ cardbus_detach(device_t cbdev) > cardbus_detach_card(cbdev); > #ifdef PCI_RES_BUS > sc = device_get_softc(cbdev); > + device_printf(cbdev, "Freeing up the allocatd bus\n"); > (void)bus_release_resource(cbdev, PCI_RES_BUS, 0, sc->sc_bus); > #endif > return (0); > @@ -180,6 +181,7 @@ cardbus_attach_card(device_t cbdev) > > sc = device_get_softc(cbdev); > cardbus_detach_card(cbdev); /* detach existing cards */ > + POWER_DISABLE_SOCKET(brdev, cbdev); /* Turn the socket off first */ > POWER_ENABLE_SOCKET(brdev, cbdev); > domain = pcib_get_domain(cbdev); > bus = pcib_get_bus(cbdev); > > Modified: head/sys/dev/pccbb/pccbb.c > ============================================================================== > --- head/sys/dev/pccbb/pccbb.c Wed Feb 18 05:20:52 2015 (r278935) > +++ head/sys/dev/pccbb/pccbb.c Wed Feb 18 05:53:04 2015 (r278936) > @@ -155,7 +155,7 @@ SYSCTL_INT(_hw_cbb, OID_AUTO, debug, CTL > static void cbb_insert(struct cbb_softc *sc); > static void cbb_removal(struct cbb_softc *sc); > static uint32_t cbb_detect_voltage(device_t brdev); > -static void cbb_cardbus_reset_power(device_t brdev, device_t child, int on); > +static int cbb_cardbus_reset_power(device_t brdev, device_t child, int on); > static int cbb_cardbus_io_open(device_t brdev, int win, uint32_t start, > uint32_t end); > static int cbb_cardbus_mem_open(device_t brdev, int win, > @@ -958,12 +958,12 @@ cbb_do_power(device_t brdev) > /* CardBus power functions */ > /************************************************************************/ > > -static void > +static int > cbb_cardbus_reset_power(device_t brdev, device_t child, int on) > { > struct cbb_softc *sc = device_get_softc(brdev); > - uint32_t b; > - int delay, count; > + uint32_t b, h; > + int delay, count, zero_seen, func; > > /* > * Asserting reset for 20ms is necessary for most bridges. For some > @@ -1002,30 +1002,61 @@ cbb_cardbus_reset_power(device_t brdev, > 0xfffffffful && --count >= 0); > if (count < 0) > device_printf(brdev, "Warning: Bus reset timeout\n"); > + > + /* > + * Some cards (so far just an atheros card I have) seem to > + * come out of reset in a funky state. They report they are > + * multi-function cards, but have nonsense for some of the > + * higher functions. So if the card claims to be MFDEV, and > + * any of the higher functions' ID is 0, then we've hit the > + * bug and we'll try again. > + */ > + h = PCIB_READ_CONFIG(brdev, b, 0, 0, PCIR_HDRTYPE, 1); > + if ((h & PCIM_MFDEV) == 0) > + return 0; > + zero_seen = 0; > + for (func = 1; func < 8; func++) { > + h = PCIB_READ_CONFIG(brdev, b, 0, func, > + PCIR_DEVVENDOR, 4); > + if (h == 0) > + zero_seen++; > + } > + if (!zero_seen) > + return 0; > + return (EINVAL); > } > + return 0; > +} > + > +static int > +cbb_cardbus_power_disable_socket(device_t brdev, device_t child) > +{ > + cbb_power(brdev, CARD_OFF); > + cbb_cardbus_reset_power(brdev, child, 0); > + return (0); > } > > static int > cbb_cardbus_power_enable_socket(device_t brdev, device_t child) > { > struct cbb_softc *sc = device_get_softc(brdev); > - int err; > + int err, count; > > if (!CBB_CARD_PRESENT(cbb_get(sc, CBB_SOCKET_STATE))) > return (ENODEV); > > - err = cbb_do_power(brdev); > - if (err) > - return (err); > - cbb_cardbus_reset_power(brdev, child, 1); > - return (0); > -} > - > -static int > -cbb_cardbus_power_disable_socket(device_t brdev, device_t child) > -{ > - cbb_power(brdev, CARD_OFF); > - cbb_cardbus_reset_power(brdev, child, 0); > + count = 10; > + do { > + err = cbb_do_power(brdev); > + if (err) > + return (err); > + err = cbb_cardbus_reset_power(brdev, child, 1); > + if (err) { > + device_printf(brdev, "Reset failed, trying again.\n"); > + cbb_cardbus_power_disable_socket(brdev, child); > + pause("cbbErr1", hz / 10); /* wait 100ms */ > + } > + } while (err != 0 && count-- > 0); > return (0); > } > >