From nobody Fri Sep 25 06:47:57 2026 Received: from bkemail.birger-koblitz.de (bkemail.birger-koblitz.de [23.88.97.239]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 495283515E5; Wed, 16 Sep 2026 03:24:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=23.88.97.239 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789529061; cv=none; b=Jl0f4qpwVRxDfyzoX5h9P4FLlH1xJn/r/TBcnCPi8VU4mF5KIJ/W2/RlWiZXc/AadaEnBLseDnwabboKdzxVz/lq3Qi1lQP5lct1rR+sIrM7sF9NRBoUCwyDgx5l1fA5CrBYWyjNHbsffsmBiLmSLCzhjCgXpkVeoqNrJcLlOa4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789529061; c=relaxed/simple; bh=anHWsZmc/HioyP1vEPDMn744EpmT5YgretWwLYFhp2M=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=fm4QbmvmbiUasMdAwl+V1QBHPkMEY7B2DtRRQR8OB6so2bAdUAQ3PKSOgr6YbHqUL7FHb5dzyqGPfXd4rC6NSr8r2qWNWr3GDb//k8YkuZMuSyHpJgbbsoHCda11Y4im8RsYgzt6RlYBQoudu986udWvFgmEI/cX6gPNnSAKHLc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=birger-koblitz.de; spf=pass smtp.mailfrom=birger-koblitz.de; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b=ISnU2Akr; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b=jHrNV/uq; arc=none smtp.client-ip=23.88.97.239 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=birger-koblitz.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=birger-koblitz.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b="ISnU2Akr"; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b="jHrNV/uq" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=birger-koblitz.de; s=default; t=1789529057; bh=anHWsZmc/HioyP1vEPDMn744EpmT5YgretWwLYFhp2M=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=ISnU2Akr2esuTs843s9S13XzSsk4YaWs6YBqYUmMJtucPOdXZI/xAYQAKoDec1BX4 yV+BXNwDvhkvnFpKxs9lHvDoxg93AVXoipPc5ePJYcc9unEUKWnS/dSTmXkhHpbu+R 18cD7uVrulfKDdN3aa8UiOWvzxjDXM3NzUiUIjd/kiDKFklEOjrJEKyup1asOvOZol YQZus2b01NAnV18fFAovIRySWmadmJsACT07e0X3OGJ8+zAyhv/D+Y88pNYphebsPh LzKMtIhHfPGTIgZXlox7CWMdPoA5UzA172Nno/KGFp1CDV0Ik2u3oRFfsoPoqYA6vJ TK7ndkV1wDAxA== Received: by bkemail.birger-koblitz.de (Postfix, from userid 109) id 50FC63FA82; Wed, 16 Sep 2026 03:24:17 +0000 (UTC) X-Spam-Level: DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=birger-koblitz.de; s=default; t=1789529056; bh=anHWsZmc/HioyP1vEPDMn744EpmT5YgretWwLYFhp2M=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=jHrNV/uqut1qvRxdcb7Pj+PdryAqAmufiONqtwCM/WzcNvA/uCIiIGDavfAyuajfL NCPmbwkrXJOiKNgamERVvYQAasfMgSNFU9no3YCmfv0ixQvwJYOAz9SrJQ8H34qFdX VvmXdKruy1f+Pb4ZLCOaPfo7teJd+A3/Hcn77x5eufP7/CWzq7RxTPxZcOX9Noe+DF aEnDOGqIq9qdSgWXZVVhpATKtzuD5A056CwA76cTszYqv0D9RUQmHlApGtjLjh/41b ZplFFyv9nRxSR+pFM9RA1/qwJWFv/Yu/9djMNm9TndocCjiHvJet2T1mvD0XqGAGHp XkrTTng9VSKMw== Received: from DELLLaptop.net (unknown [223.86.26.228]) by bkemail.birger-koblitz.de (Postfix) with ESMTPSA id 807033FA6C; Wed, 16 Sep 2026 03:24:11 +0000 (UTC) From: Birger Koblitz Date: Wed, 16 Sep 2026 05:24:00 +0200 Subject: [PATCH net-next v12 01/15] phylink: Add phylink_mac_interrupt Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260916-ax88179a-v12-1-60c04c9924a2@birger-koblitz.de> References: <20260916-ax88179a-v12-0-60c04c9924a2@birger-koblitz.de> In-Reply-To: <20260916-ax88179a-v12-0-60c04c9924a2@birger-koblitz.de> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Russell King , Andrew Lunn , Heiner Kallweit Cc: linux-usb@vger.kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Birger Koblitz , Jianhui Xu , Nicolai Buchwitz X-Mailer: b4 0.14.2 Add the phylink_mac_interrupt() function to phylink, which passes a link-change interrupt received by the MAC to phylib. This function can be used by drivers which want to avoid polling the PHY and instead rely on an interrupt received by the MAC when a link-change happens. Signed-off-by: Birger Koblitz Reviewed-by: Andrew Lunn Reviewed-by: Nicolai Buchwitz Tested-by: Jianhui Xu --- drivers/net/phy/phylink.c | 16 ++++++++++++++++ include/linux/phylink.h | 1 + 2 files changed, 17 insertions(+) diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index 3ec3bb43910953f3d57a4601633d0c3be65e959d..96ed13458e9f399fa911a145613= d213b1c4433c8 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -1612,6 +1612,22 @@ static bool phylink_link_is_up(struct phylink *pl) return pl->netdev ? netif_carrier_ok(pl->netdev) : pl->old_link_state; } =20 +/** + * phylink_mac_interrupt() - wrapper for phy_mac_interrupt() + * @pl: a pointer to a &struct phylink returned from phylink_create() + * + * Passes a link-change interrupt received by the MAC to phylib. + */ +void phylink_mac_interrupt(struct phylink *pl) +{ + struct phy_device *phy; + + phy =3D pl->phydev; + if (phy) + phy_mac_interrupt(phy); +} +EXPORT_SYMBOL_GPL(phylink_mac_interrupt); + static void phylink_resolve(struct work_struct *w) { struct phylink *pl =3D container_of(w, struct phylink, resolve); diff --git a/include/linux/phylink.h b/include/linux/phylink.h index 1dda5c7ed5f146930d1acc6f06072e6755167af6..f6c1db837fb5062c6d42ffc6489= ec06ae84e535b 100644 --- a/include/linux/phylink.h +++ b/include/linux/phylink.h @@ -768,6 +768,7 @@ int phylink_ethtool_set_eee(struct phylink *link, struc= t ethtool_keee *eee); int phylink_mii_ioctl(struct phylink *, struct ifreq *, int); int phylink_speed_down(struct phylink *pl, bool sync); int phylink_speed_up(struct phylink *pl); +void phylink_mac_interrupt(struct phylink *pl); =20 #define phylink_zero(bm) \ bitmap_zero(bm, __ETHTOOL_LINK_MODE_MASK_NBITS) --=20 2.47.3 From nobody Fri Sep 25 06:47:57 2026 Received: from bkemail.birger-koblitz.de (bkemail.birger-koblitz.de [23.88.97.239]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2661A9460; Wed, 16 Sep 2026 03:24:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=23.88.97.239 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789529065; cv=none; b=df/obYXP96O2FsmiYQVmiv/SO6GkxWsG1oIRnuHxG14c94qGnJHzCATnzJidEBa3b9bV4B5jD1o3xgrGHVBq5p9gyeAqzZXD54H3xAcZIkyZC2OXyngLe9PE27m5iPQpVvilUr4LaqbgCrUD9GRVa9PnlOOpFes4PEUkIertrAQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789529065; c=relaxed/simple; bh=IW0//u1gpMevyolcBWeSbUdau23fguyuh11+5qqrMgQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=km1vX/lY5Kg318q/6+s2QeoqwOrxBim28k/fvRPpL8JD9hko+vr/6MPY7sQOdF89NoHQhzaotA1wkiRrpDtIRGoP08dB9XdAPc8P/2nsrXAlfZEHzlisWc/yLPbD0ACqmZ1IVCqkBB8NEBV0RxU4D951UNlwxAgtEVEDhMCXmbc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=birger-koblitz.de; spf=pass smtp.mailfrom=birger-koblitz.de; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b=sVE7EjgR; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b=vZLSQTmL; arc=none smtp.client-ip=23.88.97.239 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=birger-koblitz.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=birger-koblitz.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b="sVE7EjgR"; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b="vZLSQTmL" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=birger-koblitz.de; s=default; t=1789529062; bh=IW0//u1gpMevyolcBWeSbUdau23fguyuh11+5qqrMgQ=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=sVE7EjgR9c2h30F/rd8wXve0hkSKVqP71MWYHzhUWYaqNiDftiu8ls+wpXz0JYsJU LZZsZbFGjURphbYcmvY2PxcsVM5E0g+9smf/YWXEFDICe3P5SROMj1OIEuIrqKoTSh veRxSrEm+0DIoEHoSvvyWVvZ4HL+92oVjGiwYN39W3glJIT49Q5bnxIxXTvG7G6gyb QI3OtSn14lZv0UAtizV28s82fITXXRfhflQ1cLx0kteEh77OwiIUtCkAXzbO697HoI 2lO8RYViDj1G7DANPrCWqS6+6CNDxYbdAKWJmrOh4OCJF20fUELpSZjOkqp3NdOktl ZXm1C+7+yp13Q== Received: by bkemail.birger-koblitz.de (Postfix, from userid 109) id 7DB7E3FA7C; Wed, 16 Sep 2026 03:24:22 +0000 (UTC) X-Spam-Level: DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=birger-koblitz.de; s=default; t=1789529061; bh=IW0//u1gpMevyolcBWeSbUdau23fguyuh11+5qqrMgQ=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=vZLSQTmLcfbcA7X9FYqr/tQ2ss4tqvDm9rUcONCVNw1UQr9HkmqPWbHaD25GRUti7 I1NniDwqOKu51LTIjfO/fw3qFrKGYMKItj/MqloKg+4HLyRbJpJ7lBagg5sEu4mSG/ Tkhfmyrs2diBaL3JlSXFLKvxvVc21OMLfwVAJVTIMDKEr1Zakneu4mN3frmP/gHO04 NwmGqDVM9AjjjmWWsiu6TMACVOfSQvH9+Lp1eZPQa01WEE0RIVb6hR5CHqMb4h2ry1 2iy7ruwRPYsVr9sBAeHSsC3xwu5aso9P5+Rz/GWvObI/iE+HmbGiu9Rh8KHpIuM1aK 08k8whL3Pgb5Q== Received: from DELLLaptop.net (unknown [223.86.26.228]) by bkemail.birger-koblitz.de (Postfix) with ESMTPSA id 415893FA72; Wed, 16 Sep 2026 03:24:16 +0000 (UTC) From: Birger Koblitz Date: Wed, 16 Sep 2026 05:24:01 +0200 Subject: [PATCH net-next v12 02/15] phylib: Add support for PHYs with broken forced mode Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260916-ax88179a-v12-2-60c04c9924a2@birger-koblitz.de> References: <20260916-ax88179a-v12-0-60c04c9924a2@birger-koblitz.de> In-Reply-To: <20260916-ax88179a-v12-0-60c04c9924a2@birger-koblitz.de> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Russell King , Andrew Lunn , Heiner Kallweit Cc: linux-usb@vger.kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Birger Koblitz , Jianhui Xu , Nicolai Buchwitz X-Mailer: b4 0.14.2 Add support for PHYs which only supported auto-negotiated speed modes. This prevents a kernel warning and stack-trace within the phy_state_machine when PHYs return -EOPNOTSUPP from config_aneg() because they do not support forced modes. Signed-off-by: Birger Koblitz Reviewed-by: Andrew Lunn Reviewed-by: Nicolai Buchwitz Tested-by: Jianhui Xu --- drivers/net/phy/phy.c | 4 ++++ include/linux/phy.h | 1 + 2 files changed, 5 insertions(+) diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index fce9bc7be3304b408c9f3ec9b5b95c76d3680a88..b83f938fe7c3bd619ae453434fd= 9582c0a055a57 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -1190,6 +1190,10 @@ int phy_ethtool_ksettings_set(struct phy_device *phy= dev, duplex !=3D DUPLEX_FULL))) return -EINVAL; =20 + if (autoneg =3D=3D AUTONEG_DISABLE && + (phydev->drv->flags & PHY_BROKEN_FORCED)) + return -EOPNOTSUPP; + mutex_lock(&phydev->lock); phydev->autoneg =3D autoneg; =20 diff --git a/include/linux/phy.h b/include/linux/phy.h index 5f8d65868e0ff558c163421cfea5a6f3bd73a53e..d5f8e527ce8dfefd40a8b34e7c2= f9adbcd6c87c1 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -64,6 +64,7 @@ extern const int phy_basic_ports_array[3]; #define PHY_RST_AFTER_CLK_EN 0x00000002 #define PHY_POLL_CABLE_TEST 0x00000004 #define PHY_ALWAYS_CALL_SUSPEND 0x00000008 +#define PHY_BROKEN_FORCED 0x00000010 #define MDIO_DEVICE_IS_PHY 0x80000000 =20 /** --=20 2.47.3 From nobody Fri Sep 25 06:47:57 2026 Received: from bkemail.birger-koblitz.de (bkemail.birger-koblitz.de [23.88.97.239]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0E85322FDE6; Wed, 16 Sep 2026 03:24:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=23.88.97.239 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789529072; cv=none; b=pdqoBjCu19KOtRoinWPD17fBBhUlNsTp9csKtmSUgetgWUJ7ummPWMJAAA2up7rUES9x4eWPtPy+UAoQviZA3STKGfhQ7Qi3ANQegMbysMb5l1f4ktTPO5MffeDNvSio7sgHg2YBP7Lu+573A2oWz69DtLYViyQvw3kOndfQfPM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789529072; c=relaxed/simple; bh=UcT1TW4Sdw6h/EHK92PDO/srxgGudwpIfaE1pzE+OMg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Oaeq1pZoO+u+ApiQ4NrOmIY/uAa2iFjbqzkuaeG8foPU7YDnL+6wltg3/vdlJB158wpIplGQ24KXLyi8hlUVHhxp9ucrn9TXdd2ByJdHrC/yxTgujM75gTC5n8SO22Q5ia0GHmIh22o9siB47QgjRJKq+OHk//y3B3Rrje2M9HU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=birger-koblitz.de; spf=pass smtp.mailfrom=birger-koblitz.de; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b=d9hGxStL; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b=T/8f0C+F; arc=none smtp.client-ip=23.88.97.239 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=birger-koblitz.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=birger-koblitz.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b="d9hGxStL"; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b="T/8f0C+F" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=birger-koblitz.de; s=default; t=1789529067; bh=UcT1TW4Sdw6h/EHK92PDO/srxgGudwpIfaE1pzE+OMg=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=d9hGxStLOX/tgzu3stA80+Y6M7OYSRMRT7ZzzFctaXF2NV6Avery05OHqykF2Da+a ZP0hT8t6ftO36gDu35nMeFm3Z/VnHtU1Cgdg6rqm7wBoHOGwng3tMm4YSH4+Q9dmSl 0IerrqNv3TJ34o8MnIG5Qqs8stX4xaeGixkK3ofKiI2SbjfgdwHI7YgV0JgcmCFjkE xVnc5ckTkswxpk/wVHDNkbPPfMBIeUn+hmzN64DY5xdY20GIAPI7cO9E6P+zCVRqKA 5wk8bQQZmfPVi4PfaioYtMg/OKTkkJphbVrnal2yBALlbmLUOHyE0llzYpZIQPK3eS vA+bAb0LUHBDg== Received: by bkemail.birger-koblitz.de (Postfix, from userid 109) id 36B013FA6F; Wed, 16 Sep 2026 03:24:27 +0000 (UTC) X-Spam-Level: DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=birger-koblitz.de; s=default; t=1789529066; bh=UcT1TW4Sdw6h/EHK92PDO/srxgGudwpIfaE1pzE+OMg=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=T/8f0C+FP9a3eZ6DMj5QxDRNyoFm2Himtx+wr7CDNrbq57SXToudsZGdGpsvJyQch /x7sPtrb69UV+oz+P3shL4b2e3OVmYIIF+IlcdhzYWSDj4pYmxNzMA3n1CGSUVNhax /Rxjvdu20LFn8hO9pqjNVlFFItH50loBVZL76EFJzg94p7j2Uq3WgkVQWX5FR50/6y BB+Z4ZJmSnUuRWASihKMTPat9ds3ECj1DvwDGZlUhxSEpClRlsH+BbsKmr0gK4dJmz a18AeSHxvsUcCm9b1JJXST7oKUVHzf12oiLMV0+kTxlgdu7lm1YBdqgC3R7mftf3RD eiGJviKW3nNug== Received: from DELLLaptop.net (unknown [223.86.26.228]) by bkemail.birger-koblitz.de (Postfix) with ESMTPSA id 8197A3FA75; Wed, 16 Sep 2026 03:24:21 +0000 (UTC) From: Birger Koblitz Date: Wed, 16 Sep 2026 05:24:02 +0200 Subject: [PATCH net-next v12 03/15] ax88179_178a: Fix endianness of pause watermark register Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260916-ax88179a-v12-3-60c04c9924a2@birger-koblitz.de> References: <20260916-ax88179a-v12-0-60c04c9924a2@birger-koblitz.de> In-Reply-To: <20260916-ax88179a-v12-0-60c04c9924a2@birger-koblitz.de> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Russell King , Andrew Lunn , Heiner Kallweit Cc: linux-usb@vger.kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Birger Koblitz , Jianhui Xu X-Mailer: b4 0.14.2 The 16-bit pause watermark register is little endian as described in the ASIX 4.1.0 out-of-tree driver. Correct the register byte sequence but also swap the configuration values used in the code in order to keep the current behaviour. The endianness is relevant for 16-bit writes to the register. Signed-off-by: Birger Koblitz Reviewed-by: Andrew Lunn Tested-by: Jianhui Xu --- drivers/net/usb/ax88179_178a.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c index 81d8412ce8e2fac981df076ea1385e6e87525cfe..2ed46ab62c0065d32040439f31d= 44f118d7e9952 100644 --- a/drivers/net/usb/ax88179_178a.c +++ b/drivers/net/usb/ax88179_178a.c @@ -32,8 +32,8 @@ #define AX_ACCESS_EEPROM 0x04 #define AX_ACCESS_EFUS 0x05 #define AX_RELOAD_EEPROM_EFUSE 0x06 -#define AX_PAUSE_WATERLVL_HIGH 0x54 -#define AX_PAUSE_WATERLVL_LOW 0x55 +#define AX_PAUSE_WATERLVL_LOW 0x54 +#define AX_PAUSE_WATERLVL_HIGH 0x55 =20 #define PHYSICAL_LINK_STATUS 0x02 #define AX_USB_SS 0x04 @@ -1619,11 +1619,10 @@ static int ax88179_reset(struct usbnet *dev) dev->rx_urb_size =3D 1024 * 20; =20 *tmp =3D 0x34; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PAUSE_WATERLVL_LOW, 1, 1, tmp); + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PAUSE_WATERLVL_HIGH, 1, 1, tmp); =20 *tmp =3D 0x52; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PAUSE_WATERLVL_HIGH, - 1, 1, tmp); + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PAUSE_WATERLVL_LOW, 1, 1, tmp); =20 /* Enable checksum offload */ *tmp =3D AX_RXCOE_IP | AX_RXCOE_TCP | AX_RXCOE_UDP | --=20 2.47.3 From nobody Fri Sep 25 06:47:57 2026 Received: from bkemail.birger-koblitz.de (bkemail.birger-koblitz.de [23.88.97.239]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B77A237B3F9; Wed, 16 Sep 2026 03:24:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=23.88.97.239 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789529081; cv=none; b=So9isv6aaGCAXprkckzIj1/PnF6RnY1BpmTPKRVaR5KGFGE6JU63udl5Yy4SVGxqI/hO5dPUgNhaXYwPorD4KF+ivmRpnEUCirjKs0uvGkk0HBCx4iej0oFVEXXSKjuvTLLoKkBw2KIhqYrLMYkJ3Cb7EHcLQK+uFcTTu4uXDGM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789529081; c=relaxed/simple; bh=0iOQc5CXiztGz6daN9OBxQVLT9RpuRHSS0E/+LjxRVw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=bXG13PirTlmoqpucxDBxGY3PtO9SSQto8Dhn+wJjQ6/3i2Bk/moJ7gmbdK6Ye+4HT5h9yDZm2U/SyhrTZlnZNjvfB9EgOKFSEUXt+bG7Yg9b3jr9ZzT0YqUBdsBHEMrphffp0SB+j1aVikMrCYLhQtt2swsSGbKO2A62wmFOTg8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=birger-koblitz.de; spf=pass smtp.mailfrom=birger-koblitz.de; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b=SGv0ls7e; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b=LV8THFnC; arc=none smtp.client-ip=23.88.97.239 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=birger-koblitz.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=birger-koblitz.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b="SGv0ls7e"; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b="LV8THFnC" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=birger-koblitz.de; s=default; t=1789529076; bh=0iOQc5CXiztGz6daN9OBxQVLT9RpuRHSS0E/+LjxRVw=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=SGv0ls7etiiCmVTzhKVp9Kf66hdi+HkpnBej3HQSFhUd+ZjKRTC/pdJUikE2sV+fP whXAMXreL+nXDWQPOeyiN/VPrDnKzgQS9Vsth9AoUuIRiaIs31arzPrfJO02MWkErb zTa2y8Q85rpBho/tVZVOVLlBF5i+74LnAwgWDR2e3HWfFpGI3YIxwOYC2XfeUrqiKX 1q75sEVw0MaQFiaaNvlalPNFaldTrHS7gD1BET+K7dXrjUhYZU7sQ7pw9FUf5z9eua Gduv7NjM/iO4k4y1KCbe+BaHWgFYEI3MB1XynxnYQ4UmOj1dKb2rUCm5dEwAh+8ihN u3p/bWdLd1mJg== Received: by bkemail.birger-koblitz.de (Postfix, from userid 109) id 0CF8C3FA6D; Wed, 16 Sep 2026 03:24:36 +0000 (UTC) X-Spam-Level: DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=birger-koblitz.de; s=default; t=1789529071; bh=0iOQc5CXiztGz6daN9OBxQVLT9RpuRHSS0E/+LjxRVw=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=LV8THFnCEQZ3emB+9ZHtY1JyeSKFPLalHvc1/9nDWaIEhvuK174bESoatcpCuwI5d U6daY7cAy9Trsns6Cvj+//aLUyFDYsth4nI75zMG0UKb6n6cTCQ7Rv5+UR4WLL90BE 1yhsWRbXoNMnWPSV4E/WFG52PXRV7kJbXBsX4tUp1XoRFDe/e5wLG9F0vaBNHMc37e nTswLhi1J/hjYcU4fb7YjLfmfHal3aLLxb2tdJbDfUsskuqCVBku1ku/2nav20tupe dVHkyVACo9+sredZNWaIp/av9L2vpeI4gWAoK72aMe4q5rMRoUDtUd7TjmcxxELnQM LBGxb3RgI2csQ== Received: from DELLLaptop.net (unknown [223.86.26.228]) by bkemail.birger-koblitz.de (Postfix) with ESMTPSA id 370013FA72; Wed, 16 Sep 2026 03:24:26 +0000 (UTC) From: Birger Koblitz Date: Wed, 16 Sep 2026 05:24:03 +0200 Subject: [PATCH net-next v12 04/15] ax88179_178a: Split driver into library and device specific code Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260916-ax88179a-v12-4-60c04c9924a2@birger-koblitz.de> References: <20260916-ax88179a-v12-0-60c04c9924a2@birger-koblitz.de> In-Reply-To: <20260916-ax88179a-v12-0-60c04c9924a2@birger-koblitz.de> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Russell King , Andrew Lunn , Heiner Kallweit Cc: linux-usb@vger.kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Birger Koblitz , Jianhui Xu , Nicolai Buchwitz X-Mailer: b4 0.14.2 Split the ax88179_178a module code into code common to the AX88179/178a/179a and 279 family of controllers and device specific code for the currently supported devices based on the AX88179 and AX88178a. Rename the module to ax88179 to reflect the broader scope of controllers supported by the module. Signed-off-by: Birger Koblitz Reviewed-by: Andrew Lunn Reviewed-by: Nicolai Buchwitz Tested-by: Jianhui Xu --- drivers/net/usb/Makefile | 3 +- drivers/net/usb/ax88179_178a.c | 611 +------------------------------------= ---- drivers/net/usb/ax88179_lib.c | 444 ++++++++++++++++++++++++++++++ drivers/net/usb/ax88179_lib.h | 194 +++++++++++++ 4 files changed, 641 insertions(+), 611 deletions(-) diff --git a/drivers/net/usb/Makefile b/drivers/net/usb/Makefile index 4964f7b326fbcedffc1e5a1bf004aea95560db8c..ddd76fa71e2ee670888df1c9715= 632e5c04a8149 100644 --- a/drivers/net/usb/Makefile +++ b/drivers/net/usb/Makefile @@ -12,7 +12,8 @@ obj-$(CONFIG_USB_HSO) +=3D hso.o obj-$(CONFIG_USB_LAN78XX) +=3D lan78xx.o obj-$(CONFIG_USB_NET_AX8817X) +=3D asix.o asix-y :=3D asix_devices.o asix_common.o ax88172a.o -obj-$(CONFIG_USB_NET_AX88179_178A) +=3D ax88179_178a.o +obj-$(CONFIG_USB_NET_AX88179_178A) +=3D ax88179.o +ax88179-y :=3D ax88179_178a.o ax88179_lib.o obj-$(CONFIG_USB_NET_CDCETHER) +=3D cdc_ether.o obj-$(CONFIG_USB_NET_CDC_EEM) +=3D cdc_eem.o obj-$(CONFIG_USB_NET_DM9601) +=3D dm9601.o diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c index 2ed46ab62c0065d32040439f31d44f118d7e9952..6aa35c8eb594fda38f7680f8801= f0d82090c1efd 100644 --- a/drivers/net/usb/ax88179_178a.c +++ b/drivers/net/usb/ax88179_178a.c @@ -8,179 +8,12 @@ #include #include #include -#include -#include -#include #include #include - -#define AX88179_PHY_ID 0x03 -#define AX_EEPROM_LEN 0x100 -#define AX88179_EEPROM_MAGIC 0x17900b95 -#define AX_MCAST_FLTSIZE 8 -#define AX_MAX_MCAST 64 -#define AX_INT_PPLS_LINK ((u32)BIT(16)) -#define AX_RXHDR_L4_TYPE_MASK 0x1c -#define AX_RXHDR_L4_TYPE_UDP 4 -#define AX_RXHDR_L4_TYPE_TCP 16 -#define AX_RXHDR_L3CSUM_ERR 2 -#define AX_RXHDR_L4CSUM_ERR 1 -#define AX_RXHDR_CRC_ERR ((u32)BIT(29)) -#define AX_RXHDR_DROP_ERR ((u32)BIT(31)) -#define AX_ACCESS_MAC 0x01 -#define AX_ACCESS_PHY 0x02 -#define AX_ACCESS_EEPROM 0x04 -#define AX_ACCESS_EFUS 0x05 -#define AX_RELOAD_EEPROM_EFUSE 0x06 -#define AX_PAUSE_WATERLVL_LOW 0x54 -#define AX_PAUSE_WATERLVL_HIGH 0x55 - -#define PHYSICAL_LINK_STATUS 0x02 - #define AX_USB_SS 0x04 - #define AX_USB_HS 0x02 - -#define GENERAL_STATUS 0x03 -/* Check AX88179 version. UA1:Bit2 =3D 0, UA2:Bit2 =3D 1 */ - #define AX_SECLD 0x04 - -#define AX_SROM_ADDR 0x07 -#define AX_SROM_CMD 0x0a - #define EEP_RD 0x04 - #define EEP_BUSY 0x10 - -#define AX_SROM_DATA_LOW 0x08 -#define AX_SROM_DATA_HIGH 0x09 - -#define AX_RX_CTL 0x0b - #define AX_RX_CTL_DROPCRCERR 0x0100 - #define AX_RX_CTL_IPE 0x0200 - #define AX_RX_CTL_START 0x0080 - #define AX_RX_CTL_AP 0x0020 - #define AX_RX_CTL_AM 0x0010 - #define AX_RX_CTL_AB 0x0008 - #define AX_RX_CTL_AMALL 0x0002 - #define AX_RX_CTL_PRO 0x0001 - #define AX_RX_CTL_STOP 0x0000 - -#define AX_NODE_ID 0x10 -#define AX_MULFLTARY 0x16 - -#define AX_MEDIUM_STATUS_MODE 0x22 - #define AX_MEDIUM_GIGAMODE 0x01 - #define AX_MEDIUM_FULL_DUPLEX 0x02 - #define AX_MEDIUM_EN_125MHZ 0x08 - #define AX_MEDIUM_RXFLOW_CTRLEN 0x10 - #define AX_MEDIUM_TXFLOW_CTRLEN 0x20 - #define AX_MEDIUM_RECEIVE_EN 0x100 - #define AX_MEDIUM_PS 0x200 - #define AX_MEDIUM_JUMBO_EN 0x8040 - -#define AX_MONITOR_MOD 0x24 - #define AX_MONITOR_MODE_RWLC 0x02 - #define AX_MONITOR_MODE_RWMP 0x04 - #define AX_MONITOR_MODE_PMEPOL 0x20 - #define AX_MONITOR_MODE_PMETYPE 0x40 - -#define AX_GPIO_CTRL 0x25 - #define AX_GPIO_CTRL_GPIO3EN 0x80 - #define AX_GPIO_CTRL_GPIO2EN 0x40 - #define AX_GPIO_CTRL_GPIO1EN 0x20 - -#define AX_PHYPWR_RSTCTL 0x26 - #define AX_PHYPWR_RSTCTL_BZ 0x0010 - #define AX_PHYPWR_RSTCTL_IPRL 0x0020 - #define AX_PHYPWR_RSTCTL_AT 0x1000 - -#define AX_RX_BULKIN_QCTRL 0x2e -#define AX_CLK_SELECT 0x33 - #define AX_CLK_SELECT_BCS 0x01 - #define AX_CLK_SELECT_ACS 0x02 - #define AX_CLK_SELECT_ULR 0x08 - -#define AX_RXCOE_CTL 0x34 - #define AX_RXCOE_IP 0x01 - #define AX_RXCOE_TCP 0x02 - #define AX_RXCOE_UDP 0x04 - #define AX_RXCOE_TCPV6 0x20 - #define AX_RXCOE_UDPV6 0x40 - -#define AX_TXCOE_CTL 0x35 - #define AX_TXCOE_IP 0x01 - #define AX_TXCOE_TCP 0x02 - #define AX_TXCOE_UDP 0x04 - #define AX_TXCOE_TCPV6 0x20 - #define AX_TXCOE_UDPV6 0x40 - -#define AX_LEDCTRL 0x73 - -#define GMII_PHY_PHYSR 0x11 - #define GMII_PHY_PHYSR_SMASK 0xc000 - #define GMII_PHY_PHYSR_GIGA 0x8000 - #define GMII_PHY_PHYSR_100 0x4000 - #define GMII_PHY_PHYSR_FULL 0x2000 - #define GMII_PHY_PHYSR_LINK 0x400 - -#define GMII_LED_ACT 0x1a - #define GMII_LED_ACTIVE_MASK 0xff8f - #define GMII_LED0_ACTIVE BIT(4) - #define GMII_LED1_ACTIVE BIT(5) - #define GMII_LED2_ACTIVE BIT(6) - -#define GMII_LED_LINK 0x1c - #define GMII_LED_LINK_MASK 0xf888 - #define GMII_LED0_LINK_10 BIT(0) - #define GMII_LED0_LINK_100 BIT(1) - #define GMII_LED0_LINK_1000 BIT(2) - #define GMII_LED1_LINK_10 BIT(4) - #define GMII_LED1_LINK_100 BIT(5) - #define GMII_LED1_LINK_1000 BIT(6) - #define GMII_LED2_LINK_10 BIT(8) - #define GMII_LED2_LINK_100 BIT(9) - #define GMII_LED2_LINK_1000 BIT(10) - #define LED0_ACTIVE BIT(0) - #define LED0_LINK_10 BIT(1) - #define LED0_LINK_100 BIT(2) - #define LED0_LINK_1000 BIT(3) - #define LED0_FD BIT(4) - #define LED0_USB3_MASK 0x001f - #define LED1_ACTIVE BIT(5) - #define LED1_LINK_10 BIT(6) - #define LED1_LINK_100 BIT(7) - #define LED1_LINK_1000 BIT(8) - #define LED1_FD BIT(9) - #define LED1_USB3_MASK 0x03e0 - #define LED2_ACTIVE BIT(10) - #define LED2_LINK_1000 BIT(13) - #define LED2_LINK_100 BIT(12) - #define LED2_LINK_10 BIT(11) - #define LED2_FD BIT(14) - #define LED_VALID BIT(15) - #define LED2_USB3_MASK 0x7c00 - -#define GMII_PHYPAGE 0x1e -#define GMII_PHY_PAGE_SELECT 0x1f - #define GMII_PHY_PGSEL_EXT 0x0007 - #define GMII_PHY_PGSEL_PAGE0 0x0000 - #define GMII_PHY_PGSEL_PAGE3 0x0003 - #define GMII_PHY_PGSEL_PAGE5 0x0005 +#include "ax88179_lib.h" =20 static int ax88179_reset(struct usbnet *dev); =20 -struct ax88179_data { - u8 eee_enabled; - u8 eee_active; - u16 rxctl; - u8 in_pm; - u32 wol_supported; - u32 wolopts; - u8 disconnecting; -}; - -struct ax88179_int_data { - __le32 intdata1; - __le32 intdata2; -}; - static const struct { unsigned char ctrl, timer_l, timer_h, size, ifg; } AX88179_BULKIN_SIZE[] =3D { @@ -190,165 +23,6 @@ static const struct { {7, 0xcc, 0x4c, 0x18, 8}, }; =20 -static void ax88179_set_pm_mode(struct usbnet *dev, bool pm_mode) -{ - struct ax88179_data *ax179_data =3D dev->driver_priv; - - ax179_data->in_pm =3D pm_mode; -} - -static int ax88179_in_pm(struct usbnet *dev) -{ - struct ax88179_data *ax179_data =3D dev->driver_priv; - - return ax179_data->in_pm; -} - -static int __ax88179_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 i= ndex, - u16 size, void *data) -{ - int ret; - int (*fn)(struct usbnet *, u8, u8, u16, u16, void *, u16); - struct ax88179_data *ax179_data =3D dev->driver_priv; - - BUG_ON(!dev); - - if (!ax88179_in_pm(dev)) - fn =3D usbnet_read_cmd; - else - fn =3D usbnet_read_cmd_nopm; - - ret =3D fn(dev, cmd, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, index, data, size); - - if (unlikely((ret < 0) && !(ret =3D=3D -ENODEV && ax179_data->disconnecti= ng))) - netdev_warn(dev->net, "Failed to read reg index 0x%04x: %d\n", - index, ret); - - return ret; -} - -static int __ax88179_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 = index, - u16 size, const void *data) -{ - int ret; - int (*fn)(struct usbnet *, u8, u8, u16, u16, const void *, u16); - struct ax88179_data *ax179_data =3D dev->driver_priv; - - BUG_ON(!dev); - - if (!ax88179_in_pm(dev)) - fn =3D usbnet_write_cmd; - else - fn =3D usbnet_write_cmd_nopm; - - ret =3D fn(dev, cmd, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, index, data, size); - - if (unlikely((ret < 0) && !(ret =3D=3D -ENODEV && ax179_data->disconnecti= ng))) - netdev_warn(dev->net, "Failed to write reg index 0x%04x: %d\n", - index, ret); - - return ret; -} - -static void ax88179_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, - u16 index, u16 size, void *data) -{ - u16 buf; - - if (2 =3D=3D size) { - buf =3D *((u16 *)data); - cpu_to_le16s(&buf); - usbnet_write_cmd_async(dev, cmd, USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_DEVICE, value, index, &buf, - size); - } else { - usbnet_write_cmd_async(dev, cmd, USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_DEVICE, value, index, data, - size); - } -} - -static int ax88179_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 ind= ex, - u16 size, void *data) -{ - int ret; - - if (2 =3D=3D size) { - u16 buf =3D 0; - ret =3D __ax88179_read_cmd(dev, cmd, value, index, size, &buf); - le16_to_cpus(&buf); - *((u16 *)data) =3D buf; - } else if (4 =3D=3D size) { - u32 buf =3D 0; - ret =3D __ax88179_read_cmd(dev, cmd, value, index, size, &buf); - le32_to_cpus(&buf); - *((u32 *)data) =3D buf; - } else { - ret =3D __ax88179_read_cmd(dev, cmd, value, index, size, data); - } - - return ret; -} - -static int ax88179_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 in= dex, - u16 size, const void *data) -{ - int ret; - - if (2 =3D=3D size) { - u16 buf; - buf =3D *((u16 *)data); - cpu_to_le16s(&buf); - ret =3D __ax88179_write_cmd(dev, cmd, value, index, - size, &buf); - } else { - ret =3D __ax88179_write_cmd(dev, cmd, value, index, - size, data); - } - - return ret; -} - -static void ax88179_status(struct usbnet *dev, struct urb *urb) -{ - struct ax88179_int_data *event; - u32 link; - - if (urb->actual_length < 8) - return; - - event =3D urb->transfer_buffer; - le32_to_cpus((void *)&event->intdata1); - - link =3D (((__force u32)event->intdata1) & AX_INT_PPLS_LINK) >> 16; - - if (netif_carrier_ok(dev->net) !=3D link) { - usbnet_link_change(dev, link, 1); - if (!link) - netdev_info(dev->net, "ax88179 - Link status is: 0\n"); - } -} - -static int ax88179_mdio_read(struct net_device *netdev, int phy_id, int lo= c) -{ - struct usbnet *dev =3D netdev_priv(netdev); - u16 res; - - ax88179_read_cmd(dev, AX_ACCESS_PHY, phy_id, (__u16)loc, 2, &res); - return res; -} - -static void ax88179_mdio_write(struct net_device *netdev, int phy_id, int = loc, - int val) -{ - struct usbnet *dev =3D netdev_priv(netdev); - u16 res =3D (u16) val; - - ax88179_write_cmd(dev, AX_ACCESS_PHY, phy_id, (__u16)loc, 2, &res); -} - static inline int ax88179_phy_mmd_indirect(struct usbnet *dev, u16 prtad, u16 devad) { @@ -510,146 +184,11 @@ static void ax88179_disconnect(struct usb_interface = *intf) usbnet_disconnect(intf); } =20 -static void -ax88179_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo) -{ - struct usbnet *dev =3D netdev_priv(net); - struct ax88179_data *priv =3D dev->driver_priv; - - wolinfo->supported =3D priv->wol_supported; - wolinfo->wolopts =3D priv->wolopts; -} - -static int -ax88179_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo) -{ - struct usbnet *dev =3D netdev_priv(net); - struct ax88179_data *priv =3D dev->driver_priv; - - if (wolinfo->wolopts & ~(priv->wol_supported)) - return -EINVAL; - - priv->wolopts =3D wolinfo->wolopts; - - return 0; -} - static int ax88179_get_eeprom_len(struct net_device *net) { return AX_EEPROM_LEN; } =20 -static int -ax88179_get_eeprom(struct net_device *net, struct ethtool_eeprom *eeprom, - u8 *data) -{ - struct usbnet *dev =3D netdev_priv(net); - u16 *eeprom_buff; - int first_word, last_word; - int i, ret; - - if (eeprom->len =3D=3D 0) - return -EINVAL; - - eeprom->magic =3D AX88179_EEPROM_MAGIC; - - first_word =3D eeprom->offset >> 1; - last_word =3D (eeprom->offset + eeprom->len - 1) >> 1; - eeprom_buff =3D kmalloc_array(last_word - first_word + 1, sizeof(u16), - GFP_KERNEL); - if (!eeprom_buff) - return -ENOMEM; - - /* ax88179/178A returns 2 bytes from eeprom on read */ - for (i =3D first_word; i <=3D last_word; i++) { - ret =3D __ax88179_read_cmd(dev, AX_ACCESS_EEPROM, i, 1, 2, - &eeprom_buff[i - first_word]); - if (ret < 0) { - kfree(eeprom_buff); - return -EIO; - } - } - - memcpy(data, (u8 *)eeprom_buff + (eeprom->offset & 1), eeprom->len); - kfree(eeprom_buff); - return 0; -} - -static int -ax88179_set_eeprom(struct net_device *net, struct ethtool_eeprom *eeprom, - u8 *data) -{ - struct usbnet *dev =3D netdev_priv(net); - u16 *eeprom_buff; - int first_word; - int last_word; - int ret; - int i; - - netdev_dbg(net, "write EEPROM len %d, offset %d, magic 0x%x\n", - eeprom->len, eeprom->offset, eeprom->magic); - - if (eeprom->len =3D=3D 0) - return -EINVAL; - - if (eeprom->magic !=3D AX88179_EEPROM_MAGIC) - return -EINVAL; - - first_word =3D eeprom->offset >> 1; - last_word =3D (eeprom->offset + eeprom->len - 1) >> 1; - - eeprom_buff =3D kmalloc_array(last_word - first_word + 1, sizeof(u16), - GFP_KERNEL); - if (!eeprom_buff) - return -ENOMEM; - - /* align data to 16 bit boundaries, read the missing data from - the EEPROM */ - if (eeprom->offset & 1) { - ret =3D ax88179_read_cmd(dev, AX_ACCESS_EEPROM, first_word, 1, 2, - &eeprom_buff[0]); - if (ret < 0) { - netdev_err(net, "Failed to read EEPROM at offset 0x%02x.\n", first_word= ); - goto free; - } - } - - if ((eeprom->offset + eeprom->len) & 1) { - ret =3D ax88179_read_cmd(dev, AX_ACCESS_EEPROM, last_word, 1, 2, - &eeprom_buff[last_word - first_word]); - if (ret < 0) { - netdev_err(net, "Failed to read EEPROM at offset 0x%02x.\n", last_word); - goto free; - } - } - - memcpy((u8 *)eeprom_buff + (eeprom->offset & 1), data, eeprom->len); - - for (i =3D first_word; i <=3D last_word; i++) { - netdev_dbg(net, "write to EEPROM at offset 0x%02x, data 0x%04x\n", - i, eeprom_buff[i - first_word]); - ret =3D ax88179_write_cmd(dev, AX_ACCESS_EEPROM, i, 1, 2, - &eeprom_buff[i - first_word]); - if (ret < 0) { - netdev_err(net, "Failed to write EEPROM at offset 0x%02x.\n", i); - goto free; - } - msleep(20); - } - - /* reload EEPROM data */ - ret =3D ax88179_write_cmd(dev, AX_RELOAD_EEPROM_EFUSE, 0x0000, 0, 0, NULL= ); - if (ret < 0) { - netdev_err(net, "Failed to reload EEPROM data\n"); - goto free; - } - - ret =3D 0; -free: - kfree(eeprom_buff); - return ret; -} - static int ax88179_get_link_ksettings(struct net_device *net, struct ethtool_link_ksettings *cmd) { @@ -864,125 +403,6 @@ static const struct ethtool_ops ax88179_ethtool_ops = =3D { .get_ts_info =3D ethtool_op_get_ts_info, }; =20 -static void ax88179_set_multicast(struct net_device *net) -{ - struct usbnet *dev =3D netdev_priv(net); - struct ax88179_data *data =3D dev->driver_priv; - u8 *m_filter =3D ((u8 *)dev->data); - - data->rxctl =3D (AX_RX_CTL_START | AX_RX_CTL_AB | AX_RX_CTL_IPE); - - if (net->flags & IFF_PROMISC) { - data->rxctl |=3D AX_RX_CTL_PRO; - } else if (net->flags & IFF_ALLMULTI || - netdev_mc_count(net) > AX_MAX_MCAST) { - data->rxctl |=3D AX_RX_CTL_AMALL; - } else if (netdev_mc_empty(net)) { - /* just broadcast and directed */ - } else { - /* We use dev->data for our 8 byte filter buffer - * to avoid allocating memory that is tricky to free later - */ - u32 crc_bits; - struct netdev_hw_addr *ha; - - memset(m_filter, 0, AX_MCAST_FLTSIZE); - - netdev_for_each_mc_addr(ha, net) { - crc_bits =3D ether_crc(ETH_ALEN, ha->addr) >> 26; - *(m_filter + (crc_bits >> 3)) |=3D (1 << (crc_bits & 7)); - } - - ax88179_write_cmd_async(dev, AX_ACCESS_MAC, AX_MULFLTARY, - AX_MCAST_FLTSIZE, AX_MCAST_FLTSIZE, - m_filter); - - data->rxctl |=3D AX_RX_CTL_AM; - } - - ax88179_write_cmd_async(dev, AX_ACCESS_MAC, AX_RX_CTL, - 2, 2, &data->rxctl); -} - -static int -ax88179_set_features(struct net_device *net, netdev_features_t features) -{ - u8 tmp; - struct usbnet *dev =3D netdev_priv(net); - netdev_features_t changed =3D net->features ^ features; - - if (changed & NETIF_F_IP_CSUM) { - ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, &tmp); - tmp ^=3D AX_TXCOE_TCP | AX_TXCOE_UDP; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, &tmp); - } - - if (changed & NETIF_F_IPV6_CSUM) { - ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, &tmp); - tmp ^=3D AX_TXCOE_TCPV6 | AX_TXCOE_UDPV6; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, &tmp); - } - - if (changed & NETIF_F_RXCSUM) { - ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_RXCOE_CTL, 1, 1, &tmp); - tmp ^=3D AX_RXCOE_IP | AX_RXCOE_TCP | AX_RXCOE_UDP | - AX_RXCOE_TCPV6 | AX_RXCOE_UDPV6; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RXCOE_CTL, 1, 1, &tmp); - } - - return 0; -} - -static int ax88179_change_mtu(struct net_device *net, int new_mtu) -{ - struct usbnet *dev =3D netdev_priv(net); - u16 tmp16; - - WRITE_ONCE(net->mtu, new_mtu); - dev->hard_mtu =3D net->mtu + net->hard_header_len; - - if (net->mtu > 1500) { - ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, - 2, 2, &tmp16); - tmp16 |=3D AX_MEDIUM_JUMBO_EN; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, - 2, 2, &tmp16); - } else { - ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, - 2, 2, &tmp16); - tmp16 &=3D ~AX_MEDIUM_JUMBO_EN; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, - 2, 2, &tmp16); - } - - /* max qlen depend on hard_mtu and rx_urb_size */ - usbnet_update_max_qlen(dev); - - return 0; -} - -static int ax88179_set_mac_addr(struct net_device *net, void *p) -{ - struct usbnet *dev =3D netdev_priv(net); - struct sockaddr *addr =3D p; - int ret; - - if (netif_running(net)) - return -EBUSY; - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - eth_hw_addr_set(net, addr->sa_data); - - /* Set the MAC address */ - ret =3D ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_NODE_ID, ETH_ALEN, - ETH_ALEN, net->dev_addr); - if (ret < 0) - return ret; - - return 0; -} - static const struct net_device_ops ax88179_netdev_ops =3D { .ndo_open =3D usbnet_open, .ndo_stop =3D usbnet_stop, @@ -1249,35 +669,6 @@ static int ax88179_led_setting(struct usbnet *dev) return 0; } =20 -static void ax88179_get_mac_addr(struct usbnet *dev) -{ - u8 mac[ETH_ALEN]; - - memset(mac, 0, sizeof(mac)); - - /* Maybe the boot loader passed the MAC address via device tree */ - if (!eth_platform_get_mac_address(&dev->udev->dev, mac)) { - netif_dbg(dev, ifup, dev->net, - "MAC address read from device tree"); - } else { - ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_NODE_ID, ETH_ALEN, - ETH_ALEN, mac); - netif_dbg(dev, ifup, dev->net, - "MAC address read from ASIX chip"); - } - - if (is_valid_ether_addr(mac)) { - eth_hw_addr_set(dev->net, mac); - if (!is_local_ether_addr(mac)) - dev->net->addr_assign_type =3D NET_ADDR_PERM; - } else { - netdev_info(dev->net, "invalid MAC address, using random\n"); - } - - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_NODE_ID, ETH_ALEN, ETH_ALEN, - dev->net->dev_addr); -} - static int ax88179_bind(struct usbnet *dev, struct usb_interface *intf) { struct ax88179_data *ax179_data; diff --git a/drivers/net/usb/ax88179_lib.c b/drivers/net/usb/ax88179_lib.c new file mode 100644 index 0000000000000000000000000000000000000000..761701ebc0692338b5c0a9f73d0= b6965cda87d6e --- /dev/null +++ b/drivers/net/usb/ax88179_lib.c @@ -0,0 +1,444 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * ASIX AX88179/178A USB 3.0/2.0 to Gigabit Ethernet Devices + * + * Copyright (C) 2011-2013 ASIX + */ + +#include +#include "ax88179_lib.h" + +void ax88179_set_pm_mode(struct usbnet *dev, bool pm_mode) +{ + struct ax88179_data *ax179_data =3D dev->driver_priv; + + ax179_data->in_pm =3D pm_mode; +} + +static int ax88179_in_pm(struct usbnet *dev) +{ + struct ax88179_data *ax179_data =3D dev->driver_priv; + + return ax179_data->in_pm; +} + +int __ax88179_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, + u16 size, void *data) +{ + int (*fn)(struct usbnet *dev, u8 cmd, u8 rtype, u16 val, u16 i, void *d, = u16 size); + struct ax88179_data *ax179_data =3D dev->driver_priv; + int ret; + + if (!ax88179_in_pm(dev)) + fn =3D usbnet_read_cmd; + else + fn =3D usbnet_read_cmd_nopm; + + ret =3D fn(dev, cmd, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + value, index, data, size); + + if (unlikely(ret < 0 && !(ret =3D=3D -ENODEV && ax179_data->disconnecting= ))) + netdev_warn(dev->net, "Failed to read reg index 0x%04x: %d\n", + index, ret); + + return ret; +} + +static int __ax88179_write_cmd(struct usbnet *dev, u8 cmd, u16 value, + u16 index, u16 size, const void *data) +{ + int (*fn)(struct usbnet *dev, u8 cmd, u8 rtype, u16 val, u16 i, const voi= d *d, u16 size); + struct ax88179_data *ax179_data =3D dev->driver_priv; + int ret; + + if (!ax88179_in_pm(dev)) + fn =3D usbnet_write_cmd; + else + fn =3D usbnet_write_cmd_nopm; + + ret =3D fn(dev, cmd, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + value, index, data, size); + + if (unlikely(ret < 0 && !(ret =3D=3D -ENODEV && ax179_data->disconnecting= ))) + netdev_warn(dev->net, "Failed to write reg index 0x%04x: %d\n", + index, ret); + + return ret; +} + +void ax88179_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, + u16 index, u16 size, void *data) +{ + u16 buf; + + if (size =3D=3D 2) { + buf =3D *((u16 *)data); + cpu_to_le16s(&buf); + usbnet_write_cmd_async(dev, cmd, USB_DIR_OUT | USB_TYPE_VENDOR | + USB_RECIP_DEVICE, value, index, &buf, + size); + } else { + usbnet_write_cmd_async(dev, cmd, USB_DIR_OUT | USB_TYPE_VENDOR | + USB_RECIP_DEVICE, value, index, data, + size); + } +} + +int ax88179_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, + u16 size, void *data) +{ + int ret; + + if (size =3D=3D 2) { + u16 buf =3D 0; + + ret =3D __ax88179_read_cmd(dev, cmd, value, index, size, &buf); + le16_to_cpus(&buf); + *((u16 *)data) =3D buf; + } else if (size =3D=3D 4) { + u32 buf =3D 0; + + ret =3D __ax88179_read_cmd(dev, cmd, value, index, size, &buf); + le32_to_cpus(&buf); + *((u32 *)data) =3D buf; + } else { + ret =3D __ax88179_read_cmd(dev, cmd, value, index, size, data); + } + + return ret; +} + +int ax88179_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, + u16 size, const void *data) +{ + int ret; + + if (size =3D=3D 2) { + u16 buf; + + buf =3D *((u16 *)data); + cpu_to_le16s(&buf); + ret =3D __ax88179_write_cmd(dev, cmd, value, index, + size, &buf); + } else { + ret =3D __ax88179_write_cmd(dev, cmd, value, index, + size, data); + } + + return ret; +} + +void ax88179_status(struct usbnet *dev, struct urb *urb) +{ + struct ax88179_int_data *event; + u32 link; + + if (urb->actual_length < 8) + return; + + event =3D urb->transfer_buffer; + le32_to_cpus((void *)&event->intdata1); + + link =3D (((__force u32)event->intdata1) & AX_INT_PPLS_LINK) >> 16; + + if (netif_carrier_ok(dev->net) !=3D link) { + usbnet_link_change(dev, link, 1); + if (!link) + netdev_info(dev->net, "ax88179 - Link status is: 0\n"); + } +} + +int ax88179_mdio_read(struct net_device *netdev, int phy_id, int loc) +{ + struct usbnet *dev =3D netdev_priv(netdev); + u16 res; + + ax88179_read_cmd(dev, AX_ACCESS_PHY, phy_id, (__u16)loc, 2, &res); + return res; +} + +void ax88179_mdio_write(struct net_device *netdev, int phy_id, int loc, in= t val) +{ + struct usbnet *dev =3D netdev_priv(netdev); + u16 res =3D (u16)val; + + ax88179_write_cmd(dev, AX_ACCESS_PHY, phy_id, (__u16)loc, 2, &res); +} + +void ax88179_get_wol(struct net_device *net, struct ethtool_wolinfo *wolin= fo) +{ + struct usbnet *dev =3D netdev_priv(net); + struct ax88179_data *priv =3D dev->driver_priv; + + wolinfo->supported =3D priv->wol_supported; + wolinfo->wolopts =3D priv->wolopts; +} + +int ax88179_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinf= o) +{ + struct usbnet *dev =3D netdev_priv(net); + struct ax88179_data *priv =3D dev->driver_priv; + + if (wolinfo->wolopts & ~(priv->wol_supported)) + return -EINVAL; + + priv->wolopts =3D wolinfo->wolopts; + + return 0; +} + +int ax88179_get_eeprom(struct net_device *net, struct ethtool_eeprom *eepr= om, u8 *data) +{ + struct usbnet *dev =3D netdev_priv(net); + u16 *eeprom_buff; + int first_word, last_word; + int i, ret; + + if (eeprom->len =3D=3D 0) + return -EINVAL; + + eeprom->magic =3D AX88179_EEPROM_MAGIC; + + first_word =3D eeprom->offset >> 1; + last_word =3D (eeprom->offset + eeprom->len - 1) >> 1; + eeprom_buff =3D kmalloc_array(last_word - first_word + 1, sizeof(u16), + GFP_KERNEL); + if (!eeprom_buff) + return -ENOMEM; + + /* ax88179/178A returns 2 bytes from eeprom on read */ + for (i =3D first_word; i <=3D last_word; i++) { + ret =3D __ax88179_read_cmd(dev, AX_ACCESS_EEPROM, i, 1, 2, + &eeprom_buff[i - first_word]); + if (ret < 0) { + kfree(eeprom_buff); + return -EIO; + } + } + + memcpy(data, (u8 *)eeprom_buff + (eeprom->offset & 1), eeprom->len); + kfree(eeprom_buff); + return 0; +} + +int ax88179_set_eeprom(struct net_device *net, struct ethtool_eeprom *eepr= om, u8 *data) +{ + struct usbnet *dev =3D netdev_priv(net); + u16 *eeprom_buff; + int first_word; + int last_word; + int ret; + int i; + + netdev_dbg(net, "write EEPROM len %d, offset %d, magic 0x%x\n", + eeprom->len, eeprom->offset, eeprom->magic); + + if (eeprom->len =3D=3D 0) + return -EINVAL; + + if (eeprom->magic !=3D AX88179_EEPROM_MAGIC) + return -EINVAL; + + first_word =3D eeprom->offset >> 1; + last_word =3D (eeprom->offset + eeprom->len - 1) >> 1; + + eeprom_buff =3D kmalloc_array(last_word - first_word + 1, sizeof(u16), + GFP_KERNEL); + if (!eeprom_buff) + return -ENOMEM; + + /* align data to 16 bit boundaries, read the missing data from + * the EEPROM + */ + if (eeprom->offset & 1) { + ret =3D ax88179_read_cmd(dev, AX_ACCESS_EEPROM, first_word, 1, 2, + &eeprom_buff[0]); + if (ret < 0) { + netdev_err(net, "Failed to read EEPROM at offset 0x%02x.\n", first_word= ); + goto free; + } + } + + if ((eeprom->offset + eeprom->len) & 1) { + ret =3D ax88179_read_cmd(dev, AX_ACCESS_EEPROM, last_word, 1, 2, + &eeprom_buff[last_word - first_word]); + if (ret < 0) { + netdev_err(net, "Failed to read EEPROM at offset 0x%02x.\n", last_word); + goto free; + } + } + + memcpy((u8 *)eeprom_buff + (eeprom->offset & 1), data, eeprom->len); + + for (i =3D first_word; i <=3D last_word; i++) { + netdev_dbg(net, "write to EEPROM at offset 0x%02x, data 0x%04x\n", + i, eeprom_buff[i - first_word]); + ret =3D ax88179_write_cmd(dev, AX_ACCESS_EEPROM, i, 1, 2, + &eeprom_buff[i - first_word]); + if (ret < 0) { + netdev_err(net, "Failed to write EEPROM at offset 0x%02x.\n", i); + goto free; + } + msleep(20); + } + + /* reload EEPROM data */ + ret =3D ax88179_write_cmd(dev, AX_RELOAD_EEPROM_EFUSE, 0x0000, 0, 0, NULL= ); + if (ret < 0) { + netdev_err(net, "Failed to reload EEPROM data\n"); + goto free; + } + + ret =3D 0; +free: + kfree(eeprom_buff); + return ret; +} + +void ax88179_set_multicast(struct net_device *net) +{ + struct usbnet *dev =3D netdev_priv(net); + struct ax88179_data *data =3D dev->driver_priv; + u8 *m_filter =3D ((u8 *)dev->data); + + data->rxctl =3D (AX_RX_CTL_START | AX_RX_CTL_AB | AX_RX_CTL_IPE); + + if (net->flags & IFF_PROMISC) { + data->rxctl |=3D AX_RX_CTL_PRO; + } else if (net->flags & IFF_ALLMULTI || + netdev_mc_count(net) > AX_MAX_MCAST) { + data->rxctl |=3D AX_RX_CTL_AMALL; + } else if (netdev_mc_empty(net)) { + /* just broadcast and directed */ + } else { + /* We use dev->data for our 8 byte filter buffer + * to avoid allocating memory that is tricky to free later + */ + u32 crc_bits; + struct netdev_hw_addr *ha; + + memset(m_filter, 0, AX_MCAST_FLTSIZE); + + netdev_for_each_mc_addr(ha, net) { + crc_bits =3D ether_crc(ETH_ALEN, ha->addr) >> 26; + *(m_filter + (crc_bits >> 3)) |=3D (1 << (crc_bits & 7)); + } + + ax88179_write_cmd_async(dev, AX_ACCESS_MAC, AX_MULFLTARY, + AX_MCAST_FLTSIZE, AX_MCAST_FLTSIZE, + m_filter); + + data->rxctl |=3D AX_RX_CTL_AM; + } + + ax88179_write_cmd_async(dev, AX_ACCESS_MAC, AX_RX_CTL, + 2, 2, &data->rxctl); +} + +int ax88179_set_features(struct net_device *net, netdev_features_t feature= s) +{ + u8 tmp; + struct usbnet *dev =3D netdev_priv(net); + netdev_features_t changed =3D net->features ^ features; + + if (changed & NETIF_F_IP_CSUM) { + ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, &tmp); + tmp ^=3D AX_TXCOE_TCP | AX_TXCOE_UDP; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, &tmp); + } + + if (changed & NETIF_F_IPV6_CSUM) { + ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, &tmp); + tmp ^=3D AX_TXCOE_TCPV6 | AX_TXCOE_UDPV6; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, &tmp); + } + + if (changed & NETIF_F_RXCSUM) { + ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_RXCOE_CTL, 1, 1, &tmp); + tmp ^=3D AX_RXCOE_IP | AX_RXCOE_TCP | AX_RXCOE_UDP | + AX_RXCOE_TCPV6 | AX_RXCOE_UDPV6; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RXCOE_CTL, 1, 1, &tmp); + } + + return 0; +} + +void ax88179_get_mac_addr(struct usbnet *dev) +{ + u8 mac[ETH_ALEN]; + + memset(mac, 0, sizeof(mac)); + + /* Maybe the boot loader passed the MAC address via device tree */ + if (!eth_platform_get_mac_address(&dev->udev->dev, mac)) { + netif_dbg(dev, ifup, dev->net, + "MAC address read from device tree"); + } else { + ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_NODE_ID, ETH_ALEN, + ETH_ALEN, mac); + netif_dbg(dev, ifup, dev->net, + "MAC address read from ASIX chip"); + } + + if (is_valid_ether_addr(mac)) { + eth_hw_addr_set(dev->net, mac); + if (!is_local_ether_addr(mac)) + dev->net->addr_assign_type =3D NET_ADDR_PERM; + } else { + netdev_info(dev->net, "invalid MAC address, using random\n"); + } + + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_NODE_ID, ETH_ALEN, ETH_ALEN, + dev->net->dev_addr); +} + +int ax88179_change_mtu(struct net_device *net, int new_mtu) +{ + struct usbnet *dev =3D netdev_priv(net); + u16 tmp16; + + WRITE_ONCE(net->mtu, new_mtu); + dev->hard_mtu =3D net->mtu + net->hard_header_len; + + if (net->mtu > 1500) { + ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, + 2, 2, &tmp16); + tmp16 |=3D AX_MEDIUM_JUMBO_EN; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, + 2, 2, &tmp16); + } else { + ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, + 2, 2, &tmp16); + tmp16 &=3D ~AX_MEDIUM_JUMBO_EN; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, + 2, 2, &tmp16); + } + + /* max qlen depend on hard_mtu and rx_urb_size */ + usbnet_update_max_qlen(dev); + + return 0; +} + +int ax88179_set_mac_addr(struct net_device *net, void *p) +{ + struct usbnet *dev =3D netdev_priv(net); + struct sockaddr *addr =3D p; + int ret; + + if (netif_running(net)) + return -EBUSY; + if (!is_valid_ether_addr(addr->sa_data)) + return -EADDRNOTAVAIL; + + eth_hw_addr_set(net, addr->sa_data); + + /* Set the MAC address */ + ret =3D ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_NODE_ID, ETH_ALEN, + ETH_ALEN, net->dev_addr); + if (ret < 0) + return ret; + + return 0; +} + diff --git a/drivers/net/usb/ax88179_lib.h b/drivers/net/usb/ax88179_lib.h new file mode 100644 index 0000000000000000000000000000000000000000..b2ee1356727cf4b3fa05f0b0d5f= d863ac3f9a87d --- /dev/null +++ b/drivers/net/usb/ax88179_lib.h @@ -0,0 +1,194 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include +#include +#include + +#ifndef __LINUX_USBNET_AX88179_H +#define __LINUX_USBNET_AX88179_H + +#define AX88179_PHY_ID 0x03 +#define AX_EEPROM_LEN 0x100 +#define AX88179_EEPROM_MAGIC 0x17900b95 +#define AX_MCAST_FLTSIZE 8 +#define AX_MAX_MCAST 64 +#define AX_INT_PPLS_LINK ((u32)BIT(16)) +#define AX_RXHDR_L4_TYPE_MASK 0x1c +#define AX_RXHDR_L4_TYPE_UDP 4 +#define AX_RXHDR_L4_TYPE_TCP 16 +#define AX_RXHDR_L3CSUM_ERR 2 +#define AX_RXHDR_L4CSUM_ERR 1 +#define AX_RXHDR_CRC_ERR ((u32)BIT(29)) +#define AX_RXHDR_DROP_ERR ((u32)BIT(31)) +#define AX_ACCESS_MAC 0x01 +#define AX_ACCESS_PHY 0x02 +#define AX_ACCESS_EEPROM 0x04 +#define AX_ACCESS_EFUS 0x05 +#define AX_RELOAD_EEPROM_EFUSE 0x06 +#define AX_PAUSE_WATERLVL_LOW 0x54 +#define AX_PAUSE_WATERLVL_HIGH 0x55 + +#define PHYSICAL_LINK_STATUS 0x02 + #define AX_USB_SS 0x04 + #define AX_USB_HS 0x02 + +#define GENERAL_STATUS 0x03 +/* Check AX88179 version. UA1:Bit2 =3D 0, UA2:Bit2 =3D 1 */ + #define AX_SECLD 0x04 + +#define AX_SROM_ADDR 0x07 +#define AX_SROM_CMD 0x0a + #define EEP_RD 0x04 + #define EEP_BUSY 0x10 + +#define AX_SROM_DATA_LOW 0x08 +#define AX_SROM_DATA_HIGH 0x09 + +#define AX_RX_CTL 0x0b + #define AX_RX_CTL_DROPCRCERR 0x0100 + #define AX_RX_CTL_IPE 0x0200 + #define AX_RX_CTL_START 0x0080 + #define AX_RX_CTL_AP 0x0020 + #define AX_RX_CTL_AM 0x0010 + #define AX_RX_CTL_AB 0x0008 + #define AX_RX_CTL_AMALL 0x0002 + #define AX_RX_CTL_PRO 0x0001 + #define AX_RX_CTL_STOP 0x0000 + +#define AX_NODE_ID 0x10 +#define AX_MULFLTARY 0x16 + +#define AX_MEDIUM_STATUS_MODE 0x22 + #define AX_MEDIUM_GIGAMODE 0x01 + #define AX_MEDIUM_FULL_DUPLEX 0x02 + #define AX_MEDIUM_EN_125MHZ 0x08 + #define AX_MEDIUM_RXFLOW_CTRLEN 0x10 + #define AX_MEDIUM_TXFLOW_CTRLEN 0x20 + #define AX_MEDIUM_RECEIVE_EN 0x100 + #define AX_MEDIUM_PS 0x200 + #define AX_MEDIUM_JUMBO_EN 0x8040 + +#define AX_MONITOR_MOD 0x24 + #define AX_MONITOR_MODE_RWLC 0x02 + #define AX_MONITOR_MODE_RWMP 0x04 + #define AX_MONITOR_MODE_PMEPOL 0x20 + #define AX_MONITOR_MODE_PMETYPE 0x40 + +#define AX_GPIO_CTRL 0x25 + #define AX_GPIO_CTRL_GPIO3EN 0x80 + #define AX_GPIO_CTRL_GPIO2EN 0x40 + #define AX_GPIO_CTRL_GPIO1EN 0x20 + +#define AX_PHYPWR_RSTCTL 0x26 + #define AX_PHYPWR_RSTCTL_BZ 0x0010 + #define AX_PHYPWR_RSTCTL_IPRL 0x0020 + #define AX_PHYPWR_RSTCTL_AT 0x1000 + +#define AX_RX_BULKIN_QCTRL 0x2e +#define AX_CLK_SELECT 0x33 + #define AX_CLK_SELECT_BCS 0x01 + #define AX_CLK_SELECT_ACS 0x02 + #define AX_CLK_SELECT_ULR 0x08 + +#define AX_RXCOE_CTL 0x34 + #define AX_RXCOE_IP 0x01 + #define AX_RXCOE_TCP 0x02 + #define AX_RXCOE_UDP 0x04 + #define AX_RXCOE_TCPV6 0x20 + #define AX_RXCOE_UDPV6 0x40 + +#define AX_TXCOE_CTL 0x35 + #define AX_TXCOE_IP 0x01 + #define AX_TXCOE_TCP 0x02 + #define AX_TXCOE_UDP 0x04 + #define AX_TXCOE_TCPV6 0x20 + #define AX_TXCOE_UDPV6 0x40 + +#define AX_LEDCTRL 0x73 + +#define GMII_PHY_PHYSR 0x11 + #define GMII_PHY_PHYSR_SMASK 0xc000 + #define GMII_PHY_PHYSR_GIGA 0x8000 + #define GMII_PHY_PHYSR_100 0x4000 + #define GMII_PHY_PHYSR_FULL 0x2000 + #define GMII_PHY_PHYSR_LINK 0x400 + +#define GMII_LED_ACT 0x1a + #define GMII_LED_ACTIVE_MASK 0xff8f + #define GMII_LED0_ACTIVE BIT(4) + #define GMII_LED1_ACTIVE BIT(5) + #define GMII_LED2_ACTIVE BIT(6) + +#define GMII_LED_LINK 0x1c + #define GMII_LED_LINK_MASK 0xf888 + #define GMII_LED0_LINK_10 BIT(0) + #define GMII_LED0_LINK_100 BIT(1) + #define GMII_LED0_LINK_1000 BIT(2) + #define GMII_LED1_LINK_10 BIT(4) + #define GMII_LED1_LINK_100 BIT(5) + #define GMII_LED1_LINK_1000 BIT(6) + #define GMII_LED2_LINK_10 BIT(8) + #define GMII_LED2_LINK_100 BIT(9) + #define GMII_LED2_LINK_1000 BIT(10) + #define LED0_ACTIVE BIT(0) + #define LED0_LINK_10 BIT(1) + #define LED0_LINK_100 BIT(2) + #define LED0_LINK_1000 BIT(3) + #define LED0_FD BIT(4) + #define LED0_USB3_MASK 0x001f + #define LED1_ACTIVE BIT(5) + #define LED1_LINK_10 BIT(6) + #define LED1_LINK_100 BIT(7) + #define LED1_LINK_1000 BIT(8) + #define LED1_FD BIT(9) + #define LED1_USB3_MASK 0x03e0 + #define LED2_ACTIVE BIT(10) + #define LED2_LINK_1000 BIT(13) + #define LED2_LINK_100 BIT(12) + #define LED2_LINK_10 BIT(11) + #define LED2_FD BIT(14) + #define LED_VALID BIT(15) + #define LED2_USB3_MASK 0x7c00 + +#define GMII_PHYPAGE 0x1e +#define GMII_PHY_PAGE_SELECT 0x1f + #define GMII_PHY_PGSEL_EXT 0x0007 + #define GMII_PHY_PGSEL_PAGE0 0x0000 + #define GMII_PHY_PGSEL_PAGE3 0x0003 + #define GMII_PHY_PGSEL_PAGE5 0x0005 + +struct ax88179_data { + u8 eee_enabled; + u8 eee_active; + u16 rxctl; + u8 in_pm; + u32 wol_supported; + u32 wolopts; + u8 disconnecting; +}; + +struct ax88179_int_data { + __le32 intdata1; + __le32 intdata2; +}; + +void ax88179_set_pm_mode(struct usbnet *dev, bool pm_mode); +int __ax88179_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, u= 16 size, void *data); +int ax88179_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, u16= size, void *data); +int ax88179_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, u1= 6 size, + const void *data); +void ax88179_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 in= dex, + u16 size, void *data); +int ax88179_mdio_read(struct net_device *netdev, int phy_id, int loc); +void ax88179_mdio_write(struct net_device *netdev, int phy_id, int loc, in= t val); +void ax88179_status(struct usbnet *dev, struct urb *urb); +void ax88179_get_wol(struct net_device *net, struct ethtool_wolinfo *wolin= fo); +int ax88179_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinf= o); +int ax88179_get_eeprom(struct net_device *net, struct ethtool_eeprom *eepr= om, u8 *data); +int ax88179_set_eeprom(struct net_device *net, struct ethtool_eeprom *eepr= om, u8 *data); +void ax88179_set_multicast(struct net_device *net); +int ax88179_set_features(struct net_device *net, netdev_features_t feature= s); +void ax88179_get_mac_addr(struct usbnet *dev); +int ax88179_change_mtu(struct net_device *net, int new_mtu); +int ax88179_set_mac_addr(struct net_device *net, void *p); +#endif /*__LINUX_USBNET_AX88179_H */ --=20 2.47.3 From nobody Fri Sep 25 06:47:57 2026 Received: from bkemail.birger-koblitz.de (bkemail.birger-koblitz.de [23.88.97.239]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B12B222FDE6; Wed, 16 Sep 2026 03:24:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=23.88.97.239 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789529081; cv=none; b=QSzOqPESJE444VMszCUdFj+cvg0yNLan7BgXVhcU72tlrxZch2Veyb1Q0zfzNVxGIv5oUH7Qglxl6QB8Mug4PpghCSagtPkfl/p1kg3fbIZLuaripNM3zaijH3jhBdMmrO6ZNLqlHyKCL26TFV4UZ+rqaLo8xibr7+3iKt4pQnU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789529081; c=relaxed/simple; bh=ZGl5Vcmlux3CLdbnKMcw3UCD1AYWBXFWxW0/LVCsG1s=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=j+0f07c3tchZbDcV9g23farnANT061X9WGIlpbMfl7uQXEYejDTaZM+ArZ8Sd68bjj1DmA7HHAMq07YDkwUtZ/YpfODhnpS3cp7bCMKjV5okEJgecM48Tl59OQ+z3pjhN0qKGtheuS4+GPND344+IsyNrRUb5q25M0vZpq6hGnc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=birger-koblitz.de; spf=pass smtp.mailfrom=birger-koblitz.de; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b=flbWCJtP; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b=flbWCJtP; arc=none smtp.client-ip=23.88.97.239 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=birger-koblitz.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=birger-koblitz.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b="flbWCJtP"; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b="flbWCJtP" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=birger-koblitz.de; s=default; t=1789529077; bh=ZGl5Vcmlux3CLdbnKMcw3UCD1AYWBXFWxW0/LVCsG1s=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=flbWCJtPPyBZWXHz+aRrfq8mkTxdJvpSthZDdepJWHo6tvjaI6Ws3dhdYrsv5TfEO ZZCpFLXCCa5OFS18APd8asajSoly1d1+EMnylalCbQ6k1W/U/GXQUyF6WmtgTvIG9S PV1uQ7l/NJokUyLmUaUblXzQ54cKi/YK4hnnczncj15vnTXPLj++2kjvfZxRBDY05B jScm7yVPibQWzt2jidaXlvYBoYEl9hpRIl9Gkd0lrcXX/fO7ZYqsdwCKYjzBk/vw81 zKdJwawoRbQKZD4ot7JpO/Ocot4ElBesHZGATaZTErUPt9mva0C0VtOt4CJKQqVPpk R12uq7trbaouA== Received: by bkemail.birger-koblitz.de (Postfix, from userid 109) id EDEDB3FA80; Wed, 16 Sep 2026 03:24:37 +0000 (UTC) X-Spam-Level: DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=birger-koblitz.de; s=default; t=1789529077; bh=ZGl5Vcmlux3CLdbnKMcw3UCD1AYWBXFWxW0/LVCsG1s=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=flbWCJtPPyBZWXHz+aRrfq8mkTxdJvpSthZDdepJWHo6tvjaI6Ws3dhdYrsv5TfEO ZZCpFLXCCa5OFS18APd8asajSoly1d1+EMnylalCbQ6k1W/U/GXQUyF6WmtgTvIG9S PV1uQ7l/NJokUyLmUaUblXzQ54cKi/YK4hnnczncj15vnTXPLj++2kjvfZxRBDY05B jScm7yVPibQWzt2jidaXlvYBoYEl9hpRIl9Gkd0lrcXX/fO7ZYqsdwCKYjzBk/vw81 zKdJwawoRbQKZD4ot7JpO/Ocot4ElBesHZGATaZTErUPt9mva0C0VtOt4CJKQqVPpk R12uq7trbaouA== Received: from DELLLaptop.net (unknown [223.86.26.228]) by bkemail.birger-koblitz.de (Postfix) with ESMTPSA id 37CB73F6DB; Wed, 16 Sep 2026 03:24:32 +0000 (UTC) From: Birger Koblitz Date: Wed, 16 Sep 2026 05:24:04 +0200 Subject: [PATCH net-next v12 05/15] ax88179_178a: Add netdev2data() convenience function Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260916-ax88179a-v12-5-60c04c9924a2@birger-koblitz.de> References: <20260916-ax88179a-v12-0-60c04c9924a2@birger-koblitz.de> In-Reply-To: <20260916-ax88179a-v12-0-60c04c9924a2@birger-koblitz.de> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Russell King , Andrew Lunn , Heiner Kallweit Cc: linux-usb@vger.kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Birger Koblitz , Jianhui Xu X-Mailer: b4 0.14.2 Add a convenience function for the ethtool ops that use phylink and need to retrieve the ax88179_data structure from net_device. Signed-off-by: Birger Koblitz Reviewed-by: Andrew Lunn Tested-by: Jianhui Xu --- drivers/net/usb/ax88179_lib.c | 7 +++++++ drivers/net/usb/ax88179_lib.h | 1 + 2 files changed, 8 insertions(+) diff --git a/drivers/net/usb/ax88179_lib.c b/drivers/net/usb/ax88179_lib.c index 761701ebc0692338b5c0a9f73d0b6965cda87d6e..ea36aef3d3e45ee4f84362a1b87= 628a12a355bbf 100644 --- a/drivers/net/usb/ax88179_lib.c +++ b/drivers/net/usb/ax88179_lib.c @@ -128,6 +128,13 @@ int ax88179_write_cmd(struct usbnet *dev, u8 cmd, u16 = value, u16 index, return ret; } =20 +struct ax88179_data *netdev2data(struct net_device *net) +{ + struct usbnet *dev =3D netdev_priv(net); + + return dev->driver_priv; +} + void ax88179_status(struct usbnet *dev, struct urb *urb) { struct ax88179_int_data *event; diff --git a/drivers/net/usb/ax88179_lib.h b/drivers/net/usb/ax88179_lib.h index b2ee1356727cf4b3fa05f0b0d5fd863ac3f9a87d..9ff2a94a6fb2de4ee85f25e913a= e2fe263bcea7c 100644 --- a/drivers/net/usb/ax88179_lib.h +++ b/drivers/net/usb/ax88179_lib.h @@ -181,6 +181,7 @@ void ax88179_write_cmd_async(struct usbnet *dev, u8 cmd= , u16 value, u16 index, u16 size, void *data); int ax88179_mdio_read(struct net_device *netdev, int phy_id, int loc); void ax88179_mdio_write(struct net_device *netdev, int phy_id, int loc, in= t val); +struct ax88179_data *netdev2data(struct net_device *net); void ax88179_status(struct usbnet *dev, struct urb *urb); void ax88179_get_wol(struct net_device *net, struct ethtool_wolinfo *wolin= fo); int ax88179_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinf= o); --=20 2.47.3 From nobody Fri Sep 25 06:47:57 2026 Received: from bkemail.birger-koblitz.de (bkemail.birger-koblitz.de [23.88.97.239]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8F86038F255; Wed, 16 Sep 2026 03:24:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=23.88.97.239 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789529094; cv=none; b=u975dBzvt39XuMGMxDyZ7Bm9t1ujT7OzFNGumtzz+etS+AhRpfib6XbxIKarG8qJQrc3168nM17m0qGVm2TH44Wvvarb1QaRlbyB5eQefnQM+KnnzoyP0u+vw7x1MUM5gcDDWCsjWOR3rXgkW2b3ZYTRTNKnwICRXxfLPbx/tzE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789529094; c=relaxed/simple; bh=zQO8QNtS6my4whrvgYI2o9iYwhzRlqr8g/9F3HL5PV4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Hr6HJsg5onOrX/e5LxOjs4edBQzY4sBTXCKSCaVQzbY3KDNiMTPEt1c9huTtEcIPm3LmJFw8s23bcwoFr6sGNcIIH4LavIU8M2Flnx/I/cOSwtU0DGbTfFyNmftpqEOlVWetr0aDJl2amXxDo/ESA6uWklG5TXYy2aazD+occAo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=birger-koblitz.de; spf=pass smtp.mailfrom=birger-koblitz.de; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b=1XnV0t7A; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b=a/yX4x/i; arc=none smtp.client-ip=23.88.97.239 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=birger-koblitz.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=birger-koblitz.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b="1XnV0t7A"; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b="a/yX4x/i" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=birger-koblitz.de; s=default; t=1789529087; bh=zQO8QNtS6my4whrvgYI2o9iYwhzRlqr8g/9F3HL5PV4=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=1XnV0t7AspVaG3pW/F+QmtlIuGsG7O6E3qDv1Gl7RDfUHEFse/lQImnlNIyoqh/Gl p2agR7nphhjeHfs7zh0KMwayEDhs+0yJJtpw1EvYPwRowT8okb0HWWqSoPOHzMCC4H o4lNd7CV0tONhK6HKDEYnUjmuvBApIHn6b2rkQnwoYAOGXwqU8l3gdXY/ZRpEGYXm5 79R6f2mf9zeNeQ3LJM37i+vEDiZpk46VCeaQaQ5tn3poK8aqm9tq4PdVCMheyqYldW D127gt2c40rnWfra8mLjXs/clp3dljOKLeB9Imh5B5zq0CCL2/AAr1kA0n6simhfFX eaDAl4WcW7Atw== Received: by bkemail.birger-koblitz.de (Postfix, from userid 109) id 8C8D33FA6E; Wed, 16 Sep 2026 03:24:47 +0000 (UTC) X-Spam-Level: DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=birger-koblitz.de; s=default; t=1789529082; bh=zQO8QNtS6my4whrvgYI2o9iYwhzRlqr8g/9F3HL5PV4=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=a/yX4x/iYaNJgjWirEvdw3vs/zMNyZvSlg7tx5FDh3x9qCZCK7tDBC+faOv44mPR9 K6lDvB3YhSAIocIfPRFoBrIUh5P11crhqpqBiJwN3zfzPvFtLUyZfYbo/M8xQjGpeu iftK0LnRSlYtjrpsGPdbP2aW6vJdnuLQmslHmMfMg5HoObIvxDXGao9F/xO8xiPKeg iS42qqQkpJZLpyQM5+XkfLE9LWQwp2jNtQU1XVix61UQawGhb/Zq4zUBjvXF7AhTrp CLUdIs3NdugGoqTzl+sp5L0KkXWPYkCSsoyif0M2Y5CTnO+LoWQAo4JwtXx3M3Wa7E hd/3pOcuKDHYQ== Received: from DELLLaptop.net (unknown [223.86.26.228]) by bkemail.birger-koblitz.de (Postfix) with ESMTPSA id C851D3FA6C; Wed, 16 Sep 2026 03:24:37 +0000 (UTC) From: Birger Koblitz Date: Wed, 16 Sep 2026 05:24:05 +0200 Subject: [PATCH net-next v12 06/15] ax88179_178a: Add HW support for AX179A-based chips Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260916-ax88179a-v12-6-60c04c9924a2@birger-koblitz.de> References: <20260916-ax88179a-v12-0-60c04c9924a2@birger-koblitz.de> In-Reply-To: <20260916-ax88179a-v12-0-60c04c9924a2@birger-koblitz.de> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Russell King , Andrew Lunn , Heiner Kallweit Cc: linux-usb@vger.kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Birger Koblitz , Jianhui Xu X-Mailer: b4 0.14.2 This adds bindings and HW support for AX179A-based USB-Ethernet controllers. The AX179A-family of chips consists of the AX88279 (2.5GBit PHY) AX88179A/B (1GBit PHY, B variant has wider temperature range) AX772D/E (100Mbit PHY) The controllers all have the same vendor and device ID (0x0b95, 0x1790) and are distinguished by their BCD device versions, which are 2.00 AX88179A/B 3.00 AX88772D/E 4.00 AX88279 For all chips, the driver calls the same ax88179a_bind() function and the chips are then distinguished by the chip version and BCD device ID. The AX179A-based chips all provide both a CDC-NCM compatible USB interface, and a proprietary vendor interface. By default, the proprietary vendor interface is not active and Linux will load the CDC-NCM driver to support the devices. If the ax88179_178a module is configured by the OS to have precedence over CDC-NCM, then this driver will switch the device to use the vendor interface, and the device will be controlled by the ax88179_178a driver when the device is probed again after an automatic reset by the device. Signed-off-by: Birger Koblitz Reviewed-by: Andrew Lunn Tested-by: Jianhui Xu --- MAINTAINERS | 6 + drivers/net/usb/Kconfig | 2 +- drivers/net/usb/Makefile | 2 +- drivers/net/usb/ax88179_178a.c | 12 + drivers/net/usb/ax88179_lib.h | 159 ++++++ drivers/net/usb/ax88179a_devices.c | 973 +++++++++++++++++++++++++++++++++= ++++ 6 files changed, 1152 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 0b42e898f4d8e4892e943bb3db839ff9afcd3569..442e8ea3ca04e41037021fe0457= 0549ecdde49ab 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4020,6 +4020,12 @@ S: Maintained F: Documentation/devicetree/bindings/net/asix,ax88796c.yaml F: drivers/net/ethernet/asix/ax88796c_* =20 +ASIX AX88179 USB ETHERNET DRIVER +M: Birger Koblitz +L: netdev@vger.kernel.org +S: Maintained +F: drivers/net/usb/ax88179* + ASIX PHY DRIVER [RUST] M: FUJITA Tomonori R: Trevor Gross diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig index 52a5c0922c79fc52906d4d4040ec2b3411ff0984..115990b0d9537aea2776544c976= 8b034f32aa7a4 100644 --- a/drivers/net/usb/Kconfig +++ b/drivers/net/usb/Kconfig @@ -199,7 +199,7 @@ config USB_NET_AX88179_178A tristate "ASIX AX88179/178A USB 3.0/2.0 to Gigabit Ethernet" depends on USB_USBNET select CRC32 - select PHYLIB + select PHYLINK default y help This option adds support for ASIX AX88179 based USB 3.0/2.0 diff --git a/drivers/net/usb/Makefile b/drivers/net/usb/Makefile index ddd76fa71e2ee670888df1c9715632e5c04a8149..2ecead0181eaf8d66fb6f5dbd6f= 2905b22b6eb57 100644 --- a/drivers/net/usb/Makefile +++ b/drivers/net/usb/Makefile @@ -13,7 +13,7 @@ obj-$(CONFIG_USB_LAN78XX) +=3D lan78xx.o obj-$(CONFIG_USB_NET_AX8817X) +=3D asix.o asix-y :=3D asix_devices.o asix_common.o ax88172a.o obj-$(CONFIG_USB_NET_AX88179_178A) +=3D ax88179.o -ax88179-y :=3D ax88179_178a.o ax88179_lib.o +ax88179-y :=3D ax88179_178a.o ax88179a_devices.o ax88179_lib.o obj-$(CONFIG_USB_NET_CDCETHER) +=3D cdc_ether.o obj-$(CONFIG_USB_NET_CDC_EEM) +=3D cdc_eem.o obj-$(CONFIG_USB_NET_DM9601) +=3D dm9601.o diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c index 6aa35c8eb594fda38f7680f8801f0d82090c1efd..a2c596305f7988175ef56afbc85= 3e798406159f6 100644 --- a/drivers/net/usb/ax88179_178a.c +++ b/drivers/net/usb/ax88179_178a.c @@ -1270,6 +1270,18 @@ static const struct driver_info at_umc2000sp_info = =3D { =20 static const struct usb_device_id products[] =3D { { + /* ASIX AX88179A USB 3.2 1000Mbit Ethernet */ + USB_DEVICE_VER(0x0b95, 0x1790, 0x0200, 0x0200), + .driver_info =3D (unsigned long)&ax88179a_info, +}, { + /* ASIX AX88772D USB 2.0 100Mbit Ethernet */ + USB_DEVICE_VER(0x0b95, 0x1790, 0x0300, 0x0300), + .driver_info =3D (unsigned long)&ax88772d_info, +}, { + /* ASIX AX88279 USB 3.2 2500Mbit Ethernet */ + USB_DEVICE_VER(0x0b95, 0x1790, 0x0400, 0x0400), + .driver_info =3D (unsigned long)&ax88279_info, +}, { /* ASIX AX88179 10/100/1000 */ USB_DEVICE_AND_INTERFACE_INFO(0x0b95, 0x1790, 0xff, 0xff, 0), .driver_info =3D (unsigned long)&ax88179_info, diff --git a/drivers/net/usb/ax88179_lib.h b/drivers/net/usb/ax88179_lib.h index 9ff2a94a6fb2de4ee85f25e913ae2fe263bcea7c..2e4d35c74ee8b32cd2916924b85= d5427860bb08c 100644 --- a/drivers/net/usb/ax88179_lib.h +++ b/drivers/net/usb/ax88179_lib.h @@ -2,6 +2,7 @@ =20 #include #include +#include #include =20 #ifndef __LINUX_USBNET_AX88179_H @@ -25,17 +26,34 @@ #define AX_ACCESS_EEPROM 0x04 #define AX_ACCESS_EFUS 0x05 #define AX_RELOAD_EEPROM_EFUSE 0x06 +#define AX88179A_WAKEUP_SETTING 0x07 +#define AX_FW_MODE 0x08 +#define AX_GPHY_CTL 0x0F +#define AX88179A_FLASH_READ 0x21 +#define AX88179A_FLASH_WEN 0x22 +#define AX88179A_FLASH_WDIS 0x23 +#define AX88179A_FLASH_WRITE 0x24 +#define AX88179A_PHY_CLAUSE45 0x27 +#define AX88179A_FLASH_ERASE_SECTION 0x28 +#define AX88179A_ACCESS_BL 0x2A +#define AX88179A_PHY_POWER 0x31 +#define AX88179A_AUTODETACH 0xC0 + #define AX_PAUSE_WATERLVL_LOW 0x54 #define AX_PAUSE_WATERLVL_HIGH 0x55 =20 +#define AX_FW_MODE_179A 0x01 #define PHYSICAL_LINK_STATUS 0x02 #define AX_USB_SS 0x04 #define AX_USB_HS 0x02 + #define AX_USB_FS 0x01 =20 #define GENERAL_STATUS 0x03 /* Check AX88179 version. UA1:Bit2 =3D 0, UA2:Bit2 =3D 1 */ #define AX_SECLD 0x04 =20 +#define AX_CHIP_STATUS 0x05 + #define AX_SROM_ADDR 0x07 #define AX_SROM_CMD 0x0a #define EEP_RD 0x04 @@ -55,6 +73,15 @@ #define AX_RX_CTL_PRO 0x0001 #define AX_RX_CTL_STOP 0x0000 =20 +#define AX88179A_ETH_TX_GAP 0x0D + +#define AX88179A_BFM_DATA 0x0E + #define AX_TX_QUEUE_CFG 0x02 + #define AX_TX_QUEUE_SET 0x08 + #define AX_TX_Q1_AHB_FC_EN 0x10 + #define AX_TX_Q2_AHB_FC_EN 0x20 + #define AX_XGMII_EN 0x80 + #define AX_NODE_ID 0x10 #define AX_MULFLTARY 0x16 =20 @@ -84,7 +111,20 @@ #define AX_PHYPWR_RSTCTL_IPRL 0x0020 #define AX_PHYPWR_RSTCTL_AT 0x1000 =20 +#define AX88179A_VLAN_ID_ADDRESS 0x2A + +#define AX88179A_VLAN_ID_CONTROL 0x2B + #define AX_VLAN_CONTROL_WE 0x0001 + #define AX_VLAN_CONTROL_RD 0x0002 + #define AX_VLAN_CONTROL_VSO 0x0010 + #define AX_VLAN_CONTROL_VFE 0x0020 + +#define AX88179A_VLAN_ID_DATA0 0x2C +#define AX88179A_VLAN_ID_DATA1 0x2D + #define AX_RX_BULKIN_QCTRL 0x2e +#define AX_GPHY_EEE_CTRL 0x01 + #define AX_CLK_SELECT 0x33 #define AX_CLK_SELECT_BCS 0x01 #define AX_CLK_SELECT_ACS 0x02 @@ -104,7 +144,51 @@ #define AX_TXCOE_TCPV6 0x20 #define AX_TXCOE_UDPV6 0x40 =20 +#define AX88179A_MAC_BM_INT_MASK 0x41 +#define AX88179A_MAC_BM_RX_DMA_CTL 0x43 +#define AX88179A_MAC_BM_TX_DMA_CTL 0x46 + +#define AX88179A_MAC_RX_STATUS_CDC 0x6D + #define AX_LSOFC_WCNT_7_ACCESS 0x03 + #define AX_GMII_CRC_APPEND 0x10 + #define AX_LEDCTRL 0x73 +#define AX88179A_MAC_ARC_CTRL 0x9E +#define AX88179A_MAC_SWP_CTRL 0xB1 + +#define AX88179A_MAC_TX_PAUSE 0xB2 + +#define AX88179A_MAC_CDC_DELAY_TX 0xB5 + +#define AX88179A_MAC_PATH 0xB7 + #define AX_MAC_RX_PATH_READY 0x01 + #define AX_MAC_TX_PATH_READY 0x02 + +#define AX88179A_NEW_PAUSE_CTRL 0xB8 + #define AX_NEW_PAUSE_EN 0x01 + +#define AX88179A_MAC_BULK_OUT_CTRL 0xB9 + #define AX_MAC_EFF_EN 0x02 + +#define AX88179A_MAC_RX_DATA_CDC_CNT 0xC0 + #define AX_MAC_LSO_ERR_EN 0x04 + #define AX_MAC_MIQFFCTRL_FORMAT 0x10 + #define AX_MAC_MIQFFCTRL_DROP_CRC 0x20 + +#define AX88179A_AUTODETACH_DELAY (5UL << 8) +#define AX88179A_AUTODETACH_EN 1 + +#define AX88179A_MAC_LSO_ENHANCE_CTRL 0xC3 + #define AX_LSO_ENHANCE_EN 0x01 + +#define AX88179A_MAC_TX_HDR_CKSUM 0xCC +#define AX88179A_EP5_EHR 0xF9 + +#define AX_PHY_POWER 0x02 + +#define EPHY_LOW_POWER_EN 0x01 +#define S5_WOL_EN 0x04 +#define S5_WOL_LOW_POWER 0x20 =20 #define GMII_PHY_PHYSR 0x11 #define GMII_PHY_PHYSR_SMASK 0xc000 @@ -157,6 +241,56 @@ #define GMII_PHY_PGSEL_PAGE3 0x0003 #define GMII_PHY_PGSEL_PAGE5 0x0005 =20 +/* TX Descriptor */ +#define AX179A_TX_DESC_LEN_MASK 0x1FFFFF +#define AX179A_TX_DESC_DROP_PADD BIT(28) +#define AX179A_TX_DESC_VLAN BIT(29) +#define AX179A_TX_DESC_MSS_MASK 0x7FFF +#define AX179A_TX_DESC_MSS_SHIFT 0x20 +#define AX179A_TX_DESC_VLAN_MASK 0xFFFF +#define AX179A_TX_DESC_VLAN_SHIFT 0x30 + +/* RX Packet Descriptor */ +#define AX179A_RX_PD_L4_ERR BIT(0) +#define AX179A_RX_PD_L3_ERR BIT(1) +#define AX179A_RX_PD_L4_TYPE_MASK 0x1C +#define AX179A_RX_PD_L4_UDP 0x04 +#define AX179A_RX_PD_L4_TCP 0x10 +#define AX179A_RX_PD_L3_TYPE_MASK 0x60 +#define AX179A_RX_PD_L3_IP 0x20 +#define AX179A_RX_PD_L3_IP6 0x40 + +#define AX179A_RX_PD_VLAN BIT(10) +#define AX179A_RX_PD_RX_OK BIT(11) +#define AX179A_RX_PD_DROP BIT(31) +#define AX179A_RX_PD_LEN_MASK 0x7FFF0000 +#define AX179A_RX_PD_LEN_SHIFT 0x10 +#define AX179A_RX_PD_VLAN_SHIFT 0x20 + +/* RX Descriptor header */ +#define AX179A_RX_DH_PKT_CNT_MASK 0x1FFF +#define AX179A_RX_DH_DESC_OFFSET_MASK 0xFFFFE000 +#define AX179A_RX_DH_DESC_OFFSET_SHIFT 0x0D + +#define AX179A_RX_HW_PAD 0x02 + +#define AX_ADVERTISE_2500 0x1000 + +enum ax_ether_link_speed { + ETHER_LINK_NONE =3D 0, + ETHER_LINK_10 =3D 1, + ETHER_LINK_100 =3D 2, + ETHER_LINK_1000 =3D 3, + ETHER_LINK_2500 =3D 4, +}; + +enum ax_chip_version { + AX_VERSION_INVALID =3D 0x0, + AX_VERSION_AX88179 =3D 0x4, + AX_VERSION_AX88179A =3D 0x6, /* Also AX88772D */ + AX_VERSION_AX88279 =3D 0x7, +}; + struct ax88179_data { u8 eee_enabled; u8 eee_active; @@ -165,6 +299,22 @@ struct ax88179_data { u32 wol_supported; u32 wolopts; u8 disconnecting; + u8 chip_version; + u8 fw_version[4]; + u8 is_ax88772d; + u8 ip_align; + u8 link; + u8 speed; + u8 full_duplex; + u8 rx_checksum; + u8 eeprom_read_cmd; + u8 eeprom_write_cmd; + u8 eeprom_wen; + u16 eeprom_block; + struct mii_bus *mdio; + struct phy_device *phydev; + struct phylink *phylink; + struct phylink_config phylink_config; }; =20 struct ax88179_int_data { @@ -172,6 +322,10 @@ struct ax88179_int_data { __le32 intdata2; }; =20 +struct ax_bulkin_settings { + unsigned char ctrl, timer_l, timer_h, size, ifg; +}; + void ax88179_set_pm_mode(struct usbnet *dev, bool pm_mode); int __ax88179_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, u= 16 size, void *data); int ax88179_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, u16= size, void *data); @@ -192,4 +346,9 @@ int ax88179_set_features(struct net_device *net, netdev= _features_t features); void ax88179_get_mac_addr(struct usbnet *dev); int ax88179_change_mtu(struct net_device *net, int new_mtu); int ax88179_set_mac_addr(struct net_device *net, void *p); + +extern const struct driver_info ax88179a_info; +extern const struct driver_info ax88772d_info; +extern const struct driver_info ax88279_info; + #endif /*__LINUX_USBNET_AX88179_H */ diff --git a/drivers/net/usb/ax88179a_devices.c b/drivers/net/usb/ax88179a_= devices.c new file mode 100644 index 0000000000000000000000000000000000000000..5dac7a137c323ba18375aadd631= f7bad6de22a93 --- /dev/null +++ b/drivers/net/usb/ax88179a_devices.c @@ -0,0 +1,973 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include +#include +#include "ax88179_lib.h" + +#define AX88279_EEPROM_LEN 0x4000 +#define AX88179A_EEPROM_LEN (32 * 20) + +enum ax_bulk_in_speeds { + BULK_IN_SPEED_2G5 =3D 0, + BULK_IN_SPEED_1G_SS =3D 1, + BULK_IN_SPEED_1G_HS =3D 2, + BULK_IN_SPEED_100_FULL_SS =3D 3, + BULK_IN_SPEED_100_HALF_SS =3D 4, + BULK_IN_SPEED_100_FULL_HS =3D 5, + BULK_IN_SPEED_100_HALF_HS =3D 6, + BULK_IN_SPEED_FS =3D 7, +}; + +static const struct ax_bulkin_settings AX88179A_BULKIN_SIZE[] =3D { + [BULK_IN_SPEED_1G_SS] =3D {5, 0x7B, 0x00, 0x17, 0x0F}, + [BULK_IN_SPEED_1G_HS] =3D {5, 0xC0, 0x02, 0x06, 0x0F}, + [BULK_IN_SPEED_100_FULL_SS] =3D {7, 0xF0, 0x00, 0x0C, 0x0F}, + [BULK_IN_SPEED_100_HALF_SS] =3D {6, 0x00, 0x00, 0x06, 0x0F}, + [BULK_IN_SPEED_100_FULL_HS] =3D {5, 0xC0, 0x04, 0x06, 0x0F}, + [BULK_IN_SPEED_100_HALF_HS] =3D {7, 0xC0, 0x04, 0x06, 0x0F}, + [BULK_IN_SPEED_FS] =3D {7, 0x00, 0x00, 0x03, 0x3F}, +}; + +static const struct ax_bulkin_settings AX88772D_BULKIN_SIZE[] =3D { + [BULK_IN_SPEED_100_FULL_HS] =3D {5, 0xC0, 0x04, 0x06, 0x0F}, + [BULK_IN_SPEED_100_HALF_HS] =3D {7, 0xC0, 0x04, 0x06, 0x0F}, + [BULK_IN_SPEED_FS] =3D {7, 0x00, 0x00, 0x03, 0x3F}, +}; + +static const struct ax_bulkin_settings AX88279_BULKIN_SIZE[] =3D { + [BULK_IN_SPEED_2G5] =3D {5, 0x10, 0x01, 0x11, 0x0F}, + [BULK_IN_SPEED_1G_SS] =3D {7, 0xB3, 0x01, 0x11, 0x0F}, + [BULK_IN_SPEED_1G_HS] =3D {7, 0xC0, 0x02, 0x06, 0x0F}, + [BULK_IN_SPEED_100_FULL_SS] =3D {7, 0x80, 0x01, 0x03, 0x0F}, + [BULK_IN_SPEED_100_HALF_SS] =3D {7, 0x80, 0x01, 0x03, 0x0F}, + [BULK_IN_SPEED_100_FULL_HS] =3D {7, 0x80, 0x01, 0x03, 0x0F}, + [BULK_IN_SPEED_100_HALF_HS] =3D {7, 0x80, 0x01, 0x03, 0x0F}, + [BULK_IN_SPEED_FS] =3D {7, 0x00, 0x00, 0x03, 0x3F}, +}; + +static int ax88179_mdiobus_read(struct mii_bus *bus, int phy_id, int regnu= m) +{ + struct usbnet *dev =3D bus->priv; + struct ax88179_data *priv; + u16 res; + + priv =3D dev->driver_priv; + /* When reading PHYSID, return unused PHY-IDs from the ASIX vendor range = */ + if (phy_id =3D=3D AX88179_PHY_ID && regnum =3D=3D MII_PHYSID1) + return 0x003b; + if (phy_id =3D=3D AX88179_PHY_ID && regnum =3D=3D MII_PHYSID2) { + if (priv->chip_version =3D=3D AX_VERSION_AX88179A && priv->is_ax88772d) + return 0x772d; + else if (priv->chip_version =3D=3D AX_VERSION_AX88179A) + return 0x179a; + else if (priv->chip_version =3D=3D AX_VERSION_AX88279) + return 0x2790; + } + + ax88179_read_cmd(dev, AX_ACCESS_PHY, phy_id, (__u16)regnum, 2, &res); + return res; +} + +static int ax88179_mdiobus_write(struct mii_bus *bus, int phy_id, int regn= um, u16 val) +{ + struct usbnet *dev =3D bus->priv; + + return ax88179_write_cmd(dev, AX_ACCESS_PHY, phy_id, (__u16)regnum, 2, &v= al); +} + +static int ax179a_read_mmd(struct usbnet *dev, u16 dev_addr, u16 reg) +{ + u16 res; + int ret; + + ret =3D ax88179_read_cmd(dev, AX88179A_PHY_CLAUSE45, dev_addr, reg, 2, &r= es); + if (ret < 0) + return ret; + return res; +} + +static int ax179a_write_mmd(struct usbnet *dev, u16 dev_addr, u16 reg, u16= data) +{ + return ax88179_write_cmd(dev, AX88179A_PHY_CLAUSE45, dev_addr, reg, 2, &d= ata); +} + +static int ax88179_mdiobus_read_c45(struct mii_bus *bus, int addr, int dev= num, int regnum) +{ + struct usbnet *dev =3D bus->priv; + + if (addr !=3D AX88179_PHY_ID) + return -EINVAL; + + return ax179a_read_mmd(dev, devnum, regnum); +} + +static int ax88179_mdiobus_write_c45(struct mii_bus *bus, int addr, int de= vnum, + int regnum, u16 val) +{ + struct usbnet *dev =3D bus->priv; + + if (addr !=3D AX88179_PHY_ID) + return -EINVAL; + + return ax179a_write_mmd(dev, devnum, regnum, val); +} + +static void ax88179a_status(struct usbnet *dev, struct urb *urb) +{ + struct ax88179_data *data =3D dev->driver_priv; + + if (urb->actual_length < 8) + return; + + phylink_mac_interrupt(data->phylink); +} + +static int ax88179a_auto_detach(struct usbnet *dev) +{ + u16 tmp16; + + tmp16 =3D AX88179A_AUTODETACH_DELAY; + ax88179_write_cmd(dev, AX88179A_AUTODETACH, tmp16, 0, 0, NULL); + return 0; +} + +static void ax88179a_bulkin_config(struct usbnet *dev, u8 link_sts, u8 spe= ed, bool full_duplex) +{ + struct ax88179_data *ax179_data =3D dev->driver_priv; + const struct ax_bulkin_settings *bulkin_data; + int index =3D 0; + + switch (speed) { + case ETHER_LINK_2500: /* AX88279 only */ + index =3D BULK_IN_SPEED_2G5; + break; + + case ETHER_LINK_1000: /* AX88279 & AX88178A */ + if (link_sts & AX_USB_SS) + index =3D BULK_IN_SPEED_1G_SS; + else if (link_sts & AX_USB_HS) + index =3D BULK_IN_SPEED_1G_HS; + break; + + case ETHER_LINK_100: + if (link_sts & AX_USB_SS) + index =3D BULK_IN_SPEED_100_FULL_SS; + else if (link_sts & AX_USB_HS) + index =3D BULK_IN_SPEED_100_FULL_HS; + if (!full_duplex) + index++; + break; + + case ETHER_LINK_10: + index =3D BULK_IN_SPEED_FS; + break; + + default: /* No link */ + index =3D BULK_IN_SPEED_FS; + } + + if (ax179_data->chip_version =3D=3D AX_VERSION_AX88279 && (link_sts & AX_= USB_FS)) + index =3D BULK_IN_SPEED_FS; + + if (ax179_data->chip_version =3D=3D AX_VERSION_AX88279) { + bulkin_data =3D AX88279_BULKIN_SIZE; + } else { + if (ax179_data->is_ax88772d) + bulkin_data =3D AX88772D_BULKIN_SIZE; + else + bulkin_data =3D AX88179A_BULKIN_SIZE; + } + + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_BULKIN_QCTRL, 5, 5, &bulkin_d= ata[index]); +} + +static void ax88179a_get_pauseparam(struct net_device *net, struct ethtool= _pauseparam *pause) +{ + struct ax88179_data *data =3D netdev2data(net); + + phylink_ethtool_get_pauseparam(data->phylink, pause); +} + +static int ax88179a_set_pauseparam(struct net_device *net, struct ethtool_= pauseparam *pause) +{ + struct ax88179_data *data =3D netdev2data(net); + + return phylink_ethtool_set_pauseparam(data->phylink, pause); +} + +static int ax88179a_get_eeprom_len(struct net_device *net) +{ + struct ax88179_data *ax179_data =3D netdev2data(net); + + if (ax179_data->chip_version >=3D AX_VERSION_AX88279) + return AX88279_EEPROM_LEN; + else + return AX88179A_EEPROM_LEN; +} + +static const struct ethtool_ops ax88179a_ethtool_ops =3D { + .get_link =3D ethtool_op_get_link, + .get_msglevel =3D usbnet_get_msglevel, + .set_msglevel =3D usbnet_set_msglevel, + .get_wol =3D ax88179_get_wol, + .set_wol =3D ax88179_set_wol, + .get_eeprom_len =3D ax88179a_get_eeprom_len, + .get_eeprom =3D ax88179_get_eeprom, + .set_eeprom =3D ax88179_set_eeprom, + .nway_reset =3D usbnet_nway_reset, + .get_link_ksettings =3D phy_ethtool_get_link_ksettings, + .set_link_ksettings =3D phy_ethtool_set_link_ksettings, + .get_pauseparam =3D ax88179a_get_pauseparam, + .set_pauseparam =3D ax88179a_set_pauseparam, + .get_ts_info =3D ethtool_op_get_ts_info, +}; + +static void ax88179a_mdio_unregister(struct ax88179_data *data) +{ + mdiobus_unregister(data->mdio); + mdiobus_free(data->mdio); +} + +static int ax88179a_init_phy(struct usbnet *dev) +{ + struct ax88179_data *data =3D dev->driver_priv; + int ret; + + data->phydev =3D mdiobus_get_phy(data->mdio, AX88179_PHY_ID); + if (!data->phydev) { + netdev_err(dev->net, "Could not find PHY\n"); + return -ENODEV; + } + + data->phydev->irq =3D PHY_MAC_INTERRUPT; + ret =3D phylink_connect_phy(data->phylink, data->phydev); + if (ret) { + netdev_err(dev->net, "Could not connect PHY\n"); + return ret; + } + + phy_suspend(data->phydev); + data->phydev->mac_managed_pm =3D true; + + phy_attached_info(data->phydev); + + return 0; +} + +static void ax88179a_mac_config(struct phylink_config *config, unsigned in= t mode, + const struct phylink_link_state *state) +{ + /* Nothing to do */ +} + +static void ax88179a_mac_link_down(struct phylink_config *config, + unsigned int mode, phy_interface_t interface) +{ + /* Nothing to do */ +} + +static void ax88179a_mac_link_up(struct phylink_config *config, + struct phy_device *phy, + unsigned int phy_mode, phy_interface_t interface, + int speed, int duplex, + bool tx_pause, bool rx_pause) +{ + struct usbnet *dev =3D netdev_priv(to_net_dev(config->dev)); + struct ax88179_data *ax179_data =3D dev->driver_priv; + u8 tmp8, link_sts, reg8[3]; + u8 bulk_config_speed =3D 0; + u16 tmp16, mode; + + /* Stop RX/TX for link configuration */ + tmp16 =3D AX_RX_CTL_STOP; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, &tmp16); + tmp8 =3D 0; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_MAC_PATH, 1, 1, &tmp8); + + tmp8 =3D 0xa5; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_MAC_CDC_DELAY_TX, 1, 1, &t= mp8); + + tmp16 =3D 0x0410; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PAUSE_WATERLVL_LOW, 2, 2, &tmp16= ); + + tmp8 =3D 0; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_ETH_TX_GAP, 1, 1, &tmp8); + + tmp8 =3D 0x07; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_EP5_EHR, 1, 1, &tmp8); + + tmp8 =3D 0x28 | AX_NEW_PAUSE_EN; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_NEW_PAUSE_CTRL, 1, 1, &tmp= 8); + + mode =3D AX_MEDIUM_RECEIVE_EN; + if (tx_pause) + mode |=3D AX_MEDIUM_TXFLOW_CTRLEN; + if (rx_pause) + mode |=3D AX_MEDIUM_RXFLOW_CTRLEN; + + switch (speed) { + case SPEED_2500: + reg8[0] =3D 0x00; + reg8[1] =3D 0xF8; + reg8[2] =3D 0x07; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_MAC_TX_PAUSE, 3, 3, reg8); + + reg8[0] =3D 0x78; + reg8[1] =3D (AX_LSOFC_WCNT_7_ACCESS << 5); + reg8[2] =3D 0; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_MAC_RX_STATUS_CDC, 3, 3, = reg8); + + reg8[0] =3D 0x40; + reg8[1] =3D AX_MAC_MIQFFCTRL_FORMAT | AX_MAC_MIQFFCTRL_DROP_CRC | AX_MAC= _LSO_ERR_EN; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_MAC_RX_DATA_CDC_CNT, 2, 2= , reg8); + + tmp8 =3D AX_XGMII_EN; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_BFM_DATA, 1, 1, &tmp8); + + tmp8 =3D 0x1C | AX_LSO_ENHANCE_EN; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_MAC_LSO_ENHANCE_CTRL, 1, = 1, &tmp8); + + mode |=3D AX_MEDIUM_GIGAMODE | AX_MEDIUM_FULL_DUPLEX; + bulk_config_speed =3D ETHER_LINK_2500; + + break; + + case SPEED_1000: + mode |=3D AX_MEDIUM_GIGAMODE; + bulk_config_speed =3D ETHER_LINK_1000; + fallthrough; + + case SPEED_100: + reg8[0] =3D 0x78; + reg8[1] =3D (AX_LSOFC_WCNT_7_ACCESS << 5) | AX_GMII_CRC_APPEND; + reg8[2] =3D 0; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_MAC_RX_STATUS_CDC, 3, 3, = reg8); + + tmp8 =3D 0x40; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_MAC_RX_DATA_CDC_CNT, 1, 1= , &tmp8); + if (!bulk_config_speed) + bulk_config_speed =3D ETHER_LINK_100; + break; + + case SPEED_10: + reg8[0] =3D 0xFA; + reg8[1] =3D (AX_LSOFC_WCNT_7_ACCESS << 5) | AX_GMII_CRC_APPEND; + reg8[2] =3D 0xFF; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_MAC_RX_STATUS_CDC, 3, 3, = reg8); + + tmp8 =3D 0xFA; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_MAC_RX_DATA_CDC_CNT, 1, 1= , &tmp8); + + bulk_config_speed =3D ETHER_LINK_10; + break; + } + + ax88179_read_cmd(dev, AX_ACCESS_MAC, PHYSICAL_LINK_STATUS, 1, 1, &link_st= s); + ax88179a_bulkin_config(dev, link_sts, bulk_config_speed, !!duplex); + + if (ax179_data->chip_version < AX_VERSION_AX88279) { + tmp8 =3D 0; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_BFM_DATA, 1, 1, &tmp8); + } + + if (duplex) + mode |=3D AX_MEDIUM_FULL_DUPLEX; + + if (dev->net->mtu > 1500) + mode |=3D AX_MEDIUM_JUMBO_EN; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, 2, 2, &mode); + + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, &ax179_data->rxctl= ); + + tmp8 =3D AX_MAC_RX_PATH_READY | AX_MAC_TX_PATH_READY; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_MAC_PATH, 1, 1, &tmp8); +} + +static const struct phylink_mac_ops ax88179a_phylink_mac_ops =3D { + .mac_config =3D ax88179a_mac_config, + .mac_link_down =3D ax88179a_mac_link_down, + .mac_link_up =3D ax88179a_mac_link_up, +}; + +static int ax88179a_phylink_setup(struct usbnet *dev) +{ + struct ax88179_data *data =3D dev->driver_priv; + phy_interface_t phy_if_mode; + struct phylink *phylink; + + data->phylink_config.dev =3D &dev->net->dev; + data->phylink_config.type =3D PHYLINK_NETDEV; + data->phylink_config.mac_capabilities =3D MAC_SYM_PAUSE | MAC_ASYM_PAUSE = | MAC_100; + if (data->is_ax88772d) + data->phylink_config.mac_capabilities |=3D MAC_10; + else if (data->chip_version < AX_VERSION_AX88279) + data->phylink_config.mac_capabilities |=3D MAC_10 | MAC_1000; + else + data->phylink_config.mac_capabilities |=3D MAC_1000 | MAC_2500FD; + + if (!data->is_ax88772d) { + data->phylink_config.lpi_capabilities =3D MAC_100FD | MAC_1000FD; + data->phylink_config.eee_enabled_default =3D false; + } + + if (data->chip_version =3D=3D AX_VERSION_AX88279) { + __set_bit(PHY_INTERFACE_MODE_2500BASEX, + data->phylink_config.supported_interfaces); + __set_bit(PHY_INTERFACE_MODE_SGMII, + data->phylink_config.supported_interfaces); + phy_if_mode =3D PHY_INTERFACE_MODE_2500BASEX; + } else { + __set_bit(PHY_INTERFACE_MODE_SGMII, + data->phylink_config.supported_interfaces); + phy_if_mode =3D PHY_INTERFACE_MODE_SGMII; + } + + phylink =3D phylink_create(&data->phylink_config, dev->net->dev.fwnode, + phy_if_mode, &ax88179a_phylink_mac_ops); + if (IS_ERR(phylink)) + return PTR_ERR(phylink); + + data->phylink =3D phylink; + return 0; +} + +static int ax88179a_init_mdio(struct usbnet *dev) +{ + struct ax88179_data *data =3D dev->driver_priv; + int ret; + + data->mdio =3D mdiobus_alloc(); + if (!data->mdio) + return -ENOMEM; + + data->mdio->priv =3D dev; + data->mdio->read =3D ax88179_mdiobus_read; + data->mdio->write =3D ax88179_mdiobus_write; + data->mdio->read_c45 =3D ax88179_mdiobus_read_c45; + data->mdio->write_c45 =3D ax88179_mdiobus_write_c45; + data->mdio->name =3D "AX88179A MDIO Bus"; + data->mdio->phy_mask =3D ~(1 << AX88179_PHY_ID); + /* mii bus name is usb-- */ + snprintf(data->mdio->id, MII_BUS_ID_SIZE, "usb-%03d:%03d", + dev->udev->bus->busnum, dev->udev->devnum); + + ret =3D mdiobus_register(data->mdio); + if (ret) { + netdev_err(dev->net, "Could not register MDIO bus (err %d)\n", ret); + mdiobus_free(data->mdio); + data->mdio =3D NULL; + } + + return ret; +} + +static int ax88179a_mii_ioctl(struct net_device *net, struct ifreq *rq, in= t cmd) +{ + struct ax88179_data *data =3D netdev2data(net); + + return phylink_mii_ioctl(data->phylink, rq, cmd); +} + +static const struct net_device_ops ax88179a_netdev_ops =3D { + .ndo_open =3D usbnet_open, + .ndo_stop =3D usbnet_stop, + .ndo_start_xmit =3D usbnet_start_xmit, + .ndo_tx_timeout =3D usbnet_tx_timeout, + .ndo_get_stats64 =3D dev_get_tstats64, + .ndo_change_mtu =3D ax88179_change_mtu, + .ndo_set_mac_address =3D ax88179_set_mac_addr, + .ndo_validate_addr =3D eth_validate_addr, + .ndo_eth_ioctl =3D ax88179a_mii_ioctl, +}; + +static int ax88179a_bind(struct usbnet *dev, struct usb_interface *intf) +{ + struct usb_device *udev =3D interface_to_usbdev(intf); + struct ax88179_data *ax179_data; + int ret; + u8 reg8; + + /* Check if vendor configuration */ + if (udev->actconfig->desc.bConfigurationValue !=3D 1) { + netdev_info(dev->net, "Switching to vendor mode\n"); + usb_driver_set_configuration(udev, 1); + return -ENODEV; + } + + ret =3D usbnet_get_endpoints(dev, intf); + if (ret < 0) + return ret; + + ax179_data =3D kzalloc_obj(*ax179_data); + if (!ax179_data) + return -ENOMEM; + + dev->driver_priv =3D ax179_data; + + ret =3D ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_CHIP_STATUS, + 1, 1, &ax179_data->chip_version); + if (ret < 0) + goto err_nodev; + + ax179_data->chip_version =3D (ax179_data->chip_version & 0xf0) >> 4; + ax179_data->is_ax88772d =3D 0; + if (ax179_data->chip_version =3D=3D AX_VERSION_AX88179A) { + if (le16_to_cpu(udev->descriptor.bcdDevice) =3D=3D 0x300) + ax179_data->is_ax88772d =3D 1; + } + + for (int i =3D 0; i < 3; i++) { + ret =3D ax88179_read_cmd(dev, AX88179A_ACCESS_BL, (0xFD + i), + 1, 1, &ax179_data->fw_version[i]); + if (ret < 0) + ax179_data->fw_version[i] =3D 0xff; + } + netdev_info(dev->net, "AX88179A/279/772D Chip Version: %x, FW: %d.%d.%d.%= d\n", + ax179_data->chip_version, + ax179_data->fw_version[0], ax179_data->fw_version[1], + ax179_data->fw_version[2], ax179_data->fw_version[3]); + + /* The AX88279 requires both the AX_RX_CTL_IPE and AX_RX_CTL_DROPCRCERR + * bits set in AX_RX_CTL for creating correct RX-URBs. AX_RX_CTL_DROPCRCE= RR + * is anyway set for all chips, make sure AX_RX_CTL_IPE is set via ip_ali= gn. + * Also configure eeprom access parameters. + */ + if (ax179_data->chip_version =3D=3D AX_VERSION_AX88279) { + ax179_data->ip_align =3D 1; + ax179_data->eeprom_read_cmd =3D AX88179A_FLASH_READ; + ax179_data->eeprom_write_cmd =3D AX88179A_FLASH_WRITE; + ax179_data->eeprom_block =3D 256; + ax179_data->eeprom_wen =3D 1; + } else { + ax179_data->ip_align =3D 0; + ax179_data->eeprom_read_cmd =3D AX_ACCESS_EFUS; + ax179_data->eeprom_write_cmd =3D AX_ACCESS_EFUS; + ax179_data->eeprom_block =3D 20; + ax179_data->eeprom_wen =3D 0; + } + + dev->net->netdev_ops =3D &ax88179a_netdev_ops; + dev->net->ethtool_ops =3D &ax88179a_ethtool_ops; + dev->net->needed_headroom =3D 8; + dev->net->needed_tailroom =3D 8; + dev->net->min_mtu =3D ETH_MIN_MTU; + dev->hard_mtu =3D 9 * 1024; + dev->net->max_mtu =3D dev->hard_mtu - dev->net->hard_header_len; + + if (!ax179_data->is_ax88772d) + dev->mii.supports_gmii =3D 1; + + dev->net->features |=3D NETIF_F_SG | NETIF_F_IP_CSUM | + NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM | NETIF_F_TSO | + NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX | + NETIF_F_HW_VLAN_CTAG_FILTER; + + dev->net->hw_features |=3D dev->net->features; + + dev->net->vlan_features =3D NETIF_F_SG | NETIF_F_IP_CSUM | + NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM | NETIF_F_TSO; + + netif_set_tso_max_size(dev->net, 16384); + + /* Enable Transmission of Link Speed byte in interrupt URB */ + ax88179_write_cmd(dev, AX_FW_MODE, AX_FW_MODE_179A, 0, 0, NULL); + ax88179_write_cmd(dev, AX_RELOAD_EEPROM_EFUSE, 0, 0, 0, NULL); + + /* Read MAC address from DTB or ASIX chip */ + ax88179_get_mac_addr(dev); + memcpy(dev->net->perm_addr, dev->net->dev_addr, ETH_ALEN); + + /* Power PHY for probing */ + reg8 =3D AX_PHY_POWER; + ax88179_write_cmd(dev, AX88179A_PHY_POWER, 0, 0, 1, ®8); + msleep(250); + + ret =3D ax88179a_init_mdio(dev); + if (ret) + goto err_nodev; + + ret =3D ax88179a_phylink_setup(dev); + if (ret) + goto phylink_err; + + ret =3D ax88179a_init_phy(dev); + if (ret) + goto initphy_err; + + return 0; + +initphy_err: + phylink_destroy(ax179_data->phylink); +phylink_err: + ax88179a_mdio_unregister(ax179_data); +err_nodev: + kfree(ax179_data); + ax179_data =3D NULL; + + return ret; +} + +static void ax88179a_unbind(struct usbnet *dev, struct usb_interface *intf) +{ + struct ax88179_data *ax179_data =3D dev->driver_priv; + u16 tmp16; + u8 tmp8; + + /* Configure RX control register =3D> stop operation */ + tmp16 =3D AX_RX_CTL_STOP; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, &tmp16); + + rtnl_lock(); + phylink_disconnect_phy(ax179_data->phylink); + rtnl_unlock(); + phylink_destroy(ax179_data->phylink); + ax88179a_mdio_unregister(ax179_data); + + tmp8 =3D 0; + ax88179_write_cmd(dev, AX88179A_PHY_POWER, 0, 0, 1, &tmp8); + + kfree(ax179_data); +} + +static void ax88179a_rx_checksum(struct sk_buff *skb, u64 pkt_desc) +{ + u32 pkt_type; + + skb->ip_summed =3D CHECKSUM_NONE; + /* checksum error bit is set */ + if (pkt_desc & AX179A_RX_PD_L4_ERR || pkt_desc & AX179A_RX_PD_L3_ERR) + return; + + pkt_type =3D pkt_desc & AX179A_RX_PD_L4_TYPE_MASK; + /* It must be a TCP or UDP packet with a valid checksum */ + if (pkt_type =3D=3D AX179A_RX_PD_L4_TCP || pkt_type =3D=3D AX179A_RX_PD_L= 4_UDP) + skb->ip_summed =3D CHECKSUM_UNNECESSARY; +} + +static int ax88179a_rx_fixup(struct usbnet *dev, struct sk_buff *skb) +{ + struct ax88179_data *ax179_data =3D dev->driver_priv; + struct sk_buff *ax_skb; + u32 hdr_off, pkt_end; + u64 *pkt_desc_ptr; + u16 vlan_tag; + u16 pkt_cnt; + u64 rx_hdr; + + /* SKB contents for AX179A-based chips: + * + * ... + * + * + * ... + * + * + * + * where: + * contains pkt_len data bytes and padding: + * 2 bytes of IP alignment (optional, depends on AX_RX_CTL_IPE flag) + * packet data received + * optional padding to 8-bytes boundary + * contains 8 bytes: + * pkt_len and fields AX_RXHDR_* + * contains 8 bytes: + * pkt_cnt and hdr_off (offset of ) + * + * pkt_cnt is number of entries in the per-packet metadata array. + */ + + if (!skb || skb->len < sizeof(rx_hdr)) + goto err; + + /* RX Descriptor Header */ + skb_trim(skb, skb->len - sizeof(rx_hdr)); + rx_hdr =3D *(u64 *)skb_tail_pointer(skb); + + /* Check these packets */ + hdr_off =3D (rx_hdr & AX179A_RX_DH_DESC_OFFSET_MASK) >> AX179A_RX_DH_DESC= _OFFSET_SHIFT; + pkt_cnt =3D rx_hdr & AX179A_RX_DH_PKT_CNT_MASK; + + /* Consistency check header position */ + if (hdr_off !=3D skb->len - (pkt_cnt * sizeof(rx_hdr))) + goto err; + + /* Make sure that the bounds of the metadata array are inside the SKB + * (and in front of the counter at the end). + */ + if (pkt_cnt * 8 + hdr_off > skb->len) + goto err; + + /* Packets must not overlap the metadata array */ + skb_trim(skb, hdr_off); + + if (!pkt_cnt) + goto err; + + /* Get the first RX packet descriptor */ + pkt_desc_ptr =3D (u64 *)(skb->data + hdr_off); + le64_to_cpus(pkt_desc_ptr); + + pkt_end =3D 0; + while (pkt_cnt--) { + u64 pkt_desc =3D *pkt_desc_ptr; + u32 pkt_len_plus_padd; + u32 pkt_len; + + pkt_len =3D (u32)((pkt_desc & AX179A_RX_PD_LEN_MASK) >> AX179A_RX_PD_LEN= _SHIFT) + - (ax179_data->ip_align ? 2 : 0); + pkt_len_plus_padd =3D ((pkt_len + 7 + (ax179_data->ip_align ? 2 : 0)) & = 0x7FFF8); + + pkt_end +=3D pkt_len_plus_padd; + if (pkt_end > hdr_off || (pkt_cnt =3D=3D 0 && pkt_end !=3D hdr_off)) + goto err; + + if (pkt_desc & AX179A_RX_PD_DROP || !(pkt_desc & AX179A_RX_PD_RX_OK) || + pkt_len > (dev->hard_mtu + AX179A_RX_HW_PAD)) { + skb_pull(skb, pkt_len_plus_padd); + + /* Next RX Packet Descriptor */ + pkt_desc_ptr++; + continue; + } + + ax_skb =3D netdev_alloc_skb_ip_align(dev->net, pkt_len); + if (!ax_skb) + goto err; + + skb_put(ax_skb, pkt_len); + memcpy(ax_skb->data, skb->data + (ax179_data->ip_align ? AX179A_RX_HW_PA= D : 0), + pkt_len); + + if (ax179_data->rx_checksum) + ax88179a_rx_checksum(ax_skb, pkt_desc); + + if (pkt_desc & AX179A_RX_PD_VLAN) { + vlan_tag =3D pkt_desc >> AX179A_RX_PD_VLAN_SHIFT; + __vlan_hwaccel_put_tag(ax_skb, htons(ETH_P_8021Q), vlan_tag); + } + + usbnet_skb_return(dev, ax_skb); + skb_pull(skb, pkt_len_plus_padd); + + /* Next RX Packet Header */ + pkt_desc_ptr++; + } + + return 1; + +err: + return 0; +} + +static struct sk_buff *ax88179a_tx_fixup(struct usbnet *dev, struct sk_buf= f *skb, gfp_t flags) +{ + u64 tx_desc =3D skb->len & AX179A_TX_DESC_LEN_MASK; + int frame_size =3D dev->maxpacket; + struct sk_buff *ax_skb; + u64 *tx_desc_ptr; + int padding_size; + int headroom; + int tailroom; + u16 tci =3D 0; + + /* TSO MSS */ + tx_desc |=3D ((u64)(skb_shinfo(skb)->gso_size & AX179A_TX_DESC_MSS_MASK))= << + AX179A_TX_DESC_MSS_SHIFT; + + headroom =3D (skb->len + sizeof(tx_desc)) % 8; + padding_size =3D headroom ? 8 - headroom : 0; + + if (((skb->len + sizeof(tx_desc) + padding_size) % frame_size) =3D=3D 0) { + padding_size +=3D 8; + tx_desc |=3D AX179A_TX_DESC_DROP_PADD; + } + + if ((dev->net->features & NETIF_F_HW_VLAN_CTAG_TX) && (vlan_get_tag(skb, = &tci) >=3D 0)) { + tx_desc |=3D AX179A_TX_DESC_VLAN; + tx_desc |=3D ((u64)tci & AX179A_TX_DESC_VLAN_MASK) << AX179A_TX_DESC_VLA= N_SHIFT; + } + + if (!dev->can_dma_sg && (dev->net->features & NETIF_F_SG) && skb_lineariz= e(skb)) { + dev_kfree_skb_any(skb); + return NULL; + } + + headroom =3D skb_headroom(skb); + tailroom =3D skb_tailroom(skb); + + if (!(headroom >=3D sizeof(tx_desc) && tailroom >=3D padding_size)) { + ax_skb =3D skb_copy_expand(skb, sizeof(tx_desc), padding_size, flags); + dev_kfree_skb_any(skb); + skb =3D ax_skb; + if (!skb) + return NULL; + } + if (padding_size !=3D 0) + skb_put_zero(skb, padding_size); + /* Copy TX header */ + tx_desc_ptr =3D skb_push(skb, sizeof(tx_desc)); + put_unaligned_le64(tx_desc, tx_desc_ptr); + + usbnet_set_skb_tx_stats(skb, 1, 0); + + return skb; +} + +static int ax88179a_reset(struct usbnet *dev) +{ + struct ax88179_data *ax179_data =3D dev->driver_priv; + u16 *tmp16; + u8 buf[5]; + u8 *tmp; + + tmp16 =3D (u16 *)buf; + tmp =3D (u8 *)buf; + + /* Power up ethernet PHY */ + *tmp =3D AX_PHY_POWER; + ax88179_write_cmd(dev, AX88179A_PHY_POWER, 0, 0, 1, tmp); + msleep(250); + + /* Ethernet PHY Auto Detach*/ + ax88179a_auto_detach(dev); + + *tmp =3D AX_MAC_EFF_EN; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_MAC_BULK_OUT_CTRL, 1, 1, t= mp); + + *tmp16 =3D 0; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, tmp16); + + *tmp =3D 0x04; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PAUSE_WATERLVL_LOW, 1, 1, tmp); + *tmp =3D 0x10; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PAUSE_WATERLVL_HIGH, 1, 1, tmp); + + *tmp =3D 0; + if (dev->net->features & NETIF_F_HW_VLAN_CTAG_FILTER) + *tmp |=3D AX_VLAN_CONTROL_VFE; + if (dev->net->features & NETIF_F_HW_VLAN_CTAG_RX) + *tmp |=3D AX_VLAN_CONTROL_VSO; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_CONTROL, 1, 1, tmp= ); + + *tmp =3D 0xff; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_MAC_BM_INT_MASK, 1, 1, tmp= ); + + *tmp =3D 0; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_MAC_BM_RX_DMA_CTL, 1, 1, t= mp); + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_MAC_BM_TX_DMA_CTL, 1, 1, t= mp); + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_MAC_ARC_CTRL, 1, 1, tmp); + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_MAC_SWP_CTRL, 1, 1, tmp); + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_MAC_TX_HDR_CKSUM, 1, 1, tm= p); + + /* Read MAC address from DTB or asix chip */ + ax88179_get_mac_addr(dev); + memcpy(dev->net->perm_addr, dev->net->dev_addr, ETH_ALEN); + + /* The Bulk-Register configuration for the AX88179A is done in + * ax88179a_mac_link_up(), once the link is up for a given link and USB-s= peed. + */ + if (ax179_data->is_ax88772d) + dev->rx_urb_size =3D 1024 * 24; + else + dev->rx_urb_size =3D 1024 * 48; + + /* Enable checksum offload */ + *tmp =3D AX_RXCOE_IP | AX_RXCOE_TCP | AX_RXCOE_UDP | + AX_RXCOE_TCPV6 | AX_RXCOE_UDPV6; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RXCOE_CTL, 1, 1, tmp); + ax179_data->rx_checksum =3D 1; + + *tmp =3D AX_TXCOE_IP | AX_TXCOE_TCP | AX_TXCOE_UDP | + AX_TXCOE_TCPV6 | AX_TXCOE_UDPV6; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, tmp); + + /* Configure RX control register =3D> start operation */ + ax179_data->rxctl =3D AX_RX_CTL_DROPCRCERR | AX_RX_CTL_START | + AX_RX_CTL_AP | AX_RX_CTL_AMALL | AX_RX_CTL_AB; + if (ax179_data->ip_align) + ax179_data->rxctl |=3D AX_RX_CTL_IPE; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, &ax179_data->rxctl= ); + + if (ax179_data->chip_version < AX_VERSION_AX88179A) + *tmp =3D AX_MONITOR_MODE_PMETYPE | AX_MONITOR_MODE_PMEPOL | AX_MONITOR_M= ODE_RWMP; + else + *tmp =3D AX_MONITOR_MODE_RWMP; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MOD, 1, 1, tmp); + + /* Configure default medium type =3D> giga */ + *tmp16 =3D AX_MEDIUM_RECEIVE_EN | AX_MEDIUM_TXFLOW_CTRLEN | + AX_MEDIUM_RXFLOW_CTRLEN | AX_MEDIUM_FULL_DUPLEX; + if (!ax179_data->is_ax88772d) + *tmp16 |=3D AX_MEDIUM_GIGAMODE; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, 2, 2, tmp16); + + /* Check if WoL is supported */ + ax179_data->wol_supported =3D 0; + if (ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MOD, + 1, 1, &tmp) > 0) + ax179_data->wol_supported =3D WAKE_MAGIC | WAKE_PHY; + + phylink_start(ax179_data->phylink); + + usbnet_link_change(dev, 0, 0); + + return 0; +} + +static int ax88179a_stop(struct usbnet *dev) +{ + struct ax88179_data *ax179_data =3D dev->driver_priv; + u16 reg16; + u8 reg8; + + ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, 2, 2, ®16); + reg16 &=3D ~AX_MEDIUM_RECEIVE_EN; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, 2, 2, ®16= ); + + reg16 =3D 0; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, ®16); + + reg8 =3D 0; + ax88179_read_cmd(dev, AX88179A_PHY_POWER, 0, 0, 1, ®8); + + phylink_stop(ax179_data->phylink); + + return 0; +} + +const struct driver_info ax88179a_info =3D { + .description =3D "ASIX AX88179A USB 3.2 Gigabit Ethernet", + .bind =3D ax88179a_bind, + .unbind =3D ax88179a_unbind, + .status =3D ax88179a_status, + .reset =3D ax88179a_reset, + .stop =3D ax88179a_stop, + .flags =3D FLAG_ETHER | FLAG_FRAMING_AX | FLAG_MULTI_PACKET | FLAG_AVOID_= UNLINK_URBS, + .rx_fixup =3D ax88179a_rx_fixup, + .tx_fixup =3D ax88179a_tx_fixup, +}; + +const struct driver_info ax88772d_info =3D { + .description =3D "ASIX AX88772D/E USB 2.0 Fast Ethernet", + .bind =3D ax88179a_bind, + .unbind =3D ax88179a_unbind, + .status =3D ax88179a_status, + .reset =3D ax88179a_reset, + .stop =3D ax88179a_stop, + .flags =3D FLAG_ETHER | FLAG_FRAMING_AX | FLAG_MULTI_PACKET | FLAG_AVOID_= UNLINK_URBS, + .rx_fixup =3D ax88179a_rx_fixup, + .tx_fixup =3D ax88179a_tx_fixup, +}; + +const struct driver_info ax88279_info =3D { + .description =3D "ASIX AX88279 USB 3.2 2.5Gigabit Ethernet", + .bind =3D ax88179a_bind, + .unbind =3D ax88179a_unbind, + .status =3D ax88179a_status, + .reset =3D ax88179a_reset, + .stop =3D ax88179a_stop, + .flags =3D FLAG_ETHER | FLAG_FRAMING_AX | FLAG_MULTI_PACKET | FLAG_AVOID_= UNLINK_URBS, + .rx_fixup =3D ax88179a_rx_fixup, + .tx_fixup =3D ax88179a_tx_fixup, +}; --=20 2.47.3 From nobody Fri Sep 25 06:47:57 2026 Received: from bkemail.birger-koblitz.de (bkemail.birger-koblitz.de [23.88.97.239]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 04BD9399013; Wed, 16 Sep 2026 03:24:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=23.88.97.239 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789529092; cv=none; b=F3rnAxhXFSfZSI5wIc//zs2wXMNLOAXsxnD2wd/9CqQue2YrXuRpZNh+rEUR2NAsJmDQ09H5akSp/XcFso5x5zI5833s8VnslzREJU3qtWOiTfIHuBinlkRcS5PIe9ZYMm425JODIIfJuutHrh/FYWeO7u0MdMs9lgz6KrtPbQo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789529092; c=relaxed/simple; bh=LgT2j6yqRy2OxDj7YnSkWiMKWiluE/LZmQEYV7eqCVM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=tec/P82+QZBB+nVfhLMBJCc7rEbKsFH2HFSh6B5E+gaLkQShxV+N+WeNjbox4tAG/ws192PzR+Fn5mIvoHnjBG0KbDyqK4mYChScw7obifSLdbXTGRTY/IeBMbSg8b6z+sPQD1/Gtb9rHAg4LxV3Li8y9t5hKmBUJAuwUhMQMd8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=birger-koblitz.de; spf=pass smtp.mailfrom=birger-koblitz.de; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b=aTIWzxfc; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b=Bl/y9hgz; arc=none smtp.client-ip=23.88.97.239 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=birger-koblitz.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=birger-koblitz.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b="aTIWzxfc"; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b="Bl/y9hgz" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=birger-koblitz.de; s=default; t=1789529089; bh=LgT2j6yqRy2OxDj7YnSkWiMKWiluE/LZmQEYV7eqCVM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=aTIWzxfcBL9RgCSShzvcUmzEzCKXX2otogmwNh49XpwzFSs/nOM07PMAyr6m3VYsl jHNsWRs88NnzWgd0+2PnzPjEJ1IgFv0x3kifBu07cmscADOTJop/jo6C7HWdeafLii iGt6lwHFV+w58dgFBXAxEOlXCByMM7VLCyUpbunQJtbfQpVTzOUrykSx02wpfkcTFv ztKC6QmLV6aklZSA7gZjU8SsrnH4HzI+C0o77BEfSW6BOQ4ZuembhuG3hTMSjzkCqk Epja/JUvRzIc43PKJ+QH+nJA21bcstzEXx1eYSjcp6kIfSnJoNSH0W24bC1gAXi7dR +HGymMqREoDbw== Received: by bkemail.birger-koblitz.de (Postfix, from userid 109) id 4CD333FA75; Wed, 16 Sep 2026 03:24:49 +0000 (UTC) X-Spam-Level: DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=birger-koblitz.de; s=default; t=1789529088; bh=LgT2j6yqRy2OxDj7YnSkWiMKWiluE/LZmQEYV7eqCVM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Bl/y9hgzdHtDNxD5ot+IPZBXJ2MX0h+t4J/Qv29MFt4S+ToNmYVgMj6/2fQDE4qY0 G5wE/onUX7MVNXiCIu6Yf0ynkKkeNqBqhdCUNN6guSIdAIorPH6mszEWviYpZ8POjb bTzo2HBiUOfNKMIPiC1J4PuPrR8da7QHw9LvC1xEl82V9nUGBCRFhz3vOjPDvyKrPo c9QgRH8gmT9a+A33PCyJ2EpdGQ2Wei2M9ANY+m5xU3TownRNyc0Ze2PXrmT3M66Jou 7tYmsVOSaF/jddkQB1ER0zZGZ+MmDo5kQubA72rHLr5b57J3bFrrFm/TgHTUXaEQfi /qDej+HEVTidA== Received: from DELLLaptop.net (unknown [223.86.26.228]) by bkemail.birger-koblitz.de (Postfix) with ESMTPSA id 50C273F6DB; Wed, 16 Sep 2026 03:24:43 +0000 (UTC) From: Birger Koblitz Date: Wed, 16 Sep 2026 05:24:06 +0200 Subject: [PATCH net-next v12 07/15] ax88179_178a: Add EEE configuration support for AX88179A MACs Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260916-ax88179a-v12-7-60c04c9924a2@birger-koblitz.de> References: <20260916-ax88179a-v12-0-60c04c9924a2@birger-koblitz.de> In-Reply-To: <20260916-ax88179a-v12-0-60c04c9924a2@birger-koblitz.de> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Russell King , Andrew Lunn , Heiner Kallweit Cc: linux-usb@vger.kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Birger Koblitz , Jianhui Xu X-Mailer: b4 0.14.2 The AX88179A uses a simple HW configuration for EEE via a single EEE configuration register without LPI timer support Add support for this EEE enable/disable register and replace the EEE. Signed-off-by: Birger Koblitz Reviewed-by: Andrew Lunn Tested-by: Jianhui Xu --- drivers/net/usb/ax88179a_devices.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/net/usb/ax88179a_devices.c b/drivers/net/usb/ax88179a_= devices.c index 5dac7a137c323ba18375aadd631f7bad6de22a93..785919e14e861e5e44a67a74076= 90a0cd8ddb180 100644 --- a/drivers/net/usb/ax88179a_devices.c +++ b/drivers/net/usb/ax88179a_devices.c @@ -384,10 +384,27 @@ static void ax88179a_mac_link_up(struct phylink_confi= g *config, ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_MAC_PATH, 1, 1, &tmp8); } =20 +static void ax88179a_mac_disable_tx_lpi(struct phylink_config *config) +{ + struct usbnet *dev =3D netdev_priv(to_net_dev(config->dev)); + + ax88179_write_cmd(dev, AX_GPHY_CTL, AX_GPHY_EEE_CTRL, false, 0, NULL); +} + +static int ax88179a_mac_enable_tx_lpi(struct phylink_config *config, u32 t= imer, bool tx_clk_stop) +{ + struct usbnet *dev =3D netdev_priv(to_net_dev(config->dev)); + + /* AX88179A does not provide LPI timer registers */ + return ax88179_write_cmd(dev, AX_GPHY_CTL, AX_GPHY_EEE_CTRL, true, 0, NUL= L); +} + static const struct phylink_mac_ops ax88179a_phylink_mac_ops =3D { .mac_config =3D ax88179a_mac_config, .mac_link_down =3D ax88179a_mac_link_down, .mac_link_up =3D ax88179a_mac_link_up, + .mac_disable_tx_lpi =3D ax88179a_mac_disable_tx_lpi, + .mac_enable_tx_lpi =3D ax88179a_mac_enable_tx_lpi, }; =20 static int ax88179a_phylink_setup(struct usbnet *dev) --=20 2.47.3 From nobody Fri Sep 25 06:47:57 2026 Received: from bkemail.birger-koblitz.de (bkemail.birger-koblitz.de [23.88.97.239]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 27AB83B7B70; Wed, 16 Sep 2026 03:24:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=23.88.97.239 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789529098; cv=none; b=J6dmkN1KmQ8MuP2PtnYTZ2T6llk9gPQgqWgtROJH5veDXD4XTapDuK5zO/l9Xewq5SCGiiS7+UzjBeKHpzKSeMk0aDYsniAfS8OnBYPHJD/24Ukad1FPAyuhpUTO2b9qhIMSxd/ZoWaqf3Uozu3iS79SSpCf0wIZWrsydjTmZhU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789529098; c=relaxed/simple; bh=E86tN22/K+HeBlTbVmZcHbD38nvcSu04QMpPK2iR/dw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ujXQsNOjwGfDAENlpAXrrXQzDMsFd66MAjA3BonHcE64e7q50m73oxgJZVnpXjj7aaLG6Hh92XoJUCQ0yPaMD5TKmpvaLsZoIzWvwx9+UVlIL1raewGejwW5FC2F1Qtkw32P2cLTieanZ9bKfpkL7EdKX6C/UwGzJ0GlayqU7PI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=birger-koblitz.de; spf=pass smtp.mailfrom=birger-koblitz.de; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b=jaBTnaCX; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b=kuK/NGW6; arc=none smtp.client-ip=23.88.97.239 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=birger-koblitz.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=birger-koblitz.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b="jaBTnaCX"; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b="kuK/NGW6" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=birger-koblitz.de; s=default; t=1789529094; bh=E86tN22/K+HeBlTbVmZcHbD38nvcSu04QMpPK2iR/dw=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=jaBTnaCX+Hj4WacRXZIrlm17qopqqZlGHHqG1XbKOh3jA3Wa+tKN9d0pyRRU6qXNO hBYvHjiGRXma7qFg0IuMPjOouGFd0ItXQIciFk7SWS8PJTPcsRrZbNTVrH+6om5gp7 kDWe+9yYUcReAOkbaxs0FkifREXe95+x3pVge4PNqwEQkziTkcA8BZQVQcfHdwSjXm F4gxQqtvOcfCDQAqwvI3Jw3iZZ3lJGH33UYmkU9CNcPUNSbqWjdnWeddEo0sPtfJ/W XlhLzvrdMVAYrp3NCDI6o5fISI+IU6SrnUJ4xwGw+ZyG/dvMxpOtWfo62u7FVB0hIu 3SrRt59v7lBsw== Received: by bkemail.birger-koblitz.de (Postfix, from userid 109) id 6A9363FA6E; Wed, 16 Sep 2026 03:24:54 +0000 (UTC) X-Spam-Level: DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=birger-koblitz.de; s=default; t=1789529093; bh=E86tN22/K+HeBlTbVmZcHbD38nvcSu04QMpPK2iR/dw=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=kuK/NGW6XyuhXf5VgNEcQ8cJaMcOGmkDFW2fk6lk5VHeAfq11xvzPxa6JV6yY2EAa U8nP3jn4DpUj3DHiw0kU/5KwKLOJhfKN4TkfQwAgY8GopJ1s5fKxtRPtCEukHuqwPb TiLF5FFfVMB5HnljTtPwVcfWatHQsYFrclSEOblTxoQezyQedg2+fxdnKxyh9WID6j Fo7xDH9SRmMCrwAuNJPZwH0bfac/YYvkKHmKOCHXxdOb3QEewdtPYMKliLFcO4qqfj TFdKKglYGS1vRWMHIovywHhlyluy8jmtdKO8GXxE3QuvYoJJ04U9B1kp+eBgYLZreJ F2gj7F+VHSe+Q== Received: from DELLLaptop.net (unknown [223.86.26.228]) by bkemail.birger-koblitz.de (Postfix) with ESMTPSA id 0C18B3FA6F; Wed, 16 Sep 2026 03:24:48 +0000 (UTC) From: Birger Koblitz Date: Wed, 16 Sep 2026 05:24:07 +0200 Subject: [PATCH net-next v12 08/15] ax88179_178a: Add EEE configuration support for AX88179A PHYs Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260916-ax88179a-v12-8-60c04c9924a2@birger-koblitz.de> References: <20260916-ax88179a-v12-0-60c04c9924a2@birger-koblitz.de> In-Reply-To: <20260916-ax88179a-v12-0-60c04c9924a2@birger-koblitz.de> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Russell King , Andrew Lunn , Heiner Kallweit Cc: linux-usb@vger.kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Birger Koblitz , Jianhui Xu , Nicolai Buchwitz X-Mailer: b4 0.14.2 Configure phylink to work with the PHYs in the AX88197A controllers and provide ethtool get/set eee operations calling into phylink. Signed-off-by: Birger Koblitz Reviewed-by: Andrew Lunn Reviewed-by: Nicolai Buchwitz Tested-by: Jianhui Xu --- drivers/net/usb/ax88179a_devices.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/net/usb/ax88179a_devices.c b/drivers/net/usb/ax88179a_= devices.c index 785919e14e861e5e44a67a7407690a0cd8ddb180..6bf1ac17aa1d5abfc854eb3ac08= 96c69875ea0d7 100644 --- a/drivers/net/usb/ax88179a_devices.c +++ b/drivers/net/usb/ax88179a_devices.c @@ -206,6 +206,20 @@ static int ax88179a_get_eeprom_len(struct net_device *= net) return AX88179A_EEPROM_LEN; } =20 +static int ax88179a_get_eee(struct net_device *net, struct ethtool_keee *e= data) +{ + struct ax88179_data *ax179_data =3D netdev2data(net); + + return phylink_ethtool_get_eee(ax179_data->phylink, edata); +} + +static int ax88179a_set_eee(struct net_device *net, struct ethtool_keee *e= data) +{ + struct ax88179_data *ax179_data =3D netdev2data(net); + + return phylink_ethtool_set_eee(ax179_data->phylink, edata); +} + static const struct ethtool_ops ax88179a_ethtool_ops =3D { .get_link =3D ethtool_op_get_link, .get_msglevel =3D usbnet_get_msglevel, @@ -215,6 +229,8 @@ static const struct ethtool_ops ax88179a_ethtool_ops = =3D { .get_eeprom_len =3D ax88179a_get_eeprom_len, .get_eeprom =3D ax88179_get_eeprom, .set_eeprom =3D ax88179_set_eeprom, + .get_eee =3D ax88179a_get_eee, + .set_eee =3D ax88179a_set_eee, .nway_reset =3D usbnet_nway_reset, .get_link_ksettings =3D phy_ethtool_get_link_ksettings, .set_link_ksettings =3D phy_ethtool_set_link_ksettings, @@ -440,6 +456,10 @@ static int ax88179a_phylink_setup(struct usbnet *dev) phy_if_mode =3D PHY_INTERFACE_MODE_SGMII; } =20 + memcpy(data->phylink_config.lpi_interfaces, + data->phylink_config.supported_interfaces, + sizeof(data->phylink_config.lpi_interfaces)); + phylink =3D phylink_create(&data->phylink_config, dev->net->dev.fwnode, phy_if_mode, &ax88179a_phylink_mac_ops); if (IS_ERR(phylink)) --=20 2.47.3 From nobody Fri Sep 25 06:47:57 2026 Received: from bkemail.birger-koblitz.de (bkemail.birger-koblitz.de [23.88.97.239]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3E18B3C0A11; Wed, 16 Sep 2026 03:25:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=23.88.97.239 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789529103; cv=none; b=URFpolF6JLhCr9lNuEne6/TbEz4kbuXC0llJREdsyMM96sVWxIFwZzVywO9Y65m/WPUzIjkZgkBc27t5FgPBZLD5jkoV9LK7MHvXcoEmPCSpkqNXmGXV+3qJ0IxgYElftH5nFL4F9OsYu/NirMgWzBUuuWN/FKw+ys5mmGyTl3Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789529103; c=relaxed/simple; bh=U50kM65lOf2Bb8OvBkSl2nDfzU//rlKGj0rtbqYTKWI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Dy+j/lgm2nTTBEsRzA1YOGPqMhCUBJ6Dxd1PhGiVcb3NSBJd+isVmEuQ/ivj0FtEi3OgyDtnJS5f4PLrxakMZSRO3ydZrm5Klt27iKvKOPK7UvoPnwnzGe14Pp/aaMODQxR4IdkTdiWZc5PFJ2Y6/UdAyOo4uKipIvKDOQbxNS4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=birger-koblitz.de; spf=pass smtp.mailfrom=birger-koblitz.de; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b=o9gaf9AC; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b=Jm2ooWIx; arc=none smtp.client-ip=23.88.97.239 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=birger-koblitz.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=birger-koblitz.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b="o9gaf9AC"; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b="Jm2ooWIx" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=birger-koblitz.de; s=default; t=1789529099; bh=U50kM65lOf2Bb8OvBkSl2nDfzU//rlKGj0rtbqYTKWI=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=o9gaf9ACrODGm0JPF0N9MJ8s65+3GHEtWEDeFg0avDt+s6UtlgoXVIf4C3j+/Xdbi a3bjSJ5DCdVDhOi2/B5qUVRDOYbxNtGWPXZXr6IWRMZ0R0kBuDRSnV7WPF3arTCeCB nVLSS7QftULgi4SrtT3OTjeOj6LpXELhGsSN4lsyAr0f++P0US5R605ICcrcrqxpfW nFfnVxNHnx/CQK4iKG4ekwN/XHSnRfAEoZEVPS0SuJCspOePgsa3ihSurSmF9iMM3b 6MC14v2eUbtLPuD7A3pyZ5bPZ4MEPNNieAWtGcmW+Z5kbBS3vYACuci9AiqyoKOoG5 rBNxhJ1EVEBBQ== Received: by bkemail.birger-koblitz.de (Postfix, from userid 109) id 1D0D03FA6F; Wed, 16 Sep 2026 03:24:59 +0000 (UTC) X-Spam-Level: DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=birger-koblitz.de; s=default; t=1789529098; bh=U50kM65lOf2Bb8OvBkSl2nDfzU//rlKGj0rtbqYTKWI=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Jm2ooWIxxx7VFXcOUah/M1ylkm0eW4NUaqln2pjRhXZ1LLFo3jGJKSlc5qaeHXFcB 4Zx6JmtyR7WaEzur7vLB4SZ1GSs+uPT5xbk5qxYdmBjcwB+gtaTfp2mPgpXEU68jYY tHQOUTcngNyuGHRK+KAmFPs2h9ZwPEmjxbBXMSNnubBZlNTCSkZrAKm/5+r0M9I53K B1Ji9bwNX+IwEKZVY2/+pLIaKfw4N95eX/aKN40618AAG8V9d8zzJml4hg+FbkSVdi hIvo2H/oNM8UcIdrX+oWdPIfzktBmy4o99q0OUDNa15G3xjotn7DJTH0fAj59cY3O+ Obk5gAM6lXSsQ== Received: from DELLLaptop.net (unknown [223.86.26.228]) by bkemail.birger-koblitz.de (Postfix) with ESMTPSA id 86BF23F6DB; Wed, 16 Sep 2026 03:24:54 +0000 (UTC) From: Birger Koblitz Date: Wed, 16 Sep 2026 05:24:08 +0200 Subject: [PATCH net-next v12 09/15] ax88179_178a: Add VLAN offload support for AX88179A Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260916-ax88179a-v12-9-60c04c9924a2@birger-koblitz.de> References: <20260916-ax88179a-v12-0-60c04c9924a2@birger-koblitz.de> In-Reply-To: <20260916-ax88179a-v12-0-60c04c9924a2@birger-koblitz.de> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Russell King , Andrew Lunn , Heiner Kallweit Cc: linux-usb@vger.kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Birger Koblitz , Jianhui Xu X-Mailer: b4 0.14.2 The AX88179A-based chips support VLAN offload. Add configuration support in netdev_ops. Features supported are: NETIF_F_HW_VLAN_CTAG_TX, NETIF_F_HW_VLAN_CTAG_RX and NETIF_F_HW_VLAN_CTAG_FILTER. Signed-off-by: Birger Koblitz Reviewed-by: Andrew Lunn Tested-by: Jianhui Xu --- drivers/net/usb/ax88179_lib.c | 2 + drivers/net/usb/ax88179a_devices.c | 102 +++++++++++++++++++++++++++++++++= ++++ 2 files changed, 104 insertions(+) diff --git a/drivers/net/usb/ax88179_lib.c b/drivers/net/usb/ax88179_lib.c index ea36aef3d3e45ee4f84362a1b87628a12a355bbf..3324069e90fc352048817963f27= a49ed3872b348 100644 --- a/drivers/net/usb/ax88179_lib.c +++ b/drivers/net/usb/ax88179_lib.c @@ -346,6 +346,7 @@ int ax88179_set_features(struct net_device *net, netdev= _features_t features) { u8 tmp; struct usbnet *dev =3D netdev_priv(net); + struct ax88179_data *data =3D dev->driver_priv; netdev_features_t changed =3D net->features ^ features; =20 if (changed & NETIF_F_IP_CSUM) { @@ -365,6 +366,7 @@ int ax88179_set_features(struct net_device *net, netdev= _features_t features) tmp ^=3D AX_RXCOE_IP | AX_RXCOE_TCP | AX_RXCOE_UDP | AX_RXCOE_TCPV6 | AX_RXCOE_UDPV6; ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RXCOE_CTL, 1, 1, &tmp); + data->rx_checksum =3D !!(features & NETIF_F_RXCSUM); } =20 return 0; diff --git a/drivers/net/usb/ax88179a_devices.c b/drivers/net/usb/ax88179a_= devices.c index 6bf1ac17aa1d5abfc854eb3ac0896c69875ea0d7..481139f71ac26f218b672622eec= 93c7a026c0089 100644 --- a/drivers/net/usb/ax88179a_devices.c +++ b/drivers/net/usb/ax88179a_devices.c @@ -239,6 +239,62 @@ static const struct ethtool_ops ax88179a_ethtool_ops = =3D { .get_ts_info =3D ethtool_op_get_ts_info, }; =20 +static int ax88179a_vlan_rx_kill_vid(struct net_device *net, __be16 proto,= u16 vid) +{ + struct usbnet *dev =3D netdev_priv(net); + u8 vlan_ctrl; + u16 reg16; + u8 reg8; + + ax88179_read_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_CONTROL, 1, 1, ®= 8); + vlan_ctrl =3D reg8; + + /* Address */ + reg8 =3D (vid / 16); + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_ADDRESS, 1, 1, &re= g8); + + /* Data */ + reg8 =3D vlan_ctrl | AX_VLAN_CONTROL_RD; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_CONTROL, 1, 1, &re= g8); + + ax88179_read_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_DATA0, 2, 2, ®16= ); + reg16 &=3D ~(1 << (vid % 16)); + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_DATA0, 2, 2, ®1= 6); + + reg8 =3D vlan_ctrl | AX_VLAN_CONTROL_WE; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_CONTROL, 1, 1, &re= g8); + + return 0; +} + +static int ax88179a_vlan_rx_add_vid(struct net_device *net, __be16 proto, = u16 vid) +{ + struct usbnet *dev =3D netdev_priv(net); + u8 vlan_ctrl; + u16 reg16; + u8 reg8; + + ax88179_read_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_CONTROL, 1, 1, ®= 8); + vlan_ctrl =3D reg8; + + /* Address */ + reg8 =3D (vid / 16); + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_ADDRESS, 1, 1, &re= g8); + + /* Data */ + reg8 =3D vlan_ctrl | AX_VLAN_CONTROL_RD; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_CONTROL, 1, 1, &re= g8); + + ax88179_read_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_DATA0, 2, 2, ®16= ); + reg16 |=3D (1 << (vid % 16)); + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_DATA0, 2, 2, ®1= 6); + + reg8 =3D vlan_ctrl | AX_VLAN_CONTROL_WE; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_CONTROL, 1, 1, &re= g8); + + return 0; +} + static void ax88179a_mdio_unregister(struct ax88179_data *data) { mdiobus_unregister(data->mdio); @@ -506,6 +562,49 @@ static int ax88179a_mii_ioctl(struct net_device *net, = struct ifreq *rq, int cmd) return phylink_mii_ioctl(data->phylink, rq, cmd); } =20 +static int ax88179a_set_features(struct net_device *net, netdev_features_t= features) +{ + struct usbnet *dev =3D netdev_priv(net); + netdev_features_t changed; + int ret; + u8 tmp; + + changed =3D net->features ^ features; + + ret =3D ax88179_set_features(net, features); + if (ret) + return ret; + + if (changed & NETIF_F_HW_VLAN_CTAG_FILTER) { + ax88179_read_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_CONTROL, 1, 1, &tm= p); + tmp ^=3D AX_VLAN_CONTROL_VFE; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_CONTROL, 1, 1, &t= mp); + if (features & NETIF_F_HW_VLAN_CTAG_FILTER) { + for (int i =3D 0; i < 256; i++) { + u16 tmp16 =3D 0; + /* Address */ + tmp =3D i; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_ADDRESS, + 1, 1, &tmp); + /* Data */ + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_DATA0, + 2, 2, &tmp16); + tmp =3D AX_VLAN_CONTROL_WE; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_CONTROL, + 1, 1, &tmp); + } + } + } + + if (changed & NETIF_F_HW_VLAN_CTAG_RX) { + ax88179_read_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_CONTROL, 1, 1, &tm= p); + tmp ^=3D AX_VLAN_CONTROL_VSO; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX88179A_VLAN_ID_CONTROL, 1, 1, &t= mp); + } + + return 0; +} + static const struct net_device_ops ax88179a_netdev_ops =3D { .ndo_open =3D usbnet_open, .ndo_stop =3D usbnet_stop, @@ -516,6 +615,9 @@ static const struct net_device_ops ax88179a_netdev_ops = =3D { .ndo_set_mac_address =3D ax88179_set_mac_addr, .ndo_validate_addr =3D eth_validate_addr, .ndo_eth_ioctl =3D ax88179a_mii_ioctl, + .ndo_set_features =3D ax88179a_set_features, + .ndo_vlan_rx_add_vid =3D ax88179a_vlan_rx_add_vid, + .ndo_vlan_rx_kill_vid =3D ax88179a_vlan_rx_kill_vid, }; =20 static int ax88179a_bind(struct usbnet *dev, struct usb_interface *intf) --=20 2.47.3 From nobody Fri Sep 25 06:47:57 2026 Received: from bkemail.birger-koblitz.de (bkemail.birger-koblitz.de [23.88.97.239]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D22B837C119; Wed, 16 Sep 2026 03:25:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=23.88.97.239 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789529107; cv=none; b=oj3smfHxm1szZ9NbOv7Vbnj3kEWAMEZQUkWPMTav8Q9q7yXEGpCCvbZj5YDCcDEmidLzCXX7Cwk7r7tqZjxH56r/cQPe3hOzQnhGX2GXdb/vWZ5bSvPNtWyel3D1zV/KJegRPN/s1Mpgqq8QZAhkiMXLOt+Q0qCzt3PAiXp8uMU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789529107; c=relaxed/simple; bh=NcbNkay5OqNhKbALtpWwHiOqWRFp2I3RdeCx/AOF7mg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=tSDrkNoGCE2ZXxrFpY8SDV/nLEy7qo3O+jz8/4MpwmT0xN8KD0bw/JrhOPNuY5zB3LiTzjJEEBkOSNOn9Tk/9yJ/5U6TIotpuywWjB9WhRF03Qay6/TDJR4PSlcJFoLuX7pRdm/xwqCqC5Dj32UOi/lCziAc42N8ZDrzqvj+BBk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=birger-koblitz.de; spf=pass smtp.mailfrom=birger-koblitz.de; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b=VC9axKxp; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b=lPupUxuL; arc=none smtp.client-ip=23.88.97.239 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=birger-koblitz.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=birger-koblitz.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b="VC9axKxp"; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b="lPupUxuL" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=birger-koblitz.de; s=default; t=1789529104; bh=NcbNkay5OqNhKbALtpWwHiOqWRFp2I3RdeCx/AOF7mg=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=VC9axKxpwVuhc0eH4MHe7ibQUEp+03hw3HIZsev94HEpKWYHg717u1f3QwHla8LpG PL4WjnDi+H0OK7PAtPtHw6TwZNUOiCEp5sig1jBFgRto/89pX+LASd5e9P15F/pdDX VI7Su8Xz5NQu8f1EBU6Ek1xBoQt4StDcqJCoNKjV5jguwscrCejPhVFrNNbwT6kNaS To5MIfJY4gvhw9PbsYLFu16kWjfRHtu2A256yqiJlSTTGEyySpAcjUaKQtVX70MwXY 3EHaYSj3uHIV0JEunxTHkUrLgOgfHYTl5SsqjnE9sdbgftEotMJgstm3QKfSAb5ShI YJGW3tbGXqhZg== Received: by bkemail.birger-koblitz.de (Postfix, from userid 109) id 01D0B3FA72; Wed, 16 Sep 2026 03:25:04 +0000 (UTC) X-Spam-Level: DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=birger-koblitz.de; s=default; t=1789529103; bh=NcbNkay5OqNhKbALtpWwHiOqWRFp2I3RdeCx/AOF7mg=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=lPupUxuLcPIaWmPQq9w18A4oIcIbQE9ZC9wT1J+1IU+pwn3gA/CtM/yOXf3XVP/Qr yHYfb1ucAAqM5ZdeouVqSmHkF+mzKrmvjC9y5ksfAjZHdjaNaA/ZN9rClIS1dMS9+M UDmlrpWbB+h2sjYlqblWwLh3/ifxcm9beqShlVy+Yo1vbWG6SHSh3qP2LfEOGoHnBu A5cL2TWXpPu8WRcs8NMCi66+FXdS75wa2la/GlqnPAzYIl8Q3nUFxnCNG0zPoAqXRO t4eJhRiRWFJ26T/xeZ0JcfNnZggpNJxY6aTSSu5wSfNDC5OG4Ep59k6y7JiC+d3/HM oruHi23u+wfmQ== Received: from DELLLaptop.net (unknown [223.86.26.228]) by bkemail.birger-koblitz.de (Postfix) with ESMTPSA id F36A73FA6C; Wed, 16 Sep 2026 03:24:58 +0000 (UTC) From: Birger Koblitz Date: Wed, 16 Sep 2026 05:24:09 +0200 Subject: [PATCH net-next v12 10/15] ax88179_178a: Add AX179A/AX279 multicast configuration Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260916-ax88179a-v12-10-60c04c9924a2@birger-koblitz.de> References: <20260916-ax88179a-v12-0-60c04c9924a2@birger-koblitz.de> In-Reply-To: <20260916-ax88179a-v12-0-60c04c9924a2@birger-koblitz.de> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Russell King , Andrew Lunn , Heiner Kallweit Cc: linux-usb@vger.kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Birger Koblitz , Jianhui Xu X-Mailer: b4 0.14.2 Add support for conditionally setting the ip_alignement flag AX_RX_CTL_IPE in AX_RX_CTL and make sure that AX_RX_CTL_DROPCRCERR is also set to be consistent with the initial configuration in ax88179_reset() Signed-off-by: Birger Koblitz Reviewed-by: Andrew Lunn Tested-by: Jianhui Xu --- drivers/net/usb/ax88179_lib.c | 8 ++++++-- drivers/net/usb/ax88179a_devices.c | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/net/usb/ax88179_lib.c b/drivers/net/usb/ax88179_lib.c index 3324069e90fc352048817963f27a49ed3872b348..708b0b23f1363daf90f329a3e6b= 6a2721d110387 100644 --- a/drivers/net/usb/ax88179_lib.c +++ b/drivers/net/usb/ax88179_lib.c @@ -305,10 +305,14 @@ int ax88179_set_eeprom(struct net_device *net, struct= ethtool_eeprom *eeprom, u8 void ax88179_set_multicast(struct net_device *net) { struct usbnet *dev =3D netdev_priv(net); - struct ax88179_data *data =3D dev->driver_priv; u8 *m_filter =3D ((u8 *)dev->data); + struct ax88179_data *data; + + data =3D dev->driver_priv; =20 - data->rxctl =3D (AX_RX_CTL_START | AX_RX_CTL_AB | AX_RX_CTL_IPE); + data->rxctl =3D (AX_RX_CTL_START | AX_RX_CTL_AB | AX_RX_CTL_DROPCRCERR); + if (data->ip_align) + data->rxctl |=3D AX_RX_CTL_IPE; =20 if (net->flags & IFF_PROMISC) { data->rxctl |=3D AX_RX_CTL_PRO; diff --git a/drivers/net/usb/ax88179a_devices.c b/drivers/net/usb/ax88179a_= devices.c index 481139f71ac26f218b672622eec93c7a026c0089..e77450bc3299fb1a3698b36cab2= 785e82cf759a6 100644 --- a/drivers/net/usb/ax88179a_devices.c +++ b/drivers/net/usb/ax88179a_devices.c @@ -615,6 +615,7 @@ static const struct net_device_ops ax88179a_netdev_ops = =3D { .ndo_set_mac_address =3D ax88179_set_mac_addr, .ndo_validate_addr =3D eth_validate_addr, .ndo_eth_ioctl =3D ax88179a_mii_ioctl, + .ndo_set_rx_mode =3D ax88179_set_multicast, .ndo_set_features =3D ax88179a_set_features, .ndo_vlan_rx_add_vid =3D ax88179a_vlan_rx_add_vid, .ndo_vlan_rx_kill_vid =3D ax88179a_vlan_rx_kill_vid, --=20 2.47.3 From nobody Fri Sep 25 06:47:57 2026 Received: from bkemail.birger-koblitz.de (bkemail.birger-koblitz.de [23.88.97.239]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3E3E835DA69; Wed, 16 Sep 2026 03:25:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=23.88.97.239 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789529113; cv=none; b=pgCOVkbVQeprkDGPOFTWCMrC9rHOuJttPnYruBLZxpmzkva2JgHamWwidu+i4qb2Qiy/GooTaA7HcE74ncIFOvJrmsMUZCtsvhwg4uixqPRDNAA+VL7v3ZQKS2cqTftWMsFDk6uca4qy6UAckMHj0UCZblqkmAWtEH/2vyhr8KE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789529113; c=relaxed/simple; bh=lC61MN8nqUOmxti+MUkrYTRbYi8j/0XheQ/3EVgD4oY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=qdsYTGYF6bMp+2F50k70jita1Q7YGAtvvOHVvolMuLucRDQslVWBuVF2w9uXBcCdxBBzwqUmDUtz3muv56x3a64sBr2Uw2ttAcwZDUtrO2am/ghUUm8LIedAfqDHaUDeysZYtZWLjA12QpRH8CiQGQoXsWxbzPiedmKCP5UFGG4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=birger-koblitz.de; spf=pass smtp.mailfrom=birger-koblitz.de; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b=DU1EBOgz; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b=K99gYUyO; arc=none smtp.client-ip=23.88.97.239 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=birger-koblitz.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=birger-koblitz.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b="DU1EBOgz"; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b="K99gYUyO" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=birger-koblitz.de; s=default; t=1789529110; bh=lC61MN8nqUOmxti+MUkrYTRbYi8j/0XheQ/3EVgD4oY=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=DU1EBOgz0QI5kxWXQD5ukxQXT6kPblNDy1FAdUq6i2Ee+Njg2S7p94/eie4asZEeZ Bs4ooSqORhN7zJ50IG9Gt+Oy+4IsNt4HUwv2pxkzETuuN69bF6RJkzntEJ/fvJ4MLh EttzJBHLSs4pgpwy8yAPrhIbzGSAmLr1WI+KDB6e0Vzyh73R9ijRlSnUXnrXeAPZSM 8tS4DtN9LETfYOUfogQrIUZBcN3VLDvFMyQJERKUBjTm6gtCHefXaA3Da8SuC9psin CUSVkZfE8rYN6pHJhMbkKK5HFbcrtJzqIPjHf+VILSir2TRQdabQJKIEn9UPMbs5Le RcrpY1w0meZvw== Received: by bkemail.birger-koblitz.de (Postfix, from userid 109) id 8AA2E3FA7D; Wed, 16 Sep 2026 03:25:10 +0000 (UTC) X-Spam-Level: DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=birger-koblitz.de; s=default; t=1789529109; bh=lC61MN8nqUOmxti+MUkrYTRbYi8j/0XheQ/3EVgD4oY=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=K99gYUyO4uCepDnkQ2v51420z2nC5LLZmp5v/DYa6LposFNgStjIJnjtz98q84uLp iKRwueS80dg/TDoi1/I2WirCsGjAKTU/aIEhkhSx2fm1ebbXEo8tmGmFEhDG5r2BWK 1GNBW5Ek7zVmAWJag5kigWCHxBgSCfpPUFhwno5UPYh5tmeUFPcZfMUEKqRE0QUaMy LTRkvDpeF6QZWCp94ukkDG/NVPpEOsdfMwUeUJcrEHFWO699kIrq7VjFplKUsXSZ3x x2fpBxOlNNnT/3p91ggLu4MkN3ueZYzUbnL9uKw7ckA2/BCG82YmSuHXQfzAwSJyEh W1aAetYNk5TMg== Received: from DELLLaptop.net (unknown [223.86.26.228]) by bkemail.birger-koblitz.de (Postfix) with ESMTPSA id 58F913FA6C; Wed, 16 Sep 2026 03:25:03 +0000 (UTC) From: Birger Koblitz Date: Wed, 16 Sep 2026 05:24:10 +0200 Subject: [PATCH net-next v12 11/15] ax88179_178a: Add Suspend/resume support for AX88179A/772D/279 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260916-ax88179a-v12-11-60c04c9924a2@birger-koblitz.de> References: <20260916-ax88179a-v12-0-60c04c9924a2@birger-koblitz.de> In-Reply-To: <20260916-ax88179a-v12-0-60c04c9924a2@birger-koblitz.de> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Russell King , Andrew Lunn , Heiner Kallweit Cc: linux-usb@vger.kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Birger Koblitz , Jianhui Xu X-Mailer: b4 0.14.2 The suspend and resume functions are called via the usb_driver structure, for which the driver has only a single instance. Add wrapper functions for the different implementations for the AX88179 and AX179A architecutres in ax88179_lib which calls the 2 implementations in ax88179_178a and ax88179a_devices, respectively. Signed-off-by: Birger Koblitz Suggested-by: Jianhui Xu Reviewed-by: Andrew Lunn Tested-by: Jianhui Xu --- drivers/net/usb/ax88179_178a.c | 9 ++-- drivers/net/usb/ax88179_lib.c | 19 ++++++++ drivers/net/usb/ax88179_lib.h | 4 ++ drivers/net/usb/ax88179a_devices.c | 95 ++++++++++++++++++++++++++++++++++= +++- 4 files changed, 123 insertions(+), 4 deletions(-) diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c index a2c596305f7988175ef56afbc853e798406159f6..93031b9ee92bc64c53387291616= aa3b40db6feb9 100644 --- a/drivers/net/usb/ax88179_178a.c +++ b/drivers/net/usb/ax88179_178a.c @@ -684,6 +684,9 @@ static int ax88179_bind(struct usbnet *dev, struct usb_= interface *intf) =20 dev->driver_priv =3D ax179_data; =20 + ax179_data->resume =3D ax88179_resume; + ax179_data->suspend =3D ax88179_suspend; + dev->net->netdev_ops =3D &ax88179_netdev_ops; dev->net->ethtool_ops =3D &ax88179_ethtool_ops; dev->net->needed_headroom =3D 8; @@ -1342,9 +1345,9 @@ static struct usb_driver ax88179_178a_driver =3D { .name =3D "ax88179_178a", .id_table =3D products, .probe =3D usbnet_probe, - .suspend =3D ax88179_suspend, - .resume =3D ax88179_resume, - .reset_resume =3D ax88179_resume, + .suspend =3D ax88179_suspend_wrapper, + .resume =3D ax88179_resume_wrapper, + .reset_resume =3D ax88179_resume_wrapper, .disconnect =3D ax88179_disconnect, .supports_autosuspend =3D 1, .disable_hub_initiated_lpm =3D 1, diff --git a/drivers/net/usb/ax88179_lib.c b/drivers/net/usb/ax88179_lib.c index 708b0b23f1363daf90f329a3e6b6a2721d110387..3b498206c50d5b5d9d5cd489114= ef28bf280fe97 100644 --- a/drivers/net/usb/ax88179_lib.c +++ b/drivers/net/usb/ax88179_lib.c @@ -455,3 +455,22 @@ int ax88179_set_mac_addr(struct net_device *net, void = *p) return 0; } =20 +int ax88179_suspend_wrapper(struct usb_interface *intf, pm_message_t messa= ge) +{ + struct usbnet *dev =3D usb_get_intfdata(intf); + struct ax88179_data *priv; + + priv =3D dev->driver_priv; + + return priv->suspend(intf, message); +} + +int ax88179_resume_wrapper(struct usb_interface *intf) +{ + struct usbnet *dev =3D usb_get_intfdata(intf); + struct ax88179_data *priv; + + priv =3D dev->driver_priv; + return priv->resume(intf); +} + diff --git a/drivers/net/usb/ax88179_lib.h b/drivers/net/usb/ax88179_lib.h index 2e4d35c74ee8b32cd2916924b85d5427860bb08c..16a6dcbd6e66e37d3da0e57d280= 0c29d8a95a34a 100644 --- a/drivers/net/usb/ax88179_lib.h +++ b/drivers/net/usb/ax88179_lib.h @@ -315,6 +315,8 @@ struct ax88179_data { struct phy_device *phydev; struct phylink *phylink; struct phylink_config phylink_config; + int (*resume)(struct usb_interface *intf); + int (*suspend)(struct usb_interface *intf, pm_message_t message); }; =20 struct ax88179_int_data { @@ -346,6 +348,8 @@ int ax88179_set_features(struct net_device *net, netdev= _features_t features); void ax88179_get_mac_addr(struct usbnet *dev); int ax88179_change_mtu(struct net_device *net, int new_mtu); int ax88179_set_mac_addr(struct net_device *net, void *p); +int ax88179_suspend_wrapper(struct usb_interface *intf, pm_message_t messa= ge); +int ax88179_resume_wrapper(struct usb_interface *intf); =20 extern const struct driver_info ax88179a_info; extern const struct driver_info ax88772d_info; diff --git a/drivers/net/usb/ax88179a_devices.c b/drivers/net/usb/ax88179a_= devices.c index e77450bc3299fb1a3698b36cab2785e82cf759a6..ff41d20c219d46392c2633a1eaf= f021385490b0e 100644 --- a/drivers/net/usb/ax88179a_devices.c +++ b/drivers/net/usb/ax88179a_devices.c @@ -5,6 +5,8 @@ #include #include "ax88179_lib.h" =20 +static int ax88179a_reset(struct usbnet *dev); + #define AX88279_EEPROM_LEN 0x4000 #define AX88179A_EEPROM_LEN (32 * 20) =20 @@ -123,6 +125,53 @@ static void ax88179a_status(struct usbnet *dev, struct= urb *urb) phylink_mac_interrupt(data->phylink); } =20 +static int ax88179a_suspend(struct usb_interface *intf, pm_message_t messa= ge) +{ + struct usbnet *dev =3D usb_get_intfdata(intf); + struct ax88179_data *priv; + u16 tmp16; + u8 tmp8; + + priv =3D dev->driver_priv; + ax88179_set_pm_mode(dev, true); + + if (netif_running(dev->net)) { + rtnl_lock(); + phylink_suspend(priv->phylink, !!priv->wolopts); + rtnl_unlock(); + } + + /* Enable WoL */ + if (priv->wolopts) { + ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MOD, 1, 1, &tmp8); + if (priv->wolopts & WAKE_PHY) + tmp8 |=3D AX_MONITOR_MODE_RWLC; + if (priv->wolopts & WAKE_MAGIC) + tmp8 |=3D AX_MONITOR_MODE_RWMP; + + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MOD, 1, 1, &tmp8); + + ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, 2, 2, &tmp16= ); + tmp16 |=3D AX_MEDIUM_RECEIVE_EN; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, 2, 2, &tmp1= 6); + + if (priv->chip_version =3D=3D AX_VERSION_AX88279) + ax88179_write_cmd(dev, AX88179A_WAKEUP_SETTING, 8, + EPHY_LOW_POWER_EN | S5_WOL_EN + | S5_WOL_LOW_POWER | 0x8000, 0, NULL); + else + ax88179_write_cmd(dev, AX88179A_WAKEUP_SETTING, 0, + EPHY_LOW_POWER_EN, 0, NULL); + + } else if (priv->chip_version =3D=3D AX_VERSION_AX88279) { + ax88179_write_cmd(dev, AX88179A_WAKEUP_SETTING, 8, 0x8000, 0, NULL); + } + + usbnet_suspend(intf, message); + ax88179_set_pm_mode(dev, false); + return 0; +} + static int ax88179a_auto_detach(struct usbnet *dev) { u16 tmp16; @@ -132,6 +181,43 @@ static int ax88179a_auto_detach(struct usbnet *dev) return 0; } =20 +static int ax88179a_resume(struct usb_interface *intf) +{ + struct usbnet *dev =3D usb_get_intfdata(intf); + struct ax88179_data *ax179_data; + u8 reg8; + + ax179_data =3D dev->driver_priv; + ax88179_set_pm_mode(dev, true); + + ax88179_read_cmd(dev, AX88179A_PHY_POWER, 0, 0, 1, ®8); + if (!(reg8 & AX_PHY_POWER)) { + reg8 =3D AX_PHY_POWER; + ax88179_write_cmd(dev, AX88179A_PHY_POWER, 0, 0, 1, ®8); + msleep(250); + } + ax88179_write_cmd(dev, AX_FW_MODE, AX_FW_MODE_179A, 0, 0, NULL); + + /* Now, that AX_FW_MODE_179A is enabled, the PHY needs a power-cycle. + * PHY-power is re-enabled in ax88179_reset() + */ + reg8 =3D 0; + ax88179_write_cmd(dev, AX88179A_PHY_POWER, 0, 0, 1, ®8); + msleep(250); + + ax88179a_reset(dev); + + if (netif_running(dev->net)) { + rtnl_lock(); + phylink_resume(ax179_data->phylink); + rtnl_unlock(); + } + + ax88179_set_pm_mode(dev, false); + + return usbnet_resume(intf); +} + static void ax88179a_bulkin_config(struct usbnet *dev, u8 link_sts, u8 spe= ed, bool full_duplex) { struct ax88179_data *ax179_data =3D dev->driver_priv; @@ -687,6 +773,9 @@ static int ax88179a_bind(struct usbnet *dev, struct usb= _interface *intf) ax179_data->eeprom_wen =3D 0; } =20 + ax179_data->resume =3D ax88179a_resume; + ax179_data->suspend =3D ax88179a_suspend; + dev->net->netdev_ops =3D &ax88179a_netdev_ops; dev->net->ethtool_ops =3D &ax88179a_ethtool_ops; dev->net->needed_headroom =3D 8; @@ -1048,7 +1137,11 @@ static int ax88179a_reset(struct usbnet *dev) 1, 1, &tmp) > 0) ax179_data->wol_supported =3D WAKE_MAGIC | WAKE_PHY; =20 - phylink_start(ax179_data->phylink); + /* ax88179a_reset() may also be called from resume context, phylink + * is already started, then. + */ + if (!ax179_data->in_pm) + phylink_start(ax179_data->phylink); =20 usbnet_link_change(dev, 0, 0); =20 --=20 2.47.3 From nobody Fri Sep 25 06:47:57 2026 Received: from bkemail.birger-koblitz.de (bkemail.birger-koblitz.de [23.88.97.239]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2DB363BED71; Wed, 16 Sep 2026 03:25:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=23.88.97.239 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789529118; cv=none; b=mkvKNduwKuhlY7m5kH669Fgv35btrxpGbdxqYdr8sbA3qc/tB9wFRVcnJyqIAY1oOuPXkQEVdrDMo6TOvWU1/dyZ4j2lQcaTxX7muYJI/o8/sO6ulG41jqabEKF3Xj9EptajxgyVN7AOnSP0RVKaxzpImIgEUkoN4t1akfyLFr0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789529118; c=relaxed/simple; bh=UycHjv35v2b8ptI4Xk7Ev3ErbXHCmXL8d3dB02epejw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=chGh0a2rXZpJ3dyhs3kKIk1VjEtHvrX6bDwxfG9OIi5Yhew3irXtJG1KUzZCGoLPNCFLa1FY4sFrqpvrEWCT6GdTZ/Z2d+mVELK9bF/GVZk/OPecQ4zH6sIjpcQ/uo3aXvFogrr9MgXfxLGbrPA29xNFIz2YcohrFNEcw+BQmb0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=birger-koblitz.de; spf=pass smtp.mailfrom=birger-koblitz.de; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b=WVQiJjuV; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b=c7W00RaF; arc=none smtp.client-ip=23.88.97.239 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=birger-koblitz.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=birger-koblitz.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b="WVQiJjuV"; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b="c7W00RaF" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=birger-koblitz.de; s=default; t=1789529114; bh=UycHjv35v2b8ptI4Xk7Ev3ErbXHCmXL8d3dB02epejw=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=WVQiJjuVajHNg0BYwhHny4UNW4zzXQ77xwGP+yIAhBe3aEAMdserLgKHUZF7BhB8T YDFBe2J2RLYd159X6Mf969sQpcwGE1kVZsNtfdv+fWBcTL7wUDWiK/JTPIzCSu2Wzr y4S7rmurtsAKkWGWNrzwnWUje/oYn95/bvbd96Y9SEdybFL62kTL/MJvOTtcYxSNIU RFRCUm0W9ebAGYAVmWNZQoRyAzvAI2ykV5gcLtuvfF0oRYzFJBxRcjglFoA/YLy6Xs /TIiAYpOdkDgsgEpzFNhFEpex5F6Mgc2GuVCMpvxP5+0OTD8AGAnmPM8x/93EGDiN8 41KF25Aq28g4g== Received: by bkemail.birger-koblitz.de (Postfix, from userid 109) id 7B07E3FA75; Wed, 16 Sep 2026 03:25:14 +0000 (UTC) X-Spam-Level: DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=birger-koblitz.de; s=default; t=1789529113; bh=UycHjv35v2b8ptI4Xk7Ev3ErbXHCmXL8d3dB02epejw=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=c7W00RaFaL93qT009+pkM8hkNJKvyzAxk2pGQ5A4uwRCh4D89Z+lC2rkQbSdOkn+6 YUWOGNcADeveT/sXSgmibzgp4acp4/BmLcg8he9Y0Q1rMnlttg6ZjaNRLU30VteuRb YLAw8ymmAUm7WvasiQVXP334+oorH5W9pdN9eO/LJz/WgqoZXo03Jb2vfUlvem+eQM x2IrPpO/YhjUxQ55EB5ibIHS2c+hkc5Ye2iRu/jDsJHeuejxq/eArhzYDjM3CAOLWm RyR4oh15iqbuDydlltu2P33r/YmMYOyaavimVtZ8tUWRmsUhoetlzZP4OPiCIcw31O izmfHftUgBGBQ== Received: from DELLLaptop.net (unknown [223.86.26.228]) by bkemail.birger-koblitz.de (Postfix) with ESMTPSA id DEB9E3F6DB; Wed, 16 Sep 2026 03:25:09 +0000 (UTC) From: Birger Koblitz Date: Wed, 16 Sep 2026 05:24:11 +0200 Subject: [PATCH net-next v12 12/15] ax88179_178a: Add ethtool get_drvinfo Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260916-ax88179a-v12-12-60c04c9924a2@birger-koblitz.de> References: <20260916-ax88179a-v12-0-60c04c9924a2@birger-koblitz.de> In-Reply-To: <20260916-ax88179a-v12-0-60c04c9924a2@birger-koblitz.de> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Russell King , Andrew Lunn , Heiner Kallweit Cc: linux-usb@vger.kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Birger Koblitz , Jianhui Xu , Nicolai Buchwitz X-Mailer: b4 0.14.2 Add ax88179a_get_drvinfo() as implementation of get_drvinfo, in order to provide information about the device firmware. Signed-off-by: Birger Koblitz Reviewed-by: Andrew Lunn Reviewed-by: Nicolai Buchwitz Tested-by: Jianhui Xu --- drivers/net/usb/ax88179a_devices.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/net/usb/ax88179a_devices.c b/drivers/net/usb/ax88179a_= devices.c index ff41d20c219d46392c2633a1eaff021385490b0e..6225b88681e623a570cf75aef8d= 10e70d3ab2cbf 100644 --- a/drivers/net/usb/ax88179a_devices.c +++ b/drivers/net/usb/ax88179a_devices.c @@ -218,6 +218,20 @@ static int ax88179a_resume(struct usb_interface *intf) return usbnet_resume(intf); } =20 +static void ax88179a_get_drvinfo(struct net_device *net, struct ethtool_dr= vinfo *info) +{ + struct ax88179_data *priv =3D netdev2data(net); + + /* Inherit standard device info */ + usbnet_get_drvinfo(net, info); + if (priv->chip_version < AX_VERSION_AX88179A) + return; + + snprintf(info->fw_version, sizeof(info->fw_version), "%d.%d.%d.%d", + priv->fw_version[0], priv->fw_version[1], + priv->fw_version[2], priv->fw_version[3]); +} + static void ax88179a_bulkin_config(struct usbnet *dev, u8 link_sts, u8 spe= ed, bool full_duplex) { struct ax88179_data *ax179_data =3D dev->driver_priv; @@ -307,6 +321,7 @@ static int ax88179a_set_eee(struct net_device *net, str= uct ethtool_keee *edata) } =20 static const struct ethtool_ops ax88179a_ethtool_ops =3D { + .get_drvinfo =3D ax88179a_get_drvinfo, .get_link =3D ethtool_op_get_link, .get_msglevel =3D usbnet_get_msglevel, .set_msglevel =3D usbnet_set_msglevel, --=20 2.47.3 From nobody Fri Sep 25 06:47:57 2026 Received: from bkemail.birger-koblitz.de (bkemail.birger-koblitz.de [23.88.97.239]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8D29239794A; Wed, 16 Sep 2026 03:25:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=23.88.97.239 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789529122; cv=none; b=sKib5n4bQeN2iuUNArLgAT4qVceqgfM/TyywkQGZwHsNe4kpA01tSX7MsOD9q+41f/0yO/JKHNPi89GRHNJ2DmQKOlFK+YS2YRlWXdcT+MY+YgGLqQzUQVRSklO8eRyLXLzgO8v1kIpyUW+XqJ85yUqp3en8kEVFXx5UeDA6uks= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789529122; c=relaxed/simple; bh=eLtKd2xjP3hitZ3DbQJEkoULvZ7CfjWfHNJ/8aqi8bw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Je1owxEy/daL0qC2SH+bkA9l9wGwR0CzWLr7jtC7gXhtdVcCGWeCECWbaO+0ADYtvMQTu7b23BjRUf6BN+RiUDbloVU4RCKLJYTQitSR0XJgGLf+2s6rcmcF9uyT1x43kQFQjC9+TzcSrzCCbvBTt9w2DTcTm7ufEDcEUaTfE78= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=birger-koblitz.de; spf=pass smtp.mailfrom=birger-koblitz.de; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b=qdN8qOPA; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b=qdN8qOPA; arc=none smtp.client-ip=23.88.97.239 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=birger-koblitz.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=birger-koblitz.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b="qdN8qOPA"; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b="qdN8qOPA" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=birger-koblitz.de; s=default; t=1789529118; bh=eLtKd2xjP3hitZ3DbQJEkoULvZ7CfjWfHNJ/8aqi8bw=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=qdN8qOPA5N2jOJm1qpzOJ9wj8Y6ulr4W4AcGicMrSpQVjeGFbd9bibHTfFui5Frv+ yVICie5SRW4MjPJBbq9y27Az3cosisbdzHYKXkWPEwyxxxydrfopazwnM5GED3i+7E PdaljUu64ZipuTSAfzuglEDsoz/FmdmQl3q3b72NxrzIkIVrHAldlWloDqR98a3+5r 7lpr078Ug5rP+EkAt0toR7JIyQr/3mhB7EJsZeQ3ps9o2FPmcRtppqPP/+7lTGbrEP dhWhh/1uf+ZIpDeMu7ujw+l6tZNgba0u6TlqzhbBGmY/KxH+mKCe9xHzhxNVy/3hV1 UcXswiz3dSsaw== Received: by bkemail.birger-koblitz.de (Postfix, from userid 109) id D75A33FA6F; Wed, 16 Sep 2026 03:25:18 +0000 (UTC) X-Spam-Level: DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=birger-koblitz.de; s=default; t=1789529118; bh=eLtKd2xjP3hitZ3DbQJEkoULvZ7CfjWfHNJ/8aqi8bw=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=qdN8qOPA5N2jOJm1qpzOJ9wj8Y6ulr4W4AcGicMrSpQVjeGFbd9bibHTfFui5Frv+ yVICie5SRW4MjPJBbq9y27Az3cosisbdzHYKXkWPEwyxxxydrfopazwnM5GED3i+7E PdaljUu64ZipuTSAfzuglEDsoz/FmdmQl3q3b72NxrzIkIVrHAldlWloDqR98a3+5r 7lpr078Ug5rP+EkAt0toR7JIyQr/3mhB7EJsZeQ3ps9o2FPmcRtppqPP/+7lTGbrEP dhWhh/1uf+ZIpDeMu7ujw+l6tZNgba0u6TlqzhbBGmY/KxH+mKCe9xHzhxNVy/3hV1 UcXswiz3dSsaw== Received: from DELLLaptop.net (unknown [223.86.26.228]) by bkemail.birger-koblitz.de (Postfix) with ESMTPSA id 64E163FA6C; Wed, 16 Sep 2026 03:25:14 +0000 (UTC) From: Birger Koblitz Date: Wed, 16 Sep 2026 05:24:12 +0200 Subject: [PATCH net-next v12 13/15] ax88179_178a: Update driver name and information Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260916-ax88179a-v12-13-60c04c9924a2@birger-koblitz.de> References: <20260916-ax88179a-v12-0-60c04c9924a2@birger-koblitz.de> In-Reply-To: <20260916-ax88179a-v12-0-60c04c9924a2@birger-koblitz.de> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Russell King , Andrew Lunn , Heiner Kallweit Cc: linux-usb@vger.kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Birger Koblitz , Jianhui Xu , Nicolai Buchwitz X-Mailer: b4 0.14.2 Add additionally supported devices to Kconfig description, add further requirements such as PHYLINK. Update driver name in usb_driver and update MODULE_DESCRIPTION to include the additionally supported chips. Signed-off-by: Birger Koblitz Reviewed-by: Andrew Lunn Reviewed-by: Nicolai Buchwitz Tested-by: Jianhui Xu --- drivers/net/usb/Kconfig | 10 +++++++--- drivers/net/usb/Makefile | 2 +- drivers/net/usb/ax88179_178a.c | 8 ++++---- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig index 115990b0d9537aea2776544c9768b034f32aa7a4..4158455a2da76cd43a9a9d9d0e8= c66028d57b095 100644 --- a/drivers/net/usb/Kconfig +++ b/drivers/net/usb/Kconfig @@ -195,11 +195,12 @@ config USB_NET_AX8817X This driver creates an interface named "ethX", where X depends on what other networking devices you have in use. =20 -config USB_NET_AX88179_178A - tristate "ASIX AX88179/178A USB 3.0/2.0 to Gigabit Ethernet" +config USB_NET_AX88179 + tristate "ASIX AX88179/179A/178A USB 3.0/2.0 to Gigabit Ethernet" depends on USB_USBNET - select CRC32 select PHYLINK + select AX88796B_PHY + select CRC32 default y help This option adds support for ASIX AX88179 based USB 3.0/2.0 @@ -207,6 +208,9 @@ config USB_NET_AX88179_178A =20 This driver should work with at least the following devices: * ASIX AX88179 + * ASIX AX88179A/B + * ASIX AX88279 + * ASIX AX88772D/E * ASIX AX88178A * Sitcomm LN-032 =20 diff --git a/drivers/net/usb/Makefile b/drivers/net/usb/Makefile index 2ecead0181eaf8d66fb6f5dbd6f2905b22b6eb57..4026f19ecb826a6465de38f1d9b= b0e4c0af80421 100644 --- a/drivers/net/usb/Makefile +++ b/drivers/net/usb/Makefile @@ -12,7 +12,7 @@ obj-$(CONFIG_USB_HSO) +=3D hso.o obj-$(CONFIG_USB_LAN78XX) +=3D lan78xx.o obj-$(CONFIG_USB_NET_AX8817X) +=3D asix.o asix-y :=3D asix_devices.o asix_common.o ax88172a.o -obj-$(CONFIG_USB_NET_AX88179_178A) +=3D ax88179.o +obj-$(CONFIG_USB_NET_AX88179) +=3D ax88179.o ax88179-y :=3D ax88179_178a.o ax88179a_devices.o ax88179_lib.o obj-$(CONFIG_USB_NET_CDCETHER) +=3D cdc_ether.o obj-$(CONFIG_USB_NET_CDC_EEM) +=3D cdc_eem.o diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c index 93031b9ee92bc64c53387291616aa3b40db6feb9..2601a8875b9e2644780d3537574= 4875197277712 100644 --- a/drivers/net/usb/ax88179_178a.c +++ b/drivers/net/usb/ax88179_178a.c @@ -1341,8 +1341,8 @@ static const struct usb_device_id products[] =3D { }; MODULE_DEVICE_TABLE(usb, products); =20 -static struct usb_driver ax88179_178a_driver =3D { - .name =3D "ax88179_178a", +static struct usb_driver ax88179_driver =3D { + .name =3D "ax88179", .id_table =3D products, .probe =3D usbnet_probe, .suspend =3D ax88179_suspend_wrapper, @@ -1353,7 +1353,7 @@ static struct usb_driver ax88179_178a_driver =3D { .disable_hub_initiated_lpm =3D 1, }; =20 -module_usb_driver(ax88179_178a_driver); +module_usb_driver(ax88179_driver); =20 -MODULE_DESCRIPTION("ASIX AX88179/178A based USB 3.0/2.0 Gigabit Ethernet D= evices"); +MODULE_DESCRIPTION("ASIX AX88179/179A/178A based USB 3.0/2.0 Gigabit Ether= net Devices"); MODULE_LICENSE("GPL"); --=20 2.47.3 From nobody Fri Sep 25 06:47:57 2026 Received: from bkemail.birger-koblitz.de (bkemail.birger-koblitz.de [23.88.97.239]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 731782DEA93; Wed, 16 Sep 2026 03:25:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=23.88.97.239 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789529128; cv=none; b=PSV9jURHbqcB3ip9uxwh32d9R9+2+ar6BsIvkGcHiwuC4SrooS1DGWKN43Q2ylcpZSLpY2PTjqvqriaQurq9fPKah6vkGvcm8+ryEaC/kuluro1lybkJeVA//pN1pnnebovdo5YObE3Ds4fem2LOMS4dERkpwJnGF/5zZNbZqS4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789529128; c=relaxed/simple; bh=UwFIzRQMfJ1MxgoTQjb3y9TiMkx6AEb3Nh/UhYWowPQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=heREGoHLdMcKI6Lu77B8xI0s6zeFqwKyOw5NAzvS2nzhaApN7MzS51S7Ux0A/5bJ5IglBagrMHavYGH9UVH8+QVmvcp1EmUihq/X7qomAEqpCEhKmFjVyY65cmDaPtdu3yvXYd8o9/h2nSRhw5fYftcYlMSJyRmYfUfOVJ/iyiM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=birger-koblitz.de; spf=pass smtp.mailfrom=birger-koblitz.de; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b=Di3FoBMv; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b=mhYNc9P3; arc=none smtp.client-ip=23.88.97.239 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=birger-koblitz.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=birger-koblitz.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b="Di3FoBMv"; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b="mhYNc9P3" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=birger-koblitz.de; s=default; t=1789529124; bh=UwFIzRQMfJ1MxgoTQjb3y9TiMkx6AEb3Nh/UhYWowPQ=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Di3FoBMvzluLezK8MlLTYzkI75LtNfUp2cFeqt9TSeYlzV3h4UqSMJOdPFbXrFrrq L7bG0OV9PjVHevgAdypAXOOMnM9cu1uLFDaAasxjIvZ5KVpiKnLTEXQ3h7Tv4FqyIg LcIB1h0rC1qquQrXAj1RqIHmUMjVdeD+srZv4NLqLnNBHBoF+4ycHHrGh3pwF4b5Vz ggEvqIR8+XgvYufwfrKJ5Y51dkqsXcPnDv3282Z3+WjWdORacktJmrDR7BxsnXtsnj kw9vl8Gvu9bxpQWOttu+J9E1Yn1vBrbtjxho5ClSRF9IjcEwAcyCH6dnavxTpX+JnO 5vpOcENKoXBcw== Received: by bkemail.birger-koblitz.de (Postfix, from userid 109) id C3D393FA7B; Wed, 16 Sep 2026 03:25:24 +0000 (UTC) X-Spam-Level: DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=birger-koblitz.de; s=default; t=1789529123; bh=UwFIzRQMfJ1MxgoTQjb3y9TiMkx6AEb3Nh/UhYWowPQ=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=mhYNc9P3ZpKXnsVi8gGRG6qJEyxxg5MEQqkFnKEz62UzTUDT6BuQ2sUTCRTmhxNlp aZbjLdVAlkIvr2FIVvdCoiS4XAcb2MP7lEQV9c8IRUeDV2bbJtT4kWs+tLar4cxXaU GcM5PnVEEGQQrAok3jgd9XRet2rFSEdH3OyHlG2OVZckwbnNljWhFI21WjtVp4EicD uu2HGnUU1B4VxLFNbdAROV5O3ZqxHUP4lrl/pZ7RRVZCjgmwq88JiFiV83q6TSL3Cm v0JDu1dQFTdj5IMDKhU88lRGiWEmdhDDa6pSRjn4cYuFrQmUUgJW5/C7NgZ96GDhCA EK8NhDSYszDzQ== Received: from DELLLaptop.net (unknown [223.86.26.228]) by bkemail.birger-koblitz.de (Postfix) with ESMTPSA id EA6013F6DB; Wed, 16 Sep 2026 03:25:18 +0000 (UTC) From: Birger Koblitz Date: Wed, 16 Sep 2026 05:24:13 +0200 Subject: [PATCH net-next v12 14/15] ax88179_178a: Add support for AX88179A/772D/279 EEPROM access Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260916-ax88179a-v12-14-60c04c9924a2@birger-koblitz.de> References: <20260916-ax88179a-v12-0-60c04c9924a2@birger-koblitz.de> In-Reply-To: <20260916-ax88179a-v12-0-60c04c9924a2@birger-koblitz.de> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Russell King , Andrew Lunn , Heiner Kallweit Cc: linux-usb@vger.kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Birger Koblitz , Jianhui Xu X-Mailer: b4 0.14.2 The AX88179A/772D devices have 32 efuses with 20 bytes each, which can be randomly programmed. The AX88279 has 16K FLASH. Provide ethtool read capability for these devices. However, no write access is provided. Signed-off-by: Birger Koblitz Reviewed-by: Andrew Lunn Tested-by: Jianhui Xu --- drivers/net/usb/ax88179_178a.c | 19 +++++++++++++++ drivers/net/usb/ax88179_lib.c | 54 ++++++++++++++++++++++++++++++++------= ---- 2 files changed, 61 insertions(+), 12 deletions(-) diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c index 2601a8875b9e2644780d35375744875197277712..4c69568ec4a2387573808c29a0c= bf86b77657038 100644 --- a/drivers/net/usb/ax88179_178a.c +++ b/drivers/net/usb/ax88179_178a.c @@ -687,6 +687,19 @@ static int ax88179_bind(struct usbnet *dev, struct usb= _interface *intf) ax179_data->resume =3D ax88179_resume; ax179_data->suspend =3D ax88179_suspend; =20 + ret =3D ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_CHIP_STATUS, + 1, 1, &ax179_data->chip_version); + if (ret < 0) + goto err_nodev; + + ax179_data->chip_version =3D (ax179_data->chip_version & 0xf0) >> 4; + ax179_data->is_ax88772d =3D 0; + ax179_data->ip_align =3D 1; + ax179_data->eeprom_read_cmd =3D AX_ACCESS_EEPROM; + ax179_data->eeprom_write_cmd =3D AX_ACCESS_EEPROM; + ax179_data->eeprom_block =3D 2; + ax179_data->eeprom_wen =3D 0; + dev->net->netdev_ops =3D &ax88179_netdev_ops; dev->net->ethtool_ops =3D &ax88179_ethtool_ops; dev->net->needed_headroom =3D 8; @@ -711,6 +724,12 @@ static int ax88179_bind(struct usbnet *dev, struct usb= _interface *intf) ax88179_reset(dev); =20 return 0; + +err_nodev: + kfree(ax179_data); + ax179_data =3D NULL; + + return ret; } =20 static void ax88179_unbind(struct usbnet *dev, struct usb_interface *intf) diff --git a/drivers/net/usb/ax88179_lib.c b/drivers/net/usb/ax88179_lib.c index 3b498206c50d5b5d9d5cd489114ef28bf280fe97..db77b7d4539ec52756a93d3c56d= 46155de5570df 100644 --- a/drivers/net/usb/ax88179_lib.c +++ b/drivers/net/usb/ax88179_lib.c @@ -194,36 +194,61 @@ int ax88179_set_wol(struct net_device *net, struct et= htool_wolinfo *wolinfo) return 0; } =20 +static void +ax88179_eeprom_access_params(struct ax88179_data *ax179_data, int i, u16 *= value, u16 *idx) +{ + /* AX88179 has a word-addressable EEPROM + * AX88179A uses EFUSES with 20 bytes length + * AX88279 has an EEPROM addressable in 256 byte blocks + */ + if (ax179_data->chip_version < AX_VERSION_AX88179A) { + *value =3D i; + *idx =3D 1; + } else if (ax179_data->chip_version >=3D AX_VERSION_AX88279) { + *value =3D (i * ax179_data->eeprom_block) >> 16; + *idx =3D (i * ax179_data->eeprom_block) & 0xffff; + } else { + *value =3D i << 4; + *idx =3D 0; + } +} + int ax88179_get_eeprom(struct net_device *net, struct ethtool_eeprom *eepr= om, u8 *data) { struct usbnet *dev =3D netdev_priv(net); - u16 *eeprom_buff; - int first_word, last_word; - int i, ret; + struct ax88179_data *ax179_data; + int first, last, i, ret; + u8 *eeprom_buff; + + ax179_data =3D dev->driver_priv; =20 if (eeprom->len =3D=3D 0) return -EINVAL; =20 eeprom->magic =3D AX88179_EEPROM_MAGIC; =20 - first_word =3D eeprom->offset >> 1; - last_word =3D (eeprom->offset + eeprom->len - 1) >> 1; - eeprom_buff =3D kmalloc_array(last_word - first_word + 1, sizeof(u16), - GFP_KERNEL); + first =3D eeprom->offset / ax179_data->eeprom_block; + last =3D (eeprom->offset + eeprom->len - 1) / ax179_data->eeprom_block; + + eeprom_buff =3D kzalloc((last - first + 1) * ax179_data->eeprom_block, GF= P_KERNEL); if (!eeprom_buff) return -ENOMEM; =20 - /* ax88179/178A returns 2 bytes from eeprom on read */ - for (i =3D first_word; i <=3D last_word; i++) { - ret =3D __ax88179_read_cmd(dev, AX_ACCESS_EEPROM, i, 1, 2, - &eeprom_buff[i - first_word]); + for (i =3D first; i <=3D last; i++) { + u16 value, idx; + + ax88179_eeprom_access_params(ax179_data, i, &value, &idx); + ret =3D __ax88179_read_cmd(dev, ax179_data->eeprom_read_cmd, + value, idx, ax179_data->eeprom_block, + eeprom_buff + (i - first) * ax179_data->eeprom_block); + if (ret < 0) { kfree(eeprom_buff); return -EIO; } } =20 - memcpy(data, (u8 *)eeprom_buff + (eeprom->offset & 1), eeprom->len); + memcpy(data, eeprom_buff + eeprom->offset % ax179_data->eeprom_block, eep= rom->len); kfree(eeprom_buff); return 0; } @@ -231,12 +256,17 @@ int ax88179_get_eeprom(struct net_device *net, struct= ethtool_eeprom *eeprom, u8 int ax88179_set_eeprom(struct net_device *net, struct ethtool_eeprom *eepr= om, u8 *data) { struct usbnet *dev =3D netdev_priv(net); + struct ax88179_data *ax179_data; u16 *eeprom_buff; int first_word; int last_word; int ret; int i; =20 + ax179_data =3D dev->driver_priv; + if (ax179_data->chip_version >=3D AX_VERSION_AX88179A) + return -EOPNOTSUPP; + netdev_dbg(net, "write EEPROM len %d, offset %d, magic 0x%x\n", eeprom->len, eeprom->offset, eeprom->magic); =20 --=20 2.47.3 From nobody Fri Sep 25 06:47:57 2026 Received: from bkemail.birger-koblitz.de (bkemail.birger-koblitz.de [23.88.97.239]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 131243BD25E; Wed, 16 Sep 2026 03:25:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=23.88.97.239 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789529134; cv=none; b=uIgwysSGo+tgbIpXCO5Ms3r47nxSeD9zPC59VYxd79SMDdXXjT49oKjvtqFWq2nifq3VOS2tBsZ74NO/AIYmaB0mEfVmR6rUZPR7GqLvf9akRom5M4gQtxePb9fzNYmjMNzrwnaFRzvLGlcrRS53TxEdDuDQPAHya773FTpmyFo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789529134; c=relaxed/simple; bh=th9j8IMz7cxt9OCRiUZdYPhFqg5LPYWjI6IEu1Zq3NM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=rYhS5l1atHKijfy4uMcgAsuXHT6GS2yR9kiU22J7hXn6M/O/+8fWJt6NVdH609BlLd5EvHGG7CW5fvOkkJKdhGNmTPytwWROOogoN9+ca/jlqLgp3V5dIs02591ukoLu5izkN63OU6DpiSugiWymVJ+1/FfRmuXidyFvPkq6Ye0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=birger-koblitz.de; spf=pass smtp.mailfrom=birger-koblitz.de; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b=AaejxEiS; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b=Sb+soTQx; arc=none smtp.client-ip=23.88.97.239 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=birger-koblitz.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=birger-koblitz.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b="AaejxEiS"; dkim=pass (2048-bit key) header.d=birger-koblitz.de header.i=@birger-koblitz.de header.b="Sb+soTQx" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=birger-koblitz.de; s=default; t=1789529131; bh=th9j8IMz7cxt9OCRiUZdYPhFqg5LPYWjI6IEu1Zq3NM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=AaejxEiSEHQPM4dW2+t7dGZkaV46sL10kD3xNKIGBepFpnPcGvtWP8r3LYx62wS1I wlz6B4wcl4pjzXkcYXm4dzeT6U4zqT6ht0EN/IiA/59331MwlqkfwD0fYcPAtW7zIi 5FC4oJm7J27VXlDYkTm8YgS0awJhtsKJAn1kCA6tPjtU/qKPB/6g1/R3MLMAgHpZ6U SvVAI80gmbwNoFmXJTfHRUMjDbtu6Xz6u/XdQEzN6QpYi0ws+bbbxVwLFsoO8//RuC i/9avk3E/PM06kORne4xJ+MvkWsvVYdbYQzZ/U+3ISluyJ7YBoQhDHSqn6JXpbA67D ggz+QGgpt0mhQ== Received: by bkemail.birger-koblitz.de (Postfix, from userid 109) id 3C56A3FA72; Wed, 16 Sep 2026 03:25:31 +0000 (UTC) X-Spam-Level: DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=birger-koblitz.de; s=default; t=1789529128; bh=th9j8IMz7cxt9OCRiUZdYPhFqg5LPYWjI6IEu1Zq3NM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Sb+soTQxZybCoFQW/agNm3FA5AZCBK3CXKoLJjhowdM5rKOgbyqglYxspubAaoJ5m hC9h8aXENkmtf4WiwVpReRQrGJpp9KjllMFgO4ztsUvwWn0c24leFdRfrmi0SZTyA7 N5pxOlXM8kIkJIkwMT4+AvM/EaoSB4LFrI/hTw+YjM8gZbg9x/BL2aoLVttbpy3tPQ +Fsb8S682TWqZKKxxgiH1ILHfffPRb2W1jnsUaQVB/IqWQDq942QLqJNk/sK9LLfMx D2lSKUJCABC9ApxHcTBvEi01wFKzXekkupqZAR+pVhLs3s/PB6FXBSwr39SvXrMTCx itpKQrp5b5ldw== Received: from DELLLaptop.net (unknown [223.86.26.228]) by bkemail.birger-koblitz.de (Postfix) with ESMTPSA id 8EA363FA6C; Wed, 16 Sep 2026 03:25:24 +0000 (UTC) From: Birger Koblitz Date: Wed, 16 Sep 2026 05:24:14 +0200 Subject: [PATCH net-next v12 15/15] ax88796b: Add support for AX88772D, AX88179A and AX88279 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260916-ax88179a-v12-15-60c04c9924a2@birger-koblitz.de> References: <20260916-ax88179a-v12-0-60c04c9924a2@birger-koblitz.de> In-Reply-To: <20260916-ax88179a-v12-0-60c04c9924a2@birger-koblitz.de> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Russell King , Andrew Lunn , Heiner Kallweit Cc: linux-usb@vger.kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Birger Koblitz , Jianhui Xu X-Mailer: b4 0.14.2 The AX88772D, AX88179A and AX88279 are 100MBit, 1GBit and respectively 2.5 GBit PHYs that are found in ASIX USB-Ethernet controllers of the same name. Signed-off-by: Birger Koblitz Reviewed-by: Andrew Lunn Tested-by: Jianhui Xu --- drivers/net/phy/ax88796b.c | 161 +++++++++++++++++++++++++++++++++++++++++= ++++ 1 file changed, 161 insertions(+) diff --git a/drivers/net/phy/ax88796b.c b/drivers/net/phy/ax88796b.c index f20ddf64914993f7097070d1f56c1103ec1e40e8..62f6beb25f41e703dc02add7358= 917d59ac8f2ac 100644 --- a/drivers/net/phy/ax88796b.c +++ b/drivers/net/phy/ax88796b.c @@ -13,6 +13,19 @@ #define PHY_ID_ASIX_AX88772A 0x003b1861 #define PHY_ID_ASIX_AX88772C 0x003b1881 #define PHY_ID_ASIX_AX88796B 0x003b1841 +#define PHY_ID_ASIX_AX88772D 0x003b772d +#define PHY_ID_ASIX_AX88179A 0x003b179a +#define PHY_ID_ASIX_AX88279 0x003b2790 + +#define AX_ADVERTISE_2500 0x1000 + +/* MII Vendor registers */ +#define AX_CTRL_STATUS 0x1d +#define AX_CTRL_STATUS_SPEED_MASK 0x0c +#define AX_CTRL_STATUS_SPEED_10 0x0 +#define AX_CTRL_STATUS_SPEED_100 0x4 +#define AX_CTRL_STATUS_SPEED_1000 0x8 +#define AX_CTRL_STATUS_SPEED_2500 0xc =20 MODULE_DESCRIPTION("Asix PHY driver"); MODULE_AUTHOR("Michael Schmitz "); @@ -83,6 +96,103 @@ static int asix_ax88772a_read_status(struct phy_device = *phydev) return 0; } =20 +static int asix_ax88279_read_status(struct phy_device *phydev) +{ + int ret, val; + + ret =3D genphy_read_status(phydev); + if (ret) + return ret; + + /* Read actual speed from vendor register */ + val =3D phy_read(phydev, AX_CTRL_STATUS); + switch (val & AX_CTRL_STATUS_SPEED_MASK) { + case AX_CTRL_STATUS_SPEED_2500: + phydev->speed =3D SPEED_2500; + break; + case AX_CTRL_STATUS_SPEED_1000: + phydev->speed =3D SPEED_1000; + break; + case AX_CTRL_STATUS_SPEED_100: + phydev->speed =3D SPEED_100; + break; + case AX_CTRL_STATUS_SPEED_10: + phydev->speed =3D SPEED_10; + } + + /* MDIO_AN_10GBT_STAT_LP2_5G is broken, but we can deduce that + * the link-partner advertised 2500M if remotely AN succceded + * for link speed > 1000M and we locally have a link speed of + * 2500M + */ + val =3D phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_STAT); + if (val >=3D 0 && val & MDIO_AN_10GBT_STAT_REMOK) { + linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, + phydev->lp_advertising, + phydev->speed =3D=3D SPEED_2500); + } + /* Only supports full duplex */ + phydev->duplex =3D DUPLEX_FULL; + + /* PHY switches interface between 2.5GBit and slower modes */ + if (phydev->speed =3D=3D SPEED_2500) + phydev->interface =3D PHY_INTERFACE_MODE_2500BASEX; + else + phydev->interface =3D PHY_INTERFACE_MODE_SGMII; + + return 0; +} + +static int asix_ax88279_config_aneg(struct phy_device *phydev) +{ + bool adv_2500; + int ret; + + if (phydev->autoneg =3D=3D AUTONEG_DISABLE) { + phydev_warn(phydev, "Disabling autoneg is not supported\n"); + return -EOPNOTSUPP; + } + + ret =3D genphy_config_aneg(phydev); + + if (ret < 0) + return ret; + + adv_2500 =3D linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phyd= ev->advertising); + ret =3D phy_modify(phydev, MII_ADVERTISE, AX_ADVERTISE_2500, + adv_2500 ? AX_ADVERTISE_2500 : 0); + + return ret; +} + +static int asix_ax88279_get_features(struct phy_device *phydev) +{ + int ret; + + /* MDIO_DEVS1/2 empty, so set mmds_present bits to allow reading abilitie= s */ + phydev->c45_ids.mmds_present |=3D MDIO_DEVS_PMAPMD | MDIO_DEVS_AN; + + linkmode_set_bit_array(phy_basic_ports_array, ARRAY_SIZE(phy_basic_ports_= array), + phydev->supported); + + ret =3D genphy_c45_pma_read_abilities(phydev); + if (ret < 0) + return ret; + + /* AX88279 does not support reported 100baseT-half duplex mode */ + linkmode_clear_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, phydev->supported= ); + + return 0; +} + +static int asix_ax88279_config_init(struct phy_device *phydev) +{ + __set_bit(PHY_INTERFACE_MODE_2500BASEX, phydev->possible_interfaces); + __set_bit(PHY_INTERFACE_MODE_SGMII, phydev->possible_interfaces); + + return 0; +} + static void asix_ax88772a_link_change_notify(struct phy_device *phydev) { /* Reset PHY, otherwise MII_LPA will provide outdated information. @@ -94,6 +204,25 @@ static void asix_ax88772a_link_change_notify(struct phy= _device *phydev) } } =20 +static int asix_ax88772D_get_features(struct phy_device *phydev) +{ + int ret; + __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) =3D {}; + + /* MDIO_DEVS1/2 empty, so set mmds_present bits to allow reading abilitie= s */ + phydev->c45_ids.mmds_present |=3D MDIO_DEVS_PMAPMD | MDIO_DEVS_AN; + + ret =3D genphy_read_abilities(phydev); + if (ret < 0) + return ret; + + /* AX88772D does not support reported 1000baseT mode */ + linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, mask); + linkmode_andnot(phydev->supported, phydev->supported, mask); + + return 0; +} + static struct phy_driver asix_driver[] =3D { { PHY_ID_MATCH_EXACT(PHY_ID_ASIX_AX88772A), @@ -111,6 +240,35 @@ static struct phy_driver asix_driver[] =3D { .suspend =3D genphy_suspend, .resume =3D genphy_resume, .soft_reset =3D asix_soft_reset, +}, { + PHY_ID_MATCH_EXACT(PHY_ID_ASIX_AX88772D), + .name =3D "Asix Electronics AX88772D", + .flags =3D PHY_IS_INTERNAL, + .get_features =3D asix_ax88772D_get_features, + .read_mmd =3D genphy_read_mmd_c45, + .write_mmd =3D genphy_write_mmd_c45, + .suspend =3D genphy_suspend, + .resume =3D genphy_resume, +}, { + PHY_ID_MATCH_EXACT(PHY_ID_ASIX_AX88179A), + .name =3D "Asix Electronics AX88179A", + .flags =3D PHY_IS_INTERNAL, + .suspend =3D genphy_suspend, + .resume =3D genphy_resume, + .read_mmd =3D genphy_read_mmd_c45, + .write_mmd =3D genphy_write_mmd_c45, +}, { + PHY_ID_MATCH_EXACT(PHY_ID_ASIX_AX88279), + .name =3D "Asix Electronics AX88279", + .flags =3D PHY_IS_INTERNAL | PHY_BROKEN_FORCED, + .get_features =3D asix_ax88279_get_features, + .read_status =3D asix_ax88279_read_status, + .config_aneg =3D asix_ax88279_config_aneg, + .config_init =3D asix_ax88279_config_init, + .read_mmd =3D genphy_read_mmd_c45, + .write_mmd =3D genphy_write_mmd_c45, + .suspend =3D genphy_suspend, + .resume =3D genphy_resume, }, { PHY_ID_MATCH_MODEL(PHY_ID_ASIX_AX88796B), .name =3D "Asix Electronics AX88796B", @@ -124,6 +282,9 @@ static const struct mdio_device_id __maybe_unused asix_= tbl[] =3D { { PHY_ID_MATCH_EXACT(PHY_ID_ASIX_AX88772A) }, { PHY_ID_MATCH_EXACT(PHY_ID_ASIX_AX88772C) }, { PHY_ID_MATCH_MODEL(PHY_ID_ASIX_AX88796B) }, + { PHY_ID_MATCH_EXACT(PHY_ID_ASIX_AX88772D) }, + { PHY_ID_MATCH_EXACT(PHY_ID_ASIX_AX88179A) }, + { PHY_ID_MATCH_EXACT(PHY_ID_ASIX_AX88279) }, { } }; =20 --=20 2.47.3